refs #7470
These tests had a random failure on travis for Node v6 w/ sqlite. I
figured I would update them to return promises, and remove state, to
make debugging easier, and hopefully fix any issues.
no issue
- webhooks UI requires the ability to edit webhooks
- added `edit` permission for `webhook`
- added `edit` method to v2 webhook controller
- added `PUT /webhooks/:id` route to v2 Admin API routes
refs #9942
* Added new middleware to trigger events
* Refactored webhooks service
- added new trigger service, moved listen service to its own file
- started listening to new site.changed event
- cleaned up trigger service to work with new webhook fields
- cleaned up tests
- removed redundant trigger method in v0.1 controller
refs #9866
- invent preview api, but only used internally
- the idea of a preview api is definitiely reaslistic and came up in the past a couple of times
- by that we don't have to differentiate between pages or posts controller
- still support v0.1
- preview controller is not registered for http, only internal handling
refs #9866
- the entry helper is used for static pages and post lookups
- now that we support changing the api version, we have to respect the resource type
- for v2: we ask the pages controller for static pages
- in v0.1: pages and posts lived on the same route
- we are talking about the content API (!) - not admin api
refs #9866
- the static pages router uses the entry controller
- and the entry controller uses the lookup helper
- the lookup helper needs to either fetch static pages or posts
- v2 uses pages and posts controller
refs #9866
- we fallback to v0.1 by default
- we support different formats
- this opens the box to switch the ghost api version for the whole blog site
- i had to add a different notation for overrides.json, because the structure is not optimal (i only want the versions, not the shortcuts)
closes#10024
- Updated input serializers for posts/tags/users to handle absolute urls conversion
-------
1. Ghost stores relative images urls
2. API V2 returns images with absolute urls
3. Ghost-Admin sends absolute urls back on any save e.g. update user
**Current behavior**: This will override the relative image path in db to absolute, which in turn won't get updated in future if domain or protocol changes for e.g.
**Fix**: On save/update, input serializers converts any absolute image url paths back to relative if the base URL from image fields matches the configured URL
no-issue
- Added spam prevention to POST /session
- This blocks repeated requests the the /session endpoint preventing brute
force password attacks
- Updated session controller to reset brute middleware
- This updates the session controller to reset the brute force protection
on a successful login. This is required so that a user is not locked out
forever :o!!
* Extended webhooks schema/model and connected with integrations
refs #9942
- Updated webhooks schema with new columns - name, integration_id, secret, last_triggered_at, api_version
- Updated webhooks and integration model to map relationships
- Updated schema hash
- Updated test utils to exclude new webhooks columns for response comparison
* Added migration script for new webhooks columns
refs #9942
- Added migration script in 2.3 to add new columns to webhooks
* Updated schema hash
* Updated maxLength for api_version in schema
* Removed concurrency value from migration script
* Added defaults for webhooks model
* Added status field to webhooks for last trigger status
* Updated schema hash
* Fixed tests with status field
* Removed concurrency value in migration script
* Cleanup
* Updated schema with new fields
- last_triggered_status, last_triggered_error
no-issue
There are a few libraries, including node core that when given an array
for a query parameter will encode it as repeated query params. e.g.
```
{someParam: ['a', 'b']}
// becomes
'?someParam=a&someParam=b'
```
This adds a check for the value to stop us 500ing on repeated keys and
to add easier interop with http clients
refs #9866
- Extracted url decoration logic to utility in output serializers in posts, pages, users, and tags
- Added test cases for url usage by child object (tags of posts)
refs #9866
- Refactored overrides config to include direct version configs(v0.1, v2), supported versions map to direct version
- Refactored `getApiPath` to handle direct versions as well as mappings of supported version
closes#9962
- Fixed the bug with url being set to /404 when id was not present on the model
- Added a functional test to cover this bug
- Refactored url decorating methods to be more clear about the nature of passed parameters
* Added API Key auth middleware to v2 content API
refs #9865
- add `auth.authenticate.authenticateContentApiKey` middleware
- accepts `?key=` query param, sets `req.api_key` if it's a known Content API key
- add `requiresAuthorizedUserOrApiKey` authorization middleware
- passes if either `req.user` or `req.api_key` exists
- update `authenticatePublic` middleware stack for v2 content routes
* Fixed functional content api tests
no-issue
This fixes the functional content api tests so they use the content api
auth.
* Fixed context check and removed skip
* Updated cors middleware for content api
* Removed client_id from frame.context
no-issue
The v2 api doesn't have a notion of clients as we do not use oauth for it
* Fixed tests for posts input serializer
refs #9866
- Added logic ensuring page filter is always set to false in posts endpoint for Content API
- Added functional tests to pages and posts
- Added absolute_url logic in pages controller
* Stopped api key from assigning the 'Owner' role
refs #9865
We do not want api keys to be able to assign the Owner role to any other
key or user.
* Cleaned up Role model permissible method
no-issue
refs #9866
- there was a missing step in the shared validator
- we have to differentiate between data validation for browse/read and data validation for add/edit
- furthermore, the data validation for add/edit was missing and was not copied over from v0.1 (check structure of incoming body)
- adds the ability to require properties from req.body.docName[0]
closes#9972
* Added breaking test for node v6 session auth
* Updated session middleware to support node v6
This uses the legacy url to obtain the origin rather than the WHATWG
URL class in order to support node <6.14.4
closes#9927
- Added post model implementation to be able to store up to 10 versions of mobiledoc
- Bumped GQL to support filtering on the mobiledoc revision table
- Added tests ensuring new functionality works
* Added api_key_id to frame.context
refs #9865
This is to allow controllers to check permissions using api_key_id data.
* Removed client and client_id from frame.context
refs #9865
This is unused as we only support oauth on v0.1 API.
closes#9959
This issue existed because the logic assumed that if there were no
query parameters then there would be no `query` object. However this is
not the case. What we really wanted to check was for the existence of an
"r" query param - the code has been refactor to explicitly do this now.
refs #9866
- test/functional/
- test/functional/api
- test/functional/api/v0.1
- test/functional/api/v0.1/utils
- test/functional/api/v2
- test/functional/api/v2/admin
- test/functional/api/v2/admin/utils
- test/functional/api/v2/content
- test/functional/api/v2/content/utils
- updated grunt file
- instead of `grunt test-routes`, you now need to use `grunt test-functional` (docs are updated)
You can use `localUtils.API.getApiQuery('posts/')` and it will generate the correct API url.
refs #9866
- moved the tests either to unit tests or routing tests
- or removed test case (a lot)
- this commit is very big 🤪, it was not rly possible to create clean commits for this
- it only changes the test env, no real code is touched
Next steps:
- optimise folder structure + make v2 testing possible
- reduce some more tests from routing and model integeration tests
refs #9866
- the global utility should for now not generate API urls
- we only have one test which generates the API url
- for now it will live in this test file
- if we have multiple cases, we can reconsider this
refs #9866
- the sdk does not use the url utility
- it just respects what you pass in
- there is no need to test this behaviour for multiple API versions
refs #9326, refs #9866
**ATTENTION: This is the first iteration. Bugs are expected.**
Main Goals:
- add support for multiple API versions.
- do not touch v0.1 implementation
- do not break v0.1
## Problems with the existing v0.1 implementation
1. It tried to be generic and helpful, but it was a mixture of generic and explicit logic living in basically two files: utils.js and index.js.
2. Supporting multiple api versions means, you want to have as less as possible code per API version. With v0.1 it is impossible to reduce the API controller implementation.
----
This commit adds three things:
1. The tiny framework with well-defined API stages.
2. An example implementation of serving static pages via /pages for the content v2 API.
3. Unit tests to prove that the API framework works in general.
## API Stages
- validation
- input serialization
- permissions
- query
- output serialization
Each request should go through these stages. It is possible to disable stages, but it's not recommended.
The code for each stage will either live in a shared folder or in the API version itself. It depends how API specific the validation or serialization is. Depends on the use case.
We should add a specific API validator or serializer if the use case is API format specific.
We should put everything else to shared.
The goal is to add as much as possible into the shared API layer to reduce the logic per API version.
---
Serializers and validators can be added:
- for each request
- for specific controllers
- for specific actions
---
There is room for improvements/extensions:
1. Remove http header configuration from the API controller, because the API controller should not know about http - decouple.
2. Put permissions helpers into shared. I've just extracted and capsulated the permissions helpers into a single file for now. It had no priority. The focus was on the framework itself.
etc.
---
You can find more information about it in the API README.md (api/README.md)
- e.g. find more information about the structure
- e.g. example controllers
The docs are not perfect. We will improve the docs in the next two weeks.
---
Upcoming tasks:
- prepare test env to test multiple API versions
- copy over the controllers from v0.1 to v2
- adapt the v2 express app to use the v2 controllers
refs #9866
- Added test util method for api path based on version
- Updated all hardcoded v0.1 tests strings to use dynamic string from util method
- Updated hardcoded v0.1 tests using regex match to use string equal with new util method
refs #9865
Note that this controller is the singular, that's because we plan to
make a session resource controller to be used with /sessions, wheras
this is on /session
Moved URL attributes logic from the model into API layer
refs #9866
- Moved URL related attribute calculation for posts, users, and tags into API layer
- Added test coverage for url attributes in tags/authors/primary_tags/primary_authors
no issue
- support promise and none promise tasks
- helpful if you create an array of operations and not all of the operations/tasks are async
- `response instanceof Promise` does not work for all cases e.g. some usages return a transaction/bookshelf chain
refs https://github.com/TryGhost/Ghost/issues/9865
- schema migrations
- adds `integrations` and `api_keys` tables
- inserts `integration` and `api_key` permissions and Administrator role relationships
- inserts `Admin Integration` role and permissions
- adds `Integration` model
- adds `ApiKey` model
- creates default secret if not given
- hardcodes associated role based on key type
- `admin` = `Admin API Client`
- `content` = no role
- updates `Role` model to use `bookshelf-relations` for auto cleanup of permission relationships on destroy
refs #9865
* This service handles the session store and exporting middleware to be
used for creating and managing sessions
* Updates the auth service index.js file in line with how we do things elsewhere
* After wrapping the exports in a getter, the usage of rewire had broken
the authenticate tests, this commit _removes_ rewire from the tests, calls `init` on
the models before the tests (needed because rewire isn't there) and also
cleans up the use of var.
refs #9866
- preparation for v2
- moved api/ to api/v0.1
- do export v0.1 straight from the api folder, we don't want to touch this right now
- that means currently if you require the api folder, we return v0.1 by default
- there were some direct requires of api files in the test env
- some of them use rewire
- for now, we just correct the require path to require api/v0.1/
- we touch the test env next week
**Docs about V2 design are coming soon!**
refs #9866
- added api version config to overrides, which makes it possible to have a centralized api versioning configuration
- the next PR will use this config in the web folder
- make api url generation in url service flexible and dynamic
- remove hardcoded API_PATH
- updated all places which used `urlFor('api'..)` -> we now ask for explicit api version
refs #8576
- adds new API endpoint `/uploads/profile-image` for uploading profile images
- new validation which fails with error message if uploaded image is not square
- Renamed getImageSizeFromFilePath to getImageSizeFromStoragePath, because it's more explicit
- Add new getImageSizeFromPath method, which is used in the new dimensions middleware
- Ensure we use the sharp middleware to auto-resize the uploaded profile pictures
- Ensure the new route get's added to v2
While this makes sure all future profile images uploaded are square, this doesn’t affect any existing non-square profile image. Needs more thought on how to handle existing non-square profile images for the purpose of making theming easier in future.
Extended uncapitalise unit tests
refs #9866
- Proved that the middleware works for many API versions
- Added test case to prove that the version identifier gets lowercased too
refs #9866
- Removed `res.isAdmin` flag in v2 express app
- Did not touch v0.1 express app
- Separated url redirect middleware for admin and content API
refs #9866
- Registered Content API under /ghost/api/v2/content/
- Registered Admin API under /ghost/api/v2/admin/
- Moved API v0.1 implementation to web/api/v0.1
- Created web/api/v2 for the new api endpoints
- Started with reducing the implementation for the new Content API (the Content api does not serve admin api endpoints, that's why it was reducible)
- Covered parent-app module with basic test checking correct applications/routes are being mounted
- Added a readme file, which contains a warning using v2, because it's under active development!
- This PR does only make the new endpoints available, we have not:
- optimised the web folder (e.g. res.isAdmin)
- started with different API controllers
- reason: we want to do more preparation tasks before we copy the api controllers
no issue
- private blogging was once part of a single big express app, see: c1a2601514
- therefor we needed to differentiate if the request is for /api/v0.1 or for the actual site
- nowadays, we register apps only for the site express app
refs #9848
- Disabled image optimization for .gif files as a temporary solution until sharp library starts supporting latest version of libvips
- Disabled image optimization for .svg/.svgz files as permanent solution as these file types are being converted to .png
closes#9832
The API _should_ be returning absolute URLs for everything, 3rd party applications require absolute urls to read and display ghost data correctly. Currently they have to concat the blog url and the resource url, which is very uncomfortable.
Changing the public api like this would be considered a breaking change however so we've opted to put it behind a query parameter named `absolute_urls`.
refs #4453
* On by default
* Added config to disable resizing
* Added basic image optimization processing
* Added dep: sharp (optional dep)
* Added resize middleware
* Take care of rotation based on EXIF information
* Removed all meta data from optimised image
* Added handling if sharp could not get installed
* Do not read ext twice - optimisation
* Do not call sharp if config is disabled
* Do not remove the original image which was uploaded (store 2 images)
* Support of `req.files` for internal logic
* Disabled cache to enable file removal on Windows
closes#9134
- Added form_id, input_id, and button_id parameters to subscribe_form helper
- Added id parameter to input_email helper
- Added test coverage to input_email helper
- Added quotes to id attributes for consistency
- Added subscribe_form helper tests
- Updated express to v4 in helper tests
closes#9786
- Make GET request when url has no provider match
- The HEAD request was made in order to send less data over the wire when
checking for redirects for urls that do not have an oembed provider
match. We are now going to look for provider metatags withing the
response of the request - rather than making a HEAD followed by a GET if
no redirect is found, this condenses that to a single request.
- Try to get OEmbed data from tag if no provider
- Here we parse the HTML response of the resource and look for a link tag
that will give us the oembed resource url which we can use to fetch the
embed html
closes#9644
- Removed google blogsearch from pingList, because it's dead (https://plus.google.com/+GoogleWebmasters/posts/46W7ZwVrwqg)
- Updated pingomatic method weblogUpdate -> weblogUpdates
- Updated RPC response handler to check for errors, log improvement
- the pingomatic service sends back a 200 even when it errors, so we
check the xml response to see if it's good, it throws and passes of to
the catch handler already in place
- Avoid multiline XML error message strings, but
includes a catch in case our regex stops working with a fallback to
multiline XML error message
- we check for arbitrary whitespace between different XML tags,
which I haven't seen in any of the responses - but it could change I
guess. I haven't added support of whitespace between the tags, as I
believe that would be a different value with XML spec. And we wanna
match on exact values here.
no issue
- we have to explicitly reset the previous `updated_at` field, because Bookshelf auto-updates this field on each update
- we have to extend the condition to avoid updating the `updated_by` field
- detect and respect `options.migrating`
* 🐛 Dynamic Routing Beta: Shortform `author.foo` is not allowed
refs #9601
- otherwise you get access to {{author}} in the theme, which is deprecated & causes errors
- recommend not using {{author}} as data longform name in the yaml validator
- (internal usage is still allowed)
- also warn against using reserved data key names like filter, resource, limit etc - maybe remove this restriction later but seems like a sensible validation right now.
no issue
- Organising your content
From: Here, the theme would assign the post publicly displayed tags of Blog - but it would also keep a private record of the post being tagged with #video.
To: Here, the theme would assign the post publicly displayed tags of News - but it would also keep a private record of the post being tagged with #video.
refs #9601
- when using the short form `data: tag.welcome` the redirect is enabled by default
- /tag/welcome/ will redirect to the channel/collection which makes use of the data key
- you can disable the redirect by using the long form
e.g. data:
tag:
resource: tags
type: read
slug: welcome
redirect: false
closes#9774, refs #9742
- added new fixture posts for Ghost 2.0
- added migration file to remove old fixture posts
- only remove them if they are owned by the Ghost author and if they are tagged with getting-started
- added new fixture posts if you had all (!) old fixture posts
- ensure on rollback we remove the new fixture posts again
- updated default settings
refs #9742
- removed usage of single permalink setting
- with dynamic routing this configuration does no longer makes sense
- because you can configure your permalinks in the routes.yaml
- furthermore you can have multiple collections with multiple permalinks
- removed @blog.permalinks
- do not export permalink setting
- do not import permalink setting
- permalink setting UI will be removed soon
- get rid of {globals.permalink} completely
- remove yaml in-built migration
- do not expose settings.permalinks via the private API
- do not allow to edit this setting
- keep phyiscal value in case a blog needs to rollback from v2 to v1
- sorted out when the routers should be created
- ensure routes.yaml file doesn't get validated before Ghost is fully ready to start
refs #9742, refs #9724
- handle König Editor format for 2.0
- adapted importer to be able to import 1.0 and 2.0 exports
- added migration scripts
- remove labs flag for Koenig
- migrate all old editor posts to new editor format
- ensure we protect the code against mobiledoc or html field being null
- ensure we create a blank mobiledoc structure if mobiledoc field is null (model layer)
- ensure you can fully rollback 2.0 to 1.0
- keep mobiledoc/markdown version 1 logic to be able to rollback (deprecated code)
refs #9742
- rebase against master updated some docs links again
- go over code base again and double check that all docs links are correct
- 2.0 will become the latest version on our readme pages
no issue
- these tests were a mess
- we had many duplicated tests
- it was very hard to work with the exporter files
- i have tidied up the whole file
- first section: all general importer tests based on the current Ghost version
- second section: 1.0 tests
- everything is now JSON based (much easier to control)
refs 9742
- when we've introduced Ghost 1.0, we have noticed that we broke Disqus comments
- Disqus comments use a unique identifier, which is the post id
- that means if you have exported your LTS content and imported it into 1.0, all resource identifiers are regenerated
- but the Disqus must use the original post resource id
- that's why we have imported the old post id and remembered it in the `amp` field 🤠
- that was the only field which was available and un-used
- now in Ghost 2.0, we would like to rename the `amp` field to `comment_id`
- string length: 50 (i thought it might be safer to not use 24 characters, because who knows if support other comment id's in the future)