Skip to content

Commit

Permalink
Merge pull request #178 from 00sOrg/Feat/177
Browse files Browse the repository at this point in the history
✨ [Feat] Implement delete event api
  • Loading branch information
gitwub5 authored Oct 3, 2024
2 parents 2101f28 + ac7b92b commit 49d3c7d
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 3 deletions.
11 changes: 11 additions & 0 deletions src/common/api/status/error.status.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,11 @@ export class ErrorStatus implements BaseCode {
400,
'주소를 찾을 수 없습니다.',
);
static readonly EVENT_NOT_OWNER = new ErrorStatus(
false,
400,
'이벤트의 소유자가 아닙니다.',
);

//S3 에러
static readonly S3_UPLOAD_FAILURE = new ErrorStatus(
Expand Down Expand Up @@ -127,4 +132,10 @@ export class ErrorStatus implements BaseCode {
400,
'Push 메시지를 보내는데 실패했습니다',
);

static readonly S3_DELETE_FAILURE = new ErrorStatus(
false,
400,
'이미지 삭제에 실패했습니다.',
);
}
20 changes: 19 additions & 1 deletion src/external/s3/s3.service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { PutObjectCommand, S3Client } from '@aws-sdk/client-s3';
import {
DeleteObjectCommand,
PutObjectCommand,
S3Client,
} from '@aws-sdk/client-s3';
import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { ErrorStatus } from 'src/common/api/status/error.status';
Expand Down Expand Up @@ -43,4 +47,18 @@ export class S3Service {
const region = this.configService.get<string>('BUCKET_REGION');
return `https://${bucketName}.s3.${region}.amazonaws.com/${key}`;
}

async delete(key: string): Promise<void> {
const data = {
Bucket: this.configService.get<string>('BUCKET_NAME'),
Key: key,
};

try {
const command = new DeleteObjectCommand(data);
await this.s3Client.send(command);
} catch (error) {
throw new ExceptionHandler(ErrorStatus.S3_DELETE_FAILURE);
}
}
}
4 changes: 2 additions & 2 deletions src/modules/events/entities/comment.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ export class Comment extends DefaultEntity {
@PrimaryGeneratedColumn({ type: 'bigint' })
id!: number;

@ManyToOne(() => Event)
@ManyToOne(() => Event, { onDelete: 'CASCADE' })
@JoinColumn()
event!: Event;

@ManyToOne(() => Member)
@ManyToOne(() => Member, { onDelete: 'CASCADE' })
@JoinColumn()
member!: Member;

Expand Down
14 changes: 14 additions & 0 deletions src/modules/events/events.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
Query,
UseInterceptors,
UploadedFile,
Delete,
} from '@nestjs/common';
import { EventsService } from './services/events.service';
import { CreateEventDto } from './dto/create-event.dto';
Expand Down Expand Up @@ -235,4 +236,17 @@ export class EventsController {
const member = req.user;
return await this.eventsService.getEvents(member);
}

@Delete(':id(\\d+)')
@ApiOperation({ summary: '이벤트 삭제' })
@ApiSuccessResponse()
@ApiFailureResponse(
ErrorStatus.EVENT_NOT_FOUND,
ErrorStatus.INTERNAL_SERVER_ERROR,
ErrorStatus.S3_DELETE_FAILURE,
)
async deleteEvent(@Param('id') id: string, @Request() req) {
const member = req.user;
await this.eventsService.deleteEvent(Number(id), member);
}
}
4 changes: 4 additions & 0 deletions src/modules/events/repository/events.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,4 +104,8 @@ export class EventsRepository {
.where('event.memberId = :memberId', { memberId })
.getMany();
}

async delete(event: Event): Promise<void> {
await this.eventRepository.delete({ id: event.id });
}
}
14 changes: 14 additions & 0 deletions src/modules/events/services/events.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,20 @@ export class EventsService {
return GetEventsDto.of(events);
}

async deleteEvent(eventId: number, member: Member) {
const event = await this.eventsRepository.findById(eventId);
if (!event) {
throw new ExceptionHandler(ErrorStatus.EVENT_NOT_FOUND);
}
if (event.member.id !== member.id) {
throw new ExceptionHandler(ErrorStatus.EVENT_NOT_OWNER);
}
if (event.media) {
await this.s3Service.delete(event.media);
}
await this.eventsRepository.delete(event);
}

private isValidLocation(lat: number, lng: number) {
if (
lat === undefined ||
Expand Down
33 changes: 33 additions & 0 deletions test/unit/events.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ describe('EventService', () => {
update: jest.fn(),
findByTitleLike: jest.fn(),
findAllByMember: jest.fn(),
delete: jest.fn(),
},
},
{
Expand All @@ -71,6 +72,7 @@ describe('EventService', () => {
provide: S3Service,
useValue: {
upload: jest.fn(),
delete: jest.fn(),
},
},
{
Expand Down Expand Up @@ -556,4 +558,35 @@ describe('EventService', () => {
expect(result).toEqual(getEventsDto);
});
});

describe('deleteEvent', () => {
let event: Event;
let member: Member;
beforeEach(() => {
member = new MemberBuilder().id(1).build();
event = new EventBuilder().id(1).member(member).media('test').build();
});
it('should delete the event successfully', async () => {
jest.spyOn(eventsRepository, 'findById').mockResolvedValue(event);
jest.spyOn(s3Service, 'delete').mockResolvedValue(undefined);
jest.spyOn(eventsRepository, 'delete').mockResolvedValue(undefined);
await eventsService.deleteEvent(event.id, member);
expect(eventsRepository.findById).toHaveBeenCalledWith(event.id);
expect(s3Service.delete).toHaveBeenCalledWith(event.media);
expect(eventsRepository.delete).toHaveBeenCalledWith(event);
});
it('should throw EVENT_NOT_FOUND if the event is not found', async () => {
jest.spyOn(eventsRepository, 'findById').mockResolvedValue(null);
await expect(eventsService.deleteEvent(event.id, member)).rejects.toThrow(
new ExceptionHandler(ErrorStatus.EVENT_NOT_FOUND),
);
});
it('should throw EVENT_NOT_OWNER if the member is not the owner of the event', async () => {
const anotherMember = new MemberBuilder().id(2).build();
jest.spyOn(eventsRepository, 'findById').mockResolvedValue(event);
await expect(
eventsService.deleteEvent(event.id, anotherMember),
).rejects.toThrow(new ExceptionHandler(ErrorStatus.EVENT_NOT_OWNER));
});
});
});

0 comments on commit 49d3c7d

Please sign in to comment.