diff --git a/src/main/java/com/yau/digitalrmb/DigitalRmbApplication.java b/src/main/java/com/yau/digitalrmb/DigitalRmbApplication.java index d9e24af..ecdd7b9 100644 --- a/src/main/java/com/yau/digitalrmb/DigitalRmbApplication.java +++ b/src/main/java/com/yau/digitalrmb/DigitalRmbApplication.java @@ -2,8 +2,10 @@ package com.yau.digitalrmb; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.context.properties.ConfigurationPropertiesScan; @SpringBootApplication +@ConfigurationPropertiesScan public class DigitalRmbApplication { public static void main(String[] args) { diff --git a/src/main/java/com/yau/digitalrmb/platformintegration/config/PlatformIntegrationProperties.java b/src/main/java/com/yau/digitalrmb/platformintegration/config/PlatformIntegrationProperties.java new file mode 100644 index 0000000..62358db --- /dev/null +++ b/src/main/java/com/yau/digitalrmb/platformintegration/config/PlatformIntegrationProperties.java @@ -0,0 +1,72 @@ +package com.yau.digitalrmb.platformintegration.config; + +import jakarta.validation.Valid; +import jakarta.validation.constraints.AssertTrue; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Getter; +import lombok.Setter; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.validation.annotation.Validated; + +import java.time.Duration; + +@Getter +@Setter +@Validated +@ConfigurationProperties("platform-integration") +public class PlatformIntegrationProperties { + @Valid + private Datasource datasource = new Datasource(); + @Valid + private Token token = new Token(); + @Valid + private Cas cas = new Cas(); + @Valid + private Frontend frontend = new Frontend(); + + @Getter + @Setter + public static class Datasource { + @NotBlank + private String url; + @NotBlank + private String username; + @NotBlank + private String password; + } + + @Getter + @Setter + public static class Token { + @NotNull + private Duration maxAge; + @NotBlank + private String teacherClaimValue; + @NotBlank + private String studentClaimValue; + + @AssertTrue(message = "token.max-age must be positive") + public boolean isMaxAgePositive() { + return maxAge != null && !maxAge.isNegative() && !maxAge.isZero(); + } + } + + @Getter + @Setter + public static class Cas { + @NotBlank + private String loginUrl; + @NotBlank + private String validateUrl; + @NotBlank + private String callbackUrl; + } + + @Getter + @Setter + public static class Frontend { + @NotBlank + private String callbackUrl; + } +} diff --git a/src/main/java/com/yau/digitalrmb/platformintegration/domain/PlatformRole.java b/src/main/java/com/yau/digitalrmb/platformintegration/domain/PlatformRole.java new file mode 100644 index 0000000..63bf6f8 --- /dev/null +++ b/src/main/java/com/yau/digitalrmb/platformintegration/domain/PlatformRole.java @@ -0,0 +1,25 @@ +package com.yau.digitalrmb.platformintegration.domain; + +public enum PlatformRole { + TEACHER("JT_S_02"), + STUDENT("JT_S_03"); + + private final String jobType; + + PlatformRole(String jobType) { + this.jobType = jobType; + } + + public static PlatformRole fromJobType(String jobType) { + for (PlatformRole role : values()) { + if (role.jobType.equals(jobType)) { + return role; + } + } + throw new IllegalArgumentException("Unsupported platform job type: " + jobType); + } + + public String jobType() { + return jobType; + } +} diff --git a/src/main/resources/application-test.yml b/src/main/resources/application-test.yml index dcabcd0..d2e94dd 100644 --- a/src/main/resources/application-test.yml +++ b/src/main/resources/application-test.yml @@ -14,3 +14,18 @@ security: bootstrap-admin: username: admin password: ChangeMe123! +platform-integration: + datasource: + url: jdbc:h2:mem:platform;MODE=MySQL;DB_CLOSE_DELAY=-1;DATABASE_TO_LOWER=TRUE + username: sa + password: test-password + token: + max-age: PT2M + teacher-claim-value: teacher + student-claim-value: student + cas: + login-url: https://sso.example.edu/login + validate-url: https://sso.example.edu/p3/serviceValidate + callback-url: https://rmb.example.edu/api/v1/auth/cas/callback + frontend: + callback-url: https://rmb.example.edu/sso-callback diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 656b54e..3e0cc16 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -24,3 +24,18 @@ management: springdoc: swagger-ui: enabled: false +platform-integration: + datasource: + url: ${DIGITAL_RMB_PLATFORM_DB_URL} + username: ${DIGITAL_RMB_PLATFORM_DB_USERNAME} + password: ${DIGITAL_RMB_PLATFORM_DB_PASSWORD} + token: + max-age: PT2M + teacher-claim-value: teacher + student-claim-value: student + cas: + login-url: ${DIGITAL_RMB_CAS_LOGIN_URL} + validate-url: ${DIGITAL_RMB_CAS_VALIDATE_URL} + callback-url: ${DIGITAL_RMB_CAS_CALLBACK_URL} + frontend: + callback-url: ${DIGITAL_RMB_FRONTEND_CALLBACK_URL} diff --git a/src/test/java/com/yau/digitalrmb/platformintegration/config/PlatformIntegrationPropertiesTest.java b/src/test/java/com/yau/digitalrmb/platformintegration/config/PlatformIntegrationPropertiesTest.java new file mode 100644 index 0000000..b6ef7c4 --- /dev/null +++ b/src/test/java/com/yau/digitalrmb/platformintegration/config/PlatformIntegrationPropertiesTest.java @@ -0,0 +1,43 @@ +package com.yau.digitalrmb.platformintegration.config; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; +import org.springframework.context.annotation.Configuration; + +import java.time.Duration; + +import static org.assertj.core.api.Assertions.assertThat; + +class PlatformIntegrationPropertiesTest { + private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() + .withConfiguration(AutoConfigurations.of(PropertiesConfiguration.class)) + .withPropertyValues( + "platform-integration.datasource.url=jdbc:mysql://localhost:3306/tianze", + "platform-integration.datasource.username=readonly", + "platform-integration.datasource.password=secret", + "platform-integration.token.max-age=PT2M", + "platform-integration.token.teacher-claim-value=teacher", + "platform-integration.token.student-claim-value=student", + "platform-integration.cas.login-url=https://sso.example.edu/login", + "platform-integration.cas.validate-url=https://sso.example.edu/p3/serviceValidate", + "platform-integration.cas.callback-url=https://rmb.example.edu/api/v1/auth/cas/callback", + "platform-integration.frontend.callback-url=https://rmb.example.edu/sso-callback"); + + @Test + void bindsReadOnlyDatasourceAndAuthenticationEndpoints() { + contextRunner.run(context -> { + PlatformIntegrationProperties properties = context.getBean(PlatformIntegrationProperties.class); + + assertThat(properties.getDatasource().getUsername()).isEqualTo("readonly"); + assertThat(properties.getToken().getMaxAge()).isEqualTo(Duration.ofMinutes(2)); + assertThat(properties.getCas().getCallbackUrl()).isEqualTo("https://rmb.example.edu/api/v1/auth/cas/callback"); + }); + } + + @Configuration(proxyBeanMethods = false) + @EnableConfigurationProperties(PlatformIntegrationProperties.class) + static class PropertiesConfiguration { + } +} diff --git a/src/test/java/com/yau/digitalrmb/platformintegration/domain/PlatformRoleTest.java b/src/test/java/com/yau/digitalrmb/platformintegration/domain/PlatformRoleTest.java new file mode 100644 index 0000000..353f32e --- /dev/null +++ b/src/test/java/com/yau/digitalrmb/platformintegration/domain/PlatformRoleTest.java @@ -0,0 +1,17 @@ +package com.yau.digitalrmb.platformintegration.domain; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class PlatformRoleTest { + + @Test + void mapsOnlyTeacherAndStudentJobTypes() { + assertThat(PlatformRole.fromJobType("JT_S_02")).isEqualTo(PlatformRole.TEACHER); + assertThat(PlatformRole.fromJobType("JT_S_03")).isEqualTo(PlatformRole.STUDENT); + assertThatThrownBy(() -> PlatformRole.fromJobType("JT_S_01")) + .isInstanceOf(IllegalArgumentException.class); + } +}