Skip to content

Commit 10ab5b6

Browse files
Tsukilcimbajin
authored andcommitted
feat(server): change time fomat to yyyy-MM-dd HH:mm:ss.SSS
1 parent 389b753 commit 10ab5b6

56 files changed

Lines changed: 4540 additions & 608 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/rest/RestResult.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,15 @@
1818
package org.apache.hugegraph.rest;
1919

2020
import java.io.IOException;
21+
import java.text.SimpleDateFormat;
2122
import java.util.ArrayList;
2223
import java.util.List;
2324

2425
import com.fasterxml.jackson.databind.JavaType;
2526
import com.fasterxml.jackson.databind.JsonNode;
2627
import com.fasterxml.jackson.databind.Module;
2728
import com.fasterxml.jackson.databind.ObjectMapper;
29+
import com.fasterxml.jackson.databind.SerializationFeature;
2830

2931
import lombok.SneakyThrows;
3032
import okhttp3.Response;
@@ -33,6 +35,11 @@ public class RestResult {
3335

3436
private static final ObjectMapper MAPPER = new ObjectMapper();
3537

38+
static {
39+
MAPPER.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
40+
MAPPER.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"));
41+
}
42+
3643
private final int status;
3744
private final RestHeaders headers;
3845
private final String content;

hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/DateUtil.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import java.util.concurrent.ConcurrentHashMap;
2323

2424
import org.apache.hugegraph.date.SafeDateFormat;
25+
2526
import com.google.common.collect.ImmutableMap;
2627

2728
public final class DateUtil {
@@ -46,7 +47,7 @@ public static Date parse(String value) {
4647
}
4748
}
4849
throw new IllegalArgumentException(String.format(
49-
"Expected date format is: %s, but got '%s'", VALID_DFS.values(), value));
50+
"Expected date format is: %s, but got '%s'", VALID_DFS.values(), value));
5051
}
5152

5253
public static Date parse(String value, String df) {

hugegraph-commons/hugegraph-common/src/main/java/org/apache/hugegraph/util/JsonUtilCommon.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,15 @@
1818
package org.apache.hugegraph.util;
1919

2020
import java.io.IOException;
21+
import java.text.SimpleDateFormat;
2122

2223
import org.apache.hugegraph.rest.SerializeException;
2324

2425
import com.fasterxml.jackson.core.JsonProcessingException;
2526
import com.fasterxml.jackson.databind.JsonNode;
2627
import com.fasterxml.jackson.databind.Module;
2728
import com.fasterxml.jackson.databind.ObjectMapper;
29+
import com.fasterxml.jackson.databind.SerializationFeature;
2830

2931
/**
3032
* Utility class for JSON operations.
@@ -36,6 +38,11 @@ public final class JsonUtilCommon {
3638
*/
3739
private static final ObjectMapper MAPPER = new ObjectMapper();
3840

41+
static {
42+
MAPPER.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
43+
MAPPER.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"));
44+
}
45+
3946
/**
4047
* Registers a module with the ObjectMapper.
4148
*

hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/API.java

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -241,33 +241,29 @@ public static boolean checkAndParseAction(String action) {
241241
}
242242
}
243243

244-
//todo: auth
245-
//public static boolean hasAdminPerm(GraphManager manager, String user) {
246-
// return manager.authManager().isAdminManager(user);
247-
//}
248-
//
249-
//public static boolean hasSpaceManagerPerm(GraphManager manager,
250-
// String graphSpace,
251-
// String user) {
252-
// return manager.authManager().isSpaceManager(graphSpace, user);
253-
//}
254-
255-
//public static boolean hasAnySpaceManagerPerm(GraphManager manager,
256-
// String user) {
257-
// return manager.authManager().isSpaceManager(user);
258-
//}
259-
//
260-
//public static boolean hasAdminOrSpaceManagerPerm(GraphManager manager,
261-
// String graphSpace,
262-
// String user) {
263-
// return hasAdminPerm(manager, user) ||
264-
// hasSpaceManagerPerm(manager, graphSpace, user);
265-
//}
244+
public static boolean hasAdminPerm(GraphManager manager, String user) {
245+
return manager.authManager().isAdminManager(user);
246+
}
247+
248+
public static boolean hasSpaceManagerPerm(GraphManager manager,
249+
String graphSpace,
250+
String user) {
251+
return manager.authManager().isSpaceManager(graphSpace, user);
252+
}
253+
254+
public static boolean hasAdminOrSpaceManagerPerm(GraphManager manager,
255+
String graphSpace,
256+
String user) {
257+
return hasAdminPerm(manager, user) ||
258+
hasSpaceManagerPerm(manager, graphSpace, user);
259+
}
266260

267261
public static void validPermission(boolean hasPermission, String user,
268262
String action) {
269-
E.checkArgument(hasPermission, "The user [%s] has no permission to [%s].",
270-
user, action);
263+
if (!hasPermission) {
264+
throw new jakarta.ws.rs.ForbiddenException(
265+
String.format("The user [%s] has no permission to [%s].", user, action));
266+
}
271267
}
272268

273269
public static class ApiMeasurer {

hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/filter/AuthenticationFilter.java

Lines changed: 109 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,8 @@
3030
import javax.xml.bind.DatatypeConverter;
3131

3232
import org.apache.hugegraph.auth.HugeAuthenticator;
33-
import org.apache.hugegraph.auth.HugeAuthenticator.RequiredPerm;
34-
import org.apache.hugegraph.auth.HugeAuthenticator.RolePerm;
3533
import org.apache.hugegraph.auth.HugeAuthenticator.User;
34+
import org.apache.hugegraph.auth.HugeGraphAuthProxy;
3635
import org.apache.hugegraph.auth.RolePermission;
3736
import org.apache.hugegraph.config.HugeConfig;
3837
import org.apache.hugegraph.core.GraphManager;
@@ -54,6 +53,8 @@
5453
import jakarta.ws.rs.Priorities;
5554
import jakarta.ws.rs.container.ContainerRequestContext;
5655
import jakarta.ws.rs.container.ContainerRequestFilter;
56+
import jakarta.ws.rs.container.ContainerResponseContext;
57+
import jakarta.ws.rs.container.ContainerResponseFilter;
5758
import jakarta.ws.rs.container.PreMatching;
5859
import jakarta.ws.rs.core.Context;
5960
import jakarta.ws.rs.core.HttpHeaders;
@@ -64,11 +65,13 @@
6465
@Provider
6566
@PreMatching
6667
@Priority(Priorities.AUTHENTICATION)
67-
public class AuthenticationFilter implements ContainerRequestFilter {
68+
public class AuthenticationFilter implements ContainerRequestFilter, ContainerResponseFilter {
6869

6970
public static final String BASIC_AUTH_PREFIX = "Basic ";
7071
public static final String BEARER_TOKEN_PREFIX = "Bearer ";
7172

73+
public static final String ALL_GRAPH_SPACES = "*";
74+
7275
private static final Logger LOG = Log.logger(AuthenticationFilter.class);
7376

7477
private static final AntPathMatcher MATCHER = new AntPathMatcher();
@@ -97,11 +100,38 @@ public void filter(ContainerRequestContext context) throws IOException {
97100
if (isWhiteAPI(context)) {
98101
return;
99102
}
103+
GraphManager manager = this.managerProvider.get();
100104
User user = this.authenticate(context);
101-
Authorizer authorizer = new Authorizer(user, context.getUriInfo());
105+
106+
// Inject request graph space into AuthContext for permission check
107+
// Extract graphspace from path like: /graphspaces/{graphspace}/...
108+
String path = context.getUriInfo().getPath();
109+
LOG.debug("AuthenticationFilter: path={}", path);
110+
if (path != null && path.contains("graphspaces/")) {
111+
String[] parts = path.split("/");
112+
for (int i = 0; i < parts.length - 1; i++) {
113+
if ("graphspaces".equals(parts[i]) && i + 1 < parts.length) {
114+
String requestGraphSpace = parts[i + 1];
115+
HugeGraphAuthProxy.setRequestGraphSpace(requestGraphSpace);
116+
LOG.debug("AuthenticationFilter: set RequestGraphSpace={}", requestGraphSpace);
117+
break;
118+
}
119+
}
120+
}
121+
122+
Authorizer authorizer = new Authorizer(manager, user, context.getUriInfo());
102123
context.setSecurityContext(authorizer);
103124
}
104125

126+
@Override
127+
public void filter(ContainerRequestContext requestContext,
128+
ContainerResponseContext responseContext) throws IOException {
129+
// Clean up ThreadLocal variables after request is processed
130+
// This prevents memory leaks in thread pool
131+
HugeGraphAuthProxy.resetSpaceContext();
132+
LOG.debug("HugeGraphAuthProxy ThreadLocal cleaned up after request");
133+
}
134+
105135
protected User authenticate(ContainerRequestContext context) {
106136
GraphManager manager = this.managerProvider.get();
107137
E.checkState(manager != null, "Context GraphManager is absent");
@@ -188,10 +218,12 @@ public static class Authorizer implements SecurityContext {
188218
private final UriInfo uri;
189219
private final User user;
190220
private final Principal principal;
221+
private final GraphManager manager;
191222

192-
public Authorizer(final User user, final UriInfo uri) {
223+
public Authorizer(GraphManager manager, final User user, final UriInfo uri) {
193224
E.checkNotNull(user, "user");
194225
E.checkNotNull(uri, "uri");
226+
this.manager = manager;
195227
this.uri = uri;
196228
this.user = user;
197229
this.principal = new UserPrincipal();
@@ -232,19 +264,56 @@ public String getAuthenticationScheme() {
232264

233265
private boolean matchPermission(String required) {
234266
boolean valid;
235-
RequiredPerm requiredPerm;
267+
HugeAuthenticator.RequiredPerm requiredPerm;
268+
269+
/*
270+
* if request url contains graph space and the corresponding space
271+
* does not enable permission check, return true
272+
* */
273+
if (!isAuth()) {
274+
return true;
275+
}
236276

237-
if (!required.startsWith(HugeAuthenticator.KEY_OWNER)) {
238-
// Permission format like: "admin"
239-
requiredPerm = new RequiredPerm();
277+
if (!required.startsWith(HugeAuthenticator.KEY_GRAPHSPACE)) {
278+
// Permission format like: "admin", "space", "analyst", "space_member"
279+
requiredPerm = new HugeAuthenticator.RequiredPerm();
240280
requiredPerm.owner(required);
281+
282+
// For space-level roles, set graphSpace from path parameter
283+
if ("space".equals(required) || "space_member".equals(required)) {
284+
// If graphspace parameter is not in path, use DEFAULT
285+
List<String> graphSpaceParams = this.uri.getPathParameters().get("graphspace");
286+
String graphSpace = "DEFAULT";
287+
if (graphSpaceParams != null && !graphSpaceParams.isEmpty()) {
288+
graphSpace = graphSpaceParams.get(0);
289+
}
290+
requiredPerm.graphSpace(graphSpace);
291+
}
292+
293+
// Role inheritance is handled in HugeAuthenticator.matchSpace()
294+
valid = HugeAuthenticator.RolePerm.matchApiRequiredPerm(this.role(), requiredPerm);
241295
} else {
242-
// The required like: $owner=graph1 $action=vertex_write
243-
requiredPerm = RequiredPerm.fromPermission(required);
296+
// The required like:
297+
// $graphspace=graphspace $owner=graph1 $action=vertex_write
298+
requiredPerm = HugeAuthenticator.RequiredPerm.fromPermission(required);
299+
300+
/*
301+
* Replace graphspace value (it may be a variable) if the
302+
* permission format like:
303+
* "$graphspace=$graphspace $owner=$graph $action=vertex_write"
304+
*/
305+
String graphSpace = requiredPerm.graphSpace();
306+
if (graphSpace.startsWith(HugeAuthenticator.VAR_PREFIX)) {
307+
int prefixLen = HugeAuthenticator.VAR_PREFIX.length();
308+
assert graphSpace.length() > prefixLen;
309+
graphSpace = graphSpace.substring(prefixLen);
310+
graphSpace = this.getPathParameter(graphSpace);
311+
requiredPerm.graphSpace(graphSpace);
312+
}
244313

245314
/*
246-
* Replace owner value (it may be a variable) if the permission
247-
* format like: "$owner=$graph $action=vertex_write"
315+
* Replace owner value(it may be a variable) if the permission
316+
* format like: "$graphspace=$graphspace $owner=$graph $action=vertex_write"
248317
*/
249318
String owner = requiredPerm.owner();
250319
if (owner.startsWith(HugeAuthenticator.VAR_PREFIX)) {
@@ -255,32 +324,47 @@ private boolean matchPermission(String required) {
255324
owner = this.getPathParameter(owner);
256325
requiredPerm.owner(owner);
257326
}
327+
valid = HugeAuthenticator.RolePerm.matchApiRequiredPerm(this.role(), requiredPerm);
258328
}
259329

260-
if (LOG.isDebugEnabled()) {
261-
LOG.debug("Verify permission {} {} for user '{}' with role {}",
262-
requiredPerm.action().string(), requiredPerm.resourceObject(),
263-
this.user.username(), this.user.role());
264-
}
265-
266-
// verify role permission
267-
valid = RolePerm.match(this.role(), requiredPerm);
268-
269-
if (!valid && LOG.isInfoEnabled() &&
330+
if (!valid &&
270331
!required.equals(HugeAuthenticator.USER_ADMIN)) {
271-
LOG.info("User '{}' is denied to {} {}", this.user.username(),
272-
requiredPerm.action().string(), requiredPerm.resourceObject());
332+
LOG.info(
333+
user.userId().asString(),
334+
requiredPerm.action().string(),
335+
requiredPerm.resourceObject());
273336
}
274337
return valid;
275338
}
276339

277340
private String getPathParameter(String key) {
278341
List<String> params = this.uri.getPathParameters().get(key);
342+
// For graphspace parameter, use "DEFAULT" if not present in path
343+
if ("graphspace".equals(key) && (params == null || params.isEmpty())) {
344+
return "DEFAULT";
345+
}
279346
E.checkState(params != null && params.size() == 1,
280347
"There is no matched path parameter: '%s'", key);
281348
return params.get(0);
282349
}
283350

351+
private boolean isAuth() {
352+
List<String> params = this.uri.getPathParameters().get(
353+
"graphspace");
354+
if (params != null && params.size() == 1) {
355+
String graphSpace = params.get(0);
356+
if (ALL_GRAPH_SPACES.equals(graphSpace)) {
357+
return true;
358+
}
359+
E.checkArgumentNotNull(this.manager.graphSpace(graphSpace),
360+
"The graph space '%s' does not exist",
361+
graphSpace);
362+
return this.manager.graphSpace(graphSpace).auth();
363+
} else {
364+
return true;
365+
}
366+
}
367+
284368
private final class UserPrincipal implements Principal {
285369

286370
@Override

hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/filter/ExceptionFilter.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ public static class TracedExceptionAPI extends API {
8989
@GET
9090
@Timed
9191
@Produces(APPLICATION_JSON_WITH_CHARSET)
92-
@RolesAllowed({"admin"})
92+
@RolesAllowed({"space_member"})
9393
public Object get() {
9494
return ImmutableMap.of("trace", TracedExceptionMapper.forcedTrace);
9595
}
@@ -98,7 +98,7 @@ public Object get() {
9898
@Timed
9999
@Consumes(APPLICATION_JSON)
100100
@Produces(APPLICATION_JSON_WITH_CHARSET)
101-
@RolesAllowed({"admin"})
101+
@RolesAllowed({"space_member"})
102102
public Object trace(boolean trace) {
103103
TracedExceptionMapper.forcedTrace = trace;
104104
return ImmutableMap.of("trace", TracedExceptionMapper.forcedTrace);

0 commit comments

Comments
 (0)