feat(education): complete Flyway migration and atomic submit

This commit is contained in:
2026-07-30 12:06:55 +08:00
parent ce02f8acb4
commit 79a5799502
228 changed files with 32551 additions and 1376 deletions

View File

@@ -31,9 +31,7 @@ public interface TenantCommonApi {
* @param id 租户编号
* @return 租户信息,不存在时返回 null
*/
default TenantRespDTO getTenant(Long id) {
throw new UnsupportedOperationException("getTenant is not implemented");
}
TenantRespDTO getTenant(Long id);
/**
* 根据租户名获得租户信息
@@ -41,9 +39,7 @@ public interface TenantCommonApi {
* @param name 租户名
* @return 租户信息,不存在时返回 null
*/
default TenantRespDTO getTenantByName(String name) {
throw new UnsupportedOperationException("getTenantByName is not implemented");
}
TenantRespDTO getTenantByName(String name);
/**
* 根据域名获得租户信息
@@ -51,8 +47,6 @@ public interface TenantCommonApi {
* @param website 域名
* @return 租户信息,不存在时返回 null
*/
default TenantRespDTO getTenantByWebsite(String website) {
throw new UnsupportedOperationException("getTenantByWebsite is not implemented");
}
TenantRespDTO getTenantByWebsite(String website);
}

View File

@@ -0,0 +1,95 @@
package cn.iocoder.yudao.framework.tenant.core.security;
import cn.iocoder.yudao.framework.common.biz.infra.logger.ApiErrorLogCommonApi;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.security.core.LoginUser;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.framework.tenant.config.TenantProperties;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.yudao.framework.tenant.core.service.TenantFrameworkService;
import cn.iocoder.yudao.framework.web.config.WebProperties;
import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.mock.web.MockFilterChain;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.security.core.context.SecurityContextHolder;
import java.util.HashSet;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
class TenantSecurityWebFilterTest {
private TenantSecurityWebFilter filter;
private TenantFrameworkService tenantFrameworkService;
@BeforeEach
void setUp() {
WebProperties webProperties = new WebProperties();
TenantProperties tenantProperties = new TenantProperties();
tenantProperties.setIgnoreUrls(new HashSet<>());
tenantFrameworkService = mock(TenantFrameworkService.class);
filter = new TenantSecurityWebFilter(webProperties, tenantProperties, new HashSet<>(),
new GlobalExceptionHandler("test", mock(ApiErrorLogCommonApi.class)), tenantFrameworkService);
}
@AfterEach
void tearDown() {
SecurityContextHolder.clearContext();
TenantContextHolder.clear();
}
@Test
void missingTenantOnProtectedRequestIsRejected() throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/app-api/education/context");
MockHttpServletResponse response = doFilter(request);
assertEquals(400, jsonCode(response));
}
@Test
void authenticatedTenantMismatchIsRejected() throws Exception {
setLoginUser(1L, 10L);
TenantContextHolder.setTenantId(20L);
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/app-api/education/context");
MockHttpServletResponse response = doFilter(request);
assertEquals(403, jsonCode(response));
}
@Test
void authenticatedTenantFillsMissingRequestTenant() throws Exception {
setLoginUser(1L, 10L);
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/app-api/education/context");
MockHttpServletResponse response = new MockHttpServletResponse();
MockFilterChain chain = new MockFilterChain();
filter.doFilter(request, response, chain);
assertEquals(10L, TenantContextHolder.getTenantId());
verify(tenantFrameworkService).validTenant(10L);
assertEquals(request, chain.getRequest());
}
private MockHttpServletResponse doFilter(MockHttpServletRequest request) throws Exception {
MockHttpServletResponse response = new MockHttpServletResponse();
filter.doFilter(request, response, new MockFilterChain());
return response;
}
private static int jsonCode(MockHttpServletResponse response) throws Exception {
String content = response.getContentAsString();
int start = content.indexOf("\"code\":") + 7;
int end = content.indexOf(',', start);
return Integer.parseInt(content.substring(start, end));
}
private static void setLoginUser(Long userId, Long tenantId) {
LoginUser user = new LoginUser();
user.setId(userId);
user.setTenantId(tenantId);
user.setUserType(UserTypeEnum.MEMBER.getValue());
SecurityFrameworkUtils.setLoginUser(user, new MockHttpServletRequest());
}
}

View File

@@ -29,10 +29,6 @@
</dependency>
<!-- DB 相关 -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
</dependency>
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
@@ -41,7 +37,6 @@
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.microsoft.sqlserver</groupId>

View File

@@ -42,7 +42,7 @@ public class DesensitizeTest {
DesensitizeDemo d = JsonUtils.parseObject(JsonUtils.toJsonString(desensitizeDemo), DesensitizeDemo.class);
// 断言
assertNotNull(d);
assertEquals("***", d.getNickname());
assertEquals("***", d.getNickname());
assertEquals("998800********31", d.getBankCard());
assertEquals("粤A6***6", d.getCarLicense());
assertEquals("0108*****22", d.getFixedPhone());