refs #9028
- add two new endpoints for uploading/downloading the redirects (file based)
- reload/re-register redirects on runtime
- migration for 1.9 to add permissions for redirects download/upload
refs https://github.com/TryGhost/Ghost/issues/8859
- We don't need the config option for Unsplash anymore
- The private endpoint (/configuration/private) was introduced for Unsplash
* Improved log output for welcome email error
no issue
- if Ghost is unable to send a welcome email, the server log printe a huge error log
- the reason was that each component wrapped the original error into a new error instance
- so the stack grows and grows
- the golden rule should always be: the smallest/lowest component should instanitate a specifc error
- the caller can expect to receive a custom Ghost error
* Tidy up error messages for mail failures and fix tests
- We never use "Error:" notation in our translations
- Make the error messages consistent and show a reason if possible
closes#8342
- no need to add a migration, because when we'released 1.0, OAuth was never an option
- it was disabled in April, 1.0-beta was released in June
- remove all remote authentication code
no issue
- if you blog runs on a custom domain, but your admin panel is configured using a different domain
-> Ghost losts the origin header
- we had this situation once with pretty urls (your request get's redirected from /posts to /posts/, see https://github.com/TryGhost/Ghost/pull/8094)
- we've moved all our redirect logic to Ghost and ran into the same situation
- i've added proper test to ensure it won't happen again
no issue
- Consistent naming for postLookup
- makes it easier to search and inspect the various usages
- Cleanup unneeded code
- Make res.render calls more consistent
- add some consistency to the calls to res.render
- Remove ancient reference to dataProvider
- Let's call it models everywhere now...
- Use consistent formatting across the API
- we're no longer using alignment in vars
- Misc other consistency changes in API
- always refer to local utils as apiUtils
- logical grouping of requires - dependencies, utils, "lib common" etc
- use xAPI to refer to API endpoints, e.g. mailAPI, settingsAPI for clarity
no issue
v1.0.0 is no longer the standard in the docs, so I updated all of the URLs containing it with v1
Note: I tried squashing commits, but failed. I'll try again in the future with throwaway changes
Secondary Note: I tested most of the URLs listed and got no 404s!
no issue
- adds a ghost-backup client
- adds a client authenticated endpoint to export blog for ghost-backup client only
- allows some additional overrides during import
- allows for an import by file to override locking a user and double hashing the password
no issue
- Split routes out from the API app 🎨
- Use the same pattern as the blog app
- General cleanup/unification across all of the `app.js` files
- Split middleware config out from API routes
- Logical groupings make it easier to see WTF is going on 😬
refs #8859
- adds new `configuration/private` endpoint for exposing config that should not be accessible without authentication
- adds `unsplashAPI` to private config
- adds empty `unsplash` config to default settings
no issue
- Upgraded ghost-ignition
- Use debug from ghost-ignition everywhere in the code base
- Remove debug dependency
- Fixed random typo in Gruntfile.js
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
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
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
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
🎨🐛 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 #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
📡 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
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
- 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
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
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
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
* 🔥 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)
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.