Commit Graph

246 Commits

Author SHA1 Message Date
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
“kirrg001”
1421c92ba5 post-scheduling
refs #6413
- PUT endpoint to publish a post/page for the scheduler
- fn endpoint to get all scheduled posts (with from/to query params) for the scheduler
- hardcoded permission handling for scheduler client
- fix event bug: unscheduled
- basic structure for scheduling
- post scheduling basics
- offer easy option to change adapter
- integrate the default scheduler adapter
- update scheduled posts when blog TZ changes
- safety check before scheduler can publish a post (not allowed to publish in the future or past)
- add force flag to allow publishing in the past
- invalidate cache header for /schedules/posts/:id
2016-06-14 10:52:13 +02:00
Austin Burdine
44537bd15f deps: lodash@4.13.1
closes #6911
- update lodash to v4
- remove lodash.tostring override
- remove lodash from greenkeeper ignore
2016-06-11 13:13:55 -06:00
Hannah Wolfe
80a79172c4 Revert "Revert "Force UTC at process level"" 2016-06-03 09:06:18 +01:00
Hannah Wolfe
b2051dacf7 Fix post model deletes tags when editing post only
fixes #6919, refs #6917

- resolves the problem by guarding for `tags` being undefined or null
   - If it is undefined, we don't do any tag processing
   - If it is null, we don't do any tag processing
   - To delete all tags, you would provide `tags: []`
- adds tests at both the model (using withRelated) and API (using includes) layers
- moves the tests for the post updateTags functionality from the tag model spec to the post model spec & cleans up a bit
2016-06-02 22:52:34 +01:00
Hannah Wolfe
78e693f469 Revert "Force UTC at process level" 2016-06-02 14:38:02 +01:00
kirrg001
ec176c243a Force UTC at process level
issues #6406 #6399
- all dates are stored as UTC with this commit
- use moment.tz.setDefault('UTC')
- add migration file to recalculate local datetimes to UTC
- store all dates in same format into our three supported databases
- add option to remeber migrations inside settings (core)
- support DST offset for migration
- ensure we force UTC in test env
- run whole migration as transaction
- extend: Settings.findOne function
2016-06-02 13:23:09 +02:00
Katharina Irrgang
f644d99460 add small permission improvements
no issue
- do not check client type in auth middleware
- offer filtering for findAll function in base
- add isInternalContext to base model
2016-05-08 14:22:55 +02:00
Joerg Henning
0f3cb44227 deps: validator@5.1.0
closes #6462

- monkey-patch validator.extends() since it was dropped by validator @5.0.0
- coerce input to string prior to validation (custom toString func)
- need to handle boolean validation based on column type not isIn()
- use `lodash.tostring` to convert input values to strings
2016-04-19 09:39:12 +08:00
Katharina Irrgang
d24466a284 add events for post scheduling
refs #6413
- accept scheduled status
- add a lot of tests for all kinds of edge cases
- compare dates without ms because mysql does not store ms
2016-04-18 16:44:41 +02:00
Joerg Henning
4a3d8c7ae8 Remove sanitize() from model/base because clean code 2016-04-03 08:17:17 +08:00
Hannah Wolfe
48b846b13d Merge pull request #6631 from dbalders/draft-slug
Update Post Slug while Draft on Title Changes
2016-03-29 15:35:08 +01:00
David Balderston
81c215dbe5 Update Post Slug while Draft on Title Changes
Closes #5062

* As long as the post has never been published, update the slug to
match the new title if the title is changed
2016-03-23 10:20:22 -07:00
Jason Williams
136bdbd9ff Return http status 204 on deletes
Closes #2871
- Refactor api http handlers.
- Update tests.
- Remove special handling of responses in ember adapter.
2016-03-22 11:42:48 -05:00
Jason Williams
9fe573a0c5 Refactor content deletion
- Simplify the `init` method in `models/index.js` so that it no longer
  returns a promise. Easier to use.
- Eliminates the `deleteAllContent` method from `models/index.js` as it
  can all be handled at the API layer in a single spot.
- Optimize `destroyAllContent` in `api/db.js`. Eliminates
  double-fetching every post from the database and converting it to
  JSON. Also only fetches ids from the database instead of the entire
  model.
- Eliminates the custom static method `destroy` in the Post model in
  favor of handling detaching tag relations in a single place (the
  `destroying` event). This also eliminates a big source of unneeded
  database round trips--needing to get post ids to feed into
  `Post.destroy()` which then re-fetches the post again.
2016-03-22 10:10:09 -05:00
rfpe
7abcc43907 Harvest server side strings
closes #5617
- Replace all hard-coded server-side strings with i18n translations
2015-12-19 12:12:16 +01:00
Hannah Wolfe
e84b7f3217 Cache permalinks & postsPerPage on config.theme
no issue

- Cache the permalinks & postsPerPage settings on the config.theme object
- Use the config.theme cache to reference these items throughout the frontend of a blog
- Removes the need for workarounds and extra code to handle async fetches
- Makes these values accessible to all themes, which is very useful now we have the API stuff
2015-12-15 08:16:53 +00:00
Hannah Wolfe
6a0f1cf231 Filter plugin with enforce/default logic
refs #5614, #5943

- adds a new 'filter' bookshelf plugin which extends the model
- the filter plugin provides handling for merging/combining various filters (enforced, defaults and custom/user-provided)
- the filter plugin also handles the calls to gql
- post processing is also moved to the plugin, to be further refactored/removed in future
- adds tests showing how filter could be abused prior to this commit
2015-11-17 10:39:44 +00:00
Hannah Wolfe
4dac01cbf9 Refactor old processOptions/where to use GQL JSON
refs #5943

- no longer assume the options in processOptions are set
- set where to a new GQL JSON-like statement object
- rather than setting options, add statements which can be understood by knexify
- pass the statements through knexify to build the query
2015-11-12 17:24:09 +00:00
Hannah Wolfe
b8bab0e74c Removing featured option code
ref #5943

- found some more code that can be removed
2015-11-09 12:15:40 +00:00
vdemedes
6db41584e7 Add order parameter
refs #5602
- add "order" to default browse options
- parse order parameter in Base model
- accept "order" option in Post, User and Tag models
- add tests for posts order
- add tests for tags order
- add tests for users order
2015-10-28 14:14:03 +01:00
Sebastian Gierlinger
9dc4efca13 Merge pull request #6005 from ErisDS/old-filter-clean
Remove featured, tag, author & role API params
2015-10-27 13:05:12 +01:00
vdemedes
0a0aaf01b2 Replace missing title with "(Untitled)" when creating a post
closes #6014
- replace missing title with "(Untitled)" when creating a post
- add a test for creating post without title
2015-10-27 12:15:09 +01:00
Hannah Wolfe
b8a3415726 Remove featured, tag, author & role API params
refs #5943

- removed featured, tag and author parameters from posts API
   - featured was only used in tests
- removed role filter from users API
   - role was only used in tests
- fixed up the tests, skipping those that don't quite work yet
2015-10-27 10:53:51 +00:00
Hannah Wolfe
b5cebb9ec6 Add filter parameter using GQL
refs #5604, refs #5463

- deps: ghost-gql@0.0.2
- adds code to wire up the filtering to a paginated query
- updated pagination plugin count query to use 'distinct' so it's more robust
- rename paginationUtils.query to addLimitAndOffset to be more explicit and make the code clearer
- add a new 'advanced browsing spec' set of tests for tracking these features as they are built out
2015-10-22 11:29:05 +01:00
Oliver Schneider
13adaec6e7 fix for page deletion not updating sitemap-page.xml
closes #5913

Sitemap deletion is based on the page.unpublished event. The previous
logic was always sending post.unpublished instead. If page or post
event is triggered is based on the ‘page’ attribute of the model. When
the destroyed handler all attributes are already cleared from the model
which makes this logic always fall back to post.

The fix is to move to the destroying event which still has all the
model values in place.
2015-10-12 09:26:26 +02:00
Delgermurun
a501711e71 Remove findAll from models that has findPage
closes #4577
- removed findAll from Post and User
- refactored deleteAllContent and data importer
2015-10-02 18:01:35 +08:00
Hannah Wolfe
0462607296 Don't allow published_by override
- published_by should be set by business logic, rather than by users

Credits: An anonymous researcher working with Beyond Security's SecuriTeam Secure Disclosure program
2015-09-25 17:44:49 +01:00
cobbspur
c0b5de6e81 Fix handling of slugs on import
closes Issue #5812

- pass importing property through to utils
- fix safeString method for imports
2015-09-23 17:41:44 +01:00
Hannah Wolfe
a3f107da8e Maintain tag order for posts
refs #5727, #5602

- Add new 'order' column to posts_tags table
- Migrate all existing posts_tags to have a correct value for 'order'
- Rewrite updateTags to not remove all tags, and to correctly maintain order
- Add transaction support for tag operations
- Many tests
2015-09-02 16:39:34 +01:00
Hannah Wolfe
e9a96816ac Adding 'fields' param for browse requests
refs #5601, #5463, #5343

- adds rudimentary support for a 'fields' parameter on browse requests
2015-08-28 19:08:22 +01:00
Hannah Wolfe
16407b41ee Merge pull request #5655 from sebgie/extract-permissions
Refactor handlePermissions
2015-08-11 19:32:20 +01:00
Sebastian Gierlinger
44622d943d Refactor handlePermissions
no issue
- extract handlePermissions to utils
- added NoPermissionError when canThis() rejects
- omitted users.js because it uses special permission handling
2015-08-11 16:03:57 +02:00
Hannah Wolfe
a00eace849 Next/Prev Post helpers include author & tags
closes #5150

- Post API understands next.author, next.tags, previous.author and previous.tags
- Post Read request filters out those properties and does the right thing with them
- Prev/Next post helpers send extra include properties
- Tests updated
2015-08-10 08:58:25 +01:00
cobbspur
870d6af066 Fix API query for featured posts
No Issue

- fixes bug where featured: false was not being built into query
- adds tests
2015-07-29 02:42:08 +01:00
Hannah Wolfe
a0ee69d365 Merge pull request #5591 from halfdan/fix/5573
Do not serialize toJSON to get published_at
2015-07-21 16:54:24 +01:00
Fabian Becker
ed0854d770 Do not serialize toJSON to get published_at 2015-07-21 00:38:55 +02:00
Fabian Becker
4500b14989 Use previousAttributes when model is destroyed
fixes #5589
2015-07-20 14:41:40 +02:00
Sebastian Gierlinger
64e20735a3 Merge pull request #5491 from ErisDS/issue-5490-no-post-url
Add event handling to pagination plugin
2015-06-29 11:44:22 +02:00
Hannah Wolfe
4772e38521 Add event handling to pagination plugin
closes #5490

- use same event handling pattern as fetchAll
- add support for `fetching:collection` to post model
- add tests to check that url is fetched via findAll and findPage
2015-06-26 22:56:03 +01:00
Hannah Wolfe
f6322da4c9 Use extends correctly & consistently
- extends clobbers the first argument you pass to it, so that should not be a variable that is used elsewhere, if you're also assigning the value, as it will have unintended side effects.
2015-06-25 19:56:27 +01:00
Hannah Wolfe
7705e30995 Use 'author' for relation instead of 'author_id'
- this clears a todo in the codebase & gets rid of a few lines of unnecessary code
2015-06-24 10:00:24 +01:00
Hannah Wolfe
7761873db7 Abstract findPage & add pagination Bookshelf plugin
closes #2896

- move default options / custom code into model functions
- move most of the filtering logic into base/utils.filtering (to be relocated)
- move the remainder of findPage back into base/index.js and remove from posts/users&tags
- move pagination-specific logic to a separate 'plugin' file
- pagination provides new fetchPage function, similar to fetchAll but handling pagination
- findPage model method uses fetchPage
- plugin is fully unit-tested and documented
2015-06-22 10:20:47 +01:00
Hannah Wolfe
4cd2865021 Refactor pagination count query
refs #2896

- remove duplicate query-building code
- use the same approach for creating the count query from the main query
- restructure the code to match more closely across the 3 findPage functions (prep for further refactoring)
2015-06-15 19:24:47 +01:00
Hannah Wolfe
16f98ee80b Move pagination formatting into a util
refs #2896

- moves repeated code out of models
- creates a new file for unit-testable code (this should be moved in future)
- adds a default for `page` as that seems sensible
- adds 100% test coverage for the new file
2015-06-15 16:46:42 +01:00
Hannah Wolfe
177cdf1eb1 Misc cleanup: moving files & naming functions 2015-06-15 09:43:19 +01:00
Adrian Estrada
107c9602c1 API: Adding featured filter option to posts.browse
Closes #5152
- Adds `featured` filter option to posts.browse method modifying the model to take it too
2015-05-13 16:18:50 -05:00
Hannah Wolfe
e26e83d40a Refactor to remove author.email from API
refs #2330

- Pass through `options` to all toJSON calls on posts, tags, and users
- Use options.context.user to determine whether it's OK to return user.email
- Remove author.email handling code from frontend.js
2015-04-17 22:27:04 +01:00
Hannah Wolfe
196bbfce18 Refactor sitemaps to use centralised events
fixes #5104, refs #4348, #2263

- Create a centralised event module
- Hook it up for posts, pages, tags and users
- Use it in sitemaps instead of direct method calls
- Use it for xmlrpc calls
- Check events are fired in model tests
- Update sitemap tests to work with new code
- Fix a bug where invited users were appearing in sitemaps
- Move sitemaps and xmlrpc into a directory together
2015-04-05 19:32:18 +01:00
Hannah Wolfe
1db59e12ee Move showdown extensions to ghost-showdown
no issue

- We already maintain our own fork of showdown, this moves our custom extensions to our fork
- Code duplication is removed
- Tests are also moved to the other repo
2015-03-17 20:18:08 +00:00
Hannah Wolfe
0e80d77100 Only import can override published_by
no issue

- published_by should be set to the current user, unless we are in import mode

Credits: Matteo Beccaro
2015-02-28 16:27:30 +00:00
Eugene Kulabuhov
0e2709c42f [API] Retrieve next and previous post
closes #4262
- implementation based on #1545
- added integration test. Modified mocked posts because code requires published_at timestamps to be different.
- fixed 2 broken tests that depended on mocked posts to have "new Date()" as their timestamps
- added checks to only query db if next/previous post requested
2015-01-13 12:49:16 +00:00
Jason Williams
633cf1385a Run tag add operations in sequence
Closes #4697
- Run tag add operations in sequence instead of in parallel
  since generateSlug will hand out duplicate slugs until one of
  them is committed to the database.
- Add test.
- Misc cleanup of method parameter names and jshint hints.
2014-12-22 00:41:10 +00:00
Hannah Wolfe
6af0b83b7c Merge pull request #4670 from jaswilli/model-opt
Optimize model class methods
2014-12-19 21:19:01 +00:00
Jason Williams
5c6d45f258 Optimize model class methods
No Issue
- Reorder promise chains to defer database queries until they
  are needed.
- Execute database queries that are not dependent on each other in
  parallel instead of sequentially.
- Reduce the number of variables used to hold state across multiple
  promise blocks.
- Do not go async unless necessary.
2014-12-19 00:54:22 +00:00
Delgermurun
afdb3a948d Add 'id' to post sort fields. So there is no longer equally sorted posts.
closes #4648
- Add id to order by fields on posts API
- Order by id on posts controller
2014-12-18 11:34:26 +08:00
cobbspur
cd5d87ddf2 Return computed url with post object
closes #4445

- post model gets permalink format
- post model queries urlPathForPost to return computed url
- url helper modified to use post url
- urlForPost method abolished and replaced where necessary
- updated tests
2014-12-10 17:23:02 +00:00
Sebastian Gierlinger
0b2541b19f Merge pull request #4575 from ErisDS/highlight
Adds markdown highlight support
2014-12-04 15:00:01 +01:00
Hannah Wolfe
9783f16e76 Adds markdown highlight support
closes #4574

- adds highlight showdown extension with tests
2014-12-04 13:37:29 +00:00
Sebastian Gierlinger
319887c77b Merge pull request #4573 from ErisDS/limit-all-sitemaps
Add limit=all consistently to users, posts & tags
2014-12-04 09:45:33 +01:00
Hannah Wolfe
9b146e59bb Add limit=all consistently to users, posts & tags
refs #623, #4348

- this fixes sitemaps to list all posts, pages, tags and users
- makes the API behave consistently across all paginated resources
2014-12-03 18:46:26 +00:00
Hannah Wolfe
13757041d9 Merge pull request #4270 from mispy/footnotes2
Footnotes extension for Showdown
2014-12-03 13:38:47 +00:00
Sebastian Gierlinger
9b8141bb08 Merge pull request #4530 from ErisDS/issue-4498
API - no more m-2-m relation ids by default
2014-12-02 20:49:47 +01:00
Hannah Wolfe
4cb909542a API - no more m-2-m relation ids by default
closes #4498

- remove toJSON code which returns only IDs from objects
- don't auto-include tags & fields in post responses
- don't auto-include roles in user responses
- fix #allthethings that made assumptions about the auto-includes, or otherwise were only working because of the auto-include
2014-12-02 19:24:44 +00:00
Jacob Gable
2cfa18475a Generate sitemap files
Closes #623

- Add basic init and eventing scaffold
- Add sitemap-index.xml generation
- Broke out generators to individual files, added request handler
- Add page, author and tag xml files; add index mapping
- Add SiteMapManager unit tests
- Add Generators tests
- Cache invalidation headers for sitemap-*.xml
- Redirect sitemap.xml to index and rename to sitemap-index
- Handle page convert and publish/draft changes
- Add very basic functional test for route existence
- Add cache headers to sitemap routes
2014-11-30 10:49:45 -08:00