2019-02-20 18:18:50 +00:00
|
|
|
import { isEmpty } from 'lodash';
|
2019-03-04 21:10:12 +00:00
|
|
|
|
|
|
|
import { getUserById as _getUserById } from '../utils/user-stats';
|
2019-02-20 23:05:31 +00:00
|
|
|
import {
|
|
|
|
getAccessTokenFromRequest,
|
|
|
|
errorTypes,
|
|
|
|
authHeaderNS
|
|
|
|
} from '../utils/getSetAccessToken';
|
2018-08-31 15:04:04 +00:00
|
|
|
import { homeLocation } from '../../../config/env';
|
2019-02-20 23:05:31 +00:00
|
|
|
import { jwtSecret as _jwtSecret } from '../../../config/secrets';
|
2018-08-29 19:52:41 +00:00
|
|
|
|
2018-05-23 20:10:56 +00:00
|
|
|
import { wrapHandledError } from '../utils/create-handled-error';
|
|
|
|
|
2018-11-29 12:12:15 +00:00
|
|
|
// We need to tunnel through a proxy path set up within
|
|
|
|
// the gatsby app, at this time, that path is /internal
|
2019-02-15 21:02:38 +00:00
|
|
|
const apiProxyRE = /^\/internal\/|^\/external\//;
|
|
|
|
const newsShortLinksRE = /^\/internal\/n\/|^\/internal\/p\?/;
|
|
|
|
const loopbackAPIPathRE = /^\/internal\/api\//;
|
|
|
|
|
2019-02-16 13:51:46 +00:00
|
|
|
const _whiteListREs = [newsShortLinksRE, loopbackAPIPathRE];
|
2019-02-15 21:02:38 +00:00
|
|
|
|
2019-02-16 13:51:46 +00:00
|
|
|
export function isWhiteListedPath(path, whiteListREs = _whiteListREs) {
|
|
|
|
return whiteListREs.some(re => re.test(path));
|
2019-02-15 21:02:38 +00:00
|
|
|
}
|
2018-11-29 12:12:15 +00:00
|
|
|
|
2019-02-20 23:05:31 +00:00
|
|
|
export default ({ jwtSecret = _jwtSecret, getUserById = _getUserById } = {}) =>
|
2019-02-20 18:18:50 +00:00
|
|
|
function requestAuthorisation(req, res, next) {
|
2019-02-16 13:51:46 +00:00
|
|
|
const { path } = req;
|
|
|
|
if (apiProxyRE.test(path) && !isWhiteListedPath(path)) {
|
2019-02-20 23:05:31 +00:00
|
|
|
const { accessToken, error, jwt } = getAccessTokenFromRequest(
|
|
|
|
req,
|
|
|
|
jwtSecret
|
|
|
|
);
|
|
|
|
if (!accessToken && error === errorTypes.noTokenFound) {
|
2019-02-16 13:51:46 +00:00
|
|
|
throw wrapHandledError(
|
|
|
|
new Error('Access token is required for this request'),
|
|
|
|
{
|
|
|
|
type: 'info',
|
|
|
|
redirect: `${homeLocation}/signin`,
|
|
|
|
message: 'Access token is required for this request',
|
|
|
|
status: 403
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
2019-02-20 23:05:31 +00:00
|
|
|
if (!accessToken && error === errorTypes.invalidToken) {
|
|
|
|
throw wrapHandledError(new Error('Access token is invalid'), {
|
2018-05-23 20:10:56 +00:00
|
|
|
type: 'info',
|
2018-08-29 19:52:41 +00:00
|
|
|
redirect: `${homeLocation}/signin`,
|
2018-05-23 20:10:56 +00:00
|
|
|
message: 'Your access token is invalid',
|
|
|
|
status: 403
|
2019-02-16 13:51:46 +00:00
|
|
|
});
|
|
|
|
}
|
2019-02-20 23:05:31 +00:00
|
|
|
if (!accessToken && error === errorTypes.expiredToken) {
|
2019-08-09 18:27:26 +00:00
|
|
|
throw wrapHandledError(new Error('Access token is no longer valid'), {
|
2018-05-23 20:10:56 +00:00
|
|
|
type: 'info',
|
2018-08-29 19:52:41 +00:00
|
|
|
redirect: `${homeLocation}/signin`,
|
2019-08-09 18:27:26 +00:00
|
|
|
message: 'Access token is no longer valid',
|
2018-05-23 20:10:56 +00:00
|
|
|
status: 403
|
2019-02-16 13:51:46 +00:00
|
|
|
});
|
|
|
|
}
|
2019-02-20 23:05:31 +00:00
|
|
|
res.set(authHeaderNS, jwt);
|
2019-02-20 18:18:50 +00:00
|
|
|
if (isEmpty(req.user)) {
|
2019-02-20 23:05:31 +00:00
|
|
|
const { userId } = accessToken;
|
2019-02-20 18:18:50 +00:00
|
|
|
return getUserById(userId)
|
2019-02-16 13:51:46 +00:00
|
|
|
.then(user => {
|
|
|
|
if (user) {
|
|
|
|
req.user = user;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
})
|
|
|
|
.then(next)
|
|
|
|
.catch(next);
|
|
|
|
} else {
|
2019-02-20 18:18:50 +00:00
|
|
|
return Promise.resolve(next());
|
2019-02-16 13:51:46 +00:00
|
|
|
}
|
2018-05-24 11:19:51 +00:00
|
|
|
}
|
2019-02-20 18:18:50 +00:00
|
|
|
return Promise.resolve(next());
|
2019-02-16 13:51:46 +00:00
|
|
|
};
|