init
This commit is contained in:
11
backend/.env.example
Normal file
11
backend/.env.example
Normal file
@@ -0,0 +1,11 @@
|
||||
K12STUDY_DB_HOST=localhost
|
||||
K12STUDY_DB_PORT=5432
|
||||
K12STUDY_DB_NAME=k12study
|
||||
K12STUDY_DB_USER=k12study
|
||||
K12STUDY_DB_PASSWORD=k12study
|
||||
|
||||
K12STUDY_REDIS_HOST=localhost
|
||||
K12STUDY_REDIS_PORT=6379
|
||||
K12STUDY_REDIS_PASSWORD=
|
||||
|
||||
AI_CLIENT_BASE_URL=http://localhost:9000
|
||||
23
backend/ai-client/pom.xml
Normal file
23
backend/ai-client/pom.xml
Normal file
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.k12study</groupId>
|
||||
<artifactId>k12study-backend</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>ai-client</artifactId>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.k12study</groupId>
|
||||
<artifactId>api-ai</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.k12study.aiclient.client;
|
||||
|
||||
import com.k12study.api.ai.dto.AiHealthDto;
|
||||
import org.springframework.web.client.RestClient;
|
||||
|
||||
public class HttpPythonAiClient implements PythonAiClient {
|
||||
private final RestClient restClient;
|
||||
|
||||
public HttpPythonAiClient(RestClient restClient) {
|
||||
this.restClient = restClient;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AiHealthDto health() {
|
||||
try {
|
||||
AiHealthDto response = restClient.get()
|
||||
.uri("/health")
|
||||
.retrieve()
|
||||
.body(AiHealthDto.class);
|
||||
return response == null ? new AiHealthDto("python-ai", "UNKNOWN", "0.1.0") : response;
|
||||
} catch (Exception exception) {
|
||||
return new AiHealthDto("python-ai", "UNREACHABLE", "0.1.0");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.k12study.aiclient.client;
|
||||
|
||||
import com.k12study.api.ai.dto.AiHealthDto;
|
||||
|
||||
public interface PythonAiClient {
|
||||
AiHealthDto health();
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.k12study.aiclient.config;
|
||||
|
||||
import com.k12study.aiclient.client.HttpPythonAiClient;
|
||||
import com.k12study.aiclient.client.PythonAiClient;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.client.RestClient;
|
||||
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(AiClientProperties.class)
|
||||
public class AiClientAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
public RestClient aiRestClient(AiClientProperties properties) {
|
||||
return RestClient.builder().baseUrl(properties.getBaseUrl()).build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PythonAiClient pythonAiClient(RestClient aiRestClient) {
|
||||
return new HttpPythonAiClient(aiRestClient);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.k12study.aiclient.config;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
@ConfigurationProperties(prefix = "ai.client")
|
||||
public class AiClientProperties {
|
||||
private String baseUrl = "http://localhost:9000";
|
||||
|
||||
public String getBaseUrl() {
|
||||
return baseUrl;
|
||||
}
|
||||
|
||||
public void setBaseUrl(String baseUrl) {
|
||||
this.baseUrl = baseUrl;
|
||||
}
|
||||
}
|
||||
25
backend/apis/api-ai/pom.xml
Normal file
25
backend/apis/api-ai/pom.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.k12study</groupId>
|
||||
<artifactId>k12study-backend</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>api-ai</artifactId>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.k12study</groupId>
|
||||
<artifactId>common-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.k12study.api.ai.dto;
|
||||
|
||||
public record AiHealthDto(
|
||||
String name,
|
||||
String status,
|
||||
String version
|
||||
) {
|
||||
}
|
||||
25
backend/apis/api-auth/pom.xml
Normal file
25
backend/apis/api-auth/pom.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.k12study</groupId>
|
||||
<artifactId>k12study-backend</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>api-auth</artifactId>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.k12study</groupId>
|
||||
<artifactId>common-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.k12study.api.auth.dto;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public record CurrentUserResponse(
|
||||
String userId,
|
||||
String username,
|
||||
String displayName,
|
||||
String provinceCode,
|
||||
String areaCode,
|
||||
String tenantId,
|
||||
String deptId,
|
||||
List<String> roles
|
||||
) {
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.k12study.api.auth.dto;
|
||||
|
||||
public record LoginRequest(
|
||||
String username,
|
||||
String password,
|
||||
String provinceCode,
|
||||
String areaCode,
|
||||
String tenantId
|
||||
) {
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.k12study.api.auth.dto;
|
||||
|
||||
public record TokenResponse(
|
||||
String accessToken,
|
||||
String refreshToken,
|
||||
String tokenType,
|
||||
long expiresIn
|
||||
) {
|
||||
}
|
||||
25
backend/apis/api-upms/pom.xml
Normal file
25
backend/apis/api-upms/pom.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.k12study</groupId>
|
||||
<artifactId>k12study-backend</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>api-upms</artifactId>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.k12study</groupId>
|
||||
<artifactId>common-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.k12study.api.upms.dto;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public record AreaNodeDto(
|
||||
String areaCode,
|
||||
String areaName,
|
||||
String areaLevel,
|
||||
String provinceCode,
|
||||
List<AreaNodeDto> children
|
||||
) {
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.k12study.api.upms.dto;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public record CurrentRouteUserDto(
|
||||
String userId,
|
||||
String username,
|
||||
String displayName,
|
||||
String tenantId,
|
||||
String deptId,
|
||||
List<String> permissionCodes
|
||||
) {
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.k12study.api.upms.dto;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public record DeptNodeDto(
|
||||
String deptId,
|
||||
String deptName,
|
||||
String deptType,
|
||||
String tenantId,
|
||||
String deptPath,
|
||||
List<DeptNodeDto> children
|
||||
) {
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.k12study.api.upms.dto;
|
||||
|
||||
public enum LayoutType {
|
||||
DEFAULT,
|
||||
SIDEBAR
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.k12study.api.upms.dto;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public record RouteMetaDto(
|
||||
String title,
|
||||
String icon,
|
||||
List<String> permissionCodes,
|
||||
boolean hidden
|
||||
) {
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.k12study.api.upms.dto;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public record RouteNodeDto(
|
||||
String id,
|
||||
String path,
|
||||
String name,
|
||||
String component,
|
||||
LayoutType layout,
|
||||
RouteMetaDto meta,
|
||||
List<RouteNodeDto> children
|
||||
) {
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.k12study.api.upms.dto;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public record TenantNodeDto(
|
||||
String tenantId,
|
||||
String tenantName,
|
||||
String tenantType,
|
||||
String provinceCode,
|
||||
String areaCode,
|
||||
String tenantPath,
|
||||
List<TenantNodeDto> children
|
||||
) {
|
||||
}
|
||||
21
backend/apis/pom.xml
Normal file
21
backend/apis/pom.xml
Normal file
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>com.k12study</groupId>
|
||||
<artifactId>k12study-backend</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>apis-parent</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<modules>
|
||||
<module>api-auth</module>
|
||||
<module>api-upms</module>
|
||||
<module>api-ai</module>
|
||||
</modules>
|
||||
</project>
|
||||
50
backend/auth/pom.xml
Normal file
50
backend/auth/pom.xml
Normal file
@@ -0,0 +1,50 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.k12study</groupId>
|
||||
<artifactId>k12study-backend</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>auth</artifactId>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.k12study</groupId>
|
||||
<artifactId>common-web</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.k12study</groupId>
|
||||
<artifactId>common-security</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.k12study</groupId>
|
||||
<artifactId>common-redis</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.k12study</groupId>
|
||||
<artifactId>api-auth</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springdoc</groupId>
|
||||
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.k12study.auth;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication(scanBasePackages = {"com.k12study.auth", "com.k12study.common"})
|
||||
public class AuthApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(AuthApplication.class, args);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.k12study.auth.config;
|
||||
|
||||
import com.k12study.auth.AuthApplication;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.FilterType;
|
||||
|
||||
@Configuration
|
||||
@ComponentScan(
|
||||
basePackages = "com.k12study.auth",
|
||||
excludeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = AuthApplication.class)
|
||||
)
|
||||
public class AuthModuleConfiguration {
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.k12study.auth.controller;
|
||||
|
||||
import com.k12study.api.auth.dto.CurrentUserResponse;
|
||||
import com.k12study.api.auth.dto.LoginRequest;
|
||||
import com.k12study.api.auth.dto.TokenResponse;
|
||||
import com.k12study.auth.service.AuthService;
|
||||
import com.k12study.common.api.response.ApiResponse;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestHeader;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/auth")
|
||||
public class AuthController {
|
||||
private final AuthService authService;
|
||||
|
||||
public AuthController(AuthService authService) {
|
||||
this.authService = authService;
|
||||
}
|
||||
|
||||
@PostMapping("/login")
|
||||
public ApiResponse<TokenResponse> login(@RequestBody LoginRequest request) {
|
||||
return ApiResponse.success("登录成功", authService.login(request));
|
||||
}
|
||||
|
||||
@PostMapping("/refresh")
|
||||
public ApiResponse<TokenResponse> refresh(@RequestParam("refreshToken") String refreshToken) {
|
||||
return ApiResponse.success("刷新成功", authService.refresh(refreshToken));
|
||||
}
|
||||
|
||||
@GetMapping("/current-user")
|
||||
public ApiResponse<CurrentUserResponse> currentUser(
|
||||
@RequestHeader(value = "Authorization", required = false) String authorizationHeader) {
|
||||
return ApiResponse.success(authService.currentUser(authorizationHeader));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package com.k12study.auth.service;
|
||||
|
||||
import com.k12study.api.auth.dto.CurrentUserResponse;
|
||||
import com.k12study.api.auth.dto.LoginRequest;
|
||||
import com.k12study.api.auth.dto.TokenResponse;
|
||||
import com.k12study.common.security.context.RequestUserContextHolder;
|
||||
import com.k12study.common.security.jwt.JwtTokenProvider;
|
||||
import com.k12study.common.security.jwt.JwtUserPrincipal;
|
||||
import java.util.List;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class AuthService {
|
||||
private final JwtTokenProvider jwtTokenProvider;
|
||||
|
||||
public AuthService(JwtTokenProvider jwtTokenProvider) {
|
||||
this.jwtTokenProvider = jwtTokenProvider;
|
||||
}
|
||||
|
||||
public TokenResponse login(LoginRequest request) {
|
||||
String username = request.username() == null || request.username().isBlank() ? "admin" : request.username();
|
||||
JwtUserPrincipal principal = new JwtUserPrincipal(
|
||||
"U10001",
|
||||
username,
|
||||
"K12Study 管理员",
|
||||
request.tenantId() == null || request.tenantId().isBlank() ? "SCH-HQ" : request.tenantId(),
|
||||
"DEPT-HQ-ADMIN"
|
||||
);
|
||||
String accessToken = jwtTokenProvider.createAccessToken(principal);
|
||||
String refreshToken = jwtTokenProvider.createAccessToken(principal);
|
||||
return new TokenResponse(accessToken, refreshToken, "Bearer", 12 * 60 * 60);
|
||||
}
|
||||
|
||||
public TokenResponse refresh(String refreshToken) {
|
||||
JwtUserPrincipal principal = jwtTokenProvider.parse(refreshToken);
|
||||
String accessToken = jwtTokenProvider.createAccessToken(principal);
|
||||
return new TokenResponse(accessToken, refreshToken, "Bearer", 12 * 60 * 60);
|
||||
}
|
||||
|
||||
public CurrentUserResponse currentUser(String authorizationHeader) {
|
||||
if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
|
||||
JwtUserPrincipal principal = jwtTokenProvider.parse(authorizationHeader.substring("Bearer ".length()));
|
||||
return new CurrentUserResponse(
|
||||
principal.userId(),
|
||||
principal.username(),
|
||||
principal.displayName(),
|
||||
"330000",
|
||||
"330100",
|
||||
principal.tenantId(),
|
||||
principal.deptId(),
|
||||
List.of("SUPER_ADMIN", "ORG_ADMIN")
|
||||
);
|
||||
}
|
||||
var context = RequestUserContextHolder.get();
|
||||
return new CurrentUserResponse(
|
||||
context == null ? "U10001" : context.userId(),
|
||||
context == null ? "admin" : context.username(),
|
||||
context == null ? "K12Study 管理员" : context.displayName(),
|
||||
"330000",
|
||||
"330100",
|
||||
context == null ? "SCH-HQ" : context.tenantId(),
|
||||
context == null ? "DEPT-HQ-ADMIN" : context.deptId(),
|
||||
List.of("SUPER_ADMIN", "ORG_ADMIN")
|
||||
);
|
||||
}
|
||||
}
|
||||
28
backend/auth/src/main/resources/application.yml
Normal file
28
backend/auth/src/main/resources/application.yml
Normal file
@@ -0,0 +1,28 @@
|
||||
server:
|
||||
port: 8081
|
||||
|
||||
spring:
|
||||
application:
|
||||
name: k12study-auth
|
||||
data:
|
||||
redis:
|
||||
host: ${K12STUDY_REDIS_HOST:localhost}
|
||||
port: ${K12STUDY_REDIS_PORT:6379}
|
||||
password: ${K12STUDY_REDIS_PASSWORD:}
|
||||
|
||||
management:
|
||||
health:
|
||||
redis:
|
||||
enabled: false
|
||||
endpoints:
|
||||
web:
|
||||
exposure:
|
||||
include: health,info
|
||||
|
||||
auth:
|
||||
enabled: true
|
||||
gateway-mode: true
|
||||
whitelist:
|
||||
- /auth/login
|
||||
- /auth/refresh
|
||||
- /actuator/**
|
||||
41
backend/boot-dev/pom.xml
Normal file
41
backend/boot-dev/pom.xml
Normal file
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.k12study</groupId>
|
||||
<artifactId>k12study-backend</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>boot-dev</artifactId>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.k12study</groupId>
|
||||
<artifactId>auth</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.k12study</groupId>
|
||||
<artifactId>upms</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.k12study</groupId>
|
||||
<artifactId>ai-client</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.k12study.bootdev;
|
||||
|
||||
import com.k12study.aiclient.config.AiClientAutoConfiguration;
|
||||
import com.k12study.auth.config.AuthModuleConfiguration;
|
||||
import com.k12study.upms.config.UpmsModuleConfiguration;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
@SpringBootApplication(scanBasePackages = {"com.k12study.bootdev", "com.k12study.common"})
|
||||
@Import({AuthModuleConfiguration.class, UpmsModuleConfiguration.class, AiClientAutoConfiguration.class})
|
||||
public class BootDevApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(BootDevApplication.class, args);
|
||||
}
|
||||
}
|
||||
39
backend/boot-dev/src/main/resources/application.yml
Normal file
39
backend/boot-dev/src/main/resources/application.yml
Normal file
@@ -0,0 +1,39 @@
|
||||
server:
|
||||
port: 8088
|
||||
servlet:
|
||||
context-path: /api
|
||||
|
||||
spring:
|
||||
application:
|
||||
name: k12study-boot-dev
|
||||
autoconfigure:
|
||||
exclude:
|
||||
- org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
|
||||
- org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration
|
||||
- com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration
|
||||
data:
|
||||
redis:
|
||||
host: ${K12STUDY_REDIS_HOST:localhost}
|
||||
port: ${K12STUDY_REDIS_PORT:6379}
|
||||
password: ${K12STUDY_REDIS_PASSWORD:}
|
||||
|
||||
management:
|
||||
health:
|
||||
redis:
|
||||
enabled: false
|
||||
endpoints:
|
||||
web:
|
||||
exposure:
|
||||
include: health,info
|
||||
|
||||
auth:
|
||||
enabled: true
|
||||
gateway-mode: false
|
||||
whitelist:
|
||||
- /auth/login
|
||||
- /auth/refresh
|
||||
- /actuator/**
|
||||
|
||||
ai:
|
||||
client:
|
||||
base-url: http://localhost:9000
|
||||
25
backend/common/common-api/pom.xml
Normal file
25
backend/common/common-api/pom.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.k12study</groupId>
|
||||
<artifactId>k12study-backend</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>common-api</artifactId>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.k12study</groupId>
|
||||
<artifactId>common-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.k12study.common.api.response;
|
||||
|
||||
import com.k12study.common.core.utils.TraceIdHolder;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public class ApiResponse<T> {
|
||||
private final int code;
|
||||
private final String message;
|
||||
private final T data;
|
||||
private final String traceId;
|
||||
|
||||
private ApiResponse(int code, String message, T data, String traceId) {
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
this.data = data;
|
||||
this.traceId = traceId;
|
||||
}
|
||||
|
||||
public static <T> ApiResponse<T> success(T data) {
|
||||
return new ApiResponse<>(0, "OK", data, TraceIdHolder.getOrCreate());
|
||||
}
|
||||
|
||||
public static <T> ApiResponse<T> success(String message, T data) {
|
||||
return new ApiResponse<>(0, message, data, TraceIdHolder.getOrCreate());
|
||||
}
|
||||
|
||||
public static <T> ApiResponse<T> failure(int code, String message) {
|
||||
return new ApiResponse<>(code, message, null, TraceIdHolder.getOrCreate());
|
||||
}
|
||||
}
|
||||
24
backend/common/common-core/pom.xml
Normal file
24
backend/common/common-core/pom.xml
Normal file
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.k12study</groupId>
|
||||
<artifactId>k12study-backend</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>common-core</artifactId>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.k12study.common.core.constants;
|
||||
|
||||
public final class SecurityConstants {
|
||||
public static final String TRACE_ID = "X-Trace-Id";
|
||||
public static final String HEADER_USER_ID = "X-User-Id";
|
||||
public static final String HEADER_USERNAME = "X-Username";
|
||||
public static final String HEADER_DISPLAY_NAME = "X-Display-Name";
|
||||
public static final String HEADER_TENANT_ID = "X-Tenant-Id";
|
||||
public static final String HEADER_DEPT_ID = "X-Dept-Id";
|
||||
|
||||
private SecurityConstants() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.k12study.common.core.domain;
|
||||
|
||||
public record RouteKey(
|
||||
String provinceCode,
|
||||
String areaCode,
|
||||
String tenantId,
|
||||
String tenantPath,
|
||||
String deptId,
|
||||
String deptPath
|
||||
) {
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.k12study.common.core.utils;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public final class TraceIdHolder {
|
||||
private static final ThreadLocal<String> TRACE_ID = new ThreadLocal<>();
|
||||
|
||||
private TraceIdHolder() {
|
||||
}
|
||||
|
||||
public static String getOrCreate() {
|
||||
String value = TRACE_ID.get();
|
||||
if (value == null || value.isBlank()) {
|
||||
value = UUID.randomUUID().toString().replace("-", "");
|
||||
TRACE_ID.set(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public static void set(String traceId) {
|
||||
TRACE_ID.set(traceId);
|
||||
}
|
||||
|
||||
public static void clear() {
|
||||
TRACE_ID.remove();
|
||||
}
|
||||
}
|
||||
28
backend/common/common-mybatis/pom.xml
Normal file
28
backend/common/common-mybatis/pom.xml
Normal file
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.k12study</groupId>
|
||||
<artifactId>k12study-backend</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>common-mybatis</artifactId>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.k12study</groupId>
|
||||
<artifactId>common-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.k12study.common.mybatis.config;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class MybatisPlusConfiguration {
|
||||
}
|
||||
19
backend/common/common-redis/pom.xml
Normal file
19
backend/common/common-redis/pom.xml
Normal file
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.k12study</groupId>
|
||||
<artifactId>k12study-backend</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>common-redis</artifactId>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.k12study.common.redis.config;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class RedisConfiguration {
|
||||
}
|
||||
38
backend/common/common-security/pom.xml
Normal file
38
backend/common/common-security/pom.xml
Normal file
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.k12study</groupId>
|
||||
<artifactId>k12study-backend</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>common-security</artifactId>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.k12study</groupId>
|
||||
<artifactId>common-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-impl</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-jackson</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,82 @@
|
||||
package com.k12study.common.security.config;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
@ConfigurationProperties(prefix = "auth")
|
||||
public class AuthProperties {
|
||||
private boolean enabled = true;
|
||||
private boolean gatewayMode = false;
|
||||
private String tokenHeader = "Authorization";
|
||||
private String tokenPrefix = "Bearer ";
|
||||
private String secret = "k12study-dev-secret-k12study-dev-secret";
|
||||
private Duration accessTokenTtl = Duration.ofHours(12);
|
||||
private Duration refreshTokenTtl = Duration.ofDays(7);
|
||||
private List<String> whitelist = new ArrayList<>(List.of("/actuator/**", "/auth/login", "/auth/refresh"));
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public boolean isGatewayMode() {
|
||||
return gatewayMode;
|
||||
}
|
||||
|
||||
public void setGatewayMode(boolean gatewayMode) {
|
||||
this.gatewayMode = gatewayMode;
|
||||
}
|
||||
|
||||
public String getTokenHeader() {
|
||||
return tokenHeader;
|
||||
}
|
||||
|
||||
public void setTokenHeader(String tokenHeader) {
|
||||
this.tokenHeader = tokenHeader;
|
||||
}
|
||||
|
||||
public String getTokenPrefix() {
|
||||
return tokenPrefix;
|
||||
}
|
||||
|
||||
public void setTokenPrefix(String tokenPrefix) {
|
||||
this.tokenPrefix = tokenPrefix;
|
||||
}
|
||||
|
||||
public String getSecret() {
|
||||
return secret;
|
||||
}
|
||||
|
||||
public void setSecret(String secret) {
|
||||
this.secret = secret;
|
||||
}
|
||||
|
||||
public Duration getAccessTokenTtl() {
|
||||
return accessTokenTtl;
|
||||
}
|
||||
|
||||
public void setAccessTokenTtl(Duration accessTokenTtl) {
|
||||
this.accessTokenTtl = accessTokenTtl;
|
||||
}
|
||||
|
||||
public Duration getRefreshTokenTtl() {
|
||||
return refreshTokenTtl;
|
||||
}
|
||||
|
||||
public void setRefreshTokenTtl(Duration refreshTokenTtl) {
|
||||
this.refreshTokenTtl = refreshTokenTtl;
|
||||
}
|
||||
|
||||
public List<String> getWhitelist() {
|
||||
return whitelist;
|
||||
}
|
||||
|
||||
public void setWhitelist(List<String> whitelist) {
|
||||
this.whitelist = whitelist;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.k12study.common.security.config;
|
||||
|
||||
import com.k12study.common.security.jwt.JwtTokenProvider;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(AuthProperties.class)
|
||||
public class SecurityAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
public JwtTokenProvider jwtTokenProvider(AuthProperties authProperties) {
|
||||
return new JwtTokenProvider(authProperties);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.k12study.common.security.context;
|
||||
|
||||
public record RequestUserContext(
|
||||
String userId,
|
||||
String username,
|
||||
String displayName,
|
||||
String tenantId,
|
||||
String deptId
|
||||
) {
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.k12study.common.security.context;
|
||||
|
||||
public final class RequestUserContextHolder {
|
||||
private static final ThreadLocal<RequestUserContext> CONTEXT = new ThreadLocal<>();
|
||||
|
||||
private RequestUserContextHolder() {
|
||||
}
|
||||
|
||||
public static void set(RequestUserContext context) {
|
||||
CONTEXT.set(context);
|
||||
}
|
||||
|
||||
public static RequestUserContext get() {
|
||||
return CONTEXT.get();
|
||||
}
|
||||
|
||||
public static void clear() {
|
||||
CONTEXT.remove();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.k12study.common.security.jwt;
|
||||
|
||||
import com.k12study.common.security.config.AuthProperties;
|
||||
import io.jsonwebtoken.Claims;
|
||||
import io.jsonwebtoken.Jwts;
|
||||
import io.jsonwebtoken.security.Keys;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.Instant;
|
||||
import java.util.Date;
|
||||
import javax.crypto.SecretKey;
|
||||
|
||||
public class JwtTokenProvider {
|
||||
private final AuthProperties authProperties;
|
||||
private final SecretKey secretKey;
|
||||
|
||||
public JwtTokenProvider(AuthProperties authProperties) {
|
||||
this.authProperties = authProperties;
|
||||
this.secretKey = Keys.hmacShaKeyFor(authProperties.getSecret().getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
public String createAccessToken(JwtUserPrincipal principal) {
|
||||
Instant now = Instant.now();
|
||||
return Jwts.builder()
|
||||
.subject(principal.userId())
|
||||
.claim("username", principal.username())
|
||||
.claim("displayName", principal.displayName())
|
||||
.claim("tenantId", principal.tenantId())
|
||||
.claim("deptId", principal.deptId())
|
||||
.issuedAt(Date.from(now))
|
||||
.expiration(Date.from(now.plus(authProperties.getAccessTokenTtl())))
|
||||
.signWith(secretKey)
|
||||
.compact();
|
||||
}
|
||||
|
||||
public JwtUserPrincipal parse(String token) {
|
||||
Claims claims = Jwts.parser()
|
||||
.verifyWith(secretKey)
|
||||
.build()
|
||||
.parseSignedClaims(token)
|
||||
.getPayload();
|
||||
return new JwtUserPrincipal(
|
||||
claims.getSubject(),
|
||||
claims.get("username", String.class),
|
||||
claims.get("displayName", String.class),
|
||||
claims.get("tenantId", String.class),
|
||||
claims.get("deptId", String.class)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.k12study.common.security.jwt;
|
||||
|
||||
public record JwtUserPrincipal(
|
||||
String userId,
|
||||
String username,
|
||||
String displayName,
|
||||
String tenantId,
|
||||
String deptId
|
||||
) {
|
||||
}
|
||||
34
backend/common/common-web/pom.xml
Normal file
34
backend/common/common-web/pom.xml
Normal file
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.k12study</groupId>
|
||||
<artifactId>k12study-backend</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>common-web</artifactId>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.k12study</groupId>
|
||||
<artifactId>common-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.k12study</groupId>
|
||||
<artifactId>common-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.k12study</groupId>
|
||||
<artifactId>common-security</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.k12study.common.web.config;
|
||||
|
||||
import com.k12study.common.core.constants.SecurityConstants;
|
||||
import com.k12study.common.core.utils.TraceIdHolder;
|
||||
import com.k12study.common.security.context.RequestUserContext;
|
||||
import com.k12study.common.security.context.RequestUserContextHolder;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
@Configuration
|
||||
public class CommonWebMvcConfiguration extends OncePerRequestFilter {
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
FilterChain filterChain) throws ServletException, IOException {
|
||||
try {
|
||||
String traceId = request.getHeader(SecurityConstants.TRACE_ID);
|
||||
TraceIdHolder.set(traceId == null || traceId.isBlank() ? TraceIdHolder.getOrCreate() : traceId);
|
||||
|
||||
RequestUserContextHolder.set(new RequestUserContext(
|
||||
request.getHeader(SecurityConstants.HEADER_USER_ID),
|
||||
request.getHeader(SecurityConstants.HEADER_USERNAME),
|
||||
request.getHeader(SecurityConstants.HEADER_DISPLAY_NAME),
|
||||
request.getHeader(SecurityConstants.HEADER_TENANT_ID),
|
||||
request.getHeader(SecurityConstants.HEADER_DEPT_ID)
|
||||
));
|
||||
response.setHeader(SecurityConstants.TRACE_ID, TraceIdHolder.getOrCreate());
|
||||
filterChain.doFilter(request, response);
|
||||
} finally {
|
||||
TraceIdHolder.clear();
|
||||
RequestUserContextHolder.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.k12study.common.web.exception;
|
||||
|
||||
public class BizException extends RuntimeException {
|
||||
private final int code;
|
||||
|
||||
public BizException(int code, String message) {
|
||||
super(message);
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.k12study.common.web.exception;
|
||||
|
||||
import com.k12study.common.api.response.ApiResponse;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
|
||||
@RestControllerAdvice
|
||||
public class GlobalExceptionHandler {
|
||||
|
||||
@ExceptionHandler(BizException.class)
|
||||
public ApiResponse<Void> handleBizException(BizException exception) {
|
||||
return ApiResponse.failure(exception.getCode(), exception.getMessage());
|
||||
}
|
||||
|
||||
@ExceptionHandler(Exception.class)
|
||||
public ApiResponse<Void> handleException(Exception exception) {
|
||||
return ApiResponse.failure(500, exception.getMessage());
|
||||
}
|
||||
}
|
||||
24
backend/common/pom.xml
Normal file
24
backend/common/pom.xml
Normal file
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>com.k12study</groupId>
|
||||
<artifactId>k12study-backend</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>common-parent</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<modules>
|
||||
<module>common-api</module>
|
||||
<module>common-core</module>
|
||||
<module>common-web</module>
|
||||
<module>common-security</module>
|
||||
<module>common-mybatis</module>
|
||||
<module>common-redis</module>
|
||||
</modules>
|
||||
</project>
|
||||
35
backend/gateway/pom.xml
Normal file
35
backend/gateway/pom.xml
Normal file
@@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.k12study</groupId>
|
||||
<artifactId>k12study-backend</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>gateway</artifactId>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.k12study</groupId>
|
||||
<artifactId>common-security</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-gateway</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.k12study.gateway;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication(scanBasePackages = {"com.k12study.gateway", "com.k12study.common"})
|
||||
public class GatewayApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(GatewayApplication.class, args);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package com.k12study.gateway.filter;
|
||||
|
||||
import com.k12study.common.core.constants.SecurityConstants;
|
||||
import com.k12study.common.security.config.AuthProperties;
|
||||
import com.k12study.common.security.jwt.JwtTokenProvider;
|
||||
import com.k12study.common.security.jwt.JwtUserPrincipal;
|
||||
import java.util.List;
|
||||
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
|
||||
import org.springframework.cloud.gateway.filter.GlobalFilter;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
@Component
|
||||
public class JwtRelayFilter implements GlobalFilter, Ordered {
|
||||
private final AuthProperties authProperties;
|
||||
private final JwtTokenProvider jwtTokenProvider;
|
||||
private final AntPathMatcher antPathMatcher = new AntPathMatcher();
|
||||
|
||||
public JwtRelayFilter(AuthProperties authProperties, JwtTokenProvider jwtTokenProvider) {
|
||||
this.authProperties = authProperties;
|
||||
this.jwtTokenProvider = jwtTokenProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
|
||||
String path = exchange.getRequest().getURI().getPath();
|
||||
if (!authProperties.isEnabled() || matches(path, authProperties.getWhitelist())) {
|
||||
return chain.filter(exchange);
|
||||
}
|
||||
|
||||
String authorization = exchange.getRequest().getHeaders().getFirst(authProperties.getTokenHeader());
|
||||
if (authorization == null || !authorization.startsWith(authProperties.getTokenPrefix())) {
|
||||
return unauthorized(exchange, "Missing token");
|
||||
}
|
||||
|
||||
try {
|
||||
String token = authorization.substring(authProperties.getTokenPrefix().length());
|
||||
JwtUserPrincipal principal = jwtTokenProvider.parse(token);
|
||||
var mutatedRequest = exchange.getRequest().mutate()
|
||||
.header(SecurityConstants.HEADER_USER_ID, principal.userId())
|
||||
.header(SecurityConstants.HEADER_USERNAME, principal.username())
|
||||
.header(SecurityConstants.HEADER_DISPLAY_NAME, principal.displayName())
|
||||
.header(SecurityConstants.HEADER_TENANT_ID, principal.tenantId())
|
||||
.header(SecurityConstants.HEADER_DEPT_ID, principal.deptId())
|
||||
.build();
|
||||
return chain.filter(exchange.mutate().request(mutatedRequest).build());
|
||||
} catch (Exception exception) {
|
||||
return unauthorized(exchange, "Invalid token");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return -100;
|
||||
}
|
||||
|
||||
private boolean matches(String path, List<String> patterns) {
|
||||
return patterns.stream().anyMatch(pattern -> antPathMatcher.match(pattern, path));
|
||||
}
|
||||
|
||||
private Mono<Void> unauthorized(ServerWebExchange exchange, String message) {
|
||||
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
|
||||
exchange.getResponse().getHeaders().set(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
|
||||
byte[] body = ("{\"code\":401,\"message\":\"" + message + "\",\"data\":null}").getBytes();
|
||||
return exchange.getResponse().writeWith(Mono.just(exchange.getResponse()
|
||||
.bufferFactory()
|
||||
.wrap(body)));
|
||||
}
|
||||
}
|
||||
34
backend/gateway/src/main/resources/application.yml
Normal file
34
backend/gateway/src/main/resources/application.yml
Normal file
@@ -0,0 +1,34 @@
|
||||
server:
|
||||
port: 8080
|
||||
|
||||
spring:
|
||||
application:
|
||||
name: k12study-gateway
|
||||
cloud:
|
||||
gateway:
|
||||
routes:
|
||||
- id: auth
|
||||
uri: http://localhost:8081
|
||||
predicates:
|
||||
- Path=/api/auth/**
|
||||
filters:
|
||||
- StripPrefix=1
|
||||
- id: upms
|
||||
uri: http://localhost:8082
|
||||
predicates:
|
||||
- Path=/api/upms/**
|
||||
filters:
|
||||
- StripPrefix=1
|
||||
|
||||
management:
|
||||
endpoints:
|
||||
web:
|
||||
exposure:
|
||||
include: health,info
|
||||
|
||||
auth:
|
||||
enabled: true
|
||||
whitelist:
|
||||
- /api/auth/login
|
||||
- /api/auth/refresh
|
||||
- /actuator/**
|
||||
115
backend/pom.xml
Normal file
115
backend/pom.xml
Normal file
@@ -0,0 +1,115 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>com.k12study</groupId>
|
||||
<artifactId>k12study-backend</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
<name>k12study-backend</name>
|
||||
|
||||
<modules>
|
||||
<module>common</module>
|
||||
<module>apis</module>
|
||||
<module>ai-client</module>
|
||||
<module>auth</module>
|
||||
<module>upms</module>
|
||||
<module>gateway</module>
|
||||
<module>boot-dev</module>
|
||||
</modules>
|
||||
|
||||
<properties>
|
||||
<java.version>21</java.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.release>${java.version}</maven.compiler.release>
|
||||
|
||||
<spring.boot.version>3.3.5</spring.boot.version>
|
||||
<spring.cloud.version>2023.0.3</spring.cloud.version>
|
||||
<mybatis.plus.version>3.5.7</mybatis.plus.version>
|
||||
<postgresql.version>42.7.4</postgresql.version>
|
||||
<jjwt.version>0.12.6</jjwt.version>
|
||||
<springdoc.version>2.6.0</springdoc.version>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-dependencies</artifactId>
|
||||
<version>${spring.boot.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-dependencies</artifactId>
|
||||
<version>${spring.cloud.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
|
||||
<version>${mybatis.plus.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<version>${postgresql.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-api</artifactId>
|
||||
<version>${jjwt.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-impl</artifactId>
|
||||
<version>${jjwt.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-jackson</artifactId>
|
||||
<version>${jjwt.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springdoc</groupId>
|
||||
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
|
||||
<version>${springdoc.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.13.0</version>
|
||||
<configuration>
|
||||
<release>${maven.compiler.release}</release>
|
||||
<encoding>${project.build.sourceEncoding}</encoding>
|
||||
<parameters>true</parameters>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<version>${spring.boot.version}</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>aliyun-public</id>
|
||||
<name>aliyun-public</name>
|
||||
<url>https://maven.aliyun.com/repository/public</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
</project>
|
||||
14
backend/python-ai/README.md
Normal file
14
backend/python-ai/README.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# Python AI Placeholder
|
||||
|
||||
This service is the placeholder for OCR, grading and speech evaluation capabilities.
|
||||
|
||||
## Run
|
||||
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
uvicorn app.main:app --reload --port 9000
|
||||
```
|
||||
|
||||
## Endpoints
|
||||
|
||||
- `GET /health`
|
||||
13
backend/python-ai/app/main.py
Normal file
13
backend/python-ai/app/main.py
Normal file
@@ -0,0 +1,13 @@
|
||||
from fastapi import FastAPI
|
||||
|
||||
|
||||
app = FastAPI(title="K12Study Python AI", version="0.1.0")
|
||||
|
||||
|
||||
@app.get("/health")
|
||||
def health():
|
||||
return {
|
||||
"name": "python-ai",
|
||||
"status": "UP",
|
||||
"version": "0.1.0",
|
||||
}
|
||||
2
backend/python-ai/requirements.txt
Normal file
2
backend/python-ai/requirements.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
fastapi==0.115.12
|
||||
uvicorn==0.34.0
|
||||
50
backend/upms/pom.xml
Normal file
50
backend/upms/pom.xml
Normal file
@@ -0,0 +1,50 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.k12study</groupId>
|
||||
<artifactId>k12study-backend</artifactId>
|
||||
<version>0.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>upms</artifactId>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.k12study</groupId>
|
||||
<artifactId>common-web</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.k12study</groupId>
|
||||
<artifactId>common-security</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.k12study</groupId>
|
||||
<artifactId>common-mybatis</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.k12study</groupId>
|
||||
<artifactId>api-upms</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springdoc</groupId>
|
||||
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.k12study.upms;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication(scanBasePackages = {"com.k12study.upms", "com.k12study.common"})
|
||||
public class UpmsApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(UpmsApplication.class, args);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.k12study.upms.config;
|
||||
|
||||
import com.k12study.upms.UpmsApplication;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.FilterType;
|
||||
|
||||
@Configuration
|
||||
@ComponentScan(
|
||||
basePackages = "com.k12study.upms",
|
||||
excludeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = UpmsApplication.class)
|
||||
)
|
||||
public class UpmsModuleConfiguration {
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.k12study.upms.controller;
|
||||
|
||||
import com.k12study.api.upms.dto.AreaNodeDto;
|
||||
import com.k12study.api.upms.dto.CurrentRouteUserDto;
|
||||
import com.k12study.api.upms.dto.DeptNodeDto;
|
||||
import com.k12study.api.upms.dto.RouteNodeDto;
|
||||
import com.k12study.api.upms.dto.TenantNodeDto;
|
||||
import com.k12study.common.api.response.ApiResponse;
|
||||
import com.k12study.upms.service.UpmsQueryService;
|
||||
import java.util.List;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/upms")
|
||||
public class UpmsController {
|
||||
private final UpmsQueryService upmsQueryService;
|
||||
|
||||
public UpmsController(UpmsQueryService upmsQueryService) {
|
||||
this.upmsQueryService = upmsQueryService;
|
||||
}
|
||||
|
||||
@GetMapping("/routes")
|
||||
public ApiResponse<List<RouteNodeDto>> routes() {
|
||||
return ApiResponse.success(upmsQueryService.routes());
|
||||
}
|
||||
|
||||
@GetMapping("/areas/tree")
|
||||
public ApiResponse<List<AreaNodeDto>> areas() {
|
||||
return ApiResponse.success(upmsQueryService.areas());
|
||||
}
|
||||
|
||||
@GetMapping("/tenants/tree")
|
||||
public ApiResponse<List<TenantNodeDto>> tenants() {
|
||||
return ApiResponse.success(upmsQueryService.tenants());
|
||||
}
|
||||
|
||||
@GetMapping("/depts/tree")
|
||||
public ApiResponse<List<DeptNodeDto>> departments() {
|
||||
return ApiResponse.success(upmsQueryService.departments());
|
||||
}
|
||||
|
||||
@GetMapping("/current-user")
|
||||
public ApiResponse<CurrentRouteUserDto> currentUser() {
|
||||
return ApiResponse.success(upmsQueryService.currentUser());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.k12study.upms.domain;
|
||||
|
||||
public record SysArea(
|
||||
String areaCode,
|
||||
String parentCode,
|
||||
String areaName,
|
||||
String areaLevel,
|
||||
String provinceCode
|
||||
) {
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.k12study.upms.domain;
|
||||
|
||||
public record SysDept(
|
||||
String deptId,
|
||||
String parentDeptId,
|
||||
String tenantId,
|
||||
String deptName,
|
||||
String deptType,
|
||||
String deptPath
|
||||
) {
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.k12study.upms.domain;
|
||||
|
||||
public record SysTenant(
|
||||
String tenantId,
|
||||
String parentTenantId,
|
||||
String tenantName,
|
||||
String tenantType,
|
||||
String provinceCode,
|
||||
String areaCode,
|
||||
String tenantPath
|
||||
) {
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
package com.k12study.upms.service;
|
||||
|
||||
import com.k12study.api.upms.dto.AreaNodeDto;
|
||||
import com.k12study.api.upms.dto.CurrentRouteUserDto;
|
||||
import com.k12study.api.upms.dto.DeptNodeDto;
|
||||
import com.k12study.api.upms.dto.LayoutType;
|
||||
import com.k12study.api.upms.dto.RouteMetaDto;
|
||||
import com.k12study.api.upms.dto.RouteNodeDto;
|
||||
import com.k12study.api.upms.dto.TenantNodeDto;
|
||||
import com.k12study.common.security.context.RequestUserContextHolder;
|
||||
import java.util.List;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class UpmsQueryService {
|
||||
|
||||
public List<RouteNodeDto> routes() {
|
||||
return List.of(
|
||||
new RouteNodeDto(
|
||||
"dashboard",
|
||||
"/",
|
||||
"dashboard",
|
||||
"dashboard",
|
||||
LayoutType.SIDEBAR,
|
||||
new RouteMetaDto("控制台", "layout-dashboard", List.of("dashboard:view"), false),
|
||||
List.of()
|
||||
),
|
||||
new RouteNodeDto(
|
||||
"tenant-management",
|
||||
"/tenant",
|
||||
"tenant-management",
|
||||
"tenant",
|
||||
LayoutType.SIDEBAR,
|
||||
new RouteMetaDto("租户组织", "building-2", List.of("tenant:view"), false),
|
||||
List.of()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public List<AreaNodeDto> areas() {
|
||||
return List.of(
|
||||
new AreaNodeDto(
|
||||
"330000",
|
||||
"浙江省",
|
||||
"province",
|
||||
"330000",
|
||||
List.of(
|
||||
new AreaNodeDto("330100", "杭州市", "city", "330000", List.of())
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public List<TenantNodeDto> tenants() {
|
||||
return List.of(
|
||||
new TenantNodeDto(
|
||||
"SCH-HQ",
|
||||
"K12Study 总校",
|
||||
"head_school",
|
||||
"330000",
|
||||
"330100",
|
||||
"/SCH-HQ/",
|
||||
List.of(
|
||||
new TenantNodeDto(
|
||||
"SCH-ZJ-HZ-01",
|
||||
"杭州分校",
|
||||
"city_school",
|
||||
"330000",
|
||||
"330100",
|
||||
"/SCH-HQ/SCH-ZJ-HZ-01/",
|
||||
List.of()
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public List<DeptNodeDto> departments() {
|
||||
return List.of(
|
||||
new DeptNodeDto(
|
||||
"DEPT-HQ",
|
||||
"总校教学部",
|
||||
"grade",
|
||||
"SCH-HQ",
|
||||
"/DEPT-HQ/",
|
||||
List.of(
|
||||
new DeptNodeDto(
|
||||
"DEPT-HQ-MATH",
|
||||
"数学学科组",
|
||||
"subject",
|
||||
"SCH-HQ",
|
||||
"/DEPT-HQ/DEPT-HQ-MATH/",
|
||||
List.of()
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public CurrentRouteUserDto currentUser() {
|
||||
var context = RequestUserContextHolder.get();
|
||||
return new CurrentRouteUserDto(
|
||||
context == null ? "U10001" : context.userId(),
|
||||
context == null ? "admin" : context.username(),
|
||||
context == null ? "K12Study 管理员" : context.displayName(),
|
||||
context == null ? "SCH-HQ" : context.tenantId(),
|
||||
context == null ? "DEPT-HQ-ADMIN" : context.deptId(),
|
||||
List.of("dashboard:view", "tenant:view", "dept:view")
|
||||
);
|
||||
}
|
||||
}
|
||||
23
backend/upms/src/main/resources/application.yml
Normal file
23
backend/upms/src/main/resources/application.yml
Normal file
@@ -0,0 +1,23 @@
|
||||
server:
|
||||
port: 8082
|
||||
|
||||
spring:
|
||||
application:
|
||||
name: k12study-upms
|
||||
autoconfigure:
|
||||
exclude:
|
||||
- org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
|
||||
- org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration
|
||||
- com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration
|
||||
|
||||
management:
|
||||
endpoints:
|
||||
web:
|
||||
exposure:
|
||||
include: health,info
|
||||
|
||||
auth:
|
||||
enabled: true
|
||||
gateway-mode: true
|
||||
whitelist:
|
||||
- /actuator/**
|
||||
Reference in New Issue
Block a user