1. 新增 iwork 同步用户组织信息接口

2. 修复错误设置版本信息在 zt-dependencies 的 bug
This commit is contained in:
chenbowen
2025-11-20 18:27:01 +08:00
parent 52a0b561f9
commit 0b646295da
27 changed files with 2040 additions and 151 deletions

View File

@@ -0,0 +1,121 @@
package com.zt.plat.module.system.service.integration.iwork.impl;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkOrgQueryReqVO;
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkOrgRespVO;
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkOrgSyncReqVO;
import com.zt.plat.module.system.framework.integration.iwork.config.IWorkProperties;
import com.zt.plat.module.system.service.integration.iwork.IWorkOrgRestService;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import okhttp3.mockwebserver.RecordedRequest;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.util.DigestUtils;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.time.Clock;
import java.time.Duration;
import java.time.Instant;
import java.time.ZoneOffset;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import static org.assertj.core.api.Assertions.assertThat;
class IWorkOrgRestServiceImplTest {
private MockWebServer mockWebServer;
private IWorkOrgRestService service;
private IWorkProperties properties;
private Clock fixedClock;
@BeforeEach
void setUp() throws Exception {
mockWebServer = new MockWebServer();
mockWebServer.start();
properties = buildProperties();
fixedClock = Clock.fixed(Instant.ofEpochMilli(1_672_531_200_000L), ZoneOffset.UTC);
service = new IWorkOrgRestServiceImpl(properties, new ObjectMapper(), fixedClock);
}
@AfterEach
void tearDown() throws Exception {
mockWebServer.shutdown();
}
@Test
void shouldListSubcompanies() throws Exception {
mockWebServer.enqueue(jsonResponse("{\"code\":\"1\",\"data\":{\"page\":1}}"));
IWorkOrgQueryReqVO reqVO = new IWorkOrgQueryReqVO();
reqVO.setParams(Map.of("curpage", 1));
IWorkOrgRespVO respVO = service.listSubcompanies(reqVO);
assertThat(respVO.isSuccess()).isTrue();
assertThat(respVO.getPayload()).containsEntry("page", 1);
RecordedRequest request = mockWebServer.takeRequest();
assertThat(request.getPath()).isEqualTo(properties.getOrg().getPaths().getSubcompanyPage());
String decoded = URLDecoder.decode(request.getBody().readUtf8(), StandardCharsets.UTF_8);
assertThat(decoded).contains("params={\"curpage\":1}");
String tokenJson = extractField(decoded, "token");
assertThat(tokenJson).isNotBlank();
assertThat(tokenJson).contains("\"ts\":\"1672531200000\"");
String expectedKey = DigestUtils.md5DigestAsHex("test-seed1672531200000".getBytes(StandardCharsets.UTF_8)).toUpperCase();
assertThat(tokenJson).contains("\"key\":\"" + expectedKey + "\"");
}
@Test
void shouldSyncDepartments() throws Exception {
mockWebServer.enqueue(jsonResponse("{\"code\":\"1\",\"result\":{}}"));
IWorkOrgSyncReqVO reqVO = new IWorkOrgSyncReqVO();
reqVO.setData(List.of(Map.of("@action", "add", "code", "demo")));
IWorkOrgRespVO respVO = service.syncDepartments(reqVO);
assertThat(respVO.isSuccess()).isTrue();
assertThat(respVO.getPayload()).containsKey("result");
RecordedRequest request = mockWebServer.takeRequest();
assertThat(request.getPath()).isEqualTo(properties.getOrg().getPaths().getSyncDepartment());
String decoded = URLDecoder.decode(request.getBody().readUtf8(), StandardCharsets.UTF_8);
assertThat(decoded).contains("data=[{\"@action\":\"add\",\"code\":\"demo\"}]");
}
private MockResponse jsonResponse(String body) {
return new MockResponse()
.setHeader("Content-Type", "application/json")
.setBody(body);
}
private String extractField(String decoded, String key) {
return Arrays.stream(decoded.split("&"))
.filter(part -> part.startsWith(key + "="))
.map(part -> part.substring(key.length() + 1))
.findFirst()
.orElse("");
}
private IWorkProperties buildProperties() {
IWorkProperties properties = new IWorkProperties();
properties.setBaseUrl(mockWebServer.url("/").toString());
properties.getClient().setConnectTimeout(Duration.ofSeconds(5));
properties.getClient().setResponseTimeout(Duration.ofSeconds(5));
properties.getOrg().setTokenSeed("test-seed");
IWorkProperties.OrgPaths paths = properties.getOrg().getPaths();
paths.setSubcompanyPage("/api/hrm/resful/getHrmsubcompanyWithPage");
paths.setDepartmentPage("/api/hrm/resful/getHrmdepartmentWithPage");
paths.setJobTitlePage("/api/hrm/resful/getJobtitleInfoWithPage");
paths.setUserPage("/api/hrm/resful/getHrmUserInfoWithPage");
paths.setSyncSubcompany("/api/hrm/resful/synSubcompany");
paths.setSyncDepartment("/api/hrm/resful/synDepartment");
paths.setSyncJobTitle("/api/hrm/resful/synJobtitle");
paths.setSyncUser("/api/hrm/resful/synHrmresource");
return properties;
}
}

View File

@@ -0,0 +1,85 @@
package com.zt.plat.module.system.service.sso;
import com.zt.plat.module.system.framework.sso.config.ExternalSsoProperties;
import com.zt.plat.module.system.service.logger.LoginLogService;
import com.zt.plat.module.system.service.logger.OperateLogService;
import com.zt.plat.module.system.service.oauth2.OAuth2TokenService;
import com.zt.plat.module.system.service.sso.strategy.ExternalSsoStrategy;
import com.zt.plat.module.system.service.user.AdminUserService;
import org.junit.jupiter.api.Test;
import org.springframework.test.util.ReflectionTestUtils;
import java.util.Collections;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
class ExternalSsoServiceImplTest {
@Test
void selectStrategy_returnsExactMatch_whenStrategySupportsSource() {
ExternalSsoStrategy exactStrategy = mock(ExternalSsoStrategy.class);
ExternalSsoStrategy fallbackStrategy = mock(ExternalSsoStrategy.class);
when(exactStrategy.supports("BRMS")).thenReturn(true);
ExternalSsoServiceImpl service = newService(List.of(exactStrategy, fallbackStrategy));
ExternalSsoStrategy selected = invokeSelectStrategy(service, "BRMS");
assertThat(selected).isSameAs(exactStrategy);
}
@Test
void selectStrategy_returnsWildcardStrategy_whenNoExactMatch() {
ExternalSsoStrategy strictStrategy = mock(ExternalSsoStrategy.class);
ExternalSsoStrategy wildcardStrategy = mock(ExternalSsoStrategy.class);
when(strictStrategy.supports("ERP")).thenReturn(false);
when(strictStrategy.supports(null)).thenReturn(false);
when(wildcardStrategy.supports("ERP")).thenReturn(false);
when(wildcardStrategy.supports(null)).thenReturn(true);
ExternalSsoServiceImpl service = newService(List.of(strictStrategy, wildcardStrategy));
ExternalSsoStrategy selected = invokeSelectStrategy(service, "ERP");
assertThat(selected).isSameAs(wildcardStrategy);
}
@Test
void selectStrategy_returnsNull_whenNoStrategyAvailable() {
ExternalSsoServiceImpl service = newService(Collections.emptyList());
ExternalSsoStrategy selected = invokeSelectStrategy(service, "ANY");
assertThat(selected).isNull();
}
@Test
void selectStrategy_skipsStrategy_whenSupportsThrowsException() {
ExternalSsoStrategy unstableStrategy = mock(ExternalSsoStrategy.class);
ExternalSsoStrategy fallbackStrategy = mock(ExternalSsoStrategy.class);
when(unstableStrategy.supports("CRM")).thenThrow(new IllegalStateException("boom"));
when(unstableStrategy.supports(null)).thenReturn(false);
when(fallbackStrategy.supports("CRM")).thenReturn(false);
when(fallbackStrategy.supports(null)).thenReturn(true);
ExternalSsoServiceImpl service = newService(List.of(unstableStrategy, fallbackStrategy));
ExternalSsoStrategy selected = invokeSelectStrategy(service, "CRM");
assertThat(selected).isSameAs(fallbackStrategy);
}
@SuppressWarnings("unchecked")
private ExternalSsoStrategy invokeSelectStrategy(ExternalSsoServiceImpl service, String sourceSystem) {
return ReflectionTestUtils.invokeMethod(service, "selectStrategy", sourceSystem);
}
private ExternalSsoServiceImpl newService(List<ExternalSsoStrategy> strategies) {
ExternalSsoProperties properties = new ExternalSsoProperties();
AdminUserService adminUserService = mock(AdminUserService.class);
LoginLogService loginLogService = mock(LoginLogService.class);
OAuth2TokenService oauth2TokenService = mock(OAuth2TokenService.class);
OperateLogService operateLogService = mock(OperateLogService.class);
return new ExternalSsoServiceImpl(properties, strategies, adminUserService,
loginLogService, oauth2TokenService, operateLogService);
}
}