用户组织权限管理系统(基于Nest.js)

3 篇文章 0 订阅

用户组织权限管理系统

技术栈:

  • 前端:Vue + ElementUi + TypeScript
  • 后端:nest.js + mysql + redis

演示地址

用户组织管理系统(演示地址)
github

功能设计

BSp-blog.png

数据库设计

用户实体
@Entity()
export class User {
  @PrimaryGeneratedColumn()
  id: number;

  @Column({ length: 500 })
  name: string;

  @Column({nullable: true, type: 'text'})
  desc: string;

  @Column({
    nullable: true,
    length: 100,
    select: false,
  })
  password: string;

  @Column( {select: false} )
  email: string;

  @Column({nullable: true})
  age: string;

  @Column({nullable: true})
  address: string;

  @Column({nullable: true})
  nick: string;

  @Column({default: 0})
  status: number;

  @ManyToOne(type => Role, role => role.users)
  role: Role;

  @ManyToMany( type => Organization, orientation => orientation.users)
  organizations: Organization[];

  @Column({default: 0})
  isDelete: number;

  @Column({default: '', nullable: true })
  crateTime: string;

  @Column({default: '', nullable: true })
  updateTime: string;

  @Column({default: '', nullable: true })
  deleteTime: string;
}

角色实体
@Entity()
export class Role {
  @PrimaryGeneratedColumn()
  id: number;

  @Column({ length: 500 })
  name: string;

  @Column('text', {nullable: true})
  desc: string;

  @Column()
  code: string;

  @ManyToMany(type => Authority, authority => authority.roles)
  @JoinTable()
  authority: Authority[];

  @OneToMany(type => User, user => user.role)
  users: User[];

  @Column({default: 0})
  isDelete: number;

  @Column({default: '', nullable: true })
  crateTime: string;

  @Column({default: '', nullable: true })
  updateTime: string;

  @Column({default: '', nullable: true })
  deleteTime: string;
}
资源实体
@Entity()
export class Authority {
  @PrimaryGeneratedColumn()
  id: number;

  @Column({ length: 500 })
  name: string;

  @Column('text', {nullable: true})
  desc: string;

  @Column()
  path: string;

  @Column()
  value: string;

  @Column()
  parentId: number;

  @Column({default: '', nullable: true })
  parentName: string;

  @Column({nullable: true})
  icon: string;

  @Column({nullable: false})
  system: string;

  @Column()
  code: string;

  @ManyToMany(type => Role, role => role.authority)
  roles: Role[];

  @Column({default: 0})
  isDelete: number;

  @Column({default: '', nullable: true })
  crateTime: string;

  @Column({default: '', nullable: true })
  updateTime: string;

  @Column({default: '', nullable: true })
  deleteTime: string;
}

API实现

数据库配置(main.module.ts)
TypeOrmModule.forRoot(
        {
          type: 'mysql',
          host: mysqlConfig.host,
          port: 3306,
          username: mysqlConfig.userName,
          password: mysqlConfig.password,
          database: 'b_simple_user_center',
          entities: [join(__dirname, '**/**.entity{.ts,.js}')],
          synchronize: true,
        },
    ),
全局缓存
CacheModule.register({
          store: redisStore,
          host: redisCacheConfig.host,
          port: redisCacheConfig.port,
          ttl: redisCacheConfig.ttl, // seconds
          max: redisCacheConfig.max, // seconds
      }),
业务层实现

该系统中使用typeorm操作数据库,常见的typeorm操作方式包Entity Manager 和Query Builder,结合系统多条件查询场景,因此采用Query Builder方式,控制层和服务层为一一对应关系,代码内参见src/controller、src/service

采坑点

nest多条件查询
...
const queryConditionList = ['c.isDelete = :isDelete'];
            if (query.name) {
                queryConditionList.push('c.name LIKE :name');
            }
            const queryCondition = queryConditionList.join(' AND ');
            const res = await this.productBrandRepository
                .createQueryBuilder('c')
                .where(queryCondition, {
                    name: `%${query.name}%`,
                    isDelete: 0,
                })
                .orderBy('c.name', 'ASC')
                .skip((query.page - 1) * query.pageSize)
                .take(query.pageSize)
                .getManyAndCount();
...
typeorm实体间任意联查

typeorm中联查任意实体(在实体关系间没有表关联)时,getManyAndCount无法查询关联字段,必须采用getRawAndEntities,typeorm文档书写有误。

...
            const res = await this.productAttributeRepository
                .createQueryBuilder('c')
                .leftJoinAndSelect(ProductAttributeCategoryEntity, 'a', 'a.id = c.product_attribute_category_id')
                .where(queryCondition, {
                    name: `%${query.name}%`,
                    isDelete: 0,
                    productAttributeCategoryId: Number(query.cateAttrId),
                    type: Number(query.type),
                })
                .orderBy('c.name', 'ASC')
                .skip((query.page - 1) * query.pageSize)
                .take(query.pageSize)
                .getRawAndEntities();


...
JWT用户认证拆分单独服务

用户系统中与身份认证拆分成单独的服务(网关服务)
http://blog.canyuegongzi.xyz/

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值