Merge branch 'feature/SUPPORT-8817_1_9_5_adding_extract_request_with_empty_ervu_id' into hotfix/1.9.4

# Conflicts:
#	resources/src/main/resources/business-model/LK RP FL/screen-form-fl.page
This commit is contained in:
gulnaz 2025-01-31 11:23:48 +03:00
commit f57847eeea
12 changed files with 144 additions and 25 deletions

View file

@ -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<Object, Bytes> 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<Object, Bytes> replyingKafkaService) {
public ExtractController(PersonalDataService personalDataService, ReplyingKafkaService<Object, Bytes> replyingKafkaService) {
this.personalDataService = personalDataService;
this.replyingKafkaService = replyingKafkaService;
}
@GetMapping(value = "/extract/{formatRegistry}")
public ResponseEntity<Resource> 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);

View file

@ -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) {
}

View file

@ -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);
}

View file

@ -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<? extends GrantedAuthority> getAuthorities() {
return authentication.getAuthorities();

View file

@ -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);
}
}

View file

@ -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.");

View file

@ -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();

View file

@ -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();

View file

@ -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` - класс для идентификации в заголовке запроса на получение выписки из Реестра повесток/Реестра воинского учета

39
config/local.env Normal file
View file

@ -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

View file

@ -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

View file

@ -75,6 +75,7 @@
<property name="ervu.kafka.recruit.request.topic" value="ervu.recruit.info.request"/>
<property name="ervu.kafka.recruit.reply.topic" value="ervu.recruit.info.response"/>
<property name="ervu.kafka.recruit.header.class" value="Request@urn://rostelekom.ru/RP-SummonsTR/1.0.5"/>
<property name="ervu.kafka.registry.extract.empty.request.topic" value="ervu.extract.empty.request"/>
<property name="ervu.kafka.registry.extract.request.topic" value="ervu.extract.info.request"/>
<property name="ervu.kafka.registry.extract.reply.topic" value="ervu.extract.info.response"/>
<property name="ervu.kafka.extract.header.class" value="request@urn://rostelekom.ru/ERVU-extractFromRegistryTR/1.0.3"/>