11package com .dmu .debug_visual .collab .rest ;
22
3+ import com .dmu .debug_visual .collab .domain .entity .CodeSession .SessionStatus ;
34import com .dmu .debug_visual .security .CustomUserDetails ;
45import com .dmu .debug_visual .collab .rest .dto .CreateRoomRequest ;
56import com .dmu .debug_visual .collab .rest .dto .CreateSessionRequest ;
1819import org .springframework .security .core .annotation .AuthenticationPrincipal ;
1920import org .springframework .web .bind .annotation .*;
2021
21- @ Tag (name = "협업 방 및 세션 관리 API" , description = "실시간 협업을 위한 방과 코드 세션을 생성하고 관리합니다." )
22+ import java .util .Map ;
23+
24+ @ Tag (name = "협업 방 및 세션 관리 API" , description = "실시간 협업을 위한 방 생성, 세션 관리, 권한 부여, 강퇴 등 모든 REST API를 제공합니다." )
2225@ RestController
23- @ RequestMapping ("/api/collab-rooms " )
26+ @ RequestMapping ("/api/collab" )
2427@ RequiredArgsConstructor
2528public class RoomController {
2629
27- private final RoomService roomService ; // DB 관련 서비스
30+ private final RoomService roomService ;
2831
29- @ Operation (summary = "새로운 협업 방 생성" , description = "DB에 새로운 협업 방을 생성하고, 방장(owner)을 첫 참여자로 자동 등록합니다." )
32+ // --- 방 관리 ---
33+ @ Operation (summary = "새로운 협업 방 생성" , description = "DB에 새로운 협업 방을 생성하고, 방장을 첫 참여자로 자동 등록합니다." )
3034 @ ApiResponses ({
31- @ ApiResponse (responseCode = "200" , description = "방 생성 성공" ,
32- content = @ Content (mediaType = "application/json" , schema = @ Schema (implementation = RoomResponse .class ))),
35+ @ ApiResponse (responseCode = "200" , description = "방 생성 성공" , content = @ Content (schema = @ Schema (implementation = RoomResponse .class ))),
3336 @ ApiResponse (responseCode = "401" , description = "인증 실패" , content = @ Content )
3437 })
35- @ PostMapping
36- public ResponseEntity <RoomResponse > createRoom (
37- @ RequestBody CreateRoomRequest request ,
38- @ AuthenticationPrincipal CustomUserDetails userDetails
39- ) {
38+ @ PostMapping ("/rooms" )
39+ public ResponseEntity <RoomResponse > createRoom (@ RequestBody CreateRoomRequest request , @ AuthenticationPrincipal CustomUserDetails userDetails ) {
4040 String ownerUserId = userDetails .getUsername ();
4141 RoomResponse response = roomService .createRoom (request , ownerUserId );
4242 return ResponseEntity .ok (response );
4343 }
4444
45- @ Operation (summary = "방 안에 새 코드 세션 생성 " , description = "기존에 생성된 협업 방 안에 독립적인 새 코드 편집 세션을 생성합니다 ." )
45+ @ Operation (summary = "방에서 참가자 강퇴 (방장 전용) " , description = "방장이 특정 참가자를 방에서 영구적으로 제외시킵니다. 강퇴된 참가자는 해당 방의 모든 세션에서도 제거됩니다 ." )
4646 @ ApiResponses ({
47- @ ApiResponse (responseCode = "200" , description = "세션 생성 성공" ,
48- content = @ Content (mediaType = "application/json" , schema = @ Schema (implementation = SessionResponse .class ))),
49- @ ApiResponse (responseCode = "401" , description = "인증 실패" , content = @ Content ),
50- @ ApiResponse (responseCode = "403" , description = "해당 방의 참여자가 아님" , content = @ Content ),
51- @ ApiResponse (responseCode = "404" , description = "존재하지 않는 방" , content = @ Content )
47+ @ ApiResponse (responseCode = "200" , description = "강퇴 성공" ),
48+ @ ApiResponse (responseCode = "401" , description = "인증 실패" ),
49+ @ ApiResponse (responseCode = "403" , description = "권한 없음 (방장이 아님)" ),
50+ @ ApiResponse (responseCode = "404" , description = "방 또는 참가자를 찾을 수 없음" )
5251 })
53- @ PostMapping ("/{roomId}/sessions" )
54- public ResponseEntity <SessionResponse > createSession (
55- @ Parameter (description = "세션을 생성할 방의 고유 ID (UUID)" , required = true )
56- @ PathVariable String roomId ,
52+ @ DeleteMapping ("/rooms/{roomId}/participants/{targetUserId}" )
53+ public ResponseEntity <Void > kickParticipant (
54+ @ Parameter (description = "대상 방의 고유 ID" ) @ PathVariable String roomId ,
55+ @ Parameter (description = "강퇴시킬 사용자의 ID" ) @ PathVariable String targetUserId ,
56+ @ AuthenticationPrincipal CustomUserDetails userDetails ) {
57+ roomService .kickParticipant (roomId , userDetails .getUsername (), targetUserId );
58+ return ResponseEntity .ok ().build ();
59+ }
5760
61+ // --- 세션 관리 ---
62+ @ Operation (summary = "방 안에 새 코드 세션 생성 (방송 시작)" , description = "기존 방 안에 독립적인 새 코드 편집 세션을 생성합니다. 생성자는 자동으로 쓰기 권한을 가집니다." )
63+ @ ApiResponses ({
64+ @ ApiResponse (responseCode = "200" , description = "세션 생성 성공" , content = @ Content (schema = @ Schema (implementation = SessionResponse .class ))),
65+ @ ApiResponse (responseCode = "401" , description = "인증 실패" ),
66+ @ ApiResponse (responseCode = "404" , description = "존재하지 않는 방" )
67+ })
68+ @ PostMapping ("/rooms/{roomId}/sessions" )
69+ public ResponseEntity <SessionResponse > createSession (
70+ @ Parameter (description = "세션을 생성할 방의 고유 ID" ) @ PathVariable String roomId ,
5871 @ RequestBody CreateSessionRequest request ,
59- @ AuthenticationPrincipal CustomUserDetails userDetails
60- ) {
72+ @ AuthenticationPrincipal CustomUserDetails userDetails ) {
6173 String creatorUserId = userDetails .getUsername ();
6274 SessionResponse response = roomService .createCodeSessionInRoom (roomId , request , creatorUserId );
6375 return ResponseEntity .ok (response );
6476 }
65- }
77+
78+ @ Operation (summary = "세션 상태 변경 (방송 켜기/끄기, 세션 생성자 전용)" , description = "세션의 상태를 'ACTIVE' 또는 'INACTIVE'로 변경합니다." )
79+ @ ApiResponses ({
80+ @ ApiResponse (responseCode = "200" , description = "상태 변경 성공" ),
81+ @ ApiResponse (responseCode = "401" , description = "인증 실패" ),
82+ @ ApiResponse (responseCode = "403" , description = "권한 없음 (세션 생성자가 아님)" ),
83+ @ ApiResponse (responseCode = "404" , description = "세션을 찾을 수 없음" )
84+ })
85+ @ PatchMapping ("/sessions/{sessionId}/status" )
86+ public ResponseEntity <Void > updateSessionStatus (
87+ @ Parameter (description = "상태를 변경할 세션의 고유 ID" ) @ PathVariable String sessionId ,
88+ @ RequestBody Map <String , SessionStatus > statusMap ,
89+ @ AuthenticationPrincipal CustomUserDetails userDetails ) {
90+ roomService .updateSessionStatus (sessionId , userDetails .getUsername (), statusMap .get ("status" ));
91+ return ResponseEntity .ok ().build ();
92+ }
93+
94+ // --- 세션 권한 관리 ---
95+ @ Operation (summary = "세션 내 쓰기 권한 부여 (세션 생성자 전용)" , description = "세션 생성자가 특정 참가자에게 해당 세션의 쓰기 권한을 부여합니다." )
96+ @ ApiResponses ({
97+ @ ApiResponse (responseCode = "200" , description = "권한 부여 성공" ),
98+ @ ApiResponse (responseCode = "401" , description = "인증 실패" ),
99+ @ ApiResponse (responseCode = "403" , description = "권한 없음 (세션 생성자가 아님)" ),
100+ @ ApiResponse (responseCode = "404" , description = "세션 또는 참가자를 찾을 수 없음" )
101+ })
102+ @ PostMapping ("/sessions/{sessionId}/permissions/{targetUserId}" )
103+ public ResponseEntity <Void > grantWritePermission (
104+ @ Parameter (description = "권한을 부여할 세션의 고유 ID" ) @ PathVariable String sessionId ,
105+ @ Parameter (description = "권한을 부여받을 사용자의 ID" ) @ PathVariable String targetUserId ,
106+ @ AuthenticationPrincipal CustomUserDetails userDetails ) {
107+ roomService .grantWritePermissionInSession (sessionId , userDetails .getUsername (), targetUserId );
108+ return ResponseEntity .ok ().build ();
109+ }
110+
111+ @ Operation (summary = "세션 내 쓰기 권한 회수 (세션 생성자 전용)" , description = "세션 생성자가 특정 참가자의 쓰기 권한을 회수합니다." )
112+ @ ApiResponses ({
113+ @ ApiResponse (responseCode = "200" , description = "권한 회수 성공" ),
114+ @ ApiResponse (responseCode = "401" , description = "인증 실패" ),
115+ @ ApiResponse (responseCode = "403" , description = "권한 없음 (세션 생성자가 아님)" ),
116+ @ ApiResponse (responseCode = "404" , description = "세션 또는 참가자를 찾을 수 없음" )
117+ })
118+ @ DeleteMapping ("/sessions/{sessionId}/permissions/{targetUserId}" )
119+ public ResponseEntity <Void > revokeWritePermission (
120+ @ Parameter (description = "권한을 회수할 세션의 고유 ID" ) @ PathVariable String sessionId ,
121+ @ Parameter (description = "권한을 회수당할 사용자의 ID" ) @ PathVariable String targetUserId ,
122+ @ AuthenticationPrincipal CustomUserDetails userDetails ) {
123+ roomService .revokeWritePermissionInSession (sessionId , userDetails .getUsername (), targetUserId );
124+ return ResponseEntity .ok ().build ();
125+ }
126+ }
127+
0 commit comments