Commit Graph

310 Commits

Author SHA1 Message Date
Kevin Ansfield
2b34327544 🐛 Fixed plaintext field not being cleared when post body is removed
closes https://github.com/TryGhost/Ghost/issues/10557
- add conditional for plaintext changing rather than only being present for when to set a new plaintext value
2019-03-04 14:03:44 +00:00
kirrg001
58153ad47d Fixed "html" being marked as changed if mobiledoc or html was not changed
no issue

- if you html is NULL e.g. you create a draft post, we always set "html" to ""
- this get's marked as changed
- !this.get('html') was added for the 2.0 migration, because some posts had custom mobiledoc, but no html value
2019-02-23 22:02:42 +01:00
kirrg001
641b67e784 Fixed x_by being detected as changed if owner updates resources
refs #9299

- `contextUser` returns a number and if the previous x_by is "1", then bookshelf marks it as changed ("1" !== 1)
- this is a left over from 0.x, because we still owner as id 1
- as soon as we fix 9299, we don't have to worry about this anymore, because we will fetch the owner id if we need it
2019-02-23 22:00:24 +01:00
Katharina Irrgang
dfd350bd69
Cleaned up Admin API v2 posts/pages input serializer (#10516)
no issue

- make use of filter instead of status=all or data.page
- nql was designed to filter data on database layer
- do not break v0.1
- we just got rid of the "status" query param, you should use the filter instead
- get rid of the ugly condition to remove page field if "fields" param was used
- allow filtering on model layer for "findOne"
  - do not allow filtering for "findOne" on API layer for now
  - the API controller defines what is allowed
  - the model layer can allow more by default
  - we can re-use the powerful filter logic without adding hacks
2019-02-22 12:07:34 +01:00
Katharina Irrgang
0a70226128 Separated pages & posts in Admin API v2 (#10494)
refs #10438, refs #10106

* Renamed existing pages ctrl
* Splitted posts & pages for Admin API v2
* Added pages JSON input schema for Admin API v2
* Removed single author for Content & Admin API v2
  - single author is not documented
  - single author usage is deprecated in v0.1
  - single author usage is removed in API v2
* Splitted posts & postsPublic controller for v2
* Removed requirement to send `status=all` from Admin API v2
* Removed `status` option from pages Content API v2
* Removed `status` options from Users Admin API v2
2019-02-22 10:17:14 +07:00
kirrg001
b83232bf0c Added more webhooks & changed payload
refs #10461

- do not break the existing webhooks by keeping both payload formats for subscribers events
- refactored webhooks service to run models through target API version
- added new events described in the target issue reference
- this refactoring & enhancement is undocumented, further breaking changes will happen because we are actively working on: https://github.com/TryGhost/Ghost/issues/10438
2019-02-07 23:14:27 +01:00
kirrg001
82c5fc7f5a Ensured API can ask model.wasChanged
refs #10461

- the model layer (only post & user) fetches the model after update
- i assume it was added to ensure a response with all fields
- quick fixing it for now to ensure API layer can access ".wasChanged" to be able to decide if a request modified a resource or not

@NOTE: Bookshelf does not physically update a resource if nothing has changed.
2019-02-07 22:07:13 +01:00
kirrg001
865366c7c8 Ensured consistency for event handlers in the model layer
no issue

- the event chain works like this:
  - if a model registers an event, it get's triggered, because it's stronger than the base model
- but you have to call the base model to agree on a contract, because base model implements generic logic in event handlers
- this was inconsistently used
2019-02-07 11:02:35 +01:00
kirrg001
cca3317a11 Simplfied action trigger in base model
refs #10431

- the model layer triggers a couple of events on resource update
  e.g. post to page -> post.deleted, post.added
- the resource_type must be always "post", because "page" is not an official model (Bookshelf won't be able to resolve the resource anymore)
- the action streams looks very confusion if you see deleted and added actions when toggling the post to a static page
- therefor the easiest approach for now is to only store actions for: added, edited, deleted
- and we will add the context information asap
  - e.g. you will see that status was changed from "draft" to "published"
- we can also introduce extra published actions if we want
- relying on the internal event system right now makes things just more complicated and we want to keep it simple
2019-02-06 22:21:06 +01:00
kirrg001
8bb2c7d3d5 Added model implementation for actions
refs #10431

- added actions model
- added logic in event emiiter to insert actions if supported
2019-02-06 21:36:09 +01:00
kirrg001
11c910ec8c Avoided to store empty plaintext if html does not contain any text
no issue
2019-01-31 23:14:12 +01:00
kirrg001
24a2208625 Fixed 500 when sending wrong mobiledoc structure
refs #10438
2019-01-31 13:33:05 +01:00
kirrg001
d20bdfd9c1 Moved more allowed options for findPage to base model
no issue

- no need to define these options in each model
2019-01-29 23:29:06 +01:00
kirrg001
87bb3052a8 Moved allowed filter option to base model
no issue

- no need to define the filter option in each model
2019-01-29 22:57:11 +01:00
Fabien O'Carroll
95880dddeb
🐛 Updated base model to store null instead of empty string (#10425)
refs #10388 

This updates the base model to retrieve column information, and explicitly set every property whose column is `nullable` and content is the empty string (`""`) to `null`
2019-01-28 16:58:28 +01:00
Katharina Irrgang
4acc375fb6
Bumped knex & bookshelf dependencies (#10404)
refs #9389, refs #9248

- https://github.com/bookshelf/bookshelf/releases/tag/0.14.0
- Bookshelf has fixed it's previous attr handling, see https://github.com/bookshelf/bookshelf/pull/1848
- SQlite3 double slashes was merged into knex and released 👻tgriesser/knex@c746dea
2019-01-21 21:53:11 +01:00
Fabien O'Carroll
809a167a55 Updated permissible methods for hasApiKeyPermissions (#9970)
refs #9865

This updates all current permissible methods to use the new function
signature which includes the hasApiKeyPermissions parameter. It also
makes sure that the hasApiKeyPermissions argument is taken into account
whenever checking before returning a resolved promise.

To be continued. This is just a tiny part of the big picture. None of these changes are fully committed to stay as they are.
2019-01-18 13:39:53 +01:00
Naz Gargol
df1ba8aee1
Added ability to notify and update url service about changes in related resources (#10336)
refs https://github.com/TryGhost/Ghost/issues/10124

- This PR introduced additional db calls in URL service due to the need for a model recalculation (we can't rely on the objects that come with events)
2019-01-08 09:48:53 +00:00
Katharina Irrgang
9d7c3bd726
🐛 Fixed all known filter limitations (#10159)
refs #10105, closes #10108, closes https://github.com/TryGhost/Ghost/issues/9950, refs https://github.com/TryGhost/Ghost/issues/9923, refs https://github.com/TryGhost/Ghost/issues/9916, refs https://github.com/TryGhost/Ghost/issues/9574, refs https://github.com/TryGhost/Ghost/issues/6345, refs https://github.com/TryGhost/Ghost/issues/6309, refs https://github.com/TryGhost/Ghost/issues/6158, refs https://github.com/TryGhost/GQL/issues/16

- removed GQL dependency
- replaced GQL with our brand new NQL implementation
- fixed all known filter limitations
- GQL suffered from some underlying filter bugs, which NQL tried to fix
- the bugs were mostly in how we query the database for relation filtering
- the underlying problem was caused by a too simple implementation of querying the relations
- mongo-knex has implemented a more robust and complex filtering mechanism for relations
- replaced logic in our bookshelf filter plugin
- we pass the custom, default and override filters from Ghost to NQL, which then are getting parsed and merged into a mongo JSON object. The mongo JSON is getting attached by mongo-knex.

NQL: https://github.com/NexesJS/NQL
mongo-knex: https://github.com/NexesJS/mongo-knex
2018-12-11 11:53:40 +01:00
Katharina Irrgang
090a936e16
Moved raw order for author filtering to correct place (#10166) (#10171)
refs #10105

- ordering !== filtering
2018-11-15 16:17:51 +01:00
Katharina Irrgang
e89a27f3ab
Replaced options.where GQL statements with filter notation (#10160)
refs #10105

- `options.where` is an older deprecated logic
- before the filter language was invented, Ghost generates statements for knex
- if we want to replace GQL with NQL, we can't generate these statements
- they are not understood from NQL, because NQL uses mongo JSON
- go through usages and rewrite the statements
- invent `extraFilters` for now
- we need to keep the support for `status` or `staticPages` for now (API requirement)
- IMO both shortcuts in the extra filters should be removed in the future

This commit is required for https://github.com/TryGhost/Ghost/pull/10159!
2018-11-15 15:53:24 +01:00
Katharina Irrgang
2e81852b22
Moved raw order for tag filtering to correct place (#10166)
refs #10105

- ordering !== filtering
2018-11-15 15:27:31 +01: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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
Hannah Wolfe
1c382792ef Prev & next post filtering, with primary tag support (#9141)
closes #9140
* Rip out existing prev/next implementation
* New implementation using filter
* Support next/prev in primary_tag
2017-10-13 15:44:39 +01:00
Hannah Wolfe
fcd3c6847b 🐛 Fixed author role permission to change author (#9067)
🐛  Fixed author role permission to change author

no issue

- To be able to fix this bug, we had to solve tasks from #9043
- This bug affects the private / undocumented API only
- Author role users should not be allowed to change the author of a post
2017-09-27 13:12:53 +02:00
Hannah Wolfe
b468d6dbe2 Support for attribute-based permissions (#9025)
refs #8602

- Add the wiring to pass attributes around the permission system
- Allows us to get access to the important "unsafe" attributes that are changing
- E.g. status for posts
- This can then be used to determine whether a user has permission to perform an attribute-based action
- E.g. publish a post (change status)
2017-09-26 18:06:14 +02:00
kirrg001
c99557d9a3 🐛 Fixed disqus comment id when exporting/importing 1.x content
no issue

- while i was testing random failures, i discovered an edge case for disqus
- you start a new 1.0 blog, you add disqus, the unique identifer is the post id (object id)
- now you export your content and import it on a new instance
- the importer detects that the amp field is null and imports the old object id as comment id
- but the post model is not prepared for this case
- see next commit for tests

**NOTE**: The comment id had two different data types (Number or String). Disqus expects a string. So this should not change any behaviour, now that the comment_id is always a string.
2017-09-12 16:29:59 +01:00
Kevin Ansfield
47322e4239 Re-instate mobiledoc dom rendering with bypass of SimpleDOM parsing (#8937)
closes #8757

- update the markdown card render method to use SimpleDOM's `createRawHtmlSection`. This avoids SimpleDOM parsing and tokenization of broken or unsupported free-form HTML that markdown allows
- replace markdown extraction/render with mobiledoc's renderer in the `Post` model
- removes `jsdom` as it's no longer necessary
2017-08-31 12:09:02 +02:00
Hannah Wolfe
c6d54ceea1 🐛 Fixed internal tags being used as primary tags (#8934)
fixes #8920

- Implements logic such that internal tags cannot be primary tags
- If the first tag on a post is an internal tag, that post will not have a primary tag
2017-08-24 13:07:19 +01:00
Hannah Wolfe
cafabff89e 🐛 Fixed duplicate subdirs in plaintext (#8882)
fixes #8845

- We had a report of weird URLS being output in admin stories view
- This is due to plaintext being incorrectly generated
- In order for a URL to be correct, it would need to already contain the subdirectory
- This line in the post model adds it as well, causing a duplicate
- Hence removing this line is the fix
2017-08-15 11:31:22 +01:00
Hannah Wolfe
353e11dafb Primary tag (#8669)
refs #8668

- return primary tag from Post API
- support primary tag in URL
2017-07-31 13:00:03 +04:00
Kevin Ansfield
57ffa4571c 🐛 fix "unbalanced tag" errors on save/import (#8759)
refs https://github.com/TryGhost/Ghost/issues/8757

- remove mobiledoc parsing, it's reliance on SimpleDom makes it too
fragile when dealing with the unconstrained user-entered HTML that is
allowed in markdown
2017-07-27 12:10:15 +04:00
Katharina Irrgang
ce3830f8a9 🚓 disqus comments (#8762)
closes #8760

- we have to remember the old post id's when migrating a blog from LTS to 1.0
- otherwise we would break disqus comments, because they rely on the post id
- this should fix the discovered situation
2017-07-27 11:55:23 +04:00
Kevin Ansfield
85496f409a 🔥 remove posts.markdown field (#8497)
closes #8479

- removes `markdown` field from schema
- removes `legacyMarkdown` converter
- updates tests to work with `mobiledoc` field instead of `markdown` and adapt for mobiledoc HTML output where necessary
2017-05-31 16:46:29 +02:00
Hannah Wolfe
3e60941054 Add ?formats param to Posts API (#8305)
refs #8275
- Adds support for `formats` param
- Returns `html` by default
- Can optionally return other formats by providing a comma-separated list
2017-05-30 11:40:39 +01:00
Katharina Irrgang
1f37ff6053 🎨 refactor the importer (#8473)
refs #5422

- we can support null titles after this PR if we want
- user model: fix getAuthorRole
- user model: support adding roles by name
- we support this for roles as well, this makes it easier when importing related user roles (because usually roles already exists in the database and the related id's are wrong e.g. roles_users)
- base model: support for null created_at or updated_at values
- post or tag slugs are always safe strings
- enable an import of a null slug, no need to crash or to cover this on import layer
- add new DataImporter logic
    - uses a class inheritance mechanism to achieve an easier readability and maintenance
    - schema validation (happens on model layer) was ignored
    - allow to import unknown user id's (see https://github.com/TryGhost/Ghost/issues/8365)
    - most of the duplication handling happens on model layer (we can use the power of unique fields and errors from the database)
- the import is splitted into three steps:
  - beforeImport
    --> prepares the data to import, sorts out relations (roles, tags), detects fields (for LTS)
  - doImport
    --> does the actual import
  - afterImport
    --> updates the data after successful import e.g. update all user reference fields e.g. published_by (compares the imported data with the current state of the database)
- import images: markdown can be null
- show error message when json handler can't parse file
- do not request gravatar if email is null
- return problems/warnings after successful import
- optimise warnings in importer
- do not return warnings for role duplications, no helpful information
- error handler: return context information of error
- we show the affected json entries as one line in the UI
- show warning for: detected duplicated tag
- schema validation: fix valueMustBeBoolean translation
- remove context property from json parse error
2017-05-23 17:18:13 +01:00
Katharina Irrgang
b22151ac92 🎨 do not ping slack if we import content (#8476)
closes #7275

- forward options for events (post model only for now)
2017-05-22 17:24:59 +09:00
Kevin Ansfield
5d868d14ad replace custom showdown fork with markdown-it (#8451)
refs https://github.com/TryGhost/Ghost-Admin/pull/690, closes #1501, closes #2093, closes #4592, closes #4627, closes #4659, closes #5039, closes #5237, closes #5587, closes #5625, closes #5632, closes #5822, closes #5939, closes #6840, closes #7183, closes #7536

- replace custom showdown fork with markdown-it
- swaps showdown for markdown-it when rendering markdown
- match existing header ID behaviour
- allow headers without a space after the #s
- add duplicate header ID handling
- remove legacy markdown spec
- move markdown-it setup into markdown-converter util
- update mobiledoc specs to match markdown-it newline behaviour
- update data-generator HTML to match markdown-it newline behaviour
- fix Post "converts html to plaintext" test
- update rss spec to match markdown-it newline behaviour
- close almost all related showdown bugs
2017-05-15 18:48:14 +02:00
Katharina Irrgang
9bea2077cf 🐛 ensure import of scheduled posts works (#8454)
closes #8354

- i thought about transforming scheduled posts into drafts on export, but this has two disadvantages:
  1. existing exports with scheduled posts won't import
  2. if you schedule a post for next week and you export/import earlier, the post is back to draft
- by this we ensure that we can simply import the post back to a scheduled post
- if the published_at is already in the past, the scheduler will care and instantly publish the post
2017-05-12 15:11:52 +02:00
Katharina Irrgang
c93f03b87e post update collision detection (#8328) (#8362)
closes #5599

If two users edit the same post, it can happen that they override each others content or post settings. With this change this won't happen anymore.

 Update collision for posts
- add a new bookshelf plugin to detect these changes
- use the `changed` object of bookshelf -> we don't have to create our own diff
- compare client and server updated_at field
- run editing posts in a transaction (see comments in code base)

🙀  update collision for tags
- `updateTags` for adding posts on `onCreated` - happens after the post was inserted
   --> it's "okay" to attach the tags afterwards on insert
   --> there is no need to add collision for inserting data
   --> it's very hard to move the updateTags call to `onCreating`, because the `updateTags` function queries the database to look up the affected post
- `updateTags` while editing posts on `onSaving` - all operations run in a transactions and are rolled back if something get's rejected

- Post model edit: if we push a transaction from outside, take this one

  introduce options.forUpdate
- if two queries happening in a transaction we have to signalise knex/mysql that we select for an update
- otherwise the following case happens:
  >> you fetch posts for an update
  >> a user requests comes in and updates the post (e.g. sets title to "X")
  >> you update the fetched posts, title would get overriden to the old one

use options.forUpdate and protect internal post updates: model listeners
- use a transaction for listener updates
- signalise forUpdate
- write a complex test

use options.forUpdate and protect internal post updates: scheduling
- publish endpoint runs in a transaction
- add complex test
- @TODO: right now scheduling api uses posts api, therefor we had to extend the options for api's
  >> allowed to pass transactions through it
  >> but these are only allowed if defined from outside {opts: [...]}
  >> so i think this is fine and not dirty
  >> will wait for opinions
  >> alternatively we have to re-write the scheduling endpoint to use the models directly
2017-04-19 14:53:23 +01:00
Katharina Irrgang
f2fd075075 🎨 fix previos/current date comparison (isEqual in bookshelf) (#8357)
no issue

- client dates are sent as ISO format (moment(..).format())
- server dates are in JS Date format
  >> when bookshelf fetches data from the database, all dates are transformed into JS dates
  >> see `parse` helper function
- Bookshelf updates the model with the client data via Bookshelf's `set` function
- therefor Bookshelf uses a simple `isEqual` function from lodash to detect changes
- .previous(attr) and .get(attr) return false
- that has the concequence that dates are always marked as "changed"
- internally we use our `hasDateChanged` if we have to compare previous/updated dates
- but Bookshelf is not in our control for this case
2017-04-19 10:59:09 +02:00
Hannah Wolfe
06fc5f4508 Autofill plaintext field on save (#8304)
refs #8275

- If the HTML field has changed, update the plaintext field
- Use html-to-text to generate a plaintext version of the HTML which retains some structure
- Add a couple of tests - although there's much to do here!
2017-04-11 10:55:36 +02:00
Katharina Irrgang
59a8911830 🐛 fix hasDateChanged (#8291)
no issue
- i don't know if this never worked or has worked and something changed in bookshelf
- but this fixes: saving the content (no change for published_at) of a scheduled post within the 2minutes window
- add `beforeWrite` option to hasDateChanged helper, see comment
- use previous for `beforeWrite` operations
- add a test and fix some other small issues in the scheduler tests
2017-04-06 17:49:59 +01:00
Ryan McCarvill
f61aa662c1 Removed ghost editor dependency (#8137)
refs #7429
- ☢️ 👷🏻‍♀️ This PR removes the dependency on Ghost-Editor and replaces it with the Mobiledoc DOM renderer. It includes new DOM based default cards and atoms.
2017-03-14 18:07:33 +00:00
Katharina Irrgang
2d19ae2c6c 🔥 😎 remove old migrations (#7887)
refs #7489

- remove old migration code
- this logic was sourced out to knex-migrator
2017-01-25 13:47:49 +00:00
Marc Bachmann
353330bb8a chore(package): update uuid to version 3.0.0 (#7742) 2017-01-04 17:10:29 +01:00
Katharina Irrgang
7eb316b786 replace auto increment id's by object id (#7495)
* 🛠  bookshelf tarball, bson-objectid

* 🎨  schema changes

- change increment type to string
- add a default fallback for string length 191 (to avoid adding this logic to every single column which uses an ID)
- remove uuid, because ID now represents a global resource identifier
- keep uuid for post, because we are using this as preview id
- keep uuid for clients for now - we are using this param for Ghost-Auth

*   base model: generate ObjectId on creating event

- each new resource get's a auto generate ObjectId
- this logic won't work for attached models, this commit comes later

* 🎨  centralised attach method

When attaching models there are two things important two know

1. To be able to attach an ObjectId, we need to register the `onCreating` event the fetched model!This is caused by the Bookshelf design in general. On this target model we are attaching the new model.
2. We need to manually fetch the target model, because Bookshelf has a weird behaviour (which is known as a bug, see see https://github.com/tgriesser/bookshelf/issues/629). The most important property when attaching a model is `parentFk`, which is the foreign key. This can be null when fetching the model with the option `withRelated`. To ensure quality and consistency, the custom attach wrapper always fetches the target model manual. By fetching the target model (again) is a little performance decrease, but it also has advantages: we can register the event, and directly unregister the event again. So very clean code.

Important: please only use the custom attach wrapper in the future.

* 🎨  token model had overriden the onCreating function because of the created_at field

- we need to ensure that the base onCreating hook get's triggered for ALL models
- if not, they don't get an ObjectId assigned
- in this case: be smart and check if the target model has a created_at field

* 🎨  we don't have a uuid field anymore, remove the usages

- no default uuid creation in models
- i am pretty sure we have some more definitions in our tests (for example in the export json files), but that is too much work to delete them all

* 🎨  do not parse ID to Number

- we had various occurances of parsing all ID's to numbers
- we don't need this behaviour anymore
- ID is string
- i will adapt the ID validation in the next commit

* 🎨  change ID regex for validation

- we only allow: ID as ObjectId, ID as 1 and ID as me
- we need to keep ID 1, because our whole software relies on ID 1 (permissions etc)

* 🎨  owner fixture

- roles: [4] does not work anymore
- 4 means -> static id 4
- this worked in an auto increment system (not even in a system with distributed writes)
- with ObjectId we generate each ID automatically (for static and dynamic resources)
- it is possible to define all id's for static resources still, but that means we need to know which ID is already used and for consistency we have to define ObjectId's for these static resources
- so no static id's anymore, except of: id 1 for owner and id 0 for external usage (because this is required from our permission system)
- NOTE: please read through the comment in the user model


* 🎨  tests: DataGenerator and test utils

First of all: we need to ensure using ObjectId's in the tests. When don't, we can't ensure that ObjectId's work properly.
This commit brings lot's of dynamic into all the static defined id's.
In one of the next commits, i will adapt all the tests.

* 🚨  remove counter in Notification API

- no need to add a counter
- we simply generate ObjectId's (they are auto incremental as well)
- our id validator does only allow ObjectId as id,1 and me

* 🎨  extend contextUser in Base Model

- remove isNumber check, because id's are no longer numbers, except of id 0/1
- use existing isExternalUser
- support id 0/1 as string or number

*   Ghost Owner has id 1

- ensure we define this id in the fixtures.json
- doesn't matter if number or string

* 🎨  functional tests adaptions

- use dynamic id's

* 🎨  fix unit tests

* 🎨  integration tests adaptions

* 🎨  change importer utils

- all our export examples (test/fixtures/exports) contain id's as numbers
- fact: but we ignore them anyway when inserting into the database, see https://github.com/TryGhost/Ghost/blob/master/core/server/data/import/utils.js#L249
- in 0e6ed957cd (diff-70f514a06347c048648be464819503c4L67) i removed parsing id's to integers
- i realised that this ^ check just existed, because the userIdToMap was an object key and object keys are always strings!
- i think this logic is a little bit complicated, but i don't want to refactor this now
- this commit ensures when trying to find the user, the id comparison works again
- i've added more documentation to understand this logic ;)
- plus i renamed an attribute to improve readability

* 🎨  Data-Generator: add more defaults to createUser

- if i use the function DataGenerator.forKnex.createUser i would like to get a full set of defaults

* 🎨  test utils: change/extend function set for functional tests

- functional tests work a bit different
- they boot Ghost and seed the database
- some functional tests have mis-used the test setup
- the test setup needs two sections: integration/unit and functional tests
- any functional test is allowed to either add more data or change data in the existing Ghost db
- but what it should not do is: add test fixtures like roles or users from our DataGenerator and cross fingers it will work
- this commit adds a clean method for functional tests to add extra users

* 🎨  functional tests adaptions

- use last commit to insert users for functional tests clean
- tidy up usage of testUtils.setup or testUtils.doAuth

* 🐛  test utils: reset database before init

- ensure we don't have any left data from other tests in the database when starting ghost

* 🐛  fix test (unrelated to this PR)

- fixes a random failure
- return statement was missing

* 🎨  make changes for invites
2016-11-17 09:09:11 +00:00
Katharina Irrgang
8cd5d9f6fe 🎨 register events in base model (#7560)
refs #7432

- all models implemented it's own initialize fn to register events
- we can register all events in the base model
- important: we only listen on the event, if the model has defined a hook for it
- this is just a small clean up PR
- register more bookshelf events
2016-10-14 13:37:01 +01:00
Ryan McCarvill
ff9e6b5393 Upgraded editor (#7516)
refs #7429

Finally it's starting to feel like a real editor, although there will be another version bump over the weekend which improves the toolbar behaviour and usability, and enables image uploading.

- Added the start of a new toolbar, what we're (well I am) calling the Owesome bar, not to be confused with the Firefox Awesome bar. It's a cultural thing. (google "O for awesome").
- The idea of dragging and dropping cards has been removed for now, although the code will still be in there as we will support dragging cards around fairly shortly. When apps are included a better card interface will be required for a larger amount of app created content cards (Oh yeah!)
- Ghost Server now pulls in it's configuration from Ghost-Editor, this allows Ghost-Editor to a) keep cards up to date, and b) define what happens if a card is missing.
- The whole cards in admin written in ember and cards in server written in javascript thing is still very much a work in progress, it's kind of messy as we find the optimum solution (which isn't the current sollution).

So yeah, this is a WIP not the final styling, not the final interactions, not the final anything... :)

Adds a new mobile doc editor which has:
- A new toolbar
- Basic image uploading capability
2016-10-10 07:09:32 +01:00
Katharina Irrgang
d81bc91bd2 Error creation (#7477)
refs #7116, refs #2001

- Changes the way Ghost errors are implemented to benefit from proper inheritance
- Moves all error definitions into a single file
- Changes the error constructor to take an options object, rather than needing the arguments to be passed in the correct order.
- Provides a wrapper so that any errors that haven't already been converted to GhostErrors get converted before they are displayed.

Summary of changes:

* 🐛  set NODE_ENV in config handler
*   add GhostError implementation (core/server/errors.js)
  - register all errors in one file
  - inheritance from GhostError
  - option pattern
* 🔥  remove all error files
*   wrap all errors into GhostError in case of HTTP
* 🎨  adaptions
  - option pattern for errors
  - use GhostError when needed
* 🎨  revert debug deletion and add TODO for error id's
2016-10-06 13:27:35 +01:00
Katharina Irrgang
1882278b5b 🎨 configurable logging with bunyan (#7431)
- 🛠  add bunyan and prettyjson, remove morgan

-   add logging module
  - GhostLogger class that handles setup of bunyan
  - PrettyStream for stdout

-   config for logging
  - @TODO: testing level fatal?

-   log each request via GhostLogger (express middleware)
  - @TODO: add errors to output

- 🔥  remove errors.updateActiveTheme
  - we can read the value from config

- 🔥  remove 15 helper functions in core/server/errors/index.js
  - all these functions get replaced by modules:
    1. logging
    2. error middleware handling for html/json
    3. error creation (which will be part of PR #7477)

-   add express error handler for html/json
  - one true error handler for express responses
  - contains still some TODO's, but they are not high priority for first implementation/integration
  - this middleware only takes responsibility of either rendering html responses or return json error responses

- 🎨  use new express error handler in middleware/index
  - 404 and 500 handling

- 🎨  return error instead of error message in permissions/index.js
  - the rule for error handling should be: if you call a unit, this unit should return a custom Ghost error

- 🎨  wrap serve static module
  - rule: if you call a module/unit, you should always wrap this error
  - it's always the same rule
  - so the caller never has to worry about what comes back
  - it's always a clear error instance
  - in this case: we return our notfounderror if serve static does not find the resource
  - this avoid having checks everywhere

- 🎨  replace usages of errors/index.js functions and adapt tests
  - use logging.error, logging.warn
  - make tests green
  - remove some usages of logging and throwing api errors -> because when a request is involved, logging happens automatically

- 🐛  return errorDetails to Ghost-Admin
  - errorDetails is used for Theme error handling

- 🎨  use 500er error for theme is missing error in theme-handler

- 🎨  extend file rotation to 1w
2016-10-04 16:33:43 +01:00
Ryan McCarvill
be666b1b1a Update Ghost Editor to 0.0.8 #7429 (#7474)
This release includes:

    Ghost Editor, this is required to get access to the built in cards

Ghost Editor includes:

    Responsive toolbars 🔨 🔧
    Both Ember and Plain javascript cards 🎴
    An embeded HTML card ✍️

This is still an early release, but things are moving in the right direction. :)

We're still defining the spec for the UI, so expect drastic changes over the next couple of weeks.

This is going to be a great writing experience and we can't wait to show what we have planned.
2016-10-03 15:42:34 +01:00
Ryan McCarvill
7edc518d5a [WIP] Mobile-Doc based renderer (#7437)
Refs #7429

Added mobile-doc renderer

------------

- Added generic mobiledoc-renderer
- Kept the existing showdown editor for legacy mode.
2016-09-26 15:23:49 +02:00
kirrg001
0ae0a0b490 🎨 change how we get and set config
refs #6982
- a replace for all config usages
- always use config.get or config.set
- this a pure replacement, no logic has changed

[ci skip]
2016-09-20 15:59:34 +01:00
Katharina Irrgang
c8119eee1f 🎨 source out url utils from ConfigManager (#7347)
refs #6982
2016-09-20 15:59:34 +01:00
Katharina Irrgang
9349e99e54 🐛 fix delete by author as transaction (#7145)
closes #7137

Deleting the content from the database runs in a transaction. see
https://github.com/TryGhost/Ghost/blob/master/core/server/api/users.js#L390

`destroyByAuthor` is one of the operations we trigger to delete all the conent, see https://github.com/TryGhost/Ghost/blob/master/core/server/models/post.js#L647

The post model has a specific hook for deleting content to delete the relations as well, see https://github.com/TryGhost/Ghost/blob/master/core/server/models/post.js#L122

This hook is part of the transaction. But the `options` are ignored. `(model/*, attr, options*/)` 
We use the `options` to forward the transaction reference, which we need to pass into the bookshelf queries. So `return model.load('tags').call('related', 'tags').call('detach')` does not forward the transaction and that's why it stucks when deleting the content.
2016-09-19 14:45:36 +01:00
Vijay Kandy
ffd3ec563a fix: "url" field is undefined when restricting returned fields (#7089)
closes #6625

- "url" and "author" fields depend on {id, published_at, slug, author_id} to construct post url.
- implemented a generic solution by defining defaultColumnsToFetch() in
  base class for models.
- findPage() calls defaultColumnsToFetch() before loading models
- results are transformed by filtering out additional properties to return just the requested fields
- Added a test case to check for url and author fields
- Renamed allColumns as requestedColumns and used _.map instead of Promise.map
2016-07-18 22:21:47 +02:00
Katharina Irrgang
416c215018 change default order of posts (#7096)
closes #6932
- new default order of posts: scheduled, draft, published
- invent orderDefaultRaw fn for each model
- each model is able to create a default raw order query
- separate count and fetch query for fetchPage, because the count query where group/order statements attached
2016-07-15 11:04:10 +01:00
kirrg001
f8ba12481d fix: prev next posts
closes #7015
2016-06-20 15:44:02 +02:00