Skip to content
Snippets Groups Projects
Commit de87acd2 authored by nahyun's avatar nahyun
Browse files

Merge branch 'feat/auth' into 'dev'

Feat/auth 프로젝트 role 조회 api 추가

See merge request !3
parents 0b638ed2 cf23a243
No related branches found
No related tags found
3 merge requests!15Feat/certificate,!6Feat/forwarding 포트포워딩 CRUD,!3Feat/auth 프로젝트 role 조회 api 추가
......@@ -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));
}
}
package com.aolda.itda.dto.auth;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import java.util.List;
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class ProjectRoleDTO {
private String projectName;
private String roleName;
}
......@@ -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;
......
......@@ -3,7 +3,6 @@ package com.aolda.itda.service;
import com.aolda.itda.dto.auth.LoginRequestDTO;
import com.aolda.itda.dto.auth.LoginResponseDTO;
import com.aolda.itda.dto.auth.ProjectIdAndNameDTO;
import com.aolda.itda.dto.auth.ProjectRoleDTO;
import com.aolda.itda.exception.CustomException;
import com.aolda.itda.exception.ErrorCode;
import com.fasterxml.jackson.core.JsonProcessingException;
......@@ -15,6 +14,7 @@ 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.RestTemplate;
import java.util.*;
......@@ -88,8 +88,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 +104,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 +115,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 +140,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 +168,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();
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment