mirror of
https://github.com/iflytek/skillhub.git
synced 2026-10-07 02:57:51 +00:00
feat(cli): add Device Auth controllers
This commit is contained in:
parent
9a4d64b11b
commit
f47377cff1
4 changed files with 139 additions and 0 deletions
|
|
@ -0,0 +1,32 @@
|
|||
package com.iflytek.skillhub.controller;
|
||||
|
||||
import com.iflytek.skillhub.auth.device.DeviceAuthService;
|
||||
import com.iflytek.skillhub.auth.device.DeviceCodeResponse;
|
||||
import com.iflytek.skillhub.auth.device.DeviceTokenResponse;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/cli/auth/device")
|
||||
public class DeviceAuthController {
|
||||
|
||||
private final DeviceAuthService deviceAuthService;
|
||||
|
||||
public DeviceAuthController(DeviceAuthService deviceAuthService) {
|
||||
this.deviceAuthService = deviceAuthService;
|
||||
}
|
||||
|
||||
@PostMapping("/code")
|
||||
public DeviceCodeResponse requestDeviceCode() {
|
||||
return deviceAuthService.generateDeviceCode();
|
||||
}
|
||||
|
||||
@PostMapping("/token")
|
||||
public DeviceTokenResponse pollToken(@RequestBody TokenRequest request) {
|
||||
return deviceAuthService.pollToken(request.deviceCode());
|
||||
}
|
||||
|
||||
public record TokenRequest(String deviceCode) {}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
package com.iflytek.skillhub.controller;
|
||||
|
||||
import com.iflytek.skillhub.auth.device.DeviceAuthService;
|
||||
import com.iflytek.skillhub.auth.rbac.PlatformPrincipal;
|
||||
import com.iflytek.skillhub.dto.ApiResponse;
|
||||
import com.iflytek.skillhub.dto.ApiResponseFactory;
|
||||
import com.iflytek.skillhub.dto.MessageResponse;
|
||||
import org.springframework.security.core.annotation.AuthenticationPrincipal;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/device")
|
||||
public class DeviceAuthWebController extends BaseApiController {
|
||||
|
||||
private final DeviceAuthService deviceAuthService;
|
||||
|
||||
public DeviceAuthWebController(ApiResponseFactory responseFactory, DeviceAuthService deviceAuthService) {
|
||||
super(responseFactory);
|
||||
this.deviceAuthService = deviceAuthService;
|
||||
}
|
||||
|
||||
@PostMapping("/authorize")
|
||||
public ApiResponse<MessageResponse> authorizeDevice(
|
||||
@RequestBody AuthorizeRequest request,
|
||||
@AuthenticationPrincipal PlatformPrincipal principal
|
||||
) {
|
||||
deviceAuthService.authorizeDeviceCode(request.userCode(), principal.userId());
|
||||
return ok("response.success.update", new MessageResponse("Device authorized successfully"));
|
||||
}
|
||||
|
||||
public record AuthorizeRequest(String userCode) {}
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
package com.iflytek.skillhub.controller;
|
||||
|
||||
import com.iflytek.skillhub.auth.device.DeviceAuthService;
|
||||
import com.iflytek.skillhub.auth.device.DeviceCodeResponse;
|
||||
import com.iflytek.skillhub.auth.device.DeviceTokenResponse;
|
||||
import com.iflytek.skillhub.domain.namespace.NamespaceMemberRepository;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
@SpringBootTest
|
||||
@AutoConfigureMockMvc
|
||||
@ActiveProfiles("test")
|
||||
class DeviceAuthControllerTest {
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@MockBean
|
||||
private DeviceAuthService deviceAuthService;
|
||||
|
||||
@MockBean
|
||||
private NamespaceMemberRepository namespaceMemberRepository;
|
||||
|
||||
@Test
|
||||
void requestDeviceCode_returns_code() throws Exception {
|
||||
DeviceCodeResponse response = new DeviceCodeResponse(
|
||||
"device_abc123",
|
||||
"ABCD-1234",
|
||||
"https://skillhub.example.com/device",
|
||||
900,
|
||||
5
|
||||
);
|
||||
|
||||
given(deviceAuthService.generateDeviceCode()).willReturn(response);
|
||||
|
||||
mockMvc.perform(post("/api/v1/cli/auth/device/code")
|
||||
.contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.deviceCode").value("device_abc123"))
|
||||
.andExpect(jsonPath("$.userCode").value("ABCD-1234"))
|
||||
.andExpect(jsonPath("$.verificationUri").value("https://skillhub.example.com/device"))
|
||||
.andExpect(jsonPath("$.expiresIn").value(900))
|
||||
.andExpect(jsonPath("$.interval").value(5));
|
||||
}
|
||||
|
||||
@Test
|
||||
void pollToken_returns_pending() throws Exception {
|
||||
DeviceTokenResponse response = DeviceTokenResponse.pending();
|
||||
|
||||
given(deviceAuthService.pollToken("device_abc123")).willReturn(response);
|
||||
|
||||
mockMvc.perform(post("/api/v1/cli/auth/device/token")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content("{\"deviceCode\": \"device_abc123\"}"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.error").value("authorization_pending"))
|
||||
.andExpect(jsonPath("$.accessToken").isEmpty())
|
||||
.andExpect(jsonPath("$.tokenType").isEmpty());
|
||||
}
|
||||
}
|
||||
|
|
@ -66,6 +66,7 @@ public class SecurityConfig {
|
|||
"/api/v1/health",
|
||||
"/api/v1/auth/providers",
|
||||
"/api/v1/auth/me",
|
||||
"/api/v1/cli/auth/device/**",
|
||||
"/actuator/health",
|
||||
"/v3/api-docs/**",
|
||||
"/swagger-ui/**",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue