Commit Graph

695 Commits

Author SHA1 Message Date
Aileen Nowak
23f59c341c Replaced routeKeywords in config with hard coded keywords (#9561)
no issue
- removed the `routeKeywords` property from the config and used hard coded keywords.
- removed `routeKeywords` from public configuration API endpoint, as it's no longer used in the Admin.
2018-04-17 10:36:05 +01:00
kirrg001
d209a4d013 🐛 Fixed importer bug: can't resolve authors relation
closes #9547

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

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

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

e.g. 1500 posts

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

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

### key notes

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

- updated the schema type to 'WebSite' as it is the correct spelling according to schema.org. See [here](http://schema.org/WebSite)
2018-03-23 10:50:28 +07:00
Mante Bridts
7ed822cc0c 🐛Fixed i18n for the {{meta_title}} helper (#9468)
closes #9466

- make 'page' in the meta title translatable through subexpression in the meta title helper
- e.g. `{{meta_title page=(t....)}}`
2018-03-19 09:48:07 +01:00
kirrg001
68d8154d4f Imported nested tags by foreign key
no issue

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

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

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

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

* added fixtures for contributor role
* update post api tests to prevent contributor publishing post
* update permissible function in role/user model
* fix additional author code in invites
* update contributor role migration for knex-migrator v3
* fix paths in contrib migration
* ensure contributors can't edit or delete published posts, fix routing tests [ci skip]
* update db fixtures hash
* strip tags from post if contributor
* cleanup post permissible function
* excludedAttrs to ignore tag updates for now (might be removed later)
* ensure contributors can't edit another's post
* migration script for 1.21
2018-02-07 10:46:22 +01:00
kirrg001
39ee95cc07 Make use of ES6 arrow functions in our data importer
no issue

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

- Updated our privacy document
- Updated docs.ghost.org for privacy config behaviour
- contains a migration script to remove old settings keys
2018-01-09 15:20:00 +01:00
kirrg001
eb0a11d53a Fixed import test: post duplication detection within a file to import
no issue

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

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

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

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

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

- do not run import with `Promise.all`
- with a large import file, we run an enormous amount of queries in parallel, which does not allow Node to cleanup memory
- tested with an 13mb import file
- requires bookshelf-relations 0.1.4
2018-01-02 23:21:45 +01:00
kirrg001
64626dedd1 Moved social utility to lib/social
refs #9178

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

- i am not super happy about `const imageLib = require('../lib/image')`
- i don't really like the name `imageLib`
- but i had no better idea 😃
- if we use the same name in the whole project, it's very easy to rename the folder or the variable
2017-12-14 20:46:53 +01:00
kirrg001
bb06a8426d Moved tokens, url safe and safe string utility to lib/security
refs #9178

- we could now also move any crypto usages to lib/security, but no priority
- the main goal is to tidy up our utils folder
2017-12-14 13:38:00 +01:00
kirrg001
4fe7c9d7fc Moved validateRedirects helper to data/validation
refs #9178
2017-12-14 11:55:10 +01:00
Katharina Irrgang
192ebb1739
Moved labs, auth, permissions, settings, mail, themes to services (#9339)
refs #9178

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

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

- we are modifying the global validator dependency, which is bad
- see https://github.com/chriso/validator.js/issues/525#issuecomment-213149570
- we should create our own class and expose a singleton for the whole Ghost project
2017-12-14 01:15:12 +01:00
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
485c264c69 Use Promise support which was added in fs-extra 3.x
no issue

- now that we use bluebird globally, we can use the promise support from fs-extra
2017-12-13 20:57:11 +01:00
kirrg001
d83f474ff8 Always require fs-extra - consistency change
no issue
2017-12-13 20:57:11 +01:00
Katharina Irrgang
397400b4f8
Moved visibility utility to static model fn (#9327)
refs #9178

- this logic belongs to a static model helper
- the visibility property is a model property, the knowledge about the visibility values belongs to the model
- rename the functions, so they make more sense
2017-12-13 13:19:51 +01:00
kirrg001
2c2d1e93cc Fixed wrong require path in webhook-permissions
no issue

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

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

- we have to take care that we don't end up in circular dependencies
  - e.g. API requires UrlService and UrlService needs to require the API (for requesting data)
- update the references
- we would like to get rid of the utils folder, this is/was the most complicated change
2017-12-11 20:05:33 +01:00
Katharina Irrgang
0bb81bb3c4
Bump knex-migrator to version 3.1.1 (#9199)
no issue

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

**For development only: Please ensure you run `npm i -g knex-migrator@latest` to update your global installation to v3. We always prefer the local installation, but v3 has modified and added binaries.**
2017-12-05 09:14:55 +01:00
Guillem Andreu
860b38a1a7 🐛 Fixed Sitemap when permalink contains Primary Tag (#9273)
closes #9272

- included tags in sitemap post-generator
2017-11-27 12:38:56 +01:00
Kevin Ansfield
bffb3dbd90
Webhooks support for subscriber events (#9230)
no issue

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

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

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

- add `webhooks` table to store event names and target urls
- add `POST` and `DELETE` endpoints for `/webhooks/`
- configure `subscribers.added` and `subscribers.deleted` events to trigger registered webhooks
2017-11-21 15:43:14 +00:00
Aileen Nowak
1bb9d4ff00 Set soft limits for blog title and description (#9250)
refs #8143

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

The `validateSettings` fn in our validations checks for existing `validations` properties in our `default-settings.json` file, similar to other tables in our `schema.js`.
2017-11-16 13:58:22 +01:00
John O'Nolan
0d54326121 Give default Ghost user fixture a helpful bio (#9241)
no issue

Had a couple of people ask about how to delete welcome posts easily, so adding a bio to the default user to draw a little more attention to it
2017-11-14 10:23:38 +00:00
Aileen Nowak
a35c0c29e0 Added more database soft limits (#9225)
refs #8143

Sets soft limits for certain db fields:

- `posts`:
	- `title`: 255 chars (current hard limit: 2,000 chars)
	- `meta_title`: 300 chars (current hard limit: 2,000 chars)
	- `meta_description`: 500 chars (current hard limit: 2,000 chars)
- `users`:
	- `bio`: 200 chars (current hard limit: 65,535 chars)
	- `location`: 150 chars (current hard limit: 65,535 chars)
	- `meta_description`: 500 chars (current hard limit: 2,000 chars)
	- `meta_title`: 300 chars (current hard limit: 2,000 chars)
- `tags`:
	- `description`: 500 chars (current hard limit: 65,535 chars)
	- `meta_title`: 300 chars (current hard limit: 2,000 chars)
	- `meta_description`: 500 chars (current hard limit: 2,000 chars)

- same error message for isLength validator as for hard limits (more improvements are comming with https://github.com/TryGhost/Ghost/issues/6050)
- added more tests for importer
- added dynamic translation key handling for validators errors (isLength is only supported atm)
2017-11-09 15:22:20 +01:00
Hannah Wolfe
86c6cec433 Moved RSS module -> services & controllers
refs #5091, #9192, #9178

- Get the RSS module into a much better shape
- Controller -> /controllers/rss
- Remainder -> /services/rss
- Moved tests to match & updated requires
2017-11-08 08:09:44 +00:00
Hannah Wolfe
60fd98679f
Split RSS module into controller + other (#9224)
refs #5091, refs #9192

- This is similar to #9218, in that I'm revealing bits of code that are "controllers" in our codebase. As opposed to routes, services, renderers etc.
- This also reveals some code which is identical to the channels controller
- There is more to do here, but for now I've got the module split up, and the tests split and improved.
- Next I'll split RSS into controller + service, DRY up the controller code, etc
2017-11-07 20:00:03 +00:00
rambii
341948966d 🐛 Fixed custom_excerpt not being used in RSS feeds (#9219)
closes #9210

* use `custom_excerpt` before `meta_description` in rss
2017-11-07 10:16:14 +00:00
Hannah Wolfe
bcf5a1bc34
Switch to Eslint (#9197)
refs #9178

* Add eslint deps, remove old lint deps
* Add eslint config, remove old lint configs
* Config for server and tests are different
* Tweaked rules to suit us
* Fix linting in codebase - lots of indent changes.
* Fix a real broken test
2017-11-01 13:44:54 +00:00
kirrg001
9d4ed8c61c Replaced extract-zip-fork by extract-zip
no issue

- we had to fork the original repository at one point, because of slow maintenance
- maintenance is back now
- https://github.com/maxogden/extract-zip/pull/52 was merged and released
2017-10-31 12:11:59 +01:00
Hannah Wolfe
b5228f5c43 Rename blog -> site
- We're going to be moving towards this naming convention more
- Doing this now makes it easier to name other things
2017-10-26 18:09:56 +01:00
Aileen Nowak
c8cbbc4eb6 Improved password validation rules (#9171)
refs #9150 

- Moves the password length fn from `models/user` to `data/validation` where the other validator functions live.
- Added password validation rules. Password rules added:
   - Disallow obviously bad passwords: '1234567890', 'qwertyuiop', 'asdfghjkl;' and 'asdfghjklm' for example
   - Disallow passwords that contain the words 'password' or 'ghost'
   - Disallow passwords that match the user's email address
   - Disallow passwords that match the blog domain or blog title
   - Disallow passwords that include 50% or more of the same characters: 'aaaaaaaaaa', '1111111111' and 'ababababab' for example.
- Password validation returns an `Object` now, that includes an `isValid` and `message` property to differentiate between the two error messages (password too short or password insecure).
- Use a catch predicate in `api/authentication` on `passwordReset`, so the correct `ValidationError` will be thrown during the password reset flow rather then an `UnauthorizedError`.
- When in setup flow, the blog title is not available yet from `settingsCache`. We therefore supply it from the received form data in the user model `setup` method to have it accessible for the validation.
2017-10-26 11:01:24 +01:00
Hannah Wolfe
e659766f55 Move xmlrpc & slack to services (#9179)
refs #9178

- Introduce the /services/ folder
- Move xmlrpc there
- Move slack there
- In slack: remove a usage of the settings API that should use settingsCache
- In slack: Simplify the tests 
- Various tiny changes to move towards code consistency
2017-10-25 15:27:56 +01:00
Hannah Wolfe
ac3feb96d6 🐛 Prevents xmlrpc pings happening on import (#9165)
closes #9164

- check options.importing on xmlrpc
- also don't ping if private
- cleanup slack to work the same way
- update tests
- TODO: we need to prevent this event happening altogether
2017-10-23 18:30:33 +01:00
Aileen Nowak
d4b6390fd6 Improved importer logic for password in users (#9161)
refs #9150

- move data manipulation for importing users from `importers/data/users` to `model/user` for more consistency (see behaviour of post imports)
- changed importing logic in `onSaving` fn for user model:
   - when importing, we set the password to a random uid and don't validate, just hash it and lock the user
   - when importing with `importPersistUser` we check if the password is a bcrypt hash already and fall back to normal behaviour if not (set random password, lock user, and hash password)
   - don't run validations when importing
2017-10-19 10:43:52 +01:00
Katharina Irrgang
594b0c2d14 Custom post templates (#9073)
closes #9060

- Update `gscan` - it now extracts custom templates and exposes them to Ghost
- Add `custom_template` field to post schema w/ 1.13 migration
- Return `templates` array for the active theme in `/themes/` requests
- Users with Author/Editor roles can now request `/themes/`
- Front-end will render `custom_template` for posts if it exists, template priority is now:
  1. `post/page-{{slug}}.hbs`
  2. `{{custom_template}}.hbs`
  3. `post/page.hbs`
2017-10-10 13:36:35 +01:00
Hannah Wolfe
2941932ebe Removed hardcoded url structures from RSS (#9113)
refs #5091

- This removes hardcoded config to generate feed urls
- This means that RSS feeds work properly for custom channels
- Remaining assumption is that paginated feeds will end /pageNum/
- Added extra tests
- Don't pass through query params
2017-10-09 16:08:53 +02:00
Aileen Nowak
19167c1af2 🐛 Fixed author helper not returning the correct url (#9102)
closes #9101

With 506a0c3e9e we don't expose the `status` field for author context anymore, which is used to determine the correct URL for the `{{url}}` helper in https://github.com/TryGhost/Ghost/blob/master/core/server/data/schema/checks.js#L13

This fix uses the field `profile_image` instead and adds a missing test for author context to the `{{url}}` helper test.
2017-10-05 13:50:55 +02:00
Katharina Irrgang
7800ed3d8b Private RSS feed (#9088)
refs #9001

When a blog is in private mode there is now an unguessable URL that allows access to the RSS feed for internal use, commenting systems, etc.

- add public hash for private blogging
  - auto generate on bootstrap if missing
  - global hash, we can re-use in the future
- update private blogging middleware to detect the private RSS URL and rewrite it so that the normal rss route/code is used for display
- if a normal `/rss/` route is accessed with a private session return a 404
2017-10-05 11:07:32 +01:00
kirrg001
41c9db30b5 Debug: MySQL logging hook
no issue
2017-10-04 10:05:35 +01:00
Katharina Irrgang
d943fc7cc9 Allow Upload/Download of redirects.json (#9029)
refs #9028

- add two new endpoints for uploading/downloading the redirects (file based)
- reload/re-register redirects on runtime
- migration for 1.9 to add permissions for redirects download/upload
2017-09-21 16:01:03 +01:00
kirrg001
f478e4f9c8 🎨 Enabled Unsplash by default
refs https://github.com/TryGhost/Ghost/issues/8859

There are four cases:

- unsplash setting is empty (default), admin can enable the app by default (hardcoded isActive:true)
- unsplash settings are set, unsplash is disabled, admin detects that app was disabled on purpose
- unsplash setting is set, unsplash is enabled and has a key, app is enabled, old key get's ignored and overridden on the next save
- unsplash setting is set, unsplash is enabled and has no key, app is enabled
2017-09-20 11:44:47 +01:00
Aileen Nowak
0ce24b48bd Moved published_at creation to fixtures/utils (#8595)
no issue

- follow-up from #8573
- bove the hack that creates published_at values from the migration fn to our fixture util
2017-09-19 12:54:01 +02:00
Hannah Wolfe
4237446277 Misc cleanup & consistency amends (#9002)
no issue

- Consistent naming for postLookup
   - makes it easier to search and inspect the various usages
- Cleanup unneeded code
- Make res.render calls more consistent
- add some consistency to the calls to res.render
- Remove ancient reference to dataProvider
- Let's call it models everywhere now...
- Use consistent formatting across the API
- we're no longer using alignment in vars
- Misc other consistency changes in API
- always refer to local utils as apiUtils
- logical grouping of requires - dependencies, utils, "lib common" etc
- use xAPI to refer to API endpoints, e.g. mailAPI, settingsAPI for clarity
2017-09-12 17:31:14 +02:00
Aileen Nowak
eef7932e94 Refactor: fetch image dimensions from local file storage (#8900)
refs #8868

- Removed image-size in blog logo fn for meta data and made it synchronous
- Renamed `image-size-from-url.js` to `image-size.js` (incl. the test)
- Added second fn `getImageSizeFromFilePath` that reads from local file storage
- Added guard in `getImageSizeFromUrl` that checks if the image should be on local file storage and uses the new fn then instead
- Added a fn `fetchDimensionsFromBuffer` that takes the file buffer and returns an `imageObject` with dimensions.
- Added a new utils.js in `adapters/storage` for getting the file storage path
2017-09-05 14:13:22 +02:00
Austin Burdine
a9e668a949 🐛 Fixed only save imported post ids if amp field is empty (#8967)
closes #8963

- if an LTS export is imported into a 1.0 blog, then the 1.0 blog is
exported and re-imported into another 1.0 blog, any post ids from the
lts import were getting clobbered. This only saves the post id if the
amp field does not already exist
- add failing test that passes w/change
2017-09-04 09:48:56 +02:00
Kevin Ansfield
f7ce8d0e79 Fix lint error 2017-08-22 14:06:36 +01:00
Kevin Ansfield
2928f649a0 Fix "add-backup-client" migration
no issue
- use correct parameters for `addFixturesForModel` method
2017-08-22 13:51:44 +01:00
David Wolfe
c3fcb3105f Add ghost-backup client to trigger export (#8911)
no issue
- adds a ghost-backup client
- adds a client authenticated endpoint to export blog for ghost-backup client only
- allows some additional overrides during import
- allows for an import by file to override locking a user and double hashing the password
2017-08-22 11:15:40 +01:00
Kevin Ansfield
d064eda229 Add configuration/private endpoint and settings for Unsplash (#8895)
refs #8859

- adds new `configuration/private` endpoint for exposing config that should not be accessible without authentication
- adds `unsplashAPI` to private config
- adds empty `unsplash` config to default settings
2017-08-15 15:59:16 +01:00
Hannah Wolfe
bd41dba35b 🦄 Channels: Stored config in res.locals not req (#8884)
refs #5091

- This tiny refactor opens the door for using channel config inside of helpers
- This means that ghost_head, and the next_post/prev_post helpers can be context aware
2017-08-14 10:21:24 +07:00
Aileen Nowak
cfbb7f6c6b Facebook and Twitter data per post feature (#8827)
closes #8334

- adds title, image and description to structured data to be rendered as open graph and twitter data.
- if meta title and description for a post exists already, the custom structured data will overwrite those for `og:` and `twitter:` data. `JSON-LD` (Schema.org`) is not affected and will stay the same.
- adds tests
- adds new og and twitter fields to schema incl. migration
2017-08-03 15:48:39 +04:00
Sam Wilskey
d73133d74b 🐛 Fixed keeping user inactive during user import (#8738)
closes #8651

- inactive users are suspended users or the owner user on blog setup
- added a check to see if user is inactive in import
- passes all tests
2017-08-03 13:21:37 +04:00
Katharina Irrgang
8f39d6cb5f Code Injection per Post feature (#8820)
no issue

- add 1.4 database migration to add two new fields to the database (use type text, because of max row size)
- handle global code injection vs. post code injection
- add tests
2017-08-02 13:38:19 +04:00
Katharina Irrgang
c9e3f8b180 🐛 Fix ghost update with migrations (#8810)
no issue

- if you backup your database and you are in the middle of a transaction, the transaction was not fully forwarded
- we were running into a pool error in knex
2017-08-01 17:27:13 +04:00
Kevin Ansfield
4da94a287f 📝 Correct typos in default welcome posts (#8807)
closes #8806
- `omellete` -> `omelette`
- `sleak` -> `sleek`
2017-08-01 13:04:08 +04:00
Katharina Irrgang
7845617607 Custom Post Excerpt Feature (#8792)
closes #8793

- 1.3 post excerpt migration
  - add 1.3 migration to add `excerpt` to post schema

NOTE:
    - knex-migrator relies on the package.json safe version
    - so right now Ghost is on 1.2
    - the migration script is for 1.3
    - if you pull down the PR (or if we merge this PR into master), you have to run `knex-migrator migrate --v 1.3 --force`
    - knex-migrator will tell you what you have todo

- Bump dependencies
  - knex-migrator@2.1.3
- Soft limit for custom_excerpt
- Extended {{excerpt}} to use custom excerpt
   - when a `custom_excerpt` field exists, the `{{excerpt}}` helper will output this and fall back to autogenerated excerpt if not.
- Refactored behaviour of (meta) description
   - html tag `<meta name="description" />` for posts, tags and author doesn't get rendered if not provided.
        - fallback for `author.bio` removed
        - fallback for `tag.description` removed
   - structured data and schema.org for `post` context takes the following order to render description fields:
        1. custom excerpt
        2. meta description
        3. automated excerpt (50 words)
    - updated and added tests to reflect the changes
2017-08-01 12:39:34 +04:00
Katharina Irrgang
b003a6c173 🐛 fix transfer ownership (#8784)
closes #8781

- when the ownership get's transferred, the id of the new owner is not '1' anymore
- we previously added a database rule, which signalises if the blog is setup or not, see 827aa15757 (diff-7a2fe80302d7d6bf67f97cdccef1f71fR542)
- this database rule is based on the owner id being '1', which is wrong when you transfer ownership
- we should keep in mind, that the owner id being '1' is only the default Ghost setup, but it can change
- blog is setup if the owner is locked
2017-07-31 13:37:37 +04:00
John O'Nolan
0b5de14900 🎨 Improved SEO meta titles for paginated archives (#8785)
closes #8575
2017-07-31 13:13:06 +04: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
John O'Nolan
4333604480 Fix fixture typo 2017-07-31 12:43:58 +04:00
Katharina Irrgang
3462f07f58 🎨 take the latest attached role when importing (#8765)
refs #8756

- there was a bug in one of the last LTS releases, which produced duplicated attached roles to users
- we want to prevent that on import and take the latest created based on the autoincrement id
2017-07-27 13:25:01 +04:00
John O'Nolan
0698be503a Site description fixture update (#8763)
No issue
2017-07-27 12:26:31 +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
Katharina Irrgang
5ff7574324 🐛 user was not imported, but the importer tries to correct the reference (#8722)
no issue

- this is usually an edge case, but i investigated because i thought that the importer is broken
- the importer logic is build like this:
   - it creates a transaction
   - this transactions runs through:
      - beforeImport
      - doImport
      - afterImport
   - afterImport corrects user references and if a user could not be imported, we have to protect that
       NOTE: we could create two transactions to be more correct, but building this had no priority because of edge cases only
             having two transactions would solve: you first add the data (error or success), then you correct the data
   - usually a user can be always imported (!), but there are a few edge cases (e.g. multiple roles attached)
2017-07-21 09:59:18 +01:00
Katharina Irrgang
59d7302da5 🐛 import invalid dates (#8712)
closes #8703, closes #8015

- add sanitize fn to importer
- check wether an imported date is a valid date
- if not, print a warning
2017-07-20 11:24:23 +01:00
Katharina Irrgang
90fc7a6c06 🐛 respect owner user id references when importing (#8693)
closes #8691 

There was a condition added when i've refactored the importer.

> if (models.User.isOwnerUser(obj[key])) {

This condition is absolutely wrong! If you import an owner user, this owner user get's imported as administrator. But the original owner user id reference must be updated as well, so that the reference points to the new administrator id ✌🏻
2017-07-20 11:11:56 +01:00
Katharina Irrgang
35f12273ee 🔥 remove beta mentioning's (#8673)
no issue

- preparation for rc.1
2017-07-11 14:05:55 +01:00
John O'Nolan
cb2f754472 Update welcome post fixture (#8672)
Closes #8620

Info about how to delete the default Ghost user and all of the welcome posts along with it
2017-07-10 20:38:03 +07:00
Hannah Wolfe
6a45ca2605 🐛 Honour labs defaults on import (#8667)
closes #8601

- This makes sure that when you do an import, you still get the LATEST
  default settings for labs. Even if you had a different value before.
- LTS -> 1.0 is an upgrade, and Public API should be on by default, even if you
  had deliberately turned it off before.
- Cheeky test added
2017-07-09 14:31:53 +02:00
Aileen Nowak
827aa15757 Add new fixture Ghost Author (#8638)
refs #8620

Adds a new Ghost Author user, which is the author of the new welcome blog posts. The user is set to active, so the author slug works (otherwise it would render a 404, when user is suspended). Furthermore, there's one little fix in the user model, which was checking only for `active` user to decide the signup or setup process for the UI. Adding one more conditional to check if the found active user is also the owner, prevents to get redirected to sign in.
2017-07-06 00:18:27 +02:00
Hannah Wolfe
2058127dc5 Enable Public API by default (#8600)
closes #8601 

- this doesn't take the feature out of beta, but does enable it by default
- no need to enable the public api in the test anymore
- because public api is enabled by default
2017-06-20 10:10:49 +07:00
David Wolfe
bc301463c7 Fix sitemap for author permalink (#8585)
refs #8494
- include author in postgenerator for sitemap
2017-06-15 18:25:18 +01:00
Aileen Nowak
57f8367cdf 🐛 Add published_at to post model fixtures (#8573)
closes #8562
- before we create our model fixtures, we assign a `published_at` property with a difference of 1 second for each blog post, so the `prev_post` and `next_post` helpers work correctly
2017-06-13 10:27:42 +01:00
Katharina Irrgang
f5ef8dbb52 📖 replace any support.ghost.org link (#8555)
refs #7421
2017-06-08 20:34:20 +01:00
Kevin Ansfield
f675a962cf 📖 new default post content (#8548)
closes #8542
- updates default post fixtures
- adds default logo and cover images to settings fixtures
- update tests due to coupling to dev/prod fixtures
2017-06-08 16:36:14 +01:00
David Wolfe
b081ae34b5 🎨 Support LTS imports (#8498)
refs #8141

- update importer for LTS fields
- optimise for LTS export fixtures
- add image/language test for LTS import
- ensure post image is mapped to feature_image
- create mobiledoc values from markdown and html
- if mobiledoc is null, use markdown or html to create a mobiledoc markdown card
- update import mapping to use locale
- defaultLang in settings now maps to default_locale
- language for post and user models now maps to locale
- posts are not always loaded in correct same order so we select the posts we want to validate
- ensure if mobiledoc field is not in export we can still import from markdown
- map last_login to last_seen
- for users the importer maps last_login to last_seen
- add warning for legacyActiveTheme
- for export with old activeTheme key provide a warning that theme is not installed
- add importer test for LTS user long email
- add a test for LTS export where email address could be longer than alpha
- fix for importer date tests on mysql
- use valueOf in moment to compare times stored in different formats
- ignore warnings for not found settings in import
- use a flag to ignore NotFound Entries for settings during import
2017-06-04 11:53:00 +02:00
kirrg001
78ac63d8ad 🎨 add cache control configurations into the default config
refs #7488

- cache control can be overridden if needed
2017-05-31 16:12:11 +01:00
Katharina Irrgang
18b71f32b1 🎨 rename language to locale and use en as default locale (#8490)
no issue
- this PR references indirecty to https://github.com/TryGhost/Ghost/pull/8437
- i would like to have the settings change already in place before we release the beta
- the i18n feature is able to change the locale of Ghost
- most i18n libraries use locale
- adding/changing settings doesn't require a migration file, but it can make the database a bit messy (because you can end up with default_locale and lang)
- furthermore we agreed that the default locale for Ghost should be simply `en`, not `en_US` or `en_GB`
2017-05-31 16:05:49 +01: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
John O'Nolan
476caa5c2f 🎨 Update fixtures: Ghost owner (#8460)
no issue

- use a better name for default user pre-setup
- make it clear that this email address is an example, not real
2017-05-29 19:25:19 +02:00
Katharina Irrgang
925d72198c 🐛 Ensure post tags sort order is correct when importing (#8481)
refs #6967, refs #5422

- imports posts tags by post id and sort order
- test: fix order problem (sqlite)
2017-05-23 19:12:08 +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
Aileen Nowak
1b965fab95 🎨 Move scheduling and storage in adapters/ (#8435)
no issue

Move `core/server/scheduling` to `core/server/adapters/scheduling` and
`core/server/storage` to `core/server/adapters/storage`
2017-05-15 12:52:01 +02:00
Kevin Ansfield
c71cf643e2 update default post to use a single markdown card (#8448)
no issue

- now that we've switched to using a SimpleMDE based editor in Ghost-Admin the default post needs to match the expected single-markdown-card format
2017-05-12 10:08:45 +02:00
Katharina Irrgang
4e2474a018 🎨 settings inconsistency (#8381)
no issue
- replace camelCase settings keys with underscore_case for consistency
- discussed here https://github.com/TryGhost/Ghost-Admin/pull/661#discussion_r112939982
2017-04-24 18:41:00 +01:00
Katharina Irrgang
76bd4fdef6 🙀 Image field naming & new img_url helper (#8364)
* 🙀  change database schema for images
    - rename user/post/tag images
    - contains all the required changes from the schema change

* Refactor helper/meta data
    - rename cover to cover_image
    - also rename default settings to match the pattern
    - rename image to profile_image for user
    - rename image to feature_image for tags/posts

* {{image}} >>> {{img_url}}
    - rename
    - change the functionality
    - attr is required
    - e.g. {{img_url feature_image}}

* gscan 1.0.0
    - update yarn.lock

* Update casper reference: 1.0-changes
    - see 5487b4da8d
2017-04-24 18:21:47 +01:00
Aileen Nowak
e19e91044d 🙇 Blog icon utils and publisher.logo for JSON-LD (#8297)
refs #8221, closes #7688, refs #7558

🙇  Improve meta data publisher logo behaviour
This is a follow-up PR for #8285.

Reasons: The code changes of #8285 caused error messages when falling back to the default `favicon.ico`, as the `image-size` tool doesn't support `ico` files.

This PR takes the logic to decide which logo needs to be listed in our schema into a new fn `blog_logo.js`. There we have now three decisions:
1. If we have a publication **logo**, we'll take that one
2. If we have no publication logo, but an **icon** we'll use this one.
3. If we have none of the above things, we fall back to our default `favicon.ico`

Additional, we're hard coding image dimensions for whenever the logo is an `.ico` file and built and extra decision to not call `image-size` when the dimension are already given.

I will create another follow-up PR, which checks the extension type for the file and offers it as a util.

🛠  Blog icon util

refs #7688

Serve functionality around the blog icon in its own util:
- getIconDimensions -> async function that takes the filepath of on ico file and returns its dimensions
- isIcoImageType -> returns true if file has `.ico` extension
- getIconType -> returns icon-type (`x-icon` or `png`)
- getIconUrl -> returns the absolut or relativ URL for the favicon: `[subdirectory or not]favicon.[ico or png]`

📖  Get .ico sizes for meta data & logo improvement

refs #7558
refs #8221

Use the new `blogIconUtil` in meta data to fetch the dimensions of `.ico` files.

Improvements for `publisher.logo`: We're now returning a hard-coded 'faked' image dimensions value to render an `imageObject` and prevent error our schema (Google structured data). As soon as an image (`.ico` or non-`.ico`) is too large, but - in case of non-`.ico` - a square format, be set the image-dimensions to 60px width and height. This reduces the chances of getting constantly error messages from Googles' webmaster tools.

- add getIconPath util
2017-04-11 18:32:06 +02:00
Katharina Irrgang
049b6d9874 add issued_by column to access token (#8284)
closes #6626

- see https://github.com/TryGhost/Ghost/issues/6626#issuecomment-291445977
- adding this column could make our lives easier in the future
2017-04-11 13:12:14 +01:00
Aileen Nowak
a3387adb99 🐝 Add image property to rss (#8289)
refs #7688

Adds an image property to our generated rss data, which links to the favicon (has to be `.png` reg. http://www.rssboard.org/rss-2-0-1#ltimagegtSubelementOfLtchannelgt).
2017-04-11 13:54:52 +02:00
Aileen Nowak
4ba5cc862a 🐛 Blog icon improvements (#8298)
refs #7688

- renders the correct `/favicon.ico` or `/favcicon.png` in `{{ghost_head}}`
- removes an regex issue in `serve-favicon`
2017-04-10 12:04:46 +01:00
Hannah Wolfe
a413d70313 Asset amends (#8294)
refs #8221

🔥 Remove ghost=true concept from asset url helper

 💯 Introduce CSS minification with cssnano
- add new grunt-cssnano dependency
- wire up grunt task to minify public/ghost.css

🎨 Rename minification config & hash params
- Change minifyInProduction -> hasMinFile
  - this means this asset should have a .min file available
- Change minifyAssets -> useMinFiles
  - this means that in this env we want to serve .min files if available

🎨 Update public/ghost.css to serve .min for prod
- add the new `hasMinFile` property

🎨 Move minified asset handling to asset_url util
- this logic should be in the util, not the asset helper
- updated tests

📖 Error handler always needs asset helper
- this removes the TODO and adds a more sensible comment
- we also need to update our theme documentation around error templates

🔥 Don't use asset helper in ghost head
- use getAssetUrl util instead!
- removed TODO

📖 Update proxy docs
🎨 Simplify asset helper & add tests
- this refactor is a step prior to moving this from metadata to being a url util
- needed to skip some new tests

🐛 Add missing handler for css file
2017-04-10 11:30:21 +02:00
Aileen Nowak
f0f3c2f2a7 👋🏼 Don't use ghosticon.jpg from admin assets (#8285)
refs #8221

Use our default `favicon.ico` instead of `ghosticon.jpg` which is served from the admins' assets.
Adds additionally fake image dimensions for our json-ld data to satisfy Google.
2017-04-07 14:07:47 +01:00
Aileen Nowak
83f084608f 💁🏻 Moveshared/ to server/public (#8273)
refs #8221

Instead of serving our shared assets from a `shared/` folder, we move the file, which are used server side to `server/public`.
Adds a new `config.paths` entry: `publicFilePath` and renames the middleware to serve the files to reflect the changes.
Adds `404-ghost.png` images to be used by the server side rendered default template `error.hbs`.
2017-04-07 13:21:41 +01:00
Katharina Irrgang
587ff6f026 🎨 change last_login to last_seen (#8259)
refs #8258

* 🎨  change last_login to last_seen

- rename the column
- a change in Ghost-Admin is required as well

* test utils: revert export examples

* revert line breaks
2017-04-05 20:45:55 +01:00
Hannah Wolfe
9b3c3943ef Add new plaintext field (#8276)
refs #8275

- this PR only adds the field for now, so we can merge this along with other DB changes
2017-04-05 21:28:13 +02:00
Hannah Wolfe
4b49f39e55 📖 Change the welcome to ghost fixture to be mobiledoc (#8277)
refs #8275

- this switches over the fixture to be mobiledoc based. Most of the content was to do with markdown so it has been replaced with placeholder text
- content will be replaced via #8275
2017-04-05 21:16:28 +02:00
Katharina Irrgang
817b8d09ca 😱 🎨 Refactor storage adapter (#8229)
refs #7687

There are four main changes in this PR:

we have outsourced the base storage adapter to npm, because for storage developers it's annoying to inherit from a script within Ghost
we hacked theme storage handling into the default local storage adapter - this was reverted, instead we have added a static theme storage here
use classes instead of prototyping
optimise the storage adapter in general - everything is explained in each commit

----

* rename local-file-store to LocalFileStorage

I would like to keep the name pattern i have used for scheduling.
If a file is a class, the file name reflects the class name.
We can discuss this, if concerns are raised.

* Transform LocalFileStorage to class and inherit from new base

- inherit from npm ghost-storage-base
- rewrite to class
- no further refactoring, happens later

* Rename core/test/unit/storage/local-file-store_spec.js -> core/test/unit/storage/LocalFileStorage_spec.js

* Fix wrong require in core/test/unit/storage/LocalFileStorage_spec.js

* remove base storage and test

- see https://github.com/kirrg001/Ghost-Storage-Base
- the test has moved to this repo as well

* Use npm ghost-storage-base in storage/index.js

* remove the concept of getStorage('themes')

This concept was added when we added themes as a feature.
Back then, we have changed the local storage adapter to support images and themes.
This has added some hacks into the local storage adapters.
We want to revert this change and add a simple static theme storage.

Will adapt the api/themes layer in the next commits.

* Revert LocalFileStorage

- revert serve
- revert delete

* add storagePath as property to LocalFileStorage

- define one property which holds the storage path
- could be considered to pass from outside, but found that not helpful, as other storage adapters do not need this property
- IMPORTANT: save has no longer a targetDir option, because this was used to pass the alternative theme storage path
- IMPORTANT: exists has now an alternative targetDir, this makes sense, because
  - you can either ask the storage exists('my-file') and it will look in the base storage path
  - or you pass a specific path where to look exists('my-file', /path/to/dir)

* LocalFileStorage: get rid of store pattern

- getUniqueFileName(THIS)
- this doesn't make sense, instances always have access to this by default

* Add static theme storage

- inherits from the local file storage, because they both operate on the file system
- IMPORTANT: added a TODO to consider a merge of themes/loader and themes/storage
- but will be definitely not part of this PR

* Use new static theme storage in api/themes

- storage functions are simplified!

* Add https://github.com/kirrg001/Ghost-Storage-Base as dependency

- tarball for now, as i am still testing
- will release if PR review get's accepted

* Adapt tests and jscs/jshint

* 🐛  fix storage.read in favicon utility

- wrong implementation of error handling

* 🎨  optimise error messages for custom storage adapter errors

* little renaming in the storage utlity

- purpose is to have access to the custom storage instance and to the custom storage class
- see next commit why

* optimise instanceof base storage

- instanceof is always tricky in javascript
- if multiple modules exist, it can happen that instanceof is false

* fix getTargetDir

- the importer uses the `targetDir` option to ensure that images land in the correct folder

* ghost-storage-base@0.0.1 package.json dependency
2017-04-05 15:10:34 +01:00
Hannah Wolfe
243b387063 Helper Proxy & single express-hbs instance (#8225)
refs #8126, #8221, #8223

 New 'Proxy' for all helper requires
- this is not currently enforced, but could be, much like apps
- the proxy object is HUGE
- changed date to use SafeString, this should have been there anyway
- use the proxy for all helpers, including those in apps 😁

 🎨 Single instance of hbs for theme + for errors
- we now have theme/engine instead of requiring express-hbs everywhere
- only error-handler still also requires express-hbs, this is so that we can render errors without extra crud
- TODO: remove the asset helper after #8126 IF it is not needed, or else remove the TODO

🎨 Cleanup visibility utils
🎨 Clean up the proxy a little bit
🚨 Unskip test as it now works!
🎨 Minor amends as per comments
2017-04-04 18:07:35 +02:00
Aileen Nowak
e06547ae78 Split css server templates (#8234)
closes #8126

* Remove default template dependency on client side CSS

See Issue #8126

Adds these files under /shared
- normalizer.css
- error.css
- extracted.css (for subscribers.css and private.css)

Also makes these files available as public static content

* Remove default template dependency on client CSS

closes #8126
needs e3acd3c

This is a replacement PR of #8217 (thanks @TienSFU25 for the whole work 🤗), because these changes are needed urgently and blocking other work.

Adds a new `ghost.css` file in `/core/shared/` to be used for server side template rendering (`error.hbs`, `subscribe.hbs` and `private.hbs`).
2017-04-04 10:06:38 +01:00
Hannah Wolfe
3416c05064 Posts per page as theme-config (#8149)
closes #8131

- Remove ppp from default-settings.json
- Remove ppp from meta (unused?\!)
-  Basic concept of theme config
- use theme config ppp setting
-  Make @config.posts_per_page helper available
- rather than @blog.posts_per_page, we now have @config.posts_per_page
- 🚨 Test updates
- Adding TODO note
2017-03-14 18:03:36 +01:00
Hannah Wolfe
b2f1d0559b Themes API activation permissions & validation (#8104)
refs #8093

 Add activate theme permission
- add permission to activate themes
- update tests
- also: update tests for invites
TODO: change how the active theme setting is updated to reduce extra permissions

 Move theme validation to gscan
- add a new gscan validation method and use it for upload
- update activate endpoint to do validation also using gscan
- change to using SettingsModel instead of API so that we don't call validation or permissions on the settings API
- remove validation from the settings model
- remove the old validation function
- add new invalid theme message to translations & remove a bunch of theme validation related unused keys

📖  Planned changes

🚨 Tests for theme activation API endpoint
🐛 Don't allow deleting the active theme

🚫 Prevent activeTheme being set via settings API
- We want to control how this happens in future.
- We still want to store the information in settings, via the model.
- We just don't want to be able to change this info via the settings edit endpoint

🐛  Fix warnings for uploads & add for activations
- warnings for uploads were broken in f8b498d
- fix the response + adds tests to cover that warnings are correctly returned
- add the same response to activations + more tests
- activations now return a single theme object - the theme that was activated + any warnings

🎨 Improve how we generate theme API responses
- remove the requirement to pass in the active theme!
- move this to a specialist function, away from the list

🎨 Do not load gscan on boot
2017-03-13 12:44:44 +01:00
Katharina Irrgang
27f17c973d 🎨 handle case: sync email after logout (#8097)
no issue

If the user changes the email in the remote auth service and executes a logout directly afterwards, the user would lock himself out of his blog, because the email sync happens once per hour right now.
For that case, we have to store the ghost auth id.
2017-03-08 14:31:22 +00:00
Katharina Irrgang
27e659a21e 🐛 export database read settings from database (#8103)
* 🐛  export database read settings from database

no issue

- the backup script uses the export database lib and is broken if knex-migrator is called via shell, the settings cache is not loaded
- i have changed the export database lib to read the settings key directly from the db

* use get('value')
2017-03-08 10:26:57 +00:00
Hannah Wolfe
a5ab2ffc13 🔥 🎨 No more updateSettingsCache (#8090)
no issue

🔥 Remove unnecessary cache update
🎨 simplify updateSettingsCache()
🎨 Simplify readSettingsResult
- although this is more code, it's now much clearer what happens in the two cases
🎨 Don't use readSettingResult for edit
🎨 Simplify updateSettingsCache further
🔥 Remove now unused readSettingsResult
🎨 Change populateDefault to return all
🎨 Move the findAll call out of updateSettingsCache
🔥 Remove updateSettingsCache!!
🎨 Restructure init & finish up settingsCache
- move initialisation into settingsCache.init AT LAST
- change settingCache to use cloneDeep, so that the object can't be modified outside of the functions
- add lots of docs to settings cache
🎨 Cleanup db api endpoints
🔥 Don't populate settings in migrations
2017-03-02 23:00:01 +01:00
Hannah Wolfe
690ff05588 🔥 🎨 Themes & settings misc cleanup (#8061)
no issue

🔥 remove unused loadThemes API method
🚨 Add tests for themes.readOne
🔥 Don't update settings cache for imports
- this isn't needed as of #8057
- settings.edit fires an event, that will result in the update happening automatically
🎨 Move validation to themes
- slowly collecting all theme-related code together
🔥 Reduce DEBUG output
- all this info is a bit tooooo much!
2017-02-27 23:30:49 +01:00
Hannah Wolfe
63723aa36a 🎨 Move settings cache & cleanup settings API (#8057)
closes #8037

🔥 Remove API-level default settings population
- This is a relic!
- We ALWAYS populate defaults on server start therefore this code could never run.
- This was a lot of complicated code that wasn't even needed!!

🎨 Move settings cache
- Move settings cache to be its own thing
- Update all references
- Adds TODOs for further cleanup

🎨 Create settings initialisation step
- Create new settings library, which will eventually house more code
- Unify the interface for initialising settings (will be more useful later)
- Reduce number of calls to updateSettingsCache
2017-02-27 16:53:04 +01:00
Hannah Wolfe
fe90cf2be2 Theme loading part 1 (#7989)
no issue

*  Add new server start & stop events
* 🔥 Get rid of unused availableApps concept
- when we need an API endpoint for a list of apps, we'll build one 😝
*  Move theme loading into a module
- move loading from API method to a module method and use as needed
- wire up read one vs read all as per LTS
- read one (the active theme) on boot, and read the rest after
- fudge validation - this isn't all that helpful
* Settings API tests need to preload themes
- this used to automatically happen as part of loading settings
- now we need to trigger this to happen specifically for this test
2017-02-22 00:26:19 +01:00
Hannah Wolfe
348e4c2a95 Miscellaneous code cleanup (#8031)
no issue

- 🔥 Remove duplicated file
- 💄 🐷  Cleanup double slashes
- 💄 🐷 Remove duplicate require
2017-02-21 10:39:09 +01:00
Katharina Irrgang
2e1d7fcc42 🚨 database: change hard limits and field types (#7932)
refs #7432

🚨  database: change hard limits and field types

- we went over all schema fields and decided to decrease/increase the hard limits
- the core goal is to have more flexibility in the future
- we reconsidered string vs. text

There are 5 groups:

- small strings: 50 characters
    - static strings
    - status, visibility, language, role name, permission name, client name etc.
- medium strings: 191 characters
    - all unique fields or fields which can be unique in the future
    - slug, tokens, user name, password, tag name, email
- large strings: 1000-2000 characters
    - these fields need to be very flexible
    - these fields get a soft limit attached (in a different PR)
    - post title, meta title, meta description, urls
- medium text: 64kb characters
    - bio, settings, location, tour
- long text: 1000000000 chars
    - html, amp, mobiledoc, markdown

🙄  sort_order for tests

- sort order was not set for the tests, so it was always 0
- mysql could return a different result

in my case:
- field length 156 returned the following related tags ["bacon", "kitchen"]
- field length 157 returned the following related tags ["kitchen", "kitchen"]

Change client.secret to 191

Tweak field lengths

- Add 24 char limit for ids
- Limited fields are the exact length they need
- Unified 1000 and 2000 char string classes to all be 2000
- Changed descriptions to be either 2000, except user & tag which is text 65535 as these may be used to store HTML later?!
- Updated tests

🛠  Update importer tests

- The old 001-003 tests are kind of less relevant now.
- Rather than worrying about past versions of the data structure, we should check that the importer only imports what we consider to be valid data
- I've changed the tests to treat the title-length check as a length-validation check, rather than a test for each of the old versions

🔥 Remove foreign key from subscribers.post_id

- There's no real need to have an index on this column, it just makes deleting posts hard.
- Same as created_by type columns, we can reference ids without needing keys/indexes
2017-02-17 23:20:59 +01:00
Hannah Wolfe
b00d9fee6d 🎨 ⏱ Cleanup / optimise the server.init() function (#7985)
refs #2182

* 🔥 Remove unused options from server init
- this is left over from old code and is now unused

* 🎨 Move knex-migrator check to db health

- Move complex check function into own module
- Call module from server/index.js
- This just improves the readability of server/index.js

* 🔥 Remove old comments

- These comments all make no sense now!

* 🎨 ⏱ Move model init out of promise chain

- Model.init() does not return a promise
- Therefore, we can move it to the top of the init function, outside of the promise change
- This should be a minor optimisation, and again improves readability /clarity of what's happening

*  ⁉️ Move DBHash init / first run to Settings model

- this structure is left over from when we had code we executed on the first run of Ghost
- the implementation used the API to initialise one setting before populateDefaults is called
- this had lots of dependencies - the whole model, API, and permissions structure had to be initialised for it to work
- the new implementation is simpler, it captures the dbHash getting initialised during populateDefaults()
- it also adds an event, so we can do first-run code later if we really want to (or maybe apps can?!)
- perhaps this is hiding behaviour, and there's a nicer way to do it, but populateDefaults seems like a sane place to populate a default setting 😁

* ⏱ Optimise require order so config is first

- the first require to config will cause the files to be read etc
- this ensures that it happens early, and isn't confusingly timed as part of loading a different module

* 🎨 Simplify settings model changes
2017-02-17 17:44:34 +01:00
Katharina Irrgang
d9707eb57c public client registration: remember auth url (#7994)
no issue

- we have to remember the auth url in Ghost
- if Ghost starts for the first time, it registers a public client in the defined auth service
- if you change the auth service, Ghost won't recognize
- if Ghost doesn't recognize, you will see a client does not exist error in Ghost Admin
2017-02-14 12:41:28 +00:00
Katharina Irrgang
f3d16352b1 🎨 😎 config env usages (#7929)
refs #7488

- remove all ugly env checks
- rather use config properties
- replace process.env.NODE_ENV by config.get('env')
2017-02-03 18:25:39 +00:00
Katharina Irrgang
2a52af1d99 🔥 remove imageRelPath (#7927)
refs #7488

- remove imageRelPath
- instead add a static image prefix to the url helper
2017-02-03 14:42:05 +00:00
Katharina Irrgang
0201c431d7 🔥 do not store settings in config (#7924)
* 🎨  🔥  do not store settings in config and make settings cache easier available

- remove remembering settings value in theme config
- if we need a cache value, we are asking the settings cache directly
- instead of settings.getSettingSync we use settings.cache.get

- added TODO:
  - think about moving the settings cache out of api/settings
  - we could create a folder named cache cache/settings
  - this settings cache listens on model changes for settings
  - decoupling

* 🔥  remove timezone from config

- no need to store in overrides config and in defaults settings

* 🎨  context object helper

- replace config.get('theme') by settings cache

* 🎨  replace config.get('theme') by settings.cache.get

* 🎨  adapt tests

* fixes from comments
2017-02-03 13:15:11 +00:00
Katharina Irrgang
16f5d1fdaf 🎨 add urlFor('admin') and increase usage of urlFor helper (#7935)
refs #7488

- to be able to refactor the url configuration in ghost, we need to go step by step making this possible
- reduce the usage of forceAdminSSL
- add a urlFor('admin') helper, which returns the admin url + path e.g. http://my-blog.com/blog/ghost
- increase usage of urlFor helper
- do not expose getBaseUrl, use urlFor('home') (home === blog)
2017-02-02 18:51:35 +00:00
Vivek Kannan
5507adadf1 Import from LTS blogs now properly adds tags to posts. (#7926)
closes #7866

- Importer now uses Javascript's Map instead of the normal object to ensure that tags are properly associated with their corresponding posts.
2017-01-31 17:50:44 +01:00
Aileen Nowak
d2f2888da0 Favicon URI (#7700)
closes #7688

- Use `/favicon.ico` and `/favicon.png` in blog app. Depending on type of storage (custom upload = local file storage), serves either from storage adapter with `read()` method or reads the bytes via `fs`.
- Redirects requests for `favicon.ico` to `favicon.png` if custom `png` icon is uploaded and vice versa.
- Redirect requests for `favicon.png` to `favicon.ico` if default icon is used (in `core/shared`).
- Changes the `{{asset}}` helper for favicon to not serve from theme assets anymore. It will either be served the custom blog-icon or the default one.
- The `{{@blog.icon}}` helper renders the url of the **uploaded** blog icon. It won't render the default icon.
2017-01-26 18:01:19 +00:00
Katharina Irrgang
584bd15b76 🔥 remove database version (#7894)
refs #7489

- as we are now using a different migration approach (knex-migrator), we don't need to remember the database version anymore
- it was once used to check the state of a database and based on it we decided to migrate or not
- with knex-migrator everything depends on the migration table entries and the current ghost version you are on
- on current master the leftover usage is to add the db version when exporting the database, which can be replaced by reading the ghost version
- removing this solves also an interesting migration case with knex-migrator:
  - you are on 1.0
  - you update to 1.1, but 1.1 has no migrations
  - the db version would remain in 1.0
  - because the db version was only updated when knex migrator executed a migration
2017-01-26 12:12:00 +00:00
Katharina Irrgang
c070c9722d 🐛 re-run init migrations protection (#7899)
no issue

- if re-running the init scripts (for example: you lost the init rows in the migrations table), then it was throwing errors
- 1. the owner slug and email can change -> no match and it tried to reinsert the user with id 1, which failed
- 2. querying an inactive user is not allowed, because the user model protects against it
2017-01-25 22:08:09 +01:00
Katharina Irrgang
0424c6675c 🐛 fix backup database (#7898)
refs #7489

The require path for the db backup was wrong. The before hook could not execute db backup.
Furthermore, i have replaced the logging in the backup script.
2017-01-25 20:34:31 +01: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
Aileen Nowak
ca521e234f 🐷 Rename 'favicon' to 'icon' (#7888)
refs TryGhost/Ghost#7688

Just renames `favicon` to `icon` as our usage for it will not be for favicon purposes only.
2017-01-25 11:02:02 +01:00
Katharina Irrgang
78eacb19e9 🛠 use Ignition for logging/errors (#7869)
no issue

- we started implementing logging and error handling in Ghost
- later we outsourced both into a module
- use the module now in Ghost
- this commit basically just removes the logging and error implementation and uses Ignition
2017-01-23 11:04:01 +00:00
Aileen Nowak
7cb57bff3d Find favicon in Ghost (#7713)
refs #7688

Adds logic in theme settings api to either serve an uploaded favicon and give it the type `upload` or use the default settings `default`, which will serve the favicon from our shared directory.

TODOs for #7688:
- [X] Figure out, which favicon should be used (uploaded or default) -> this PR
- [ ] Serve and redirect the favicon for any browser requests, incl. redirects
- [ ] Upload favicon via `general/settings` and implement basic admin validations -> [WIP] TryGhost/Ghost-Admin#397
- [ ] Built server side validations
2017-01-23 10:13:52 +01:00
Aileen Nowak
2f3081fa9f Make AMP optional (#7830)
closes #7769

Because Google AMP is bitching around and shows errors in Googles' webmaster tools for missing post images and blog icons, we decided to make AMP optional. It will be enabled by default, but can be disabled in general settings. Once disabled, the `amp` route doesn't work anymore.

This PR contains the back end changes for Ghost-alpha:
- Adds `amp` to settings table incl default setting `true`
- Adds `amp` value to our settings cache
- Changes the route handling of AMP app to check for the `amp` setting first.
- Adds tests to check the route handling and ghost_head output
- Includes changes to `post-lookup.js` as done by @kirrg001 in #7842
2017-01-17 16:40:06 +01:00
Katharina Irrgang
5210271474 🐛 import subscribers (#7834)
closes #7748

- logic for import of subscribers was just missing
2017-01-10 19:38:20 +00:00
Katharina Irrgang
8031102596 🎨 escape sameAs for structured data (#7833)
closes #7832

- escape output for json-ld
2017-01-10 12:21:37 +00:00
Aileen Nowak
7cd13e6122 🔑 Update Validator to 6.2.1 (#7823)
no issue

Uses new version of [validator](https://github.com/chriso/validator.js) which checks also for in URL embedded script tags.
2017-01-10 13:05:25 +01: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
3d3101ad0e 🐛 invite permissions for Editor (#7724)
closes #7723

- editor role had no permissions assigned for invites
2016-11-16 13:49:55 +00:00
Katharina Irrgang
0f855c538e 🎨 invites roles table into a field on the invites table (#7705)
* 🎨  schema change

- simply role_id attribute

* 🎨  update invite model

- remove all methods we don't need
- ensure we remove the relation from the model
- ensure we do not allow to call withRelated

* 🎨  adapt api changes

* 🎨  adapt auth module

* 🎨  adapt tests

* 🎨  better error handling

* schema update
2016-11-16 09:33:44 +00:00
Aileen Nowak
06061d5d6c 💄 Improve URL consistency, Part 1: urlJoin (#7668)
refs #7666

Use urlJoin for more consistency instead of concatenating url strings.
2016-11-14 14:38:55 +00:00
Hannah Wolfe
4a2ddbe2ae Merge pull request #7701 from kirrg001/1.0.0-dev/fix-brute-schema
🐛  fix brute
2016-11-14 14:34:31 +00:00
kirrg001
424f7fba0d 🎨 use bigInteger as type for brute schema
- i thought of keeping our schema, because it might be less confusing
- it's basically the same config brute-knex uses as default
- see last commit why we are using this type definition
2016-11-10 11:50:23 +01:00
Katharina Irrgang
b48031fa0e 🎨 unique constraint for permission and role name (#7674)
refs #7494,  refs #7495 

I saw tests adding permissions and roles twice. (see screenshots)
That happened because the setup in the test was mis-used and there is no restriction for static resources to create duplicates.
With this PR i suggest to make name unique.
2016-11-09 15:02:49 +00:00
Katharina Irrgang
48387e4ffd 🎨 tidy up static id (owner, internal, external) usages (#7675)
refs #7494, refs #7495 

This PR is an extracted clean up feature of #7495.
We are using everywhere static id checks (userId === 0 or userId === 1).
This PR moves the static values into the Base model.
This makes it 1. way more readable and 2. we can change the id's in a central place.

I changed the most important occurrences - no tests are touched (yet!).

The background is: when changing from auto increment id (number) to ObjectId's (string) we still need to support id 1 and 0, because Ghost relies on these two static id's.
I would like to support using both: 0/1 as string and 0/1 as number.

1 === owner/internal
0 === external

Another important change:
User Model does not longer define the contextUser method, because i couldn't find a reason?
I looked in Git history, see 6e48275160
2016-11-09 15:01:07 +00:00
kirrg001
974c6071e8 🐛 fix brute schema
no issue

- brute-knex uses timestamp type, see https://github.com/llambda/brute-knex/blob/master/index.js
- so we also defined timestamp type
- see http://stackoverflow.com/questions/9192027/invalid-default-value-for-create-date-timestamp-field
- see http://stackoverflow.com/questions/35237278/mysql-invalid-default-value-for-timestamp-when-no-default-value-is-given
- mysql does not allow a second timestamp without default value
- we have to options: define a default value or allow null or use dateTime
- let's use dateTime, as 1. we are using it for all our dates in Ghost and 2. it's recommended
- read here http://www.sqlteam.com/article/timestamps-vs-datetime-data-types
- there are some difference, i think the most important difference is that TIMESTAMP changes if the tz changes in your database
- lifetime is timestamp not a bigInteger, this was a mistake i think (see https://github.com/llambda/brute-knex/blob/master/index.js#L115)
2016-11-09 12:14:26 +01:00
Katharina Irrgang
0a744c2781 🎨 public client registration updates (#7690)
* 🎨  use updateClient function to update redirectUri

refs #7654

* 🎨  name instead of clientName
* 🎨  config.get('theme:title') for client name

- initial read can happen from config

*   register public client: client name and description

- no update yet
- for initial client creation
- we forward title/description to Ghost Auth
- TODO: use settings-cache when merged

*   store blog_uri in db
* 🎨  passport logic changes

- use updateClient instead of changeCallbackURL
- be able to update: blog title, blog description, redirectUri and blogUri
- remove retries, they get implemented in passport-ghost soon
- reorder logic a bit

* 🛠  passport-ghost 1.2.0

* 🎨  tests: extend DataGenerator createClient

- set some defaults

* 🎨  tests

- extend tests
- 👻

*   run auth.init in background

- no need to block the bootstrap process
- if client can't be registered, you will see an error
- ensure Ghost-Admin renders correctly

* 🛠   passport-ghost 1.3.0

- retries

* 🎨  use client_uri in Client Schema

- adapt changes
- use blog_uri only when calling the passport-ghost instance
- Ghost uses the client_uri notation to improve readability

*   read blog title/description from settings cache

* 🚨  Ghost Auth returns email instead of email_address

- adapt Ghost
2016-11-08 14:21:25 +00:00
David Wolfe
68af2145a1 Replace memory spam prevention with brute-express (#7579)
no issue

- removes count from user checks model
- uses brute express brute with brute-knex adaptor to store persisted data on spam prevention
- implement brute force protection for password/token exchange, password resets and private blogging
2016-11-08 12:33:19 +01:00
Katharina Irrgang
bae0de6cd5 knex-migrator v2 (#7605)
* 🎨  knex-migrator reset

[ci skip]

*   add migration example

- hooks
- 1.0

[ci skip]

* 🛠  knex-migrator tarball

- remove when released

[ci skip]

* 🎨  jscs/jshint

* 🕵🏻 do not drop the database connection when running tests

- please read the comments in the commit

* 🔥  remove example migration

* 🛠  knex-migrator 0.1.0

* 🛠  knex-migrator 0.1.1

- fix a single test to ensure we catch the error

* 🛠  knex-migrator 0.1.2

* 🎨  make tests green

- added my keyword: kate-migrations
- i will go over all TODO's when removing the old migrations code

* 🛠  knex-migrator update

* 🛠  knex-migrator 0.2.0
2016-11-07 11:39:49 +00:00
Hannah Wolfe
9a7ebeef1c Use moment-timezone when using .tz() (#7653)
refs #7449, refs #7514, refs #7643

- We've had a couple of issues raised, and a few people in #help all report the same error:
> Cannot read property 'zone' of undefined
When starting Ghost.

I'm not sure why this seems to work sometimes, and not others, however it would seem that we
should require moment-timezone anywhere we want to use timezone features.

This PR fixes the LOC shown in #7449 as the problem line + I searched for any other potential problems
2016-10-31 14:44:24 +01:00
Katharina Irrgang
8d8d7bdb26 knex migrator (#7565)
refs #7489
- remove sephiroth
- use knex migrator npm
- goodbye bootup script
- 🎨  update README
- 🎨  knex migrator @ 0.0.2
2016-10-17 13:50:29 +01:00
Katharina Irrgang
869a35c97d migrations: seeding is part of init db task (#7545)
* 🎨  move heart of fixtures to schema folder and change user model

- add fixtures.json to schema folder
- add fixture utils to schema folder
- keep all the logic!

--> FIXTURE.JSON
- add owner user with roles

--> USER MODEL
- add password as default
- findAll: allow querying inactive users when internal context (defaultFilters)
- findOne: do not remove values from original object!
- add: do not remove values from original object!

* 🔥  remove migrations key from default_settings.json

- this was a temporary invention for an older migration script
- sephiroth keep alls needed information in a migration collection

* 🔥   add code property to errors

- add code property to errors
- IMPORTANT: please share your opinion about that
- this is a copy paste behaviour of how node is doing that (errno, code etc.)
- so code specifies a GhostError

* 🎨  change error handling in versioning

- no need to throw specific database errors anymore (this was just a temporary solution)
- now: we are throwing real DatabaseVersionErrors
- specified by a code
- background: the versioning unit has not idea about seeding and population of the database
- it just throws what it knows --> database version does not exist or settings table does not exist

* 🎨  sephiroth optimisations

- added getPath function to get the path to init scripts and migration scripts
- migrationPath is still hardcoded (see TODO)
- tidy up database naming to transacting

*   migration init scripts are now complete

- 1. add tables
- 2. add fixtures
- 3. add default settings

* 🎨  important: make bootup script smaller!

- remove all TODO'S except of one
- no seeding logic in bootup script anymore 🕵🏻

*   sephiroth: allow params for init command

- param: skip (do not run this script)
- param: only (only run this script)
- very simple way

* 🎨  adapt tests and test env

- do not use migrate.populate anymore
- use sephiroth instead
- jscs/jshint

* 🎨  fix User model status checks
2016-10-12 16:18:57 +01:00
Katharina Irrgang
677502813e 🎨 replace process.env.NODE_ENV usages by config.get('env') (#7544)
closes #6629

- i had the case that in gravatar process.env.NODE_ENV was undefined and indexOf of undefined crashe my application
- so always use config to read current env
2016-10-11 13:53:52 +01:00
Katharina Irrgang
9fad7f1d69 use migration runner for init db (#7502)
refs #7489

* 🎨  protect error when creating owner
* 🎨  reset migration table
- temporary solution, see TODO's
* 🎨  use sephiroth in bootUp script
- do not populate the database
- ask sephiroth for database state
- do seeding manually (this will be removed in next seeding PR)
* 🎨  rewrite createTableIfNotExists because it causes error when running twice
- see knex issue
- hasTable and createTable
- indexes can cause trouble when calling them twice
* 🎨  tests: populate db in test env
- when forking db
- when starting ghost()
- this basically affects only the functional tests
* 🎨  server spec test adaption
- we now throw an error when database is not populated, instead of populating the database
* 🎨   migration spec adaption
- reset database now deletes migration table
- we will move the reset script into sephiroth and then we make it pretty
* 🎨  error creation adaption in bootUp
* 🎨  fixes
- sephiroth error handling
- fix tests
2016-10-11 13:37:11 +01:00
Hannah Wolfe
59e2694acf Misc Middleware cleanup (#7526)
* 💄 Combine slashes & uncapitalise middleware

- these bits of middleware belong together
- ideally they should be optimised

* 🎨 Move ghostLocals out of themeHandler

GhostLocals sets several important values which are needed for every part of the application,
admin, api and theme. Therefore, it doesn't make sense for it to be bundled in the themeHandler.

* 🐛 Fix the uncapitalise middleware

- Updated to make correct use of req.baseUrl, req.path, req.url & req.originalUrl
- Updated the tests to actually cover our weird cases

* 🎨 Move ghostVersion logic out of config

* 💄 Group static / asset-related middleware together

* 🔥 Remove /shared/ asset handling

- The 5 files which are located in `/shared/` are all handled by individual calls to `serveSharedFile`
- Therefore this code is redundant
2016-10-10 21:14:32 +02:00
Katharina Irrgang
8d9414e8ba 🎨 optimise sephiroth error handling (#7531)
refs #7489
2016-10-10 18:31:32 +01:00
Katharina Irrgang
c4fa34224f Migration runner - first iteration (#7501)
refs #7489
- add independent migratio runner
- add init script
- this is not connected to Ghost yet, but next PR will
2016-10-10 13:27:31 +01:00
Hannah Wolfe
63094d3cc7 Move internal tags out of labs (#7519)
closes #6165

- internal tags has been in labs for a couple of months, we've fixed some bugs & are ready to ship
- removes all code that tests for the labs flag
- also refactors the various usage of the visibility filter into a single util
- all the tests still pass!!!
- this marks #6165 as closed because I think the remaining UI tasks will be handled as part of a larger piece of work
2016-10-10 09:51:03 +01:00
Hannah Wolfe
c74f65683e 🎨 Change asset path to /ghost/assets (#7504)
closes #7503

- Update this server-side to serve assets from ghost/assets
- a Ghost-Admin PR changes the client to always request them from there
2016-10-07 17:05:36 -05:00
Katharina Irrgang
f9561eed29 🎨 use nullable(false) for knex schema builder (#7511)
refs #7470
2016-10-07 10:17:39 +01:00
Katharina Irrgang
e2e83a0f7b Migration: New database versioning (#7499)
refs #7489

- new database versioning scheme which is based upon the Ghost version, and so easier to reason about
- massive refactor of all the version related code 

Summary of changes:

*   new error: DatabaseNotSeeded
* 🎨  change versioning module
  - versioning is based on Ghost Version
* 🎨  change bootUp file
  - add big picture description
  - version error get's trigger from versioning module
* 🎨  default setting for database version is null
  - very important change: this is caused by the big picture
  - see bootUp description
  - the database version get's set by the seed script later
  - db version is by default null
  - 1. population happens (we ensure that this has finished, by checking if each table exists)   
  - 2. seeds happening (we ensure that seeds happend if database version is set to X.X)
* 🎨  temporary change for population logic
  - set database version after population happens
  - ensure population of default settings happend before
  - both: get's removed in next iteration
* 🎨  adapt tests && mark TODO's
* 🎨  err instance checking
2016-10-06 14:50:55 +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
32700a0e5a 🔥 remove all migration files (#7498)
refs #7489
- a simple PR to remove all the old migration files
- remove related tests
2016-10-05 19:57:32 +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
Hannah Wolfe
e40290af5d 🎨 Use GhostAuth name and example emails (#7475)
refs #7452

- remove references to 'patronus' in favour of GhostAuth, Note: this will require databases to be deleted ;)
- remove email addresses from test data
2016-10-03 15:11:43 +01:00
Katharina Irrgang
1867e1a75e 🎨 run database population in transaction (#7448)
* 🎨  run database population in transaction

refs #6574, refs #7432

- create transaction for creating tables
- if an error occurs or a container get's destroyed before population finishes, transaction is rolled back

* 🎨  simplify transaction creation and test
2016-09-30 14:05:17 +01:00
Katharina Irrgang
6473c9e858 Ghost OAuth (#7451)
issue #7452

Remote oauth2 authentication with Ghost.org.

This PR supports:

- oauth2 login or local login
- authentication on blog setup
- authentication on invite
- normal authentication
- does not contain many, many tests, but we'll improve in the next alpha weeks
2016-09-30 12:45:59 +01:00
kirrg001
d0356a257e 🐛 fix circular dependency in new bootUp script
closes #7440
2016-09-27 12:18:45 +02:00
kirrg001
b79a18ca8f 🎨 Separate invites from user
refs #7420
- remove invite logic from user
- add invite model and adapt affected logic for inviting team members
2016-09-26 11:08:43 +02:00
Hannah Wolfe
264661ee09 🐛 Refresh assetHash on theme override (#7430)
closes #7423

- Extend our dirty theme override cache clear hack to also reset the asset hash
_ This brings alpha into line with the LTS branch
- This still needs a rewrite for Ghost 1.0.0 🙄
2016-09-23 13:05:44 +02:00
Katharina Irrgang
32a5982430 utf8mb4 support (#7409)
closes #5519, closes #6197

- default encoding is utf8mb4 instead of utf8
- support emojis
- read here why: http://dev.mysql.com/doc/refman/5.7/en/innodb-restrictions.html
- read here why: https://dev.mysql.com/doc/refman/5.5/en/charset-unicode-conversion.html
2016-09-20 15:59:34 +01:00
Hannah Wolfe
9a520f39fb 🎨 Preparation for going alpha (#7404)
- Don't let people start Ghost Alpha with non-alpha databases.
- Provide a new welcome message for development mode (a little bit of positive reinforcment)
- Provide a RED WARNING when in production mode (will still be used for developing, but we can ignore)
- Change package.json to 1.0.0-alpha.0, we won't relelase this, will bump to .1 for release
2016-09-20 15:59:34 +01:00
kirrg001
8115d83782 🔥 remove postgres support
refs #1333, refs #5878, refs #5321
2016-09-20 15:59:34 +01:00
kirrg001
231fea4766 🎨 adaption from master merge
no issue
[ci skip]
2016-09-20 15:59:34 +01:00
kirrg001
6a97873f98 🎨 🔦 refactor content paths (images, apps, themes, storage, scheduling)
refs #6982
- create config util fn: getContentPath
- we can later let the user change the folder names in contentPath
- get rid of custom/default storage paths

[ci skip]
2016-09-20 15:59:34 +01:00
kirrg001
f4bee50e86 🎨 create assetHash if not available in asset_url helper
refs #6982
- was before generated in ConfigManager

[ci skip]
2016-09-20 15:59:34 +01:00
kirrg001
34e48dc49a 🎨 🔦 do not append isPostgreSQL to config
refs #6982
- we cannot add functions to nconf

[ci skip]
2016-09-20 15:59:34 +01: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
kirrg001
0b2940d587 🎨 add getSubdir and getProtectedSlugs
refs #6982

- do not add the subdir property as static config value
- create functions to read subdir and protected slugs on runtime
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
Hannah Wolfe
a791b43f1e 🐛 😱 Fixing extract-zip derp-moment
There are no words for this!
2016-09-14 22:47:41 +01:00
David Wolfe
1cf0b940ad Do not show internal tags in RSS feed (#7385)
closes #7367

- checks tags are visibile if internal tags are enabled in labs
- dirty quick update to tests
2016-09-14 19:14:08 +01:00
Hannah Wolfe
de66a61f59 hides internal tags from displaying in meta data (#7379)
closes #7348

- only filter keywords if the internal tag lab feature is turned on
2016-09-14 17:33:24 +00:00