Строим блог на Areto фреймворк

Модель пользователя

Класс модели пользователя User наследуется от >areto/db/ActiveRecord. Он отвечает за интерфейс аутентификации пользователя, а также за сохранение модели в базе данных.

model/User.js

const Base = require('areto/db/ActiveRecord');
module.exports = class User extends Base {
  // place methods here
};
module.exports.init(module);
const SecurityHelper = require('areto/helper/SecurityHelper');

В методе getConstants определяются статичные свойства класса.

  • TABLE - название таблицы, в которую сохраняется модель.
  • ATTRS - атрибуты модели, которые сохраняются в базу данных. В качестве идентификатора используется атрибут _id, который по умолчанию автоматически создается в MongoDB для каждой новой записи.

Статичные свойства доступны как через сам класса, так и его экземпляр: User.TABLE === (new User).TABLE === (new User).constructor.TABLE.

Для инициализации статичных свойств используется метод init, который вызывается сразу после определения класса. Аргументом ему передается значение текущего файла-модуля Node.js: module.exports.init(module).

model/User.js

static getConstants () {
  return {
    TABLE: 'user',
    ATTRS: [
      'name',
      'email',
      'role',
      'status',
      'passwordHash',
      'authKey'
    ],
    BEHAVIORS: {
      'timestamp': require('areto/behavior/TimestampBehavior')
    },
    STATUS_PENDING: 'penging',
    STATUS_ACTIVE: 'active',
    STATUS_BANNED: 'banned',
    ROLE_READER: 'reader',
    ROLE_AUTHOR: 'author',
    ROLE_EDITOR: 'editor',
    ROLE_MODERATOR: 'moderator',
    ROLE_ADMIN: 'admin',
    AUTH_KEY_LENGTH: 16
  };
}

Метод findIdentity находит в базе данных запись по указанному id и status === 'active'. Это необходимо при поиске идентифицированного пользователя по id, хранящемуся в сессии.

model/User.js

static findIdentity (id) {
 return this.findById(id).and({
    status: this.STATUS_ACTIVE
 });
}

Метод init вызывается сразу после создания модели. В нем проводится инициализация начальных значений атрибутов. При переопределении init для корректной работы класса необходимо вызывать родительский метод super.init.

model/User.js

constructor (config) {
  super(config);
  this.set('role', this.ROLE_AUTHOR);
  this.set('status', this.STATUS_ACTIVE);
}

Метод getTitle отдает название модели для отображения в различных случаях. По умолчанию используется id.

model/User.js

getTitle () {
  return this.get('name');
}

Вспомогательные методы isActive, isBanned для проверки текущего статуса пользователя.

model/User.js

isActive () {
  return this.get('status') === this.STATUS_ACTIVE;
}

isBanned () {
  return this.get('status') === this.STATUS_BANNED;
}

Метод getAssignments возвращает роль пользователя, хранящуюся в атрибуте role, что необходимо для авторизации доступа к ресурсам блога.

model/User.js

async getAssignments () {
  return [this.get('role')];
}

Метод beforeSave вызывается перед сохранением модели. Метод асинхронный, поэтому по окончанию работы должен быть вызван callback cb. Также при переопределении необходимо вызывать родительский метод.

model/User.js

async beforeSave (insert) {
  await super.beforeSave(insert);
  this.setPasswordHash();
  if (insert) {
    this.setAuthKey();
  }
}

setAuthKey () {
  this.set('authKey', SecurityHelper.generateRandomString(this.AUTH_KEY_LENGTH));
}

Последняя пара методов отвечают за работу с паролем пользователя. Для этого используется вспомогательный класс areto/helpers/Security, который подключается после инициализации User. В базе данных сохраняется только хэш пароля, полученный алгоритмом sha1.

model/User.js

validatePassword (password) {
  return SecurityHelper.validatePassword(password, this.get('passwordHash'));
}

setPasswordHash () {
  let password = this.get('password');
  if (password) {
    this.set('passwordHash', SecurityHelper.encryptPassword(password));
  }
}