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]

Reply via email to