Build a blog with Areto Node.js framework

Sign in form

The login form receives a email / password and finds the appropriate user account in the database.

Sign-in form

model/SignInForm.js

const CAPTCHA_SCENARIO = 'captcha';
const Base = require('areto/base/Model');
module.exports = class SignInForm extends Base {
};
module.exports.init(module);
const async = require('areto/helper/AsyncHelper');
const RateLimit = require('areto/web/rate-limit/RateLimit');
const LoginByEmail = require('../component/auth/LoginByEmail');

Validation of form needed to filter invalid input values.

model/SignInForm.js

static getConstants () {
  return {
    RULES: [
      [['email', 'password'], 'required'],
      ['email', 'email'],
      ['password', 'string', {min: 6, max:24}],
      ['rememberMe', 'boolean'],
      ['captchaCode', 'required', {on: [CAPTCHA_SCENARIO]}],
      ['captchaCode', {
        Class: require('areto/captcha/CaptchaValidator'),
        on: [CAPTCHA_SCENARIO]
      }]
    ],
    ATTR_LABELS: {
      rememberMe: 'Remember me',
      captchaCode: 'Verification code'
    },
    CAPTCHA_SCENARIO
  };
}

The login method checks the form data. If there are no errors it passes control to the checkUser method that will search a user account in the database.

model/SignInForm.js

login (complete) {
  async.series([
    cb => this.validate(cb),
    cb => this.hasError() ? complete() : cb(),
    cb => async.waterfall([
      cb => this.createLoginByEmail().login(cb),
      (result, cb)=> {
        if (result.error) {
          this.addError('email', result.error);
        }
        this.updateRateLimit(cb);
      },
      cb => {
        this.toggleCaptchaScenario();
        cb();
      }
    ], cb)
  ], complete);
}

Look for user in checkUser by the unique login. This is the email. If the user with passed email exists, you will create a User instance. Its methods make further validate the user.

Pay attention to the same server response in cases of a non-existent user email and the wrong password. This disables the brute force of existing logins in the database.

In addition to authentication, the model checks account status. If a user is blocked, the server will return a message login error.

After successful validation webuser.login binds the current user's session to found a model. If the rememberMe flag is checked, the service's data will be added to the browser's cookies. It is required for automatic user log on to the given period (7 days).

model/SignInForm.js

constructor (config) {
  super(Object.assign({
    // user: new WebUser
    rateLimit: SignInForm.module.components.rateLimit,
    rateLimitType: 'signIn',
    rememberPeriod: 7 * 24 * 3600
  }, config));
}

createLoginByEmail () {
  return new LoginByEmail({
    'email': this.get('email'),
    'password': this.get('password'),
    'rememberMe': this.get('rememberMe'),
    'user': this.user
  });
}

updateRateLimit (cb) {
  if (!this._rateLimitModel) {
    return cb();
  }
  if (this.hasError()) {
    return this._rateLimitModel.increment(cb);
  }
  this.isCaptchaRequired() // captcha has been validated
    ? this._rateLimitModel.reset(cb)
    : cb();
}