diff --git a/backend/src/main/java/ru/micord/ervu/controller/ExtractController.java b/backend/src/main/java/ru/micord/ervu/controller/ExtractController.java index f749eb6..f8de58e 100644 --- a/backend/src/main/java/ru/micord/ervu/controller/ExtractController.java +++ b/backend/src/main/java/ru/micord/ervu/controller/ExtractController.java @@ -16,8 +16,13 @@ import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; import rtl.pgs.ervu.proto.ExtractRegistry; import rtl.pgs.ervu.proto.ResponseData; +import ru.micord.ervu.dto.ExtractEmptyRequestDto; import ru.micord.ervu.dto.ExtractRequestDto; import ru.micord.ervu.kafka.service.ReplyingKafkaService; +import ru.micord.ervu.security.esia.model.PersonModel; +import ru.micord.ervu.security.esia.service.PersonalDataService; +import ru.micord.ervu.security.esia.token.EsiaTokensStore; +import ru.micord.ervu.security.webbpm.jwt.UserIdsPair; import ru.micord.ervu.security.webbpm.jwt.util.SecurityUtil; /** @@ -25,28 +30,48 @@ import ru.micord.ervu.security.webbpm.jwt.util.SecurityUtil; */ @RestController public class ExtractController { - + private final PersonalDataService personalDataService; private final ReplyingKafkaService replyingKafkaService; + @Value("${ervu.kafka.registry.extract.empty.request.topic}") + private String registryExtractEmptyRequestTopic; @Value("${ervu.kafka.registry.extract.request.topic}") private String registryExtractRequestTopic; @Value("${ervu.kafka.registry.extract.reply.topic}") private String registryExtractReplyTopic; - public ExtractController(ReplyingKafkaService replyingKafkaService) { + public ExtractController(PersonalDataService personalDataService, ReplyingKafkaService replyingKafkaService) { + this.personalDataService = personalDataService; this.replyingKafkaService = replyingKafkaService; } @GetMapping(value = "/extract/{formatRegistry}") public ResponseEntity getExtract(@PathVariable String formatRegistry) { - String ervuId = SecurityUtil.getErvuId(); + UserIdsPair userIdsPair = SecurityUtil.getUserIdsPair(); - if (ervuId == null) { - return ResponseEntity.noContent().build(); + String ervuId = userIdsPair.getErvuId(); + byte[] reply; + + if (ervuId != null) { + ExtractRequestDto request = new ExtractRequestDto(ervuId, formatRegistry); + reply = replyingKafkaService.sendMessageAndGetReply(registryExtractRequestTopic, + registryExtractReplyTopic, request + ).get(); + } + else { + String esiaUserId = userIdsPair.getEsiaUserId(); // esiaUserid is not null here + String esiaAccessToken = EsiaTokensStore.getAccessToken(esiaUserId); + PersonModel personModel = personalDataService.getPersonModel(esiaAccessToken); + + ExtractEmptyRequestDto emptyRequest = new ExtractEmptyRequestDto( + personModel.getLastName(), + personModel.getFirstName(), personModel.getMiddleName(), personModel.getBirthDate(), + personModel.getSnils(), formatRegistry + ); + reply = replyingKafkaService.sendMessageAndGetReply(registryExtractEmptyRequestTopic, + registryExtractReplyTopic, emptyRequest + ).get(); } - ExtractRequestDto request = new ExtractRequestDto(ervuId, formatRegistry); - byte[] reply = replyingKafkaService.sendMessageAndGetReply(registryExtractRequestTopic, - registryExtractReplyTopic, request).get(); try { ResponseData responseData = ResponseData.parseFrom(reply); diff --git a/backend/src/main/java/ru/micord/ervu/dto/ExtractEmptyRequestDto.java b/backend/src/main/java/ru/micord/ervu/dto/ExtractEmptyRequestDto.java new file mode 100644 index 0000000..03c423a --- /dev/null +++ b/backend/src/main/java/ru/micord/ervu/dto/ExtractEmptyRequestDto.java @@ -0,0 +1,8 @@ +package ru.micord.ervu.dto; + +/** + * @author r.latypov + */ +public record ExtractEmptyRequestDto(String lastName, String firstName, String middleName, + String birthDate, String snils, String formatExtractRegistry) { +} diff --git a/backend/src/main/java/ru/micord/ervu/security/esia/service/EsiaAuthService.java b/backend/src/main/java/ru/micord/ervu/security/esia/service/EsiaAuthService.java index a3257ac..92df043 100644 --- a/backend/src/main/java/ru/micord/ervu/security/esia/service/EsiaAuthService.java +++ b/backend/src/main/java/ru/micord/ervu/security/esia/service/EsiaAuthService.java @@ -48,7 +48,7 @@ import ru.micord.ervu.security.webbpm.jwt.helper.SecurityHelper; import ru.micord.ervu.security.webbpm.jwt.service.JwtTokenService; import ru.micord.ervu.security.webbpm.jwt.model.Token; -import static ru.micord.ervu.security.webbpm.jwt.util.SecurityUtil.getCurrentUsername; +import static ru.micord.ervu.security.webbpm.jwt.util.SecurityUtil.getCurrentUserEsiaId; /** * @author Eduard Tihomirov @@ -412,7 +412,7 @@ public class EsiaAuthService { private String getMessageId(Exception exception) { return Integer.toUnsignedString(Objects - .hashCode(getCurrentUsername()), 36) + .hashCode(getCurrentUserEsiaId()), 36) + "-" + Integer.toUnsignedString(exception.hashCode(), 36); } diff --git a/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/JwtAuthentication.java b/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/JwtAuthentication.java index 47f6567..bc6aa03 100644 --- a/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/JwtAuthentication.java +++ b/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/JwtAuthentication.java @@ -17,8 +17,11 @@ public class JwtAuthentication implements Authentication { private final Authentication authentication; private final String token; + private final UserIdsPair userIdsPair; + public JwtAuthentication(Authentication authentication, String userAccountId, String token) { this.userAccountId = userAccountId; + this.userIdsPair = new UserIdsPair(userAccountId); this.authentication = authentication; this.token = token; } @@ -31,6 +34,10 @@ public class JwtAuthentication implements Authentication { return userAccountId; } + public UserIdsPair getUserIdsPair() { + return userIdsPair; + } + @Override public Collection getAuthorities() { return authentication.getAuthorities(); diff --git a/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/UserIdsPair.java b/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/UserIdsPair.java new file mode 100644 index 0000000..e28f8f2 --- /dev/null +++ b/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/UserIdsPair.java @@ -0,0 +1,36 @@ +package ru.micord.ervu.security.webbpm.jwt; + +public class UserIdsPair { + private final String esiaUserId; + private final String ervuId; + + public UserIdsPair(String idsConcatenated) { + + if (idsConcatenated == null) { + this.esiaUserId = null; + this.ervuId = null; + } + else { + String[] ids = idsConcatenated.split(":"); + this.esiaUserId = ids[0]; + this.ervuId = ids.length == 2 ? ids[1] : null; + } + } + + public UserIdsPair(String esiaUserId, String ervuId) { + this.esiaUserId = esiaUserId; + this.ervuId = ervuId; + } + + public String getEsiaUserId() { + return esiaUserId; + } + + public String getErvuId() { + return ervuId; + } + + public String getIdsConcatenated() { + return esiaUserId + (ervuId == null ? "" : ":" + ervuId); + } +} diff --git a/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/service/JwtTokenService.java b/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/service/JwtTokenService.java index aab89b6..a7dc81c 100644 --- a/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/service/JwtTokenService.java +++ b/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/service/JwtTokenService.java @@ -15,6 +15,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import ru.micord.ervu.security.esia.token.EsiaTokensStore; +import ru.micord.ervu.security.webbpm.jwt.UserIdsPair; import ru.micord.ervu.security.webbpm.jwt.model.Token; import ru.cg.webbpm.modules.resources.api.ResourceMetadataUtils; @@ -42,16 +43,17 @@ public class JwtTokenService { } public Token createAccessToken(String userAccountId, Long expiresIn, String ervuId) { + String idsConcatenated = new UserIdsPair(userAccountId, ervuId).getIdsConcatenated(); Date expirationDate = new Date(System.currentTimeMillis() + 1000L * expiresIn); String value = Jwts.builder() - .setSubject(userAccountId + ":" + ervuId) + .setSubject(idsConcatenated) .setIssuer(tokenIssuerName) .setIssuedAt(new Date(System.currentTimeMillis())) .setExpiration(expirationDate) .signWith(SIGNING_KEY) .compact(); - return new Token(userAccountId + ":" + ervuId, tokenIssuerName, expirationDate, value); + return new Token(idsConcatenated, tokenIssuerName, expirationDate, value); } public boolean isValid(Token token) { @@ -64,8 +66,8 @@ public class JwtTokenService { LOGGER.info("Token {} is expired ", token.getValue()); return false; } - String[] ids = token.getUserAccountId().split(":"); - return EsiaTokensStore.validateAccessToken(ids[0]); + String esiaUserId = new UserIdsPair(token.getUserAccountId()).getEsiaUserId(); + return EsiaTokensStore.validateAccessToken(esiaUserId); } public Token getToken(String token) { @@ -89,8 +91,8 @@ public class JwtTokenService { String authToken = extractAuthToken(request); if (authToken != null) { - String[] ids = getToken(authToken).getUserAccountId().split(":"); - return ids[0]; + String esiaUserId = new UserIdsPair(getToken(authToken).getUserAccountId()).getEsiaUserId(); + return esiaUserId; } else { throw new RuntimeException("Failed to get auth data. User unauthorized."); diff --git a/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/util/SecurityUtil.java b/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/util/SecurityUtil.java index ef8555e..d1dcafe 100644 --- a/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/util/SecurityUtil.java +++ b/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/util/SecurityUtil.java @@ -8,6 +8,7 @@ import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.web.util.WebUtils; import ru.micord.ervu.security.webbpm.jwt.JwtAuthentication; +import ru.micord.ervu.security.webbpm.jwt.UserIdsPair; public final class SecurityUtil { public static final String AUTH_TOKEN = "auth_token"; @@ -23,17 +24,13 @@ public final class SecurityUtil { return cookie != null ? cookie.getValue() : null; } - public static String getErvuId() { + public static UserIdsPair getUserIdsPair() { return Optional.ofNullable(SecurityContextHolder.getContext().getAuthentication()) - .map(a -> ((JwtAuthentication) a).getUserAccountId()) - .map(userAccountId -> { - String ervuId = userAccountId.split(":")[1]; - return "null".equals(ervuId) ? null : ervuId; - }) + .map(a -> ((JwtAuthentication) a).getUserIdsPair()) .orElse(null); } - public static String getCurrentUsername() { + public static String getCurrentUserEsiaId() { Authentication auth = SecurityContextHolder.getContext().getAuthentication(); if (auth != null && auth.isAuthenticated()) { return auth.getName(); diff --git a/backend/src/main/java/ru/micord/ervu/service/SubpoenaService.java b/backend/src/main/java/ru/micord/ervu/service/SubpoenaService.java index 438338d..9093bce 100644 --- a/backend/src/main/java/ru/micord/ervu/service/SubpoenaService.java +++ b/backend/src/main/java/ru/micord/ervu/service/SubpoenaService.java @@ -31,7 +31,9 @@ public class SubpoenaService { } public SubpoenaResponseDto getSubpoenaData() { - String ervuId = SecurityUtil.getErvuId(); + String ervuId = SecurityUtil.getUserIdsPair() == null + ? null + : SecurityUtil.getUserIdsPair().getErvuId(); if (ervuId == null) { return new SubpoenaResponseDto.Builder().build(); diff --git a/config.md b/config.md index 0920c80..f82d9cd 100644 --- a/config.md +++ b/config.md @@ -784,7 +784,8 @@ JBPM использует 3 корневых категории логирова - `ERVU_KAFKA_RECRUIT_HEADER_CLASS` - класс для идентификации в заголовке запроса на получение данных о повестке, временных мерах и воинском учете - `ERVU_KAFKA_SUBPOENA_EXTRACT_REQUEST_TOPIC` - топик для отправки запроса на получение выписки из Реестра повесток - `ERVU_KAFKA_SUBPOENA_EXTRACT_REPLY_TOPIC` - топик для получения выписки из Реестра повесток -- `ERVU_KAFKA_REGISTRY_EXTRACT_REQUEST_TOPIC` - топик для отправки запроса на получение выписки из Реестра воинского учета +- `ERVU_KAFKA_REGISTRY_EXTRACT_EMPTY_REQUEST_TOPIC` - топик для отправки запроса на получение выписки из Реестра воинского учета при отсутствии ErvuId +- `ERVU_KAFKA_REGISTRY_EXTRACT_REQUEST_TOPIC` - топик для отправки запроса на получение выписки из Реестра воинского учета при наличии ErvuId - `ERVU_KAFKA_REGISTRY_EXTRACT_REPLY_TOPIC` - топик для получения выписки из Реестра воинского учета - `ERVU_KAFKA_EXTRACT_HEADER_CLASS` - класс для идентификации в заголовке запроса на получение выписки из Реестра повесток/Реестра воинского учета diff --git a/config/local.env b/config/local.env new file mode 100644 index 0000000..65cf00d --- /dev/null +++ b/config/local.env @@ -0,0 +1,39 @@ +TZ=Europe/Moscow + +# App datasource +DB_APP_USERNAME=ervu_lkrp_fl +DB_APP_PASSWORD=ervu_lkrp_fl +DB_APP_HOST=10.10.31.119 +DB_APP_PORT=5432 +DB_APP_NAME=ervu_lkrp_fl + +ESIA_SCOPES=snils, fullname, birthdate, id_doc +ESIA_BASE_URI=https://esia-portal1.test.gosuslugi.ru/ +ESIA_ISSUER_URL=http://esia-portal1.test.gosuslugi.ru/ +ESIA_CLIENT_ID=MNSV93 +ESIA_CLIENT_CERT_HASH=CF35A98C48E48665EA73530537BAFBB51F911C434ADC89215C2F86DCD04E28C5 +ESIA_REDIRECT_URL=http://localhost:8080/ + +SIGN_URL=https://ervu-sign-dev.k8s.micord.ru/sign +SIGN_VERIFY_URL=https://ervu-sign-dev.k8s.micord.ru/verify + +ERVU_KAFKA_BOOTSTRAP_SERVERS=local-kafka:9094 +ERVU_KAFKA_USERNAME=user2 +ERVU_KAFKA_PASSWORD=Blfi9d2OFG +ERVU_KAFKA_SASL_MECHANISM=PLAIN +ERVU_KAFKA_SECURITY_PROTOCOL=PLAINTEXT +ERVU_KAFKA_GROUP_ID=ervu-lkrp-fl-new +ERVU_KAFKA_REPLY_TOPIC=ervu.lkpr.person.search.response +ERVU_KAFKA_REQUEST_TOPIC=ervu.lkpr.person.search.request +ERVU_KAFKA_REPLY_TIMEOUT=5 +ERVU_KAFKA_RECRUIT_REQUEST_TOPIC=ervu.recruit.info.request +ERVU_KAFKA_RECRUIT_REPLY_TOPIC=ervu.recruit.info.response +ERVU_KAFKA_RECRUIT_HEADER_CLASS=Request@urn://rostelekom.ru/RP-SummonsTR/1.0.5 +ERVU_KAFKA_REGISTRY_EXTRACT_EMPTY_REQUEST_TOPIC=ervu.extract.empty.request +ERVU_KAFKA_REGISTRY_EXTRACT_REQUEST_TOPIC=ervu.extract.info.request +ERVU_KAFKA_REGISTRY_EXTRACT_REPLY_TOPIC=ervu.extract.info.response +ERVU_KAFKA_EXTRACT_HEADER_CLASS=request@urn://rostelekom.ru/ERVU-extractFromRegistryTR/1.0.3 +ERVU_KAFKA_DOC_LOGIN_MODULE=org.apache.kafka.common.security.plain.PlainLoginModule + +ESIA_TOKEN_CLEAR_CRON=0 0 */1 * * * +COOKIE_PATH=/fl diff --git a/config/micord.env b/config/micord.env index 4d9a355..99cd3d6 100644 --- a/config/micord.env +++ b/config/micord.env @@ -28,6 +28,7 @@ ERVU_KAFKA_REPLY_TIMEOUT=30 ERVU_KAFKA_RECRUIT_REQUEST_TOPIC=ervu.recruit.info.request ERVU_KAFKA_RECRUIT_REPLY_TOPIC=ervu.recruit.info.response ERVU_KAFKA_RECRUIT_HEADER_CLASS=Request@urn://rostelekom.ru/RP-SummonsTR/1.0.5 +ERVU_KAFKA_REGISTRY_EXTRACT_EMPTY_REQUEST_TOPIC=ervu.extract.empty.request ERVU_KAFKA_REGISTRY_EXTRACT_REQUEST_TOPIC=ervu.extract.info.request ERVU_KAFKA_REGISTRY_EXTRACT_REPLY_TOPIC=ervu.extract.info.response ERVU_KAFKA_EXTRACT_HEADER_CLASS=request@urn://rostelekom.ru/ERVU-extractFromRegistryTR/1.0.3 diff --git a/config/standalone/dev/standalone.xml b/config/standalone/dev/standalone.xml index 1428635..bce507f 100644 --- a/config/standalone/dev/standalone.xml +++ b/config/standalone/dev/standalone.xml @@ -75,6 +75,7 @@ +