Nest.js + vue реализует систему разрешений для организации пользователей.

NestJS

Система управления правами организации пользователей

Стек технологий:

  • Внешний интерфейс: 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.Уровень управления и уровень службы находятся в одном to-one соответствие. См. src/controller в коде. , src/service

Пит-Пойнт

вложенный запрос с несколькими условиями

...
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 разделяет отдельные службы

Система пользователя и аутентификация личности разделены на отдельные службы (службы шлюза).

Оригинальный адрес:www.yongfeifeilove.xyz:3002/blog/nest/Использовать…