2.1.11 • Published 3 years ago

ld-egg-frame v2.1.11

Weekly downloads
65
License
MIT
Repository
-
Last release
3 years ago

框架说明

端信息校验(auth/webAuth)

主要功能:登录用户身份信息校验
说明:依据client头字段进行不同端的校验,框架提供默认的`web=>app/middleware/webAuth.js`中间件,用户可以自定义其他端的中间件校验。
如果配置了接口权限校验,会根据用户信息进行接口权限校验。
// 自定义端信息校验案例(例如weapp中间校验)
// 新建中间件 app/middleware/weappAuth.js
module.exports = (opts, app) => {
  return async function weapp(ctx, next) {
    // 常用的写法
    if (ctx.request.header.client !== 'weapp') return await next();
    const jwtDecoded = ctx.getJwtDecoded();
    
    // TODO 业务处理
    ctx.weappUser = await app.getModel('weappUser').findById(jwtDecoded.userId);

    await next();
  };
};

// 配置 app/config/config.default.js, 新增配置
expotrs.middleware = [ 'weappAuth' ]
exports.weappAuth = {
    ... // 自定义需要的配置
}

配置

jwt配置
// 其他配置详见egg-jwt
{
    enable: true,
    access: ['GET /abc/cba'] // 配置jwt白名单,这里配置接口同时会跳过webAuth的校验
}
auth配置
// 如果关闭后,仅校验头部带client的接口,其他接口不做校验,默认开启
{ enable: true }
webAuth配置
{
    enable: true,
    interfaceEnable: true, // 是否开启接口校验
    // 通用接口,不进行接口校验,但是有进行token校验
    interfaceAccess: [
        'GET /user/menu',
        'GET /common/uptoken',
        'GET /common/upsetting',
        'GET /user/info',
    ],
}
安全配置(跨域)
exports.security = {
  origin: '',
  allowMethods: 'GET,HEAD,PUT,POST,DELETE,PATCH',
  csrf: { enable: false },
  domainWhiteList: [ 'http://localhost:9527' ],
};

基于mongoose封装的快捷方法

  // 查看某个值最大值的对象
  async max(field, filter = {}) {
    const res = await this.findOne(filter).sort({ [field]: -1 });
    return res;
  },
  // 查看某个值最小值的对象
  async min(field, filter = {}) {
    const res = await this.findOne(filter).sort({ [field]: 1 });
    return res;
  },
  // 查看某个值的最小值
  async minField(field, filter = {}) {
    const res = await this.findOne(filter, field).sort({ [field]: 1 });
    return res ? res._doc[field] : void 0;
  },
  // 查看某个值的最大值
  async maxField(field, filter = {}) {
    const res = await this.findOne(filter, field).sort({ [field]: -1 });
    return res ? res._doc[field] : void 0;
  },
  // 查找符合条件的id
  async findIds(filter = {}) {
    const docs = await this.find(filter, '_id');
    return docs.map(e => e.id);
  },
  // 查找符合条件的字段
  async findFields(filter = {}, key) {
    const docs = await this.find(filter, key);
    return docs.map(e => e[key]);
  },
  // 符合查询条件的内容是否存在
  async exist(filter) {
    const q = await this.countDocuments(filter);
    return q > 0;
  },
  // 查看id数组的数据是否全部
  async idsExist(ids) {
    const q = await this.countDocuments({ _id: { $in: ids } });
    return q === ids.length;
  },
  // 递增
  async inc(filter, doc) {
    if (isObjectId) filter = { _id: filter };
    return await this.update(filter, { $inc: doc });
  },
  // 列表查询
  async list(filter, page = 1, perPage = 10, select = null, opts = {}) {
    page = Number(page || 1);
    perPage = Number(perPage || 10);
    const skip = perPage * (page - 1);
    const sort = opts.sort || { createdAt: -1 };
    const list = await this.find(filter, select, _.omit(opts, [ 'sort' ])).skip(skip).limit(perPage)
      .sort(sort);
    const total = await this.countDocuments(filter);
    return {
      list,
      pagination: {
        perPage,
        page,
        total,
      },
    };
  },
  async getOne(filter, select = null, opts = {}) {
    if (isObjectId) filter = { _id: filter };
    const doc = await this.findOne(filter, select, opts);
    if (!doc) throw Error('getOne:未找到文档');
    return doc;
  },
  async update(id, data) {
    const doc = await this.findById(id);
    if (!doc) throw Error('update:未找到文档');
    Object.keys(data).forEach(k => { doc.set(k, data[k]); });
    doc.save();
    return doc;
  },
  async upsert(condition, data, opts = {}) {
    opts = Object.assign({ upsert: true, new: true }, opts);
    const old = await this.findOne(condition);
    if (!old) Object.assign(data, opts.initData || {});
    return await this.findOneAndUpdate(condition, data, opts);
  },
  async delete(id) {
    const doc = await this.findById(id);
    if (!doc) throw Error('delete:未找到文档');
    doc.remove();
    return doc;
  },

框架默认

默认表

user表
// 校验规则
exports.fields = {
  account: 'required|string',
  password: 'required|password',
  name: 'string',
  phoneNumber: 'mobile',
  roleIds: 'required|array',
  creatorId: 'objectId',
};

exports.update = {
  enable: [ 'name', 'roleIds', 'phoneNumber' ],
  privacy: [ 'password' ],
};
exports.fetch = {
  privacy: [ 'password' ],
};
exports.fetchAll = exports.fetchList = {
  input: {
    roleId: 'objectId',
  },
  search: [ 'account' ],
  privacy: [ 'password' ],
  async beforeHook() {
    const { ctx } = this;
    const roleId = ctx.input.roleId;
    if (roleId) {
      ctx.addFilter({
        roleIds: roleId,
      });
    }
  },
};

exports.destory = {
  privacy: [ 'password' ],
  async beforeHook() {
    const { ctx, app } = this;
    const operator = ctx.user;
    const delUser = await app.getModel('user').findById(ctx.params._id);
    if (delUser.account === 'super') ctx.throwBizError('超管用户不允许删除');
    if (operator.account !== 'super') ctx.throwBizError('仅允许超管删除用户');
  },
};


exports.autoRestful = true;
exports.zhName = '用户';
exports.support = [ 'update', 'fetchList', 'fetch', 'fetchAll', 'destory' ];
role表
exports.fields = {
  name: 'required|string',
  mark: 'string',
  menuIds: 'array',
  interfaceIds: 'array',
  permissions: 'required|array',
};

exports.create = {
  unique: [ 'name' ],
  default: { permissions: [] },
};

exports.update = {
  unique: [ 'name' ],
};
exports.fetchList = {
  search: [ 'name', 'mark' ],
};

exports.destory = {
  async afterHook(entity) {
    const { app } = this;
    await app.getModel('user').updateMany({ roleIds: entity.id }, { $pull: { roleIds: entity.id } });
  },
};
exports.zhName = '角色';
exports.autoRestful = true;
menu表
exports.fields = {
  path: 'required|string',
  component: 'required|string',
  name: 'required|string',
  meta: 'required|object',
  hide: 'boolean',
  alwaysShow: 'boolean',
  parentId: 'objectId',
  type: 'required|string|in:root,sub',
  interfaceIds: 'required|array',
};

exports.update = exports.create = {
  unique: [ 'name' ],
  async beforeHook() {
    const { ctx, app } = this;
    const input = ctx.input;
    if (input.type === 'sub' && !input.parentId) ctx.throwBizError('子菜单必须传父菜单Id');

    if (input.parentId) {
      const parentExist = await app.getModel('menu').qk.exist({ _id: input.parentId });
      if (!parentExist) ctx.throwBizError('父级菜单不存在');
    }

    const interfaceExist = await app.getModel('interface').qk.idsExist(input.interfaceIds);
    if (!interfaceExist) ctx.throwBizError('存在未知接口');

  },
};


exports.autoRestful = true;
exports.zhName = '菜单';
exports.support = [ 'create', 'update', 'fetch', 'destory' ];
interface表
exports.fields = {
  name: 'string',
  alias: 'string',
  path: 'required|string',
  mark: 'required|string',
  method: 'required|string',
  state: 'required|string',
  access: 'required|boolean',
};

exports.fetchAll = exports.fetchList = {
  search: [ 'name', 'mark' ],
  input: {
    access: 'boolean',
    state: 'string',
  },
  match: [ 'state', 'access' ],
};
exports.autoRestful = true;
exports.zhName = '接口';
exports.support = [ 'fetchAll', 'fetchList' ];

默认控制器

  • controller/common.js
  • controller/permission.js
  • controller/user.js
  • controller/web.js

默认服务

  • service/user.js
  • service/role.js
  • service/menu.js
  • service/interface.js

默认中间件

  • middleware/errorHandler.js
  • middleware/jwt.js

默认路由

  // 权限配置
  router.put('刷新接口信息', '/sys/permission/interface', controller.permission.refreshInterface);
  router.put('更新白名单接口', '/sys/permission/interface/access', controller.permission.updateAccessInterface);
  router.put('绑定角色', '/user/role', controller.permission.bindRole);
  router.put('配置角色权限', '/role/permission', controller.permission.setRolePermission);
  router.get('获取菜单树', '/menu/tree', controller.permission.getMenuTree);
  router.get('获取用户菜单树', '/user/menu', controller.permission.getUserMenu);
  router.get('获取用户信息', '/user/info', controller.user.getInfo);
  router.post('添加用户', '/user', controller.user.addUser);

  // 后台 登录注册
  router.post('后台登录', '/web/login', controller.web.login);
  router.post('后台注册', '/web/register', controller.web.register);

  // 资源上传
  router.get('获取OSS上传token', '/common/uptoken', controller.common.uptoken);
  router.get('获取OSS配置', '/common/upsetting', controller.common.uploadSetting);
  // 权限配置
  router.put('刷新接口信息', '/sys/permission/interface', controller.permission.refreshInterface);
  router.put('更新白名单接口', '/sys/permission/interface/access', controller.permission.updateAccessInterface);
  router.put('绑定角色', '/user/role', controller.permission.bindRole);
  router.put('配置角色权限', '/role/permission', controller.permission.setRolePermission);
  router.get('获取菜单树', '/menu/tree', controller.permission.getMenuTree);
  router.get('获取用户菜单树', '/user/menu', controller.permission.getUserMenu);
  router.get('获取用户信息', '/user/info', controller.user.getInfo);
  router.post('添加用户', '/user', controller.user.addUser);

  // 后台 登录注册
  router.post('后台登录', '/web/login', controller.web.login);
  router.post('后台注册', '/web/register', controller.web.register);

  // 资源上传
  router.get('获取OSS上传token', '/common/uptoken', controller.common.uptoken);
  router.get('获取OSS配置', '/common/upsetting', controller.common.uploadSetting);

备忘

  • 中间件的顺序:coreMiddleware > 插件中间件 > 应用中间件

参考

egg.js官网

2.1.11

3 years ago

2.1.10

3 years ago

2.1.9

3 years ago

2.1.8

3 years ago

2.1.7

3 years ago

2.1.6

3 years ago

2.1.5

3 years ago

2.1.2

3 years ago

2.0.3

3 years ago

2.1.1

3 years ago

2.0.2

3 years ago

2.1.3

3 years ago

2.1.0

3 years ago

2.0.1

3 years ago

2.0.0

3 years ago

1.0.31

3 years ago

1.0.30

3 years ago

1.0.29

3 years ago

1.0.26

3 years ago

1.0.25

3 years ago

1.0.24

3 years ago

1.0.28

3 years ago

1.0.27

3 years ago

1.0.22

3 years ago

1.0.23

3 years ago

1.0.21

3 years ago

1.0.20

3 years ago

1.0.19

3 years ago

1.0.18

3 years ago

1.0.17

3 years ago

1.0.16

3 years ago

1.0.15

3 years ago

1.0.14

3 years ago

1.0.13

3 years ago

1.0.12

3 years ago

1.0.11

3 years ago

1.0.10

3 years ago

1.0.9

3 years ago

1.0.8

3 years ago

1.0.7

3 years ago

1.0.6

3 years ago

1.0.5

3 years ago

1.0.4

3 years ago

1.0.3

3 years ago

1.0.2

3 years ago

1.0.1

3 years ago

1.0.0

3 years ago