2016-10-11 11:36:00 +03:00
|
|
|
// # API routes
|
🎉 🎨 ✨ Remove middleware/index.js (#7548)
closes #4172, closes #6948, refs #7491, refs #7488, refs #7542, refs #7484
* 🎨 Co-locate all admin-related code in /admin
- move all the admin related code from controllers, routes and helpers into a single location
- add error handling middleware explicitly to adminApp
- re-order blogApp middleware to ensure the shared middleware is mounted after the adminApp
- TODO: rethink the structure of /admin, this should probably be an internal app
* 💄 Group global middleware together
- There are only a few pieces of middleware which are "global"
- These are needed for the admin, blog and api
- Everything else is only needed in one or two places
* ✨ Introduce a separate blogApp
- create a brand-new blogApp
- mount all blog/theme only middleware etc onto blogApp
- mount error handling on blogApp only
* 🎨 Separate error handling for HTML & API JSON
- split JSON and HTML error handling into separate functions
- re-introduce a way to not output the stack for certain errors
- add more tests around errors & an assertion framework for checking JSON Errors
- TODO: better 404 handling for static assets
Rationale:
The API is very different to the blog/admin panel:
- It is intended to only ever serve JSON, never HTML responses
- It is intended to always serve JSON
Meanwhile the blog and admin panel have no need for JSON errors,
when an error happens on those pages, we should serve HTML pages
which are nicely formatted with the error & using the correct template
* 🐛 Fix checkSSL to work for subapps
- in order to make this work on a sub app we need to use the pattern `req.originalUrl || req.url`
* 🔥 Get rid of decide-is-admin (part 1/2)
- delete decide-is-admin & tests
- add two small functions to apiApp and adminApp to set res.isAdmin
- mount checkSSL on all the apps
- TODO: deduplicate the calls to checkSSL by making blogApp a subApp :D
- PART 2/2: finish cleaning this up by removing it from where it's not needed and giving it a more specific name
Rationale:
Now that we have both an adminApp and an apiApp,
we can temporarily replace this weird path-matching middleware
with middleware that sets res.isAdmin for api & admin
* 🎨 Wire up prettyURLs on all Apps
- prettyURLs is needed for all requests
- it cannot be global because it has to live after asset middleware, and before routing
- this does not result in duplicate redirects, but does result in duplicate checks
- TODO: resolve extra middleware in stack by making blogApp a sub app
* ⏱ Add debug to API setup
* 🎨 Rename blogApp -> parentApp in middleware
* 🎨 Co-locate all blog-related code in /blog
- Move all of the blogApp code from middleware/index.js to blog/app.js
- Move routes/frontend.js to blog/routes.js
- Remove the routes/index.js and routes folder, this is empty now!
- @TODO is blog the best name for this? 🤔
- @TODO sort out the big hunk of asset-related mess
- @TODO also separate out the concept of theme from blog
* 🎉 Replace middleware index with server/app.js
- The final piece of the puzzle! 🎉 🎈 🎂
- We no longer have our horrendous middleware/index.js
- Instead, we have a set of app.js files, which all use a familiar pattern
* 💄 Error handling fixups
2016-10-13 18:24:09 +03:00
|
|
|
var debug = require('debug')('ghost:api'),
|
|
|
|
express = require('express'),
|
2016-10-11 11:36:00 +03:00
|
|
|
tmpdir = require('os').tmpdir,
|
|
|
|
|
|
|
|
// This essentially provides the controllers for the routes
|
|
|
|
api = require('../api'),
|
|
|
|
|
|
|
|
// Include the middleware
|
|
|
|
|
|
|
|
// API specific
|
|
|
|
auth = require('../auth'),
|
|
|
|
cors = require('../middleware/api/cors'), // routes only?!
|
2016-11-08 14:33:19 +03:00
|
|
|
brute = require('../middleware/brute'), // routes only
|
2016-10-11 11:36:00 +03:00
|
|
|
versionMatch = require('../middleware/api/version-match'), // global
|
|
|
|
|
|
|
|
// Handling uploads & imports
|
|
|
|
upload = require('multer')({dest: tmpdir()}), // routes only
|
|
|
|
validation = require('../middleware/validation'), // routes only
|
|
|
|
|
|
|
|
// Shared
|
|
|
|
bodyParser = require('body-parser'), // global, shared
|
|
|
|
cacheControl = require('../middleware/cache-control'), // global, shared
|
🔥✨ remove forceAdminSSL and urlSSL, add admin url (#7937)
* 🔥 kill apiUrl helper, use urlFor helper instead
More consistency of creating urls.
Creates an easier ability to add config changes.
Attention: urlFor function is getting a little nesty, BUT that is for now wanted to make easier and centralised changes to the configs.
The url util need's refactoring anyway.
* 🔥 urlSSL
Remove all urlSSL usages.
Add TODO's for the next commit to re-add logic for deleted logic.
e.g.
- cors helper generated an array of url's to allow requests from the defined config url's -> will be replaced by the admin url if available
- theme handler prefered the urlSSL in case it was defined -> will be replaced by using the urlFor helper to get the blog url (based on the request secure flag)
The changes in this commit doesn't have to be right, but it helped going step by step.
The next commit is the more interesting one.
* 🔥 ✨ remove forceAdminSSL, add new admin url and adapt logic
I wanted to remove the forceAdminSSL as separate commit, but was hard to realise.
That's why both changes are in one commit:
1. remove forceAdminSSL
2. add admin.url option
- fix TODO's from last commits
- rewrite the ssl middleware!
- create some private helper functions in the url helper to realise the changes
- rename some wordings and functions e.g. base === blog (we have so much different wordings)
- i would like to do more, but this would end in a non readable PR
- this commit contains the most important changes to offer admin.url option
* 🤖 adapt tests
IMPORTANT
- all changes in the routing tests were needed, because each routing test did not start the ghost server
- they just required the ghost application, which resulted in a random server port
- having a random server port results in a redirect, caused by the ssl/redirect middleware
* 😎 rename check-ssl middleware
* 🎨 fix theme-handler because of master rebase
2017-02-03 21:13:22 +03:00
|
|
|
urlRedirects = require('../middleware/url-redirects'),
|
🎉 🎨 ✨ Remove middleware/index.js (#7548)
closes #4172, closes #6948, refs #7491, refs #7488, refs #7542, refs #7484
* 🎨 Co-locate all admin-related code in /admin
- move all the admin related code from controllers, routes and helpers into a single location
- add error handling middleware explicitly to adminApp
- re-order blogApp middleware to ensure the shared middleware is mounted after the adminApp
- TODO: rethink the structure of /admin, this should probably be an internal app
* 💄 Group global middleware together
- There are only a few pieces of middleware which are "global"
- These are needed for the admin, blog and api
- Everything else is only needed in one or two places
* ✨ Introduce a separate blogApp
- create a brand-new blogApp
- mount all blog/theme only middleware etc onto blogApp
- mount error handling on blogApp only
* 🎨 Separate error handling for HTML & API JSON
- split JSON and HTML error handling into separate functions
- re-introduce a way to not output the stack for certain errors
- add more tests around errors & an assertion framework for checking JSON Errors
- TODO: better 404 handling for static assets
Rationale:
The API is very different to the blog/admin panel:
- It is intended to only ever serve JSON, never HTML responses
- It is intended to always serve JSON
Meanwhile the blog and admin panel have no need for JSON errors,
when an error happens on those pages, we should serve HTML pages
which are nicely formatted with the error & using the correct template
* 🐛 Fix checkSSL to work for subapps
- in order to make this work on a sub app we need to use the pattern `req.originalUrl || req.url`
* 🔥 Get rid of decide-is-admin (part 1/2)
- delete decide-is-admin & tests
- add two small functions to apiApp and adminApp to set res.isAdmin
- mount checkSSL on all the apps
- TODO: deduplicate the calls to checkSSL by making blogApp a subApp :D
- PART 2/2: finish cleaning this up by removing it from where it's not needed and giving it a more specific name
Rationale:
Now that we have both an adminApp and an apiApp,
we can temporarily replace this weird path-matching middleware
with middleware that sets res.isAdmin for api & admin
* 🎨 Wire up prettyURLs on all Apps
- prettyURLs is needed for all requests
- it cannot be global because it has to live after asset middleware, and before routing
- this does not result in duplicate redirects, but does result in duplicate checks
- TODO: resolve extra middleware in stack by making blogApp a sub app
* ⏱ Add debug to API setup
* 🎨 Rename blogApp -> parentApp in middleware
* 🎨 Co-locate all blog-related code in /blog
- Move all of the blogApp code from middleware/index.js to blog/app.js
- Move routes/frontend.js to blog/routes.js
- Remove the routes/index.js and routes folder, this is empty now!
- @TODO is blog the best name for this? 🤔
- @TODO sort out the big hunk of asset-related mess
- @TODO also separate out the concept of theme from blog
* 🎉 Replace middleware index with server/app.js
- The final piece of the puzzle! 🎉 🎈 🎂
- We no longer have our horrendous middleware/index.js
- Instead, we have a set of app.js files, which all use a familiar pattern
* 💄 Error handling fixups
2016-10-13 18:24:09 +03:00
|
|
|
prettyURLs = require('../middleware/pretty-urls'),
|
2016-10-11 11:36:00 +03:00
|
|
|
maintenance = require('../middleware/maintenance'), // global, shared
|
|
|
|
errorHandler = require('../middleware/error-handler'), // global, shared
|
|
|
|
|
|
|
|
// Temporary
|
|
|
|
// @TODO find a more appy way to do this!
|
|
|
|
labs = require('../middleware/labs'),
|
|
|
|
|
2017-03-03 19:41:20 +03:00
|
|
|
/**
|
|
|
|
* Authentication for public endpoints
|
|
|
|
* @TODO find a better way to bundle these authentication packages
|
|
|
|
*
|
|
|
|
* IMPORTANT
|
|
|
|
* - cors middleware MUST happen before pretty urls, because otherwise cors header can get lost
|
|
|
|
* - cors middleware MUST happen after authenticateClient, because authenticateClient reads the trusted domains
|
|
|
|
*/
|
2016-10-11 11:36:00 +03:00
|
|
|
authenticatePublic = [
|
|
|
|
auth.authenticate.authenticateClient,
|
|
|
|
auth.authenticate.authenticateUser,
|
2017-03-03 19:41:20 +03:00
|
|
|
auth.authorize.requiresAuthorizedUserPublicAPI,
|
|
|
|
cors,
|
|
|
|
prettyURLs
|
2016-10-11 11:36:00 +03:00
|
|
|
],
|
|
|
|
// Require user for private endpoints
|
|
|
|
authenticatePrivate = [
|
|
|
|
auth.authenticate.authenticateClient,
|
|
|
|
auth.authenticate.authenticateUser,
|
2017-03-03 19:41:20 +03:00
|
|
|
auth.authorize.requiresAuthorizedUser,
|
|
|
|
cors,
|
|
|
|
prettyURLs
|
2016-10-11 11:36:00 +03:00
|
|
|
];
|
|
|
|
|
|
|
|
// @TODO refactor/clean this up - how do we want the routing to work long term?
|
|
|
|
function apiRoutes() {
|
|
|
|
var apiRouter = express.Router();
|
|
|
|
|
|
|
|
// alias delete with del
|
|
|
|
apiRouter.del = apiRouter.delete;
|
|
|
|
|
|
|
|
// ## CORS pre-flight check
|
|
|
|
apiRouter.options('*', cors);
|
|
|
|
|
|
|
|
// ## Configuration
|
2016-10-28 16:07:46 +03:00
|
|
|
apiRouter.get('/configuration', api.http(api.configuration.read));
|
2016-10-11 11:36:00 +03:00
|
|
|
apiRouter.get('/configuration/:key', authenticatePrivate, api.http(api.configuration.read));
|
|
|
|
apiRouter.get('/configuration/timezones', authenticatePrivate, api.http(api.configuration.read));
|
|
|
|
|
|
|
|
// ## Posts
|
|
|
|
apiRouter.get('/posts', authenticatePublic, api.http(api.posts.browse));
|
|
|
|
|
|
|
|
apiRouter.post('/posts', authenticatePrivate, api.http(api.posts.add));
|
|
|
|
apiRouter.get('/posts/:id', authenticatePublic, api.http(api.posts.read));
|
|
|
|
apiRouter.get('/posts/slug/:slug', authenticatePublic, api.http(api.posts.read));
|
|
|
|
apiRouter.put('/posts/:id', authenticatePrivate, api.http(api.posts.edit));
|
|
|
|
apiRouter.del('/posts/:id', authenticatePrivate, api.http(api.posts.destroy));
|
|
|
|
|
|
|
|
// ## Schedules
|
|
|
|
apiRouter.put('/schedules/posts/:id', [
|
|
|
|
auth.authenticate.authenticateClient,
|
|
|
|
auth.authenticate.authenticateUser
|
|
|
|
], api.http(api.schedules.publishPost));
|
|
|
|
|
|
|
|
// ## Settings
|
|
|
|
apiRouter.get('/settings', authenticatePrivate, api.http(api.settings.browse));
|
|
|
|
apiRouter.get('/settings/:key', authenticatePrivate, api.http(api.settings.read));
|
|
|
|
apiRouter.put('/settings', authenticatePrivate, api.http(api.settings.edit));
|
|
|
|
|
|
|
|
// ## Users
|
|
|
|
apiRouter.get('/users', authenticatePublic, api.http(api.users.browse));
|
|
|
|
apiRouter.get('/users/:id', authenticatePublic, api.http(api.users.read));
|
|
|
|
apiRouter.get('/users/slug/:slug', authenticatePublic, api.http(api.users.read));
|
|
|
|
apiRouter.get('/users/email/:email', authenticatePublic, api.http(api.users.read));
|
|
|
|
|
|
|
|
apiRouter.put('/users/password', authenticatePrivate, api.http(api.users.changePassword));
|
|
|
|
apiRouter.put('/users/owner', authenticatePrivate, api.http(api.users.transferOwnership));
|
|
|
|
apiRouter.put('/users/:id', authenticatePrivate, api.http(api.users.edit));
|
|
|
|
|
|
|
|
apiRouter.post('/users', authenticatePrivate, api.http(api.users.add));
|
|
|
|
apiRouter.del('/users/:id', authenticatePrivate, api.http(api.users.destroy));
|
|
|
|
|
|
|
|
// ## Tags
|
|
|
|
apiRouter.get('/tags', authenticatePublic, api.http(api.tags.browse));
|
|
|
|
apiRouter.get('/tags/:id', authenticatePublic, api.http(api.tags.read));
|
|
|
|
apiRouter.get('/tags/slug/:slug', authenticatePublic, api.http(api.tags.read));
|
|
|
|
apiRouter.post('/tags', authenticatePrivate, api.http(api.tags.add));
|
|
|
|
apiRouter.put('/tags/:id', authenticatePrivate, api.http(api.tags.edit));
|
|
|
|
apiRouter.del('/tags/:id', authenticatePrivate, api.http(api.tags.destroy));
|
|
|
|
|
|
|
|
// ## Subscribers
|
|
|
|
apiRouter.get('/subscribers', labs.subscribers, authenticatePrivate, api.http(api.subscribers.browse));
|
|
|
|
apiRouter.get('/subscribers/csv', labs.subscribers, authenticatePrivate, api.http(api.subscribers.exportCSV));
|
|
|
|
apiRouter.post('/subscribers/csv',
|
|
|
|
labs.subscribers,
|
|
|
|
authenticatePrivate,
|
|
|
|
upload.single('subscribersfile'),
|
|
|
|
validation.upload({type: 'subscribers'}),
|
|
|
|
api.http(api.subscribers.importCSV)
|
|
|
|
);
|
|
|
|
apiRouter.get('/subscribers/:id', labs.subscribers, authenticatePrivate, api.http(api.subscribers.read));
|
|
|
|
apiRouter.post('/subscribers', labs.subscribers, authenticatePublic, api.http(api.subscribers.add));
|
|
|
|
apiRouter.put('/subscribers/:id', labs.subscribers, authenticatePrivate, api.http(api.subscribers.edit));
|
|
|
|
apiRouter.del('/subscribers/:id', labs.subscribers, authenticatePrivate, api.http(api.subscribers.destroy));
|
|
|
|
|
|
|
|
// ## Roles
|
|
|
|
apiRouter.get('/roles/', authenticatePrivate, api.http(api.roles.browse));
|
|
|
|
|
|
|
|
// ## Clients
|
|
|
|
apiRouter.get('/clients/slug/:slug', api.http(api.clients.read));
|
|
|
|
|
|
|
|
// ## Slugs
|
|
|
|
apiRouter.get('/slugs/:type/:name', authenticatePrivate, api.http(api.slugs.generate));
|
|
|
|
|
|
|
|
// ## Themes
|
2017-02-21 17:59:03 +03:00
|
|
|
apiRouter.get('/themes/', authenticatePrivate, api.http(api.themes.browse));
|
|
|
|
|
2016-10-11 11:36:00 +03:00
|
|
|
apiRouter.get('/themes/:name/download',
|
|
|
|
authenticatePrivate,
|
|
|
|
api.http(api.themes.download)
|
|
|
|
);
|
|
|
|
|
|
|
|
apiRouter.post('/themes/upload',
|
|
|
|
authenticatePrivate,
|
|
|
|
upload.single('theme'),
|
|
|
|
validation.upload({type: 'themes'}),
|
|
|
|
api.http(api.themes.upload)
|
|
|
|
);
|
|
|
|
|
2017-03-08 13:46:03 +03:00
|
|
|
apiRouter.put('/themes/:name/activate',
|
|
|
|
authenticatePrivate,
|
|
|
|
api.http(api.themes.activate)
|
|
|
|
);
|
|
|
|
|
2016-10-11 11:36:00 +03:00
|
|
|
apiRouter.del('/themes/:name',
|
|
|
|
authenticatePrivate,
|
|
|
|
api.http(api.themes.destroy)
|
|
|
|
);
|
|
|
|
|
|
|
|
// ## Notifications
|
|
|
|
apiRouter.get('/notifications', authenticatePrivate, api.http(api.notifications.browse));
|
|
|
|
apiRouter.post('/notifications', authenticatePrivate, api.http(api.notifications.add));
|
|
|
|
apiRouter.del('/notifications/:id', authenticatePrivate, api.http(api.notifications.destroy));
|
|
|
|
|
|
|
|
// ## DB
|
|
|
|
apiRouter.get('/db', authenticatePrivate, api.http(api.db.exportContent));
|
|
|
|
apiRouter.post('/db',
|
|
|
|
authenticatePrivate,
|
|
|
|
upload.single('importfile'),
|
|
|
|
validation.upload({type: 'db'}),
|
|
|
|
api.http(api.db.importContent)
|
|
|
|
);
|
|
|
|
apiRouter.del('/db', authenticatePrivate, api.http(api.db.deleteAllContent));
|
|
|
|
|
|
|
|
// ## Mail
|
|
|
|
apiRouter.post('/mail', authenticatePrivate, api.http(api.mail.send));
|
|
|
|
apiRouter.post('/mail/test', authenticatePrivate, api.http(api.mail.sendTest));
|
|
|
|
|
|
|
|
// ## Slack
|
|
|
|
apiRouter.post('/slack/test', authenticatePrivate, api.http(api.slack.sendTest));
|
|
|
|
|
|
|
|
// ## Authentication
|
|
|
|
apiRouter.post('/authentication/passwordreset',
|
2016-11-08 14:33:19 +03:00
|
|
|
brute.globalReset,
|
|
|
|
brute.userReset,
|
2016-10-11 11:36:00 +03:00
|
|
|
api.http(api.authentication.generateResetToken)
|
|
|
|
);
|
2016-11-08 14:33:19 +03:00
|
|
|
apiRouter.put('/authentication/passwordreset', brute.globalBlock, api.http(api.authentication.resetPassword));
|
2016-10-11 11:36:00 +03:00
|
|
|
apiRouter.post('/authentication/invitation', api.http(api.authentication.acceptInvitation));
|
|
|
|
apiRouter.get('/authentication/invitation', api.http(api.authentication.isInvitation));
|
|
|
|
apiRouter.post('/authentication/setup', api.http(api.authentication.setup));
|
|
|
|
apiRouter.put('/authentication/setup', authenticatePrivate, api.http(api.authentication.updateSetup));
|
|
|
|
apiRouter.get('/authentication/setup', api.http(api.authentication.isSetup));
|
|
|
|
apiRouter.post('/authentication/token',
|
2016-11-08 14:33:19 +03:00
|
|
|
brute.globalBlock,
|
|
|
|
brute.userLogin,
|
2016-10-11 11:36:00 +03:00
|
|
|
auth.authenticate.authenticateClient,
|
|
|
|
auth.oauth.generateAccessToken
|
|
|
|
);
|
|
|
|
|
|
|
|
apiRouter.post('/authentication/revoke', authenticatePrivate, api.http(api.authentication.revoke));
|
|
|
|
|
|
|
|
// ## Uploads
|
|
|
|
// @TODO: rename endpoint to /images/upload (or similar)
|
|
|
|
apiRouter.post('/uploads',
|
|
|
|
authenticatePrivate,
|
|
|
|
upload.single('uploadimage'),
|
|
|
|
validation.upload({type: 'images'}),
|
|
|
|
api.http(api.uploads.add)
|
|
|
|
);
|
|
|
|
|
2017-01-26 12:01:52 +03:00
|
|
|
apiRouter.post('/uploads/icon',
|
|
|
|
authenticatePrivate,
|
|
|
|
upload.single('uploadimage'),
|
|
|
|
validation.upload({type: 'icons'}),
|
|
|
|
validation.blogIcon(),
|
|
|
|
api.http(api.uploads.add)
|
|
|
|
);
|
|
|
|
|
2016-10-11 11:36:00 +03:00
|
|
|
// ## Invites
|
|
|
|
apiRouter.get('/invites', authenticatePrivate, api.http(api.invites.browse));
|
|
|
|
apiRouter.get('/invites/:id', authenticatePrivate, api.http(api.invites.read));
|
|
|
|
apiRouter.post('/invites', authenticatePrivate, api.http(api.invites.add));
|
|
|
|
apiRouter.del('/invites/:id', authenticatePrivate, api.http(api.invites.destroy));
|
|
|
|
|
|
|
|
return apiRouter;
|
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = function setupApiApp() {
|
🎉 🎨 ✨ Remove middleware/index.js (#7548)
closes #4172, closes #6948, refs #7491, refs #7488, refs #7542, refs #7484
* 🎨 Co-locate all admin-related code in /admin
- move all the admin related code from controllers, routes and helpers into a single location
- add error handling middleware explicitly to adminApp
- re-order blogApp middleware to ensure the shared middleware is mounted after the adminApp
- TODO: rethink the structure of /admin, this should probably be an internal app
* 💄 Group global middleware together
- There are only a few pieces of middleware which are "global"
- These are needed for the admin, blog and api
- Everything else is only needed in one or two places
* ✨ Introduce a separate blogApp
- create a brand-new blogApp
- mount all blog/theme only middleware etc onto blogApp
- mount error handling on blogApp only
* 🎨 Separate error handling for HTML & API JSON
- split JSON and HTML error handling into separate functions
- re-introduce a way to not output the stack for certain errors
- add more tests around errors & an assertion framework for checking JSON Errors
- TODO: better 404 handling for static assets
Rationale:
The API is very different to the blog/admin panel:
- It is intended to only ever serve JSON, never HTML responses
- It is intended to always serve JSON
Meanwhile the blog and admin panel have no need for JSON errors,
when an error happens on those pages, we should serve HTML pages
which are nicely formatted with the error & using the correct template
* 🐛 Fix checkSSL to work for subapps
- in order to make this work on a sub app we need to use the pattern `req.originalUrl || req.url`
* 🔥 Get rid of decide-is-admin (part 1/2)
- delete decide-is-admin & tests
- add two small functions to apiApp and adminApp to set res.isAdmin
- mount checkSSL on all the apps
- TODO: deduplicate the calls to checkSSL by making blogApp a subApp :D
- PART 2/2: finish cleaning this up by removing it from where it's not needed and giving it a more specific name
Rationale:
Now that we have both an adminApp and an apiApp,
we can temporarily replace this weird path-matching middleware
with middleware that sets res.isAdmin for api & admin
* 🎨 Wire up prettyURLs on all Apps
- prettyURLs is needed for all requests
- it cannot be global because it has to live after asset middleware, and before routing
- this does not result in duplicate redirects, but does result in duplicate checks
- TODO: resolve extra middleware in stack by making blogApp a sub app
* ⏱ Add debug to API setup
* 🎨 Rename blogApp -> parentApp in middleware
* 🎨 Co-locate all blog-related code in /blog
- Move all of the blogApp code from middleware/index.js to blog/app.js
- Move routes/frontend.js to blog/routes.js
- Remove the routes/index.js and routes folder, this is empty now!
- @TODO is blog the best name for this? 🤔
- @TODO sort out the big hunk of asset-related mess
- @TODO also separate out the concept of theme from blog
* 🎉 Replace middleware index with server/app.js
- The final piece of the puzzle! 🎉 🎈 🎂
- We no longer have our horrendous middleware/index.js
- Instead, we have a set of app.js files, which all use a familiar pattern
* 💄 Error handling fixups
2016-10-13 18:24:09 +03:00
|
|
|
debug('API setup start');
|
2016-10-11 11:36:00 +03:00
|
|
|
var apiApp = express();
|
|
|
|
|
🎉 🎨 ✨ Remove middleware/index.js (#7548)
closes #4172, closes #6948, refs #7491, refs #7488, refs #7542, refs #7484
* 🎨 Co-locate all admin-related code in /admin
- move all the admin related code from controllers, routes and helpers into a single location
- add error handling middleware explicitly to adminApp
- re-order blogApp middleware to ensure the shared middleware is mounted after the adminApp
- TODO: rethink the structure of /admin, this should probably be an internal app
* 💄 Group global middleware together
- There are only a few pieces of middleware which are "global"
- These are needed for the admin, blog and api
- Everything else is only needed in one or two places
* ✨ Introduce a separate blogApp
- create a brand-new blogApp
- mount all blog/theme only middleware etc onto blogApp
- mount error handling on blogApp only
* 🎨 Separate error handling for HTML & API JSON
- split JSON and HTML error handling into separate functions
- re-introduce a way to not output the stack for certain errors
- add more tests around errors & an assertion framework for checking JSON Errors
- TODO: better 404 handling for static assets
Rationale:
The API is very different to the blog/admin panel:
- It is intended to only ever serve JSON, never HTML responses
- It is intended to always serve JSON
Meanwhile the blog and admin panel have no need for JSON errors,
when an error happens on those pages, we should serve HTML pages
which are nicely formatted with the error & using the correct template
* 🐛 Fix checkSSL to work for subapps
- in order to make this work on a sub app we need to use the pattern `req.originalUrl || req.url`
* 🔥 Get rid of decide-is-admin (part 1/2)
- delete decide-is-admin & tests
- add two small functions to apiApp and adminApp to set res.isAdmin
- mount checkSSL on all the apps
- TODO: deduplicate the calls to checkSSL by making blogApp a subApp :D
- PART 2/2: finish cleaning this up by removing it from where it's not needed and giving it a more specific name
Rationale:
Now that we have both an adminApp and an apiApp,
we can temporarily replace this weird path-matching middleware
with middleware that sets res.isAdmin for api & admin
* 🎨 Wire up prettyURLs on all Apps
- prettyURLs is needed for all requests
- it cannot be global because it has to live after asset middleware, and before routing
- this does not result in duplicate redirects, but does result in duplicate checks
- TODO: resolve extra middleware in stack by making blogApp a sub app
* ⏱ Add debug to API setup
* 🎨 Rename blogApp -> parentApp in middleware
* 🎨 Co-locate all blog-related code in /blog
- Move all of the blogApp code from middleware/index.js to blog/app.js
- Move routes/frontend.js to blog/routes.js
- Remove the routes/index.js and routes folder, this is empty now!
- @TODO is blog the best name for this? 🤔
- @TODO sort out the big hunk of asset-related mess
- @TODO also separate out the concept of theme from blog
* 🎉 Replace middleware index with server/app.js
- The final piece of the puzzle! 🎉 🎈 🎂
- We no longer have our horrendous middleware/index.js
- Instead, we have a set of app.js files, which all use a familiar pattern
* 💄 Error handling fixups
2016-10-13 18:24:09 +03:00
|
|
|
// @TODO finish refactoring this away.
|
|
|
|
apiApp.use(function setIsAdmin(req, res, next) {
|
2017-02-02 21:51:35 +03:00
|
|
|
// api === isAdmin
|
🎉 🎨 ✨ Remove middleware/index.js (#7548)
closes #4172, closes #6948, refs #7491, refs #7488, refs #7542, refs #7484
* 🎨 Co-locate all admin-related code in /admin
- move all the admin related code from controllers, routes and helpers into a single location
- add error handling middleware explicitly to adminApp
- re-order blogApp middleware to ensure the shared middleware is mounted after the adminApp
- TODO: rethink the structure of /admin, this should probably be an internal app
* 💄 Group global middleware together
- There are only a few pieces of middleware which are "global"
- These are needed for the admin, blog and api
- Everything else is only needed in one or two places
* ✨ Introduce a separate blogApp
- create a brand-new blogApp
- mount all blog/theme only middleware etc onto blogApp
- mount error handling on blogApp only
* 🎨 Separate error handling for HTML & API JSON
- split JSON and HTML error handling into separate functions
- re-introduce a way to not output the stack for certain errors
- add more tests around errors & an assertion framework for checking JSON Errors
- TODO: better 404 handling for static assets
Rationale:
The API is very different to the blog/admin panel:
- It is intended to only ever serve JSON, never HTML responses
- It is intended to always serve JSON
Meanwhile the blog and admin panel have no need for JSON errors,
when an error happens on those pages, we should serve HTML pages
which are nicely formatted with the error & using the correct template
* 🐛 Fix checkSSL to work for subapps
- in order to make this work on a sub app we need to use the pattern `req.originalUrl || req.url`
* 🔥 Get rid of decide-is-admin (part 1/2)
- delete decide-is-admin & tests
- add two small functions to apiApp and adminApp to set res.isAdmin
- mount checkSSL on all the apps
- TODO: deduplicate the calls to checkSSL by making blogApp a subApp :D
- PART 2/2: finish cleaning this up by removing it from where it's not needed and giving it a more specific name
Rationale:
Now that we have both an adminApp and an apiApp,
we can temporarily replace this weird path-matching middleware
with middleware that sets res.isAdmin for api & admin
* 🎨 Wire up prettyURLs on all Apps
- prettyURLs is needed for all requests
- it cannot be global because it has to live after asset middleware, and before routing
- this does not result in duplicate redirects, but does result in duplicate checks
- TODO: resolve extra middleware in stack by making blogApp a sub app
* ⏱ Add debug to API setup
* 🎨 Rename blogApp -> parentApp in middleware
* 🎨 Co-locate all blog-related code in /blog
- Move all of the blogApp code from middleware/index.js to blog/app.js
- Move routes/frontend.js to blog/routes.js
- Remove the routes/index.js and routes folder, this is empty now!
- @TODO is blog the best name for this? 🤔
- @TODO sort out the big hunk of asset-related mess
- @TODO also separate out the concept of theme from blog
* 🎉 Replace middleware index with server/app.js
- The final piece of the puzzle! 🎉 🎈 🎂
- We no longer have our horrendous middleware/index.js
- Instead, we have a set of app.js files, which all use a familiar pattern
* 💄 Error handling fixups
2016-10-13 18:24:09 +03:00
|
|
|
res.isAdmin = true;
|
|
|
|
next();
|
|
|
|
});
|
|
|
|
|
2016-10-11 11:36:00 +03:00
|
|
|
// API middleware
|
|
|
|
|
|
|
|
// Body parsing
|
|
|
|
apiApp.use(bodyParser.json({limit: '1mb'}));
|
|
|
|
apiApp.use(bodyParser.urlencoded({extended: true, limit: '1mb'}));
|
|
|
|
|
|
|
|
// send 503 json response in case of maintenance
|
|
|
|
apiApp.use(maintenance);
|
|
|
|
|
🎉 🎨 ✨ Remove middleware/index.js (#7548)
closes #4172, closes #6948, refs #7491, refs #7488, refs #7542, refs #7484
* 🎨 Co-locate all admin-related code in /admin
- move all the admin related code from controllers, routes and helpers into a single location
- add error handling middleware explicitly to adminApp
- re-order blogApp middleware to ensure the shared middleware is mounted after the adminApp
- TODO: rethink the structure of /admin, this should probably be an internal app
* 💄 Group global middleware together
- There are only a few pieces of middleware which are "global"
- These are needed for the admin, blog and api
- Everything else is only needed in one or two places
* ✨ Introduce a separate blogApp
- create a brand-new blogApp
- mount all blog/theme only middleware etc onto blogApp
- mount error handling on blogApp only
* 🎨 Separate error handling for HTML & API JSON
- split JSON and HTML error handling into separate functions
- re-introduce a way to not output the stack for certain errors
- add more tests around errors & an assertion framework for checking JSON Errors
- TODO: better 404 handling for static assets
Rationale:
The API is very different to the blog/admin panel:
- It is intended to only ever serve JSON, never HTML responses
- It is intended to always serve JSON
Meanwhile the blog and admin panel have no need for JSON errors,
when an error happens on those pages, we should serve HTML pages
which are nicely formatted with the error & using the correct template
* 🐛 Fix checkSSL to work for subapps
- in order to make this work on a sub app we need to use the pattern `req.originalUrl || req.url`
* 🔥 Get rid of decide-is-admin (part 1/2)
- delete decide-is-admin & tests
- add two small functions to apiApp and adminApp to set res.isAdmin
- mount checkSSL on all the apps
- TODO: deduplicate the calls to checkSSL by making blogApp a subApp :D
- PART 2/2: finish cleaning this up by removing it from where it's not needed and giving it a more specific name
Rationale:
Now that we have both an adminApp and an apiApp,
we can temporarily replace this weird path-matching middleware
with middleware that sets res.isAdmin for api & admin
* 🎨 Wire up prettyURLs on all Apps
- prettyURLs is needed for all requests
- it cannot be global because it has to live after asset middleware, and before routing
- this does not result in duplicate redirects, but does result in duplicate checks
- TODO: resolve extra middleware in stack by making blogApp a sub app
* ⏱ Add debug to API setup
* 🎨 Rename blogApp -> parentApp in middleware
* 🎨 Co-locate all blog-related code in /blog
- Move all of the blogApp code from middleware/index.js to blog/app.js
- Move routes/frontend.js to blog/routes.js
- Remove the routes/index.js and routes folder, this is empty now!
- @TODO is blog the best name for this? 🤔
- @TODO sort out the big hunk of asset-related mess
- @TODO also separate out the concept of theme from blog
* 🎉 Replace middleware index with server/app.js
- The final piece of the puzzle! 🎉 🎈 🎂
- We no longer have our horrendous middleware/index.js
- Instead, we have a set of app.js files, which all use a familiar pattern
* 💄 Error handling fixups
2016-10-13 18:24:09 +03:00
|
|
|
// Force SSL if required
|
|
|
|
// must happen AFTER asset loading and BEFORE routing
|
🔥✨ remove forceAdminSSL and urlSSL, add admin url (#7937)
* 🔥 kill apiUrl helper, use urlFor helper instead
More consistency of creating urls.
Creates an easier ability to add config changes.
Attention: urlFor function is getting a little nesty, BUT that is for now wanted to make easier and centralised changes to the configs.
The url util need's refactoring anyway.
* 🔥 urlSSL
Remove all urlSSL usages.
Add TODO's for the next commit to re-add logic for deleted logic.
e.g.
- cors helper generated an array of url's to allow requests from the defined config url's -> will be replaced by the admin url if available
- theme handler prefered the urlSSL in case it was defined -> will be replaced by using the urlFor helper to get the blog url (based on the request secure flag)
The changes in this commit doesn't have to be right, but it helped going step by step.
The next commit is the more interesting one.
* 🔥 ✨ remove forceAdminSSL, add new admin url and adapt logic
I wanted to remove the forceAdminSSL as separate commit, but was hard to realise.
That's why both changes are in one commit:
1. remove forceAdminSSL
2. add admin.url option
- fix TODO's from last commits
- rewrite the ssl middleware!
- create some private helper functions in the url helper to realise the changes
- rename some wordings and functions e.g. base === blog (we have so much different wordings)
- i would like to do more, but this would end in a non readable PR
- this commit contains the most important changes to offer admin.url option
* 🤖 adapt tests
IMPORTANT
- all changes in the routing tests were needed, because each routing test did not start the ghost server
- they just required the ghost application, which resulted in a random server port
- having a random server port results in a redirect, caused by the ssl/redirect middleware
* 😎 rename check-ssl middleware
* 🎨 fix theme-handler because of master rebase
2017-02-03 21:13:22 +03:00
|
|
|
apiApp.use(urlRedirects);
|
🎉 🎨 ✨ Remove middleware/index.js (#7548)
closes #4172, closes #6948, refs #7491, refs #7488, refs #7542, refs #7484
* 🎨 Co-locate all admin-related code in /admin
- move all the admin related code from controllers, routes and helpers into a single location
- add error handling middleware explicitly to adminApp
- re-order blogApp middleware to ensure the shared middleware is mounted after the adminApp
- TODO: rethink the structure of /admin, this should probably be an internal app
* 💄 Group global middleware together
- There are only a few pieces of middleware which are "global"
- These are needed for the admin, blog and api
- Everything else is only needed in one or two places
* ✨ Introduce a separate blogApp
- create a brand-new blogApp
- mount all blog/theme only middleware etc onto blogApp
- mount error handling on blogApp only
* 🎨 Separate error handling for HTML & API JSON
- split JSON and HTML error handling into separate functions
- re-introduce a way to not output the stack for certain errors
- add more tests around errors & an assertion framework for checking JSON Errors
- TODO: better 404 handling for static assets
Rationale:
The API is very different to the blog/admin panel:
- It is intended to only ever serve JSON, never HTML responses
- It is intended to always serve JSON
Meanwhile the blog and admin panel have no need for JSON errors,
when an error happens on those pages, we should serve HTML pages
which are nicely formatted with the error & using the correct template
* 🐛 Fix checkSSL to work for subapps
- in order to make this work on a sub app we need to use the pattern `req.originalUrl || req.url`
* 🔥 Get rid of decide-is-admin (part 1/2)
- delete decide-is-admin & tests
- add two small functions to apiApp and adminApp to set res.isAdmin
- mount checkSSL on all the apps
- TODO: deduplicate the calls to checkSSL by making blogApp a subApp :D
- PART 2/2: finish cleaning this up by removing it from where it's not needed and giving it a more specific name
Rationale:
Now that we have both an adminApp and an apiApp,
we can temporarily replace this weird path-matching middleware
with middleware that sets res.isAdmin for api & admin
* 🎨 Wire up prettyURLs on all Apps
- prettyURLs is needed for all requests
- it cannot be global because it has to live after asset middleware, and before routing
- this does not result in duplicate redirects, but does result in duplicate checks
- TODO: resolve extra middleware in stack by making blogApp a sub app
* ⏱ Add debug to API setup
* 🎨 Rename blogApp -> parentApp in middleware
* 🎨 Co-locate all blog-related code in /blog
- Move all of the blogApp code from middleware/index.js to blog/app.js
- Move routes/frontend.js to blog/routes.js
- Remove the routes/index.js and routes folder, this is empty now!
- @TODO is blog the best name for this? 🤔
- @TODO sort out the big hunk of asset-related mess
- @TODO also separate out the concept of theme from blog
* 🎉 Replace middleware index with server/app.js
- The final piece of the puzzle! 🎉 🎈 🎂
- We no longer have our horrendous middleware/index.js
- Instead, we have a set of app.js files, which all use a familiar pattern
* 💄 Error handling fixups
2016-10-13 18:24:09 +03:00
|
|
|
|
2016-10-11 11:36:00 +03:00
|
|
|
// Check version matches for API requests, depends on res.locals.safeVersion being set
|
|
|
|
// Therefore must come after themeHandler.ghostLocals, for now
|
|
|
|
apiApp.use(versionMatch);
|
|
|
|
|
|
|
|
// API shouldn't be cached
|
|
|
|
apiApp.use(cacheControl('private'));
|
|
|
|
|
|
|
|
// Routing
|
|
|
|
apiApp.use(apiRoutes());
|
|
|
|
|
|
|
|
// API error handling
|
🎉 🎨 ✨ Remove middleware/index.js (#7548)
closes #4172, closes #6948, refs #7491, refs #7488, refs #7542, refs #7484
* 🎨 Co-locate all admin-related code in /admin
- move all the admin related code from controllers, routes and helpers into a single location
- add error handling middleware explicitly to adminApp
- re-order blogApp middleware to ensure the shared middleware is mounted after the adminApp
- TODO: rethink the structure of /admin, this should probably be an internal app
* 💄 Group global middleware together
- There are only a few pieces of middleware which are "global"
- These are needed for the admin, blog and api
- Everything else is only needed in one or two places
* ✨ Introduce a separate blogApp
- create a brand-new blogApp
- mount all blog/theme only middleware etc onto blogApp
- mount error handling on blogApp only
* 🎨 Separate error handling for HTML & API JSON
- split JSON and HTML error handling into separate functions
- re-introduce a way to not output the stack for certain errors
- add more tests around errors & an assertion framework for checking JSON Errors
- TODO: better 404 handling for static assets
Rationale:
The API is very different to the blog/admin panel:
- It is intended to only ever serve JSON, never HTML responses
- It is intended to always serve JSON
Meanwhile the blog and admin panel have no need for JSON errors,
when an error happens on those pages, we should serve HTML pages
which are nicely formatted with the error & using the correct template
* 🐛 Fix checkSSL to work for subapps
- in order to make this work on a sub app we need to use the pattern `req.originalUrl || req.url`
* 🔥 Get rid of decide-is-admin (part 1/2)
- delete decide-is-admin & tests
- add two small functions to apiApp and adminApp to set res.isAdmin
- mount checkSSL on all the apps
- TODO: deduplicate the calls to checkSSL by making blogApp a subApp :D
- PART 2/2: finish cleaning this up by removing it from where it's not needed and giving it a more specific name
Rationale:
Now that we have both an adminApp and an apiApp,
we can temporarily replace this weird path-matching middleware
with middleware that sets res.isAdmin for api & admin
* 🎨 Wire up prettyURLs on all Apps
- prettyURLs is needed for all requests
- it cannot be global because it has to live after asset middleware, and before routing
- this does not result in duplicate redirects, but does result in duplicate checks
- TODO: resolve extra middleware in stack by making blogApp a sub app
* ⏱ Add debug to API setup
* 🎨 Rename blogApp -> parentApp in middleware
* 🎨 Co-locate all blog-related code in /blog
- Move all of the blogApp code from middleware/index.js to blog/app.js
- Move routes/frontend.js to blog/routes.js
- Remove the routes/index.js and routes folder, this is empty now!
- @TODO is blog the best name for this? 🤔
- @TODO sort out the big hunk of asset-related mess
- @TODO also separate out the concept of theme from blog
* 🎉 Replace middleware index with server/app.js
- The final piece of the puzzle! 🎉 🎈 🎂
- We no longer have our horrendous middleware/index.js
- Instead, we have a set of app.js files, which all use a familiar pattern
* 💄 Error handling fixups
2016-10-13 18:24:09 +03:00
|
|
|
apiApp.use(errorHandler.resourceNotFound);
|
|
|
|
apiApp.use(errorHandler.handleJSONResponse);
|
|
|
|
|
|
|
|
debug('API setup end');
|
2016-10-11 11:36:00 +03:00
|
|
|
|
|
|
|
return apiApp;
|
|
|
|
};
|