lib/Realm.js

/*
 * @Author: caizeyong
 * @Date: 2020-12-02 13:07:39
 * @Description: 
 */
const AuthenticationToken = require('./AuthenticationToken')
const { TokenInvalidException,
  AuthenticationException } = require('./AuthException')

/**
 * @class
 * @classdesc 数据源类,主要用于通过调用 service/RPC/HTTP/model 等来为 subject 提供 认证 和 授权信息
 */
class Realm {
  /**
   * @constructor
   * @param {object} ctx egg's ctx
   */
  constructor (ctx) {
    /**
     * egg 的 ctx 对象,通过它来调用相关的其他资源
     * @public
     */
    this.ctx = ctx
  }
  /**
   * 判断当前 Realm 是否支持某种 Token 实例
   * @param {AuthenticationToken} token 
   */
  static supports (token) {
    return token instanceof AuthenticationToken
  }
  /**
   * 认证
   * @param {AuthenticationToken} token 认证 token 实例
   * @returns {object} 认证成功返回用户信息,包含的字段 id 用于给 token 设置 [uuid]{@link AuthenticationToken#uuid}
   * @throws {TokenInvalidException} token 非 AuthenticationToken 实例异常
   * @throws {AuthenticationException} 用户找不到异常,可在此处扩展异常类型来明确是账号或是密码不对
   */
  async authenticate (token) {
    if (token instanceof AuthenticationToken) {
      const user = await this.ctx.auth.user.findUserByAccountAndPassword(token.getPrincipals(), token.getCredentials())
      if (!user) {
        throw new AuthenticationException()
      }
      return user
    } else {
      throw new TokenInvalidException()
    }
  }
  /**
   * 获取角色
   * @param {AuthenticationToken} token 认证 token 实例
   * @returns {array<object>} 角色信息,每个角色必须包含结构 {id: xxx, name: yyy}
   * @throws {TokenInvalidException}
   */
  async getRoles (token) {
    if (token instanceof AuthenticationToken) {
      const roles = await this.ctx.auth.role.findRolesByUserID(token.getUUID())
      return roles.map(r => r.role)
    } else {
      throw new TokenInvalidException()
    }
  }
  /**
   * 通过角色 id 获取权限集合
   * @param {array<string|number>} roleIds 角色 id 集合
   * @returns {array<string>} 权限信息
   */
  async getPermissions (roleIds) {
    let permissions = await this.ctx.auth.permission.getPermissionsByRoleId(roleIds)
    permissions = permissions.map(p => {
      return p.permission.name
    })
    return permissions
  }
}

module.exports = Realm