Skip to content
Merged
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package com.mtvs.devlinkbackend.character.controller;

import com.mtvs.devlinkbackend.character.dto.UserCharacterRegistRequestDTO;
import com.mtvs.devlinkbackend.character.dto.UserCharacterUpdateRequestDTO;
import com.mtvs.devlinkbackend.character.entity.UserCharacter;
import com.mtvs.devlinkbackend.character.service.UserCharacterService;
import com.mtvs.devlinkbackend.util.JwtUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/character")
public class UserCharacterController {
private final UserCharacterService userCharacterService;
private final JwtUtil jwtUtil;

public UserCharacterController(UserCharacterService userCharacterService, JwtUtil jwtUtil) {
this.userCharacterService = userCharacterService;
this.jwtUtil = jwtUtil;
}

@Operation(summary = "캐릭터 등록", description = "새로운 캐릭터를 등록합니다.")
@ApiResponse(responseCode = "201", description = "캐릭터가 성공적으로 등록되었습니다.")
@PostMapping
public ResponseEntity<UserCharacter> registerCharacter(
@RequestBody UserCharacterRegistRequestDTO userCharacterRegistRequestDTO,
@RequestHeader(name = "Authorization") String authorizationHeader) throws Exception {

String accountId = jwtUtil.getSubjectFromAuthHeaderWithoutAuth(authorizationHeader);
UserCharacter userCharacter = userCharacterService.registCharacter(userCharacterRegistRequestDTO, accountId);
return new ResponseEntity<>(userCharacter, HttpStatus.CREATED);
}

@Operation(summary = "캐릭터 조회", description = "계정 ID로 캐릭터를 조회합니다.")
@ApiResponse(responseCode = "200", description = "캐릭터가 성공적으로 조회되었습니다.")
@ApiResponse(responseCode = "404", description = "해당 계정 ID로 캐릭터를 찾을 수 없습니다.")
@GetMapping
public ResponseEntity<UserCharacter> getCharacter(
@RequestHeader(name = "Authorization") String authorizationHeader) throws Exception {

String accountId = jwtUtil.getSubjectFromAuthHeaderWithoutAuth(authorizationHeader);
UserCharacter userCharacter = userCharacterService.findCharacterByAccountId(accountId);
if (userCharacter == null) {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
return new ResponseEntity<>(userCharacter, HttpStatus.OK);
}

@Operation(summary = "캐릭터 수정", description = "계정 ID로 캐릭터를 수정합니다.")
@ApiResponse(responseCode = "200", description = "캐릭터가 성공적으로 수정되었습니다.")
@ApiResponse(responseCode = "404", description = "해당 계정 ID로 캐릭터를 찾을 수 없습니다.")
@PatchMapping
public ResponseEntity<UserCharacter> updateCharacter(
@RequestBody UserCharacterUpdateRequestDTO userCharacterUpdateRequestDTO,
@RequestHeader(name = "Authorization") String authorizationHeader) throws Exception {

String accountId = jwtUtil.getSubjectFromAuthHeaderWithoutAuth(authorizationHeader);
try {
UserCharacter updatedCharacter = userCharacterService.updateCharacter(userCharacterUpdateRequestDTO, accountId);
return new ResponseEntity<>(updatedCharacter, HttpStatus.OK);
} catch (IllegalArgumentException e) {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
}

@Operation(summary = "캐릭터 삭제", description = "계정 ID로 캐릭터를 삭제합니다.")
@ApiResponse(responseCode = "204", description = "캐릭터가 성공적으로 삭제되었습니다.")
@ApiResponse(responseCode = "404", description = "해당 계정 ID로 캐릭터를 찾을 수 없습니다.")
@DeleteMapping
public ResponseEntity<Void> deleteCharacter(
@RequestHeader(name = "Authorization") String authorizationHeader) throws Exception {

String accountId = jwtUtil.getSubjectFromAuthHeaderWithoutAuth(authorizationHeader);
userCharacterService.deleteCharacterByAccountId(accountId);
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.mtvs.devlinkbackend.character.dto;

import lombok.*;

import java.util.List;

@Getter @Setter
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class UserCharacterRegistRequestDTO {
private List<Integer> status;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.mtvs.devlinkbackend.character.dto;

import lombok.*;

import java.util.List;

@Getter @Setter
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class UserCharacterUpdateRequestDTO {
private Long characterId;
private List<Integer> status;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.mtvs.devlinkbackend.character.entity;

import jakarta.persistence.*;
import lombok.Getter;

import java.util.List;

@Table(name = "USER_CHARACTER")
@Entity(name = "UserCharacter")
@Getter
public class UserCharacter {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "CHARACTER_ID")
private Long characterId;

@Column(name = "ACCOUNT_ID", unique = true)
private String accountId;

@ElementCollection
@CollectionTable(name = "STATUS_LIST", joinColumns = @JoinColumn(name = "CHARACTER_ID"))
@Column(name = "STATUS")
private List<Integer> status;

public UserCharacter() {
}

public UserCharacter(String accountId, List<Integer> status) {
this.accountId = accountId;
this.status = status;
}

public void setAccountId(String accountId) {
this.accountId = accountId;
}

public void setStatus(List<Integer> status) {
this.status = status;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.mtvs.devlinkbackend.character.repository;

import com.mtvs.devlinkbackend.character.entity.UserCharacter;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface UserCharacterRepository extends JpaRepository<UserCharacter, Long> {
UserCharacter findByAccountId(String accountId);
void deleteByAccountId(String accountId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.mtvs.devlinkbackend.character.service;

import com.mtvs.devlinkbackend.character.dto.UserCharacterRegistRequestDTO;
import com.mtvs.devlinkbackend.character.dto.UserCharacterUpdateRequestDTO;
import com.mtvs.devlinkbackend.character.entity.UserCharacter;
import com.mtvs.devlinkbackend.character.repository.UserCharacterRepository;
import jakarta.transaction.Transactional;
import org.springframework.stereotype.Service;

@Service
public class UserCharacterService {
private final UserCharacterRepository userCharacterRepository;

public UserCharacterService(UserCharacterRepository userCharacterRepository) {
this.userCharacterRepository = userCharacterRepository;
}

@Transactional
public UserCharacter registCharacter(UserCharacterRegistRequestDTO userCharacterRegistRequestDTO, String accountId) {
return userCharacterRepository.save(new UserCharacter(
accountId,
userCharacterRegistRequestDTO.getStatus()
));
}

public UserCharacter findCharacterByAccountId(String accountId) {
return userCharacterRepository.findByAccountId(accountId);
}

@Transactional
public UserCharacter updateCharacter(UserCharacterUpdateRequestDTO userCharacterUpdateRequestDTO, String accountId) {
UserCharacter userCharacter = userCharacterRepository.findByAccountId(accountId);
if(userCharacter == null)
throw new IllegalArgumentException("잘못된 계정으로 캐릭터 수정 시도");

userCharacter.setStatus(userCharacterUpdateRequestDTO.getStatus());
return userCharacter;
}

public void deleteCharacterByAccountId(String accountId) {
userCharacterRepository.deleteByAccountId(accountId);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package com.mtvs.devlinkbackend.crud;

import com.mtvs.devlinkbackend.character.dto.UserCharacterRegistRequestDTO;
import com.mtvs.devlinkbackend.character.dto.UserCharacterUpdateRequestDTO;
import com.mtvs.devlinkbackend.character.service.UserCharacterService;
import jakarta.transaction.Transactional;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Order;
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 java.util.List;
import java.util.stream.Stream;

@SpringBootTest
@Transactional
public class UserCharacterCRUDTest {
@Autowired
private UserCharacterService userCharacterService;

private static Stream<Arguments> registUserCharacter() {
return Stream.of(
Arguments.of(new UserCharacterRegistRequestDTO(
List.of(5,6)
), "계정3"),
Arguments.of(new UserCharacterRegistRequestDTO(
List.of(7,8)
), "계정4")
);
}

private static Stream<Arguments> modifyUserCharacter() {
return Stream.of(
Arguments.of(new UserCharacterUpdateRequestDTO(
1L,
List.of(13,2)
), "계정1"),
Arguments.of(new UserCharacterUpdateRequestDTO(
2L,
List.of(43,4)
), "계정2")
);
}

@BeforeEach
public void setUp() {
userCharacterService.registCharacter(new UserCharacterRegistRequestDTO(
List.of(1,2)
), "계정1");
userCharacterService.registCharacter(new UserCharacterRegistRequestDTO(
List.of(3,4)
), "계정2");
}

@Order(1)
@DisplayName("UserCharacter 등록")
@MethodSource("registUserCharacter")
@ParameterizedTest
public void testRegistUserCharacter(UserCharacterRegistRequestDTO userCharacterRegistRequestDTO, String accountId) {
Assertions.assertDoesNotThrow(() -> userCharacterService.registCharacter(userCharacterRegistRequestDTO, accountId));
}

@Order(2)
@DisplayName("계정 ID로 UserCharacter 조회")
@ValueSource(strings = {"계정1", "계정2"})
@ParameterizedTest
public void testFindUserCharacterByAccountId(String accountId) {
Assertions.assertDoesNotThrow(() -> userCharacterService.findCharacterByAccountId(accountId));
}

@Order(3)
@DisplayName("UserCharacter 수정")
@MethodSource("modifyUserCharacter")
@ParameterizedTest
public void testUpdateUserCharacter(UserCharacterUpdateRequestDTO userCharacterUpdateRequestDTO, String accountId) {
Assertions.assertDoesNotThrow(() -> userCharacterService.updateCharacter(userCharacterUpdateRequestDTO, accountId));
}

@Order(4)
@DisplayName("UserCharacter 삭제")
@ValueSource(strings = {"계정1", "계정2"})
@ParameterizedTest
public void testDeleteByAccountId(String accountId) {
Assertions.assertDoesNotThrow(() -> userCharacterService.deleteCharacterByAccountId(accountId));
}
}