diff --git a/hubble-be/pom.xml b/hubble-be/pom.xml
index 0cbd63c5..b5a0b911 100644
--- a/hubble-be/pom.xml
+++ b/hubble-be/pom.xml
@@ -70,7 +70,7 @@
com.baidu.hugegraphhugegraph-common
- 1.8.8
+ 1.8.9org.apache.logging.log4j
@@ -111,8 +111,17 @@
org.apache.logging.log4jlog4j-slf4j-impl
+
+ com.baidu.hugegraph
+ hugegraph-client
+
+
+ com.baidu.hugegraph
+ hugegraph-client
+ 1.9.6
+ commons-fileupload
diff --git a/hubble-be/src/main/java/com/baidu/hugegraph/HugeGraphHubble.java b/hubble-be/src/main/java/com/baidu/hugegraph/HugeGraphHubble.java
index e5c2c7fd..586669f2 100644
--- a/hubble-be/src/main/java/com/baidu/hugegraph/HugeGraphHubble.java
+++ b/hubble-be/src/main/java/com/baidu/hugegraph/HugeGraphHubble.java
@@ -24,6 +24,7 @@
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.scheduling.annotation.EnableScheduling;
@@ -32,6 +33,7 @@
@SpringBootApplication
@EnableScheduling
@MapperScan("com.baidu.hugegraph.mapper")
+@ServletComponentScan(basePackages = "com.baidu.hugegraph.filter")
public class HugeGraphHubble extends SpringBootServletInitializer {
public static void main(String[] args) {
diff --git a/hubble-be/src/main/java/com/baidu/hugegraph/common/Constant.java b/hubble-be/src/main/java/com/baidu/hugegraph/common/Constant.java
index c7600a2c..acb8e513 100644
--- a/hubble-be/src/main/java/com/baidu/hugegraph/common/Constant.java
+++ b/hubble-be/src/main/java/com/baidu/hugegraph/common/Constant.java
@@ -74,4 +74,6 @@ public final class Constant {
);
public static final String[] LIKE_WILDCARDS = {"%", "_", "^", "[", "]"};
+
+ public static final String BEARER_TOKEN_PREFIX = "Bearer ";
}
diff --git a/hubble-be/src/main/java/com/baidu/hugegraph/config/ClientConfiguration.java b/hubble-be/src/main/java/com/baidu/hugegraph/config/ClientConfiguration.java
new file mode 100644
index 00000000..5af6b38a
--- /dev/null
+++ b/hubble-be/src/main/java/com/baidu/hugegraph/config/ClientConfiguration.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2017 HugeGraph Authors
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.baidu.hugegraph.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import com.baidu.hugegraph.driver.HugeClient;
+import com.baidu.hugegraph.driver.HugeClientBuilder;
+import com.baidu.hugegraph.options.HubbleOptions;
+import com.baidu.hugegraph.util.SessionUtil;
+
+import lombok.extern.log4j.Log4j2;
+
+@Log4j2
+@Configuration
+public class ClientConfiguration {
+
+ public static final String AUTH_CLIENT_NAME = "authClient";
+ public static final String ADMIN_CLIENT_NAME = "adminClient";
+
+ @Bean(AUTH_CLIENT_NAME)
+ public HugeClient authClient(HugeConfig config) {
+ String authUrl = config.get(HubbleOptions.AUTH_REMOTE_URL);
+ String authGraph = config.get(HubbleOptions.AUTH_GRAPH);
+ HugeClient authClient = HugeClient.builder(authUrl, authGraph).build();
+
+ SessionUtil.authClient = authClient;
+
+ return authClient;
+ }
+
+ @Bean(ADMIN_CLIENT_NAME)
+ public HugeClient adminClient(HugeConfig config) {
+ String authUrl = config.get(HubbleOptions.AUTH_REMOTE_URL);
+ String authGraph = config.get(HubbleOptions.AUTH_GRAPH);
+ String adminPassword = config.get(HubbleOptions.ADMIN_PASSWORD);
+ HugeClient adminClient = new HugeClientBuilder(authUrl, authGraph)
+ .configUser("admin", adminPassword)
+ .build();
+
+ SessionUtil.adminClient = adminClient;
+
+ return adminClient;
+ }
+}
diff --git a/hubble-be/src/main/java/com/baidu/hugegraph/config/JacksonConfig.java b/hubble-be/src/main/java/com/baidu/hugegraph/config/JacksonConfig.java
index df690635..575ad3fa 100644
--- a/hubble-be/src/main/java/com/baidu/hugegraph/config/JacksonConfig.java
+++ b/hubble-be/src/main/java/com/baidu/hugegraph/config/JacksonConfig.java
@@ -48,7 +48,7 @@ public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
return mapper;
}
- public static class ResponseSerailizer extends JsonSerializer {
+ public static class ResponseSerializer extends JsonSerializer {
@Override
public void serialize(Response response, JsonGenerator generator,
diff --git a/hubble-be/src/main/java/com/baidu/hugegraph/controller/project/ProjectController.java b/hubble-be/src/main/java/com/baidu/hugegraph/controller/project/ProjectController.java
new file mode 100644
index 00000000..786c5ab4
--- /dev/null
+++ b/hubble-be/src/main/java/com/baidu/hugegraph/controller/project/ProjectController.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2017 HugeGraph Authors
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.baidu.hugegraph.controller.project;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.baidu.hugegraph.common.Constant;
+import com.baidu.hugegraph.entity.project.ProjectEntity;
+import com.baidu.hugegraph.service.project.ProjectService;
+import com.baidu.hugegraph.util.Ex;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+
+@RestController
+@RequestMapping(Constant.API_VERSION + "graph-connections/project")
+public class ProjectController {
+
+ @Autowired
+ private ProjectService projectService;
+
+ @PostMapping
+ public ProjectEntity createProject(@RequestBody ProjectEntity project) {
+ this.checkParamsValid(project, true);
+ return this.projectService.createProject(project);
+ }
+
+ @PutMapping
+ public ProjectEntity updateProject(@RequestBody ProjectEntity project) {
+ this.checkParamsValid(project, false);
+ return this.projectService.updateProject(project);
+ }
+
+ @DeleteMapping("{id}")
+ public void deleteProject(@PathVariable("id") String projectId) {
+ this.projectService.deleteProject(projectId);
+ }
+
+ @GetMapping("/list")
+ public IPage list(@RequestParam(value = "project_name",
+ required = false)
+ String projectName,
+ @RequestParam(name = "page_no",
+ required = false,
+ defaultValue = "1")
+ int pageNo,
+ @RequestParam(name = "page_size",
+ required = false,
+ defaultValue = "10")
+ int pageSize) {
+ return this.projectService.list(projectName, pageNo, pageSize);
+ }
+
+ private void checkParamsValid(ProjectEntity entity, boolean create) {
+ Ex.check(StringUtils.isNotEmpty(entity.getName()),
+ "common.param.cannot-be-null-or-empty", "project_name");
+ Ex.check(CollectionUtils.isNotEmpty(entity.getAdminUsers()),
+ "common.param.cannot-be-null-or-empty", "admin_users");
+ Ex.check(CollectionUtils.isNotEmpty(entity.getOpUsers()),
+ "common.param.cannot-be-null-or-empty", "op_users");
+ if (create) {
+ Ex.check(entity.getId() == null,
+ "common.param.must-be-null", "id");
+ } else {
+ Ex.check(entity.getId() != null,
+ "common.param.cannot-be-null", "id");
+ }
+ }
+}
diff --git a/hubble-be/src/main/java/com/baidu/hugegraph/controller/schema/PropertyKeyController.java b/hubble-be/src/main/java/com/baidu/hugegraph/controller/schema/PropertyKeyController.java
index d92646e8..70381763 100644
--- a/hubble-be/src/main/java/com/baidu/hugegraph/controller/schema/PropertyKeyController.java
+++ b/hubble-be/src/main/java/com/baidu/hugegraph/controller/schema/PropertyKeyController.java
@@ -41,8 +41,8 @@
import com.baidu.hugegraph.entity.schema.UsingCheckEntity;
import com.baidu.hugegraph.exception.ExternalException;
import com.baidu.hugegraph.service.schema.PropertyKeyService;
-import com.baidu.hugegraph.util.HubbleUtil;
import com.baidu.hugegraph.util.Ex;
+import com.baidu.hugegraph.util.HubbleUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import lombok.extern.log4j.Log4j2;
diff --git a/hubble-be/src/main/java/com/baidu/hugegraph/controller/system/LoginController.java b/hubble-be/src/main/java/com/baidu/hugegraph/controller/system/LoginController.java
new file mode 100644
index 00000000..9df6acfd
--- /dev/null
+++ b/hubble-be/src/main/java/com/baidu/hugegraph/controller/system/LoginController.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2017 HugeGraph Authors
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.baidu.hugegraph.controller.system;
+
+import org.apache.http.HttpHeaders;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestHeader;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.baidu.hugegraph.common.Constant;
+import com.baidu.hugegraph.controller.BaseController;
+import com.baidu.hugegraph.entity.login.LoginBody;
+import com.baidu.hugegraph.entity.login.LoginResult;
+import com.baidu.hugegraph.entity.user.UserEntity;
+import com.baidu.hugegraph.service.system.AuthService;
+import com.baidu.hugegraph.util.E;
+
+@RestController
+@RequestMapping(Constant.API_VERSION + "graph-connections/login")
+public class LoginController extends BaseController {
+
+ @Autowired
+ private AuthService authService;
+
+ @PostMapping
+ public LoginResult login(@RequestBody LoginBody loginBody) {
+ return this.authService.login(loginBody);
+ }
+
+ @DeleteMapping
+ public void logout() {
+ this.authService.logout();
+ }
+
+ @GetMapping("/user")
+ public UserEntity currentUser(@RequestHeader(HttpHeaders.AUTHORIZATION)
+ String token) {
+ E.checkArgumentNotNull(token,
+ "Request header Authorization must not be null");
+ return this.authService.getCurrentUser();
+ }
+}
diff --git a/hubble-be/src/main/java/com/baidu/hugegraph/controller/user/UserController.java b/hubble-be/src/main/java/com/baidu/hugegraph/controller/user/UserController.java
new file mode 100644
index 00000000..2da898fc
--- /dev/null
+++ b/hubble-be/src/main/java/com/baidu/hugegraph/controller/user/UserController.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2017 HugeGraph Authors
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.baidu.hugegraph.controller.user;
+
+import java.util.List;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.baidu.hugegraph.common.Constant;
+import com.baidu.hugegraph.entity.user.UserEntity;
+import com.baidu.hugegraph.service.user.UserService;
+import com.baidu.hugegraph.util.Ex;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+
+@RestController
+@RequestMapping(Constant.API_VERSION + "graph-connections/user")
+public class UserController {
+
+ @Autowired
+ private UserService userService;
+
+ @PostMapping
+ public UserEntity create(@RequestBody UserEntity user) {
+ this.checkUser(user, true);
+ return this.userService.createUser(user);
+ }
+
+ @PutMapping
+ public UserEntity update(@RequestBody UserEntity user) {
+ this.checkUser(user, false);
+ return this.userService.updateUser(user);
+ }
+
+ @DeleteMapping
+ public void delete(@RequestBody List userIds) {
+ this.userService.deleteUser(userIds);
+ }
+
+ @GetMapping
+ public IPage list(@RequestParam(value = "user_name",
+ required = false)
+ String userName,
+ @RequestParam(name = "page_no",
+ required = false,
+ defaultValue = "1")
+ int pageNo,
+ @RequestParam(name = "page_size",
+ required = false,
+ defaultValue = "10")
+ int pageSize) {
+ return this.userService.list(userName, pageNo, pageSize);
+ }
+
+ private void checkUser(UserEntity entity, boolean create) {
+ Ex.check(StringUtils.isNotEmpty(entity.getUsername()),
+ "common.param.cannot-be-null-or-empty", "user_name");
+ Ex.check(StringUtils.isNotEmpty(entity.getPassword()),
+ "common.param.cannot-be-null-or-empty", "user_password");
+ if (create) {
+ Ex.check(entity.getId() == null,
+ "common.param.must-be-null", "id");
+ } else {
+ Ex.check(entity.getId() != null,
+ "common.param.cannot-be-null", "id");
+ }
+ }
+}
diff --git a/hubble-be/src/main/java/com/baidu/hugegraph/entity/login/LoginBody.java b/hubble-be/src/main/java/com/baidu/hugegraph/entity/login/LoginBody.java
new file mode 100644
index 00000000..cd818829
--- /dev/null
+++ b/hubble-be/src/main/java/com/baidu/hugegraph/entity/login/LoginBody.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2017 HugeGraph Authors
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.baidu.hugegraph.entity.login;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class LoginBody {
+
+ @JsonProperty("user_name")
+ private String name;
+
+ @JsonProperty("password")
+ private String password;
+}
diff --git a/hubble-be/src/main/java/com/baidu/hugegraph/entity/login/LoginResult.java b/hubble-be/src/main/java/com/baidu/hugegraph/entity/login/LoginResult.java
new file mode 100644
index 00000000..014e30ea
--- /dev/null
+++ b/hubble-be/src/main/java/com/baidu/hugegraph/entity/login/LoginResult.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2017 HugeGraph Authors
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.baidu.hugegraph.entity.login;
+
+import java.util.List;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class LoginResult {
+
+ @JsonProperty("token")
+ private String token;
+
+ @JsonProperty("allowed_menus")
+ private List allowedMenus;
+}
diff --git a/hubble-be/src/main/java/com/baidu/hugegraph/entity/project/ProjectEntity.java b/hubble-be/src/main/java/com/baidu/hugegraph/entity/project/ProjectEntity.java
new file mode 100644
index 00000000..fe5b9788
--- /dev/null
+++ b/hubble-be/src/main/java/com/baidu/hugegraph/entity/project/ProjectEntity.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2017 HugeGraph Authors
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.baidu.hugegraph.entity.project;
+
+import java.util.List;
+import java.util.Set;
+
+import com.baidu.hugegraph.entity.user.AuthElement;
+import com.baidu.hugegraph.structure.auth.Project;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class ProjectEntity extends AuthElement {
+
+ private static final long serialVersionUID = 6004765261545877970L;
+
+ @JsonProperty("project_name")
+ private String name;
+
+ @JsonProperty("project_graphs")
+ private Set graphs;
+
+ @JsonProperty("admin_users")
+ private List adminUsers;
+
+ @JsonProperty("op_users")
+ private List opUsers;
+
+ @JsonProperty("description")
+ private String description;
+
+ public static Project convertToProject(ProjectEntity entity) {
+ Project project = new Project();
+ project.description(entity.description);
+ project.name(entity.name);
+ project.graphs(entity.graphs);
+ return project;
+ }
+}
diff --git a/hubble-be/src/main/java/com/baidu/hugegraph/entity/schema/LabelUpdateEntity.java b/hubble-be/src/main/java/com/baidu/hugegraph/entity/schema/LabelUpdateEntity.java
index 58b02f1f..29ee9829 100644
--- a/hubble-be/src/main/java/com/baidu/hugegraph/entity/schema/LabelUpdateEntity.java
+++ b/hubble-be/src/main/java/com/baidu/hugegraph/entity/schema/LabelUpdateEntity.java
@@ -26,10 +26,7 @@
import com.fasterxml.jackson.annotation.JsonProperty;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
import lombok.Data;
-import lombok.NoArgsConstructor;
@Data
public abstract class LabelUpdateEntity implements Typifiable {
diff --git a/hubble-be/src/main/java/com/baidu/hugegraph/entity/user/AuthElement.java b/hubble-be/src/main/java/com/baidu/hugegraph/entity/user/AuthElement.java
new file mode 100644
index 00000000..6c9ab527
--- /dev/null
+++ b/hubble-be/src/main/java/com/baidu/hugegraph/entity/user/AuthElement.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2017 HugeGraph Authors
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.baidu.hugegraph.entity.user;
+
+import java.io.Serializable;
+import java.util.Date;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public abstract class AuthElement implements Serializable {
+
+ private static final long serialVersionUID = -2330255923178206308L;
+
+ @JsonProperty("id")
+ protected String id;
+
+ @JsonProperty("create")
+ protected Date create;
+
+ @JsonProperty("update")
+ protected Date update;
+
+ @JsonProperty("creator")
+ protected String creator;
+}
diff --git a/hubble-be/src/main/java/com/baidu/hugegraph/entity/user/UserEntity.java b/hubble-be/src/main/java/com/baidu/hugegraph/entity/user/UserEntity.java
new file mode 100644
index 00000000..fe7d71fa
--- /dev/null
+++ b/hubble-be/src/main/java/com/baidu/hugegraph/entity/user/UserEntity.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2017 HugeGraph Authors
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.baidu.hugegraph.entity.user;
+
+import java.util.List;
+
+import com.baidu.hugegraph.structure.auth.Group;
+import com.baidu.hugegraph.structure.auth.HugeGroupTag;
+import com.baidu.hugegraph.structure.auth.User;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class UserEntity extends AuthElement {
+
+ private static final long serialVersionUID = 3121398441504040737L;
+
+ @JsonProperty("user_name")
+ private String username;
+
+ @JsonProperty("user_password")
+ private String password;
+
+ @JsonProperty("user_phone")
+ private String phone;
+
+ @JsonProperty("user_email")
+ private String email;
+
+ @JsonProperty("user_description")
+ private String description;
+
+ @JsonProperty("user_groups")
+ private List groups;
+
+ @JsonProperty("platform_role")
+ private List platformRoles;
+
+ public static User convertToUser(UserEntity userEntity) {
+ User user = new User();
+ user.name(userEntity.username);
+ user.password(userEntity.password);
+ user.phone(userEntity.phone);
+ user.email(userEntity.email);
+ user.description(userEntity.description);
+ user.id(userEntity.id);
+ return user;
+ }
+
+ public static UserEntity convertFromUser(User user) {
+ UserEntity userEntity = new UserEntity();
+ userEntity.username = user.name();
+ userEntity.password = user.password();
+ userEntity.phone = user.phone();
+ userEntity.email = user.email();
+ userEntity.description = user.description();
+ userEntity.id = user.id().toString();
+ return userEntity;
+ }
+}
diff --git a/hubble-be/src/main/java/com/baidu/hugegraph/filter/AuthFilter.java b/hubble-be/src/main/java/com/baidu/hugegraph/filter/AuthFilter.java
new file mode 100644
index 00000000..ed9526a1
--- /dev/null
+++ b/hubble-be/src/main/java/com/baidu/hugegraph/filter/AuthFilter.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2017 HugeGraph Authors
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.baidu.hugegraph.filter;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Set;
+import java.util.function.Supplier;
+
+import javax.annotation.Resource;
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.annotation.WebFilter;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.core.MediaType;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.http.HttpHeaders;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+import com.baidu.hugegraph.common.Constant;
+import com.baidu.hugegraph.common.Response;
+import com.baidu.hugegraph.config.ClientConfiguration;
+import com.baidu.hugegraph.driver.HugeClient;
+import com.baidu.hugegraph.util.JsonUtil;
+import com.baidu.hugegraph.util.SessionUtil;
+import com.google.common.collect.ImmutableSet;
+
+import lombok.extern.log4j.Log4j2;
+
+@Log4j2
+@WebFilter(filterName = "authFilter", urlPatterns = "/*")
+public class AuthFilter implements Filter {
+
+ private static final Set WHITE_API = ImmutableSet.of(
+ buildPath(RequestMethod.POST,
+ Constant.API_VERSION + "graph-connections/login")
+ );
+
+ @Resource(name = ClientConfiguration.AUTH_CLIENT_NAME)
+ private HugeClient authClient;
+
+ @Override
+ public void doFilter(ServletRequest servletRequest,
+ ServletResponse servletResponse,
+ FilterChain filterChain)
+ throws IOException, ServletException {
+ HttpServletRequest request = (HttpServletRequest) servletRequest;
+ if (isWhiteAPI(request)) {
+ filterChain.doFilter(servletRequest, servletResponse);
+ return;
+ }
+
+ try {
+ String authorization = request.getHeader(HttpHeaders.AUTHORIZATION);
+ // Missed token and request uri not in white list
+ if (StringUtils.isEmpty(authorization)) {
+ String msg = "Missed authorization token";
+ writeResponse(servletResponse, () -> {
+ return Response.builder()
+ .status(Constant.STATUS_BAD_REQUEST)
+ .message(msg)
+ .build();
+ });
+ return;
+ }
+ // Illegal token format
+ if (StringUtils.isNotEmpty(authorization) &&
+ !authorization.startsWith(Constant.BEARER_TOKEN_PREFIX)) {
+ String msg = "Only HTTP Bearer authentication is supported";
+ writeResponse(servletResponse, () -> {
+ return Response.builder()
+ .status(Constant.STATUS_BAD_REQUEST)
+ .message(msg)
+ .build();
+ });
+ return;
+ }
+
+ this.authClient.setAuthContext(authorization);
+
+ filterChain.doFilter(servletRequest, servletResponse);
+ } finally {
+ this.authClient.resetAuthContext();
+ SessionUtil.reset();
+ }
+ }
+
+ private static String buildPath(RequestMethod method, String path) {
+ return buildPath(method.name(), path);
+ }
+
+ private static String buildPath(String method, String path) {
+ return String.join(":", method, path);
+ }
+
+ private static boolean isWhiteAPI(HttpServletRequest request) {
+ String url = request.getRequestURI();
+ return WHITE_API.contains(buildPath(request.getMethod(), url));
+ }
+
+ private void writeResponse(ServletResponse servletResponse,
+ Supplier responseSupplier) {
+ Response response = responseSupplier.get();
+
+ servletResponse.setCharacterEncoding("UTF-8");
+ servletResponse.setContentType(MediaType.APPLICATION_JSON);
+
+ try (PrintWriter writer = servletResponse.getWriter()) {
+ writer.print(JsonUtil.toJson(response));
+ } catch (IOException e) {
+ log.error("Failed to get response writer ",e);
+ }
+ }
+}
diff --git a/hubble-be/src/main/java/com/baidu/hugegraph/handler/ExceptionAdvisor.java b/hubble-be/src/main/java/com/baidu/hugegraph/handler/ExceptionAdvisor.java
index 436d963e..8a942d7d 100644
--- a/hubble-be/src/main/java/com/baidu/hugegraph/handler/ExceptionAdvisor.java
+++ b/hubble-be/src/main/java/com/baidu/hugegraph/handler/ExceptionAdvisor.java
@@ -19,6 +19,8 @@
package com.baidu.hugegraph.handler;
+import javax.ws.rs.NotAuthorizedException;
+
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ExceptionHandler;
@@ -96,6 +98,17 @@ public Response exceptionHandler(IllegalGremlinException e) {
.build();
}
+ @ExceptionHandler(NotAuthorizedException.class)
+ @ResponseStatus(HttpStatus.OK)
+ public Response exceptionHandler(NotAuthorizedException e) {
+ String message = this.handleMessage(e.getMessage(), null);
+ return Response.builder()
+ .status(Constant.STATUS_UNAUTHORIZED)
+ .message(message)
+ .cause(e.getCause())
+ .build();
+ }
+
private String handleMessage(String message, Object[] args) {
String[] strArgs = null;
if (args != null && args.length > 0) {
diff --git a/hubble-be/src/main/java/com/baidu/hugegraph/mapper/UserResourcesMapper.java b/hubble-be/src/main/java/com/baidu/hugegraph/mapper/UserResourcesMapper.java
new file mode 100644
index 00000000..ece6ff60
--- /dev/null
+++ b/hubble-be/src/main/java/com/baidu/hugegraph/mapper/UserResourcesMapper.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2017 HugeGraph Authors
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.baidu.hugegraph.mapper;
+
+import java.util.List;
+
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+import org.springframework.stereotype.Component;
+
+@Mapper
+@Component
+public interface UserResourcesMapper {
+
+ @Select("")
+ List userResourcesList(@Param("roles") List roles);
+}
diff --git a/hubble-be/src/main/java/com/baidu/hugegraph/options/HubbleOptions.java b/hubble-be/src/main/java/com/baidu/hugegraph/options/HubbleOptions.java
index 890834c0..17185a65 100644
--- a/hubble-be/src/main/java/com/baidu/hugegraph/options/HubbleOptions.java
+++ b/hubble-be/src/main/java/com/baidu/hugegraph/options/HubbleOptions.java
@@ -228,4 +228,29 @@ public static synchronized HubbleOptions instance() {
null,
"hugegraph"
);
+
+ public static final ConfigOption AUTH_REMOTE_URL =
+ new ConfigOption<>(
+ "auth.remote_url",
+ "The remote url of auth-server, use this url to create a " +
+ "client to do auth operations.",
+ disallowEmpty(),
+ "http://127.0.0.1:8080"
+ );
+
+ public static final ConfigOption AUTH_GRAPH =
+ new ConfigOption<>(
+ "auth.graph",
+ "The graph name of auth-server.",
+ disallowEmpty(),
+ "hugegraph"
+ );
+
+ public static final ConfigOption ADMIN_PASSWORD =
+ new ConfigOption<>(
+ "auth.admin_password",
+ "The password of admin user in auth-server.",
+ disallowEmpty(),
+ "hugegraph"
+ );
}
diff --git a/hubble-be/src/main/java/com/baidu/hugegraph/service/project/ProjectService.java b/hubble-be/src/main/java/com/baidu/hugegraph/service/project/ProjectService.java
new file mode 100644
index 00000000..a7c39cef
--- /dev/null
+++ b/hubble-be/src/main/java/com/baidu/hugegraph/service/project/ProjectService.java
@@ -0,0 +1,203 @@
+/*
+ * Copyright 2017 HugeGraph Authors
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.baidu.hugegraph.service.project;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import javax.annotation.Resource;
+
+import org.apache.commons.lang.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.baidu.hugegraph.common.Constant;
+import com.baidu.hugegraph.config.ClientConfiguration;
+import com.baidu.hugegraph.driver.HugeClient;
+import com.baidu.hugegraph.entity.project.ProjectEntity;
+import com.baidu.hugegraph.entity.user.UserEntity;
+import com.baidu.hugegraph.service.user.UserService;
+import com.baidu.hugegraph.structure.auth.Belong;
+import com.baidu.hugegraph.structure.auth.Group;
+import com.baidu.hugegraph.structure.auth.HugeGroupTag;
+import com.baidu.hugegraph.structure.auth.Project;
+import com.baidu.hugegraph.util.PageUtil;
+import com.baidu.hugegraph.util.SessionUtil;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.google.common.collect.Lists;
+
+@Service
+public class ProjectService {
+
+ @Resource(name = ClientConfiguration.AUTH_CLIENT_NAME)
+ private HugeClient authClient;
+
+ @Resource(name = ClientConfiguration.ADMIN_CLIENT_NAME)
+ private HugeClient adminClient;
+
+ @Autowired
+ private UserService userService;
+
+ public ProjectEntity createProject(ProjectEntity entity) {
+ Project project = ProjectEntity.convertToProject(entity);
+ project = this.authClient.auth().createProject(project);
+
+ createUserBelong(entity.getAdminUsers(), project.adminGroup());
+ createUserBelong(entity.getOpUsers(), project.opGroup());
+
+ entity.setId(project.id().toString());
+ return entity;
+ }
+
+ public ProjectEntity updateProject(ProjectEntity entity) {
+ Project current = this.authClient.auth().getProject(entity.getId());
+
+ this.updateUserBelong(entity.getAdminUsers(), current.adminGroup());
+ this.updateUserBelong(entity.getOpUsers(), current.opGroup());
+
+ Project project = ProjectEntity.convertToProject(entity);
+ this.authClient.auth().updateProject(project);
+
+ return entity;
+ }
+
+ public void deleteProject(String projectId) {
+ this.authClient.auth().deleteProject(projectId);
+ }
+
+ public IPage list(String projectName, int pageNo,
+ int pageSize) {
+ List projects = this.adminClient.auth().listProjects();
+
+ if (StringUtils.isNotEmpty(projectName)) {
+ projects = projects.stream()
+ .filter(project -> {
+ return project.name().contains(projectName);
+ })
+ .collect(Collectors.toList());
+ }
+
+ List entities = projects.stream()
+ .map(this::projectToEntity)
+ .collect(Collectors.toList());
+ UserEntity currentUser = SessionUtil.currentUser();
+ List groups = this.userService
+ .listGroupByUser(currentUser.getId());
+ Set tags = groups.stream()
+ .map(Group::tag)
+ .filter(Objects::nonNull)
+ .collect(Collectors.toSet());
+
+ if (!tags.contains(HugeGroupTag.SUPER_ADMIN) &&
+ !"admin".equals(currentUser.getUsername())) {
+ entities = entities.stream().filter(entity -> {
+ boolean adminHasCurrentUser =
+ entity.getAdminUsers()
+ .stream()
+ .anyMatch(user -> {
+ return user.equals(currentUser.getId());
+ });
+ boolean opHasCurrentUser =
+ entity.getOpUsers()
+ .stream()
+ .anyMatch(user -> {
+ return user.equals(currentUser.getId());
+ });
+ return adminHasCurrentUser || opHasCurrentUser;
+ }).collect(Collectors.toList());
+ }
+
+ return PageUtil.page(entities, pageNo, pageSize);
+ }
+
+ private void createUserBelong(List userIds, String groupId) {
+ List belongs = userIds.stream()
+ .map(user -> {
+ Belong belong = new Belong();
+ belong.user(user);
+ belong.group(groupId);
+ return belong;
+ })
+ .collect(Collectors.toList());
+ for (Belong belong : belongs) {
+ this.authClient.auth().createBelong(belong);
+ }
+ }
+
+ private void updateUserBelong(List userIds, String groupId) {
+ List belongs = this.adminClient.auth()
+ .listBelongsByGroup(groupId,
+ Constant.NO_LIMIT);
+
+ Map map =
+ belongs.stream()
+ .collect(Collectors.toMap(belong -> {
+ return (String) belong.user();
+ }, belong -> {
+ return (String) belong.id();
+ }));
+ Set currentUsers = map.keySet();
+
+ List needCreateUsers = Lists.newArrayList(currentUsers);
+ needCreateUsers.removeAll(userIds);
+
+ List needRemoveUsers = Lists.newArrayList(userIds);
+ needRemoveUsers.removeAll(currentUsers);
+
+ this.createUserBelong(needCreateUsers, groupId);
+ needRemoveUsers.stream()
+ .map(map::get)
+ .forEach(belong -> {
+ this.authClient.auth().deleteBelong(belong);
+ });
+ }
+
+ private ProjectEntity projectToEntity(Project project) {
+ ProjectEntity entity = new ProjectEntity();
+ entity.setId(project.id().toString());
+ entity.setDescription(project.description());
+ entity.setCreate(project.createTime());
+ entity.setCreator(project.creator());
+ List adminUsers = this.adminClient
+ .auth()
+ .listBelongsByGroup(
+ project.adminGroup(),
+ Constant.NO_LIMIT)
+ .stream()
+ .map(belong -> (String) belong.user())
+ .collect(Collectors.toList());
+ entity.setAdminUsers(adminUsers);
+ List opUsers = this.adminClient
+ .auth()
+ .listBelongsByGroup(
+ project.opGroup(),
+ Constant.NO_LIMIT)
+ .stream()
+ .map(belong -> {
+ return (String) belong.user();
+ })
+ .collect(Collectors.toList());
+ entity.setOpUsers(opUsers);
+ return entity;
+ }
+}
diff --git a/hubble-be/src/main/java/com/baidu/hugegraph/service/system/AuthService.java b/hubble-be/src/main/java/com/baidu/hugegraph/service/system/AuthService.java
new file mode 100644
index 00000000..75f23960
--- /dev/null
+++ b/hubble-be/src/main/java/com/baidu/hugegraph/service/system/AuthService.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2017 HugeGraph Authors
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.baidu.hugegraph.service.system;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+import javax.annotation.Resource;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.baidu.hugegraph.common.Constant;
+import com.baidu.hugegraph.config.ClientConfiguration;
+import com.baidu.hugegraph.driver.HugeClient;
+import com.baidu.hugegraph.entity.login.LoginBody;
+import com.baidu.hugegraph.entity.login.LoginResult;
+import com.baidu.hugegraph.entity.user.UserEntity;
+import com.baidu.hugegraph.mapper.UserResourcesMapper;
+import com.baidu.hugegraph.service.user.UserService;
+import com.baidu.hugegraph.structure.auth.Group;
+import com.baidu.hugegraph.structure.auth.Login;
+import com.baidu.hugegraph.structure.auth.TokenPayload;
+import com.baidu.hugegraph.util.SessionUtil;
+
+@Service
+public class AuthService {
+
+ @Resource(name = ClientConfiguration.AUTH_CLIENT_NAME)
+ private HugeClient authClient;
+ @Autowired
+ private UserService userService;
+ @Autowired
+ private UserResourcesMapper userResourcesMapper;
+
+ public LoginResult login(LoginBody loginEntity) {
+ Login login = new Login();
+ login.name(loginEntity.getName());
+ login.password(loginEntity.getPassword());
+
+ String token = this.authClient.auth().login(login).token();
+
+ List allowedMenus = null;
+ try {
+ this.authClient.setAuthContext(Constant.BEARER_TOKEN_PREFIX + token);
+ TokenPayload payload = this.authClient.auth().verifyToken();
+
+ List groups = this.userService.listGroupByUser(payload.userId());
+ List roleTypes = groups.stream()
+ .filter(group -> group.tag() != null)
+ .map(group -> (int) group.tag().code())
+ .distinct()
+ .collect(Collectors.toList());
+ if (CollectionUtils.isNotEmpty(roleTypes)) {
+ allowedMenus = userResourcesMapper.userResourcesList(roleTypes);
+ }
+ } finally {
+ this.authClient.resetAuthContext();
+ }
+
+ return LoginResult.builder()
+ .token(token)
+ .allowedMenus(allowedMenus)
+ .build();
+ }
+
+ public void logout() {
+ this.authClient.auth().logout();
+ }
+
+ public UserEntity getCurrentUser() {
+ return SessionUtil.currentUser();
+ }
+}
diff --git a/hubble-be/src/main/java/com/baidu/hugegraph/service/user/UserService.java b/hubble-be/src/main/java/com/baidu/hugegraph/service/user/UserService.java
new file mode 100644
index 00000000..d8945bbd
--- /dev/null
+++ b/hubble-be/src/main/java/com/baidu/hugegraph/service/user/UserService.java
@@ -0,0 +1,204 @@
+/*
+ * Copyright 2017 HugeGraph Authors
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.baidu.hugegraph.service.user;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import javax.annotation.Resource;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Service;
+
+import com.baidu.hugegraph.common.Constant;
+import com.baidu.hugegraph.config.ClientConfiguration;
+import com.baidu.hugegraph.driver.HugeClient;
+import com.baidu.hugegraph.entity.user.UserEntity;
+import com.baidu.hugegraph.structure.auth.Belong;
+import com.baidu.hugegraph.structure.auth.Group;
+import com.baidu.hugegraph.structure.auth.HugeGroupTag;
+import com.baidu.hugegraph.structure.auth.User;
+import com.baidu.hugegraph.structure.schema.VertexLabel;
+import com.baidu.hugegraph.util.E;
+import com.baidu.hugegraph.util.PageUtil;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.google.common.collect.Lists;
+
+@Service
+public class UserService {
+
+ @Resource(name = ClientConfiguration.AUTH_CLIENT_NAME)
+ private HugeClient authClient;
+ @Resource(name = ClientConfiguration.ADMIN_CLIENT_NAME)
+ private HugeClient adminClient;
+
+ public UserEntity createUser(UserEntity userEntity) {
+ User user = UserEntity.convertToUser(userEntity);
+ user = this.authClient.auth().createUser(user);
+
+ try {
+ List platformRoles = userEntity.getPlatformRoles();
+ if (CollectionUtils.isNotEmpty(platformRoles)) {
+ for (HugeGroupTag tag : platformRoles) {
+ E.checkArgument(HugeGroupTag.SUPER_ADMIN.equals(tag) ||
+ HugeGroupTag.OP_SUPER_ADMIN.equals(tag),
+ "The parameter platformRoles must " +
+ "be in (%s, %s)",
+ HugeGroupTag.SUPER_ADMIN,
+ HugeGroupTag.OP_SUPER_ADMIN);
+
+ Belong belong = new Belong();
+ belong.user(user);
+ belong.group(groupByName(tag.name()));
+ this.authClient.auth().createBelong(belong);
+ }
+ }
+ } catch (Exception e) {
+ this.authClient.auth().deleteUser(user.id());
+ throw e;
+ }
+
+ userEntity.setId(user.id().toString());
+ return userEntity;
+ }
+
+ public UserEntity updateUser(UserEntity userEntity) {
+ User user = UserEntity.convertToUser(userEntity);
+ user = this.authClient.auth().updateUser(user);
+
+ List platformRoles = userEntity.getPlatformRoles();
+ platformRoles = platformRoles == null ? new ArrayList<>() :
+ platformRoles;
+
+ List groups = this.listGroupByUser(user.id().toString());
+ List userAdminTags =
+ groups.stream()
+ .map(Group::tag)
+ .filter(tag -> {
+ return HugeGroupTag.SUPER_ADMIN.equals(tag) ||
+ HugeGroupTag.OP_SUPER_ADMIN.equals(tag);
+ })
+ .collect(Collectors.toList());
+
+ List needCreateBelongTags =
+ new ArrayList<>(platformRoles);
+ needCreateBelongTags.removeAll(userAdminTags);
+ List needRemoveBelongTags =
+ new ArrayList<>(userAdminTags);
+ needRemoveBelongTags.removeAll(platformRoles);
+
+ for (HugeGroupTag tag : needCreateBelongTags) {
+ Belong belong = new Belong();
+ belong.group(groupByName(tag.name()));
+ belong.user(user);
+ this.authClient.auth().createBelong(belong);
+ }
+
+ Map