BVB Source Codes

parse-server Show UsersRouter.js Source code

Return Download parse-server: download UsersRouter.js Source code - Download parse-server Source code - Type:.js
  1. // These methods handle the User-related routes.
  2.  
  3. import deepcopy       from 'deepcopy';
  4. import Parse          from 'parse/node';
  5. import Config         from '../Config';
  6. import AccountLockout from '../AccountLockout';
  7. import ClassesRouter  from './ClassesRouter';
  8. import rest           from '../rest';
  9. import Auth           from '../Auth';
  10. import passwordCrypto from '../password';
  11. import RestWrite      from '../RestWrite';
  12. const cryptoUtils = require('../cryptoUtils');
  13.  
  14. export class UsersRouter extends ClassesRouter {
  15.   handleFind(req) {
  16.     req.params.className = '_User';
  17.     return super.handleFind(req);
  18.   }
  19.  
  20.   handleGet(req) {
  21.     req.params.className = '_User';
  22.     return super.handleGet(req);
  23.   }
  24.  
  25.   handleCreate(req) {
  26.     const data = deepcopy(req.body);
  27.     req.body = data;
  28.     req.params.className = '_User';
  29.  
  30.     return super.handleCreate(req);
  31.   }
  32.  
  33.   handleUpdate(req) {
  34.     req.params.className = '_User';
  35.     return super.handleUpdate(req);
  36.   }
  37.  
  38.   handleDelete(req) {
  39.     req.params.className = '_User';
  40.     return super.handleDelete(req);
  41.   }
  42.  
  43.   handleMe(req) {
  44.     if (!req.info || !req.info.sessionToken) {
  45.       throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'invalid session token');
  46.     }
  47.     const sessionToken = req.info.sessionToken;
  48.     return rest.find(req.config, Auth.master(req.config), '_Session',
  49.       { sessionToken },
  50.       { include: 'user' }, req.info.clientSDK)
  51.       .then((response) => {
  52.         if (!response.results ||
  53.           response.results.length == 0 ||
  54.           !response.results[0].user) {
  55.           throw new Parse.Error(Parse.Error.INVALID_SESSION_TOKEN, 'invalid session token');
  56.         } else {
  57.           const user = response.results[0].user;
  58.           // Send token back on the login, because SDKs expect that.
  59.           user.sessionToken = sessionToken;
  60.  
  61.           // Remove hidden properties.
  62.           for (var key in user) {
  63.             if (user.hasOwnProperty(key)) {
  64.               // Regexp comes from Parse.Object.prototype.validate
  65.               if (key !== "__type" && !(/^[A-Za-z][0-9A-Za-z_]*$/).test(key)) {
  66.                 delete user[key];
  67.               }
  68.             }
  69.           }
  70.  
  71.           return { response: user };
  72.         }
  73.       });
  74.   }
  75.  
  76.   handleLogIn(req) {
  77.     // Use query parameters instead if provided in url
  78.     if (!req.body.username && req.query.username) {
  79.       req.body = req.query;
  80.     }
  81.  
  82.     // TODO: use the right error codes / descriptions.
  83.     if (!req.body.username) {
  84.       throw new Parse.Error(Parse.Error.USERNAME_MISSING, 'username is required.');
  85.     }
  86.     if (!req.body.password) {
  87.       throw new Parse.Error(Parse.Error.PASSWORD_MISSING, 'password is required.');
  88.     }
  89.     if (typeof req.body.username !== 'string' || typeof req.body.password !== 'string') {
  90.       throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Invalid username/password.');
  91.     }
  92.  
  93.     let user;
  94.     let isValidPassword = false;
  95.  
  96.     return req.config.database.find('_User', { username: req.body.username })
  97.       .then((results) => {
  98.         if (!results.length) {
  99.           throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Invalid username/password.');
  100.         }
  101.         user = results[0];
  102.  
  103.         if (req.config.verifyUserEmails && req.config.preventLoginWithUnverifiedEmail && !user.emailVerified) {
  104.           throw new Parse.Error(Parse.Error.EMAIL_NOT_FOUND, 'User email is not verified.');
  105.         }
  106.         return passwordCrypto.compare(req.body.password, user.password);
  107.       })
  108.       .then((correct) => {
  109.         isValidPassword = correct;
  110.         const accountLockoutPolicy = new AccountLockout(user, req.config);
  111.         return accountLockoutPolicy.handleLoginAttempt(isValidPassword);
  112.       })
  113.       .then(() => {
  114.         if (!isValidPassword) {
  115.           throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Invalid username/password.');
  116.         }
  117.  
  118.         // handle password expiry policy
  119.         if (req.config.passwordPolicy && req.config.passwordPolicy.maxPasswordAge) {
  120.           let changedAt = user._password_changed_at;
  121.  
  122.           if (!changedAt) {
  123.             // password was created before expiry policy was enabled.
  124.             // simply update _User object so that it will start enforcing from now
  125.             changedAt = new Date();
  126.             req.config.database.update('_User', {username: user.username},
  127.               {_password_changed_at: Parse._encode(changedAt)});
  128.           } else {
  129.             // check whether the password has expired
  130.             if (changedAt.__type == 'Date') {
  131.               changedAt = new Date(changedAt.iso);
  132.             }
  133.             // Calculate the expiry time.
  134.             const expiresAt = new Date(changedAt.getTime() + 86400000 * req.config.passwordPolicy.maxPasswordAge);
  135.             if (expiresAt < new Date()) // fail of current time is past password expiry time
  136.               throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Your password has expired. Please reset your password.');
  137.           }
  138.         }
  139.  
  140.         const token = 'r:' + cryptoUtils.newToken();
  141.         user.sessionToken = token;
  142.         delete user.password;
  143.  
  144.         // Sometimes the authData still has null on that keys
  145.         // https://github.com/ParsePlatform/parse-server/issues/935
  146.         if (user.authData) {
  147.           Object.keys(user.authData).forEach((provider) => {
  148.             if (user.authData[provider] === null) {
  149.               delete user.authData[provider];
  150.             }
  151.           });
  152.           if (Object.keys(user.authData).length == 0) {
  153.             delete user.authData;
  154.           }
  155.         }
  156.  
  157.         req.config.filesController.expandFilesInObject(req.config, user);
  158.  
  159.         const expiresAt = req.config.generateSessionExpiresAt();
  160.         const sessionData = {
  161.           sessionToken: token,
  162.           user: {
  163.             __type: 'Pointer',
  164.             className: '_User',
  165.             objectId: user.objectId
  166.           },
  167.           createdWith: {
  168.             'action': 'login',
  169.             'authProvider': 'password'
  170.           },
  171.           restricted: false,
  172.           expiresAt: Parse._encode(expiresAt)
  173.         };
  174.  
  175.         if (req.info.installationId) {
  176.           sessionData.installationId = req.info.installationId
  177.         }
  178.  
  179.         const create = new RestWrite(req.config, Auth.master(req.config), '_Session', null, sessionData);
  180.         return create.execute();
  181.       }).then(() => {
  182.         return { response: user };
  183.       });
  184.   }
  185.  
  186.   handleLogOut(req) {
  187.     const success = {response: {}};
  188.     if (req.info && req.info.sessionToken) {
  189.       return rest.find(req.config, Auth.master(req.config), '_Session',
  190.         { sessionToken: req.info.sessionToken }, undefined, req.info.clientSDK
  191.       ).then((records) => {
  192.         if (records.results && records.results.length) {
  193.           return rest.del(req.config, Auth.master(req.config), '_Session',
  194.             records.results[0].objectId
  195.           ).then(() => {
  196.             return Promise.resolve(success);
  197.           });
  198.         }
  199.         return Promise.resolve(success);
  200.       });
  201.     }
  202.     return Promise.resolve(success);
  203.   }
  204.  
  205.   _throwOnBadEmailConfig(req) {
  206.     try {
  207.       Config.validateEmailConfiguration({
  208.         emailAdapter: req.config.userController.adapter,
  209.         appName: req.config.appName,
  210.         publicServerURL: req.config.publicServerURL,
  211.         emailVerifyTokenValidityDuration: req.config.emailVerifyTokenValidityDuration
  212.       });
  213.     } catch (e) {
  214.       if (typeof e === 'string') {
  215.         // Maybe we need a Bad Configuration error, but the SDKs won't understand it. For now, Internal Server Error.
  216.         throw new Parse.Error(Parse.Error.INTERNAL_SERVER_ERROR, 'An appName, publicServerURL, and emailAdapter are required for password reset and email verification functionality.');
  217.       } else {
  218.         throw e;
  219.       }
  220.     }
  221.   }
  222.  
  223.   handleResetRequest(req) {
  224.     this._throwOnBadEmailConfig(req);
  225.  
  226.     const { email } = req.body;
  227.     if (!email) {
  228.       throw new Parse.Error(Parse.Error.EMAIL_MISSING, "you must provide an email");
  229.     }
  230.     if (typeof email !== 'string') {
  231.       throw new Parse.Error(Parse.Error.INVALID_EMAIL_ADDRESS, 'you must provide a valid email string');
  232.     }
  233.     const userController = req.config.userController;
  234.     return userController.sendPasswordResetEmail(email).then(() => {
  235.       return Promise.resolve({
  236.         response: {}
  237.       });
  238.     }, err => {
  239.       if (err.code === Parse.Error.OBJECT_NOT_FOUND) {
  240.         throw new Parse.Error(Parse.Error.EMAIL_NOT_FOUND, `No user found with email ${email}.`);
  241.       } else {
  242.         throw err;
  243.       }
  244.     });
  245.   }
  246.  
  247.   handleVerificationEmailRequest(req) {
  248.     this._throwOnBadEmailConfig(req);
  249.  
  250.     const { email } = req.body;
  251.     if (!email) {
  252.       throw new Parse.Error(Parse.Error.EMAIL_MISSING, 'you must provide an email');
  253.     }
  254.     if (typeof email !== 'string') {
  255.       throw new Parse.Error(Parse.Error.INVALID_EMAIL_ADDRESS, 'you must provide a valid email string');
  256.     }
  257.  
  258.     return req.config.database.find('_User', { email: email }).then((results) => {
  259.       if (!results.length || results.length < 1) {
  260.         throw new Parse.Error(Parse.Error.EMAIL_NOT_FOUND, `No user found with email ${email}`);
  261.       }
  262.       const user = results[0];
  263.  
  264.       if (user.emailVerified) {
  265.         throw new Parse.Error(Parse.Error.OTHER_CAUSE, `Email ${email} is already verified.`);
  266.       }
  267.  
  268.       const userController = req.config.userController;
  269.       userController.sendVerificationEmail(user);
  270.       return { response: {} };
  271.     });
  272.   }
  273.  
  274.  
  275.   mountRoutes() {
  276.     this.route('GET', '/users', req => { return this.handleFind(req); });
  277.     this.route('POST', '/users', req => { return this.handleCreate(req); });
  278.     this.route('GET', '/users/me', req => { return this.handleMe(req); });
  279.     this.route('GET', '/users/:objectId', req => { return this.handleGet(req); });
  280.     this.route('PUT', '/users/:objectId', req => { return this.handleUpdate(req); });
  281.     this.route('DELETE', '/users/:objectId', req => { return this.handleDelete(req); });
  282.     this.route('GET', '/login', req => { return this.handleLogIn(req); });
  283.     this.route('POST', '/logout', req => { return this.handleLogOut(req); });
  284.     this.route('POST', '/requestPasswordReset', req => { return this.handleResetRequest(req); });
  285.     this.route('POST', '/verificationEmailRequest', req => { return this.handleVerificationEmailRequest(req); });
  286.   }
  287. }
  288.  
  289. export default UsersRouter;
  290.  
downloadUsersRouter.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