From caac306fd9c3c19012d948b3c7f6be6256a3aae0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EC=B2=9C=20=EC=A7=84=EA=B0=95?= <jjjjjk12@ajou.ac.kr>
Date: Mon, 10 Mar 2025 16:29:35 +0900
Subject: [PATCH 1/2] =?UTF-8?q?feat:=20=EC=96=B4=EB=93=9C=EB=AF=BC=20?=
 =?UTF-8?q?=EA=B6=8C=ED=95=9C=20=ED=99=95=EC=9D=B8=20=EB=A1=9C=EC=A7=81=20?=
 =?UTF-8?q?=EC=B6=94=EA=B0=80?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../aolda/itda/dto/auth/LoginResponseDTO.java |  2 +-
 .../com/aolda/itda/service/AuthService.java   | 83 +++++++++++++++++--
 2 files changed, 78 insertions(+), 7 deletions(-)

diff --git a/src/main/java/com/aolda/itda/dto/auth/LoginResponseDTO.java b/src/main/java/com/aolda/itda/dto/auth/LoginResponseDTO.java
index a5aa14a..33ba32f 100644
--- a/src/main/java/com/aolda/itda/dto/auth/LoginResponseDTO.java
+++ b/src/main/java/com/aolda/itda/dto/auth/LoginResponseDTO.java
@@ -13,5 +13,5 @@ import java.util.List;
 @Builder
 public class LoginResponseDTO {
     private Boolean isAdmin;
-    private List<ProjectIdAndNameDTO> lists;
+    private List<ProjectIdAndNameDTO> projects;
 }
diff --git a/src/main/java/com/aolda/itda/service/AuthService.java b/src/main/java/com/aolda/itda/service/AuthService.java
index 88062f7..80f7196 100644
--- a/src/main/java/com/aolda/itda/service/AuthService.java
+++ b/src/main/java/com/aolda/itda/service/AuthService.java
@@ -38,15 +38,16 @@ public class AuthService {
 
         String userId = user.get("id");
         String token = user.get("token");
+        String systemToken = getSystemToken(userId, loginRequestDTO.getPassword());
 
         if (userId == null || token == null) {
             throw new CustomException(ErrorCode.INVALID_USER_INFO);
         }
 
-        response.addHeader("X-Subject-Token", token);
+        response.addHeader("X-Subject-Token", systemToken != null ? systemToken : token);
         return LoginResponseDTO.builder()
-                .isAdmin(false)
-                .lists(getProjectsWithUser(user))
+                .isAdmin(systemToken != null)
+                .projects(getProjectsWithUser(user))
                 .build();
     }
 
@@ -88,6 +89,50 @@ public class AuthService {
                     "token", token);
     }
 
+    private String getSystemToken(String id, String password) {
+
+        String url = keystone + "/auth/tokens";
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(MediaType.APPLICATION_JSON);
+
+        String requestBody = "{\n" +
+                "    \"auth\": {\n" +
+                "        \"identity\": {\n" +
+                "            \"methods\": [\n" +
+                "                \"password\"\n" +
+                "            ],\n" +
+                "            \"password\": {\n" +
+                "                \"user\": {\n" +
+                "                    \"id\": \"" + id + "\",\n" +
+                "                    \"password\": \"" + password + "\"\n" +
+                "                }\n" +
+                "            }\n" +
+                "        },\n" +
+                "        \"scope\": {\n" +
+                "            \"system\": {\n" +
+                "                \"all\": true\n" +
+                "            }\n" +
+                "        }\n" +
+                "    }\n" +
+                "}";
+
+        HttpEntity<String> requestEntity;
+        ResponseEntity<Map> res;
+        try {
+            requestEntity = new HttpEntity<>(requestBody, headers);
+            res = restTemplate.postForEntity(url, requestEntity, Map.class);
+        } catch (RuntimeException e) {
+            return null;
+        }
+
+        Map<String, Object> resToken = (Map<String, Object>) res.getBody().get("token");
+        Map<String, Object> resUser = (Map<String, Object>) resToken.get("user");
+        String userId = (String) resUser.get("id");
+        String token = res.getHeaders().getFirst("X-Subject-Token");
+
+        return token;
+    }
+
     // 특정 사용자의 특정 프로젝트 내 최고 권한 반환
     public Map<String, String> getBestRoleWithinProject(String token, String projectId) throws JsonProcessingException {
         return getBestRoleWithinProject(Map.of(
@@ -107,7 +152,7 @@ public class AuthService {
         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());
+        headers.set("X-Auth-Token", token);
 
         HttpEntity<String> requestEntity = new HttpEntity<>(headers);
         ResponseEntity<String> res = restTemplate.exchange(url, HttpMethod.GET, requestEntity, String.class);
@@ -151,7 +196,7 @@ public class AuthService {
         String url = keystone + "/users/" + userId + "/projects";
 
         HttpHeaders headers = new HttpHeaders();
-        headers.set("X-Auth-Token", getAdminToken());
+        headers.set("X-Auth-Token", token);
 
         HttpEntity<String> requestEntity = new HttpEntity<>(headers);
         ResponseEntity<String> res = restTemplate.exchange(url, HttpMethod.GET, requestEntity, String.class);
@@ -172,7 +217,7 @@ public class AuthService {
     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-Auth-Token", token);
         headers.set("X-Subject-Token", token);
         HttpEntity<String> requestEntity = new HttpEntity<>(headers);
         ResponseEntity<String> res;
@@ -184,4 +229,30 @@ public class AuthService {
         return objectMapper.readTree(res.getBody()).path("token").path("user").path("id").asText();
 
     }
+
+    private Boolean isAdmin(Map<String, String> user) throws JsonProcessingException {
+        String url = keystone + "/role_assignments?user.id=" + user.get("id") + "&scope.system&include_names";
+        HttpHeaders headers = new HttpHeaders();
+        headers.set("X-Auth-Token", user.get("token"));
+        HttpEntity<String> requestEntity = new HttpEntity<>(headers);
+        ResponseEntity<String> res;
+        try {
+            res = restTemplate.exchange(url, HttpMethod.GET, requestEntity, String.class);
+        } catch (RuntimeException e) {
+            e.printStackTrace();
+            System.out.println("runtime");
+            return false;
+        }
+        JsonNode node = objectMapper.readTree(res.getBody()).path("role_assignments");
+        String system_all = node.path("scope").path("system").path("all").asText();
+        String role = node.path("role").path("name").asText();
+        System.out.println("role: " + role);
+        if (system_all.equals("true") && role.equals("admin")) {
+            System.out.println(system_all);
+            return true;
+        }
+        System.out.println("hi");
+        return false;
+
+    }
 }
-- 
GitLab


From 7320a6e16e89547ad69925d35196b7d0d57a43b3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EC=B2=9C=20=EC=A7=84=EA=B0=95?= <jjjjjk12@ajou.ac.kr>
Date: Mon, 10 Mar 2025 17:31:35 +0900
Subject: [PATCH 2/2] =?UTF-8?q?fix:=20project=20token=EC=9C=BC=EB=A1=9C=20?=
 =?UTF-8?q?project=20role=20=ED=99=95=EC=9D=B8=ED=95=98=EB=8F=84=EB=A1=9D?=
 =?UTF-8?q?=20=EC=88=98=EC=A0=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../com/aolda/itda/service/AuthService.java   | 52 ++++++++++++++++++-
 1 file changed, 51 insertions(+), 1 deletion(-)

diff --git a/src/main/java/com/aolda/itda/service/AuthService.java b/src/main/java/com/aolda/itda/service/AuthService.java
index 80f7196..1dea9a2 100644
--- a/src/main/java/com/aolda/itda/service/AuthService.java
+++ b/src/main/java/com/aolda/itda/service/AuthService.java
@@ -15,6 +15,7 @@ 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.RestClientException;
 import org.springframework.web.client.RestTemplate;
 
 import java.util.*;
@@ -133,11 +134,59 @@ public class AuthService {
         return token;
     }
 
+    private String getProjectToken(String unscopedToken, String projectId) {
+
+        String url = keystone + "/auth/tokens";
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(MediaType.APPLICATION_JSON);
+
+
+        String requestBody = "{\n" +
+                "    \"auth\": {\n" +
+                "        \"identity\": {\n" +
+                "            \"methods\": [\n" +
+                "                \"token\"\n" +
+                "            ],\n" +
+                "            \"token\": {\n" +
+                "                \"id\": \"" + unscopedToken +"\"\n" +
+                "            }\n" +
+                "        },\n" +
+                "        \"scope\": {\n" +
+                "            \"project\": {\n" +
+                "                \"id\": \""+ projectId +"\"\n" +
+                "            }\n" +
+                "        }\n" +
+                "    }\n" +
+                "}";
+
+        HttpEntity<String> requestEntity;
+        ResponseEntity<Map> res;
+        try {
+            requestEntity = new HttpEntity<>(requestBody, headers);
+            res = restTemplate.postForEntity(url, requestEntity, Map.class);
+        } catch (HttpClientErrorException.Forbidden e) {
+            return unscopedToken;
+        }
+        catch (RuntimeException e) {
+            e.printStackTrace();
+            throw new CustomException(ErrorCode.INVALID_TOKEN);
+        }
+
+        Map<String, Object> resToken = (Map<String, Object>) res.getBody().get("token");
+        Map<String, Object> resUser = (Map<String, Object>) resToken.get("user");
+        String userId = (String) resUser.get("id");
+        String token = res.getHeaders().getFirst("X-Subject-Token");
+
+        return token;
+    }
+
+
     // 특정 사용자의 특정 프로젝트 내 최고 권한 반환
     public Map<String, String> getBestRoleWithinProject(String token, String projectId) throws JsonProcessingException {
+
         return getBestRoleWithinProject(Map.of(
                 "id", validateTokenAndGetUserId(token),
-                "token", token),
+                "token", getProjectToken(token, projectId)),
                 projectId);
     }
 
@@ -224,6 +273,7 @@ public class AuthService {
         try {
             res = restTemplate.exchange(url, HttpMethod.GET, requestEntity, String.class);
         } catch (HttpClientErrorException.NotFound e) {
+            System.out.println("validate");
             throw new CustomException(ErrorCode.INVALID_TOKEN);
         }
         return objectMapper.readTree(res.getBody()).path("token").path("user").path("id").asText();
-- 
GitLab