Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions src/main/java/flipnote/group/adapter/in/web/GroupController.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package flipnote.group.adapter.in.web;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
Expand All @@ -17,9 +18,11 @@
import flipnote.group.api.dto.response.FindGroupResponseDto;
import flipnote.group.application.port.in.ChangeGroupUseCase;
import flipnote.group.application.port.in.CreateGroupUseCase;
import flipnote.group.application.port.in.DeleteGroupUseCase;
import flipnote.group.application.port.in.FindGroupUseCase;
import flipnote.group.application.port.in.command.ChangeGroupCommand;
import flipnote.group.application.port.in.command.CreateGroupCommand;
import flipnote.group.application.port.in.command.DeleteGroupCommand;
import flipnote.group.application.port.in.command.FindGroupCommand;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
Expand All @@ -32,6 +35,7 @@ public class GroupController {
private final CreateGroupUseCase createGroupUseCase;
private final ChangeGroupUseCase changeGroupUseCase;
private final FindGroupUseCase findGroupUseCase;
private final DeleteGroupUseCase deleteGroupUseCase;

/**
* 그룹 생성 API
Expand Down Expand Up @@ -111,4 +115,32 @@ public ResponseEntity<FindGroupResponseDto> findGroup(
return ResponseEntity.ok(res);
}

/**
* 그룹 삭제
* todo 추후 권환 체크 후 권환 확인 후 삭제
* @param userId
* @param groupId
* @return
*/
@DeleteMapping("/{groupId}")
public ResponseEntity<Void> deleteGroup(
@RequestHeader("X-USER-ID") Long userId,
@PathVariable("groupId") Long groupId
) {

DeleteGroupCommand cmd = new DeleteGroupCommand(userId, groupId);

deleteGroupUseCase.deleteGroup(cmd);

return ResponseEntity.noContent().build();
}
Comment on lines +118 to +136
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

엔드포인트 구조는 적절합니다. TODO 코멘트에 오타가 있습니다.

Line 120: 권환권한 (2회 반복). 사소하지만 나중에 TODO를 검색할 때 혼동을 줄 수 있습니다.

-	 * todo 추후 권환 체크 후 권환 확인 후 삭제
+	 * todo 추후 권한 체크 후 권한 확인 후 삭제
🤖 Prompt for AI Agents
In `@src/main/java/flipnote/group/adapter/in/web/GroupController.java` around
lines 118 - 136, Fix the typo in the TODO comment inside GroupController (in the
deleteGroup method of class GroupController): change both occurrences of "권환" to
"권한" so the TODO reads correctly (e.g., "추후 권한 체크 후 권한 확인 후 삭제"), preserving the
comment structure and spacing.


//todo 그룹 내 멤버 조회

//todo 그룹 전체 조회

//todo 내 그룹 전체 조회

//todo 내가 생성한 그룹 전체 조회

}
18 changes: 18 additions & 0 deletions src/main/java/flipnote/group/adapter/in/web/MemberController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package flipnote.group.adapter.in.web;

public class MemberController {
//todo 가인 신청 요청

//todo 그룹 내 가입 신청한 리스트 조회

//todo 가입신청 응답

//todo 가입신청 삭제

//todo 내가 신청한 가입신청 리스트 조회

//todo 초대

//todo 그룹 멤버 추방

}
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,9 @@ public Group findById(Long id) {
);
return GroupMapper.toDomain(groupEntity);
}

@Override
public void delete(Long groupId) {
groupRepository.deleteById(groupId);
}
Comment on lines +39 to +42
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

존재하지 않는 그룹 삭제 시 예외 처리 부재

Spring Data JPA 3.x의 deleteById는 해당 ID의 엔티티가 존재하지 않아도 예외 없이 무시됩니다. 같은 클래스의 findById는 존재하지 않을 때 IllegalArgumentException을 던지므로 동작이 일관되지 않습니다. 존재하지 않는 그룹에 대해 204를 반환하면 클라이언트에게 잘못된 성공 신호를 줄 수 있습니다.

🔧 존재 확인 후 삭제하는 방식 제안
 `@Override`
 public void delete(Long groupId) {
-    groupRepository.deleteById(groupId);
+    if (!groupRepository.existsById(groupId)) {
+        throw new IllegalArgumentException("Group not Exist");
+    }
+    groupRepository.deleteById(groupId);
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@Override
public void delete(Long groupId) {
groupRepository.deleteById(groupId);
}
`@Override`
public void delete(Long groupId) {
if (!groupRepository.existsById(groupId)) {
throw new IllegalArgumentException("Group not Exist");
}
groupRepository.deleteById(groupId);
}
🤖 Prompt for AI Agents
In
`@src/main/java/flipnote/group/adapter/out/persistence/GroupRepositoryAdapter.java`
around lines 39 - 42, The delete method in GroupRepositoryAdapter currently
calls groupRepository.deleteById(groupId) without checking existence, which is
inconsistent with findById's behavior; update GroupRepositoryAdapter.delete(Long
groupId) to first verify the group exists (e.g., use
groupRepository.existsById(groupId) or reuse findById logic) and if not present
throw the same IllegalArgumentException used elsewhere, otherwise call
groupRepository.deleteById(groupId) to perform the deletion so behavior and
client responses remain consistent.

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package flipnote.group.application.port.in;

import flipnote.group.application.port.in.command.DeleteGroupCommand;

public interface DeleteGroupUseCase {
void deleteGroup(DeleteGroupCommand cmd);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package flipnote.group.application.port.in.command;

public record DeleteGroupCommand(
Long userId,
Long groupId
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@ public interface GroupRepositoryPort {
Long saveNewGroup(Group group);

Group findById(Long id);

void delete(Long id);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package flipnote.group.application.service;

import org.springframework.stereotype.Service;

import flipnote.group.application.port.in.DeleteGroupUseCase;
import flipnote.group.application.port.in.command.DeleteGroupCommand;
import flipnote.group.application.port.out.GroupRepositoryPort;
import lombok.RequiredArgsConstructor;

@Service
@RequiredArgsConstructor
public class DeleteGroupService implements DeleteGroupUseCase {

private final GroupRepositoryPort groupRepository;

@Override
public void deleteGroup(DeleteGroupCommand cmd) {
groupRepository.delete(cmd.groupId());
}
Comment on lines +10 to +19
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

@Transactional 누락 및 권한 검증 부재

두 가지 문제가 있습니다:

  1. @Transactional 누락: 삭제는 쓰기 작업이므로 @Transactional 어노테이션이 필요합니다. 향후 삭제 로직이 복잡해지면(연관 데이터 정리 등) 트랜잭션 보장이 필수적입니다.

  2. userId가 사용되지 않음: DeleteGroupCommanduserId가 전달되지만 서비스에서 전혀 참조하지 않습니다. 현재 상태에서는 어떤 사용자든 임의의 그룹을 삭제할 수 있어 보안 위험이 있습니다. TODO로 남겨두셨지만, 최소한 그룹 소유자인지 확인하는 로직은 이 PR에 포함하는 것을 권장합니다.

🔧 `@Transactional` 추가 및 소유자 검증 제안
 package flipnote.group.application.service;

+import org.springframework.transaction.annotation.Transactional;
 import org.springframework.stereotype.Service;

 import flipnote.group.application.port.in.DeleteGroupUseCase;
 import flipnote.group.application.port.in.command.DeleteGroupCommand;
 import flipnote.group.application.port.out.GroupRepositoryPort;
 import lombok.RequiredArgsConstructor;

 `@Service`
 `@RequiredArgsConstructor`
 public class DeleteGroupService implements DeleteGroupUseCase {

 	private final GroupRepositoryPort groupRepository;

 	`@Override`
+	`@Transactional`
 	public void deleteGroup(DeleteGroupCommand cmd) {
+		var group = groupRepository.findById(cmd.groupId());
+		// TODO: group.getOwnerId()와 cmd.userId() 비교하여 권한 검증
 		groupRepository.delete(cmd.groupId());
 	}

 }
🤖 Prompt for AI Agents
In `@src/main/java/flipnote/group/application/service/DeleteGroupService.java`
around lines 10 - 19, Add transactional and ownership checks to
DeleteGroupService: annotate the class or deleteGroup method with
`@Transactional`, load the group via GroupRepositoryPort (e.g., findById or
getById) inside deleteGroup(DeleteGroupCommand cmd), verify that the fetched
group's ownerId equals cmd.userId, and if not throw an appropriate
access/authorization exception; only call groupRepository.delete(cmd.groupId())
after the existence and ownership checks succeed (and handle group-not-found by
throwing a not-found exception).


}