package com.cloudhandson.ddsbackoffice.service; import com.cloudhandson.vpdbackoffice.service.AppException; import java.util.List; import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Service; /** Maps a verified OIDC issuer and subject to one active HMM application user. */ @Service public class DdsMcpExternalIdentityResolver { private final JdbcTemplate jdbcTemplate; public DdsMcpExternalIdentityResolver(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } public long resolveApplicationUserId(String issuer, String subject) { if (!safe(issuer) || !safe(subject)) { throw denied(); } try { List userIds = jdbcTemplate.query(""" SELECT b.application_user_id FROM cb_external_identity_binding b JOIN cb_app_user u ON u.user_id = b.application_user_id WHERE b.issuer = ? AND b.subject = ? AND b.active = 'Y' AND u.active = 'Y' """, (row, ignored) -> row.getLong("application_user_id"), issuer, subject); if (userIds.size() != 1) { throw denied(); } return userIds.getFirst(); } catch (AppException exception) { throw exception; } catch (DataAccessException exception) { throw new AppException("DDS_CONTEXT_UNAVAILABLE: 외부 ID 매핑을 확인할 수 없습니다."); } } private boolean safe(String value) { return value != null && !value.isBlank() && value.length() <= 512; } private AppException denied() { return new AppException("AUTHORIZATION_DENIED: 외부 OIDC 사용자를 DDS에 매핑할 수 없습니다."); } }