Merge remote-tracking branch 'origin/hotfix/1.9.8' into feature/SUPPORT-8897_fix_handler
This commit is contained in:
commit
cb6b472268
49 changed files with 1425 additions and 121 deletions
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ru.micord.ervu.lkrp</groupId>
|
||||
<artifactId>fl</artifactId>
|
||||
<version>1.9.5-SNAPSHOT</version>
|
||||
<version>1.9.8-SNAPSHOT</version>
|
||||
</parent>
|
||||
<groupId>ru.micord.ervu.lkrp.fl</groupId>
|
||||
<artifactId>backend</artifactId>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,88 @@
|
|||
package ru.micord.ervu.audit.config;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.kafka.clients.CommonClientConfigs;
|
||||
import org.apache.kafka.clients.admin.AdminClientConfig;
|
||||
import org.apache.kafka.clients.admin.NewTopic;
|
||||
import org.apache.kafka.clients.producer.ProducerConfig;
|
||||
import org.apache.kafka.common.config.SaslConfigs;
|
||||
import org.apache.kafka.common.serialization.StringSerializer;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.kafka.config.TopicBuilder;
|
||||
import org.springframework.kafka.core.DefaultKafkaProducerFactory;
|
||||
import org.springframework.kafka.core.KafkaAdmin;
|
||||
import org.springframework.kafka.core.KafkaTemplate;
|
||||
import org.springframework.kafka.core.ProducerFactory;
|
||||
|
||||
/**
|
||||
* @author Adel Kalimullin
|
||||
*/
|
||||
@Configuration
|
||||
public class AuditKafkaConfig {
|
||||
@Value("${audit.kafka.bootstrap.servers}")
|
||||
private String bootstrapServers;
|
||||
@Value("${audit.kafka.security.protocol}")
|
||||
private String securityProtocol;
|
||||
@Value("${audit.kafka.login.module:org.apache.kafka.common.security.scram.ScramLoginModule}")
|
||||
private String loginModule;
|
||||
@Value("${audit.kafka.username}")
|
||||
private String username;
|
||||
@Value("${audit.kafka.password}")
|
||||
private String password;
|
||||
@Value("${audit.kafka.sasl.mechanism}")
|
||||
private String saslMechanism;
|
||||
@Value("${audit.kafka.authorization.topic}")
|
||||
private String authorizationTopic;
|
||||
@Value("${audit.kafka.action.topic}")
|
||||
private String actionTopic;
|
||||
@Value("${audit.kafka.file.download.topic}")
|
||||
private String fileDownloadTopic;
|
||||
|
||||
@Bean("auditProducerFactory")
|
||||
public ProducerFactory<String, String> producerFactory() {
|
||||
Map<String, Object> configProps = new HashMap<>();
|
||||
configProps.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);
|
||||
configProps.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
|
||||
configProps.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
|
||||
configProps.put(CommonClientConfigs.SECURITY_PROTOCOL_CONFIG, securityProtocol);
|
||||
configProps.put(SaslConfigs.SASL_JAAS_CONFIG, loginModule + " required username=\""
|
||||
+ username + "\" password=\"" + password + "\";");
|
||||
configProps.put(SaslConfigs.SASL_MECHANISM, saslMechanism);
|
||||
return new DefaultKafkaProducerFactory<>(configProps);
|
||||
}
|
||||
|
||||
@Bean("auditTemplate")
|
||||
public KafkaTemplate<String, String> kafkaTemplate() {
|
||||
return new KafkaTemplate<>(producerFactory());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public KafkaAdmin auditKafkaAdmin() {
|
||||
Map<String, Object> configs = new HashMap<>();
|
||||
configs.put(AdminClientConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);
|
||||
configs.put(AdminClientConfig.SECURITY_PROTOCOL_CONFIG, securityProtocol);
|
||||
configs.put(SaslConfigs.SASL_JAAS_CONFIG, loginModule + " required username=\""
|
||||
+ username + "\" password=\"" + password + "\";");
|
||||
configs.put(SaslConfigs.SASL_MECHANISM, saslMechanism);
|
||||
return new KafkaAdmin(configs);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public NewTopic auditAuthTopic() {
|
||||
return TopicBuilder.name(authorizationTopic).build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public NewTopic auditActionTopic() {
|
||||
return TopicBuilder.name(actionTopic).build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public NewTopic auditDownloadTopic() {
|
||||
return TopicBuilder.name(fileDownloadTopic).build();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
package ru.micord.ervu.audit.constants;
|
||||
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @author Adel Kalimullin
|
||||
*/
|
||||
public final class AuditConstants {
|
||||
public static final String SUBSYSTEM_TYPE = "FL";
|
||||
public static final String LOGOUT_EVENT_TYPE = "logout";
|
||||
public static final String LOGIN_EVENT_TYPE = "login";
|
||||
public static final String SUCCESS_STATUS = "success";
|
||||
public static final String FAILURE_STATUS = "failure";
|
||||
|
||||
private static final Map<String, String> routeDescriptions = Map.of(
|
||||
"/", "Главная",
|
||||
"/mydata", "Мои данные",
|
||||
"/subpoena", "Повестки",
|
||||
"/restriction", "Временные меры"
|
||||
);
|
||||
|
||||
private static final Map<String, String> downloadTypes = Map.of(
|
||||
"1", "Выписка из реестра воинского учета ФЛ",
|
||||
"2", "Выписка из реестра повесток ФЛ"
|
||||
);
|
||||
|
||||
public static String getRouteDescription(String route) {
|
||||
return Optional.ofNullable(routeDescriptions.get(route))
|
||||
.orElseThrow(() -> new IllegalArgumentException("Invalid route :" + route));
|
||||
}
|
||||
|
||||
public static String getDownloadType(String formatRegistry) {
|
||||
return Optional.ofNullable(downloadTypes.get(formatRegistry))
|
||||
.orElseThrow(
|
||||
() -> new IllegalArgumentException("Invalid formatRegistry :" + formatRegistry));
|
||||
}
|
||||
|
||||
private AuditConstants() {
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
package ru.micord.ervu.audit.controller;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import ru.micord.ervu.audit.model.AuditActionRequest;
|
||||
import ru.micord.ervu.audit.service.AuditService;
|
||||
|
||||
/**
|
||||
* @author Adel Kalimullin
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/audit")
|
||||
public class AuditController {
|
||||
private final AuditService auditService;
|
||||
|
||||
public AuditController(AuditService auditService) {
|
||||
this.auditService = auditService;
|
||||
}
|
||||
|
||||
@PostMapping("/action")
|
||||
public ResponseEntity<Void> auditAction(HttpServletRequest request,
|
||||
@RequestBody AuditActionRequest actionEvent) {
|
||||
auditService.processActionEvent(request, actionEvent);
|
||||
return ResponseEntity.ok().build();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
package ru.micord.ervu.audit.model;
|
||||
|
||||
/**
|
||||
* @author Adel Kalimullin
|
||||
*/
|
||||
public class AuditActionEvent extends AuditEvent {
|
||||
private String eventType;
|
||||
private String description;
|
||||
private String sourceUrl;
|
||||
private String fileName;
|
||||
|
||||
public AuditActionEvent(
|
||||
String esiaPersonId, String eventTime, String eventType,
|
||||
String description, String sourceUrl, String fileName) {
|
||||
super(esiaPersonId, eventTime);
|
||||
this.eventType = eventType;
|
||||
this.description = description;
|
||||
this.sourceUrl = sourceUrl;
|
||||
this.fileName = fileName;
|
||||
}
|
||||
|
||||
public String getFileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public void setFileName(String fileName) {
|
||||
this.fileName = fileName;
|
||||
}
|
||||
|
||||
public String getEventType() {
|
||||
return eventType;
|
||||
}
|
||||
|
||||
public void setEventType(String eventType) {
|
||||
this.eventType = eventType;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getSourceUrl() {
|
||||
return sourceUrl;
|
||||
}
|
||||
|
||||
public void setSourceUrl(String sourceUrl) {
|
||||
this.sourceUrl = sourceUrl;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
package ru.micord.ervu.audit.model;
|
||||
|
||||
/**
|
||||
* @author Adel Kalimullin
|
||||
*/
|
||||
public class AuditActionRequest {
|
||||
private String route;
|
||||
private String sourceUrl;
|
||||
private String eventType;
|
||||
private String fileName;
|
||||
|
||||
public String getFileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public void setFileName(String fileName) {
|
||||
this.fileName = fileName;
|
||||
}
|
||||
|
||||
public String getRoute() {
|
||||
return route;
|
||||
}
|
||||
|
||||
public void setRoute(String route) {
|
||||
this.route = route;
|
||||
}
|
||||
|
||||
public String getSourceUrl() {
|
||||
return sourceUrl;
|
||||
}
|
||||
|
||||
public void setSourceUrl(String sourceUrl) {
|
||||
this.sourceUrl = sourceUrl;
|
||||
}
|
||||
|
||||
public String getEventType() {
|
||||
return eventType;
|
||||
}
|
||||
|
||||
public void setEventType(String eventType) {
|
||||
this.eventType = eventType;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
package ru.micord.ervu.audit.model;
|
||||
|
||||
|
||||
public class AuditAuthorizationEvent extends AuditEvent {
|
||||
private String status;
|
||||
private String eventType;
|
||||
private String firstName;
|
||||
private String lastName;
|
||||
private String middleName;
|
||||
private String snils;
|
||||
private String serverIp;
|
||||
private String serverHostName;
|
||||
private String clientIp;
|
||||
private String clientHostName;
|
||||
|
||||
public AuditAuthorizationEvent(
|
||||
String esiaPersonId, String eventTime, String firstName,
|
||||
String lastName, String middleName, String snils,
|
||||
String status, String eventType, String serverIp,
|
||||
String serverHostName, String clientIp, String clientHostName) {
|
||||
super(esiaPersonId, eventTime);
|
||||
this.status = status;
|
||||
this.firstName = firstName;
|
||||
this.lastName = lastName;
|
||||
this.middleName = middleName;
|
||||
this.snils = snils;
|
||||
this.eventType = eventType;
|
||||
this.serverIp = serverIp;
|
||||
this.serverHostName = serverHostName;
|
||||
this.clientIp = clientIp;
|
||||
this.clientHostName = clientHostName;
|
||||
}
|
||||
|
||||
public String getFirstName() {
|
||||
return firstName;
|
||||
}
|
||||
|
||||
public void setFirstName(String firstName) {
|
||||
this.firstName = firstName;
|
||||
}
|
||||
|
||||
public String getLastName() {
|
||||
return lastName;
|
||||
}
|
||||
|
||||
public void setLastName(String lastName) {
|
||||
this.lastName = lastName;
|
||||
}
|
||||
|
||||
public String getMiddleName() {
|
||||
return middleName;
|
||||
}
|
||||
|
||||
public void setMiddleName(String middleName) {
|
||||
this.middleName = middleName;
|
||||
}
|
||||
|
||||
public String getSnils() {
|
||||
return snils;
|
||||
}
|
||||
|
||||
public void setSnils(String snils) {
|
||||
this.snils = snils;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(String status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public String getEventType() {
|
||||
return eventType;
|
||||
}
|
||||
|
||||
public void setEventType(String eventType) {
|
||||
this.eventType = eventType;
|
||||
}
|
||||
|
||||
public String getServerIp() {
|
||||
return serverIp;
|
||||
}
|
||||
|
||||
public void setServerIp(String serverIp) {
|
||||
this.serverIp = serverIp;
|
||||
}
|
||||
|
||||
public String getServerHostName() {
|
||||
return serverHostName;
|
||||
}
|
||||
|
||||
public void setServerHostName(String serverHostName) {
|
||||
this.serverHostName = serverHostName;
|
||||
}
|
||||
|
||||
public String getClientIp() {
|
||||
return clientIp;
|
||||
}
|
||||
|
||||
public void setClientIp(String clientIp) {
|
||||
this.clientIp = clientIp;
|
||||
}
|
||||
|
||||
public String getClientHostName() {
|
||||
return clientHostName;
|
||||
}
|
||||
|
||||
public void setClientHostName(String clientHostName) {
|
||||
this.clientHostName = clientHostName;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
package ru.micord.ervu.audit.model;
|
||||
|
||||
|
||||
/**
|
||||
* @author Adel Kalimullin
|
||||
*/
|
||||
public class AuditDownloadEvent extends AuditEvent {
|
||||
private String downloadType;
|
||||
private String fileName;
|
||||
private String s3FileUrl;
|
||||
private String fileSize;
|
||||
private String status;
|
||||
|
||||
public AuditDownloadEvent(
|
||||
String esiaPersonId, String eventTime, String downloadType,
|
||||
String fileName, String s3FileUrl, String fileSize,
|
||||
String status) {
|
||||
super(esiaPersonId, eventTime);
|
||||
this.downloadType = downloadType;
|
||||
this.fileName = fileName;
|
||||
this.s3FileUrl = s3FileUrl;
|
||||
this.fileSize = fileSize;
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public String getS3FileUrl() {
|
||||
return s3FileUrl;
|
||||
}
|
||||
|
||||
public void setS3FileUrl(String s3FileUrl) {
|
||||
this.s3FileUrl = s3FileUrl;
|
||||
}
|
||||
|
||||
public String getDownloadType() {
|
||||
return downloadType;
|
||||
}
|
||||
|
||||
public void setDownloadType(String downloadType) {
|
||||
this.downloadType = downloadType;
|
||||
}
|
||||
|
||||
public String getFileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public void setFileName(String fileName) {
|
||||
this.fileName = fileName;
|
||||
}
|
||||
|
||||
public String getFileSize() {
|
||||
return fileSize;
|
||||
}
|
||||
|
||||
public void setFileSize(String fileSize) {
|
||||
this.fileSize = fileSize;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(String status) {
|
||||
this.status = status;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
package ru.micord.ervu.audit.model;
|
||||
|
||||
import ru.micord.ervu.audit.constants.AuditConstants;
|
||||
|
||||
/**
|
||||
* @author Adel Kalimullin
|
||||
*/
|
||||
|
||||
public abstract class AuditEvent {
|
||||
protected final String subsystem = AuditConstants.SUBSYSTEM_TYPE;
|
||||
protected String esiaPersonId;
|
||||
protected String eventTime;
|
||||
|
||||
protected AuditEvent(String esiaPersonId, String eventTime) {
|
||||
this.esiaPersonId = esiaPersonId;
|
||||
this.eventTime = eventTime;
|
||||
}
|
||||
|
||||
public String getEsiaPersonId() {
|
||||
return esiaPersonId;
|
||||
}
|
||||
|
||||
public void setEsiaPersonId(String esiaPersonId) {
|
||||
this.esiaPersonId = esiaPersonId;
|
||||
}
|
||||
|
||||
public String getSubsystem() {
|
||||
return subsystem;
|
||||
}
|
||||
|
||||
public String getEventTime() {
|
||||
return eventTime;
|
||||
}
|
||||
|
||||
public void setEventTime(String eventTime) {
|
||||
this.eventTime = eventTime;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
package ru.micord.ervu.audit.service;
|
||||
|
||||
/**
|
||||
* @author Adel Kalimullin
|
||||
*/
|
||||
public interface AuditKafkaPublisher {
|
||||
void publishEvent(String topicName, String message);
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
package ru.micord.ervu.audit.service;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import ru.micord.ervu.audit.model.AuditActionRequest;
|
||||
import ru.micord.ervu.security.esia.model.PersonModel;
|
||||
|
||||
/**
|
||||
* @author Adel Kalimullin
|
||||
*/
|
||||
public interface AuditService {
|
||||
void processActionEvent(HttpServletRequest request, AuditActionRequest auditActionRequest);
|
||||
|
||||
void processAuthEvent(HttpServletRequest request, PersonModel personModel, String status,
|
||||
String eventType);
|
||||
|
||||
void processDownloadEvent(HttpServletRequest request, int fileSize, String fileName,
|
||||
String formatRegistry, String status);
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
package ru.micord.ervu.audit.service.impl;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.kafka.core.KafkaTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
import ru.micord.ervu.audit.service.AuditKafkaPublisher;
|
||||
|
||||
/**
|
||||
* @author Adel Kalimullin
|
||||
*/
|
||||
@Service
|
||||
public class BaseAuditKafkaPublisher implements AuditKafkaPublisher {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(BaseAuditKafkaPublisher.class);
|
||||
private final KafkaTemplate<String, String> kafkaTemplate;
|
||||
@Value("${audit.kafka.enabled}")
|
||||
private boolean auditEnabled;
|
||||
|
||||
public BaseAuditKafkaPublisher(
|
||||
@Qualifier("auditTemplate") KafkaTemplate<String, String> kafkaTemplate) {
|
||||
this.kafkaTemplate = kafkaTemplate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void publishEvent(String topic, String message) {
|
||||
if (auditEnabled) {
|
||||
kafkaTemplate.send(topic, message)
|
||||
.addCallback(
|
||||
result -> {
|
||||
},
|
||||
ex -> LOGGER.error("Failed to send message to topic {}: {}", topic, ex.getMessage(),
|
||||
ex
|
||||
)
|
||||
);
|
||||
}
|
||||
else {
|
||||
LOGGER.info("Audit is disabled. Event not published.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
package ru.micord.ervu.audit.service.impl;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import ru.micord.ervu.audit.constants.AuditConstants;
|
||||
import ru.micord.ervu.audit.model.AuditActionEvent;
|
||||
import ru.micord.ervu.audit.model.AuditActionRequest;
|
||||
import ru.micord.ervu.audit.model.AuditAuthorizationEvent;
|
||||
import ru.micord.ervu.audit.model.AuditDownloadEvent;
|
||||
import ru.micord.ervu.audit.service.AuditKafkaPublisher;
|
||||
import ru.micord.ervu.audit.service.AuditService;
|
||||
import ru.micord.ervu.security.esia.model.PersonModel;
|
||||
import ru.micord.ervu.security.webbpm.jwt.service.JwtTokenService;
|
||||
import ru.micord.ervu.util.DateUtils;
|
||||
import ru.micord.ervu.util.NetworkUtils;
|
||||
|
||||
/**
|
||||
* @author Adel Kalimullin
|
||||
*/
|
||||
@Service
|
||||
public class BaseAuditService implements AuditService {
|
||||
private final AuditKafkaPublisher auditPublisher;
|
||||
private final JwtTokenService jwtTokenService;
|
||||
private final ObjectMapper objectMapper;
|
||||
@Value("${audit.kafka.authorization.topic}")
|
||||
private String authorizationTopic;
|
||||
@Value("${audit.kafka.action.topic}")
|
||||
private String actionTopic;
|
||||
@Value("${audit.kafka.file.download.topic}")
|
||||
private String fileDownloadTopic;
|
||||
|
||||
public BaseAuditService(AuditKafkaPublisher auditPublisher, JwtTokenService jwtTokenService,
|
||||
ObjectMapper objectMapper) {
|
||||
this.auditPublisher = auditPublisher;
|
||||
this.jwtTokenService = jwtTokenService;
|
||||
this.objectMapper = objectMapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processActionEvent(
|
||||
HttpServletRequest request, AuditActionRequest auditActionRequest) {
|
||||
String userAccountId = jwtTokenService.getUserAccountId(request);
|
||||
String description = AuditConstants.getRouteDescription(auditActionRequest.getRoute());
|
||||
|
||||
AuditActionEvent event = new AuditActionEvent(
|
||||
userAccountId,
|
||||
DateUtils.getClientTimeFromRequest(request),
|
||||
auditActionRequest.getEventType(),
|
||||
description,
|
||||
auditActionRequest.getSourceUrl(),
|
||||
auditActionRequest.getFileName()
|
||||
);
|
||||
String message = convertToMessage(event);
|
||||
auditPublisher.publishEvent(actionTopic, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processAuthEvent(HttpServletRequest request, PersonModel personModel, String status,
|
||||
String eventType) {
|
||||
String serverIp = NetworkUtils.getServerIp();
|
||||
String clientIp = NetworkUtils.getClientIp(request);
|
||||
String serverHostName = NetworkUtils.getHostName(serverIp);
|
||||
String clientHostName = NetworkUtils.getHostName(clientIp);
|
||||
|
||||
AuditAuthorizationEvent event = new AuditAuthorizationEvent(
|
||||
personModel.getPrnsId(),
|
||||
DateUtils.getClientTimeFromRequest(request),
|
||||
personModel.getFirstName(),
|
||||
personModel.getLastName(),
|
||||
personModel.getMiddleName(),
|
||||
personModel.getSnils(),
|
||||
status,
|
||||
eventType,
|
||||
serverIp,
|
||||
serverHostName,
|
||||
clientIp,
|
||||
clientHostName
|
||||
);
|
||||
String message = convertToMessage(event);
|
||||
auditPublisher.publishEvent(authorizationTopic, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processDownloadEvent(
|
||||
HttpServletRequest request, int fileSize, String fileName, String formatRegistry,
|
||||
String status) {
|
||||
String userAccountId = jwtTokenService.getUserAccountId(request);
|
||||
|
||||
AuditDownloadEvent event = new AuditDownloadEvent(
|
||||
userAccountId,
|
||||
DateUtils.getClientTimeFromRequest(request),
|
||||
AuditConstants.getDownloadType(formatRegistry),
|
||||
fileName,
|
||||
null,
|
||||
String.valueOf(fileSize),
|
||||
status
|
||||
);
|
||||
String message = convertToMessage(event);
|
||||
auditPublisher.publishEvent(fileDownloadTopic, message);
|
||||
}
|
||||
|
||||
private String convertToMessage(Object event) {
|
||||
try {
|
||||
return objectMapper.writeValueAsString(event);
|
||||
}
|
||||
catch (JsonProcessingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,9 +2,11 @@ package ru.micord.ervu.controller;
|
|||
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
|
||||
import com.google.protobuf.ByteString;
|
||||
import com.google.protobuf.InvalidProtocolBufferException;
|
||||
import org.apache.kafka.clients.consumer.ConsumerRecord;
|
||||
import org.apache.kafka.common.utils.Bytes;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.core.io.InputStreamResource;
|
||||
|
|
@ -15,10 +17,13 @@ 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.RestController;
|
||||
import rtl.pgs.ervu.proto.ExtractRegistry;
|
||||
import rtl.pgs.ervu.proto.ResponseData;
|
||||
import ru.micord.ervu.audit.constants.AuditConstants;
|
||||
import ru.micord.ervu.audit.service.AuditService;
|
||||
import ru.micord.ervu.dto.ExtractEmptyRequestDto;
|
||||
import ru.micord.ervu.dto.ExtractRequestDto;
|
||||
import ru.micord.ervu.kafka.dto.EmptyExtract;
|
||||
import ru.micord.ervu.kafka.dto.Extract;
|
||||
import ru.micord.ervu.kafka.dto.FullExtract;
|
||||
import ru.micord.ervu.kafka.service.ReplyingKafkaService;
|
||||
import ru.micord.ervu.security.esia.model.PersonModel;
|
||||
import ru.micord.ervu.security.esia.service.PersonalDataService;
|
||||
|
|
@ -26,6 +31,8 @@ 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;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* @author gulnaz
|
||||
*/
|
||||
|
|
@ -33,6 +40,7 @@ import ru.micord.ervu.security.webbpm.jwt.util.SecurityUtil;
|
|||
public class ExtractController {
|
||||
private final PersonalDataService personalDataService;
|
||||
private final ReplyingKafkaService<Object, Bytes> replyingKafkaService;
|
||||
private final AuditService auditService;
|
||||
|
||||
@Value("${ervu.kafka.registry.extract.empty.request.topic}")
|
||||
private String registryExtractEmptyRequestTopic;
|
||||
|
|
@ -40,33 +48,38 @@ public class ExtractController {
|
|||
private String registryExtractRequestTopic;
|
||||
@Value("${ervu.kafka.registry.extract.reply.topic}")
|
||||
private String registryExtractReplyTopic;
|
||||
@Value("${ervu.kafka.registry.extract.type.header:empty}")
|
||||
private String registryExtractTypeHeader;
|
||||
|
||||
public ExtractController(PersonalDataService personalDataService, ReplyingKafkaService<Object, Bytes> replyingKafkaService) {
|
||||
public ExtractController(
|
||||
PersonalDataService personalDataService,
|
||||
ReplyingKafkaService<Object, Bytes> replyingKafkaService,
|
||||
AuditService auditService
|
||||
) {
|
||||
this.personalDataService = personalDataService;
|
||||
this.replyingKafkaService = replyingKafkaService;
|
||||
this.auditService = auditService;
|
||||
}
|
||||
|
||||
@GetMapping(value = "/extract/{formatRegistry}")
|
||||
public ResponseEntity<Resource> getExtract(@PathVariable String formatRegistry) {
|
||||
public ResponseEntity<Resource> getExtract(HttpServletRequest servletRequest, @PathVariable String formatRegistry) {
|
||||
UserIdsPair userIdsPair = SecurityUtil.getUserIdsPair();
|
||||
String ervuId = userIdsPair.getErvuId();
|
||||
String fileName;
|
||||
ByteString file;
|
||||
ConsumerRecord<String, Bytes> record;
|
||||
boolean isEmpty = true;
|
||||
|
||||
try {
|
||||
if (ervuId != null) {
|
||||
ExtractRequestDto request = new ExtractRequestDto(ervuId, formatRegistry);
|
||||
byte[] reply = replyingKafkaService.sendMessageAndGetReply(registryExtractRequestTopic,
|
||||
registryExtractReplyTopic, request).get();
|
||||
ResponseData responseData = ResponseData.parseFrom(reply);
|
||||
ExtractRegistry extractRegistry = responseData.getDataRegistryInformation()
|
||||
.getExtractRegistry();
|
||||
fileName = extractRegistry.getFileName();
|
||||
file = extractRegistry.getFile();
|
||||
|
||||
record = replyingKafkaService.sendMessageAndGetReply(
|
||||
registryExtractRequestTopic, registryExtractReplyTopic, request);
|
||||
isEmpty = Arrays.stream(record.headers().toArray())
|
||||
.filter(header -> header.key().equals(registryExtractTypeHeader))
|
||||
.findFirst()
|
||||
.map(header -> Boolean.parseBoolean(new String(header.value(), StandardCharsets.UTF_8)))
|
||||
.orElseThrow();
|
||||
}
|
||||
else {
|
||||
String esiaUserId = userIdsPair.getEsiaUserId(); // esiaUserid is not null here
|
||||
String esiaUserId = userIdsPair.getEsiaUserId(); // esiaUserId is not null here
|
||||
String esiaAccessToken = EsiaTokensStore.getAccessToken(esiaUserId);
|
||||
PersonModel personModel = personalDataService.getPersonModel(esiaAccessToken);
|
||||
|
||||
|
|
@ -75,24 +88,32 @@ public class ExtractController {
|
|||
personModel.getFirstName(), personModel.getMiddleName(), personModel.getBirthDate(),
|
||||
personModel.getSnils(), formatRegistry
|
||||
);
|
||||
byte[] reply = replyingKafkaService.sendMessageAndGetReply(registryExtractEmptyRequestTopic,
|
||||
registryExtractReplyTopic, emptyRequest).get();
|
||||
rtl.pgs.ervu.proto.emptyrequest.ResponseData responseData = rtl.pgs.ervu.proto.emptyrequest.ResponseData
|
||||
.parseFrom(reply);
|
||||
rtl.pgs.ervu.proto.emptyrequest.ExtractRegistry extractRegistry = responseData.getDataRegistryInformation()
|
||||
.getExtractRegistry();
|
||||
fileName = extractRegistry.getFileName();
|
||||
file = extractRegistry.getFile();
|
||||
record = replyingKafkaService.sendMessageAndGetReply(registryExtractEmptyRequestTopic,
|
||||
registryExtractReplyTopic, emptyRequest);
|
||||
}
|
||||
byte[] bytes = record.value().get();
|
||||
String fileName = null;
|
||||
int size = 0;
|
||||
|
||||
try {
|
||||
Extract extract = ervuId == null || isEmpty ? new EmptyExtract(bytes) : new FullExtract(bytes);
|
||||
fileName = extract.getFileName();
|
||||
String encodedFilename = URLEncoder.encode(fileName, StandardCharsets.UTF_8);
|
||||
ByteString file = extract.getFile();
|
||||
InputStreamResource resource = new InputStreamResource(file.newInput());
|
||||
size = file.size();
|
||||
auditService.processDownloadEvent(servletRequest, size, fileName, formatRegistry,
|
||||
AuditConstants.SUCCESS_STATUS
|
||||
);
|
||||
return ResponseEntity.ok()
|
||||
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename*=UTF-8''" + encodedFilename)
|
||||
.contentType(MediaType.APPLICATION_OCTET_STREAM)
|
||||
.body(resource);
|
||||
}
|
||||
catch (InvalidProtocolBufferException e) {
|
||||
auditService.processDownloadEvent(servletRequest, size, fileName, formatRegistry,
|
||||
AuditConstants.FAILURE_STATUS
|
||||
);
|
||||
throw new RuntimeException("Failed to parse data", e);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,15 +10,14 @@ import proto.ervu.rp.summons.RecruitmentInfo;
|
|||
import ru.micord.ervu.dto.Restriction;
|
||||
import ru.micord.ervu.dto.SubpoenaResponseDto;
|
||||
import org.springframework.stereotype.Component;
|
||||
import proto.ervu.rp.summons.MeasuresTemporary;
|
||||
import proto.ervu.rp.summons.ResponseDataAddress;
|
||||
import proto.ervu.rp.summons.SummonsInfo;
|
||||
import proto.ervu.rp.summons.SummonsResponseData;
|
||||
|
||||
import static ru.micord.ervu.util.DateUtil.convertToLocalDate;
|
||||
import static ru.micord.ervu.util.DateUtils.convertToLocalDate;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
import static ru.micord.ervu.util.DateUtil.convertToString;
|
||||
import static ru.micord.ervu.util.DateUtil.getDaysTill;
|
||||
import static ru.micord.ervu.util.DateUtils.convertToString;
|
||||
import static ru.micord.ervu.util.DateUtils.getDaysTill;
|
||||
|
||||
/**
|
||||
* @author gulnaz
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
|
||||
import static org.springframework.util.StringUtils.hasText;
|
||||
import static ru.micord.ervu.util.DateUtil.convertToLocalDate;
|
||||
import static ru.micord.ervu.util.DateUtil.convertToString;
|
||||
import static ru.micord.ervu.util.DateUtils.convertToLocalDate;
|
||||
import static ru.micord.ervu.util.DateUtils.convertToString;
|
||||
|
||||
/**
|
||||
* @author gulnaz
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
package ru.micord.ervu.kafka.dto;
|
||||
|
||||
import com.google.protobuf.InvalidProtocolBufferException;
|
||||
import rtl.pgs.ervu.proto.emptyrequest.ExtractRegistry;
|
||||
import rtl.pgs.ervu.proto.emptyrequest.ResponseData;
|
||||
|
||||
/**
|
||||
* @author gulnaz
|
||||
*/
|
||||
public class EmptyExtract extends Extract {
|
||||
|
||||
public EmptyExtract(byte[] bytes) throws InvalidProtocolBufferException {
|
||||
ResponseData responseData = ResponseData.parseFrom(bytes);
|
||||
ExtractRegistry extractRegistry = responseData.getDataRegistryInformation()
|
||||
.getExtractRegistry();
|
||||
fileName = extractRegistry.getFileName();
|
||||
file = extractRegistry.getFile();
|
||||
}
|
||||
}
|
||||
20
backend/src/main/java/ru/micord/ervu/kafka/dto/Extract.java
Normal file
20
backend/src/main/java/ru/micord/ervu/kafka/dto/Extract.java
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
package ru.micord.ervu.kafka.dto;
|
||||
|
||||
import com.google.protobuf.ByteString;
|
||||
|
||||
/**
|
||||
* @author gulnaz
|
||||
*/
|
||||
public abstract class Extract {
|
||||
|
||||
protected String fileName;
|
||||
protected ByteString file;
|
||||
|
||||
public String getFileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public ByteString getFile() {
|
||||
return file;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
package ru.micord.ervu.kafka.dto;
|
||||
|
||||
import com.google.protobuf.InvalidProtocolBufferException;
|
||||
import rtl.pgs.ervu.proto.ExtractRegistry;
|
||||
import rtl.pgs.ervu.proto.ResponseData;
|
||||
|
||||
/**
|
||||
* @author gulnaz
|
||||
*/
|
||||
public class FullExtract extends Extract {
|
||||
|
||||
public FullExtract(byte[] bytes) throws InvalidProtocolBufferException {
|
||||
ResponseData responseData = ResponseData.parseFrom(bytes);
|
||||
ExtractRegistry extractRegistry = responseData.getDataRegistryInformation()
|
||||
.getExtractRegistry();
|
||||
fileName = extractRegistry.getFileName();
|
||||
file = extractRegistry.getFile();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package ru.micord.ervu.kafka.exception;
|
||||
|
||||
import org.springframework.context.support.MessageSourceAccessor;
|
||||
|
||||
import ru.cg.webbpm.modules.core.runtime.api.LocalizedException;
|
||||
import ru.cg.webbpm.modules.core.runtime.api.MessageBundleUtils;
|
||||
|
||||
/**
|
||||
* @author Emir Suleimanov
|
||||
*/
|
||||
public class KafkaMessageReplyTimeoutException extends LocalizedException {
|
||||
private static final MessageSourceAccessor MESSAGE_SOURCE = MessageBundleUtils.createAccessor("messages/common_errors_messages");
|
||||
private static final String KAFKA_REPLY_TIMEOUT = "kafka_reply_timeout";
|
||||
|
||||
public KafkaMessageReplyTimeoutException(Throwable cause) {
|
||||
super(KAFKA_REPLY_TIMEOUT, MESSAGE_SOURCE, cause);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +1,10 @@
|
|||
package ru.micord.ervu.kafka.service;
|
||||
|
||||
import org.apache.kafka.clients.consumer.ConsumerRecord;
|
||||
|
||||
public interface ReplyingKafkaService<T, V> {
|
||||
|
||||
V sendMessageAndGetReply(String requestTopic,
|
||||
ConsumerRecord<String, V> sendMessageAndGetReply(String requestTopic,
|
||||
String replyTopic,
|
||||
T requestMessage);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import org.slf4j.Logger;
|
|||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.kafka.requestreply.ReplyingKafkaTemplate;
|
||||
import org.springframework.kafka.requestreply.RequestReplyFuture;
|
||||
import ru.micord.ervu.kafka.exception.KafkaMessageReplyTimeoutException;
|
||||
import ru.micord.ervu.kafka.service.ReplyingKafkaService;
|
||||
|
||||
/**
|
||||
|
|
@ -19,14 +20,13 @@ public abstract class BaseReplyingKafkaService<T, V> implements ReplyingKafkaSer
|
|||
private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||
|
||||
@Override
|
||||
public V sendMessageAndGetReply(String requestTopic, String replyTopic, T requestMessage) {
|
||||
public ConsumerRecord<String, V> sendMessageAndGetReply(String requestTopic, String replyTopic, T requestMessage) {
|
||||
long startTime = System.currentTimeMillis();
|
||||
RequestReplyFuture<String, T, V> replyFuture = getTemplate().sendAndReceive(
|
||||
getProducerRecord(requestTopic, replyTopic, requestMessage));
|
||||
|
||||
try {
|
||||
V result = Optional.ofNullable(replyFuture.get())
|
||||
.map(ConsumerRecord::value)
|
||||
ConsumerRecord<String, V> result = Optional.ofNullable(replyFuture.get())
|
||||
.orElseThrow(() -> new RuntimeException("Kafka return result is null"));
|
||||
LOGGER.info("Thread {} - KafkaSendMessageAndGetReply: {} ms",
|
||||
Thread.currentThread().getId(), System.currentTimeMillis() - startTime);
|
||||
|
|
@ -35,7 +35,7 @@ public abstract class BaseReplyingKafkaService<T, V> implements ReplyingKafkaSer
|
|||
catch (InterruptedException | ExecutionException e) {
|
||||
LOGGER.error("Thread {} - KafkaSendMessageAndGetReply: {} ms",
|
||||
Thread.currentThread().getId(), System.currentTimeMillis() - startTime);
|
||||
throw new RuntimeException("Failed to get kafka response", e);
|
||||
throw new KafkaMessageReplyTimeoutException(e);
|
||||
}
|
||||
}
|
||||
protected abstract ReplyingKafkaTemplate<String, T, V> getTemplate();
|
||||
|
|
|
|||
|
|
@ -39,10 +39,10 @@ public class EsiaController {
|
|||
}
|
||||
|
||||
@GetMapping(value = "/esia/auth")
|
||||
public ResponseEntity<?> esiaAuth(@RequestParam(value = "code", required = false) String code,
|
||||
public void esiaAuth(@RequestParam(value = "code", required = false) String code,
|
||||
@RequestParam(value = "error", required = false) String error, HttpServletRequest request,
|
||||
HttpServletResponse response) {
|
||||
return esiaAuthService.getEsiaTokensByCode(code, error, request, response);
|
||||
esiaAuthService.authEsiaTokensByCode(code, error, request, response);
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/esia/refresh")
|
||||
|
|
|
|||
|
|
@ -24,9 +24,10 @@ import org.slf4j.Logger;
|
|||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.context.support.MessageSourceAccessor;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import ru.micord.ervu.audit.constants.AuditConstants;
|
||||
import ru.micord.ervu.audit.service.AuditService;
|
||||
import ru.micord.ervu.kafka.model.Document;
|
||||
import ru.micord.ervu.kafka.model.Person;
|
||||
import ru.micord.ervu.kafka.model.Response;
|
||||
|
|
@ -50,6 +51,7 @@ 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.getCurrentUserEsiaId;
|
||||
import ru.cg.webbpm.modules.core.runtime.api.MessageBundleUtils;
|
||||
|
||||
/**
|
||||
* @author Eduard Tihomirov
|
||||
|
|
@ -57,7 +59,8 @@ import static ru.micord.ervu.security.webbpm.jwt.util.SecurityUtil.getCurrentUse
|
|||
@Service
|
||||
public class EsiaAuthService {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||
|
||||
private static final MessageSourceAccessor MESSAGE_SOURCE = MessageBundleUtils.createAccessor(
|
||||
"messages/common_errors_messages");
|
||||
@Autowired
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
|
|
@ -74,6 +77,9 @@ public class EsiaAuthService {
|
|||
@Autowired
|
||||
private PersonalDataService personalDataService;
|
||||
|
||||
@Autowired
|
||||
private AuditService auditService;
|
||||
|
||||
@Autowired
|
||||
private SecurityHelper securityHelper;
|
||||
|
||||
|
|
@ -151,13 +157,10 @@ public class EsiaAuthService {
|
|||
return uriBuilder.toString();
|
||||
}
|
||||
|
||||
public ResponseEntity<?> getEsiaTokensByCode(String esiaAuthCode, String error,
|
||||
public void authEsiaTokensByCode(String esiaAuthCode, String error,
|
||||
HttpServletRequest request, HttpServletResponse response) {
|
||||
if (error != null && !error.equals("null")) {
|
||||
return new ResponseEntity<>(
|
||||
"Произошла неизвестная ошибка. Обратитесь к системному администратору",
|
||||
HttpStatus.FORBIDDEN
|
||||
);
|
||||
throw new EsiaException(error);
|
||||
}
|
||||
String esiaAccessTokenStr = null;
|
||||
String prnOid = null;
|
||||
|
|
@ -239,22 +242,27 @@ public class EsiaAuthService {
|
|||
Thread.currentThread().getId(), signSecret, requestAccessToken, verifySecret);
|
||||
}
|
||||
PersonModel personModel = null;
|
||||
String ervuId = null, status = null;
|
||||
try {
|
||||
personModel = personalDataService.getPersonModel(esiaAccessTokenStr);
|
||||
Response ervuIdResponse = getErvuIdResponse(personModel);
|
||||
createTokenAndAddCookie(response, prnOid, ervuIdResponse.getErvuId(), expiresIn);
|
||||
return ResponseEntity.ok("Authentication successful");
|
||||
ervuId = ervuIdResponse.getErvuId();
|
||||
status = AuditConstants.SUCCESS_STATUS;
|
||||
}
|
||||
catch (Exception e) {
|
||||
createTokenAndAddCookie(response, prnOid, null, expiresIn);
|
||||
String messageId = getMessageId(e);
|
||||
String messageWithId = String.format("[%s] %s", messageId, e.getMessage());
|
||||
LOGGER.error(messageWithId, e);
|
||||
return new ResponseEntity<>(
|
||||
"Произошла ошибка " + messageId + ". Обратитесь к системному администратору",
|
||||
HttpStatus.FORBIDDEN
|
||||
status = AuditConstants.FAILURE_STATUS;
|
||||
if (e instanceof EsiaException || e instanceof JsonProcessingException) {
|
||||
throw new EsiaException(e);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if (personModel != null) {
|
||||
auditService.processAuthEvent(
|
||||
request, personModel, status, AuditConstants.LOGIN_EVENT_TYPE
|
||||
);
|
||||
}
|
||||
createTokenAndAddCookie(response, prnOid, ervuId, expiresIn);
|
||||
}
|
||||
}
|
||||
|
||||
public void getEsiaTokensByRefreshToken(HttpServletRequest request, HttpServletResponse response) {
|
||||
|
|
@ -359,9 +367,12 @@ public class EsiaAuthService {
|
|||
}
|
||||
|
||||
public String logout(HttpServletRequest request, HttpServletResponse response) {
|
||||
PersonModel personModel = null;
|
||||
try {
|
||||
securityHelper.clearAccessCookies(response);
|
||||
String userId = jwtTokenService.getUserAccountId(request);
|
||||
String accessToken = EsiaTokensStore.getAccessToken(userId);
|
||||
personModel = personalDataService.getPersonModel(accessToken);
|
||||
securityHelper.clearAccessCookies(response);
|
||||
EsiaTokensStore.removeAccessToken(userId);
|
||||
EsiaTokensStore.removeRefreshToken(userId);
|
||||
String logoutUrl = esiaConfig.getEsiaBaseUri() + esiaConfig.getEsiaLogoutUrl();
|
||||
|
|
@ -369,10 +380,19 @@ public class EsiaAuthService {
|
|||
URL url = new URL(logoutUrl);
|
||||
Map<String, String> params = mapOf(
|
||||
"client_id", esiaConfig.getClientId(),
|
||||
"redirect_url", redirectUrl);
|
||||
"redirect_url", redirectUrl
|
||||
);
|
||||
auditService.processAuthEvent(
|
||||
request, personModel, AuditConstants.SUCCESS_STATUS, AuditConstants.LOGOUT_EVENT_TYPE
|
||||
);
|
||||
return buildUrl(url, params);
|
||||
}
|
||||
catch (Exception e) {
|
||||
if (personModel != null){
|
||||
auditService.processAuthEvent(
|
||||
request, personModel, AuditConstants.FAILURE_STATUS, AuditConstants.LOGOUT_EVENT_TYPE
|
||||
);
|
||||
}
|
||||
throw new EsiaException(e);
|
||||
}
|
||||
}
|
||||
|
|
@ -381,7 +401,7 @@ public class EsiaAuthService {
|
|||
Person person = copyToPerson(personModel);
|
||||
String kafkaResponse = replyingKafkaService.sendMessageAndGetReply(requestTopic,
|
||||
requestReplyTopic, objectMapper.writeValueAsString(person)
|
||||
);
|
||||
).value();
|
||||
return objectMapper.readValue(kafkaResponse, Response.class);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ public class SubpoenaService {
|
|||
}
|
||||
SubpoenaRequestDto subpoenaRequestDto = new SubpoenaRequestDto(ervuId);
|
||||
byte[] reply = replyingKafkaService.sendMessageAndGetReply(recruitRequestTopic,
|
||||
recruitReplyTopic, subpoenaRequestDto).get();
|
||||
recruitReplyTopic, subpoenaRequestDto).value().get();
|
||||
|
||||
try {
|
||||
SummonsResponseData responseData = SummonsResponseData.parseFrom(reply);
|
||||
|
|
|
|||
|
|
@ -1,19 +1,39 @@
|
|||
package ru.micord.ervu.util;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* @author gulnaz
|
||||
*/
|
||||
public final class DateUtil {
|
||||
public final class DateUtils {
|
||||
|
||||
public static final DateTimeFormatter DEFAULT_FORMATTER = DateTimeFormatter.ofPattern("dd.MM.yyyy");
|
||||
|
||||
private DateUtil() {}
|
||||
private static final DateTimeFormatter DATE_TIME_WITH_TIMEZONE_FORMATTER =
|
||||
DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSX");
|
||||
|
||||
private DateUtils() {
|
||||
}
|
||||
|
||||
public static String getClientTimeFromRequest(HttpServletRequest request) {
|
||||
String clientTimeZone = request.getHeader("Client-Time-Zone");
|
||||
ZoneId zoneId;
|
||||
try {
|
||||
zoneId = ZoneId.of(clientTimeZone);
|
||||
}
|
||||
catch (Exception e) {
|
||||
zoneId = ZoneId.systemDefault();
|
||||
}
|
||||
return ZonedDateTime.now(zoneId).format(DATE_TIME_WITH_TIMEZONE_FORMATTER);
|
||||
}
|
||||
|
||||
public static LocalDate convertToLocalDate(String date) {
|
||||
return StringUtils.hasText(date)
|
||||
53
backend/src/main/java/ru/micord/ervu/util/NetworkUtils.java
Normal file
53
backend/src/main/java/ru/micord/ervu/util/NetworkUtils.java
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
package ru.micord.ervu.util;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* @author Adel Kalimullin
|
||||
*/
|
||||
public final class NetworkUtils {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(NetworkUtils.class);
|
||||
private static final String IP_HEADER = "X-Forwarded-For";
|
||||
private static final String UNKNOWN = "unknown";
|
||||
|
||||
private NetworkUtils() {
|
||||
}
|
||||
|
||||
public static String getServerIp() {
|
||||
try {
|
||||
InetAddress inetAddress = InetAddress.getLocalHost();
|
||||
return inetAddress.getHostAddress();
|
||||
}
|
||||
catch (UnknownHostException e) {
|
||||
LOGGER.error("Failed to get local IP address", e);
|
||||
return UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
public static String getClientIp(HttpServletRequest request) {
|
||||
String ip = request.getHeader(IP_HEADER);
|
||||
if (StringUtils.hasText(ip) && !ip.equalsIgnoreCase(UNKNOWN)) {
|
||||
return ip.split(",")[0].trim();
|
||||
}
|
||||
else {
|
||||
return request.getRemoteAddr();
|
||||
}
|
||||
}
|
||||
|
||||
public static String getHostName(String ip) {
|
||||
try {
|
||||
InetAddress inetAddress = InetAddress.getByName(ip);
|
||||
return inetAddress.getHostName();
|
||||
}
|
||||
catch (UnknownHostException e) {
|
||||
LOGGER.error("Unknown host for IP {}", ip, e);
|
||||
return UNKNOWN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
error.unknown=Система временно недоступна. Пожалуйста, повторите попытку позже.
|
||||
|
|
@ -0,0 +1 @@
|
|||
error.unknown=The system is temporarily unavailable. Please try again later.
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
kafka_reply_timeout=Превышено время ожидания ответа от сервера. Попробуйте повторить запрос позже или обратитесь к системному администратору
|
||||
access_denied=Доступ запрещен. Пользователь должен быть включен в группу "Сотрудник, ответственный за военно-учетную работу" в ЕСИА
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
kafka_reply_timeout=Превышено время ожидания ответа от сервера. Попробуйте повторить запрос позже или обратитесь к системному администратору
|
||||
access_denied=Доступ запрещен. Пользователь должен быть включен в группу "Сотрудник, ответственный за военно-учетную работу" в ЕСИА
|
||||
10
config.md
10
config.md
|
|
@ -788,6 +788,16 @@ JBPM использует 3 корневых категории логирова
|
|||
- `ERVU_KAFKA_REGISTRY_EXTRACT_REQUEST_TOPIC` - топик для отправки запроса на получение выписки из Реестра воинского учета при наличии ErvuId
|
||||
- `ERVU_KAFKA_REGISTRY_EXTRACT_REPLY_TOPIC` - топик для получения выписки из Реестра воинского учета
|
||||
- `ERVU_KAFKA_EXTRACT_HEADER_CLASS` - класс для идентификации в заголовке запроса на получение выписки из Реестра повесток/Реестра воинского учета
|
||||
- `AUDIT_KAFKA_AUTHORIZATION_TOPIC` - топик для отправки аудита в журнал авторизации
|
||||
- `AUDIT_KAFKA_ACTION_TOPIC` - топик для отправки аудита в журнал действий пользователя
|
||||
- `AUDIT_KAFKA_FILE_DOWNLOAD_TOPIC` - топик для отправки аудита в журнал загрузки ЮЛ и ФЛ
|
||||
- `AUDIT_KAFKA_BOOTSTRAP_SERVERS` - список пар хост:порт, использующихся для установки первоначального соединения с кластером Kafka
|
||||
- `AUDIT_KAFKA_SECURITY_PROTOCOL` - протокол, используемый для взаимодействия с брокерами
|
||||
- `AUDIT_KAFKA_DOC_LOGIN_MODULE` - имя класса для входа в систему для SASL-соединений в формате, используемом конфигурационными файлами JAAS
|
||||
- `AUDIT_KAFKA_USERNAME` - пользователь для подключения к Kafka
|
||||
- `AUDIT_KAFKA_PASSWORD` - пароль для подключения к Kafka
|
||||
- `AUDIT_KAFKA_SASL_MECHANISM` - механизм SASL, используемый для клиентских подключений
|
||||
- `AUDIT_KAFKA_ENABLED` - флажок для включения записи аудита в кафку
|
||||
|
||||
# Прочее
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,16 @@ 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.scram.ScramLoginModule
|
||||
AUDIT_KAFKA_AUTHORIZATION_TOPIC=ervu.lkrp.auth.events
|
||||
AUDIT_KAFKA_ACTION_TOPIC=ervu.lkrp.action.events
|
||||
AUDIT_KAFKA_FILE_DOWNLOAD_TOPIC=ervu.lkrp.import.file
|
||||
AUDIT_KAFKA_BOOTSTRAP_SERVERS=
|
||||
AUDIT_KAFKA_SECURITY_PROTOCOL=
|
||||
AUDIT_KAFKA_DOC_LOGIN_MODULE=
|
||||
AUDIT_KAFKA_USERNAME=
|
||||
AUDIT_KAFKA_PASSWORD=
|
||||
AUDIT_KAFKA_SASL_MECHANISM=
|
||||
AUDIT_KAFKA_ENABLED=false
|
||||
|
||||
ESIA_TOKEN_CLEAR_CRON=0 0 */1 * * *
|
||||
COOKIE_PATH=/fl
|
||||
|
|
|
|||
|
|
@ -80,6 +80,16 @@
|
|||
<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"/>
|
||||
<property name="esia.token.clear.cron" value="0 0 */1 * * *"/>
|
||||
<property name="audit.kafka.bootstrap.servers" value="localhost:9092"/>
|
||||
<property name="audit.kafka.authorization.topic" value="ervu.lkrp.auth.events"/>
|
||||
<property name="audit.kafka.file.download.topic" value="ervu.lkrp.import.file"/>
|
||||
<property name="audit.kafka.action.topic" value="ervu.lkrp.action.events"/>
|
||||
<property name="audit.kafka.security.protocol" value="SASL_PLAINTEXT"/>
|
||||
<property name="audit.kafka.doc.login.module" value="org.apache.kafka.common.security.scram.ScramLoginModule"/>
|
||||
<property name="audit.kafka.sasl.mechanism" value="SCRAM-SHA-256"/>
|
||||
<property name="audit.kafka.username" value="user1"/>
|
||||
<property name="audit.kafka.password" value="Blfi9d2OFG"/>
|
||||
<property name="audit.kafka.enabled" value="false"/>
|
||||
</system-properties>
|
||||
<management>
|
||||
<audit-log>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ru.micord.ervu.lkrp</groupId>
|
||||
<artifactId>fl</artifactId>
|
||||
<version>1.9.5-SNAPSHOT</version>
|
||||
<version>1.9.8-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<groupId>ru.micord.ervu.lkrp.fl</groupId>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ru.micord.ervu.lkrp</groupId>
|
||||
<artifactId>fl</artifactId>
|
||||
<version>1.9.5-SNAPSHOT</version>
|
||||
<version>1.9.8-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<groupId>ru.micord.ervu.lkrp.fl</groupId>
|
||||
|
|
|
|||
42
frontend/src/ts/ervu/LinkClickHandler.ts
Normal file
42
frontend/src/ts/ervu/LinkClickHandler.ts
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
import {AnalyticalScope, Behavior, Control, NotNull} from "@webbpm/base-package";
|
||||
import {ElementRef} from "@angular/core";
|
||||
import {AuditService} from "./service/AuditService";
|
||||
import {LinkEventTypeEnum} from "./component/enum/LinkEventTypeEnum";
|
||||
|
||||
@AnalyticalScope(Control)
|
||||
export class LinkClickHandler extends Behavior {
|
||||
@NotNull()
|
||||
public eventType: LinkEventTypeEnum;
|
||||
private control: Control;
|
||||
private auditService: AuditService;
|
||||
private el: ElementRef;
|
||||
|
||||
initialize() {
|
||||
this.control = this.getScript(Control);
|
||||
this.el = this.control.getEl();
|
||||
super.initialize();
|
||||
}
|
||||
|
||||
bindEvents() {
|
||||
super.bindEvents();
|
||||
if (this.el) {
|
||||
this.el.nativeElement.addEventListener('click',
|
||||
(event: MouseEvent) => this.onClickFunction(event));
|
||||
}
|
||||
}
|
||||
|
||||
unbindEvents() {
|
||||
super.unbindEvents()
|
||||
if (this.el) {
|
||||
this.el.nativeElement.removeEventListener('click',
|
||||
(event: MouseEvent) => this.onClickFunction(event));
|
||||
}
|
||||
}
|
||||
|
||||
private onClickFunction(event: MouseEvent) {
|
||||
const target = event.target as HTMLElement;
|
||||
if (target.tagName === 'A') {
|
||||
this.auditService.logActionAudit(this.eventType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -29,8 +29,12 @@ export class ExtractLoadService extends Behavior {
|
|||
this.errorEvent.subscribe(() => console.log("error event occurred", this.errorEvent));
|
||||
this.onClickFunction = () => {
|
||||
console.log("click event occurred");
|
||||
const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
||||
this.httpClient.get('extract/' + this.formatRegistry, {
|
||||
responseType: 'blob',
|
||||
headers: {
|
||||
"Client-Time-Zone": timeZone,
|
||||
},
|
||||
observe: 'response'
|
||||
}).toPromise()
|
||||
.then((response) => {
|
||||
|
|
|
|||
5
frontend/src/ts/ervu/component/enum/LinkEventTypeEnum.ts
Normal file
5
frontend/src/ts/ervu/component/enum/LinkEventTypeEnum.ts
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
export enum LinkEventTypeEnum {
|
||||
NAVIGATION_TO_SOURCE = "Переход на другие источники",
|
||||
DOWNLOAD_TEMPLATE = "Скачивание шаблона",
|
||||
DOWNLOAD_EXAMPLE = "Скачивание примера заполнения формы"
|
||||
}
|
||||
|
|
@ -36,6 +36,9 @@ export class InMemoryStaticGrid extends GridV2 {
|
|||
super.initGrid();
|
||||
this.subscription = this.injector.get(ErvuDataService).message.subscribe(value => {
|
||||
this.rowData = value ? value[this.dataList] : null;
|
||||
this.initDeferred.promise.then(() => {
|
||||
this.refreshData();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
43
frontend/src/ts/ervu/service/AuditService.ts
Normal file
43
frontend/src/ts/ervu/service/AuditService.ts
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
import {Injectable} from "@angular/core";
|
||||
import {HttpClient} from "@angular/common/http";
|
||||
import {Router} from "@angular/router";
|
||||
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class AuditService {
|
||||
|
||||
constructor(private httpClient: HttpClient, private router: Router) {
|
||||
}
|
||||
|
||||
public logActionAudit(eventType: string, fileName?: string): void {
|
||||
const currentRoute = this.router.url;
|
||||
const sourceUrl = window.location.href;
|
||||
const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
||||
|
||||
const data: AuditAction = {
|
||||
eventType: eventType,
|
||||
sourceUrl: sourceUrl,
|
||||
route: currentRoute,
|
||||
fileName: fileName
|
||||
};
|
||||
|
||||
this.httpClient.post("audit/action", data, {
|
||||
headers: {
|
||||
"Client-Time-Zone": timeZone,
|
||||
}
|
||||
}).toPromise();
|
||||
}
|
||||
}
|
||||
|
||||
export interface AuditAction {
|
||||
eventType: string;
|
||||
sourceUrl: string;
|
||||
route: string;
|
||||
fileName?: string;
|
||||
}
|
||||
|
||||
export class AuditConstants {
|
||||
public static readonly OPEN_PAGE_EVENT = "Открытие страницы";
|
||||
}
|
||||
|
|
@ -24,6 +24,7 @@ import {LogOutComponent} from "./component/logout.component";
|
|||
import {LoadForm} from "../../ervu/component/container/LoadForm";
|
||||
import {InMemoryStaticGrid} from "../../ervu/component/grid/InMemoryStaticGrid";
|
||||
import {AuthenticationService} from "../security/authentication.service";
|
||||
import {AuditService} from "../../ervu/service/AuditService";
|
||||
import {HomeLandingComponent} from "./component/home-landing.component";
|
||||
|
||||
registerLocaleData(localeRu);
|
||||
|
|
@ -64,7 +65,7 @@ export function checkAuthentication(authService: AuthenticationService): () => P
|
|||
DIRECTIVES
|
||||
],
|
||||
providers: [
|
||||
AuthenticationService,
|
||||
AuthenticationService, AuditService,
|
||||
{
|
||||
provide: APP_INITIALIZER,
|
||||
useFactory: checkAuthentication,
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import {
|
|||
Router
|
||||
} from "@angular/router";
|
||||
import {ProgressIndicationService} from "@webbpm/base-package";
|
||||
import {AuditConstants, AuditService} from "../../../ervu/service/AuditService";
|
||||
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
|
|
@ -21,7 +22,8 @@ export class WebbpmComponent {
|
|||
|
||||
constructor(private router: Router,
|
||||
private progressIndicationService: ProgressIndicationService,
|
||||
private cd: ChangeDetectorRef) {
|
||||
private cd: ChangeDetectorRef,
|
||||
private auditService: AuditService) {
|
||||
router.events.subscribe((event: Event) => {
|
||||
if (event instanceof NavigationStart) {
|
||||
progressIndicationService.showProgressBar();
|
||||
|
|
@ -32,6 +34,12 @@ export class WebbpmComponent {
|
|||
|| event instanceof NavigationError
|
||||
|| event instanceof NavigationCancel) {
|
||||
progressIndicationService.hideProgressBar();
|
||||
|
||||
if (event instanceof NavigationEnd
|
||||
&& event.url != '/home'
|
||||
&& event.url != '/access-denied') {
|
||||
this.auditService.logActionAudit(AuditConstants.OPEN_PAGE_EVENT);
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
|||
2
pom.xml
2
pom.xml
|
|
@ -4,7 +4,7 @@
|
|||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>ru.micord.ervu.lkrp</groupId>
|
||||
<artifactId>fl</artifactId>
|
||||
<version>1.9.5-SNAPSHOT</version>
|
||||
<version>1.9.8-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
<modules>
|
||||
<module>backend</module>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ru.micord.ervu.lkrp</groupId>
|
||||
<artifactId>fl</artifactId>
|
||||
<version>1.9.5-SNAPSHOT</version>
|
||||
<version>1.9.8-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<groupId>ru.micord.ervu.lkrp.fl</groupId>
|
||||
|
|
|
|||
|
|
@ -1034,6 +1034,7 @@
|
|||
<componentRootId>6f1b4ecf-7311-41ea-87f7-56f77ea66251</componentRootId>
|
||||
<name>Гиперссылка - на Госуслугах</name>
|
||||
<container>false</container>
|
||||
<expanded>false</expanded>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="2fe08181-8a1e-4cda-be3a-0b0ddcb21603">
|
||||
<properties>
|
||||
|
|
@ -1072,6 +1073,22 @@
|
|||
</value>
|
||||
</entry>
|
||||
</properties>
|
||||
</scripts>
|
||||
<scripts id="53f844ea-7cd7-4bd3-b9fa-0ba97d517b5f">
|
||||
<classRef type="TS">
|
||||
<className>LinkClickHandler</className>
|
||||
<packageName>ervu</packageName>
|
||||
</classRef>
|
||||
<enabled>true</enabled>
|
||||
<expanded>true</expanded>
|
||||
<properties>
|
||||
<entry>
|
||||
<key>eventType</key>
|
||||
<value>
|
||||
<simple>"NAVIGATION_TO_SOURCE"</simple>
|
||||
</value>
|
||||
</entry>
|
||||
</properties>
|
||||
</scripts>
|
||||
</children>
|
||||
</children>
|
||||
|
|
|
|||
|
|
@ -223,7 +223,6 @@
|
|||
<componentRootId>a674ce01-eadd-4297-b782-53e45e059310</componentRootId>
|
||||
<name>HB - (сценарий) в связи с неявкой в военкомат без уважительной причины в течение 20 календарных</name>
|
||||
<container>true</container>
|
||||
<expanded>false</expanded>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="bf098f19-480e-44e4-9084-aa42955c4d0f">
|
||||
<properties>
|
||||
|
|
@ -325,7 +324,6 @@
|
|||
<componentRootId>854640d1-9de8-4d5a-8f00-5d33cdf097f3</componentRootId>
|
||||
<name>HB - (сценарий) в качестве ограничения, направленного на обеспечение явки в военкомат</name>
|
||||
<container>true</container>
|
||||
<expanded>false</expanded>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="bf098f19-480e-44e4-9084-aa42955c4d0f">
|
||||
<properties>
|
||||
|
|
@ -450,7 +448,6 @@
|
|||
<componentRootId>0276d338-dbbc-406a-a356-96f7fd02a5a6</componentRootId>
|
||||
<name>Таблица - временные меры</name>
|
||||
<container>true</container>
|
||||
<expanded>false</expanded>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="fe8cfe1c-5381-411e-aee6-cf4b38fcea07">
|
||||
<properties>
|
||||
|
|
@ -623,7 +620,6 @@
|
|||
<componentRootId>040fa808-ccbf-4844-b179-d63f54dc220a</componentRootId>
|
||||
<name>HB - запрет на выезд из России</name>
|
||||
<container>true</container>
|
||||
<expanded>false</expanded>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="bf098f19-480e-44e4-9084-aa42955c4d0f">
|
||||
<properties>
|
||||
|
|
@ -869,7 +865,6 @@
|
|||
<componentRootId>573a720b-91f7-4e25-a441-7fd3133fdf31</componentRootId>
|
||||
<name>HB - запрет на постановку в налоговом органе физического лица в качестве налогоплательщика, применяющего спец</name>
|
||||
<container>true</container>
|
||||
<expanded>false</expanded>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="bf098f19-480e-44e4-9084-aa42955c4d0f">
|
||||
<properties>
|
||||
|
|
@ -1683,7 +1678,6 @@
|
|||
<componentRootId>52dc50c2-9c0c-44a8-94fb-ff190bdce295</componentRootId>
|
||||
<name>VB - правый</name>
|
||||
<container>true</container>
|
||||
<expanded>false</expanded>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="bf098f19-480e-44e4-9084-aa42955c4d0f">
|
||||
<properties>
|
||||
|
|
@ -1818,7 +1812,6 @@
|
|||
<componentRootId>ffa21c64-1030-45c8-9901-db59f298fc11</componentRootId>
|
||||
<name>Диалоговые окна (информационные)</name>
|
||||
<container>true</container>
|
||||
<expanded>false</expanded>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="bf098f19-480e-44e4-9084-aa42955c4d0f"/>
|
||||
<scripts id="72befe90-1915-483f-b88c-d1ec5d4bdc8e"/>
|
||||
|
|
@ -2045,6 +2038,22 @@
|
|||
<scripts id="f203f156-be32-4131-9c86-4d6bac6d5d56">
|
||||
<enabled>false</enabled>
|
||||
</scripts>
|
||||
<scripts id="a1579d08-139a-429e-8601-2bf95aa91147">
|
||||
<classRef type="TS">
|
||||
<className>LinkClickHandler</className>
|
||||
<packageName>ervu</packageName>
|
||||
</classRef>
|
||||
<enabled>true</enabled>
|
||||
<expanded>true</expanded>
|
||||
<properties>
|
||||
<entry>
|
||||
<key>eventType</key>
|
||||
<value>
|
||||
<simple>"NAVIGATION_TO_SOURCE"</simple>
|
||||
</value>
|
||||
</entry>
|
||||
</properties>
|
||||
</scripts>
|
||||
</children>
|
||||
<children id="56f58b69-0324-4823-bb69-98682542e514">
|
||||
<prototypeId>fd7e47b9-dce1-4d14-9f3a-580c79f59579</prototypeId>
|
||||
|
|
@ -2456,6 +2465,22 @@
|
|||
<scripts id="f203f156-be32-4131-9c86-4d6bac6d5d56">
|
||||
<enabled>false</enabled>
|
||||
</scripts>
|
||||
<scripts id="f2041b5d-0cd4-4b7f-a790-98edc48e9d86">
|
||||
<classRef type="TS">
|
||||
<className>LinkClickHandler</className>
|
||||
<packageName>ervu</packageName>
|
||||
</classRef>
|
||||
<enabled>true</enabled>
|
||||
<expanded>true</expanded>
|
||||
<properties>
|
||||
<entry>
|
||||
<key>eventType</key>
|
||||
<value>
|
||||
<simple>"NAVIGATION_TO_SOURCE"</simple>
|
||||
</value>
|
||||
</entry>
|
||||
</properties>
|
||||
</scripts>
|
||||
</children>
|
||||
<children id="8ae2b128-9044-428e-b88e-7095f1207c97">
|
||||
<prototypeId>fd7e47b9-dce1-4d14-9f3a-580c79f59579</prototypeId>
|
||||
|
|
@ -2891,6 +2916,22 @@
|
|||
<scripts id="f203f156-be32-4131-9c86-4d6bac6d5d56">
|
||||
<enabled>false</enabled>
|
||||
</scripts>
|
||||
<scripts id="9d29fb9f-020d-46eb-a8c4-efd831aae46a">
|
||||
<classRef type="TS">
|
||||
<className>LinkClickHandler</className>
|
||||
<packageName>ervu</packageName>
|
||||
</classRef>
|
||||
<enabled>true</enabled>
|
||||
<expanded>true</expanded>
|
||||
<properties>
|
||||
<entry>
|
||||
<key>eventType</key>
|
||||
<value>
|
||||
<simple>"NAVIGATION_TO_SOURCE"</simple>
|
||||
</value>
|
||||
</entry>
|
||||
</properties>
|
||||
</scripts>
|
||||
</children>
|
||||
<children id="67caa536-dc5e-49c6-a8b9-c3c4cf9d0459">
|
||||
<prototypeId>fd7e47b9-dce1-4d14-9f3a-580c79f59579</prototypeId>
|
||||
|
|
@ -3002,7 +3043,6 @@
|
|||
<componentRootId>6a606277-7950-41b1-a59f-7d1deb5cccd2</componentRootId>
|
||||
<name>Уважительные причины неявки в военкомат</name>
|
||||
<container>true</container>
|
||||
<expanded>false</expanded>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="cf4526a1-96ab-4820-8aa9-62fb54c2b64c">
|
||||
<properties>
|
||||
|
|
@ -3174,6 +3214,7 @@
|
|||
<componentRootId>613a502f-2276-454e-bb91-4596be5e94cf</componentRootId>
|
||||
<name>Гиперссылка - Закон о воинской обязанности и военной службе, ст. 7.</name>
|
||||
<container>false</container>
|
||||
<expanded>false</expanded>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="2fe08181-8a1e-4cda-be3a-0b0ddcb21603">
|
||||
<properties>
|
||||
|
|
@ -3215,6 +3256,7 @@
|
|||
<componentRootId>81c3d5d2-0f2e-401d-b107-4ad7467f7b30</componentRootId>
|
||||
<name>Текст(гссылка) - Закон о воинской обязанности и военной службе, ст. 7.</name>
|
||||
<container>false</container>
|
||||
<expanded>false</expanded>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="cf4526a1-96ab-4820-8aa9-62fb54c2b64c">
|
||||
<properties>
|
||||
|
|
@ -3232,6 +3274,22 @@
|
|||
<scripts id="f203f156-be32-4131-9c86-4d6bac6d5d56">
|
||||
<enabled>false</enabled>
|
||||
</scripts>
|
||||
<scripts id="9cc0c0c5-77a3-410f-874b-4d3879a36124">
|
||||
<classRef type="TS">
|
||||
<className>LinkClickHandler</className>
|
||||
<packageName>ervu</packageName>
|
||||
</classRef>
|
||||
<enabled>true</enabled>
|
||||
<expanded>true</expanded>
|
||||
<properties>
|
||||
<entry>
|
||||
<key>eventType</key>
|
||||
<value>
|
||||
<simple>"NAVIGATION_TO_SOURCE"</simple>
|
||||
</value>
|
||||
</entry>
|
||||
</properties>
|
||||
</scripts>
|
||||
</children>
|
||||
<children id="6dd87957-9a07-4c23-b203-90d8fb8bc181">
|
||||
<prototypeId>fd7e47b9-dce1-4d14-9f3a-580c79f59579</prototypeId>
|
||||
|
|
@ -3344,7 +3402,6 @@
|
|||
<componentRootId>07d89523-77ea-40f3-96d0-952c74b082b0</componentRootId>
|
||||
<name>AC - для вызова диалогов</name>
|
||||
<container>true</container>
|
||||
<expanded>false</expanded>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="bf098f19-480e-44e4-9084-aa42955c4d0f">
|
||||
<properties>
|
||||
|
|
|
|||
|
|
@ -513,7 +513,6 @@
|
|||
<componentRootId>4e247261-22c9-4b75-bc42-1214d6478193</componentRootId>
|
||||
<name>HB заголовок - Повестки</name>
|
||||
<container>true</container>
|
||||
<expanded>false</expanded>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="bf098f19-480e-44e4-9084-aa42955c4d0f">
|
||||
<properties>
|
||||
|
|
@ -573,7 +572,6 @@
|
|||
<componentRootId>3962166c-e12b-4866-b6fc-e53c9f233272</componentRootId>
|
||||
<name>VB - 1.1.1.1 (на имя выписана повестка) сценарий</name>
|
||||
<container>true</container>
|
||||
<expanded>false</expanded>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="bf098f19-480e-44e4-9084-aa42955c4d0f">
|
||||
<properties>
|
||||
|
|
@ -640,7 +638,6 @@
|
|||
<componentRootId>54ec4ded-0f1d-44b1-beea-1d10f2c65d6b</componentRootId>
|
||||
<name>HB - явитесь по повестке в военкомат</name>
|
||||
<container>true</container>
|
||||
<expanded>false</expanded>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="bf098f19-480e-44e4-9084-aa42955c4d0f"/>
|
||||
<scripts id="b6068710-0f31-48ec-8e03-c0c1480a40c0"/>
|
||||
|
|
@ -783,7 +780,6 @@
|
|||
<componentRootId>54755bcb-801b-450d-aa2e-046e2a405538</componentRootId>
|
||||
<name>VB - 1.1.1.1 (на ? дату нет сформированных повесток) сценарий</name>
|
||||
<container>true</container>
|
||||
<expanded>false</expanded>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="bf098f19-480e-44e4-9084-aa42955c4d0f">
|
||||
<properties>
|
||||
|
|
@ -919,7 +915,6 @@
|
|||
<componentRootId>ae6bbd9c-b3f6-458a-9c19-07e06a4716da</componentRootId>
|
||||
<name>VB - 1.1.1.1 (в реестре нет информации о сформированных повестках) сценарий</name>
|
||||
<container>true</container>
|
||||
<expanded>false</expanded>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="bf098f19-480e-44e4-9084-aa42955c4d0f">
|
||||
<properties>
|
||||
|
|
@ -1773,7 +1768,6 @@
|
|||
<componentRootId>8ed0924a-73dc-4732-8426-0a7217654309</componentRootId>
|
||||
<name>HB - данные загружаются</name>
|
||||
<container>true</container>
|
||||
<expanded>false</expanded>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="bf098f19-480e-44e4-9084-aa42955c4d0f">
|
||||
<properties>
|
||||
|
|
@ -2443,7 +2437,6 @@
|
|||
<componentRootId>935a9f9f-4d12-4813-b313-919627c0e642</componentRootId>
|
||||
<name>VB - 1.1.2.2 (применены временные меры) сценарий</name>
|
||||
<container>true</container>
|
||||
<expanded>false</expanded>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="bf098f19-480e-44e4-9084-aa42955c4d0f">
|
||||
<properties>
|
||||
|
|
@ -3000,7 +2993,6 @@
|
|||
<componentRootId>4b46dfb0-e372-48e7-96cb-6d488cbfbc55</componentRootId>
|
||||
<name>VB - 1.1.2.2 (на "дата" нет действующих ограничений) сценарий</name>
|
||||
<container>true</container>
|
||||
<expanded>false</expanded>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="bf098f19-480e-44e4-9084-aa42955c4d0f">
|
||||
<properties>
|
||||
|
|
@ -3153,7 +3145,6 @@
|
|||
<componentRootId>751006da-a8d6-45c6-8eee-0895c30f8035</componentRootId>
|
||||
<name>VB - 1.1.2.2 (В реестре нет информации о примененных временных мерах) сценарий</name>
|
||||
<container>true</container>
|
||||
<expanded>false</expanded>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="bf098f19-480e-44e4-9084-aa42955c4d0f">
|
||||
<properties>
|
||||
|
|
@ -3216,7 +3207,6 @@
|
|||
<componentRootId>a4bb1eb3-c05a-4c96-acc4-885a99e4e28d</componentRootId>
|
||||
<name>HB - данные загружаются</name>
|
||||
<container>true</container>
|
||||
<expanded>false</expanded>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="bf098f19-480e-44e4-9084-aa42955c4d0f">
|
||||
<properties>
|
||||
|
|
@ -7326,7 +7316,6 @@
|
|||
<componentRootId>cc277790-aa36-4798-9a37-97d2a381e5e8</componentRootId>
|
||||
<name>Реестр воинского учета</name>
|
||||
<container>true</container>
|
||||
<expanded>false</expanded>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="cf4526a1-96ab-4820-8aa9-62fb54c2b64c">
|
||||
<properties>
|
||||
|
|
@ -7524,6 +7513,7 @@
|
|||
<componentRootId>61e47a39-6f30-4d52-92db-fce8f0df062c</componentRootId>
|
||||
<name>Текст(гссылка) - Закон о воинской обязанности и военной службе, ст. 8.2.</name>
|
||||
<container>false</container>
|
||||
<expanded>false</expanded>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="cf4526a1-96ab-4820-8aa9-62fb54c2b64c">
|
||||
<properties>
|
||||
|
|
@ -7541,6 +7531,22 @@
|
|||
<scripts id="f203f156-be32-4131-9c86-4d6bac6d5d56">
|
||||
<enabled>false</enabled>
|
||||
</scripts>
|
||||
<scripts id="ed835461-d64e-44b3-aa26-63abb48473ad">
|
||||
<classRef type="TS">
|
||||
<className>LinkClickHandler</className>
|
||||
<packageName>ervu</packageName>
|
||||
</classRef>
|
||||
<enabled>true</enabled>
|
||||
<expanded>true</expanded>
|
||||
<properties>
|
||||
<entry>
|
||||
<key>eventType</key>
|
||||
<value>
|
||||
<simple>"NAVIGATION_TO_SOURCE"</simple>
|
||||
</value>
|
||||
</entry>
|
||||
</properties>
|
||||
</scripts>
|
||||
</children>
|
||||
<children id="757294ad-d1dd-4a9f-987d-40a666b2ad9d">
|
||||
<prototypeId>fd7e47b9-dce1-4d14-9f3a-580c79f59579</prototypeId>
|
||||
|
|
@ -7652,7 +7658,6 @@
|
|||
<componentRootId>018ebef5-5b82-464e-ae64-b8a38c11a244</componentRootId>
|
||||
<name>Реестр повесток</name>
|
||||
<container>true</container>
|
||||
<expanded>false</expanded>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="cf4526a1-96ab-4820-8aa9-62fb54c2b64c">
|
||||
<properties>
|
||||
|
|
@ -7970,6 +7975,22 @@
|
|||
<scripts id="f203f156-be32-4131-9c86-4d6bac6d5d56">
|
||||
<enabled>false</enabled>
|
||||
</scripts>
|
||||
<scripts id="f5574121-d46d-4ce1-a314-515f81571e49">
|
||||
<classRef type="TS">
|
||||
<className>LinkClickHandler</className>
|
||||
<packageName>ervu</packageName>
|
||||
</classRef>
|
||||
<enabled>true</enabled>
|
||||
<expanded>true</expanded>
|
||||
<properties>
|
||||
<entry>
|
||||
<key>eventType</key>
|
||||
<value>
|
||||
<simple>"NAVIGATION_TO_SOURCE"</simple>
|
||||
</value>
|
||||
</entry>
|
||||
</properties>
|
||||
</scripts>
|
||||
</children>
|
||||
<children id="7281e53c-3e98-453f-935a-cd5f93420620">
|
||||
<prototypeId>fd7e47b9-dce1-4d14-9f3a-580c79f59579</prototypeId>
|
||||
|
|
@ -8088,7 +8109,6 @@
|
|||
<componentRootId>e40b27e3-8df0-4e8c-adeb-6e24de6f18d2</componentRootId>
|
||||
<name>Временные меры</name>
|
||||
<container>true</container>
|
||||
<expanded>false</expanded>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="cf4526a1-96ab-4820-8aa9-62fb54c2b64c">
|
||||
<properties>
|
||||
|
|
@ -8441,6 +8461,22 @@
|
|||
<scripts id="f203f156-be32-4131-9c86-4d6bac6d5d56">
|
||||
<enabled>false</enabled>
|
||||
</scripts>
|
||||
<scripts id="72fc7c7d-ab13-40f5-a79d-75619e3af934">
|
||||
<classRef type="TS">
|
||||
<className>LinkClickHandler</className>
|
||||
<packageName>ervu</packageName>
|
||||
</classRef>
|
||||
<enabled>true</enabled>
|
||||
<expanded>true</expanded>
|
||||
<properties>
|
||||
<entry>
|
||||
<key>eventType</key>
|
||||
<value>
|
||||
<simple>"NAVIGATION_TO_SOURCE"</simple>
|
||||
</value>
|
||||
</entry>
|
||||
</properties>
|
||||
</scripts>
|
||||
</children>
|
||||
<children id="52473ef0-1993-4be5-a86f-7cbc6dc8e75a">
|
||||
<prototypeId>fd7e47b9-dce1-4d14-9f3a-580c79f59579</prototypeId>
|
||||
|
|
@ -8566,7 +8602,6 @@
|
|||
<componentRootId>dce4d66d-4b4f-4883-a54c-e44e96a06a53</componentRootId>
|
||||
<name>Уважительные причины неявки в военкомат</name>
|
||||
<container>true</container>
|
||||
<expanded>false</expanded>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="cf4526a1-96ab-4820-8aa9-62fb54c2b64c">
|
||||
<properties>
|
||||
|
|
@ -8796,6 +8831,22 @@
|
|||
<scripts id="f203f156-be32-4131-9c86-4d6bac6d5d56">
|
||||
<enabled>false</enabled>
|
||||
</scripts>
|
||||
<scripts id="9b7eead5-b15c-4e63-a6c2-ef164b092268">
|
||||
<classRef type="TS">
|
||||
<className>LinkClickHandler</className>
|
||||
<packageName>ervu</packageName>
|
||||
</classRef>
|
||||
<enabled>true</enabled>
|
||||
<expanded>true</expanded>
|
||||
<properties>
|
||||
<entry>
|
||||
<key>eventType</key>
|
||||
<value>
|
||||
<simple>"NAVIGATION_TO_SOURCE"</simple>
|
||||
</value>
|
||||
</entry>
|
||||
</properties>
|
||||
</scripts>
|
||||
</children>
|
||||
<children id="3e33975b-5bde-4d58-a4d5-a7acb9633beb">
|
||||
<prototypeId>fd7e47b9-dce1-4d14-9f3a-580c79f59579</prototypeId>
|
||||
|
|
@ -8907,7 +8958,6 @@
|
|||
<componentRootId>5777f90d-5b51-4c1b-b0cc-4ace05faa8f3</componentRootId>
|
||||
<name>Диалог - Отрицательное количество дней до явки в военкомат</name>
|
||||
<container>true</container>
|
||||
<expanded>false</expanded>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="cf4526a1-96ab-4820-8aa9-62fb54c2b64c">
|
||||
<properties>
|
||||
|
|
@ -9221,7 +9271,6 @@
|
|||
<componentRootId>2452bb18-95f0-4bfc-a40d-52b59e3c5cd6</componentRootId>
|
||||
<name>AC - на вызов диалоговых окон</name>
|
||||
<container>true</container>
|
||||
<expanded>false</expanded>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="bf098f19-480e-44e4-9084-aa42955c4d0f">
|
||||
<properties>
|
||||
|
|
@ -10210,7 +10259,6 @@
|
|||
<componentRootId>5443b358-365f-4bfd-bb4c-f2854dd96da4</componentRootId>
|
||||
<name>Диалоговые окна отправки на электронную почту</name>
|
||||
<container>true</container>
|
||||
<expanded>false</expanded>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="bf098f19-480e-44e4-9084-aa42955c4d0f"/>
|
||||
<scripts id="72befe90-1915-483f-b88c-d1ec5d4bdc8e"/>
|
||||
|
|
@ -10373,6 +10421,22 @@
|
|||
<value>
|
||||
<simple>"https://www.gosuslugi.ru"</simple>
|
||||
</value>
|
||||
</entry>
|
||||
</properties>
|
||||
</scripts>
|
||||
<scripts id="a5b10562-a190-4409-bbc9-afc6e9dcf26d">
|
||||
<classRef type="TS">
|
||||
<className>LinkClickHandler</className>
|
||||
<packageName>ervu</packageName>
|
||||
</classRef>
|
||||
<enabled>true</enabled>
|
||||
<expanded>true</expanded>
|
||||
<properties>
|
||||
<entry>
|
||||
<key>eventType</key>
|
||||
<value>
|
||||
<simple>"NAVIGATION_TO_SOURCE"</simple>
|
||||
</value>
|
||||
</entry>
|
||||
</properties>
|
||||
</scripts>
|
||||
|
|
@ -10507,7 +10571,6 @@
|
|||
<componentRootId>f25ca4de-d55b-4a06-bb4c-5eedd65d4095</componentRootId>
|
||||
<name>Диалог - Отправка выписки на электронную почту - к удалению</name>
|
||||
<container>true</container>
|
||||
<expanded>false</expanded>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="cf4526a1-96ab-4820-8aa9-62fb54c2b64c">
|
||||
<properties>
|
||||
|
|
@ -10684,6 +10747,22 @@
|
|||
<value>
|
||||
<simple>"https://www.gosuslugi.ru"</simple>
|
||||
</value>
|
||||
</entry>
|
||||
</properties>
|
||||
</scripts>
|
||||
<scripts id="d727881a-0a95-45a3-ad0d-e9d6d58e816a">
|
||||
<classRef type="TS">
|
||||
<className>LinkClickHandler</className>
|
||||
<packageName>ervu</packageName>
|
||||
</classRef>
|
||||
<enabled>true</enabled>
|
||||
<expanded>true</expanded>
|
||||
<properties>
|
||||
<entry>
|
||||
<key>eventType</key>
|
||||
<value>
|
||||
<simple>"NAVIGATION_TO_SOURCE"</simple>
|
||||
</value>
|
||||
</entry>
|
||||
</properties>
|
||||
</scripts>
|
||||
|
|
@ -10903,7 +10982,6 @@
|
|||
<componentRootId>673d4fd7-0527-41df-abcd-2ab522bb161c</componentRootId>
|
||||
<name>Диалог - Выписка отправлена - к удалению</name>
|
||||
<container>true</container>
|
||||
<expanded>false</expanded>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="cf4526a1-96ab-4820-8aa9-62fb54c2b64c">
|
||||
<properties>
|
||||
|
|
@ -11083,7 +11161,6 @@
|
|||
<componentRootId>d9788c7d-ebeb-413a-969a-a33f167a2bd9</componentRootId>
|
||||
<name>Диалог - не удалось отправить выписку</name>
|
||||
<container>true</container>
|
||||
<expanded>false</expanded>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="cf4526a1-96ab-4820-8aa9-62fb54c2b64c">
|
||||
<properties>
|
||||
|
|
@ -11276,7 +11353,6 @@
|
|||
<componentRootId>8aff628b-a0a4-4296-854d-8a03dbef5937</componentRootId>
|
||||
<name>AC - на вызов диалоговых окон</name>
|
||||
<container>true</container>
|
||||
<expanded>false</expanded>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="bf098f19-480e-44e4-9084-aa42955c4d0f"/>
|
||||
<scripts id="72befe90-1915-483f-b88c-d1ec5d4bdc8e"/>
|
||||
|
|
|
|||
|
|
@ -195,7 +195,6 @@
|
|||
<componentRootId>2d0083b3-0994-4131-9cfc-de84cab46dab</componentRootId>
|
||||
<name>HB - явитесь по повестке в военкомат. Ели не придёте в срок, к Вам применят временные меры</name>
|
||||
<container>true</container>
|
||||
<expanded>false</expanded>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="bf098f19-480e-44e4-9084-aa42955c4d0f">
|
||||
<properties>
|
||||
|
|
@ -338,6 +337,7 @@
|
|||
<componentRootId>fc2ddccc-d84c-4b0b-a9fc-5aa1391d590b</componentRootId>
|
||||
<name>FS - информация по повестке</name>
|
||||
<container>true</container>
|
||||
<expanded>false</expanded>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="46f20297-81d1-4786-bb17-2a78ca6fda6f">
|
||||
<properties>
|
||||
|
|
@ -1101,6 +1101,22 @@
|
|||
<scripts id="f203f156-be32-4131-9c86-4d6bac6d5d56">
|
||||
<enabled>false</enabled>
|
||||
</scripts>
|
||||
<scripts id="bf78cf16-a0a1-41ee-9945-8670cd247a15">
|
||||
<classRef type="TS">
|
||||
<className>LinkClickHandler</className>
|
||||
<packageName>ervu</packageName>
|
||||
</classRef>
|
||||
<enabled>true</enabled>
|
||||
<expanded>true</expanded>
|
||||
<properties>
|
||||
<entry>
|
||||
<key>eventType</key>
|
||||
<value>
|
||||
<simple>"NAVIGATION_TO_SOURCE"</simple>
|
||||
</value>
|
||||
</entry>
|
||||
</properties>
|
||||
</scripts>
|
||||
</children>
|
||||
</children>
|
||||
<children id="7aabbeed-3e64-4cdd-8fe3-841b134da135">
|
||||
|
|
@ -1133,6 +1149,12 @@
|
|||
</item>
|
||||
</value>
|
||||
</entry>
|
||||
<entry>
|
||||
<key>visible</key>
|
||||
<value>
|
||||
<simple>false</simple>
|
||||
</value>
|
||||
</entry>
|
||||
</properties>
|
||||
</scripts>
|
||||
</children>
|
||||
|
|
@ -2099,6 +2121,7 @@
|
|||
<componentRootId>713e58f9-9106-4e75-bf08-23761e541e51</componentRootId>
|
||||
<name>VB - правый</name>
|
||||
<container>true</container>
|
||||
<expanded>false</expanded>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="bf098f19-480e-44e4-9084-aa42955c4d0f">
|
||||
<properties>
|
||||
|
|
@ -2412,7 +2435,6 @@
|
|||
<componentRootId>c9c74406-f8f4-4a9a-8a62-57fe026f5fa5</componentRootId>
|
||||
<name>FS - (если вы не можете явиться по уважительной причине)</name>
|
||||
<container>true</container>
|
||||
<expanded>false</expanded>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="46f20297-81d1-4786-bb17-2a78ca6fda6f">
|
||||
<properties>
|
||||
|
|
@ -2505,7 +2527,6 @@
|
|||
<componentRootId>2f73cbfa-c121-49b0-994a-1bc17d654e1a</componentRootId>
|
||||
<name>FS - (дней до применения всех временных мер)</name>
|
||||
<container>true</container>
|
||||
<expanded>false</expanded>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="46f20297-81d1-4786-bb17-2a78ca6fda6f">
|
||||
<properties>
|
||||
|
|
@ -2611,7 +2632,6 @@
|
|||
<componentRootId>d63ff6bf-f971-4a5e-8b36-e4c5a2e48771</componentRootId>
|
||||
<name>Диалоговые окна (информационные)</name>
|
||||
<container>true</container>
|
||||
<expanded>false</expanded>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="bf098f19-480e-44e4-9084-aa42955c4d0f"/>
|
||||
<scripts id="72befe90-1915-483f-b88c-d1ec5d4bdc8e"/>
|
||||
|
|
@ -2838,6 +2858,22 @@
|
|||
<scripts id="f203f156-be32-4131-9c86-4d6bac6d5d56">
|
||||
<enabled>false</enabled>
|
||||
</scripts>
|
||||
<scripts id="11e50082-7200-4ad6-bd54-ee10c3c0b5a2">
|
||||
<classRef type="TS">
|
||||
<className>LinkClickHandler</className>
|
||||
<packageName>ervu</packageName>
|
||||
</classRef>
|
||||
<enabled>true</enabled>
|
||||
<expanded>true</expanded>
|
||||
<properties>
|
||||
<entry>
|
||||
<key>eventType</key>
|
||||
<value>
|
||||
<simple>"NAVIGATION_TO_SOURCE"</simple>
|
||||
</value>
|
||||
</entry>
|
||||
</properties>
|
||||
</scripts>
|
||||
</children>
|
||||
<children id="b6aa0a33-f198-4846-9105-64aa80094be6">
|
||||
<prototypeId>fd7e47b9-dce1-4d14-9f3a-580c79f59579</prototypeId>
|
||||
|
|
@ -3249,6 +3285,22 @@
|
|||
<scripts id="f203f156-be32-4131-9c86-4d6bac6d5d56">
|
||||
<enabled>false</enabled>
|
||||
</scripts>
|
||||
<scripts id="3faadefb-4757-4f48-8b41-ffde6981f883">
|
||||
<classRef type="TS">
|
||||
<className>LinkClickHandler</className>
|
||||
<packageName>ervu</packageName>
|
||||
</classRef>
|
||||
<enabled>true</enabled>
|
||||
<expanded>true</expanded>
|
||||
<properties>
|
||||
<entry>
|
||||
<key>eventType</key>
|
||||
<value>
|
||||
<simple>"NAVIGATION_TO_SOURCE"</simple>
|
||||
</value>
|
||||
</entry>
|
||||
</properties>
|
||||
</scripts>
|
||||
</children>
|
||||
<children id="e78fddf7-4f36-45cf-89a7-29c68e3616e8">
|
||||
<prototypeId>fd7e47b9-dce1-4d14-9f3a-580c79f59579</prototypeId>
|
||||
|
|
@ -3360,7 +3412,6 @@
|
|||
<componentRootId>43f57db1-0f42-4d3c-8166-45e7691b124a</componentRootId>
|
||||
<name>Временные меры</name>
|
||||
<container>true</container>
|
||||
<expanded>false</expanded>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="cf4526a1-96ab-4820-8aa9-62fb54c2b64c">
|
||||
<properties>
|
||||
|
|
@ -3684,6 +3735,22 @@
|
|||
<scripts id="f203f156-be32-4131-9c86-4d6bac6d5d56">
|
||||
<enabled>false</enabled>
|
||||
</scripts>
|
||||
<scripts id="ce2084ca-ce7d-4789-9ba2-e78cc8df9bef">
|
||||
<classRef type="TS">
|
||||
<className>LinkClickHandler</className>
|
||||
<packageName>ervu</packageName>
|
||||
</classRef>
|
||||
<enabled>true</enabled>
|
||||
<expanded>true</expanded>
|
||||
<properties>
|
||||
<entry>
|
||||
<key>eventType</key>
|
||||
<value>
|
||||
<simple>"NAVIGATION_TO_SOURCE"</simple>
|
||||
</value>
|
||||
</entry>
|
||||
</properties>
|
||||
</scripts>
|
||||
</children>
|
||||
<children id="c90d9a4f-0c35-47a1-a07c-345240c3b7d3">
|
||||
<prototypeId>fd7e47b9-dce1-4d14-9f3a-580c79f59579</prototypeId>
|
||||
|
|
@ -3802,7 +3869,6 @@
|
|||
<componentRootId>76ac701a-62f6-493e-8ab3-9391e956c3f1</componentRootId>
|
||||
<name>Уважительные причины неявки в военкомат</name>
|
||||
<container>true</container>
|
||||
<expanded>false</expanded>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="cf4526a1-96ab-4820-8aa9-62fb54c2b64c">
|
||||
<properties>
|
||||
|
|
@ -4032,6 +4098,22 @@
|
|||
<scripts id="f203f156-be32-4131-9c86-4d6bac6d5d56">
|
||||
<enabled>false</enabled>
|
||||
</scripts>
|
||||
<scripts id="29b36664-c038-438c-b4a4-41eb37d0225f">
|
||||
<classRef type="TS">
|
||||
<className>LinkClickHandler</className>
|
||||
<packageName>ervu</packageName>
|
||||
</classRef>
|
||||
<enabled>true</enabled>
|
||||
<expanded>true</expanded>
|
||||
<properties>
|
||||
<entry>
|
||||
<key>eventType</key>
|
||||
<value>
|
||||
<simple>"NAVIGATION_TO_SOURCE"</simple>
|
||||
</value>
|
||||
</entry>
|
||||
</properties>
|
||||
</scripts>
|
||||
</children>
|
||||
<children id="72183341-d63b-4e4b-85a5-0187806b8158">
|
||||
<prototypeId>fd7e47b9-dce1-4d14-9f3a-580c79f59579</prototypeId>
|
||||
|
|
@ -4448,5 +4530,87 @@
|
|||
</properties>
|
||||
</scripts>
|
||||
</children>
|
||||
<children id="66d254b2-bf2b-40eb-b175-ccc50b9dceed">
|
||||
<prototypeId>98594cec-0a9b-4cef-af09-e1b71cb2ad9e</prototypeId>
|
||||
<componentRootId>66d254b2-bf2b-40eb-b175-ccc50b9dceed</componentRootId>
|
||||
<name>AC - временная мера</name>
|
||||
<container>false</container>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="37dff5c8-1599-4984-b107-c44a87b6da2e">
|
||||
<properties>
|
||||
<entry>
|
||||
<key>elseActions</key>
|
||||
<value>
|
||||
<item id="8d3cc8e0-b29f-465f-bfd5-5b04403944b8" removed="true"/>
|
||||
</value>
|
||||
</entry>
|
||||
<entry>
|
||||
<key>eventRefs</key>
|
||||
<value>
|
||||
<item id="8bf6b67c-543f-4637-abc9-abc82dab3401" removed="false">
|
||||
<value>
|
||||
<complex>
|
||||
<entry>
|
||||
<key>behavior</key>
|
||||
<value>
|
||||
<simple>{"objectId":"05e0b1a0-7d08-4480-8532-b19692e8812a","packageName":"component.button","className":"Button","type":"TS"}</simple>
|
||||
</value>
|
||||
</entry>
|
||||
<entry>
|
||||
<key>propertyName</key>
|
||||
<value>
|
||||
<simple>"clickEvent"</simple>
|
||||
</value>
|
||||
</entry>
|
||||
</complex>
|
||||
</value>
|
||||
</item>
|
||||
</value>
|
||||
</entry>
|
||||
<entry>
|
||||
<key>ifCondition</key>
|
||||
<value>
|
||||
<complex>
|
||||
<entry>
|
||||
<key>logicalOperation</key>
|
||||
<value>
|
||||
<simple>null</simple>
|
||||
</value>
|
||||
</entry>
|
||||
</complex>
|
||||
</value>
|
||||
</entry>
|
||||
<entry>
|
||||
<key>thenActions</key>
|
||||
<value>
|
||||
<item id="d67b987f-e771-4551-808b-28c56b13febc" removed="false">
|
||||
<value>
|
||||
<complex>
|
||||
<entry>
|
||||
<key>behavior</key>
|
||||
<value>
|
||||
<simple>{"objectId":"43f57db1-0f42-4d3c-8166-45e7691b124a","packageName":"component","className":"Dialog","type":"TS"}</simple>
|
||||
</value>
|
||||
</entry>
|
||||
<entry>
|
||||
<key>method</key>
|
||||
<value>
|
||||
<simple>"show"</simple>
|
||||
</value>
|
||||
</entry>
|
||||
<entry>
|
||||
<key>value</key>
|
||||
<value>
|
||||
<simple>null</simple>
|
||||
</value>
|
||||
</entry>
|
||||
</complex>
|
||||
</value>
|
||||
</item>
|
||||
</value>
|
||||
</entry>
|
||||
</properties>
|
||||
</scripts>
|
||||
</children>
|
||||
</rootObjects>
|
||||
</xmlPage>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue