Commit Graph

3288 Commits

Author SHA1 Message Date
kirrg001
d8a7edd9aa Added TODO's for entry and preview controller
refs #9866
2018-10-18 19:41:07 +02:00
kirrg001
cbf2817e39 Added missing read pages endpoint
refs #9866

- the endpoints were missing
- the site app needs pages.read for v2
2018-10-18 19:41:07 +02:00
kirrg001
8caf8009ae Added TODO to amp_content
refs #9866

- this can be removed if we drop v0.1
2018-10-18 19:41:07 +02:00
kirrg001
15f6c2421c Fixed entry controller to handle v2 and v0.1 url response
refs #9866

- v2 returns absolute urls
- v0.1 returns relative urls
- this is a little ugly, but don't know how else to solve currently
2018-10-18 19:41:07 +02:00
kirrg001
640290c31b Updated blog site components to respect the api version
refs #9866

- the api call must be dynamic based on the api version information
2018-10-18 19:41:07 +02:00
kirrg001
3f9d0f51f5 Changed how we determine if a resource is owned by an url generator
refs #9601

- api v2 returns absolute urls
- api v0.1 returns relative urls
- it's easier if we compare by id
2018-10-18 19:41:07 +02:00
kirrg001
987e41e8d6 Attached api version to res.locals context
refs #9866

- each request get's the ghost api version attached
- this makes it possible to access the version in all steps (routing, theme helpers)
2018-10-18 19:41:07 +02:00
kirrg001
1f55c90037 Supported reading ghost api engine
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)
2018-10-18 19:41:07 +02:00
Fabien O'Carroll
17feb14e4a Added HTTP BREAD for integrations resource (#9985)
refs #9865

* Added generic messaging for resource not found
* Ensured integration model uses transaction for writes
* Created POST /integrations endpoint
* Created GET /integrations/:id endpoint
* Created GET /integrations endpoint
* Created PUT /integrations/:id endpoint
* Created DELETE /integrations/:id endpoint
2018-10-18 14:03:56 +01:00
Rishabh Garg
915d5612a1 🐛 Fixed relative image URLs becoming absolute URLs on save (#10025)
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
2018-10-18 12:18:47 +01:00
Fabien O'Carroll
e865d2218c 🐛 Fixed pagination/duplicate posts and users appearing in admin area (#10031)
closes #10029

- allowed page option for users, posts, & tags browse 
  - The page query param was not forwarding to the query, meaning that when the admin client requested the next page of users or posts, it would receive the first page again.
2018-10-18 10:05:51 +01:00
Fabien O'Carroll
ae71f2deca Added spam prevention for v2 sessions (#10030)
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!!
2018-10-18 09:58:29 +01:00
Nazar Gargol
fd958addb6 Migrated update check to use api v2
refs #9866

- Switched update checker to api v2
- Updated and cleaned up the corresponding test suite
- Updated the frame pipeline to respect context passed in with Frame instance
- Exposed 'active' verison from api index module
2018-10-18 00:13:31 +02:00
Nazar Gargol
49a729f77f Excluded sessions table from exporter (#9961)
refs #9865

- Made sessions table to be skipped during the export process
2018-10-17 18:29:24 +07:00
Rishabh Garg
c638863cb9 Updated webhooks schema and add relation (#10018)
* 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
2018-10-17 18:17:13 +07:00
Fabien O'Carroll
4f1866a263
Allowed for repeated query parameters for arrays (#10021)
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
2018-10-17 13:43:32 +07:00
kirrg001
15a8951bc7 Respected hasUserPermissions & hasAppPermissions in invite model
no issue

- the permission service expects from the permissible function to respect the input values
  - hasUserPermissions
  - hasAppPermissions
2018-10-16 18:00:05 +02:00
kirrg001
14a1bdbcf6 Removed invite before adding in v2
refs #9866

- the logic in v2 was missing
- it exists in v0.1
2018-10-16 17:26:24 +02:00
kirrg001
a65702df1d Extended api/index.js to export all available api versions
refs #9866
2018-10-16 16:03:32 +02:00
Nazar Gargol
d582c06eee Optimized usage of urls in API v2
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)
2018-10-16 13:02:04 +02:00
Fabien O'Carroll
2fbc5aa257
Added apiImpl.data to apiOptions for serialisation (#10016)
no-issue

This is to give serializers access to the expected data properties so
that can be used for filtering.
2018-10-16 16:51:50 +07:00
Rishabh Garg
51dde1e38c
Refactored config to handle direct calls for specific version (#10012)
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
2018-10-16 15:20:51 +05:30
Fabien O'Carroll
3a70cdb2b6
Updated Integration model to use generateSlug (#10009)
no-issue

This ensures that slugs are stripped of illegal characters, and that we
do not create duplicates.
2018-10-16 12:25:54 +07:00
Nazar Gargol
9fd9186557
🐛 Fixed 'url' attribute miscalculation when when requested as the only part of fields filter (#9969)
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
2018-10-15 14:47:56 +02:00
Fabien O'Carroll
561c4b208d
Removed OPTIONS cors middleware from content api (#10013)
no-issue

The content API only supports GET requests so has no need for cors
middleware on OPTIONS. This also removes the router.del helper as it's
not used
2018-10-15 18:47:31 +07:00
Fabien O'Carroll
943e1c872c
Removed POST /subscribers from v2 content api (#10010)
no-issue

The content api is for serving read-only content only. This route does
not belong here.
2018-10-15 16:28:23 +07:00
Fabien O'Carroll
3db102a776
Added API Key auth middleware to v2 content API (#10005)
* 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
2018-10-15 16:23:34 +07:00
Fabien O'Carroll
856af02e08
Updated ApiKey onSaving to forward options (#9994)
refs #9865

We require models to forward options on, so that any transactions continue to work
2018-10-14 16:54:10 +07:00
Nazar Gargol
76f4a4bb03
Enforced non-page posts only to be returned by /posts endpoint from Content API (#10002)
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
2018-10-13 00:48:49 +02:00
Katharina Irrgang
981ad28283
Changed tags content api to v2 (#10004)
refs #9866
2018-10-13 00:11:48 +02:00
Katharina Irrgang
c907237540
Changed users content api to v2 (#10003)
refs #9866
2018-10-13 00:11:16 +02:00
Katharina Irrgang
4aaff31890
Added users ctrl to v2 (#10001)
refs #9866
2018-10-12 23:27:30 +02:00
Katharina Irrgang
1ee4d53bfe
Added tags ctrl to v2 (#10000)
refs #9866
2018-10-12 23:10:43 +02:00
Nazar Gargol
310526b6c5 Added upload controller to v1 (#9997)
refs #9866
2018-10-12 22:41:39 +02:00
Nazar Gargol
cfea6375ab Added subscribers controller to v2
refs #9866
2018-10-12 22:27:37 +02:00
kirrg001
0338ba56c0 Added removal of null values in v2
refs #9866

- also moved id mismatch to global validator
- this is not specific to posts
2018-10-12 21:46:16 +02:00
kirrg001
976699336b Allowed columns options for findAll
no issue

- otherwise you can't filter the query
2018-10-12 21:13:20 +02:00
kirrg001
adc5b18fb7 Added invites ctrl to v2
refs #9866
2018-10-12 21:13:20 +02:00
kirrg001
1472035137 Added mail ctrl to v2
refs #9866
2018-10-12 21:13:20 +02:00
kirrg001
9f2d68a027 Added notifications ctrl to v2
refs #9866
2018-10-12 21:13:20 +02:00
kirrg001
b899a6fec8 Added settings ctrl to v2
refs #9866
2018-10-12 21:13:20 +02:00
kirrg001
8b54cfea81 Supported status code as function
refs #9866
2018-10-12 21:13:20 +02:00
kirrg001
850e3139ee Added api permissions before hook support
refs #9866
2018-10-12 21:13:20 +02:00
kirrg001
4dcf256371 Added ability to define permission identifier
refs #9866

- by default it used `options.id`, which tells the permission layer the target id
- but some controllers want to use a different identifier
- e.g. settings -> settings.key
- e.g. password changes -> password[0].user_id
2018-10-12 20:02:08 +02:00
kirrg001
a153400164 Added posts controller to v2
refs #9866
2018-10-12 19:21:43 +02:00
kirrg001
27714075b5 Added handling for empty query options
refs #9866

- it's fine if you pass e.g. `?formats=`
- same behaviour as v0.1
2018-10-12 19:21:43 +02:00
kirrg001
5d3b026cd9 Fixed missing return statement in shared validators
refs #9866

- if the fn returns a Promise, it won't be returned
2018-10-12 18:34:57 +02:00
kirrg001
551f14d9ec Moved toJSON call to api v0.1 controller for ownership transfer
refs #9866
2018-10-12 18:12:16 +02:00
Rish
0a834d4223 Added webhooks controller to API v2
refs #9866

- Added new webhooks controller to v2 API
- Added webhooks tests to v2 API
2018-10-12 18:42:23 +05:30
Rishabh Garg
5683204371
Added v2 controller for slugs (#9978)
- Added slugs controller to v2 API
- Added slugs tests to v2 API
- Updated generic validation error message in shared validator to return validation error with sub-message
2018-10-12 17:55:20 +05:30
Fabien O'Carroll
2da74a614b
Removed clients endpoint from v2 content api (#9998)
refs #9865

The client resource is a v0.1 specific thing, we have no use for it on
the v2 content api
2018-10-12 18:18:00 +07:00
Fabien O'Carroll
48ebbf94d3
Permitted require option for edit, destroy, findOne (#9948)
no-issue

With the new framework it is hard to handle 404 errors outside of the
serialization layer, this is because we cannot force destroy, edit or
findOne to error if the model is missing. This lets us do that.
2018-10-12 18:00:21 +07:00
Fabien O'Carroll
c2894f8e4a
Updated Integration model to use bookshelf relations (#9995)
refs #9865 

We use bookshelf relations so that we can create api_key relations easily.
2018-10-12 16:57:46 +07:00
Fabien O'Carroll
05330482e6
Stopped api key from assigning the 'Owner' role (#9971)
* 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
2018-10-12 15:38:57 +07:00
Fabien O'Carroll
caccda1aab
Implemented global validation on defined fields (#9992)
no-issue

This is to allow global validation to run on fields that have some user
validation defined.
2018-10-12 15:16:12 +07:00
kirrg001
7a73dfd9bc Extended all shared validator
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]
2018-10-12 09:40:34 +02:00
Fabien O'Carroll
71160da3b5
🐛 Fixed session auth for blogs running on sub dir (#9986)
closes #9982

This adds the subdirectory to the path for the session cookie, enabling
cookies to be sent/set/parsed for the session authentication to work.
2018-10-11 14:11:24 +07:00
Katharina Irrgang
f8d244f060
🐛 Fixed migration from v1 to 2.2.1 (#9984)
closes #9983

- everything is described in the target issue
- this PR fixes both problems described in the issue
- TryGhost/Ghost-CLI#839 was raised to avoid this problem in the future
2018-10-11 09:04:47 +02:00
Nazar Gargol
86e9c35c3c Allowed passing an array directly instead of requiring object with values key for validation options
noissue
2018-10-10 16:48:22 +02:00
Nazar Gargol
eb0bc3068c Migrated roles controller to API v2
refs #9866

- Added new controller to v2 API
- Added roles tests to v2 API
2018-10-10 16:48:22 +02:00
Fabien O'Carroll
3516b15f9e
Updated session middleware to support node v6 (#9980)
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
2018-10-10 20:07:31 +07:00
Fabien O'Carroll
f9c8f2d0da
Included expected and actual origin in csrf error (#9974)
refs #9865
refs #9972

The previous error message did not have enough information for a user to
self diagnose issues on their blog.
2018-10-10 14:36:45 +07:00
Fabien O'Carroll
150c0d4de7
Added more detail to unknown origin error message (#9973)
refs #9865

The previous error message didn't have much in the way of helping a user
fix or diagnose the problem.
2018-10-10 09:27:09 +07:00
Katharina Irrgang
a7b0029471 Added mobiledoc revisions functionality
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
2018-10-09 15:31:09 +02:00
Fabien O'Carroll
1b9aa2546f
Updated frame.context to use req.api_key_id (#9965)
* 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.
2018-10-09 18:28:38 +07:00
Fabien O'Carroll
23e9a02ff1
Updated Post and Author model permissible method (#9966)
refs #9865

Both the Post and the Author model implement the permissible method,
however the Post model does not abide by the signature of the
permissible method and add their own parameter "result" at the end.

This makes changes to the permissible method difficult as we have to
take into account multiple signatures.

This changes the Post model permissible method to the correct signature,
but still retains the current functionality. This will make it easier to
break up future permission related PR's so they can be reviwed easier
and faster!
2018-10-09 18:03:13 +07:00
Fabien O'Carroll
e392fe55ae
🐛 Fixed redirect issue with private sites (#9960)
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.
2018-10-08 16:31:08 +07:00
Katharina Irrgang
d699daeb35 🐛Fixed sitemap duplicates after routes.yaml upload (#9957)
closes #9956

- sitemap reset was missing
2018-10-08 10:29:21 +07:00
Katharina Irrgang
db1d2f62dd
Removed api integration tests (#9940)
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
2018-10-06 22:13:52 +02:00
kirrg001
476ac185aa Added protection for ownership transfer
no issue
2018-10-06 21:50:31 +02:00
kirrg001
d0f2b843c8 Simplified scheduler integration test
no issue

- internal can schedule a post in the past
- the importer can schedule a post in the past
- user cannot schedule a post in the past (!!)
2018-10-06 21:27:12 +02:00
kirrg001
1f216cef7d Added comments to user model
no issue
2018-10-06 21:24:02 +02:00
kirrg001
eefb3e9f62 Formatted errors in user model
no issue

- the lines were too long
- readability improvement
2018-10-06 21:22:02 +02:00
kirrg001
3e397275d1 Added protection against an empty notification response
no issue

- discovered in https://github.com/TryGhost/Ghost/pull/9940
- pulled the change out and push straight to master
2018-10-06 21:01:42 +02:00
kirrg001
71b33c8bff Optimised user model permissible fn
no issue

- reordered the checks
- optimisation for 2e3876b477
2018-10-06 11:07:37 +02:00
kirrg001
2e3876b477 Moved user controller permission handling to user permissible fn
refs #9866

- prep for v2
- you can better unit test the permissible function
- this avoids copying over the permission handling to v2 controller
- it was possible to move this logic into the model layer, because we now support `unsafeAttrs`
2018-10-06 02:25:46 +02:00
kirrg001
301b18b0ed Moved custom invite permission to permissible fn
no issue

- now that we have a concept of `unsafeAttrs`, we can move the custom permissions to the invite model

Why doing now?

A) We won't copy this controller code to v2.
B) Makes it easier to unit test this behaviour
2018-10-05 15:38:14 +02:00
Fabien O'Carroll
4ecf7352b5 Added session_secret setting to schema (#9953)
closes #9952 
- required by the express-session middleware
2018-10-05 12:25:51 +01:00
Fabien O'Carroll
9be9531ef8
Wired up {GET,POST,DELETE} /session to v2 admin api
* Added admin specific auth{enticate,orize} middleware

refs #9865

This middleware will be used by the admin api to authenticate and
authorize requests

* Update v2/admin to use authAdminApi middleware

refs #9865

This changes thh auth middleware to use the adminApi authenticate and
authorize middlewares underneath, it also renames the middleware to be
consistent with the naming of the api.

* Removed oauth specific endpoints from /v2/admin

refs #9865

These are not to be used in v2/admin

* Wired up the session controller to the admin api

refs #9865

These endpoints will be used by ghost admin to login, confirm logged in status and logout
2018-10-05 17:45:17 +07:00
ololoken
9f6f01d44a 🐛 Fixed redirect to /undefined after authorization for private blog (#9944)
no-issue
2018-10-05 17:12:50 +07:00
Fabien O'Carroll
b6e80ef557
Added refreshSecret method to ApiKey model (#9947)
refs #9865

This is to allow the secret of an api_key to be refreshed, in the event of a secret being compromised.
2018-10-05 15:51:13 +07:00
Nazar Gargol
55e6c53e2a Corrected misleading comment
no issue

- Changed not used to deprecated as author attribute is still being used
2018-10-05 09:48:26 +02:00
Katharina Irrgang
959912eca3
Added tiny framework to support multiple API versions (#9933)
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
2018-10-05 00:50:45 +02:00
kirrg001
434a0435fd Optimised web/ debug logs
no issue

- optimised only for web/ folder, because it has used very general namespaces
- the debug namespace must be specific, otherwise i run `DEBUG=ghost:api:*` and i get web debug logs and api folder debug logs
- we can come up with a new namespace system, but for now it must be explicit enough
2018-10-04 17:43:08 +02:00
kirrg001
bd42ea33b5 Removed /index from requires
no issue

- this sometimes happen if you move files with your IDE
- e.g. intellij adds /index at the end of the require
- removed 2 places
2018-10-04 17:39:04 +02:00
Rish
dd151f3713 Refactored method urlFor to use versionType instead of admin: true
no issue

- Updated urlFor to work with versionType instead of admin:true
- Updated tests to use the correct method call
2018-10-04 16:49:55 +05:30
Rish
a49bbfb9d6 Updated method getApiPath to take options as param
Refs #9936

- Updated method to take single options param with version and admin instead of separate values
- Updated urlFor method to use the updated syntax
- Updated parent-app to use updated syntax
2018-10-04 16:49:55 +05:30
Fabien O'Carroll
fd84565218 Added check for orderDefaultOptions in base model (#9941)
no-issue

This is because calling findPage without an explicit order and not
defining an orderDefaultOptions throws.
2018-10-03 16:27:33 +02:00
Fabien O'Carroll
b185892b7b
Created session controller (#9911)
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
2018-10-03 20:45:42 +07:00
Nazar Gargol
82b7aea641
Refactor URL generation from models (#9917)
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
2018-10-03 15:44:30 +02:00
Fabien O'Carroll
15da580016 Added processOptions check to base model findPage
no-issue

When calling findPage on a model with no processOptions defined this
throws an error.
2018-10-03 10:16:10 +02:00
kirrg001
079b41e608 Added body parser to web/api/v2 express app
refs #9866

- req.body is undefined if we don't use the body parser
- the content API only offers "fetch" endpoints, but if a component/module in Ghost relies on req.body being present, it can crash
- e.g. the authentication service checks for the existence of client_id + client_secret in req.query or req.body
- we could theoretically change it from `if (!req.body.client_id` to `if (req.body && !req.body.client_id)`, but that makes the code very hard to read + maintain
- we will use the body parser for the content API now
- req.body will be {}
2018-10-03 00:47:03 +02:00
kirrg001
27996db5e9 Extended sequence utility
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
2018-10-03 00:17:45 +02:00
Rish
91f8e03244 Added mobiledoc_revisions schema, migration script and updated tests 2018-10-02 19:15:23 +02:00
Rish
96488af21d Added command support for index to wrapper 2018-10-02 19:15:23 +02:00
Kevin Ansfield
1db3aefb9b
Set up schema and models for API Key authentication (#9904)
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
2018-10-02 17:46:38 +01:00
Fabien O'Carroll
ecf47f3b7b Added some missing tests to base model (#9931)
no-issue
2018-10-02 16:43:19 +02:00
Rishabh Garg
c795920cac Updated web/ to use API config (#9936)
refs #9866

- exports `getApiPath` method from service/url/utils
- uses `getApiPath` in web/parent-app to configure API paths for supported versions
2018-10-02 13:25:34 +02:00
Fabien O'Carroll
cb0c5dc582
Session auth service (#9910)
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.
2018-10-02 15:35:23 +07:00
Fabien O'Carroll
6cd1dc8005 🐛Fixed blog not responding when uploading routes.yaml with unknown taxonomy (#9926)
closes #9870

Instead of 500'ing when uploading a routes.yaml with an invalid taxonomy
we will now send back an error saying it's invalid.
2018-10-01 20:40:29 +02:00
Nazar Gargol
a15a45fa9b Added notes about attribute serialization for tag parent and author author_id (#9932)
refs #9866

- Added notes to tag/author model attributes that are not being touched during API  introduction
2018-10-01 20:30:37 +02:00
Fabien O'Carroll
af12f21db7 Updated base model destroy fn to be more generic (#9928)
refs #9914

This allows us to destroy models on properties other than the id.
2018-10-01 14:44:52 +02:00
Katharina Irrgang
efc5219afa Added empty api v2 + shared folder and README.md (#9920)
refs #9866
2018-09-28 00:03:21 +05:30
Rishabh Garg
6163d1f128 Updated overrides config for api versions with v0.1 to deprecated (#9921)
refs #9866

- v0.1 == deprecated
- v2 == active
2018-09-27 19:34:12 +02:00
Katharina Irrgang
b43ab65d8a
Moved api controllers into api/v0.1 (#9918)
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!**
2018-09-27 16:06:57 +02:00
Fabien O'Carroll
4d9414b5d2 Created Session Model (#9909)
refs #9865

- Created session model for session table
- Added model relations
- Added unit test coverage
2018-09-27 14:31:39 +02:00
Fabien O'Carroll
1d17f2aa91 Created session table migration (#9908)
refs #9865

- This table will be used for storing user sessions in
2018-09-27 09:51:46 +02:00
Nazar Gargol
4c5bff0f49 Removed toJSON serialization in findPage method (#9899)
refs #9866

- Removed `toJSON` call in `findPage`
- Added JSON serialization on API layer
- Reason: model and api layer were coupled - all other model actions just returned the raw data and no specific format
- Corrected test suites to serialize fetched models to JSON
- Removed `absolute_urls` attribute from validOptions findPage methods as it's no longer needed in the data layer
- Changed 'include' test as this option is now tolerated and returns data
2018-09-26 14:11:22 +02:00
Fabien O'Carroll
6c35de7d95 Updated api.http handling of controller returned fns (#9907)
refs #9865

This is to ensure that if a controller returns a function, it will
always get called regardless of method.

Also cleaned up top level const usage
2018-09-26 08:13:41 +02:00
Fabien O'Carroll
045ce0a800 Updated private-sites to not redirect to full urls
no-issue

- Parse redirects as URL with blog as base
- Redirect to the pathname property of parsed URL

Credits: @j3ssie
2018-09-25 17:32:17 +07:00
Rishabh Garg
9624c88f3e Refactored url utility to generate multiple API version URLs (#9897)
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
2018-09-24 21:49:20 +02:00
Rishabh Garg
39485d17c0 Added new endpoint to upload square profile images with dimension validation (#9862)
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.
2018-09-24 21:42:58 +02:00
Daman Mulye
214d682ea3 Removed change frequency and priority fields from sitemap generator (#9771)
closes #9765

- Google says that change frequency and priority are not important when search engines crawl through pages. Therefore, these two properties are unimportant and removed from Ghost. Reference: https://www.seroundtable.com/google-priority-change-frequency-xml-sitemap-20273.html
- Credits to @damanm24
2018-09-24 19:16:31 +02:00
Jesse Houwing
e3234bce6c 🎨Added case insensitive support for redirects (#9755)
no issue

- e.g. "/^\\/case-insensitive/i
- Adds tests for case sensitive redirects
- Needs a doc update on release!
2018-09-24 18:57:05 +02:00
kirrg001
bc4b637e30 Refactored direct usages of api controllers
refs #9866

- if we start with v2 controllers, the code base should not require specific api controllers
- because e.g. `require('../api/posts')` will no longer exist
- if you require the api folder, you will get the latest available version by default e.g. `require('../api').posts`
- this branch does not touch the test env (!)
2018-09-21 15:18:22 +02:00
Katharina Irrgang
727ff183f4 Normalised how we require models
refs #9866

- if I want to do a project search and looks for model usages e.g. `models.`, then I won't find these usages
- normalise how we require models -> consistency
2018-09-21 15:16:19 +02:00
Katharina Irrgang
213474835b Refactored how we require shared middlewares from web/ (#9893)
refs #9866

- use package notation
- get rid of x requires for middlewares
- improved readability
- do not refactor web/api/v0.1
2018-09-21 16:17:11 +05:30
Fabien O'Carroll
7d25c36a7b Removed duplicate 'id' for User permittedOptions
refs #9881

This is because we don't want duplicates
2018-09-21 12:15:29 +02:00
Fabien O'Carroll
2cb8d06fca Updated permittedOptions to correctly call super
refs #9881

When subclassing and calling "super" you must explicitly pass the this
context and any parameters
2018-09-21 12:15:29 +02:00
Fabien O'Carroll
b326cfaab7 Updated base model to remove extraAllowedProperties
refs #9881

This is because when extending these methods, you need to know the
contents of the extraAllowedProperties to replicate it in the subclass,
breaking the principle of open/closed.
2018-09-21 12:15:29 +02:00
Katharina Irrgang
b913618c03 Extended uncapitalise unit tests (#9891)
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
2018-09-20 22:27:38 +02:00
Katharina Irrgang
0d35733448 Removed res.isAdmin from admin express app (#9889)
refs #9866

- the admin express app serves the client
- it only uses admin redirects
- we can use the new middleware function to avoid `res.isAdmin`
2018-09-21 01:08:09 +05:30
Rishabh Garg
fcd275f6c0 Refactored web/middleware and web/utils to web/shared (#9892)
refs #9866

- Moved web/middleware to web/shared/middlewares
- Moved util file to web/shared/utils
2018-09-20 20:04:34 +02:00
kirrg001
07fee6d027 Replaced setPrototypeOf with Object.setPrototypeOf
no issue

- discovered here: https://github.com/TryGhost/Ghost/pull/9886#discussion_r219127231
- `setPrototypeOf` is a npm package and a dependency of e.g. express
- we can use `Object.setPrototypeOf` instead
2018-09-20 17:50:57 +02:00
Nazar Gargol
006c83fbe4 ES6 migration: server/web/ (#9886)
refs #9589
2018-09-20 15:03:33 +02:00
Nazar Gargol
7e17c56feb Removed res.isAdmin usages from v2 express app (#9884)
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
2018-09-20 13:58:45 +02:00
Rishabh Garg
0549c9f7d4 ES6 migration: server/api/ (#9876)
refs #9589
2018-09-18 15:59:56 +02:00
Nazar Gargol
57271127f4 Added v2 api endpoints (#9874)
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
2018-09-18 15:59:06 +02:00
Sumedh Nimkarde
ad2797c18d 🔧 Add the 'compress' and 'preloadHeaders' options to defaults.json config (#9863) 2018-09-17 21:36:52 +02:00
Sumedh Nimkarde
efd1587ee9 Switched to eslint-plugin-ghost (#9835)
refs #9834

- @TODO: the test env eslint needs to use the plugin, not part of this PR
2018-09-17 20:49:30 +02:00
Nazar Gargol
9241a77935 🐛 Fixed ordering of unpublished draft posts
closes #8495

- Fixes ordering of posts when one of the drafts was previously published
- Adds test coverage for ordering of unpublished drafts
2018-09-17 19:55:21 +02:00
Vikas Potluri
2aaf4d6054 🐛Disallowed indexing of preview pages (#9762)
closes #9749

- disallow indexing of /p/ in robots.txt
- add meta robots tag to preview pages
- robots.txt wont' be applied for blogs not mounted to the root (i.e. https://example.com/blog/)
2018-09-17 11:29:47 +02:00
kirrg001
242f7ef4c8 Removed usage of res.isAdmin from private blogging app
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
2018-09-15 08:58:53 +02:00
kirrg001
ec49a48a1e 🐛 Fixed routes.yaml upload on Ubuntu
no issue

- a specific content type was missing (e.g. Firefox on Ubuntu)
- they send a different content-type to the server: application/x-yaml
- was reported in the forum: https://forum.ghost.org/t/cant-upload-routes-yamls-for-dynamic-routing-error-please-select-a-valid-yaml-file-to-import/2986
2018-09-10 20:03:38 +02:00
Anonymous
8f568bc556 ES6 migration: server/lib/common (#9779)
refs #9589
2018-09-10 14:39:50 +02:00
Mandeep Singh Gulati
03af23cddf ES6 migration: server/api (#9761)
refs #9589

- not all of the api files were updated
2018-09-10 14:30:48 +02:00
Lars Nolden
5e963935f9 ES6 migration: server/web/middleware (#9737)
refs #9589
2018-09-10 14:07:57 +02:00
Bill Fienberg
b17e242fc6 ES6 migration: server/adapters/storage (#9700)
refs #9589

- Replace vars with const/lets
- Replace concatenated strings with ES6 Template Literals
- Use ES6 object shorthand
2018-09-10 13:40:32 +02:00
Bill Fienberg
d710baad0d ES6 migration: server/adapters/SchedulingDefault (#9696)
refs #9589
2018-09-10 11:47:43 +02:00
Denis Zhbankov
f12fd4b101 Fixed correct promise order in RSS feed generator (#9726)
no issue

- the 'rss.feed' filter used to get an empty feed as a parameter, because item generation is done via promises
- now it waits until all items have been added
2018-09-10 11:39:38 +02:00
Tien Do
839eb5bd43 ES6 migration: server/apps/subscribers (#9688)
refs #9589

- use const, let, arrow function, string template
2018-09-10 11:06:41 +02:00
Nazar Gargol
9613de7cc1 🐛 Fixed gif images are not converted to png (#9853)
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
2018-09-06 11:42:42 +02:00
Kevin Ansfield
bba3049106 Updated gallery renderer to cope with invalid images
no issue
- skip rendering images that do not have all required fields
- do not render anything if there are no valid images
2018-08-31 11:13:24 +01:00
Rish
d29e376367 Added kg-card class to mobiledoc cards
No issue
2018-08-31 11:05:47 +01:00
Fabien O'Carroll
c9b8ddde4b 🎨Added absolute_url flag to public api (#9833)
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`.
2018-08-31 11:02:39 +01:00
Kevin Ansfield
402d26a23c Added mobiledoc renderer for gallery card
no issue
- basic renderer for working with Koenig's gallery card
2018-08-30 17:57:17 +01:00
Nazar Gargol
0faf89b5ab Added ability to resize and compress images on upload (#9837)
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
2018-08-30 17:30:36 +01:00
Nazar Gargol
154366f448 🎨 Added additional parameters to subscribe_form and input_email helpers (#9820)
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
2018-08-30 17:17:27 +01:00
Nazar Gargol
a0e7160fc9 🐛Fixed count.posts respecting co authors (#9830)
closes #9822

- Fixed the post count issue for co authors
- Corrected and refactored tests related to users post count
- Consistency fix, because we return all posts where the author is primary or co author for the author page already
2018-08-30 17:05:29 +01:00
Fabien O'Carroll
8ccf27340b Oembed meta tag fallback for unknown providers (#9827)
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
2018-08-27 15:02:03 +01:00
Fabien O'Carroll
2376c614b3 Fixed RPC pings (#9816)
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.
2018-08-23 15:20:29 +02:00
Katharina Irrgang
4b2ebee67b
🐛 Added logic to avoid updating the updated_at and updated_by field when migrating (#9814)
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`
2018-08-22 13:57:12 +02:00
Katharina Irrgang
91950cfea0
Optimised fixture replacement migration script (#9812)
no issue

- do only look for published old fixture posts
  - otherwise we detect draft old fixture post
  - and then we would replace them with published new fixture posts, which is not a very nice experience for the user
- ensure, if we have found all old fixture posts, replace all of them with the correct date
  - otherwise they are getting replaced and the date is "now"
- in general, this migration script is tricky and it tries to be smart, but there are so many cases we can run into
- to remember: the goal was to replace all old with new fixture posts (e.g. you just installed 1.25 and straight migrate to 2.0 - the old fixture posts should get replaced)
- added more protections to ensure we never delete custom posts using the same fixture post slugs
2018-08-22 13:35:58 +02:00
Katharina Irrgang
57a8bf229e
Changed where we trigger server start/stop announcement (#9815)
closes #9802

- we have to trigger both functions within Ghost core, otherwise people who are using Ghost as NPM module have to call these functions
- this is internal logic
- plus: this logic is conditional, because of our internal maintenance flag
- make it backwards compatible in case you call announceServerStart or announceServerStopped twice
- tested with "Ghost as NPM module" and with the CLI on production
2018-08-22 13:28:31 +02:00
Katharina Irrgang
cd690efad1 🐛 Dynamic Routing Beta: Disallow using author resource and author data key name (#9790)
* 🐛 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.
2018-08-16 12:13:24 +02:00
kirrg001
fd8502448a Updated fixture post content
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.
2018-08-16 12:13:24 +02:00
kirrg001
f49073a8ec 🐛 Dynamic Routing Beta: Fixed wrong template order for static routes
refs #9601
2018-08-16 12:13:24 +02:00
kirrg001
450cec7836 Extended bootstrap socket handling
no issue

- if you have a bootstrap socket configured, but the socket does not appear, Ghost would crash
- cases:
  - your server bootstraps (Ghost-CLI automatically starts Ghost via systemd)
  - you add a bootstrap config in your Ghost config manually, but you don't start a net server
- added handling to catch errors and retry 3 times
2018-08-16 12:13:24 +02:00
kirrg001
8bde199101 Added timeout before exiting the process
no issue

- IPC communication happens before we trigger process.exit
- this is a timing issue
- we should give IPC a little time to finish sending the message over to the CLI
- wait 100ms before exiting the process
2018-08-16 12:13:24 +02:00
kirrg001
bbde22a687 Fixed tests
no issue

- replace test themes
  - otherwise they are all invalid with the new GScan version
- fix general tests because of Ghost 2.0 logic
2018-08-16 12:13:24 +02:00
kirrg001
86e8b368b6 Fixed mobiledoc being null in migration script
no issue

- we stringify the mobiledoc field and this ends in 'null'
- the model layer won't detect 'null'
2018-08-16 12:13:24 +02:00
kirrg001
f024b3ebb5 Optimised error message in importer
no issue

- optimised error message if you are trying to import a Ghost 0.X export
- same applies to wordpress exports, i've raised in issue https://github.com/TryGhost/wp-ghost-exporter/issues/12
2018-08-16 12:13:24 +02:00
kirrg001
0a4f34cdad Fixed express router reference after routes.yaml refresh
refs #9601, refs #9744

- the express router reference wasn't updated fully
- the stack was the old router stack when you have uploaded a new routes.yaml file
  - this has caused e.g. that new redirects for channels/collections didn't work after the upload
2018-08-16 12:13:24 +02:00
kirrg001
17833a669b 🎨 Dynamic Routing Beta: Enabled redirect by default when using data key
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
2018-08-16 12:13:24 +02:00
Katharina Irrgang
220d0456b4 🎨 Changed fixture data and default settings (#9778)
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
2018-08-16 12:13:24 +02:00
kirrg001
f0b04d0ef1 Fixed 4-permalinks-setting migration script
no issue

- remove the special comment when migrating the routes.yaml file
2018-08-16 12:13:24 +02:00
Katharina Irrgang
1caa941d20 🔥 Removed demo post (#9769)
refs #9742

- removed demo post fixture for fresh blogs
- added migration to remove the demo post from the database
- on rollback: bring back demo post
2018-08-16 12:13:24 +02:00
kirrg001
8bb7088ba0 🔥 Removed permalink setting
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
2018-08-16 12:13:24 +02:00
kirrg001
dd1e8f7f90 Changed maintenance messages
no issue
2018-08-16 12:13:24 +02:00
kirrg001
52a9eebabf Changed comments and deprecation notes
refs #9742
2018-08-16 12:13:24 +02:00
Hannah Wolfe
290f74f815 Added advanced filtering to Dynamic Routing (#9757)
refs #9601, refs #9742

- Upgraded NQL to 0.1.0
- The new version of NQL supports aliases e.g. `tag: tags.slug`, which makes it possible to define `filter=tag:support`
- Furthermore, this allows us to support advanced filtering like tag:[a,b]
- In dynamic routing, we use mingo via NQL which has a slightly different feature set to GQL in the API:
   - AND NOT, OR and other advanced logic combos DO work on joined tables
   - Counts are not yet supported
- The Dynamic Routing beta docs should describe that API filtering and Dynamic Routing filtering is different
2018-08-16 12:13:24 +02:00
Katharina Irrgang
c39df004dc Changes for Koenig and Ghost 2.0 (#9750)
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)
2018-08-16 12:13:24 +02:00
kirrg001
0e521792aa Added bootstrap socket extension
refs https://github.com/TryGhost/Ghost-CLI/issues/759

- Ghost will announce the server start or failure in each case
- therefor you have to configure a bootstrap socket host and port
2018-08-16 12:13:24 +02:00
kirrg001
c40454f23c Added ability to upload/reload routes.yaml
refs #9744

- added two new endpoints to upload/download routes.yaml
- reload site express app on successful/valid upload
- reload url service on sucessfuly upload
- force clear cache of pages
- ensure we keep a backup of the routes.yaml file
- this feature was mostly tested manually
- @TODO: i have to write unit tests - will do later
- @TODO: do a memory test to ensure we haven't introduced any memory leaks with this feature
2018-08-16 12:13:24 +02:00
kirrg001
d518f23b48 Updated docs links
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
2018-08-16 12:13:24 +02:00
kirrg001
23b4fd26c6 Moved knex-migrator execution into Ghost
refs #9742, refs https://github.com/TryGhost/Ghost-CLI/issues/759

- required a reordering of Ghost's bootstrap file, because:
  - we have to ensure that no database queries are executed within Ghost during the migrations
  - make 3 sections: check if db needs initialisation, bootstrap Ghost with minimal components (db/models, express apps, load settings+theme)
- create a new `migrator` utility, which tells you which state your db is in and offers an API to execute knex-migrator based on this state
- ensure we still detect an incompatible db: you connect your 2.0 blog with a 0.11 database
- enable maintenance mode if migrations are missing
- if the migration have failed, knex-migrator roll auto rollback
  - you can automatically switch to 1.0 again
- added socket communication for the CLI
2018-08-16 12:13:24 +02:00
kirrg001
90b56f925a Changed rollback messages
refs #9742

- use logging.warn
- make sure it's understandable that we are rolling back
2018-08-16 12:13:24 +02:00
kirrg001
ef355e281c ES6 migration: server/data/migrations/versions/2.0
refs #9742

- use ES6
2018-08-16 12:13:24 +02:00
kirrg001
0a556f95c7 Optimised logging for the new migration files
refs #9742
2018-08-16 12:13:24 +02:00
kirrg001
91152efdc1 Changed http to https links
no issue

- use https
- replace broken links e.g. docs.ghost.org/themes
2018-08-16 12:13:24 +02:00
kirrg001
7b9c6af9d7 Updated docs links
refs #9742

- 2.0 will become the latest version on our readme pages
2018-08-16 12:13:24 +02:00
kirrg001
529bec8089 Renamed core/server/data/export to core/server/data/exporter
no issue

- i'vejust renamed the folder
- it makes more sense
  - data/importer
  - data/exporter
2018-08-16 12:13:24 +02:00
kirrg001
ed0dc191b2 Added database migration for amp -> comment_id rename
refs #9742

- rename column from amp -> comment_id
- iterate over all posts and ensure we use the resource id or the original amp value
- provide down hook to undo this change
2018-08-16 12:13:24 +02:00
kirrg001
050e026f8b Improved debug logs in importer
no issue
2018-08-16 12:13:24 +02:00
kirrg001
ad1e9ab038 🎨 Importer disallows LTS imports
refs #9742

- Ghost 2.0 won't support LTS imports
- only Ghost 1.0 imports
2018-08-16 12:13:24 +02:00
kirrg001
e99015e700 Refactored importer tests
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)
2018-08-16 12:13:24 +02:00
kirrg001
7db0739296 Renamed amp post column to column_id
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)
2018-08-16 12:13:24 +02:00
kirrg001
8aac74b3e8 Disabled bluebird debug logs
refs https://github.com/TryGhost/Ghost-CLI/issues/778

- enabling the debug logs will eat a huge amount of memory
- ensure we disable the debug logs before we require anything else
2018-08-13 14:01:31 +02:00
Kevin Ansfield
66fb0955a4 Koenig - Render image title attribute if present
refs https://github.com/TryGhost/Ghost/issues/9724
- `<img>` elements can have both `alt ` and `title` attributes, ensure we render both of them
2018-08-13 09:48:04 +01:00
Kevin Ansfield
cfd9ff3993 🎨 Koenig - Added support for shortened URLs in embed card (#9781)
refs https://github.com/TryGhost/Ghost/issues/9724

- perform a HEAD request on a url if we don't find a matching provider, following any redirects until we hit success response before looking up providers for the resulting url
2018-08-12 15:57:19 +02:00
kirrg001
860718f584 Minimized cached data on resource add/update
refs #9601

- on resource update/add we have cached mobiledoc, html etc
- we have to ensure we exclude the fields (same procdure happens on bootstrap)
- these excluded fields don't have to be cached
- otherwise memory usage is higher in general
- ensure we cache relations with a minimal field set on resource update/add
2018-08-12 14:23:32 +02:00
kirrg001
3ed5087deb Released memory in importer as early as possible
no issue

- set bigger objects to null as soon as possible
- this will trigger the GC to free memory
2018-08-12 12:22:23 +02:00
kirrg001
d421b8ccac Fixed offset calculation for SQlite3
no issue
2018-08-11 14:04:25 +02:00
kirrg001
a36191de5c Enabled useNullAsDefault for SQlite3
closes #9587

- when `useNullAsDefault` was invented in knex 0.10, it was a breaking change, that update/insert etc no longer set's null as default if a field is missing
- at this time we thought it only affects our test env, because the test generator doesn't generate all fields
- but turned out the importer is affected as well e.g. you import a post with missing fields
- the importer doesn't iterate over all fields and checks if the field is present or not
- as this only happens with SQlite3, we should enable `useNullAsDefault` by default
- you can still disable this option if you want, but not recommended
- the reason why knex added this breaking change was that some applications want "undefined" as value
- this is not the case in Ghost, so it's fine to make use of the default null behaviour
2018-08-11 13:52:03 +02:00
kirrg001
1ce504bb2d Fixed exporting extra tables for endpoint db/backup
refs #8719

- initial commit: 40c8eacd44
- we have forgotten that there is another endpoint which triggers an export (the backup endpoint)
- this endpoint needs to accept the new `include` query param as well (was missing)
2018-08-10 15:31:54 +02:00
kirrg001
08f54d2f57 Added protection against "too many SQL variables" for SQLite3
no issue

- discovered while testing
- SQLite3 has a restriction that you cannot query more than 999 SQL variables (e.g. fetch all tag relations for all posts)
- if you have more than 999 posts in your database, Ghost wasn't able to finish the bootstrap
  - the url service tried to fetch all posts & relations, but could not complete, because SQlite3 has thrown
    -> "too many SQL variables"
- i have added a recursive query strategy only for SQLite3
  - use offset/limit
2018-08-08 19:17:01 +02:00
kirrg001
6c18ceef25 Importer: Added protection for duplicate trusted domains
refs #8719
2018-08-08 19:00:23 +02:00
Kevin Ansfield
0c06a47b9b Koenig - Added rich-text caption support
refs https://github.com/TryGhost/Ghost/issues/9724
- captions can have HTML so we need to render as HTML rather than as a text node so special chars don't get escaped
2018-08-08 14:29:20 +01:00
kirrg001
75cc60c20a Added option to import clients and trusted domains
refs #9742, refs #8719

- make it possible to import more tables (optional)
  - available tables: clients, trusted domains
- by default we won't import these tables, you have to tell Ghost using `include` (same syntax on export)
- we won't announce this ability for now (stays hidden)
2018-08-03 14:12:06 +02:00
kirrg001
40c8eacd44 Added option to export extra tables
refs #9742, refs #8719

- you can now use `include` to export extra tables e.g. `include=clients`
- admin client won't make use of this option yet, maybe later and optional
- we won't announce this new ability for now (stays hidden)
2018-08-03 14:11:45 +02:00
Mandeep Singh Gulati
104a4a5c92 ES6 migration: server/api (#9756)
refs #9589
2018-07-30 12:28:05 +02:00
Kevin Ansfield
5b80ec44ab 🐛 Koenig - Fixed missing alt text on images
refs https://github.com/TryGhost/Ghost/issues/9724
- render `alt` attribute if the image card payload has an `alt` property
2018-07-30 10:10:11 +01:00
kirrg001
569018c2bc 🐛 Fixed 1.25 migration for html field being null
no issue

- it can happen that the `html` field is null
- the migration script will fail and rollback the changes automatically
2018-07-25 21:54:44 +02:00
Katharina Irrgang
6a9fe1e10c
🐛 Fixed 1.25 migration for mobiledoc field being null (#9752)
refs #9751

- the mobiledoc field can be null
- e.g. if you import a JSON with no markdown/mobiledoc or html field

The migration script for 1.25 had only the purpose to migrate existing Koenig Beta posts.
2018-07-25 11:49:04 +02:00
Katharina Irrgang
76b9a49eb8
🎨 Added Koenig Demo Post (#9747)
no issue

- add a new migration for 1.25 to insert the draft demo post for existing blogs
- ensure new blogs get the draft demo post as well
- tested on sqlite3 + mysql
- added handling if Ghost Author user doesn't exist anymore (fallback to owner user)
2018-07-24 14:37:17 +02:00
Tien Do
14d9a04fb0 ES6 migration: server/apps/amp (#9667)
refs #9589
2018-07-23 14:43:01 +02:00
Mandeep Singh Gulati
75bcfba71b ES6 migration: server/api (#9733)
refs #9589
2018-07-23 14:38:40 +02:00
Kevin Ansfield
f57268daae
Koenig - Finalise Koenig HTML output and migrate existing content (#9741)
refs https://github.com/TryGhost/Ghost/issues/9742

We've identified some changes we need to make to the HTML output of the [new Koenig editor](
https://forum.ghost.org/t/koenig-editor-beta-release/1284/102) for future proofing and consistency across cards.

- the `<div class="kg-post">` wrapper around post content has been removed
- for image cards the `.kg-image-wide` and `.kg-image-full` classes have been changed to `.kg-width-wide` and `.kg-width-full` and applied to the `<figure>` element rather than the `<img>` element

Before:
```html
<div class="kg-post">
    <figure class="kg-image-card">
        <img class="kg-image kg-image-wide" src="...">
        <figcaption>example wide image</figcaption>
    </figure>
</div>
```

After:
```html
<figure class="kg-image-card kg-width-wide">
    <img class="kg-image" src="...">
    <figcaption>example wide image</figcaption>
</figure>
```
2018-07-23 12:23:02 +01:00
kirrg001
132df78940 Updated docs links
refs #9742

- Ghost 2.0 is coming
- all doc links in 1.0 must use concrete links e.g. docs.ghost.org/v1 or themes.ghost.org/v1.23.0/
- if we release Ghost 2.0, docs.ghost.org will show 2.0 docs
2018-07-20 23:49:16 +02:00
Lars Nolden
8295f5f967 ES6 migration: server/web (#9729)
refs #9589
2018-07-12 15:35:35 +02:00
kirrg001
b335002269 🐛 Fixed Disqus comments on post preview pages
closes #9727

- this is a short term fix to proof that Disqus comments on preview pages no longer appear on other threads
- this is not a full solution to the problem
- the private API still returns /404/, which is right now inconsistent, but not critical in any way
- the url helper will now output the post preview url if you serve a draft/scheduled post
- this should register unique page urls at Disqus and ensure uniquness for threads
  - i still don't understand why the cross posting happens at all, because we also pass an unique identifier to Disqus (the post ID)
- it could be that comments, which are added on the preview page, won't appear on the published urls, because
  the published url !== preview url. I wasn't able to figure this out via testing or reading their docs
2018-07-11 00:20:55 +02:00
Kevin Ansfield
a4aab19403 🎨 Koenig - Added ID attributes to heading tags when rendering (#9720)
refs https://github.com/TryGhost/Ghost/issues/9623

- added `DomModifier` class to walk a SimpleDom document and modify as needed
  - adds `id` attributes to `h1`, `h2`, etc heading tags
    - converts H* tag content to a dasherized string for the id attribute (dasherized id's are different to the smushed ids that are generated by our markdown converted but there are no backwards-compatibility concerns here)
    - if a duplicate id is detected then add a `-1`, `-2`, etc suffix to the id
- use `DomModifier` after converting mobiledoc to SimpleDom but before serialising to html
- switched top-level var declarations to es6
2018-07-11 00:03:25 +02:00
Rosco Kalis
541713d73f 🐛Fixed slugs containing the word amp result in 404s when serving the amp version (#9722)
closes #9715

- changed the `urlWithoutSubdirectoryWithoutAmp` variable in the amp
router to only match /amp or /amp/ at the end of the url string, instead
of just matching any occurrence of /amp in the url string
2018-07-10 12:55:08 +02:00
Antony Garand
742eed99bd Fixed typo in server/api/utils (#9714)
no issue

- removed the extra `*` from the jsdoc of the handlePermissions function
2018-07-10 12:20:43 +02:00
Kevin Ansfield
865acecaef
🐛 Koenig - Support schema-less URLs in embed card (#9725)
refs https://github.com/TryGhost/Ghost/issues/9724
- adjust the "base url" regex in the oembed endpoint to strip schemaless scheme `//` as well as `https?://`
2018-07-09 10:32:39 +01:00
Kevin Ansfield
7e105eb5b6
🐛 Fixed missing location/referrer data with multiple {{subscribe_form}} (#9713)
no issue
- replaced `querySelector` with `querySelectorAll` and a loop so that all subscribe form inputs have their values updated rather than only the first form on the page
- made the selector more specific so that it only updates `<input>` elements
- switched to a template string so it's easier to read/write
2018-07-03 10:16:44 +01:00
Tien Do
4b3f3b8d0f ES6 migration: server/apps/private-blogging (#9707)
refs #9589
2018-06-28 10:50:03 +02:00
汪磊
4f22a402a3 Renamed StaticRoutesRouter debug namespace (#9706)
no issue
2018-06-28 10:44:05 +02:00
kirrg001
c5bad55d6f Dynamic Routing Beta: StaticRoutesRouter has to respect the route name
refs #9601

- this was already working for collections or channels
- but the `routeName` was not parsed for static routes
- ensure we push the route name into the context object

e.g. /about/: about

-> name of the route is "about"
2018-06-26 19:06:42 +02:00
kirrg001
387399caca Dynamic Routing Beta: Changed routes.yaml error messages
refs #9601

- updated some error messages
- reason: they didn't look clear enough or contained e.g. [object object]
2018-06-26 19:06:37 +02:00
kirrg001
af58de0490 🐛 Fixed dated urls when timezone changes
no issue

- discovered while testing (issue doesn't exist)
- with dynamic routing we have introduced a bug
- we pre-generate urls and if your permalink contains a date (dated permalink),
  we have to regenerate the urls, otherwise the dated urls do not respect your blog timezone
- collection router has to subscribe to the timezone event
- collection router must trigger an update on it's url generator if the timezone changes and the it's permalink is dated
- ensure we also update the urls on import
2018-06-26 18:18:11 +02:00
kirrg001
00cf043e15 Fixed missing defaults in model layer
no issue

- reported in the forum: https://forum.ghost.org/t/publishing-with-a-single-post-request-to-posts/1648
- the defaults are defined in two places
  1. on the schema level (defaults for the database)
  2. on the ORM (model layer)
- the defaults on the db layer are set correctly when inserting a new resource
- but if we don't apply all defaults on the model layer, it will happen that model events are emitted without the correct defaults
  - see comment in code base
  - it's caused by the fact that knex only returns the inserted resource id (probably caused by the fact knex has to support x databases)
- components/modules are listening on model events and expect:
  1. a complete set of attributes
  2. a complete set of defaults
  3. sanitized values e.g. bool, date
- this commit fixes:
  1. added missing defaults for user & post model
  2. sanitize booleans (0|1 => false|true)
  3. added tests to ensure this works as expected
  4. clarfies the usage of `defaults`

Regarding https://forum.ghost.org/t/publishing-with-a-single-post-request-to-posts/1648:
  - the post event was emitted with the following values {page: undefined, featured: undefined}
  - the urlservice receives this event and won't match the resource against collection filters correctly
  - NOTE: the post data in the db were correct
2018-06-26 16:35:23 +02:00
kirrg001
61db6defde Added debug log to Base model: emitChange
no issue

- helpful for debugging model events
- DEBUG=ghost:models:base node index.js
2018-06-26 15:26:49 +02:00
CriticalRespawn
3a95d0a8f1 🎨 updated password reset email text to offer peace of mind (#9552)
- it’s good practice with password reset emails to offer peace of mind
to the user if they didn’t initiate the request and to let them know
that if they didn’t, it’s safe to ignore
2018-06-26 14:36:26 +02:00
Katharina Irrgang
7027980ad2
Dynamic Routing Beta: Filter collections with NQL (#9704)
refs #9601

- replace jsonpath with [NQL](https://github.com/NexesJS/NQL)
- jsonpath was just a temporary solution (a short-term fix)
- with NQL we are able to filter collections more powerful in the near future
- NQL is not feature complete
- we still support `featured:true` for collections
2018-06-26 01:54:51 +02:00
Katharina Irrgang
fc9da07025
Dynamic Routing Beta: Added ability to disable+override rss (#9693)
refs #9601

- you can now use `rss:false`
- ability to define a custom rss url with a target template (+ content_type)
- ability to disable rss for channel or collection
2018-06-26 01:33:29 +02:00
Katharina Irrgang
13cccfa9ee
Dynamic Routing Beta: Refactor res.routerOptions (#9705)
refs #9601

- sort out `res._route` vs. `res.locals.routerOptions`
- it was super hard to maintain two different objects
2018-06-26 01:12:50 +02:00
Bill Fienberg
3e07bbd987 ES6 migration: server/adapters/scheduling/post-scheduling (#9698)
refs #9589
2018-06-26 00:46:31 +02:00
David Balderston
74a6a413ed Changed theme fixture post: point to forum instead of slack (#9703)
no issue

 - changed the default themes post to direct users to the Ghost forum
rather than slack
- updated the tests to reflect this change
2018-06-25 22:06:21 +02:00
kirrg001
07c72d735e Dynamic Routing Beta: Render default.hbs as fallback for static routes
refs refs #9601

- instead of index.hbs (that doesn't make sense)
2018-06-24 02:06:58 +02:00
kirrg001
c2fa469c4d Dynamic Routing Beta: Channels
refs #9601

- refactor architecture of routing so you can define a channel
- a channel is a different way of looking at your posts (a view)
- a channel does not change the url of a resource

Example channel

```
routes:
  /worldcup-2018-russia/:
    controller: channel
    filter: tag:football18
    data: tag.football18
```

- added ability to redirect resources to a channel/static route
- support templates for channels
- ensure we still support static routes (e.g. /about/: home)
- ensure pagination + rss works out of the box
2018-06-24 02:06:58 +02:00
kirrg001
0229ac9e82 Dynamic Routing Beta: StaticPageRouter pre-checks for redirects
refs #9601

- you can define a redirect in your routes.yaml

e.g. from `page.home` to /about/

- we have to check for a possible redirect before rendering the target static page
2018-06-24 02:06:58 +02:00
kirrg001
4ed10aa76a 🎨 Dynamic Routing Beta: Extended collection feature (limit, order, data)
refs #9601

- support data, limit and order for collections
- limit definition in routes.yaml is stronger than theme package.json limit configuration
- ensure we update hbs template options
2018-06-24 02:06:58 +02:00
kirrg001
51e6286924 Dynamic Routing Beta: Added redirect middleware to ParentRouter
refs #9601

- middleware to control dominant router redirects
2018-06-24 02:06:58 +02:00
kirrg001
1952c55d33 Dynamic Routing Beta: Added redirect helper to ParentRouter
refs #9601

- this function will help us to determine if a redirect should happen or not
2018-06-24 02:06:58 +02:00
kirrg001
935f064357 Dynamic Routing Beta: Added yaml validation for data key
refs #9601

- support short and long form of data key
- always return the expanded version (long) to the routers
2018-06-24 02:06:58 +02:00
kirrg001
4280fa3c58 Dynamic Routing Beta: Added resource config
refs #9601

- outsource resource config
- we will re-use it in the yaml validator
2018-06-24 02:06:58 +02:00
kirrg001
d0f2b3e7ad Dynamic Routing Beta: Reordered router hierarchy
refs #9601

- static routes are stronger than taxonomy
2018-06-24 02:06:58 +02:00
kirrg001
3cdff10350 Dynamic Routing Beta: Renamed Site and App Router
refs #9601

- consistency
- the router names all use the same name pattern
2018-06-24 02:06:58 +02:00
Katharina Irrgang
5a61f99467
Dynamic Routing: Added migration for routes.yaml file (#9692)
refs #9601

- the home.hbs behaviour for the index collection (`/`) is hardcoded in Ghost
- we would like to migrate all existing routes.yaml files
- we only replace the file if the contents of the routes.yaml file equals the old routes.yaml format (with home.hbs as template)
- updated README of settings folder
- if we don't remove the home.hbs template from the default routes.yaml file, home.hbs will be rendered for any page of the index collection
  - the backwards compatible behaviour was different
  - only render home.hbs for page 1
- remember: the default routes.yaml file reflects how Ghost was working without dynamic routing
2018-06-22 20:28:01 +02:00
kirrg001
a1b55509df Dynamic Routing Beta: collection name behaviour
refs #9601

Example:

```
collections:
  /podcast/:
    permalink: /{slug}/
```

- the name of the collection is remembered as `routerName` (in the case above: "podcast")
- the name of the collection is important for two things
  1. context value
  2. template name
- the context value is available for specific theme helpers e.g. is helper, body_class helper
- we auto-lookup the collection name in your theme e.g. podcast.hbs
- this logic does not apply to static routes
- if you define templates on your collection, they are stronger than the collection name
2018-06-21 20:59:43 +02:00
kirrg001
0046dce39f Dynamic Routing Beta: Better template support
refs #9601

- single or multiple template definition
- possible formats:

```
routes:
  /about/: about
```

```
routes:
  /about/:
    template: about
```

```
routes:
  /about/:
    template:
      - about
      - me
```

```
collections
  /posts/:
    template:
      - posts
      - general
```

```
collections
  /posts/:
    template: posts
```
2018-06-21 16:22:45 +02:00
kirrg001
1a79aac673 Fixed collection ownership if a published post status changes to featured
refs #9601

- implementation of resource listener updated
- if you define two collections: `featured:true` (1) and `page:false` (2) you can run into the following bug:
  - you create a published post (owned by (2))
  - you change the status to featured
  - still owned by (2), because the filter still matches (it's still not a static page)
- this adaption fixes the behaviour
- less smart logic, but less error prone
2018-06-17 10:41:05 +02:00
Bill Fienberg
960ee2f20e ES6 migration: server/adapters/scheduling/utils.js (#9689)
refs #9589
2018-06-14 19:15:12 +02:00
Kevin Ansfield
a16077a8e3 Koenig - Do not render image cards with no src on the front-end
refs https://github.com/TryGhost/Ghost/issues/9623
- blank images may be used in the editor as placeholders, don't render them on the front-end
2018-06-14 14:57:09 +01:00
kirrg001
87c01c131b 🐛 Fixed {{#is "index"}}
closes https://github.com/TryGhost/Ghost/issues/9674

- with dynamic routing the first collection get's the "index" context attached
- the index context signalises the main post listening route (first collection)
- this behaviour was present < 1.24 - we have to keep this behaviour
2018-06-14 11:53:13 +02:00
kirrg001
e99fb78b66 Added debug log in error handler
no issue

- very helpful when a test is not green
- `DEBUG=ghost:error-handler`
2018-06-14 00:36:19 +02:00
kirrg001
691daa2a49 ParentRouter: Added wrapper for Express Router
refs #9601

- if you call `express.Router()`, the router's name is always "router"
- that is caused by the closure behaviour in express:
  - https://github.com/expressjs/express/blob/4.16.3/lib/router/index.js#L46
- Ghost creates a couple of express routers for dynamic routing
  - it depends how much you configure in your routes.yaml file
  - but every router is called "router"
  - this is hard to work with
- with this router wrapping logic, we are able to give each router an exact name

If you enable `DEBUG=ghost:services:routing:*`, you have seen this before

> ghost:services:routing:ParentRouter site: mountRouter: router +0ms

With the wrapper logic, you will see:

> ghost:services:routing:ParentRouter site: mountRouter: StaticPagesRouter +0ms

- furthermore, if you have to access the router stack (`app.router.stack`), you can easily identify and find router instances by name
2018-06-13 21:22:10 +02:00
kirrg001
8a10826518 Protected error if routes.yaml file doesn't contain any collections
no issue

- if you define no collections, but a static route, it can happen that the target template to render
  makes use of the {{ghost_head}} helper
- the {{ghost_head}} helper tries to create the primary rss feed url
- at the moment: no collections, no primary rss feed url
- if we offer the option to define custom rss rules, this function might need an extension
2018-06-13 21:01:05 +02:00
Katharina Irrgang
7b0d5d465b 🐛 Fixed preview url and Zapier on subdirectory (#9683)
closes #9675

- with dynamic routing we have introduced a breaking change, which we have overseen
- Ghost does not return absolute urls, that's why the clients need to concat the blog url and the resource url
- with 1.24.0 Ghost returned resource urls including the subdirectory
- this caused trouble for e.g. zapier or the preview feature in the admin client
- revert breaking change and ensure we only expose resource urls without subdirectory
2018-06-12 16:36:58 +01:00
Kevin Ansfield
fe8c07333d Koenig - Embed card renderer
refs https://github.com/TryGhost/Ghost/issues/9623
- add `embed` card renderer
2018-06-12 16:18:01 +01:00
Kevin Ansfield
ca20f3a6b0 Added /oembed API endpoint
refs https://github.com/TryGhost/Ghost/issues/9623
- add `oembed-parser` module for checking provider availability for a url and fetching data from the provider
  - require it in the `overrides.js` file before the general Promise override so that the `promise-wrt` sub-dependency doesn't attempt to extend the Bluebird promise implementation
- add `/oembed` authenticated endpoint
  - takes `?url=` query parameter to match against known providers
  - adds safeguard against oembed-parser's providers list not recognising http+https and www+non-www
  - responds with `ValidationError` if no provider is found
  - responds with oembed response from matched provider's oembed endpoint if match is found
2018-06-12 16:18:01 +01:00
Miguel Piedrafita
d506e86f76 🎨Updated private mode message (#9677)
closes #9676

- changed "blog" to "site"
- use blog title for meta title description
2018-06-11 23:35:23 +02:00
Miguel Piedrafita
56ef66ccfe Fixed typo in: core/server/services/apps/index.js (#9673)
no issue

- typo in comment
2018-06-11 23:19:07 +02:00
kirrg001
f25f7ac54b 🐛 Fixed slug template for tags and authors
no issue

- was introduced with dynamic routing beta: https://github.com/TryGhost/Ghost/releases/tag/1.24.0
- the slug param wasn't forwarded correctly
- you were not able to render a custom tag or author template e.g. `tag-news.hbs`
2018-06-11 22:06:47 +02:00
Hannah Wolfe
0dd619b688
Improved error message for URL Service 503s
- simplify language + consistency with other similar messages
2018-06-11 17:01:07 +01:00
kirrg001
60cdfe29fe 🐛 Fixed "No default engine was specified and no extension was provided"
refs #9681

- we already had a protection against these situations when serving the site (theme)
- it can happen that we have to initialise the express engine in the error handler in case the first request to /ghost produces an error (e.g. 503)
- otherwise the underlying error message is hidden and Ghost doesn't render the error html template correctly
2018-06-11 11:24:07 +02:00
kirrg001
f943acea58 🐛 Fixed unable to publish a post after slack hook import
no issue

- reported here: https://forum.ghost.org/t/issues-with-unconfigured-slack-new-post-fails-with-can-not-find-property-url-of-undefined/1569
- the value of the slack settings was incorrect
- introduced in 1.24.1
- this adds a protection for invalid slack settings values
- this adds the correct code
- furthermore: in the next minor we will add a small migration script to correct any affected incorrect slack settings values
2018-06-11 11:08:08 +02:00
kirrg001
e4807a779c 🐛 Fixed default theme context
closes #9674

- the collection router had a hardcoded default context "home"
  - this is wrong
- the context array get's automatically filled for the collection
  - if you are serving a page e.g. /page/2/ -> it's "paged"
  - if you are serving / -> it's "home"
    - same for {{body_class}}, it outputs "home-template" on "/"
    - this is the same behaviour as in 1.23.x
2018-06-08 15:11:47 +02:00
kirrg001
2d70b8fe20 🐛 Fixed template order not being respected after refresh
no issue

- reverse must happen once in the constructor
- otherwise we reverse the array on each request
  - Ghost would randomly pick the first and then the second template
2018-06-08 15:11:43 +02:00
kirrg001
a66478576f 🎨 Importer no longer imports the slack hook
no issue

- from now on: you have to manually reconfigure your slack hook after importing your data
- we were running into trouble that Ghost had import slack hooks, because it can happen very fast
  that you are importing someone's slack hook
2018-06-07 10:16:54 +02:00
kirrg001
839d82b398 🐛 Fixed post redirect with query params
no issue

- reported here: https://forum.ghost.org/t/best-practice-for-appending-a-query-string-to-a-post/1535
- there was a bug that query params were not respected and this ended in a 301 redirect losing them
2018-06-07 09:52:51 +02:00
kirrg001
3155ea2aa7 🐛 Fixed urls being /404/ after starting the Ghost server
no issue

- there was a timing bug in Ghost
- we do operations in parallel on bootstrap
  - 1) we fetch the resources as early as possible
  - 2) we do all the rest (express bootstrapping, theme loading, router registration) etc.
- it can happen that (2) happens too slow and ends in the situation that the queue, which is responsible
  to handle both parallel actions, does not wait for the routers and closes the event
- this is a short term fix
- i need to reconsider if there is a better long term fix
2018-06-07 09:27:24 +02:00
kirrg001
872f20dac6 Removed unused folder: controllers
refs https://github.com/TryGhost/Ghost/pull/9596

- forgot to remove the folder
- it's not used anymore
- 😇
2018-06-06 06:38:15 +02:00
Katharina Irrgang
b392d1925a
Dynamic Routing Beta (#9596)
refs #9601

### Dynamic Routing

This is the beta version of dynamic routing. 

- we had a initial implementation of "channels" available in the codebase
- we have removed and moved this implementation 
- there is now a centralised place for dynamic routing - server/services/routing
- each routing component is represented by a router type e.g. collections, routes, static pages, taxonomies, rss, preview of posts
- keep as much as possible logic of routing helpers, middlewares and controllers
- ensure test coverage
- connect all the things together
  - yaml file + validation
  - routing + routers
  - url service
  - sitemaps
  - url access
- deeper implementation of yaml validations
  - e.g. hard require slashes
- ensure routing hierarchy/order
  - e.g. you enable the subscriber app
  - you have a custom static page, which lives under the same slug /subscribe
  - static pages are stronger than apps
  - e.g. the first collection owns the post it has filtered
  - a post cannot live in two collections
- ensure apps are still working and hook into the routers layer (or better said: and register in the routing service)
- put as much as possible comments to the code base for better understanding
- ensure a clean debug log
- ensure we can unmount routes
  - e.g. you have a collection permalink of /:slug/ represented by {globals.permalink}
  - and you change the permalink in the admin to dated permalink
  - the express route get's refreshed from /:slug/ to /:year/:month/:day/:slug/
  - unmount without server restart, yey
- ensure we are backwards compatible
  - e.g. render home.hbs for collection index if collection route is /
  - ensure you can access your configured permalink from the settings table with {globals.permalink}

### Render 503 if url service did not finish

- return 503 if the url service has not finished generating the resource urls

### Rewrite sitemaps

- we have rewritten the sitemaps "service", because the url generator does no longer happen on runtime
- we generate all urls on bootstrap
- the sitemaps service will consume created resource and router urls
- these urls will be shown on the xml pages
- we listen on url events
- we listen on router events
- we no longer have to fetch the resources, which is nice
  - the urlservice pre-fetches resources and emits their urls
- the urlservice is the only component who knows which urls are valid
- i made some ES6 adaptions
- we keep the caching logic -> only regenerate xml if there is a change
- updated tests
- checked test coverage (100%)

### Re-work usage of Url utility

- replace all usages of `urlService.utils.urlFor` by `urlService.getByResourceId`
  - only for resources e.g. post, author, tag
- this is important, because with dynamic routing we no longer create static urls based on the settings permalink on runtime
- adapt url utility
- adapt tests
2018-06-05 19:02:20 +02:00
kirrg001
9b704f1691 Fixed single lodash import
no issue

- the dot notation only works if you install a single lodash dependency e.g. `yarn install lodash.get`
- otherwise we have to use `lodash/get`
2018-06-04 22:44:41 +02:00
Tien Do
3afc2654aa 🐛Fixed short urls when private blogging is enabled (#9628)
close #9578

- updated condition to disable RSS for private blog
- use regex
- ensure private rss feed still works
2018-06-04 18:57:18 +02:00
Lundin Matthews
a993994d68 ES6 migration: core/server/helpers/asset.js (#9662)
refs #9628
2018-06-04 18:30:21 +02:00
kirrg001
dd668892d7 Removed more 'use strict' usages
no issue

- after we have dropped node 4, we have removed all 'use strict' usages
- but they came back from older pull requests
2018-06-02 21:38:11 +02:00
kirrg001
af5717762d Fixed incorrect return value for publicAPI from the configuration endpoint
no issue

- discovered while coding
- the value was always false, because we've tried to read the value from the config object
- the value lives in the database and is accessible via the labs service
2018-05-31 15:14:59 +02:00
Katharina Irrgang
b8c142747a
🐛Fixed uppercase tag associations on import (#9655)
no issue

- we sanitise any incoming slug on the model layer e.g uppercase -> lowercase
- and when importing e.g. an uppercase slug, the importer was trying to compare the uppercase slug with the sanitised slug
2018-05-28 23:58:06 +02:00
Ivan Akulov
7f696c0b50 Fixed missing Bluebird require in security/password.js (#9624)
no issue
2018-05-28 23:01:01 +02:00
Kevin Ansfield
6c1e5511fc 🐛 Fixed infinite redirect when subdirectory equals top level domain (#9621)
closes https://github.com/TryGhost/Ghost/issues/9620

- adjust the `deduplicateSubDir` function's regex to only match duplicate subdirectories when the `url` is only a path rather than full url or the duplicate match starts with a `/`
2018-05-28 12:18:34 +02:00
Kevin Ansfield
c50f60f8cd Koenig - Use loose BEM naming for image style classes
refs https://github.com/TryGhost/Ghost/issues/9505
2018-05-22 09:40:16 +01:00
ololoken
86c28e382e 🐛 Fixed /edit shortcut not working in Safari (#9637)
closes #9633 
- use non-hash URL for admin redirects so that redirects are followed correctly by Safari when admin is on different domain
2018-05-21 15:26:32 +01:00
Aileen Nowak
6e117e63fb 🐛 Fixed gscan errors not caught for corrupted zips
closes TryGhost/Support#426
refs TryGhost/gscan#106
needs TryGhost/gscan#107

GScan can return errors, which was not handled in our theme validator and caused Ghost to crash completely. GScan will now return an Ignition error when its not able to read the `.zip` file.

e. g.: `{"errors":[{"message":"Failed to read zip file","context":"tife.zip","errorType":"ValidationError","errorDetails":"invalid relative path: ../tife/"}]}`
2018-05-16 10:20:30 +08:00
Kevin Ansfield
f54db75ed1 Koenig - Code card server-side rendering
refs https://github.com/TryGhost/Ghost/issues/9623
- add support for `code` card that renders into `<pre><code>...</code></pre>`
- render language class if one is provided
2018-05-15 16:27:34 +01:00
Kevin Ansfield
bd75d7551d Koenig - Remove developer experiments flag requirement
refs https://github.com/TryGhost/Ghost/issues/9505
- remove requirement for the `enableDeveloperExperiments` flag to be able to use Koenig
- it's now possible to enable as a standard Labs beta feature
2018-05-15 13:20:40 +01:00
Kevin Ansfield
367c5b9639 Koenig - Fixed empty HTML card rendering undefined
refs https://github.com/TryGhost/Ghost/issues/9623
- add tests for undefined payloads in container cards
- add guard for undefined payload in html card
2018-05-15 10:09:52 +01:00
Kevin Ansfield
d10cb5cb6b Fixed error message for failed xmlrpc request
no issue
- error message was stating the error occurred in the `slack` service rather than the `xmlrpc` service
2018-05-10 10:16:34 +01:00
Kevin Ansfield
e953a1c3a8
Koenig - Versioned renderer (#9606)
refs https://github.com/TryGhost/Ghost/issues/9505
- updates mobiledoc converter's `render` method to accept a `version` argument
    - `1` === Ghost 1.0's markdown-only renderer output
    - `2` === Koenig's full mobiledoc renderer output
- switch between mobiledoc renderer versions in Post model's `onSaving` hook
    - version 1 by default
    - version 2 if Koenig is enabled (currently behind dev experiments config + labs flag)
    - version 2 if the post's mobiledoc is not compatible with the markdown-only renderer
- "version 2" full-Koenig mobiledoc renderer output
    - wraps content in a `.kg-post` div
    - removes wrapper around markdown and html card output
    - adds classes to image card output including selected image size/style
- standardises es6 usage across mobiledoc related files
2018-05-04 14:59:39 +01:00
kirrg001
b0de6eaf87 Replace knex.transaction by models.Base.transaction
no issue

- there was mixed usage of how we instantiate a transaction
- with fb79f24316 (diff-f8d02ad12b13d44b912bbf46cf7193b6) it's becoming important
  to use bookshelf transactions
2018-05-03 11:44:32 +02:00
kirrg001
5f5f0021db 🔥 Drop Node v4 Support
no issue

- support ends today
- see https://github.com/nodejs/Release
- removed `use strict`
2018-05-01 14:06:18 +02:00
kirrg001
ab5199267b Renamed urlService.getUrl to urlService.getUrlByResourceId
no issue

- explicit function naming
- no functional change, only renaming
2018-04-25 19:37:39 +02:00
kirrg001
2a1be3729d Fixed wrong default filter for default collection
refs #9601

- while i was testing different collections and different filters, i somehow thought that the default
  collection does not contain featured posts 😀 🙊
- this is wrong (!!!!)
- the url service is not yet connected
- so: this is not a bug
2018-04-25 16:17:31 +02:00
kirrg001
02abe3862e Use bookshelf-relations for Permission model: roles
refs https://github.com/TryGhost/Ghost/pull/9592

- we add bookshelf-relations step by step if we need it
- with https://github.com/TryGhost/Ghost/pull/9592 we have rewritten the test env to use Bookshelf
  - this is important for our new url service
  - because the service is listening on model updates and updates the urls based on the model events
- so with moving to Bookshelf, we need any easy way to add relations
  - the test env inserts test fixtures
  - it adds permissions and each permission get's roles attached
  - `models.Permission.add({roles: [...]})
2018-04-25 12:27:39 +02:00
kirrg001
27ebc3d1ac Added unit tests for models.Invite.add
no issue

- replaced token creation by `lib.common.security`
- added unit tests for adding invites
- allow a different invite status for internal access
2018-04-25 11:56:45 +02:00
kirrg001
f63de38f36 🐛 Fixed {{author}} for post preview
- we still need to support the single author usage
- author properties weren't accessible
- added `author` include
2018-04-23 09:11:58 +02:00
kirrg001
6ac00255e3 Renamed resources to taxonomies in default routes yaml file
refs https://github.com/TryGhost/Team/issues/65

- this was incorrect
- we don't use the wording `resources` in the routes yaml file
2018-04-21 01:17:52 +02:00
kirrg001
0ac19dcf84 Load yaml settings files synchronously
refs https://github.com/TryGhost/Team/issues/65

- it's easier for the architecture if we read the setting files synchronously,
  because the dynamic routing component is part of the express bootstrap and
  the whole routing bootstrap is synchronously
- for now: we only read one file anyway
- it's for now easier to read the file synchronously, then i don't have to change
  any existing express bootstrap architecture
2018-04-20 15:25:06 +02:00
kirrg001
e43bdad818 Fixed broken i18n keys
refs #9519

- discovered by https://github.com/TryGhost/Ghost/issues/9519#issuecomment-374891164
2018-04-18 15:05:20 +02:00
Vikas Potluri
ce98d272fe Removed unnecessary type attribute in script tags (#9586)
closes #9585

- for reference: https://stackoverflow.com/questions/3485606/will-removing-the-type-from-a-script-tag-break-in-any-browsers
2018-04-18 14:33:31 +02:00
kirrg001
097e1d1fac Url Service: trigger url event with relative/absolute urls
refs https://github.com/TryGhost/Team/issues/65

- this is just the first optimisation regarding relative/absolute urls
- the full strike will happen when i start with the url utility re-write
- for now: there will be only one subscriber of url events -> the sitemaps service
- the sitemaps service outputs absolute urls
  - we don't want to receive an url event and ask the url service again to get an absolute version of the url
2018-04-18 11:33:46 +02:00
Rosco Kalis
2a4d759b78 🎨Removed seconds option from {{reading_time}} (#9573)
closes #9569

- Removed the `<1 min read` time clause, effectively making `1 min read` the minimum reading time
- Removed the `seconds` option for i18n strings, which contained the less than one minute display string
- Kept the other i18n string options the same
- Amended and improved tests for new functionality
2018-04-18 10:55:08 +08:00
kirrg001
2667ad366c Show correct importer context objects
refs #9584

- object by reference 🎡
- we modify the object later on
- this has resulted in a wrong context output in the admin client
  - e.g. we've output an updated user reference
2018-04-18 00:14:46 +02:00
kirrg001
f9ffc395c0 Removed unneeded Promise.resolve
no issue

- was not removed during url service cleanup
- the function runs synchronously
- has no impact on functionality
2018-04-17 15:55:55 +02:00
kirrg001
79c790c891 Fixed url service did not respect subdirectory setup's
refs https://github.com/TryGhost/Team/issues/65

- currently we generate a relative resource url
- if you configure a subdirectory, the urls have to respect that
  - e.g. you configure `localhost:2368/blog`, your url results in e.g. `/blog/my-post/`
- this is not yet a critical bug, because the url service is not connected yet

- @TODO: consider absolute vs. relative urls in the url service
2018-04-17 15:52:57 +02:00
kirrg001
d86441e9b2 Fixed last occurance of `config.get('routeKeywords')
no issue

- 23f59c341c was not rebased against master
2018-04-17 12:07:24 +02:00
Aileen Nowak
23f59c341c Replaced routeKeywords in config with hard coded keywords (#9561)
no issue
- removed the `routeKeywords` property from the config and used hard coded keywords.
- removed `routeKeywords` from public configuration API endpoint, as it's no longer used in the Admin.
2018-04-17 10:36:05 +01:00
Katharina Irrgang
6a4af1f465
Rewrite url service (#9550)
refs https://github.com/TryGhost/Team/issues/65

We are currently work on dynamic routing (aka channels).
An important piece of this feature is the url service, which always knows the url of a resource at any time.
Resources can belong to collections or taxonomies, which can be defined in a [routing yaml file](https://github.com/TryGhost/Ghost/issues/9528). We are currently shipping portions, which will at end form the full dynamic routing feature.

### Key Notes

- each routing type (collections, taxonomies, static pages) is registered in order - depending on the yaml routes file configuration
- static pages are an internal concept - they sit at the end of the subscriber queue
- we make use of a temporary [`Channels2`](https://github.com/TryGhost/Ghost/pull/9550/files#diff-9e7251409844521470c9829013cd1563) file, which simulates the current static routing in Ghost (this file will be modified, removed or whatever - this is one of the next steps)
- two way binding: you can ask for a resource url based on the resource id, you can ask for the resource based on the url
- in theory it's possible that multiple resources generate the same url: we don't handle this with collision (because this is error prone), we handle this with the order of serving content. if you ask the service for a resource, which lives behind e.g. /test/, you will get the resource which is served
- loose error handling -> log errors and handle instead of throw error and do nothing (we log the errors with a specific code, so we can react in case there is a bug)
- the url services fetches all resources on bootstrap. we only fetch and keep a reduced set of attributes (basically the main body of a resource)
- the bootstrap time will decrease a very little (depending on the amount of resources you have in your database)
- we still offer the option to disable url preloading (in your config `disableUrlPreload: true`) - this option will be removed as soon as the url service is connected. You can disable the service in case you encounter a problem
- **the url service is not yet connected, we will connect the service step by step. The first version should be released to pre-catch bugs. The next version will add 503 handling if the url service is not ready and it will consume urls for resources.**


----

- the url service generates urls based on resources (posts, pages, users, tags)
- the url service keeps track of resource changes
- the url service keeps track of resource removal/insert
- the architecture:
  - each routing type is represented by a url generator
    - a routing type is a collection, a taxonomiy or static pages
  - a queue which ensures that urls are unique and can be owned by one url generator
    - the hierarchy of registration defines that
  - we query knex, because bookshelf is too slow
- removed old url service files + logic
- added temp channels alternative (Channels2) -> this file will look different soon, it's for now the temporary connector to the url service. Also the name of the file is not optimal, but that is not really important right now.
2018-04-17 11:29:04 +02:00
kirrg001
fabce59e0b Trigger database ready event
no issue

- the database is ready when:
  1. knex-migrator health is green (or `knexMigrator.isDatabaseOK`)
  2. the settings where populated
2018-04-15 23:53:18 +02:00
kirrg001
b2a8165d01 Consistent event names
no issue

- rename event to `server.stop`
- rename event to `server.start`
- we are using the dot notation
2018-04-15 23:52:42 +02:00
Aileen Nowak
63642fd8ad YAML settings loader and parser
closes #9528

These code changes introduce a YAML parser which will load and parse YAML files from the `/content/settings` directory. There are three major parts involved:

1. `ensure-settings.js`: this fn takes care that on bootstrap, the supported files are present in the `/content/settings` directory. If the files are not present, they get copied back from our default files. The default files to copy from are located in `core/server/services/settings`.

2. `loader.js`: the settings loader reads the requested `yaml` file from the disk and passes it to the yaml parser, which returns a `json` object of the file. The settings loader throws an error, if the file is not accessible, e. g. because of permission errors.

3. `yaml-parser`: gets passed a `yaml` file and returns a `json` object. If the file is not parseable, it returns a clear error that contains the information, what and where the parsing error occurred (e. g. line number and reason).

- added a `get()` fn to settings services, that returns the settings object that's asked for. e. g. `settings.get('routes').then(()...` will return the `routes` settings.
- added a `getAll()` fn to settings services, that returns all available settings in an object. The object looks like: `{routes: {routes: {}, collections: {}, resources: {}}, globals: {value: {}}`, assuming that we have to supported settings `routes` and `globals`.

Further additions:
- config `contentPath` for `settings`
- config overrides for default `yaml` files location in `/core/server/services/settings`

**Important**: These code changes are in preparation for Dynamic Routing and not yet used. The process of copying the supported `yaml` files (in this first step, the `routes.yaml` file) is not yet activated.
2018-04-15 19:40:22 +02:00
Katharina Irrgang
7273786459
Fetch relations by default when insert/updating posts (#9568)
no issue

- required for model events
- otherwise you won't receive a full data set
  - in worst case you have to re-fetch the post
- required for the url service
  - the url service always needs relations (authors,tags) to be able to generate the url properly

@IMPORTANT
- no API change, we still return what you are asking for
  - we first edit/add the resource
  - then we fetch the data with the API options
  - @TODO: this can be optimised and will improve performance
    	   picking/selecting it from the insert/update response
- this is an internal change
2018-04-15 12:12:20 +02:00
kirrg001
5d21ce0644 🐛 Fixed post preview
closes #9567

- we have to ensure that `post.authors` is available
- changed `include` option
  - `include=author` is deprecated
2018-04-15 10:08:06 +02:00
CriticalRespawn
6b9f9a0ece 🐛Fixed author page has only shown primary author posts
closes #9545

- posts only showed on an author page when the author was primary
2018-04-10 22:56:25 +02:00
Kevin Ansfield
3a27e557ed Protect generated post.html and post.plaintext fields (#9559)
closes https://github.com/TryGhost/Ghost/issues/9512

- loop through list of generated fields in `Post.onSaving` and reset their values if a new value was passed in via attributes
2018-04-10 22:45:31 +02:00
kirrg001
d209a4d013 🐛 Fixed importer bug: can't resolve authors relation
closes #9547

- you setup a blog with the following owner:
  - email: test@ghost.org
  - name: test
  - slug: test
- now you import a JSON db file, which holds the exact same owner
  - this owner won't be imported, because it's a duplicate
  - but the slug is different (!)
- the importer tries to find a matching existing user, but won't find anything
- the importer then send an empty authors array `post.authors=[]` into the model layer
- this is not allowed -> this would mean, you are actively trying to unset all authors
2018-04-10 01:10:06 +02:00
kirrg001
aecca28257 Optimised emitChange for destroyed resources
no issue

- see comment in code base
2018-04-06 19:10:59 +02:00
Katharina Irrgang
fb79f24316
Fixed model events and transactions (#9524)
no issue

- if multiple queries run in a transaction, the model events are triggered before the txn finished
- if the txn rolls back, the events are anyway emitted
- the events are triggered too early
- solution:
  - `emitChange` needs to detect that a transaction is happening
  - it listens on a txn event to determine if events should be triggered
2018-04-06 18:19:45 +02:00
kirrg001
25cd7c7756 Simplify destroy post API endpoint implementation
no issue

- no need to fetch the post before
- the model implementation does that already
2018-04-06 15:49:25 +02:00
kirrg001
c8f2dd11ba Fixed post.unpublished when deleting all content
no issue

- if you delete all content, we expect two events
  - `post.deleted` and `post.unpublished`
- `post.unpublished` was never triggered, because the api implementation made use of `collection.invoke(`destroy`)`
- what happened?
  - you fetch all posts (columns:id)
  - you destroy the post (only id column is available)
  - the model events are triggered
  - but you have no access to a default set of data
  - the result is that the event handler can't even tell if this is a post or a page
- added a proper test to ensure which events are triggered
2018-04-06 15:49:25 +02:00
kirrg001
0ae6cbe34d Fixed transactions for Tag.destroy
no issue

- if you pass a transaction to `Tag.destroy`, it would freeze
- because `detach(null, options)` was missing
- added a new test
2018-04-06 15:49:25 +02:00
kirrg001
89e4201b67 Clarify the behaviour of defaultColumnsToFetch in the post model
no issue

- add a big comment
- describe:
  - how this works
  - why this is in place
  - what does currently not work
  - and why it will work with channels
- @TODO:
  - figure out how to disallow:
  - `models.Post.findAll({columns: id})`
  - `post.save(data)`
  - this will trigger bookshelf events and model events
  - url generation currently needs a set of attributes (e.g. slug, published_at)
    - will be auto-fixed with channels, because you can call `urlService.getUrl(post.id)`
  - but what doesn't get solved is our model events
    - e.g. `emitChange` needs `post.get('page')` to determine if it's a page
2018-04-06 13:32:10 +02:00
kirrg001
5928a5b240 Extended check for updated_at on model update
no issue

- ensure the schema type has a key `updated_at`, otherwise ignore
2018-04-05 18:51:58 +02:00
kirrg001
da80019aca Removed taking care of bookshelf's changed model keys
no issue

- this is no longer needed for now
- it was anyway a little bit ugly to modify bookshelf's `changed` object
- if we want to change something about figuring out if a model has changed (including relations)
  -> we probably need to override bookshelf
2018-04-05 18:51:58 +02:00
kirrg001
853b518a51 Sanitize incoming model relation data
refs #9548

- we always receive date strings from the client in ISO format
- we ensure that we transform these strings into JS dates for comparison
- when the client sends relations, we need to ensure that relations are checked as well
- will only work for the post model for now, because this is the only model which uses `bookshelf-relations`
- added unit tests
- removed some model tests, which do the same
2018-04-05 18:51:58 +02:00
kirrg001
5c5ecfd61d A bit of ES6 for models/base/index.js
no issue
2018-04-05 18:51:58 +02:00
kirrg001
bda76acba6 Extended the API object validation
refs #9548

- do not forward `tag.parent` to the model layer
  - the model layer should only know `tag.parent_id`
  - and the API should only expose `tag.parent` (this is an API feature)
  - currently Ghost has a mixture of using `toJSON` and the API validation layer for this
  - we just continue with this for now (no time to fix this)
- disallow sending nested-nested relations
  - unsupported
  - see comment for more information
  - this can cause problems with calling `hasChanged` on relations
- add unit tests
2018-04-05 18:51:58 +02:00
kirrg001
5dc2dddfc2 Fixed migration script 1.22 for invalid authors
no issue

- the previous commit will insert two post author relations if the author id of a post is invalid
- if a blog has an invalid author_id (which should be an edge case), we update the author id to the owner id
  - `posts_authors` are auto inserted in this case
2018-04-02 12:27:06 +02:00
Katharina Irrgang
7bbde460af
Speed up 1.22 migration script (#9541)
no issue

- insert `posts_authors` relation via knex
- massive speed improvement

e.g. 1500 posts

- before: ~1min
- after: ~10sec
2018-04-02 12:00:00 +02:00
Katharina Irrgang
40d0a745df Multiple authors (#9426)
no issue

This PR adds the server side logic for multiple authors. This adds the ability to add multiple authors per post. We keep and support single authors (maybe till the next major - this is still in discussion)

### key notes

- `authors` are not fetched by default, only if we need them
- the migration script iterates over all posts and figures out if an author_id is valid and exists (in master we can add invalid author_id's) and then adds the relation (falls back to owner if invalid)
- ~~i had to push a fork of bookshelf to npm because we currently can't bump bookshelf + the two bugs i discovered are anyway not yet merged (https://github.com/kirrg001/bookshelf/commits/master)~~ replaced by new bookshelf release
- the implementation of single & multiple authors lives in a single place (introduction of a new concept: model relation)
- if you destroy an author, we keep the behaviour for now -> remove all posts where the primary author id matches. furthermore, remove all relations in posts_authors (e.g. secondary author)
- we make re-use of the `excludeAttrs` concept which was invented in the contributors PR (to protect editing authors as author/contributor role) -> i've added a clear todo that we need a logic to make a diff of the target relation -> both for tags and authors
- `authors` helper available (same as `tags` helper)
- `primary_author` computed field available
- `primary_author` functionality available (same as `primary_tag` e.g. permalinks, prev/next helper etc)
2018-03-27 15:16:15 +01:00
Katharina Irrgang
7c6f690eb5 🐛 Fixed updated_at not being updated (#9532)
closes #9520

- it contains a dependency bump of the latest Bookshelf release
- Bookshelf introduced a bug in the last release
  - see https://github.com/bookshelf/bookshelf/pull/1583
  - see https://github.com/bookshelf/bookshelf/pull/1798
- this has caused trouble in Ghost
  - the `updated_at` attribute was not automatically set anymore

---

The bookshelf added one breaking change: it's allow to pass custom `updated_at` and `created_at`.
We already have a protection for not being able to override the `created_at` date on update.
We had to add another protection to now allow to only change the `updated_at` property.
You can only change `updated_at` if you actually change something else e.g. the title of a post.

To be able to implement this check i discovered that Bookshelfs `model.changed` object has a tricky behaviour.
It remembers **all** attributes, which where changed, doesn't matter if they are valid or invalid model properties.
We had to add a line of code to avoid remembering none valid model attributes in this object.

e.g. you change `tag.parent` (no valid model attribute). The valid property is `tag.parent_id`.
     If you pass `tag.parent` but the value has **not** changed (`tag.parent` === `tag.parent_id`), it will output you `tag.changed.parent`. But this is wrong.
     Bookshelf detects `changed` attributes too early. Or if you think the other way around, Ghost detects valid attributes too late.
     But the current earliest possible stage is the `onSaving` event, there is no earlier way to pick valid attributes (except of `.forge`, but we don't use this fn ATM).
     Later: the API should transform `tag.parent` into `tag.parent_id`, but we are not using it ATM, so no need to pre-optimise.
     The API already transforms `post.author` into `post.author_id`.
2018-03-26 14:12:02 +01:00
CriticalRespawn
60386dbba5 🐛Fixed misspelled schema.org type for WebSite (#9526)
closes #9525

- updated the schema type to 'WebSite' as it is the correct spelling according to schema.org. See [here](http://schema.org/WebSite)
2018-03-23 10:50:28 +07:00
Rosco Kalis
4013023d60 🐛Added more language support to {{reading_time}} helper (#9509)
closes #9507

- Changed the utils.wordCount implementation to the one used by simpleMDE
- Added extra À-ÿ to the regex to support diacritics characters
- Added corresponding text with Chinese text mentioned in the issue
2018-03-22 10:27:02 +07:00
kirrg001
f0c8e3c95a Fixed wrong i18n key
refs #9519

- `errors.models.posts.postNotFound` -> wrong
- `errors.models.post.postNotFound`  -> correct
- the i18n lib just logs the error and falls back to a valid error key
- wrong i18n keys will never break Ghost
2018-03-21 08:41:05 +01:00
Katharina Irrgang
95423ea8fa
Bump dependencies (#9513)
no issue

- knex@0.14.4
- bookshelf@0.13.0
- knex-migrator@3.1.4
- brute-knex@4feff38ad2
- bookshelf-relations@0.2.0

### Fixes for Bookshelf 0.13

- they introduced some breaking changes
- https://github.com/bookshelf/bookshelf/blob/master/CHANGELOG.md#breaking-changes
- adapt event handling in Ghost and in bookshelf-relations
2018-03-19 16:27:06 +01:00
Rosco Kalis
3d8bf02a8d Redirected /amp links to original post when AMP is disabled (#9496)
closes #9495

- Added a clause for amp being disabled
- In this clause, we strip the final 'amp/' part of the url, and redirect
- Changed corresponding test in frontend_spec.js
- Used `urlService.utils.redirect301()` instead of `res.redirect()`
2018-03-19 16:11:48 +07:00
Mante Bridts
7ed822cc0c 🐛Fixed i18n for the {{meta_title}} helper (#9468)
closes #9466

- make 'page' in the meta title translatable through subexpression in the meta title helper
- e.g. `{{meta_title page=(t....)}}`
2018-03-19 09:48:07 +01:00
Vikas Potluri
63aeebb144 🐛 Fixed escaping < in reading time helper (#9508)
no issue

Using the < character raw isn't w3 complaint
2018-03-19 09:47:58 +07:00
CriticalRespawn
735d9775ee 🐛Fixed data-* attributes from being stripped in AMP HTML (#9501)
closes #9500

- Added `data-*` to `allowedAMPAttributes`, so it will not get stripped out.
2018-03-16 09:45:07 +07:00
CriticalRespawn
25b94bba75 🐛Fixed <br> tag from duplicating in AMP transform (#9502)
closes #9499 

- added `br` to self closing tags option for `sanitize-html` when cleaning the ampified HTML
2018-03-16 09:39:29 +07:00
Kevin Ansfield
df1188d25a
Fix Node.js 4.x compatibility (#9503)
no issue
- fixes compatibility issue introduced in 7548ace32d
2018-03-15 09:50:25 +00:00
Kevin Ansfield
7548ace32d Koenig - Output captions for image and embed cards
refs https://github.com/TryGhost/Ghost/issues/9311
- very basic implementation, still needs proper classes and default stylesheet implementation
- change image card output to a `<figure>` with optional `<figcaption>`
- add optional `<p>` caption output to the html card
2018-03-14 18:21:30 +00:00
Rosco Kalis
301e1b2419 🎨Improved image counting for the {{reading_time}} helper (#9366)
refs #9200

- We have not yet counted the images within your html, this commit counts images based on the this algorithm: https://blog.medium.com/read-time-and-you-bc2048ab620c
- Added imageCount utility, which counts images using an img-tag regex, amended from the general tag-regex found in wordCount
- Added this imageCount to the {{reading_time}} helper, adding 12 seconds to the reading time for every image
- The feature image is still counted as before
- The first image adds 12 seconds, the second 11, the third 10, and so on
- Images from the tenth onwards add 3 seconds to the reading time
2018-03-05 09:30:15 +01:00
Aileen Nowak
1da2eec915 🐛Fixed image properties to be reset to null after removal (#9432)
closes #9085

Fixes an issue, where the client sets image properties to `""` after deleting the image. This causes problems with the query filter (see https://github.com/TryGhost/GQL/issues/24), as they have to be `null`.

Added a check in the model layer saving method to set value  to `null`, when the property is empty.

Affected models and properties:
- `posts`:
	- `feature_image`
	- `og_image`
	- `twitter_image`
- `users`:
	- `profile_image`
	- `cover_image`
- `tags`:
	- `feature_image`
2018-03-05 09:10:27 +01:00
kirrg001
e01b61dcf4 Proper error handling for permissible implementations
no issue

- currently if you would like to edit a resource (e.g. post) and you pass an invalid model id, the following happens
  - permission check calls `Post.permissible`
  - the Post could not find the post, but ignored it and returned `userPermissions:true`
  - then the model layer is queried again and figured out that the post does not exist
- A: there is no need to query the model twice
- B: we needed proper error handling for post and role model
2018-02-21 16:59:48 +01:00
kirrg001
68d8154d4f Imported nested tags by foreign key
no issue

- replace logic for preparing nested tags
- if you have nested tags in your file, we won't update or update the target tag
- we simply would like to add the relationship to the database
- use same approach as base class
  - add `posts_tags` to target post model
  - update identifiers
  - insert relation by foreign key `tag_id`
- bump bookshelf-relations to 0.1.10
2018-02-20 09:56:45 +01:00
kirrg001
5a4dd6b792 Increased speed of importer
no issue

- change behaviour from updating user references after the actual import to update the user reference before the actual import
  - updating user references after the import is way less case intense
  - that was the initial decision for updating the references afterwards
  - but that does not play well with adding nested relations by identifier
- the refactoring is required for multiple authors
  - if we e.g. store invalid author id's, we won't be able to add a belongs-to-many relation for multiple authors
  - bookshelf-relations is generic and always tries to find a matching target before attching a model
  - invalid user references won't work anymore
- this change has a very good side affect
  - 17mb takes on master ~1,5seconds
    - on this branch it takes ~45seconds
  - also the memory usage is way lower and stabler
  - 40mb takes 1,6s (times out on master)
2018-02-20 09:56:45 +01:00
kirrg001
12724df8e4 Define belongsToMany foreign keys for tags in the model layer
no issue

- otherwise we will have trouble in the future fetching relations by foreign key
  - e.g. `tag_id: {id}`
  - this won't work if we don't explicitly define the name of the keys
  - bookshelf can't fulfil the request
- this does not change any behaviour, it just makes use of the ability to define the names of your foreign keys
2018-02-20 08:49:00 +01:00
Katharina Irrgang
0aff9f33d9
Improved validation layer (#9427)
refs https://github.com/TryGhost/Ghost/issues/3658

- the `validateSchema` helper was a bit broken
  - if you add a user without email, you will receive a database error
  - but the validation error should catch that email is passed with null
- it was broken, because:
  - A: it called `toJSON` -> this can remove properties from the output (e.g. password)
  - B: we only validated fields, which were part of the JSON data (model.hasOwnProperty)
- we now differentiate between schema validation for update and insert
- fixed one broken import test
  - if you import a post without a status, it should not error
  - it falls back to the default value
- removed user model `onValidate`
  - the user model added a custom implementation of `onValidate`, because of a bug which we experienced (see https://github.com/TryGhost/Ghost/issues/3638)
  - with the refactoring this is no longer required - we only validate fields which have changed when updating resources
  - also, removed extra safe catch when logging in (no longer needed - unit tested)
- add lot's of unit tests to proof the code change
- always call the base class, except you have a good reason
2018-02-16 00:49:15 +01:00
kirrg001
355ef54702 Removed isNew usages in model layer
no issue

- `isNew` does not work in Ghost, because Ghost does not use auto increment id's
- see https://github.com/bookshelf/bookshelf/issues/1265
- see https://github.com/bookshelf/bookshelf/blob/0.10.3/src/base/model.js#L211
- we only had one occurance, which was anyway redundant
  - if you add a user, `hasChanged('password') is true
  - if you edit a user and the password has changed, `hasChanged('password')` is true as well

NOTE #1:

1. We can't override `isNew` and throw an error, because bookshelf makes use of `isNew` as well, but it's a fallback if `options.method` is not set.
2. It's hard to re-implement `isNew` based on `options.method`, because then we need to ensure that this value is always set (requires a couple of changes)

NOTE #2:
If we need to differentiate if a model is new or edited, we should manually check for `options.method === insert`.

NOTE #3:
The unit tests are much faster compared to the model integration tests.
I did a comparision with the same test assertion:
  - unit test takes 70ms
  - integration test takes 190ms
2018-02-15 22:11:49 +01:00
kirrg001
2b76d7a492 Added lib.security.password lib
no issue

- move password hashing and password comparison to lib/security/password
- added two unit test
- FYI: password hashing takes ~100ms
  - we could probably mock password hashing in certain cases when unit testing
2018-02-15 21:13:04 +01:00
Katharina Irrgang
c6a95c6478
Sorted out the mixed usages of include and withRelated (#9425)
no issue

- this commit cleans up the usages of `include` and `withRelated`.

### API layer (`include`)
- as request parameter e.g. `?include=roles,tags`
- as theme API parameter e.g. `{{get .... include="author"}}`
- as internal API access e.g. `api.posts.browse({include: 'author,tags'})`
- the `include` notation is more readable than `withRelated`
- and it allows us to use a different easier format (comma separated list)
- the API utility transforms these more readable properties into model style (or into Ghost style)

### Model access (`withRelated`)
- e.g. `models.Post.findPage({withRelated: ['tags']})`
- driven by bookshelf

---

Commits explained.

* Reorder the usage of `convertOptions`

- 1. validation
- 2. options convertion
- 3. permissions
- the reason is simple, the permission layer access the model layer
  - we have to prepare the options before talking to the model layer
- added `convertOptions` where it was missed (not required, but for consistency reasons)

* Use `withRelated` when accessing the model layer and use `include` when accessing the API layer

* Change `convertOptions` API utiliy

- API Usage
  - ghost.api(..., {include: 'tags,authors'})
  - `include` should only be used when calling the API (either via request or via manual usage)
  - `include` is only for readability and easier format
- Ghost (Model Layer Usage)
  - models.Post.findOne(..., {withRelated: ['tags', 'authors']})
  - should only use `withRelated`
  - model layer cannot read 'tags,authors`
  - model layer has no idea what `include` means, speaks a different language
  - `withRelated` is bookshelf
  - internal usage

* include-count plugin: use `withRelated` instead of `include`

- imagine you outsource this plugin to git and publish it to npm
- `include` is an unknown option in bookshelf

* Updated `permittedOptions` in base model

- `include` is no longer a known option

* Remove all occurances of `include` in the model layer

* Extend `filterOptions` base function

- this function should be called as first action
- we clone the unfiltered options
- check if you are using `include` (this is a protection which could help us in the beginning)
- check for permitted and (later on default `withRelated`) options
- the usage is coming in next commit

* Ensure we call `filterOptions` as first action

- use `ghostBookshelf.Model.filterOptions` as first action
- consistent naming pattern for incoming options: `unfilteredOptions`
- re-added allowed options for `toJSON`
- one unsolved architecture problem:
  - if you override a function e.g. `edit`
  - then you should call `filterOptions` as first action
  - the base implementation of e.g. `edit` will call it again
  - future improvement

* Removed `findOne` from Invite model

- no longer needed, the base implementation is the same
2018-02-15 10:53:53 +01:00
Hannah Wolfe
fe0197b226 🐛Fixed {{get}} helper's date comparison (#9454)
no issue

- Date comparisons are possible via API, but there's no way to inject a valid date into the get helper
- JavaScript's Date.toString() function outputs dates in a useless format
- Swap to using Date.toISOString() and now the format can be understood anywhere!
- {{#get "posts" filter="published_at:<='{{published_at}}'"}}{{/get}} works now as expected
2018-02-14 18:33:07 +01:00
Katharina Irrgang
9ede5905f6
Reduce toJSON implementation: use the power of bookshelf (#9423)
refs #6103

- simplify `toJSON`
- `baseKey` was not used - have not find a single use case
- all the functionality of our `toJSON` is offered in bookshelf
- `omitPivot` does remove pivot elements from the JSON obj (bookshelf feature)
- `shallow` allows you to not return relations
- make use of `serialize`, see http://bookshelfjs.org/docs/src_base_model.js.html#line260
- fetching nested relations e.g. `users.roles` still works (unrelated to this refactoring)

> pick('shallow', 'baseKey', 'include', 'context')

We will re-add options validation in https://github.com/TryGhost/Ghost/pull/9427, but then with the official way: use `filterOptions`.

---

We return all fetched relations (pre-defined with `withRelated`) by default.
You can disable it with `shallow:true`.
2018-02-14 17:32:11 +01:00
Katharina Irrgang
58157b1411
🐛Fixed asset redirects (#9455)
closes #9445

- redirects all asset requests if https is configured (theme, core, images)
- re-use and extend our url-redirect middleware
- add proper integration tests for our express site app (no db interaction, component testing required for such important use cases)
- i added some more general tests
- should avoid mixed content warnings in the browser
2018-02-14 17:21:31 +01:00
kirrg001
ed4fde4f00 🐛 Fixed migrating from < 1.13 to 1.21
no issue

- discovered while testing
- the fixture utility needed a protection against non existent roles in the database
  - it tries to fetch the contributor role from the database, which does not exist yet
2018-02-07 12:31:21 +01:00
Austin Burdine
777247cbc7 Contributor Role (#9315)
closes #9314 

* added fixtures for contributor role
* update post api tests to prevent contributor publishing post
* update permissible function in role/user model
* fix additional author code in invites
* update contributor role migration for knex-migrator v3
* fix paths in contrib migration
* ensure contributors can't edit or delete published posts, fix routing tests [ci skip]
* update db fixtures hash
* strip tags from post if contributor
* cleanup post permissible function
* excludedAttrs to ignore tag updates for now (might be removed later)
* ensure contributors can't edit another's post
* migration script for 1.21
2018-02-07 10:46:22 +01:00
Katharina Irrgang
a274d61a8c Removed html usage in error messages (#9444)
no issue

- all of the error message keys were unused
- the only html anchor i found was for mail, but this doesn't change anything, because the admin does only show the message and not the context at the moment
2018-02-07 09:35:48 +01:00
Kevin Ansfield
fb973dbbf2 Fixed missing export of card-markdown card and broken tests
no issue
- fixes rendering bug introduced in 0833b28557
- updates test generators/fixtures to use new card names
2018-02-01 16:26:56 +01:00
Kevin Ansfield
05bcf7ee6a Fixed missing export of card-markdown card
no issue
- fixes the bug introduced in 0833b28557
2018-02-01 15:50:43 +01:00
Kevin Ansfield
0833b28557 Koenig - Rename server-side cards
refs https://github.com/TryGhost/Ghost/issues/9311
- match card names to the new generic Koenig card names introduced in 95a068615d
2018-02-01 12:40:49 +01:00
Chuck Lam
ffc6088c7a Fixed comment in facebook_url helper (#9430)
no issue
2018-01-28 18:25:06 +01:00
kirrg001
39ee95cc07 Make use of ES6 arrow functions in our data importer
no issue

- reduces the usage of `self`
2018-01-28 15:48:24 +01:00
kirrg001
2a10c83d92 Improved memory usage in importer
no issue

- returning and remembering the data, which was imported, is...
  - not required when using the API
  - not required when importing via script
  - required for tests
  - added an option to have control over it
- make more usage of local variables
  - the GC cannot tidy up variables, which are defined outside of a loop, but used in the loop
- try to keep less memory in process
  - reduce the number of properties we have to remember
2018-01-28 14:26:38 +01:00
kirrg001
5f9c3b92bd Improved Base importer constructor readability
no issue

- better differentiation between options and data
- better readability how to access required data from file
2018-01-28 13:35:21 +01:00
kirrg001
82bb3aaea1 Do not import unknown author id, fallback to owner id
no issue

- if you import a JSON file with a post, which has an unknown author,
  the target user was removed from the blog
- Ghost can handle this case and still succeeds with import
  - but we have stored an `author_id` in the database, which does not map to any user and won't map in the future
- this can trouble if we add support for multiple authors
  - currently, we only return the `author_id` to the client and the client can map with `author_id` with users fetched by the API
    - if it does not find a user, it just falls back to a different user
  - but multiple authors have to be included explicit (`include=authors`) and we will return a mapped (author_id => user) result
  - it won't be able to find the user, because we lookup the database
  - this would result in an error
- there is in general no reason to import (or store) an unknown/invalid `author_id` into the database
- on import, we show you a warning and you can choose a different author if you want
- solution: fallback to owner user and extend warning
  - it's not a behaviour change, you still can import unknown author id's and the import won't fail
  - but we ensure valid author id's
- updated test
- further more: returning `author={}` when requesting `include=author` could trouble with ember currently
  - it expects the author to be returned
2018-01-27 12:54:36 +01:00
kirrg001
c6f30a46d2 Avoid knex warning when destroying a user
no issue

- the warning is "Transaction was already complete"
- destroying a user happens in a transaction, but the event is not asynchronous
  - so we have to ensure that we don't operate on a finished transaction
2018-01-27 12:31:51 +01:00
kirrg001
b4f355f713 Removed the usages of this.forge(null, {context: options.context})
no issue

- refs fe461da110
- the access plugin was removed
- no need to pass `context` as parameter for `.forge`
2018-01-26 00:35:39 +01:00
kirrg001
fe461da110 Deleted bookshelf access plugin
refs #9127

- permission checks can happen everywhere in the code base
  - we would like to create a context class
- global access to `options.context.is(...)`
- please read more about the access plugin in #9127 section "Model layer and the access plugin".
- removed the plugin and use direct context checks
2018-01-25 17:54:28 +01:00
Kevin Ansfield
69d5fac61e
Resurrect the old alpha Koenig editor (#9277)
requires https://github.com/TryGhost/Ghost-Admin/pull/916
- add "enableDeveloperExperiments" config flag
- allow any HTML payload through in the HTML mobiledoc card
  - same approach as taken in the markdown card, running the markup through SimpleDOM isn't necessary and is prone to breaking because of it's limited parsing and error handling abilities

To use Koenig modify your `config.development.json` file and add the following flag to the top-level object:

```
"enableDeveloperExperiments": true
```

If you restart the dev server you will then see a new section on the Labs screen with a Koenig Editor checkbox to enable/disable the editor.

⚠️ The editor is in a _very_ broken state, it's there for developer testing and on-going development. _Do not_ try to use this on any production data!
2018-01-18 15:43:22 +00:00
kirrg001
357ea3dffd 🐛 Fixed showing old release notifications in the about page
no issue

- reported in slack (https://ghost.slack.com/files/U8QV8DXQB/F8TSBQ532/image.png)
- do not expose old release notification
  - e.g. you are on 1.20.0
  - you receive a notification for 1.20.1 to update
  - you update to 1.20.1
- ensure we protect exposing the release notification (compare against blog version)
- protect against wrong formats
- @TODO: the notifications could store a `version` property
  - by that we could use `notification.version` and don't have to match the version in the message
2018-01-18 12:19:55 +01:00
Peter Garland
35fbba3bcb Fixed bad references to common.i18n (#9402)
no issue

- happened during refactoring (search+replace)
2018-01-17 17:28:42 +01:00
Katharina Irrgang
c062114e47
Increased cache-control for ghost-sdk.min.js and ghost.min.css (#9399)
no issue

- we increase the client in-memory expiry for production built assets
- as soon as there will be another release, a new asset hash is generated and the client cache is invalidated automatically (doesn't matter how long we store the file in the client)
- the next step is to get rid of having asset hashs part as query params
  - ghost-sdk.min.js?v=1234 is becoming e.g. ghost-sdk-1234.min.js
  - reasons:
    - A: performance tools complain about it
    - B: we no longer invalidate the asset hashs for built assets if the theme changes
2018-01-16 12:22:29 +01:00
Katharina Irrgang
e480c7c50d 🐛 Reload translations if active theme get's overridden (#9392)
no issue

- discovered while testing
  - activate theme
  - download theme
  - modify theme
  - upload theme
  - override? yes
  - translation files are not reloaded, because the database is up-to-date
- remove un-used events in theme api layer
- trigger event from theme service
2018-01-12 09:19:28 +00:00
Hugo Marisco
ccb5fd837e Fixed wrong status code for incorrect token requests (#9374)
closes #9346

- server returned 500, happened when you send an empty username/password
- return 400 instead
- error message is/was correct
2018-01-11 16:17:03 +01:00
David Wolfe
b69b9780a9 Backup endpoint improvements (#9365)
closes #9297

- backup endpoint returns JSON
- allows setting of export filename
- DRY up code
- the endpoint is not documented, no breaking change
2018-01-11 16:03:21 +01:00
kirrg001
ccb3b3de38 Fixed 1.20 migration script
no issue

- `models.Settings.destroy` only accepts one argument
2018-01-09 21:38:13 +01:00
Katharina Irrgang
5b77f052d9
Update Notification improvements (#9123)
closes #5071

- Remove hardcoded notification in admin controller
  - NOTE: update check notifications are no longer blocking the admin rendering
  - this is one of the most import changes
  - we remove the hardcoded release message
  - we also remove adding a notification manually in here, because this will work differently from now on
    -> you receive a notification (release or custom) in the update check module and this module adds the notification as is to our database

- Change default core settings keys
  - remove displayUpdateNotification
    -> this was used to store the release version number send from the UCS
    -> based on this value, Ghost creates a notification container with self defined values
    -> not needed anymore

- rename seenNotifications to notifications
  -> the new notifications key will hold both
     1. the notification from the USC
     2. the information about if a notification was seen or not
  - this key hold only one release notification
  - and n custom notifications

- Update Check Module: Request to the USC depends on the privacy configuration
  - useUpdateCheck: true -> does a checkin in the USC (exposes data)
  - useUpdateCheck: false -> does only a GET query to the USC (does not expose any data)
  - make the request handling dynamic, so it depends on the flag
  - add an extra logic to be able to define a custom USC endpoint (helpful for testing)
  - add an extra logic to be able to force the request to the service (helpful for testing)

- Update check module: re-work condition when a check should happen
  - only if the env is not correct
  - remove deprecated config.updateCheck
  - remove isPrivacyDisabled check (handled differently now, explained in last commit)

- Update check module: remove `showUpdateNotification` and readability
  - showUpdateNotification was used in the admin controller to fetch the latest release version number from the db
  - no need to check against semver in general, the USC takes care of that (no need to double check)
  - improve readability of `nextUpdateCheck` condition

- Update check module: refactor `updateCheckResponse`
  - remove db call to displayUpdateNotification, not used anymore
  - support receiving multiple custom notifications
  - support custom notification groups
  - the default group is `all` - this will always be consumed
  - groups can be extended via config e.g. `notificationGroups: ['migration']`

- Update check module: refactor createCustomNotification helper
  - get rid of taking over notification duplication handling (this is not the task of the update check module)
  - ensure we have good fallback values for non present attributes in a notification
  - get rid of semver check (happens in the USC) - could be reconsidered later if LTS is gone

- Refactor notification API
  - reason: get rid of in process notification store
    -> this was an object hold in process
    -> everything get's lost after restart
    -> not helpful anymore, because imagine the following case
      -> you get a notification
      -> you store it in process
      -> you mark this notification as seen
      -> you restart Ghost, you will receive the same notification on the next check again
      -> because we are no longer have a separate seen notifications object
  - use database settings key `notification` instead
  - refactor all api endpoints to support reading and storing into the `notifications` object
  - most important: notification deletion happens via a `seen` property (the notification get's physically deleted 3 month automatically)
    -> we have to remember a seen property, because otherwise you don't know which notification was already received/seen

- Add listener to remove seen notifications automatically after 3 month
  - i just decided for 3 month (we can decrease?)
  - at the end it doesn't really matter, as long as the windows is not tooooo short
  - listen on updates for the notifications settings
  - check if notification was seen and is older than 3 month
  - ignore release notification

- Updated our privacy document
- Updated docs.ghost.org for privacy config behaviour
- contains a migration script to remove old settings keys
2018-01-09 15:20:00 +01:00
juan-g
f671f9d2c9 Theme translations and blog localisation (#8437)
refs #5345, refs #3801

- Blog localisation
  - default is `en` (English)
  - you can change the language code in the admin panel, see https://github.com/TryGhost/Ghost-Admin/pull/703
  - blog behaviour changes depending on the language e.g. date helper format
  - theme translation get's loaded if available depending on the language setting
  - falls back to english if not available

- Theme translation
  - complete automatic translation of Ghost's frontend for site visitors (themes, etc.), to quickly deploy a site in a non-English language
  - added {{t}} and {{lang}} helper
  - no backend or admin panel translations (!)
  - easily readable translation keys - very simple translation
  - server restart required when adding new language files or changing existing files in the theme
  - no language code validation for now (will be added soon)
  - a full theme translation requires to translate Ghost core templates (e.g. subscriber form)
  - when activating a different theme, theme translations are auto re-loaded
  - when switching language of blog, theme translations are auto re-loaded

- Bump gscan to version 1.3.0 to support more known helpers

**Documentation can be found at https://themes.ghost.org/v1.20.0/docs/i18n.**
2018-01-09 14:50:57 +01:00
Katharina Irrgang
dcb2aa9ad4
Improved forwarding model options in the API layer (#9380)
no issue

- our API layer uses a unit to combine incoming data and options
- e.g. `options.data` is the end result
- we have to take care that we don't pass data into the model layer

Credits: Olivier Arteau
2018-01-09 13:26:09 +01:00
Aileen Nowak
430973b85b 🐛 Fixed date helper timezone bug
closes #9381

Fixes a bug where the date helper would ignore any timezone settings, when called with a specific date option, e. g. `published_at`, as `timezone` was only ever assigned when called without options.
2018-01-09 13:05:54 +01:00
Aileen Nowak
b99d3bc70a Revert "🐛 Fixed date helper timezone bug (#9382)"
This reverts commit c3b0219d70.
2018-01-09 13:05:54 +01:00
汪磊
c3b0219d70 🐛 Fixed date helper timezone bug (#9382)
closes #9381

Fixes a bug where the date helper would ignore any timezone settings, when called with a specific date option, e. g. `published_at`.
2018-01-09 17:44:01 +07:00
kirrg001
a1393762f6 Lazily require modules in lib/common/index
no issue

- decreases chance of not-loaded modules or circular dependencies
- e.g. the i18n implementation will use the settings-cache and the settings-cache uses lib/common/events
2018-01-08 21:12:16 +01:00
Aileen Nowak
19a6c8a426 Added test for images w/o extensions for image size util (#9367)
closes #9022

Images without extensions don't need to be manipulated, as we're now reading the bytes and pass those to the `image-size` lib.

This PR adds another `user-agent` to emulate multiple browser requests, as I stumbled over an example where the image without extension is protected otherwise.

Added a test, that works with above mentioned image, but is currently mocked. Nevertheless, the image worked as a PoC, that we're able to read the bytes of an image without its extension and still return the dimensions of the image.
2018-01-04 12:03:41 +01:00
Katharina Irrgang
341f719d92
Extended ghost version utility (#9278)
refs https://github.com/TryGhost/Ghost-Release/issues/24

- differentiate between
  1. original package.json version (can contain pre and build suffix)
  2. full package.json version X.X.X-{pre} (optional)
  3. safe package.json version X.X (major+minor)
2018-01-03 20:20:18 +01:00
kirrg001
eb0a11d53a Fixed import test: post duplication detection within a file to import
no issue

- with 29e143fa9a import queries no longer run in parallel
- this commit simply adds a small code snippet to reflect the importer behaviour

1) duplicate slugs *within* a file are getting ignored
2) existing posts in the database and posts to import with the same slug, result in duplicates

Further improvements regarding duplication detection will happen via #8717.
2018-01-03 13:34:15 +00:00
kirrg001
428008e63d Revert "🐛 Fixed importer duplicate detection for posts"
refs #8717

- we decided to not changing the current importer behaviour
- no slug duplication detection means, importing posts can result in duplicates
2018-01-03 13:34:15 +00:00
kirrg001
02bd71d0f5 🐛 Fixed importer duplicate detection for posts
closes #8717

- this is now required, because we run import queries sequentiell
- this code protects two cases:
  - you have duplicate slugs in the JSON file (the first get's inserted, the second get's ignored)
  - you have an existing slug in the database and you try to import the same slug, get's ignored
2018-01-03 00:07:41 +01:00
kirrg001
29e143fa9a 🐛 Fixed large imports
closes #9348

- do not run import with `Promise.all`
- with a large import file, we run an enormous amount of queries in parallel, which does not allow Node to cleanup memory
- tested with an 13mb import file
- requires bookshelf-relations 0.1.4
2018-01-02 23:21:45 +01:00
Aileen Nowak
ae741b1a18 Removed bluebird promise wrap in request lib (#9343)
refs #9178, refs #8988

With 7353c87d7f we use Bluebird globally for Promises. Therefore, the request lib doesn't need to be wrapped in a bluebird Promise anymore.

This was originally done, so we can work with catch predicated in our image-size lib.

Updated the tests to proof, that the catch predicates work.

The tests fail, as soon as the Promise overwrite is commented out.
2018-01-02 12:18:56 +01:00
汪磊
7a98c99cba Renamed BasicErorRenderer to BasicErrorRenderer (#9358)
no issue

- typo 🙊
2018-01-02 10:33:43 +01:00
Hannah Wolfe
bcf6e9f517 Fixed error trying to render 404 for missing asset
refs #8868

- Loading the admin prior to a build results in: Failed to lookup view "error-404" in views directory
- This fixes that error, by splitting the HTMLErrorRenderer and the ThemeErrorRenderer into two separate things
2017-12-22 20:08:59 +00:00
juan-g
4cca2353e0 consistency change for english translation keys: use camel case (#9347)
no issue

- required for #8437 
- one instance of hyphenated key changed; the rest of keys in file
_core/server/translations/en.json_ are already camelCase
- also converted `common.i18n.t()` calls to this key in file
_core/server/update-check.js_
- this allows to simplify i18n to an unified use of `jsonpath`
2017-12-18 15:47:55 +01:00
Katharina Irrgang
a5af7d6384 Used request lib in xmlrpc (#9333)
refs #9178, refs https://github.com/TryGhost/Ghost/pull/8980
2017-12-15 16:50:18 +07:00
Katharina Irrgang
6e94cedfa2 Ensure cors check happens for /authentication/token route (#9317)
no issue

- otherwise external browser clients run into cors problems
2017-12-15 09:35:48 +00:00
Abijeet Patro
73c0bf554a 🐛 Fixed emoji in Slack test notification not rendered by Discord (#9313)
closes #9263

- changed emoji for Slack test notification to 😄 which will be correctly rendered as emoji by both, Slack and Discord.
2017-12-15 11:19:37 +07:00
kirrg001
991ccb1d35 Moved make-absolute-urls to url service
refs #9178

- this util uses the url services (!)
- moving this file into lib would not make sense right now
  - that would mean a module requires first ../lib/url, which then requires ../services/url
- the url service definitely need a clean up 😃
2017-12-14 22:34:37 +01:00
kirrg001
64626dedd1 Moved social utility to lib/social
refs #9178

- not 100% sure about this, but i think it makes right now the most sense
- we have already a url service and creating another lib/url is confusing at the moment
- i'll copy the last utility `makeAbsoluteUrls` to the url service for now
- see next commit for explanation (!)
2017-12-14 22:34:05 +01:00
kirrg001
b474fb0d16 Moved ghost-version to lib
refs #9178
2017-12-14 22:14:55 +01:00
kirrg001
1a9a10c82b Moved zip folder, read csv and package-json to lib/fs
refs #9178, refs 849e97640f

- i've reconsidered, these modules belong to lib
- prettify package-json module
2017-12-14 22:07:53 +01:00
kirrg001
82597080be Burn dirty require of api utils
refs #9178

- `checkFileExists` and `checkFileIsValid` where dirty required from web/middleware
- these two functions are only used in the target middleware
- let's move them
2017-12-14 21:25:51 +01:00
kirrg001
849e97640f Moved zip folder utility to services/themes
refs #9178

- it's only used for themes currently
- this is definitely a util which could be useful lib
- if we have a second use case, we can move it
2017-12-14 21:02:47 +01:00
kirrg001
fc5b4dd934 Moved image utils to lib/image
refs #9178

- i am not super happy about `const imageLib = require('../lib/image')`
- i don't really like the name `imageLib`
- but i had no better idea 😃
- if we use the same name in the whole project, it's very easy to rename the folder or the variable
2017-12-14 20:46:53 +01:00
kirrg001
740b247a80 Avoid moment deprecation warning when validating incoming dates
no issue

> Deprecation warning: value provided is not in a recognized ISO format. moment construction falls back to js Date(), which is not reliable across all browsers and versions.
2017-12-14 17:04:06 +01:00
kirrg001
634fdbfa96 Tests: Do not re-register model events in settings cache
no issue

> (node:63849) Warning: Possible EventEmitter memory leak detected. 101 settings.edited listeners added. Use emitter.setMaxListeners() to increase limit

- the settings cache was initialised per test
- it registered the model events over and over again
- add a simple shutdown function, which can be called from the test env
2017-12-14 16:41:30 +01:00
Katharina Irrgang
18e15934fd Used request lib in slack service (#9335)
refs #9178

- tested with slack
2017-12-14 22:08:48 +07:00
Katharina Irrgang
50b65bca0c Moved default-cards app to lib/mobiledoc (#9341)
refs #9178, refs https://github.com/TryGhost/Ghost/pull/9338
2017-12-14 14:44:01 +00:00
kirrg001
a3091a3012 Moved utils constants to lib/constants
refs #9178
2017-12-14 14:13:40 +01:00
kirrg001
c5169e23c4 Moved unique identifier generation to lib/security
refs #9178
2017-12-14 13:52:20 +01:00
kirrg001
bb06a8426d Moved tokens, url safe and safe string utility to lib/security
refs #9178

- we could now also move any crypto usages to lib/security, but no priority
- the main goal is to tidy up our utils folder
2017-12-14 13:38:00 +01:00
Katharina Irrgang
9de13ae3ad Moved mobiledoc/markdown converters to apps/default-cards (#9338)
refs #9178

- they definitely don't belong to server/utils
- i think the best place is putting them into the card apps
- the the post model needs to ask the app for it's converters
- move tests as well
2017-12-14 11:09:54 +00:00
kirrg001
4fe7c9d7fc Moved validateRedirects helper to data/validation
refs #9178
2017-12-14 11:55:10 +01:00
Katharina Irrgang
2956c2c247 Use request lib in webhooks api (#9336)
refs #9178

- add retries and timeout
2017-12-14 10:00:34 +00:00
Katharina Irrgang
941379ddba Use request lib in gravatar utility (#9337)
refs #9178
2017-12-14 09:51:05 +00:00
Katharina Irrgang
192ebb1739
Moved labs, auth, permissions, settings, mail, themes to services (#9339)
refs #9178

- move tests as well
2017-12-14 03:01:23 +01:00
kirrg001
dac9ffc473 Removed leftover usages for globalUtils.sequence
refs #9178
2017-12-14 01:40:15 +01:00
kirrg001
660a407c16 Burn asset-hash utility
refs #9178

- Ghost uses the Node crypto lib always direct (require('crypto'))
- it doesn't make sense to outsource a single crypto statement (for the asset hash)
- we either have to write a crypto wrapper to avoid writing long crypto statements or we keep the direct usages for every case
- for now, wrapping the crypto calls into a lib/crypto has no priority
2017-12-14 01:33:01 +01:00
kirrg001
11a8245ca6 Added TODO to core/server/data/validation/index.js
no issue

- we are modifying the global validator dependency, which is bad
- see https://github.com/chriso/validator.js/issues/525#issuecomment-213149570
- we should create our own class and expose a singleton for the whole Ghost project
2017-12-14 01:15:12 +01:00
Katharina Irrgang
11765351cc
Use request lib in update-check module (#9334)
refs #9178

- works with local update check service
- tested success/error cases
2017-12-14 00:26:11 +01:00
kirrg001
7460076206 Moved request to lib/request
refs #9178

- next steps are to
  A: test if global.Promise works with `got` (see https://github.com/TryGhost/Ghost/pull/8988#issuecomment-351532881)
  B: re-use request utility everywhere
  C: request lib requires data/validator, which is dirty
2017-12-13 22:37:42 +01:00
kirrg001
f83cbf6117 Moved pipeline/sequence to lib/promise
refs #9178

- continue with killing our global utils folder
- i haven't found any better naming for lib/promise
- so, require single files for now
- instead of doing `promiseLib = require('../lib/promise')`
- we can optimise the requires later
2017-12-13 22:20:02 +01:00
kirrg001
0d65e7f24f Renamed apiUtils to localUtils - consistency change
refs #9178

- we should always use the same naming patterns
2017-12-13 22:14:19 +01:00
kirrg001
6e915e8e89 Moved removeOpenRedirectFromUrl to local web utils
refs #9178

- see https://github.com/TryGhost/Ghost/issues/9178#issuecomment-351521897
2017-12-13 22:06:31 +01:00
kirrg001
485c264c69 Use Promise support which was added in fs-extra 3.x
no issue

- now that we use bluebird globally, we can use the promise support from fs-extra
2017-12-13 20:57:11 +01:00
kirrg001
d83f474ff8 Always require fs-extra - consistency change
no issue
2017-12-13 20:57:11 +01:00
kirrg001
7353c87d7f Set Promise to be Bluebird globally
closes #9064
2017-12-13 20:57:11 +01:00
Katharina Irrgang
4f35f86713
Moved word-count utility to helpers/utils.js (#9328)
refs #9178

- each package/module has a local utility (e.g. api, helpers, adapters)
- these are very small utility functions which are only used from this package
- they don't belong into the global lib/utils
2017-12-13 14:05:53 +01:00
Katharina Irrgang
397400b4f8
Moved visibility utility to static model fn (#9327)
refs #9178

- this logic belongs to a static model helper
- the visibility property is a model property, the knowledge about the visibility values belongs to the model
- rename the functions, so they make more sense
2017-12-13 13:19:51 +01:00
Hannah Wolfe
79ca6c575c Cleared out old unused events
no issue

- Because of 9248 we send too many events and this is not reliable
- Remove everything except the well understood published events
2017-12-13 09:08:25 +00:00
kirrg001
2c2d1e93cc Fixed wrong require path in webhook-permissions
no issue

- the require path to the logging module was wrong
- because of ac2578b419
2017-12-12 15:23:07 +01:00
Katharina Irrgang
a98346e2ce Migration for webhook permissions (#9320)
refs https://github.com/TryGhost/Ghost/pull/9230
2017-12-12 14:12:34 +00:00
kirrg001
6f6c8f4521 Import lib/common only
refs #9178

- avoid importing 4 modules (logging, errors, events and i18n)
- simply require common in each file
2017-12-12 10:28:13 +01:00
kirrg001
ac2578b419 Moved errors,logging,i18n and events to lib/common
refs #9178
2017-12-12 10:28:13 +01:00
kirrg001
4265afe580 Moved utils/url.js to UrlService
refs #9178

- we have to take care that we don't end up in circular dependencies
  - e.g. API requires UrlService and UrlService needs to require the API (for requesting data)
- update the references
- we would like to get rid of the utils folder, this is/was the most complicated change
2017-12-11 20:05:33 +01:00
kirrg001
7d99ee8466 Small UrlService optimisations
no issue

- rename the config option to disable preloading the urls
- always expose the urlservice as singleton
- do the initialisation of the service inside the constructor
2017-12-11 20:05:33 +01:00
Katharina Irrgang
7bcccc71dc
Moved apps into web folder (#9308)
refs #9178

- move express apps to one place (called `web`)
- requires https://github.com/TryGhost/Ghost-Admin/pull/923
- any further improvements are not part of this PR
- this PR just moves the files and ensures the paths are up-to-date
2017-12-06 17:37:54 +01:00
Katharina Irrgang
0bb81bb3c4
Bump knex-migrator to version 3.1.1 (#9199)
no issue

- adapt major changes of knex-migrator v3
- adapt migration scripts, simplify and add `down` (rollback) hook if possible
- clear Ghost cache after init hook (because of `knex-migrator migrate --init`)
- ensure db migrations work with the CLI
- updated troubleshooting guide (https://docs.ghost.org/v1/docs/troubleshooting#section-task-execute-is-not-a-function)

**For development only: Please ensure you run `npm i -g knex-migrator@latest` to update your global installation to v3. We always prefer the local installation, but v3 has modified and added binaries.**
2017-12-05 09:14:55 +01:00
kirrg001
533ae22c2b Added protection for incorrect i18n variable names
closes #9305

- add a try/catch when formatting messages
- fallback to the general error message if error ocurred
- log the error
2017-12-04 17:13:12 +01:00
kirrg001
0be734a05c Fixed incorrect i18n variable names
no issue
2017-12-04 16:58:02 +01:00
Katharina Irrgang
9e388aee4d 🎨 Improved error handling for images on file storage which don't exist (#9282)
refs https://github.com/TryGhost/Team/issues/41

- differentiate error codes
- return 404 if image was not found
- else return a 500
- use i18n keys
- use errors.utils.isIgnitionError (!)
2017-11-28 14:27:18 +00:00
kirrg001
be9ce107bd Re-attach error to request object if error occurs when rendering error template
no issue

- otherwise we won't see the error in the logs
2017-11-28 13:44:14 +00:00
kirrg001
e8075262eb 🎨 Improved pagination misusage error
refs https://github.com/TryGhost/Team/issues/41, refs https://github.com/TryGhost/gscan/issues/85

- if you are using the pagination helper not inside a resource context, you will receive an error
- improve error message, because it was not clear what happened
- downgrade error level to normal, because it's not a critical error from Ghost's perspective, from user perspective it is
- added help docs link and added a callout to our docs
2017-11-28 13:44:14 +00:00
Katharina Irrgang
d87fbeca49 🐛 Fixed error handling for html response (#9280)
refs https://github.com/TryGhost/Team/issues/41

- if you add invalid handlebars logic e.g. {{if condition condition}}, handlebars throws an error
- in case of having invalid hbs in an amp page, the amp component throwed another syntax error (which is fixed in this PR)
- furthermore the `setTemplate` helper function had a logic bug, which did not handle errors correctly
  - if there is an error and a template is set (e.g. amp), we have to still render the error page and not the amp page
- this fix only ensures that the error handling is correct, we still see the error of the "ugly" handlebars message
  - e.g. [amp.hbs] Cannot read property 'includeZero' of undefined
  - but no longer -> Cannot read property 'html' of undefined (which was a syntax error in Ghost)
2017-11-28 12:00:43 +00:00
Katharina Irrgang
3004e03bc6 🐛 Fixed throwing 500 for invalid encoded urls (#9279)
refs https://github.com/TryGhost/Team/issues/41

- if you send invalid encoded url components in the path, the server tried to decode the url
- if it contains invalid characters like /AF%, it throwed a 500
- we return a page not found error instead
2017-11-28 11:39:38 +00:00
Guillem Andreu
860b38a1a7 🐛 Fixed Sitemap when permalink contains Primary Tag (#9273)
closes #9272

- included tags in sitemap post-generator
2017-11-27 12:38:56 +01:00
Kevin Ansfield
94360c8a32
🐛 Fixed import and redirect uploads for Win10/Edge (#9267)
closes https://github.com/TryGhost/Ghost/issues/9236
- added `text/plain` to the allowed mime types for db and redirect uploads
2017-11-22 17:30:53 +00:00
Kevin Ansfield
bffb3dbd90
Webhooks support for subscriber events (#9230)
no issue

Support for http://resthooks.org style webhooks that can be used with Zapier triggers. This can currently be used in two ways:

a) adding a webhook record to the DB manually
b) using the API with password auth and POSTing to /webhooks/ (this is private API so not documented)

⚠️ only _https_ URLs are supported in the webhook `target_url` field 🚨

- add `webhooks` table to store event names and target urls
- add `POST` and `DELETE` endpoints for `/webhooks/`
- configure `subscribers.added` and `subscribers.deleted` events to trigger registered webhooks
2017-11-21 15:43:14 +00:00
Katharina Irrgang
dfd4afea19 Add bookshelf-relations (#9252)
no issue

- added https://github.com/TryGhost/bookshelf-relations as dependency
- remove existing tag handling

--- 

* Important: Ensure we trigger parent initialize function

- otherwise the plugin is unable to listen on model events
- important: event order for listeners is Ghost -> Plugin
- Ghost should be able to listen on the events as first instance
- e.g. be able to modify/validate relationships

* Fix tag validation

- we detect lower/update case slugs for tags manually
- this can't be taken over from the plugin obviously
- ensure we update the target model e.g. this.set('tags', ...)

* override base fn: `permittedAttributes`

- ensure we call the base
- put relations on top
- each relation is allowed to be passed
- the plugin will auto-unset any relations to it does not reach the database

* Ensure we run add/edit/delete within a transaction

- updating nested relationships requires sql queries
- all sql statements have to run in a single transaction to ensure we rollback everything if an error occurs
- use es6
2017-11-21 13:28:05 +00:00
Aileen Nowak
982a75d6be 🐛 Fixed slugs from exceeding db limit (#9251)
closes #8143

Fixed a potential issue (edge-case), where our generated and validated (in terms of check for existance and add a counter) would return a slug, that will exceed the maximum length of the slug fields (191 chars).

This is mostly possible for the post title, which can be 255 chars long and would generate a slug with the same length. This would prevent the user from actually saving a post.

I tried first to determine the expected length for a slug that already exists, but decided that the **easier** and simplyfied implementation is to always cut a slug to **185 chars** (+ counter). This makes it easier to find duplicates and includes a possible high number of counts (edge-edge-case).

The slug will not be cut down to 185 chars if it's an import.
2017-11-21 14:21:22 +01:00
Hannah Wolfe
5e5b90ac29
Added Url Service to track all URLs in the system (#9247)
refs #9192

- Introduces a url service that can be initialised
- Added a concept of Resources and resource config.json that contains details about the resources in the system that we may want to make customisable 
- Note that individual resources know how to create their own Urls... this is important for later
- Url Service loads all of the resources, and stores their URLs
- The UrlService binds to all events, so that when a resource changes its url and related data can be updated if needed
- There is a temporary config guard so that this can be turned off easily
2017-11-16 13:03:24 +00:00
Aileen Nowak
1bb9d4ff00 Set soft limits for blog title and description (#9250)
refs #8143

Add max length validations to settings:
- `blog.title`: 150 chars
- `blog.description`: 200 chars

The `validateSettings` fn in our validations checks for existing `validations` properties in our `default-settings.json` file, similar to other tables in our `schema.js`.
2017-11-16 13:58:22 +01:00
kirrg001
c4044aa498 Do not log error if i18n.doesTranslationKeyExist is called
no issue

- when calling `doesTranslationKeyExist`, we want to know if a key exists, we don't want to log if the key was not found
- this can mess up the server log
2017-11-14 14:03:48 +01:00
Katharina Irrgang
76689ecbee 🐛 Fixed pagination error (#9243)
no issue

- see explanation https://github.com/TryGhost/Ghost/pull/8129#issuecomment-286061529
- we catch the db error if it occurs, we can't simply check the length of the page param, because sqlite/mysql behaves differently
2017-11-14 12:47:58 +00:00
Kevin Ansfield
bcc98e5536 Added GET/DELETE /subscribers/email/:email/ endpoints (#9238)
no issue

- useful for managing subscribers via external systems/API calls where it's likely only the e-mail address will be known
- adds `GET /subscribers/email/:email/`
- adds `DELETE /subscribers/email/:email/`
2017-11-14 12:09:41 +01:00
John O'Nolan
0d54326121 Give default Ghost user fixture a helpful bio (#9241)
no issue

Had a couple of people ask about how to delete welcome posts easily, so adding a bio to the default user to draw a little more attention to it
2017-11-14 10:23:38 +00:00
kirrg001
0eb84d7f8a 🐛 Fixed concurrent renew of access tokens
no issue

- it can happen that concurrent requests try to renew access tokens with the same refresh token
- in this case it could happen that you received a token deletion error
- add propert locking
- ensure we don't run into deadlocks
- manual testing with async.times for parallel requests (was able to reproduce the error)
2017-11-14 10:22:09 +00:00
kirrg001
4b21fc1d59 Allow forUpdate for any model
no issue

- this was only supported for the Post Model until now
- locking should be possible for every resource depending on the use case
2017-11-14 10:22:09 +00:00