From f0764d698fdeb47a08eebbe1bd80aa6af549e3e9 Mon Sep 17 00:00:00 2001 From: kaede10 Date: Mon, 12 Aug 2024 10:43:14 +0800 Subject: [PATCH 1/3] add permission --- .../adapter/query/CoAdminAdapter.java | 78 ++++++++++++++++++ .../adapter/query/CoMaintainerAdapter.java | 74 +++++++++++++++++ .../common/account/UerPermissionDef.java | 5 ++ .../common/account/UserPermission.java | 82 +++++++++++++++++++ .../annotation/CoMaintainerPermission.java | 22 +++++ .../common/aop/CoMaintainerAspect.java | 64 +++++++++++++++ 6 files changed, 325 insertions(+) create mode 100644 src/main/java/com/easysoftware/adapter/query/CoAdminAdapter.java create mode 100644 src/main/java/com/easysoftware/adapter/query/CoMaintainerAdapter.java create mode 100644 src/main/java/com/easysoftware/common/annotation/CoMaintainerPermission.java create mode 100644 src/main/java/com/easysoftware/common/aop/CoMaintainerAspect.java diff --git a/src/main/java/com/easysoftware/adapter/query/CoAdminAdapter.java b/src/main/java/com/easysoftware/adapter/query/CoAdminAdapter.java new file mode 100644 index 0000000..bb9488c --- /dev/null +++ b/src/main/java/com/easysoftware/adapter/query/CoAdminAdapter.java @@ -0,0 +1,78 @@ +package com.easysoftware.adapter.query; + +import java.util.HashMap; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import com.easysoftware.common.account.UerPermissionDef; +import com.easysoftware.common.account.UserPermission; +import com.easysoftware.common.annotation.PreUserPermission; +import com.easysoftware.common.aop.RequestLimitRedis; +import com.easysoftware.common.entity.MessageCode; +import com.easysoftware.common.utils.ResultUtil; + +@RestController +@RequestMapping("/collaboration/admin") +public class CoAdminAdapter { + /** + * Logger for ApplicationVersionQueryAdapter. + */ + private static final Logger LOGGER = LoggerFactory.getLogger(CoAdminAdapter.class); + + /** + * Define current functional permissions. + */ + private static final String[] REQUIRE_PERMISSIONS = {UerPermissionDef.COLLABORATION_PERMISSION_ADMIN}; + + /** + * Autowired UserPermission for check user permission. + */ + @Autowired + private UserPermission userPermission; + + /** + * Endpoint to search for repos based on the provided search + * condition. + * + * @param repo The search condition for querying repos. + * @return ResponseEntity. + */ + @GetMapping() + @RequestLimitRedis() + @PreUserPermission(UerPermissionDef.COLLABORATION_PERMISSION_ADMIN) + public ResponseEntity queryRepos(@RequestParam(value = "repo") String repo) { + return ResultUtil.success(HttpStatus.OK, "success"); + } + + /** + * Check if the user has permission to access. + * + * @return ResponseEntity. + */ + @GetMapping("/permission") + @RequestLimitRedis() + public ResponseEntity checkPermission() { + HashMap result = new HashMap<>(); + try { + boolean permissionFlag = userPermission.checkUserPermission(REQUIRE_PERMISSIONS); + + if (permissionFlag) { + result.put("allow_access", Boolean.TRUE); + } else { + result.put("allow_access", Boolean.FALSE); + } + return ResultUtil.success(HttpStatus.OK, result); + } catch (Exception e) { + LOGGER.error("Authentication exception"); + return ResultUtil.fail(HttpStatus.UNAUTHORIZED, MessageCode.EC00020); + } + } +} diff --git a/src/main/java/com/easysoftware/adapter/query/CoMaintainerAdapter.java b/src/main/java/com/easysoftware/adapter/query/CoMaintainerAdapter.java new file mode 100644 index 0000000..160a001 --- /dev/null +++ b/src/main/java/com/easysoftware/adapter/query/CoMaintainerAdapter.java @@ -0,0 +1,74 @@ +package com.easysoftware.adapter.query; + +import java.util.HashMap; +import java.util.HashSet; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import com.easysoftware.common.account.UserPermission; +import com.easysoftware.common.annotation.CoMaintainerPermission; +import com.easysoftware.common.aop.RequestLimitRedis; +import com.easysoftware.common.entity.MessageCode; +import com.easysoftware.common.utils.ResultUtil; + +@RestController +@RequestMapping("/collaboration/maintainer") +public class CoMaintainerAdapter { + + /** + * Logger for CoMaintainerAdapter. + */ + private static final Logger LOGGER = LoggerFactory.getLogger(CoMaintainerAdapter.class); + + /** + * Autowired UserPermission for check user permission. + */ + @Autowired + private UserPermission userPermission; + + /** + * Endpoint to search for repos based on the provided search + * condition. + * + * @param repo repo name. + * @return ResponseEntity. + */ + @GetMapping() + @RequestLimitRedis() + @CoMaintainerPermission() + public ResponseEntity queryRepos(@RequestParam(value = "repo") String repo) { + return ResultUtil.success(HttpStatus.OK, "success"); + } + + /** + * Check if the user has permission to access. + * + * @return ResponseEntity. + */ + @GetMapping("/permission") + @RequestLimitRedis() + public ResponseEntity checkPermission() { + HashMap result = new HashMap<>(); + try { + HashSet permissionRepos = userPermission.getUserRepoList(); + + if (permissionRepos.size() > 0) { + result.put("allow_access", Boolean.TRUE); + } else { + result.put("allow_access", Boolean.FALSE); + } + return ResultUtil.success(HttpStatus.OK, result); + } catch (Exception e) { + LOGGER.error("Authentication exception"); + return ResultUtil.fail(HttpStatus.UNAUTHORIZED, MessageCode.EC00020); + } + } +} diff --git a/src/main/java/com/easysoftware/common/account/UerPermissionDef.java b/src/main/java/com/easysoftware/common/account/UerPermissionDef.java index db81a11..a0d3aec 100644 --- a/src/main/java/com/easysoftware/common/account/UerPermissionDef.java +++ b/src/main/java/com/easysoftware/common/account/UerPermissionDef.java @@ -6,6 +6,11 @@ public final class UerPermissionDef { */ public static final String USER_PERMISSION_READ = "easysoftwareread"; + /** + * user permission - easysoftwareadmin. + */ + public static final String COLLABORATION_PERMISSION_ADMIN = "easysoftwareadmin"; + private UerPermissionDef() { throw new RuntimeException("Not supported for instantiation"); } diff --git a/src/main/java/com/easysoftware/common/account/UserPermission.java b/src/main/java/com/easysoftware/common/account/UserPermission.java index 051f025..d72ca7e 100644 --- a/src/main/java/com/easysoftware/common/account/UserPermission.java +++ b/src/main/java/com/easysoftware/common/account/UserPermission.java @@ -46,6 +46,18 @@ public class UserPermission { @Value("${oneid.permissionApi}") private String permissionApi; + /** + * Value injected for the user info API. + */ + @Value("${oneid.userInfoApi}") + private String userInfoApi; + + /** + * Value injected for the user info API. + */ + @Value("${oneid.userReposApi}") + private String userReposApi; + /** * Value injected for the cookie token name. */ @@ -73,6 +85,76 @@ public class UserPermission { return Arrays.stream(requirePermissions).anyMatch(permissionSet::contains); } + /** + * Check if user has repo permission. + * @param repo repo required user permission. + * @return Permission matching results. + */ + public boolean checkUserRepoPermission(String repo) { + HashSet repoSet = this.getUserRepoList(); + if (Objects.isNull(repoSet) || repoSet.isEmpty()) { + return false; + } + + /* Check if user has repo permission */ + return repoSet.contains(repo); + } + + /** + * Get user login name by user token and manage token. + * @return login name. + */ + public String getUserLogin() { + String userToken = getUserToken(); + String manageToken = getManageToken(); + + // 使用userToke、manageToken查询用户信息 + Cookie cookie = getCookie(cookieTokenName); + String response = HttpClientUtil.getHttpClient(userInfoApi, manageToken, userToken, cookie.getValue()); + JsonNode resJson = ObjectMapperUtil.toJsonNode(response); + + String resCode = resJson.get("code").asText(); + if (!"200".equals(resCode)) { + LOGGER.error("query user login name failed"); + throw new HttpRequestException("query user login name failed"); + } + String loginName = null; + JsonNode identities = resJson.get("data").get("identities"); + for (JsonNode identity : identities) { + if (identity.has("identity") && identity.get("identity").asText().equalsIgnoreCase("gitee")) { + loginName = identity.get("login_name").asText(); + } + } + return loginName; + } + + /** + * Get user repos. + * @return Collection of repos. + */ + public HashSet getUserRepoList() { + String login = getUserLogin(); + if (login == null) { + throw new HttpRequestException("user login name is null"); + } + String response = HttpClientUtil.getHttpClient(String.format(userReposApi, login), null, null, null); + JsonNode resJson = ObjectMapperUtil.toJsonNode(response); + + String resCode = resJson.get("code").asText(); + + if (!"200".equals(resCode)) { + LOGGER.error("query user repos failed"); + throw new HttpRequestException("query user repos failed"); + } + HashSet repoSet = new HashSet<>(); + JsonNode repos = resJson.get("data"); + for (JsonNode repo : repos) { + repoSet.add(repo.asText()); + } + + return repoSet; + } + /** * Get user permission by user token and manage token. * @return Collection of user permissions. diff --git a/src/main/java/com/easysoftware/common/annotation/CoMaintainerPermission.java b/src/main/java/com/easysoftware/common/annotation/CoMaintainerPermission.java new file mode 100644 index 0000000..f2325f4 --- /dev/null +++ b/src/main/java/com/easysoftware/common/annotation/CoMaintainerPermission.java @@ -0,0 +1,22 @@ +package com.easysoftware.common.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.annotation.Retention; +import java.lang.annotation.Inherited; +import java.lang.annotation.Documented; + +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Inherited +@Documented +public @interface CoMaintainerPermission { + + /** + * Specifies the number of allowed requests (default value: 5). + * + * @return Default to empty. + */ + String[] value() default {}; +} diff --git a/src/main/java/com/easysoftware/common/aop/CoMaintainerAspect.java b/src/main/java/com/easysoftware/common/aop/CoMaintainerAspect.java new file mode 100644 index 0000000..24bd899 --- /dev/null +++ b/src/main/java/com/easysoftware/common/aop/CoMaintainerAspect.java @@ -0,0 +1,64 @@ +package com.easysoftware.common.aop; + +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Component; + +import com.easysoftware.common.account.UserPermission; +import com.easysoftware.common.entity.MessageCode; +import com.easysoftware.common.utils.ResultUtil; + +import jakarta.servlet.http.HttpServletRequest; + +@Aspect +@Component +public class CoMaintainerAspect { + /** + * Logger for CoMaintainerAspect. + */ + private static final Logger LOGGER = LoggerFactory.getLogger(CoMaintainerAspect.class); + + /** + * Autowired UserPermission for get user permission. + */ + @Autowired + private UserPermission userPermission; + + /** + * Autowired HttpServletRequest for handling HTTP request information. + */ + @Autowired + private HttpServletRequest request; + + /** + * Advice method called before a method with CoMaintainerPermission, and authentication. + * @param joinPoint The JoinPoint representing the intercepted method. + * @throws Throwable if an error occurs during method execution, or authentication fail. + * @return Business processing results. + */ + @Around("@annotation(com.easysoftware.common.annotation.CoMaintainerPermission)") + public Object around(final ProceedingJoinPoint joinPoint) throws Throwable { + try { + String repo = request.getParameter("repo"); + + /* Check if the user has repo permission */ + boolean permissionFlag = userPermission.checkUserRepoPermission(repo); + + if (!permissionFlag) { + LOGGER.error("Insufficient permissions"); + return ResultUtil.fail(HttpStatus.FORBIDDEN, MessageCode.EC00019); + } + } catch (Exception e) { + LOGGER.error("Authentication exception"); + return ResultUtil.fail(HttpStatus.UNAUTHORIZED, MessageCode.EC00020); + } + + /* 业务处理 */ + return joinPoint.proceed(); + } +} -- Gitee From 634e9c2b199ae086dcff9db58790626eecc42b66 Mon Sep 17 00:00:00 2001 From: kaede10 Date: Mon, 12 Aug 2024 14:44:31 +0800 Subject: [PATCH 2/3] add copy right --- .../easysoftware/adapter/query/CoAdminAdapter.java | 13 ++++++++++++- .../adapter/query/CoMaintainerAdapter.java | 13 ++++++++++++- .../easysoftware/common/account/UserPermission.java | 4 ++-- .../common/annotation/CoMaintainerPermission.java | 11 +++++++++++ .../easysoftware/common/aop/CoMaintainerAspect.java | 11 +++++++++++ 5 files changed, 48 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/easysoftware/adapter/query/CoAdminAdapter.java b/src/main/java/com/easysoftware/adapter/query/CoAdminAdapter.java index bb9488c..2b7aca5 100644 --- a/src/main/java/com/easysoftware/adapter/query/CoAdminAdapter.java +++ b/src/main/java/com/easysoftware/adapter/query/CoAdminAdapter.java @@ -1,3 +1,14 @@ +/* Copyright (c) 2024 openEuler Community + EasySoftware is licensed under the Mulan PSL v2. + You can use this software according to the terms and conditions of the Mulan PSL v2. + You may obtain a copy of Mulan PSL v2 at: + http://license.coscl.org.cn/MulanPSL2 + THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + See the Mulan PSL v2 for more details. +*/ + package com.easysoftware.adapter.query; import java.util.HashMap; @@ -71,7 +82,7 @@ public class CoAdminAdapter { } return ResultUtil.success(HttpStatus.OK, result); } catch (Exception e) { - LOGGER.error("Authentication exception"); + LOGGER.error("Authentication exception - {}", e.getMessage()); return ResultUtil.fail(HttpStatus.UNAUTHORIZED, MessageCode.EC00020); } } diff --git a/src/main/java/com/easysoftware/adapter/query/CoMaintainerAdapter.java b/src/main/java/com/easysoftware/adapter/query/CoMaintainerAdapter.java index 160a001..0e5287f 100644 --- a/src/main/java/com/easysoftware/adapter/query/CoMaintainerAdapter.java +++ b/src/main/java/com/easysoftware/adapter/query/CoMaintainerAdapter.java @@ -1,3 +1,14 @@ +/* Copyright (c) 2024 openEuler Community + EasySoftware is licensed under the Mulan PSL v2. + You can use this software according to the terms and conditions of the Mulan PSL v2. + You may obtain a copy of Mulan PSL v2 at: + http://license.coscl.org.cn/MulanPSL2 + THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + See the Mulan PSL v2 for more details. +*/ + package com.easysoftware.adapter.query; import java.util.HashMap; @@ -67,7 +78,7 @@ public class CoMaintainerAdapter { } return ResultUtil.success(HttpStatus.OK, result); } catch (Exception e) { - LOGGER.error("Authentication exception"); + LOGGER.error("Authentication exception - {}", e.getMessage()); return ResultUtil.fail(HttpStatus.UNAUTHORIZED, MessageCode.EC00020); } } diff --git a/src/main/java/com/easysoftware/common/account/UserPermission.java b/src/main/java/com/easysoftware/common/account/UserPermission.java index d72ca7e..ae0330e 100644 --- a/src/main/java/com/easysoftware/common/account/UserPermission.java +++ b/src/main/java/com/easysoftware/common/account/UserPermission.java @@ -53,7 +53,7 @@ public class UserPermission { private String userInfoApi; /** - * Value injected for the user info API. + * Value injected for the user repos API. */ @Value("${oneid.userReposApi}") private String userReposApi; @@ -108,7 +108,7 @@ public class UserPermission { String userToken = getUserToken(); String manageToken = getManageToken(); - // 使用userToke、manageToken查询用户信息 + // 使用userToken、manageToken查询用户信息 Cookie cookie = getCookie(cookieTokenName); String response = HttpClientUtil.getHttpClient(userInfoApi, manageToken, userToken, cookie.getValue()); JsonNode resJson = ObjectMapperUtil.toJsonNode(response); diff --git a/src/main/java/com/easysoftware/common/annotation/CoMaintainerPermission.java b/src/main/java/com/easysoftware/common/annotation/CoMaintainerPermission.java index f2325f4..51b0c62 100644 --- a/src/main/java/com/easysoftware/common/annotation/CoMaintainerPermission.java +++ b/src/main/java/com/easysoftware/common/annotation/CoMaintainerPermission.java @@ -1,3 +1,14 @@ +/* Copyright (c) 2024 openEuler Community + EasySoftware is licensed under the Mulan PSL v2. + You can use this software according to the terms and conditions of the Mulan PSL v2. + You may obtain a copy of Mulan PSL v2 at: + http://license.coscl.org.cn/MulanPSL2 + THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + See the Mulan PSL v2 for more details. +*/ + package com.easysoftware.common.annotation; import java.lang.annotation.ElementType; diff --git a/src/main/java/com/easysoftware/common/aop/CoMaintainerAspect.java b/src/main/java/com/easysoftware/common/aop/CoMaintainerAspect.java index 24bd899..58aa561 100644 --- a/src/main/java/com/easysoftware/common/aop/CoMaintainerAspect.java +++ b/src/main/java/com/easysoftware/common/aop/CoMaintainerAspect.java @@ -1,3 +1,14 @@ +/* Copyright (c) 2024 openEuler Community + EasySoftware is licensed under the Mulan PSL v2. + You can use this software according to the terms and conditions of the Mulan PSL v2. + You may obtain a copy of Mulan PSL v2 at: + http://license.coscl.org.cn/MulanPSL2 + THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + See the Mulan PSL v2 for more details. +*/ + package com.easysoftware.common.aop; import org.aspectj.lang.ProceedingJoinPoint; -- Gitee From 48da61e3977de8c66b0e2d36b70434f9ee773efb Mon Sep 17 00:00:00 2001 From: kaede10 Date: Mon, 12 Aug 2024 14:50:04 +0800 Subject: [PATCH 3/3] log error message --- .../java/com/easysoftware/common/aop/CoMaintainerAspect.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/easysoftware/common/aop/CoMaintainerAspect.java b/src/main/java/com/easysoftware/common/aop/CoMaintainerAspect.java index 58aa561..e12d7c2 100644 --- a/src/main/java/com/easysoftware/common/aop/CoMaintainerAspect.java +++ b/src/main/java/com/easysoftware/common/aop/CoMaintainerAspect.java @@ -65,7 +65,7 @@ public class CoMaintainerAspect { return ResultUtil.fail(HttpStatus.FORBIDDEN, MessageCode.EC00019); } } catch (Exception e) { - LOGGER.error("Authentication exception"); + LOGGER.error("Authentication exception - {}", e.getMessage()); return ResultUtil.fail(HttpStatus.UNAUTHORIZED, MessageCode.EC00020); } -- Gitee