This is an automated email from the ASF dual-hosted git repository.
gongchao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hertzbeat.git
The following commit(s) were added to refs/heads/master by this push:
new a9827bbce [refactor] move code from AccountController to
AccountService (#2373)
a9827bbce is described below
commit a9827bbcef7bae74e301a79491f1dc8df33120c2
Author: Calvin <[email protected]>
AuthorDate: Sun Jul 28 10:35:01 2024 +0800
[refactor] move code from AccountController to AccountService (#2373)
Co-authored-by: tomsun28 <[email protected]>
---
.../manager/controller/AccountController.java | 78 +++------------
.../hertzbeat/manager/service/AccountService.java | 44 +++++++++
.../manager/service/impl/AccountServiceImpl.java | 110 +++++++++++++++++++++
.../manager/controller/AccountControllerTest.java | 19 +++-
4 files changed, 185 insertions(+), 66 deletions(-)
diff --git
a/manager/src/main/java/org/apache/hertzbeat/manager/controller/AccountController.java
b/manager/src/main/java/org/apache/hertzbeat/manager/controller/AccountController.java
index 54fdd517e..29a53fbe5 100644
---
a/manager/src/main/java/org/apache/hertzbeat/manager/controller/AccountController.java
+++
b/manager/src/main/java/org/apache/hertzbeat/manager/controller/AccountController.java
@@ -19,25 +19,19 @@ package org.apache.hertzbeat.manager.controller;
import static
org.apache.hertzbeat.common.constants.CommonConstants.MONITOR_LOGIN_FAILED_CODE;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
-import com.usthe.sureness.provider.SurenessAccount;
-import com.usthe.sureness.provider.SurenessAccountProvider;
-import com.usthe.sureness.provider.ducument.DocumentAccountProvider;
-import com.usthe.sureness.util.JsonWebTokenUtil;
-import com.usthe.sureness.util.Md5Util;
-import io.jsonwebtoken.Claims;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
-import java.util.HashMap;
-import java.util.List;
import java.util.Map;
+import javax.naming.AuthenticationException;
import lombok.extern.slf4j.Slf4j;
import org.apache.hertzbeat.common.entity.dto.Message;
-import org.apache.hertzbeat.common.util.JsonUtil;
import org.apache.hertzbeat.manager.pojo.dto.LoginDto;
import org.apache.hertzbeat.manager.pojo.dto.RefreshTokenResponse;
+import org.apache.hertzbeat.manager.service.AccountService;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@@ -50,49 +44,21 @@ import
org.springframework.web.bind.annotation.RestController;
* Authentication registration TOKEN management API
*/
@Tag(name = "Auth Manage API")
-@RestController()
+@RestController
@RequestMapping(value = "/api/account/auth", produces =
{APPLICATION_JSON_VALUE})
@Slf4j
public class AccountController {
- /**
- * Token validity time in seconds
- */
- private static final long PERIOD_TIME = 3600L;
- /**
- * account data provider
- */
- private SurenessAccountProvider accountProvider = new
DocumentAccountProvider();
+ @Autowired
+ private AccountService accountService;
@PostMapping("/form")
@Operation(summary = "Account password login to obtain associated user
information", description = "Account password login to obtain associated user
information")
public ResponseEntity<Message<Map<String, String>>> authGetToken(@Valid
@RequestBody LoginDto loginDto) {
- SurenessAccount account =
accountProvider.loadAccount(loginDto.getIdentifier());
- if (account == null || account.getPassword() == null) {
- return ResponseEntity.ok(Message.fail(MONITOR_LOGIN_FAILED_CODE,
"Incorrect Account or Password"));
- } else {
- String password = loginDto.getCredential();
- if (account.getSalt() != null) {
- password = Md5Util.md5(password + account.getSalt());
- }
- if (!account.getPassword().equals(password)) {
- return
ResponseEntity.ok(Message.fail(MONITOR_LOGIN_FAILED_CODE, "Incorrect Account or
Password"));
- }
- if (account.isDisabledAccount() || account.isExcessiveAttempts()) {
- return
ResponseEntity.ok(Message.fail(MONITOR_LOGIN_FAILED_CODE, "Expired or Illegal
Account"));
- }
+ try {
+ return
ResponseEntity.ok(Message.success(accountService.authGetToken(loginDto)));
+ } catch (AuthenticationException e) {
+ return ResponseEntity.ok(Message.fail(MONITOR_LOGIN_FAILED_CODE,
e.getMessage()));
}
- // Get the roles the user has - rbac
- List<String> roles = account.getOwnRoles();
- // Issue TOKEN
- String issueToken =
JsonWebTokenUtil.issueJwt(loginDto.getIdentifier(), PERIOD_TIME, roles);
- Map<String, Object> customClaimMap = new HashMap<>(1);
- customClaimMap.put("refresh", true);
- String issueRefresh =
JsonWebTokenUtil.issueJwt(loginDto.getIdentifier(), PERIOD_TIME << 5,
customClaimMap);
- Map<String, String> resp = new HashMap<>(2);
- resp.put("token", issueToken);
- resp.put("refreshToken", issueRefresh);
- resp.put("role", JsonUtil.toJson(roles));
- return ResponseEntity.ok(Message.success(resp));
}
@GetMapping("/refresh/{refreshToken}")
@@ -101,30 +67,12 @@ public class AccountController {
@Parameter(description = "Refresh TOKEN", example = "xxx")
@PathVariable("refreshToken") @NotNull final String refreshToken) {
try {
- Claims claims = JsonWebTokenUtil.parseJwt(refreshToken);
- String userId = String.valueOf(claims.getSubject());
- boolean isRefresh = claims.get("refresh", Boolean.class);
- if (userId == null || !isRefresh) {
- return
ResponseEntity.ok(Message.fail(MONITOR_LOGIN_FAILED_CODE, "Illegal Refresh
Token"));
- }
- SurenessAccount account = accountProvider.loadAccount(userId);
- if (account == null) {
- return
ResponseEntity.ok(Message.fail(MONITOR_LOGIN_FAILED_CODE, "Not Exists This
Token Mapping Account"));
- }
- List<String> roles = account.getOwnRoles();
- String issueToken = issueToken(userId, roles, PERIOD_TIME);
- String issueRefresh = issueToken(userId, roles, PERIOD_TIME << 5);
- RefreshTokenResponse response = new
RefreshTokenResponse(issueToken, issueRefresh);
- return ResponseEntity.ok(Message.success(response));
+ return
ResponseEntity.ok(Message.success(accountService.refreshToken(refreshToken)));
+ } catch (AuthenticationException e) {
+ return ResponseEntity.ok(Message.fail(MONITOR_LOGIN_FAILED_CODE,
e.getMessage()));
} catch (Exception e) {
log.error("Exception occurred during token refresh: {}",
e.getClass().getName(), e);
return ResponseEntity.ok(Message.fail(MONITOR_LOGIN_FAILED_CODE,
"Refresh Token Expired or Error"));
}
}
-
- private String issueToken(String userId, List<String> roles, long
expirationMillis) {
- Map<String, Object> customClaimMap = new HashMap<>(1);
- customClaimMap.put("refresh", true);
- return JsonWebTokenUtil.issueJwt(userId, expirationMillis, roles,
customClaimMap);
- }
}
diff --git
a/manager/src/main/java/org/apache/hertzbeat/manager/service/AccountService.java
b/manager/src/main/java/org/apache/hertzbeat/manager/service/AccountService.java
new file mode 100644
index 000000000..9a47f80c1
--- /dev/null
+++
b/manager/src/main/java/org/apache/hertzbeat/manager/service/AccountService.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hertzbeat.manager.service;
+
+import java.util.Map;
+import javax.naming.AuthenticationException;
+import org.apache.hertzbeat.manager.pojo.dto.LoginDto;
+import org.apache.hertzbeat.manager.pojo.dto.RefreshTokenResponse;
+
+/**
+ * Account service
+ */
+public interface AccountService {
+ /**
+ * Account password login to obtain associated user information
+ * @param loginDto loginDto
+ * @return token info
+ * @throws AuthenticationException when authentication is failed
+ */
+ Map<String, String> authGetToken(LoginDto loginDto) throws
AuthenticationException;
+
+ /**
+ * Use refresh TOKEN to re-acquire TOKEN
+ * @param refreshToken refreshToken
+ * @return token and refresh token
+ * @throws AuthenticationException failed to refresh
+ */
+ RefreshTokenResponse refreshToken(String refreshToken) throws
AuthenticationException;
+}
diff --git
a/manager/src/main/java/org/apache/hertzbeat/manager/service/impl/AccountServiceImpl.java
b/manager/src/main/java/org/apache/hertzbeat/manager/service/impl/AccountServiceImpl.java
new file mode 100644
index 000000000..e59a18f95
--- /dev/null
+++
b/manager/src/main/java/org/apache/hertzbeat/manager/service/impl/AccountServiceImpl.java
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hertzbeat.manager.service.impl;
+
+import com.usthe.sureness.provider.SurenessAccount;
+import com.usthe.sureness.provider.SurenessAccountProvider;
+import com.usthe.sureness.provider.ducument.DocumentAccountProvider;
+import com.usthe.sureness.util.JsonWebTokenUtil;
+import com.usthe.sureness.util.Md5Util;
+import io.jsonwebtoken.Claims;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.naming.AuthenticationException;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.hertzbeat.common.util.JsonUtil;
+import org.apache.hertzbeat.manager.pojo.dto.LoginDto;
+import org.apache.hertzbeat.manager.pojo.dto.RefreshTokenResponse;
+import org.apache.hertzbeat.manager.service.AccountService;
+import org.springframework.core.Ordered;
+import org.springframework.core.annotation.Order;
+import org.springframework.stereotype.Service;
+
+/**
+ * Implementation of Account service
+ */
+@Service
+@Order(value = Ordered.HIGHEST_PRECEDENCE)
+@Slf4j
+public class AccountServiceImpl implements AccountService {
+ /**
+ * Token validity time in seconds
+ */
+ private static final long PERIOD_TIME = 3600L;
+ /**
+ * account data provider
+ */
+ private final SurenessAccountProvider accountProvider = new
DocumentAccountProvider();
+
+ @Override
+ public Map<String, String> authGetToken(LoginDto loginDto) throws
AuthenticationException {
+ SurenessAccount account =
accountProvider.loadAccount(loginDto.getIdentifier());
+ if (account == null || account.getPassword() == null) {
+ throw new AuthenticationException("Incorrect Account or Password");
+ } else {
+ String password = loginDto.getCredential();
+ if (account.getSalt() != null) {
+ password = Md5Util.md5(password + account.getSalt());
+ }
+ if (!account.getPassword().equals(password)) {
+ throw new AuthenticationException("Incorrect Account or
Password");
+ }
+ if (account.isDisabledAccount() || account.isExcessiveAttempts()) {
+ throw new AuthenticationException("Expired or Illegal
Account");
+ }
+ }
+ // Get the roles the user has - rbac
+ List<String> roles = account.getOwnRoles();
+ // Issue TOKEN
+ String issueToken =
JsonWebTokenUtil.issueJwt(loginDto.getIdentifier(), PERIOD_TIME, roles);
+ Map<String, Object> customClaimMap = new HashMap<>(1);
+ customClaimMap.put("refresh", true);
+ String issueRefresh =
JsonWebTokenUtil.issueJwt(loginDto.getIdentifier(), PERIOD_TIME << 5,
customClaimMap);
+ Map<String, String> resp = new HashMap<>(2);
+ resp.put("token", issueToken);
+ resp.put("refreshToken", issueRefresh);
+ resp.put("role", JsonUtil.toJson(roles));
+
+ return resp;
+ }
+
+ @Override
+ public RefreshTokenResponse refreshToken(String refreshToken) throws
AuthenticationException {
+ Claims claims = JsonWebTokenUtil.parseJwt(refreshToken);
+ String userId = String.valueOf(claims.getSubject());
+ boolean isRefresh = claims.get("refresh", Boolean.class);
+ if (userId == null || !isRefresh) {
+ throw new AuthenticationException("Illegal Refresh Token");
+ }
+ SurenessAccount account = accountProvider.loadAccount(userId);
+ if (account == null) {
+ throw new AuthenticationException("Not Exists This Token Mapping
Account");
+ }
+ List<String> roles = account.getOwnRoles();
+ String issueToken = issueToken(userId, roles, PERIOD_TIME);
+ String issueRefresh = issueToken(userId, roles, PERIOD_TIME << 5);
+ return new RefreshTokenResponse(issueToken, issueRefresh);
+ }
+
+ private String issueToken(String userId, List<String> roles, long
expirationMillis) {
+ Map<String, Object> customClaimMap = new HashMap<>(1);
+ customClaimMap.put("refresh", true);
+ return JsonWebTokenUtil.issueJwt(userId, expirationMillis, roles,
customClaimMap);
+ }
+}
diff --git
a/manager/src/test/java/org/apache/hertzbeat/manager/controller/AccountControllerTest.java
b/manager/src/test/java/org/apache/hertzbeat/manager/controller/AccountControllerTest.java
index 634c32a4e..cb50ea0e1 100644
---
a/manager/src/test/java/org/apache/hertzbeat/manager/controller/AccountControllerTest.java
+++
b/manager/src/test/java/org/apache/hertzbeat/manager/controller/AccountControllerTest.java
@@ -20,13 +20,19 @@ package org.apache.hertzbeat.manager.controller;
import static
org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static
org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import com.usthe.sureness.util.JsonWebTokenUtil;
+import java.util.HashMap;
+import java.util.Map;
+import javax.naming.AuthenticationException;
import org.apache.hertzbeat.common.constants.CommonConstants;
import org.apache.hertzbeat.common.util.JsonUtil;
import org.apache.hertzbeat.manager.pojo.dto.LoginDto;
+import org.apache.hertzbeat.manager.service.AccountService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
@@ -43,6 +49,8 @@ class AccountControllerTest {
@InjectMocks
private AccountController accountController;
+ @Mock
+ private AccountService accountService;
@BeforeEach
void setUp() {
@@ -59,6 +67,12 @@ class AccountControllerTest {
.identifier("admin")
.credential("hertzbeat")
.build();
+ Map<String, String> resp = new HashMap<>(2);
+ resp.put("token", "token");
+ resp.put("refreshToken", "refreshToken");
+ resp.put("role", "roles");
+ Mockito.when(accountService.authGetToken(loginDto)).thenReturn(resp);
+
this.mockMvc.perform(MockMvcRequestBuilders.post("/api/account/auth/form")
.contentType(MediaType.APPLICATION_JSON)
.content(JsonUtil.toJson(loginDto)))
@@ -67,6 +81,7 @@ class AccountControllerTest {
.andExpect(jsonPath("$.data.token").exists())
.andReturn();
loginDto.setCredential("wrong_credential");
+ Mockito.when(accountService.authGetToken(loginDto)).thenThrow(new
AuthenticationException());
this.mockMvc.perform(MockMvcRequestBuilders.post("/api/account/auth/form")
.contentType(MediaType.APPLICATION_JSON)
.content(JsonUtil.toJson(loginDto)))
@@ -76,8 +91,10 @@ class AccountControllerTest {
@Test
void refreshToken() throws Exception {
+ String refreshToken = "123456";
+ Mockito.when(accountService.refreshToken(refreshToken)).thenThrow(new
AuthenticationException());
this.mockMvc.perform(MockMvcRequestBuilders.get("/api/account/auth/refresh/{refreshToken}",
- "123456"))
+ refreshToken))
.andExpect(jsonPath("$.code").value((int)
CommonConstants.MONITOR_LOGIN_FAILED_CODE))
.andReturn();
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]