import { OperateUserAuthDto } from '@dtos/auth.dto'; import { CreateOrganizationDto } from '@dtos/organization.dto'; import { OrganizationEntity } from '@entities/organization.entity'; import { UserEntity } from '@entities/user.entity'; import { forwardRef, HttpException, HttpStatus, Inject, Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { AuthService } from '@services/auth.service'; import { MessageService } from '@services/message.service'; import { UserService } from '@services/user.service'; import { WikiService } from '@services/wiki.service'; import { AuthEnum, buildMessageURL, IOrganization, IUser } from '@think/domains'; import { Repository } from 'typeorm'; @Injectable() export class OrganizationService { constructor( @InjectRepository(OrganizationEntity) private readonly organizationRepo: Repository, @Inject(forwardRef(() => AuthService)) private readonly authService: AuthService, @Inject(forwardRef(() => UserService)) private readonly userService: UserService, @Inject(forwardRef(() => MessageService)) private readonly messageService: MessageService, @Inject(forwardRef(() => WikiService)) private readonly wikiService: WikiService ) {} public async findById(id: string) { return await this.organizationRepo.findOne(id); } public async findByIds(ids) { return await this.organizationRepo.findByIds(ids); } /** * 创建组织 * @param user * @param dto * @returns */ public async createOrganization(user: IUser, dto: CreateOrganizationDto) { const [, count] = await this.organizationRepo.findAndCount({ createUserId: user.id }); if (count >= 5) { throw new HttpException('个人可创建组织上限为 5 个', HttpStatus.FORBIDDEN); } const data = { ...dto, createUserId: user.id, }; if (await this.organizationRepo.findOne({ name: data.name })) { throw new HttpException('该组织已存在', HttpStatus.BAD_REQUEST); } const organization = await this.organizationRepo.save(await this.organizationRepo.create(data)); await this.authService.createOrUpdateAuth(user.id, { auth: AuthEnum.creator, organizationId: organization.id, wikiId: null, documentId: null, }); return organization; } /** * 更新组织信息 * @param user * @param dto */ public async updateOrganization(user: IUser, organizationId: IOrganization['id'], dto: CreateOrganizationDto) { await this.authService.canEdit(user.id, { organizationId, wikiId: null, documentId: null, }); const oldData = await this.organizationRepo.findOne(organizationId); if (!oldData) { throw new HttpException('目标组织不存在', HttpStatus.NOT_FOUND); } return await this.organizationRepo.save(await this.organizationRepo.merge(oldData, dto)); } /** * 删除组织 * @param user * @param organizationId * @returns */ async deleteOrganization(user: IUser, organizationId) { const organization = await this.organizationRepo.findOne(organizationId); await this.authService.canDelete(user.id, { organizationId: organization.id, wikiId: null, documentId: null, }); await Promise.all([ this.authService.deleteOrganization(organization.id), this.organizationRepo.remove(organization), this.wikiService.deleteOrganizationWiki(user, organizationId), ]); return organization; } /** * 获取用户个人组织 * @param user * @returns */ public async getPersonalOrganization(user: IUser) { const organization = await this.organizationRepo.findOne({ createUserId: user.id, isPersonal: true }); return organization; } /** * 获取用户可访问的组织 * @param user */ public async getUserOrganizations(user: IUser) { const ids = await this.authService.getUserCanViewOrganizationIds(user.id); return await this.organizationRepo.findByIds(ids); } /** * 获取组织详情 * @param user * @returns */ public async getOrganizationDetail(user: IUser, id: IOrganization['id']) { const organization = await this.organizationRepo.findOne({ id }); if (!organization) { throw new HttpException('组织不存在', HttpStatus.NOT_FOUND); } await this.authService.canView(user.id, { organizationId: id, wikiId: null, documentId: null, }); return organization; } /** * 获取组织成员 * @param user * @param shortId * @returns */ public async getMembers(user: IUser, id: IOrganization['id'], pagination) { const organization = await this.organizationRepo.findOne({ id }); if (!organization) { throw new HttpException('组织不存在', HttpStatus.NOT_FOUND); } await this.authService.canView(user.id, { organizationId: id, wikiId: null, documentId: null, }); const { data: usersAuth, total } = await this.authService.getUsersAuthInOrganization(organization.id, pagination); const userIds = usersAuth.map((auth) => auth.userId); const users = await this.userService.findByIds(userIds); const withUserData = usersAuth.map((auth) => { return { auth, user: users.find((user) => user.id === auth.userId), }; }); return { data: withUserData, total }; } /** * 添加组织成员 * @param user * @param wikiId * @param dto * @returns */ async addMember(user: UserEntity, organizationId, dto: OperateUserAuthDto) { const organization = await this.organizationRepo.findOne(organizationId); if (!organization) { throw new HttpException('组织不存在', HttpStatus.NOT_FOUND); } const targetUser = await this.userService.findOne({ name: dto.userName }); if (!targetUser) { throw new HttpException('用户不存在', HttpStatus.BAD_REQUEST); } const ret = await this.authService.createOrUpdateOtherUserAuth(user.id, targetUser.id, { auth: dto.userAuth, organizationId: organization.id, wikiId: null, documentId: null, }); await this.messageService.notify(targetUser.id, { title: `您被添加到组织「${organization.name}」`, message: `您被添加到知识库「${organization.name}」,快去看看吧!`, url: buildMessageURL('toOrganization')({ organizationId: organization.id, }), uniqueId: organization.id, }); return ret; } /** * 修改组织成员 * @param user * @param wikiId * @param dto * @returns */ async updateMember(user: UserEntity, organizationId, dto: OperateUserAuthDto) { const organization = await this.organizationRepo.findOne(organizationId); if (!organization) { throw new HttpException('组织不存在', HttpStatus.NOT_FOUND); } const targetUser = await this.userService.findOne({ name: dto.userName }); if (!targetUser) { throw new HttpException('用户不存在', HttpStatus.BAD_REQUEST); } const ret = await this.authService.createOrUpdateOtherUserAuth(user.id, targetUser.id, { auth: dto.userAuth, organizationId: organization.id, wikiId: null, documentId: null, }); await this.messageService.notify(targetUser.id, { title: `组织「${organization.name}」权限变更`, message: `您在组织「${organization.name}」权限已变更,快去看看吧!`, url: buildMessageURL('toOrganization')({ organizationId: organization.id, }), uniqueId: organization.id, }); return ret; } /** * 删除组织成员 * @param user * @param wikiId * @param dto * @returns */ async deleteMember(user: UserEntity, organizationId, dto: OperateUserAuthDto) { const organization = await this.organizationRepo.findOne(organizationId); if (!organization) { throw new HttpException('组织不存在', HttpStatus.NOT_FOUND); } const targetUser = await this.userService.findOne({ name: dto.userName }); if (!targetUser) { throw new HttpException('用户不存在', HttpStatus.BAD_REQUEST); } const ret = await this.authService.deleteOtherUserAuth(user.id, targetUser.id, { auth: dto.userAuth, organizationId: organization.id, wikiId: null, documentId: null, }); await this.messageService.notify(targetUser.id, { title: `组织「${organization.name}」权限收回`, message: `您在组织「${organization.name}」权限已收回!`, url: buildMessageURL('toOrganization')({ organizationId: organization.id, }), uniqueId: organization.id, }); return ret; } }