From 47f64dc4b819320793e30459e8fe6e3b2d08660d Mon Sep 17 00:00:00 2001 From: root Date: Thu, 27 Nov 2025 14:24:10 +0300 Subject: [PATCH] add Session Settings --- pom.xml | 4 +- .../controller/AuthInfoController.java | 27 -- .../controller/DebugAuthController.java | 6 + .../model/session/SessionSettings.java | 26 +- .../repository/AuthInfoRepositoryJdbc.java | 250 ------------------ .../repository/SettingsRepositoryJdbc.java | 49 ++++ .../copperside/service/DebugAuthService.java | 7 +- .../util/DurationFlexibleDeserializer.java | 54 ++++ .../util/SessionSettingsHelper.java | 91 ++++--- src/main/resources/application.yaml | 6 +- .../sql/auth/find_rolesettings_by_authid.sql | 16 +- .../sql/auth/find_settings_by_authid.sql | 3 + 12 files changed, 199 insertions(+), 340 deletions(-) delete mode 100644 src/main/java/ru/copperside/controller/AuthInfoController.java delete mode 100644 src/main/java/ru/copperside/repository/AuthInfoRepositoryJdbc.java create mode 100644 src/main/java/ru/copperside/repository/SettingsRepositoryJdbc.java create mode 100644 src/main/java/ru/copperside/util/DurationFlexibleDeserializer.java create mode 100644 src/main/resources/sql/auth/find_settings_by_authid.sql diff --git a/pom.xml b/pom.xml index 0f8f25c..6736fb4 100644 --- a/pom.xml +++ b/pom.xml @@ -18,8 +18,8 @@ - 25 - 25 + 17 + 17 UTF-8 2.8.14 diff --git a/src/main/java/ru/copperside/controller/AuthInfoController.java b/src/main/java/ru/copperside/controller/AuthInfoController.java deleted file mode 100644 index 16aa082..0000000 --- a/src/main/java/ru/copperside/controller/AuthInfoController.java +++ /dev/null @@ -1,27 +0,0 @@ -/* -package ru.copperside.controller; - -import lombok.RequiredArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import ru.copperside.model.authinfo.AuthInfo; -import ru.copperside.service.AuthInfoService; - -@RestController -@RequestMapping("/api/authinfo") -@RequiredArgsConstructor -public class AuthInfoController { - private final AuthInfoService service; - - // Пример: GET /api/authinfo/user123?type=Secret - @GetMapping("/{dataId}") - public ResponseEntity getByDataIdAndType( - @PathVariable String dataId - ) { - return ResponseEntity.ok(service.getByDataIdAndType(dataId)); - } -} -*/ \ No newline at end of file diff --git a/src/main/java/ru/copperside/controller/DebugAuthController.java b/src/main/java/ru/copperside/controller/DebugAuthController.java index eb05ac6..064a20d 100644 --- a/src/main/java/ru/copperside/controller/DebugAuthController.java +++ b/src/main/java/ru/copperside/controller/DebugAuthController.java @@ -7,6 +7,7 @@ import ru.copperside.model.authinfo.SecretData; import ru.copperside.model.dto.RolePermissionDto; import ru.copperside.model.enums.AuthenticationType; import ru.copperside.model.permission.Permission; +import ru.copperside.model.session.SessionSettings; import ru.copperside.service.DebugAuthService; import java.util.List; @@ -55,4 +56,9 @@ public class DebugAuthController { ) { return ResponseEntity.ok(service.getPermissions(hierarchyId)); } + + @GetMapping("/merged") + public ResponseEntity merged(@RequestParam Long authId) { + return ResponseEntity.ok(service.getMerged(authId)); + } } \ No newline at end of file diff --git a/src/main/java/ru/copperside/model/session/SessionSettings.java b/src/main/java/ru/copperside/model/session/SessionSettings.java index e6bca14..70080a2 100644 --- a/src/main/java/ru/copperside/model/session/SessionSettings.java +++ b/src/main/java/ru/copperside/model/session/SessionSettings.java @@ -3,18 +3,38 @@ package ru.copperside.model.session; import lombok.Builder; import lombok.extern.jackson.Jacksonized; import ru.copperside.model.enums.AuthType; +import com.fasterxml.jackson.annotation.JsonAlias; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import ru.copperside.util.DurationFlexibleDeserializer; import java.time.Duration; import java.util.List; + @Jacksonized -@Builder +@Builder(toBuilder = true) public record SessionSettings( - Duration ttl, + @JsonAlias({"Ttl", "TTL", "ttl"}) + @JsonDeserialize( + using = DurationFlexibleDeserializer.class + ) + java.time.Duration ttl, + + @JsonAlias({"AutoProlongation", "autoProlongation"}) Boolean autoProlongation, + + @JsonAlias({"AuthType", "authType"}) AuthType authType, - List authStepTypes, + + @JsonAlias({"AuthStepTypes", "authStepTypes"}) + java.util.List authStepTypes, + + @JsonAlias({"IgnoreConfirmation", "ignoreConfirmation"}) Boolean ignoreConfirmation, + + @JsonAlias({"OneActiveSession", "oneActiveSession"}) Boolean oneActiveSession, + + @JsonAlias({"InMemory", "inMemory"}) Boolean inMemory ) {} \ No newline at end of file diff --git a/src/main/java/ru/copperside/repository/AuthInfoRepositoryJdbc.java b/src/main/java/ru/copperside/repository/AuthInfoRepositoryJdbc.java deleted file mode 100644 index 4ed9480..0000000 --- a/src/main/java/ru/copperside/repository/AuthInfoRepositoryJdbc.java +++ /dev/null @@ -1,250 +0,0 @@ -/* -package ru.copperside.repository; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ObjectNode; -import lombok.RequiredArgsConstructor; -import org.springframework.jdbc.core.RowMapper; -import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; -import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; -import org.springframework.stereotype.Repository; - - -import ru.copperside.model.authinfo.*; -import ru.copperside.model.enums.AuthType; -import ru.copperside.model.enums.KeyUsage; -import ru.copperside.model.enums.SecretType; -import ru.copperside.model.session.SessionSettings; -import ru.copperside.sql.SqlRegistry; -import ru.copperside.util.SessionSettingsHelper; - -import static ru.copperside.util.RepoMappingHelper.*; - -import java.sql.ResultSet; -import java.time.Duration; -import java.util.ArrayList; -import java.util.EnumSet; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.atomic.AtomicReference; - -@Repository -@RequiredArgsConstructor -public class AuthInfoRepositoryJdbc implements AuthInfoRepository { - private final NamedParameterJdbcTemplate jdbc; - private final ObjectMapper om; - private final SqlRegistry sqlRegistry; - - private static final String SQL_INIT = "auth/find_authinfo_init_by_dataid_and_type"; - private static final String SQL_PRIV = "auth/find_privatedata_by_authid"; - private static final String SQL_ROLESET = "auth/find_rolesettings_by_authid"; - - @Override - public Optional findByDataIdAndType(String dataId, String type) { - var params = new MapSqlParameterSource() - .addValue("dataId", dataId) - .addValue("type", type); - - RowMapper rm = (rs, rn) -> mapAuthInfo(rs); - - List list = jdbc.query(sqlRegistry.get(SQL_INIT), params, rm); - - if (!list.isEmpty()) { - AuthInfo base = list.get(0); - if (base.authId() != null) { - JsonNode privateData = loadPrivateData(base.authId()); - return Optional.of(base.toBuilder().privateData(privateData).build()); - } - } - - return Optional.empty(); - } - - private JsonNode loadPrivateData(Long authId) { - if (authId == null) return null; - var params = new MapSqlParameterSource().addValue("authId", authId); - ObjectNode pd = om.createObjectNode(); - - jdbc.query(sqlRegistry.get(SQL_PRIV), params, rs -> { - String key = rs.getString("KEY"); - String value = rs.getString("VALUE"); - try { - JsonNode node = om.readTree(value); - pd.set(key, node); - } catch (Exception e) { - pd.put(key, value); - } - }); - return pd; - } - - private AuthInfo mapAuthInfo(ResultSet rs) { - try { - Long authId = getLong(rs, "AD_AUTHID"); // AD_AUTHID -> AuthInfo.authId - String dataId = rs.getString("AD_DATAID"); // AD_DATAID -> AuthInfo.dataId - Long hierarchyId = getLong(rs, "AH_HIERARCHYID"); // AH_HIERARCHYID -> AuthInfo.hierarchyId - String displayName = rs.getString("AH_DISPLAYNAME"); // AH_DISPLAYNAME -> AuthInfo.displayName - String secretType = rs.getString("AD_TYPE"); - - Boolean isEnabled = null; - Boolean needActivation = null; - - JsonNode paramsJson = readJsonFlexible(rs, "AI_PARAMETERS", om); - if (paramsJson != null && !paramsJson.isNull()) { - isEnabled = getBooleanCaseInsensitive(paramsJson, "IsEnabled", "isEnabled"); - needActivation = getBooleanCaseInsensitive(paramsJson, "NeedActivation", "needActivation"); - } - - SecretData secretData = null; - JsonNode secretJson = readJsonFlexible(rs, "AD_DATA", om); - - if (secretJson != null && !secretJson.isNull()) { - Boolean sdIsEnabled = getBooleanCaseInsensitive(secretJson, "IsEnable", "isEnabled"); - String keyUsageStr = getStringCaseInsensitive(secretJson, "KeyUsage", "keyUsage"); - String secretTypeStr = getStringCaseInsensitive(secretJson, "SecretType", "secretType"); - String secretValue = getStringCaseInsensitive(secretJson, "Secret", "secret"); - - EnumSet keyUsages = parseKeyUsageSet(secretJson, keyUsageStr); - SecretType sType = parseSecretType(secretTypeStr); - - secretData = SecretData.builder() - .type(secretType) // тип секрета из AD_TYPE (внешний) - .isEnabled(sdIsEnabled) - .keyUsage(keyUsages) - .secretType(sType) - .secret(secretValue) - .build(); - }else { - secretData = SecretData.builder() - .type(secretType) - .build(); - } - - JsonNode aiSettingsJson = readJsonFlexible(rs, "AI_SETTINGS", om); - SessionSettings sessionSettings = computeSessionSettings(authId, aiSettingsJson); // ⬅️ главный расчёт - - return AuthInfo.builder() - .authId(authId) - .dataId(dataId) - .hierarchyId(hierarchyId) - .displayName(displayName) - .isEnabled(isEnabled) - .needActivation(needActivation) - .permissions(List.of()) - .sessionSettings(sessionSettings) - .sessionData(null) - .privateData(null) - .secretData(secretData) - .build(); - } catch (Exception e) { - throw new IllegalStateException("Failed to map AuthInfo", e); - } - } - - private SessionSettings computeSessionSettings(Long authId, JsonNode aiSettingsJson) { - // userSettings = {}; merge(AI_SETTINGS, false) - SessionSettings userSettings = SessionSettingsHelper.merge( - SessionSettings.builder().build(), - mapSessionSettings(aiSettingsJson), - false - ); - - // Ролевые настройки с ORDER BY LEVEL (накатываем последовательно isRole=true) - var resultRef = new AtomicReference<>(SessionSettings.builder().build()); - var params = new MapSqlParameterSource().addValue("authId", authId); - jdbc.query(sqlRegistry.get(SQL_ROLESET), params, rs -> { - JsonNode roleJson = readJsonFlexible(rs, "SETTINGS", om); - SessionSettings roleSet = mapSessionSettings(roleJson); - resultRef.set(SessionSettingsHelper.merge(resultRef.get(), roleSet, true)); - }); - - // финально поверх — userSettings (isRole=false) - return SessionSettingsHelper.merge(resultRef.get(), userSettings, false); - } - - private SessionSettings mapSessionSettings(JsonNode node) { - if (node == null || node.isNull()) return null; - - Duration ttl = null; - if (node.hasNonNull("ttlSec")) { - ttl = Duration.ofSeconds(node.path("ttlSec").asLong(0)); - } else if (node.hasNonNull("ttl")) { - try { ttl = Duration.parse(node.path("ttl").asText()); } catch (Exception ignore) {} - } - - AuthType authType = null; - if (node.hasNonNull("authType")) { - var at = node.get("authType"); - if (at.isInt()) { - authType = AuthType.fromCode(at.asInt(0)); - } else { - try { authType = AuthType.valueOf(at.asText()); } catch (Exception ignore) {} - } - } - - List steps = new ArrayList<>(); - if (node.hasNonNull("authStepTypes") && node.get("authStepTypes").isArray()) { - for (JsonNode n : node.get("authStepTypes")) { - steps.add(n.asText()); - } - } - - return new SessionSettingsBuilder() - .ttl(ttl) - .autoProlongation(asNullableBool(node, "autoProlongation")) - .authType(authType) - .authStepTypes(steps) - .ignoreConfirmation(asNullableBool(node, "ignoreConfirmation")) - .oneActiveSession(asNullableBool(node, "oneActiveSession")) - .inMemory(asNullableBool(node, "inMemory")) - .build(); - } - - private Boolean asNullableBool(JsonNode node, String field) { - return node.has(field) && !node.get(field).isNull() ? node.get(field).asBoolean() : null; - } - - private static final class SessionSettingsBuilder { - private Duration ttl; - private Boolean autoProlongation; - private AuthType authType; - private List authStepTypes; - private Boolean ignoreConfirmation; - private Boolean oneActiveSession; - private Boolean inMemory; - - SessionSettingsBuilder() {} - SessionSettingsBuilder(SessionSettings base) { - if (base == null) return; - this.ttl = base.ttl(); - this.autoProlongation = base.autoProlongation(); - this.authType = base.authType(); - this.authStepTypes = base.authStepTypes(); - this.ignoreConfirmation = base.ignoreConfirmation(); - this.oneActiveSession = base.oneActiveSession(); - this.inMemory = base.inMemory(); - } - - SessionSettingsBuilder ttl(Duration v) { this.ttl = v; return this; } - SessionSettingsBuilder autoProlongation(Boolean v) { this.autoProlongation = v; return this; } - SessionSettingsBuilder authType(AuthType v) { this.authType = v; return this; } - SessionSettingsBuilder authStepTypes(List v) { this.authStepTypes = v; return this; } - SessionSettingsBuilder ignoreConfirmation(Boolean v) { this.ignoreConfirmation = v; return this; } - SessionSettingsBuilder oneActiveSession(Boolean v) { this.oneActiveSession = v; return this; } - SessionSettingsBuilder inMemory(Boolean v) { this.inMemory = v; return this; } - - SessionSettings build() { - return SessionSettings.builder() - .ttl(ttl) - .autoProlongation(autoProlongation) - .authType(authType) - .authStepTypes(authStepTypes == null ? null : List.copyOf(authStepTypes)) - .ignoreConfirmation(ignoreConfirmation) - .oneActiveSession(oneActiveSession) - .inMemory(inMemory) - .build(); - } - } -} -*/ \ No newline at end of file diff --git a/src/main/java/ru/copperside/repository/SettingsRepositoryJdbc.java b/src/main/java/ru/copperside/repository/SettingsRepositoryJdbc.java new file mode 100644 index 0000000..1a583af --- /dev/null +++ b/src/main/java/ru/copperside/repository/SettingsRepositoryJdbc.java @@ -0,0 +1,49 @@ +package ru.copperside.repository; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectReader; +import lombok.RequiredArgsConstructor; +import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.stereotype.Repository; +import ru.copperside.model.session.SessionSettings; +import ru.copperside.sql.SqlRegistry; + +import java.util.List; +import java.util.Objects; + +import static ru.copperside.util.RepoMappingHelper.readJson; +import static ru.copperside.util.SessionSettingsHelper.merge; + +@Repository +@RequiredArgsConstructor +public class SettingsRepositoryJdbc implements SettingsRepository { + + private final NamedParameterJdbcTemplate jdbc; + private final ObjectMapper om; + private final SqlRegistry sql; + + private ObjectReader settingsReader() { + return om.readerFor(SessionSettings.class); + } + + @Override + public SessionSettings loadMerged(Long authId) { + var p = new MapSqlParameterSource().addValue("authId", authId); + + // user + SessionSettings user = jdbc.query(sql.get("auth/find_settings_by_authid"), p, rs -> + rs.next() ? readJson(rs, "AI_SETTINGS", settingsReader()) : null); + + // roles (по уровням, порядке дерева) + List roles = jdbc.query(sql.get("auth/find_rolesettings_by_authid"), p, + (rs, rn) -> readJson(rs, "SETTINGS", settingsReader())); + + // merge: роли последовательно (isRole=true), затем поверх пользовательские (isRole=false) + SessionSettings acc = roles.stream() + .filter(Objects::nonNull) + .reduce(SessionSettings.builder().build(), (a, r) -> merge(a, r, true), (a, b) -> b); + + return merge(acc, user, false); + } +} \ No newline at end of file diff --git a/src/main/java/ru/copperside/service/DebugAuthService.java b/src/main/java/ru/copperside/service/DebugAuthService.java index 736bbf3..fa6d63b 100644 --- a/src/main/java/ru/copperside/service/DebugAuthService.java +++ b/src/main/java/ru/copperside/service/DebugAuthService.java @@ -6,8 +6,10 @@ import ru.copperside.model.authinfo.SecretData; import ru.copperside.model.dto.RolePermissionDto; import ru.copperside.model.enums.AuthenticationType; import ru.copperside.model.permission.Permission; +import ru.copperside.model.session.SessionSettings; import ru.copperside.repository.PermissionsRepository; import ru.copperside.repository.SecretRepository; +import ru.copperside.repository.SettingsRepository; import java.util.List; @@ -17,6 +19,7 @@ public class DebugAuthService { private final SecretRepository secretRepository; private final PermissionsRepository permissionsRepository; + private final SettingsRepository settingsRepository; public SecretData getSecretData(String dataId, String type) { // если не указали type — считаем Secret @@ -40,6 +43,8 @@ public class DebugAuthService { public List getPermissions(Long hierarchyId) { return permissionsRepository.findCompiledByHierarchyId(hierarchyId); } - + public SessionSettings getMerged(Long authId) { + return settingsRepository.loadMerged(authId); + } } \ No newline at end of file diff --git a/src/main/java/ru/copperside/util/DurationFlexibleDeserializer.java b/src/main/java/ru/copperside/util/DurationFlexibleDeserializer.java new file mode 100644 index 0000000..767437d --- /dev/null +++ b/src/main/java/ru/copperside/util/DurationFlexibleDeserializer.java @@ -0,0 +1,54 @@ +package ru.copperside.util; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; + +import java.io.IOException; +import java.time.Duration; + +public class DurationFlexibleDeserializer extends JsonDeserializer { + + @Override + public Duration deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { + JsonNode node = p.getCodec().readTree(p); + if (node == null || node.isNull()) return null; + + // число → секунды + if (node.isNumber()) { + return Duration.ofSeconds(node.longValue()); + } + + String s = node.asText(null); + if (s == null || s.isBlank()) return null; + + // Формат "hh:mm:ss" как в C# TimeSpan ("00:10:00") + if (s.matches("\\d{1,2}:\\d{2}:\\d{2}")) { + String[] parts = s.split(":"); + long h = Long.parseLong(parts[0]); + long m = Long.parseLong(parts[1]); + long sec = Long.parseLong(parts[2]); + return Duration.ofHours(h).plusMinutes(m).plusSeconds(sec); + } + + // ISO-8601 (P1D, PT10M, ...) + if (s.startsWith("P") || s.startsWith("p")) { + try { return Duration.parse(s); } catch (Exception ignore) {} + } + + // короткие формы: "1h", "30m", "15s", "600" (сек) + try { + String v = s.trim().toLowerCase(); + if (v.endsWith("h")) return Duration.ofHours(Long.parseLong(v.substring(0, v.length()-1))); + if (v.endsWith("m")) return Duration.ofMinutes(Long.parseLong(v.substring(0, v.length()-1))); + if (v.endsWith("s")) return Duration.ofSeconds(Long.parseLong(v.substring(0, v.length()-1))); + return Duration.ofSeconds(Long.parseLong(v)); + } catch (Exception ignore) {} + + // последняя попытка — ISO + try { return Duration.parse(s); } catch (Exception ignore) {} + + return null; + } +} \ No newline at end of file diff --git a/src/main/java/ru/copperside/util/SessionSettingsHelper.java b/src/main/java/ru/copperside/util/SessionSettingsHelper.java index 7b682dc..304b24a 100644 --- a/src/main/java/ru/copperside/util/SessionSettingsHelper.java +++ b/src/main/java/ru/copperside/util/SessionSettingsHelper.java @@ -1,64 +1,63 @@ package ru.copperside.util; -import ru.copperside.model.enums.AuthType; import ru.copperside.model.session.SessionSettings; -import java.time.Duration; import java.util.LinkedHashSet; -import java.util.List; -import java.util.Set; public final class SessionSettingsHelper { private SessionSettingsHelper() {} - public static SessionSettings merge(SessionSettings target, SessionSettings merge, boolean isRole) { - if (target == null && merge == null) return null; - if (target == null) target = SessionSettings.builder().build(); - if (merge == null) return target; + /** Merge session settings. isRole=true — логика «ролевого» слияния из C#. */ + public static SessionSettings merge(SessionSettings base, SessionSettings merge, boolean isRole) { + if (base == null) base = SessionSettings.builder().build(); + if (merge == null) return base; - Duration ttl = target.ttl(); - Boolean auto = target.autoProlongation(); - AuthType at = target.authType(); - List steps = target.authStepTypes(); - Boolean ign = target.ignoreConfirmation(); - Boolean one = target.oneActiveSession(); - Boolean mem = target.inMemory(); + var b = base.toBuilder(); - if (isRole) { - if (merge.ttl() != null) ttl = merge.ttl(); - if (merge.autoProlongation() != null) auto = merge.autoProlongation(); - if (merge.authType() != null) at = (at == null) ? merge.authType() : max(at, merge.authType()); - if (merge.authStepTypes() != null && !merge.authStepTypes().isEmpty()) { - Set s = new LinkedHashSet<>(); - if (steps != null) s.addAll(steps); - s.addAll(merge.authStepTypes()); - steps = List.copyOf(s); + // TTL, AutoProlongation + if (merge.ttl() != null) b.ttl(merge.ttl()); + if (merge.autoProlongation() != null) b.autoProlongation(merge.autoProlongation()); + + // AuthType: для ролей — берём максимальный (по ordinal), иначе — прямое присваивание + if (merge.authType() != null) { + if (isRole) { + var current = b.build().authType(); + if (current == null || current.ordinal() < merge.authType().ordinal()) { + b.authType(merge.authType()); + } + } else { + b.authType(merge.authType()); } - if (merge.ignoreConfirmation() != null) { - if (ign == null) ign = merge.ignoreConfirmation(); - else if (!merge.ignoreConfirmation()) ign = false; - } - } else { - if (merge.ttl() != null) ttl = merge.ttl(); - if (merge.autoProlongation() != null) auto = merge.autoProlongation(); - if (merge.authType() != null) at = merge.authType(); - if (merge.authStepTypes() != null) steps = merge.authStepTypes(); - if (merge.ignoreConfirmation() != null) ign = merge.ignoreConfirmation(); - if (merge.oneActiveSession() != null) one = merge.oneActiveSession(); } - mem = Boolean.TRUE.equals(mem) || Boolean.TRUE.equals(merge.inMemory()); + // AuthStepTypes: роли — объединение множеств; пользователь — overwrite + if (merge.authStepTypes() != null) { + if (isRole && base.authStepTypes() != null) { + var set = new LinkedHashSet<>(base.authStepTypes()); + set.addAll(merge.authStepTypes()); + b.authStepTypes(set.stream().toList()); + } else { + b.authStepTypes(merge.authStepTypes()); + } + } - return SessionSettings.builder() - .ttl(ttl).autoProlongation(auto).authType(at) - .authStepTypes(steps) - .ignoreConfirmation(ign).oneActiveSession(one).inMemory(mem) - .build(); - } + // IgnoreConfirmation: роли — если хоть одна роль false → false; пользователь — overwrite + if (merge.ignoreConfirmation() != null) { + if (isRole) { + var cur = base.ignoreConfirmation(); + if (cur == null) b.ignoreConfirmation(merge.ignoreConfirmation()); + else if (!merge.ignoreConfirmation()) b.ignoreConfirmation(false); + } else { + b.ignoreConfirmation(merge.ignoreConfirmation()); + } + } - private static AuthType max(AuthType a, AuthType b) { - int ca = a == null ? 0 : a.ordinal(); - int cb = b == null ? 0 : b.ordinal(); - return (ca >= cb) ? a : b; // Unknown < Simple < TwoStep + // OneActiveSession — простое присваивание (если задано) + if (merge.oneActiveSession() != null) b.oneActiveSession(merge.oneActiveSession()); + + // InMemory: ИЛИ + b.inMemory(Boolean.TRUE.equals(base.inMemory()) || Boolean.TRUE.equals(merge.inMemory())); + + return b.build(); } } \ No newline at end of file diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index b369370..c4595cb 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -3,7 +3,7 @@ server: spring: datasource: - url: jdbc:oracle:thin:@127.0.0.1:1521/TKBPAYPDB - username: WFMPROP - password: WFMPROP + url: jdbc:oracle:thin:@cdm-oradb-02.ad.transcapital.com:1523/wfm + username: AUTH + password: .,z;pws-2shds driver-class-name: oracle.jdbc.OracleDriver diff --git a/src/main/resources/sql/auth/find_rolesettings_by_authid.sql b/src/main/resources/sql/auth/find_rolesettings_by_authid.sql index 0fb87a9..2087dfb 100644 --- a/src/main/resources/sql/auth/find_rolesettings_by_authid.sql +++ b/src/main/resources/sql/auth/find_rolesettings_by_authid.sql @@ -1,11 +1,11 @@ SELECT r.SETTINGS FROM ( - SELECT ah.HIERARCHYID, ah."LEVEL" - FROM AUTHHIERARCHY ah, AUTHHIERARCHY ah2 - WHERE ah.LEFTKEY <= ah2.LEFTKEY - AND ah.RIGHTKEY >= ah2.RIGHTKEY - AND ah2.AUTHID = :authId - ) h - JOIN HIERARCHYROLE hr ON h.HIERARCHYID = hr.HIERARCHYID - JOIN ROLES r ON r.ROLEID = hr.ROLEID + SELECT ah.HIERARCHYID, ah."LEVEL" + FROM AUTHHIERARCHY ah, AUTHHIERARCHY ah2 + WHERE ah.LEFTKEY <= ah2.LEFTKEY + AND ah.RIGHTKEY >= ah2.RIGHTKEY + AND ah2.AUTHID = :authId +) h +JOIN HIERARCHYROLE hr ON hr.HIERARCHYID = h.HIERARCHYID +JOIN ROLES r ON r.ROLEID = hr.ROLEID ORDER BY h."LEVEL" \ No newline at end of file diff --git a/src/main/resources/sql/auth/find_settings_by_authid.sql b/src/main/resources/sql/auth/find_settings_by_authid.sql new file mode 100644 index 0000000..ea32aec --- /dev/null +++ b/src/main/resources/sql/auth/find_settings_by_authid.sql @@ -0,0 +1,3 @@ +SELECT ai.SETTINGS AS AI_SETTINGS +FROM AUTHIDS ai +WHERE ai.AUTHID = :authId \ No newline at end of file