diff --git a/build.gradle b/build.gradle index 47d9ccc..087b383 100644 --- a/build.gradle +++ b/build.gradle @@ -21,6 +21,7 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.boot:spring-boot-starter-data-mongodb' implementation 'me.paulschwarz:spring-dotenv:4.0.0' implementation 'org.springframework.boot:spring-boot-starter-oauth2-client' // 3.3.x 버전으로 변경 없음 implementation 'io.jsonwebtoken:jjwt-api:0.11.2' diff --git a/src/main/java/com/mtvs/devlinkbackend/DevlinkBackendApplication.java b/src/main/java/com/mtvs/devlinkbackend/DevlinkBackendApplication.java index a04d1a6..26aa236 100644 --- a/src/main/java/com/mtvs/devlinkbackend/DevlinkBackendApplication.java +++ b/src/main/java/com/mtvs/devlinkbackend/DevlinkBackendApplication.java @@ -2,8 +2,10 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.data.mongodb.config.EnableMongoAuditing; @SpringBootApplication +@EnableMongoAuditing public class DevlinkBackendApplication { public static void main(String[] args) { diff --git a/src/main/java/com/mtvs/devlinkbackend/channel/controller/ChannelController.java b/src/main/java/com/mtvs/devlinkbackend/channel/controller/ChannelController.java new file mode 100644 index 0000000..0ee66b2 --- /dev/null +++ b/src/main/java/com/mtvs/devlinkbackend/channel/controller/ChannelController.java @@ -0,0 +1,71 @@ +package com.mtvs.devlinkbackend.channel.controller; + +import com.mtvs.devlinkbackend.channel.dto.ChannelRegistRequestDTO; +import com.mtvs.devlinkbackend.channel.dto.ChannelUpdateRequestDTO; +import com.mtvs.devlinkbackend.channel.entity.Channel; +import com.mtvs.devlinkbackend.channel.service.ChannelService; +import com.mtvs.devlinkbackend.config.JwtUtil; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/api/channel") +public class ChannelController { + private final ChannelService channelService; + private final JwtUtil jwtUtil; + + public ChannelController(ChannelService channelService, JwtUtil jwtUtil) { + this.channelService = channelService; + this.jwtUtil = jwtUtil; + } + + // 새 채널 생성 + @PostMapping + public ResponseEntity createChannel( + @RequestBody ChannelRegistRequestDTO channelRegistRequestDTO, + @RequestHeader(name = "Authorization") String authorizationHeader) throws Exception { + + String accountId = jwtUtil.getSubjectFromAuthHeaderWithoutAuth(authorizationHeader); + Channel savedChannel = channelService.saveChannel(channelRegistRequestDTO, accountId); + return ResponseEntity.ok(savedChannel); + } + + // 모든 채널 조회 + @GetMapping + public ResponseEntity> getAllChannels() { + List channels = channelService.findAllChannels(); + return ResponseEntity.ok(channels); + } + + // 특정 채널 조회 + @GetMapping("/{channelId}") + public ResponseEntity getChannelById(@PathVariable String channelId) { + return channelService.findChannelByChannelId(channelId) + .map(ResponseEntity::ok) + .orElse(ResponseEntity.notFound().build()); + } + + // 채널 업데이트 + @PatchMapping + public ResponseEntity updateChannel( + @RequestBody ChannelUpdateRequestDTO channelUpdateRequestDTO, + @RequestHeader(name = "Authorization") String authorizationHeader) throws Exception { + + String accountId = jwtUtil.getSubjectFromAuthHeaderWithoutAuth(authorizationHeader); + try { + Channel updatedChannel = channelService.updateChannel(channelUpdateRequestDTO, accountId); + return ResponseEntity.ok(updatedChannel); + } catch (IllegalArgumentException e) { + return ResponseEntity.badRequest().body(null); + } + } + + // 채널 삭제 + @DeleteMapping("/{channelId}") + public ResponseEntity deleteChannel(@PathVariable String channelId) { + channelService.deleteChannel(channelId); + return ResponseEntity.noContent().build(); + } +} diff --git a/src/main/java/com/mtvs/devlinkbackend/channel/dto/ChannelRegistRequestDTO.java b/src/main/java/com/mtvs/devlinkbackend/channel/dto/ChannelRegistRequestDTO.java new file mode 100644 index 0000000..b26bbf6 --- /dev/null +++ b/src/main/java/com/mtvs/devlinkbackend/channel/dto/ChannelRegistRequestDTO.java @@ -0,0 +1,16 @@ +package com.mtvs.devlinkbackend.channel.dto; + +import com.mtvs.devlinkbackend.channel.entity.PositionType; +import lombok.*; + +import java.util.List; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@ToString +@Data +public class ChannelRegistRequestDTO { + private List positionTypes; +} \ No newline at end of file diff --git a/src/main/java/com/mtvs/devlinkbackend/channel/dto/ChannelUpdateRequestDTO.java b/src/main/java/com/mtvs/devlinkbackend/channel/dto/ChannelUpdateRequestDTO.java new file mode 100644 index 0000000..a55268f --- /dev/null +++ b/src/main/java/com/mtvs/devlinkbackend/channel/dto/ChannelUpdateRequestDTO.java @@ -0,0 +1,17 @@ +package com.mtvs.devlinkbackend.channel.dto; + +import com.mtvs.devlinkbackend.channel.entity.PositionType; +import lombok.*; + +import java.util.List; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@ToString +@Data +public class ChannelUpdateRequestDTO { + private String channelId; + private List positionTypes; +} \ No newline at end of file diff --git a/src/main/java/com/mtvs/devlinkbackend/channel/entity/Channel.java b/src/main/java/com/mtvs/devlinkbackend/channel/entity/Channel.java new file mode 100644 index 0000000..f3c08a0 --- /dev/null +++ b/src/main/java/com/mtvs/devlinkbackend/channel/entity/Channel.java @@ -0,0 +1,45 @@ +package com.mtvs.devlinkbackend.channel.entity; + +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.ToString; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.Id; +import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.mongodb.core.annotation.Collation; +import org.springframework.data.mongodb.core.mapping.Document; +import org.springframework.data.mongodb.core.mapping.Field; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.UUID; + +@Data +@NoArgsConstructor +@ToString +@Document(collection = "channel") +public class Channel { + @Id + private String channelId; + + @Field(name = "owner_id") + private String ownerId; + + private List positionTypes; // 여러 개의 position과 type 저장 + + @CreatedDate + private LocalDateTime createdAt; + + @LastModifiedDate + private LocalDateTime modifiedAt; + + public Channel(String ownerId, List positionTypes) { + this.channelId = UUID.randomUUID().toString(); + this.ownerId = ownerId; + this.positionTypes = positionTypes; + } + + public void setPositionTypes(List positionTypes) { + this.positionTypes = positionTypes; + } +} \ No newline at end of file diff --git a/src/main/java/com/mtvs/devlinkbackend/channel/entity/PositionType.java b/src/main/java/com/mtvs/devlinkbackend/channel/entity/PositionType.java new file mode 100644 index 0000000..0291bfd --- /dev/null +++ b/src/main/java/com/mtvs/devlinkbackend/channel/entity/PositionType.java @@ -0,0 +1,33 @@ +package com.mtvs.devlinkbackend.channel.entity; + +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.data.mongodb.core.mapping.Field; + +@Data +@NoArgsConstructor +public class PositionType { + private Position position; + + @Field("type") + private String type; + + public PositionType(Position position, String type) { + this.position = position; + this.type = type; + } + + @Data + @NoArgsConstructor + public static class Position { + private int x; + private int y; + private int z; + + public Position(int x, int y, int z) { + this.x = x; + this.y = y; + this.z = z; + } + } +} diff --git a/src/main/java/com/mtvs/devlinkbackend/channel/repository/ChannelRepository.java b/src/main/java/com/mtvs/devlinkbackend/channel/repository/ChannelRepository.java new file mode 100644 index 0000000..d642c9d --- /dev/null +++ b/src/main/java/com/mtvs/devlinkbackend/channel/repository/ChannelRepository.java @@ -0,0 +1,10 @@ +package com.mtvs.devlinkbackend.channel.repository; + +import com.mtvs.devlinkbackend.channel.entity.Channel; +import org.springframework.data.mongodb.repository.MongoRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface ChannelRepository extends MongoRepository { + +} \ No newline at end of file diff --git a/src/main/java/com/mtvs/devlinkbackend/channel/service/ChannelService.java b/src/main/java/com/mtvs/devlinkbackend/channel/service/ChannelService.java new file mode 100644 index 0000000..646dea2 --- /dev/null +++ b/src/main/java/com/mtvs/devlinkbackend/channel/service/ChannelService.java @@ -0,0 +1,58 @@ +package com.mtvs.devlinkbackend.channel.service; + +import com.mtvs.devlinkbackend.channel.dto.ChannelRegistRequestDTO; +import com.mtvs.devlinkbackend.channel.dto.ChannelUpdateRequestDTO; +import com.mtvs.devlinkbackend.channel.entity.Channel; +import com.mtvs.devlinkbackend.channel.repository.ChannelRepository; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.Optional; + +@Service +public class ChannelService { + private final ChannelRepository channelRepository; + + public ChannelService(ChannelRepository channelRepository) { + this.channelRepository = channelRepository; + } + + // 새 채널 저장 + @Transactional + public Channel saveChannel(ChannelRegistRequestDTO channelRegistRequestDTO, String accountId) { + return channelRepository.save(new Channel( + accountId, + channelRegistRequestDTO.getPositionTypes() + )); + } + + // 모든 채널 조회 + + public List findAllChannels() { + return channelRepository.findAll(); + } + + // ID로 특정 채널 조회 + public Optional findChannelByChannelId(String channelId) { + return channelRepository.findById(channelId); + } + + // ID로 채널 업데이트 + @Transactional + public Channel updateChannel(ChannelUpdateRequestDTO channelUpdateRequestDTO, String accountId) { + Optional channel = channelRepository.findById(channelUpdateRequestDTO.getChannelId()); + if (channel.isPresent()) { + Channel foundChannel = channel.get(); + if(foundChannel.getOwnerId().equals(accountId)) { + foundChannel.setPositionTypes(channelUpdateRequestDTO.getPositionTypes()); + return foundChannel; + } else throw new IllegalArgumentException("주인이 아닌 다른 사용자 계정으로 채널 수정 시도중"); + } else throw new IllegalArgumentException("요청한 channelId로 해당 채널이 존재하지 않음"); + } + + // ID로 채널 삭제 + public void deleteChannel(String channelId) { + channelRepository.deleteById(channelId); + } +} diff --git a/src/main/java/com/mtvs/devlinkbackend/comment/controller/CommentController.java b/src/main/java/com/mtvs/devlinkbackend/comment/controller/CommentController.java index 863c2f2..5204461 100644 --- a/src/main/java/com/mtvs/devlinkbackend/comment/controller/CommentController.java +++ b/src/main/java/com/mtvs/devlinkbackend/comment/controller/CommentController.java @@ -35,7 +35,7 @@ public ResponseEntity registComment( @RequestBody CommentRegistRequestDTO commentRegistRequestDTO, @RequestHeader(name = "Authorization") String authorizationHeader) throws Exception { - String accountId = jwtUtil.getSubjectFromTokenWithoutAuth(authorizationHeader); + String accountId = jwtUtil.getSubjectFromAuthHeaderWithoutAuth(authorizationHeader); Comment comment = commentService.registComment(commentRegistRequestDTO, accountId); return ResponseEntity.status(HttpStatus.CREATED).body(comment); } @@ -65,7 +65,7 @@ public ResponseEntity> findCommentsByRequestId(@PathVariable Long public ResponseEntity> findCommentsByAccountId( @RequestHeader(name = "Authorization") String authorizationHeader) throws Exception { - String accountId = jwtUtil.getSubjectFromTokenWithoutAuth(authorizationHeader); + String accountId = jwtUtil.getSubjectFromAuthHeaderWithoutAuth(authorizationHeader); List comments = commentService.findCommentsByAccountId(accountId); return ResponseEntity.ok(comments); } @@ -81,7 +81,7 @@ public ResponseEntity updateComment( @RequestBody CommentUpdateRequestDTO commentUpdateRequestDTO, @RequestHeader(name = "Authorization") String authorizationHeader) throws Exception { - String accountId = jwtUtil.getSubjectFromTokenWithoutAuth(authorizationHeader); + String accountId = jwtUtil.getSubjectFromAuthHeaderWithoutAuth(authorizationHeader); Comment updatedComment = commentService.updateComment(commentUpdateRequestDTO, accountId); return ResponseEntity.ok(updatedComment); } diff --git a/src/main/java/com/mtvs/devlinkbackend/config/JwtAuthenticationFilter.java b/src/main/java/com/mtvs/devlinkbackend/config/JwtAuthenticationFilter.java index d0034d8..b465602 100644 --- a/src/main/java/com/mtvs/devlinkbackend/config/JwtAuthenticationFilter.java +++ b/src/main/java/com/mtvs/devlinkbackend/config/JwtAuthenticationFilter.java @@ -1,6 +1,6 @@ package com.mtvs.devlinkbackend.config; -import com.mtvs.devlinkbackend.oauth2.service.EpicGamesTokenService; +import com.mtvs.devlinkbackend.oauth2.service.UserService; import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; import jakarta.servlet.http.Cookie; @@ -17,11 +17,11 @@ @Component public class JwtAuthenticationFilter extends OncePerRequestFilter { private final JwtUtil jwtUtil; - private final EpicGamesTokenService epicGamesTokenService; + private final UserService userService; - public JwtAuthenticationFilter(JwtUtil jwtUtil, EpicGamesTokenService epicGamesTokenService) { + public JwtAuthenticationFilter(JwtUtil jwtUtil, UserService userService) { this.jwtUtil = jwtUtil; - this.epicGamesTokenService = epicGamesTokenService; + this.userService = userService; } @Override @@ -38,30 +38,24 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse if (StringUtils.hasText(authorizationHeader) && authorizationHeader.startsWith("Bearer ")) { token = authorizationHeader.substring(7); // "Bearer " 이후의 토큰 부분 추출 } else { - // 헤더에 액세스 토큰이 없는 경우, 쿠키에서 리프레시 토큰 추출 - token = getRefreshTokenFromCookies(request); - if (token != null) { - // 리프레시 토큰으로 새 액세스 토큰 발급 - token = epicGamesTokenService.getAccessTokenByRefreshToken(token); - - // 새로 발급된 액세스 토큰을 Authorization 헤더에 추가 - response.setHeader("Authorization", "Bearer " + token); - } else { - System.out.println("refrehToken으로 accessToken 발급하려다가 refreshToken 없어서 실패"); - return; - } + response.setStatus(450); // 잘못된 인증 헤더 + return; } try { // 토큰 검증 | 검증 성공 시 SecurityContext에 인증 정보 저장 - String userPrincipal = jwtUtil.getSubjectFromTokenWithAuth(token); + String accountId = jwtUtil.getSubjectFromAuthHeaderWithAuth(token); UsernamePasswordAuthenticationToken authentication = - new UsernamePasswordAuthenticationToken(userPrincipal, null, null); + new UsernamePasswordAuthenticationToken(accountId, null, null); SecurityContextHolder.getContext().setAuthentication(authentication); + } catch (Exception e) { // 검증 실패 시 401 에러 설정 - response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + if(e.getMessage().equals("JWT is expired")) + response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + else + response.setStatus(449); // 헤더에 들어 있는 토큰이 잘못됨 return; } diff --git a/src/main/java/com/mtvs/devlinkbackend/config/JwtUtil.java b/src/main/java/com/mtvs/devlinkbackend/config/JwtUtil.java index 3b1987b..0947631 100644 --- a/src/main/java/com/mtvs/devlinkbackend/config/JwtUtil.java +++ b/src/main/java/com/mtvs/devlinkbackend/config/JwtUtil.java @@ -28,33 +28,33 @@ public JwtUtil(EpicGamesJWKCache jwkCache) { } // JWT 서명 및 검증을 통한 Claims 추출 - public Map getClaimsFromTokenWithAuth(String token) throws Exception { + public Map getClaimsFromAuthHeaderWithAuth(String authorizationHeader) throws Exception { // Claims 검증 - JWTClaimsSet claims = getClaimsFromToken(token); + JWTClaimsSet claims = getClaimsFromToken(extractToken(authorizationHeader)); validateClaims(claims); // 검증이 완료되었을 경우 모든 Claims을 Map으로 변환하여 반환 return convertClaimsToMap(claims); } - // JWT 서명 및 검증을 통한 Claims 추출 - public Map getClaimsFromTokenWithoutAuth(String token) throws Exception { + // JWT Claims 추출 + public Map getClaimsFromAuthHeaderWithoutAuth(String authorizationHeader) throws Exception { // Claims 검증 - JWTClaimsSet claims = getClaimsFromToken(token); + JWTClaimsSet claims = getClaimsFromToken(extractToken(authorizationHeader)); // 검증이 완료되었을 경우 모든 Claims을 Map으로 변환하여 반환 return convertClaimsToMap(claims); } // 검증된 'sub' 값, accountId 반환 - public String getSubjectFromTokenWithAuth(String token) throws Exception { - Map claims = getClaimsFromTokenWithAuth(token); + public String getSubjectFromAuthHeaderWithAuth(String authorizationHeader) throws Exception { + Map claims = getClaimsFromAuthHeaderWithAuth(authorizationHeader); return (String) claims.get("sub"); } - // 검증된 'sub' 값, accountId 반환 - public String getSubjectFromTokenWithoutAuth(String token) throws Exception { - Map claims = getClaimsFromTokenWithoutAuth(token); + // 검증되지 않은 'sub' 값, accountId 반환 + public String getSubjectFromAuthHeaderWithoutAuth(String authorizationHeader) throws Exception { + Map claims = getClaimsFromAuthHeaderWithoutAuth(authorizationHeader); return (String) claims.get("sub"); } @@ -86,7 +86,7 @@ private JWTClaimsSet getClaimsFromToken(String token) throws Exception { SignedJWT signedJWT = SignedJWT.parse(token); JWK jwk = jwkCache.getCachedJWKSet().getKeyByKeyId(signedJWT.getHeader().getKeyID()); - if (jwk == null || !JWSAlgorithm.RS256.equals(jwk.getAlgorithm())) { + if (jwk == null || !JWSAlgorithm.RS256.equals(signedJWT.getHeader().getAlgorithm())) { throw new RuntimeException("JWK key is missing or invalid algorithm"); } @@ -104,4 +104,13 @@ private Map convertClaimsToMap(JWTClaimsSet claims) { claims.getClaims().forEach(claimsMap::put); return claimsMap; } + + private String extractToken(String authorizationHeader) { + System.out.println(authorizationHeader); + if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) { + return authorizationHeader.substring(7); + } else { + throw new IllegalArgumentException("Authorization header must start with 'Bearer '"); + } + } } diff --git a/src/main/java/com/mtvs/devlinkbackend/ether/controller/EtherController.java b/src/main/java/com/mtvs/devlinkbackend/ether/controller/EtherController.java index 52009bd..864aa99 100644 --- a/src/main/java/com/mtvs/devlinkbackend/ether/controller/EtherController.java +++ b/src/main/java/com/mtvs/devlinkbackend/ether/controller/EtherController.java @@ -35,7 +35,7 @@ public ResponseEntity registEther( @RequestBody EtherRegistRequestDTO etherRegistRequestDTO, @RequestHeader(name = "Authorization") String authorizationHeader) throws Exception { - String accountId = jwtUtil.getSubjectFromTokenWithoutAuth(authorizationHeader); + String accountId = jwtUtil.getSubjectFromAuthHeaderWithoutAuth(authorizationHeader); Ether newEther = etherService.registEther(etherRegistRequestDTO, accountId); return ResponseEntity.ok(newEther); } @@ -61,7 +61,7 @@ public ResponseEntity findEtherByEtherId(@PathVariable Long etherId) { public ResponseEntity> findEthersByAccountId( @RequestHeader(name = "Authorization") String authorizationHeader) throws Exception { - String accountId = jwtUtil.getSubjectFromTokenWithoutAuth(authorizationHeader); + String accountId = jwtUtil.getSubjectFromAuthHeaderWithoutAuth(authorizationHeader); List ethers = etherService.findEthersByAccountId(accountId); return ResponseEntity.ok(ethers); } diff --git a/src/main/java/com/mtvs/devlinkbackend/guild/controller/GuildController.java b/src/main/java/com/mtvs/devlinkbackend/guild/controller/GuildController.java index b0a4c0e..f20ba5e 100644 --- a/src/main/java/com/mtvs/devlinkbackend/guild/controller/GuildController.java +++ b/src/main/java/com/mtvs/devlinkbackend/guild/controller/GuildController.java @@ -35,7 +35,7 @@ public Guild createGuild( @RequestBody GuildRegistRequestDTO guildRegistRequestDTO, @RequestHeader(name = "Authorization") String authorizationHeader) throws Exception { - String accountId = jwtUtil.getSubjectFromTokenWithoutAuth(authorizationHeader); + String accountId = jwtUtil.getSubjectFromAuthHeaderWithoutAuth(authorizationHeader); return guildService.createGuild(guildRegistRequestDTO, accountId); } @@ -62,7 +62,7 @@ public List findGuildsByGuildNameContaining(@RequestParam String guildNam public List findGuildsByOwnerId( @RequestHeader(name = "Authorization") String authorizationHeader) throws Exception { - String ownerId = jwtUtil.getSubjectFromTokenWithoutAuth(authorizationHeader); + String ownerId = jwtUtil.getSubjectFromAuthHeaderWithoutAuth(authorizationHeader); return guildService.findGuildsByOwnerId(ownerId); } @@ -72,7 +72,7 @@ public List findGuildsByOwnerId( public List findGuildsByMemberIdContaining( @RequestHeader(name = "Authorization") String authorizationHeader) throws Exception { - String memberId = jwtUtil.getSubjectFromTokenWithoutAuth(authorizationHeader); + String memberId = jwtUtil.getSubjectFromAuthHeaderWithoutAuth(authorizationHeader); return guildService.findGuildsByMemberIdContaining(memberId); } @@ -87,7 +87,7 @@ public Guild updateGuild( @RequestBody GuildUpdateRequestDTO guildUpdateRequestDTO, @RequestHeader(name = "Authorization") String authorizationHeader) throws Exception { - String accountId = jwtUtil.getSubjectFromTokenWithoutAuth(authorizationHeader); + String accountId = jwtUtil.getSubjectFromAuthHeaderWithoutAuth(authorizationHeader); return guildService.updateGuild(guildUpdateRequestDTO, accountId); } @@ -102,7 +102,7 @@ public Guild addMemberToGuild( @RequestBody GuildMemberModifyRequestDTO guildMemberModifyRequestDTO, @RequestHeader(name = "Authorization") String authorizationHeader) throws Exception { - String accountId = jwtUtil.getSubjectFromTokenWithoutAuth(authorizationHeader); + String accountId = jwtUtil.getSubjectFromAuthHeaderWithoutAuth(authorizationHeader); return guildService.addMemberToGuild(guildMemberModifyRequestDTO, accountId); } @@ -117,7 +117,7 @@ public Guild removeMemberFromGuild( @RequestBody GuildMemberModifyRequestDTO guildMemberModifyRequestDTO, @RequestHeader(name = "Authorization") String authorizationHeader) throws Exception { - String accountId = jwtUtil.getSubjectFromTokenWithoutAuth(authorizationHeader); + String accountId = jwtUtil.getSubjectFromAuthHeaderWithoutAuth(authorizationHeader); return guildService.removeMemberToGuild(guildMemberModifyRequestDTO, accountId); } diff --git a/src/main/java/com/mtvs/devlinkbackend/oauth2/controller/Oauth2UserController.java b/src/main/java/com/mtvs/devlinkbackend/oauth2/controller/Oauth2UserController.java index 6dcfb3c..69be88c 100644 --- a/src/main/java/com/mtvs/devlinkbackend/oauth2/controller/Oauth2UserController.java +++ b/src/main/java/com/mtvs/devlinkbackend/oauth2/controller/Oauth2UserController.java @@ -1,16 +1,17 @@ package com.mtvs.devlinkbackend.oauth2.controller; +import com.mtvs.devlinkbackend.config.JwtUtil; import com.mtvs.devlinkbackend.oauth2.dto.EpicGamesCallbackRequestDTO; +import com.mtvs.devlinkbackend.oauth2.entity.User; import com.mtvs.devlinkbackend.oauth2.service.EpicGamesTokenService; import com.mtvs.devlinkbackend.oauth2.service.UserService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; -import jakarta.servlet.http.Cookie; -import jakarta.servlet.http.HttpServletResponse; import org.springframework.http.*; import org.springframework.web.bind.annotation.*; +import java.util.List; import java.util.Map; @RestController @@ -19,10 +20,12 @@ public class Oauth2UserController { private final EpicGamesTokenService epicGamesTokenService; private final UserService userService; + private final JwtUtil jwtUtil; - public Oauth2UserController(EpicGamesTokenService epicGamesTokenService, UserService userService) { + public Oauth2UserController(EpicGamesTokenService epicGamesTokenService, UserService userService, JwtUtil jwtUtil) { this.epicGamesTokenService = epicGamesTokenService; this.userService = userService; + this.jwtUtil = jwtUtil; } // 로컬 user 정보 가져오는 API @@ -37,10 +40,9 @@ public Oauth2UserController(EpicGamesTokenService epicGamesTokenService, UserSer @ApiResponse(responseCode = "401", description = "인증되지 않음") }) public ResponseEntity getLocalUserInfo(@RequestHeader("Authorization") String authorizationHeader) { - try { - String token = extractToken(authorizationHeader); - return ResponseEntity.ok(userService.findUserByAccessToken(token)); + try { + return ResponseEntity.ok(userService.findUserByAuthorizationHeader(authorizationHeader)); } catch (Exception e) { return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Invalid token"); } @@ -60,9 +62,11 @@ public ResponseEntity getLocalUserInfo(@RequestHeader("Authorization") String public ResponseEntity getEpicGamesUserInfo( @RequestHeader("Authorization") String authorizationHeader) { + System.out.println(authorizationHeader); + try { - Map userAccount = - epicGamesTokenService.getEpicGamesUserAccount(extractToken(authorizationHeader)); + List> userAccount = + epicGamesTokenService.getEpicGamesUserAccount(authorizationHeader); return ResponseEntity.ok(userAccount); } catch (Exception e) { @@ -70,6 +74,17 @@ public ResponseEntity getEpicGamesUserInfo( } } + @GetMapping("/epicgames/accountId") + public ResponseEntity getAccountId( + @RequestHeader("Authorization") String authorizationHeader) { + + try { + return ResponseEntity.ok(jwtUtil.getSubjectFromAuthHeaderWithAuth(authorizationHeader)); + } catch (Exception e) { + return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Invalid token"); + } + } + @PostMapping("/epicgames/callback") @Operation( summary = "EpicGames AccessToken 요청", @@ -80,38 +95,31 @@ public ResponseEntity getEpicGamesUserInfo( @ApiResponse(responseCode = "400", description = "잘못된 헤더 또는 파라미터 전달"), }) public ResponseEntity handleEpicGamesCallback( - @RequestBody EpicGamesCallbackRequestDTO payload, HttpServletResponse response) { + @RequestBody EpicGamesCallbackRequestDTO payload) { String code = payload.getCode(); Map tokenBody = epicGamesTokenService.getAccessTokenAndRefreshTokenByCode(code); - if (tokenBody != null) { - String accessToken = (String) tokenBody.get("access_token"); - String refreshToken = (String) tokenBody.get("refresh_token"); - - // accessToken과 refreshToken을 쿠키에 담아 return - Cookie accessTokenCookie = new Cookie("access_token", "Bearer " + accessToken); - accessTokenCookie.setMaxAge(15 * 60); - accessTokenCookie.setSecure(true); - Cookie refreshTokenCookie = new Cookie("refresh_token", "Bearer " + refreshToken); - refreshTokenCookie.setMaxAge(3 * 60 * 60); - refreshTokenCookie.setSecure(true); - - response.addCookie(accessTokenCookie); - response.addCookie(refreshTokenCookie); + if (tokenBody != null) + return ResponseEntity.status(HttpStatus.CREATED).body(tokenBody); + else + return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); + } - return ResponseEntity.status(HttpStatus.CREATED).build(); - } + @PostMapping("/login") + public ResponseEntity authLogin( + @RequestHeader(name = "Authorization") String authorizationHeader) { + User user = userService.findUserByAuthorizationHeader(authorizationHeader); - return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); + // 222 : 해당 User는 이미 서비스를 사용한 경험이 있음 + // 260 : 해당 User가 처음 서비스를 사용 + return user != null ? ResponseEntity.status(222).body("Existing User") : ResponseEntity.status(260).body("New User"); } - private String extractToken(String authorizationHeader) { - if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) { - return authorizationHeader.substring(7); - } else { - throw new IllegalArgumentException("Authorization header must start with 'Bearer '"); - } + @PatchMapping("/local/user-info") + public ResponseEntity updateLocalUserInfo() { + // User 추가 정보 확정되면 개발 예정 + return ResponseEntity.ok().build(); } } diff --git a/src/main/java/com/mtvs/devlinkbackend/oauth2/service/EpicGamesTokenService.java b/src/main/java/com/mtvs/devlinkbackend/oauth2/service/EpicGamesTokenService.java index d38da38..64c6cd8 100644 --- a/src/main/java/com/mtvs/devlinkbackend/oauth2/service/EpicGamesTokenService.java +++ b/src/main/java/com/mtvs/devlinkbackend/oauth2/service/EpicGamesTokenService.java @@ -3,6 +3,7 @@ import com.mtvs.devlinkbackend.config.JwtUtil; import com.mtvs.devlinkbackend.oauth2.component.EpicGamesJWKCache; import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.*; import org.springframework.stereotype.Service; import org.springframework.util.LinkedMultiValueMap; @@ -11,17 +12,23 @@ import java.nio.charset.StandardCharsets; import java.util.Base64; +import java.util.List; import java.util.Map; @Service public class EpicGamesTokenService { - @Value("${spring.security.oauth2.client.registration.epicgames.client-id}") + @Value("${epicgames.registration.client-id}") private String clientId; - @Value("${spring.security.oauth2.client.registration.epicgames.client-secret}") + @Value("${epicgames.registration.client-secret}") private String clientSecret; - private final String redirectUri = ""; + @Value("${epicgames.registration.deployment-id}") + private String deploymentId; + + private final String getAuthorizationCodeURL = "https://www.epicgames.com/id/authorize"; + private final String getAccessTokenURL = "https://api.epicgames.dev/epic/oauth/v2/token"; + private final String getAccountURL = "https://api.epicgames.dev/epic/id/v2/accounts?accountId="; private final EpicGamesJWKCache jwkCache; private final JwtUtil jwtUtil; @@ -33,34 +40,9 @@ public EpicGamesTokenService(EpicGamesJWKCache jwkCache, JwtUtil jwtUtil) { } // 오프라인 JWT 검증 및 파싱 메서드 - public Map validateAndParseToken(String token) throws Exception { + public Map validateAuthHeaderAndParseToken(String authorizationHeader) throws Exception { // JWT 토큰 검증 및 파싱하여 Claims를 추출 - return jwtUtil.getClaimsFromTokenWithoutAuth(token); - } - - public String getAccessTokenByRefreshToken(String refreshToken) { - // Epic Games의 OAuth2 토큰 엔드포인트 호출 - RestTemplate restTemplate = new RestTemplate(); - HttpHeaders headers = new HttpHeaders(); - - // Basic Authentication 헤더 추가 - String auth = clientId + ":" + clientSecret; - byte[] encodedAuth = Base64.getEncoder().encode(auth.getBytes(StandardCharsets.UTF_8)); - String authHeader = "Basic " + new String(encodedAuth); - headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); - headers.set("Authorization", authHeader); - - // 요청 본문 설정 - MultiValueMap body = new LinkedMultiValueMap<>(); - body.add("grant_type", "refresh_token"); - body.add("token", refreshToken); - - HttpEntity> request = new HttpEntity<>(body, headers); - - // Epic Games 토큰 엔드포인트에 요청 - ResponseEntity response = restTemplate.postForEntity("https://api.epicgames.dev/epic/oauth/v2/token", request, Map.class); - - return (String) response.getBody().get("sub"); + return jwtUtil.getClaimsFromAuthHeaderWithAuth(authorizationHeader); } public Map getAccessTokenAndRefreshTokenByCode(String code) { @@ -72,51 +54,56 @@ public Map getAccessTokenAndRefreshTokenByCode(String code) { String auth = clientId + ":" + clientSecret; byte[] encodedAuth = Base64.getEncoder().encode(auth.getBytes(StandardCharsets.UTF_8)); String authHeader = "Basic " + new String(encodedAuth); - headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + headers.set("Content-Type", "application/x-www-form-urlencoded"); headers.set("Authorization", authHeader); // 요청 본문 설정 MultiValueMap body = new LinkedMultiValueMap<>(); body.add("grant_type", "authorization_code"); body.add("code", code); - body.add("redirect_uri", redirectUri); + body.add("scope", "basic_profile friends_list presence"); + body.add("deployment_id", deploymentId); HttpEntity> request = new HttpEntity<>(body, headers); // Epic Games 토큰 엔드포인트 요청 - ResponseEntity response = restTemplate.exchange( - "https://api.epicgames.dev/epic/oauth/v2/token", + ResponseEntity> response = restTemplate.exchange( + getAccessTokenURL, HttpMethod.POST, request, - Map.class + new ParameterizedTypeReference>() {} ); return response.getBody(); } - public Map getEpicGamesUserAccount(String accessToken) { + public List> getEpicGamesUserAccount(String authorizationHeader) throws Exception { // Epic Games의 OAuth2 토큰 엔드포인트 호출 RestTemplate restTemplate = new RestTemplate(); HttpHeaders headers = new HttpHeaders(); // Bearer Authentication 헤더 추가 - headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); - headers.set("Authorization", accessToken); + headers.set("Authorization", authorizationHeader); + headers.set("Content-Type", "application/x-www-form-urlencoded"); - HttpEntity> request = new HttpEntity<>(headers); + HttpEntity> request = new HttpEntity<>(new LinkedMultiValueMap<>(), headers); // Epic Games 토큰 엔드포인트 요청 - ResponseEntity response; + ResponseEntity>> response; + String accountId = jwtUtil.getSubjectFromAuthHeaderWithoutAuth(authorizationHeader); + System.out.println(accountId); try { response = restTemplate.exchange( - "https://api.epicgames.dev/epic/id/v2/accounts?accountId=" + jwtUtil.getClaimsFromTokenWithAuth(accessToken), + getAccountURL + accountId, HttpMethod.GET, request, - Map.class + new ParameterizedTypeReference>>() {} ); + System.out.println(response); } catch (Exception e) { - throw new RuntimeException(e); + e.printStackTrace(); + throw new RuntimeException("API 요청 중 오류 발생 : " + e.getMessage()); } return response.getBody(); diff --git a/src/main/java/com/mtvs/devlinkbackend/oauth2/service/UserService.java b/src/main/java/com/mtvs/devlinkbackend/oauth2/service/UserService.java index fc394d2..fdb5882 100644 --- a/src/main/java/com/mtvs/devlinkbackend/oauth2/service/UserService.java +++ b/src/main/java/com/mtvs/devlinkbackend/oauth2/service/UserService.java @@ -19,7 +19,7 @@ public UserService(UserRepository userRepository, JwtUtil jwtUtil) { public User registUserByAccessToken(String accessToken) { try { - String accountId = jwtUtil.getSubjectFromTokenWithoutAuth(accessToken); + String accountId = jwtUtil.getSubjectFromAuthHeaderWithoutAuth(accessToken); return userRepository.save(new User( accountId )); @@ -28,9 +28,9 @@ public User registUserByAccessToken(String accessToken) { } } - public User findUserByAccessToken(String accessToken) { + public User findUserByAuthorizationHeader(String authorizationHeader) { try { - String accountId = jwtUtil.getSubjectFromTokenWithoutAuth(accessToken); + String accountId = jwtUtil.getSubjectFromAuthHeaderWithoutAuth(extractToken(authorizationHeader)); return userRepository.findUserByAccountId(accountId); } catch (Exception e) { throw new RuntimeException(e); @@ -39,7 +39,7 @@ public User findUserByAccessToken(String accessToken) { public void updateUserByAccessToken(String accessToken, UserUpdateRequestDTO userUpdateRequestDTO) { try { - String accountId = jwtUtil.getSubjectFromTokenWithoutAuth(accessToken); + String accountId = jwtUtil.getSubjectFromAuthHeaderWithoutAuth(accessToken); User user = userRepository.findUserByAccountId(accountId); if(user != null) { user.setEmail(userUpdateRequestDTO.getEmail()); @@ -53,10 +53,18 @@ public void updateUserByAccessToken(String accessToken, UserUpdateRequestDTO use public void deleteUserByAccessToken(String accessToken) { try { - String accountId = jwtUtil.getSubjectFromTokenWithAuth(accessToken); + String accountId = jwtUtil.getSubjectFromAuthHeaderWithAuth(accessToken); userRepository.deleteUserByAccountId(accountId); } catch (Exception e) { throw new RuntimeException(e); } } + + private String extractToken(String authorizationHeader) { + if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) { + return authorizationHeader.substring(7); + } else { + throw new IllegalArgumentException("Authorization header must start with 'Bearer '"); + } + } } diff --git a/src/main/java/com/mtvs/devlinkbackend/question/controller/QuestionController.java b/src/main/java/com/mtvs/devlinkbackend/question/controller/QuestionController.java index 52e3427..c51567d 100644 --- a/src/main/java/com/mtvs/devlinkbackend/question/controller/QuestionController.java +++ b/src/main/java/com/mtvs/devlinkbackend/question/controller/QuestionController.java @@ -42,7 +42,7 @@ public ResponseEntity createQuestion( @RequestBody QuestionRegistRequestDTO questionRegistRequestDTO, @RequestHeader(name = "Authorization") String authorizationHeader) throws Exception { - String accountId = jwtUtil.getSubjectFromTokenWithAuth(authorizationHeader); + String accountId = jwtUtil.getSubjectFromAuthHeaderWithAuth(authorizationHeader); Question createdQuestion = questionService.registQuestion(questionRegistRequestDTO, accountId); return ResponseEntity.ok(createdQuestion); } @@ -98,7 +98,7 @@ public ResponseEntity> getQuestionsByAccountIdWithPaging( @RequestParam int page, @RequestHeader(name = "Authorization") String authorizationHeader) throws Exception { - String accountId = jwtUtil.getSubjectFromTokenWithoutAuth(authorizationHeader); + String accountId = jwtUtil.getSubjectFromAuthHeaderWithoutAuth(authorizationHeader); List questions = questionService.findQuestionsByAccountIdWithPaging(page, accountId); return ResponseEntity.ok(questions); } @@ -118,7 +118,7 @@ public ResponseEntity updateQuestion( @RequestBody QuestionUpdateRequestDTO questionUpdateRequestDTO, @RequestHeader(name = "Authorization") String authorizationHeader) throws Exception { - String accountId = jwtUtil.getSubjectFromTokenWithoutAuth(authorizationHeader); + String accountId = jwtUtil.getSubjectFromAuthHeaderWithoutAuth(authorizationHeader); try { Question updatedQuestion = questionService.updateQuestion(questionUpdateRequestDTO, accountId); return ResponseEntity.ok(updatedQuestion); diff --git a/src/main/java/com/mtvs/devlinkbackend/reply/controller/ReplyController.java b/src/main/java/com/mtvs/devlinkbackend/reply/controller/ReplyController.java index ef2014a..e010ac2 100644 --- a/src/main/java/com/mtvs/devlinkbackend/reply/controller/ReplyController.java +++ b/src/main/java/com/mtvs/devlinkbackend/reply/controller/ReplyController.java @@ -36,7 +36,7 @@ public ResponseEntity registReply( @RequestBody ReplyRegistRequestDTO replyRegistRequestDTO, @RequestHeader(name = "Authorization") String authorizationHeader) throws Exception { - String accountId = jwtUtil.getSubjectFromTokenWithAuth(authorizationHeader); + String accountId = jwtUtil.getSubjectFromAuthHeaderWithAuth(authorizationHeader); Reply reply = replyService.registReply(replyRegistRequestDTO, accountId); return ResponseEntity.ok(reply); } @@ -75,7 +75,7 @@ public ResponseEntity> findRepliesByQuestionId(@PathVariable Long qu public ResponseEntity> findRepliesByAccountId( @RequestHeader(name = "Authorization") String authorizationHeader) throws Exception { - String accountId = jwtUtil.getSubjectFromTokenWithoutAuth(authorizationHeader); + String accountId = jwtUtil.getSubjectFromAuthHeaderWithoutAuth(authorizationHeader); List replies = replyService.findRepliesByAccountId(accountId); return ResponseEntity.ok(replies); } @@ -91,7 +91,7 @@ public ResponseEntity updateReply( @RequestBody ReplyUpdateRequestDTO replyUpdateRequestDTO, @RequestHeader(name = "Authorization") String authorizationHeader) throws Exception { - String accountId = jwtUtil.getSubjectFromTokenWithoutAuth(authorizationHeader); + String accountId = jwtUtil.getSubjectFromAuthHeaderWithoutAuth(authorizationHeader); try { Reply updatedReply = replyService.updateReply(replyUpdateRequestDTO, accountId); return ResponseEntity.ok(updatedReply); diff --git a/src/main/java/com/mtvs/devlinkbackend/request/controller/RequestController.java b/src/main/java/com/mtvs/devlinkbackend/request/controller/RequestController.java index adae769..76f7f67 100644 --- a/src/main/java/com/mtvs/devlinkbackend/request/controller/RequestController.java +++ b/src/main/java/com/mtvs/devlinkbackend/request/controller/RequestController.java @@ -37,7 +37,7 @@ public ResponseEntity registerRequest( @RequestBody RequestRegistRequestDTO requestDTO, @RequestHeader(name = "Authorization") String authorizationHeader) throws Exception { - String accountId = jwtUtil.getSubjectFromTokenWithoutAuth(authorizationHeader); + String accountId = jwtUtil.getSubjectFromAuthHeaderWithoutAuth(authorizationHeader); Request newRequest = requestService.registRequest(requestDTO, accountId); return new ResponseEntity<>(newRequest, HttpStatus.CREATED); } @@ -65,7 +65,7 @@ public ResponseEntity getRequestById(@PathVariable Long requestId) { public ResponseEntity> getRequestsByAccountId( @RequestHeader(name = "Authorization") String authorizationHeader) throws Exception { - String accountId = jwtUtil.getSubjectFromTokenWithoutAuth(authorizationHeader); + String accountId = jwtUtil.getSubjectFromAuthHeaderWithoutAuth(authorizationHeader); List requests = requestService.findRequestsByAccountId(accountId); return ResponseEntity.ok(requests); } @@ -94,7 +94,7 @@ public ResponseEntity updateRequest( @RequestHeader(name = "Authorization") String authorizationHeader) { try { - String accountId = jwtUtil.getSubjectFromTokenWithoutAuth(authorizationHeader); + String accountId = jwtUtil.getSubjectFromAuthHeaderWithoutAuth(authorizationHeader); Request updatedRequest = requestService.updateRequest(requestDTO, accountId); return ResponseEntity.ok(updatedRequest); } catch (Exception e) { diff --git a/src/main/java/com/mtvs/devlinkbackend/team/controller/TeamController.java b/src/main/java/com/mtvs/devlinkbackend/team/controller/TeamController.java index 5e2d407..4ed5681 100644 --- a/src/main/java/com/mtvs/devlinkbackend/team/controller/TeamController.java +++ b/src/main/java/com/mtvs/devlinkbackend/team/controller/TeamController.java @@ -1,6 +1,7 @@ package com.mtvs.devlinkbackend.team.controller; import com.mtvs.devlinkbackend.config.JwtUtil; +import com.mtvs.devlinkbackend.team.dto.TeamMemberModifyRequestDTO; import com.mtvs.devlinkbackend.team.dto.TeamRegistRequestDTO; import com.mtvs.devlinkbackend.team.dto.TeamUpdateRequestDTO; import com.mtvs.devlinkbackend.team.entity.Team; @@ -63,7 +64,7 @@ public ResponseEntity getTeamById( public ResponseEntity> getTeamsByPmId( @RequestHeader(name = "Authorization") String authorizationHeader) throws Exception { - String pmId = jwtUtil.getSubjectFromTokenWithoutAuth(authorizationHeader); + String pmId = jwtUtil.getSubjectFromAuthHeaderWithoutAuth(authorizationHeader); List teams = teamService.findTeamsByPmId(pmId); return ResponseEntity.ok(teams); } @@ -88,7 +89,7 @@ public ResponseEntity> getTeamsByTeamNameContaining( public ResponseEntity> getTeamsByMemberIdContaining( @RequestHeader(name = "Authorization") String authorizationHeader) throws Exception { - String memberId = jwtUtil.getSubjectFromTokenWithoutAuth(authorizationHeader); + String memberId = jwtUtil.getSubjectFromAuthHeaderWithoutAuth(authorizationHeader); List teams = teamService.findTeamsByMemberIdContaining(memberId); return ResponseEntity.ok(teams); } @@ -112,6 +113,36 @@ public ResponseEntity updateTeam( } } + @Operation(summary = "팀 멤버 추가", description = "길드에 멤버를 추가합니다.") + @ApiResponses({ + @ApiResponse(responseCode = "200", description = "멤버가 성공적으로 추가되었습니다."), + @ApiResponse(responseCode = "403", description = "추가 권한이 없습니다."), + @ApiResponse(responseCode = "404", description = "길드를 찾을 수 없습니다.") + }) + @PostMapping("/member") + public Team addMemberToTeam( + @RequestBody TeamMemberModifyRequestDTO teamMemberModifyRequestDTO, + @RequestHeader(name = "Authorization") String authorizationHeader) throws Exception { + + String accountId = jwtUtil.getSubjectFromAuthHeaderWithoutAuth(authorizationHeader); + return teamService.addMemberToTeam(teamMemberModifyRequestDTO, accountId); + } + + @Operation(summary = "팀 멤버 제거", description = "길드에서 멤버를 제거합니다.") + @ApiResponses({ + @ApiResponse(responseCode = "200", description = "멤버가 성공적으로 제거되었습니다."), + @ApiResponse(responseCode = "403", description = "제거 권한이 없습니다."), + @ApiResponse(responseCode = "404", description = "길드를 찾을 수 없습니다.") + }) + @DeleteMapping("/member") + public Team removeMemberFromTeam( + @RequestBody TeamMemberModifyRequestDTO teamMemberModifyRequestDTO, + @RequestHeader(name = "Authorization") String authorizationHeader) throws Exception { + + String accountId = jwtUtil.getSubjectFromAuthHeaderWithoutAuth(authorizationHeader); + return teamService.removeMemberToTeam(teamMemberModifyRequestDTO, accountId); + } + @Operation(summary = "팀 삭제", description = "ID를 통해 팀을 삭제합니다.") @ApiResponses(value = { @ApiResponse(responseCode = "204", description = "팀이 성공적으로 삭제되었습니다."), diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index d41b934..efb0718 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -21,9 +21,16 @@ spring: user-name-attribute: sub datasource: driver-class-name: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://localhost:3306/devlink - username: root - password: 1234 + url: jdbc:mysql://125.132.216.190:15531/devlink + username: ${MYSQL_USERNAME} + password: ${MYSQL_PASSWORD} + data: + mongodb: + host: 125.132.216.190 + port: 15532 + database: devlink + username: ${MONGO_USERNAME} + password: ${MONGO_PASSWORD} jpa: show-sql: true database: mysql @@ -47,4 +54,16 @@ logging: level: org: springframework: - security: DEBUG \ No newline at end of file + security: DEBUG + +epicgames: + registration: + client-id: ${EPIC_GAMES_CLIENT_ID} + client-secret: ${EPIC_GAMES_CLIENT_SECRET} + deployment-id: ${EPIC_GAMES_DEPLOYMENT_ID} + provider: + epicgames: + authorization-uri: https://www.epicgames.com/id/authorize + token-uri: https://api.epicgames.dev/epic/oauth/v2/token + account-uri: https://api.epicgames.dev/epic/id/v2/accounts + validate-uri: https://api.epicgames.dev/epic/oauth/v2/tokenInfo \ No newline at end of file diff --git a/src/test/java/com/mtvs/devlinkbackend/crud/ChannelCRUDTest.java b/src/test/java/com/mtvs/devlinkbackend/crud/ChannelCRUDTest.java new file mode 100644 index 0000000..cdc8514 --- /dev/null +++ b/src/test/java/com/mtvs/devlinkbackend/crud/ChannelCRUDTest.java @@ -0,0 +1,75 @@ +package com.mtvs.devlinkbackend.crud; + +import com.mtvs.devlinkbackend.channel.dto.ChannelRegistRequestDTO; +import com.mtvs.devlinkbackend.channel.dto.ChannelUpdateRequestDTO; +import com.mtvs.devlinkbackend.channel.entity.PositionType; +import com.mtvs.devlinkbackend.channel.service.ChannelService; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.junit.jupiter.params.provider.ValueSource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Arrays; +import java.util.stream.Stream; + +@SpringBootTest +@Transactional +public class ChannelCRUDTest { + + @Autowired + private ChannelService channelService; + + private static Stream newChannel() { + return Stream.of( + Arguments.of(new ChannelRegistRequestDTO(Arrays.asList(new PositionType(new PositionType.Position(1, 2, 3), "chair"))), "0bb31d25962c4817be894044371d4d3c"), + Arguments.of(new ChannelRegistRequestDTO(Arrays.asList(new PositionType(new PositionType.Position(4, 5, 6), "grass"))), "0bb31d25962c4817be894044371d4d3c") + ); + } + + private static Stream modifiedChannel() { + return Stream.of( + Arguments.of(new ChannelUpdateRequestDTO("27ceb93e-bf35-4058-9a07-46550cf1aa00", Arrays.asList(new PositionType(new PositionType.Position(1, 2, 3), "chair"))), "0bb31d25962c4817be894044371d4d3c"), + Arguments.of(new ChannelUpdateRequestDTO("27ceb93e-bf35-4058-9a07-46550cf1aa00", Arrays.asList(new PositionType(new PositionType.Position(3, 1, 2), "block"))), "0bb31d25962c4817be894044371d4d3c") + ); + } + + @DisplayName("채널 등록 테스트") + @ParameterizedTest + @MethodSource("newChannel") + public void testCreateChannel(ChannelRegistRequestDTO channelRegistRequestDTO, String accountId) { + Assertions.assertDoesNotThrow(() -> channelService.saveChannel(channelRegistRequestDTO, accountId)); + } + + @DisplayName("채널 PK로 조회 테스트") + @ValueSource(strings = {"79673000-2800-4226-ac32-fae65cd0a55c"}) + @ParameterizedTest + public void testFindChannelByChannelId(String channelId) { + Assertions.assertDoesNotThrow(() -> channelService.findChannelByChannelId(channelId)); + } + + @DisplayName("모든 채널 조회 테스트") + @Test + public void testFindAllChannels() { + Assertions.assertDoesNotThrow(() -> channelService.findAllChannels()); + } + + @DisplayName("채널 수정 테스트") + @MethodSource("modifiedChannel") + @ParameterizedTest + public void testUpdateChannel(ChannelUpdateRequestDTO channelUpdateRequestDTO, String accountId) { + Assertions.assertDoesNotThrow(() -> channelService.updateChannel(channelUpdateRequestDTO, accountId)); + } + + @DisplayName("채널 삭제 테스트") + @ValueSource(strings = {"79673000-2800-4226-ac32-fae65cd0a55c"}) + @ParameterizedTest + public void testDeleteChannel(String channelId) { + Assertions.assertDoesNotThrow(() -> channelService.deleteChannel(channelId)); + } +} diff --git a/src/test/java/com/mtvs/devlinkbackend/crud/TeamCRUDTest.java b/src/test/java/com/mtvs/devlinkbackend/crud/TeamCRUDTest.java index 1c81c3c..2547da1 100644 --- a/src/test/java/com/mtvs/devlinkbackend/crud/TeamCRUDTest.java +++ b/src/test/java/com/mtvs/devlinkbackend/crud/TeamCRUDTest.java @@ -1,5 +1,6 @@ package com.mtvs.devlinkbackend.crud; +import com.mtvs.devlinkbackend.team.dto.TeamMemberModifyRequestDTO; import com.mtvs.devlinkbackend.team.dto.TeamRegistRequestDTO; import com.mtvs.devlinkbackend.team.dto.TeamUpdateRequestDTO; import com.mtvs.devlinkbackend.team.service.TeamService; @@ -31,13 +32,20 @@ private static Stream newTeam() { ); } - private static Stream modifiedTeam() { + private static Stream updatedTeam() { return Stream.of( Arguments.of(new TeamUpdateRequestDTO(1L,"팀 이름0", "소개0", List.of("계정2","계정3")), "계정1"), Arguments.of(new TeamUpdateRequestDTO(2L,"팀 이름00", "소개00", List.of("계정1","계정3")), "계정2") ); } + private static Stream modifiedTeam() { + return Stream.of( + Arguments.of(new TeamMemberModifyRequestDTO(1L, List.of("계정2","계정3")), "계정1"), + Arguments.of(new TeamMemberModifyRequestDTO(2L, List.of("계정3","계정4")), "계정2") + ); + } + @DisplayName("팀 추가 테스트") @ParameterizedTest @MethodSource("newTeam") @@ -83,7 +91,7 @@ public void testFindTeamsByTeamNameContaining(String teamName) { } @DisplayName("팀 수정 테스트") - @MethodSource("modifiedTeam") + @MethodSource("updatedTeam") @ParameterizedTest @Order(5) public void testUpdateTeam(TeamUpdateRequestDTO questionUpdateRequestDTO, String accountId) { @@ -91,10 +99,28 @@ public void testUpdateTeam(TeamUpdateRequestDTO questionUpdateRequestDTO, String System.out.println(teamService.updateTeam(questionUpdateRequestDTO, accountId))); } + @DisplayName("팀 멤버 추가 테스트") + @MethodSource("modifiedTeam") + @ParameterizedTest + @Order(5) + public void testAddMemberToTeam(TeamMemberModifyRequestDTO teamMemberModifyRequestDTO, String accountId) { + Assertions.assertDoesNotThrow(() -> + System.out.println(teamService.addMemberToTeam(teamMemberModifyRequestDTO, accountId))); + } + + @DisplayName("팀 멤버 삭제 테스트") + @MethodSource("modifiedTeam") + @ParameterizedTest + @Order(5) + public void testRemoveMemberToTeam(TeamMemberModifyRequestDTO teamMemberModifyRequestDTO, String accountId) { + Assertions.assertDoesNotThrow(() -> + System.out.println(teamService.removeMemberToTeam(teamMemberModifyRequestDTO, accountId))); + } + @DisplayName("팀 삭제 테스트") @ValueSource(longs = {0,1}) @ParameterizedTest - @Order(6) + @Order(8) public void testDeleteTeam(long teamId) { Assertions.assertDoesNotThrow(() -> teamService.deleteTeam(teamId));