为了账号安全,请及时绑定邮箱和手机立即绑定

【金秋打卡】第22天 作品的查询、更新,编写权限认证装饰器

标签:
Node.js

课程名称web前端架构师
课程章节:第16周 第八章 编写作品相关代码以及学习装饰器的使用
主讲老师:张轩
课程内容:作品的查询、更新,编写权限认证装饰器

作品的查询

首先编写查询条件接口

export interface IndexCondition {
  pageIndex?: number // 页码
  pageSize?: number // 数量
  select?: string | string[] // 查询字段
  // 关联结合
  populate?: string | { 
    path?: string
    select?: string
  }
  customSort?: Record<string, any> // 排序
  find?: Record<string, any> // 查询条件
}

定义默认的查询条件

const defaultIndexCondition:Required<IndexCondition> = {
  pageIndex: 0,
  pageSize: 10,
  populate: '',
  select: '',
  customSort: { createdAt: -1 },
  find: {},
};

获取列表

// app/service/Work.ts
  public async getList(condition: IndexCondition) {
    const { ctx } = this;
    const findCondition = { ...defaultIndexCondition, ...condition };
    const { find, pageIndex, pageSize, select, populate, customSort } = findCondition;
    const list = await ctx.model.Work.find(find).select(select)
      .populate(populate)
      .skip(pageIndex * pageSize)
      .limit(pageSize)
      .sort(customSort)
      .lean();

    const count = await ctx.model.Work.find(find).count();
    return {
      list,
      count,
    };
  }

获取用户传入的查询条件并将它改造成我们定义的查询条件的格式

// app/controller/work.ts
async myList() {
    const { ctx, service } = this;
    const userId = ctx.state.user._id;
    const { pageIndex, pageSize, isTemplate, title } = ctx.query;
    const listCondition: IndexCondition = {
      select: 'id author coverImg desc title user isHot createAt',
      populate: {
        path: 'user',
        select: 'username nickname picture',
      },
      find: {
        user: userId,
        ...(title && { title: { $regex: title } }),
        ...(isTemplate && { userId: !!parseInt(isTemplate) }),
      },
      ...(pageIndex && { pageIndex: parseInt(pageIndex) }),
      ...(pageSize && { pageSize: parseInt(pageSize) }),
    };
    const res = await service.work.getList(listCondition);
    ctx.helper.success({ ctx, res });
  }

更新和删除作品

在更新作品和删除作品之前都需要进行权限认证,判断是不是当前用户的作品,是的话才能进行删除

更新和删除的权限认证代码相似,所以我们可以将权限校验的代码写成装饰器,这样方便复用

下面编写权限认证装饰器, 用户可以传入结合名称和用户的 key,例如我们查询作品

const userId = ctx.state.user._id; // 用户 id
// 查询到该作品
const work = await ctx.model.Work.findOne({ id });
if(work.user.toString() !== userId){
  // 不是该作品的作者,没有权限修改
  ...
}
// 有权限修改
...
import { Controller } from 'egg';
import { errMsgType } from '../error';


/**
 * @param modelName 集合名称
 * @param errType 错误类型
 * @param userKey 用户在文档中的 key, 默认是 user
 * @return
 */
export default function checkPermission(modelName: string, errType: errMsgType, userKey = 'user') {
  return (_target, _propertyKey, descriptor: PropertyDescriptor) => {
    const originMethod = descriptor.value;
    descriptor.value = async function(...args:any[]) {
      const that = this as Controller;
      // eslint-disable-next-line @typescript-eslint/ban-ts-comment
      // @ts-ignore
      const { ctx } = that;
      const userId = ctx.state.user._id;
      const id = ctx.params.id;

      const work = await ctx.model[modelName].findOne({ id });
      if (!work || work[userKey].toString() !== userId) {
        return ctx.helper.error({ ctx, errType });
      }
      return originMethod.apply(this, ...args);
    };
  };
}

发布作品和发布为模版

发布作品和发布模版与修改作品很类似

  • 发布作品 status 修改为 2
    • status 1 未发布, 2 发布, 3 强制下线
  • 发布为模版 isTemplate 修改为 true
  • 修改作品 可以修改所有字段
// app/service/Work.ts
public async publish(id: string, isTemplate = false) {
  const { ctx } = this;
  const res = await ctx.model.Work.findOneAndUpdate({ id }, {
    status: 2,
    isTemplate,
  }, { new: true });
  return res;
}

发布和发布为模版只有 isTemplate 这一个字段不同

  @checkPermission('Work', 'workNoPermissonFail')
  async publish(isTemplate: boolean) {
    const { ctx, service } = this;
    const id = ctx.params.id;
    const res = await service.work.publish(id, isTemplate);
    ctx.helper.success({ ctx, res });
  }
  async publishWork() {
    await this.publish(true);
  }
  async publishTemplate() {
    await this.publish(false);
  }

图片描述

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
Python工程师
手记
粉丝
2
获赞与收藏
1

关注作者,订阅最新文章

阅读免费教程

  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消