diff --git a/src/main/java/com/aolda/itda/controller/AuthController.java b/src/main/java/com/aolda/itda/controller/AuthController.java index 274ad8fe399c07e460c495151160a017cd8f1b52..79046d2d2459cde40b302cc0e190d3240280257e 100644 --- a/src/main/java/com/aolda/itda/controller/AuthController.java +++ b/src/main/java/com/aolda/itda/controller/AuthController.java @@ -6,10 +6,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("/api/auth") @@ -24,4 +21,11 @@ public class AuthController { return ResponseEntity.ok(authService.userLogin(response, loginRequestDTO)); } + + @GetMapping("/role") + public ResponseEntity<Object> roleWithinProject(@RequestHeader("X-Subject-Token") String token, + @RequestParam String projectId) throws JsonProcessingException { + + return ResponseEntity.ok(authService.getBestRoleWithinProject(token, projectId)); + } } diff --git a/src/main/java/com/aolda/itda/exception/ErrorCode.java b/src/main/java/com/aolda/itda/exception/ErrorCode.java index 6bcb6431ef8ff826b318abd9d72cc5d2255aadcd..0916e71a1ef9a0824f3541ae257d490236c42cb3 100644 --- a/src/main/java/com/aolda/itda/exception/ErrorCode.java +++ b/src/main/java/com/aolda/itda/exception/ErrorCode.java @@ -9,7 +9,10 @@ import org.springframework.http.HttpStatus; public enum ErrorCode { // User - INVALID_USER_INFO(HttpStatus.BAD_REQUEST, "잘못된 회원 정보입니다"); + INVALID_USER_INFO(HttpStatus.BAD_REQUEST, "잘못된 회원 정보입니다"), + + // Token + INVALID_TOKEN(HttpStatus.BAD_REQUEST, "잘못된 토큰입니다"); private final HttpStatus status; private final String message; diff --git a/src/main/java/com/aolda/itda/service/AuthService.java b/src/main/java/com/aolda/itda/service/AuthService.java index 5f071eef2e680b74779350994fb6c355e2333b66..6fea01ea0d611b09e88be7aa338edeb6887025ff 100644 --- a/src/main/java/com/aolda/itda/service/AuthService.java +++ b/src/main/java/com/aolda/itda/service/AuthService.java @@ -15,6 +15,9 @@ import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.*; import org.springframework.stereotype.Service; +import org.springframework.web.client.HttpClientErrorException; +import org.springframework.web.client.HttpStatusCodeException; +import org.springframework.web.client.RestClientException; import org.springframework.web.client.RestTemplate; import java.util.*; @@ -88,8 +91,15 @@ public class AuthService { "token", token); } - // 특정 사용자의 프로젝트별 Role 반환 - private List<ProjectRoleDTO> getRolesWithProjects(Map<String, String> user) throws JsonProcessingException { + // 특정 사용자의 특정 프로젝트 내 최고 권한 반환 + public Map<String, String> getBestRoleWithinProject(String token, String projectId) throws JsonProcessingException { + return getBestRoleWithinProject(Map.of( + "id", validateTokenAndGetUserId(token), + "token", token), + projectId); + } + + private Map<String, String> getBestRoleWithinProject(Map<String, String> user, String projectId) throws JsonProcessingException { String userId = user.get("id"); String token = user.get("token"); @@ -97,7 +107,7 @@ public class AuthService { throw new CustomException(ErrorCode.INVALID_USER_INFO); } - String url = keystone + "/role_assignments?user.id=" + userId + "&effective&include_names=true"; + String url = keystone + "/role_assignments?user.id=" + userId + "&effective&include_names=true&scope.project.id=" + projectId; HttpHeaders headers = new HttpHeaders(); headers.set("X-Auth-Token", getAdminToken()); @@ -108,19 +118,23 @@ public class AuthService { JsonNode node = objectMapper.readTree(res.getBody()); ArrayNode arrayNode = (ArrayNode) node.get("role_assignments"); - List<ProjectRoleDTO> lists = new ArrayList<>(); + String bestRole = "reader"; for (JsonNode assignment : arrayNode) { - String projectName = assignment.path("scope").path("project").path("name").asText(); String roleName = assignment.path("role").path("name").asText(); - ProjectRoleDTO projectRoleDTO = new ProjectRoleDTO(projectName, roleName); - lists.add(projectRoleDTO); + if (roleName.equals("admin")) { // admin인 경우 + bestRole = roleName; + } else if (roleName.equals("manager") && !bestRole.equals("admin")) { // 최고 권한이 admin이 아닌 경우 + bestRole = roleName; + } else if (roleName.equals("member") && bestRole.equals("reader")) { // 최고 권한이 reader인 경우 + bestRole = roleName; + } } - return lists; + return Map.of("role", bestRole); } // 관리자용 토큰 발행 @@ -129,6 +143,7 @@ public class AuthService { return user.get("token"); } + // 특정 사용자의 참여 프로젝트 반환 private List<ProjectIdAndNameDTO> getProjectsWithUser(Map<String, String> user) throws JsonProcessingException { String userId = user.get("id"); String token = user.get("token"); @@ -156,4 +171,20 @@ public class AuthService { } return lists; } + + private String validateTokenAndGetUserId(String token) throws JsonProcessingException { + String url = keystone + "/auth/tokens"; + HttpHeaders headers = new HttpHeaders(); + headers.set("X-Auth-Token", getAdminToken()); + headers.set("X-Subject-Token", token); + HttpEntity<String> requestEntity = new HttpEntity<>(headers); + ResponseEntity<String> res; + try { + res = restTemplate.exchange(url, HttpMethod.GET, requestEntity, String.class); + } catch (HttpClientErrorException.NotFound e) { + throw new CustomException(ErrorCode.INVALID_TOKEN); + } + return objectMapper.readTree(res.getBody()).path("token").path("user").path("id").asText(); + + } }