feat(rbac): add user-ding-mapping CRUD endpoints

This commit is contained in:
2026-07-09 16:31:50 +08:00
parent 4f3b5112b0
commit c928ee0f65
4 changed files with 83 additions and 5 deletions

View File

@@ -1,8 +1,8 @@
import { Injectable, Logger, NotFoundException } from '@nestjs/common';
import { Injectable, Logger, NotFoundException, ConflictException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, In } from 'typeorm';
import * as bcrypt from 'bcryptjs';
import { Permission, Role, User, Class, ClassStudent, ClassTeacher, ClassSchedule, Student } from '../entities';
import { Permission, Role, User, Class, ClassStudent, ClassTeacher, ClassSchedule, Student, UserDingMapping } from '../entities';
const PRESET_PERMISSIONS: Array<{ code: string; name: string; group: string }> = [
{ code: 'dashboard:view', name: '查看数据面板', group: 'dashboard' },
@@ -171,6 +171,7 @@ export class RbacService {
@InjectRepository(ClassTeacher) private classTeacherRepo: Repository<ClassTeacher>,
@InjectRepository(ClassSchedule) private classScheduleRepo: Repository<ClassSchedule>,
@InjectRepository(Student) private studentRepo: Repository<Student>,
@InjectRepository(UserDingMapping) private mappingRepo: Repository<UserDingMapping>,
) {}
async seedData(): Promise<void> {
@@ -246,6 +247,38 @@ export class RbacService {
this.logger.log(`种子数据初始化完成: ${allPerms.length} 权限点, ${allRoles.length} 角色`);
}
// ---- 钉钉用户绑定 ----
async getUserDingMappings(): Promise<UserDingMapping[]> {
return this.mappingRepo.find({ relations: ['user'] });
}
async createUserDingMapping(dto: { userId: number; dingUserId: string; dingName?: string; dingMobile?: string }) {
const existing = await this.mappingRepo.findOne({ where: { dingUserId: dto.dingUserId } });
if (existing) throw new ConflictException(`钉钉用户 ${dto.dingUserId} 已绑定到本地用户 #${existing.userId}`);
const userExisting = await this.mappingRepo.findOne({ where: { userId: dto.userId } });
if (userExisting) throw new ConflictException(`本地用户 #${dto.userId} 已绑定到钉钉用户 ${userExisting.dingUserId}`);
const mapping = this.mappingRepo.create(dto);
return this.mappingRepo.save(mapping);
}
async deleteUserDingMapping(id: number) {
const mapping = await this.mappingRepo.findOne({ where: { id } });
if (!mapping) throw new NotFoundException('绑定记录不存在');
await this.mappingRepo.remove(mapping);
return { success: true };
}
async getUnboundUsers(): Promise<{ id: number; username: string; name: string }[]> {
return this.userRepo
.createQueryBuilder('u')
.leftJoin(UserDingMapping, 'm', 'm.userId = u.id')
.where('m.id IS NULL')
.andWhere('u.isArchived = false')
.select(['u.id', 'u.username', 'u.name'])
.getMany();
}
async findAllRoles(): Promise<Role[]> {
return this.roleRepo.find({
relations: ['permissions'],