This is an automated email from the ASF dual-hosted git repository.
vgalaxies pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-hugegraph.git
The following commit(s) were added to refs/heads/master by this push:
new 8c1ee710d feat(server): LoginAPI support token_expire field (#2754)
8c1ee710d is described below
commit 8c1ee710d6f7fae26cade37dcf4968b422b108d6
Author: John <[email protected]>
AuthorDate: Mon May 5 11:49:12 2025 +0800
feat(server): LoginAPI support token_expire field (#2754)
Co-authored-by: imbajin <[email protected]>
---
.../org/apache/hugegraph/api/auth/LoginAPI.java | 5 +-
.../apache/hugegraph/auth/HugeGraphAuthProxy.java | 193 +++++++++++----------
.../org/apache/hugegraph/auth/AuthManager.java | 2 +
.../apache/hugegraph/auth/StandardAuthManager.java | 21 ++-
.../java/org/apache/hugegraph/core/AuthTest.java | 138 +++++++--------
5 files changed, 188 insertions(+), 171 deletions(-)
diff --git
a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/auth/LoginAPI.java
b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/auth/LoginAPI.java
index 50bf1a78d..5e1bdb636 100644
---
a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/auth/LoginAPI.java
+++
b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/api/auth/LoginAPI.java
@@ -70,7 +70,8 @@ public class LoginAPI extends API {
checkCreatingBody(jsonLogin);
try {
- String token = manager.authManager().loginUser(jsonLogin.name,
jsonLogin.password);
+ String token = manager.authManager()
+ .loginUser(jsonLogin.name,
jsonLogin.password, jsonLogin.expire);
HugeGraph g = graph(manager, graph);
return manager.serializer(g).writeMap(ImmutableMap.of("token",
token));
} catch (AuthenticationException e) {
@@ -131,6 +132,8 @@ public class LoginAPI extends API {
private String name;
@JsonProperty("user_password")
private String password;
+ @JsonProperty("token_expire")
+ private long expire;
@Override
public void checkCreate(boolean isBatch) {
diff --git
a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/auth/HugeGraphAuthProxy.java
b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/auth/HugeGraphAuthProxy.java
index 63d391279..383504e80 100644
---
a/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/auth/HugeGraphAuthProxy.java
+++
b/hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/auth/HugeGraphAuthProxy.java
@@ -110,15 +110,16 @@ import jakarta.ws.rs.NotAuthorizedException;
public final class HugeGraphAuthProxy implements HugeGraph {
+ private static final Logger LOG = Log.logger(HugeGraphAuthProxy.class);
+ private static final ThreadLocal<Context> CONTEXTS = new
InheritableThreadLocal<>();
+
static {
HugeGraph.registerTraversalStrategies(HugeGraphAuthProxy.class);
}
- private static final Logger LOG = Log.logger(HugeGraphAuthProxy.class);
private final Cache<Id, UserWithRole> usersRoleCache;
private final Cache<Id, RateLimiter> auditLimiters;
private final double auditLogMaxRate;
-
private final HugeGraph hugegraph;
private final TaskSchedulerProxy taskScheduler;
private final AuthManagerProxy authManager;
@@ -141,6 +142,40 @@ public final class HugeGraphAuthProxy implements HugeGraph
{
LOG.info("Audit log rate limit is {}/s", this.auditLogMaxRate);
}
+ static Context setContext(Context context) {
+ Context old = CONTEXTS.get();
+ CONTEXTS.set(context);
+ return old;
+ }
+
+ static void resetContext() {
+ CONTEXTS.remove();
+ }
+
+ private static Context getContext() {
+ // Return task context first
+ String taskContext = TaskManager.getContext();
+ User user = User.fromJson(taskContext);
+ if (user != null) {
+ return new Context(user);
+ }
+
+ return CONTEXTS.get();
+ }
+
+ private static String getContextString() {
+ Context context = getContext();
+ if (context == null) {
+ return null;
+ }
+ return context.user().toJson();
+ }
+
+ static void logUser(User user, String path) {
+ LOG.info("User '{}' login from client [{}] with path '{}'",
+ user.username(), user.client(), path);
+ }
+
@Override
public HugeGraph hugegraph() {
this.verifyAdminPermission();
@@ -1016,6 +1051,61 @@ public final class HugeGraphAuthProxy implements
HugeGraph {
return result;
}
+ static class Context {
+
+ private static final Context ADMIN = new Context(User.ADMIN);
+
+ private final User user;
+
+ public Context(User user) {
+ E.checkNotNull(user, "user");
+ this.user = user;
+ }
+
+ public static Context admin() {
+ return ADMIN;
+ }
+
+ public User user() {
+ return this.user;
+ }
+ }
+
+ static class ContextTask implements Runnable {
+
+ private final Runnable runner;
+ private final Context context;
+
+ public ContextTask(Runnable runner) {
+ this.context = getContext();
+ this.runner = runner;
+ }
+
+ @Override
+ public void run() {
+ setContext(this.context);
+ try {
+ this.runner.run();
+ } finally {
+ resetContext();
+ }
+ }
+ }
+
+ public static class ContextThreadPoolExecutor extends ThreadPoolExecutor {
+
+ public ContextThreadPoolExecutor(int corePoolSize, int maxPoolSize,
+ ThreadFactory threadFactory) {
+ super(corePoolSize, maxPoolSize, 0L, TimeUnit.MILLISECONDS,
+ new LinkedBlockingQueue<>(), threadFactory);
+ }
+
+ @Override
+ public void execute(Runnable command) {
+ super.execute(new ContextTask(command));
+ }
+ }
+
class TaskSchedulerProxy implements TaskScheduler {
private final TaskScheduler taskScheduler;
@@ -1622,8 +1712,14 @@ public final class HugeGraphAuthProxy implements
HugeGraph {
@Override
public String loginUser(String username, String password) {
+ return this.loginUser(username, password, -1L);
+ }
+
+ // TODO: the expire haven't been implemented yet
+ @Override
+ public String loginUser(String username, String password, long expire)
{
try {
- return this.authManager.loginUser(username, password);
+ return this.authManager.loginUser(username, password, expire);
} catch (AuthenticationException e) {
throw new NotAuthorizedException(e.getMessage(), e);
}
@@ -1841,95 +1937,4 @@ public final class HugeGraphAuthProxy implements
HugeGraph {
return this.origin.toString();
}
}
-
- private static final ThreadLocal<Context> CONTEXTS = new
InheritableThreadLocal<>();
-
- protected static Context setContext(Context context) {
- Context old = CONTEXTS.get();
- CONTEXTS.set(context);
- return old;
- }
-
- protected static void resetContext() {
- CONTEXTS.remove();
- }
-
- protected static Context getContext() {
- // Return task context first
- String taskContext = TaskManager.getContext();
- User user = User.fromJson(taskContext);
- if (user != null) {
- return new Context(user);
- }
-
- return CONTEXTS.get();
- }
-
- protected static String getContextString() {
- Context context = getContext();
- if (context == null) {
- return null;
- }
- return context.user().toJson();
- }
-
- protected static void logUser(User user, String path) {
- LOG.info("User '{}' login from client [{}] with path '{}'",
- user.username(), user.client(), path);
- }
-
- static class Context {
-
- private static final Context ADMIN = new Context(User.ADMIN);
-
- private final User user;
-
- public Context(User user) {
- E.checkNotNull(user, "user");
- this.user = user;
- }
-
- public User user() {
- return this.user;
- }
-
- public static Context admin() {
- return ADMIN;
- }
- }
-
- static class ContextTask implements Runnable {
-
- private final Runnable runner;
- private final Context context;
-
- public ContextTask(Runnable runner) {
- this.context = getContext();
- this.runner = runner;
- }
-
- @Override
- public void run() {
- setContext(this.context);
- try {
- this.runner.run();
- } finally {
- resetContext();
- }
- }
- }
-
- public static class ContextThreadPoolExecutor extends ThreadPoolExecutor {
-
- public ContextThreadPoolExecutor(int corePoolSize, int maxPoolSize,
- ThreadFactory threadFactory) {
- super(corePoolSize, maxPoolSize, 0L, TimeUnit.MILLISECONDS,
- new LinkedBlockingQueue<>(), threadFactory);
- }
-
- @Override
- public void execute(Runnable command) {
- super.execute(new ContextTask(command));
- }
- }
}
diff --git
a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/AuthManager.java
b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/AuthManager.java
index 51c72fba4..a2c76d395 100644
---
a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/AuthManager.java
+++
b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/AuthManager.java
@@ -121,6 +121,8 @@ public interface AuthManager {
String loginUser(String username, String password) throws
AuthenticationException;
+ String loginUser(String username, String password, long expire) throws
AuthenticationException;
+
void logoutUser(String token);
UserWithRole validateUser(String username, String password);
diff --git
a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/StandardAuthManager.java
b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/StandardAuthManager.java
index 103c58afc..1ec2711d7 100644
---
a/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/StandardAuthManager.java
+++
b/hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/auth/StandardAuthManager.java
@@ -114,6 +114,13 @@ public class StandardAuthManager implements AuthManager {
this.ipWhiteListEnabled = false;
}
+ /**
+ * Maybe can define an proxy class to choose forward or call local
+ */
+ public static boolean isLocal(AuthManager authManager) {
+ return authManager instanceof StandardAuthManager;
+ }
+
private <V> Cache<Id, V> cache(String prefix, long capacity,
long expiredTime) {
String name = prefix + "-" + this.graph.name();
@@ -636,6 +643,13 @@ public class StandardAuthManager implements AuthManager {
@Override
public String loginUser(String username, String password)
throws AuthenticationException {
+ return this.loginUser(username, password, -1L);
+ }
+
+ // TODO: the expire haven't been implemented yet
+ @Override
+ public String loginUser(String username, String password, long expire)
+ throws AuthenticationException {
HugeUser user = this.matchUser(username, password);
if (user == null) {
String msg = "Incorrect username or password";
@@ -717,13 +731,6 @@ public class StandardAuthManager implements AuthManager {
this.ipWhiteListEnabled = status;
}
- /**
- * Maybe can define an proxy class to choose forward or call local
- */
- public static boolean isLocal(AuthManager authManager) {
- return authManager instanceof StandardAuthManager;
- }
-
public <R> R commit(Callable<R> callable) {
this.groups.autoCommit(false);
this.access.autoCommit(false);
diff --git
a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/AuthTest.java
b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/AuthTest.java
index 1db7af924..60bfdace8 100644
---
a/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/AuthTest.java
+++
b/hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/core/AuthTest.java
@@ -55,6 +55,63 @@ import com.google.common.collect.ImmutableSet;
public class AuthTest extends BaseCoreTest {
+ private static Id makeProjectAndAddGraph(HugeGraph graph,
+ String projectName,
+ String graphName) {
+ HugeProject project = makeProject(projectName, "");
+ AuthManager authManager = graph.authManager();
+ Id projectId = authManager.createProject(project);
+ projectId = authManager.projectAddGraphs(projectId,
+ ImmutableSet.of(graphName));
+ Assert.assertNotNull(projectId);
+ return projectId;
+ }
+
+ private static HugeProject makeProject(String name, String desc) {
+ HugeProject project = new HugeProject(name, desc);
+ project.creator("admin");
+ return project;
+ }
+
+ private static HugeUser makeUser(String name, String password) {
+ HugeUser user = new HugeUser(name);
+ user.password(password);
+ user.creator("admin");
+ return user;
+ }
+
+ private static HugeGroup makeGroup(String name) {
+ HugeGroup group = new HugeGroup(name);
+ group.creator("admin");
+ return group;
+ }
+
+ private static HugeTarget makeTarget(String name, String url) {
+ HugeTarget target = new HugeTarget(name, url);
+ target.creator("admin");
+ return target;
+ }
+
+ private static HugeTarget makeTarget(String name, String graph, String url,
+ List<HugeResource> ress) {
+ HugeTarget target = new HugeTarget(name, graph, url, ress);
+ target.creator("admin");
+ return target;
+ }
+
+ private static HugeBelong makeBelong(Id user, Id group) {
+ HugeBelong belong = new HugeBelong(user, group);
+ belong.creator("admin");
+ return belong;
+ }
+
+ private static HugeAccess makeAccess(Id group, Id target,
+ HugePermission permission) {
+ HugeAccess access = new HugeAccess(group, target, permission);
+ access.creator("admin");
+ return access;
+ }
+
@After
public void clearAll() {
HugeGraph graph = graph();
@@ -301,7 +358,7 @@ public class AuthTest extends BaseCoreTest {
group = authManager.getGroup(id);
Assert.assertEquals("group1", group.name());
- Assert.assertEquals(null, group.description());
+ Assert.assertNull(group.description());
Assert.assertEquals(group.create(), group.update());
Assert.assertEquals(ImmutableMap.of("group_name", "group1",
@@ -632,7 +689,7 @@ public class AuthTest extends BaseCoreTest {
HugeBelong belong = authManager.getBelong(id1);
Assert.assertEquals(user, belong.source());
Assert.assertEquals(group1, belong.target());
- Assert.assertEquals(null, belong.description());
+ Assert.assertNull(belong.description());
Assert.assertEquals(belong.create(), belong.update());
Map<String, Object> expected = new HashMap<>();
@@ -647,7 +704,7 @@ public class AuthTest extends BaseCoreTest {
belong = authManager.getBelong(id2);
Assert.assertEquals(user, belong.source());
Assert.assertEquals(group2, belong.target());
- Assert.assertEquals(null, belong.description());
+ Assert.assertNull(belong.description());
Assert.assertEquals(belong.create(), belong.update());
expected = new HashMap<>();
@@ -1321,11 +1378,11 @@ public class AuthTest extends BaseCoreTest {
authManager.createUser(user);
// Login
- authManager.loginUser("test", "pass");
+ authManager.loginUser("test", "pass", 10080L);
// Invalid username or password
Assert.assertThrows(AuthenticationException.class, () -> {
- authManager.loginUser("huge", "graph");
+ authManager.loginUser("huge", "graph", 10080L);
}, e -> {
Assert.assertContains("Incorrect username or password",
e.getMessage());
});
@@ -1338,7 +1395,7 @@ public class AuthTest extends BaseCoreTest {
HugeUser user = makeUser("test", StringEncoding.hashPassword("pass"));
Id userId = authManager.createUser(user);
- String token = authManager.loginUser("test", "pass");
+ String token = authManager.loginUser("test", "pass", 10080L);
UserWithRole userWithRole;
userWithRole = authManager.validateUser(token);
@@ -1375,7 +1432,7 @@ public class AuthTest extends BaseCoreTest {
Id userId = authManager.createUser(user);
// Login
- String token = authManager.loginUser("test", "pass");
+ String token = authManager.loginUser("test", "pass", 10080L);
// Logout
Cache<Id, String> tokenCache = Whitebox.getInternalState(authManager,
@@ -1500,79 +1557,22 @@ public class AuthTest extends BaseCoreTest {
List<HugeProject> projects = authManager.listAllProject(1);
Assert.assertNotNull(projects);
- Assert.assertTrue(projects.size() == 1);
+ Assert.assertEquals(1, projects.size());
projects = authManager.listAllProject(-1);
Assert.assertNotNull(projects);
- Assert.assertTrue(projects.size() == 3);
+ Assert.assertEquals(3, projects.size());
projects = authManager.listAllProject(3);
Assert.assertNotNull(projects);
- Assert.assertTrue(projects.size() == 3);
+ Assert.assertEquals(3, projects.size());
projects = authManager.listAllProject(4);
Assert.assertNotNull(projects);
- Assert.assertTrue(projects.size() == 3);
+ Assert.assertEquals(3, projects.size());
projects = authManager.listAllProject(2);
Assert.assertNotNull(projects);
- Assert.assertTrue(projects.size() == 2);
- }
-
- private static Id makeProjectAndAddGraph(HugeGraph graph,
- String projectName,
- String graphName) {
- HugeProject project = makeProject(projectName, "");
- AuthManager authManager = graph.authManager();
- Id projectId = authManager.createProject(project);
- projectId = authManager.projectAddGraphs(projectId,
- ImmutableSet.of(graphName));
- Assert.assertNotNull(projectId);
- return projectId;
- }
-
- private static HugeProject makeProject(String name, String desc) {
- HugeProject project = new HugeProject(name, desc);
- project.creator("admin");
- return project;
- }
-
- private static HugeUser makeUser(String name, String password) {
- HugeUser user = new HugeUser(name);
- user.password(password);
- user.creator("admin");
- return user;
- }
-
- private static HugeGroup makeGroup(String name) {
- HugeGroup group = new HugeGroup(name);
- group.creator("admin");
- return group;
- }
-
- private static HugeTarget makeTarget(String name, String url) {
- HugeTarget target = new HugeTarget(name, url);
- target.creator("admin");
- return target;
- }
-
- private static HugeTarget makeTarget(String name, String graph, String url,
- List<HugeResource> ress) {
- HugeTarget target = new HugeTarget(name, graph, url, ress);
- target.creator("admin");
- return target;
- }
-
- private static HugeBelong makeBelong(Id user, Id group) {
- HugeBelong belong = new HugeBelong(user, group);
- belong.creator("admin");
- return belong;
- }
-
- private static HugeAccess makeAccess(Id group, Id target,
- HugePermission permission) {
- HugeAccess access = new HugeAccess(group, target, permission);
- access.creator("admin");
- return access;
+ Assert.assertEquals(2, projects.size());
}
}