From 161f9320a32ba421bc34d2bbcf6e4dfe1b35f1fa Mon Sep 17 00:00:00 2001 From: guoshoujing Date: Tue, 15 Jun 2021 19:33:59 +0800 Subject: [PATCH 1/7] add login module --- hubble-be/pom.xml | 11 ++- .../com/baidu/hugegraph/HugeGraphHubble.java | 2 + .../config/AuthClientConfiguration.java | 42 ++++++++++++ .../controller/system/LoginController.java | 67 +++++++++++++++++++ .../hugegraph/entity/login/LoginBody.java | 40 +++++++++++ .../hugegraph/entity/login/LoginResult.java | 37 ++++++++++ .../hugegraph/entity/user/AuthElement.java | 49 ++++++++++++++ .../baidu/hugegraph/entity/user/Group.java | 42 ++++++++++++ .../hugegraph/entity/user/HubbleUser.java | 53 +++++++++++++++ .../baidu/hugegraph/filter/AuthFilter.java | 65 ++++++++++++++++++ .../hugegraph/options/HubbleOptions.java | 18 +++++ .../service/system/LoginService.java | 52 ++++++++++++++ .../service/system/TokenService.java | 55 +++++++++++++++ .../baidu/hugegraph/util/ServletUtils.java | 42 ++++++++++++ .../resources/hugegraph-hubble.properties | 3 + 15 files changed, 577 insertions(+), 1 deletion(-) create mode 100644 hubble-be/src/main/java/com/baidu/hugegraph/config/AuthClientConfiguration.java create mode 100644 hubble-be/src/main/java/com/baidu/hugegraph/controller/system/LoginController.java create mode 100644 hubble-be/src/main/java/com/baidu/hugegraph/entity/login/LoginBody.java create mode 100644 hubble-be/src/main/java/com/baidu/hugegraph/entity/login/LoginResult.java create mode 100644 hubble-be/src/main/java/com/baidu/hugegraph/entity/user/AuthElement.java create mode 100644 hubble-be/src/main/java/com/baidu/hugegraph/entity/user/Group.java create mode 100644 hubble-be/src/main/java/com/baidu/hugegraph/entity/user/HubbleUser.java create mode 100644 hubble-be/src/main/java/com/baidu/hugegraph/filter/AuthFilter.java create mode 100644 hubble-be/src/main/java/com/baidu/hugegraph/service/system/LoginService.java create mode 100644 hubble-be/src/main/java/com/baidu/hugegraph/service/system/TokenService.java create mode 100644 hubble-be/src/main/java/com/baidu/hugegraph/util/ServletUtils.java diff --git a/hubble-be/pom.xml b/hubble-be/pom.xml index 0cbd63c5..5e815cb6 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.4 + 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/config/AuthClientConfiguration.java b/hubble-be/src/main/java/com/baidu/hugegraph/config/AuthClientConfiguration.java new file mode 100644 index 00000000..b01469fd --- /dev/null +++ b/hubble-be/src/main/java/com/baidu/hugegraph/config/AuthClientConfiguration.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.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import com.baidu.hugegraph.driver.HugeClient; +import com.baidu.hugegraph.options.HubbleOptions; + +import lombok.extern.log4j.Log4j2; + +@Log4j2 +@Configuration +public class AuthClientConfiguration { + + public static final String AUTH_CLIENT_NAME = "authClient"; + + @Bean(AUTH_CLIENT_NAME) + public HugeClient authClient(HugeConfig config) { + String authUrl = config.get(HubbleOptions.AUTH_REMOTE_URL); + String authGraph = config.get(HubbleOptions.AUTH_GRAPH_STORE); + return HugeClient.builder(authUrl, authGraph).build(); + } +} 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..26004e45 --- /dev/null +++ b/hubble-be/src/main/java/com/baidu/hugegraph/controller/system/LoginController.java @@ -0,0 +1,67 @@ +/* + * 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.HubbleUser; +import com.baidu.hugegraph.service.system.LoginService; +import com.baidu.hugegraph.service.system.TokenService; +import com.baidu.hugegraph.util.E; + +@RestController +@RequestMapping(Constant.API_VERSION + "graph-connections/login") +public class LoginController extends BaseController { + + @Autowired + private LoginService loginService; + @Autowired + private TokenService tokenService; + + @PostMapping + public LoginResult login(@RequestBody LoginBody loginBody) { + return this.loginService.login(loginBody); + } + + @DeleteMapping + public void logout() { + this.loginService.logout(); + } + + @GetMapping("/user") + public HubbleUser currentUser(@RequestHeader(HttpHeaders.AUTHORIZATION) + String token) { + E.checkArgumentNotNull(token, + "Request header Authorization must not be null"); + return this.tokenService.getUser(); + } +} 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..e0985ddb --- /dev/null +++ b/hubble-be/src/main/java/com/baidu/hugegraph/entity/login/LoginResult.java @@ -0,0 +1,37 @@ +/* + * 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 LoginResult { + + @JsonProperty("token") + private String token; +} 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/Group.java b/hubble-be/src/main/java/com/baidu/hugegraph/entity/user/Group.java new file mode 100644 index 00000000..4035490f --- /dev/null +++ b/hubble-be/src/main/java/com/baidu/hugegraph/entity/user/Group.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.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 Group extends AuthElement { + + private static final long serialVersionUID = 3848451889435904990L; + + @JsonProperty("group_name") + private String name; + + @JsonProperty("group_description") + private String description; +} diff --git a/hubble-be/src/main/java/com/baidu/hugegraph/entity/user/HubbleUser.java b/hubble-be/src/main/java/com/baidu/hugegraph/entity/user/HubbleUser.java new file mode 100644 index 00000000..73dec1cd --- /dev/null +++ b/hubble-be/src/main/java/com/baidu/hugegraph/entity/user/HubbleUser.java @@ -0,0 +1,53 @@ +/* + * 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.fasterxml.jackson.annotation.JsonProperty; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class HubbleUser 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_groups") + private List groups; +} 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..b7a89dbb --- /dev/null +++ b/hubble-be/src/main/java/com/baidu/hugegraph/filter/AuthFilter.java @@ -0,0 +1,65 @@ +/* + * 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 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 org.apache.commons.lang.StringUtils; +import org.apache.http.HttpHeaders; + +import com.baidu.hugegraph.driver.HugeClient; +import com.baidu.hugegraph.config.AuthClientConfiguration; + +import lombok.extern.log4j.Log4j2; + +@Log4j2 +@WebFilter(filterName = "authFilter", urlPatterns = "/*") +public class AuthFilter implements Filter { + + @Resource(name = AuthClientConfiguration.AUTH_CLIENT_NAME) + private HugeClient client; + + @Override + public void doFilter(ServletRequest servletRequest, + ServletResponse servletResponse, + FilterChain filterChain) + throws IOException, ServletException { + try { + String authorization = ((HttpServletRequest) servletRequest) + .getHeader(HttpHeaders.AUTHORIZATION); + if (StringUtils.isNotEmpty(authorization)) { + this.client.setAuthContext(authorization); + } + + filterChain.doFilter(servletRequest, servletResponse); + } finally { + this.client.resetAuthContext(); + } + } +} 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..9df51cb1 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,22 @@ public static synchronized HubbleOptions instance() { null, "hugegraph" ); + + public static final ConfigOption AUTH_REMOTE_URL = + new ConfigOption<>( + "auth.remote_url", + "The name of graph used to store authentication " + + "information, like users, only for " + + "com.baidu.hugegraph.auth.StandardAuthenticator.", + disallowEmpty(), + "localhost" + ); + + public static final ConfigOption AUTH_GRAPH_STORE = + new ConfigOption<>( + "auth.graph_store", + "The graph name of auth-server.", + disallowEmpty(), + "hugegraph" + ); } diff --git a/hubble-be/src/main/java/com/baidu/hugegraph/service/system/LoginService.java b/hubble-be/src/main/java/com/baidu/hugegraph/service/system/LoginService.java new file mode 100644 index 00000000..08a024d9 --- /dev/null +++ b/hubble-be/src/main/java/com/baidu/hugegraph/service/system/LoginService.java @@ -0,0 +1,52 @@ +/* + * 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 javax.annotation.Resource; + +import org.springframework.stereotype.Service; + +import com.baidu.hugegraph.driver.HugeClient; +import com.baidu.hugegraph.entity.login.LoginBody; +import com.baidu.hugegraph.config.AuthClientConfiguration; +import com.baidu.hugegraph.entity.login.LoginResult; +import com.baidu.hugegraph.structure.auth.Login; + +@Service +public class LoginService { + + @Resource(name = AuthClientConfiguration.AUTH_CLIENT_NAME) + private HugeClient authClient; + + 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(); + return LoginResult.builder() + .token(token) + .build(); + } + + public void logout() { + this.authClient.auth().logout(); + } +} diff --git a/hubble-be/src/main/java/com/baidu/hugegraph/service/system/TokenService.java b/hubble-be/src/main/java/com/baidu/hugegraph/service/system/TokenService.java new file mode 100644 index 00000000..4970096d --- /dev/null +++ b/hubble-be/src/main/java/com/baidu/hugegraph/service/system/TokenService.java @@ -0,0 +1,55 @@ +/* + * 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.Map; + +import javax.annotation.Resource; + +import org.springframework.stereotype.Service; + +import com.baidu.hugegraph.driver.HugeClient; +import com.baidu.hugegraph.entity.user.HubbleUser; +import com.baidu.hugegraph.config.AuthClientConfiguration; +import com.baidu.hugegraph.structure.auth.User; + +@Service +public class TokenService { + + private static final String USER_NAME = "user_name"; + private static final String USER_ID = "user_id"; + + @Resource(name = AuthClientConfiguration.AUTH_CLIENT_NAME) + private HugeClient authClient; + + public HubbleUser getUser() { + Map payload = this.authClient.auth().verifyToken(); + String userId = (String) payload.get(USER_ID); + User user = this.authClient.auth().getUser(userId); + + // TODO Set user auth info + return HubbleUser.builder() + .username(user.name()) + .password(user.password()) + .phone(user.phone()) + .email(user.email()) + .build(); + } +} 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/resources/hugegraph-hubble.properties b/hubble-be/src/main/resources/hugegraph-hubble.properties index 1da61f6b..0020a28c 100644 --- a/hubble-be/src/main/resources/hugegraph-hubble.properties +++ b/hubble-be/src/main/resources/hugegraph-hubble.properties @@ -12,3 +12,6 @@ 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_store=hugegraph \ No newline at end of file From 06df54a3e82b08b61f6dc6807fede96d92123b46 Mon Sep 17 00:00:00 2001 From: guoshoujing Date: Wed, 16 Jun 2021 11:25:06 +0800 Subject: [PATCH 2/7] add token verify exception advisor --- .../baidu/hugegraph/handler/ExceptionAdvisor.java | 13 +++++++++++++ .../com/baidu/hugegraph/options/HubbleOptions.java | 9 ++++----- .../src/main/resources/hugegraph-hubble.properties | 2 +- 3 files changed, 18 insertions(+), 6 deletions(-) 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/options/HubbleOptions.java b/hubble-be/src/main/java/com/baidu/hugegraph/options/HubbleOptions.java index 9df51cb1..8a88ab0d 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 @@ -232,16 +232,15 @@ public static synchronized HubbleOptions instance() { public static final ConfigOption AUTH_REMOTE_URL = new ConfigOption<>( "auth.remote_url", - "The name of graph used to store authentication " + - "information, like users, only for " + - "com.baidu.hugegraph.auth.StandardAuthenticator.", + "The remote url of auth-server, use this url to create a " + + "client to do auth operations.", disallowEmpty(), - "localhost" + "http://127.0.0.1:8080" ); public static final ConfigOption AUTH_GRAPH_STORE = new ConfigOption<>( - "auth.graph_store", + "auth.graph", "The graph name of auth-server.", disallowEmpty(), "hugegraph" diff --git a/hubble-be/src/main/resources/hugegraph-hubble.properties b/hubble-be/src/main/resources/hugegraph-hubble.properties index 0020a28c..d6ad7106 100644 --- a/hubble-be/src/main/resources/hugegraph-hubble.properties +++ b/hubble-be/src/main/resources/hugegraph-hubble.properties @@ -14,4 +14,4 @@ server.protocol=http #ssl.client_truststore_password= auth.remote_url=http://127.0.0.1:8080 -auth.graph_store=hugegraph \ No newline at end of file +auth.graph=hugegraph From 85e06a98465a00e131dbdeadce2afdc00f01af8e Mon Sep 17 00:00:00 2001 From: guoshoujing Date: Wed, 16 Jun 2021 17:20:23 +0800 Subject: [PATCH 3/7] improve code --- .../config/AuthClientConfiguration.java | 2 +- .../controller/system/LoginController.java | 13 ++--- .../hugegraph/entity/user/HubbleUser.java | 3 + .../hugegraph/options/HubbleOptions.java | 2 +- .../{LoginService.java => AuthService.java} | 26 ++++++++- .../service/system/TokenService.java | 55 ------------------- 6 files changed, 34 insertions(+), 67 deletions(-) rename hubble-be/src/main/java/com/baidu/hugegraph/service/system/{LoginService.java => AuthService.java} (67%) delete mode 100644 hubble-be/src/main/java/com/baidu/hugegraph/service/system/TokenService.java diff --git a/hubble-be/src/main/java/com/baidu/hugegraph/config/AuthClientConfiguration.java b/hubble-be/src/main/java/com/baidu/hugegraph/config/AuthClientConfiguration.java index b01469fd..b0e3e060 100644 --- a/hubble-be/src/main/java/com/baidu/hugegraph/config/AuthClientConfiguration.java +++ b/hubble-be/src/main/java/com/baidu/hugegraph/config/AuthClientConfiguration.java @@ -36,7 +36,7 @@ public class AuthClientConfiguration { @Bean(AUTH_CLIENT_NAME) public HugeClient authClient(HugeConfig config) { String authUrl = config.get(HubbleOptions.AUTH_REMOTE_URL); - String authGraph = config.get(HubbleOptions.AUTH_GRAPH_STORE); + String authGraph = config.get(HubbleOptions.AUTH_GRAPH); return HugeClient.builder(authUrl, authGraph).build(); } } 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 index 26004e45..8c61a727 100644 --- 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 @@ -34,8 +34,7 @@ import com.baidu.hugegraph.entity.login.LoginBody; import com.baidu.hugegraph.entity.login.LoginResult; import com.baidu.hugegraph.entity.user.HubbleUser; -import com.baidu.hugegraph.service.system.LoginService; -import com.baidu.hugegraph.service.system.TokenService; +import com.baidu.hugegraph.service.system.AuthService; import com.baidu.hugegraph.util.E; @RestController @@ -43,18 +42,16 @@ public class LoginController extends BaseController { @Autowired - private LoginService loginService; - @Autowired - private TokenService tokenService; + private AuthService authService; @PostMapping public LoginResult login(@RequestBody LoginBody loginBody) { - return this.loginService.login(loginBody); + return this.authService.login(loginBody); } @DeleteMapping public void logout() { - this.loginService.logout(); + this.authService.logout(); } @GetMapping("/user") @@ -62,6 +59,6 @@ public HubbleUser currentUser(@RequestHeader(HttpHeaders.AUTHORIZATION) String token) { E.checkArgumentNotNull(token, "Request header Authorization must not be null"); - return this.tokenService.getUser(); + return this.authService.getCurrentUser(); } } diff --git a/hubble-be/src/main/java/com/baidu/hugegraph/entity/user/HubbleUser.java b/hubble-be/src/main/java/com/baidu/hugegraph/entity/user/HubbleUser.java index 73dec1cd..65f6f8eb 100644 --- a/hubble-be/src/main/java/com/baidu/hugegraph/entity/user/HubbleUser.java +++ b/hubble-be/src/main/java/com/baidu/hugegraph/entity/user/HubbleUser.java @@ -48,6 +48,9 @@ public class HubbleUser extends AuthElement { @JsonProperty("user_email") private String email; + @JsonProperty("user_description") + private String description; + @JsonProperty("user_groups") private List groups; } 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 8a88ab0d..914d5d77 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 @@ -238,7 +238,7 @@ public static synchronized HubbleOptions instance() { "http://127.0.0.1:8080" ); - public static final ConfigOption AUTH_GRAPH_STORE = + public static final ConfigOption AUTH_GRAPH = new ConfigOption<>( "auth.graph", "The graph name of auth-server.", diff --git a/hubble-be/src/main/java/com/baidu/hugegraph/service/system/LoginService.java b/hubble-be/src/main/java/com/baidu/hugegraph/service/system/AuthService.java similarity index 67% rename from hubble-be/src/main/java/com/baidu/hugegraph/service/system/LoginService.java rename to hubble-be/src/main/java/com/baidu/hugegraph/service/system/AuthService.java index 08a024d9..b1c1a4c8 100644 --- a/hubble-be/src/main/java/com/baidu/hugegraph/service/system/LoginService.java +++ b/hubble-be/src/main/java/com/baidu/hugegraph/service/system/AuthService.java @@ -19,18 +19,25 @@ package com.baidu.hugegraph.service.system; +import java.util.Map; + import javax.annotation.Resource; import org.springframework.stereotype.Service; +import com.baidu.hugegraph.config.AuthClientConfiguration; import com.baidu.hugegraph.driver.HugeClient; import com.baidu.hugegraph.entity.login.LoginBody; -import com.baidu.hugegraph.config.AuthClientConfiguration; import com.baidu.hugegraph.entity.login.LoginResult; +import com.baidu.hugegraph.entity.user.HubbleUser; import com.baidu.hugegraph.structure.auth.Login; +import com.baidu.hugegraph.structure.auth.User; @Service -public class LoginService { +public class AuthService { + + private static final String TOKEN_USER_NAME = "user_name"; + private static final String TOKEN_USER_ID = "user_id"; @Resource(name = AuthClientConfiguration.AUTH_CLIENT_NAME) private HugeClient authClient; @@ -49,4 +56,19 @@ public LoginResult login(LoginBody loginEntity) { public void logout() { this.authClient.auth().logout(); } + + public HubbleUser getCurrentUser() { + Map payload = this.authClient.auth().verifyToken(); + String userId = (String) payload.get(TOKEN_USER_ID); + User user = this.authClient.auth().getUser(userId); + + // TODO Set user auth info + return HubbleUser.builder() + .username(user.name()) + .password(user.password()) + .phone(user.phone()) + .email(user.email()) + .description(user.description()) + .build(); + } } diff --git a/hubble-be/src/main/java/com/baidu/hugegraph/service/system/TokenService.java b/hubble-be/src/main/java/com/baidu/hugegraph/service/system/TokenService.java deleted file mode 100644 index 4970096d..00000000 --- a/hubble-be/src/main/java/com/baidu/hugegraph/service/system/TokenService.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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.Map; - -import javax.annotation.Resource; - -import org.springframework.stereotype.Service; - -import com.baidu.hugegraph.driver.HugeClient; -import com.baidu.hugegraph.entity.user.HubbleUser; -import com.baidu.hugegraph.config.AuthClientConfiguration; -import com.baidu.hugegraph.structure.auth.User; - -@Service -public class TokenService { - - private static final String USER_NAME = "user_name"; - private static final String USER_ID = "user_id"; - - @Resource(name = AuthClientConfiguration.AUTH_CLIENT_NAME) - private HugeClient authClient; - - public HubbleUser getUser() { - Map payload = this.authClient.auth().verifyToken(); - String userId = (String) payload.get(USER_ID); - User user = this.authClient.auth().getUser(userId); - - // TODO Set user auth info - return HubbleUser.builder() - .username(user.name()) - .password(user.password()) - .phone(user.phone()) - .email(user.email()) - .build(); - } -} From 3d7d6ac695cf3c635c889452e93a72404acb39fe Mon Sep 17 00:00:00 2001 From: guoshoujing Date: Thu, 17 Jun 2021 17:34:40 +0800 Subject: [PATCH 4/7] add exception check in AuthFilter --- hubble-be/pom.xml | 2 +- .../baidu/hugegraph/filter/AuthFilter.java | 74 ++++++++++++++++++- .../hugegraph/service/system/AuthService.java | 8 +- 3 files changed, 74 insertions(+), 10 deletions(-) diff --git a/hubble-be/pom.xml b/hubble-be/pom.xml index 5e815cb6..61ff4da8 100644 --- a/hubble-be/pom.xml +++ b/hubble-be/pom.xml @@ -120,7 +120,7 @@ com.baidu.hugegraph hugegraph-client - 1.9.4 + 1.9.5 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 index b7a89dbb..39eff7cd 100644 --- a/hubble-be/src/main/java/com/baidu/hugegraph/filter/AuthFilter.java +++ b/hubble-be/src/main/java/com/baidu/hugegraph/filter/AuthFilter.java @@ -20,6 +20,9 @@ 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; @@ -29,12 +32,18 @@ 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.driver.HugeClient; import com.baidu.hugegraph.config.AuthClientConfiguration; +import com.baidu.hugegraph.util.JsonUtil; +import com.google.common.collect.ImmutableSet; import lombok.extern.log4j.Log4j2; @@ -42,6 +51,13 @@ @WebFilter(filterName = "authFilter", urlPatterns = "/*") public class AuthFilter implements Filter { + private static final String BEARER_TOKEN_PREFIX = "Bearer "; + + private static final Set WHITE_API = ImmutableSet.of( + buildPath(RequestMethod.POST, + Constant.API_VERSION + "graph-connections/login") + ); + @Resource(name = AuthClientConfiguration.AUTH_CLIENT_NAME) private HugeClient client; @@ -51,15 +67,65 @@ public void doFilter(ServletRequest servletRequest, FilterChain filterChain) throws IOException, ServletException { try { - String authorization = ((HttpServletRequest) servletRequest) - .getHeader(HttpHeaders.AUTHORIZATION); - if (StringUtils.isNotEmpty(authorization)) { - this.client.setAuthContext(authorization); + HttpServletRequest request = (HttpServletRequest) servletRequest; + String authorization = request.getHeader(HttpHeaders.AUTHORIZATION); + + // Missed token and request uri not in white list + if (StringUtils.isEmpty(authorization) && !isWhiteAPI(request)) { + 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(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.client.setAuthContext(authorization); + filterChain.doFilter(servletRequest, servletResponse); } finally { this.client.resetAuthContext(); } } + + 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("Response error",e); + } + } } 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 index b1c1a4c8..951a15f9 100644 --- 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 @@ -31,14 +31,12 @@ import com.baidu.hugegraph.entity.login.LoginResult; import com.baidu.hugegraph.entity.user.HubbleUser; import com.baidu.hugegraph.structure.auth.Login; +import com.baidu.hugegraph.structure.auth.TokenPayload; import com.baidu.hugegraph.structure.auth.User; @Service public class AuthService { - private static final String TOKEN_USER_NAME = "user_name"; - private static final String TOKEN_USER_ID = "user_id"; - @Resource(name = AuthClientConfiguration.AUTH_CLIENT_NAME) private HugeClient authClient; @@ -58,8 +56,8 @@ public void logout() { } public HubbleUser getCurrentUser() { - Map payload = this.authClient.auth().verifyToken(); - String userId = (String) payload.get(TOKEN_USER_ID); + TokenPayload payload = this.authClient.auth().verifyToken(); + String userId = payload.userId(); User user = this.authClient.auth().getUser(userId); // TODO Set user auth info From ee42aea11c9089987de2d77e2f82b12940edf152 Mon Sep 17 00:00:00 2001 From: guoshoujing Date: Fri, 25 Jun 2021 14:25:27 +0800 Subject: [PATCH 5/7] improve code style --- .../hugegraph/controller/schema/PropertyKeyController.java | 2 +- .../com/baidu/hugegraph/entity/schema/LabelUpdateEntity.java | 3 --- .../src/main/java/com/baidu/hugegraph/filter/AuthFilter.java | 2 +- .../java/com/baidu/hugegraph/service/system/AuthService.java | 2 -- 4 files changed, 2 insertions(+), 7 deletions(-) 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/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/filter/AuthFilter.java b/hubble-be/src/main/java/com/baidu/hugegraph/filter/AuthFilter.java index 39eff7cd..9a5d659d 100644 --- a/hubble-be/src/main/java/com/baidu/hugegraph/filter/AuthFilter.java +++ b/hubble-be/src/main/java/com/baidu/hugegraph/filter/AuthFilter.java @@ -40,8 +40,8 @@ import com.baidu.hugegraph.common.Constant; import com.baidu.hugegraph.common.Response; -import com.baidu.hugegraph.driver.HugeClient; import com.baidu.hugegraph.config.AuthClientConfiguration; +import com.baidu.hugegraph.driver.HugeClient; import com.baidu.hugegraph.util.JsonUtil; import com.google.common.collect.ImmutableSet; 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 index 951a15f9..5947b6a1 100644 --- 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 @@ -19,8 +19,6 @@ package com.baidu.hugegraph.service.system; -import java.util.Map; - import javax.annotation.Resource; import org.springframework.stereotype.Service; From f94f17b2a293279633024898f0d4cc62a889761f Mon Sep 17 00:00:00 2001 From: guoshoujing Date: Mon, 19 Jul 2021 16:14:49 +0800 Subject: [PATCH 6/7] add user/project module --- hubble-be/pom.xml | 2 +- .../com/baidu/hugegraph/common/Constant.java | 2 + ...guration.java => ClientConfiguration.java} | 25 ++- .../baidu/hugegraph/config/JacksonConfig.java | 2 +- .../controller/project/ProjectController.java | 95 ++++++++ .../controller/system/LoginController.java | 4 +- .../controller/user/UserController.java | 93 ++++++++ .../hugegraph/entity/login/LoginResult.java | 5 + .../Group.java => project/ProjectEntity.java} | 32 ++- .../user/{HubbleUser.java => UserEntity.java} | 30 ++- .../baidu/hugegraph/filter/AuthFilter.java | 26 ++- .../hugegraph/mapper/UserResourcesMapper.java | 42 ++++ .../hugegraph/options/HubbleOptions.java | 8 + .../service/project/ProjectService.java | 203 +++++++++++++++++ .../hugegraph/service/system/AuthService.java | 56 +++-- .../hugegraph/service/user/UserService.java | 204 ++++++++++++++++++ .../com/baidu/hugegraph/util/SessionUtil.java | 49 +++++ .../src/main/resources/database/data.sql | 7 + .../src/main/resources/database/schema.sql | 14 ++ .../resources/hugegraph-hubble.properties | 1 + 20 files changed, 860 insertions(+), 40 deletions(-) rename hubble-be/src/main/java/com/baidu/hugegraph/config/{AuthClientConfiguration.java => ClientConfiguration.java} (60%) create mode 100644 hubble-be/src/main/java/com/baidu/hugegraph/controller/project/ProjectController.java create mode 100644 hubble-be/src/main/java/com/baidu/hugegraph/controller/user/UserController.java rename hubble-be/src/main/java/com/baidu/hugegraph/entity/{user/Group.java => project/ProjectEntity.java} (57%) rename hubble-be/src/main/java/com/baidu/hugegraph/entity/user/{HubbleUser.java => UserEntity.java} (59%) create mode 100644 hubble-be/src/main/java/com/baidu/hugegraph/mapper/UserResourcesMapper.java create mode 100644 hubble-be/src/main/java/com/baidu/hugegraph/service/project/ProjectService.java create mode 100644 hubble-be/src/main/java/com/baidu/hugegraph/service/user/UserService.java create mode 100644 hubble-be/src/main/java/com/baidu/hugegraph/util/SessionUtil.java diff --git a/hubble-be/pom.xml b/hubble-be/pom.xml index 61ff4da8..b5a0b911 100644 --- a/hubble-be/pom.xml +++ b/hubble-be/pom.xml @@ -120,7 +120,7 @@ com.baidu.hugegraph hugegraph-client - 1.9.5 + 1.9.6 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/AuthClientConfiguration.java b/hubble-be/src/main/java/com/baidu/hugegraph/config/ClientConfiguration.java similarity index 60% rename from hubble-be/src/main/java/com/baidu/hugegraph/config/AuthClientConfiguration.java rename to hubble-be/src/main/java/com/baidu/hugegraph/config/ClientConfiguration.java index b0e3e060..5af6b38a 100644 --- a/hubble-be/src/main/java/com/baidu/hugegraph/config/AuthClientConfiguration.java +++ b/hubble-be/src/main/java/com/baidu/hugegraph/config/ClientConfiguration.java @@ -23,20 +23,41 @@ 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 AuthClientConfiguration { +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); - return HugeClient.builder(authUrl, authGraph).build(); + 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/system/LoginController.java b/hubble-be/src/main/java/com/baidu/hugegraph/controller/system/LoginController.java index 8c61a727..9df6acfd 100644 --- 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 @@ -33,7 +33,7 @@ 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.HubbleUser; +import com.baidu.hugegraph.entity.user.UserEntity; import com.baidu.hugegraph.service.system.AuthService; import com.baidu.hugegraph.util.E; @@ -55,7 +55,7 @@ public void logout() { } @GetMapping("/user") - public HubbleUser currentUser(@RequestHeader(HttpHeaders.AUTHORIZATION) + public UserEntity currentUser(@RequestHeader(HttpHeaders.AUTHORIZATION) String token) { E.checkArgumentNotNull(token, "Request header Authorization must not be null"); 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/LoginResult.java b/hubble-be/src/main/java/com/baidu/hugegraph/entity/login/LoginResult.java index e0985ddb..014e30ea 100644 --- 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 @@ -19,6 +19,8 @@ package com.baidu.hugegraph.entity.login; +import java.util.List; + import com.fasterxml.jackson.annotation.JsonProperty; import lombok.AllArgsConstructor; @@ -34,4 +36,7 @@ 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/user/Group.java b/hubble-be/src/main/java/com/baidu/hugegraph/entity/project/ProjectEntity.java similarity index 57% rename from hubble-be/src/main/java/com/baidu/hugegraph/entity/user/Group.java rename to hubble-be/src/main/java/com/baidu/hugegraph/entity/project/ProjectEntity.java index 4035490f..fe5b9788 100644 --- a/hubble-be/src/main/java/com/baidu/hugegraph/entity/user/Group.java +++ b/hubble-be/src/main/java/com/baidu/hugegraph/entity/project/ProjectEntity.java @@ -17,8 +17,13 @@ * under the License. */ -package com.baidu.hugegraph.entity.user; +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; @@ -30,13 +35,30 @@ @NoArgsConstructor @AllArgsConstructor @Builder -public class Group extends AuthElement { +public class ProjectEntity extends AuthElement { - private static final long serialVersionUID = 3848451889435904990L; + private static final long serialVersionUID = 6004765261545877970L; - @JsonProperty("group_name") + @JsonProperty("project_name") private String name; - @JsonProperty("group_description") + @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/user/HubbleUser.java b/hubble-be/src/main/java/com/baidu/hugegraph/entity/user/UserEntity.java similarity index 59% rename from hubble-be/src/main/java/com/baidu/hugegraph/entity/user/HubbleUser.java rename to hubble-be/src/main/java/com/baidu/hugegraph/entity/user/UserEntity.java index 65f6f8eb..fe7d71fa 100644 --- a/hubble-be/src/main/java/com/baidu/hugegraph/entity/user/HubbleUser.java +++ b/hubble-be/src/main/java/com/baidu/hugegraph/entity/user/UserEntity.java @@ -21,6 +21,9 @@ 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; @@ -32,7 +35,7 @@ @NoArgsConstructor @AllArgsConstructor @Builder -public class HubbleUser extends AuthElement { +public class UserEntity extends AuthElement { private static final long serialVersionUID = 3121398441504040737L; @@ -53,4 +56,29 @@ public class HubbleUser extends AuthElement { @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 index 9a5d659d..9af8d1e1 100644 --- a/hubble-be/src/main/java/com/baidu/hugegraph/filter/AuthFilter.java +++ b/hubble-be/src/main/java/com/baidu/hugegraph/filter/AuthFilter.java @@ -40,9 +40,10 @@ import com.baidu.hugegraph.common.Constant; import com.baidu.hugegraph.common.Response; -import com.baidu.hugegraph.config.AuthClientConfiguration; +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; @@ -51,27 +52,29 @@ @WebFilter(filterName = "authFilter", urlPatterns = "/*") public class AuthFilter implements Filter { - private static final String BEARER_TOKEN_PREFIX = "Bearer "; - private static final Set WHITE_API = ImmutableSet.of( buildPath(RequestMethod.POST, Constant.API_VERSION + "graph-connections/login") ); - @Resource(name = AuthClientConfiguration.AUTH_CLIENT_NAME) - private HugeClient client; + @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 { - HttpServletRequest request = (HttpServletRequest) servletRequest; String authorization = request.getHeader(HttpHeaders.AUTHORIZATION); - // Missed token and request uri not in white list - if (StringUtils.isEmpty(authorization) && !isWhiteAPI(request)) { + if (StringUtils.isEmpty(authorization)) { String msg = "Missed authorization token"; writeResponse(servletResponse, () -> { return Response.builder() @@ -83,7 +86,7 @@ public void doFilter(ServletRequest servletRequest, } // Illegal token format if (StringUtils.isNotEmpty(authorization) && - !authorization.startsWith(BEARER_TOKEN_PREFIX)) { + !authorization.startsWith(Constant.BEARER_TOKEN_PREFIX)) { String msg = "Only HTTP Bearer authentication is supported"; writeResponse(servletResponse, () -> { return Response.builder() @@ -94,11 +97,12 @@ public void doFilter(ServletRequest servletRequest, return; } - this.client.setAuthContext(authorization); + this.authClient.setAuthContext(authorization); filterChain.doFilter(servletRequest, servletResponse); } finally { - this.client.resetAuthContext(); + this.authClient.resetAuthContext(); + SessionUtil.reset(); } } 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 914d5d77..cdbdffa6 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 @@ -245,4 +245,12 @@ public static synchronized HubbleOptions instance() { disallowEmpty(), "hugegraph" ); + + public static final ConfigOption ADMIN_PASSWORD = + new ConfigOption<>( + "auth.admin_password", + "The password of admin user in auth-server.", + disallowEmpty(), + "pa" + ); } 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 index 5947b6a1..75f23960 100644 --- 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 @@ -19,24 +19,37 @@ 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.config.AuthClientConfiguration; +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.HubbleUser; +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.structure.auth.User; +import com.baidu.hugegraph.util.SessionUtil; @Service public class AuthService { - @Resource(name = AuthClientConfiguration.AUTH_CLIENT_NAME) + @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(); @@ -44,8 +57,28 @@ public LoginResult login(LoginBody loginEntity) { 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(); } @@ -53,18 +86,7 @@ public void logout() { this.authClient.auth().logout(); } - public HubbleUser getCurrentUser() { - TokenPayload payload = this.authClient.auth().verifyToken(); - String userId = payload.userId(); - User user = this.authClient.auth().getUser(userId); - - // TODO Set user auth info - return HubbleUser.builder() - .username(user.name()) - .password(user.password()) - .phone(user.phone()) - .email(user.email()) - .description(user.description()) - .build(); + 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/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..20129090 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); \ No newline at end of file diff --git a/hubble-be/src/main/resources/database/schema.sql b/hubble-be/src/main/resources/database/schema.sql index cc03c3e7..7cd535ac 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`) +); \ No newline at end of file diff --git a/hubble-be/src/main/resources/hugegraph-hubble.properties b/hubble-be/src/main/resources/hugegraph-hubble.properties index d6ad7106..b2a5f155 100644 --- a/hubble-be/src/main/resources/hugegraph-hubble.properties +++ b/hubble-be/src/main/resources/hugegraph-hubble.properties @@ -15,3 +15,4 @@ server.protocol=http auth.remote_url=http://127.0.0.1:8080 auth.graph=hugegraph +auth.admin_password=pa From 5d962368f8e8efb4d3b49ea0d9a8027d795284a7 Mon Sep 17 00:00:00 2001 From: guoshoujing Date: Wed, 21 Jul 2021 14:24:57 +0800 Subject: [PATCH 7/7] improve code style --- .../src/main/java/com/baidu/hugegraph/filter/AuthFilter.java | 2 +- .../main/java/com/baidu/hugegraph/options/HubbleOptions.java | 2 +- hubble-be/src/main/resources/database/data.sql | 2 +- hubble-be/src/main/resources/database/schema.sql | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) 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 index 9af8d1e1..ed9526a1 100644 --- a/hubble-be/src/main/java/com/baidu/hugegraph/filter/AuthFilter.java +++ b/hubble-be/src/main/java/com/baidu/hugegraph/filter/AuthFilter.java @@ -129,7 +129,7 @@ private void writeResponse(ServletResponse servletResponse, try (PrintWriter writer = servletResponse.getWriter()) { writer.print(JsonUtil.toJson(response)); } catch (IOException e) { - log.error("Response error",e); + log.error("Failed to get response writer ",e); } } } 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 cdbdffa6..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 @@ -251,6 +251,6 @@ public static synchronized HubbleOptions instance() { "auth.admin_password", "The password of admin user in auth-server.", disallowEmpty(), - "pa" + "hugegraph" ); } diff --git a/hubble-be/src/main/resources/database/data.sql b/hubble-be/src/main/resources/database/data.sql index 20129090..559f29cf 100644 --- a/hubble-be/src/main/resources/database/data.sql +++ b/hubble-be/src/main/resources/database/data.sql @@ -10,4 +10,4 @@ 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); \ No newline at end of file +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 7cd535ac..d0bfbee5 100644 --- a/hubble-be/src/main/resources/database/schema.sql +++ b/hubble-be/src/main/resources/database/schema.sql @@ -130,4 +130,4 @@ CREATE TABLE IF NOT EXISTS `resources_role_rel` ( `resources_id` INT NOT NULL DEFAULT -1, `role_type` INT NOT NULL DEFAULT -1, PRIMARY KEY (`id`) -); \ No newline at end of file +);