no issue
- Upgraded ghost-ignition
- Use debug from ghost-ignition everywhere in the code base
- Remove debug dependency
- Fixed random typo in Gruntfile.js
fixes#8845
- We had a report of weird URLS being output in admin stories view
- This is due to plaintext being incorrectly generated
- In order for a URL to be correct, it would need to already contain the subdirectory
- This line in the post model adds it as well, causing a duplicate
- Hence removing this line is the fix
fixes#8898
- This is a user error, not a system error
- Downgrading to a 4xx status code means it doesn't appear in logs where it shouldn't
- We didn't have a suitable error available so I added UpdateCollisionError with 409 status
refs #5091
- This tiny refactor opens the door for using channel config inside of helpers
- This means that ghost_head, and the next_post/prev_post helpers can be context aware
refs #5091
- occurred to me whilst documenting the custom homepage config, that RSS and pagination
need to be optional
- added a very quick if statement & tests
- needs further refactoring & test improvements
- this will not disable the RSS url output in meta data yet 😔
no issue
- 404 errors clutter up the log files and stdout when developing
- We don't really need these as more than a single line, like other requests
- This is how it worked in LTS
- This is also more consistent with other software (e.g. nginx)
closes#8334
- adds title, image and description to structured data to be rendered as open graph and twitter data.
- if meta title and description for a post exists already, the custom structured data will overwrite those for `og:` and `twitter:` data. `JSON-LD` (Schema.org`) is not affected and will stay the same.
- adds tests
- adds new og and twitter fields to schema incl. migration
closes#8651
- inactive users are suspended users or the owner user on blog setup
- added a check to see if user is inactive in import
- passes all tests
closes#8808
Problem:
- In certain cases, particularly in production mode, errors would be hidden
- E.g. fatal theme errors could not be seen, users instead saw "Failed to lookup view 'error' in views directory"
- This is extremely unhelpful, particularly for people upgrading from 1.0.0 or 1.0.1 where the disqus rule was added
afterwards and modified casper would error
Solution:
- Ensure that we properly setup handlebars when we throw an error
- If engines is not set, set all the view engine related properties
no issue
- add 1.4 database migration to add two new fields to the database (use type text, because of max row size)
- handle global code injection vs. post code injection
- add tests
refs #8700
- if you used a url e.g. /page/2abc/ ghost would interpret the 2 as /page/2/
- these urls should have returned 404, but instead were responding correctly
- this effectively creates duplicate pages
- added a test, but needed a dirty hack to get it to work 😞
- TODO: update casper fixture and use it in channel tests!
no issue
- if you backup your database and you are in the middle of a transaction, the transaction was not fully forwarded
- we were running into a pool error in knex
closes#8793
- 1.3 post excerpt migration
- add 1.3 migration to add `excerpt` to post schema
NOTE:
- knex-migrator relies on the package.json safe version
- so right now Ghost is on 1.2
- the migration script is for 1.3
- if you pull down the PR (or if we merge this PR into master), you have to run `knex-migrator migrate --v 1.3 --force`
- knex-migrator will tell you what you have todo
- Bump dependencies
- knex-migrator@2.1.3
- Soft limit for custom_excerpt
- Extended {{excerpt}} to use custom excerpt
- when a `custom_excerpt` field exists, the `{{excerpt}}` helper will output this and fall back to autogenerated excerpt if not.
- Refactored behaviour of (meta) description
- html tag `<meta name="description" />` for posts, tags and author doesn't get rendered if not provided.
- fallback for `author.bio` removed
- fallback for `tag.description` removed
- structured data and schema.org for `post` context takes the following order to render description fields:
1. custom excerpt
2. meta description
3. automated excerpt (50 words)
- updated and added tests to reflect the changes
closes#8781
- when the ownership get's transferred, the id of the new owner is not '1' anymore
- we previously added a database rule, which signalises if the blog is setup or not, see 827aa15757 (diff-7a2fe80302d7d6bf67f97cdccef1f71fR542)
- this database rule is based on the owner id being '1', which is wrong when you transfer ownership
- we should keep in mind, that the owner id being '1' is only the default Ghost setup, but it can change
- blog is setup if the owner is locked
closes#8605
- This file has already been moved, might as well get the rename out of the way
- Especially as we don't migrate clients - everyone will now need to make just one change
refs #8756
- there was a bug in one of the last LTS releases, which produced duplicated attached roles to users
- we want to prevent that on import and take the latest created based on the autoincrement id
refs https://github.com/TryGhost/Ghost/issues/8757
- remove mobiledoc parsing, it's reliance on SimpleDom makes it too
fragile when dealing with the unconstrained user-entered HTML that is
allowed in markdown
closes#8760
- we have to remember the old post id's when migrating a blog from LTS to 1.0
- otherwise we would break disqus comments, because they rely on the post id
- this should fix the discovered situation
closes https://github.com/TryGhost/Ghost/issues/8743
- the serializer in our mobiledoc renderer didn't have the list of non-closing HTML tags passed in which meant that tags such as `<br>` in the markdown HTML output were being re-serialized to `<br></br>` which is invalid HTML which (at least Chrome) then attempts to fix by rendering it as `<br><br>` instead
- the elements with incorrect rendering that may result in unwanted "fixing" by browsers are `AREA`, `BASE`, `BR`, `COL`, `COMMAND`, `EMBED`, `HR`, `IMG`, `INPUT`, `KEYGEN`, `LINK`, `META`, `PARAM`, `SOURCE`, `TRACK`, and `WBR`
no issue
- this is usually an edge case, but i investigated because i thought that the importer is broken
- the importer logic is build like this:
- it creates a transaction
- this transactions runs through:
- beforeImport
- doImport
- afterImport
- afterImport corrects user references and if a user could not be imported, we have to protect that
NOTE: we could create two transactions to be more correct, but building this had no priority because of edge cases only
having two transactions would solve: you first add the data (error or success), then you correct the data
- usually a user can be always imported (!), but there are a few edge cases (e.g. multiple roles attached)
no issue
- if you upload a huge import file, parallel operations can throw errors e.g. lock wait exceeds
- this can happen if multiple transactions run in parallel
- there is no need to run:
1. the removal of active tokens on import, because imported users have no active session
2. rescheduling logic on timezone, because importing scheduled posts works out of the box via the model layer (if a published date is detected and it's in the future, the post get's scheduled)
closes#8645, closes#8710
- locked users were once part of the category "active users", but were moved to the inactive category
-> we have added a protection of not being able to edit yourself when you are either suspended or locked
- but they are not really active users, they are restricted, because they have no access to the admin panel
- support three categories: active, inactive, restricted
* - revert restricted states
- instead, update permission layer: fallback to `all` by default, because you are able to serve any user status
- add more tests
- ATTENTION: there is a behaviour change, that a blog owner's author page can be served before setting up the blog, see conversation on slack
-> LTS serves 404
-> 1.0 would serve 200
closes#8691
There was a condition added when i've refactored the importer.
> if (models.User.isOwnerUser(obj[key])) {
This condition is absolutely wrong! If you import an owner user, this owner user get's imported as administrator. But the original owner user id reference must be updated as well, so that the reference points to the new administrator id ✌🏻
no issue
- if you delete an active user, Ghost logs an error message (Ghost does not crash!)
- but the event logic is not triggered, that means we don't delete the users tokens
- token deletion happens on: suspend a user and delete a user
no issue
- if you destroy a user with an unknown user id, Ghost would crash
- because `userModel.hasRole` is undefined
- there is actually a bigger underlying architectual problem:
- the permission check should rely on an existing user
- so there should be a first api layer, which 1. validates (this code exists) and 2. ensures that requested database id's exist
- but this requires a bigger refactoring
closes#8601
- This makes sure that when you do an import, you still get the LATEST
default settings for labs. Even if you had a different value before.
- LTS -> 1.0 is an upgrade, and Public API should be on by default, even if you
had deliberately turned it off before.
- Cheeky test added
no issue
Seems like we forgot to update the AMP template to reflect our image helper changes.
- Replaces `{{image}}` helper with `{{img_url}}` for `feature_image`
- Removes `{{meta_description}}` helper
refs #8620
Adds a new Ghost Author user, which is the author of the new welcome blog posts. The user is set to active, so the author slug works (otherwise it would render a 404, when user is suspended). Furthermore, there's one little fix in the user model, which was checking only for `active` user to decide the signup or setup process for the UI. Adding one more conditional to check if the found active user is also the owner, prevents to get redirected to sign in.
closes#8601
- this doesn't take the feature out of beta, but does enable it by default
- no need to enable the public api in the test anymore
- because public api is enabled by default
closes#8565
- isPasswordCorrect fn returns a specific error, which we simply forward
- no need to wrap a custom error into a new custom error
- the rule is always: if you are using a Ghost unit/function, you can expect that this unit returns a custom error
closes#8568
- use our `urlJoin` util to concatenate the URL (not the query part of it, as this is not supported in `urlJoin`) and to prevent possible missing or double slashes, as `config.apiUrl` could be with or without trailing slash
closes#8562
- before we create our model fixtures, we assign a `published_at` property with a difference of 1 second for each blog post, so the `prev_post` and `next_post` helpers work correctly
closes#8542
- updates default post fixtures
- adds default logo and cover images to settings fixtures
- update tests due to coupling to dev/prod fixtures
refs #8530
- display theme name for non-fatal errors
- minor wording tweak
- remove duplicate lodash require
- use the shiny new calculated property syntax
refs #8222
- differentiate between errors and fatal errors
- use gscan errors in theme middleware
- Adds a new `error()` method to `currentActiveTheme` constructor which will return the errors we receive from gscan
- In middleware, if a theme couldn't be activated because it's invalid, we'll fetch the erros and send them to our error handler. We also use a new property `hideStack` to control, if the stack (in dev mode and if available) should be shown or the gscan errors (in prod mode, or in dev if no stack error)
- In our error handler we use this conditional to send a new property `gscan` to our error theme
- In `error.hbs` we'll iterate through possible `gscan` error objects and render them.
- remove stack printing
- stack for theme developers in development mode doesn't make sense
- stack in production doesn't make sense
- the stack is usually hard to read
- if you are developer you can read the error stack on the server log
- utils.packages: transform native error into Ghost error
- use `onlyFatalErrors` for gscan format and differeniate fatal errors vo.2
- optimise bootstrap error handling
- transform theme is missing into an error
- add new translation key
- show html tags for error.hbs template: rule
refs #8141
- update importer for LTS fields
- optimise for LTS export fixtures
- add image/language test for LTS import
- ensure post image is mapped to feature_image
- create mobiledoc values from markdown and html
- if mobiledoc is null, use markdown or html to create a mobiledoc markdown card
- update import mapping to use locale
- defaultLang in settings now maps to default_locale
- language for post and user models now maps to locale
- posts are not always loaded in correct same order so we select the posts we want to validate
- ensure if mobiledoc field is not in export we can still import from markdown
- map last_login to last_seen
- for users the importer maps last_login to last_seen
- add warning for legacyActiveTheme
- for export with old activeTheme key provide a warning that theme is not installed
- add importer test for LTS user long email
- add a test for LTS export where email address could be longer than alpha
- fix for importer date tests on mysql
- use valueOf in moment to compare times stored in different formats
- ignore warnings for not found settings in import
- use a flag to ignore NotFound Entries for settings during import
no issue
- this PR references indirecty to https://github.com/TryGhost/Ghost/pull/8437
- i would like to have the settings change already in place before we release the beta
- the i18n feature is able to change the locale of Ghost
- most i18n libraries use locale
- adding/changing settings doesn't require a migration file, but it can make the database a bit messy (because you can end up with default_locale and lang)
- furthermore we agreed that the default locale for Ghost should be simply `en`, not `en_US` or `en_GB`
closes#8479
- removes `markdown` field from schema
- removes `legacyMarkdown` converter
- updates tests to work with `mobiledoc` field instead of `markdown` and adapt for mobiledoc HTML output where necessary
refs #8152
- as long as OAuth is disabled, we can revert the url redirection (see comment)
- the redirect only happens if you configure a specific `admin.url`
- add another test case, which was missing
refs #5422
- we can support null titles after this PR if we want
- user model: fix getAuthorRole
- user model: support adding roles by name
- we support this for roles as well, this makes it easier when importing related user roles (because usually roles already exists in the database and the related id's are wrong e.g. roles_users)
- base model: support for null created_at or updated_at values
- post or tag slugs are always safe strings
- enable an import of a null slug, no need to crash or to cover this on import layer
- add new DataImporter logic
- uses a class inheritance mechanism to achieve an easier readability and maintenance
- schema validation (happens on model layer) was ignored
- allow to import unknown user id's (see https://github.com/TryGhost/Ghost/issues/8365)
- most of the duplication handling happens on model layer (we can use the power of unique fields and errors from the database)
- the import is splitted into three steps:
- beforeImport
--> prepares the data to import, sorts out relations (roles, tags), detects fields (for LTS)
- doImport
--> does the actual import
- afterImport
--> updates the data after successful import e.g. update all user reference fields e.g. published_by (compares the imported data with the current state of the database)
- import images: markdown can be null
- show error message when json handler can't parse file
- do not request gravatar if email is null
- return problems/warnings after successful import
- optimise warnings in importer
- do not return warnings for role duplications, no helpful information
- error handler: return context information of error
- we show the affected json entries as one line in the UI
- show warning for: detected duplicated tag
- schema validation: fix valueMustBeBoolean translation
- remove context property from json parse error
no issue
The simpledom interpreter that the Mobiledoc DOM renderer uses does not allow for unbalanced or incorrect HTML such as that which is entered by a user.
This PR adds a step where the HTML is sanitised and balanced before being passed to simpledom.
- use latest jsdom (+pin version), update yarn.lock, add comments
- don't use node-4 incompatible shorthand method definition
- grab <body> content rather than document content
- update markdown card specs to match markdown-it behaviour
- revert to jsdom 9.12.0 for node 4.x support, close window to free memory
- moved 3rd party libs into render function
refs https://github.com/TryGhost/Ghost-Admin/pull/690, closes#1501, closes#2093, closes#4592, closes#4627, closes#4659, closes#5039, closes#5237, closes#5587, closes#5625, closes#5632, closes#5822, closes#5939, closes#6840, closes#7183, closes#7536
- replace custom showdown fork with markdown-it
- swaps showdown for markdown-it when rendering markdown
- match existing header ID behaviour
- allow headers without a space after the #s
- add duplicate header ID handling
- remove legacy markdown spec
- move markdown-it setup into markdown-converter util
- update mobiledoc specs to match markdown-it newline behaviour
- update data-generator HTML to match markdown-it newline behaviour
- fix Post "converts html to plaintext" test
- update rss spec to match markdown-it newline behaviour
- close almost all related showdown bugs
closes#8354
- i thought about transforming scheduled posts into drafts on export, but this has two disadvantages:
1. existing exports with scheduled posts won't import
2. if you schedule a post for next week and you export/import earlier, the post is back to draft
- by this we ensure that we can simply import the post back to a scheduled post
- if the published_at is already in the past, the scheduler will care and instantly publish the post
closes#8436
- this is how the from field looks like "blog title <owner@blog.com>"
- so if you set your blog title with double quotes, it throws a syntax error from the smtp library
closes#8426
- if you import posts with updated_at=null, you are not able to save this post anymore
- i am not sure how this is even possible, but maybe there is a case where updated_at can be null
no issue
- now that we've switched to using a SimpleMDE based editor in Ghost-Admin the default post needs to match the expected single-markdown-card format
no issue
- if you start Ghost and you theme is invalid, you only get a warning, but no reason
- furthermore, if any error is thrown in Ghost, which is not a custom Ignition error, we take care that the error message to inherit from shows up
* 🙀 change database schema for images
- rename user/post/tag images
- contains all the required changes from the schema change
* Refactor helper/meta data
- rename cover to cover_image
- also rename default settings to match the pattern
- rename image to profile_image for user
- rename image to feature_image for tags/posts
* {{image}} >>> {{img_url}}
- rename
- change the functionality
- attr is required
- e.g. {{img_url feature_image}}
* gscan 1.0.0
- update yarn.lock
* Update casper reference: 1.0-changes
- see 5487b4da8d
closes#5599
If two users edit the same post, it can happen that they override each others content or post settings. With this change this won't happen anymore.
✨ Update collision for posts
- add a new bookshelf plugin to detect these changes
- use the `changed` object of bookshelf -> we don't have to create our own diff
- compare client and server updated_at field
- run editing posts in a transaction (see comments in code base)
🙀 update collision for tags
- `updateTags` for adding posts on `onCreated` - happens after the post was inserted
--> it's "okay" to attach the tags afterwards on insert
--> there is no need to add collision for inserting data
--> it's very hard to move the updateTags call to `onCreating`, because the `updateTags` function queries the database to look up the affected post
- `updateTags` while editing posts on `onSaving` - all operations run in a transactions and are rolled back if something get's rejected
- Post model edit: if we push a transaction from outside, take this one
✨ introduce options.forUpdate
- if two queries happening in a transaction we have to signalise knex/mysql that we select for an update
- otherwise the following case happens:
>> you fetch posts for an update
>> a user requests comes in and updates the post (e.g. sets title to "X")
>> you update the fetched posts, title would get overriden to the old one
use options.forUpdate and protect internal post updates: model listeners
- use a transaction for listener updates
- signalise forUpdate
- write a complex test
use options.forUpdate and protect internal post updates: scheduling
- publish endpoint runs in a transaction
- add complex test
- @TODO: right now scheduling api uses posts api, therefor we had to extend the options for api's
>> allowed to pass transactions through it
>> but these are only allowed if defined from outside {opts: [...]}
>> so i think this is fine and not dirty
>> will wait for opinions
>> alternatively we have to re-write the scheduling endpoint to use the models directly
no issue
- client dates are sent as ISO format (moment(..).format())
- server dates are in JS Date format
>> when bookshelf fetches data from the database, all dates are transformed into JS dates
>> see `parse` helper function
- Bookshelf updates the model with the client data via Bookshelf's `set` function
- therefor Bookshelf uses a simple `isEqual` function from lodash to detect changes
- .previous(attr) and .get(attr) return false
- that has the concequence that dates are always marked as "changed"
- internally we use our `hasDateChanged` if we have to compare previous/updated dates
- but Bookshelf is not in our control for this case
no issue
- the UTC offset diff of the current and previous timezone must switch
- i have added more tests and more example case descriptions to understand why
refs #8221, closes#7688, refs #7558🙇 Improve meta data publisher logo behaviour
This is a follow-up PR for #8285.
Reasons: The code changes of #8285 caused error messages when falling back to the default `favicon.ico`, as the `image-size` tool doesn't support `ico` files.
This PR takes the logic to decide which logo needs to be listed in our schema into a new fn `blog_logo.js`. There we have now three decisions:
1. If we have a publication **logo**, we'll take that one
2. If we have no publication logo, but an **icon** we'll use this one.
3. If we have none of the above things, we fall back to our default `favicon.ico`
Additional, we're hard coding image dimensions for whenever the logo is an `.ico` file and built and extra decision to not call `image-size` when the dimension are already given.
I will create another follow-up PR, which checks the extension type for the file and offers it as a util.
🛠 Blog icon util
refs #7688
Serve functionality around the blog icon in its own util:
- getIconDimensions -> async function that takes the filepath of on ico file and returns its dimensions
- isIcoImageType -> returns true if file has `.ico` extension
- getIconType -> returns icon-type (`x-icon` or `png`)
- getIconUrl -> returns the absolut or relativ URL for the favicon: `[subdirectory or not]favicon.[ico or png]`
📖 Get .ico sizes for meta data & logo improvement
refs #7558
refs #8221
Use the new `blogIconUtil` in meta data to fetch the dimensions of `.ico` files.
Improvements for `publisher.logo`: We're now returning a hard-coded 'faked' image dimensions value to render an `imageObject` and prevent error our schema (Google structured data). As soon as an image (`.ico` or non-`.ico`) is too large, but - in case of non-`.ico` - a square format, be set the image-dimensions to 60px width and height. This reduces the chances of getting constantly error messages from Googles' webmaster tools.
- add getIconPath util
refs #8275
- If the HTML field has changed, update the plaintext field
- Use html-to-text to generate a plaintext version of the HTML which retains some structure
- Add a couple of tests - although there's much to do here!
refs #8221🔥 Remove ghost=true concept from asset url helper
✨💯 Introduce CSS minification with cssnano
- add new grunt-cssnano dependency
- wire up grunt task to minify public/ghost.css
🎨 Rename minification config & hash params
- Change minifyInProduction -> hasMinFile
- this means this asset should have a .min file available
- Change minifyAssets -> useMinFiles
- this means that in this env we want to serve .min files if available
🎨 Update public/ghost.css to serve .min for prod
- add the new `hasMinFile` property
🎨 Move minified asset handling to asset_url util
- this logic should be in the util, not the asset helper
- updated tests
📖 Error handler always needs asset helper
- this removes the TODO and adds a more sensible comment
- we also need to update our theme documentation around error templates
🔥 Don't use asset helper in ghost head
- use getAssetUrl util instead!
- removed TODO
📖 Update proxy docs
🎨 Simplify asset helper & add tests
- this refactor is a step prior to moving this from metadata to being a url util
- needed to skip some new tests
🐛 Add missing handler for css file
refs #8221
Use our default `favicon.ico` instead of `ghosticon.jpg` which is served from the admins' assets.
Adds additionally fake image dimensions for our json-ld data to satisfy Google.
refs #8221
Instead of serving our shared assets from a `shared/` folder, we move the file, which are used server side to `server/public`.
Adds a new `config.paths` entry: `publicFilePath` and renames the middleware to serve the files to reflect the changes.
Adds `404-ghost.png` images to be used by the server side rendered default template `error.hbs`.
closes#7687
- change location from content/storage or content/scheduling to content/adapters/storage or content/adapters/scheduling
- i have added a @TODO to https://github.com/TryGhost/Ghost/issues/7421 to check if both adapter types needs an update in the documentation
no issue
- i don't know if this never worked or has worked and something changed in bookshelf
- but this fixes: saving the content (no change for published_at) of a scheduled post within the 2minutes window
- add `beforeWrite` option to hasDateChanged helper, see comment
- use previous for `beforeWrite` operations
- add a test and fix some other small issues in the scheduler tests
no issue
🐛 subscriber: sanitize email vol. 2
- ensure email get's sanitized for every error case
🐛 validator.isEmptyOrURL doesn't accept non strings
- otherwise it shows a weird error message in the client
✨ new tests for subscriber app
- routing tests
* change tests for Ghost 1.0
* it took me 15min to find this 😡
refs #8258
* 🎨 change last_login to last_seen
- rename the column
- a change in Ghost-Admin is required as well
* test utils: revert export examples
* revert line breaks
refs #8275
- this switches over the fixture to be mobiledoc based. Most of the content was to do with markdown so it has been replaced with placeholder text
- content will be replaced via #8275
refs #7687
There are four main changes in this PR:
we have outsourced the base storage adapter to npm, because for storage developers it's annoying to inherit from a script within Ghost
we hacked theme storage handling into the default local storage adapter - this was reverted, instead we have added a static theme storage here
use classes instead of prototyping
optimise the storage adapter in general - everything is explained in each commit
----
* rename local-file-store to LocalFileStorage
I would like to keep the name pattern i have used for scheduling.
If a file is a class, the file name reflects the class name.
We can discuss this, if concerns are raised.
* Transform LocalFileStorage to class and inherit from new base
- inherit from npm ghost-storage-base
- rewrite to class
- no further refactoring, happens later
* Rename core/test/unit/storage/local-file-store_spec.js -> core/test/unit/storage/LocalFileStorage_spec.js
* Fix wrong require in core/test/unit/storage/LocalFileStorage_spec.js
* remove base storage and test
- see https://github.com/kirrg001/Ghost-Storage-Base
- the test has moved to this repo as well
* Use npm ghost-storage-base in storage/index.js
* remove the concept of getStorage('themes')
This concept was added when we added themes as a feature.
Back then, we have changed the local storage adapter to support images and themes.
This has added some hacks into the local storage adapters.
We want to revert this change and add a simple static theme storage.
Will adapt the api/themes layer in the next commits.
* Revert LocalFileStorage
- revert serve
- revert delete
* add storagePath as property to LocalFileStorage
- define one property which holds the storage path
- could be considered to pass from outside, but found that not helpful, as other storage adapters do not need this property
- IMPORTANT: save has no longer a targetDir option, because this was used to pass the alternative theme storage path
- IMPORTANT: exists has now an alternative targetDir, this makes sense, because
- you can either ask the storage exists('my-file') and it will look in the base storage path
- or you pass a specific path where to look exists('my-file', /path/to/dir)
* LocalFileStorage: get rid of store pattern
- getUniqueFileName(THIS)
- this doesn't make sense, instances always have access to this by default
* Add static theme storage
- inherits from the local file storage, because they both operate on the file system
- IMPORTANT: added a TODO to consider a merge of themes/loader and themes/storage
- but will be definitely not part of this PR
* Use new static theme storage in api/themes
- storage functions are simplified!
* Add https://github.com/kirrg001/Ghost-Storage-Base as dependency
- tarball for now, as i am still testing
- will release if PR review get's accepted
* Adapt tests and jscs/jshint
* 🐛 fix storage.read in favicon utility
- wrong implementation of error handling
* 🎨 optimise error messages for custom storage adapter errors
* little renaming in the storage utlity
- purpose is to have access to the custom storage instance and to the custom storage class
- see next commit why
* optimise instanceof base storage
- instanceof is always tricky in javascript
- if multiple modules exist, it can happen that instanceof is false
* fix getTargetDir
- the importer uses the `targetDir` option to ensure that images land in the correct folder
* ghost-storage-base@0.0.1 package.json dependency
refs #8126, #8221, #8223✨ New 'Proxy' for all helper requires
- this is not currently enforced, but could be, much like apps
- the proxy object is HUGE
- changed date to use SafeString, this should have been there anyway
- use the proxy for all helpers, including those in apps 😁✨🎨 Single instance of hbs for theme + for errors
- we now have theme/engine instead of requiring express-hbs everywhere
- only error-handler still also requires express-hbs, this is so that we can render errors without extra crud
- TODO: remove the asset helper after #8126 IF it is not needed, or else remove the TODO
🎨 Cleanup visibility utils
🎨 Clean up the proxy a little bit
🚨 Unskip test as it now works!
🎨 Minor amends as per comments
closes#8067
- this is only a bug present for remote authentication
- right now the remote service does not return the name of the user
- depends on an internal PR
- force regenerating the slug on setup
- override name for signin or invite if needed
closes#8126
* Remove default template dependency on client side CSS
See Issue #8126
Adds these files under /shared
- normalizer.css
- error.css
- extracted.css (for subscribers.css and private.css)
Also makes these files available as public static content
* Remove default template dependency on client CSS
closes#8126
needs e3acd3c
This is a replacement PR of #8217 (thanks @TienSFU25 for the whole work 🤗), because these changes are needed urgently and blocking other work.
Adds a new `ghost.css` file in `/core/shared/` to be used for server side template rendering (`error.hbs`, `subscribe.hbs` and `private.hbs`).
refs https://github.com/TryGhost/Ghost/issues/8161, requires https://github.com/TryGhost/Ghost-Admin/pull/590
- adds a development-only route to the admin app that redirects to ember-cli's livereload script
- updates Gruntfile `watch` task to pass the `live-reload-base-url` param with subdirectory support
- updates Gruntfile `bgShell:client` task to filter potentially confusing output from `ember serve`
- removes `Livereload server on http://localhost:49153`
- removes `Serving on http://localhost:4200/`
With this and the required Ghost-Admin PR, when using `grunt dev` the admin screen will refresh any time a file is changed. It will also allow client tests to be run simultaneously by visiting http://localhost:4200/tests
no issue
🔥 Remove adminHbs concept from tests
🔥 Get rid of unnecessary helper test utils
🔥 Remove helper missing code
- this hasn't been registered / used for ages 😱
- gscan no longer allows us to activate themes that have missing helpers, so this wouldn't be used anyway
TODO: consider whether we should make a way to override this?
🎨 Reduce coupling inside of /helpers
🎨 Use settingsCache in ghost_foot
✨ Labs util for enabling helpers
🎨 Move loadCoreHelpers to blog
- This needs a proper home, but at the very least it doesn't belong
in server/app.js!
🎨 Use settingsCache in ghost_head
closes#8187
- if you start Ghost via the Ghost-CLI, the path to the favicon must be absolute
- because the CLI spawns a Ghost process from the root folder of the CLI folder e.g. node current/index.js
no issue
🔥 Remove DIRTY HACK for API
- this is no longer needed, because themes get mounted in every case
✨ Switch to concept of 'mounted' theme
- check if active theme is mounted
- if not, mount it
- mounting is a function OF the active theme
🎨 Move theme middleware to theme module
🎨 Update theme middleware function names
- update the function names and comments to be more representative of their current functions
- this was pretty old and out of date!
🚨 Fixup tests for middleware
- ensure the objects match what we expect
- based partially on theme docs
Update TODO
no issue
- change out should.equal for // jshint ignore:line
- ensure should is the first require in every test, and ALWAYS require
- make sinon the second require, and sandbox the last thing
- ALWAYS use sandbox, futureproofs tests against contributors who don't know it
- change require formatting
no issue
🎨🐛 Ensure cache is updated correctly for themes
- Insure the cache invalidation headers are always set correctly for the themes API
📖 Theme API comments / function naming
- this is an update for clarity, so we can see what further improvements can be made
🐛🎨 Add permissions to themes.browse
refs #8041
Calls `getImageSize` with an timeout of 6sec. and adds a default timeout (in case, function is called without optional timeout) of 10sec, to prevent node from using its default timeout of 2minutes 😱
refs TryGhost/Ghost#8140
refs TryGhost/Ghost-Admin#593
- now that the admin index page is just html, we don't need handlebars anymore
- as we can use res.sendFile to send the static HTML file, don't need to "render" it anymore
- remove the view engine, hbs and the use of helpers - it's all unneeded
- change the filenames to .html to reflect this
refs #7429
- ☢️👷🏻♀️ This PR removes the dependency on Ghost-Editor and replaces it with the Mobiledoc DOM renderer. It includes new DOM based default cards and atoms.
closes#8131
- Remove ppp from default-settings.json
- Remove ppp from meta (unused?\!)
- ✨ Basic concept of theme config
- use theme config ppp setting
- ✨ Make @config.posts_per_page helper available
- rather than @blog.posts_per_page, we now have @config.posts_per_page
- 🚨 Test updates
- Adding TODO note
closes#4424
- meta description is an optional SEO tag that we can provide when we have sensible output
- in the cases where we have no useful output, we should not output the tag at all
- ghost_head now takes care of this, and themes should not include their own meta description tag
closes#7242
- before this, the get helper's else was used for empty resultsets
- the argument was made that we should fall through to a foreach or with helper's else instead
- I agree that this is the more natural, consistent approach, and so would like to change it for Ghost 1.0
E.g. as of this PR we now have:
{{#get "posts" filter="tag:doesnt-exist"}}
{{#foreach posts}}
{{else}}
this ges executed because there are no results
{{/foreach}}
{{/get}}
instead of
{{#get "posts" filter="tag:doesnt-exist"}}
{{#foreach posts}}
{{else}}
{{/foreach}}
{{each}}
this ges executed because there are no results
{{/get}}
refs #8140✨ Support new default-prod.hbs template for admin
✨ Redirect ghost admin urls without a #
✨ Update admin urls to include #
🎨 Move the admin templates
🔥 Remove redirect to setup middleware
🚨 Tests for new middleware
refs #7491
- this hack is so legacy I almost forgot about it 😈
- in the beginning of Ghost there were no post images
- someone figured out you could do {{content words="0"}} and it would pull out the first image in your post
- this was never documented, but enough theme developers found it that when we upgraded downsize to get rid of the bug
- we needed to add a hack to keep compatibility.
- This has to die in 🔥 for Ghost 1.0
refs #8032
- this was used to disable the upload image functionality in Ghost-Admin
- we no longer need this boolean, because people can add their own storage adapter
closes#8079
- add a new view type of defaultViews, as this is NOTHING to do with the admin!
- rename user-error.hbs to error.hbs, because this can be for any sort of error
- reimplement custom errors, but with a stack like channels & single templates
- change ghost_head to only not output on 500+ server errors, rather than 400+ user errors
- add coverage for the new template functions
closes#8082
- Update the `pickTemplate` logic to
a) rely on getActive().hasTemplate() instead of being passed a list of paths
b) support the concept of a fallback, which is returned if there is no theme, or if the theme doesn't have a more specific template
- Update every instance of template picking, across the 3 internalApps, and render-channel, to use this new logic
- update the tests
📡 Add debug for the 3 theme activation methods
There are 3 different ways that a theme can be activated in Ghost:
A. On boot: we load the active theme from the file system, according to the `activeTheme` setting
B. On API "activate": when an /activate/ request is triggered for a theme, we validate & change the `activeTheme` setting
C. On API "override": if uploading a theme with the same name, we override. Using a dirty hack to make this work.
A: setting is done, should load & validate + next request does mounting
B: load is done, should validate & change setting + next request does mounting
C: load, validate & setting are all done + a hack is needed to ensure the next request does mounting
✨ Validate w/ gscan when theme activating on boot
- use the new gscan validation validate.check() method when activating on boot
✨ New concept of active theme
- add ActiveTheme class
- make it possible to set a theme to be active, and to get the active theme
- call the new themes.activate() method in all 3 cases where we activate a theme
🎨 Use new activeTheme to simplify theme code
- make use of the new concept where we can, to reduce & simplify code
- use new hasPartials() method so we don't have to do file lookups
- use path & name getters to reduce use of getContentPath etc
- remove requirement on req.app.get('activeTheme') from static-theme middleware (more on this soon)
🚨 Improve theme unit tests (TODO: fix inter-dep)
- The theme unit tests are borked! They all pass because they don't test the right things.
- This improves them, but they are still dependent on each-other
- configHbsForContext tests don't pass if the activateTheme tests aren't run first
- I will fix this in a later PR
no issue
- this is secured by client credentials
- you can only fetch the user info if the user is connected to your blog (invited, owner)
- passport ghost instance stores the client credentials in the instance, no need to pass them into
- tested on staging
no issue
🎨 simplify loader - use loadOneTheme for init
- use loadOneTheme for init
- move updateThemeList to the one place that it is used
- this just reduces the surface area of the loader
🎨 Move init up to index temporarily
- need to figure out what stuff goes in here as well as loading themes
- will move it again later once I've got it figured out
🎨 Reorder & cleanup theme middleware
- move the order in blog/app.js so that theme middleware isn't called for shared assets
- add comments & cleanup in the middleware itself, for clarity
🎨 Simplify the logic in themes middleware
- Separate out config dependent on settings changing and config dependent on request
- Move blogApp.set('views') - no reason why this isn't in the theme activation method as
it's actually simpler if it is there, we already know the active theme exists & can remove the if-guard
🎨 Improve error handling for missing theme
- ensure we display a warning
- don't have complex logic for handling errors
- move loading of an empty hbs object into the error-handler as this will support more cases
🐛 Fix assetHash clearing bug on theme switch
- asset hash wasn't correctly being set on theme switch
🎨 Remove themes.read & test loader instead
- Previously, we've simplified loader & improved error handling
- We are now able to completely remove theme.read as it's nothing more than a wrapper for package.read
- This also means we can change our tests from testing the theme reader to loader
refs #8111
- Ghost returns now all (active+none active) users by default
- protect login with suspended status
- test permissions and add extra protection for suspending myself
- if a user is suspended and tries to activate himself, he won't be able to proceed the login to get a new token
refs #8093✨ Add activate theme permission
- add permission to activate themes
- update tests
- also: update tests for invites
TODO: change how the active theme setting is updated to reduce extra permissions
✨ Move theme validation to gscan
- add a new gscan validation method and use it for upload
- update activate endpoint to do validation also using gscan
- change to using SettingsModel instead of API so that we don't call validation or permissions on the settings API
- remove validation from the settings model
- remove the old validation function
- add new invalid theme message to translations & remove a bunch of theme validation related unused keys
📖 Planned changes
🚨 Tests for theme activation API endpoint
🐛 Don't allow deleting the active theme
🚫 Prevent activeTheme being set via settings API
- We want to control how this happens in future.
- We still want to store the information in settings, via the model.
- We just don't want to be able to change this info via the settings edit endpoint
🐛✨ Fix warnings for uploads & add for activations
- warnings for uploads were broken in f8b498d
- fix the response + adds tests to cover that warnings are correctly returned
- add the same response to activations + more tests
- activations now return a single theme object - the theme that was activated + any warnings
🎨 Improve how we generate theme API responses
- remove the requirement to pass in the active theme!
- move this to a specialist function, away from the list
🎨 Do not load gscan on boot
no issue
If the user changes the email in the remote auth service and executes a logout directly afterwards, the user would lock himself out of his blog, because the email sync happens once per hour right now.
For that case, we have to store the ghost auth id.
no issue
- browse will now include the correct activated theme again
- PUT /theme/:name/activate will activate a theme
- tests now read from a temp directory not content/themes
- all tests check errors and responses
* 🐛 export database read settings from database
no issue
- the backup script uses the export database lib and is broken if knex-migrator is called via shell, the settings cache is not loaded
- i have changed the export database lib to read the settings key directly from the db
* use get('value')
closes#8099, refs https://github.com/TryGhost/Ignition/issues/28
- use new utility to detect if an error has not yet been handled & convert it to a generic Ghost error
- update theme_spec tests to include checking error messages, which catches this issue
no issue
🔥 Remove unnecessary cache update
🎨 simplify updateSettingsCache()
🎨 Simplify readSettingsResult
- although this is more code, it's now much clearer what happens in the two cases
🎨 Don't use readSettingResult for edit
🎨 Simplify updateSettingsCache further
🔥 Remove now unused readSettingsResult
🎨 Change populateDefault to return all
🎨 Move the findAll call out of updateSettingsCache
🔥 Remove updateSettingsCache!!
🎨 Restructure init & finish up settingsCache
- move initialisation into settingsCache.init AT LAST
- change settingCache to use cloneDeep, so that the object can't be modified outside of the functions
- add lots of docs to settings cache
🎨 Cleanup db api endpoints
🔥 Don't populate settings in migrations
* 🎨 deny auto switch
no issue
- deny auth switch after the blog was setup
- setup completed depends on the status of the user right now, see comments
* Updates from comments
- re-use statuses in user model
- update error message
refs #7812, closes#7958
- fixes boolean logic wrt to theme cache value from config
- disable cache for admin assets in development
- only add asset hash in production
no issue
🎨 Switch themes API to use config.availableThemes
- this gets rid of the only places where settings.availableThemes are used
🔥 Get rid of settings.availableThemes
- this is no longer used anywhere
- also get rid of every related call to updateSettingsCache
🔥 Replace config.availableThemes with theme cache
- Creates a tailor-made in-memory cache for themes inside the theme module
- Add methods for getting & setting items on the cache
- Move all references to config.availableThemes to use the new cache
- This can be abstracted later to support other kinds of caches?
🎨 Start improving theme lib's API
Still TODO: simplifying/clarifying:
- what is the structure of the internal list
- what is the difference between a package list, and a theme list?
- what is the difference between reading a theme and loading it?
- how do we update the theme list (add/remove)
- how do we refresh the theme list? (hot reload?!)
- how do we get from an internal list, to one that is sent as part of the API?
- how are we going to handle theme storage: read/write, such that the path is configurable
🎨 Use themeList consistently
🎨 Update list after storage
no issue
- if knex-migrator loads the MigratorConfig too much stuff was required, which increases the memory usage
- i have deleted the IncorrectUsage errors for now, because this error should actually never appear
closes#8056🎨 Collect together the package-related utils
- read directory actually reads a directory of packages
- parse package json is very tighly related to this
🎨 Move filterPaths -> packages.filterPackages
- this function is related to packages, not settings
- move the function to the new utils/packages
- add 100% test coverage
🎨 Simplify filterPackages code
🎨 Simplify reading of packages & themes
- This massively reduces all the complex code in the read packages & themes utils
- Added full test coverage
🎨 Improve & clarify active prop in filterPackages
- active is returned from API endpoints to combine data from multiple sources
- see https://github.com/TryGhost/Ghost/pull/8064#discussion_r103514810🎨 Better error handling
🔥 Temporarily remove custom error templates
- we will reimplement this later when we have got a better concept of loading the active theme in place
- refs #8079
no issue
🔥 remove unused loadThemes API method
🚨 Add tests for themes.readOne
🔥 Don't update settings cache for imports
- this isn't needed as of #8057
- settings.edit fires an event, that will result in the update happening automatically
🎨 Move validation to themes
- slowly collecting all theme-related code together
🔥 Reduce DEBUG output
- all this info is a bit tooooo much!
closes#8037🔥 Remove API-level default settings population
- This is a relic!
- We ALWAYS populate defaults on server start therefore this code could never run.
- This was a lot of complicated code that wasn't even needed!!
🎨 Move settings cache
- Move settings cache to be its own thing
- Update all references
- Adds TODOs for further cleanup
🎨 Create settings initialisation step
- Create new settings library, which will eventually house more code
- Unify the interface for initialising settings (will be more useful later)
- Reduce number of calls to updateSettingsCache
* ✨ ghost auth: sync email
refs #7452
- sync email changes in background (every hour right now)
- sync logged in user only!
- no sync if auth strategy password is used
- GET /users/me is triggered on every page refresh
- added TODO to support or add long polling for syncing data later
- no tests yet on purpose, as i would like to get a basic review first
* 🐩 use events
- remember sync per user
no issue
* ✨ Add new server start & stop events
* 🔥 Get rid of unused availableApps concept
- when we need an API endpoint for a list of apps, we'll build one 😝
* ✨ Move theme loading into a module
- move loading from API method to a module method and use as needed
- wire up read one vs read all as per LTS
- read one (the active theme) on boot, and read the rest after
- fudge validation - this isn't all that helpful
* Settings API tests need to preload themes
- this used to automatically happen as part of loading settings
- now we need to trigger this to happen specifically for this test
refs #7432🚨 database: change hard limits and field types
- we went over all schema fields and decided to decrease/increase the hard limits
- the core goal is to have more flexibility in the future
- we reconsidered string vs. text
There are 5 groups:
- small strings: 50 characters
- static strings
- status, visibility, language, role name, permission name, client name etc.
- medium strings: 191 characters
- all unique fields or fields which can be unique in the future
- slug, tokens, user name, password, tag name, email
- large strings: 1000-2000 characters
- these fields need to be very flexible
- these fields get a soft limit attached (in a different PR)
- post title, meta title, meta description, urls
- medium text: 64kb characters
- bio, settings, location, tour
- long text: 1000000000 chars
- html, amp, mobiledoc, markdown
🙄 sort_order for tests
- sort order was not set for the tests, so it was always 0
- mysql could return a different result
in my case:
- field length 156 returned the following related tags ["bacon", "kitchen"]
- field length 157 returned the following related tags ["kitchen", "kitchen"]
Change client.secret to 191
Tweak field lengths
- Add 24 char limit for ids
- Limited fields are the exact length they need
- Unified 1000 and 2000 char string classes to all be 2000
- Changed descriptions to be either 2000, except user & tag which is text 65535 as these may be used to store HTML later?!
- Updated tests
🛠 Update importer tests
- The old 001-003 tests are kind of less relevant now.
- Rather than worrying about past versions of the data structure, we should check that the importer only imports what we consider to be valid data
- I've changed the tests to treat the title-length check as a length-validation check, rather than a test for each of the old versions
🔥 Remove foreign key from subscribers.post_id
- There's no real need to have an index on this column, it just makes deleting posts hard.
- Same as created_by type columns, we can reference ids without needing keys/indexes
refs #2182
* 🔥 Remove unused options from server init
- this is left over from old code and is now unused
* 🎨 Move knex-migrator check to db health
- Move complex check function into own module
- Call module from server/index.js
- This just improves the readability of server/index.js
* 🔥 Remove old comments
- These comments all make no sense now!
* 🎨 ⏱ Move model init out of promise chain
- Model.init() does not return a promise
- Therefore, we can move it to the top of the init function, outside of the promise change
- This should be a minor optimisation, and again improves readability /clarity of what's happening
* ✨⁉️ Move DBHash init / first run to Settings model
- this structure is left over from when we had code we executed on the first run of Ghost
- the implementation used the API to initialise one setting before populateDefaults is called
- this had lots of dependencies - the whole model, API, and permissions structure had to be initialised for it to work
- the new implementation is simpler, it captures the dbHash getting initialised during populateDefaults()
- it also adds an event, so we can do first-run code later if we really want to (or maybe apps can?!)
- perhaps this is hiding behaviour, and there's a nicer way to do it, but populateDefaults seems like a sane place to populate a default setting 😁
* ⏱ Optimise require order so config is first
- the first require to config will cause the files to be read etc
- this ensures that it happens early, and isn't confusingly timed as part of loading a different module
* 🎨 Simplify settings model changes
refs #2182
* ⏱ Add boot timer - improve visibility of boot time
I've been playing around with Ghost start times a lot recently.
Every time I do, I add a console.time output for boot, which is annoying.
This commit adds that change permanently. We can always revert later before shipping 1.0 😁
* ⏱ Add debug call before main requires
- this demonstrates that the majority of boot time is spent on requires
- had to rejig the var pattern because of the linter... 💩
* 🐷💄 Special debug mode for config
- I ❤️ being able to output the config, but this is not useful when trying to debug / optimise timings.
- This change makes it so we can see how long it takes to do config work by default
- If we want to output config specifically, we do `DEBUG=ghost:*,ghost-config npm start`
- This also prevents nconf.get() from being called unnecessarily
no issue
- we have to remember the auth url in Ghost
- if Ghost starts for the first time, it registers a public client in the defined auth service
- if you change the auth service, Ghost won't recognize
- if Ghost doesn't recognize, you will see a client does not exist error in Ghost Admin
no issue
- auth.init happens in background and if an error occurs, Ghost will log this error to stdout/file
- do not double create Ignition error
- update passport-ghost to handle a none response from the auth service (e.g. wrong auth url), see 123da4dd94
* 🎨 update configuration files: database
refs #7488
- no default database configuration
- production: default is MySQL
* 🎨 add transport stdout to production for now
refs #7488
- production will log to stdout and file for now
- to reduce the risk of confusing users
- users would not see any stdout and they don't know that Ghost logs into file only in production
* 🎨 sanitize database properties
refs #7488
ServiceWorkers can only control the scope from which they have been served. Our service workers live, like all other files, in an `asset` folder - and could in theory only work on other files in there.
This commit fake-serves our service workers from `/ghost/`, thus allowing them to give everything offline powers.
refs #7488
- we have recently changed our url redirects
- see https://github.com/TryGhost/Ghost/pull/7937
- the url has a canonical meaning and that's why Ghost shouldn't force redirect to the blog url
closes#7256
- original code changes made by @golya in https://github.com/TryGhost/Ghost/pull/7304
- refactored edit method in user model to validate an existing email address
- added test coverage for existing email update in user model spec
no issue
- we had two middlewares:
1. url-redirects
2. redirects
- this was confusing, so i renamed (2) to custom redirects
custom-redirects.js: you can define custom redirects for your blog in a JSON file
url-redirects.js: Ghost takes care of required admin url or SSL redirects
no issue
- the update check service now supports a LTS option
- sending lts=false will force the update check service to search for the latest non LTS release
- as 1.0.0 is still in alpha, there is no latest release available
- that's why the update check service returns an error saying, there is no latest release available
- this error get's logged to shell right now
- as soon as we release 1.0.0, the error auto disappears
No behaviour change in any previous alpha version or any LTS release as they don't send the LTS option.
refs #7707
- be able to add a custom redirect file into the content folder
- define redirects as JSON format
The redirects feature is already present in the LTS branch.
I was not able to cherry-pick over, too many changes or conflicts.
Creating a PR to ensure 1. tests pass and 2. overview of code changes.
I had to add an example active theme to our test fixture utils, because otherwise Ghost will complain when forking Ghost.
* 🔥 kill apiUrl helper, use urlFor helper instead
More consistency of creating urls.
Creates an easier ability to add config changes.
Attention: urlFor function is getting a little nesty, BUT that is for now wanted to make easier and centralised changes to the configs.
The url util need's refactoring anyway.
* 🔥 urlSSL
Remove all urlSSL usages.
Add TODO's for the next commit to re-add logic for deleted logic.
e.g.
- cors helper generated an array of url's to allow requests from the defined config url's -> will be replaced by the admin url if available
- theme handler prefered the urlSSL in case it was defined -> will be replaced by using the urlFor helper to get the blog url (based on the request secure flag)
The changes in this commit doesn't have to be right, but it helped going step by step.
The next commit is the more interesting one.
* 🔥✨ remove forceAdminSSL, add new admin url and adapt logic
I wanted to remove the forceAdminSSL as separate commit, but was hard to realise.
That's why both changes are in one commit:
1. remove forceAdminSSL
2. add admin.url option
- fix TODO's from last commits
- rewrite the ssl middleware!
- create some private helper functions in the url helper to realise the changes
- rename some wordings and functions e.g. base === blog (we have so much different wordings)
- i would like to do more, but this would end in a non readable PR
- this commit contains the most important changes to offer admin.url option
* 🤖 adapt tests
IMPORTANT
- all changes in the routing tests were needed, because each routing test did not start the ghost server
- they just required the ghost application, which resulted in a random server port
- having a random server port results in a redirect, caused by the ssl/redirect middleware
* 😎 rename check-ssl middleware
* 🎨 fix theme-handler because of master rebase
* 🎨🔥 do not store settings in config and make settings cache easier available
- remove remembering settings value in theme config
- if we need a cache value, we are asking the settings cache directly
- instead of settings.getSettingSync we use settings.cache.get
- added TODO:
- think about moving the settings cache out of api/settings
- we could create a folder named cache cache/settings
- this settings cache listens on model changes for settings
- decoupling
* 🔥 remove timezone from config
- no need to store in overrides config and in defaults settings
* 🎨 context object helper
- replace config.get('theme') by settings cache
* 🎨 replace config.get('theme') by settings.cache.get
* 🎨 adapt tests
* fixes from comments
refs #7488
- to be able to refactor the url configuration in ghost, we need to go step by step making this possible
- reduce the usage of forceAdminSSL
- add a urlFor('admin') helper, which returns the admin url + path e.g. http://my-blog.com/blog/ghost
- increase usage of urlFor helper
- do not expose getBaseUrl, use urlFor('home') (home === blog)
refs #7488
- rename file keys for config files, see https://github.com/TryGhost/Ghost/pull/7493/files
- add tests to avoid running into config hierarchy problems again
- overrides.json is the strongest!
- argv/env can override any default
- custom config can override defaults
- reorganise util functions for config again
closes#7866
- Importer now uses Javascript's Map instead of the normal object to ensure that tags are properly associated with their corresponding posts.
refs #7688
Update the `ghost_head_spec` to reflect the current changes (we're not having a default `icon` setting in our config anymore). Render the link to the default favicon to be relative.
closes#7688
- Use `/favicon.ico` and `/favicon.png` in blog app. Depending on type of storage (custom upload = local file storage), serves either from storage adapter with `read()` method or reads the bytes via `fs`.
- Redirects requests for `favicon.ico` to `favicon.png` if custom `png` icon is uploaded and vice versa.
- Redirect requests for `favicon.png` to `favicon.ico` if default icon is used (in `core/shared`).
- Changes the `{{asset}}` helper for favicon to not serve from theme assets anymore. It will either be served the custom blog-icon or the default one.
- The `{{@blog.icon}}` helper renders the url of the **uploaded** blog icon. It won't render the default icon.
refs #7489
- as we are now using a different migration approach (knex-migrator), we don't need to remember the database version anymore
- it was once used to check the state of a database and based on it we decided to migrate or not
- with knex-migrator everything depends on the migration table entries and the current ghost version you are on
- on current master the leftover usage is to add the db version when exporting the database, which can be replaced by reading the ghost version
- removing this solves also an interesting migration case with knex-migrator:
- you are on 1.0
- you update to 1.1, but 1.1 has no migrations
- the db version would remain in 1.0
- because the db version was only updated when knex migrator executed a migration
refs #7688
Adds an `uploads/icon/` endpoint to the api route to get a seperate entry point for blog icon validations. The blog icon validation will specifically check for images which have icon extensions (`.ico` & `.png`) and throw errors if:
- the icon file size is too big (>100kb)
- the icon is not a squaer
- the icon size is smaller than 32px
- the icon size is larger than 1000px
- the icon is not `.ico` or `.png` extension
TODOs for this PR:
- [X] get image dimensions
- [X] validate for image
- [X] size
- [X] form (must be square)
- [X] type
- [X] dimenstion (min 32px and max 1,000px)
- [X] return appropriate error messages
- [X] write tests
--------------------
TODOs for #7688:
- [X] Figure out, which favicon should be used (uploaded or default) -> #7713
- [ ] Serve and redirect the favicon for any browser requests, incl. redirects -> #7700 [WIP]
- [X] Upload favicon via `general/settings` and implement basic admin validations -> TryGhost/Ghost-Admin#397
- [X] Build server side validations -> this PR
no issue
- if re-running the init scripts (for example: you lost the init rows in the migrations table), then it was throwing errors
- 1. the owner slug and email can change -> no match and it tried to reinsert the user with id 1, which failed
- 2. querying an inactive user is not allowed, because the user model protects against it
refs #7489
The require path for the db backup was wrong. The before hook could not execute db backup.
Furthermore, i have replaced the logging in the backup script.
refs #7724
- we already fixed the permissions for the editor
- see 3d3101ad0e
- but as we are inside of a refactoring process, we had two fixtures.json files
- we fixed the fixtures.json in the wrong place
- now that the permissions are used, we can see failing tests
- i have added the correct permissions handling
closes#7766, refs #7579
- ensure we are using the correct brute keys
- ensure we are using req.ip as Ghost is configured with trust proxy option
- tidy up a little
no issue
- we started implementing logging and error handling in Ghost
- later we outsourced both into a module
- use the module now in Ghost
- this commit basically just removes the logging and error implementation and uses Ignition
refs #7688
Adds logic in theme settings api to either serve an uploaded favicon and give it the type `upload` or use the default settings `default`, which will serve the favicon from our shared directory.
TODOs for #7688:
- [X] Figure out, which favicon should be used (uploaded or default) -> this PR
- [ ] Serve and redirect the favicon for any browser requests, incl. redirects
- [ ] Upload favicon via `general/settings` and implement basic admin validations -> [WIP] TryGhost/Ghost-Admin#397
- [ ] Built server side validations
refs #7666
Using `urlFor('home')` instead `config.get('url')` in Ghost.
When `urlFor('home', true)` returns the absolute adress of the blog as defined in the config.
Will always return a trailing `/`.
closes#7839
- when a browser sends a request to the API without a trailing slash, we are using connect-slashes to redirect permanently
- but because the CORS middleware was registered after the redirect, the CORS headers got lost
closes#7769
Because Google AMP is bitching around and shows errors in Googles' webmaster tools for missing post images and blog icons, we decided to make AMP optional. It will be enabled by default, but can be disabled in general settings. Once disabled, the `amp` route doesn't work anymore.
This PR contains the back end changes for Ghost-alpha:
- Adds `amp` to settings table incl default setting `true`
- Adds `amp` value to our settings cache
- Changes the route handling of AMP app to check for the `amp` setting first.
- Adds tests to check the route handling and ghost_head output
- Includes changes to `post-lookup.js` as done by @kirrg001 in #7842
closes#7826
- expose raw url value inside `{{navigation}}` helper
- modify `{{url}}` helper to urlencode values and mark as HTML-safe to avoid Handlebars additional HTML-escaping
no issue
Expand the existing validation for subscriber email to not only check for the existence, but also if it's a valid email address. If it's not a valid email address, it will throw an error.
Credits: Eliran Itzhak & Shashank Kumar
* 🛠 bookshelf tarball, bson-objectid
* 🎨 schema changes
- change increment type to string
- add a default fallback for string length 191 (to avoid adding this logic to every single column which uses an ID)
- remove uuid, because ID now represents a global resource identifier
- keep uuid for post, because we are using this as preview id
- keep uuid for clients for now - we are using this param for Ghost-Auth
* ✨ base model: generate ObjectId on creating event
- each new resource get's a auto generate ObjectId
- this logic won't work for attached models, this commit comes later
* 🎨 centralised attach method
When attaching models there are two things important two know
1. To be able to attach an ObjectId, we need to register the `onCreating` event the fetched model!This is caused by the Bookshelf design in general. On this target model we are attaching the new model.
2. We need to manually fetch the target model, because Bookshelf has a weird behaviour (which is known as a bug, see see https://github.com/tgriesser/bookshelf/issues/629). The most important property when attaching a model is `parentFk`, which is the foreign key. This can be null when fetching the model with the option `withRelated`. To ensure quality and consistency, the custom attach wrapper always fetches the target model manual. By fetching the target model (again) is a little performance decrease, but it also has advantages: we can register the event, and directly unregister the event again. So very clean code.
Important: please only use the custom attach wrapper in the future.
* 🎨 token model had overriden the onCreating function because of the created_at field
- we need to ensure that the base onCreating hook get's triggered for ALL models
- if not, they don't get an ObjectId assigned
- in this case: be smart and check if the target model has a created_at field
* 🎨 we don't have a uuid field anymore, remove the usages
- no default uuid creation in models
- i am pretty sure we have some more definitions in our tests (for example in the export json files), but that is too much work to delete them all
* 🎨 do not parse ID to Number
- we had various occurances of parsing all ID's to numbers
- we don't need this behaviour anymore
- ID is string
- i will adapt the ID validation in the next commit
* 🎨 change ID regex for validation
- we only allow: ID as ObjectId, ID as 1 and ID as me
- we need to keep ID 1, because our whole software relies on ID 1 (permissions etc)
* 🎨 owner fixture
- roles: [4] does not work anymore
- 4 means -> static id 4
- this worked in an auto increment system (not even in a system with distributed writes)
- with ObjectId we generate each ID automatically (for static and dynamic resources)
- it is possible to define all id's for static resources still, but that means we need to know which ID is already used and for consistency we have to define ObjectId's for these static resources
- so no static id's anymore, except of: id 1 for owner and id 0 for external usage (because this is required from our permission system)
- NOTE: please read through the comment in the user model
* 🎨 tests: DataGenerator and test utils
First of all: we need to ensure using ObjectId's in the tests. When don't, we can't ensure that ObjectId's work properly.
This commit brings lot's of dynamic into all the static defined id's.
In one of the next commits, i will adapt all the tests.
* 🚨 remove counter in Notification API
- no need to add a counter
- we simply generate ObjectId's (they are auto incremental as well)
- our id validator does only allow ObjectId as id,1 and me
* 🎨 extend contextUser in Base Model
- remove isNumber check, because id's are no longer numbers, except of id 0/1
- use existing isExternalUser
- support id 0/1 as string or number
* ✨ Ghost Owner has id 1
- ensure we define this id in the fixtures.json
- doesn't matter if number or string
* 🎨 functional tests adaptions
- use dynamic id's
* 🎨 fix unit tests
* 🎨 integration tests adaptions
* 🎨 change importer utils
- all our export examples (test/fixtures/exports) contain id's as numbers
- fact: but we ignore them anyway when inserting into the database, see https://github.com/TryGhost/Ghost/blob/master/core/server/data/import/utils.js#L249
- in 0e6ed957cd (diff-70f514a06347c048648be464819503c4L67) i removed parsing id's to integers
- i realised that this ^ check just existed, because the userIdToMap was an object key and object keys are always strings!
- i think this logic is a little bit complicated, but i don't want to refactor this now
- this commit ensures when trying to find the user, the id comparison works again
- i've added more documentation to understand this logic ;)
- plus i renamed an attribute to improve readability
* 🎨 Data-Generator: add more defaults to createUser
- if i use the function DataGenerator.forKnex.createUser i would like to get a full set of defaults
* 🎨 test utils: change/extend function set for functional tests
- functional tests work a bit different
- they boot Ghost and seed the database
- some functional tests have mis-used the test setup
- the test setup needs two sections: integration/unit and functional tests
- any functional test is allowed to either add more data or change data in the existing Ghost db
- but what it should not do is: add test fixtures like roles or users from our DataGenerator and cross fingers it will work
- this commit adds a clean method for functional tests to add extra users
* 🎨 functional tests adaptions
- use last commit to insert users for functional tests clean
- tidy up usage of testUtils.setup or testUtils.doAuth
* 🐛 test utils: reset database before init
- ensure we don't have any left data from other tests in the database when starting ghost
* 🐛 fix test (unrelated to this PR)
- fixes a random failure
- return statement was missing
* 🎨 make changes for invites
* 🎨 schema change
- simply role_id attribute
* 🎨 update invite model
- remove all methods we don't need
- ensure we remove the relation from the model
- ensure we do not allow to call withRelated
* 🎨 adapt api changes
* 🎨 adapt auth module
* 🎨 adapt tests
* 🎨 better error handling
* schema update
- see https://github.com/AdamPflug/express-brute/issues/45
- we have to handle two cases ATM: with and without callback
- in case we call the lib synchronous (which we should not actually), we will log the error so we get informed
- i thought of keeping our schema, because it might be less confusing
- it's basically the same config brute-knex uses as default
- see last commit why we are using this type definition
refs #7494, refs #7495
I saw tests adding permissions and roles twice. (see screenshots)
That happened because the setup in the test was mis-used and there is no restriction for static resources to create duplicates.
With this PR i suggest to make name unique.
refs #7494, refs #7495
This PR is an extracted clean up feature of #7495.
We are using everywhere static id checks (userId === 0 or userId === 1).
This PR moves the static values into the Base model.
This makes it 1. way more readable and 2. we can change the id's in a central place.
I changed the most important occurrences - no tests are touched (yet!).
The background is: when changing from auto increment id (number) to ObjectId's (string) we still need to support id 1 and 0, because Ghost relies on these two static id's.
I would like to support using both: 0/1 as string and 0/1 as number.
1 === owner/internal
0 === external
Another important change:
User Model does not longer define the contextUser method, because i couldn't find a reason?
I looked in Git history, see 6e48275160
no issue
- in Ignition we have added keeping the original stack, i copied it over
- i would like to use Ignition in Ghost asap to avoid having inconsistencies
- added support for options.err is a string
- extend tests
* 🎨 use updateClient function to update redirectUri
refs #7654
* 🎨 name instead of clientName
* 🎨 config.get('theme:title') for client name
- initial read can happen from config
* ✨ register public client: client name and description
- no update yet
- for initial client creation
- we forward title/description to Ghost Auth
- TODO: use settings-cache when merged
* ✨ store blog_uri in db
* 🎨 passport logic changes
- use updateClient instead of changeCallbackURL
- be able to update: blog title, blog description, redirectUri and blogUri
- remove retries, they get implemented in passport-ghost soon
- reorder logic a bit
* 🛠 passport-ghost 1.2.0
* 🎨 tests: extend DataGenerator createClient
- set some defaults
* 🎨 tests
- extend tests
- 👻
* ✨ run auth.init in background
- no need to block the bootstrap process
- if client can't be registered, you will see an error
- ensure Ghost-Admin renders correctly
* 🛠 passport-ghost 1.3.0
- retries
* 🎨 use client_uri in Client Schema
- adapt changes
- use blog_uri only when calling the passport-ghost instance
- Ghost uses the client_uri notation to improve readability
* ✨ read blog title/description from settings cache
* 🚨 Ghost Auth returns email instead of email_address
- adapt Ghost
* 🎨 settingsCache is available
- do not destroy the object reference
- added TODO to reconsider the config values for theme
- get one or all cached settings
* 🚨 remove api.init
- this functiion has just wrapped a function to update the settings cache
- if we have multiple tasks todo later, we can re-add
- but for now: this is way easier to read
- adapt test
* 🎨 tests
no issue
- removes count from user checks model
- uses brute express brute with brute-knex adaptor to store persisted data on spam prevention
- implement brute force protection for password/token exchange, password resets and private blogging
* 🎨 knex-migrator reset
[ci skip]
* ✨ add migration example
- hooks
- 1.0
[ci skip]
* 🛠 knex-migrator tarball
- remove when released
[ci skip]
* 🎨 jscs/jshint
* 🕵🏻 do not drop the database connection when running tests
- please read the comments in the commit
* 🔥 remove example migration
* 🛠 knex-migrator 0.1.0
* 🛠 knex-migrator 0.1.1
- fix a single test to ensure we catch the error
* 🛠 knex-migrator 0.1.2
* 🎨 make tests green
- added my keyword: kate-migrations
- i will go over all TODO's when removing the old migrations code
* 🛠 knex-migrator update
* 🛠 knex-migrator 0.2.0
* 🔥 remove User model functions
- validateToken
- generateToken
- resetPassword
- all this logic will re-appear in a different way
Token logic:
- was already extracted as separate PR, see https://github.com/TryGhost/Ghost/pull/7554
- we will use this logic in the controller, you will see in the next commits
Reset Password:
Was just a wrapper for calling the token logic and change the password.
We can reconsider keeping the function to call: changePassword and activate the status of the user - but i think it's fine to trigger these two actions from the controlling unit.
* 🔥 remove password reset tests from User model
- we already have unit tests for change password and the token logic
- i will re-check at the end if any test case is missing - but for now i will just burn the tests
* ✨ add token logic to controlling unit
generateResetToken endpoint
- the only change here is instead of calling the User model to generate a token, we generate the token via utils
- we fetch the user by email, and generate a hash and return
resetPassword endpoint
- here we have changed a little bit more
- first of all: we have added the validation check if the new passwords match
- a new helper method to extract the token informations
- the brute force security check, which can be handled later from the new bruteforce middleware (see TODO)
- the actual reset function is doing the steps: load me the user, compare the token, change the password and activate the user
- we can think of wrapping these steps into a User model function
- i was not sure about it, because it is actually part of the controlling unit
[ci skip]
* 🎨 tidy up
- jscs
- jshint
- naming functions
- fixes
* ✨ add a test for resetting the password
- there was none
- added a test to reset the password
* 🎨 add more token tests
- ensure quality
- ensure logic we had
* 🔥 remove compare new password check from User Model
- this part of controlling unit
* ✨ compare new passwords for user endpoint
- we deleted the logic in User Model
- we are adding the logic to controlling unit
* 🐛 spam prevention forgotten can crash
- no validation happend before this middleware
- it just assumes that the root key is present
- when we work on our API, we need to ensure that
1. pre validation happens
2. we call middlewares
3. ...
* 🎨 token translation key
refs #7449, refs #7514, refs #7643
- We've had a couple of issues raised, and a few people in #help all report the same error:
> Cannot read property 'zone' of undefined
When starting Ghost.
I'm not sure why this seems to work sometimes, and not others, however it would seem that we
should require moment-timezone anywhere we want to use timezone features.
This PR fixes the LOC shown in #7449 as the problem line + I searched for any other potential problems
closes#7628
With this PR we expose a public configuration endpoint.
When /ghost is requested, we don't load and render the configurations into the template anymore. Instead, Ghost-Admin can request the public configuration endpoint.
* 🎨 make configuration endpoint public
* 🔥 remove loading configurations in admin app
- do not render them into the default html page
* ✨ load client credentials in configuration endpoint
- this is not a security issue, because we have exposed this information anyway before (by rendering them into the requested html page)
* 🎨 extend existing configuration integration test
* ✨ tests: add ghost-auth to data generator
* ✨ add functional test
* 🔥 remove type/value pattern
* 🎨 do not return stringified JSON objects
* 🎨 rotation config
- every parameter is configureable
- increase default number of files to 100
* 🎨 ghost.log location
- example: content/logs/http___my_ghost_blog_com_ghost.log
- user can change the path to something custom by setting logging.path
* 🛠 add response-time as dependency
* 🎨 readable PrettyStream
- tidy up
- generic handling (was important to support more use cases, for example: logging.info({ anyKey: anyValue }))
- common log format
- less code 🕵🏻
* 🎨 GhostLogger cleanup
- remove setLoggers -> this function had too much of redundant code
- instead: add smart this.log function
- remove logging.request (---> GhostLogger just forwards the values, it doesn't matter if that is a request or not a request)
- make .warn .debug .info .error small and smart
* 🎨 app.js: add response time as middleware and remove logging.request
* 🎨 setStdoutStream and setFileStream
- redesign GhostLogger to add CustomLoggers very easily
----> Example CustomLogger
function CustomLogger(options) {
// Base iterates over defined transports
// EXAMPLE: ['stdout', 'elasticsearch']
Base.call(this, options);
}
util.inherits(...);
// OVERRIDE default stdout stream and your own!!!
CustomLogger.prototype.setStdoutStream = function() {}
// add a new stream
// get's called automatically when transport elasticsearch is defined
CustomLogger.prototype.setElasticsearchStream = function() {}
* 🎨 log into multiple file by default
- content/logs/domain.error.log --> contains only the errors
- content/logs/domain.log --> contains everything
- rotation for both files
* 🔥 remove logging.debug and use npm debug only
* ✨ shortcuts for mode and level
* 🎨 jshint/jscs
* 🎨 stdout as much as possible for an error
* 🎨 fix tests
* 🎨 remove req.ip from log output, remove response-time dependency
* 🎨 create middleware for logging
- added TODO to move logging middleware to ignition
* ✨ id for each error instance
- copy paste of ignition
- on purpose for now
- delete TODO, wohoo
- use id property instead of uid, see http://jsonapi.org/format/#errors
* 🕵🏻 remove TODO for decouple req.err
- can't find a nicer alternative solution
- added some more descriptions to code pieces in our error-handler
* 🎨 use uuid.v1
- timestamp based
no issue
- add tests for makePathsAbsolute
- add support for windows paths
When Ghost-CLI inits the database of the current GhostVersion (in /current), then it uses knex-migrator to do that.
Knex migrator is reading the .knex-migrator file of the current Ghost version. This returns a relative path to the database location.
The problem: knex-migrator will init the database in the root folder of Ghost-CLI /content/data instead of /current/content . And when you start Ghost (ghost start), it always complains that
that database is not initialised, because it expects the database in /current/content...
* 🎨 move config_spec to config/index_spec
- add one more test case
* 🎨 one token endpoint
refs #7562
- delete /authentication/ghost
- Ghost-Admin will use /authentication/token for all use cases (password, refresh token and ghost.org authorization code)
- add new grant_type `authorization_code`
* 🎨 update comment description and remove spamPrevention.resetCounter
* 🎨 do not call generateSlug twice for User.setup
* 🎨 call generatePasswordHash onSaving only
- now we can add defaults to User Model
- it was not possible before because add User model did the following:
1. validate password length
2. hash password manually
3. call ghostBookshelf.Model.add and THEN bookshelf defaults fn gets triggered
- call generatePasswordHash in onSaving hook for all use case
- add more tests to user model, juhu
refs #7432
- all models implemented it's own initialize fn to register events
- we can register all events in the base model
- important: we only listen on the event, if the model has defined a hook for it
- this is just a small clean up PR
- register more bookshelf events
closes#4172, closes#6948, refs #7491, refs #7488, refs #7542, refs #7484
* 🎨 Co-locate all admin-related code in /admin
- move all the admin related code from controllers, routes and helpers into a single location
- add error handling middleware explicitly to adminApp
- re-order blogApp middleware to ensure the shared middleware is mounted after the adminApp
- TODO: rethink the structure of /admin, this should probably be an internal app
* 💄 Group global middleware together
- There are only a few pieces of middleware which are "global"
- These are needed for the admin, blog and api
- Everything else is only needed in one or two places
* ✨ Introduce a separate blogApp
- create a brand-new blogApp
- mount all blog/theme only middleware etc onto blogApp
- mount error handling on blogApp only
* 🎨 Separate error handling for HTML & API JSON
- split JSON and HTML error handling into separate functions
- re-introduce a way to not output the stack for certain errors
- add more tests around errors & an assertion framework for checking JSON Errors
- TODO: better 404 handling for static assets
Rationale:
The API is very different to the blog/admin panel:
- It is intended to only ever serve JSON, never HTML responses
- It is intended to always serve JSON
Meanwhile the blog and admin panel have no need for JSON errors,
when an error happens on those pages, we should serve HTML pages
which are nicely formatted with the error & using the correct template
* 🐛 Fix checkSSL to work for subapps
- in order to make this work on a sub app we need to use the pattern `req.originalUrl || req.url`
* 🔥 Get rid of decide-is-admin (part 1/2)
- delete decide-is-admin & tests
- add two small functions to apiApp and adminApp to set res.isAdmin
- mount checkSSL on all the apps
- TODO: deduplicate the calls to checkSSL by making blogApp a subApp :D
- PART 2/2: finish cleaning this up by removing it from where it's not needed and giving it a more specific name
Rationale:
Now that we have both an adminApp and an apiApp,
we can temporarily replace this weird path-matching middleware
with middleware that sets res.isAdmin for api & admin
* 🎨 Wire up prettyURLs on all Apps
- prettyURLs is needed for all requests
- it cannot be global because it has to live after asset middleware, and before routing
- this does not result in duplicate redirects, but does result in duplicate checks
- TODO: resolve extra middleware in stack by making blogApp a sub app
* ⏱ Add debug to API setup
* 🎨 Rename blogApp -> parentApp in middleware
* 🎨 Co-locate all blog-related code in /blog
- Move all of the blogApp code from middleware/index.js to blog/app.js
- Move routes/frontend.js to blog/routes.js
- Remove the routes/index.js and routes folder, this is empty now!
- @TODO is blog the best name for this? 🤔
- @TODO sort out the big hunk of asset-related mess
- @TODO also separate out the concept of theme from blog
* 🎉 Replace middleware index with server/app.js
- The final piece of the puzzle! 🎉🎈🎂
- We no longer have our horrendous middleware/index.js
- Instead, we have a set of app.js files, which all use a familiar pattern
* 💄 Error handling fixups
no issue
- preperation for User model refactoring
- add independent util to generate reset hash, compare a hash and extract information out of it
- this code is basically a copy/paste of User model (generateResetToken, validateToken)
no issue
- preperation for User model refactoring
- the rule is:
--> when calling a unit, this unit should return something new
--> and NOT modifying an existing object and return it (this is an unexpected behaviour, especially for utils and libs)
refs #7555
- temporary fix to make travis green
- that should not have a any bad effect on scheduling
- we just let the job awake a bit later
- the job logic is strong enough to catch the job if setTimeout awakes too late (that can happen, because setTimeout is not accurate)
- if (moment().diff(moment(Number(timestamp))) <= self.beforePingInMs) --> is smaller ensures that even if the diff is negative, it get's executed
* 🎨 move heart of fixtures to schema folder and change user model
- add fixtures.json to schema folder
- add fixture utils to schema folder
- keep all the logic!
--> FIXTURE.JSON
- add owner user with roles
--> USER MODEL
- add password as default
- findAll: allow querying inactive users when internal context (defaultFilters)
- findOne: do not remove values from original object!
- add: do not remove values from original object!
* 🔥 remove migrations key from default_settings.json
- this was a temporary invention for an older migration script
- sephiroth keep alls needed information in a migration collection
* 🔥 add code property to errors
- add code property to errors
- IMPORTANT: please share your opinion about that
- this is a copy paste behaviour of how node is doing that (errno, code etc.)
- so code specifies a GhostError
* 🎨 change error handling in versioning
- no need to throw specific database errors anymore (this was just a temporary solution)
- now: we are throwing real DatabaseVersionErrors
- specified by a code
- background: the versioning unit has not idea about seeding and population of the database
- it just throws what it knows --> database version does not exist or settings table does not exist
* 🎨 sephiroth optimisations
- added getPath function to get the path to init scripts and migration scripts
- migrationPath is still hardcoded (see TODO)
- tidy up database naming to transacting
* ✨ migration init scripts are now complete
- 1. add tables
- 2. add fixtures
- 3. add default settings
* 🎨 important: make bootup script smaller!
- remove all TODO'S except of one
- no seeding logic in bootup script anymore 🕵🏻
* ✨ sephiroth: allow params for init command
- param: skip (do not run this script)
- param: only (only run this script)
- very simple way
* 🎨 adapt tests and test env
- do not use migrate.populate anymore
- use sephiroth instead
- jscs/jshint
* 🎨 fix User model status checks
no issue
When using Ghost OAuth, exchanging the authorization code for an access token was returning a token along with an `expires_in` property containing a JavaScript date representation rather than the number of seconds the token is valid for. This was resulting in the client expecting it's access token to be valid until the year 48796(!) and so never attempting to refresh it's access_token.
- return token expiration time of 3600 seconds / 1hr
closes#6629
- i had the case that in gravatar process.env.NODE_ENV was undefined and indexOf of undefined crashe my application
- so always use config to read current env
refs #7489
* 🎨 protect error when creating owner
* 🎨 reset migration table
- temporary solution, see TODO's
* 🎨 use sephiroth in bootUp script
- do not populate the database
- ask sephiroth for database state
- do seeding manually (this will be removed in next seeding PR)
* 🎨 rewrite createTableIfNotExists because it causes error when running twice
- see knex issue
- hasTable and createTable
- indexes can cause trouble when calling them twice
* 🎨 tests: populate db in test env
- when forking db
- when starting ghost()
- this basically affects only the functional tests
* 🎨 server spec test adaption
- we now throw an error when database is not populated, instead of populating the database
* 🎨 migration spec adaption
- reset database now deletes migration table
- we will move the reset script into sephiroth and then we make it pretty
* 🎨 error creation adaption in bootUp
* 🎨 fixes
- sephiroth error handling
- fix tests
refs #4172
* 🎨 Use bodyParser only where it is needed
This is a pretty extreme optimisation, however in the interests of killing middleware/index.js it
seemed prudent to move towards not having in there that wasn't strictly necessary 😁
We should reassess how apps do this sort of thing, but it seems pretty sane to declare bodyParsing
if and only if it is necessary.
* 🎨 Move all API code to API router
* 🎨 Refactor API into an App, not just a router
- Apps have their own rendering engines, only the frontend & the admin panel need views
- The API should be JSON only, with minimal middleware
- Individual sections within the API could/should be treated as Routers
* 🎨 Flatten API middleware inclusion
- get rid of the weird middleware object
- move the api-only middleware into the middleware/api folder
- we can see the logging mode as HTTP mode
- standalone logging should still log everything
- tidy up the PrettyStreamer a little big and add current expectation tests
* 💄 Combine slashes & uncapitalise middleware
- these bits of middleware belong together
- ideally they should be optimised
* 🎨 Move ghostLocals out of themeHandler
GhostLocals sets several important values which are needed for every part of the application,
admin, api and theme. Therefore, it doesn't make sense for it to be bundled in the themeHandler.
* 🐛 Fix the uncapitalise middleware
- Updated to make correct use of req.baseUrl, req.path, req.url & req.originalUrl
- Updated the tests to actually cover our weird cases
* 🎨 Move ghostVersion logic out of config
* 💄 Group static / asset-related middleware together
* 🔥 Remove /shared/ asset handling
- The 5 files which are located in `/shared/` are all handled by individual calls to `serveSharedFile`
- Therefore this code is redundant
- GhostLogging always expected an stdout stream
- so it was not possible to use production env with GhostLogger, because an error was happening
- temporary fix!
refs #7116
- The long format logs were making it hard to see the debug statements
- Seeing headers for every asset is a bit much
- "short" format doesn't output bodyPretty
- This needs love as there's no reason to calculate bodyPretty if we aren't using it
- The default output should be discussed
- req.url doesn't include the full path when apps are mounted
- Use mode instead of format & pass config correctly
refs #7488
If you want to set properties for our configuration values using
environment variables on the command line, Linux and MacOS return an
invalid identifier error.
```
$ export database:connection:host=127.0.0.1
-bash: export: `database:connection:host=127.0.0.1': not a valid
identifier
```
According to the nconf documentation a custom separator can be set. The
docs suggest `'__'` which this PR adds.
closes#2597
- Remove .archive-template
- Remove .page
- Don't output .post-template on pages
- Use `page-slug` instead of `page-template-slug`
- Always output `page-slug` irrelevant of whether or not there is a custom template
closes#6165
- internal tags has been in labs for a couple of months, we've fixed some bugs & are ready to ship
- removes all code that tests for the labs flag
- also refactors the various usage of the visibility filter into a single util
- all the tests still pass!!!
- this marks #6165 as closed because I think the remaining UI tasks will be handled as part of a larger piece of work
refs #7429
Finally it's starting to feel like a real editor, although there will be another version bump over the weekend which improves the toolbar behaviour and usability, and enables image uploading.
- Added the start of a new toolbar, what we're (well I am) calling the Owesome bar, not to be confused with the Firefox Awesome bar. It's a cultural thing. (google "O for awesome").
- The idea of dragging and dropping cards has been removed for now, although the code will still be in there as we will support dragging cards around fairly shortly. When apps are included a better card interface will be required for a larger amount of app created content cards (Oh yeah!)
- Ghost Server now pulls in it's configuration from Ghost-Editor, this allows Ghost-Editor to a) keep cards up to date, and b) define what happens if a card is missing.
- The whole cards in admin written in ember and cards in server written in javascript thing is still very much a work in progress, it's kind of messy as we find the optimum solution (which isn't the current sollution).
So yeah, this is a WIP not the final styling, not the final interactions, not the final anything... :)
Adds a new mobile doc editor which has:
- A new toolbar
- Basic image uploading capability