104 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			104 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
import { isEmpty } from 'lodash';
 | 
						|
 | 
						|
import { getUserById as _getUserById } from '../utils/user-stats';
 | 
						|
import {
 | 
						|
  getAccessTokenFromRequest,
 | 
						|
  errorTypes,
 | 
						|
  authHeaderNS
 | 
						|
} from '../utils/getSetAccessToken';
 | 
						|
import { homeLocation } from '../../../config/env';
 | 
						|
import { jwtSecret as _jwtSecret } from '../../../config/secrets';
 | 
						|
 | 
						|
import { wrapHandledError } from '../utils/create-handled-error';
 | 
						|
 | 
						|
const authRE = /^\/auth\//;
 | 
						|
const confirmEmailRE = /^\/confirm-email$/;
 | 
						|
const newsShortLinksRE = /^\/n\/|^\/p\//;
 | 
						|
const publicUserRE = /^\/api\/users\/get-public-profile$/;
 | 
						|
const publicUsernameRE = /^\/api\/users\/exists$/;
 | 
						|
const resubscribeRE = /^\/resubscribe\//;
 | 
						|
const showCertRE = /^\/certificate\/showCert\//;
 | 
						|
// note: signin may not have a trailing slash
 | 
						|
const signinRE = /^\/signin/;
 | 
						|
const statusRE = /^\/status\/ping$/;
 | 
						|
const unsubscribedRE = /^\/unsubscribed\//;
 | 
						|
const unsubscribeRE = /^\/u\/|^\/unsubscribe\/|^\/ue\//;
 | 
						|
const updateHooksRE = /^\/hooks\/update-paypal$|^\/hooks\/update-stripe$/;
 | 
						|
 | 
						|
// note: this would be replaced by webhooks later
 | 
						|
const donateRE = /^\/donate\/charge-stripe$/;
 | 
						|
 | 
						|
const _whiteListREs = [
 | 
						|
  authRE,
 | 
						|
  confirmEmailRE,
 | 
						|
  newsShortLinksRE,
 | 
						|
  publicUserRE,
 | 
						|
  publicUsernameRE,
 | 
						|
  resubscribeRE,
 | 
						|
  showCertRE,
 | 
						|
  signinRE,
 | 
						|
  statusRE,
 | 
						|
  unsubscribedRE,
 | 
						|
  unsubscribeRE,
 | 
						|
  updateHooksRE,
 | 
						|
  donateRE
 | 
						|
];
 | 
						|
 | 
						|
export function isWhiteListedPath(path, whiteListREs = _whiteListREs) {
 | 
						|
  return whiteListREs.some(re => re.test(path));
 | 
						|
}
 | 
						|
 | 
						|
export default ({ jwtSecret = _jwtSecret, getUserById = _getUserById } = {}) =>
 | 
						|
  function requestAuthorisation(req, res, next) {
 | 
						|
    const { path } = req;
 | 
						|
    if (!isWhiteListedPath(path)) {
 | 
						|
      const { accessToken, error, jwt } = getAccessTokenFromRequest(
 | 
						|
        req,
 | 
						|
        jwtSecret
 | 
						|
      );
 | 
						|
      if (!accessToken && error === errorTypes.noTokenFound) {
 | 
						|
        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
 | 
						|
          }
 | 
						|
        );
 | 
						|
      }
 | 
						|
      if (!accessToken && error === errorTypes.invalidToken) {
 | 
						|
        throw wrapHandledError(new Error('Access token is invalid'), {
 | 
						|
          type: 'info',
 | 
						|
          redirect: `${homeLocation}/signin`,
 | 
						|
          message: 'Your access token is invalid',
 | 
						|
          status: 403
 | 
						|
        });
 | 
						|
      }
 | 
						|
      if (!accessToken && error === errorTypes.expiredToken) {
 | 
						|
        throw wrapHandledError(new Error('Access token is no longer valid'), {
 | 
						|
          type: 'info',
 | 
						|
          redirect: `${homeLocation}/signin`,
 | 
						|
          message: 'Access token is no longer valid',
 | 
						|
          status: 403
 | 
						|
        });
 | 
						|
      }
 | 
						|
      res.set(authHeaderNS, jwt);
 | 
						|
      if (isEmpty(req.user)) {
 | 
						|
        const { userId } = accessToken;
 | 
						|
        return getUserById(userId)
 | 
						|
          .then(user => {
 | 
						|
            if (user) {
 | 
						|
              req.user = user;
 | 
						|
            }
 | 
						|
            return;
 | 
						|
          })
 | 
						|
          .then(next)
 | 
						|
          .catch(next);
 | 
						|
      } else {
 | 
						|
        return Promise.resolve(next());
 | 
						|
      }
 | 
						|
    }
 | 
						|
    return Promise.resolve(next());
 | 
						|
  };
 |