Система управления правами организации пользователей
Стек технологий:
- Внешний интерфейс: Vue + ElementUi + TypeScript
- Серверная часть: nest.js + mysql + redis
демонстрационный адрес
Система управления организацией пользователей (демо-адрес) github
особенности дизайна
Дизайн базы данных
Объект пользователя
@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/Использовать…