├── src ├── main │ ├── resources │ │ ├── usermgmtdb_upgrade_1.2.sql │ │ ├── usermgmtdb_upgrade_1.1.sql │ │ ├── usermgmtdb.sql │ │ ├── log4j2.xml │ │ ├── application.properties │ │ ├── usermgmtdb-data.sql │ │ └── application.yaml │ └── java │ │ └── org │ │ └── edgegallery │ │ └── user │ │ └── auth │ │ ├── config │ │ ├── validate │ │ │ ├── IStringTrim.java │ │ │ ├── ICheckParams.java │ │ │ ├── annotation │ │ │ │ └── ParameterValidate.java │ │ │ ├── AbstractCheckParamsGenericUtils.java │ │ │ └── ValidateAspect.java │ │ ├── OAuthClientDetail.java │ │ ├── security │ │ │ ├── PasswordEncoder.java │ │ │ ├── AuthInMemoryAuthorizationCodeServices.java │ │ │ ├── LoginFailureListener.java │ │ │ ├── OAuthRedirectStrategy.java │ │ │ ├── OAuthUnauthorizedEntryPoint.java │ │ │ ├── LoginFailHandler.java │ │ │ ├── AuthServerTokenEnhancer.java │ │ │ ├── ExtendAuthorizationCodeTokenGranter.java │ │ │ └── LoginSuccessHandler.java │ │ ├── SmsConfig.java │ │ ├── RedisConfig.java │ │ ├── ServiceConfig.java │ │ ├── OAuthClientDetailsConfig.java │ │ ├── filter │ │ │ └── GuestUserAuthenticationFilter.java │ │ └── DescriptionConfig.java │ │ ├── exception │ │ └── UserAuthException.java │ │ ├── db │ │ ├── entity │ │ │ ├── TenantPermissionVo.java │ │ │ ├── TenantPermissionPo.java │ │ │ ├── RolePo.java │ │ │ └── TenantPo.java │ │ ├── EnumRole.java │ │ ├── EnumPlatform.java │ │ ├── mapper │ │ │ └── TenantPoMapper.java │ │ └── custom │ │ │ └── TenantTransactionRepository.java │ │ ├── controller │ │ ├── dto │ │ │ ├── response │ │ │ │ ├── GetAccessTokenRespDto.java │ │ │ │ ├── LogoutRespDto.java │ │ │ │ ├── QueryUserRespDto.java │ │ │ │ ├── FormatRespDto.java │ │ │ │ ├── RoleDto.java │ │ │ │ ├── UniquenessRespDto.java │ │ │ │ ├── ErrorRespDto.java │ │ │ │ ├── TenantRespDto.java │ │ │ │ └── BaseTenantRespDto.java │ │ │ └── request │ │ │ │ ├── GetAccessTokenReqDto.java │ │ │ │ ├── TenantRegisterReqDto.java │ │ │ │ ├── VerificationReqDto.java │ │ │ │ ├── VerificationReqByMailDto.java │ │ │ │ ├── UniqueReqDto.java │ │ │ │ ├── QueryUserCtrlDto.java │ │ │ │ ├── BaseTenantBasicReqDto.java │ │ │ │ ├── ModifyPasswordReqDto.java │ │ │ │ └── QueryUserReqDto.java │ │ ├── HealthCheck.java │ │ ├── base │ │ │ └── AbstractBeGenericServlet.java │ │ ├── AccessTokenController.java │ │ └── VerificationController.java │ │ ├── external │ │ └── iam │ │ │ ├── IExternalIamLogin.java │ │ │ ├── IExternalIamService.java │ │ │ ├── ExternalUserUtil.java │ │ │ ├── model │ │ │ └── ExternalUser.java │ │ │ └── service │ │ │ ├── ExternalIamLoginImpl.java │ │ │ └── ExternalIamServiceImpl.java │ │ ├── utils │ │ ├── CommonUtil.java │ │ ├── ValidatorUtil.java │ │ ├── Consts.java │ │ ├── AnonymizeUtil.java │ │ ├── UserLockUtil.java │ │ ├── redis │ │ │ ├── RedisPoolUtil.java │ │ │ └── RedisUtil.java │ │ ├── ErrorEnum.java │ │ └── HttpsUtil.java │ │ ├── service │ │ ├── MailService.java │ │ └── HwCloudVerification.java │ │ └── MainServer.java └── test │ ├── resources │ ├── usermgmt-test.sql │ ├── application.yaml │ ├── application.properties │ └── usermgmt-test-data.sql │ └── java │ └── org │ └── edgegallery │ └── user │ └── auth │ ├── controller │ ├── UserControllerTest.java │ ├── ForgetPasswordApiTest.java │ ├── VerficationApiTest.java │ └── RegisterApiTest.java │ ├── DBTest.java │ └── service │ ├── OAuthTokenTest.java │ └── RegisterTest.java ├── .gitignore ├── docker └── Dockerfile └── README.md /src/main/resources/usermgmtdb_upgrade_1.2.sql: -------------------------------------------------------------------------------- 1 | alter table tbl_tenant add PWEFFECTTIME TIMESTAMP NULL; 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | static/ 3 | # local env files 4 | .env.local 5 | .env.*.local 6 | 7 | # Log files 8 | *.log 9 | 10 | # Editor directories and files 11 | .idea 12 | .vscode 13 | *.suo 14 | *.ntvs* 15 | *.njsproj 16 | *.sln 17 | *.sw? 18 | *.exe 19 | *.iml 20 | -------------------------------------------------------------------------------- /src/main/resources/usermgmtdb_upgrade_1.1.sql: -------------------------------------------------------------------------------- 1 | alter table tbl_tenant alter column TELEPHONENUMBER drop NOT NULL; 2 | alter table tbl_tenant add MAILADDRESS VARCHAR(50) NULL; 3 | alter table tbl_tenant add CREATETIME TIMESTAMP NULL; 4 | alter table tbl_tenant add MODIFYTIME TIMESTAMP NULL; 5 | alter table tbl_tenant add CONSTRAINT MAILADDRESS UNIQUE (mailaddress); 6 | 7 | update tbl_tenant set MAILADDRESS = '13800000000@edgegallery.org' where USERNAME = 'guest'; 8 | update tbl_tenant set MAILADDRESS = '13800000001@edgegallery.org' where USERNAME = 'admin'; 9 | update tbl_tenant set CREATETIME = now(), MODIFYTIME = now(); 10 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/config/validate/IStringTrim.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.config.validate; 18 | 19 | public interface IStringTrim { 20 | void stringTrim(); 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/exception/UserAuthException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.exception; 18 | 19 | public class UserAuthException extends Exception { 20 | 21 | public UserAuthException(String message) { 22 | super(message); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/config/validate/ICheckParams.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.config.validate; 18 | 19 | import fj.data.Either; 20 | import org.edgegallery.user.auth.controller.dto.response.FormatRespDto; 21 | 22 | public interface ICheckParams { 23 | 24 | Either checkData(); 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/db/entity/TenantPermissionVo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.db.entity; 18 | 19 | import java.util.List; 20 | import lombok.Getter; 21 | import lombok.Setter; 22 | 23 | @Getter 24 | @Setter 25 | public class TenantPermissionVo extends TenantPo { 26 | 27 | private List roles; 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/db/EnumRole.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.db; 18 | 19 | /** 20 | * roles info. 21 | */ 22 | public enum EnumRole { 23 | /** 24 | * Guest. 25 | */ 26 | GUEST, 27 | /** 28 | * Tenant. 29 | */ 30 | TENANT, 31 | /** 32 | * Admin. 33 | */ 34 | ADMIN 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/controller/dto/response/GetAccessTokenRespDto.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.controller.dto.response; 18 | 19 | import lombok.AllArgsConstructor; 20 | import lombok.Getter; 21 | import lombok.Setter; 22 | 23 | @Setter 24 | @Getter 25 | @AllArgsConstructor 26 | public class GetAccessTokenRespDto { 27 | 28 | private String accessToken; 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/controller/dto/response/LogoutRespDto.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.controller.dto.response; 18 | 19 | import lombok.Getter; 20 | import lombok.Setter; 21 | 22 | @Getter 23 | @Setter 24 | public class LogoutRespDto { 25 | 26 | private String status; 27 | 28 | private Boolean enableSms; 29 | 30 | private Boolean enableMail; 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/controller/dto/response/QueryUserRespDto.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.controller.dto.response; 18 | 19 | import java.util.List; 20 | import lombok.Getter; 21 | import lombok.Setter; 22 | import lombok.ToString; 23 | 24 | @ToString 25 | @Setter 26 | @Getter 27 | public class QueryUserRespDto { 28 | 29 | private int totalCount; 30 | 31 | private List userList; 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/config/OAuthClientDetail.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.config; 18 | 19 | import lombok.Getter; 20 | import lombok.Setter; 21 | 22 | @Getter 23 | @Setter 24 | public class OAuthClientDetail { 25 | private boolean clientEnabled; 26 | 27 | private String clientId; 28 | 29 | private String clientSecret; 30 | 31 | private String clientUrl; 32 | 33 | private String clientAccessUrl; 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/db/entity/TenantPermissionPo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.db.entity; 18 | 19 | import lombok.Getter; 20 | import lombok.Setter; 21 | import org.edgegallery.user.auth.db.EnumPlatform; 22 | import org.edgegallery.user.auth.db.EnumRole; 23 | 24 | @Getter 25 | @Setter 26 | public class TenantPermissionPo extends TenantPo { 27 | 28 | private EnumPlatform platform; 29 | 30 | private EnumRole role; 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/config/validate/annotation/ParameterValidate.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.config.validate.annotation; 18 | 19 | import java.lang.annotation.ElementType; 20 | import java.lang.annotation.Retention; 21 | import java.lang.annotation.RetentionPolicy; 22 | import java.lang.annotation.Target; 23 | 24 | @Retention(RetentionPolicy.RUNTIME) 25 | @Target({ElementType.METHOD}) 26 | public @interface ParameterValidate { 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/config/security/PasswordEncoder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.config.security; 18 | 19 | import org.springframework.security.crypto.password.Pbkdf2PasswordEncoder; 20 | import org.springframework.stereotype.Component; 21 | 22 | @Component 23 | public class PasswordEncoder extends Pbkdf2PasswordEncoder { 24 | 25 | PasswordEncoder() { 26 | this.setAlgorithm(Pbkdf2PasswordEncoder.SecretKeyFactoryAlgorithm.PBKDF2WithHmacSHA256); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/external/iam/IExternalIamLogin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.external.iam; 18 | 19 | import org.springframework.security.core.userdetails.UserDetails; 20 | 21 | public interface IExternalIamLogin { 22 | /** 23 | * load user from external iam system. 24 | * 25 | * @param userFlag user flag 26 | * @param password password 27 | * @return UserDetails 28 | */ 29 | UserDetails loadUser(String userFlag, String password); 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/controller/dto/response/FormatRespDto.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.controller.dto.response; 18 | 19 | import javax.ws.rs.core.Response; 20 | import lombok.AllArgsConstructor; 21 | import lombok.Getter; 22 | import lombok.Setter; 23 | import lombok.ToString; 24 | 25 | @Setter 26 | @Getter 27 | @ToString 28 | @AllArgsConstructor 29 | public class FormatRespDto { 30 | 31 | private Response.Status errStatus; 32 | private ErrorRespDto errorRespDto; 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/db/EnumPlatform.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.db; 18 | 19 | /** 20 | * Platform define. 21 | */ 22 | public enum EnumPlatform { 23 | /** 24 | * App Store. 25 | */ 26 | APPSTORE, 27 | /** 28 | * Developer. 29 | */ 30 | DEVELOPER, 31 | /** 32 | * Mecm. 33 | */ 34 | MECM, 35 | /** 36 | * ATP. 37 | */ 38 | ATP, 39 | /** 40 | * Laboratory. 41 | */ 42 | LAB, 43 | /** 44 | * AppMgmt. 45 | */ 46 | APPMGMT 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/utils/CommonUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.utils; 18 | 19 | public final class CommonUtil { 20 | 21 | private CommonUtil() {} 22 | 23 | /** 24 | * judge user is inner default user. 25 | * 26 | * @param userFlag user flag 27 | * @return true if inner default user, otherwise false 28 | */ 29 | public static boolean isInnerDefaultUser(String userFlag) { 30 | return Consts.SUPER_ADMIN_NAME.equals(userFlag) || Consts.GUEST_USER_NAME.equals(userFlag); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/external/iam/IExternalIamService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.external.iam; 18 | 19 | import org.edgegallery.user.auth.external.iam.model.ExternalUser; 20 | import org.springframework.stereotype.Service; 21 | 22 | @Service("ExternalIamService") 23 | public interface IExternalIamService { 24 | /** 25 | * external login. 26 | * 27 | * @param userFlag user flag 28 | * @param password password 29 | * @return ExternalUser 30 | */ 31 | ExternalUser login(String userFlag, String password); 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/controller/dto/response/RoleDto.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.controller.dto.response; 18 | 19 | import io.swagger.annotations.ApiModelProperty; 20 | import lombok.Getter; 21 | import lombok.Setter; 22 | import lombok.ToString; 23 | import org.edgegallery.user.auth.db.EnumPlatform; 24 | import org.edgegallery.user.auth.db.EnumRole; 25 | 26 | @Getter 27 | @Setter 28 | @ToString 29 | public class RoleDto { 30 | 31 | @ApiModelProperty(required = true) 32 | private EnumPlatform platform; 33 | 34 | @ApiModelProperty(required = true) 35 | private EnumRole role; 36 | } 37 | -------------------------------------------------------------------------------- /src/test/resources/usermgmt-test.sql: -------------------------------------------------------------------------------- 1 | 2 | CREATE TABLE if not exists tbl_tenant ( 3 | TENANTID VARCHAR(100) PRIMARY KEY NOT NULL, 4 | USERNAME VARCHAR(50) NOT NULL, 5 | PASSWORD VARCHAR(100) NOT NULL, 6 | COMPANY VARCHAR(50) NULL, 7 | TELEPHONENUMBER VARCHAR(20) NULL, 8 | MAILADDRESS VARCHAR(50) NULL, 9 | GENDER VARCHAR(10) NULL, 10 | isallowed boolean NOT NULL, 11 | CREATETIME TIMESTAMP NULL, 12 | MODIFYTIME TIMESTAMP NULL, 13 | PWEFFECTTIME TIMESTAMP NULL, 14 | CONSTRAINT USERNAME UNIQUE (username), 15 | CONSTRAINT TELEPHONENUMBER UNIQUE (telephonenumber), 16 | CONSTRAINT MAILADDRESS UNIQUE (mailaddress) 17 | 18 | ); 19 | 20 | CREATE TABLE if not exists tbl_tenant_role ( 21 | TENANTID VARCHAR(100) NOT NULL, 22 | ROLEID INTEGER NOT NULL, 23 | primary key(TENANTID, ROLEID) 24 | ); 25 | 26 | 27 | CREATE TABLE if not exists tbl_role ( 28 | ID INTEGER PRIMARY KEY NOT NULL, 29 | PLATFORM VARCHAR(50) NOT NULL, 30 | ROLE VARCHAR(50) NOT NULL 31 | ); 32 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/controller/dto/response/UniquenessRespDto.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.controller.dto.response; 18 | 19 | import io.swagger.annotations.ApiModelProperty; 20 | import lombok.Getter; 21 | import lombok.Setter; 22 | 23 | @Setter 24 | @Getter 25 | public class UniquenessRespDto { 26 | @ApiModelProperty(required = true, example = "false") 27 | private boolean username; 28 | 29 | @ApiModelProperty(required = true, example = "false") 30 | private boolean telephone; 31 | 32 | @ApiModelProperty(required = true, example = "false") 33 | private boolean mailAddress; 34 | } 35 | -------------------------------------------------------------------------------- /src/main/resources/usermgmtdb.sql: -------------------------------------------------------------------------------- 1 | 2 | CREATE TABLE if not exists tbl_tenant ( 3 | TENANTID VARCHAR(100) PRIMARY KEY NOT NULL, 4 | USERNAME VARCHAR(50) NOT NULL, 5 | PASSWORD VARCHAR(100) NOT NULL, 6 | COMPANY VARCHAR(50) NULL, 7 | TELEPHONENUMBER VARCHAR(20) NULL, 8 | MAILADDRESS VARCHAR(50) NULL, 9 | GENDER VARCHAR(10) NULL, 10 | isallowed boolean NOT NULL, 11 | CREATETIME TIMESTAMP NULL, 12 | MODIFYTIME TIMESTAMP NULL, 13 | PWEFFECTTIME TIMESTAMP NULL, 14 | CONSTRAINT USERNAME UNIQUE (username), 15 | CONSTRAINT TELEPHONENUMBER UNIQUE (telephonenumber), 16 | CONSTRAINT MAILADDRESS UNIQUE (mailaddress) 17 | ); 18 | 19 | CREATE TABLE if not exists tbl_tenant_role ( 20 | TENANTID VARCHAR(100) NOT NULL, 21 | ROLEID INTEGER NOT NULL, 22 | primary key(TENANTID, ROLEID) 23 | ); 24 | 25 | CREATE TABLE if not exists tbl_role ( 26 | ID INTEGER PRIMARY KEY NOT NULL, 27 | PLATFORM VARCHAR(50) NOT NULL, 28 | ROLE VARCHAR(50) NOT NULL 29 | ); -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/config/SmsConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.config; 18 | 19 | import lombok.Getter; 20 | import lombok.Setter; 21 | import org.springframework.boot.context.properties.ConfigurationProperties; 22 | import org.springframework.stereotype.Component; 23 | 24 | @Component 25 | @ConfigurationProperties(prefix = "sms") 26 | @Getter 27 | @Setter 28 | public class SmsConfig { 29 | 30 | private String enabled; 31 | 32 | private String url; 33 | 34 | private String appKey; 35 | 36 | private String appSecret; 37 | 38 | private String sender; 39 | 40 | private String templateId; 41 | 42 | private String signature; 43 | 44 | private String statusCallBack; 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/config/RedisConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.config; 18 | 19 | import lombok.Getter; 20 | import lombok.Setter; 21 | import org.springframework.boot.context.properties.ConfigurationProperties; 22 | import org.springframework.stereotype.Component; 23 | 24 | @Component 25 | @ConfigurationProperties(prefix = "redis") 26 | @Getter 27 | @Setter 28 | public class RedisConfig { 29 | 30 | private String ip; 31 | 32 | private Integer port; 33 | 34 | private Integer verificationTimeOut; 35 | 36 | private Integer imgVerificationTimeout; 37 | 38 | private String password; 39 | 40 | private Integer maxTotal; 41 | 42 | private Integer maxIdle; 43 | 44 | private Integer maxWaitMillis; 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/config/validate/AbstractCheckParamsGenericUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.config.validate; 18 | 19 | import fj.data.Either; 20 | import org.edgegallery.user.auth.controller.dto.response.FormatRespDto; 21 | 22 | public abstract class AbstractCheckParamsGenericUtils implements ICheckParams { 23 | 24 | /** 25 | * check data. 26 | */ 27 | public Either checkData() { 28 | Either format = checkDataFormat(); 29 | if (format.isRight()) { 30 | return format; 31 | } 32 | return Either.left(true); 33 | } 34 | 35 | protected Either checkDataFormat() { 36 | return Either.left(true); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/config/ServiceConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.config; 18 | 19 | public class ServiceConfig { 20 | 21 | private ServiceConfig() { 22 | } 23 | 24 | public static final String PATTERN_IMG_VERIFICATION_CODE = "^\\d{4,4}$"; 25 | 26 | public static final String PATTERN_VERIFICATION_CODE = "^\\d{6,6}$"; 27 | 28 | public static final String PATTERN_USERNAME = "^[a-zA-Z][a-zA-Z0-9_]{5,29}$"; 29 | 30 | public static final String PATTERN_USERPW = 31 | "^(?=.*[a-zA-Z])(?=.*\\d)(?=.*[~!@#$%^&*()_+`\\-={}:\";'<>?,./]).{6,18}$"; 32 | 33 | public static final String PATTERN_TELEPHONE = "^1[34578]\\d{9}$"; 34 | 35 | public static final String PATTERN_MAILADDRESS 36 | = "^[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)*@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+$"; 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/config/OAuthClientDetailsConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.config; 18 | 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | import java.util.stream.Collectors; 22 | import lombok.Setter; 23 | import org.springframework.boot.context.properties.ConfigurationProperties; 24 | import org.springframework.stereotype.Component; 25 | 26 | @Component 27 | @ConfigurationProperties(prefix = "oauth2") 28 | @Setter 29 | public class OAuthClientDetailsConfig { 30 | 31 | private List clients = new ArrayList<>(); 32 | 33 | /** 34 | * get enabled clients. 35 | * 36 | * @return enabled client list 37 | */ 38 | public List getEnabledClients() { 39 | return clients.stream().filter(OAuthClientDetail::isClientEnabled).collect(Collectors.toList()); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/test/java/org/edgegallery/user/auth/controller/UserControllerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.controller; 18 | 19 | import com.google.gson.Gson; 20 | import org.edgegallery.user.auth.service.UserMgmtService; 21 | import org.junit.Before; 22 | import org.mockito.InjectMocks; 23 | import org.mockito.Mock; 24 | import org.mockito.MockitoAnnotations; 25 | import org.springframework.test.web.servlet.MockMvc; 26 | import org.springframework.test.web.servlet.setup.MockMvcBuilders; 27 | 28 | public class UserControllerTest { 29 | 30 | protected MockMvc mvc; 31 | 32 | @InjectMocks 33 | protected UserController userController; 34 | 35 | @Mock 36 | protected UserMgmtService userMgmtService; 37 | 38 | protected Gson gson = new Gson(); 39 | 40 | @Before 41 | public void setUp() { 42 | this.mvc = MockMvcBuilders.standaloneSetup(userController).build(); 43 | MockitoAnnotations.initMocks(this); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/config/security/AuthInMemoryAuthorizationCodeServices.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.config.security; 18 | 19 | import javax.servlet.http.HttpServletRequest; 20 | import org.springframework.beans.factory.annotation.Autowired; 21 | import org.springframework.security.oauth2.provider.OAuth2Authentication; 22 | import org.springframework.security.oauth2.provider.code.InMemoryAuthorizationCodeServices; 23 | import org.springframework.stereotype.Service; 24 | 25 | @Service 26 | public class AuthInMemoryAuthorizationCodeServices extends InMemoryAuthorizationCodeServices { 27 | @Autowired 28 | private HttpServletRequest request; 29 | 30 | @Override 31 | protected void store(String code, OAuth2Authentication authentication) { 32 | String ssoSessionId = request.getSession(false).getId(); 33 | request.getServletContext().setAttribute(code, ssoSessionId); 34 | super.store(code, authentication); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/controller/dto/response/ErrorRespDto.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.controller.dto.response; 18 | 19 | import lombok.Getter; 20 | import lombok.Setter; 21 | import lombok.ToString; 22 | import org.edgegallery.user.auth.utils.ErrorEnum; 23 | 24 | @Setter 25 | @Getter 26 | @ToString 27 | public class ErrorRespDto { 28 | private int code; 29 | private String message; 30 | 31 | /** 32 | * construct. 33 | * 34 | * @param returnCode int code 35 | * @param message msg 36 | */ 37 | private ErrorRespDto(int returnCode, String message) { 38 | this.code = returnCode; 39 | this.message = message; 40 | } 41 | 42 | /** 43 | * build from error enum define. 44 | * 45 | * @param errorEnum error define 46 | * @return ErrorRespDto 47 | */ 48 | public static ErrorRespDto build(ErrorEnum errorEnum) { 49 | return new ErrorRespDto(errorEnum.code(), errorEnum.message()); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/controller/HealthCheck.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.controller; 18 | 19 | import io.swagger.annotations.ApiOperation; 20 | import org.apache.servicecomb.provider.rest.common.RestSchema; 21 | import org.springframework.http.MediaType; 22 | import org.springframework.http.ResponseEntity; 23 | import org.springframework.stereotype.Controller; 24 | import org.springframework.web.bind.annotation.GetMapping; 25 | import org.springframework.web.bind.annotation.RequestMapping; 26 | 27 | @RestSchema(schemaId = "health") 28 | @RequestMapping("/health") 29 | @Controller 30 | public class HealthCheck { 31 | 32 | /** 33 | * Queries liveness & readiness. 34 | * 35 | * @return status code 200 when ready 36 | */ 37 | @GetMapping(value = "", produces = MediaType.APPLICATION_JSON_VALUE) 38 | @ApiOperation(value = "health check", response = String.class) 39 | public ResponseEntity healthCheck() { 40 | return ResponseEntity.ok("ok"); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/controller/dto/request/GetAccessTokenReqDto.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.controller.dto.request; 18 | 19 | import javax.validation.constraints.NotEmpty; 20 | import javax.validation.constraints.NotNull; 21 | import lombok.Getter; 22 | import lombok.Setter; 23 | import org.edgegallery.user.auth.config.validate.AbstractCheckParamsGenericUtils; 24 | import org.edgegallery.user.auth.config.validate.IStringTrim; 25 | import org.springframework.util.StringUtils; 26 | 27 | @Getter 28 | @Setter 29 | public class GetAccessTokenReqDto extends AbstractCheckParamsGenericUtils implements IStringTrim { 30 | @NotNull 31 | @NotEmpty 32 | private String userFlag; 33 | 34 | @NotNull 35 | @NotEmpty 36 | private String password; 37 | 38 | /** 39 | * check basic data by trim. 40 | */ 41 | public void stringTrim() { 42 | this.userFlag = StringUtils.trimWhitespace(this.userFlag); 43 | this.password = StringUtils.trimWhitespace(this.password); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/controller/dto/request/TenantRegisterReqDto.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.controller.dto.request; 18 | 19 | import io.swagger.annotations.ApiModel; 20 | import io.swagger.annotations.ApiModelProperty; 21 | import javax.validation.constraints.Pattern; 22 | import lombok.Getter; 23 | import lombok.Setter; 24 | import org.edgegallery.user.auth.config.ServiceConfig; 25 | import org.edgegallery.user.auth.config.validate.IStringTrim; 26 | import org.springframework.util.StringUtils; 27 | 28 | @Setter 29 | @Getter 30 | @ApiModel(value = "TenantRegisterRequest") 31 | public class TenantRegisterReqDto extends BaseTenantBasicReqDto implements IStringTrim { 32 | 33 | @ApiModelProperty(required = true, example = "Test@Password") 34 | @Pattern(regexp = ServiceConfig.PATTERN_USERPW) 35 | private String password; 36 | 37 | /** 38 | * check basic data by trim. 39 | */ 40 | public void stringTrim() { 41 | super.stringTrim(); 42 | this.password = StringUtils.trimWhitespace(this.password); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/test/resources/application.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2020-2021 Huawei Technologies Co., Ltd. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | servicecomb-config-order: 2 17 | APPLICATION_ID: edgegallery #应用名 18 | service_description: 19 | name: user-mgmt-be-test #微服务名 20 | version: 1.0.0 #微服务版本 21 | environment: development 22 | servicecomb: 23 | boot: 24 | waitUp.timeoutInMilliseconds: 1000 25 | 26 | ###spring config###### 27 | server: 28 | port: 8067 29 | servlet: 30 | context-path: /auth-server 31 | session: 32 | timeout: 600 33 | cookie: 34 | name: AUTHSERVERSESSIONID 35 | spring: 36 | datasource: 37 | url: jdbc:h2:mem:test;DB_CLOSE_DELAY=0;MODE=PostgreSQL 38 | username: 39 | password: 40 | driver-class-name: org.h2.Driver 41 | schema: classpath:usermgmt-test.sql 42 | data: classpath:usermgmt-test-data.sql 43 | main: 44 | allow-bean-definition-overriding: true 45 | 46 | ###spring mybatis#### 47 | mybatis: 48 | mapper-locations: classpath:mybatis/sql/*.xml 49 | oauth2: 50 | clients: 51 | - clientEnabled: true 52 | clientId: test 53 | clientSecret: test 54 | clientUrl: test 55 | clientAccessUrl: test -------------------------------------------------------------------------------- /src/test/resources/application.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2020-2021 Huawei Technologies Co., Ltd. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | ##### Redis config ##### 18 | redis.ip=${REDIS_IP:user-mgmt-redis-svc} 19 | redis.port=${REDIS_PORT:6379} 20 | redis.password=${REDIS_PASSWORD:111111} 21 | redis.verificationTimeOut=${REDIS_VERIFICATION_TIMEOUT:300} 22 | redis.imgVerificationTimeout=${REDIS_IMG_VERIFICATION_TIMEOUT:180} 23 | redis.maxTotal=${REDIS_MAX_TOTAL:1000} 24 | redis.maxIdle=${REDIS_MAX_IDLE:50} 25 | redis.maxWaitMillis=${REDIS_MAX_WAIT_MILLIS:100} 26 | #### jwt config #### 27 | jwt.publicKey=${JWT_PUBLIC_KEY:} 28 | jwt.encryptedPrivateKey=${JWT_ENCRYPTED_PRIVATE_KEY:} 29 | jwt.encryptPassword=${JWT_ENCRYPT_PASSWORD:} 30 | #### cors config #### 31 | cors.allow.origins=${CORS_ALLOW_ORIGINS:*} 32 | #### Mail config #### 33 | mail.enabled=${MAIL_ENABLED:false} 34 | spring.mail.host=${MAIL_HOST:} 35 | spring.mail.port=${MAIL_PORT:25} 36 | spring.mail.username=${MAIL_SENDER:} 37 | #### security policy config #### 38 | secPolicy.pwTimeout=${SECPOLICY_PW_TIMEOUT:90} 39 | #### external iam config #### 40 | external.iam.enabled=${EXTERNAL_IAM_ENABLED:false} 41 | external.iam.endpoint=${EXTERNAL_IAM_ENDPOINT:} 42 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/db/entity/RolePo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.db.entity; 18 | 19 | import io.swagger.annotations.ApiModelProperty; 20 | import javax.persistence.Entity; 21 | import javax.persistence.Table; 22 | import lombok.AllArgsConstructor; 23 | import lombok.Getter; 24 | import lombok.Setter; 25 | import org.edgegallery.user.auth.db.EnumPlatform; 26 | import org.edgegallery.user.auth.db.EnumRole; 27 | 28 | @Entity 29 | @Table(name = "tbl_role") 30 | @Setter 31 | @Getter 32 | @AllArgsConstructor 33 | public class RolePo { 34 | 35 | private int id; 36 | 37 | @ApiModelProperty(required = true) 38 | private EnumPlatform platform; 39 | 40 | @ApiModelProperty(required = true) 41 | private EnumRole role; 42 | 43 | public RolePo(int id) { 44 | this.id = id; 45 | } 46 | 47 | /** 48 | *set role info. 49 | */ 50 | public RolePo(EnumPlatform platform, EnumRole role) { 51 | this.platform = platform; 52 | this.role = role; 53 | } 54 | 55 | public String toString() { 56 | return platform + "_" + role; 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/controller/dto/request/VerificationReqDto.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.controller.dto.request; 18 | 19 | import com.fasterxml.jackson.annotation.JsonProperty; 20 | import com.google.gson.annotations.SerializedName; 21 | import io.swagger.annotations.ApiModelProperty; 22 | import javax.validation.constraints.Pattern; 23 | import lombok.Getter; 24 | import lombok.Setter; 25 | import org.edgegallery.user.auth.config.ServiceConfig; 26 | import org.edgegallery.user.auth.config.validate.AbstractCheckParamsGenericUtils; 27 | import org.edgegallery.user.auth.config.validate.IStringTrim; 28 | import org.springframework.util.StringUtils; 29 | 30 | @Setter 31 | @Getter 32 | public class VerificationReqDto extends AbstractCheckParamsGenericUtils implements IStringTrim { 33 | 34 | @SerializedName("telephone") 35 | @JsonProperty("telephone") 36 | @ApiModelProperty(required = true, example = "15191881159") 37 | @Pattern(regexp = ServiceConfig.PATTERN_TELEPHONE) 38 | private String telephone; 39 | 40 | @Override 41 | public void stringTrim() { 42 | this.telephone = StringUtils.trimWhitespace(telephone); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/controller/base/AbstractBeGenericServlet.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.controller.base; 18 | 19 | import fj.data.Either; 20 | import javax.ws.rs.core.Response.Status; 21 | import org.edgegallery.user.auth.controller.dto.response.FormatRespDto; 22 | import org.springframework.http.ResponseEntity; 23 | 24 | public abstract class AbstractBeGenericServlet { 25 | 26 | protected ResponseEntity buildResponse(Either either) { 27 | return either.isRight() ? buildErrorResponse(either.right().value()) : ResponseEntity.ok(either.left().value()); 28 | } 29 | 30 | protected ResponseEntity buildCreatedResponse(Either either) { 31 | return either.isRight() ? buildErrorResponse(either.right().value()) 32 | : ResponseEntity.status(Status.CREATED.getStatusCode()).body(either.left().value()); 33 | } 34 | 35 | private ResponseEntity buildErrorResponse(FormatRespDto formatRespDto) { 36 | return ResponseEntity.status(formatRespDto.getErrStatus().getStatusCode()) 37 | .body(formatRespDto.getErrorRespDto()); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/utils/ValidatorUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.utils; 18 | 19 | import fj.data.Either; 20 | import java.util.Set; 21 | import javax.validation.ConstraintViolation; 22 | import javax.validation.Validation; 23 | import javax.validation.Validator; 24 | 25 | public class ValidatorUtil { 26 | 27 | private static Validator validator = Validation.buildDefaultValidatorFactory().getValidator(); 28 | 29 | private ValidatorUtil() {} 30 | 31 | /** 32 | * check parameters. 33 | * @param obj obj 34 | * @param T 35 | * @return 36 | */ 37 | public static Either validate(T obj) { 38 | Set> set = validator.validate(obj); 39 | if (set == null || set.isEmpty()) { 40 | return Either.left(true); 41 | } 42 | StringBuilder sb = new StringBuilder(); 43 | for (ConstraintViolation violation : set) { 44 | sb.append(violation.getPropertyPath().toString()); 45 | sb.append(":"); 46 | sb.append(violation.getMessage()).append(". "); 47 | } 48 | return Either.right(sb.toString()); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/config/security/LoginFailureListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.config.security; 18 | 19 | import org.edgegallery.user.auth.utils.UserLockUtil; 20 | import org.springframework.beans.factory.annotation.Autowired; 21 | import org.springframework.context.ApplicationListener; 22 | import org.springframework.security.authentication.BadCredentialsException; 23 | import org.springframework.security.authentication.event.AbstractAuthenticationFailureEvent; 24 | import org.springframework.stereotype.Component; 25 | 26 | @Component 27 | public class LoginFailureListener implements ApplicationListener { 28 | 29 | @Autowired 30 | private UserLockUtil userLockUtil; 31 | 32 | @Override 33 | public void onApplicationEvent(AbstractAuthenticationFailureEvent event) { 34 | if (event.getException().getClass().equals(BadCredentialsException.class)) { 35 | // when login failed, the getName method return original login credential: user name or email or telephone 36 | String userFlag = event.getAuthentication().getName(); 37 | userLockUtil.addFailedCount(userFlag); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/controller/dto/request/VerificationReqByMailDto.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.controller.dto.request; 18 | 19 | import com.fasterxml.jackson.annotation.JsonProperty; 20 | import com.google.gson.annotations.SerializedName; 21 | import io.swagger.annotations.ApiModelProperty; 22 | import javax.validation.constraints.Pattern; 23 | import lombok.Getter; 24 | import lombok.Setter; 25 | import org.edgegallery.user.auth.config.ServiceConfig; 26 | import org.edgegallery.user.auth.config.validate.AbstractCheckParamsGenericUtils; 27 | import org.edgegallery.user.auth.config.validate.IStringTrim; 28 | import org.springframework.util.StringUtils; 29 | 30 | @Setter 31 | @Getter 32 | public class VerificationReqByMailDto extends AbstractCheckParamsGenericUtils implements IStringTrim { 33 | 34 | @SerializedName("mailAddress") 35 | @JsonProperty("mailAddress") 36 | @ApiModelProperty(required = true, example = "test@edgegallery.org") 37 | @Pattern(regexp = ServiceConfig.PATTERN_MAILADDRESS) 38 | private String mailAddress; 39 | 40 | @Override 41 | public void stringTrim() { 42 | this.mailAddress = StringUtils.trimWhitespace(mailAddress); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/config/security/OAuthRedirectStrategy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.config.security; 18 | 19 | import java.io.IOException; 20 | import javax.servlet.http.HttpServletRequest; 21 | import javax.servlet.http.HttpServletResponse; 22 | import org.springframework.security.web.DefaultRedirectStrategy; 23 | 24 | public class OAuthRedirectStrategy extends DefaultRedirectStrategy { 25 | @Override 26 | public void sendRedirect(HttpServletRequest request, HttpServletResponse response, String url) throws IOException { 27 | String redirectUrl = calculateRedirectUrl(request.getContextPath(), url); 28 | Object returnToAttr = request.getSession().getAttribute("return_to"); 29 | Object enableSms = request.getSession().getAttribute("enableSms"); 30 | Object enableMail = request.getSession().getAttribute("enableMail"); 31 | if (returnToAttr != null && enableSms != null && enableMail != null) { 32 | redirectUrl += "?return_to=" + returnToAttr.toString(); 33 | redirectUrl += "&enable_sms=" + enableSms.toString(); 34 | redirectUrl += "&enable_mail=" + enableMail.toString(); 35 | } 36 | response.sendRedirect(redirectUrl); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/external/iam/ExternalUserUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.external.iam; 18 | 19 | import org.edgegallery.user.auth.db.EnumRole; 20 | import org.edgegallery.user.auth.utils.Consts; 21 | import org.springframework.util.StringUtils; 22 | 23 | public final class ExternalUserUtil { 24 | 25 | private ExternalUserUtil() {} 26 | 27 | /** 28 | * judge is external user. 29 | * 30 | * @param userInfo user info 31 | * @return true if external user, otherwise false 32 | */ 33 | public static boolean isExternalUser(String userInfo) { 34 | if (StringUtils.isEmpty(userInfo)) { 35 | return true; 36 | } 37 | 38 | return userInfo.startsWith(Consts.EXTERNAL_USER_PREFIX); 39 | } 40 | 41 | /** 42 | * convert user role. 43 | * 44 | * @param userRole user role 45 | * @return EnumRole 46 | */ 47 | public static EnumRole convertUserRole(String userRole) { 48 | if (StringUtils.isEmpty(userRole)) { 49 | return EnumRole.TENANT; 50 | } 51 | 52 | try { 53 | return EnumRole.valueOf(userRole); 54 | } catch (IllegalArgumentException iae) { 55 | return EnumRole.TENANT; 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/resources/log4j2.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 23 | 24 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/db/entity/TenantPo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.db.entity; 18 | 19 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 20 | import java.util.UUID; 21 | import javax.persistence.Entity; 22 | import javax.persistence.Id; 23 | import javax.persistence.Table; 24 | import lombok.Getter; 25 | import lombok.Setter; 26 | 27 | @Entity 28 | @Table(name = "tbl_tenant") 29 | @JsonIgnoreProperties(ignoreUnknown = true) 30 | @Setter 31 | @Getter 32 | public class TenantPo { 33 | 34 | @Id 35 | private String tenantId; 36 | 37 | private String username; 38 | 39 | private String password; 40 | 41 | private String company; 42 | 43 | private String telephoneNumber; 44 | 45 | private String mailAddress; 46 | 47 | private String gender; 48 | 49 | // default is true 50 | private boolean isAllowed = true; 51 | 52 | private String createTime; 53 | 54 | private String modifyTime; 55 | 56 | public void setTenantId(String tenantId) { 57 | this.tenantId = tenantId; 58 | } 59 | 60 | /** 61 | * generate tenant id. 62 | * 63 | * @return 64 | */ 65 | public String getTenantId() { 66 | if (this.tenantId == null) { 67 | this.tenantId = UUID.randomUUID().toString(); 68 | } 69 | return this.tenantId; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/controller/dto/request/UniqueReqDto.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.controller.dto.request; 18 | 19 | import io.swagger.annotations.ApiModelProperty; 20 | import javax.validation.constraints.Pattern; 21 | import lombok.Getter; 22 | import lombok.Setter; 23 | import org.edgegallery.user.auth.config.ServiceConfig; 24 | import org.edgegallery.user.auth.config.validate.AbstractCheckParamsGenericUtils; 25 | import org.edgegallery.user.auth.config.validate.IStringTrim; 26 | import org.springframework.util.StringUtils; 27 | 28 | 29 | @Getter 30 | @Setter 31 | public class UniqueReqDto extends AbstractCheckParamsGenericUtils implements IStringTrim { 32 | 33 | @ApiModelProperty(required = true, example = "zhangtest") 34 | @Pattern(regexp = ServiceConfig.PATTERN_USERNAME) 35 | private String username; 36 | 37 | @ApiModelProperty(example = "15191881203") 38 | @Pattern(regexp = ServiceConfig.PATTERN_TELEPHONE) 39 | private String telephone; 40 | 41 | @ApiModelProperty(example = "test@edgegallery.org") 42 | @Pattern(regexp = ServiceConfig.PATTERN_MAILADDRESS) 43 | private String mailAddress; 44 | 45 | @Override 46 | public void stringTrim() { 47 | this.username = StringUtils.trimWhitespace(username); 48 | this.telephone = StringUtils.trimWhitespace(telephone); 49 | this.mailAddress = StringUtils.trimWhitespace(mailAddress); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/utils/Consts.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.utils; 18 | 19 | import java.time.format.DateTimeFormatter; 20 | 21 | public class Consts { 22 | 23 | private Consts() { 24 | } 25 | 26 | public static final String SUPER_ADMIN_NAME = "admin"; 27 | 28 | public static final String GUEST_USER_NAME = "guest"; 29 | 30 | public static final String GUEST_USER_PW = "guest"; 31 | 32 | public static final String DATE_PATTERN = "yyyy-MM-dd"; 33 | 34 | public static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern(DATE_PATTERN); 35 | 36 | public static final int FIRST_LOGIN_JUDGE_DAYCOUNT = 5 * 365; 37 | 38 | public static final long MILLIS_ONE_DAY = 1 * 24 * 3600 * 1000L; 39 | 40 | public static final int SECOND_HALF_DAY = 3600 * 12; 41 | 42 | public static final int CLIENT_LOGIN_TIMEOUT = 5000; 43 | 44 | public static final class PwModifyScene { 45 | private PwModifyScene() { 46 | } 47 | 48 | public static final int FIRSTLOGIN = 1; 49 | 50 | public static final int EXPIRED = 2; 51 | } 52 | 53 | public static final String GRANT_TYPE = "authorization_code"; 54 | 55 | public static final String EXTERNAL_USER_PREFIX = "EU-"; 56 | 57 | public static final class ExternalUserType { 58 | private ExternalUserType() { 59 | } 60 | 61 | public static final String EXTERNAL_IAM_USER = "1"; 62 | } 63 | } 64 | 65 | -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2020-2021 Huawei Technologies Co., Ltd. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | ##### Redis config ##### 17 | redis.ip=${REDIS_IP:user-mgmt-redis-svc} 18 | redis.port=${REDIS_PORT:6379} 19 | redis.password=${REDIS_PASSWORD:} 20 | redis.verificationTimeout=${REDIS_VERIFICATION_TIMEOUT:300} 21 | redis.imgVerificationTimeout=${REDIS_IMG_VERIFICATION_TIMEOUT:180} 22 | redis.maxTotal=${REDIS_MAX_TOTAL:1000} 23 | redis.maxIdle=${REDIS_MAX_IDLE:50} 24 | redis.maxWaitMillis=${REDIS_MAX_WAIT_MILLIS:100000} 25 | #### SMS config #### 26 | sms.enabled=${SMS_ENABLED:false} 27 | sms.url=${SMS_URL:} 28 | sms.appKey=${SMS_APP_KEY:} 29 | sms.appSecret=${SMS_APP_SECRET:} 30 | sms.sender=${SMS_SENDER:} 31 | sms.templateId=${SMS_TEMPLATE_ID:} 32 | sms.signature=${SMS_APP_SIGNATURE:} 33 | sms.statusCallBack=${SMS_STATUS_CALL_BACK:} 34 | #### Mail config #### 35 | mail.enabled=${MAIL_ENABLED:false} 36 | spring.mail.host=${MAIL_HOST:} 37 | spring.mail.port=${MAIL_PORT:25} 38 | spring.mail.username=${MAIL_SENDER:} 39 | spring.mail.password=${MAIL_AUTH_CODE:} 40 | spring.mail.default-encoding=UTF-8 41 | #### jwt config #### 42 | jwt.publicKey=${JWT_PUBLIC_KEY:} 43 | jwt.encryptedPrivateKey=${JWT_ENCRYPTED_PRIVATE_KEY:} 44 | jwt.encryptPassword=${JWT_ENCRYPT_PASSWORD:} 45 | #### cors config #### 46 | cors.allow.origins=${CORS_ALLOW_ORIGINS:*} 47 | #### security policy config #### 48 | secPolicy.pwTimeout=${SECPOLICY_PW_TIMEOUT:90} 49 | #### external iam config #### 50 | external.iam.enabled=${EXTERNAL_IAM_ENABLED:false} 51 | external.iam.endpoint=${EXTERNAL_IAM_ENDPOINT:} 52 | -------------------------------------------------------------------------------- /docker/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2020-2021 Huawei Technologies Co., Ltd. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | FROM swr.cn-north-4.myhuaweicloud.com/eg-common/openjdk:8u201-jre-alpine 16 | 17 | # Define all environment variable here 18 | ENV JAVA_HOME /usr/lib/jvm/java-1.8-openjdk 19 | ENV TZ='Asia/Shanghai' 20 | ENV APP_FILE user-mgmt-be.jar 21 | ENV APP_HOME /usr/app 22 | ENV UID=166 23 | ENV GID=166 24 | ENV USER_NAME=eguser 25 | ENV GROUP_NAME=eggroup 26 | ENV ENV="/etc/profile" 27 | 28 | # # CREATE APP USER ## 29 | # Set umask 30 | RUN sed -i "s|umask 022|umask 027|g" /etc/profile 31 | 32 | # Create the home directory for the new app user. 33 | RUN mkdir -p /usr/app 34 | RUN mkdir -p /usr/app/bin 35 | 36 | # Create an app user so our program doesn't run as root. 37 | RUN apk update &&\ 38 | apk add shadow &&\ 39 | apk add --update ttf-dejavu fontconfig &&\ 40 | groupadd -r -g $GID $GROUP_NAME &&\ 41 | useradd -r -u $UID -g $GID -d $APP_HOME -s /sbin/nologin -c "Docker image user" $USER_NAME 42 | 43 | WORKDIR $APP_HOME 44 | 45 | RUN chmod -R 750 $APP_HOME &&\ 46 | chmod -R 550 $APP_HOME/bin &&\ 47 | mkdir -p -m 750 $APP_HOME/config &&\ 48 | mkdir -p -m 750 $APP_HOME/log &&\ 49 | mkdir -p -m 700 $APP_HOME/ssl &&\ 50 | chown -R $USER_NAME:$GROUP_NAME $APP_HOME &&\ 51 | chown -R $USER_NAME:$GROUP_NAME $APP_HOME/log 52 | 53 | COPY --chown=$USER_NAME:$GROUP_NAME target/*.jar $APP_HOME/bin 54 | 55 | EXPOSE 8067 56 | # Change to the app user. 57 | USER $USER_NAME 58 | # Execute script & application 59 | ENTRYPOINT ["sh", "-c"] 60 | CMD ["exec java -jar -Dlog4j2.formatMsgNoLookups=true ./bin/$APP_FILE"] 61 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/db/mapper/TenantPoMapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.db.mapper; 18 | 19 | import java.util.List; 20 | import org.apache.ibatis.annotations.Mapper; 21 | import org.edgegallery.user.auth.controller.dto.request.QueryUserReqDto; 22 | import org.edgegallery.user.auth.controller.dto.response.TenantRespDto; 23 | import org.edgegallery.user.auth.db.entity.RolePo; 24 | import org.edgegallery.user.auth.db.entity.TenantPo; 25 | 26 | @Mapper 27 | public interface TenantPoMapper { 28 | 29 | /** 30 | * saving the driver instance object to the DB using the mybaties. 31 | */ 32 | 33 | TenantPo getTenantBasicPoData(String tenantId); 34 | 35 | TenantPo getTenantByTelephone(String telephoneNumber); 36 | 37 | TenantPo getTenantByMailAddress(String mailAddress); 38 | 39 | TenantPo getTenantByUsername(String username); 40 | 41 | TenantPo getTenantByUniqueFlag(String uniqueFlag); 42 | 43 | int updateTenantById(TenantRespDto user); 44 | 45 | void deleteRolesByTenantId(String tenantId); 46 | 47 | List getRolePoByTenantId(String tenantId); 48 | 49 | int addTenantPo(TenantPo tenantPo); 50 | 51 | int modifyPassword(String tenantId, String password); 52 | 53 | String getPwEffectTime(String username); 54 | 55 | int insertRolesByTenantId(String tenantId, List roles); 56 | 57 | boolean deleteUser(String tenantId); 58 | 59 | Integer queryUserCount(QueryUserReqDto queryReq); 60 | 61 | List queryUsers(QueryUserReqDto queryReq); 62 | 63 | boolean updateStatus(String tenantId, boolean allowFlag); 64 | 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/config/filter/GuestUserAuthenticationFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.config.filter; 18 | 19 | import javax.servlet.http.HttpServletRequest; 20 | import javax.servlet.http.HttpServletResponse; 21 | import org.edgegallery.user.auth.utils.Consts; 22 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 23 | import org.springframework.security.core.Authentication; 24 | import org.springframework.security.core.AuthenticationException; 25 | import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; 26 | import org.springframework.security.web.util.matcher.AntPathRequestMatcher; 27 | 28 | public class GuestUserAuthenticationFilter extends AbstractAuthenticationProcessingFilter { 29 | 30 | // default user is "guest", accessing from root url "/". 31 | public GuestUserAuthenticationFilter() { 32 | super(new AntPathRequestMatcher("/", "GET")); 33 | } 34 | 35 | @Override 36 | public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) 37 | throws AuthenticationException { 38 | UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken( 39 | Consts.GUEST_USER_NAME, Consts.GUEST_USER_PW); 40 | this.setDetails(request, authRequest); 41 | return this.getAuthenticationManager().authenticate(authRequest); 42 | } 43 | 44 | protected void setDetails(HttpServletRequest request, UsernamePasswordAuthenticationToken authRequest) { 45 | authRequest.setDetails(this.authenticationDetailsSource.buildDetails(request)); 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/service/MailService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.service; 18 | 19 | import org.slf4j.Logger; 20 | import org.slf4j.LoggerFactory; 21 | import org.springframework.beans.factory.annotation.Autowired; 22 | import org.springframework.beans.factory.annotation.Value; 23 | import org.springframework.mail.MailException; 24 | import org.springframework.mail.SimpleMailMessage; 25 | import org.springframework.mail.javamail.JavaMailSender; 26 | import org.springframework.stereotype.Service; 27 | 28 | @Service 29 | public class MailService { 30 | private static final Logger LOGGER = LoggerFactory.getLogger(MailService.class); 31 | 32 | @Autowired 33 | private JavaMailSender mailSender; 34 | 35 | @Value("${spring.mail.username}") 36 | private String from; 37 | 38 | /** 39 | * send simple mail. 40 | * 41 | * @param receiver mail receiver 42 | * @param subject mail subject 43 | * @param content mail content 44 | * @return true if send success, otherwise false 45 | */ 46 | public boolean sendSimpleMail(String receiver, String subject, String content) { 47 | SimpleMailMessage message = new SimpleMailMessage(); 48 | message.setFrom(from); 49 | message.setTo(receiver); 50 | message.setSubject(subject); 51 | message.setText(content); 52 | 53 | try { 54 | mailSender.send(message); 55 | } catch (MailException mailEx) { 56 | LOGGER.error("send simple mail failed, error is {}", mailEx.getMessage()); 57 | return false; 58 | } 59 | 60 | LOGGER.info("send simple mail success"); 61 | return true; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/controller/dto/request/QueryUserCtrlDto.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.controller.dto.request; 18 | 19 | import io.swagger.annotations.ApiModelProperty; 20 | import javax.validation.constraints.Max; 21 | import javax.validation.constraints.Min; 22 | import javax.validation.constraints.Pattern; 23 | import lombok.Getter; 24 | import lombok.Setter; 25 | import org.edgegallery.user.auth.config.validate.AbstractCheckParamsGenericUtils; 26 | import org.edgegallery.user.auth.config.validate.IStringTrim; 27 | import org.springframework.util.StringUtils; 28 | 29 | @Setter 30 | @Getter 31 | public class QueryUserCtrlDto extends AbstractCheckParamsGenericUtils implements IStringTrim { 32 | private static final String DEFAULT_SORTBY = "createTime"; 33 | 34 | private static final String DEFAULT_SORTORDER = "DESC"; 35 | 36 | @Min(value = -1) 37 | private int offset; 38 | 39 | @Min(value = 0) 40 | @Max(value = 100) 41 | private int limit; 42 | 43 | @ApiModelProperty(example = "userName") 44 | @Pattern(regexp = "(?i)userName|(?i)createTime") 45 | private String sortBy; 46 | 47 | @ApiModelProperty(example = "ASC") 48 | @Pattern(regexp = "(?i)ASC|(?i)DESC") 49 | private String sortOrder; 50 | 51 | /** 52 | * check basic data by trim. 53 | */ 54 | public void stringTrim() { 55 | this.sortBy = StringUtils.trimWhitespace(this.sortBy); 56 | if (StringUtils.isEmpty(this.sortBy)) { 57 | this.sortBy = DEFAULT_SORTBY; 58 | } 59 | 60 | this.sortOrder = StringUtils.trimWhitespace(this.sortOrder); 61 | if (StringUtils.isEmpty(this.sortOrder)) { 62 | this.sortOrder = DEFAULT_SORTORDER; 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/controller/dto/response/TenantRespDto.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.controller.dto.response; 18 | 19 | import io.swagger.annotations.ApiModelProperty; 20 | import java.util.ArrayList; 21 | import java.util.List; 22 | import lombok.Getter; 23 | import lombok.Setter; 24 | import lombok.ToString; 25 | import org.edgegallery.user.auth.db.entity.RolePo; 26 | import org.edgegallery.user.auth.db.entity.TenantPo; 27 | 28 | @ToString 29 | @Setter 30 | @Getter 31 | public class TenantRespDto extends BaseTenantRespDto { 32 | 33 | @ApiModelProperty(required = true, example = "37423702-051a-46b4-bf2b-f190759cc0b8") 34 | private String userId; 35 | 36 | @ApiModelProperty(required = true) 37 | private List permissions; 38 | 39 | /** 40 | * set tenant response value. 41 | */ 42 | public void setResponse(TenantPo tenantPo) { 43 | this.setUserId(tenantPo.getTenantId()); 44 | this.setUsername(tenantPo.getUsername()); 45 | this.setMailAddress(tenantPo.getMailAddress()); 46 | this.setTelephone(tenantPo.getTelephoneNumber()); 47 | this.setAllowed(tenantPo.isAllowed()); 48 | this.setCreateTime(tenantPo.getCreateTime()); 49 | 50 | this.anonymize(); 51 | } 52 | 53 | /** 54 | * set tenant role permission. 55 | */ 56 | public void setPermission(List rolePos) { 57 | List roleDtos = new ArrayList<>(); 58 | for (RolePo rolePo : rolePos) { 59 | RoleDto dto = new RoleDto(); 60 | dto.setPlatform(rolePo.getPlatform()); 61 | dto.setRole(rolePo.getRole()); 62 | roleDtos.add(dto); 63 | } 64 | this.setPermissions(roleDtos); 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/controller/dto/request/BaseTenantBasicReqDto.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.controller.dto.request; 18 | 19 | import io.swagger.annotations.ApiModelProperty; 20 | import javax.validation.constraints.Pattern; 21 | import lombok.Getter; 22 | import lombok.Setter; 23 | import org.edgegallery.user.auth.config.ServiceConfig; 24 | import org.edgegallery.user.auth.config.validate.AbstractCheckParamsGenericUtils; 25 | import org.edgegallery.user.auth.config.validate.IStringTrim; 26 | import org.springframework.util.StringUtils; 27 | 28 | @Setter 29 | @Getter 30 | public abstract class BaseTenantBasicReqDto extends AbstractCheckParamsGenericUtils implements IStringTrim { 31 | 32 | @ApiModelProperty(required = true, example = "TestUser1") 33 | @Pattern(regexp = ServiceConfig.PATTERN_USERNAME) 34 | private String username; 35 | 36 | @ApiModelProperty(required = true, example = "huawei") 37 | private String company; 38 | 39 | @ApiModelProperty(required = true, example = "male") 40 | private String gender; 41 | 42 | @ApiModelProperty(example = "15533449966") 43 | private String telephone; 44 | 45 | @ApiModelProperty(example = "test@edgegallery.org") 46 | private String mailAddress; 47 | 48 | private boolean isAllowed = true; 49 | 50 | /** 51 | * check basic data by trim. 52 | */ 53 | public void stringTrim() { 54 | this.username = StringUtils.trimWhitespace(this.username); 55 | this.company = StringUtils.trimWhitespace(this.company); 56 | this.gender = StringUtils.trimWhitespace(this.gender); 57 | this.telephone = StringUtils.trimWhitespace(this.telephone); 58 | this.mailAddress = StringUtils.trimWhitespace(this.mailAddress); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/resources/usermgmtdb-data.sql: -------------------------------------------------------------------------------- 1 | -- supported platforms and roles 2 | insert into tbl_role (ID, PLATFORM, ROLE) values 3 | (1, 'APPSTORE', 'GUEST'),(2, 'APPSTORE', 'TENANT'),(3, 'APPSTORE', 'ADMIN'), 4 | (4, 'DEVELOPER', 'GUEST'),(5, 'DEVELOPER', 'TENANT'),(6, 'DEVELOPER', 'ADMIN'), 5 | (7, 'MECM', 'GUEST'),(8, 'MECM', 'TENANT'),(9, 'MECM', 'ADMIN'), 6 | (10, 'ATP', 'GUEST'),(11, 'ATP', 'TENANT'),(12, 'ATP', 'ADMIN'), 7 | (13, 'LAB', 'GUEST'),(14, 'LAB', 'TENANT'),(15, 'LAB', 'ADMIN'), 8 | (16, 'APPMGMT', 'GUEST'),(17, 'APPMGMT', 'TENANT'),(18, 'APPMGMT', 'ADMIN') 9 | ON CONFLICT(id) do nothing; 10 | 11 | -- add a guest user 12 | insert into tbl_tenant (TENANTID, USERNAME, PASSWORD, COMPANY, TELEPHONENUMBER, MAILADDRESS, GENDER, isallowed, CREATETIME, MODIFYTIME) 13 | values('de3565b1-a7c2-42b9-b281-3f032af29ff7', 'guest', 14 | '59756fda85ebddee6024d5cc0e6edcde3226693257a9c1eb662c56426b8a4f232b3d56c321adbd91', 'company', '13800000000', '13800000000@edgegallery.org', '1', true, now(), now()) 15 | ON CONFLICT(TENANTID) do nothing; 16 | 17 | -- add a admin user 18 | insert into tbl_tenant (TENANTID, USERNAME, PASSWORD, COMPANY, TELEPHONENUMBER, MAILADDRESS, GENDER, isallowed, CREATETIME, MODIFYTIME, PWEFFECTTIME) 19 | values('39937079-99fe-4cd8-881f-04ca8c4fe09d', 'admin', 20 | '45709693f38464c0c0fbf525ec7a740ddf63e28ef39e56836601dc43b00ed20c86713bbcd73bb215', 'company', '13800000001', '13800000001@edgegallery.org', '1', true, now(), now(), now() - interval '10y') 21 | ON CONFLICT(TENANTID) do nothing; 22 | 23 | -- set the permissions for guest user 24 | insert into tbl_tenant_role (TENANTID, ROLEID) values 25 | ('de3565b1-a7c2-42b9-b281-3f032af29ff7', 1), 26 | ('de3565b1-a7c2-42b9-b281-3f032af29ff7', 4), 27 | ('de3565b1-a7c2-42b9-b281-3f032af29ff7', 7), 28 | ('de3565b1-a7c2-42b9-b281-3f032af29ff7', 10), 29 | ('de3565b1-a7c2-42b9-b281-3f032af29ff7', 13), 30 | ('de3565b1-a7c2-42b9-b281-3f032af29ff7', 16) 31 | ON CONFLICT(TENANTID, ROLEID) do nothing; 32 | 33 | insert into tbl_tenant_role (TENANTID, ROLEID) values 34 | ('39937079-99fe-4cd8-881f-04ca8c4fe09d', 3), 35 | ('39937079-99fe-4cd8-881f-04ca8c4fe09d', 6), 36 | ('39937079-99fe-4cd8-881f-04ca8c4fe09d', 9), 37 | ('39937079-99fe-4cd8-881f-04ca8c4fe09d', 12), 38 | ('39937079-99fe-4cd8-881f-04ca8c4fe09d', 15), 39 | ('39937079-99fe-4cd8-881f-04ca8c4fe09d', 18) 40 | ON CONFLICT(TENANTID, ROLEID) do nothing; -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/utils/AnonymizeUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.utils; 18 | 19 | import org.apache.commons.lang3.StringUtils; 20 | 21 | public final class AnonymizeUtil { 22 | 23 | private static final int MOBILE_PHONE_LEN = 11; 24 | 25 | private static final String MASK_SIGN = "****"; 26 | 27 | private AnonymizeUtil() {} 28 | 29 | /** 30 | * anonymize mail address. 31 | * 32 | * @param phoneNum mobile phone number 33 | * @return anonymized phone number 34 | */ 35 | public static String anonymizePhoneNum(String phoneNum) { 36 | if (StringUtils.isEmpty(phoneNum) || phoneNum.length() != MOBILE_PHONE_LEN) { 37 | return phoneNum; 38 | } 39 | return phoneNum.substring(0, 3).concat(MASK_SIGN).concat(phoneNum.substring(7)); 40 | } 41 | 42 | /** 43 | * anonymize mail address. 44 | * 45 | * @param mailAddress email address 46 | * @return anonymized email address 47 | */ 48 | public static String anonymizeMail(String mailAddress) { 49 | if (StringUtils.isEmpty(mailAddress)) { 50 | return mailAddress; 51 | } 52 | 53 | int pos = mailAddress.indexOf("@"); 54 | if (pos <= 1) { 55 | return mailAddress; 56 | } 57 | 58 | return mailAddress.substring(0, 1).concat(MASK_SIGN).concat(mailAddress.substring(pos)); 59 | } 60 | 61 | /** 62 | * check if anonymized. 63 | * 64 | * @param strValue check str 65 | * @return if anonymized 66 | */ 67 | public static boolean isAnonymized(String strValue) { 68 | if (StringUtils.isEmpty(strValue)) { 69 | return false; 70 | } 71 | 72 | return strValue.indexOf(MASK_SIGN) >= 0; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/controller/dto/response/BaseTenantRespDto.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.controller.dto.response; 18 | 19 | import io.swagger.annotations.ApiModelProperty; 20 | import lombok.Getter; 21 | import lombok.Setter; 22 | import org.edgegallery.user.auth.db.entity.TenantPo; 23 | import org.edgegallery.user.auth.utils.AnonymizeUtil; 24 | import org.springframework.util.StringUtils; 25 | 26 | @Setter 27 | @Getter 28 | public abstract class BaseTenantRespDto { 29 | 30 | @ApiModelProperty(required = true, example = "TestUser1") 31 | private String username; 32 | 33 | @ApiModelProperty(required = true, example = "test@edgegallery.org") 34 | private String mailAddress; 35 | 36 | @ApiModelProperty(required = true, example = "15533449966") 37 | private String telephone; 38 | 39 | private boolean isAllowed; 40 | 41 | private String createTime; 42 | 43 | /** 44 | * check basic data by trim. 45 | */ 46 | public void trim() { 47 | this.username = StringUtils.trimWhitespace(this.username); 48 | this.mailAddress = StringUtils.trimWhitespace(this.mailAddress); 49 | this.telephone = StringUtils.trimWhitespace(this.telephone); 50 | } 51 | 52 | /** 53 | * anonymize some sensitive information. 54 | */ 55 | public void anonymize() { 56 | this.telephone = AnonymizeUtil.anonymizePhoneNum(this.telephone); 57 | this.mailAddress = AnonymizeUtil.anonymizeMail(this.mailAddress); 58 | } 59 | 60 | /** 61 | * assign anonymized value. 62 | * 63 | * @param oldUserPo old user po object 64 | */ 65 | public void assignAnonymizedValue(TenantPo oldUserPo) { 66 | if (AnonymizeUtil.isAnonymized(this.telephone)) { 67 | setTelephone(oldUserPo.getTelephoneNumber()); 68 | } 69 | if (AnonymizeUtil.isAnonymized(this.mailAddress)) { 70 | setMailAddress(oldUserPo.getMailAddress()); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/config/DescriptionConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.config; 18 | 19 | public class DescriptionConfig { 20 | 21 | private DescriptionConfig() { 22 | } 23 | 24 | public static final String REGISTER_MSG = "The API can receive register user request. If register success, it will " 25 | + "return status 201. If username or telephone has existed, or verification code is error, it will reutrn " 26 | + "status 403. If database connection has exception, it will return status 500. If register failed, it " 27 | + "will return status 400."; 28 | 29 | public static final String MODIFY_PASSWORD_MSG = "The API can receive the modify password request. If modify " 30 | + "success, it will return status 200. If the user do not exist or the verification code is error, it " 31 | + "will return status 403. If database connection has exception, it will return status 500. If modify " 32 | + "failed, it will return status 400."; 33 | 34 | public static final String VERIFICATION_SMS_MSG = 35 | "The API can receive the send verification code by sms request. If send " 36 | + "verification code success, it will return status 200. If send verification code error, it will return " 37 | + "status 417."; 38 | 39 | public static final String VERIFICATION_MAIL_MSG = 40 | "The API can receive the send verification code by mail request. If send " 41 | + "verification code success, it will return status 200. If send verification code error, it will return " 42 | + "status 417."; 43 | 44 | public static final String UNIQUENESS_MSG = "The API can receive the unique verify request for mailAddress or " 45 | + "telephone or username. If the request param is unique, it will return status 200, " 46 | + "otherwise it will return status 400."; 47 | 48 | public static final String LOGOUT_MSG = "The API can receive the logout request, If logout successful, it will" 49 | + " return status 200, otherwise it will return status 500."; 50 | } 51 | 52 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/external/iam/model/ExternalUser.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.external.iam.model; 18 | 19 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 20 | import com.fasterxml.jackson.annotation.JsonProperty; 21 | import lombok.AllArgsConstructor; 22 | import lombok.Getter; 23 | import lombok.NoArgsConstructor; 24 | import lombok.Setter; 25 | import org.edgegallery.user.auth.external.iam.ExternalUserUtil; 26 | import org.edgegallery.user.auth.utils.Consts; 27 | 28 | @JsonIgnoreProperties(ignoreUnknown = true) 29 | @Setter 30 | @Getter 31 | @AllArgsConstructor 32 | @NoArgsConstructor 33 | public class ExternalUser { 34 | 35 | private static final int COMBINED_USERINFO_LEN = 5; 36 | 37 | @JsonProperty("userId") 38 | private String userId; 39 | 40 | @JsonProperty("userName") 41 | private String userName; 42 | 43 | @JsonProperty("mailAddress") 44 | private String mailAddress; 45 | 46 | @JsonProperty("userRole") 47 | private String userRole; 48 | 49 | /** 50 | * build combined user info. 51 | * 52 | * @return combined user info 53 | */ 54 | public String build() { 55 | StringBuilder combinedUserInfo = new StringBuilder(Consts.EXTERNAL_USER_PREFIX) 56 | .append(Consts.ExternalUserType.EXTERNAL_IAM_USER).append(";") 57 | .append(getUserId()).append(";") 58 | .append(getUserName()).append(";") 59 | .append(getMailAddress() == null ? "" : getMailAddress()).append(";") 60 | .append(ExternalUserUtil.convertUserRole(getUserRole())).append(";"); 61 | return combinedUserInfo.toString(); 62 | } 63 | 64 | /** 65 | * parse from combined user info. 66 | * 67 | * @param combinedUserInfo combined user info 68 | */ 69 | public void parse(String combinedUserInfo) { 70 | String[] combinedUserInfoArr = combinedUserInfo.split(";"); 71 | if (combinedUserInfoArr.length < COMBINED_USERINFO_LEN) { 72 | return; 73 | } 74 | 75 | int index = 1; 76 | setUserId(combinedUserInfoArr[index++]); 77 | setUserName(combinedUserInfoArr[index++]); 78 | setMailAddress(combinedUserInfoArr[index++]); 79 | setUserRole(combinedUserInfoArr[index]); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/config/security/OAuthUnauthorizedEntryPoint.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.config.security; 18 | 19 | import java.io.IOException; 20 | import javax.servlet.ServletException; 21 | import javax.servlet.http.HttpServletRequest; 22 | import javax.servlet.http.HttpServletResponse; 23 | import org.springframework.security.core.AuthenticationException; 24 | import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint; 25 | 26 | public class OAuthUnauthorizedEntryPoint extends LoginUrlAuthenticationEntryPoint { 27 | private String enableSmsStr; 28 | 29 | private String enableMailStr; 30 | 31 | /** 32 | * constructor. 33 | * 34 | * @param loginFormUrl login form url 35 | * @param enableSmsStr enable sms flag 36 | * @param enableMailStr enable mail flag 37 | */ 38 | public OAuthUnauthorizedEntryPoint(String loginFormUrl, String enableSmsStr, String enableMailStr) { 39 | super(loginFormUrl); 40 | this.enableSmsStr = enableSmsStr; 41 | this.enableMailStr = enableMailStr; 42 | } 43 | 44 | @Override 45 | public void commence(HttpServletRequest request, HttpServletResponse response, 46 | AuthenticationException authException) throws IOException, ServletException { 47 | String queryString = request.getQueryString(); 48 | if (queryString != null && queryString.contains("redirect_uri")) { 49 | String[] params = queryString.split("&"); 50 | for (String param : params) { 51 | if (param.contains("redirect_uri")) { 52 | String returnToUrl = param.replace("redirect_uri=", "").replace("/login", ""); 53 | request.getSession().setAttribute("return_to", returnToUrl); 54 | request.getSession().setAttribute("enableSms", enableSmsStr); 55 | request.getSession().setAttribute("enableMail", enableMailStr); 56 | break; 57 | } 58 | } 59 | } 60 | OAuthRedirectStrategy oauthRedirectStrategy = new OAuthRedirectStrategy(); 61 | String redirectUrl = buildRedirectUrlToLoginPage(request, response, authException); 62 | oauthRedirectStrategy.sendRedirect(request, response, redirectUrl); 63 | } 64 | } -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/config/security/LoginFailHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.config.security; 18 | 19 | import com.google.gson.Gson; 20 | import java.io.IOException; 21 | import javax.servlet.http.HttpServletRequest; 22 | import javax.servlet.http.HttpServletResponse; 23 | import org.edgegallery.user.auth.controller.dto.response.ErrorRespDto; 24 | import org.edgegallery.user.auth.utils.ErrorEnum; 25 | import org.slf4j.Logger; 26 | import org.slf4j.LoggerFactory; 27 | import org.springframework.http.HttpStatus; 28 | import org.springframework.http.MediaType; 29 | import org.springframework.security.authentication.LockedException; 30 | import org.springframework.security.core.AuthenticationException; 31 | import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler; 32 | import org.springframework.stereotype.Component; 33 | 34 | @Component 35 | public class LoginFailHandler extends SimpleUrlAuthenticationFailureHandler { 36 | 37 | private static final Logger LOGGER = LoggerFactory.getLogger(LoginFailHandler.class); 38 | 39 | @Override 40 | public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, 41 | AuthenticationException exception) throws IOException { 42 | response.setContentType(MediaType.APPLICATION_JSON_VALUE); 43 | ErrorRespDto errorRespDto = ErrorRespDto.build(ErrorEnum.LOGIN_FAILED); 44 | errorRespDto.setMessage(exception.getLocalizedMessage()); 45 | if (exception instanceof LockedException) { 46 | response.setStatus(HttpStatus.LOCKED.value()); 47 | response.getWriter().println( 48 | new Gson().toJson(errorRespDto)); 49 | } else { 50 | if (errorRespDto.getMessage().equalsIgnoreCase(ErrorEnum.VERIFY_CODE_ERROR.message())) { 51 | response.setStatus(HttpStatus.BAD_REQUEST.value()); 52 | errorRespDto.setCode(ErrorEnum.VERIFY_CODE_ERROR.code()); 53 | response.getWriter().println(new Gson() 54 | .toJson(errorRespDto)); 55 | } else { 56 | response.setStatus(HttpStatus.UNAUTHORIZED.value()); 57 | response.getWriter().println(new Gson() 58 | .toJson(errorRespDto)); 59 | } 60 | } 61 | LOGGER.error("failed to get token."); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/utils/UserLockUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.utils; 18 | 19 | import es.moki.ratelimitj.core.limiter.request.RequestLimitRule; 20 | import es.moki.ratelimitj.core.limiter.request.RequestRateLimiter; 21 | import es.moki.ratelimitj.inmemory.request.InMemorySlidingWindowRequestRateLimiter; 22 | import java.time.Duration; 23 | import java.util.Collections; 24 | import java.util.HashMap; 25 | import java.util.Map; 26 | import java.util.Set; 27 | import org.springframework.stereotype.Component; 28 | 29 | @Component 30 | public class UserLockUtil { 31 | 32 | // when login failed 5 times, account will be locked. 33 | private static final Set REQUEST_LIMIT_RULES = Collections 34 | .singleton(RequestLimitRule.of(Duration.ofMinutes(5), 4)); 35 | 36 | // locked overtime 37 | private static final long OVERTIME = 5 * 60 * 1000L; 38 | 39 | private static final RequestRateLimiter LIMITER = new InMemorySlidingWindowRequestRateLimiter(REQUEST_LIMIT_RULES); 40 | 41 | private static final Map LOCKED_USERS_MAP = new HashMap<>(); 42 | 43 | /** 44 | * judge whether the user is locked. 45 | * 46 | * @param userFlag user flag(user name or email or telephone) 47 | * @return is the user locked 48 | */ 49 | public boolean isLocked(String userFlag) { 50 | if (!LOCKED_USERS_MAP.containsKey(userFlag)) { 51 | return false; 52 | } 53 | 54 | long lockedTime = LOCKED_USERS_MAP.get(userFlag); 55 | if (System.currentTimeMillis() - lockedTime < OVERTIME) { 56 | return true; 57 | } else { 58 | LOCKED_USERS_MAP.remove(userFlag); 59 | return false; 60 | } 61 | } 62 | 63 | /** 64 | * add failed count when login failed. 65 | * 66 | * @param userFlag user flag(user name or email or telephone) 67 | */ 68 | public void addFailedCount(String userFlag) { 69 | boolean isOverLimit = LIMITER.overLimitWhenIncremented(userFlag); 70 | if (isOverLimit) { 71 | LOCKED_USERS_MAP.put(userFlag, System.currentTimeMillis()); 72 | } 73 | } 74 | 75 | /** 76 | * clear failed count when login success. 77 | * 78 | * @param userFlag user flag(user name or email or telephone) 79 | */ 80 | public void clearFailedCount(String userFlag) { 81 | LIMITER.resetLimit(userFlag); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/external/iam/service/ExternalIamLoginImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.external.iam.service; 18 | 19 | import java.util.Arrays; 20 | import java.util.List; 21 | import java.util.stream.Collectors; 22 | import org.edgegallery.user.auth.db.EnumPlatform; 23 | import org.edgegallery.user.auth.db.EnumRole; 24 | import org.edgegallery.user.auth.external.iam.ExternalUserUtil; 25 | import org.edgegallery.user.auth.external.iam.IExternalIamLogin; 26 | import org.edgegallery.user.auth.external.iam.IExternalIamService; 27 | import org.edgegallery.user.auth.external.iam.model.ExternalUser; 28 | import org.slf4j.Logger; 29 | import org.slf4j.LoggerFactory; 30 | import org.springframework.beans.factory.annotation.Autowired; 31 | import org.springframework.security.core.GrantedAuthority; 32 | import org.springframework.security.core.authority.SimpleGrantedAuthority; 33 | import org.springframework.security.core.userdetails.User; 34 | import org.springframework.security.core.userdetails.UserDetails; 35 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 36 | import org.springframework.security.crypto.password.Pbkdf2PasswordEncoder; 37 | import org.springframework.stereotype.Component; 38 | 39 | @Component 40 | public class ExternalIamLoginImpl implements IExternalIamLogin { 41 | 42 | private static final Logger LOGGER = LoggerFactory.getLogger(ExternalIamLoginImpl.class); 43 | 44 | @Autowired 45 | private Pbkdf2PasswordEncoder passwordEncoder; 46 | 47 | @Autowired 48 | private IExternalIamService externalIamService; 49 | 50 | @Override 51 | public UserDetails loadUser(String userFlag, String password) { 52 | LOGGER.info("load user from external iam."); 53 | ExternalUser externalUser = externalIamService.login(userFlag, password); 54 | if (externalUser == null) { 55 | LOGGER.error("external login failed."); 56 | throw new UsernameNotFoundException("User not found: " + userFlag); 57 | } 58 | 59 | EnumRole userRole = ExternalUserUtil.convertUserRole(externalUser.getUserRole()); 60 | List authorities = Arrays.stream(EnumPlatform.values()) 61 | .map(plat -> new SimpleGrantedAuthority("ROLE_" + plat + "_" + userRole.toString())) 62 | .collect(Collectors.toList()); 63 | return new User(externalUser.build(), passwordEncoder.encode(password), true, true, true, true, 64 | authorities); 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/MainServer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth; 18 | 19 | import java.security.KeyManagementException; 20 | import java.security.NoSuchAlgorithmException; 21 | import java.security.cert.X509Certificate; 22 | import javax.net.ssl.HttpsURLConnection; 23 | import javax.net.ssl.SSLContext; 24 | import javax.net.ssl.TrustManager; 25 | import javax.net.ssl.X509TrustManager; 26 | import org.apache.http.conn.ssl.NoopHostnameVerifier; 27 | import org.apache.servicecomb.springboot2.starter.EnableServiceComb; 28 | import org.mybatis.spring.annotation.MapperScan; 29 | import org.slf4j.Logger; 30 | import org.slf4j.LoggerFactory; 31 | import org.springframework.boot.SpringApplication; 32 | import org.springframework.boot.autoconfigure.SpringBootApplication; 33 | import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration; 34 | import org.springframework.scheduling.annotation.EnableScheduling; 35 | 36 | @SpringBootApplication(scanBasePackages = "org.edgegallery.user.auth", exclude = {SecurityAutoConfiguration.class}) 37 | @MapperScan(basePackages = {"org.edgegallery.user.auth.db.mapper"}) 38 | @EnableScheduling 39 | @EnableServiceComb 40 | public class MainServer { 41 | private static final Logger LOGGER = LoggerFactory.getLogger(MainServer.class); 42 | 43 | /** 44 | * Main. 45 | */ 46 | public static void main(String[] args) throws NoSuchAlgorithmException, KeyManagementException { 47 | 48 | // do not check host name 49 | TrustManager[] trustAllCerts = new TrustManager[] { 50 | new X509TrustManager() { 51 | public X509Certificate[] getAcceptedIssuers() { 52 | return new X509Certificate[0]; 53 | } 54 | 55 | public void checkClientTrusted(X509Certificate[] certs, String authType) { 56 | LOGGER.info("checks client trusted"); 57 | } 58 | 59 | public void checkServerTrusted(X509Certificate[] certs, String authType) { 60 | LOGGER.info("checks server trusted"); 61 | } 62 | } 63 | }; 64 | SSLContext sc = SSLContext.getInstance("TLSv1.2"); 65 | sc.init(null, trustAllCerts, new java.security.SecureRandom()); 66 | HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); 67 | HttpsURLConnection.setDefaultHostnameVerifier(NoopHostnameVerifier.INSTANCE); 68 | SpringApplication.run(MainServer.class, args); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/db/custom/TenantTransactionRepository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.db.custom; 18 | 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | import org.edgegallery.user.auth.controller.dto.response.RoleDto; 22 | import org.edgegallery.user.auth.controller.dto.response.TenantRespDto; 23 | import org.edgegallery.user.auth.db.entity.RolePo; 24 | import org.edgegallery.user.auth.db.entity.TenantPermissionVo; 25 | import org.edgegallery.user.auth.db.mapper.TenantPoMapper; 26 | import org.springframework.beans.factory.annotation.Autowired; 27 | import org.springframework.stereotype.Repository; 28 | import org.springframework.transaction.annotation.Transactional; 29 | 30 | @Repository 31 | @Transactional(rollbackFor = {Exception.class}) 32 | public class TenantTransactionRepository { 33 | 34 | @Autowired 35 | private TenantPoMapper tenantPoMapper; 36 | 37 | 38 | /** 39 | * insert tenant into db using transactions. 40 | * 41 | * @param tenantVo tenantVo 42 | * @return 43 | */ 44 | public int registerTenant(TenantPermissionVo tenantVo) { 45 | int result = 0; 46 | result += tenantPoMapper.addTenantPo(tenantVo); 47 | result += tenantPoMapper.insertRolesByTenantId(tenantVo.getTenantId(), tenantVo.getRoles()); 48 | return result; 49 | } 50 | 51 | /** 52 | * update tenant data. 53 | * 54 | * @param tenantDto request data 55 | */ 56 | public int updateTenant(TenantRespDto tenantDto) { 57 | int result = 0; 58 | result += tenantPoMapper.updateTenantById(tenantDto); 59 | return result; 60 | } 61 | 62 | /** 63 | * update tenant setting data. 64 | * 65 | * @param tenantDto tenant setting data 66 | */ 67 | public int updateTenantSetting(TenantRespDto tenantDto) { 68 | int result = 0; 69 | List roles = tenantDto.getPermissions(); 70 | tenantPoMapper.deleteRolesByTenantId(tenantDto.getUserId()); 71 | List rolePos = new ArrayList<>(); 72 | roles.forEach(role -> rolePos.add(new RolePo(role.getPlatform(), role.getRole()))); 73 | result += tenantPoMapper.insertRolesByTenantId(tenantDto.getUserId(), rolePos); 74 | return result; 75 | } 76 | 77 | /** 78 | * delete user. 79 | * 80 | * @param tenantId Tenant ID 81 | */ 82 | public void deleteUser(String tenantId) { 83 | tenantPoMapper.deleteUser(tenantId); 84 | tenantPoMapper.deleteRolesByTenantId(tenantId); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/test/java/org/edgegallery/user/auth/DBTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth; 18 | 19 | import java.util.UUID; 20 | import org.apache.commons.lang.RandomStringUtils; 21 | import org.edgegallery.user.auth.db.entity.TenantPo; 22 | import org.edgegallery.user.auth.db.mapper.TenantPoMapper; 23 | import org.junit.Assert; 24 | import org.junit.Test; 25 | import org.junit.runner.RunWith; 26 | import org.springframework.beans.factory.annotation.Autowired; 27 | import org.springframework.boot.test.context.SpringBootTest; 28 | import org.springframework.context.annotation.EnableAspectJAutoProxy; 29 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 30 | 31 | @SpringBootTest(classes = {MainServer.class}) 32 | @RunWith(SpringJUnit4ClassRunner.class) 33 | @EnableAspectJAutoProxy(proxyTargetClass = true) 34 | public class DBTest { 35 | 36 | @Autowired 37 | private TenantPoMapper mapper; 38 | 39 | @Test 40 | public void should_successfully_when_add_tenant() { 41 | TenantPo po = addTenantPo(); 42 | Assert.assertNotNull(po); 43 | } 44 | 45 | @Test 46 | public void should_successfully_when_get_tenant_by_tenantId() { 47 | TenantPo tenantPoAdd = addTenantPo(); 48 | TenantPo tenantPoGet = mapper.getTenantBasicPoData(tenantPoAdd.getTenantId()); 49 | Assert.assertEquals(tenantPoAdd.getUsername(), tenantPoGet.getUsername()); 50 | } 51 | 52 | @Test 53 | public void should_successfully_when_get_tenant_by_telephone() { 54 | TenantPo tenantPoAdd = addTenantPo(); 55 | TenantPo tenantPoGet = mapper.getTenantByTelephone(tenantPoAdd.getTelephoneNumber()); 56 | Assert.assertEquals(tenantPoAdd.getUsername(), tenantPoGet.getUsername()); 57 | } 58 | 59 | @Test 60 | public void should_successfully_when_get_tenant_by_name() { 61 | TenantPo tenantPoAdd = addTenantPo(); 62 | TenantPo tenantPoGet = mapper.getTenantByUsername(tenantPoAdd.getUsername()); 63 | Assert.assertEquals(tenantPoAdd.getTenantId(), tenantPoGet.getTenantId()); 64 | } 65 | 66 | private TenantPo addTenantPo() { 67 | TenantPo po = new TenantPo(); 68 | po.setTenantId(UUID.randomUUID().toString()); 69 | po.setUsername(RandomStringUtils.randomAlphanumeric(16)); 70 | po.setPassword("pw12#$"); 71 | po.setTelephoneNumber("13" + RandomStringUtils.randomNumeric(9)); 72 | po.setGender("male"); 73 | po.setCompany("huawei"); 74 | 75 | int res = mapper.addTenantPo(po); 76 | return res == 1 ? po : null; 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/external/iam/service/ExternalIamServiceImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.external.iam.service; 18 | 19 | import com.google.gson.Gson; 20 | import java.util.HashMap; 21 | import java.util.Map; 22 | import org.edgegallery.user.auth.external.iam.IExternalIamService; 23 | import org.edgegallery.user.auth.external.iam.model.ExternalUser; 24 | import org.slf4j.Logger; 25 | import org.slf4j.LoggerFactory; 26 | import org.springframework.beans.factory.annotation.Value; 27 | import org.springframework.http.HttpEntity; 28 | import org.springframework.http.HttpHeaders; 29 | import org.springframework.http.HttpMethod; 30 | import org.springframework.http.HttpStatus; 31 | import org.springframework.http.MediaType; 32 | import org.springframework.http.ResponseEntity; 33 | import org.springframework.stereotype.Component; 34 | import org.springframework.web.client.RestClientException; 35 | import org.springframework.web.client.RestTemplate; 36 | 37 | @Component 38 | public class ExternalIamServiceImpl implements IExternalIamService { 39 | 40 | private static final Logger LOGGER = LoggerFactory.getLogger(ExternalIamServiceImpl.class); 41 | 42 | private static final RestTemplate REST_TEMPLATE = new RestTemplate(); 43 | 44 | @Value("${external.iam.endpoint}") 45 | private String externalIamUrl; 46 | 47 | @Override 48 | public ExternalUser login(String userFlag, String password) { 49 | LOGGER.debug("external login."); 50 | HttpHeaders headers = new HttpHeaders(); 51 | headers.setContentType(MediaType.APPLICATION_JSON); 52 | 53 | Map loginReq = new HashMap<>(); 54 | loginReq.put("userFlag", userFlag); 55 | loginReq.put("password", password); 56 | 57 | String url = externalIamUrl + "/iam/users/login"; 58 | HttpEntity requestEntity = new HttpEntity<>(new Gson().toJson(loginReq), headers); 59 | try { 60 | ResponseEntity response = REST_TEMPLATE 61 | .exchange(url, HttpMethod.POST, requestEntity, ExternalUser.class); 62 | if (response == null || response.getStatusCode() != HttpStatus.OK) { 63 | LOGGER.error("external login failed."); 64 | return null; 65 | } 66 | 67 | LOGGER.debug("external login succeed."); 68 | return response.getBody(); 69 | } catch (RestClientException e) { 70 | LOGGER.error("external login failed, exception {}", e.getMessage()); 71 | return null; 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/test/java/org/edgegallery/user/auth/controller/ForgetPasswordApiTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.controller; 18 | 19 | import fj.data.Either; 20 | import javax.ws.rs.core.Response; 21 | import org.edgegallery.user.auth.controller.dto.response.ErrorRespDto; 22 | import org.edgegallery.user.auth.utils.ErrorEnum; 23 | import org.junit.Test; 24 | import org.junit.runner.RunWith; 25 | import org.edgegallery.user.auth.controller.dto.request.ModifyPasswordReqDto; 26 | import org.edgegallery.user.auth.controller.dto.response.FormatRespDto; 27 | import org.mockito.Mockito; 28 | import org.mockito.junit.MockitoJUnitRunner; 29 | import org.springframework.http.MediaType; 30 | import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; 31 | import org.springframework.test.web.servlet.result.MockMvcResultMatchers; 32 | 33 | @RunWith(MockitoJUnitRunner.class) 34 | public class ForgetPasswordApiTest extends UserControllerTest { 35 | 36 | @Test 37 | public void should_successfully_when_retrieve_pw_right() throws Exception { 38 | ModifyPasswordReqDto request = new ModifyPasswordReqDto(); 39 | request.setVerificationCode("123456"); 40 | request.setNewPassword("pw12#$W"); 41 | request.setTelephone("18012345678"); 42 | 43 | Either response = Either.left(true); 44 | Mockito.when(userMgmtService.modifyPassword(Mockito.any(ModifyPasswordReqDto.class), Mockito.any(String.class))).thenReturn(response); 45 | 46 | mvc.perform(MockMvcRequestBuilders.put("/v1/users/password").contentType(MediaType.APPLICATION_JSON_VALUE) 47 | .content(gson.toJson(request)).accept(MediaType.APPLICATION_JSON_VALUE)).andExpect(MockMvcResultMatchers.status().isOk()); 48 | } 49 | 50 | @Test 51 | public void should_failed_when_retrieve_pw_error() throws Exception { 52 | ModifyPasswordReqDto request = new ModifyPasswordReqDto(); 53 | request.setVerificationCode("123456"); 54 | request.setNewPassword("password"); 55 | request.setTelephone("18012345678"); 56 | 57 | Either response = Either.right(new FormatRespDto(Response.Status.FORBIDDEN, 58 | ErrorRespDto.build(ErrorEnum.NO_PERMISSION))); 59 | Mockito.when(userMgmtService.modifyPassword(Mockito.any(ModifyPasswordReqDto.class), Mockito.any(String.class))).thenReturn(response); 60 | 61 | mvc.perform(MockMvcRequestBuilders.put("/v1/users/password").contentType(MediaType.APPLICATION_JSON_VALUE) 62 | .content(gson.toJson(request)).accept(MediaType.APPLICATION_JSON_VALUE)).andExpect(MockMvcResultMatchers.status().isForbidden()); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/controller/AccessTokenController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.controller; 18 | 19 | import io.swagger.annotations.ApiOperation; 20 | import io.swagger.annotations.ApiParam; 21 | import io.swagger.annotations.ApiResponse; 22 | import io.swagger.annotations.ApiResponses; 23 | import lombok.extern.slf4j.Slf4j; 24 | import org.apache.http.HttpStatus; 25 | import org.apache.servicecomb.provider.rest.common.RestSchema; 26 | import org.edgegallery.user.auth.controller.base.AbstractBeGenericServlet; 27 | import org.edgegallery.user.auth.controller.dto.request.GetAccessTokenReqDto; 28 | import org.edgegallery.user.auth.controller.dto.response.ErrorRespDto; 29 | import org.edgegallery.user.auth.controller.dto.response.GetAccessTokenRespDto; 30 | import org.edgegallery.user.auth.service.AccessTokenService; 31 | import org.slf4j.Logger; 32 | import org.slf4j.LoggerFactory; 33 | import org.springframework.beans.factory.annotation.Autowired; 34 | import org.springframework.http.MediaType; 35 | import org.springframework.http.ResponseEntity; 36 | import org.springframework.stereotype.Controller; 37 | import org.springframework.web.bind.annotation.PostMapping; 38 | import org.springframework.web.bind.annotation.RequestBody; 39 | import org.springframework.web.bind.annotation.RequestMapping; 40 | 41 | @Slf4j 42 | @RestSchema(schemaId = "access-token") 43 | @RequestMapping("/v1/accesstoken") 44 | @Controller 45 | public class AccessTokenController extends AbstractBeGenericServlet { 46 | 47 | private static final Logger LOGGER = LoggerFactory.getLogger(AccessTokenController.class); 48 | 49 | @Autowired 50 | private AccessTokenService accessTokenService; 51 | 52 | /** 53 | * get access token. 54 | */ 55 | @PostMapping(value = "", produces = MediaType.APPLICATION_JSON_VALUE) 56 | @ApiOperation(value = "get access token", response = String.class) 57 | @ApiResponses(value = { 58 | @ApiResponse(code = HttpStatus.SC_OK, message = "get access token success", 59 | response = GetAccessTokenRespDto.class), 60 | @ApiResponse(code = HttpStatus.SC_BAD_REQUEST, message = "Bad Request", 61 | response = ErrorRespDto.class), 62 | @ApiResponse(code = HttpStatus.SC_UNAUTHORIZED, message = "get access token failed", 63 | response = ErrorRespDto.class) 64 | }) 65 | public ResponseEntity getAccessToken(@ApiParam(value = "GetAccessTokenReqDto", required = true) @RequestBody 66 | GetAccessTokenReqDto getAccessTokenReqDto) { 67 | LOGGER.info("get access token in controller."); 68 | return buildResponse(accessTokenService.getAccessToken(getAccessTokenReqDto)); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/controller/dto/request/ModifyPasswordReqDto.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.controller.dto.request; 18 | 19 | import com.fasterxml.jackson.annotation.JsonProperty; 20 | import com.google.gson.annotations.SerializedName; 21 | import io.swagger.annotations.ApiModelProperty; 22 | import javax.validation.constraints.Max; 23 | import javax.validation.constraints.Min; 24 | import javax.validation.constraints.Pattern; 25 | import lombok.Getter; 26 | import lombok.Setter; 27 | import org.edgegallery.user.auth.config.ServiceConfig; 28 | import org.edgegallery.user.auth.config.validate.AbstractCheckParamsGenericUtils; 29 | import org.edgegallery.user.auth.config.validate.IStringTrim; 30 | import org.springframework.util.StringUtils; 31 | 32 | @Getter 33 | @Setter 34 | public class ModifyPasswordReqDto extends AbstractCheckParamsGenericUtils implements IStringTrim { 35 | @SerializedName("type") 36 | @JsonProperty("type") 37 | @Min(value = 1) 38 | @Max(value = 2) 39 | private int type = 2; 40 | 41 | @SerializedName("newPassword") 42 | @JsonProperty("newPassword") 43 | @ApiModelProperty(required = true, example = "TestPassword1") 44 | @Pattern(regexp = ServiceConfig.PATTERN_USERPW) 45 | private String newPassword; 46 | 47 | @SerializedName("oldPassword") 48 | @JsonProperty("oldPassword") 49 | @ApiModelProperty(example = "TestOldPassword#321") 50 | private String oldPassword; 51 | 52 | @SerializedName("telephone") 53 | @JsonProperty("telephone") 54 | @ApiModelProperty(example = "15191881309") 55 | @Pattern(regexp = "|" + ServiceConfig.PATTERN_TELEPHONE) 56 | private String telephone; 57 | 58 | @SerializedName("mailAddress") 59 | @JsonProperty("mailAddress") 60 | @ApiModelProperty(example = "test@edgegallery.org") 61 | @Pattern(regexp = "|" + ServiceConfig.PATTERN_MAILADDRESS) 62 | private String mailAddress; 63 | 64 | @SerializedName("verificationCode") 65 | @JsonProperty("verificationCode") 66 | @ApiModelProperty(required = true, example = "123456") 67 | @Pattern(regexp = "|" + ServiceConfig.PATTERN_VERIFICATION_CODE) 68 | private String verificationCode; 69 | 70 | /** 71 | * check basic data by trim. 72 | */ 73 | public void stringTrim() { 74 | this.newPassword = StringUtils.trimWhitespace(this.newPassword); 75 | 76 | this.oldPassword = StringUtils.trimWhitespace(this.oldPassword); 77 | 78 | this.telephone = StringUtils.trimWhitespace(this.telephone); 79 | this.mailAddress = StringUtils.trimWhitespace(this.mailAddress); 80 | this.verificationCode = StringUtils.trimWhitespace(this.verificationCode); 81 | } 82 | 83 | /** 84 | * judge if the request is retrieve password type. 85 | * 86 | * @return true if the request is retrieve password type, otherwise false 87 | */ 88 | public boolean isRetrieveType() { 89 | return this.type == 2; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/config/validate/ValidateAspect.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.config.validate; 18 | 19 | import fj.data.Either; 20 | import java.util.Objects; 21 | import javax.ws.rs.core.Response; 22 | import org.aspectj.lang.ProceedingJoinPoint; 23 | import org.aspectj.lang.annotation.Around; 24 | import org.aspectj.lang.annotation.Aspect; 25 | import org.edgegallery.user.auth.controller.dto.response.ErrorRespDto; 26 | import org.edgegallery.user.auth.controller.dto.response.FormatRespDto; 27 | import org.edgegallery.user.auth.utils.ErrorEnum; 28 | import org.edgegallery.user.auth.utils.ValidatorUtil; 29 | import org.slf4j.Logger; 30 | import org.slf4j.LoggerFactory; 31 | import org.springframework.stereotype.Component; 32 | 33 | @Component 34 | @Aspect 35 | public class ValidateAspect { 36 | 37 | private static final Logger LOGGER = LoggerFactory.getLogger(ValidateAspect.class); 38 | 39 | /** 40 | * AOP around function. 41 | * 42 | * @param joinPoint joinPoint 43 | */ 44 | @Around("@annotation(org.edgegallery.user.auth.config.validate.annotation.ParameterValidate)") 45 | public Object around(ProceedingJoinPoint joinPoint) throws Throwable { 46 | Either result = validate(joinPoint.getArgs()); 47 | if (result.isRight()) { 48 | LOGGER 49 | .error("method={} invoke fail. error={}", joinPoint.getSignature(), result.right().value()); 50 | return result; 51 | } 52 | try { 53 | return joinPoint.proceed(); 54 | } catch (Exception e) { 55 | LOGGER.error("method={} invoke fail.", joinPoint.getSignature()); 56 | return result; 57 | } 58 | } 59 | 60 | private static Either validate(Object[] args) { 61 | Either result = Either.left(true); 62 | if (args == null || args.length == 0) { 63 | return result; 64 | } 65 | for (Object arg : args) { 66 | if (Objects.isNull(arg)) { 67 | continue; 68 | } 69 | if (arg instanceof IStringTrim) { 70 | ((IStringTrim) arg).stringTrim(); 71 | } 72 | Either validateResult = ValidatorUtil.validate(arg); 73 | if (validateResult.isRight()) { 74 | ErrorRespDto errRespDto = ErrorRespDto.build(ErrorEnum.PARA_ILLEGAL); 75 | errRespDto.setMessage(validateResult.right().value()); 76 | return Either.right(new FormatRespDto(Response.Status.BAD_REQUEST, errRespDto)); 77 | } 78 | if (arg instanceof ICheckParams) { 79 | Either dataCheckResult = ((ICheckParams) arg).checkData(); 80 | if (dataCheckResult.isRight()) { 81 | return dataCheckResult; 82 | } 83 | } 84 | } 85 | return result; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/utils/redis/RedisPoolUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.utils.redis; 18 | 19 | import io.lettuce.core.RedisClient; 20 | import io.lettuce.core.RedisURI; 21 | import io.lettuce.core.api.StatefulRedisConnection; 22 | import io.lettuce.core.support.ConnectionPoolSupport; 23 | import javax.annotation.PostConstruct; 24 | import org.apache.commons.pool2.impl.GenericObjectPool; 25 | import org.apache.commons.pool2.impl.GenericObjectPoolConfig; 26 | import org.edgegallery.user.auth.config.RedisConfig; 27 | import org.edgegallery.user.auth.exception.UserAuthException; 28 | import org.slf4j.Logger; 29 | import org.slf4j.LoggerFactory; 30 | import org.springframework.beans.factory.annotation.Autowired; 31 | import org.springframework.stereotype.Component; 32 | 33 | @Component 34 | public class RedisPoolUtil { 35 | 36 | private static final Logger LOGGER = LoggerFactory.getLogger(RedisPoolUtil.class); 37 | 38 | @Autowired 39 | private RedisConfig redisConfigWrapper; 40 | 41 | private static RedisConfig redisConfig; 42 | 43 | /** 44 | * init redis config. 45 | */ 46 | @PostConstruct 47 | public void init() { 48 | setRedisConfig(redisConfigWrapper); 49 | } 50 | 51 | private static synchronized void setRedisConfig(RedisConfig redisConfigWrapper) { 52 | if (redisConfig == null) { 53 | redisConfig = redisConfigWrapper; 54 | } 55 | } 56 | 57 | private static GenericObjectPool> getPoolInstance() { 58 | return RedisPoolUtilHandler.instance; 59 | } 60 | 61 | /** 62 | * statefull redis connection. 63 | * 64 | * @return 65 | */ 66 | public static StatefulRedisConnection getConnection() throws UserAuthException { 67 | try { 68 | return getPoolInstance().borrowObject(); 69 | } catch (Exception e) { 70 | LOGGER.error("can not get redis connection."); 71 | throw new UserAuthException("can not get redis connection."); 72 | } 73 | } 74 | 75 | static class RedisPoolUtilHandler { 76 | 77 | static GenericObjectPool> instance; 78 | 79 | private RedisPoolUtilHandler() { 80 | } 81 | 82 | static { 83 | RedisURI redisUri = RedisURI.builder().withHost(redisConfig.getIp()).withPort(redisConfig.getPort()) 84 | .withPassword(redisConfig.getPassword()).build(); 85 | GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig<>(); 86 | poolConfig.setMaxTotal(redisConfig.getMaxTotal()); 87 | poolConfig.setMaxIdle(redisConfig.getMaxIdle()); 88 | poolConfig.setMaxWaitMillis(redisConfig.getMaxWaitMillis()); 89 | poolConfig.setTestOnBorrow(true); 90 | RedisClient redisClient = RedisClient.create(redisUri); 91 | instance = ConnectionPoolSupport.createGenericObjectPool(redisClient::connect, poolConfig); 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/utils/ErrorEnum.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.utils; 18 | 19 | /** 20 | * Error Define. 21 | */ 22 | public enum ErrorEnum { 23 | /** 24 | * no login user. 25 | */ 26 | NO_LOGIN_USER(70000, "No login user."), 27 | /** 28 | * No permission. 29 | */ 30 | NO_PERMISSION(70001, "No permission."), 31 | /** 32 | * Illegal parameter. 33 | */ 34 | PARA_ILLEGAL(70002, "Illegal parameter."), 35 | /** 36 | * Database Exception. 37 | */ 38 | DATABASE_EXCEPTION(70003, "Database Exception."), 39 | /** 40 | * The user does not exist. 41 | */ 42 | USER_NOT_FOUND(70004, "The user does not exist."), 43 | /** 44 | * The mobile phone does not exist. 45 | */ 46 | MOBILEPHONE_NOT_FOUND(70005, "The mobile phone does not exist."), 47 | /** 48 | * The email address does not exist. 49 | */ 50 | MAILADDR_NOT_FOUND(70006, "The email address does not exist."), 51 | /** 52 | * The user name has been registered. 53 | */ 54 | USERNAME_REGISTERED(70007, "The user name has been registered."), 55 | /** 56 | * The mobile phone number has been registered. 57 | */ 58 | MOBILEPHONE_REGISTERED(70008, "The mobile phone number has been registered."), 59 | /** 60 | * The email address has been registered. 61 | */ 62 | MAILADDR_REGISTERED(70009, "The email address has been registered."), 63 | /** 64 | * The password is incorrect. 65 | */ 66 | PASSWORD_INCORRECT(70010, "The password is incorrect."), 67 | /** 68 | * The verification code is wrong or expired. 69 | */ 70 | VERIFY_CODE_ERROR(70011, "The verification code is wrong or expired."), 71 | /** 72 | * Sms server connect failed. 73 | */ 74 | SMS_CONNECT_FAILED(70012, "Sms server connect failed."), 75 | /** 76 | * Send verification code by sms failed. 77 | */ 78 | SEND_VERIFYCODE_SMS_FAILED(70013, "Send verification code by sms failed."), 79 | /** 80 | * Send verification code by mail failed. 81 | */ 82 | SEND_VERIFYCODE_MAIL_FAILED(70014, "Send verification code by mail failed."), 83 | /** 84 | * User register failed. 85 | */ 86 | USER_REGISTER_FAILED(70015, "User register failed."), 87 | /** 88 | * Modify password failed. 89 | */ 90 | MODIFY_PW_FAILED(70016, "Modify password failed."), 91 | /** 92 | * Login failed. 93 | */ 94 | LOGIN_FAILED(70017, "Login failed."), 95 | /** 96 | * User locked. 97 | */ 98 | USER_LOCKED(70018, "User locked."), 99 | 100 | /** 101 | * Unkown Error. 102 | */ 103 | UNKNOWN(79999, "Unkown Error."); 104 | 105 | private int code; 106 | private String message; 107 | 108 | ErrorEnum(int code, String message) { 109 | this.code = code; 110 | this.message = message; 111 | } 112 | 113 | public int code() { 114 | return this.code; 115 | } 116 | 117 | public String message() { 118 | return this.message; 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/utils/HttpsUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.utils; 18 | 19 | import io.netty.handler.codec.http.HttpResponseStatus; 20 | import java.io.IOException; 21 | import java.security.KeyManagementException; 22 | import java.security.KeyStoreException; 23 | import java.security.NoSuchAlgorithmException; 24 | import java.util.Map; 25 | import org.apache.http.HttpEntity; 26 | import org.apache.http.client.methods.CloseableHttpResponse; 27 | import org.apache.http.client.methods.HttpPost; 28 | import org.apache.http.client.methods.HttpRequestBase; 29 | import org.apache.http.conn.ssl.NoopHostnameVerifier; 30 | import org.apache.http.entity.StringEntity; 31 | import org.apache.http.impl.client.CloseableHttpClient; 32 | import org.apache.http.impl.client.HttpClients; 33 | import org.apache.http.ssl.SSLContextBuilder; 34 | import org.slf4j.Logger; 35 | import org.slf4j.LoggerFactory; 36 | import org.springframework.stereotype.Component; 37 | 38 | @Component 39 | public class HttpsUtil { 40 | 41 | private static final Logger LOGGER = LoggerFactory.getLogger(HttpsUtil.class); 42 | 43 | private boolean getResponse(HttpRequestBase httpRequest) { 44 | 45 | boolean res = false; 46 | CloseableHttpClient client = null; 47 | 48 | try { 49 | LOGGER.info("Begin sms connect"); 50 | client = HttpClients.custom().setSSLContext( 51 | new SSLContextBuilder().loadTrustMaterial(null, (x509CertChain, authType) -> true).build()) 52 | .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE).build(); 53 | try (CloseableHttpResponse response = client.execute(httpRequest)) { 54 | int respCode = response.getStatusLine().getStatusCode(); 55 | if (HttpResponseStatus.OK.code() == respCode) { 56 | res = true; 57 | } else { 58 | LOGGER.error("Send sms fail. respCode={}", respCode); 59 | } 60 | } 61 | } catch (IOException e) { 62 | LOGGER.error("https io exception: {}", e.getMessage()); 63 | } catch (NoSuchAlgorithmException | KeyStoreException | KeyManagementException e) { 64 | LOGGER.error("SSL Context exception: {}", e.getMessage()); 65 | } finally { 66 | if (client != null) { 67 | try { 68 | client.close(); 69 | } catch (IOException e) { 70 | LOGGER.error("Client close exception"); 71 | } 72 | } 73 | } 74 | 75 | return res; 76 | } 77 | 78 | /** 79 | * https post check. 80 | */ 81 | public boolean httpsPost(String url, Map headers, String bodyParam) { 82 | HttpPost post = new HttpPost(url); 83 | if (bodyParam != null) { 84 | HttpEntity entity = new StringEntity(bodyParam, "UTF-8"); 85 | post.setEntity(entity); 86 | } 87 | if (headers != null) { 88 | for (Map.Entry entry : headers.entrySet()) { 89 | post.addHeader(entry.getKey(), entry.getValue()); 90 | } 91 | } 92 | return getResponse(post); 93 | } 94 | 95 | } 96 | -------------------------------------------------------------------------------- /src/test/java/org/edgegallery/user/auth/controller/VerficationApiTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.controller; 18 | 19 | import com.google.gson.Gson; 20 | import fj.data.Either; 21 | import javax.ws.rs.core.Response; 22 | import org.edgegallery.user.auth.controller.dto.response.ErrorRespDto; 23 | import org.edgegallery.user.auth.utils.ErrorEnum; 24 | import org.junit.Before; 25 | import org.junit.Test; 26 | import org.junit.runner.RunWith; 27 | import org.edgegallery.user.auth.controller.dto.request.VerificationReqDto; 28 | import org.edgegallery.user.auth.controller.dto.response.FormatRespDto; 29 | import org.edgegallery.user.auth.service.IdentityService; 30 | import org.mockito.InjectMocks; 31 | import org.mockito.Mock; 32 | import org.mockito.Mockito; 33 | import org.mockito.MockitoAnnotations; 34 | import org.mockito.junit.MockitoJUnitRunner; 35 | import org.springframework.http.MediaType; 36 | import org.springframework.test.web.servlet.MockMvc; 37 | import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; 38 | import org.springframework.test.web.servlet.result.MockMvcResultMatchers; 39 | import org.springframework.test.web.servlet.setup.MockMvcBuilders; 40 | 41 | @RunWith(MockitoJUnitRunner.class) 42 | public class VerficationApiTest { 43 | 44 | private MockMvc mvc; 45 | 46 | @Mock 47 | private IdentityService identityService; 48 | 49 | @InjectMocks 50 | protected VerificationController verificationController; 51 | 52 | private Gson gson = new Gson(); 53 | 54 | @Before 55 | public void setUp() { 56 | this.mvc = MockMvcBuilders.standaloneSetup(verificationController).build(); 57 | MockitoAnnotations.initMocks(this); 58 | } 59 | 60 | @Test 61 | public void should_successfully_when_verify_tel_true() throws Exception { 62 | VerificationReqDto request = new VerificationReqDto(); 63 | request.setTelephone("15194251243"); 64 | 65 | Either response = Either.left(true); 66 | Mockito.when(identityService.sendVerificationCodeBySms(Mockito.any(VerificationReqDto.class))).thenReturn(response); 67 | 68 | mvc.perform(MockMvcRequestBuilders.post("/v1/identity/sms").contentType(MediaType.APPLICATION_JSON_VALUE) 69 | .content(gson.toJson(request)).accept(MediaType.APPLICATION_JSON_VALUE)) 70 | .andExpect(MockMvcResultMatchers.status().isCreated()); 71 | } 72 | 73 | @Test 74 | public void should_fail_when_verify_tel_bad_request() throws Exception { 75 | VerificationReqDto request = new VerificationReqDto(); 76 | request.setTelephone("15194251243"); 77 | 78 | Either response = Either 79 | .right(new FormatRespDto(Response.Status.BAD_REQUEST, 80 | ErrorRespDto.build(ErrorEnum.SEND_VERIFYCODE_SMS_FAILED))); 81 | Mockito.when(identityService.sendVerificationCodeBySms(Mockito.any(VerificationReqDto.class))).thenReturn(response); 82 | 83 | mvc.perform(MockMvcRequestBuilders.post("/v1/identity/sms").contentType(MediaType.APPLICATION_JSON_VALUE) 84 | .content(gson.toJson(request)).accept(MediaType.APPLICATION_JSON_VALUE)) 85 | .andExpect(MockMvcResultMatchers.status().isBadRequest()); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/config/security/AuthServerTokenEnhancer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.config.security; 18 | 19 | import java.util.HashMap; 20 | import java.util.Map; 21 | import javax.servlet.http.HttpServletRequest; 22 | import org.edgegallery.user.auth.config.SmsConfig; 23 | import org.edgegallery.user.auth.db.entity.TenantPo; 24 | import org.edgegallery.user.auth.db.mapper.TenantPoMapper; 25 | import org.edgegallery.user.auth.external.iam.ExternalUserUtil; 26 | import org.edgegallery.user.auth.external.iam.model.ExternalUser; 27 | import org.springframework.beans.factory.annotation.Autowired; 28 | import org.springframework.beans.factory.annotation.Value; 29 | import org.springframework.security.core.userdetails.User; 30 | import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; 31 | import org.springframework.security.oauth2.common.OAuth2AccessToken; 32 | import org.springframework.security.oauth2.provider.OAuth2Authentication; 33 | import org.springframework.security.oauth2.provider.token.TokenEnhancer; 34 | 35 | public class AuthServerTokenEnhancer implements TokenEnhancer { 36 | 37 | @Autowired 38 | private MecUserDetailsServiceImpl mecUserDetailsService; 39 | 40 | @Autowired 41 | private TenantPoMapper tenantPoMapper; 42 | 43 | @Autowired 44 | private HttpServletRequest request; 45 | 46 | @Autowired 47 | private SmsConfig smsConfig; 48 | 49 | @Value("${mail.enabled}") 50 | private String mailEnabled; 51 | 52 | @Value("${external.iam.enabled}") 53 | private boolean externalIamEnabled; 54 | 55 | @Override 56 | public OAuth2AccessToken enhance(OAuth2AccessToken oauth2AccessToken, OAuth2Authentication oauth2Authentication) { 57 | User user = (User) oauth2Authentication.getPrincipal(); 58 | Map additionalMap = new HashMap<>(); 59 | boolean isExternalUser = ExternalUserUtil.isExternalUser(user.getUsername()); 60 | if (isExternalUser) { 61 | ExternalUser externalUser = new ExternalUser(); 62 | externalUser.parse(user.getUsername()); 63 | additionalMap.put("userId", externalUser.getUserId()); 64 | additionalMap.put("userName", externalUser.getUserName()); 65 | } else { 66 | TenantPo tenant = tenantPoMapper.getTenantByUsername(user.getUsername()); 67 | additionalMap.put("userId", tenant != null ? tenant.getTenantId() : user.getUsername()); 68 | additionalMap.put("userName", user.getUsername()); 69 | if (mecUserDetailsService.getPwModifyScene(user.getUsername()) > 0) { 70 | additionalMap.put("pwmodiscene", null); 71 | } 72 | } 73 | 74 | additionalMap.put("enableSms", externalIamEnabled ? Boolean.FALSE : smsConfig.getEnabled()); 75 | additionalMap.put("enableMail", externalIamEnabled ? Boolean.FALSE : mailEnabled); 76 | additionalMap.put("ssoSessionId", request.getServletContext() 77 | .getAttribute(oauth2Authentication.getOAuth2Request().getRequestParameters().get("code"))); 78 | additionalMap.put("enableExternalIam", externalIamEnabled); 79 | 80 | ((DefaultOAuth2AccessToken) oauth2AccessToken).setAdditionalInformation(additionalMap); 81 | return oauth2AccessToken; 82 | } 83 | } -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/utils/redis/RedisUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.utils.redis; 18 | 19 | import io.lettuce.core.api.StatefulRedisConnection; 20 | import io.lettuce.core.api.sync.RedisCommands; 21 | import javax.annotation.PostConstruct; 22 | import org.edgegallery.user.auth.config.RedisConfig; 23 | import org.edgegallery.user.auth.exception.UserAuthException; 24 | import org.slf4j.Logger; 25 | import org.slf4j.LoggerFactory; 26 | import org.springframework.beans.factory.annotation.Autowired; 27 | import org.springframework.stereotype.Component; 28 | 29 | @Component 30 | public class RedisUtil { 31 | 32 | private static final Logger LOGGER = LoggerFactory.getLogger(RedisUtil.class); 33 | 34 | private static final String ERROR_CONNECT_REDIS_FAILED = "failed to connect redis."; 35 | 36 | private RedisUtil() { 37 | } 38 | 39 | @Autowired 40 | private RedisConfig redisConfigWrapper; 41 | 42 | private static RedisConfig redisConfig; 43 | 44 | /** 45 | * init redis config. 46 | */ 47 | @PostConstruct 48 | public void init() { 49 | setRedisConfig(redisConfigWrapper); 50 | } 51 | 52 | private static synchronized void setRedisConfig(RedisConfig redisConfigWrapper) { 53 | if (redisConfig == null) { 54 | redisConfig = redisConfigWrapper; 55 | } 56 | } 57 | 58 | /** 59 | * save value by key. 60 | * 61 | */ 62 | public static void save(RedisKeyType type, String key, String value) { 63 | try (StatefulRedisConnection connection = RedisPoolUtil.getConnection()) { 64 | RedisCommands commands = connection.sync(); 65 | commands.set(type + "-" + key, value); 66 | commands.expire(type + "-" + key, type.timeOut); 67 | } catch (UserAuthException e) { 68 | LOGGER.error(ERROR_CONNECT_REDIS_FAILED); 69 | } 70 | } 71 | 72 | /** 73 | * get value by key. 74 | * 75 | * @return 76 | */ 77 | public static String get(RedisKeyType type, String key) { 78 | try (StatefulRedisConnection connection = RedisPoolUtil.getConnection()) { 79 | return connection.sync().get(type + "-" + key); 80 | } catch (UserAuthException e) { 81 | LOGGER.error(ERROR_CONNECT_REDIS_FAILED); 82 | } 83 | return null; 84 | } 85 | 86 | /** 87 | * delete key and value. 88 | */ 89 | public static void delete(RedisKeyType type, String key) { 90 | try (StatefulRedisConnection connection = RedisPoolUtil.getConnection()) { 91 | connection.sync().del(type + "-" + key); 92 | } catch (UserAuthException e) { 93 | LOGGER.error(ERROR_CONNECT_REDIS_FAILED); 94 | } 95 | } 96 | 97 | public enum RedisKeyType { 98 | /** 99 | * timeout of verification code. 100 | */ 101 | VERIFICATION_CODE(redisConfig.getVerificationTimeOut()), 102 | /** 103 | * timeout of image verification code. 104 | */ 105 | IMG_VERIFICATION_CODE(redisConfig.getImgVerificationTimeout()); 106 | 107 | private int timeOut; 108 | 109 | RedisKeyType(int timeOut) { 110 | this.timeOut = timeOut; 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/test/resources/usermgmt-test-data.sql: -------------------------------------------------------------------------------- 1 | 2 | --MERGE INTO tbl_role 3 | -- KEY(ID) 4 | --VALUES (1, 'APPSTORE', 'GUEST'), 5 | -- (2, 'APPSTORE', 'TENANT'), 6 | -- (3, 'APPSTORE', 'ADMIN'), 7 | -- (4, 'DEVELOPER', 'GUEST'), 8 | -- (5, 'DEVELOPER', 'TENANT'), 9 | -- (6, 'DEVELOPER', 'ADMIN'), 10 | -- (7, 'MECM', 'GUEST'), 11 | -- (8, 'MECM', 'TENANT'), 12 | -- (9, 'MECM', 'ADMIN'); 13 | 14 | -- supported platforms and roles 15 | MERGE INTO tbl_role (ID, PLATFORM, ROLE) key(id) values 16 | (1, 'APPSTORE', 'GUEST'),(2, 'APPSTORE', 'TENANT'),(3, 'APPSTORE', 'ADMIN'), 17 | (4, 'DEVELOPER', 'GUEST'),(5, 'DEVELOPER', 'TENANT'),(6, 'DEVELOPER', 'ADMIN'), 18 | (7, 'MECM', 'GUEST'),(8, 'MECM', 'TENANT'),(9, 'MECM', 'ADMIN'), 19 | (10, 'ATP', 'GUEST'),(11, 'ATP', 'TENANT'),(12, 'ATP', 'ADMIN'), 20 | (13, 'LAB', 'GUEST'),(14, 'LAB', 'TENANT'),(15, 'LAB', 'ADMIN'), 21 | (16, 'APPMGMT', 'GUEST'),(17, 'APPMGMT', 'TENANT'),(18, 'APPMGMT', 'ADMIN'); 22 | -- ON CONFLICT(id) do nothing; 23 | 24 | -- add a guest user 25 | merge into tbl_tenant (TENANTID, USERNAME, PASSWORD, COMPANY, TELEPHONENUMBER, MAILADDRESS, GENDER, isallowed, CREATETIME, MODIFYTIME) key(TENANTID) 26 | values('de3565b1-a7c2-42b9-b281-3f032af29ff7', 'guest', 27 | '59756fda85ebddee6024d5cc0e6edcde3226693257a9c1eb662c56426b8a4f232b3d56c321adbd91', 'company', '13800000000', '13800000000@edgegallery.org', '1', true, now(), now()); 28 | -- ON CONFLICT(TENANTID) do nothing; 29 | 30 | -- add a admin user 31 | merge into tbl_tenant (TENANTID, USERNAME, PASSWORD, COMPANY, TELEPHONENUMBER, MAILADDRESS, GENDER, isallowed, CREATETIME, MODIFYTIME) key(TENANTID) 32 | values('39937079-99fe-4cd8-881f-04ca8c4fe09d', 'admin', 33 | '472645ad1af0101adaa6769cc865fec3b29fedeba6dc912900a59b1364b7a6bb17bb9a0575854547', 'company', '13800000001', '13800000001@edgegallery.org', '1', true, now(), now()); 34 | -- ON CONFLICT(TENANTID) do nothing; 35 | 36 | -- add a tenant1 user 37 | merge into tbl_tenant (TENANTID, USERNAME, PASSWORD, COMPANY, TELEPHONENUMBER, MAILADDRESS, GENDER, isallowed, CREATETIME, MODIFYTIME) key(TENANTID) 38 | values('dad58d01-1251-4a4c-b01a-20f221da7d39', 'tenant1', 39 | '2079699a9b02ee7443dea821b0cca4d3213d41eecc47d7464885c3aa9f756718610c632566ae205b', 'company', '13800000003', '13800000003@edgegallery.org', '1', true, now(), now()); 40 | 41 | -- add a tenant2 user 42 | merge into tbl_tenant (TENANTID, USERNAME, PASSWORD, COMPANY, TELEPHONENUMBER, MAILADDRESS, GENDER, isallowed, CREATETIME, MODIFYTIME) key(TENANTID) 43 | values('d1209326-6577-4cd5-8e8e-94709931734e', 'tenant2', 44 | '2079699a9b02ee7443dea821b0cca4d3213d41eecc47d7464885c3aa9f756718610c632566ae205b', 'company', '13800000004', '13800000004@edgegallery.org', '1', true, now(), now()); 45 | 46 | -- set the permissions for guest user 47 | merge into tbl_tenant_role (TENANTID, ROLEID) key(TENANTID, ROLEID) values 48 | ('de3565b1-a7c2-42b9-b281-3f032af29ff7', 1), 49 | ('de3565b1-a7c2-42b9-b281-3f032af29ff7', 4), 50 | ('de3565b1-a7c2-42b9-b281-3f032af29ff7', 7), 51 | ('de3565b1-a7c2-42b9-b281-3f032af29ff7', 10), 52 | ('de3565b1-a7c2-42b9-b281-3f032af29ff7', 13), 53 | ('de3565b1-a7c2-42b9-b281-3f032af29ff7', 16); 54 | -- ON CONFLICT(TENANTID, ROLEID) do nothing; 55 | 56 | merge into tbl_tenant_role (TENANTID, ROLEID) key(TENANTID, ROLEID) values 57 | ('39937079-99fe-4cd8-881f-04ca8c4fe09d', 3), 58 | ('39937079-99fe-4cd8-881f-04ca8c4fe09d', 6), 59 | ('39937079-99fe-4cd8-881f-04ca8c4fe09d', 9), 60 | ('39937079-99fe-4cd8-881f-04ca8c4fe09d', 12), 61 | ('39937079-99fe-4cd8-881f-04ca8c4fe09d', 15), 62 | ('39937079-99fe-4cd8-881f-04ca8c4fe09d', 18); 63 | -- ON CONFLICT(TENANTID, ROLEID) do nothing; 64 | 65 | merge into tbl_tenant_role (TENANTID, ROLEID) key(TENANTID, ROLEID) values 66 | ('dad58d01-1251-4a4c-b01a-20f221da7d39', 2), 67 | ('dad58d01-1251-4a4c-b01a-20f221da7d39', 5), 68 | ('dad58d01-1251-4a4c-b01a-20f221da7d39', 8), 69 | ('dad58d01-1251-4a4c-b01a-20f221da7d39', 11), 70 | ('dad58d01-1251-4a4c-b01a-20f221da7d39', 14), 71 | ('dad58d01-1251-4a4c-b01a-20f221da7d39', 17); 72 | 73 | merge into tbl_tenant_role (TENANTID, ROLEID) key(TENANTID, ROLEID) values 74 | ('d1209326-6577-4cd5-8e8e-94709931734e', 2), 75 | ('d1209326-6577-4cd5-8e8e-94709931734e', 5), 76 | ('d1209326-6577-4cd5-8e8e-94709931734e', 8), 77 | ('d1209326-6577-4cd5-8e8e-94709931734e', 11), 78 | ('d1209326-6577-4cd5-8e8e-94709931734e', 14), 79 | ('d1209326-6577-4cd5-8e8e-94709931734e', 17); -------------------------------------------------------------------------------- /src/main/resources/application.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2020-2021 Huawei Technologies Co., Ltd. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | ###servicecomb config#### 17 | servicecomb-config-order: 1 18 | APPLICATION_ID: edgegallery #应用名 19 | service_description: 20 | name: user-mgmt-be #微服务名 21 | version: 1.0.0 #微服务版本 22 | environment: development 23 | servicecomb: 24 | service: 25 | registry: 26 | address: ${SC_ADDRESS} #连接SC(Service Center,注册中心)的地址 27 | rest: 28 | address: ${LISTEN_IP:0.0.0.0}:8067 #Rest通信地址 29 | servlet: 30 | urlPattern: /cse/* #using spring mvc rest server to handle requests 31 | handler: 32 | chain: 33 | Provider: 34 | default: bizkeeper-provider 35 | ###spring config###### 36 | server: 37 | port: 8067 38 | ssl: 39 | enabled: ${SSL_ENABLED:false} 40 | protocol: TLS 41 | enabled-protocols: [TLSv1.2] 42 | ciphers: [TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 43 | TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384] 44 | key-store: ${SSL_KEY_STORE_PATH:} 45 | key-store-password: ${SSL_KEY_STORE_PASSWORD:} 46 | key-store-type: ${SSL_KEY_STORE_TYPE:} 47 | key-alias: ${SSL_KEY_ALIAS:} 48 | servlet: 49 | session: 50 | timeout: 3600 51 | cookie: 52 | name: AUTHSERVERSESSIONID 53 | spring: 54 | datasource: 55 | url: jdbc:postgresql://${POSTGRES_IP:user-mgmt-postgres-svc}:${POSTGRES_PORT:5432}/${POSTGRES_DB_NAME:usermgmtdb} 56 | username: ${POSTGRES_USERNAME} 57 | password: ${POSTGRES_PASSWORD} 58 | driver-class-name: org.postgresql.Driver 59 | initialization-mode: always 60 | schema: classpath:usermgmtdb.sql 61 | data: classpath:usermgmtdb-data.sql 62 | main: 63 | allow-bean-definition-overriding: true 64 | 65 | ###mybtis config#### 66 | mybatis: 67 | mapper-locations: classpath:mybatis/sql/*.xml 68 | 69 | ###oauth2 config#### 70 | oauth2: 71 | clients: 72 | - clientEnabled: ${OAUTH_APPSTORE_ENABLED:true} 73 | clientId: ${OAUTH_APPSTORE_CLIENT_ID:appstore-fe} 74 | clientSecret: ${OAUTH_APPSTORE_CLIENT_SECRET:} 75 | clientUrl: ${OAUTH_APPSTORE_CLIENT_URL:} 76 | clientAccessUrl: ${OAUTH_APPSTORE_CLIENT_ACCESS_URL:} 77 | - clientEnabled: ${OAUTH_DEVELOPER_ENABLED:true} 78 | clientId: ${OAUTH_DEVELOPER_CLIENT_ID:developer-fe} 79 | clientSecret: ${OAUTH_DEVELOPER_CLIENT_SECRET:} 80 | clientUrl: ${OAUTH_DEVELOPER_CLIENT_URL:} 81 | clientAccessUrl: ${OAUTH_DEVELOPER_CLIENT_ACCESS_URL:} 82 | - clientEnabled: ${OAUTH_MECM_ENABLED:true} 83 | clientId: ${OAUTH_MECM_CLIENT_ID:mecm-fe} 84 | clientSecret: ${OAUTH_MECM_CLIENT_SECRET:} 85 | clientUrl: ${OAUTH_MECM_CLIENT_URL:} 86 | clientAccessUrl: ${OAUTH_MECM_CLIENT_ACCESS_URL:} 87 | - clientEnabled: ${OAUTH_ATP_ENABLED:true} 88 | clientId: ${OAUTH_ATP_CLIENT_ID:atp-fe} 89 | clientSecret: ${OAUTH_ATP_CLIENT_SECRET:} 90 | clientUrl: ${OAUTH_ATP_CLIENT_URL:} 91 | clientAccessUrl: ${OAUTH_ATP_CLIENT_ACCESS_URL:} 92 | - clientEnabled: ${OAUTH_LAB_ENABLED:false} 93 | clientId: ${OAUTH_LAB_CLIENT_ID:lab-fe} 94 | clientSecret: ${OAUTH_LAB_CLIENT_SECRET:} 95 | clientUrl: ${OAUTH_LAB_CLIENT_URL:} 96 | clientAccessUrl: ${OAUTH_LAB_CLIENT_ACCESS_URL:} 97 | - clientEnabled: ${OAUTH_EDGEGALLERY_ENABLED:true} 98 | clientId: ${OAUTH_EDGEGALLERY_CLIENT_ID:edgegallery-fe} 99 | clientSecret: ${OAUTH_EDGEGALLERY_CLIENT_SECRET:} 100 | clientUrl: ${OAUTH_EDGEGALLERY_CLIENT_URL:} 101 | clientAccessUrl: ${OAUTH_EDGEGALLERY_CLIENT_ACCESS_URL:} 102 | - clientEnabled: ${OAUTH_APPMGMT_ENABLED:false} 103 | clientId: ${OAUTH_APPMGMT_CLIENT_ID:app-mgmt-fe} 104 | clientSecret: ${OAUTH_APPMGMT_CLIENT_SECRET:} 105 | clientUrl: ${OAUTH_APPMGMT_CLIENT_URL:} 106 | clientAccessUrl: ${OAUTH_APPMGMT_CLIENT_ACCESS_URL:} 107 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/controller/dto/request/QueryUserReqDto.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.controller.dto.request; 18 | 19 | import fj.data.Either; 20 | import io.swagger.annotations.ApiModelProperty; 21 | import java.time.LocalDate; 22 | import java.time.Period; 23 | import java.time.format.DateTimeParseException; 24 | import javax.validation.Valid; 25 | import javax.validation.constraints.Max; 26 | import javax.validation.constraints.Min; 27 | import javax.validation.constraints.NotNull; 28 | import javax.validation.constraints.Pattern; 29 | import javax.ws.rs.core.Response; 30 | import lombok.Getter; 31 | import lombok.Setter; 32 | import org.edgegallery.user.auth.config.validate.AbstractCheckParamsGenericUtils; 33 | import org.edgegallery.user.auth.config.validate.IStringTrim; 34 | import org.edgegallery.user.auth.controller.dto.response.ErrorRespDto; 35 | import org.edgegallery.user.auth.controller.dto.response.FormatRespDto; 36 | import org.edgegallery.user.auth.utils.Consts; 37 | import org.edgegallery.user.auth.utils.ErrorEnum; 38 | import org.springframework.util.StringUtils; 39 | 40 | @Setter 41 | @Getter 42 | public class QueryUserReqDto extends AbstractCheckParamsGenericUtils implements IStringTrim { 43 | private String username; 44 | 45 | private String mailAddress; 46 | 47 | private String telephone; 48 | 49 | @ApiModelProperty(example = "ADMIN") 50 | @Pattern(regexp = "ALL|ADMIN|TENANT|GUEST") 51 | private String role; 52 | 53 | @Min(value = -1) 54 | @Max(value = 1) 55 | private int status; 56 | 57 | private String createTimeBegin; 58 | 59 | private String createTimeEnd; 60 | 61 | @NotNull 62 | @Valid 63 | private QueryUserCtrlDto queryCtrl; 64 | 65 | /** 66 | * check basic data by trim. 67 | */ 68 | public void stringTrim() { 69 | this.username = StringUtils.trimWhitespace(this.username); 70 | this.mailAddress = StringUtils.trimWhitespace(this.mailAddress); 71 | this.telephone = StringUtils.trimWhitespace(this.telephone); 72 | this.role = StringUtils.trimWhitespace(this.role); 73 | this.createTimeBegin = StringUtils.trimWhitespace(this.createTimeBegin); 74 | this.createTimeEnd = StringUtils.trimWhitespace(this.createTimeEnd); 75 | this.queryCtrl.stringTrim(); 76 | } 77 | 78 | @Override 79 | protected Either checkDataFormat() { 80 | LocalDate beginDate = null; 81 | if (!StringUtils.isEmpty(createTimeBegin)) { 82 | try { 83 | beginDate = LocalDate.parse(createTimeBegin, Consts.DATE_TIME_FORMATTER); 84 | } catch (DateTimeParseException dtpe) { 85 | return Either.right(new FormatRespDto(Response.Status.BAD_REQUEST, 86 | ErrorRespDto.build(ErrorEnum.PARA_ILLEGAL))); 87 | } 88 | } 89 | 90 | LocalDate endDate = null; 91 | if (!StringUtils.isEmpty(createTimeEnd)) { 92 | try { 93 | endDate = LocalDate.parse(createTimeEnd, Consts.DATE_TIME_FORMATTER); 94 | } catch (DateTimeParseException dtpe) { 95 | return Either.right(new FormatRespDto(Response.Status.BAD_REQUEST, 96 | ErrorRespDto.build(ErrorEnum.PARA_ILLEGAL))); 97 | } 98 | } 99 | 100 | if (beginDate != null && endDate != null && beginDate.isAfter(endDate)) { 101 | return Either.right(new FormatRespDto(Response.Status.BAD_REQUEST, 102 | ErrorRespDto.build(ErrorEnum.PARA_ILLEGAL))); 103 | } 104 | 105 | if (endDate != null) { 106 | endDate = endDate.plus(Period.ofDays(1)); 107 | this.createTimeEnd = endDate.format(Consts.DATE_TIME_FORMATTER); 108 | } 109 | 110 | return Either.left(true); 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/service/HwCloudVerification.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.service; 18 | 19 | import java.nio.charset.StandardCharsets; 20 | import java.text.SimpleDateFormat; 21 | import java.util.ArrayList; 22 | import java.util.Base64; 23 | import java.util.Date; 24 | import java.util.HashMap; 25 | import java.util.List; 26 | import java.util.Map; 27 | import java.util.UUID; 28 | import org.apache.commons.codec.binary.Hex; 29 | import org.apache.commons.codec.digest.DigestUtils; 30 | import org.apache.http.HttpHeaders; 31 | import org.apache.http.NameValuePair; 32 | import org.apache.http.client.utils.URLEncodedUtils; 33 | import org.apache.http.message.BasicNameValuePair; 34 | import org.edgegallery.user.auth.config.SmsConfig; 35 | import org.edgegallery.user.auth.utils.HttpsUtil; 36 | import org.springframework.beans.factory.annotation.Autowired; 37 | import org.springframework.stereotype.Component; 38 | 39 | @Component 40 | public class HwCloudVerification { 41 | 42 | private static final String WSSE_HEADER_FORMAT = "UsernameToken Username=\"%s\",PasswordDigest=\"%s\"," 43 | + "Nonce=\"%s\",Created=\"%s\""; 44 | private static final String AUTH_HEADER_VALUE = "WSSE realm=\"SDP\",profile=\"UsernameToken\",type=\"Appkey\""; 45 | 46 | @Autowired 47 | private SmsConfig smsConfig; 48 | 49 | @Autowired 50 | private HttpsUtil httpsUtil; 51 | 52 | /** 53 | * telephone send verification code. 54 | * 55 | * @param telephone telephone 56 | * @param verificationCode verification code 57 | * @return 58 | */ 59 | public boolean sendVerificationCode(String telephone, String verificationCode) { 60 | String receiver = "+86" + telephone; 61 | String templateParas = "[\"" + verificationCode + "\"]"; 62 | String wsseHeader = buildWsseHeader(smsConfig.getAppKey(), smsConfig.getAppSecret()); 63 | Map header = new HashMap<>(); 64 | header.put(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded"); 65 | header.put(HttpHeaders.AUTHORIZATION, AUTH_HEADER_VALUE); 66 | header.put("X-WSSE", wsseHeader); 67 | String body = buildRequestBody(smsConfig.getSender(), receiver, smsConfig.getTemplateId(), templateParas, 68 | smsConfig.getStatusCallBack(), smsConfig.getSignature()); 69 | return httpsUtil.httpsPost(smsConfig.getUrl(), header, body); 70 | } 71 | 72 | static String buildRequestBody(String sender, String receiver, String templateId, String templateParas, 73 | String statusCallbackUrl, String signature) { 74 | List keyValues = new ArrayList<>(); 75 | keyValues.add(new BasicNameValuePair("from", sender)); 76 | keyValues.add(new BasicNameValuePair("to", receiver)); 77 | keyValues.add(new BasicNameValuePair("templateId", templateId)); 78 | if (null != templateParas && !templateParas.isEmpty()) { 79 | keyValues.add(new BasicNameValuePair("templateParas", templateParas)); 80 | } 81 | if (null != statusCallbackUrl && !statusCallbackUrl.isEmpty()) { 82 | keyValues.add(new BasicNameValuePair("statusCallback", statusCallbackUrl)); 83 | } 84 | if (null != signature && !signature.isEmpty()) { 85 | keyValues.add(new BasicNameValuePair("signature", signature)); 86 | } 87 | return URLEncodedUtils.format(keyValues, StandardCharsets.UTF_8); 88 | } 89 | 90 | /** 91 | * build X-WSSE. 92 | * 93 | * @param appKey appKey 94 | * @param appSecret appSecret 95 | * @return 96 | **/ 97 | static String buildWsseHeader(String appKey, String appSecret) { 98 | SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); 99 | String time = sdf.format(new Date()); //Created 100 | String nonce = UUID.randomUUID().toString().replace("-", ""); //Nonce 101 | byte[] passwordDigest = DigestUtils.sha256(nonce + time + appSecret); 102 | String hexDigest = Hex.encodeHexString(passwordDigest); 103 | String passwordDigestBase64Str = Base64.getEncoder() 104 | .encodeToString(hexDigest.getBytes(StandardCharsets.UTF_8)); 105 | return String.format(WSSE_HEADER_FORMAT, appKey, passwordDigestBase64Str, nonce, time); 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/config/security/ExtendAuthorizationCodeTokenGranter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.config.security; 18 | 19 | import java.util.HashMap; 20 | import java.util.Map; 21 | import org.edgegallery.user.auth.utils.Consts; 22 | import org.slf4j.Logger; 23 | import org.slf4j.LoggerFactory; 24 | import org.springframework.security.core.Authentication; 25 | import org.springframework.security.oauth2.common.exceptions.InvalidClientException; 26 | import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; 27 | import org.springframework.security.oauth2.common.exceptions.InvalidRequestException; 28 | import org.springframework.security.oauth2.provider.ClientDetails; 29 | import org.springframework.security.oauth2.provider.ClientDetailsService; 30 | import org.springframework.security.oauth2.provider.OAuth2Authentication; 31 | import org.springframework.security.oauth2.provider.OAuth2Request; 32 | import org.springframework.security.oauth2.provider.OAuth2RequestFactory; 33 | import org.springframework.security.oauth2.provider.TokenRequest; 34 | import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices; 35 | import org.springframework.security.oauth2.provider.token.AbstractTokenGranter; 36 | import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; 37 | 38 | /** 39 | * Extend Auth Code Token Granter. 40 | */ 41 | public class ExtendAuthorizationCodeTokenGranter extends AbstractTokenGranter { 42 | private static final Logger LOGGER = LoggerFactory.getLogger(LoginSuccessHandler.class); 43 | 44 | private final AuthorizationCodeServices authorizationCodeServices; 45 | 46 | public ExtendAuthorizationCodeTokenGranter(AuthorizationServerTokenServices tokenServices, 47 | AuthorizationCodeServices authorizationCodeServices, ClientDetailsService clientDetailsService, 48 | OAuth2RequestFactory requestFactory) { 49 | this(tokenServices, authorizationCodeServices, clientDetailsService, requestFactory, Consts.GRANT_TYPE); 50 | } 51 | 52 | protected ExtendAuthorizationCodeTokenGranter(AuthorizationServerTokenServices tokenServices, 53 | AuthorizationCodeServices authorizationCodeServices, ClientDetailsService clientDetailsService, 54 | OAuth2RequestFactory requestFactory, String grantType) { 55 | super(tokenServices, clientDetailsService, requestFactory, grantType); 56 | this.authorizationCodeServices = authorizationCodeServices; 57 | } 58 | 59 | @Override 60 | protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) { 61 | Map parameters = tokenRequest.getRequestParameters(); 62 | String authorizationCode = parameters.get("code"); 63 | String redirectUri = parameters.get("redirect_uri"); 64 | if (authorizationCode == null) { 65 | throw new InvalidRequestException("An authorization code must be supplied."); 66 | } 67 | 68 | OAuth2Authentication storedAuth = getStoredAuth(authorizationCode); 69 | if (storedAuth == null) { 70 | throw new InvalidGrantException("Invalid authorization code: " + authorizationCode); 71 | } 72 | 73 | OAuth2Request pendingOAuth2Request = storedAuth.getOAuth2Request(); 74 | String redirectUriApprovalParameter = (String) pendingOAuth2Request.getRequestParameters().get("redirect_uri"); 75 | if ((redirectUri != null || redirectUriApprovalParameter != null) && !pendingOAuth2Request.getRedirectUri() 76 | .equals(redirectUri)) { 77 | LOGGER.warn("Redirect URI mismatch, ignore it."); 78 | } 79 | 80 | String pendingClientId = pendingOAuth2Request.getClientId(); 81 | String clientId = tokenRequest.getClientId(); 82 | if (clientId != null && !clientId.equals(pendingClientId)) { 83 | throw new InvalidClientException("Client ID mismatch"); 84 | } 85 | 86 | Map combinedParameters = new HashMap<>(pendingOAuth2Request.getRequestParameters()); 87 | combinedParameters.putAll(parameters); 88 | OAuth2Request finalStoredOAuth2Request = pendingOAuth2Request.createOAuth2Request(combinedParameters); 89 | Authentication userAuth = storedAuth.getUserAuthentication(); 90 | return new OAuth2Authentication(finalStoredOAuth2Request, userAuth); 91 | } 92 | 93 | private OAuth2Authentication getStoredAuth(String authorizationCode) { 94 | return this.authorizationCodeServices.consumeAuthorizationCode(authorizationCode); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # User Management 用户管理 2 | 3 | [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) 4 | 5 | 用户管理模块为EdgeGallery平台提供了用户注册与登录、密码找回、帐号中心、用户列表管理、邮箱和手机验证等功能。 6 | 7 | ## 角色定义 8 | 9 | 用户管理模块定义了用户的角色与权限模型,包括: 10 | 11 | - **租户** 系统内的普通用户,可以创建项目/上传App等操作,租户之间数据不能相互访问。 12 | 13 | - **管理员** 系统管理员,可以对系统的应用数据进行管理和维护操作。 14 | 15 | - **访客** 直接访问Portal时,默认是访客权限,只能浏览各平台的基本功能,不能做创建、编辑和删除等操作。 16 | 17 | - **超级管理员** 系统内置一个默认用户:admin,作为平台的超级管理员。该用户可以管理其他用户,对平台已注册的所有用户进行统一管理,停用/启用用户,设置用户权限。 18 | 19 | 新注册的用户,默认是“租户”权限。“管理员”权限只能由超级管理admin在用户列表管理功能中,为租户提权获得。 20 | 21 | ## 主要特性 22 | 23 | 用户管理模块提供的主要特性可以点击查看:[用户管理模块特性设计](http://docs.edgegallery.org/en/latest/Projects/User%20Management/User_Features.html) 24 | 25 | ## 本地运行User Management服务 26 | 27 | User Management对外提供restful接口,基于开源ServiceComb微服务框架进行开发,并且集成了Spring Boot框架。能够在本地直接编译运行启动微服务,方便使用者进行本地调试。 28 | 29 | 30 | - ### 环境搭建与配置 31 | 32 | **1.环境准备:** 需要安装的工具及下载地址如下表所示。 33 | 34 | | Name | Version | Link | 35 | | ---- | ---- | ---- | 36 | | OpenJDK1.8 |1.8.0 | [download](http://openjdk.java.net/install/) 37 | | MavApache Maven |3.6.3 | [download](https://maven.apache.org/download.cgi) 38 | | IntelliJ IDEA |Community |[download](https://www.jetbrains.com/idea/download/) 39 | | Servicecomb Service-Center | 1.3.2 | [download](https://servicecomb.apache.org/cn/release/service-center-downloads/) 40 | | Postgres | 10 or above | [download](https://www.enterprisedb.com/downloads/postgres-postgresql-downloads) 41 | | Redis | 3.2.100 or above | [download](https://github.com/microsoftarchive/redis/releases) | 42 | 43 | **2.源码下载:** 使用 git clone 或者下载压缩包的形式将User Management源代码下载到本地,默认master分支。 44 | 首先需要下载依赖的父pom工程并编译: 45 | ``` 46 | git clone https://gitee.com/edgegallery/eg-parent.git 47 | mvn install 48 | ``` 49 | 然后下载当前User Management工程: 50 | ``` 51 | git clone https://gitee.com/edgegallery/user-mgmt.git 52 | ``` 53 | 54 | **3.ServiceCenter配置:** User Management使用了开源的[ServiceComb](https://servicecomb.apache.org/)框架进行开发,服务在启动时会自动注册到指定的ServiceCenter,ServiceCenter会为服务提供注册与发现能力,供其他微服务进行调用。 55 | 56 | 在启动User Management前需要先在本地启动ServiceCenter。 57 | 58 | - 首先[下载ServiceCenter](https://servicecomb.apache.org/cn/release/service-center-downloads/),如Windows系统可以选择Windows的[Binary]版本,下载完成后解压; 59 | 60 | - 双击运行start-service-center.bat和start-frontend.bat即可在本地启动ServiceCenter和可视化面板,浏览器访问 http://127.0.0.1:30103 进行查看,ServiceCenter默认启动端口为30100; 61 | 62 | - 本地运行User Management服务,需要增加如下环境变量以连接SC(Service Center,即服务中心): 63 | 64 | ``` 65 | SC_ADDRESS:连接SC的地址。本地运行的SC默认为:http://127.0.0.1:30100 66 | ``` 67 | 68 | **4.PostgreSQL数据库配置:** User Management使用了开源的[PostgreSQL](https://www.postgresql.org/)数据库存储用户的信息,本地运行时需要先安装PostgreSQL。 69 | 70 | - 推荐参考此处[安装和启动PostgreSQL](https://www.runoob.com/postgresql/windows-install-postgresql.html),建议选择9.6或以上版本; 71 | 72 | - 使用文件`/src/main/resources/usermgmtdb.sql`初始化数据库表结构; 73 | 74 | - 使用文件`/src/main/resources/usermgmtdb-data.sql`初始化默认用户信息; 75 | 76 | - 本地运行User Management服务,需要增加如下环境变量以连接数据库: 77 | 78 | ``` 79 | POSTGRES_IP:连接数据库的IP。本地运行的数据库,一般使用环回IP即可:127.0.0.1 80 | 81 | POSTGRES_PORT:连接数据库的端口。可以不配置,采取默认端口5432 82 | 83 | POSTGRES_USERNAME:数据库用户名 84 | 85 | POSTGRES_PASSWORD:数据库密码 86 | ``` 87 | 88 | **5.Redis数据库配置:** User Management使用了Redis数据库存储图形验证码、手机/邮箱验证码,本地运行时需要先安装Redis。 89 | 90 | - 推荐参考此处[安装和启动Redis](https://www.runoob.com/redis/redis-install.html); 91 | 92 | - 本地运行User Management服务,需要增加如下环境变量以连接Redis: 93 | 94 | ``` 95 | REDIS_IP:连接Redis的IP。本地运行的Redis,一般使用环回IP即可:127.0.0.1 96 | 97 | REDIS_PORT:连接Redis的端口。可以不配置,采取默认端口6379 98 | 99 | REDIS_PASSWORD:连接Redis的密码。如果没有为Redis设置密码,可以不配置 100 | ``` 101 | 102 | **6.业务平台Client配置:** User Management作为单点登录的Auth Server,各业务平台作为Auth Client。针对需要在本地运行的业务平台,User Management还需要增加对应该业务平台Client的配置信息。 103 | 104 | - 如果本地需要运行AppStore,User Management需要配置如下环境变量: 105 | 106 | ``` 107 | OAUTH_APPSTORE_CLIENT_ID:AppStore业务平台的ClientID,配置为固定值appstore-fe。也可以不配置该变量,默认为appstore-fe 108 | 109 | OAUTH_APPSTORE_CLIENT_SECRET:AppStore业务平台的Client Secret,自行定义即可,但要注意AppStore业务平台运行时设置的Client Secret要与这里保持一致。 110 | 111 | OAUTH_APPSTORE_CLIENT_URL:连接AppStore业务平台的URL,如http://x.x.x.x:30091 112 | 113 | OAUTH_APPSTORE_CLIENT_ACCESS_URL:该配置是为代理访问模式定义的变量。正常访问模式下,与OAUTH_APPSTORE_CLIENT_URL保持一致即可 114 | ``` 115 | 116 | - 类似的,如果本地要运行Developer、Mecm、ATP等平台,参考上述配置说明增加相应的环境变量配置。每个平台对应的环境变量名称请参考配置文件/src/main/resources/application.yaml中的oauth2.clients部分。 117 | 118 | - ### 拷贝前端资源 119 | 120 | 当前工程为User Management的后台,需要拷贝前端资源到后台工程的资源目录下。 121 | 122 | - 参考如下链接,编译User Management的前端资源: 123 | 124 | [https://gitee.com/edgegallery/user-mgmt-fe/blob/master/README.md](https://gitee.com/edgegallery/user-mgmt-fe/blob/master/README.md) 125 | 126 | - 编译成功后,请把dist目录下的内容拷贝到后台工程的/src/main/resources/static目录。 127 | 128 | - ### 本地运行 129 | 130 | 运行/src/main/java/org/edgegallery/user/auth/MainServer.java文件中的main函数就能启动User Management。 131 | 132 | 启动成功后,可以单独访问User Management的界面: 133 | 134 | http://x.x.x.x:8067/index.html 135 | 136 | ## Kubernetes环境部署 137 | 138 | 您还可以把User Management服务制作成Docker镜像部署在Linux环境和Kubernetes集群中运行。 139 | 140 | 请参考[helm_charts](https://gitee.com/edgegallery/helm-charts/tree/master/edgegallery)项目 141 | 142 | 143 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/controller/VerificationController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.controller; 18 | 19 | import io.swagger.annotations.ApiOperation; 20 | import io.swagger.annotations.ApiParam; 21 | import io.swagger.annotations.ApiResponse; 22 | import io.swagger.annotations.ApiResponses; 23 | import java.awt.image.BufferedImage; 24 | import java.io.ByteArrayOutputStream; 25 | import java.io.IOException; 26 | import javax.imageio.ImageIO; 27 | import javax.servlet.http.HttpServletRequest; 28 | import org.apache.http.HttpStatus; 29 | import org.apache.servicecomb.provider.rest.common.RestSchema; 30 | import org.edgegallery.user.auth.config.DescriptionConfig; 31 | import org.edgegallery.user.auth.controller.base.AbstractBeGenericServlet; 32 | import org.edgegallery.user.auth.controller.dto.request.VerificationReqByMailDto; 33 | import org.edgegallery.user.auth.controller.dto.request.VerificationReqDto; 34 | import org.edgegallery.user.auth.controller.dto.response.ErrorRespDto; 35 | import org.edgegallery.user.auth.service.IdentityService; 36 | import org.springframework.beans.factory.annotation.Autowired; 37 | import org.springframework.http.MediaType; 38 | import org.springframework.http.ResponseEntity; 39 | import org.springframework.stereotype.Controller; 40 | import org.springframework.web.bind.annotation.GetMapping; 41 | import org.springframework.web.bind.annotation.PostMapping; 42 | import org.springframework.web.bind.annotation.RequestBody; 43 | import org.springframework.web.bind.annotation.RequestMapping; 44 | import org.springframework.web.bind.annotation.ResponseBody; 45 | 46 | @RestSchema(schemaId = "identity") 47 | @RequestMapping("/v1/identity") 48 | @Controller 49 | public class VerificationController extends AbstractBeGenericServlet { 50 | 51 | @Autowired 52 | private IdentityService identityService; 53 | 54 | /** 55 | * send verification code by sms. 56 | * 57 | * @param request Request Content Body 58 | * @return send result 59 | */ 60 | @PostMapping(value = "/sms", produces = MediaType.APPLICATION_JSON_VALUE) 61 | @ApiOperation(value = "send verification code by sms", response = Object.class, notes = 62 | DescriptionConfig.VERIFICATION_SMS_MSG) 63 | @ApiResponses(value = { 64 | @ApiResponse(code = HttpStatus.SC_EXPECTATION_FAILED, message = "Expectation Failed", 65 | response = ErrorRespDto.class)}) 66 | public ResponseEntity sendVerificationCodeBySms( 67 | @ApiParam(value = "verificationRequest", required = true) @RequestBody VerificationReqDto request) { 68 | return buildCreatedResponse(identityService.sendVerificationCodeBySms(request)); 69 | } 70 | 71 | /** 72 | * send verification code by mail. 73 | * 74 | * @param request Request Content Body 75 | * @return send result 76 | */ 77 | @PostMapping(value = "/mail", produces = MediaType.APPLICATION_JSON_VALUE) 78 | @ApiOperation(value = "send verification code by mail", response = Object.class, notes = 79 | DescriptionConfig.VERIFICATION_MAIL_MSG) 80 | @ApiResponses(value = { 81 | @ApiResponse(code = HttpStatus.SC_EXPECTATION_FAILED, message = "Expectation Failed", 82 | response = ErrorRespDto.class)}) 83 | public ResponseEntity sendVerificationCodeByMail( 84 | @ApiParam(value = "verificationRequest", required = true) @RequestBody VerificationReqByMailDto request) { 85 | return buildCreatedResponse(identityService.sendVerificationCodeByMail(request)); 86 | } 87 | 88 | /** 89 | * generate image verification code. 90 | * 91 | * @return generate result 92 | */ 93 | @GetMapping(value = "/verifycode-image", produces = MediaType.IMAGE_JPEG_VALUE) 94 | @ResponseBody 95 | @ApiOperation(value = "generate image verification code", response = Object.class) 96 | public byte[] generateImgVerificationCode() throws IOException { 97 | BufferedImage image = identityService.generateImgVerificationCode(); 98 | ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 99 | ImageIO.write(image, "JPEG", outputStream); 100 | return outputStream.toByteArray(); 101 | } 102 | 103 | /** 104 | * precheck image verification code. 105 | * 106 | * @param httpServletRequest HTTP Servlet Request 107 | * @return check result 108 | */ 109 | @GetMapping(value = "/verifycode-image/precheck", produces = MediaType.APPLICATION_JSON_VALUE) 110 | @ResponseBody 111 | @ApiOperation(value = "check image verification code", response = Object.class) 112 | public ResponseEntity preCheckImgVerificationCode(HttpServletRequest httpServletRequest) { 113 | return buildResponse(identityService.preCheckImgVerificationCode(httpServletRequest)); 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /src/test/java/org/edgegallery/user/auth/service/OAuthTokenTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.service; 18 | 19 | import java.util.Collection; 20 | import java.util.Collections; 21 | import java.util.HashMap; 22 | import java.util.HashSet; 23 | import java.util.Map; 24 | import java.util.UUID; 25 | import mockit.Mock; 26 | import mockit.MockUp; 27 | import org.edgegallery.user.auth.MainServer; 28 | import org.edgegallery.user.auth.config.security.ExtendAuthorizationCodeTokenGranter; 29 | import org.edgegallery.user.auth.db.EnumRole; 30 | import org.edgegallery.user.auth.external.iam.model.ExternalUser; 31 | import org.edgegallery.user.auth.utils.Consts; 32 | import org.junit.After; 33 | import org.junit.Assert; 34 | import org.junit.Before; 35 | import org.junit.Test; 36 | import org.junit.runner.RunWith; 37 | import org.springframework.beans.factory.annotation.Autowired; 38 | import org.springframework.boot.test.context.SpringBootTest; 39 | import org.springframework.context.annotation.EnableAspectJAutoProxy; 40 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 41 | import org.springframework.security.core.Authentication; 42 | import org.springframework.security.core.GrantedAuthority; 43 | import org.springframework.security.core.userdetails.User; 44 | import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; 45 | import org.springframework.security.oauth2.common.OAuth2AccessToken; 46 | import org.springframework.security.oauth2.provider.OAuth2Authentication; 47 | import org.springframework.security.oauth2.provider.OAuth2Request; 48 | import org.springframework.security.oauth2.provider.TokenGranter; 49 | import org.springframework.security.oauth2.provider.TokenRequest; 50 | import org.springframework.security.oauth2.provider.token.TokenEnhancer; 51 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 52 | 53 | @SpringBootTest(classes = {MainServer.class}) 54 | @RunWith(SpringJUnit4ClassRunner.class) 55 | @EnableAspectJAutoProxy(proxyTargetClass = true) 56 | public class OAuthTokenTest { 57 | 58 | private static final String TEST_REDIRECT_URI = "test_redirect_uri"; 59 | 60 | private static final String TEST_CLIENT_ID = "test"; 61 | 62 | @Autowired 63 | private TokenGranter tokenGranter; 64 | 65 | @Autowired 66 | private TokenEnhancer authServerTokenEnhancer; 67 | 68 | @Before 69 | public void begin() { 70 | } 71 | 72 | @After 73 | public void end() { 74 | } 75 | 76 | @Test 77 | public void grantToken() { 78 | new MockUp() { 79 | @Mock 80 | private OAuth2Authentication getStoredAuth(String authorizationCode) { 81 | return buildOAuth2Authentication(false); 82 | } 83 | }; 84 | 85 | TokenRequest tokenReq = new TokenRequest(buildReqParameters(), TEST_CLIENT_ID, Collections.emptyList(), 86 | Consts.GRANT_TYPE); 87 | OAuth2AccessToken oAuth2AccessToken = tokenGranter.grant(Consts.GRANT_TYPE, tokenReq); 88 | Assert.assertNotNull(oAuth2AccessToken); 89 | } 90 | 91 | @Test 92 | public void tokenEnhance() { 93 | OAuth2AccessToken result = authServerTokenEnhancer 94 | .enhance(buildOAuth2AccessToken(), buildOAuth2Authentication(false)); 95 | Assert.assertNotNull(result); 96 | } 97 | 98 | @Test 99 | public void tokenEnhance_externaluser() { 100 | OAuth2AccessToken result = authServerTokenEnhancer 101 | .enhance(buildOAuth2AccessToken(), buildOAuth2Authentication(true)); 102 | Assert.assertNotNull(result); 103 | } 104 | 105 | private OAuth2AccessToken buildOAuth2AccessToken() { 106 | OAuth2AccessToken oAuth2AccessToken = new DefaultOAuth2AccessToken(UUID.randomUUID().toString()); 107 | return oAuth2AccessToken; 108 | } 109 | 110 | private OAuth2Authentication buildOAuth2Authentication(boolean buildExternalUser) { 111 | OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(buildOAuth2Request(), 112 | buildUserAuthentication(buildExternalUser)); 113 | return oAuth2Authentication; 114 | } 115 | 116 | private OAuth2Request buildOAuth2Request() { 117 | return new OAuth2Request(buildReqParameters(), TEST_CLIENT_ID, Collections.emptyList(), true, 118 | Collections.emptySet(), Collections.emptySet(), TEST_REDIRECT_URI, Collections.emptySet(), 119 | Collections.emptyMap()); 120 | } 121 | 122 | private Map buildReqParameters() { 123 | Map requestParameters = new HashMap<>(); 124 | requestParameters.put("code", "xxx"); 125 | requestParameters.put("grant_type", Consts.GRANT_TYPE); 126 | requestParameters.put("response_type", "code"); 127 | requestParameters.put("redirect_uri", TEST_REDIRECT_URI); 128 | 129 | return requestParameters; 130 | } 131 | 132 | private Authentication buildUserAuthentication(boolean buildExternalUser) { 133 | String userName = buildExternalUser ? new ExternalUser("userid-test", "username-test", "user-test@s.c", 134 | EnumRole.TENANT.name()).build() : Consts.SUPER_ADMIN_NAME; 135 | User principal = new User(userName, "", true, true, true, true, Collections.emptyList()); 136 | return new UsernamePasswordAuthenticationToken(principal, null); 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /src/main/java/org/edgegallery/user/auth/config/security/LoginSuccessHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.config.security; 18 | 19 | import java.io.IOException; 20 | import javax.servlet.ServletException; 21 | import javax.servlet.http.HttpServletRequest; 22 | import javax.servlet.http.HttpServletResponse; 23 | import org.edgegallery.user.auth.db.entity.TenantPo; 24 | import org.edgegallery.user.auth.db.mapper.TenantPoMapper; 25 | import org.edgegallery.user.auth.external.iam.ExternalUserUtil; 26 | import org.edgegallery.user.auth.external.iam.model.ExternalUser; 27 | import org.edgegallery.user.auth.utils.Consts; 28 | import org.edgegallery.user.auth.utils.UserLockUtil; 29 | import org.slf4j.Logger; 30 | import org.slf4j.LoggerFactory; 31 | import org.springframework.beans.factory.annotation.Autowired; 32 | import org.springframework.http.HttpStatus; 33 | import org.springframework.security.core.Authentication; 34 | import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; 35 | import org.springframework.security.web.savedrequest.HttpSessionRequestCache; 36 | import org.springframework.security.web.savedrequest.RequestCache; 37 | import org.springframework.security.web.savedrequest.SavedRequest; 38 | import org.springframework.stereotype.Component; 39 | import org.springframework.util.StringUtils; 40 | 41 | @Component 42 | public class LoginSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler { 43 | 44 | private static final Logger LOGGER = LoggerFactory.getLogger(LoginSuccessHandler.class); 45 | 46 | private static final String HEADER_KEY_PW_MODIFY_SCENE = "pwmodiscene"; 47 | 48 | @Autowired 49 | private MecUserDetailsServiceImpl mecUserDetailsService; 50 | 51 | @Autowired 52 | private TenantPoMapper tenantPoMapper; 53 | 54 | @Autowired 55 | private UserLockUtil userLockUtil; 56 | 57 | @Override 58 | public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, 59 | Authentication authentication) throws IOException, ServletException { 60 | response.setStatus(HttpStatus.OK.value()); 61 | LOGGER.info("login success."); 62 | 63 | String userName = authentication.getName(); 64 | boolean isExternalUser = ExternalUserUtil.isExternalUser(userName); 65 | if (isExternalUser) { 66 | clearExternalUserLock(userName); 67 | } else { 68 | clearInnerUserLock(userName); 69 | } 70 | 71 | if (userName.equalsIgnoreCase(Consts.GUEST_USER_NAME)) { 72 | String redirectUrl = getRedirectUrl(request, response); 73 | if (redirectUrl != null) { 74 | redirectUrl = redirectUrl.replace("login", "#/index"); 75 | response.sendRedirect(redirectUrl); 76 | } 77 | } else { 78 | if (!isExternalUser) { 79 | int pwModiScene = mecUserDetailsService.getPwModifyScene(userName); 80 | if (pwModiScene > 0) { 81 | response.addIntHeader(HEADER_KEY_PW_MODIFY_SCENE, pwModiScene); 82 | } 83 | } 84 | } 85 | } 86 | 87 | private void clearInnerUserLock(String userName) { 88 | userLockUtil.clearFailedCount(userName); 89 | 90 | TenantPo tenant = tenantPoMapper.getTenantByUniqueFlag(userName); 91 | if (tenant == null) { 92 | LOGGER.error("user login succeeded but not found, it is abnormal."); 93 | return; 94 | } 95 | 96 | if (!StringUtils.isEmpty(tenant.getMailAddress())) { 97 | userLockUtil.clearFailedCount(tenant.getMailAddress()); 98 | } 99 | 100 | if (!StringUtils.isEmpty(tenant.getTelephoneNumber())) { 101 | userLockUtil.clearFailedCount(tenant.getTelephoneNumber()); 102 | } 103 | } 104 | 105 | private void clearExternalUserLock(String userName) { 106 | ExternalUser externalUser = new ExternalUser(); 107 | externalUser.parse(userName); 108 | 109 | if (!StringUtils.isEmpty(externalUser.getUserName())) { 110 | userLockUtil.clearFailedCount(externalUser.getUserName()); 111 | } 112 | 113 | if (!StringUtils.isEmpty(externalUser.getMailAddress())) { 114 | userLockUtil.clearFailedCount(externalUser.getMailAddress()); 115 | } 116 | } 117 | 118 | private String getRedirectUrl(HttpServletRequest request, HttpServletResponse response) { 119 | RequestCache cache = new HttpSessionRequestCache(); 120 | SavedRequest savedRequest = cache.getRequest(request, response); 121 | if (savedRequest == null) { 122 | return null; 123 | } 124 | String url = savedRequest.getRedirectUrl(); 125 | if (StringUtils.isEmpty(url)) { 126 | return null; 127 | } 128 | String[] urlArray = url.split("\\?"); 129 | if (urlArray.length != 2) { 130 | return null; 131 | } 132 | String[] parameters = urlArray[1].split("&"); 133 | String redirectUrl = null; 134 | for (String parameter : parameters) { 135 | String[] keyValue = parameter.split("="); 136 | if (keyValue.length == 2 && keyValue[0].equalsIgnoreCase("redirect_uri")) { 137 | redirectUrl = keyValue[1]; 138 | break; 139 | } 140 | } 141 | return redirectUrl; 142 | } 143 | } -------------------------------------------------------------------------------- /src/test/java/org/edgegallery/user/auth/controller/RegisterApiTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.controller; 18 | 19 | import fj.data.Either; 20 | import javax.ws.rs.core.Response.Status; 21 | import org.edgegallery.user.auth.controller.dto.response.ErrorRespDto; 22 | import org.edgegallery.user.auth.utils.ErrorEnum; 23 | import org.junit.Test; 24 | import org.junit.runner.RunWith; 25 | import org.edgegallery.user.auth.controller.dto.request.TenantRegisterReqDto; 26 | import org.edgegallery.user.auth.controller.dto.response.FormatRespDto; 27 | import org.edgegallery.user.auth.controller.dto.response.TenantRespDto; 28 | import org.mockito.Mockito; 29 | import org.mockito.junit.MockitoJUnitRunner; 30 | import org.springframework.http.MediaType; 31 | import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; 32 | import org.springframework.test.web.servlet.result.MockMvcResultMatchers; 33 | 34 | @RunWith(MockitoJUnitRunner.class) 35 | public class RegisterApiTest extends UserControllerTest { 36 | 37 | @Test 38 | public void should_successfully_when_register_right() throws Exception { 39 | TenantRegisterReqDto request = new TenantRegisterReqDto(); 40 | request.setUsername("username"); 41 | request.setPassword("password"); 42 | 43 | Either response = Either.left(new TenantRespDto()); 44 | Mockito.when(userMgmtService.register(Mockito.any(TenantRegisterReqDto.class))).thenReturn(response); 45 | 46 | mvc.perform(MockMvcRequestBuilders.post("/v1/users").contentType(MediaType.APPLICATION_JSON_VALUE) 47 | .content(gson.toJson(request)) 48 | .accept(MediaType.APPLICATION_JSON_VALUE)).andExpect(MockMvcResultMatchers.status().isCreated()); 49 | 50 | } 51 | 52 | @Test 53 | public void should_failed_when_username_less_then_6() throws Exception { 54 | TenantRegisterReqDto request = new TenantRegisterReqDto(); 55 | request.setUsername("user"); 56 | request.setPassword("password"); 57 | 58 | Either response = Either.right(new FormatRespDto(Status.BAD_REQUEST, 59 | ErrorRespDto.build(ErrorEnum.PARA_ILLEGAL))); 60 | Mockito.when(userMgmtService.register(Mockito.any(TenantRegisterReqDto.class))).thenReturn(response); 61 | 62 | mvc.perform(MockMvcRequestBuilders.post("/v1/users").contentType(MediaType.APPLICATION_JSON_VALUE) 63 | .content(gson.toJson(request)) 64 | .accept(MediaType.APPLICATION_JSON_VALUE)).andExpect(MockMvcResultMatchers.status().isBadRequest()); 65 | 66 | } 67 | 68 | @Test 69 | public void should_failed_when_pw_less_then_6() throws Exception { 70 | TenantRegisterReqDto request = new TenantRegisterReqDto(); 71 | request.setUsername("username"); 72 | request.setPassword("pass"); 73 | 74 | Either response = Either.right(new FormatRespDto(Status.BAD_REQUEST, 75 | ErrorRespDto.build(ErrorEnum.PARA_ILLEGAL))); 76 | Mockito.when(userMgmtService.register(Mockito.any(TenantRegisterReqDto.class))).thenReturn(response); 77 | 78 | mvc.perform(MockMvcRequestBuilders.post("/v1/users").contentType(MediaType.APPLICATION_JSON_VALUE) 79 | .content(gson.toJson(request)) 80 | .accept(MediaType.APPLICATION_JSON_VALUE)).andExpect(MockMvcResultMatchers.status().isBadRequest()); 81 | 82 | } 83 | 84 | @Test 85 | public void should_failed_when_db_error() throws Exception { 86 | 87 | TenantRegisterReqDto request = new TenantRegisterReqDto(); 88 | request.setUsername("username"); 89 | request.setPassword("password"); 90 | Either response = Either.right(new FormatRespDto(Status.EXPECTATION_FAILED, 91 | ErrorRespDto.build(ErrorEnum.USER_REGISTER_FAILED))); 92 | Mockito.when(userMgmtService.register(Mockito.any(TenantRegisterReqDto.class))).thenReturn(response); 93 | 94 | mvc.perform(MockMvcRequestBuilders.post("/v1/users").contentType(MediaType.APPLICATION_JSON_VALUE) 95 | .content(gson.toJson(request)) 96 | .accept(MediaType.APPLICATION_JSON_VALUE)) 97 | .andExpect(MockMvcResultMatchers.status().isExpectationFailed()); 98 | } 99 | 100 | @Test 101 | public void should_failed_when_no_username() throws Exception { 102 | TenantRegisterReqDto request = new TenantRegisterReqDto(); 103 | request.setPassword("password"); 104 | Either response = Either.right(new FormatRespDto(Status.BAD_REQUEST, 105 | ErrorRespDto.build(ErrorEnum.PARA_ILLEGAL))); 106 | Mockito.when(userMgmtService.register(Mockito.any(TenantRegisterReqDto.class))).thenReturn(response); 107 | 108 | mvc.perform(MockMvcRequestBuilders.post("/v1/users").contentType(MediaType.APPLICATION_JSON_VALUE) 109 | .content(gson.toJson(request)) 110 | .accept(MediaType.APPLICATION_JSON_VALUE)) 111 | .andExpect(MockMvcResultMatchers.status().isBadRequest()); 112 | } 113 | 114 | @Test 115 | public void should_failed_when_no_pw() throws Exception { 116 | TenantRegisterReqDto request = new TenantRegisterReqDto(); 117 | request.setUsername("username"); 118 | Either response = Either.right(new FormatRespDto(Status.BAD_REQUEST, 119 | ErrorRespDto.build(ErrorEnum.PARA_ILLEGAL))); 120 | Mockito.when(userMgmtService.register(Mockito.any(TenantRegisterReqDto.class))).thenReturn(response); 121 | 122 | mvc.perform(MockMvcRequestBuilders.post("/v1/users").contentType(MediaType.APPLICATION_JSON_VALUE) 123 | .content(gson.toJson(request)) 124 | .accept(MediaType.APPLICATION_JSON_VALUE)) 125 | .andExpect(MockMvcResultMatchers.status().isBadRequest()); 126 | } 127 | 128 | } 129 | -------------------------------------------------------------------------------- /src/test/java/org/edgegallery/user/auth/service/RegisterTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 Huawei Technologies Co., Ltd. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.edgegallery.user.auth.service; 18 | 19 | import fj.data.Either; 20 | import mockit.Mock; 21 | import mockit.MockUp; 22 | import org.apache.commons.lang3.RandomStringUtils; 23 | import org.junit.Assert; 24 | import org.junit.Test; 25 | import org.junit.runner.RunWith; 26 | import org.edgegallery.user.auth.MainServer; 27 | import org.edgegallery.user.auth.controller.dto.request.TenantRegisterReqDto; 28 | import org.edgegallery.user.auth.controller.dto.response.FormatRespDto; 29 | import org.edgegallery.user.auth.controller.dto.response.TenantRespDto; 30 | import org.springframework.beans.factory.annotation.Autowired; 31 | import org.springframework.boot.test.context.SpringBootTest; 32 | import org.springframework.context.annotation.EnableAspectJAutoProxy; 33 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 34 | 35 | @SpringBootTest(classes = {MainServer.class}) 36 | @RunWith(SpringJUnit4ClassRunner.class) 37 | @EnableAspectJAutoProxy(proxyTargetClass = true) 38 | public class RegisterTest { 39 | 40 | @Autowired 41 | protected UserMgmtService userMgmtService; 42 | 43 | @Test 44 | public void should_successfully_when_register_new_user() { 45 | String username = "s" + RandomStringUtils.randomAlphanumeric(16); 46 | String telephone = "13" + RandomStringUtils.randomNumeric(9); 47 | 48 | TenantRegisterReqDto request = new TenantRegisterReqDto(); 49 | request.setUsername(username); 50 | request.setPassword("password1234."); 51 | request.setTelephone(telephone); 52 | request.setCompany("huawei"); 53 | request.setGender("male"); 54 | 55 | Either either = userMgmtService.register(request); 56 | Assert.assertTrue(either.isLeft()); 57 | } 58 | 59 | @Test 60 | public void should_failed_when_username_less_6() { 61 | TenantRegisterReqDto request = new TenantRegisterReqDto(); 62 | request.setUsername("user5"); 63 | request.setPassword("nihao!@123456"); 64 | request.setTelephone("15012345678"); 65 | request.setCompany("huawei"); 66 | request.setGender("male"); 67 | 68 | Either either = userMgmtService.register(request); 69 | Assert.assertTrue(either.isRight()); 70 | Assert.assertEquals(400, either.right().value().getErrStatus().getStatusCode()); 71 | 72 | } 73 | 74 | @Test 75 | public void should_failed_when_pw_less_6() { 76 | TenantRegisterReqDto request = new TenantRegisterReqDto(); 77 | request.setUsername("username"); 78 | request.setPassword("!@1Ab"); 79 | request.setTelephone("15012345678"); 80 | request.setCompany("huawei"); 81 | request.setGender("male"); 82 | 83 | Either either = userMgmtService.register(request); 84 | Assert.assertTrue(either.isRight()); 85 | 86 | } 87 | 88 | @Test 89 | public void should_failed_when_no_username() { 90 | TenantRegisterReqDto request = new TenantRegisterReqDto(); 91 | request.setPassword("nihao!@123456"); 92 | request.setTelephone("15012345678"); 93 | request.setCompany("huawei"); 94 | request.setGender("male"); 95 | 96 | Either either = userMgmtService.register(request); 97 | Assert.assertTrue(either.isRight()); 98 | 99 | } 100 | 101 | @Test 102 | public void should_failed_when_no_password() { 103 | TenantRegisterReqDto request = new TenantRegisterReqDto(); 104 | request.setUsername("username"); 105 | request.setTelephone("15012345678"); 106 | request.setCompany("huawei"); 107 | request.setGender("male"); 108 | 109 | Either either = userMgmtService.register(request); 110 | Assert.assertTrue(either.isRight()); 111 | 112 | } 113 | 114 | @Test 115 | public void should_failed_when_no_telNo() { 116 | TenantRegisterReqDto request = new TenantRegisterReqDto(); 117 | request.setUsername("username"); 118 | request.setPassword("nihao!@123456"); 119 | request.setCompany("huawei"); 120 | request.setGender("male"); 121 | 122 | Either either = userMgmtService.register(request); 123 | Assert.assertTrue(either.isRight()); 124 | } 125 | 126 | @Test 127 | public void should_failed_when_telNo_existed() { 128 | TenantRegisterReqDto request = new TenantRegisterReqDto(); 129 | request.setUsername("username"); 130 | request.setPassword("nihao!@123456"); 131 | request.setTelephone("15012345678"); 132 | request.setCompany("huawei"); 133 | request.setGender("male"); 134 | 135 | Either either = userMgmtService.register(request); 136 | Assert.assertTrue(either.isRight()); 137 | } 138 | 139 | @Test 140 | public void should_failed_when_username_existed() { 141 | TenantRegisterReqDto request = new TenantRegisterReqDto(); 142 | request.setUsername("username"); 143 | request.setPassword("nihao!@123456"); 144 | request.setTelephone("15012345678"); 145 | request.setCompany("huawei"); 146 | request.setGender("male"); 147 | 148 | Either either = userMgmtService.register(request); 149 | Assert.assertTrue(either.isLeft()); 150 | request.setTelephone("15012345677"); 151 | either = userMgmtService.register(request); 152 | Assert.assertTrue(either.isRight()); 153 | } 154 | 155 | @Test 156 | public void should_failed_when_sms_code_error() { 157 | TenantRegisterReqDto request = new TenantRegisterReqDto(); 158 | request.setUsername("username"); 159 | request.setPassword("nihao!@123456"); 160 | request.setTelephone("15012345678"); 161 | request.setCompany("huawei"); 162 | request.setGender("male"); 163 | 164 | Either either = userMgmtService.register(request); 165 | Assert.assertTrue(either.isRight()); 166 | } 167 | } 168 | --------------------------------------------------------------------------------