feat(server): adapt Hubble 2.0 frontend APIs and implement default graph/role management#1
Open
feat(server): adapt Hubble 2.0 frontend APIs and implement default graph/role management#1
Conversation
- Add listProfile endpoint with default graph sorting and prefix filtering - Add setDefault/unsetDefault/getDefault endpoints for default graph management - Add manage(PUT) endpoint for graph nickname update - Add createByForm for form-urlencoded graph creation compatibility - Auto-fill HStore/PD defaults (backend/serializer/store) during graph creation
- Add setDefaultRole/checkDefaultRole/deleteDefaultRole in GraphSpaceAPI - Add checkDefaultRole endpoint in ManagerAPI - Add default role interfaces in AuthManager - Implement default role CRUD in StandardAuthManager and StandardAuthManagerV2 - Add stub proxy methods in HugeGraphAuthProxy
- Add new SchemaTemplateAPI with list/get/create/update/delete operations - Fix package path from api.profile to api.space - Use HugeGraphAuthProxy.username() instead of authManager.username()
…#3008) - fix: use @POST/@delete for setDefault/unsetDefault (REST semantics) - fix: add null/empty validation before role field access in GraphSpaceAPI to prevent NPE in setDefaultRole/checkDefaultRole/deleteDefaultRole - fix: change isPrefix to private static and guard nickname null in GraphSpaceAPI and GraphsAPI - fix: ConfigUtil.writeConfigToString always returns JSON regardless of whether config was loaded from file, fixing listProfile endpoint - fix: add @RolesAllowed annotations to SchemaTemplateAPI endpoints - fix: use ForbiddenException (403) instead of HugeException (400) for authorization failures in SchemaTemplateAPI and GraphSpaceAPI - fix: correct LOG placeholder count in SchemaTemplateAPI.delete - fix: use HugeException ('%s') format instead of SLF4J '{}' format - fix: replace com.alipay StringUtils with commons-lang3 in ManagerAPI - fix: add @consumes and checkUpdate() validation to SchemaTemplate.update - fix: add ensurePdModeEnabled guard to ManagerAPI.checkDefaultRole - fix: guard configs null access in GraphsAPI.create clone branch
… mode ## Background Hubble 2.0 previously relied exclusively on PD mode (distributed HStore backend). This PR makes the server-side APIs fully compatible with the community default: single-node RocksDB without PD/HStore, so that Hubble remains functional out of the box for all deployment modes. ## Core bug fixes ### GraphsAPI - Fix `create()`: `backend=hstore` / `serializer=binary` defaults are now only injected when `manager.isPDEnabled()` is true, preventing graph creation failures on standalone RocksDB deployments. - Fix `manage()`: replace `exist.nickname(nickname)` (in-memory only) with `manager.updateGraphNickname()`, which persists the change to PD meta storage in distributed mode and gracefully falls back to in-memory update in standalone mode. - Fix `manage()`: relax `actionMap.size() == 2` validation to `containsKey(GRAPH_ACTION)`, so extra fields from the frontend no longer cause spurious 400 errors. - Guard `getDefaultGraph()`, `setDefault()`, `unsetDefault()`, and `getDefault()` with `isPDEnabled()` checks; return empty results in standalone mode instead of throwing NPE. - Fix `listProfile()`: guard `getDefaultGraph()` call with `isPDEnabled()`; add null-safe fallback for `gs.nickname()` in non-PD mode. ### GraphManager - `isExistedGraphNickname()`: add non-PD branch that scans in-memory graphs instead of accessing the uninitialized `metaManager`, preventing NPE in standalone mode. - New `updateGraphNickname()`: updates in-memory graph instance first, then persists nickname to `metaManager` only in PD mode. ### ConfigUtil - `writeConfigToString()`: always serializes config to JSON (previously could emit raw properties format), fixing `listProfile` deserialization. - New `isSensitiveKey()`: filters keys containing `password`, `secret`, `token`, `credential`, `private_key`, or `auth.key` from the serialized output to prevent credential leakage through the API. ### ManagerAPI - Add `ensurePdModeEnabled()` guard to all PD-specific endpoints (`createManager`, `deleteManager`, `list`, `checkRole`, `getRolesInGs`, `checkDefaultRole`). - Wrap `HugeDefaultRole.valueOf()` in try-catch to return HTTP 400 instead of HTTP 500 when an invalid role string is supplied. ### SchemaTemplateAPI - Fix incorrect `HugeException` import; replace with `ForbiddenException` for proper HTTP 403 semantics. - Add missing `@RolesAllowed` annotations and implement `checkUpdate()` validation. ### StandardAuthManager - Implement `setDefaultGraph` / `getDefaultGraph` / `unsetDefaultGraph` using marker-group pattern (HugeGroup + HugeBelong) for persistence. - Implement `createDefaultRole` / `createSpaceDefaultRole` / `isDefaultRole` / `deleteDefaultRole` with the same marker-group mechanism. - Add detailed design-note Javadoc explaining the workaround, its limitations, and the non-PD degradation path. ## Code quality improvements - Extract shared `isPrefix(Map, String)` helper and `DATE_FORMATTER` constant into the `API` base class, eliminating ~30 lines of duplicated code across `GraphsAPI` and `GraphSpaceAPI`. - Replace non-thread-safe `SimpleDateFormat` (constructed per-request) with a single static `DateTimeFormatter` (immutable, thread-safe). - Fix 12-hour clock format `hh` → 24-hour `HH` in `GraphSpaceAPI`.
… (ID vs name mismatch in standalone mode)
…raphs from PD Previously, HugeGremlinServer was started after HugeRestServer, causing ContextGremlinServer's GRAPH_CREATE listener to be registered too late. Graphs loaded from PD/meta during RestServer initialization fired their GRAPH_CREATE events before the listener existed, so they were never injected into Gremlin's global bindings. This caused: "Could not rebind [g] to [__g_DEFAULT-xx] as [__g_DEFAULT-xx] not in the Graph or TraversalSource global bindings" (HTTP 400) Fix: split HugeGremlinServer.start() into prepare() + startPrepared(). prepare() constructs ContextGremlinServer (registering listeners) before RestServer starts. startPrepared() is called after RestServer finishes loading graphs. This ensures all PD-loaded graphs are captured by the listener and injected correctly. Affected files: - HugeGraphServer: call prepare() before RestServer, startPrepared() after - HugeGremlinServer: add prepare()/startPrepared(), keep start() for compat - ContextGremlinServer: no behavioral change (listeners register on construct)
…ethods Root Cause: In StandardAuthManagerV2, the `createUser` (and other create methods: `createGroup`, `createTarget`, `createBelong`, `createAccess`) only initialized timestamps but failed to call `updateCreator()`. During serialization, `SchemaDefine.AuthElement.asMap` enforces a strict `creator != null` validation, resulting in an `IllegalStateException`. Changes: - Added `updateCreator(xxx)` calls immediately after `xxx.create(xxx.update())` in all 5 `create*` methods. - Hardened the `updateCreator` method: Introduced a fallback to "system" when `currentUsername()` returns null. This ensures the `creator` is always populated, preventing errors during system initialization when no HTTP context is available.
Add the private static isPrefix() method that was accidentally removed in a previous commit. This method is used by listProfile() to filter graphs by name or nickname prefix, with proper null handling for nickname field. This fixes a compilation error where isPrefix() was called but not defined.
Check if belong record exists before attempting to delete in unsetDefaultGraph() to prevent throwing exceptions when unsetting an already-unset default graph. This makes the API idempotent and prevents 500 errors when clients call unset multiple times. The fix aligns StandardAuthManagerV2 with StandardAuthManager, which already implements this idempotent behavior.
- SchemaTemplateAPI: add ensurePdModeEnabled() guard to all endpoints to prevent NPE when MetaManager is not initialized in standalone mode - SchemaTemplateAPI: add null body check in create() and update() to return 400 instead of NPE/500 on missing request body - GraphsAPI.listProfile: format default_update_time consistently with create_time using DATE_FORMATTER instead of raw Date serialization - GraphsAPI.manage: guard value.getClass() against null action value to prevent NPE when building the validation error message - GraphSpaceAPI.deleteDefaultRole: wrap HugeDefaultRole.valueOf() in try/catch to return 400 for invalid role values instead of 500 - GraphManager: add isPDEnabled() guard to all schema-template methods to prevent NPE when MetaManager is not available in standalone mode - GraphManager.updateGraphNickname: propagate PD persistence failure to caller with in-memory rollback, preventing silent state inconsistency
- GraphsAPI: remove duplicate private isPrefix() that shadowed the protected version in API base class, causing compilation failure - GraphsAPI: fix NPE in manage() when 'update' value is null by guarding value.getClass() in both action and update validation - GraphsAPI/GraphSpaceAPI: replace org.apache.commons.lang.StringUtils with commons-lang3 and remove org.apache.logging.log4j.util.Strings import (replaced with StringUtils equivalents) to fix potential classpath issues - GraphManager.updateGraphNickname: restore old nickname (not null) on PD persistence failure to avoid a third inconsistent state - StandardAuthManagerV2.setDefaultGraph: check existBelong() before createBelong() to make the operation idempotent; repeated POST calls for the same user/graph no longer throw HugeException - StandardAuthManagerV2.createDefaultRole: same idempotent guard via existBelong() check before createBelong() - ManagerAPI.checkDefaultRole: use @PathParam graphspace instead of @QueryParam to match the mounted path contract
StandardAuthManager (standalone RocksDB) fully implements setDefaultGraph/ unsetDefaultGraph/getDefaultGraph via HugeGroup+HugeBelong mechanism and does not require PD. The non-PD early-return guards in setDefault, unsetDefault, getDefault and listProfile were silently discarding user preferences, making the API a no-op in standalone mode. Remove the isPDEnabled() short-circuits and route all default graph operations directly through authManager, which dispatches correctly to either StandardAuthManager or StandardAuthManagerV2 depending on the deployment mode.
…nding - Fix SchemaTemplateAPI logger using wrong class (RestServer -> SchemaTemplateAPI) - Fix StandardAuthManager fabricated belong ID: replace string-constructed IDs with actual graph traversal (findBelongBinding) to correctly detect/delete existing HugeBelong edges, making setDefaultGraph/unsetDefaultGraph/ createDefaultRole idempotent - Fix HugeUser.initSchemaIfNeeded: add incremental schema upgrade so existing deployments get the user_nickname property key without full schema recreation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
setDefaultGraph/unsetDefaultGraph/getDefaultGraphin bothStandardAuthManager(standalone) andStandardAuthManagerV2(PD mode)createDefaultRole,isDefaultRole, etc.) for GraphSpacefindBelongBinding) to correctly detect/delete existingHugeBelongedgesHugeUser.initSchemaIfNeededto perform incremental schema upgrade so existing deployments get theuser_nicknameproperty keySchemaTemplateAPIlogger class name, addensurePdModeEnabledguards to all schema template endpointscommons-lang→commons-lang3), duplicateisPrefix()method, wrongHugeExceptionimport pathAuthManagerunconditionally (remove erroneousisPDEnabled()no-ops)Test plan
mvn compile -DskipTestsHugeUserschema upgrade addsuser_nicknamewithout recreating the vertex label