diff --git a/apps/server/src/core/group/dto/update-group.dto.ts b/apps/server/src/core/group/dto/update-group.dto.ts index ddaa1b0f..1e00cff0 100644 --- a/apps/server/src/core/group/dto/update-group.dto.ts +++ b/apps/server/src/core/group/dto/update-group.dto.ts @@ -1,4 +1,9 @@ import { PartialType } from '@nestjs/mapped-types'; import { CreateGroupDto } from './create-group.dto'; +import { IsNotEmpty, IsUUID } from 'class-validator'; -export class UpdateGroupDto extends PartialType(CreateGroupDto) {} +export class UpdateGroupDto extends PartialType(CreateGroupDto) { + @IsNotEmpty() + @IsUUID() + groupId: string; +} diff --git a/apps/server/src/core/group/entities/group.entity.ts b/apps/server/src/core/group/entities/group.entity.ts index 47f964be..caa31897 100644 --- a/apps/server/src/core/group/entities/group.entity.ts +++ b/apps/server/src/core/group/entities/group.entity.ts @@ -47,4 +47,6 @@ export class Group { @OneToMany(() => GroupUser, (groupUser) => groupUser.group) groupUsers: GroupUser[]; + + userCount?: number; } diff --git a/apps/server/src/core/group/services/group-user.service.ts b/apps/server/src/core/group/services/group-user.service.ts index 147dce7d..f42272ed 100644 --- a/apps/server/src/core/group/services/group-user.service.ts +++ b/apps/server/src/core/group/services/group-user.service.ts @@ -6,20 +6,20 @@ import { import { DataSource, EntityManager } from 'typeorm'; import { GroupUserRepository } from '../respositories/group-user.repository'; import { PaginationOptions } from '../../../helpers/pagination/pagination-options'; -import { - WorkspaceUser, - WorkspaceUserRole, -} from '../../workspace/entities/workspace-user.entity'; +import { WorkspaceUser } from '../../workspace/entities/workspace-user.entity'; import { transactionWrapper } from '../../../helpers/db.helper'; import { User } from '../../user/entities/user.entity'; import { GroupUser } from '../entities/group-user.entity'; import { PaginationMetaDto } from '../../../helpers/pagination/pagination-meta-dto'; import { PaginatedResult } from '../../../helpers/pagination/paginated-result'; +import { Group } from '../entities/group.entity'; +import { GroupService } from './group.service'; @Injectable() export class GroupUserService { constructor( private groupUserRepository: GroupUserRepository, + private groupService: GroupService, private dataSource: DataSource, ) {} @@ -28,9 +28,12 @@ export class GroupUserService { workspaceId: string, paginationOptions: PaginationOptions, ): Promise> { + await this.groupService.validateGroup(groupId, workspaceId); + const [groupUsers, count] = await this.groupUserRepository.findAndCount({ relations: ['user'], where: { + groupId: groupId, group: { workspaceId: workspaceId, }, @@ -57,7 +60,15 @@ export class GroupUserService { await transactionWrapper( async (manager) => { - // TODO: make duplicate code reusable + const group = await manager.findOneBy(Group, { + id: groupId, + workspaceId: workspaceId, + }); + + if (!group) { + throw new NotFoundException('Group not found'); + } + const userExists = await manager.exists(User, { where: { id: userId }, }); @@ -100,7 +111,7 @@ export class GroupUserService { } async removeUserFromGroup(userId: string, groupId: string): Promise { - const groupUser = await this.findGroupUser(userId, groupId); + const groupUser = await this.getGroupUser(userId, groupId); if (!groupUser) { throw new BadRequestException('Group member not found'); @@ -112,10 +123,18 @@ export class GroupUserService { }); } - async findGroupUser(userId: string, groupId: string): Promise { + async getGroupUser(userId: string, groupId: string): Promise { return await this.groupUserRepository.findOneBy({ userId, groupId, }); } + + async getGroupUserCount(groupId: string): Promise { + return await this.groupUserRepository.count({ + where: { + groupId: groupId, + }, + }); + } } diff --git a/apps/server/src/core/group/services/group.service.ts b/apps/server/src/core/group/services/group.service.ts index 62bbf8f1..084ed3e7 100644 --- a/apps/server/src/core/group/services/group.service.ts +++ b/apps/server/src/core/group/services/group.service.ts @@ -29,7 +29,14 @@ export class GroupService { workspaceId: string, updateGroupDto: UpdateGroupDto, ): Promise { - const group = new Group(); + const group = await this.groupRepository.findOneBy({ + id: updateGroupDto.groupId, + workspaceId: workspaceId, + }); + + if (!group) { + throw new NotFoundException('Group not found'); + } if (updateGroupDto.name) { group.name = updateGroupDto.name; @@ -43,12 +50,16 @@ export class GroupService { } async getGroup(groupId: string, workspaceId: string): Promise { - const group = await this.groupRepository.findOneBy({ - id: groupId, - workspaceId: workspaceId, - }); - - //TODO: get group member count + const group = await this.groupRepository + .createQueryBuilder('group') + .where('group.id = :groupId', { groupId }) + .andWhere('group.workspaceId = :workspaceId', { workspaceId }) + .loadRelationCountAndMap( + 'group.userCount', + 'group.groupUsers', + 'groupUsers', + ) + .getOne(); if (!group) { throw new NotFoundException('Group not found'); @@ -61,22 +72,37 @@ export class GroupService { workspaceId: string, paginationOptions: PaginationOptions, ): Promise> { - const [groupsInWorkspace, count] = await this.groupRepository.findAndCount({ - where: { - workspaceId: workspaceId, - }, - - take: paginationOptions.limit, - skip: paginationOptions.skip, - }); + const [groupsInWorkspace, count] = await this.groupRepository + .createQueryBuilder('group') + .where('group.workspaceId = :workspaceId', { workspaceId }) + .loadRelationCountAndMap( + 'group.userCount', + 'group.groupUsers', + 'groupUsers', + ) + .take(paginationOptions.limit) + .skip(paginationOptions.skip) + .getManyAndCount(); const paginationMeta = new PaginationMetaDto({ count, paginationOptions }); return new PaginatedResult(groupsInWorkspace, paginationMeta); } - async deleteGroup(groupId: string, workspaceId: string) { - await this.getGroup(groupId, workspaceId); + async deleteGroup(groupId: string, workspaceId: string): Promise { + await this.validateGroup(groupId, workspaceId); await this.groupRepository.delete(groupId); } + + async validateGroup(groupId: string, workspaceId: string): Promise { + const groupExists = await this.groupRepository.exists({ + where: { + id: groupId, + workspaceId: workspaceId, + }, + }); + if (!groupExists) { + throw new NotFoundException('Group not found'); + } + } } diff --git a/apps/server/src/core/user/user.service.ts b/apps/server/src/core/user/user.service.ts index ec73bd18..a29ecc62 100644 --- a/apps/server/src/core/user/user.service.ts +++ b/apps/server/src/core/user/user.service.ts @@ -60,10 +60,7 @@ export class UserService { } async getUserInstance(userId: string) { - console.log('what is') - const user: User = await this.findById(userId); - console.log('what one') if (!user) { throw new NotFoundException('User not found');