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.hugegraph hugegraph-common - 1.8.8 + 1.8.9 org.apache.logging.log4j @@ -111,8 +111,17 @@ org.apache.logging.log4j log4j-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 map = this.authClient + .auth() + .listBelongsByUser(user, + Constant.NO_LIMIT) + .stream() + .collect(Collectors.toMap(Belong::group, + Belong::id)); + Set needRemoveTagSet = + new HashSet<>(needRemoveBelongTags); + + List needRemoveBelongs = + needRemoveTagSet.stream() + .map(tag -> { + String groupId = + this.groupIdByName(tag.name()); + return map.get(groupId); + }) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + + for (Object belongId : needRemoveBelongs) { + this.authClient.auth().deleteBelong(belongId); + } + + return userEntity; + } + + public void deleteUser(List userIds) { + // TODO batch delete? + for (String userId : userIds) { + this.authClient.auth().deleteUser(userId); + } + } + + public IPage list(String userName, int pageNo, int pageSize) { + List users = this.authClient.auth().listUsers(Constant.NO_LIMIT); + if (StringUtils.isNotEmpty(userName)) { + users = users.stream() + .filter(user -> user.name().contains(userName)) + .collect(Collectors.toList()); + } + + IPage page = PageUtil.page(users, pageNo, pageSize); + List userEntities = page.getRecords() + .stream() + .map(UserEntity::convertFromUser) + .collect(Collectors.toList()); + // TODO batch query? + for (UserEntity user : userEntities) { + List groups = this.listGroupByUser(user.getId()); + user.setGroups(groups); + } + + Page result = new Page<>(page.getCurrent(), page.getSize(), + page.getTotal(), true); + result.setRecords(userEntities); + result.setPages(page.getPages()); + return result; + } + + public List listGroupByUser(String userId) { + List belongs = this.adminClient.auth().listBelongsByUser( + userId, + Constant.NO_LIMIT); + List groups = null; + if (CollectionUtils.isNotEmpty(belongs)) { + List groupIds = belongs.stream().map(Belong::group) + .collect(Collectors.toList()); + groups = this.adminClient.auth().listGroups(groupIds); + } + + return groups == null ? Lists.newArrayList() : groups; + } + + private String groupIdByName(String name) { + VertexLabel groupLabel = this.authClient.schema() + .getVertexLabel(Group.label()); + return StringUtils.join(groupLabel.id(), ":", name); + } + + private Group groupByName(String name) { + return this.authClient.auth().getGroup(this.groupIdByName(name)); + } +} diff --git a/hubble-be/src/main/java/com/baidu/hugegraph/util/ServletUtils.java b/hubble-be/src/main/java/com/baidu/hugegraph/util/ServletUtils.java new file mode 100644 index 00000000..023c8c52 --- /dev/null +++ b/hubble-be/src/main/java/com/baidu/hugegraph/util/ServletUtils.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.util; + +import javax.servlet.http.HttpServletRequest; + +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +public class ServletUtils { + + public static String getHeader(String header) { + return getRequest().getHeader(header); + } + + public static HttpServletRequest getRequest() { + return getRequestAttributes().getRequest(); + } + + public static ServletRequestAttributes getRequestAttributes() { + RequestAttributes attributes = RequestContextHolder.getRequestAttributes(); + return (ServletRequestAttributes) attributes; + } +} diff --git a/hubble-be/src/main/java/com/baidu/hugegraph/util/SessionUtil.java b/hubble-be/src/main/java/com/baidu/hugegraph/util/SessionUtil.java new file mode 100644 index 00000000..a16bd5b6 --- /dev/null +++ b/hubble-be/src/main/java/com/baidu/hugegraph/util/SessionUtil.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.util; + +import com.baidu.hugegraph.driver.HugeClient; +import com.baidu.hugegraph.entity.user.UserEntity; +import com.baidu.hugegraph.structure.auth.TokenPayload; +import com.baidu.hugegraph.structure.auth.User; + +public class SessionUtil { + + public static HugeClient authClient; + public static HugeClient adminClient; + private static final ThreadLocal userLocal = + new ThreadLocal<>(); + + public static UserEntity currentUser() { + if (userLocal.get() != null) { + return userLocal.get(); + } + TokenPayload payload = authClient.auth().verifyToken(); + User user = authClient.auth().getUser(payload.userId()); + + UserEntity userEntity = UserEntity.convertFromUser(user); + userLocal.set(userEntity); + return userEntity; + } + + public static void reset() { + userLocal.remove(); + } +} diff --git a/hubble-be/src/main/resources/database/data.sql b/hubble-be/src/main/resources/database/data.sql index 02129e09..559f29cf 100644 --- a/hubble-be/src/main/resources/database/data.sql +++ b/hubble-be/src/main/resources/database/data.sql @@ -4,3 +4,10 @@ SELECT 1; -- INSERT INTO `gremlin_collection`(name, content, create_time) VALUES ('first_gremlin', 'g.V().limit(10)', sysdate); -- INSERT INTO `execute_history`(execute_type, content, execute_status, duration, create_time) VALUES (0, 'g.V().limit(100)', 0, 20, sysdate); + +DELETE FROM `resources`; +DELETE FROM `resources_role_rel`; + +INSERT INTO `resources` (`id`, `path`, `type`) VALUES (1, '/test', 1); + +INSERT INTO `resources_role_rel` (`resources_id`, `role_type`) VALUES (1, 1); diff --git a/hubble-be/src/main/resources/database/schema.sql b/hubble-be/src/main/resources/database/schema.sql index cc03c3e7..d0bfbee5 100644 --- a/hubble-be/src/main/resources/database/schema.sql +++ b/hubble-be/src/main/resources/database/schema.sql @@ -117,3 +117,17 @@ CREATE TABLE IF NOT EXISTS `async_task` ( CREATE INDEX IF NOT EXISTS `load_task_conn_id` ON `load_task`(`conn_id`); CREATE INDEX IF NOT EXISTS `load_task_file_id` ON `load_task`(`file_id`); + +CREATE TABLE IF NOT EXISTS `resources` ( + `id` INT NOT NULL AUTO_INCREMENT, + `path` VARCHAR(100) NOT NULL DEFAULT '', + `type` TINYINT NOT NULL DEFAULT -1, + PRIMARY KEY (`id`) +); + +CREATE TABLE IF NOT EXISTS `resources_role_rel` ( + `id` INT NOT NULL AUTO_INCREMENT, + `resources_id` INT NOT NULL DEFAULT -1, + `role_type` INT NOT NULL DEFAULT -1, + PRIMARY KEY (`id`) +); diff --git a/hubble-be/src/main/resources/hugegraph-hubble.properties b/hubble-be/src/main/resources/hugegraph-hubble.properties index 1da61f6b..b2a5f155 100644 --- a/hubble-be/src/main/resources/hugegraph-hubble.properties +++ b/hubble-be/src/main/resources/hugegraph-hubble.properties @@ -12,3 +12,7 @@ gremlin.batch_query_ids=100 server.protocol=http #ssl.client_truststore_file= #ssl.client_truststore_password= + +auth.remote_url=http://127.0.0.1:8080 +auth.graph=hugegraph +auth.admin_password=pa