BVB Source Codes

parse-server Show middlewares.js Source code

Return Download parse-server: download middlewares.js Source code - Download parse-server Source code - Type:.js
  1. import AppCache from './cache';
  2. import log from './logger';
  3. import Parse from 'parse/node';
  4. import auth from './Auth';
  5. import Config from './Config';
  6. import ClientSDK from './ClientSDK';
  7.  
  8. // Checks that the request is authorized for this app and checks user
  9. // auth too.
  10. // The bodyparser should run before this middleware.
  11. // Adds info to the request:
  12. // req.config - the Config for this app
  13. // req.auth - the Auth for this request
  14. export function handleParseHeaders(req, res, next) {
  15.   var mountPathLength = req.originalUrl.length - req.url.length;
  16.   var mountPath = req.originalUrl.slice(0, mountPathLength);
  17.   var mount = req.protocol + '://' + req.get('host') + mountPath;
  18.  
  19.   var info = {
  20.     appId: req.get('X-Parse-Application-Id'),
  21.     sessionToken: req.get('X-Parse-Session-Token'),
  22.     masterKey: req.get('X-Parse-Master-Key'),
  23.     installationId: req.get('X-Parse-Installation-Id'),
  24.     clientKey: req.get('X-Parse-Client-Key'),
  25.     javascriptKey: req.get('X-Parse-Javascript-Key'),
  26.     dotNetKey: req.get('X-Parse-Windows-Key'),
  27.     restAPIKey: req.get('X-Parse-REST-API-Key'),
  28.     clientVersion: req.get('X-Parse-Client-Version')
  29.   };
  30.  
  31.   var basicAuth = httpAuth(req);
  32.  
  33.   if (basicAuth) {
  34.     var basicAuthAppId = basicAuth.appId;
  35.     if (AppCache.get(basicAuthAppId)) {
  36.       info.appId = basicAuthAppId;
  37.       info.masterKey = basicAuth.masterKey || info.masterKey;
  38.       info.javascriptKey = basicAuth.javascriptKey || info.javascriptKey;
  39.     }
  40.   }
  41.  
  42.   if (req.body) {
  43.     // Unity SDK sends a _noBody key which needs to be removed.
  44.     // Unclear at this point if action needs to be taken.
  45.     delete req.body._noBody;
  46.   }
  47.  
  48.   var fileViaJSON = false;
  49.  
  50.   if (!info.appId || !AppCache.get(info.appId)) {
  51.     // See if we can find the app id on the body.
  52.     if (req.body instanceof Buffer) {
  53.       // The only chance to find the app id is if this is a file
  54.       // upload that actually is a JSON body. So try to parse it.
  55.       req.body = JSON.parse(req.body);
  56.       fileViaJSON = true;
  57.     }
  58.  
  59.     if (req.body) {
  60.       delete req.body._RevocableSession;
  61.     }
  62.  
  63.     if (req.body &&
  64.       req.body._ApplicationId &&
  65.       AppCache.get(req.body._ApplicationId) &&
  66.       (!info.masterKey || AppCache.get(req.body._ApplicationId).masterKey === info.masterKey)
  67.     ) {
  68.       info.appId = req.body._ApplicationId;
  69.       info.javascriptKey = req.body._JavaScriptKey || '';
  70.       delete req.body._ApplicationId;
  71.       delete req.body._JavaScriptKey;
  72.       // TODO: test that the REST API formats generated by the other
  73.       // SDKs are handled ok
  74.       if (req.body._ClientVersion) {
  75.         info.clientVersion = req.body._ClientVersion;
  76.         delete req.body._ClientVersion;
  77.       }
  78.       if (req.body._InstallationId) {
  79.         info.installationId = req.body._InstallationId;
  80.         delete req.body._InstallationId;
  81.       }
  82.       if (req.body._SessionToken) {
  83.         info.sessionToken = req.body._SessionToken;
  84.         delete req.body._SessionToken;
  85.       }
  86.       if (req.body._MasterKey) {
  87.         info.masterKey = req.body._MasterKey;
  88.         delete req.body._MasterKey;
  89.       }
  90.       if (req.body._ContentType) {
  91.         req.headers['content-type'] = req.body._ContentType;
  92.         delete req.body._ContentType;
  93.       }
  94.     } else {
  95.       return invalidRequest(req, res);
  96.     }
  97.   }
  98.  
  99.   if (info.clientVersion) {
  100.     info.clientSDK = ClientSDK.fromString(info.clientVersion);
  101.   }
  102.  
  103.   if (fileViaJSON) {
  104.     // We need to repopulate req.body with a buffer
  105.     var base64 = req.body.base64;
  106.     req.body = new Buffer(base64, 'base64');
  107.   }
  108.  
  109.   info.app = AppCache.get(info.appId);
  110.   req.config = new Config(info.appId, mount);
  111.   req.info = info;
  112.  
  113.   var isMaster = (info.masterKey === req.config.masterKey);
  114.  
  115.   if (isMaster) {
  116.     req.auth = new auth.Auth({ config: req.config, installationId: info.installationId, isMaster: true });
  117.     next();
  118.     return;
  119.   }
  120.  
  121.   // Client keys are not required in parse-server, but if any have been configured in the server, validate them
  122.   //  to preserve original behavior.
  123.   const keys = ["clientKey", "javascriptKey", "dotNetKey", "restAPIKey"];
  124.   const oneKeyConfigured = keys.some(function(key) {
  125.     return req.config[key] !== undefined;
  126.   });
  127.   const oneKeyMatches = keys.some(function(key){
  128.     return req.config[key] !== undefined && info[key] === req.config[key];
  129.   });
  130.  
  131.   if (oneKeyConfigured && !oneKeyMatches) {
  132.     return invalidRequest(req, res);
  133.   }
  134.  
  135.   if (req.url == "/login") {
  136.     delete info.sessionToken;
  137.   }
  138.  
  139.   if (!info.sessionToken) {
  140.     req.auth = new auth.Auth({ config: req.config, installationId: info.installationId, isMaster: false });
  141.     next();
  142.     return;
  143.   }
  144.  
  145.   return Promise.resolve().then(() => {
  146.     // handle the upgradeToRevocableSession path on it's own
  147.     if (info.sessionToken &&
  148.         req.url === '/upgradeToRevocableSession' &&
  149.         info.sessionToken.indexOf('r:') != 0) {
  150.       return auth.getAuthForLegacySessionToken({ config: req.config, installationId: info.installationId, sessionToken: info.sessionToken })
  151.     } else {
  152.       return auth.getAuthForSessionToken({ config: req.config, installationId: info.installationId, sessionToken: info.sessionToken })
  153.     }
  154.   }).then((auth) => {
  155.     if (auth) {
  156.       req.auth = auth;
  157.       next();
  158.     }
  159.   })
  160.     .catch((error) => {
  161.       if(error instanceof Parse.Error) {
  162.         next(error);
  163.         return;
  164.       }
  165.       else {
  166.         // TODO: Determine the correct error scenario.
  167.         log.error('error getting auth for sessionToken', error);
  168.         throw new Parse.Error(Parse.Error.UNKNOWN_ERROR, error);
  169.       }
  170.     });
  171. }
  172.  
  173. function httpAuth(req) {
  174.   if (!(req.req || req).headers.authorization)
  175.     return ;
  176.  
  177.   var header = (req.req || req).headers.authorization;
  178.   var appId, masterKey, javascriptKey;
  179.  
  180.   // parse header
  181.   var authPrefix = 'basic ';
  182.  
  183.   var match = header.toLowerCase().indexOf(authPrefix);
  184.  
  185.   if (match == 0) {
  186.     var encodedAuth = header.substring(authPrefix.length, header.length);
  187.     var credentials = decodeBase64(encodedAuth).split(':');
  188.  
  189.     if (credentials.length == 2) {
  190.       appId = credentials[0];
  191.       var key = credentials[1];
  192.  
  193.       var jsKeyPrefix = 'javascript-key=';
  194.  
  195.       var matchKey = key.indexOf(jsKeyPrefix)
  196.       if (matchKey == 0) {
  197.         javascriptKey = key.substring(jsKeyPrefix.length, key.length);
  198.       }
  199.       else {
  200.         masterKey = key;
  201.       }
  202.     }
  203.   }
  204.  
  205.   return {appId: appId, masterKey: masterKey, javascriptKey: javascriptKey};
  206. }
  207.  
  208. function decodeBase64(str) {
  209.   return new Buffer(str, 'base64').toString()
  210. }
  211.  
  212. export function allowCrossDomain(req, res, next) {
  213.   res.header('Access-Control-Allow-Origin', '*');
  214.   res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
  215.   res.header('Access-Control-Allow-Headers', 'X-Parse-Master-Key, X-Parse-REST-API-Key, X-Parse-Javascript-Key, X-Parse-Application-Id, X-Parse-Client-Version, X-Parse-Session-Token, X-Requested-With, X-Parse-Revocable-Session, Content-Type');
  216.  
  217.   // intercept OPTIONS method
  218.   if ('OPTIONS' == req.method) {
  219.     res.sendStatus(200);
  220.   }
  221.   else {
  222.     next();
  223.   }
  224. }
  225.  
  226. export function allowMethodOverride(req, res, next) {
  227.   if (req.method === 'POST' && req.body._method) {
  228.     req.originalMethod = req.method;
  229.     req.method = req.body._method;
  230.     delete req.body._method;
  231.   }
  232.   next();
  233. }
  234.  
  235. export function handleParseErrors(err, req, res, next) {
  236.   if (err instanceof Parse.Error) {
  237.     let httpStatus;
  238.     // TODO: fill out this mapping
  239.     switch (err.code) {
  240.     case Parse.Error.INTERNAL_SERVER_ERROR:
  241.       httpStatus = 500;
  242.       break;
  243.     case Parse.Error.OBJECT_NOT_FOUND:
  244.       httpStatus = 404;
  245.       break;
  246.     default:
  247.       httpStatus = 400;
  248.     }
  249.  
  250.     res.status(httpStatus);
  251.     res.json({ code: err.code, error: err.message });
  252.     log.error(err.message, err);
  253.   } else if (err.status && err.message) {
  254.     res.status(err.status);
  255.     res.json({ error: err.message });
  256.     next(err);
  257.   } else {
  258.     log.error('Uncaught internal server error.', err, err.stack);
  259.     res.status(500);
  260.     res.json({
  261.       code: Parse.Error.INTERNAL_SERVER_ERROR,
  262.       message: 'Internal server error.'
  263.     });
  264.     next(err);
  265.   }
  266.  
  267. }
  268.  
  269. export function enforceMasterKeyAccess(req, res, next) {
  270.   if (!req.auth.isMaster) {
  271.     res.status(403);
  272.     res.end('{"error":"unauthorized: master key is required"}');
  273.     return;
  274.   }
  275.   next();
  276. }
  277.  
  278. export function promiseEnforceMasterKeyAccess(request) {
  279.   if (!request.auth.isMaster) {
  280.     const error = new Error();
  281.     error.status = 403;
  282.     error.message = "unauthorized: master key is required";
  283.     throw error;
  284.   }
  285.   return Promise.resolve();
  286. }
  287.  
  288. function invalidRequest(req, res) {
  289.   res.status(403);
  290.   res.end('{"error":"unauthorized"}');
  291. }
  292.  
downloadmiddlewares.js Source code - Download parse-server Source code
Related Source Codes/Software:
react-boilerplate - 2017-06-07
webtorrent - Streaming torrent client for the web ... 2017-06-06
machine-learning-for-software-engineers - A complete daily plan for studying to become a mac... 2017-06-06
upterm - A terminal emulator for the 21st century. 2017-06-06
lottie-android - Render After Effects animations natively on Androi... 2017-06-07
AsyncDisplayKit - Smooth asynchronous user interfaces for iOS apps. ... 2017-06-07
ionicons - The premium icon font for Ionic ... 2017-06-07
storybook - 2017-06-07
prettier - Prettier is an opinionated JavaScript formatter. ... 2017-06-08
CRYENGINE - CRYENGINE is a powerful real-time game development... 2017-06-11
postal - 2017-06-11
reactide - Reactide is the first dedicated IDE for React web ... 2017-06-11
rkt - rkt is a pod-native container engine for Linux. It... 2017-06-11
uWebSockets - Tiny WebSockets https://for... 2017-06-11
realworld - TodoMVC for the RealWorld - Exemplary fullstack Me... 2017-06-11
goreplay - GoReplay is an open-source tool for capturing and ... 2017-06-10
pyenv - Simple Python version management 2017-06-10
redux-saga - An alternative side effect model for Redux apps ... 2017-06-10
angular-starter - 2017-06-10

 Back to top