Skip to content

Commit

Permalink
Merge pull request #9 from wang-bam-bbang/post
Browse files Browse the repository at this point in the history
Post
  • Loading branch information
Kimcheolhui authored Dec 5, 2024
2 parents 5e921f6 + cabb1a4 commit eab1064
Show file tree
Hide file tree
Showing 9 changed files with 113 additions and 68 deletions.
72 changes: 39 additions & 33 deletions database_setup/database.dbml
Original file line number Diff line number Diff line change
Expand Up @@ -6,63 +6,69 @@ Project find_it {
Enum item_category {
ELECTRONICS [note: '전자기기']
WALLET [note: '지갑']
BAG [note: '가방']
CLOTHING [note: '의류']
ACCESSORIES [note: '액세서리']
DOCUMENT [note: '서류']
CARD [note: '카드']
OTHER [note: '기타']
BAG [note: '가방']
CLOTHING [note: '의류']
ACCESSORIES [note: '액세서리']
DOCUMENT [note: '서류']
CARD [note: '카드']
ETC [note: '기타']
}

Enum post_status {
PENDING [note: '미해결']
IN_PROGRESS [note: '진행 중']
RESOLVED [note: '해결됨']
CANCELLED [note: '취소됨']
}

Enum post_type {
FOUND [note: '발견']
LOST [note: '분실']
}

Enum comment_type {
COMMENT [note: '일반 댓글']
REPLY [note: '대댓글']
}

Table users {
uuid uuid [pk, not null]
name varchar [not null]
email varchar [not null, unique]
created_at timestamp [not null, default: `now()`]
updated_at timestamp [not null]

Note: '사용자 정보'
}

Table found_posts {
id uuid [pk, not null, default: `gen_random_uuid()`]
title varchar [not null]
description text [not null]
Table posts {
id serial [pk, not null]
type post_type [not null, note: '게시글 타입 (발견/분실)']
title varchar(255) [not null, note: '게시글 제목']
description text [not null, note: '게시글 설명']
images varchar[] [note: '이미지 URL 배열']
location varchar [not null, note: '발견 장소']
category item_category [not null]
status post_status [not null, default: 'PENDING']
author_id uuid [ref: > users.uuid, not null]
location varchar [not null, note: '발견/분실 장소']
category item_category [not null, default: 'ETC', note: '아이템 카테고리']
status post_status [not null, note: '게시글 상태']
created_at timestamp [not null, default: `now()`]
updated_at timestamp [not null]
deleted_at timestamp [note: '게시글 삭제 일자']
author_id uuid [ref: > users.uuid, not null, note: '작성자 UUID']

indexes {
author_id
}

Note: '발견 게시글'
Note: '게시글 정보'
}

Table lost_posts {
id uuid [pk, not null, default: `gen_random_uuid()`]
title varchar [not null]
description text [not null]
images varchar[] [note: '이미지 URL 배열']
location varchar [not null, note: '분실 추정 장소']
category item_category [not null]
status post_status [not null, default: 'PENDING']
author_id uuid [ref: > users.uuid, not null]
Table comments {
id serial [pk, not null]
content text [not null, note: '댓글 내용']
type comment_type [not null, note: '댓글 타입 (댓글/대댓글)']
created_at timestamp [not null, default: `now()`]
updated_at timestamp [not null]
is_deleted boolean [not null, default: false, note: '댓글 삭제 여부']
post_id int [ref: > posts.id, not null, note: '게시글 ID']
author_id uuid [ref: > users.uuid, not null, note: '작성자 UUID']
parent_id int [ref: > comments.id, note: '상위 댓글 ID']

indexes {
author_id
}

Note: '분실 게시글'
}
Note: '댓글 정보'
}
6 changes: 5 additions & 1 deletion src/idp/idp.service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
BadRequestException,
Injectable,
InternalServerErrorException,
UnauthorizedException,
Expand Down Expand Up @@ -52,7 +53,10 @@ export class IdpService {
if (error instanceof AxiosError && error.response?.status === 401) {
throw new UnauthorizedException();
}
throw new InternalServerErrorException();
if (error instanceof AxiosError && error.response?.status === 400) {
throw new BadRequestException(error.response.data);
}
throw new InternalServerErrorException(error.response.data);
}),
),
);
Expand Down
7 changes: 6 additions & 1 deletion src/image/image.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
BadRequestException,
Injectable,
InternalServerErrorException,
NotFoundException,
} from '@nestjs/common';
import { ConfigService } from '@nestjs/config';

Expand Down Expand Up @@ -139,7 +140,11 @@ export class ImageService {
},
});
await this.s3Client.send(command).catch((error) => {
throw new InternalServerErrorException(error);
if (error.Code === 'AccessDenied') {
throw new NotFoundException('Image key is invalid');
}

throw new InternalServerErrorException();
});
}

Expand Down
2 changes: 1 addition & 1 deletion src/post/dto/req/createPost.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export class CreatePostDto {
@ApiProperty({
type: [String],
description: 'Array of image keys/filenames for the post',
example: '[thisisanimagekey.jpg]',
example: ['thisisanimagekey.jpg'],
})
@IsString({ each: true })
@IsOptional()
Expand Down
16 changes: 16 additions & 0 deletions src/post/dto/req/myPostFilter.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { ApiProperty } from '@nestjs/swagger';
import { PostType } from '@prisma/client';
import { IsEnum, IsOptional } from 'class-validator';

export class MyPostFilterDto {
@ApiProperty({
enum: PostType,
enumName: 'PostType',
description: 'Type of post (FOUND or LOST)',
example: PostType.FOUND,
required: false,
})
@IsEnum(PostType)
@IsOptional()
type?: PostType;
}
2 changes: 1 addition & 1 deletion src/post/dto/req/postFilter.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export class PostFilterDto {
@ApiProperty({
type: Number,
description: 'Pagination cursor for next set of results',
example: 17,
example: 0,
})
@Transform(({ value }) => parseInt(value, 10), { toClassOnly: true })
@IsInt()
Expand Down
8 changes: 6 additions & 2 deletions src/post/post.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
ApiTags,
ApiUnauthorizedResponse,
} from '@nestjs/swagger';
import { MyPostFilterDto } from './dto/req/myPostFilter.dto';

@ApiTags('Post')
@Controller('post')
Expand Down Expand Up @@ -66,8 +67,11 @@ export class PostController {
@ApiBearerAuth('access-token')
@Get('my-posts')
@UseGuards(IdPGuard)
async getMyPosts(@GetUser() user: User): Promise<PostListDto> {
return this.postService.getMyPostList(user.uuid);
async getMyPosts(
@GetUser() user: User,
@Query() myPostFilterDto: MyPostFilterDto,
): Promise<PostListDto> {
return this.postService.getMyPostList(user.uuid, myPostFilterDto);
}

@ApiOperation({
Expand Down
8 changes: 6 additions & 2 deletions src/post/post.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { PostResponseDto } from './dto/res/postRes.dto';
import { Injectable } from '@nestjs/common';
import { UpdatePostDto } from './dto/req/updatePost.dto';
import { PostFilterDto } from './dto/req/postFilter.dto';
import { PostType } from '@prisma/client';

@Injectable()
export class PostRepository {
Expand Down Expand Up @@ -96,9 +97,12 @@ export class PostRepository {
};
}

async findPostsByUser(userUuid: string): Promise<PostResponseDto[]> {
async findPostsByUser(
userUuid: string,
type?: PostType,
): Promise<PostResponseDto[]> {
const posts = await this.prismaService.post.findMany({
where: { authorId: userUuid },
where: { authorId: userUuid, type },
include: {
author: {
select: {
Expand Down
60 changes: 33 additions & 27 deletions src/post/post.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { PostListDto, PostResponseDto } from './dto/res/postRes.dto';
import { UpdatePostDto } from './dto/req/updatePost.dto';
import { PostFilterDto } from './dto/req/postFilter.dto';
import { ImageService } from 'src/image/image.service';
import { MyPostFilterDto } from './dto/req/myPostFilter.dto';

@Injectable()
export class PostService {
Expand Down Expand Up @@ -52,8 +53,13 @@ export class PostService {
};
}

async getMyPostList(userUuid: string): Promise<PostListDto> {
const postList = await this.postRepository.findPostsByUser(userUuid);
async getMyPostList(
userUuid: string,
myPostFilterDto: MyPostFilterDto,
): Promise<PostListDto> {
const { type } = myPostFilterDto;

const postList = await this.postRepository.findPostsByUser(userUuid, type);

const formattedPosts = await Promise.all(
postList.map(async (post) => {
Expand Down Expand Up @@ -87,6 +93,31 @@ export class PostService {
};
}

async createPost(
createPostDto: CreatePostDto,
userUuid: string,
): Promise<PostResponseDto> {
if (createPostDto.images.length) {
await this.imageService.validateImages(createPostDto.images);
}

const newPost = await this.postRepository.createPost(
createPostDto,
userUuid,
);

const signedUrls = await this.imageService.generateSignedUrls(
newPost.images,
);

// TODO: FCM process need to be added.

return {
...newPost,
images: signedUrls,
};
}

async updatePost(
id: number,
updatePostDto: UpdatePostDto,
Expand Down Expand Up @@ -123,29 +154,4 @@ export class PostService {

return this.postRepository.deletePost(id);
}

async createPost(
createPostDto: CreatePostDto,
userUuid: string,
): Promise<PostResponseDto> {
if (createPostDto.images.length) {
await this.imageService.validateImages(createPostDto.images);
}

const newPost = await this.postRepository.createPost(
createPostDto,
userUuid,
);

const signedUrls = await this.imageService.generateSignedUrls(
newPost.images,
);

// TODO: FCM process need to be added.

return {
...newPost,
images: signedUrls,
};
}
}

0 comments on commit eab1064

Please sign in to comment.