Skip to content

Commit

Permalink
Merge pull request #51 from gsainfoteam/42-sgh
Browse files Browse the repository at this point in the history
42 sgh
  • Loading branch information
GanghyeonSeo authored Aug 29, 2024
2 parents d76f339 + 21a7150 commit 7aff62e
Show file tree
Hide file tree
Showing 11 changed files with 180 additions and 25 deletions.
1 change: 1 addition & 0 deletions prisma/dbml/schema.dbml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ Table group {
verifiedAt DateTime
presidentUuid String [not null]
deletedAt DateTime
notionPageId String
President user [not null]
UserGroup user_group [not null]
Role role [not null]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "group" ADD COLUMN "notionPageId" TEXT;
1 change: 1 addition & 0 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ model Group {
verifiedAt DateTime? @map("verified_at")
presidentUuid String @map("president_uuid") @db.Uuid
deletedAt DateTime? @map("deleted_at")
notionPageId String?
President User @relation(fields: [presidentUuid], references: [uuid])
Expand Down
3 changes: 3 additions & 0 deletions src/external/dto/res/externalInfoRes.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ class GroupWithRoleResDto implements GroupWithRole {
@ApiProperty({ type: RoleResDto, isArray: true })
Role: RoleResDto[];

@ApiProperty()
notionPageId: string | null;

@Exclude()
deletedAt: Date | null;
}
Expand Down
4 changes: 4 additions & 0 deletions src/group/dto/req/createGroup.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,8 @@ export class CreateGroupDto {
@IsString()
@IsOptional()
description?: string;

@IsString()
@IsOptional()
notionPageId?: string;
}
19 changes: 19 additions & 0 deletions src/group/dto/req/updateGroup.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { IsNotEmpty, IsOptional, IsString } from 'class-validator';

export class UpdateGroupDto {
@IsString()
@IsNotEmpty()
uuid: string;

@IsString()
@IsOptional()
name?: string;

@IsString()
@IsOptional()
description?: string;

@IsString()
@IsOptional()
notionPageId?: string;
}
3 changes: 3 additions & 0 deletions src/group/dto/res/ExpandedGroupRes.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ export class ExpandedGroupResDto implements ExpandedGroup {
return this.verifiedAt !== null;
}

@ApiProperty()
notionPageId: string | null;

constructor(partial: Partial<ExpandedGroup>) {
Object.assign(this, partial);
}
Expand Down
3 changes: 3 additions & 0 deletions src/group/dto/res/groupRes.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ export class GroupResDto implements Group {
@ApiProperty()
verifiedAt: Date | null;

@ApiProperty()
notionPageId: string | null;

@ApiProperty()
@Expose()
get verified(): boolean {
Expand Down
18 changes: 17 additions & 1 deletion src/group/group.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import { GroupListResDto, GroupResDto } from './dto/res/groupRes.dto';
import { InviteCodeResDto } from './dto/res/inviteCodeRes.dto';
import { ExpandedGroupResDto } from './dto/res/ExpandedGroupRes.dto';
import { JoinDto } from './dto/req/join.dto';
import { UpdateGroupDto } from './dto/req/updateGroup.dto';

@ApiTags('group')
@ApiOAuth2(['openid', 'email', 'profile'])
Expand Down Expand Up @@ -91,6 +92,21 @@ export class GroupController {
return this.groupService.createGroup(body, user.uuid);
}

@ApiOperation({
summary: 'Update group info',
description: '그룹의 정보를 업데이트하는 API입니다.',
})
@ApiOkResponse()
@ApiForbiddenResponse()
@ApiInternalServerErrorResponse()
@Patch()
async updateGroup(
@Body() body: UpdateGroupDto,
@GetUser() user: User,
): Promise<void> {
return this.groupService.updateGroup(body, user.uuid);
}

@ApiOperation({
summary: 'Delete a group',
description:
Expand All @@ -104,7 +120,7 @@ export class GroupController {
@Param('uuid') uuid: string,
@GetUser() user: User,
): Promise<void> {
this.groupService.deleteGroup(uuid, user.uuid);
return this.groupService.deleteGroup(uuid, user.uuid);
}

@ApiOperation({
Expand Down
108 changes: 98 additions & 10 deletions src/group/group.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,24 @@ export class GroupRepository {
});
}

async checkGroupExistenceByUuid(uuid: string): Promise<Group | null> {
this.logger.log(`checkGroupExistenceByUuid ${uuid}`);

return this.prismaService.group
.findUnique({
where: {
deletedAt: null,
uuid,
},
})
.catch((error) => {
if (error instanceof PrismaClientKnownRequestError) {
throw new InternalServerErrorException('unknown database error');
}
throw new InternalServerErrorException('unknown error');
});
}

async getGroupByName(name: string): Promise<Group | null> {
this.logger.log(`getGroupByName ${name}`);
return this.prismaService.group
Expand Down Expand Up @@ -141,7 +159,9 @@ export class GroupRepository {
{
name,
description,
}: Pick<Group, 'name'> & Partial<Pick<Group, 'description'>>,
notionPageId,
}: Pick<Group, 'name'> &
Partial<Pick<Group, 'description' | 'notionPageId'>>,
userUuid: string,
): Promise<Group> {
this.logger.log(`createGroup: ${name}`);
Expand All @@ -151,6 +171,7 @@ export class GroupRepository {
name,
description,
presidentUuid: userUuid,
notionPageId,
UserGroup: {
create: {
userUuid,
Expand Down Expand Up @@ -189,16 +210,83 @@ export class GroupRepository {
});
}

async deleteGroup(uuid: string): Promise<void> {
async updateGroup(
{
uuid,
name,
description,
notionPageId,
}: Pick<Group, 'uuid'> &
Partial<Pick<Group, 'name' | 'description' | 'notionPageId'>>,
userUuid: string,
): Promise<void> {
this.logger.log(`updateGroup ${uuid}`);

await this.prismaService.group
.update({
where: {
uuid,
UserRole: {
some: {
userUuid,
Role: {
authorities: {
has: Authority.GROUP_UPDATE,
},
},
},
},
},
data: {
name,
description,
notionPageId,
},
})
.catch((error) => {
if (error instanceof PrismaClientKnownRequestError) {
if (error.code === 'P2025') {
throw new ForbiddenException();
}
this.logger.log(error);
throw new InternalServerErrorException('unknown database error');
}
throw new InternalServerErrorException('unknown error');
});
}

async deleteGroup(uuid: string, userUuid: string): Promise<void> {
this.logger.log(`deleteGroup: ${uuid}`);
await this.prismaService.group.update({
where: {
uuid,
},
data: {
deletedAt: new Date(),
},
});

await this.prismaService.group
.update({
where: {
uuid,
UserRole: {
some: {
userUuid,
Role: {
authorities: {
has: Authority.GROUP_DELETE,
},
},
},
},
},
data: {
deletedAt: new Date(),
},
})
.catch((error) => {
if (error instanceof PrismaClientKnownRequestError) {
if (error.code === 'P2025') {
throw new ForbiddenException();
}
this.logger.log(error);
throw new InternalServerErrorException('unknown database error');
}
throw new InternalServerErrorException('unknown error');
});
}

async addUserToGroup(uuid: string, userUuid: string): Promise<void> {
Expand Down
43 changes: 29 additions & 14 deletions src/group/group.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
ForbiddenException,
Injectable,
Logger,
NotFoundException,
} from '@nestjs/common';
import { GroupRepository } from './group.repository';
import { CreateGroupDto } from './dto/req/createGroup.dto';
Expand All @@ -13,6 +14,7 @@ import * as crypto from 'crypto';
import { Authority, Group } from '@prisma/client';
import { GroupWithRole } from './types/groupWithRole';
import { ExpandedGroup } from './types/ExpandedGroup.type';
import { UpdateGroupDto } from './dto/req/updateGroup.dto';

@Injectable()
export class GroupService {
Expand Down Expand Up @@ -43,29 +45,42 @@ export class GroupService {
createGroupDto.name,
);

if (!checkGroupExistence) {
await this.groupRepository.createGroup(createGroupDto, userUuid);
} else {
if (checkGroupExistence) {
throw new ConflictException(
`Group with name ${createGroupDto.name} already exists`,
);
}

await this.groupRepository.createGroup(createGroupDto, userUuid);
}

async updateGroup(
updateGroupDto: UpdateGroupDto,
userUuid: string,
): Promise<void> {
this.logger.log(`updateGroup: ${updateGroupDto.uuid}`);

const checkGroupExistence =
await this.groupRepository.checkGroupExistenceByUuid(updateGroupDto.uuid);

if (!checkGroupExistence) {
throw new NotFoundException('Group not found');
}

await this.groupRepository.updateGroup(updateGroupDto, userUuid);
}

async deleteGroup(uuid: string, userUuid: string): Promise<void> {
this.logger.log(`deleteGroup: ${uuid}`);
if (
!(await this.groupRepository.validateAuthority(
uuid,
[Authority.GROUP_DELETE],
userUuid,
))
) {
throw new ForbiddenException(
'You do not have permission to delete group',
);

const checkGroupExistence =
await this.groupRepository.checkGroupExistenceByUuid(uuid);

if (!checkGroupExistence) {
throw new NotFoundException('Group not found');
}
await this.groupRepository.deleteGroup(uuid);

await this.groupRepository.deleteGroup(uuid, userUuid);
}

/**
Expand Down

0 comments on commit 7aff62e

Please sign in to comment.