imbajin commented on code in PR #3008:
URL: https://github.com/apache/hugegraph/pull/3008#discussion_r3142354938


##########
hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/profile/GraphsAPI.java:
##########
@@ -120,6 +126,86 @@ public Object list(@Context GraphManager manager,
         return ImmutableMap.of("graphs", filterGraphs);
     }
 
+    @GET
+    @Timed
+    @Path("profile")
+    @Produces(APPLICATION_JSON_WITH_CHARSET)
+    @RolesAllowed({"space_member", "$dynamic"})
+    public Object listProfile(@Context GraphManager manager,
+                              @Parameter(description = "The graph space name")
+                              @PathParam("graphspace") String graphSpace,
+                              @Parameter(description = "Filter graphs by name 
or nickname prefix")
+                              @QueryParam("prefix") String prefix,
+                              @Context SecurityContext sc) {
+        LOG.debug("List graph profiles in graph space {}", graphSpace);
+        if (null == manager.graphSpace(graphSpace)) {
+            throw new HugeException("Graphspace not exist!");
+        }
+        GraphSpace gs = manager.graphSpace(graphSpace);
+        String gsNickname = gs.nickname();
+
+        AuthManager authManager = manager.authManager();
+        String user = HugeGraphAuthProxy.username();
+        Map<String, Date> defaultGraphs = 
authManager.getDefaultGraph(graphSpace, user);
+
+        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        Set<String> graphs = manager.graphs(graphSpace);
+        List<Map<String, Object>> profiles = new ArrayList<>();
+        List<Map<String, Object>> defaultProfiles = new ArrayList<>();
+        for (String graph : graphs) {
+            String role = RequiredPerm.roleFor(graphSpace, graph,
+                                               HugePermission.READ);
+            if (!sc.isUserInRole(role)) {
+                continue;
+            }
+            try {
+                HugeGraph hg = graph(manager, graphSpace, graph);
+                HugeConfig config = (HugeConfig) hg.configuration();
+                String configResp = ConfigUtil.writeConfigToString(config);
+                Map<String, Object> profile =
+                        JsonUtil.fromJson(configResp, Map.class);
+                profile.put("name", graph);
+                profile.put("nickname", hg.nickname());
+                if (!isPrefix(profile, prefix)) {
+                    continue;
+                }
+                profile.put("graphspace_nickname", gsNickname);
+                
+                boolean isDefault = defaultGraphs.containsKey(graph);
+                profile.put("default", isDefault);
+                if (isDefault) {
+                    profile.put("default_update_time", 
defaultGraphs.get(graph));
+                }
+                
+                Date createTime = hg.createTime();
+                if (createTime != null) {
+                    profile.put("create_time", format.format(createTime));
+                }
+                
+                if (isDefault) {
+                    defaultProfiles.add(profile);
+                } else {
+                    profiles.add(profile);
+                }
+            } catch (ForbiddenException ignored) {
+                // ignore graphs the current user has no access to
+            }
+        }
+        defaultProfiles.addAll(profiles);
+        return defaultProfiles;
+    }
+
+    private static boolean isPrefix(Map<String, Object> profile, String 
prefix) {

Review Comment:
   ⚠️ **重复代码: `isPrefix` 在 GraphsAPI 和 GraphSpaceAPI 中有两份相同实现**
   
   `GraphSpaceAPI` 中也定义了同样签名和逻辑的 `isPrefix` 方法。建议提取到公共基类 `API` 
或工具类中,避免后续维护中两处不一致。
   



##########
hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/profile/GraphsAPI.java:
##########
@@ -155,6 +296,60 @@ public void drop(@Context GraphManager manager,
         manager.dropGraph(graphSpace, name, true);
     }
 
+    @PUT
+    @Timed
+    @Path("{name}")
+    @Consumes(APPLICATION_JSON)
+    @Produces(APPLICATION_JSON_WITH_CHARSET)
+    @RolesAllowed({"space"})
+    public Map<String, String> manage(@Context GraphManager manager,
+                                      @Parameter(description = "The graph 
space name")
+                                      @PathParam("graphspace") String 
graphSpace,
+                                      @Parameter(description = "The graph 
name")
+                                      @PathParam("name") String name,
+                                      @Parameter(description = "Action map: 
{'action':'update','update':{...}}")
+                                      Map<String, Object> actionMap) {
+        LOG.debug("Manage graph '{}' with action '{}'", name, actionMap);
+        E.checkArgument(actionMap != null && actionMap.size() == 2 &&

Review Comment:
   ⚠️ **校验过严: `actionMap.size() == 2` 会在前端多传字段时直接 400**
   
   要求请求体恰好包含 2 个 key。如果前端在 JSON 中额外带了字段(很常见的兼容场景),请求会被拒绝。建议放宽为只校验必需字段:
   
   ```suggestion
           E.checkArgument(actionMap != null &&
                           actionMap.containsKey(GRAPH_ACTION),
                           "Invalid request body '%s'", actionMap);
   ```
   



##########
hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/StandardAuthManager.java:
##########
@@ -813,6 +814,179 @@ public HugeGroup findGroup(String name) {
         return null;
     }
 
+    private static final String DEFAULT_GRAPH_MARKER = "~default_graph";

Review Comment:
   ⚠️ **建议加注释说明 marker group 设计的上下文**
   
   使用 `~default_graph:` 和 `~default_role:` 前缀的特殊 group 来模拟默认图/角色关系是一种基于现有机制的 
workaround。当前方案可工作,但有以下已知限制:
   - 这些 marker group 会出现在 `listGroups` 结果中
   - Belong ID 拼接格式(`userId + "->ug->" + groupId`)依赖内部约定
   
   建议在此处加几行注释说明设计背景和已知限制,方便后续维护者理解。未来可考虑引入独立的 default graph/role 存储机制来替代。



##########
hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/profile/GraphsAPI.java:
##########
@@ -120,6 +126,86 @@ public Object list(@Context GraphManager manager,
         return ImmutableMap.of("graphs", filterGraphs);
     }
 
+    @GET
+    @Timed
+    @Path("profile")
+    @Produces(APPLICATION_JSON_WITH_CHARSET)
+    @RolesAllowed({"space_member", "$dynamic"})
+    public Object listProfile(@Context GraphManager manager,
+                              @Parameter(description = "The graph space name")
+                              @PathParam("graphspace") String graphSpace,
+                              @Parameter(description = "Filter graphs by name 
or nickname prefix")
+                              @QueryParam("prefix") String prefix,
+                              @Context SecurityContext sc) {
+        LOG.debug("List graph profiles in graph space {}", graphSpace);
+        if (null == manager.graphSpace(graphSpace)) {
+            throw new HugeException("Graphspace not exist!");
+        }
+        GraphSpace gs = manager.graphSpace(graphSpace);
+        String gsNickname = gs.nickname();
+
+        AuthManager authManager = manager.authManager();
+        String user = HugeGraphAuthProxy.username();
+        Map<String, Date> defaultGraphs = 
authManager.getDefaultGraph(graphSpace, user);
+
+        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

Review Comment:
   ⚠️ **建议使用 `DateTimeFormatter` 替代 `SimpleDateFormat`**
   
   `SimpleDateFormat` 虽然这里是局部变量(线程安全),但 `DateTimeFormatter` 是 Java 8+ 
推荐的替代方案,线程安全且可复用为 static final 常量,性能更好:
   
   ```java
   private static final DateTimeFormatter DATE_FORMAT =
           DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to