Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public Page<AuditLogResponse> search(
tenantId, actorLogin, action, targetType, outcome, from, to);
Pageable pageable = PageRequest.of(
Math.max(0, page),
Math.min(MAX_PAGE_SIZE, Math.max(1, size == 0 ? DEFAULT_PAGE_SIZE : size)),
Math.clamp(size == 0 ? DEFAULT_PAGE_SIZE : size, 1, MAX_PAGE_SIZE),
Sort.by(Sort.Direction.DESC, "occurredAt"));
return service.search(criteria, pageable).map(entity -> AuditLogResponse.from(entity, objectMapper));
}
Expand Down
7 changes: 7 additions & 0 deletions devslab-kit-autoconfigure/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ dependencies {
implementation("org.springframework.boot:spring-boot-autoconfigure")
annotationProcessor("org.springframework.boot:spring-boot-configuration-processor")

// Lombok generates the @ConfigurationProperties accessors (DevslabKitProperties).
// Declared before nothing in particular, but both Lombok and the Spring config
// processor run as annotation processors — Lombok generates the getters/setters
// that the config processor then reads for metadata.
compileOnly("org.projectlombok:lombok")
annotationProcessor("org.projectlombok:lombok")

// Micrometer for custom metrics; consumer's spring-boot-actuator activates it at runtime.
compileOnly("io.micrometer:micrometer-core")
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package kr.devslab.kit.autoconfigure;

import kr.devslab.kit.tenant.TenantMode;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties(prefix = "devslab.kit")
@Getter
public class DevslabKitProperties {

private final Identity identity = new Identity();
Expand All @@ -13,30 +16,8 @@ public class DevslabKitProperties {
private final Audit audit = new Audit();
private final Bootstrap bootstrap = new Bootstrap();

public Identity getIdentity() {
return identity;
}

public Bootstrap getBootstrap() {
return bootstrap;
}

public Access getAccess() {
return access;
}

public Tenant getTenant() {
return tenant;
}

public Menu getMenu() {
return menu;
}

public Audit getAudit() {
return audit;
}

@Getter
@Setter
public static class Identity {

private boolean enabled = true;
Expand All @@ -45,53 +26,12 @@ public static class Identity {
private java.time.Duration lockoutDuration = java.time.Duration.ofMinutes(15);
private final Jwt jwt = new Jwt();

public Jwt getJwt() {
return jwt;
}

@Getter
@Setter
public static class Jwt {
private String secret = "change-me-please-this-is-not-a-real-secret-32b!";
private java.time.Duration ttl = java.time.Duration.ofHours(8);
private String issuer = "devslab-kit";

public String getSecret() { return secret; }
public void setSecret(String secret) { this.secret = secret; }
public java.time.Duration getTtl() { return ttl; }
public void setTtl(java.time.Duration ttl) { this.ttl = ttl; }
public String getIssuer() { return issuer; }
public void setIssuer(String issuer) { this.issuer = issuer; }
}

public boolean isEnabled() {
return enabled;
}

public void setEnabled(boolean enabled) {
this.enabled = enabled;
}

public Mode getMode() {
return mode;
}

public void setMode(Mode mode) {
this.mode = mode;
}

public int getMaxFailedAttempts() {
return maxFailedAttempts;
}

public void setMaxFailedAttempts(int maxFailedAttempts) {
this.maxFailedAttempts = maxFailedAttempts;
}

public java.time.Duration getLockoutDuration() {
return lockoutDuration;
}

public void setLockoutDuration(java.time.Duration lockoutDuration) {
this.lockoutDuration = lockoutDuration;
}

public enum Mode {
Expand All @@ -102,19 +42,15 @@ public enum Mode {
}
}

@Getter
@Setter
public static class Access {

private boolean enabled = true;

public boolean isEnabled() {
return enabled;
}

public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
}

@Getter
@Setter
public static class Tenant {

private boolean enabled = true;
Expand All @@ -124,54 +60,6 @@ public static class Tenant {
private String headerName = "X-Tenant-Id";
private int subdomainIndex = 0;

public String getHeaderName() {
return headerName;
}

public void setHeaderName(String headerName) {
this.headerName = headerName;
}

public int getSubdomainIndex() {
return subdomainIndex;
}

public void setSubdomainIndex(int subdomainIndex) {
this.subdomainIndex = subdomainIndex;
}

public boolean isEnabled() {
return enabled;
}

public void setEnabled(boolean enabled) {
this.enabled = enabled;
}

public TenantMode getMode() {
return mode;
}

public void setMode(TenantMode mode) {
this.mode = mode;
}

public String getDefaultTenantId() {
return defaultTenantId;
}

public void setDefaultTenantId(String defaultTenantId) {
this.defaultTenantId = defaultTenantId;
}

public Resolver getResolver() {
return resolver;
}

public void setResolver(Resolver resolver) {
this.resolver = resolver;
}

public enum Resolver {
FIXED,
HEADER,
Expand All @@ -181,6 +69,8 @@ public enum Resolver {
}
}

@Getter
@Setter
public static class Menu {

private boolean enabled = true;
Expand All @@ -193,24 +83,10 @@ public static class Menu {
* mutations should be visible immediately.
*/
private java.time.Duration cacheTtl = java.time.Duration.ofMinutes(5);

public boolean isEnabled() {
return enabled;
}

public void setEnabled(boolean enabled) {
this.enabled = enabled;
}

public java.time.Duration getCacheTtl() {
return cacheTtl;
}

public void setCacheTtl(java.time.Duration cacheTtl) {
this.cacheTtl = cacheTtl;
}
}

@Getter
@Setter
public static class Audit {

private boolean enabled = true;
Expand All @@ -224,37 +100,10 @@ public static class Audit {
* trading a slow request for a dropped audit row.
*/
private int asyncQueueCapacity = 1024;

public boolean isEnabled() {
return enabled;
}

public void setEnabled(boolean enabled) {
this.enabled = enabled;
}

public int getAsyncQueueCapacity() {
return asyncQueueCapacity;
}

public void setAsyncQueueCapacity(int asyncQueueCapacity) {
this.asyncQueueCapacity = asyncQueueCapacity;
}
}

/**
* First-admin bootstrap (ADR 0001). Disabled by default so a no-config
* production deploy provisions nothing. When enabled, an idempotent runner
* creates a tenant, an admin role with the full {@code admin.*} permission
* set, and a single admin user on first boot — just enough to log in to the
* dashboard and take over.
*
* <p>Drive it per environment from profile-specific config (e.g.
* {@code application-local.yml} sets {@code admin-password: admin} with
* {@code must-change-password: false}; staging/prod inject a secret and
* leave the forced rotation on). Never commit a fixed password to the
* shared {@code application.yml}.
*/
@Getter
@Setter
public static class Bootstrap {

/** Master switch. Default OFF — bootstrap runs only when explicitly enabled. */
Expand Down Expand Up @@ -294,77 +143,5 @@ public static class Bootstrap {
* startup. The primary control is that no fixed default exists at all.
*/
private boolean failOnDefaultPasswordInProd = true;

public boolean isEnabled() {
return enabled;
}

public void setEnabled(boolean enabled) {
this.enabled = enabled;
}

public String getTenantId() {
return tenantId;
}

public void setTenantId(String tenantId) {
this.tenantId = tenantId;
}

public String getAdminLoginId() {
return adminLoginId;
}

public void setAdminLoginId(String adminLoginId) {
this.adminLoginId = adminLoginId;
}

public String getAdminPassword() {
return adminPassword;
}

public void setAdminPassword(String adminPassword) {
this.adminPassword = adminPassword;
}

public String getAdminEmail() {
return adminEmail;
}

public void setAdminEmail(String adminEmail) {
this.adminEmail = adminEmail;
}

public String getRoleCode() {
return roleCode;
}

public void setRoleCode(String roleCode) {
this.roleCode = roleCode;
}

public String getRoleName() {
return roleName;
}

public void setRoleName(String roleName) {
this.roleName = roleName;
}

public boolean isMustChangePassword() {
return mustChangePassword;
}

public void setMustChangePassword(boolean mustChangePassword) {
this.mustChangePassword = mustChangePassword;
}

public boolean isFailOnDefaultPasswordInProd() {
return failOnDefaultPasswordInProd;
}

public void setFailOnDefaultPasswordInProd(boolean failOnDefaultPasswordInProd) {
this.failOnDefaultPasswordInProd = failOnDefaultPasswordInProd;
}
}
}
Loading