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
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)
* 🎨 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
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
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 #7489
- new database versioning scheme which is based upon the Ghost version, and so easier to reason about
- massive refactor of all the version related code
Summary of changes:
* ✨ new error: DatabaseNotSeeded
* 🎨 change versioning module
- versioning is based on Ghost Version
* 🎨 change bootUp file
- add big picture description
- version error get's trigger from versioning module
* 🎨 default setting for database version is null
- very important change: this is caused by the big picture
- see bootUp description
- the database version get's set by the seed script later
- db version is by default null
- 1. population happens (we ensure that this has finished, by checking if each table exists)
- 2. seeds happening (we ensure that seeds happend if database version is set to X.X)
* 🎨 temporary change for population logic
- set database version after population happens
- ensure population of default settings happend before
- both: get's removed in next iteration
* 🎨 adapt tests && mark TODO's
* 🎨 err instance checking
refs #7116, refs #2001
- Changes the way Ghost errors are implemented to benefit from proper inheritance
- Moves all error definitions into a single file
- Changes the error constructor to take an options object, rather than needing the arguments to be passed in the correct order.
- Provides a wrapper so that any errors that haven't already been converted to GhostErrors get converted before they are displayed.
Summary of changes:
* 🐛 set NODE_ENV in config handler
* ✨ add GhostError implementation (core/server/errors.js)
- register all errors in one file
- inheritance from GhostError
- option pattern
* 🔥 remove all error files
* ✨ wrap all errors into GhostError in case of HTTP
* 🎨 adaptions
- option pattern for errors
- use GhostError when needed
* 🎨 revert debug deletion and add TODO for error id's
no issue
- unsued code:
- there are no public assets anymore, might need to use this instead of shared in future, but for now lets remove it to reduce confusion
- the `input password` box was incorrectly registered as an admin helper, thinking that was needed in order to render the default template. This isn't needed.
- apps:
- small structure & comment update to amp app
- moving input_password helper into private blogging app
- refactor helpers in subscribers app
- 🛠 add bunyan and prettyjson, remove morgan
- ✨ add logging module
- GhostLogger class that handles setup of bunyan
- PrettyStream for stdout
- ✨ config for logging
- @TODO: testing level fatal?
- ✨ log each request via GhostLogger (express middleware)
- @TODO: add errors to output
- 🔥 remove errors.updateActiveTheme
- we can read the value from config
- 🔥 remove 15 helper functions in core/server/errors/index.js
- all these functions get replaced by modules:
1. logging
2. error middleware handling for html/json
3. error creation (which will be part of PR #7477)
- ✨ add express error handler for html/json
- one true error handler for express responses
- contains still some TODO's, but they are not high priority for first implementation/integration
- this middleware only takes responsibility of either rendering html responses or return json error responses
- 🎨 use new express error handler in middleware/index
- 404 and 500 handling
- 🎨 return error instead of error message in permissions/index.js
- the rule for error handling should be: if you call a unit, this unit should return a custom Ghost error
- 🎨 wrap serve static module
- rule: if you call a module/unit, you should always wrap this error
- it's always the same rule
- so the caller never has to worry about what comes back
- it's always a clear error instance
- in this case: we return our notfounderror if serve static does not find the resource
- this avoid having checks everywhere
- 🎨 replace usages of errors/index.js functions and adapt tests
- use logging.error, logging.warn
- make tests green
- remove some usages of logging and throwing api errors -> because when a request is involved, logging happens automatically
- 🐛 return errorDetails to Ghost-Admin
- errorDetails is used for Theme error handling
- 🎨 use 500er error for theme is missing error in theme-handler
- 🎨 extend file rotation to 1w
refs #7452
- remove references to 'patronus' in favour of GhostAuth, Note: this will require databases to be deleted ;)
- remove email addresses from test data
* 🎨 run database population in transaction
refs #6574, refs #7432
- create transaction for creating tables
- if an error occurs or a container get's destroyed before population finishes, transaction is rolled back
* 🎨 simplify transaction creation and test
issue #7452
Remote oauth2 authentication with Ghost.org.
This PR supports:
- oauth2 login or local login
- authentication on blog setup
- authentication on invite
- normal authentication
- does not contain many, many tests, but we'll improve in the next alpha weeks
- Don't let people start Ghost Alpha with non-alpha databases.
- Provide a new welcome message for development mode (a little bit of positive reinforcment)
- Provide a RED WARNING when in production mode (will still be used for developing, but we can ignore)
- Change package.json to 1.0.0-alpha.0, we won't relelase this, will bump to .1 for release
refs #6982
- create config util fn: getContentPath
- we can later let the user change the folder names in contentPath
- get rid of custom/default storage paths
[ci skip]
closes#7313
- Adds `getSanitizedFileName` function to storage/base.js which replaces non A-Z0-9@. chacracters with -
- modifies /api/theme.js so that zip.shortName is consistent throughout.
closes#7192
- add 008 migration
- added script to re-run 006/01
- re-run 006/01 migration for postgres in any timezone (transform formats only)
- re-run 006/01 migration for sqlite (transform formats only)
- rely on format checks for sqlite, do not check server TZ
* 🐛 fix direct update
closes#7297
- move sitemap initialisation into sitemap handler
- initialise sitemap on first request to sitemap
* 🐛 fix how we pass options to migration files
refs #7317
- clone options when passing them into the migration/fixture files
- do not use default sequence, because it does not clone the arguments
refs #7305
* 🎨 display upgrade alerts with the correct "info" style
* 💄 update use of notifications status/type/location attrs to reflect current usage
no issue
This PR takes the existing function `processUrls` in `data/xml/rss` and refactors it to be a stand-alone util.
The change is needed, as this functionality will be accessed from `apps/amp` to convert relative URLs.
closes#7186
- Add a concept of validity to each generator
- Refactor base generator to handle invalid (empty) nodes for both events & the initial generation
- Update the tests a bit, to fix some bugs in the tests
- Ensure the homepage is always present
refs #7204
- Adds a new ThemeValidationError class
- This error has a top level message, but will also contain all the individual errors within the `errorDetails` property
- Updated the API error handling to return `errorDetails` if it is present
no issue
Double slashes are treated as a HTTP calls as specified in [RFC1801](http://www.ietf.org/rfc/rfc1808.txt). Because of this behaviour the uncapitalise created an open redirect. By removing double slashes in the path we ensure open redirects cannot be created.
As an example, please click the following URL: https://dev.ghost.org///Google.com/.
This issue has been reported by pentesters of our product [LearningSpaces.io](http://learningspaces.io).
refs #2852
- improvement: ensure custom storage adapter has required functions
- serve, save and exists are from now on required functions for a custom storage adapter
- add delete as required storage function
closes#6588, #7095
* `ImageObject` with image dimensions (#7152, #7151, #7153)
- Returns meta data as promise
- returns a new Promise from meta data
- uses `Promise.props()` to resolve `getClient()` and `getMetaData()`
- Adds 'image-size' util
The util returns an object like this
```
{
height: 50,
url: 'http://myblog.com/images/cat.jpg',
width: 50
};
```
if the dimensions can be fetched and rejects with error, if not.
In case we get a locally stored image or a not complete url (like `//www.gravatar.com/andsoon`), we add the protocol to the incomplete one and use `urlFor()` to get the absolute URL. If the request fails or `image-size` is not able to read the file, we reject with error.
- adds 'image-size' module to dependencies
- adds `getImageSizeFromUrl` function that returns image dimensions
- In preparation of AMP support and to improve our schema.org JSON-LD and structured data, I made the following changes:
- Changes the following properties to be `Objects`, which have a `url` property by default and a `dimensions` property, if `width` and `height` are available:
- `metaData.coverImage`
- `metaData.authorImage`
- `metaData.blog.logo`
- Checks cache by calling `getCachedImageSizeFromUrl`. If image dimensions were fetched already, returns them from cache instead of fetching them again.
- If we have image dimensions on hand, the output in our JSON-LD changes from normal urls to be full `ImageObjects`. Applies to all images and logos.
- Special case for `publisher.logo` as it has size restrictions: if the image doesn't fulfil the restrictions (<=600 width and <=60 height), we simply output the url instead, so like before.
- Adds new property for schema.org JSON-LD: `mainEntityOfPage` as an Object.
- Adds additional Open Graph data (if we have the image size): `og:image:width` and `og:image:height`
- Adds/updates tests
* AMP router and controller (#7171, #7157)
Implements AMP in `/apps/`:
- renders `amp.hbs` if route is `/:slug/amp/`
- updates `setResponseContext` to set context to `['amp', 'post']` for a amp post and `['amp', 'page']` for a page, but will not render amp template for a page
- updates `context_spec`
- registers 'amp' as new internal app
- adds the `amp.hbs` template to `core/server/apps/amp` which will be the default template for AMP posts.
- adds `isAmpURL` to `post-lookup`
* 🎨 Use `context` in meta as array (#7205)
Instead of reading the first value of the context array, we're checking if it includes certain context values.
This is a preparation change for AMP, where the context will be delivered as `['amp', 'post']`.
* ✨ AMP helpers (#7174, #7216, #7215, #7223)
- Adds AMP helpers `{{amp_content}}`, `{{amp_component}}` and `{{amp_ghost_head}}` to support AMP:
- `{{amp_content}}`:
- Adds `Amperize` as dependency
- AMP app uses new helper `{{amp_content}}` to render AMP HTML
- `Amperize` transforms regular HTML into AMP HTML
- Adds test for `{{amp_content}}` helper
- Adds 'Sanitize-HTML` as dependendy
- After the HTML get 'amperized' we still might have some HTML tags, which are prohibited in AMP HTML, so we use `sanitize-html` to remove those. With every update, `Amperize` gets and it is able to transform more HTML tags, they valid AMP HTML tags (e. g. `video` and `amp-video`) and will therefore not be removed.
- `{{amp_ghost_head}}`:
- registers `{{amp_ghost_head}}` helper, but uses `{{ghost_head}}` code
- uses `{{amp_ghost_head}}` in `amp.hbs` instead of `{{ghost_head}}`
- `{{ghost_head}}`:
- Render `amphtml` link in metadata for post, which links to the amp post (`getAmpUrl`)
- Updates all test in metadata to support `amp` context
- Changes context conditionals to work with full array instead of first array value
- Adds conditionals, so no additional javascript gets rendered in `{{ghost_head}}`
- Removes trailing `/amp/` in URLs, so only `amphtml` link on regular post renders it
- Adds a conditional, so no code injection will be included, for an `amp` context.
- `{{amp_components}}`:
- AMP app uses new helper `{{amp_components}}` to render necessary script tags for AMP extended components as `amp-iframe`, `amp-anime` and `amp-form`
- Adds test for `{{amp_components}}`
closes#7182
When calling `config.set()` in the settings api, we want to set the active timezone of the blog to make it available in our `settingsCache`. But because the `theme` object in the `set` prototype was already set to `Etc/UTC` as default, the `_.merge` function would always overwrite our `activeTimezone` with the default value.
This PR changes the code in the way, that we always set 'Etc/UTC' for the timezone as default, _until_ we fetched our settings and therefore the `activeTimezone` setting, so we can overwrite it.
This issue had not only influence on the date helper, but everywhere in our codebase, where we rely on reading the `timezone` from our config, instead of our settings. The `{{@blog.timezone}}` helper reflected that quiet well, as it would always show `Etc/UTC`
no issue
- Source out validation logic into a upload validation middleware for all upload types (csv, image, subscribers). This unit can be later used for Ghost 1.0 as a pre validation core unit.
- More usage of route tests than controller tests. These are use case tests, a use case only changes if the product changes
no issue
- sets `settings.activeTimezone` to best-guess based on current server time when performing the timezones migration in order to prevent unexpected changes in timezone when upgrading
closes#5071
- Send application/json requests to UpdateCheck service. New UpdateCheck service accepts JSON request
- If UpdateCheck service respponse has messages[] array, iterate over the array and create custom notifications intended for current version
- Save custom notification if its not already in the store AND its uuid is not in seenNotifications array
- When a custom notification is dismissed, store its uuid in seenNotifications array
- setup test fixtures to trigger tests properly
- api_notification_spec test to ensure custom notification can be added to store and added to seenNotifications when dismissed
- update_check_spec test to ensure custom notification can be displayed for a specific Ghost version
- added test to ensure messages meant for other versions don't create notifications
closes#6948
- the hbs engine was never initialised when server starts
- when you request a page which does not exist, express jumps directly into the error handlers
- delete some dynamic hbs engine setters in theme handler
closes#6625
- "url" and "author" fields depend on {id, published_at, slug, author_id} to construct post url.
- implemented a generic solution by defining defaultColumnsToFetch() in
base class for models.
- findPage() calls defaultColumnsToFetch() before loading models
- results are transformed by filtering out additional properties to return just the requested fields
- Added a test case to check for url and author fields
- Renamed allColumns as requestedColumns and used _.map instead of Promise.map
refs #6958 (first task of it)
-includes additional tests
-Instead of removing all slashes "/g" we now specifically remove leading and trailing slashes.
closes#6932
- new default order of posts: scheduled, draft, published
- invent orderDefaultRaw fn for each model
- each model is able to create a default raw order query
- separate count and fetch query for fetchPage, because the count query where group/order statements attached
closes#7060
- changed meta referrer from origin to origin-when-cross-origi
- made referrer policy configurable via referrerPolicy option in config js
- added example to config.example.js
-modified test to reflect new defaul origin-when-cross-origin
-added a test for configuration changed referrerPolicy
refs #7023
The template can be used for all cases (different newsletter interval, different amount of blog posts, with or without blog picture).
The template can be filled with the following data structure:
- `blog.logo` is the blog logo from settings
- `blog.title` is the title of the current blog
- `blog.url` is the URL of the blog
- `blog.twitterURL` is the twitter profile URL of the blog from settings
- `blog.facebookURL` is the facebook page URL of the blog from settings
- `blog.unsubscribe` is the link for the reader to unsubscribe from the blog
- `newsletter.interval` is the interval in words like 'weekly', 'daily', 'monthly'
- `newsletter.date` is the date of the newsletter issue in a format like 'June 9th, 2016'
- `blog.post` is expected to be an array:
- `blog.post[i].picture` is the picture of the blog post. There are also conditionals, which change the inline CSS to either show a border-top if there's no picture (in that case the HTML code, that shows the picture is not active)
- `blog.post[i].title` is the title of the current blog post
- `blog.post[i].text` is the text of the current blog post, which needs to be cut down to 278 letters, plus ending with `…`
- `blog.post[i].url` is the URL of the current blog post
- `blog.post[i].tag` is the tag of the current blog post
- `blog.post[i].author` is the author of the current blog post
Important is, that only HEX HTML entities will work, especially in Outlook. So instead of `—` we need to use `—` and `’` instead of `'` or `'` and so on.
Added unit test for newsletter template in `test/unit/mail/utils_spec.js`.
no issue
This is a fix for the default-scheduler.
When a post never had a published_at value, the oldTime for removing the job would be null. And in this case we would try to delete a job with an invalidate date.
refs #6413
- PUT endpoint to publish a post/page for the scheduler
- fn endpoint to get all scheduled posts (with from/to query params) for the scheduler
- hardcoded permission handling for scheduler client
- fix event bug: unscheduled
- basic structure for scheduling
- post scheduling basics
- offer easy option to change adapter
- integrate the default scheduler adapter
- update scheduled posts when blog TZ changes
- safety check before scheduler can publish a post (not allowed to publish in the future or past)
- add force flag to allow publishing in the past
- invalidate cache header for /schedules/posts/:id
no issue
- config.theme.timezone can be undefined, when settings are not loaded from the database
- this PR will define the default blog TZ in config
- use `Etc/UTC` as default instead of `Europe/Dublin`
closes#6406
- created listeners.js connector
- merged listeners.js with events.js (in models/base)
- set a post to draft when published_at would be in the past
- reschedule a post when published_at would be in the future
refs #6949
- Adds a new VersionMismatchError with status 400 (bad request)
- Adds middleware that checks the X-Ghost-Version header if it is provided
- If it is not provided, the middleware does nothing
- If it is provided, and the versions match, the middleware does nothing
- If it is provided, and the versions don't match, the middleware returns a VersionMismatchError
- Includes both unit and a functional test to prove the middleware works alone and as part of the whole system
no issue
- changes xmlrcp & slack `init` function to be `listen`
- update the code to use `listen` instead of `init`
- changes the tests to make sure that event listeners are not wired up
- adds 100% test coverage
Since we added slack event listeners, the xmlrpc event tests have been throwing an error:
> Unhandled rejection Error
See: http://puu.sh/phvjZ.png
This is because both xmlrpc & slack are listening to `post.published` events.
xmlrpc didn't require any extra stubbing, but the slack listener did
By turning the listeners off after the tests, we reset the environment to not impact the next event test
We probably need to do more work like this to improve the systems around event handling and
make them more robust