Merge branch 'master' into hotfix/1.9.2

This commit is contained in:
Zaripov Emil 2024-12-03 09:28:33 +03:00
commit 4216a2d311
13 changed files with 538 additions and 255 deletions

View file

@ -1,9 +1,11 @@
package ru.micord.ervu.converter;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import ru.micord.ervu.dto.Restriction;
import ru.micord.ervu.dto.SubpoenaResponseDto;
import org.springframework.stereotype.Component;
import proto.ervu.rp.summons.MeasuresTemporary;
@ -13,6 +15,7 @@ import proto.ervu.rp.summons.SummonsResponseData;
import static ru.micord.ervu.util.DateUtil.convertToLocalDate;
import static java.util.Objects.requireNonNull;
import static ru.micord.ervu.util.DateUtil.convertToString;
import static ru.micord.ervu.util.DateUtil.getDaysTill;
/**
@ -64,29 +67,23 @@ public class SummonsResponseDataConverter {
.recruitmentStatusCode(
Integer.parseInt(responseData.getRecruitmentInfo().getRecruitmentStatusCode()))
.recruitmentStartDate(responseData.getRecruitmentInfo().getRecruitmentStart())
.daysToAppearance(getDaysTill(convertToLocalDate(estimatedDate)))
.otherRestrictionCount(-1);
.daysToAppearance(getDaysTill(convertToLocalDate(estimatedDate)));
summonsInfo.getMeasuresTemporaryPackagesList()
.stream()
// get last package
.max(Comparator.comparing(
mp -> requireNonNull(convertToLocalDate(mp.getPackageStartDate()))))
.ifPresent(
measuresTemporaryPackage -> {
List<MeasuresTemporary> temporariesList = measuresTemporaryPackage.getMeasuresTemporariesList();
temporariesList.forEach(measuresTemporary ->
builder.addRestriction(measuresTemporary.getMeasureName(),
measuresTemporary.getStartDate()
));
List<Restriction> restrictions = new ArrayList<>();
summonsInfo.getMeasuresTemporaryPackagesList().forEach(
measuresTemporaryPackage -> measuresTemporaryPackage.getMeasuresTemporariesList()
.forEach(measuresTemporary ->
restrictions.add(new Restriction(measuresTemporary.getMeasureName(),
convertToString(convertToLocalDate(measuresTemporary.getStartDate()))))
));
if (!temporariesList.isEmpty()) {
MeasuresTemporary firstMeasure = temporariesList.get(0);
builder.firstRestrictionName(firstMeasure.getMeasureName());
builder.firstRestrictionStartDate(firstMeasure.getStartDate());
}
builder.otherRestrictionCount(temporariesList.size() - 1);
});
if (!restrictions.isEmpty()) {
builder.addRestrictions(restrictions);
Restriction firstRestriction = restrictions.get(0);
builder.firstRestrictionName(firstRestriction.name());
builder.firstRestrictionStartDate(firstRestriction.startDate());
}
builder.otherRestrictionCount(restrictions.size() - 1);
}
return builder.build();
}

View file

@ -165,8 +165,8 @@ public record SubpoenaResponseDto(String personName, String birthDate, String do
return this;
}
public void addRestriction(String name, String date) {
this.restrictions.add(new Restriction(name, convertToString(convertToLocalDate(date))));
public void addRestrictions(List<Restriction> restrictions) {
this.restrictions.addAll(restrictions);
}
public void firstRestrictionName(String name) {

View file

@ -100,7 +100,7 @@ public class ReplyingKafkaConfig {
configProps.put(SaslConfigs.SASL_JAAS_CONFIG, loginModule + " required username=\""
+ username + "\" password=\"" + password + "\";");
configProps.put(SaslConfigs.SASL_MECHANISM, saslMechanism);
configProps.put(ConsumerConfig.GROUP_ID_CONFIG, groupId);
configProps.put(ConsumerConfig.GROUP_ID_CONFIG, groupId + "-" + UUID.randomUUID());
configProps.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
return configProps;
}
@ -122,19 +122,13 @@ public class ReplyingKafkaConfig {
@Bean
public ConcurrentMessageListenerContainer<String, String> replyContainer(
ConcurrentKafkaListenerContainerFactory<String, String> kafkaListenerContainerFactory) {
ConcurrentMessageListenerContainer<String, String> container =
kafkaListenerContainerFactory.createContainer(replyTopic);
container.getContainerProperties().setGroupId(groupId);
return container;
return kafkaListenerContainerFactory.createContainer(replyTopic);
}
@Bean
public ConcurrentMessageListenerContainer<String, Bytes> subpoenaReplyContainer(
ConcurrentKafkaListenerContainerFactory<String, Bytes> subpoenaKafkaListenerContainerFactory) {
ConcurrentMessageListenerContainer<String, Bytes> container =
subpoenaKafkaListenerContainerFactory.createContainer(recruitReplyTopic, registryExtractReplyTopic);
container.getContainerProperties().setGroupId(groupId);
return container;
return subpoenaKafkaListenerContainerFactory.createContainer(recruitReplyTopic, registryExtractReplyTopic);
}
@Bean("person")
@ -162,5 +156,6 @@ public class ReplyingKafkaConfig {
replyingKafkaTemplate.setCorrelationIdStrategy(record ->
new CorrelationKey(UUID.randomUUID().toString().getBytes(StandardCharsets.UTF_8)));
replyingKafkaTemplate.setDefaultReplyTimeout(Duration.ofSeconds(replyTimeout));
replyingKafkaTemplate.setSharedReplyTopic(true);
}
}

View file

@ -13,6 +13,7 @@ import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.security.web.authentication.session.NullAuthenticatedSessionStrategy;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
import org.springframework.security.web.csrf.CsrfTokenRequestHandler;
import org.springframework.security.web.csrf.XorCsrfTokenRequestAttributeHandler;
@ -49,31 +50,22 @@ public class SecurityConfig {
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
httpConfigure(http);
http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
http.addFilterBefore(new RequestContextFilter(), LogoutFilter.class);
http.addFilterAfter(filterChainExceptionHandler, RequestContextFilter.class);
return http.build();
}
protected void httpConfigure(HttpSecurity httpSecurity) throws Exception {
CookieCsrfTokenRepository tokenRepository = CookieCsrfTokenRepository.withHttpOnlyFalse();
tokenRepository.setCookieName(TokenConstants.CSRF_TOKEN_NAME);
tokenRepository.setHeaderName(TokenConstants.CSRF_HEADER_NAME);
tokenRepository.setCookiePath("/");
public SecurityFilterChain filterChain(HttpSecurity http,
CookieCsrfTokenRepository tokenRepository)
throws Exception {
XorCsrfTokenRequestAttributeHandler delegate = new XorCsrfTokenRequestAttributeHandler();
delegate.setCsrfRequestAttributeName(null);
// Use only the handle() method of XorCsrfTokenRequestAttributeHandler and the
// default implementation of resolveCsrfTokenValue() from CsrfTokenRequestHandler
CsrfTokenRequestHandler requestHandler = delegate::handle;
httpSecurity.authorizeHttpRequests(
http.authorizeHttpRequests(
(authorizeHttpRequests) -> authorizeHttpRequests.requestMatchers(PERMIT_ALL)
.permitAll()
.anyRequest()
.authenticated())
.csrf((csrf) -> csrf.csrfTokenRepository(tokenRepository)
.csrfTokenRequestHandler(requestHandler))
.csrfTokenRequestHandler(requestHandler)
.sessionAuthenticationStrategy(new NullAuthenticatedSessionStrategy()))
.logout((logout) -> logout.logoutUrl(ESIA_LOGOUT)
.logoutSuccessHandler(new LogoutSuccessHandler(tokenRepository, esiaAuthService)))
.exceptionHandling()
@ -81,6 +73,19 @@ public class SecurityConfig {
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
http.addFilterBefore(new RequestContextFilter(), LogoutFilter.class);
http.addFilterAfter(filterChainExceptionHandler, RequestContextFilter.class);
return http.build();
}
@Bean
public CookieCsrfTokenRepository cookieCsrfTokenRepository() {
CookieCsrfTokenRepository tokenRepository = CookieCsrfTokenRepository.withHttpOnlyFalse();
tokenRepository.setCookieName(TokenConstants.CSRF_TOKEN_NAME);
tokenRepository.setHeaderName(TokenConstants.CSRF_HEADER_NAME);
tokenRepository.setCookiePath("/");
return tokenRepository;
}
public AuthenticationEntryPoint entryPoint() {

View file

@ -1,6 +1,5 @@
package ru.micord.ervu.security.esia.service;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URL;
import java.net.URLEncoder;
@ -21,11 +20,10 @@ import javax.servlet.http.HttpServletResponse;
import com.fasterxml.jackson.databind.ObjectMapper;
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.security.authentication.AuthenticationManager;
import org.springframework.security.core.context.SecurityContext;
import ru.micord.ervu.kafka.model.Document;
import ru.micord.ervu.kafka.model.ErrorData;
import ru.micord.ervu.kafka.model.Person;
import ru.micord.ervu.kafka.model.Response;
import ru.micord.ervu.kafka.service.ReplyingKafkaService;
@ -69,6 +67,8 @@ public class EsiaAuthService {
@Autowired
private SecurityHelper securityHelper;
@Autowired
private AuthenticationManager authenticationManager;
@Value("${ervu.kafka.reply.topic}")
private String requestReplyTopic;
@ -130,12 +130,8 @@ public class EsiaAuthService {
}
private static String urlEncode(String s) {
try {
return URLEncoder.encode(s, "UTF-8")
.replace("+", "%20");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
return URLEncoder.encode(s, StandardCharsets.UTF_8)
.replace("+", "%20");
}
private static String makeRequest(URL url, Map<String, String> params) {
@ -193,21 +189,19 @@ public class EsiaAuthService {
EsiaTokenResponse.class
);
if (tokenResponse == null) {
throw new IllegalStateException("Got empty esia response");
if (tokenResponse == null || tokenResponse.getError() != null) {
String errMsg =
tokenResponse != null ? tokenResponse.getError_description() : "response is empty";
throw new IllegalStateException("Esia response error. " + errMsg);
}
if (tokenResponse.getError() != null) {
throw new RuntimeException(tokenResponse.getError_description());
}
String accessToken = tokenResponse.getAccess_token();
String refreshToken = tokenResponse.getRefresh_token();
EsiaAccessToken esiaAccessToken = personalDataService.readToken(accessToken);
String esiaAccessTokenStr = tokenResponse.getAccess_token();
String esiaRefreshTokenStr = tokenResponse.getRefresh_token();
EsiaAccessToken esiaAccessToken = personalDataService.readToken(esiaAccessTokenStr);
String prnOid = esiaAccessToken.getSbj_id();
Long expiresIn = tokenResponse.getExpires_in();
TokensStore.addAccessToken(prnOid, accessToken, expiresIn);
TokensStore.addRefreshToken(prnOid, refreshToken, expiresIn);
Response ervuIdResponse = getErvuIdResponse(accessToken);
TokensStore.addAccessToken(prnOid, esiaAccessTokenStr, expiresIn);
TokensStore.addRefreshToken(prnOid, esiaRefreshTokenStr, expiresIn);
Response ervuIdResponse = getErvuIdResponse(esiaAccessTokenStr);
Token token = jwtTokenService.createAccessToken(esiaAccessToken.getSbj_id(), expiresIn, ervuIdResponse.getErvuId());
int expiry = tokenResponse.getExpires_in().intValue();
Cookie accessCookie = securityHelper.createAccessCookie(token.getValue(), expiry);
@ -215,9 +209,10 @@ public class EsiaAuthService {
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
new UsernamePasswordAuthenticationToken(token.getUserAccountId(), null);
SecurityContext context = SecurityContextHolder.createEmptyContext();
JwtAuthentication authentication = new JwtAuthentication(usernamePasswordAuthenticationToken,
JwtAuthentication jwtAuthentication = new JwtAuthentication(usernamePasswordAuthenticationToken,
esiaAccessToken.getSbj_id(), token.getValue());
context.setAuthentication(authentication);
authenticationManager.authenticate(jwtAuthentication);
context.setAuthentication(jwtAuthentication);
SecurityContextHolder.setContext(context);
Cookie authMarkerCookie = securityHelper.createAuthMarkerCookie("true", expiry);
response.addCookie(authMarkerCookie);
@ -271,17 +266,19 @@ public class EsiaAuthService {
.send(postReq, HttpResponse.BodyHandlers.ofString());
String responseString = postResp.body();
EsiaTokenResponse tokenResponse = objectMapper.readValue(responseString, EsiaTokenResponse.class);
if (tokenResponse != null && tokenResponse.getError() != null) {
throw new RuntimeException(tokenResponse.getError_description());
if (tokenResponse == null || tokenResponse.getError() != null) {
String errMsg =
tokenResponse != null ? tokenResponse.getError_description() : "response is empty";
throw new IllegalStateException("Esia response error. " + errMsg);
}
String accessToken = tokenResponse.getAccess_token();
String newRefreshToken = tokenResponse.getRefresh_token();
EsiaAccessToken esiaAccessToken = personalDataService.readToken(accessToken);
String esiaAccessTokenStr = tokenResponse.getAccess_token();
String esiaNewRefreshTokenStr = tokenResponse.getRefresh_token();
EsiaAccessToken esiaAccessToken = personalDataService.readToken(esiaAccessTokenStr);
String prnOid = esiaAccessToken.getSbj_id();
Long expiresIn = tokenResponse.getExpires_in();
TokensStore.addAccessToken(prnOid, accessToken, expiresIn);
TokensStore.addRefreshToken(prnOid, newRefreshToken, expiresIn);
Response ervuIdResponse = getErvuIdResponse(accessToken);
TokensStore.addAccessToken(prnOid, esiaAccessTokenStr, expiresIn);
TokensStore.addRefreshToken(prnOid, esiaNewRefreshTokenStr, expiresIn);
Response ervuIdResponse = getErvuIdResponse(esiaAccessTokenStr);
Token token = jwtTokenService.createAccessToken(esiaAccessToken.getSbj_id(), expiresIn, ervuIdResponse.getErvuId());
int expiry = tokenResponse.getExpires_in().intValue();
Cookie accessCookie = securityHelper.createAccessCookie(token.getValue(), expiry);
@ -289,9 +286,10 @@ public class EsiaAuthService {
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
new UsernamePasswordAuthenticationToken(token.getUserAccountId(), null);
SecurityContext context = SecurityContextHolder.createEmptyContext();
JwtAuthentication authentication = new JwtAuthentication(usernamePasswordAuthenticationToken,
JwtAuthentication jwtAuthentication = new JwtAuthentication(usernamePasswordAuthenticationToken,
esiaAccessToken.getSbj_id(), token.getValue());
context.setAuthentication(authentication);
authenticationManager.authenticate(jwtAuthentication);
context.setAuthentication(jwtAuthentication);
SecurityContextHolder.setContext(context);
Cookie authMarkerCookie = securityHelper.createAuthMarkerCookie("true", expiry);
response.addCookie(authMarkerCookie);
@ -327,7 +325,7 @@ public class EsiaAuthService {
}
}
private void errorHandler(HttpResponse httpResponse) {
private void errorHandler(HttpResponse<?> httpResponse) {
if (httpResponse.statusCode() != 200) {
throw new RuntimeException(httpResponse.statusCode() + " " + httpResponse.body());
}

View file

@ -0,0 +1,72 @@
package ru.micord.ervu.security.listener;
import java.lang.invoke.MethodHandles;
import java.util.Arrays;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.security.authentication.event.AuthenticationSuccessEvent;
import org.springframework.security.web.csrf.CsrfTokenRepository;
import org.springframework.security.web.csrf.CsrfTokenRequestAttributeHandler;
import org.springframework.security.web.csrf.CsrfTokenRequestHandler;
import org.springframework.security.web.csrf.DeferredCsrfToken;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import static org.springframework.web.context.request.RequestAttributes.REFERENCE_REQUEST;
@Component
public class JwtUpdateListener implements ApplicationListener<AuthenticationSuccessEvent> {
private final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
private final CsrfTokenRepository tokenRepository;
private final Set<AntPathRequestMatcher> csrfUpdateRequiredPathMatchers;
private CsrfTokenRequestHandler requestHandler = new CsrfTokenRequestAttributeHandler();
@Autowired
public JwtUpdateListener(CsrfTokenRepository tokenRepository) {
Assert.notNull(tokenRepository, "tokenRepository cannot be null");
this.tokenRepository = tokenRepository;
this.csrfUpdateRequiredPathMatchers = Arrays.stream(new String[] {"/esia/auth"})
.map(AntPathRequestMatcher::new)
.collect(Collectors.toSet());
}
@Override
public void onApplicationEvent(AuthenticationSuccessEvent event) {
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
HttpServletRequest request = (HttpServletRequest) Objects.requireNonNull(requestAttributes)
.resolveReference(
REFERENCE_REQUEST);
HttpServletResponse response = ((ServletRequestAttributes) requestAttributes).getResponse();
//if csrf cookie update is not required return
if (this.csrfUpdateRequiredPathMatchers.stream()
.noneMatch(matcher -> matcher.matches(request))) {
return;
}
boolean containsToken = this.tokenRepository.loadToken(request) != null;
if (containsToken) {
this.tokenRepository.saveToken(null, request, response);
DeferredCsrfToken deferredCsrfToken = this.tokenRepository.loadDeferredToken(request,
response
);
this.requestHandler.handle(request, response, deferredCsrfToken::get);
this.logger.debug("Replaced CSRF Token");
}
}
}

View file

@ -13,6 +13,16 @@
</div>
<div class="container">
<div id="browser-check-info">
<div class="browser-check-content">
<div class="browser-check-text">
<div class="plain-text">Для обеспечения защищённого соединения с сайтом реестра повесток необходимо установить браузер Яндекс или Chromium GOST.</div>
</div>
</div>
</div>
<script>
document.getElementById("browser-check-info").hidden = navigator.userAgent.indexOf("Chromium GOST") > -1 || navigator.userAgent.indexOf("YaBrowser") > -1;
</script>
<div class="container-inside">
<div class="list-group lk-what">
<div>

View file

@ -343,6 +343,7 @@
.webbpm.ervu_lkrp_fl .right-block field-set {
font-size: var(--size-text-secondary);
}
/*
.webbpm.ervu_lkrp_fl .right-block field-set:first-child .fieldset {
padding-top: 52px;
}
@ -355,7 +356,7 @@
height: 24px;
background-image: url(../img/svg/doc.svg);
}
*/
.webbpm.ervu_lkrp_fl field-set + field-set {
margin-top: var(--indent-medium);
}
@ -468,6 +469,25 @@
border-color: var(--color-link);
}
.webbpm.ervu_lkrp_fl .grid-warning .ag-root-wrapper {
background-color: transparent;
}
.webbpm.ervu_lkrp_fl .grid-warning .ag-row,
.webbpm.ervu_lkrp_fl .grid-warning .ag-row.ag-row-hover {
border: 0 !important;
border-radius: 8px;
background-color: var(--bg-warn) !important;
}
.webbpm.ervu_lkrp_fl .grid-warning .ag-row + .ag-row {
border-top: 4px solid var(--bg-light) !important;
}
.webbpm.ervu_lkrp_fl .grid-warning .ag-row .ag-cell {
color: var(--color-text-primary) !important;
height: auto !important;
padding: var(--indent-mini);
border: 0 !important;
}
.webbpm.ervu_lkrp_fl .okved-list {
height: auto;
}

View file

@ -624,6 +624,29 @@ a.btn:is(:hover, :focus, :active) {
color: var(--color-link);
}
.browser-check-content {
font-family: 'Golos';
font-size: var(--size-text-secondary);
padding: var(--indent-mini) var(--w-screen) var(--indent-mini) calc(var(--w-screen) + 38px);
background-color: var(--bg-warn);
}
.browser-check-text {
position: relative;
padding-left: 40px;
}
.browser-check-text::before {
position: absolute;
content: url(../img/svg/info.svg);
left: 0;
top: calc((100% - 24px) / 2);
}
.text-header {
color: var(--color-link);
font-family: 'GolosB';
font-size: var(--size-text-primary);
margin-bottom: 4px;
}
/*@media ((max-width: 780px) or ((orientation: landscape) and (max-device-width : 1024px))) {*/
@media (max-width: 1024px) {
body {

View file

@ -489,7 +489,7 @@
<value>
<item id="ddf92f21-aac9-4378-b2e7-3884fa0b1164" removed="false">
<value>
<simple>"font-bold"</simple>
<simple>"subtitle"</simple>
</value>
</item>
</value>
@ -497,7 +497,7 @@
<entry>
<key>initialValue</key>
<value>
<simple>null</simple>
<simple>"Паспорт"</simple>
</value>
</entry>
</properties>

View file

@ -238,7 +238,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>
@ -378,7 +377,6 @@
<componentRootId>699b5c5c-2501-42a0-9572-692ec55de595</componentRootId>
<name>VB - текст</name>
<container>true</container>
<expanded>false</expanded>
<childrenReordered>false</childrenReordered>
<scripts id="bf098f19-480e-44e4-9084-aa42955c4d0f"/>
<scripts id="72befe90-1915-483f-b88c-d1ec5d4bdc8e"/>
@ -448,157 +446,181 @@
<componentRootId>0276d338-dbbc-406a-a356-96f7fd02a5a6</componentRootId>
<name>Таблица - временные меры</name>
<container>true</container>
<childrenReordered>false</childrenReordered>
<scripts id="fe8cfe1c-5381-411e-aee6-cf4b38fcea07">
<properties>
<entry>
<key>dataList</key>
<value>
<simple>"restrictions"</simple>
</value>
</entry>
<entry>
<key>headerHeight</key>
<value>
<simple>0.0</simple>
</value>
</entry>
<entry>
<key>rowHeight</key>
<value>
<simple>70.0</simple>
</value>
</entry>
</properties>
</scripts>
<scripts id="be8fe0e1-4909-4224-8664-be55168595c6"/>
<children id="887d096c-95f4-4938-afed-171f350accd6">
<prototypeId>c556264f-221b-4af8-9e64-f380a67c41ec</prototypeId>
<componentRootId>887d096c-95f4-4938-afed-171f350accd6</componentRootId>
<name>Наименование</name>
<container>false</container>
<childrenReordered>false</childrenReordered>
<scripts id="9c5c7a86-dc40-4b30-a5a7-5e7b4c7ea1e1"/>
<scripts id="0a01c185-920b-4328-a82d-277f917b185e">
<properties>
<entry>
<key>autoHeight</key>
<value>
<simple>true</simple>
</value>
</entry>
<entry>
<key>displayName</key>
<value>
<simple>"Наименование"</simple>
</value>
</entry>
<entry>
<key>field</key>
<value>
<complex>
<entry>
<key>column</key>
<value>
<simple>"name"</simple>
</value>
</entry>
<entry>
<key>type</key>
<value>
<simple>"java.lang.String"</simple>
</value>
</entry>
</complex>
</value>
</entry>
</properties>
</scripts>
</children>
<children id="991ac56c-fc92-4ecf-b617-d2c1a1f08bee">
<prototypeId>c556264f-221b-4af8-9e64-f380a67c41ec</prototypeId>
<componentRootId>991ac56c-fc92-4ecf-b617-d2c1a1f08bee</componentRootId>
<name>Дата</name>
<container>false</container>
<childrenReordered>false</childrenReordered>
<scripts id="9c5c7a86-dc40-4b30-a5a7-5e7b4c7ea1e1">
<properties>
<entry>
<key>renderer</key>
<value>
<complex>
<entry>
<key>label</key>
<value>
<simple>"c"</simple>
</value>
</entry>
</complex>
<implRef type="TS">
<className>ValueWithPrefixRenderer</className>
<packageName>ervu.component.grid.renderer</packageName>
</implRef>
</value>
</entry>
</properties>
</scripts>
<scripts id="0a01c185-920b-4328-a82d-277f917b185e">
<properties>
<entry>
<key>displayName</key>
<value>
<simple>"Дата"</simple>
</value>
</entry>
<entry>
<key>field</key>
<value>
<complex>
<entry>
<key>column</key>
<value>
<simple>"startDate"</simple>
</value>
</entry>
<entry>
<key>type</key>
<value>
<simple>"java.lang.String"</simple>
</value>
</entry>
</complex>
</value>
</entry>
</properties>
</scripts>
</children>
<children id="f2b252d0-4b3b-4ac2-8915-1d1481f99ef1">
<prototypeId>98594cec-0a9b-4cef-af09-e1b71cb2ad9e</prototypeId>
<componentRootId>f2b252d0-4b3b-4ac2-8915-1d1481f99ef1</componentRootId>
<name>Обработка событий</name>
<container>false</container>
<removed>true</removed>
</children>
<children id="640a3f04-fbe0-4287-9c20-69b28bc39406">
<prototypeId>364c8faa-5e56-46cd-9203-d2ec6ef2dc74</prototypeId>
<componentRootId>640a3f04-fbe0-4287-9c20-69b28bc39406</componentRootId>
<name>Наименование меры</name>
<container>false</container>
<removed>true</removed>
</children>
<removed>true</removed>
</children>
<children id="c13a9405-f8c1-4676-be98-b7cef733e6a7">
<prototypeId>f7504fc9-f501-43fe-a678-5c6ba756ba5c</prototypeId>
<componentRootId>c13a9405-f8c1-4676-be98-b7cef733e6a7</componentRootId>
<name>FS - 2 (список ограничений)</name>
<container>true</container>
<expanded>false</expanded>
<childrenReordered>false</childrenReordered>
<scripts id="46f20297-81d1-4786-bb17-2a78ca6fda6f"/>
<scripts id="7fe2f82f-5028-401e-941f-e92df36538a6"/>
<scripts id="73f52c22-5182-4860-8ee6-b9ba164ed460"/>
<scripts id="2129eba5-aac3-41d1-ba50-0a2f4b5f0a32"/>
<scripts id="865a51e1-80f5-4064-a7d2-2b251b33bdec"/>
<children id="0276d338-dbbc-406a-a356-96f7fd02a5a6">
<prototypeId>bee4e324-a660-4d99-bbc4-9fc2b084a5fc</prototypeId>
<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>
<entry>
<key>cssClasses</key>
<value>
<item id="4ece8a50-15cb-401d-8f5b-6d0dd666282a" removed="false">
<value>
<simple>"grid-warning"</simple>
</value>
</item>
<expanded>true</expanded>
</value>
</entry>
<entry>
<key>dataList</key>
<value>
<simple>"restrictions"</simple>
</value>
</entry>
<entry>
<key>headerHeight</key>
<value>
<simple>0.0</simple>
</value>
</entry>
<entry>
<key>rowHeight</key>
<value>
<simple>null</simple>
</value>
</entry>
</properties>
</scripts>
<scripts id="be8fe0e1-4909-4224-8664-be55168595c6"/>
<children id="887d096c-95f4-4938-afed-171f350accd6">
<prototypeId>c556264f-221b-4af8-9e64-f380a67c41ec</prototypeId>
<componentRootId>887d096c-95f4-4938-afed-171f350accd6</componentRootId>
<name>Наименование</name>
<container>false</container>
<childrenReordered>false</childrenReordered>
<scripts id="9c5c7a86-dc40-4b30-a5a7-5e7b4c7ea1e1"/>
<scripts id="0a01c185-920b-4328-a82d-277f917b185e">
<properties>
<entry>
<key>autoHeight</key>
<value>
<simple>true</simple>
</value>
</entry>
<entry>
<key>displayName</key>
<value>
<simple>"Наименование"</simple>
</value>
</entry>
<entry>
<key>field</key>
<value>
<complex>
<entry>
<key>column</key>
<value>
<simple>"name"</simple>
</value>
</entry>
<entry>
<key>type</key>
<value>
<simple>"java.lang.String"</simple>
</value>
</entry>
</complex>
</value>
</entry>
</properties>
</scripts>
</children>
<children id="991ac56c-fc92-4ecf-b617-d2c1a1f08bee">
<prototypeId>c556264f-221b-4af8-9e64-f380a67c41ec</prototypeId>
<componentRootId>991ac56c-fc92-4ecf-b617-d2c1a1f08bee</componentRootId>
<name>Дата</name>
<container>false</container>
<childrenReordered>false</childrenReordered>
<scripts id="9c5c7a86-dc40-4b30-a5a7-5e7b4c7ea1e1">
<properties>
<entry>
<key>renderer</key>
<value>
<complex>
<entry>
<key>label</key>
<value>
<simple>"c"</simple>
</value>
</entry>
</complex>
<implRef type="TS">
<className>ValueWithPrefixRenderer</className>
<packageName>ervu.component.grid.renderer</packageName>
</implRef>
</value>
</entry>
</properties>
</scripts>
<scripts id="0a01c185-920b-4328-a82d-277f917b185e">
<properties>
<entry>
<key>autoHeight</key>
<value>
<simple>true</simple>
</value>
</entry>
<entry>
<key>displayName</key>
<value>
<simple>"Дата"</simple>
</value>
</entry>
<entry>
<key>field</key>
<value>
<complex>
<entry>
<key>column</key>
<value>
<simple>"startDate"</simple>
</value>
</entry>
<entry>
<key>type</key>
<value>
<simple>"java.lang.String"</simple>
</value>
</entry>
</complex>
</value>
</entry>
</properties>
</scripts>
</children>
<children id="f2b252d0-4b3b-4ac2-8915-1d1481f99ef1">
<prototypeId>98594cec-0a9b-4cef-af09-e1b71cb2ad9e</prototypeId>
<componentRootId>f2b252d0-4b3b-4ac2-8915-1d1481f99ef1</componentRootId>
<name>Обработка событий</name>
<container>false</container>
<removed>true</removed>
</children>
<children id="640a3f04-fbe0-4287-9c20-69b28bc39406">
<prototypeId>364c8faa-5e56-46cd-9203-d2ec6ef2dc74</prototypeId>
<componentRootId>640a3f04-fbe0-4287-9c20-69b28bc39406</componentRootId>
<name>Наименование меры</name>
<container>false</container>
<removed>true</removed>
</children>
</children>
<children id="3d37c6ac-d693-42e0-a534-0148b6677f39">
<prototypeId>9d1b5af1-0b8f-4b1b-b9a5-c2e6acf72d91</prototypeId>
<componentRootId>3d37c6ac-d693-42e0-a534-0148b6677f39</componentRootId>
@ -615,7 +637,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>
@ -761,7 +782,6 @@
<componentRootId>7dd0d142-e1fd-4603-902f-b445f03c4ddf</componentRootId>
<name>HB - запрет на регистрацию в качестве индивидуального предпринимателя</name>
<container>true</container>
<expanded>false</expanded>
<childrenReordered>false</childrenReordered>
<scripts id="bf098f19-480e-44e4-9084-aa42955c4d0f">
<properties>
@ -875,7 +895,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>
@ -1529,7 +1548,7 @@
<value>
<item id="0738e1c9-592b-4d68-8149-2338ff6815bc" removed="false">
<value>
<simple>"font-bold"</simple>
<simple>"subtitle"</simple>
</value>
</item>
</value>
@ -1824,6 +1843,7 @@
<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"/>
@ -3215,13 +3235,6 @@
</properties>
</scripts>
</children>
<children id="15d83ba6-b210-4904-8712-5ffb950507a0">
<prototypeId>ba24d307-0b91-4299-ba82-9d0b52384ff2</prototypeId>
<componentRootId>15d83ba6-b210-4904-8712-5ffb950507a0</componentRootId>
<name>Текст(гссылка) - Закон о воинской обязанности и военной службе, ст. 7.</name>
<container>false</container>
<removed>true</removed>
</children>
<children id="81c3d5d2-0f2e-401d-b107-4ad7467f7b30">
<prototypeId>ba24d307-0b91-4299-ba82-9d0b52384ff2</prototypeId>
<componentRootId>81c3d5d2-0f2e-401d-b107-4ad7467f7b30</componentRootId>

View file

@ -1970,7 +1970,6 @@
<componentRootId>c3fc56e5-4aec-44e3-92ed-5fb7b6a68519</componentRootId>
<name>FS - 1.1.2 (Временные меры)</name>
<container>true</container>
<expanded>false</expanded>
<childrenReordered>false</childrenReordered>
<scripts id="46f20297-81d1-4786-bb17-2a78ca6fda6f">
<properties>
@ -2128,7 +2127,6 @@
<componentRootId>9f8fe06c-2f44-426e-8249-10f9cb5d76f2</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>
@ -2222,6 +2220,13 @@
<scripts id="f203f156-be32-4131-9c86-4d6bac6d5d56">
<enabled>false</enabled>
</scripts>
</children>
<children id="bdffd190-e62e-446b-aaa2-fb3f5e170af6">
<prototypeId>d7d54cfb-26b5-4dba-b56f-b6247183c24d</prototypeId>
<componentRootId>bdffd190-e62e-446b-aaa2-fb3f5e170af6</componentRootId>
<name>Горизонтальный контейнер</name>
<container>true</container>
<removed>true</removed>
</children>
<children id="3a7fedf0-a3ac-4b84-bb4e-c87eb353240d">
<prototypeId>d7d54cfb-26b5-4dba-b56f-b6247183c24d</prototypeId>
@ -2544,6 +2549,13 @@
<scripts id="f203f156-be32-4131-9c86-4d6bac6d5d56">
<enabled>false</enabled>
</scripts>
</children>
<children id="ab01ad21-ea41-413e-a1b1-bbd54ed8d959">
<prototypeId>d7d54cfb-26b5-4dba-b56f-b6247183c24d</prototypeId>
<componentRootId>ab01ad21-ea41-413e-a1b1-bbd54ed8d959</componentRootId>
<name>Горизонтальный контейнер</name>
<container>true</container>
<removed>true</removed>
</children>
<children id="4e886a36-f027-4fc0-a0d5-0e934efdc726">
<prototypeId>d7d54cfb-26b5-4dba-b56f-b6247183c24d</prototypeId>
@ -2840,6 +2852,149 @@
</entry>
</properties>
</scripts>
</children>
<children id="3bdd9af7-850c-40f8-8b79-4c1530dd8e8f">
<prototypeId>98594cec-0a9b-4cef-af09-e1b71cb2ad9e</prototypeId>
<componentRootId>3bdd9af7-850c-40f8-8b79-4c1530dd8e8f</componentRootId>
<name>Обработка событий</name>
<container>false</container>
<childrenReordered>false</childrenReordered>
<scripts id="37dff5c8-1599-4984-b107-c44a87b6da2e">
<properties>
<entry>
<key>eventRefs</key>
<value>
<item id="d24c70b5-7916-47a5-b9da-5c2c22e81c9a" removed="false">
<value>
<complex>
<entry>
<key>behavior</key>
<value>
<simple>{"objectId":"0b5b5863-6ab7-4b68-9f52-5369ac5cab9f","packageName":"component","className":"Text","type":"TS"}</simple>
</value>
</entry>
<entry>
<key>propertyName</key>
<value>
<simple>"valueChangeEvent"</simple>
</value>
</entry>
</complex>
</value>
</item>
</value>
</entry>
<entry>
<key>ifCondition</key>
<value>
<complex>
<entry>
<key>conditions</key>
<value>
<item id="d8886475-ec20-464f-ab93-f4524a4c66d9" removed="false">
<value>
<complex>
<entry>
<key>_isGroupSelected</key>
<value>
<simple>false</simple>
</value>
</entry>
<entry>
<key>one</key>
<value>
<complex>
<entry>
<key>conditionFirstPart</key>
<value>
<complex>
<entry>
<key>objectValue</key>
<value>
<complex>
<entry>
<key>behavior</key>
<value>
<simple>{"objectId":"0b5b5863-6ab7-4b68-9f52-5369ac5cab9f","packageName":"component","className":"Text","type":"TS"}</simple>
</value>
</entry>
<entry>
<key>method</key>
<value>
<simple>"getValue"</simple>
</value>
</entry>
</complex>
</value>
</entry>
</complex>
</value>
</entry>
<entry>
<key>operation</key>
<value>
<simple>"IS_EMPTY"</simple>
</value>
</entry>
</complex>
</value>
</entry>
</complex>
</value>
</item>
</value>
</entry>
<entry>
<key>logicalOperation</key>
<value>
<simple>null</simple>
</value>
</entry>
</complex>
</value>
</entry>
<entry>
<key>thenActions</key>
<value>
<item id="d69e6251-ae99-4d7c-9a63-241a3b2f91a2" removed="false">
<value>
<complex>
<entry>
<key>behavior</key>
<value>
<simple>{"objectId":"0b5b5863-6ab7-4b68-9f52-5369ac5cab9f","packageName":"component","className":"Text","type":"TS"}</simple>
</value>
</entry>
<entry>
<key>method</key>
<value>
<simple>"setVisible"</simple>
</value>
</entry>
<entry>
<key>value</key>
<value>
<complex>
<entry>
<key>staticValue</key>
<value>
<implRef type="TS">
<className>boolean</className>
<packageName></packageName>
</implRef>
<simple>false</simple>
</value>
</entry>
</complex>
</value>
</entry>
</complex>
</value>
</item>
</value>
</entry>
</properties>
</scripts>
</children>
</children>
</children>
@ -4039,7 +4194,6 @@
<componentRootId>304824d5-9f9f-4af9-9b08-6232f7536774</componentRootId>
<name>FS - 1.1.3 (Воинский учёт)</name>
<container>true</container>
<expanded>false</expanded>
<childrenReordered>false</childrenReordered>
<scripts id="46f20297-81d1-4786-bb17-2a78ca6fda6f">
<properties>
@ -4172,7 +4326,6 @@
<componentRootId>35a5afea-7a37-42fb-8cbe-55c1e4d6f170</componentRootId>
<name>Hbox - строка с текстом "Военный комиссариат "город, район, наименование""</name>
<container>true</container>
<expanded>false</expanded>
<childrenReordered>false</childrenReordered>
<scripts id="bf098f19-480e-44e4-9084-aa42955c4d0f"/>
<scripts id="b6068710-0f31-48ec-8e03-c0c1480a40c0"/>

View file

@ -155,7 +155,6 @@
<componentRootId>23a3d23b-eb21-4923-b1e9-0b0f003b5b0f</componentRootId>
<name>LoadForm</name>
<container>true</container>
<expanded>false</expanded>
<childrenReordered>false</childrenReordered>
<scripts id="9ad247a3-9c46-4f12-9949-b1c905bd73bc"/>
<scripts id="79188cdc-d646-433e-9751-1482b9247ee6"/>
@ -211,6 +210,7 @@
<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>
@ -240,6 +240,7 @@
<componentRootId>805e05e6-5c7f-42e4-8770-a742f50f45b0</componentRootId>
<name>VB</name>
<container>true</container>
<expanded>false</expanded>
<childrenReordered>false</childrenReordered>
<scripts id="bf098f19-480e-44e4-9084-aa42955c4d0f"/>
<scripts id="72befe90-1915-483f-b88c-d1ec5d4bdc8e"/>
@ -426,7 +427,7 @@
<value>
<item id="348bc76b-b78a-4637-b82e-ec46f6aad692" removed="false">
<value>
<simple>"font-bold"</simple>
<simple>"subtitle"</simple>
</value>
</item>
<item id="9fabdafd-5a2c-47e5-ad65-f2267990d9b4" removed="true"/>
@ -777,7 +778,7 @@
<value>
<item id="36c162e1-79d6-483d-9c44-a47db0781b79" removed="false">
<value>
<simple>"font-bold"</simple>
<simple>"subtitle"</simple>
</value>
</item>
</value>
@ -984,7 +985,7 @@
<value>
<item id="59faf222-4f7a-47b8-a004-54c1508eb861" removed="false">
<value>
<simple>"font-bold"</simple>
<simple>"subtitle"</simple>
</value>
</item>
</value>
@ -1017,7 +1018,7 @@
<value>
<item id="3cffbe76-05a1-4759-8e9c-d1e2cc7255ce" removed="false">
<value>
<simple>"font-bold"</simple>
<simple>"subtitle"</simple>
</value>
</item>
</value>
@ -1404,7 +1405,7 @@
<value>
<item id="8276726b-b8d6-481c-9a56-eb92173ee5db" removed="false">
<value>
<simple>"font-bold"</simple>
<simple>"subtitle"</simple>
</value>
</item>
<item id="1636520a-4ad3-4876-bfcb-c8f09d8f412d" removed="true"/>
@ -1606,7 +1607,7 @@
<value>
<item id="a9fb8420-acff-46e7-b740-3cbea6f67b9c" removed="false">
<value>
<simple>"font-bold"</simple>
<simple>"subtitle"</simple>
</value>
</item>
</value>
@ -1951,7 +1952,7 @@
<value>
<item id="8a74ab84-2507-4089-aef4-07f6ef272877" removed="false">
<value>
<simple>"font-bold"</simple>
<simple>"subtitle"</simple>
</value>
</item>
</value>
@ -2162,6 +2163,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>
@ -2447,6 +2449,7 @@
<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>
@ -2645,6 +2648,7 @@
<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"/>
@ -3978,13 +3982,6 @@
<enabled>false</enabled>
</scripts>
</children>
<children id="18b4a2ef-37be-4665-9a7a-32263121805b">
<prototypeId>ba24d307-0b91-4299-ba82-9d0b52384ff2</prototypeId>
<componentRootId>18b4a2ef-37be-4665-9a7a-32263121805b</componentRootId>
<name>Текст(гссылка) - Закон о воинской обязанности и военной службе, ст. 7.</name>
<container>false</container>
<removed>true</removed>
</children>
</children>
<children id="97416586-16fb-4d9b-b61e-cb884b7b5856">
<prototypeId>ba24d307-0b91-4299-ba82-9d0b52384ff2</prototypeId>