Validity checks for a user signup process

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
1
down vote

favorite












Background:



I have been working on a service which allows users to signup on different apps and on each login checks if the request is valid or not based on a series of checks.



The below snippet is small part of the whole application but covers my question and is working fine for now:



Code:



'use strict';

const bcrypt = require('bcrypt');
const boom = require('boom');
const joi = require('joi');
const flatten = require('lodash/flatten');
const pick = require('lodash/pick');

const models = require('../../models');
const AccessToken, App, User = models;

const debug = require('debug')('microauth:test');

const loginSchema = joi
.object(
appname: joi.string().required(),
email: joi.string().required(),
password: joi.string().required(),
)
.required();

async function run(req, res, next)
const appname, email, password = joi.attempt(req.body, loginSchema);

const app = await getApp(appname);
if (!app)
throw boom.badRequest(`Invalid app name: $appname.`);

if (app.isInactive())
throw boom.badRequest('App is not active.');


const isAuthorized, user = await authorize( email, password );
if (!user)
throw boom.notFound('User not found.');

debug(`User $user.get('email') is authorised? $isAuthorized`);
if (!isAuthorized)
throw boom.unauthorized('Invalid email or password.');


const result = await isUserBelongsToApp(user, app.get('name'));
if (!result)
throw boom.badRequest(`User is not authorised to access app.`);


return successResponse(email, app.get('secret'), res);


async function getApp(name)
return await App.findOne( name );


async function authorize( email, password )
const user = await User.findOne(
email, status: 'active' ,
withRelated: ['apps', 'roles.permissions']
);

let isAuthorized = false;
if (user)
isAuthorized = await bcrypt.compare(password, user.get('password'));

return isAuthorized, user ;


async function isUserBelongsToApp(user, appname)
let result = false;
let app = null;
app = user.related('apps').findWhere( name: appname );
if (app)
result = true;

return result, app ;


async function successResponse(email, secret, res)
const userFields = [
'device',
'email',
'firstname',
'language',
'lastname',
'phone',
'uid',
];
const roleFields = ['name', 'description'];
const permissionFields = ['name', 'object', 'action'];

let user = await User.findOne(

email: email,
,

withRelated: ['roles.permissions'],

);
user = user.toJSON();
const result = Object.assign(, ...user );
result.roles = ;
result.permissions = ;

if (user.roles)
result.roles = user.roles.map(role => pick(role, roleFields));
result.permissions = user.roles.map(role =>
return role.permissions.map(permission =>
pick(permission, permissionFields)
);
);

result.permissions = flatten(result.permissions);
const token, expiration = new AccessToken(secret).create(result);
res.json( token, expiration );


module.exports = run;


Questions:



The code above belongs to the controller of the applications, is that the right place to do all these checks?



Right now the main logic seems pretty obvious but each step depends of the previous step. Is there any better way to write the same logic?







share|improve this question



























    up vote
    1
    down vote

    favorite












    Background:



    I have been working on a service which allows users to signup on different apps and on each login checks if the request is valid or not based on a series of checks.



    The below snippet is small part of the whole application but covers my question and is working fine for now:



    Code:



    'use strict';

    const bcrypt = require('bcrypt');
    const boom = require('boom');
    const joi = require('joi');
    const flatten = require('lodash/flatten');
    const pick = require('lodash/pick');

    const models = require('../../models');
    const AccessToken, App, User = models;

    const debug = require('debug')('microauth:test');

    const loginSchema = joi
    .object(
    appname: joi.string().required(),
    email: joi.string().required(),
    password: joi.string().required(),
    )
    .required();

    async function run(req, res, next)
    const appname, email, password = joi.attempt(req.body, loginSchema);

    const app = await getApp(appname);
    if (!app)
    throw boom.badRequest(`Invalid app name: $appname.`);

    if (app.isInactive())
    throw boom.badRequest('App is not active.');


    const isAuthorized, user = await authorize( email, password );
    if (!user)
    throw boom.notFound('User not found.');

    debug(`User $user.get('email') is authorised? $isAuthorized`);
    if (!isAuthorized)
    throw boom.unauthorized('Invalid email or password.');


    const result = await isUserBelongsToApp(user, app.get('name'));
    if (!result)
    throw boom.badRequest(`User is not authorised to access app.`);


    return successResponse(email, app.get('secret'), res);


    async function getApp(name)
    return await App.findOne( name );


    async function authorize( email, password )
    const user = await User.findOne(
    email, status: 'active' ,
    withRelated: ['apps', 'roles.permissions']
    );

    let isAuthorized = false;
    if (user)
    isAuthorized = await bcrypt.compare(password, user.get('password'));

    return isAuthorized, user ;


    async function isUserBelongsToApp(user, appname)
    let result = false;
    let app = null;
    app = user.related('apps').findWhere( name: appname );
    if (app)
    result = true;

    return result, app ;


    async function successResponse(email, secret, res)
    const userFields = [
    'device',
    'email',
    'firstname',
    'language',
    'lastname',
    'phone',
    'uid',
    ];
    const roleFields = ['name', 'description'];
    const permissionFields = ['name', 'object', 'action'];

    let user = await User.findOne(

    email: email,
    ,

    withRelated: ['roles.permissions'],

    );
    user = user.toJSON();
    const result = Object.assign(, ...user );
    result.roles = ;
    result.permissions = ;

    if (user.roles)
    result.roles = user.roles.map(role => pick(role, roleFields));
    result.permissions = user.roles.map(role =>
    return role.permissions.map(permission =>
    pick(permission, permissionFields)
    );
    );

    result.permissions = flatten(result.permissions);
    const token, expiration = new AccessToken(secret).create(result);
    res.json( token, expiration );


    module.exports = run;


    Questions:



    The code above belongs to the controller of the applications, is that the right place to do all these checks?



    Right now the main logic seems pretty obvious but each step depends of the previous step. Is there any better way to write the same logic?







    share|improve this question























      up vote
      1
      down vote

      favorite









      up vote
      1
      down vote

      favorite











      Background:



      I have been working on a service which allows users to signup on different apps and on each login checks if the request is valid or not based on a series of checks.



      The below snippet is small part of the whole application but covers my question and is working fine for now:



      Code:



      'use strict';

      const bcrypt = require('bcrypt');
      const boom = require('boom');
      const joi = require('joi');
      const flatten = require('lodash/flatten');
      const pick = require('lodash/pick');

      const models = require('../../models');
      const AccessToken, App, User = models;

      const debug = require('debug')('microauth:test');

      const loginSchema = joi
      .object(
      appname: joi.string().required(),
      email: joi.string().required(),
      password: joi.string().required(),
      )
      .required();

      async function run(req, res, next)
      const appname, email, password = joi.attempt(req.body, loginSchema);

      const app = await getApp(appname);
      if (!app)
      throw boom.badRequest(`Invalid app name: $appname.`);

      if (app.isInactive())
      throw boom.badRequest('App is not active.');


      const isAuthorized, user = await authorize( email, password );
      if (!user)
      throw boom.notFound('User not found.');

      debug(`User $user.get('email') is authorised? $isAuthorized`);
      if (!isAuthorized)
      throw boom.unauthorized('Invalid email or password.');


      const result = await isUserBelongsToApp(user, app.get('name'));
      if (!result)
      throw boom.badRequest(`User is not authorised to access app.`);


      return successResponse(email, app.get('secret'), res);


      async function getApp(name)
      return await App.findOne( name );


      async function authorize( email, password )
      const user = await User.findOne(
      email, status: 'active' ,
      withRelated: ['apps', 'roles.permissions']
      );

      let isAuthorized = false;
      if (user)
      isAuthorized = await bcrypt.compare(password, user.get('password'));

      return isAuthorized, user ;


      async function isUserBelongsToApp(user, appname)
      let result = false;
      let app = null;
      app = user.related('apps').findWhere( name: appname );
      if (app)
      result = true;

      return result, app ;


      async function successResponse(email, secret, res)
      const userFields = [
      'device',
      'email',
      'firstname',
      'language',
      'lastname',
      'phone',
      'uid',
      ];
      const roleFields = ['name', 'description'];
      const permissionFields = ['name', 'object', 'action'];

      let user = await User.findOne(

      email: email,
      ,

      withRelated: ['roles.permissions'],

      );
      user = user.toJSON();
      const result = Object.assign(, ...user );
      result.roles = ;
      result.permissions = ;

      if (user.roles)
      result.roles = user.roles.map(role => pick(role, roleFields));
      result.permissions = user.roles.map(role =>
      return role.permissions.map(permission =>
      pick(permission, permissionFields)
      );
      );

      result.permissions = flatten(result.permissions);
      const token, expiration = new AccessToken(secret).create(result);
      res.json( token, expiration );


      module.exports = run;


      Questions:



      The code above belongs to the controller of the applications, is that the right place to do all these checks?



      Right now the main logic seems pretty obvious but each step depends of the previous step. Is there any better way to write the same logic?







      share|improve this question













      Background:



      I have been working on a service which allows users to signup on different apps and on each login checks if the request is valid or not based on a series of checks.



      The below snippet is small part of the whole application but covers my question and is working fine for now:



      Code:



      'use strict';

      const bcrypt = require('bcrypt');
      const boom = require('boom');
      const joi = require('joi');
      const flatten = require('lodash/flatten');
      const pick = require('lodash/pick');

      const models = require('../../models');
      const AccessToken, App, User = models;

      const debug = require('debug')('microauth:test');

      const loginSchema = joi
      .object(
      appname: joi.string().required(),
      email: joi.string().required(),
      password: joi.string().required(),
      )
      .required();

      async function run(req, res, next)
      const appname, email, password = joi.attempt(req.body, loginSchema);

      const app = await getApp(appname);
      if (!app)
      throw boom.badRequest(`Invalid app name: $appname.`);

      if (app.isInactive())
      throw boom.badRequest('App is not active.');


      const isAuthorized, user = await authorize( email, password );
      if (!user)
      throw boom.notFound('User not found.');

      debug(`User $user.get('email') is authorised? $isAuthorized`);
      if (!isAuthorized)
      throw boom.unauthorized('Invalid email or password.');


      const result = await isUserBelongsToApp(user, app.get('name'));
      if (!result)
      throw boom.badRequest(`User is not authorised to access app.`);


      return successResponse(email, app.get('secret'), res);


      async function getApp(name)
      return await App.findOne( name );


      async function authorize( email, password )
      const user = await User.findOne(
      email, status: 'active' ,
      withRelated: ['apps', 'roles.permissions']
      );

      let isAuthorized = false;
      if (user)
      isAuthorized = await bcrypt.compare(password, user.get('password'));

      return isAuthorized, user ;


      async function isUserBelongsToApp(user, appname)
      let result = false;
      let app = null;
      app = user.related('apps').findWhere( name: appname );
      if (app)
      result = true;

      return result, app ;


      async function successResponse(email, secret, res)
      const userFields = [
      'device',
      'email',
      'firstname',
      'language',
      'lastname',
      'phone',
      'uid',
      ];
      const roleFields = ['name', 'description'];
      const permissionFields = ['name', 'object', 'action'];

      let user = await User.findOne(

      email: email,
      ,

      withRelated: ['roles.permissions'],

      );
      user = user.toJSON();
      const result = Object.assign(, ...user );
      result.roles = ;
      result.permissions = ;

      if (user.roles)
      result.roles = user.roles.map(role => pick(role, roleFields));
      result.permissions = user.roles.map(role =>
      return role.permissions.map(permission =>
      pick(permission, permissionFields)
      );
      );

      result.permissions = flatten(result.permissions);
      const token, expiration = new AccessToken(secret).create(result);
      res.json( token, expiration );


      module.exports = run;


      Questions:



      The code above belongs to the controller of the applications, is that the right place to do all these checks?



      Right now the main logic seems pretty obvious but each step depends of the previous step. Is there any better way to write the same logic?









      share|improve this question












      share|improve this question




      share|improve this question








      edited May 25 at 17:46









      200_success

      123k14143399




      123k14143399









      asked May 25 at 8:45









      CodeYogi

      1,99932060




      1,99932060




















          1 Answer
          1






          active

          oldest

          votes

















          up vote
          1
          down vote













          This is only a partial review.



          I would declare your constants outside of your functions, as they are constant.
          Also, the constants you did declare outside of your functions should be chained.
          Finally, you should never call a function more than once. If you are truly using functional-programming then you should do the following:



          const required = joi.string().required(),
          loginSchema = joi
          .object(
          appname: required,
          email: required,
          password: required,
          )
          .required();


          because a given function must return the same output for the same input.



          Rewrite



          'use strict';

          const bcrypt = require('bcrypt'),
          boom = require('boom'),
          joi = require('joi'),
          flatten = require('lodash/flatten'),
          pick = require('lodash/pick');

          const models = require('../../models'),
          AccessToken, App, User = models;

          const debug = require('debug')('microauth:test');

          const userFields = [
          'device',
          'email',
          'firstname',
          'language',
          'lastname',
          'phone',
          'uid',
          ],
          roleFields = ['name', 'description'],
          permissionFields = ['name', 'object', 'action'];

          const required - joi.string().required()
          const loginSchema = joi
          .object(
          appname: required,
          email: required,
          password: required,
          )
          .required();

          async function run(req, res, next)
          const appname, email, password = joi.attempt(req.body, loginSchema);

          const app = await getApp(appname);
          (!app) && (throw boom.badRequest(`Invalid app name: $appname.`);)

          (app.isInactive()) && (throw boom.badRequest('App is not active.');)

          const isAuthorized, user = await authorize( email, password );
          (!user) && (throw boom.notFound('User not found.');)

          debug(`User $user.get('email') is authorised? $isAuthorized`);
          (!isAuthorized) && (throw boom.unauthorized('Invalid email or password.');)

          const result = await isUserBelongsToApp(user, app.get('name'));
          (!result) && (throw boom.badRequest(`User is not authorised to access app.`);)

          return successResponse(email, app.get('secret'), res);


          async function getApp(name)
          return await App.findOne( name );


          async function authorize( email, password )
          const user = await User.findOne(
          email, status: 'active' ,
          withRelated: ['apps', 'roles.permissions']
          );

          let isAuthorized = false;
          if (user)
          isAuthorized = await bcrypt.compare(password, user.get('password'));

          return isAuthorized, user ;


          async function isUserBelongsToApp(user, appname)
          let result = false;
          let app = null;
          app = user.related('apps').findWhere( name: appname );
          if (app)
          result = true;

          return result, app ;


          async function successResponse(email, secret, res)

          let user = await User.findOne(

          email: email,
          ,

          withRelated: ['roles.permissions'],

          );
          user = user.toJSON();
          const result = Object.assign(, ...user );
          result.roles = ;
          result.permissions = ;

          if (user.roles)
          result.roles = user.roles.map(role => pick(role, roleFields));
          result.permissions = user.roles.map(role =>
          return role.permissions.map(permission =>
          pick(permission, permissionFields)
          );
          );

          result.permissions = flatten(result.permissions);
          const token, expiration = new AccessToken(secret).create(result);
          res.json( token, expiration );


          module.exports = run;





          share|improve this answer





















            Your Answer




            StackExchange.ifUsing("editor", function ()
            return StackExchange.using("mathjaxEditing", function ()
            StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
            StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
            );
            );
            , "mathjax-editing");

            StackExchange.ifUsing("editor", function ()
            StackExchange.using("externalEditor", function ()
            StackExchange.using("snippets", function ()
            StackExchange.snippets.init();
            );
            );
            , "code-snippets");

            StackExchange.ready(function()
            var channelOptions =
            tags: "".split(" "),
            id: "196"
            ;
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function()
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled)
            StackExchange.using("snippets", function()
            createEditor();
            );

            else
            createEditor();

            );

            function createEditor()
            StackExchange.prepareEditor(
            heartbeatType: 'answer',
            convertImagesToLinks: false,
            noModals: false,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: null,
            bindNavPrevention: true,
            postfix: "",
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            );



            );








             

            draft saved


            draft discarded


















            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f195141%2fvalidity-checks-for-a-user-signup-process%23new-answer', 'question_page');

            );

            Post as a guest






























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes








            up vote
            1
            down vote













            This is only a partial review.



            I would declare your constants outside of your functions, as they are constant.
            Also, the constants you did declare outside of your functions should be chained.
            Finally, you should never call a function more than once. If you are truly using functional-programming then you should do the following:



            const required = joi.string().required(),
            loginSchema = joi
            .object(
            appname: required,
            email: required,
            password: required,
            )
            .required();


            because a given function must return the same output for the same input.



            Rewrite



            'use strict';

            const bcrypt = require('bcrypt'),
            boom = require('boom'),
            joi = require('joi'),
            flatten = require('lodash/flatten'),
            pick = require('lodash/pick');

            const models = require('../../models'),
            AccessToken, App, User = models;

            const debug = require('debug')('microauth:test');

            const userFields = [
            'device',
            'email',
            'firstname',
            'language',
            'lastname',
            'phone',
            'uid',
            ],
            roleFields = ['name', 'description'],
            permissionFields = ['name', 'object', 'action'];

            const required - joi.string().required()
            const loginSchema = joi
            .object(
            appname: required,
            email: required,
            password: required,
            )
            .required();

            async function run(req, res, next)
            const appname, email, password = joi.attempt(req.body, loginSchema);

            const app = await getApp(appname);
            (!app) && (throw boom.badRequest(`Invalid app name: $appname.`);)

            (app.isInactive()) && (throw boom.badRequest('App is not active.');)

            const isAuthorized, user = await authorize( email, password );
            (!user) && (throw boom.notFound('User not found.');)

            debug(`User $user.get('email') is authorised? $isAuthorized`);
            (!isAuthorized) && (throw boom.unauthorized('Invalid email or password.');)

            const result = await isUserBelongsToApp(user, app.get('name'));
            (!result) && (throw boom.badRequest(`User is not authorised to access app.`);)

            return successResponse(email, app.get('secret'), res);


            async function getApp(name)
            return await App.findOne( name );


            async function authorize( email, password )
            const user = await User.findOne(
            email, status: 'active' ,
            withRelated: ['apps', 'roles.permissions']
            );

            let isAuthorized = false;
            if (user)
            isAuthorized = await bcrypt.compare(password, user.get('password'));

            return isAuthorized, user ;


            async function isUserBelongsToApp(user, appname)
            let result = false;
            let app = null;
            app = user.related('apps').findWhere( name: appname );
            if (app)
            result = true;

            return result, app ;


            async function successResponse(email, secret, res)

            let user = await User.findOne(

            email: email,
            ,

            withRelated: ['roles.permissions'],

            );
            user = user.toJSON();
            const result = Object.assign(, ...user );
            result.roles = ;
            result.permissions = ;

            if (user.roles)
            result.roles = user.roles.map(role => pick(role, roleFields));
            result.permissions = user.roles.map(role =>
            return role.permissions.map(permission =>
            pick(permission, permissionFields)
            );
            );

            result.permissions = flatten(result.permissions);
            const token, expiration = new AccessToken(secret).create(result);
            res.json( token, expiration );


            module.exports = run;





            share|improve this answer

























              up vote
              1
              down vote













              This is only a partial review.



              I would declare your constants outside of your functions, as they are constant.
              Also, the constants you did declare outside of your functions should be chained.
              Finally, you should never call a function more than once. If you are truly using functional-programming then you should do the following:



              const required = joi.string().required(),
              loginSchema = joi
              .object(
              appname: required,
              email: required,
              password: required,
              )
              .required();


              because a given function must return the same output for the same input.



              Rewrite



              'use strict';

              const bcrypt = require('bcrypt'),
              boom = require('boom'),
              joi = require('joi'),
              flatten = require('lodash/flatten'),
              pick = require('lodash/pick');

              const models = require('../../models'),
              AccessToken, App, User = models;

              const debug = require('debug')('microauth:test');

              const userFields = [
              'device',
              'email',
              'firstname',
              'language',
              'lastname',
              'phone',
              'uid',
              ],
              roleFields = ['name', 'description'],
              permissionFields = ['name', 'object', 'action'];

              const required - joi.string().required()
              const loginSchema = joi
              .object(
              appname: required,
              email: required,
              password: required,
              )
              .required();

              async function run(req, res, next)
              const appname, email, password = joi.attempt(req.body, loginSchema);

              const app = await getApp(appname);
              (!app) && (throw boom.badRequest(`Invalid app name: $appname.`);)

              (app.isInactive()) && (throw boom.badRequest('App is not active.');)

              const isAuthorized, user = await authorize( email, password );
              (!user) && (throw boom.notFound('User not found.');)

              debug(`User $user.get('email') is authorised? $isAuthorized`);
              (!isAuthorized) && (throw boom.unauthorized('Invalid email or password.');)

              const result = await isUserBelongsToApp(user, app.get('name'));
              (!result) && (throw boom.badRequest(`User is not authorised to access app.`);)

              return successResponse(email, app.get('secret'), res);


              async function getApp(name)
              return await App.findOne( name );


              async function authorize( email, password )
              const user = await User.findOne(
              email, status: 'active' ,
              withRelated: ['apps', 'roles.permissions']
              );

              let isAuthorized = false;
              if (user)
              isAuthorized = await bcrypt.compare(password, user.get('password'));

              return isAuthorized, user ;


              async function isUserBelongsToApp(user, appname)
              let result = false;
              let app = null;
              app = user.related('apps').findWhere( name: appname );
              if (app)
              result = true;

              return result, app ;


              async function successResponse(email, secret, res)

              let user = await User.findOne(

              email: email,
              ,

              withRelated: ['roles.permissions'],

              );
              user = user.toJSON();
              const result = Object.assign(, ...user );
              result.roles = ;
              result.permissions = ;

              if (user.roles)
              result.roles = user.roles.map(role => pick(role, roleFields));
              result.permissions = user.roles.map(role =>
              return role.permissions.map(permission =>
              pick(permission, permissionFields)
              );
              );

              result.permissions = flatten(result.permissions);
              const token, expiration = new AccessToken(secret).create(result);
              res.json( token, expiration );


              module.exports = run;





              share|improve this answer























                up vote
                1
                down vote










                up vote
                1
                down vote









                This is only a partial review.



                I would declare your constants outside of your functions, as they are constant.
                Also, the constants you did declare outside of your functions should be chained.
                Finally, you should never call a function more than once. If you are truly using functional-programming then you should do the following:



                const required = joi.string().required(),
                loginSchema = joi
                .object(
                appname: required,
                email: required,
                password: required,
                )
                .required();


                because a given function must return the same output for the same input.



                Rewrite



                'use strict';

                const bcrypt = require('bcrypt'),
                boom = require('boom'),
                joi = require('joi'),
                flatten = require('lodash/flatten'),
                pick = require('lodash/pick');

                const models = require('../../models'),
                AccessToken, App, User = models;

                const debug = require('debug')('microauth:test');

                const userFields = [
                'device',
                'email',
                'firstname',
                'language',
                'lastname',
                'phone',
                'uid',
                ],
                roleFields = ['name', 'description'],
                permissionFields = ['name', 'object', 'action'];

                const required - joi.string().required()
                const loginSchema = joi
                .object(
                appname: required,
                email: required,
                password: required,
                )
                .required();

                async function run(req, res, next)
                const appname, email, password = joi.attempt(req.body, loginSchema);

                const app = await getApp(appname);
                (!app) && (throw boom.badRequest(`Invalid app name: $appname.`);)

                (app.isInactive()) && (throw boom.badRequest('App is not active.');)

                const isAuthorized, user = await authorize( email, password );
                (!user) && (throw boom.notFound('User not found.');)

                debug(`User $user.get('email') is authorised? $isAuthorized`);
                (!isAuthorized) && (throw boom.unauthorized('Invalid email or password.');)

                const result = await isUserBelongsToApp(user, app.get('name'));
                (!result) && (throw boom.badRequest(`User is not authorised to access app.`);)

                return successResponse(email, app.get('secret'), res);


                async function getApp(name)
                return await App.findOne( name );


                async function authorize( email, password )
                const user = await User.findOne(
                email, status: 'active' ,
                withRelated: ['apps', 'roles.permissions']
                );

                let isAuthorized = false;
                if (user)
                isAuthorized = await bcrypt.compare(password, user.get('password'));

                return isAuthorized, user ;


                async function isUserBelongsToApp(user, appname)
                let result = false;
                let app = null;
                app = user.related('apps').findWhere( name: appname );
                if (app)
                result = true;

                return result, app ;


                async function successResponse(email, secret, res)

                let user = await User.findOne(

                email: email,
                ,

                withRelated: ['roles.permissions'],

                );
                user = user.toJSON();
                const result = Object.assign(, ...user );
                result.roles = ;
                result.permissions = ;

                if (user.roles)
                result.roles = user.roles.map(role => pick(role, roleFields));
                result.permissions = user.roles.map(role =>
                return role.permissions.map(permission =>
                pick(permission, permissionFields)
                );
                );

                result.permissions = flatten(result.permissions);
                const token, expiration = new AccessToken(secret).create(result);
                res.json( token, expiration );


                module.exports = run;





                share|improve this answer













                This is only a partial review.



                I would declare your constants outside of your functions, as they are constant.
                Also, the constants you did declare outside of your functions should be chained.
                Finally, you should never call a function more than once. If you are truly using functional-programming then you should do the following:



                const required = joi.string().required(),
                loginSchema = joi
                .object(
                appname: required,
                email: required,
                password: required,
                )
                .required();


                because a given function must return the same output for the same input.



                Rewrite



                'use strict';

                const bcrypt = require('bcrypt'),
                boom = require('boom'),
                joi = require('joi'),
                flatten = require('lodash/flatten'),
                pick = require('lodash/pick');

                const models = require('../../models'),
                AccessToken, App, User = models;

                const debug = require('debug')('microauth:test');

                const userFields = [
                'device',
                'email',
                'firstname',
                'language',
                'lastname',
                'phone',
                'uid',
                ],
                roleFields = ['name', 'description'],
                permissionFields = ['name', 'object', 'action'];

                const required - joi.string().required()
                const loginSchema = joi
                .object(
                appname: required,
                email: required,
                password: required,
                )
                .required();

                async function run(req, res, next)
                const appname, email, password = joi.attempt(req.body, loginSchema);

                const app = await getApp(appname);
                (!app) && (throw boom.badRequest(`Invalid app name: $appname.`);)

                (app.isInactive()) && (throw boom.badRequest('App is not active.');)

                const isAuthorized, user = await authorize( email, password );
                (!user) && (throw boom.notFound('User not found.');)

                debug(`User $user.get('email') is authorised? $isAuthorized`);
                (!isAuthorized) && (throw boom.unauthorized('Invalid email or password.');)

                const result = await isUserBelongsToApp(user, app.get('name'));
                (!result) && (throw boom.badRequest(`User is not authorised to access app.`);)

                return successResponse(email, app.get('secret'), res);


                async function getApp(name)
                return await App.findOne( name );


                async function authorize( email, password )
                const user = await User.findOne(
                email, status: 'active' ,
                withRelated: ['apps', 'roles.permissions']
                );

                let isAuthorized = false;
                if (user)
                isAuthorized = await bcrypt.compare(password, user.get('password'));

                return isAuthorized, user ;


                async function isUserBelongsToApp(user, appname)
                let result = false;
                let app = null;
                app = user.related('apps').findWhere( name: appname );
                if (app)
                result = true;

                return result, app ;


                async function successResponse(email, secret, res)

                let user = await User.findOne(

                email: email,
                ,

                withRelated: ['roles.permissions'],

                );
                user = user.toJSON();
                const result = Object.assign(, ...user );
                result.roles = ;
                result.permissions = ;

                if (user.roles)
                result.roles = user.roles.map(role => pick(role, roleFields));
                result.permissions = user.roles.map(role =>
                return role.permissions.map(permission =>
                pick(permission, permissionFields)
                );
                );

                result.permissions = flatten(result.permissions);
                const token, expiration = new AccessToken(secret).create(result);
                res.json( token, expiration );


                module.exports = run;






                share|improve this answer













                share|improve this answer



                share|improve this answer











                answered May 25 at 11:10









                FreezePhoenix

                310218




                310218






















                     

                    draft saved


                    draft discarded


























                     


                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function ()
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f195141%2fvalidity-checks-for-a-user-signup-process%23new-answer', 'question_page');

                    );

                    Post as a guest













































































                    Popular posts from this blog

                    Greedy Best First Search implementation in Rust

                    Function to Return a JSON Like Objects Using VBA Collections and Arrays

                    C++11 CLH Lock Implementation