Merge branch 'master' into feature/SUPPORT-8593_marker_verify
# Conflicts: # backend/src/main/java/ru/micord/ervu/security/esia/service/EsiaAuthService.java # backend/src/main/java/ru/micord/ervu/security/esia/service/EsiaPersonalDataService.java # backend/src/main/java/ru/micord/ervu/security/esia/service/PersonalDataService.java # config/standalone/dev/standalone.xml
This commit is contained in:
commit
bb29b09aee
172 changed files with 1448 additions and 1448 deletions
101
backend/pom.xml
101
backend/pom.xml
|
|
@ -5,16 +5,12 @@
|
|||
<parent>
|
||||
<groupId>ru.micord.ervu.lkrp</groupId>
|
||||
<artifactId>fl</artifactId>
|
||||
<version>1.8.0-SNAPSHOT</version>
|
||||
<version>1.8.2</version>
|
||||
</parent>
|
||||
<groupId>ru.micord.ervu.lkrp.fl</groupId>
|
||||
<artifactId>backend</artifactId>
|
||||
<packaging>war</packaging>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.kafka</groupId>
|
||||
<artifactId>spring-kafka</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-api</artifactId>
|
||||
|
|
@ -33,23 +29,10 @@
|
|||
<artifactId>resources</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.cg.webbpm.modules.reporting.reporting-jasper</groupId>
|
||||
<artifactId>reporting-jasper-fonts</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.ocpsoft.prettytime</groupId>
|
||||
<artifactId>prettytime</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jooq</groupId>
|
||||
<artifactId>jooq</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.santuario</groupId>
|
||||
<artifactId>xmlsec</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
|
|
@ -102,6 +85,10 @@
|
|||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-config</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.kafka</groupId>
|
||||
<artifactId>spring-kafka</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.cg.webbpm.modules</groupId>
|
||||
<artifactId>inject</artifactId>
|
||||
|
|
@ -127,13 +114,8 @@
|
|||
<artifactId>error-handling-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.cg.webbpm.modules.database</groupId>
|
||||
<artifactId>database-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.cg.webbpm.modules.database</groupId>
|
||||
<artifactId>database-impl</artifactId>
|
||||
<scope>compile</scope>
|
||||
<groupId>javax.annotation</groupId>
|
||||
<artifactId>javax.annotation-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.cg.webbpm.modules.jndi</groupId>
|
||||
|
|
@ -143,50 +125,13 @@
|
|||
<groupId>ru.cg.webbpm.modules.jndi</groupId>
|
||||
<artifactId>jndi-inject</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.sun.mail</groupId>
|
||||
<artifactId>javax.mail</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.cg.webbpm.modules.database</groupId>
|
||||
<artifactId>database-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.cg.webbpm.modules</groupId>
|
||||
<artifactId>standard-annotations</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.cg.webbpm.modules.core</groupId>
|
||||
<artifactId>metrics</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.cg.webbpm.modules.reporting</groupId>
|
||||
<artifactId>reporting-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.cg.webbpm.modules.reporting</groupId>
|
||||
<artifactId>reporting-runtime-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.cg.webbpm.modules.reporting</groupId>
|
||||
<artifactId>reporting-runtime-impl</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.cg.webbpm.modules.reporting.reporting-jasper</groupId>
|
||||
<artifactId>reporting-jasper-impl</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.cg.webbpm.modules.reporting.reporting-jasper</groupId>
|
||||
<artifactId>reporting-jasper-runtime-impl</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.cg.webbpm.modules.reporting.reporting-xdoc</groupId>
|
||||
<artifactId>reporting-xdoc-impl</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.cg.webbpm.modules.reporting.reporting-xdoc</groupId>
|
||||
<artifactId>reporting-xdoc-runtime-impl</artifactId>
|
||||
<groupId>ru.cg.webbpm.modules.database</groupId>
|
||||
<artifactId>database-beans</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.liquibase</groupId>
|
||||
|
|
@ -196,30 +141,6 @@
|
|||
<groupId>ru.cg.webbpm.modules</groupId>
|
||||
<artifactId>webkit-base</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>xerces</groupId>
|
||||
<artifactId>xercesImpl</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.micord.fias</groupId>
|
||||
<artifactId>client</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.tika</groupId>
|
||||
<artifactId>tika-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.javacrumbs.shedlock</groupId>
|
||||
<artifactId>shedlock-spring</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.javacrumbs.shedlock</groupId>
|
||||
<artifactId>shedlock-provider-jdbc-template</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.cg.webbpm.packages.base</groupId>
|
||||
<artifactId>backend</artifactId>
|
||||
|
|
@ -248,6 +169,10 @@
|
|||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<extensions>
|
||||
|
|
|
|||
|
|
@ -1,12 +1,3 @@
|
|||
import java.time.Duration;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import net.javacrumbs.shedlock.core.LockProvider;
|
||||
import net.javacrumbs.shedlock.provider.jdbctemplate.JdbcTemplateLockProvider;
|
||||
import net.javacrumbs.shedlock.spring.ScheduledLockConfiguration;
|
||||
import net.javacrumbs.shedlock.spring.ScheduledLockConfigurationBuilder;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
|
@ -14,7 +5,6 @@ import org.springframework.context.annotation.EnableAspectJAutoProxy;
|
|||
import org.springframework.context.annotation.FilterType;
|
||||
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
|
||||
/**
|
||||
|
|
@ -30,13 +20,12 @@ import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
|||
"bpmn",
|
||||
"i18n",
|
||||
"errorhandling",
|
||||
"database",
|
||||
"component.addresses",
|
||||
"gen",
|
||||
"ru.cg",
|
||||
"ru.micord"
|
||||
}, excludeFilters = {
|
||||
@ComponentScan.Filter(type = FilterType.REGEX, pattern = "security.WebSecurityConfig")
|
||||
@ComponentScan.Filter(type = FilterType.REGEX, pattern = "service.sql.SqlExecutorServiceImpl")
|
||||
})
|
||||
@EnableAspectJAutoProxy(proxyTargetClass = true)
|
||||
@EnableWebMvc
|
||||
|
|
@ -47,21 +36,4 @@ public class AppConfig {
|
|||
public PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer(){
|
||||
return new PropertySourcesPlaceholderConfigurer();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ScheduledLockConfiguration taskScheduler(LockProvider lockProvider) {
|
||||
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
|
||||
scheduler.setPoolSize(12);
|
||||
scheduler.initialize();
|
||||
return ScheduledLockConfigurationBuilder
|
||||
.withLockProvider(lockProvider)
|
||||
.withTaskScheduler(scheduler)
|
||||
.withDefaultLockAtMostFor(Duration.ofHours(4))
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public LockProvider lockProvider(@Qualifier("datasource") DataSource dataSource) {
|
||||
return new JdbcTemplateLockProvider(dataSource);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
5
backend/src/main/java/SecurityInit.java
Normal file
5
backend/src/main/java/SecurityInit.java
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
|
||||
import org.springframework.web.WebApplicationInitializer;
|
||||
|
||||
public class SecurityInit extends AbstractSecurityWebApplicationInitializer implements WebApplicationInitializer {
|
||||
}
|
||||
|
|
@ -1,151 +0,0 @@
|
|||
package ru.micord.ervu.db;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.jooq.ConnectionProvider;
|
||||
import org.jooq.DSLContext;
|
||||
import org.jooq.ExecuteListener;
|
||||
import org.jooq.conf.Settings;
|
||||
import org.jooq.impl.DefaultConfiguration;
|
||||
import org.jooq.impl.DefaultDSLContext;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
|
||||
import org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import ru.fix.aggregating.profiler.PrefixedProfiler;
|
||||
import ru.fix.aggregating.profiler.Profiler;
|
||||
|
||||
import ru.cg.webbpm.modules.core.metrics.MetricsConfig;
|
||||
import ru.cg.webbpm.modules.core.runtime.api.context.ExecutionContextHelper;
|
||||
import ru.cg.webbpm.modules.database.api.ConfigurationProvider;
|
||||
import ru.cg.webbpm.modules.database.api.metrics.DataSourceWithMetrics;
|
||||
import ru.cg.webbpm.modules.database.api.provider.DslProvider;
|
||||
import ru.cg.webbpm.modules.database.bean.config.Datasource;
|
||||
import ru.cg.webbpm.modules.database.impl.DbConfInitializer;
|
||||
import ru.cg.webbpm.modules.database.impl.data_source.DataSourceConfigReader;
|
||||
import ru.cg.webbpm.modules.database.impl.data_source.DataSourceFactory;
|
||||
import ru.cg.webbpm.modules.database.impl.data_source.HikariDataSourceFactory;
|
||||
import ru.cg.webbpm.modules.database.impl.data_source.JndiDataSourceFactory;
|
||||
import ru.cg.webbpm.modules.database.impl.provider.DefaultConnectionProvider;
|
||||
import ru.cg.webbpm.modules.database.impl.provider.DslProviderImpl;
|
||||
import ru.cg.webbpm.modules.database.impl.service.ProcessSqlService;
|
||||
import ru.cg.webbpm.modules.resources.api.ResourceProvider;
|
||||
|
||||
@Configuration
|
||||
@Import(MetricsConfig.class)
|
||||
public class DbConfiguration {
|
||||
@Value("${webbpm.db.query_timeout:120}")
|
||||
private Integer queryTimeout;
|
||||
@Autowired
|
||||
private ResourceProvider resourceProvider;
|
||||
@Autowired
|
||||
private ProcessSqlService processSqlService;
|
||||
@Autowired
|
||||
private Profiler profiler;
|
||||
@Autowired
|
||||
private ExecutionContextHelper executionContextHelper;
|
||||
|
||||
@Autowired
|
||||
private ExecuteListener[] executeListeners;
|
||||
|
||||
private final Map<String, DSLContext> dslContextMap = new HashMap<>();
|
||||
private final Map<String, ConnectionProvider> connectionProviderMap = new HashMap<>();
|
||||
|
||||
@Bean
|
||||
public Datasource datasourceConfig() {
|
||||
return DataSourceConfigReader.read(resourceProvider);
|
||||
}
|
||||
|
||||
@Bean(destroyMethod = "destroy")
|
||||
public DataSourceFactory dataSourceFactory(HikariDataSourceFactory hikariDataSourceFactory) {
|
||||
return new DataSourceFactory(hikariDataSourceFactory);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Primary
|
||||
public DataSource datasource(DataSourceFactory dataSourceFactory) {
|
||||
DataSource dataSource = dataSourceFactory.createDataSource(datasourceConfig(),
|
||||
JndiDataSourceFactory::createDataSource
|
||||
);
|
||||
return new DataSourceWithMetrics(
|
||||
dataSource,
|
||||
"project",
|
||||
new PrefixedProfiler(profiler, "webbpm.db"),
|
||||
executionContextHelper
|
||||
);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PlatformTransactionManager txManager(@Qualifier("datasource") DataSource dataSource) {
|
||||
return new DataSourceTransactionManager(dataSource);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Primary
|
||||
public TransactionAwareDataSourceProxy transactionAwareDataSource(DataSource dataSource) {
|
||||
return new TransactionAwareDataSourceProxy(dataSource);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Primary
|
||||
public DefaultConnectionProvider connectionProvider(
|
||||
TransactionAwareDataSourceProxy transactionAwareDataSourceProxy) {
|
||||
return new DefaultConnectionProvider(transactionAwareDataSourceProxy, processSqlService,
|
||||
connectionProviderMap
|
||||
);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Settings jooqSettings(DataSourceFactory dataSourceFactory) {
|
||||
Settings settings = new Settings();
|
||||
if (dataSourceFactory.dataSourceType() == DataSourceFactory.DataSourceType.HIKARI) {
|
||||
settings.setQueryTimeout(queryTimeout);
|
||||
}
|
||||
return settings;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Primary
|
||||
public org.jooq.Configuration jooqConfiguration(ConnectionProvider connectionProvider,
|
||||
Settings jooqSettings) {
|
||||
DefaultConfiguration configuration = new DefaultConfiguration();
|
||||
configuration.setSQLDialect(datasourceConfig().getSqlDialect());
|
||||
jooqSettings = jooqSettings.withExecuteLogging(false);
|
||||
configuration.setSettings(jooqSettings);
|
||||
configuration.setConnectionProvider(connectionProvider);
|
||||
configuration.set(executeListeners);
|
||||
return configuration;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Primary
|
||||
public DSLContext dsl(org.jooq.Configuration configuration) {
|
||||
return new DefaultDSLContext(configuration);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ConfigurationProvider configurationProvider(
|
||||
PlatformTransactionManager platformTransactionManager) {
|
||||
return () -> platformTransactionManager;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DslProvider dslProvider(@Qualifier("dsl") DSLContext dsl) {
|
||||
return new DslProviderImpl(dsl, this.dslContextMap);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DbConfInitializer dbConfInitializer(DataSourceFactory dataSourceFactory,
|
||||
org.jooq.Configuration masterConfiguration, Datasource datasource) {
|
||||
return new DbConfInitializer(dataSourceFactory, masterConfiguration, datasource,
|
||||
processSqlService, connectionProviderMap, dslContextMap);
|
||||
}
|
||||
}
|
||||
|
|
@ -8,7 +8,6 @@ import org.apache.kafka.common.serialization.BytesDeserializer;
|
|||
import org.apache.kafka.common.serialization.StringDeserializer;
|
||||
import org.apache.kafka.common.serialization.StringSerializer;
|
||||
import org.apache.kafka.common.utils.Bytes;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
|
@ -16,12 +15,15 @@ import org.springframework.kafka.annotation.EnableKafka;
|
|||
import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory;
|
||||
import org.springframework.kafka.core.*;
|
||||
import org.springframework.kafka.listener.ConcurrentMessageListenerContainer;
|
||||
import org.springframework.kafka.requestreply.CorrelationKey;
|
||||
import org.springframework.kafka.requestreply.ReplyingKafkaTemplate;
|
||||
import org.springframework.kafka.support.serializer.JsonSerializer;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.Duration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
@Configuration
|
||||
@EnableKafka
|
||||
|
|
@ -44,8 +46,6 @@ public class ReplyingKafkaConfig {
|
|||
private String replyTopic;
|
||||
@Value("${ervu.kafka.recruit.reply.topic}")
|
||||
private String recruitReplyTopic;
|
||||
@Value("${ervu.kafka.subpoena.extract.reply.topic}")
|
||||
private String subpoenaExtractReplyTopic;
|
||||
@Value("${ervu.kafka.registry.extract.reply.topic}")
|
||||
private String registryExtractReplyTopic;
|
||||
|
||||
|
|
@ -130,35 +130,37 @@ public class ReplyingKafkaConfig {
|
|||
|
||||
@Bean
|
||||
public ConcurrentMessageListenerContainer<String, Bytes> subpoenaReplyContainer(
|
||||
ConcurrentKafkaListenerContainerFactory<String, Bytes> personKafkaListenerContainerFactory) {
|
||||
ConcurrentKafkaListenerContainerFactory<String, Bytes> subpoenaKafkaListenerContainerFactory) {
|
||||
ConcurrentMessageListenerContainer<String, Bytes> container =
|
||||
personKafkaListenerContainerFactory.createContainer(recruitReplyTopic,
|
||||
subpoenaExtractReplyTopic, registryExtractReplyTopic);
|
||||
subpoenaKafkaListenerContainerFactory.createContainer(recruitReplyTopic, registryExtractReplyTopic);
|
||||
container.getContainerProperties().setGroupId(groupId);
|
||||
return container;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Qualifier("person")
|
||||
@Bean("person")
|
||||
public ReplyingKafkaTemplate<String, String, String> replyingKafkaTemplate(
|
||||
ProducerFactory<String, String> producerFactory,
|
||||
ConcurrentMessageListenerContainer<String, String> replyContainer) {
|
||||
ReplyingKafkaTemplate<String, String, String> replyingKafkaTemplate =
|
||||
new ReplyingKafkaTemplate<>(producerFactory, replyContainer);
|
||||
replyingKafkaTemplate.setCorrelationHeaderName("messageId");
|
||||
replyingKafkaTemplate.setDefaultReplyTimeout(Duration.ofSeconds(replyTimeout));
|
||||
customizeTemplate(replyingKafkaTemplate);
|
||||
return replyingKafkaTemplate;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Qualifier("subpoena")
|
||||
@Bean("subpoena")
|
||||
public ReplyingKafkaTemplate<String, Object, Bytes> subpoenaReplyingKafkaTemplate(
|
||||
ProducerFactory<String, Object> personProducerFactory,
|
||||
ConcurrentMessageListenerContainer<String, Bytes> personReplyContainer) {
|
||||
ProducerFactory<String, Object> subpoenaProducerFactory,
|
||||
ConcurrentMessageListenerContainer<String, Bytes> subpoenaReplyContainer) {
|
||||
ReplyingKafkaTemplate<String, Object, Bytes> replyingKafkaTemplate =
|
||||
new ReplyingKafkaTemplate<>(personProducerFactory, personReplyContainer);
|
||||
replyingKafkaTemplate.setCorrelationHeaderName("messageId");
|
||||
replyingKafkaTemplate.setDefaultReplyTimeout(Duration.ofSeconds(replyTimeout));
|
||||
new ReplyingKafkaTemplate<>(subpoenaProducerFactory, subpoenaReplyContainer);
|
||||
customizeTemplate(replyingKafkaTemplate);
|
||||
return replyingKafkaTemplate;
|
||||
}
|
||||
|
||||
private void customizeTemplate(ReplyingKafkaTemplate<?, ?, ?> replyingKafkaTemplate) {
|
||||
replyingKafkaTemplate.setCorrelationHeaderName("messageId");
|
||||
replyingKafkaTemplate.setCorrelationIdStrategy(record ->
|
||||
new CorrelationKey(UUID.randomUUID().toString().getBytes(StandardCharsets.UTF_8)));
|
||||
replyingKafkaTemplate.setDefaultReplyTimeout(Duration.ofSeconds(replyTimeout));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@ public abstract class BaseReplyingKafkaService<T, V> implements ReplyingKafkaSer
|
|||
throw new RuntimeException("Failed to get kafka response", e);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract ReplyingKafkaTemplate<String, T, V> getTemplate();
|
||||
|
||||
protected abstract ProducerRecord<String, T> getProducerRecord(String requestTopic,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
package ru.micord.ervu.kafka.service.impl;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.apache.kafka.clients.producer.ProducerRecord;
|
||||
import org.apache.kafka.common.header.internals.RecordHeader;
|
||||
|
|
@ -40,8 +39,7 @@ public class SubpoenaReplyingKafkaService extends BaseReplyingKafkaService<Objec
|
|||
@Override
|
||||
protected ProducerRecord<String, Object> getProducerRecord(String requestTopic, String replyTopic,
|
||||
Object requestMessage) {
|
||||
ProducerRecord<String, Object> record = new ProducerRecord<>(requestTopic,
|
||||
UUID.randomUUID().toString(), requestMessage);
|
||||
ProducerRecord<String, Object> record = new ProducerRecord<>(requestTopic, requestMessage);
|
||||
record.headers().add(new RecordHeader(KafkaHeaders.REPLY_TOPIC, replyTopic.getBytes()));
|
||||
String headerClass = requestMessage instanceof SubpoenaRequestDto
|
||||
? recruitHeaderClass : extractHeaderClass;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
package ru.micord.ervu.security;
|
||||
|
||||
import java.io.IOException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.web.csrf.CsrfToken;
|
||||
import org.springframework.security.web.csrf.CsrfTokenRepository;
|
||||
import ru.micord.ervu.security.esia.service.EsiaAuthService;
|
||||
|
||||
public class LogoutSuccessHandler
|
||||
implements org.springframework.security.web.authentication.logout.LogoutSuccessHandler {
|
||||
|
||||
private final CsrfTokenRepository csrfTokenRepository;
|
||||
private final EsiaAuthService esiaAuthService;
|
||||
|
||||
public LogoutSuccessHandler(CsrfTokenRepository csrfTokenRepository,
|
||||
EsiaAuthService esiaAuthService) {
|
||||
this.csrfTokenRepository = csrfTokenRepository;
|
||||
this.esiaAuthService = esiaAuthService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response,
|
||||
Authentication authentication) throws IOException {
|
||||
String url = esiaAuthService.logout(request, response);
|
||||
response.setStatus(HttpServletResponse.SC_OK);
|
||||
response.getWriter().write(url);
|
||||
response.getWriter().flush();
|
||||
CsrfToken csrfToken = this.csrfTokenRepository.generateToken(request);
|
||||
this.csrfTokenRepository.saveToken(csrfToken, request, response);
|
||||
}
|
||||
}
|
||||
|
|
@ -4,38 +4,78 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
import ru.micord.ervu.security.webbpm.jwt.filter.JwtAuthenticationFilter;
|
||||
import org.springframework.security.web.authentication.logout.LogoutFilter;
|
||||
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
|
||||
import org.springframework.security.web.csrf.CsrfTokenRequestHandler;
|
||||
import org.springframework.security.web.csrf.XorCsrfTokenRequestAttributeHandler;
|
||||
import org.springframework.web.filter.RequestContextFilter;
|
||||
import ru.micord.ervu.security.esia.service.EsiaAuthService;
|
||||
import ru.micord.ervu.security.filter.FilterChainExceptionHandler;
|
||||
import ru.micord.ervu.security.webbpm.jwt.JwtAuthenticationProvider;
|
||||
import ru.micord.ervu.security.webbpm.jwt.JwtMatcher;
|
||||
import ru.micord.ervu.security.webbpm.jwt.UnauthorizedEntryPoint;
|
||||
import ru.micord.ervu.security.webbpm.jwt.filter.JwtAuthenticationFilter;
|
||||
import ru.micord.ervu.security.webbpm.jwt.helper.SecurityHelper;
|
||||
import ru.micord.ervu.security.webbpm.jwt.service.JwtTokenService;
|
||||
|
||||
import static ru.micord.ervu.security.SecurityConstants.ESIA_LOGOUT;
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
public class SecurityConfig {
|
||||
private static final String[] PERMIT_ALL = new String[] {
|
||||
"/version", "/esia/url", "/esia/auth", "esia/refresh"
|
||||
};
|
||||
@Autowired
|
||||
private JwtAuthenticationFilter jwtAuthenticationFilter;
|
||||
@Autowired
|
||||
private EsiaAuthService esiaAuthService;
|
||||
@Autowired
|
||||
private FilterChainExceptionHandler filterChainExceptionHandler;
|
||||
@Autowired
|
||||
private JwtAuthenticationProvider jwtAuthenticationProvider;
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
@Autowired
|
||||
public void configureGlobal(AuthenticationManagerBuilder auth) {
|
||||
auth.authenticationProvider(jwtAuthenticationProvider);
|
||||
}
|
||||
|
||||
@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 {
|
||||
String[] permitAll = {"/esia/url", "/esia/auth", "esia/refresh"};
|
||||
|
||||
httpSecurity.authorizeRequests()
|
||||
.antMatchers(permitAll).permitAll()
|
||||
.antMatchers("/**").authenticated()
|
||||
.and()
|
||||
.csrf().disable()
|
||||
.exceptionHandling().authenticationEntryPoint(entryPoint())
|
||||
CookieCsrfTokenRepository tokenRepository = CookieCsrfTokenRepository.withHttpOnlyFalse();
|
||||
tokenRepository.setCookiePath("/");
|
||||
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(
|
||||
(authorizeHttpRequests) -> authorizeHttpRequests.requestMatchers(PERMIT_ALL)
|
||||
.permitAll()
|
||||
.anyRequest()
|
||||
.authenticated())
|
||||
.csrf((csrf) -> csrf.csrfTokenRepository(tokenRepository)
|
||||
.csrfTokenRequestHandler(requestHandler))
|
||||
.logout((logout) -> logout.logoutUrl(ESIA_LOGOUT)
|
||||
.logoutSuccessHandler(new LogoutSuccessHandler(tokenRepository, esiaAuthService)))
|
||||
.exceptionHandling()
|
||||
.authenticationEntryPoint(entryPoint())
|
||||
.and()
|
||||
.sessionManagement()
|
||||
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
|
||||
|
|
@ -46,17 +86,23 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
|||
}
|
||||
|
||||
@Bean
|
||||
@Override
|
||||
public AuthenticationManager authenticationManagerBean() throws Exception {
|
||||
return super.authenticationManagerBean();
|
||||
AuthenticationManager authenticationManager(
|
||||
AuthenticationConfiguration authenticationConfiguration) throws Exception {
|
||||
return authenticationConfiguration.getAuthenticationManager();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public JwtAuthenticationFilter jwtAuthenticationFilter() throws Exception {
|
||||
JwtAuthenticationFilter jwtAuthenticationFilter = new JwtAuthenticationFilter("/**",
|
||||
entryPoint()
|
||||
);
|
||||
jwtAuthenticationFilter.setAuthenticationManager(authenticationManagerBean());
|
||||
public SecurityHelper securityHelper() {
|
||||
return new SecurityHelper();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public JwtAuthenticationFilter jwtAuthenticationFilter(SecurityHelper securityHelper,
|
||||
AuthenticationManager manager,
|
||||
JwtTokenService jwtTokenService) {
|
||||
JwtAuthenticationFilter jwtAuthenticationFilter = new JwtAuthenticationFilter(
|
||||
new JwtMatcher("/**", PERMIT_ALL), entryPoint(), securityHelper, jwtTokenService);
|
||||
jwtAuthenticationFilter.setAuthenticationManager(manager);
|
||||
return jwtAuthenticationFilter;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
package ru.micord.ervu.security;
|
||||
|
||||
public class SecurityConstants {
|
||||
public static final String ESIA_LOGOUT = "/esia/logout";
|
||||
}
|
||||
|
|
@ -2,16 +2,21 @@ package ru.micord.ervu.security.esia.controller;
|
|||
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import ru.micord.ervu.security.esia.model.PersonDataModel;
|
||||
import ru.micord.ervu.security.esia.model.PersonModel;
|
||||
import ru.micord.ervu.security.esia.service.EsiaAuthService;
|
||||
import ru.micord.ervu.security.esia.service.PersonalDataService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import ru.micord.ervu.security.webbpm.jwt.service.JwtTokenService;
|
||||
|
||||
/**
|
||||
* @author Eduard Tihomirov
|
||||
|
|
@ -25,13 +30,16 @@ public class EsiaController {
|
|||
@Autowired
|
||||
private PersonalDataService personalDataService;
|
||||
|
||||
@Autowired
|
||||
private JwtTokenService jwtTokenService;
|
||||
|
||||
@RequestMapping(value = "/esia/url")
|
||||
public String getEsiaUrl() {
|
||||
return esiaAuthService.generateAuthCodeUrl();
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/esia/auth", params = "code", method = RequestMethod.GET)
|
||||
public boolean esiaAuth(@RequestParam("code") String code, HttpServletRequest request, HttpServletResponse response) {
|
||||
@GetMapping(value = "/esia/auth", params = "code")
|
||||
public ResponseEntity<?> esiaAuth(@RequestParam("code") String code, HttpServletRequest request, HttpServletResponse response) {
|
||||
return esiaAuthService.getEsiaTokensByCode(code, request, response);
|
||||
}
|
||||
|
||||
|
|
@ -42,29 +50,18 @@ public class EsiaController {
|
|||
|
||||
@RequestMapping(value = "/esia/person")
|
||||
public PersonDataModel getPersonModel(HttpServletRequest request) {
|
||||
String accessToken = null;
|
||||
Cookie[] cookies = request.getCookies();
|
||||
if (cookies != null) {
|
||||
for (Cookie cookie : cookies) {
|
||||
if (cookie.getName().equals("access_token")) {
|
||||
accessToken = cookie.getValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (accessToken == null) {
|
||||
return null;
|
||||
}
|
||||
String accessToken = jwtTokenService.getAccessToken(request);
|
||||
DateFormat df = new SimpleDateFormat("dd.MM.yyyy");
|
||||
PersonModel personModel = personalDataService.getPersonModel(accessToken);
|
||||
PersonDataModel personDataModel = new PersonDataModel();
|
||||
personDataModel.birthDate = df.format(personModel.getBirthDate());
|
||||
personDataModel.birthDate = personModel.getBirthDate();
|
||||
personDataModel.fullname = personModel.getLastName() + " " + personModel.getFirstName() + " "
|
||||
+ personModel.getMiddleName();
|
||||
personDataModel.snils = personModel.getSnils();
|
||||
personDataModel.seriesAndNumber =
|
||||
personModel.getPassportModel().getSeries() + " " + personModel.getPassportModel()
|
||||
.getNumber();
|
||||
personDataModel.issueDate = df.format(personModel.getPassportModel().getIssueDate());
|
||||
personDataModel.issueDate = personModel.getPassportModel().getIssueDate();
|
||||
personDataModel.issuedBy = personModel.getPassportModel().getIssuedBy();
|
||||
personDataModel.issueId = personModel.getPassportModel().getIssueId();
|
||||
return personDataModel;
|
||||
|
|
@ -72,24 +69,8 @@ public class EsiaController {
|
|||
|
||||
@RequestMapping(value = "/esia/userfullname")
|
||||
public String getUserFullname(HttpServletRequest request) {
|
||||
String accessToken = null;
|
||||
Cookie[] cookies = request.getCookies();
|
||||
if (cookies != null) {
|
||||
for (Cookie cookie : cookies) {
|
||||
if (cookie.getName().equals("access_token")) {
|
||||
accessToken = cookie.getValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (accessToken == null) {
|
||||
return null;
|
||||
}
|
||||
String accessToken = jwtTokenService.getAccessToken(request);
|
||||
PersonModel personModel = personalDataService.getPersonModel(accessToken);
|
||||
return personModel.getLastName() + " " + personModel.getFirstName().charAt(0) + ". " + personModel.getMiddleName().charAt(0) + ".";
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/esia/logout")
|
||||
public String logout(HttpServletRequest request, HttpServletResponse response) {
|
||||
return esiaAuthService.logout(request, response);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,7 @@
|
|||
package ru.micord.ervu.security.esia.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
|
||||
/**
|
||||
|
|
@ -18,8 +16,7 @@ public class PassportModel implements Serializable {
|
|||
|
||||
private String number;
|
||||
|
||||
@JsonFormat(pattern = "dd.MM.yyyy")
|
||||
private Date issueDate;
|
||||
private String issueDate;
|
||||
|
||||
private String issueId;
|
||||
|
||||
|
|
@ -41,11 +38,11 @@ public class PassportModel implements Serializable {
|
|||
this.number = number;
|
||||
}
|
||||
|
||||
public Date getIssueDate() {
|
||||
public String getIssueDate() {
|
||||
return issueDate;
|
||||
}
|
||||
|
||||
public void setIssueDate(Date issueDate) {
|
||||
public void setIssueDate(String issueDate) {
|
||||
this.issueDate = issueDate;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,7 @@
|
|||
package ru.micord.ervu.security.esia.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
|
||||
/**
|
||||
|
|
@ -24,8 +22,7 @@ public class PersonModel implements Serializable {
|
|||
|
||||
private String middleName;
|
||||
|
||||
@JsonFormat(pattern = "dd.MM.yyyy")
|
||||
private Date birthDate;
|
||||
private String birthDate;
|
||||
|
||||
private String snils;
|
||||
|
||||
|
|
@ -71,11 +68,11 @@ public class PersonModel implements Serializable {
|
|||
this.middleName = middleName;
|
||||
}
|
||||
|
||||
public Date getBirthDate() {
|
||||
public String getBirthDate() {
|
||||
return birthDate;
|
||||
}
|
||||
|
||||
public void setBirthDate(Date birthDate) {
|
||||
public void setBirthDate(String birthDate) {
|
||||
this.birthDate = birthDate;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,16 +25,22 @@ 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.core.context.SecurityContext;
|
||||
import ru.micord.ervu.kafka.model.Document;
|
||||
import ru.micord.ervu.kafka.model.Person;
|
||||
import ru.micord.ervu.kafka.model.Response;
|
||||
import ru.micord.ervu.kafka.service.ReplyingKafkaService;
|
||||
import ru.micord.ervu.security.esia.token.TokensStore;
|
||||
import ru.micord.ervu.security.esia.config.EsiaConfig;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.stereotype.Service;
|
||||
import ru.micord.ervu.security.webbpm.jwt.JwtAuthentication;
|
||||
import ru.micord.ervu.security.webbpm.jwt.helper.SecurityHelper;
|
||||
import ru.micord.ervu.security.esia.model.EsiaAccessToken;
|
||||
import ru.micord.ervu.security.esia.model.EsiaHeader;
|
||||
import ru.micord.ervu.security.esia.model.EsiaTokenResponse;
|
||||
|
|
@ -48,10 +54,6 @@ import ru.micord.ervu.security.webbpm.jwt.model.Token;
|
|||
*/
|
||||
@Service
|
||||
public class EsiaAuthService {
|
||||
|
||||
@Value("${cookie.path:#{null}}")
|
||||
private String path;
|
||||
|
||||
@Autowired
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
|
|
@ -68,6 +70,9 @@ public class EsiaAuthService {
|
|||
@Autowired
|
||||
private PersonalDataService personalDataService;
|
||||
|
||||
@Autowired
|
||||
private SecurityHelper securityHelper;
|
||||
|
||||
@Value("${ervu.kafka.reply.topic}")
|
||||
private String requestReplyTopic;
|
||||
|
||||
|
|
@ -145,7 +150,7 @@ public class EsiaAuthService {
|
|||
return uriBuilder.toString();
|
||||
}
|
||||
|
||||
public boolean getEsiaTokensByCode(String esiaAuthCode, HttpServletRequest request, HttpServletResponse response) {
|
||||
public ResponseEntity<?> getEsiaTokensByCode(String esiaAuthCode, HttpServletRequest request, HttpServletResponse response) {
|
||||
try {
|
||||
String clientId = esiaConfig.getClientId();
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy.MM.dd HH:mm:ss xx");
|
||||
|
|
@ -187,54 +192,49 @@ public class EsiaAuthService {
|
|||
.build()
|
||||
.send(postReq, HttpResponse.BodyHandlers.ofString());
|
||||
String responseString = postResp.body();
|
||||
EsiaTokenResponse tokenResponse = objectMapper.readValue(responseString, EsiaTokenResponse.class);
|
||||
if (tokenResponse != null && tokenResponse.getError() != null) {
|
||||
EsiaTokenResponse tokenResponse = objectMapper.readValue(responseString,
|
||||
EsiaTokenResponse.class
|
||||
);
|
||||
|
||||
if (tokenResponse == null) {
|
||||
throw new IllegalStateException("Got empty esia response");
|
||||
}
|
||||
|
||||
if (tokenResponse.getError() != null) {
|
||||
throw new RuntimeException(tokenResponse.getError_description());
|
||||
}
|
||||
String cookiePath = null;
|
||||
if (path != null) {
|
||||
cookiePath = path;
|
||||
}
|
||||
else {
|
||||
cookiePath = request.getContextPath();
|
||||
}
|
||||
String accessToken = tokenResponse.getAccess_token();
|
||||
boolean verifyResult = verifyToken(accessToken);
|
||||
if (!verifyResult) {
|
||||
throw new RuntimeException("Token not valid");
|
||||
}
|
||||
Cookie cookie = new Cookie("access_token", accessToken);
|
||||
cookie.setHttpOnly(true);
|
||||
cookie.setPath(cookiePath);
|
||||
response.addCookie(cookie);
|
||||
|
||||
String refreshToken = tokenResponse.getRefresh_token();
|
||||
Cookie cookieRefresh = new Cookie("refresh_token", refreshToken);
|
||||
cookieRefresh.setHttpOnly(true);
|
||||
|
||||
cookieRefresh.setPath(cookiePath);
|
||||
response.addCookie(cookieRefresh);
|
||||
|
||||
byte[] decodedBytes = Base64.getDecoder()
|
||||
.decode(
|
||||
accessToken.substring(accessToken.indexOf('.') + 1, accessToken.lastIndexOf('.')));
|
||||
String decodedString = new String(decodedBytes);
|
||||
EsiaAccessToken esiaAccessToken = objectMapper.readValue(decodedString, EsiaAccessToken.class);
|
||||
String ervuId = getErvuId(accessToken);
|
||||
Token token = jwtTokenService.createAccessToken(esiaAccessToken.getSbj_id(), tokenResponse.getExpires_in(), ervuId);
|
||||
Cookie authToken = new Cookie("auth_token", token.getValue());
|
||||
authToken.setPath(cookiePath);
|
||||
authToken.setHttpOnly(true);
|
||||
response.addCookie(authToken);
|
||||
SecurityContextHolder.getContext()
|
||||
.setAuthentication(
|
||||
new UsernamePasswordAuthenticationToken(esiaAccessToken.getSbj_id(), null));
|
||||
|
||||
Cookie isAuth = new Cookie("webbpm.ervu-lkrp-fl", "true");
|
||||
isAuth.setMaxAge(tokenResponse.getExpires_in().intValue());
|
||||
isAuth.setPath("/");
|
||||
response.addCookie(isAuth);
|
||||
return true;
|
||||
EsiaAccessToken esiaAccessToken = personalDataService.readToken(accessToken);
|
||||
String prnOid = esiaAccessToken.getSbj_id();
|
||||
Long expiresIn = tokenResponse.getExpires_in();
|
||||
TokensStore.addAccessToken(prnOid, accessToken, expiresIn);
|
||||
TokensStore.addRefreshToken(prnOid, refreshToken, expiresIn);
|
||||
Response ervuIdResponse = getErvuIdResponse(accessToken);
|
||||
Token token = jwtTokenService.createAccessToken(esiaAccessToken.getSbj_id(), expiresIn, ervuIdResponse.getErvuId());
|
||||
int expiry = tokenResponse.getExpires_in().intValue();
|
||||
Cookie accessCookie = securityHelper.createAccessCookie(token.getValue(), expiry);
|
||||
response.addCookie(accessCookie);
|
||||
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
|
||||
new UsernamePasswordAuthenticationToken(token.getUserAccountId(), null);
|
||||
SecurityContext context = SecurityContextHolder.createEmptyContext();
|
||||
JwtAuthentication authentication = new JwtAuthentication(usernamePasswordAuthenticationToken,
|
||||
esiaAccessToken.getSbj_id(), token.getValue());
|
||||
context.setAuthentication(authentication);
|
||||
SecurityContextHolder.setContext(context);
|
||||
Cookie authMarkerCookie = securityHelper.createAuthMarkerCookie("true", expiry);
|
||||
response.addCookie(authMarkerCookie);
|
||||
if (ervuIdResponse.getErrorData() != null) {
|
||||
return new ResponseEntity<>(
|
||||
"Доступ запрещен. " + ervuIdResponse.getErrorData().getName(),
|
||||
HttpStatus.FORBIDDEN
|
||||
);
|
||||
}
|
||||
return ResponseEntity.ok("Authentication successful");
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
|
|
@ -243,15 +243,7 @@ public class EsiaAuthService {
|
|||
|
||||
public void getEsiaTokensByRefreshToken(HttpServletRequest request, HttpServletResponse response) {
|
||||
try {
|
||||
String refreshToken = null;
|
||||
Cookie[] cookies = request.getCookies();
|
||||
if (cookies != null) {
|
||||
for (Cookie cookie : cookies) {
|
||||
if (cookie.getName().equals("refresh_token")) {
|
||||
refreshToken = cookie.getValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
String refreshToken = jwtTokenService.getRefreshToken(request);
|
||||
String clientId = esiaConfig.getClientId();
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy.MM.dd HH:mm:ss xx");
|
||||
ZonedDateTime dt = ZonedDateTime.now();
|
||||
|
|
@ -300,43 +292,26 @@ public class EsiaAuthService {
|
|||
if (!verifyResult) {
|
||||
throw new RuntimeException("Token not valid");
|
||||
}
|
||||
Cookie cookie = new Cookie("access_token", accessToken);
|
||||
cookie.setHttpOnly(true);
|
||||
String cookiePath = null;
|
||||
if (path != null) {
|
||||
cookiePath = path;
|
||||
}
|
||||
else {
|
||||
cookiePath = request.getContextPath();
|
||||
}
|
||||
cookie.setPath(cookiePath);
|
||||
response.addCookie(cookie);
|
||||
|
||||
String newRefreshToken = tokenResponse.getRefresh_token();
|
||||
Cookie cookieRefresh = new Cookie("refresh_token", newRefreshToken);
|
||||
cookieRefresh.setHttpOnly(true);
|
||||
cookieRefresh.setPath(cookiePath);
|
||||
response.addCookie(cookieRefresh);
|
||||
|
||||
byte[] decodedBytes = Base64.getDecoder()
|
||||
.decode(
|
||||
accessToken.substring(accessToken.indexOf('.') + 1, accessToken.lastIndexOf('.')));
|
||||
String decodedString = new String(decodedBytes);
|
||||
EsiaAccessToken esiaAccessToken = objectMapper.readValue(decodedString, EsiaAccessToken.class);
|
||||
String ervuId = getErvuId(accessToken);
|
||||
Token token = jwtTokenService.createAccessToken(esiaAccessToken.getSbj_id(), tokenResponse.getExpires_in(), ervuId);
|
||||
Cookie authToken = new Cookie("auth_token", token.getValue());
|
||||
authToken.setPath(cookiePath);
|
||||
authToken.setHttpOnly(true);
|
||||
response.addCookie(authToken);
|
||||
SecurityContextHolder.getContext()
|
||||
.setAuthentication(
|
||||
new UsernamePasswordAuthenticationToken(esiaAccessToken.getSbj_id(), null));
|
||||
|
||||
Cookie isAuth = new Cookie("webbpm.ervu-lkrp-fl", "true");
|
||||
isAuth.setMaxAge(tokenResponse.getExpires_in().intValue());
|
||||
isAuth.setPath("/");
|
||||
response.addCookie(isAuth);
|
||||
EsiaAccessToken esiaAccessToken = personalDataService.readToken(accessToken);
|
||||
String prnOid = esiaAccessToken.getSbj_id();
|
||||
Long expiresIn = tokenResponse.getExpires_in();
|
||||
TokensStore.addAccessToken(prnOid, accessToken, expiresIn);
|
||||
TokensStore.addRefreshToken(prnOid, newRefreshToken, expiresIn);
|
||||
Response ervuIdResponse = getErvuIdResponse(accessToken);
|
||||
Token token = jwtTokenService.createAccessToken(esiaAccessToken.getSbj_id(), expiresIn, ervuIdResponse.getErvuId());
|
||||
int expiry = tokenResponse.getExpires_in().intValue();
|
||||
Cookie accessCookie = securityHelper.createAccessCookie(token.getValue(), expiry);
|
||||
response.addCookie(accessCookie);
|
||||
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
|
||||
new UsernamePasswordAuthenticationToken(token.getUserAccountId(), null);
|
||||
SecurityContext context = SecurityContextHolder.createEmptyContext();
|
||||
JwtAuthentication authentication = new JwtAuthentication(usernamePasswordAuthenticationToken,
|
||||
esiaAccessToken.getSbj_id(), token.getValue());
|
||||
context.setAuthentication(authentication);
|
||||
SecurityContextHolder.setContext(context);
|
||||
Cookie authMarkerCookie = securityHelper.createAuthMarkerCookie("true", expiry);
|
||||
response.addCookie(authMarkerCookie);
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
|
|
@ -377,23 +352,10 @@ public class EsiaAuthService {
|
|||
|
||||
public String logout(HttpServletRequest request, HttpServletResponse response) {
|
||||
try {
|
||||
Cookie[] cookies = request.getCookies();
|
||||
if (cookies != null)
|
||||
for (Cookie cookie : cookies) {
|
||||
if (cookie.getName().equals("webbpm.ervu-lkrp-fl")) {
|
||||
cookie.setValue("");
|
||||
cookie.setPath("/");
|
||||
cookie.setMaxAge(0);
|
||||
response.addCookie(cookie);
|
||||
}
|
||||
else if (cookie.getName().equals("auth_token") || cookie.getName().equals("refresh_token")
|
||||
|| cookie.getName().equals("access_token")) {
|
||||
cookie.setValue("");
|
||||
cookie.setPath(cookie.getPath());
|
||||
cookie.setMaxAge(0);
|
||||
response.addCookie(cookie);
|
||||
}
|
||||
}
|
||||
securityHelper.clearAccessCookies(response);
|
||||
String userId = jwtTokenService.getUserAccountId(request);
|
||||
TokensStore.removeAccessToken(userId);
|
||||
TokensStore.removeRefreshToken(userId);
|
||||
String logoutUrl = esiaConfig.getEsiaBaseUri() + esiaConfig.getEsiaLogoutUrl();
|
||||
String redirectUrl = esiaConfig.getRedirectUrl();
|
||||
URL url = new URL(logoutUrl);
|
||||
|
|
@ -407,22 +369,14 @@ public class EsiaAuthService {
|
|||
}
|
||||
}
|
||||
|
||||
public String getErvuId(String accessToken) {
|
||||
public Response getErvuIdResponse(String accessToken) {
|
||||
try {
|
||||
PersonModel personModel = personalDataService.getPersonModel(accessToken);
|
||||
Person person = copyToPerson(personModel);
|
||||
String kafkaResponse = replyingKafkaService.sendMessageAndGetReply(requestTopic,
|
||||
requestReplyTopic, objectMapper.writeValueAsString(person)
|
||||
);
|
||||
Response response = objectMapper.readValue(kafkaResponse, Response.class);
|
||||
if (response.getErrorData() != null) {
|
||||
throw new RuntimeException(
|
||||
"Error code = " + response.getErrorData().getCode() + ", error name = "
|
||||
+ response.getErrorData().getName());
|
||||
}
|
||||
else {
|
||||
return response.getErvuId();
|
||||
}
|
||||
return objectMapper.readValue(kafkaResponse, Response.class);
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
|
|
@ -431,7 +385,7 @@ public class EsiaAuthService {
|
|||
|
||||
private Person copyToPerson(PersonModel personModel) {
|
||||
Person person = new Person();
|
||||
person.setBirthDate(personModel.getBirthDate().toString());
|
||||
person.setBirthDate(personModel.getBirthDate());
|
||||
person.setFirstName(personModel.getFirstName());
|
||||
person.setLastName(personModel.getLastName());
|
||||
person.setSnils(personModel.getSnils());
|
||||
|
|
@ -439,7 +393,8 @@ public class EsiaAuthService {
|
|||
Document document = new Document();
|
||||
document.setNumber(personModel.getPassportModel().getNumber());
|
||||
document.setSeries(personModel.getPassportModel().getSeries());
|
||||
document.setIssueDate(personModel.getPassportModel().getIssueDate().toString());
|
||||
document.setIssueDate(personModel.getPassportModel().getIssueDate());
|
||||
person.setDocument(document);
|
||||
return person;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,8 +10,6 @@ import ru.micord.ervu.security.esia.model.PersonModel;
|
|||
public interface PersonalDataService {
|
||||
|
||||
PersonModel getPersonModel(String accessToken);
|
||||
|
||||
EsiaAccessToken readToken(String accessToken);
|
||||
|
||||
EsiaHeader readHeader(String accessToken);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
package ru.micord.ervu.security.esia.token;
|
||||
|
||||
/**
|
||||
* @author Eduard Tihomirov
|
||||
*/
|
||||
public class ExpiringToken {
|
||||
private String accessToken;
|
||||
private long expiryTime;
|
||||
|
||||
public ExpiringToken(String accessToken, long expiryTime) {
|
||||
this.accessToken = accessToken;
|
||||
this.expiryTime = expiryTime;
|
||||
}
|
||||
|
||||
public String getAccessToken() {
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
public void setAccessToken(String accessToken) {
|
||||
this.accessToken = accessToken;
|
||||
}
|
||||
|
||||
public long getExpiryTime() {
|
||||
return expiryTime;
|
||||
}
|
||||
|
||||
public void setExpiryTime(long expiryTime) {
|
||||
this.expiryTime = expiryTime;
|
||||
}
|
||||
|
||||
boolean isExpired() {
|
||||
return System.currentTimeMillis() > expiryTime;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package ru.micord.ervu.security.esia.token;
|
||||
|
||||
import net.javacrumbs.shedlock.core.SchedulerLock;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* @author Eduard Tihomirov
|
||||
*/
|
||||
@Service
|
||||
public class TokensClearShedulerService {
|
||||
@Scheduled(cron = "${esia.token.clear.cron:0 0 */1 * * *}")
|
||||
@SchedulerLock(name = "clearToken")
|
||||
@Transactional
|
||||
public void load() {
|
||||
TokensStore.removeExpiredRefreshToken();
|
||||
TokensStore.removeExpiredAccessToken();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
package ru.micord.ervu.security.esia.token;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* @author Eduard Tihomirov
|
||||
*/
|
||||
public class TokensStore {
|
||||
private static final Map<String, ExpiringToken> accessTokensMap = new ConcurrentHashMap<>();
|
||||
private static final Map<String, ExpiringToken> refreshTokensMap = new ConcurrentHashMap<>();
|
||||
|
||||
public static void addAccessToken(String prnOid, String token, long expiresIn) {
|
||||
if (token != null) {
|
||||
long expiryTime = System.currentTimeMillis() + 1000L * expiresIn;
|
||||
accessTokensMap.put(prnOid, new ExpiringToken(token, expiryTime));
|
||||
}
|
||||
}
|
||||
|
||||
public static String getAccessToken(String prnOid) {
|
||||
return accessTokensMap.get(prnOid).getAccessToken();
|
||||
}
|
||||
|
||||
public static void removeExpiredAccessToken() {
|
||||
for (String key : accessTokensMap.keySet()) {
|
||||
ExpiringToken token = accessTokensMap.get(key);
|
||||
if (token != null && token.isExpired()) {
|
||||
accessTokensMap.remove(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void removeExpiredRefreshToken() {
|
||||
for (String key : refreshTokensMap.keySet()) {
|
||||
ExpiringToken token = refreshTokensMap.get(key);
|
||||
if (token != null && token.isExpired()) {
|
||||
refreshTokensMap.remove(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void removeAccessToken(String prnOid) {
|
||||
accessTokensMap.remove(prnOid);
|
||||
}
|
||||
|
||||
public static void addRefreshToken(String prnOid, String token, long expiresIn) {
|
||||
if (token != null) {
|
||||
long expiryTime = System.currentTimeMillis() + 1000L * expiresIn;
|
||||
refreshTokensMap.put(prnOid, new ExpiringToken(token, expiryTime));
|
||||
}
|
||||
}
|
||||
|
||||
public static String getRefreshToken(String prnOid) {
|
||||
return refreshTokensMap.get(prnOid).getAccessToken();
|
||||
}
|
||||
|
||||
public static void removeRefreshToken(String prnOid) {
|
||||
refreshTokensMap.remove(prnOid);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
package ru.micord.ervu.security.filter;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
import org.springframework.web.servlet.HandlerExceptionResolver;
|
||||
|
||||
@Component
|
||||
public class FilterChainExceptionHandler extends OncePerRequestFilter {
|
||||
@Autowired
|
||||
@Qualifier("handlerExceptionResolver")
|
||||
private HandlerExceptionResolver resolver;
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
|
||||
FilterChain filterChain) {
|
||||
try {
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
catch (Exception e) {
|
||||
resolver.resolveException(request, response, null, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
package ru.micord.ervu.security.webbpm.jwt;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import io.jsonwebtoken.ExpiredJwtException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
|
|
@ -44,10 +46,12 @@ public class JwtAuthenticationProvider implements AuthenticationProvider {
|
|||
throw new BadCredentialsException("Auth token is not valid for user " + token.getUserAccountId());
|
||||
}
|
||||
|
||||
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
|
||||
new UsernamePasswordAuthenticationToken(token.getUserAccountId(), null);
|
||||
UsernamePasswordAuthenticationToken pwdToken =
|
||||
UsernamePasswordAuthenticationToken.authenticated(token.getUserAccountId(), null,
|
||||
Collections.emptyList()
|
||||
);
|
||||
|
||||
return new JwtAuthentication(usernamePasswordAuthenticationToken, token.getUserAccountId());
|
||||
return new JwtAuthentication(pwdToken, token.getUserAccountId(), token.getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -0,0 +1,33 @@
|
|||
package ru.micord.ervu.security.webbpm.jwt;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
|
||||
import static ru.micord.ervu.security.webbpm.jwt.util.SecurityUtil.extractAuthToken;
|
||||
|
||||
public final class JwtMatcher implements RequestMatcher {
|
||||
private final Set<AntPathRequestMatcher> excludedPathMatchers;
|
||||
private final AntPathRequestMatcher securedMatcher;
|
||||
|
||||
public JwtMatcher(String securedPath, String... excludedPaths) {
|
||||
this.securedMatcher = new AntPathRequestMatcher(securedPath);
|
||||
this.excludedPathMatchers = Arrays.stream(excludedPaths)
|
||||
.map(AntPathRequestMatcher::new)
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(HttpServletRequest request) {
|
||||
if (this.excludedPathMatchers.stream().anyMatch(matcher -> matcher.matches(request))) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
return extractAuthToken(request) != null && this.securedMatcher.matches(request);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,6 @@ import java.io.IOException;
|
|||
import java.lang.invoke.MethodHandles;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
|
|
@ -16,69 +15,81 @@ import org.springframework.security.core.AuthenticationException;
|
|||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import ru.micord.ervu.security.webbpm.jwt.JwtAuthentication;
|
||||
import ru.micord.ervu.security.webbpm.jwt.helper.SecurityHelper;
|
||||
import ru.micord.ervu.security.webbpm.jwt.model.Token;
|
||||
import ru.micord.ervu.security.webbpm.jwt.service.JwtTokenService;
|
||||
|
||||
import static ru.micord.ervu.security.webbpm.jwt.util.SecurityUtil.extractAuthToken;
|
||||
|
||||
|
||||
/**
|
||||
* @author Flyur Karimov
|
||||
*/
|
||||
public class JwtAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(
|
||||
MethodHandles.lookup().lookupClass());
|
||||
|
||||
private final AuthenticationEntryPoint entryPoint;
|
||||
|
||||
public JwtAuthenticationFilter(String securityPath, AuthenticationEntryPoint entryPoint) {
|
||||
super(securityPath);
|
||||
private final SecurityHelper securityHelper;
|
||||
|
||||
private final JwtTokenService jwtTokenService;
|
||||
|
||||
public JwtAuthenticationFilter(RequestMatcher requestMatcher,
|
||||
AuthenticationEntryPoint entryPoint,
|
||||
SecurityHelper securityHelper,
|
||||
JwtTokenService jwtTokenService) {
|
||||
super(requestMatcher);
|
||||
this.entryPoint = entryPoint;
|
||||
this.securityHelper = securityHelper;
|
||||
this.jwtTokenService = jwtTokenService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Authentication attemptAuthentication(HttpServletRequest httpServletRequest,
|
||||
HttpServletResponse httpServletResponse) throws AuthenticationException {
|
||||
String token = extractAuthTokenFromRequest(httpServletRequest);
|
||||
HttpServletResponse httpServletResponse)
|
||||
throws AuthenticationException {
|
||||
String tokenStr = extractAuthToken(httpServletRequest);
|
||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
if (authentication == null) {
|
||||
authentication = new JwtAuthentication(null, null, token);
|
||||
authentication = new JwtAuthentication(null, null, tokenStr);
|
||||
}
|
||||
try {
|
||||
authentication = getAuthenticationManager().authenticate(authentication);
|
||||
if (!httpServletRequest.getRequestURI().endsWith("esia/logout")) {
|
||||
Token token = jwtTokenService.getToken(tokenStr);
|
||||
String[] ids = token.getUserAccountId().split(":");
|
||||
if (ids.length != 2) {
|
||||
throw new CredentialsExpiredException("Invalid token. User has no ervuId");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (CredentialsExpiredException e) {
|
||||
securityHelper.clearAccessCookies(httpServletResponse);
|
||||
httpServletResponse.setStatus(401);
|
||||
LOGGER.warn(e.getMessage());
|
||||
return null;
|
||||
}
|
||||
return authentication;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean requiresAuthentication(HttpServletRequest request, HttpServletResponse response) {
|
||||
return extractAuthTokenFromRequest(request) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response,
|
||||
FilterChain chain, Authentication authentication) throws IOException, ServletException {
|
||||
FilterChain chain, Authentication authentication)
|
||||
throws IOException, ServletException {
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
|
||||
AuthenticationException exception) throws IOException, ServletException {
|
||||
protected void unsuccessfulAuthentication(HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
AuthenticationException exception)
|
||||
throws IOException, ServletException {
|
||||
LOGGER.error("Jwt unsuccessful authentication exception", exception);
|
||||
SecurityContextHolder.clearContext();
|
||||
entryPoint.commence(request, response, exception);
|
||||
}
|
||||
|
||||
public String extractAuthTokenFromRequest(HttpServletRequest httpRequest) {
|
||||
String token = null;
|
||||
Cookie[] cookies = httpRequest.getCookies();
|
||||
if (cookies != null) {
|
||||
for (Cookie cookie : cookies) {
|
||||
if (cookie.getName().equals("auth_token")) {
|
||||
token = cookie.getValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
return token;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,43 @@
|
|||
package ru.micord.ervu.security.webbpm.jwt.helper;
|
||||
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import ru.micord.ervu.security.webbpm.jwt.util.SecurityUtil;
|
||||
|
||||
import static ru.micord.ervu.security.webbpm.jwt.util.SecurityUtil.AUTH_MARKER;
|
||||
import static ru.micord.ervu.security.webbpm.jwt.util.SecurityUtil.AUTH_TOKEN;
|
||||
import static ru.micord.ervu.security.webbpm.jwt.util.SecurityUtil.createCookie;
|
||||
|
||||
public final class SecurityHelper {
|
||||
@Value("${cookie.path:#{null}}")
|
||||
private String accessCookiePath;
|
||||
|
||||
public void clearAccessCookies(HttpServletResponse response) {
|
||||
Cookie tokenCookie = createCookie(AUTH_TOKEN, null, null);
|
||||
tokenCookie.setMaxAge(0);
|
||||
tokenCookie.setPath(accessCookiePath);
|
||||
tokenCookie.setHttpOnly(true);
|
||||
response.addCookie(tokenCookie);
|
||||
|
||||
Cookie markerCookie = createCookie(AUTH_MARKER, null, null);
|
||||
markerCookie.setMaxAge(0);
|
||||
markerCookie.setPath("/");
|
||||
response.addCookie(markerCookie);
|
||||
}
|
||||
|
||||
public Cookie createAccessCookie(String cookieValue, int expiry) {
|
||||
Cookie authToken = createCookie(SecurityUtil.AUTH_TOKEN, cookieValue, accessCookiePath);
|
||||
authToken.setPath(accessCookiePath);
|
||||
authToken.setMaxAge(expiry);
|
||||
return authToken;
|
||||
}
|
||||
|
||||
public Cookie createAuthMarkerCookie(String cookieValue, int expiry) {
|
||||
Cookie marker = createCookie(AUTH_MARKER, cookieValue, "/");
|
||||
marker.setMaxAge(expiry);
|
||||
marker.setHttpOnly(false);
|
||||
return marker;
|
||||
}
|
||||
}
|
||||
|
|
@ -3,8 +3,8 @@ package ru.micord.ervu.security.webbpm.jwt.service;
|
|||
import java.lang.invoke.MethodHandles;
|
||||
import java.util.Base64;
|
||||
import java.util.Date;
|
||||
import java.util.Optional;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import io.jsonwebtoken.Claims;
|
||||
import io.jsonwebtoken.Jwts;
|
||||
|
|
@ -13,14 +13,14 @@ import org.slf4j.Logger;
|
|||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.stereotype.Component;
|
||||
import ru.micord.ervu.security.webbpm.jwt.JwtAuthentication;
|
||||
import ru.micord.ervu.security.esia.token.TokensStore;
|
||||
import ru.micord.ervu.security.webbpm.jwt.model.Token;
|
||||
|
||||
import ru.cg.webbpm.modules.resources.api.ResourceMetadataUtils;
|
||||
|
||||
import static ru.micord.ervu.security.webbpm.jwt.util.SecurityUtil.extractAuthToken;
|
||||
|
||||
/**
|
||||
* @author Flyur Karimov
|
||||
*/
|
||||
|
|
@ -29,11 +29,13 @@ public class JwtTokenService {
|
|||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||
|
||||
@Value("${webbpm.security.token.issuer:}")
|
||||
@Value("${webbpm.security.token.issuer:#{null}}")
|
||||
private final String tokenIssuerName =
|
||||
ResourceMetadataUtils.PROJECT_GROUP_ID + "." + ResourceMetadataUtils.PROJECT_ARTIFACT_ID;
|
||||
private final SecretKey SIGNING_KEY;
|
||||
|
||||
@Autowired
|
||||
private HttpServletRequest request;
|
||||
|
||||
@Autowired
|
||||
public JwtTokenService(@Value("${webbpm.security.token.secret.key:ZjE5ZjMxNmYtODViZC00ZTQ5LWIxZmYtOGEzYzE3Yjc1MDVk}")
|
||||
|
|
@ -78,10 +80,27 @@ public class JwtTokenService {
|
|||
}
|
||||
|
||||
public String getErvuId() {
|
||||
Optional<Authentication> authentication = Optional.ofNullable(
|
||||
SecurityContextHolder.getContext().getAuthentication());
|
||||
String jwtToken = authentication.map(auth -> ((JwtAuthentication) auth).getToken())
|
||||
.orElseThrow(() -> new RuntimeException("Failed to get auth data. User unauthorized."));
|
||||
return getToken(jwtToken).getUserAccountId().split(":")[1];
|
||||
String extractAuthToken = extractAuthToken(request);
|
||||
return getToken(extractAuthToken).getUserAccountId().split(":")[1];
|
||||
}
|
||||
|
||||
public String getAccessToken(HttpServletRequest request) {
|
||||
return TokensStore.getAccessToken(getUserAccountId(request));
|
||||
}
|
||||
|
||||
public String getRefreshToken(HttpServletRequest request) {
|
||||
return TokensStore.getRefreshToken(getUserAccountId(request));
|
||||
}
|
||||
|
||||
public String getUserAccountId(HttpServletRequest request) {
|
||||
String authToken = extractAuthToken(request);
|
||||
|
||||
if (authToken != null) {
|
||||
String[] ids = getToken(authToken).getUserAccountId().split(":");
|
||||
return ids[0];
|
||||
}
|
||||
else {
|
||||
throw new RuntimeException("Failed to get auth data. User unauthorized.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,45 @@
|
|||
package ru.micord.ervu.security.webbpm.jwt.util;
|
||||
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.web.context.request.RequestAttributes;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.util.WebUtils;
|
||||
|
||||
import static org.springframework.web.context.request.RequestAttributes.REFERENCE_REQUEST;
|
||||
|
||||
public final class SecurityUtil {
|
||||
public static final String AUTH_TOKEN = "auth_token";
|
||||
|
||||
public static final String AUTH_MARKER = "webbpm.ervu-lkrp-fl";
|
||||
|
||||
private SecurityUtil() {
|
||||
//empty
|
||||
}
|
||||
|
||||
public static Cookie createCookie(String name, String value, String path) {
|
||||
String cookieValue = value != null ? URLEncoder.encode(value, StandardCharsets.UTF_8) : null;
|
||||
Cookie cookie = new Cookie(name, cookieValue);
|
||||
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
|
||||
HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(
|
||||
REFERENCE_REQUEST);
|
||||
|
||||
if (path != null) {
|
||||
cookie.setPath(path);
|
||||
}
|
||||
else {
|
||||
cookie.setPath(request.getContextPath());
|
||||
}
|
||||
cookie.setHttpOnly(true);
|
||||
|
||||
return cookie;
|
||||
}
|
||||
|
||||
public static String extractAuthToken(HttpServletRequest httpRequest) {
|
||||
Cookie cookie = WebUtils.getCookie(httpRequest, AUTH_TOKEN);
|
||||
return cookie != null ? cookie.getValue() : null;
|
||||
}
|
||||
}
|
||||
|
|
@ -25,10 +25,6 @@ public class ExtractRpcService extends Behavior {
|
|||
private final JwtTokenService jwtTokenService;
|
||||
private final ReplyingKafkaService<Object, Bytes> replyingKafkaService;
|
||||
|
||||
@Value("${ervu.kafka.subpoena.extract.request.topic}")
|
||||
private String subpoenaExtractRequestTopic;
|
||||
@Value("${ervu.kafka.subpoena.extract.reply.topic}")
|
||||
private String subpoenaExtractReplyTopic;
|
||||
@Value("${ervu.kafka.registry.extract.request.topic}")
|
||||
private String registryExtractRequestTopic;
|
||||
@Value("${ervu.kafka.registry.extract.reply.topic}")
|
||||
|
|
@ -48,13 +44,8 @@ public class ExtractRpcService extends Behavior {
|
|||
public FileData getExtract() {
|
||||
ExtractRequestDto request = new ExtractRequestDto(jwtTokenService.getErvuId(),
|
||||
formatExtractRegistry);
|
||||
String requestTopic = request.formatExtractRegistry().equals("1")
|
||||
? subpoenaExtractRequestTopic
|
||||
: registryExtractRequestTopic;
|
||||
String replyTopic = request.formatExtractRegistry().equals("1")
|
||||
? subpoenaExtractReplyTopic
|
||||
: registryExtractReplyTopic;
|
||||
byte[] reply = replyingKafkaService.sendMessageAndGetReply(requestTopic, replyTopic, request).get();
|
||||
byte[] reply = replyingKafkaService.sendMessageAndGetReply(registryExtractRequestTopic,
|
||||
registryExtractReplyTopic, request).get();
|
||||
|
||||
try {
|
||||
ResponseData responseData = ResponseData.parseFrom(reply);
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import org.springframework.util.StringUtils;
|
|||
*/
|
||||
public final class DateUtil {
|
||||
|
||||
private static final DateTimeFormatter DEFAULT_FORMATTER = DateTimeFormatter.ofPattern("dd.MM.yyyy");
|
||||
public static final DateTimeFormatter DEFAULT_FORMATTER = DateTimeFormatter.ofPattern("dd.MM.yyyy");
|
||||
|
||||
private DateUtil() {}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +0,0 @@
|
|||
<jboss-deployment-structure>
|
||||
<deployment>
|
||||
<dependencies>
|
||||
<module name="ru.CryptoPro.JCSP"/>
|
||||
<module name="ru.CryptoPro.JCP.ASN"/>
|
||||
<module name="ru.CryptoPro.JCP"/>
|
||||
<module name="com.objsys.asn1j.runtime"/>
|
||||
</dependencies>
|
||||
</deployment>
|
||||
</jboss-deployment-structure>
|
||||
43
config.md
43
config.md
|
|
@ -741,6 +741,49 @@ JBPM использует 3 корневых категории логирова
|
|||
"jivo_chat_widget_enabled": false
|
||||
```
|
||||
|
||||
# Описание конфигурации параметров проекта
|
||||
|
||||
В micord.env заданы следующие переменные окружения:
|
||||
|
||||
#### Подключение базы данных
|
||||
- `DB_APP_USERNAME` - логин пользователя для подключения к базе данных
|
||||
- `DB_APP_PASSWORD` - пароль пользователя для доступа к базе данных
|
||||
- `DB_APP_HOST` - адрес сервера базы данных
|
||||
- `DB_APP_PORT` - порт, на котором осуществляется подключение к базе данных
|
||||
- `DB_APP_NAME` - имя базы данных, к которой необходимо подключиться
|
||||
|
||||
#### Аутентификация через ЕСИА
|
||||
- `ESIA_SCOPES` - область доступа, позволяющие получить данные о пользователе. Тип данных, к которым система-клиент намерена получить доступ
|
||||
- `ESIA_BASE_URI` - базовый url для обращения в ЕСИА
|
||||
- `ESIA_CLIENT_ID` - идентификатор системы-клиента (мнемоника системы в ЕСИА указанная прописными буквами)
|
||||
- `ESIA_REDIRECT_URL` - ссылка, по которой должен быть направлен пользователь
|
||||
Важно: `ESIA_REDIRECT_URL` должна содержать полный адрес вплоть до последнего слэша:
|
||||
> - https://lkul.ervu.loc/ - правильное значение параметра
|
||||
> - https://lkul.ervu.loc - неправильное значение параметра
|
||||
|
||||
- `SIGN_URL` - url для подписания с помощью КриптоПро секрета клиента, необходимого для аутентификации через ЕСИА
|
||||
- `ESIA_CLIENT_CERT_HASH` - параметр, содержащий хэш сертификата (fingerprint сертификата) системы-клиента в hex–формате
|
||||
|
||||
#### Конфигурация и топики Kafka
|
||||
- `ERVU_KAFKA_BOOTSTRAP_SERVERS` - список пар хост:порт, использующихся для установки первоначального соединения с кластером Kafka
|
||||
- `ERVU_KAFKA_USERNAME` - пользователь для подключения к Kafka
|
||||
- `ERVU_KAFKA_PASSWORD` - пароль для подключения к Kafka
|
||||
- `ERVU_KAFKA_SASL_MECHANISM` - механизм SASL, используемый для клиентских подключений
|
||||
- `ERVU_KAFKA_SECURITY_PROTOCOL` - протокол, используемый для взаимодействия с брокерами
|
||||
- `ERVU_KAFKA_DOC_LOGIN_MODULE` - имя класса для входа в систему для SASL-соединений в формате, используемом конфигурационными файлами JAAS
|
||||
- `ERVU_KAFKA_GROUP_ID` - идентификатор группы потребителей, который отвечает за создание группы для объединения нескольких потребителей
|
||||
- `ERVU_KAFKA_REPLY_TIMEOUT` - таймаут ожидания ответа
|
||||
- `ERVU_KAFKA_REQUEST_TOPIC` - топик для отправки запроса на получение id пользователя в системе ЕРВУ
|
||||
- `ERVU_KAFKA_REPLY_TOPIC` - топик для получения id пользователя в системе ЕРВУ
|
||||
- `ERVU_KAFKA_RECRUIT_REQUEST_TOPIC` - топик для отправки запроса на получение данных о повестке, временных мерах и воинском учете
|
||||
- `ERVU_KAFKA_RECRUIT_REPLY_TOPIC` - топик для получения данных о повестке, временных мерах и воинском учете
|
||||
- `ERVU_KAFKA_RECRUIT_HEADER_CLASS` - класс для идентификации в заголовке запроса на получение данных о повестке, временных мерах и воинском учете
|
||||
- `ERVU_KAFKA_SUBPOENA_EXTRACT_REQUEST_TOPIC` - топик для отправки запроса на получение выписки из Реестра повесток
|
||||
- `ERVU_KAFKA_SUBPOENA_EXTRACT_REPLY_TOPIC` - топик для получения выписки из Реестра повесток
|
||||
- `ERVU_KAFKA_REGISTRY_EXTRACT_REQUEST_TOPIC` - топик для отправки запроса на получение выписки из Реестра воинского учета
|
||||
- `ERVU_KAFKA_REGISTRY_EXTRACT_REPLY_TOPIC` - топик для получения выписки из Реестра воинского учета
|
||||
- `ERVU_KAFKA_EXTRACT_HEADER_CLASS` - класс для идентификации в заголовке запроса на получение выписки из Реестра повесток/Реестра воинского учета
|
||||
|
||||
# Прочее
|
||||
|
||||
## Смена удалённого репозитория
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ ESIA_REDIRECT_URL=https://lkrp-dev.micord.ru/fl/
|
|||
SIGN_URL=https://ervu-sign-dev.k8s.micord.ru/sign
|
||||
SIGN_VERIFY_URL=https://ervu-sign-dev.k8s.micord.ru/verify
|
||||
|
||||
ERVU_KAFKA_BOOTSTRAP_SERVERS=localhost:9092
|
||||
ERVU_KAFKA_BOOTSTRAP_SERVERS=http://10.10.31.11:32609
|
||||
ERVU_KAFKA_USERNAME=user1
|
||||
ERVU_KAFKA_PASSWORD=Blfi9d2OFG
|
||||
ERVU_KAFKA_SASL_MECHANISM=SCRAM-SHA-256
|
||||
|
|
@ -28,9 +28,10 @@ ERVU_KAFKA_REPLY_TIMEOUT=30
|
|||
ERVU_KAFKA_RECRUIT_REQUEST_TOPIC=ervu.recruit.info.request
|
||||
ERVU_KAFKA_RECRUIT_REPLY_TOPIC=ervu.recruit.info.response
|
||||
ERVU_KAFKA_RECRUIT_HEADER_CLASS=Request@urn://rostelekom.ru/RP-SummonsTR/1.0.5
|
||||
ERVU_KAFKA_SUBPOENA_EXTRACT_REQUEST_TOPIC=ervu.subpoena.info.request
|
||||
ERVU_KAFKA_SUBPOENA_EXTRACT_REPLY_TOPIC=ervu.subpoena.info.response
|
||||
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
|
||||
|
||||
ESIA_TOKEN_CLEAR_CRON=0 0 */1 * * *
|
||||
COOKIE_PATH=/fl
|
||||
|
|
@ -75,11 +75,10 @@
|
|||
<property name="ervu.kafka.recruit.request.topic" value="ervu.recruit.info.request"/>
|
||||
<property name="ervu.kafka.recruit.reply.topic" value="ervu.recruit.info.response"/>
|
||||
<property name="ervu.kafka.recruit.header.class" value="Request@urn://rostelekom.ru/RP-SummonsTR/1.0.5"/>
|
||||
<property name="ervu.kafka.subpoena.extract.request.topic" value="ervu.subpoena.info.request"/>
|
||||
<property name="ervu.kafka.subpoena.extract.reply.topic" value="ervu.subpoena.info.response"/>
|
||||
<property name="ervu.kafka.registry.extract.request.topic" value="ervu.extract.info.request"/>
|
||||
<property name="ervu.kafka.registry.extract.reply.topic" value="ervu.extract.info.response"/>
|
||||
<property name="ervu.kafka.extract.header.class" value="request@urn://rostelekom.ru/ERVU-extractFromRegistryTR/1.0.3"/>
|
||||
<property name="esia.token.clear.cron" value="0 0 */1 * * *"/>
|
||||
<property name="sign.verify.url" value="https://ervu-sign-dev.k8s.micord.ru/verify"/>
|
||||
</system-properties>
|
||||
<management>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ru.micord.ervu.lkrp</groupId>
|
||||
<artifactId>fl</artifactId>
|
||||
<version>1.8.0-SNAPSHOT</version>
|
||||
<version>1.8.2</version>
|
||||
</parent>
|
||||
|
||||
<groupId>ru.micord.ervu.lkrp.fl</groupId>
|
||||
|
|
|
|||
92
frontend/package-lock.json
generated
92
frontend/package-lock.json
generated
|
|
@ -1624,9 +1624,9 @@
|
|||
}
|
||||
},
|
||||
"@webbpm/base-package": {
|
||||
"version": "3.178.2",
|
||||
"resolved": "https://repo.micord.ru/repository/npm-all/@webbpm/base-package/-/base-package-3.178.2.tgz",
|
||||
"integrity": "sha512-ShqAmiaGCvrg7ffrhntshwcZJVW8cK10JsMy/OT36p7iK6B/IR0YCJZZ+GIhakLo0CZsEokhcpKBdORvfOI55g==",
|
||||
"version": "3.182.0",
|
||||
"resolved": "https://repo.micord.ru/repository/npm-all/@webbpm/base-package/-/base-package-3.182.0.tgz",
|
||||
"integrity": "sha512-8pb1hMxjiHrOPCXhWoycSJqb7LT2ldSeWnHJmS8FD53ZRJqErcYj50Nj5Yz2lcoye0OVmhFtSv/YNyRVTQX6yw==",
|
||||
"requires": {
|
||||
"tslib": "^1.9.0"
|
||||
}
|
||||
|
|
@ -1857,11 +1857,6 @@
|
|||
"color-convert": "^1.9.0"
|
||||
}
|
||||
},
|
||||
"ansicolors": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://repo.micord.ru/repository/npm-all/ansicolors/-/ansicolors-0.2.1.tgz",
|
||||
"integrity": "sha512-tOIuy1/SK/dr94ZA0ckDohKXNeBNqZ4us6PjMVLs5h1w2GBB6uPtOknp2+VF4F/zcy9LI70W+Z+pE2Soajky1w=="
|
||||
},
|
||||
"anymatch": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://repo.micord.ru/repository/npm-all/anymatch/-/anymatch-2.0.0.tgz",
|
||||
|
|
@ -2065,6 +2060,7 @@
|
|||
"version": "2.6.4",
|
||||
"resolved": "https://repo.micord.ru/repository/npm-all/async/-/async-2.6.4.tgz",
|
||||
"integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"lodash": "^4.17.14"
|
||||
}
|
||||
|
|
@ -3081,15 +3077,6 @@
|
|||
"integrity": "sha512-feylzsbDxi1gPZ1IjystzIQZagYYLvfKrSuygUCgf7z6x790VEzze5QEkdSV1U58RA7Hi0+v6fv4K54atOzATg==",
|
||||
"dev": true
|
||||
},
|
||||
"cardinal": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://repo.micord.ru/repository/npm-all/cardinal/-/cardinal-1.0.0.tgz",
|
||||
"integrity": "sha512-INsuF4GyiFLk8C91FPokbKTc/rwHqV4JnfatVZ6GPhguP1qmkRWX2dp5tepYboYdPpGWisLVLI+KsXoXFPRSMg==",
|
||||
"requires": {
|
||||
"ansicolors": "~0.2.1",
|
||||
"redeyed": "~1.0.0"
|
||||
}
|
||||
},
|
||||
"chalk": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://repo.micord.ru/repository/npm-all/chalk/-/chalk-2.4.2.tgz",
|
||||
|
|
@ -3737,11 +3724,6 @@
|
|||
"integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
|
||||
"dev": true
|
||||
},
|
||||
"csv-parse": {
|
||||
"version": "4.16.3",
|
||||
"resolved": "https://repo.micord.ru/repository/npm-all/csv-parse/-/csv-parse-4.16.3.tgz",
|
||||
"integrity": "sha512-cO1I/zmz4w2dcKHVvpCr7JVRu8/FymG5OEpmvsZYlccYolPBLoVGKUHgNoc4ZGkFeFlWGEDmMyBM+TTqRdW/wg=="
|
||||
},
|
||||
"cyclist": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://repo.micord.ru/repository/npm-all/cyclist/-/cyclist-1.0.2.tgz",
|
||||
|
|
@ -4537,11 +4519,6 @@
|
|||
"resolved": "https://repo.micord.ru/repository/npm-all/esmarttokenjs/-/esmarttokenjs-2.2.1-cg.tgz",
|
||||
"integrity": "sha512-H48OuXYP8v/CAdxD5QWgfmg/6IXmnPG4uaS3Lmx6FR64NJjK46fLK4zDd3VF/52l/5WRxnIqNPGb5krLPviPuQ=="
|
||||
},
|
||||
"esprima": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://repo.micord.ru/repository/npm-all/esprima/-/esprima-3.0.0.tgz",
|
||||
"integrity": "sha512-xoBq/MIShSydNZOkjkoCEjqod963yHNXTLC40ypBhop6yPqflPz/vTinmCfSrGcywVLnSftRf6a0kJLdFdzemw=="
|
||||
},
|
||||
"esrecurse": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://repo.micord.ru/repository/npm-all/esrecurse/-/esrecurse-4.3.0.tgz",
|
||||
|
|
@ -5702,11 +5679,6 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"humanize": {
|
||||
"version": "0.0.9",
|
||||
"resolved": "https://repo.micord.ru/repository/npm-all/humanize/-/humanize-0.0.9.tgz",
|
||||
"integrity": "sha512-bvZZ7vXpr1RKoImjuQ45hJb5OvE2oJafHysiD/AL3nkqTZH2hFCjQ3YZfCd63FefDitbJze/ispUPP0gfDsT2Q=="
|
||||
},
|
||||
"humanize-ms": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://repo.micord.ru/repository/npm-all/humanize-ms/-/humanize-ms-1.2.1.tgz",
|
||||
|
|
@ -6521,7 +6493,8 @@
|
|||
"lodash": {
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://repo.micord.ru/repository/npm-all/lodash/-/lodash-4.17.21.tgz",
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
|
||||
"dev": true
|
||||
},
|
||||
"lodash-es": {
|
||||
"version": "4.17.21",
|
||||
|
|
@ -6721,11 +6694,6 @@
|
|||
"to-regex": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"microplugin": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://repo.micord.ru/repository/npm-all/microplugin/-/microplugin-0.0.3.tgz",
|
||||
"integrity": "sha512-3wKXex4/iyALV0GX2juow66J9dabkEMgHeZAihdLTaRTzm0N+RubXioNPpfIQDPuBRxr3JbjNt7B0Lr/3yE9yQ=="
|
||||
},
|
||||
"miller-rabin": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://repo.micord.ru/repository/npm-all/miller-rabin/-/miller-rabin-4.0.1.tgz",
|
||||
|
|
@ -6817,11 +6785,6 @@
|
|||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
},
|
||||
"minimist": {
|
||||
"version": "0.0.10",
|
||||
"resolved": "https://repo.micord.ru/repository/npm-all/minimist/-/minimist-0.0.10.tgz",
|
||||
"integrity": "sha512-iotkTvxc+TwOm5Ieim8VnSNvCDjCK9S8G3scJ50ZthspSxa7jx50jkhYduuAtAjvfDUwSgOwf8+If99AlOEhyw=="
|
||||
},
|
||||
"minipass": {
|
||||
"version": "2.9.0",
|
||||
"resolved": "https://repo.micord.ru/repository/npm-all/minipass/-/minipass-2.9.0.tgz",
|
||||
|
|
@ -7348,15 +7311,6 @@
|
|||
"is-wsl": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"optimist": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://repo.micord.ru/repository/npm-all/optimist/-/optimist-0.6.1.tgz",
|
||||
"integrity": "sha512-snN4O4TkigujZphWLN0E//nQmm7790RYaE53DdL7ZYwee2D8DDo9/EyYiKUfN3rneWUjhJnueija3G9I2i0h3g==",
|
||||
"requires": {
|
||||
"minimist": "~0.0.1",
|
||||
"wordwrap": "~0.0.2"
|
||||
}
|
||||
},
|
||||
"os-browserify": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://repo.micord.ru/repository/npm-all/os-browserify/-/os-browserify-0.3.0.tgz",
|
||||
|
|
@ -8143,14 +8097,6 @@
|
|||
"resolve": "^1.1.6"
|
||||
}
|
||||
},
|
||||
"redeyed": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://repo.micord.ru/repository/npm-all/redeyed/-/redeyed-1.0.1.tgz",
|
||||
"integrity": "sha512-8eEWsNCkV2rvwKLS1Cvp5agNjMhwRe2um+y32B2+3LqOzg4C9BBPs6vzAfV16Ivb8B9HPNKIqd8OrdBws8kNlQ==",
|
||||
"requires": {
|
||||
"esprima": "~3.0.0"
|
||||
}
|
||||
},
|
||||
"reflect-metadata": {
|
||||
"version": "0.1.13",
|
||||
"resolved": "https://repo.micord.ru/repository/npm-all/reflect-metadata/-/reflect-metadata-0.1.13.tgz",
|
||||
|
|
@ -8522,12 +8468,11 @@
|
|||
}
|
||||
},
|
||||
"selectize": {
|
||||
"version": "0.12.4-cg.10",
|
||||
"resolved": "https://repo.micord.ru/repository/npm-all/selectize/-/selectize-0.12.4-cg.10.tgz",
|
||||
"integrity": "sha512-hv6kGmsFfXzG40fOinr1hRmqXsSNQyir0U7VRLHUMUdOxegY9G6vMRGemvXpN2e72jelKdwhARwQIJ7BQhXZkQ==",
|
||||
"version": "0.12.4-cg.11",
|
||||
"resolved": "https://repo.micord.ru/repository/npm-all/selectize/-/selectize-0.12.4-cg.11.tgz",
|
||||
"integrity": "sha512-Fm1W6Ur2UNwRmTseaxHQuHlh1RS9zocO6qWu+vrKxdLILc7zN+RL2paXQZBAsLORNne3aLBDfIyMZ2ykxcbhVw==",
|
||||
"requires": {
|
||||
"microplugin": "0.0.3",
|
||||
"sifter": "^0.5.1"
|
||||
"jquery": ">=1.7.0"
|
||||
}
|
||||
},
|
||||
"semver": {
|
||||
|
|
@ -8805,18 +8750,6 @@
|
|||
"object-inspect": "^1.13.1"
|
||||
}
|
||||
},
|
||||
"sifter": {
|
||||
"version": "0.5.4",
|
||||
"resolved": "https://repo.micord.ru/repository/npm-all/sifter/-/sifter-0.5.4.tgz",
|
||||
"integrity": "sha512-t2yxTi/MM/ESup7XH5oMu8PUcttlekt269RqxARgnvS+7D/oP6RyA1x3M/5w8dG9OgkOyQ8hNRWelQ8Rj4TAQQ==",
|
||||
"requires": {
|
||||
"async": "^2.6.0",
|
||||
"cardinal": "^1.0.0",
|
||||
"csv-parse": "^4.6.5",
|
||||
"humanize": "^0.0.9",
|
||||
"optimist": "^0.6.1"
|
||||
}
|
||||
},
|
||||
"signal-exit": {
|
||||
"version": "3.0.7",
|
||||
"resolved": "https://repo.micord.ru/repository/npm-all/signal-exit/-/signal-exit-3.0.7.tgz",
|
||||
|
|
@ -10539,11 +10472,6 @@
|
|||
"has-tostringtag": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"wordwrap": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://repo.micord.ru/repository/npm-all/wordwrap/-/wordwrap-0.0.3.tgz",
|
||||
"integrity": "sha512-1tMA907+V4QmxV7dbRvb4/8MaRALK6q9Abid3ndMYnbyo8piisCmeONVqVSXqQA3KaP4SLt5b7ud6E2sqP8TFw=="
|
||||
},
|
||||
"worker-farm": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://repo.micord.ru/repository/npm-all/worker-farm/-/worker-farm-1.7.0.tgz",
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@
|
|||
"@angular/platform-browser-dynamic": "7.2.15",
|
||||
"@angular/router": "7.2.15",
|
||||
"@ng-bootstrap/ng-bootstrap": "4.1.1",
|
||||
"@webbpm/base-package": "3.178.2",
|
||||
"@webbpm/base-package": "3.182.0",
|
||||
"ag-grid-angular": "29.0.0-micord.4",
|
||||
"ag-grid-community": "29.0.0-micord.4",
|
||||
"angular-calendar": "0.28.28",
|
||||
|
|
@ -57,7 +57,7 @@
|
|||
"reflect-metadata": "0.1.13",
|
||||
"rxjs": "6.4.0",
|
||||
"rxjs-compat": "6.4.0",
|
||||
"selectize": "0.12.4-cg.10",
|
||||
"selectize": "0.12.4-cg.11",
|
||||
"systemjs": "0.21.4",
|
||||
"systemjs-plugin-babel": "0.0.25",
|
||||
"tslib": "1.9.3",
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ru.micord.ervu.lkrp</groupId>
|
||||
<artifactId>fl</artifactId>
|
||||
<version>1.8.0-SNAPSHOT</version>
|
||||
<version>1.8.2</version>
|
||||
</parent>
|
||||
|
||||
<groupId>ru.micord.ervu.lkrp.fl</groupId>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
"filter_cleanup_interval_hours": 720,
|
||||
"filter_cleanup_check_period_minutes": 30,
|
||||
"auth_method": "form",
|
||||
"enable.version.in.url": "%enable.version.in.url%",
|
||||
"enable.version.in.url": "false",
|
||||
"backend.context": "fl",
|
||||
"guard.confirm_exit": false,
|
||||
"message_service_error_timeout": "",
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
%project.version%
|
||||
1.8.2-SNAPSHOT
|
||||
|
|
|
|||
|
|
@ -3,3 +3,4 @@
|
|||
<a routerLink="/mydata" class="data">Мои данные</a>
|
||||
<button ngbDropdownItem class="exit" (click)="logout()">Выйти</button>
|
||||
</div>
|
||||
<button class="exit" *ngIf="!getIsAuth()" (click)="logout()">Выйти</button>
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import {forwardRef, NgModule} from "@angular/core";
|
||||
import {APP_INITIALIZER, forwardRef, NgModule} from "@angular/core";
|
||||
import {NgbModule} from "@ng-bootstrap/ng-bootstrap";
|
||||
import {CommonModule, registerLocaleData} from "@angular/common";
|
||||
import localeRu from '@angular/common/locales/ru';
|
||||
|
|
@ -23,6 +23,7 @@ import {TextWithDialogLinks} from "../../ervu/component/textwithdialoglinks/Text
|
|||
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";
|
||||
|
||||
registerLocaleData(localeRu);
|
||||
export const DIRECTIVES = [
|
||||
|
|
@ -37,6 +38,10 @@ export const DIRECTIVES = [
|
|||
forwardRef(() => InMemoryStaticGrid)
|
||||
];
|
||||
|
||||
export function checkAuthentication(authService: AuthenticationService): () => Promise<any> {
|
||||
return () => authService.checkAuthentication();
|
||||
}
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
|
|
@ -57,6 +62,13 @@ export const DIRECTIVES = [
|
|||
DIRECTIVES
|
||||
],
|
||||
providers: [
|
||||
AuthenticationService,
|
||||
{
|
||||
provide: APP_INITIALIZER,
|
||||
useFactory: checkAuthentication,
|
||||
deps: [AuthenticationService],
|
||||
multi: true,
|
||||
},
|
||||
{ provide: ProgressIndicationService, useClass: AppProgressIndicationService }
|
||||
],
|
||||
bootstrap: [],
|
||||
|
|
|
|||
|
|
@ -27,10 +27,10 @@ export class LogOutComponent implements OnInit{
|
|||
}
|
||||
}
|
||||
|
||||
public logout(): void {
|
||||
this.httpClient.get<string>("esia/logout").toPromise().then(url => {
|
||||
logout(): Promise<any> {
|
||||
return this.httpClient.post<string>('esia/logout', {}, { responseType: 'text' as 'json' }).toPromise().then(url => {
|
||||
window.open(url, "_self");
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
public getUserFullname(): string {
|
||||
|
|
|
|||
4
frontend/src/ts/modules/security/TokenConstants.ts
Normal file
4
frontend/src/ts/modules/security/TokenConstants.ts
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
export class TokenConstants {
|
||||
public static readonly CSRF_TOKEN_NAME = "XSRF-TOKEN";
|
||||
public static readonly CSRF_HEADER_NAME = "X-XSRF-TOKEN";
|
||||
}
|
||||
27
frontend/src/ts/modules/security/authentication.service.ts
Normal file
27
frontend/src/ts/modules/security/authentication.service.ts
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
import {Injectable} from '@angular/core';
|
||||
import {HttpClient} from '@angular/common/http';
|
||||
import {Observable} from "rxjs";
|
||||
import {CookieService} from "ngx-cookie";
|
||||
import {tap} from "rxjs/operators";
|
||||
import {AppConfigService} from "@webbpm/base-package";
|
||||
|
||||
@Injectable({providedIn: 'root'})
|
||||
export class AuthenticationService {
|
||||
|
||||
constructor(private http: HttpClient,
|
||||
private cookieService: CookieService,
|
||||
private appConfigService: AppConfigService) {
|
||||
}
|
||||
|
||||
checkAuthentication(): Promise<any>{
|
||||
return this.appConfigService.load().then(value => this.http.get<any>("version").toPromise())
|
||||
}
|
||||
|
||||
logout(): Promise<string> {
|
||||
return this.http.post<string>('esia/logout', {}).toPromise();
|
||||
}
|
||||
|
||||
public isAuthenticated(): boolean {
|
||||
return this.cookieService.get('webbpm.ervu-lkrp-fl') != null;
|
||||
}
|
||||
}
|
||||
|
|
@ -2,7 +2,8 @@ import {Injectable} from "@angular/core";
|
|||
import {ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot} from "@angular/router";
|
||||
import {Observable} from "rxjs";
|
||||
import {HttpClient, HttpParams} from "@angular/common/http";
|
||||
import {CookieService} from "ngx-cookie";
|
||||
import {MessagesService} from "@webbpm/base-package";
|
||||
import {AuthenticationService} from "../authentication.service";
|
||||
|
||||
@Injectable({providedIn:'root'})
|
||||
export abstract class AuthGuard implements CanActivate {
|
||||
|
|
@ -10,7 +11,8 @@ export abstract class AuthGuard implements CanActivate {
|
|||
protected constructor(
|
||||
protected router: Router,
|
||||
private httpClient: HttpClient,
|
||||
private cookieService: CookieService
|
||||
private authenticationService: AuthenticationService,
|
||||
private messageService: MessagesService
|
||||
) {
|
||||
}
|
||||
|
||||
|
|
@ -28,15 +30,30 @@ export abstract class AuthGuard implements CanActivate {
|
|||
return true;
|
||||
}
|
||||
else if (error) {
|
||||
throw new Error(error + ', error description =' + errorDescription);
|
||||
let errorMessage = error + ', error description =' + errorDescription;
|
||||
this.messageService.error(errorMessage)
|
||||
throw new Error(errorMessage);
|
||||
}
|
||||
else if (code) {
|
||||
const params = new HttpParams().set('code', code);
|
||||
this.httpClient.get<boolean>("esia/auth", {params: params}).toPromise().then(
|
||||
() => window.open(url.origin + url.pathname, "_self"))
|
||||
.catch((reason) =>
|
||||
console.error(reason)
|
||||
);
|
||||
this.httpClient.get("esia/auth",
|
||||
{
|
||||
params: params, responseType: 'text', observe: 'response', headers: {
|
||||
"Error-intercept-skip": "true"
|
||||
}
|
||||
})
|
||||
.toPromise()
|
||||
.then(
|
||||
(response) => {
|
||||
window.open(url.origin + url.pathname, "_self");
|
||||
})
|
||||
.catch((reason) => {
|
||||
let errorMessage = reason.error.messages != null
|
||||
? reason.error.messages
|
||||
: reason.error.replaceAll('\\', '');
|
||||
this.messageService.error(errorMessage);
|
||||
console.error(reason);
|
||||
});
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
|
|
@ -51,11 +68,7 @@ export abstract class AuthGuard implements CanActivate {
|
|||
});
|
||||
}
|
||||
|
||||
private checkAccess(): Promise<boolean> | boolean {
|
||||
return this.getIsAuth() != null;
|
||||
};
|
||||
|
||||
public getIsAuth(): string {
|
||||
return this.cookieService.get('webbpm.ervu-lkrp-fl');
|
||||
private checkAccess(): boolean {
|
||||
return this.authenticationService.isAuthenticated();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
import {HttpEvent, HttpHandler, HttpInterceptor, HttpRequest} from '@angular/common/http';
|
||||
import {Injectable} from '@angular/core';
|
||||
import {Observable} from 'rxjs';
|
||||
import {CookieService} from "ngx-cookie";
|
||||
import {TokenConstants} from "../../security/TokenConstants";
|
||||
|
||||
@Injectable()
|
||||
export class AbsoluteUrlCsrfInterceptor implements HttpInterceptor {
|
||||
|
||||
constructor(private cookieService: CookieService) {
|
||||
}
|
||||
|
||||
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
|
||||
|
||||
let requestToForward = req;
|
||||
let token = this.cookieService.get(TokenConstants.CSRF_TOKEN_NAME) as string;
|
||||
|
||||
if (token != null) {
|
||||
let headers = {};
|
||||
let headerName = TokenConstants.CSRF_HEADER_NAME;
|
||||
headers[headerName] = token;
|
||||
requestToForward = req.clone({setHeaders: headers});
|
||||
}
|
||||
return next.handle(requestToForward);
|
||||
}
|
||||
}
|
||||
|
|
@ -4,9 +4,11 @@ import {
|
|||
HttpSecurityErrorInterceptor,
|
||||
HttpSecurityInterceptor
|
||||
} from "@webbpm/base-package";
|
||||
import {AbsoluteUrlCsrfInterceptor} from "./absolute-url-csrf.interceptor";
|
||||
|
||||
export const DEFAULT_HTTP_INTERCEPTOR_PROVIDERS = [
|
||||
{provide: HTTP_INTERCEPTORS, useClass: HttpSecurityInterceptor, multi: true},
|
||||
{provide: HTTP_INTERCEPTORS, useClass: HttpSecurityErrorInterceptor, multi: true},
|
||||
{provide: HTTP_INTERCEPTORS, useClass: FormDirtyInterceptor, multi: true}
|
||||
{provide: HTTP_INTERCEPTORS, useClass: FormDirtyInterceptor, multi: true},
|
||||
{provide: HTTP_INTERCEPTORS, useClass: AbsoluteUrlCsrfInterceptor, multi: true}
|
||||
];
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
import {HTTP_INTERCEPTORS} from "@angular/common/http";
|
||||
import {FormDirtyInterceptor, HttpSecurityInterceptor} from "@webbpm/base-package";
|
||||
import {DevHttpSecurityErrorInterceptor} from "./http-security-error-interceptor.dev";
|
||||
import {AbsoluteUrlCsrfInterceptor} from "./absolute-url-csrf.interceptor";
|
||||
|
||||
export const DEFAULT_HTTP_INTERCEPTOR_PROVIDERS = [
|
||||
{provide: HTTP_INTERCEPTORS, useClass: HttpSecurityInterceptor, multi: true},
|
||||
{provide: HTTP_INTERCEPTORS, useClass: DevHttpSecurityErrorInterceptor, multi: true},
|
||||
{provide: HTTP_INTERCEPTORS, useClass: FormDirtyInterceptor, multi: true}
|
||||
{provide: HTTP_INTERCEPTORS, useClass: FormDirtyInterceptor, multi: true},
|
||||
{provide: HTTP_INTERCEPTORS, useClass: AbsoluteUrlCsrfInterceptor, multi: true},
|
||||
];
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ import {
|
|||
import {AppRoutingModule} from "../app/app-routing.module";
|
||||
import {GlobalErrorHandler} from "./handler/global-error.handler.prod";
|
||||
import {DEFAULT_HTTP_INTERCEPTOR_PROVIDERS} from "./interceptor/default-interceptors.prod";
|
||||
import {HttpClientModule, HttpClientXsrfModule} from "@angular/common/http";
|
||||
import {TokenConstants} from "../security/TokenConstants";
|
||||
|
||||
let IMPORTS = [
|
||||
BrowserAnimationsModule,
|
||||
|
|
@ -30,7 +32,10 @@ let IMPORTS = [
|
|||
CoreModule,
|
||||
ComponentsModule,
|
||||
AppModule,
|
||||
WebbpmRoutingModule
|
||||
WebbpmRoutingModule,
|
||||
HttpClientModule,
|
||||
HttpClientXsrfModule.withOptions(
|
||||
{cookieName: TokenConstants.CSRF_TOKEN_NAME, headerName: TokenConstants.CSRF_HEADER_NAME})
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>ru.cg.webbpm.packages.base</groupId>
|
||||
<artifactId>resources</artifactId>
|
||||
<version>3.178.2</version>
|
||||
<version>3.182.0</version>
|
||||
<organization>
|
||||
<name>Micord</name>
|
||||
</organization>
|
||||
|
|
@ -28,13 +28,13 @@
|
|||
<jooq.version>3.19.3</jooq.version>
|
||||
<jupiter.version>5.10.2</jupiter.version>
|
||||
<enforcer.manageVersions>true</enforcer.manageVersions>
|
||||
<webbpm-platform.version>3.178.2</webbpm-platform.version>
|
||||
<webbpm-platform.version>3.182.0</webbpm-platform.version>
|
||||
<h2.version>1.4.200</h2.version>
|
||||
<build.timestamp>0829133121</build.timestamp>
|
||||
<build.timestamp>1004163046</build.timestamp>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<junit.platform.version>1.10.0</junit.platform.version>
|
||||
<enforcer.manageExclusions>true</enforcer.manageExclusions>
|
||||
<revision>3.178.2</revision>
|
||||
<revision>3.182.0</revision>
|
||||
<metadata.ts.filename>typescript.metadata.json</metadata.ts.filename>
|
||||
<package.repository.url>https://repo.micord.ru</package.repository.url>
|
||||
<maven.build.timestamp.format>MMddHHmmss</maven.build.timestamp.format>
|
||||
|
|
@ -47,19 +47,19 @@
|
|||
<dependency>
|
||||
<groupId>ru.cg.webbpm.packages.base</groupId>
|
||||
<artifactId>converters</artifactId>
|
||||
<version>3.178.2</version>
|
||||
<version>3.182.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.cg.webbpm.packages.base</groupId>
|
||||
<artifactId>backend</artifactId>
|
||||
<version>3.178.2</version>
|
||||
<version>3.182.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.cg.webbpm.packages.base</groupId>
|
||||
<artifactId>frontend</artifactId>
|
||||
<version>3.178.2</version>
|
||||
<version>3.182.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@
|
|||
<ul>
|
||||
|
||||
<li>Образец внешней ссылки: <code>https://www.wildberries.ru/catalog/${sku}/detail.aspx</code></li>
|
||||
<li>Образец внутренней ссылки: <code>products/ru.cg.webbpm.packages.base:resources:jar:3.178.2</code></li>
|
||||
<li>Образец внутренней ссылки: <code>products/ru.cg.webbpm.packages.base:resources:jar:3.182.0</code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
|
|
|
|||
|
|
@ -4,17 +4,17 @@
|
|||
<description>Base webbpm package</description>
|
||||
<groupId>ru.cg.webbpm.packages.base</groupId>
|
||||
<artifactId>resources</artifactId>
|
||||
<version>3.178.2</version>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<version>3.182.0</version>
|
||||
<studioVersion>3.182.0</studioVersion>
|
||||
|
||||
<backendModule>
|
||||
<groupId>ru.cg.webbpm.packages.base</groupId>
|
||||
<artifactId>backend</artifactId>
|
||||
<version>3.178.2</version>
|
||||
<version>3.182.0</version>
|
||||
</backendModule>
|
||||
<frontendModule>
|
||||
<packageName>@webbpm/base-package</packageName>
|
||||
<version>3.178.2</version>
|
||||
<version>3.182.0</version>
|
||||
</frontendModule>
|
||||
</packageInfo>
|
||||
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@
|
|||
<documentation>component/buttons/Кнопка.html</documentation>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<studioVersion>3.182.0</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.178.2</value>
|
||||
<value>3.182.0</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@
|
|||
<documentation>component/buttons/Кнопка_отмены.html</documentation>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<studioVersion>3.182.0</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.178.2</value>
|
||||
<value>3.182.0</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@
|
|||
<documentation>component/buttons/Кнопка_очистки_фильтра.html</documentation>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<studioVersion>3.182.0</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.178.2</value>
|
||||
<value>3.182.0</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@
|
|||
<documentation>component/buttons/Кнопка_удаления.html</documentation>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<studioVersion>3.182.0</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.178.2</value>
|
||||
<value>3.182.0</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@
|
|||
<documentation>component/buttons/Кнопка_загрузки.html</documentation>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<studioVersion>3.182.0</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.178.2</value>
|
||||
<value>3.182.0</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@
|
|||
<documentation>component/buttons/Кнопка_вызова_ошибки.html</documentation>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<studioVersion>3.182.0</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.178.2</value>
|
||||
<value>3.182.0</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -7,11 +7,11 @@
|
|||
<documentation>component/buttons/Кнопка_выполнения_бизнес-процесса.html</documentation>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<studioVersion>3.182.0</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.178.2</value>
|
||||
<value>3.182.0</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@
|
|||
<documentation>component/buttons/Кнопка_выполнения_SQL.html</documentation>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<studioVersion>3.182.0</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.178.2</value>
|
||||
<value>3.182.0</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@
|
|||
<documentation>component/buttons/Кнопка_для_фильтрации.html</documentation>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<studioVersion>3.182.0</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.178.2</value>
|
||||
<value>3.182.0</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@
|
|||
<documentation>component/buttons/Кнопка_навигации.html</documentation>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<studioVersion>3.182.0</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.178.2</value>
|
||||
<value>3.182.0</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@
|
|||
<documentation>component/buttons/Кнопка_сохранения.html</documentation>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<studioVersion>3.182.0</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.178.2</value>
|
||||
<value>3.182.0</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@
|
|||
<documentation>component/buttons/Кнопка_выбора.html</documentation>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<studioVersion>3.182.0</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.178.2</value>
|
||||
<value>3.182.0</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -1,341 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<xmlComponent>
|
||||
<id>250af338-c8df-32cc-bcc7-b56b9c7da0a5</id>
|
||||
<name>SignButton</name>
|
||||
<category>buttons</category>
|
||||
<icon>META-INF/components/icons/buttons/SignButton.png</icon>
|
||||
<localization>META-INF/components/localization/buttons/sign-button</localization>
|
||||
<documentation>component/buttons/Кнопка_подписи.html</documentation>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.178.2</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
<rootObject id="1ce5393a-8af1-4113-a5e6-b9076643ea27">
|
||||
<prototypeId>9d1b5af1-0b8f-4b1b-b9a5-c2e6acf72d91</prototypeId>
|
||||
<componentRootId>1ce5393a-8af1-4113-a5e6-b9076643ea27</componentRootId>
|
||||
<name>SignButton</name>
|
||||
<expanded>true</expanded>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="bf098f19-480e-44e4-9084-aa42955c4d0f">
|
||||
<properties/>
|
||||
</scripts>
|
||||
<scripts id="72befe90-1915-483f-b88c-d1ec5d4bdc8e">
|
||||
<properties/>
|
||||
</scripts>
|
||||
<scripts id="87f3fefa-b77b-4137-aab6-b2bcd83ce380">
|
||||
<properties/>
|
||||
</scripts>
|
||||
<children id="c3c8717f-4bf4-4c75-b5da-fbb872f21e2c">
|
||||
<prototypeId>d7d54cfb-26b5-4dba-b56f-b6247183c24d</prototypeId>
|
||||
<componentRootId>c3c8717f-4bf4-4c75-b5da-fbb872f21e2c</componentRootId>
|
||||
<name>Горизонтальный контейнер</name>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="bf098f19-480e-44e4-9084-aa42955c4d0f">
|
||||
<properties/>
|
||||
</scripts>
|
||||
<scripts id="b6068710-0f31-48ec-8e03-c0c1480a40c0">
|
||||
<properties/>
|
||||
</scripts>
|
||||
<scripts id="fe04d7fb-6c5b-46c4-b723-667732d81f4f">
|
||||
<properties/>
|
||||
</scripts>
|
||||
<children id="c7d20d03-8987-41df-8ca5-a3eecb7e5311">
|
||||
<prototypeId>fd7e47b9-dce1-4d14-9f3a-580c79f59579</prototypeId>
|
||||
<componentRootId>c7d20d03-8987-41df-8ca5-a3eecb7e5311</componentRootId>
|
||||
<name>SignButton</name>
|
||||
<removed>true</removed>
|
||||
</children>
|
||||
<children id="149c9cc0-1efe-4d1b-bf5f-f770bbd7a524">
|
||||
<prototypeId>fd7e47b9-dce1-4d14-9f3a-580c79f59579</prototypeId>
|
||||
<componentRootId>149c9cc0-1efe-4d1b-bf5f-f770bbd7a524</componentRootId>
|
||||
<name>Кнопка "Подписать"</name>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="f35a1ca5-d363-4030-9e7f-5f8d5942b08e">
|
||||
<classRef type="TS">
|
||||
<className>SignButton</className>
|
||||
<packageName>webbpm.electronic_sign</packageName>
|
||||
</classRef>
|
||||
<enabled>true</enabled>
|
||||
<expanded>true</expanded>
|
||||
<properties>
|
||||
<entry>
|
||||
<key>visible</key>
|
||||
<value>
|
||||
<complex/>
|
||||
<simple>true</simple>
|
||||
</value>
|
||||
</entry>
|
||||
<entry>
|
||||
<key>completeTaskAfterSigning</key>
|
||||
<value>
|
||||
<complex/>
|
||||
<simple>false</simple>
|
||||
</value>
|
||||
</entry>
|
||||
<entry>
|
||||
<key>allowResign</key>
|
||||
<value>
|
||||
<simple>false</simple>
|
||||
</value>
|
||||
</entry>
|
||||
<entry>
|
||||
<key>caption</key>
|
||||
<value>
|
||||
<complex/>
|
||||
<simple>"Подписать"</simple>
|
||||
</value>
|
||||
</entry>
|
||||
<entry>
|
||||
<key>disabled</key>
|
||||
<value>
|
||||
<complex/>
|
||||
<simple>false</simple>
|
||||
</value>
|
||||
</entry>
|
||||
</properties>
|
||||
</scripts>
|
||||
<scripts id="abf12295-7776-4e0b-8845-bfaca4301e0c">
|
||||
<classRef type="JAVA">
|
||||
<className>SignButtonRpcService</className>
|
||||
<packageName>ru.cg.webbpm.electronic_sign</packageName>
|
||||
</classRef>
|
||||
<enabled>true</enabled>
|
||||
<expanded>true</expanded>
|
||||
<properties/>
|
||||
</scripts>
|
||||
<scripts id="bf098f19-480e-44e4-9084-aa42955c4d0f">
|
||||
<properties/>
|
||||
<removed>true</removed>
|
||||
</scripts>
|
||||
</children>
|
||||
<children id="9efc3322-7d19-45e3-b387-76677e739237">
|
||||
<prototypeId>fd7e47b9-dce1-4d14-9f3a-580c79f59579</prototypeId>
|
||||
<componentRootId>9efc3322-7d19-45e3-b387-76677e739237</componentRootId>
|
||||
<name>Кнопка "Показать подписываемые данные"</name>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="488d1759-b42f-4c21-b9c1-79568f0a5484">
|
||||
<classRef type="TS">
|
||||
<className>DisplayDataForSignButton</className>
|
||||
<packageName>webbpm.electronic_sign</packageName>
|
||||
</classRef>
|
||||
<enabled>true</enabled>
|
||||
<expanded>true</expanded>
|
||||
<properties>
|
||||
<entry>
|
||||
<key>dialog</key>
|
||||
<value>
|
||||
<complex/>
|
||||
<simple>{"objectId":"a4a2c535-9511-4732-b355-0e7cd52e7cfa","packageName":"component","className":"Dialog","type":"TS"}</simple>
|
||||
</value>
|
||||
</entry>
|
||||
<entry>
|
||||
<key>signButton</key>
|
||||
<value>
|
||||
<complex/>
|
||||
<simple>{"objectId":"149c9cc0-1efe-4d1b-bf5f-f770bbd7a524","packageName":"webbpm.electronic_sign","className":"SignButton","type":"TS"}</simple>
|
||||
</value>
|
||||
</entry>
|
||||
<entry>
|
||||
<key>visible</key>
|
||||
<value>
|
||||
<complex/>
|
||||
<simple>true</simple>
|
||||
</value>
|
||||
</entry>
|
||||
<entry>
|
||||
<key>caption</key>
|
||||
<value>
|
||||
<complex/>
|
||||
<simple>"Показать подписываемые данные"</simple>
|
||||
</value>
|
||||
</entry>
|
||||
<entry>
|
||||
<key>disabled</key>
|
||||
<value>
|
||||
<complex/>
|
||||
<simple>false</simple>
|
||||
</value>
|
||||
</entry>
|
||||
</properties>
|
||||
</scripts>
|
||||
<scripts id="bf098f19-480e-44e4-9084-aa42955c4d0f">
|
||||
<properties/>
|
||||
<removed>true</removed>
|
||||
</scripts>
|
||||
<scripts id="47d6cdd5-c878-4e2c-8cfa-20486695e761">
|
||||
<classRef type="TS">
|
||||
<className>DisplayDataForSignButton</className>
|
||||
<packageName>webbpm.electronic_sign</packageName>
|
||||
</classRef>
|
||||
<enabled>true</enabled>
|
||||
<expanded>true</expanded>
|
||||
<properties/>
|
||||
<removed>true</removed>
|
||||
</scripts>
|
||||
</children>
|
||||
<children id="d24931e5-6127-42ba-9723-b0066817f5fb">
|
||||
<prototypeId>fd7e47b9-dce1-4d14-9f3a-580c79f59579</prototypeId>
|
||||
<componentRootId>d24931e5-6127-42ba-9723-b0066817f5fb</componentRootId>
|
||||
<name>Button</name>
|
||||
<removed>true</removed>
|
||||
</children>
|
||||
</children>
|
||||
<children id="6c132aa4-1b38-47ba-bf7c-f811b4b2cb7f">
|
||||
<prototypeId>86f297f1-ab3d-40e0-ac2f-89cc944b7f0a</prototypeId>
|
||||
<componentRootId>6c132aa4-1b38-47ba-bf7c-f811b4b2cb7f</componentRootId>
|
||||
<name>Диалог</name>
|
||||
<removed>true</removed>
|
||||
</children>
|
||||
<children id="a4a2c535-9511-4732-b355-0e7cd52e7cfa">
|
||||
<prototypeId>86f297f1-ab3d-40e0-ac2f-89cc944b7f0a</prototypeId>
|
||||
<componentRootId>a4a2c535-9511-4732-b355-0e7cd52e7cfa</componentRootId>
|
||||
<name>Диалог</name>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="cf4526a1-96ab-4820-8aa9-62fb54c2b64c">
|
||||
<properties>
|
||||
<entry>
|
||||
<key>title</key>
|
||||
<value>
|
||||
<complex/>
|
||||
<simple>"Подписываемые данные"</simple>
|
||||
</value>
|
||||
</entry>
|
||||
</properties>
|
||||
</scripts>
|
||||
<scripts id="48d405ee-5991-4027-bfee-113a895bf8f8">
|
||||
<properties/>
|
||||
</scripts>
|
||||
<scripts id="b463917a-16fc-42db-9c92-9c1027e9232e">
|
||||
<properties/>
|
||||
</scripts>
|
||||
<children id="9714ae34-d49a-47f3-83ea-742d986fa108">
|
||||
<prototypeId>ba24d307-0b91-4299-ba82-9d0b52384ff2</prototypeId>
|
||||
<componentRootId>9714ae34-d49a-47f3-83ea-742d986fa108</componentRootId>
|
||||
<name>Текст</name>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="cf4526a1-96ab-4820-8aa9-62fb54c2b64c">
|
||||
<properties/>
|
||||
</scripts>
|
||||
<scripts id="737b67e2-295f-4356-a1e1-9419344d8c85">
|
||||
<properties/>
|
||||
</scripts>
|
||||
<scripts id="a6ccccd9-354c-4725-9d34-c716cf626048">
|
||||
<properties/>
|
||||
</scripts>
|
||||
<scripts id="f203f156-be32-4131-9c86-4d6bac6d5d56">
|
||||
<enabled>false</enabled>
|
||||
</scripts>
|
||||
</children>
|
||||
<children id="47094714-1ba4-4291-ae11-2114191430e4">
|
||||
<prototypeId>fd7e47b9-dce1-4d14-9f3a-580c79f59579</prototypeId>
|
||||
<componentRootId>47094714-1ba4-4291-ae11-2114191430e4</componentRootId>
|
||||
<name>Закрыть</name>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="bf098f19-480e-44e4-9084-aa42955c4d0f">
|
||||
<properties>
|
||||
<entry>
|
||||
<key>caption</key>
|
||||
<value>
|
||||
<simple>"Закрыть"</simple>
|
||||
</value>
|
||||
</entry>
|
||||
<entry>
|
||||
<key>cssClasses</key>
|
||||
<value>
|
||||
<item id="8e8e0ee3-f6f6-4943-bbec-0071ec0ef07f" removed="false">
|
||||
<value>
|
||||
<simple>"align-center"</simple>
|
||||
</value>
|
||||
</item>
|
||||
<item id="3de6c0f8-dce8-47a2-af67-bf6c345f2579"/>
|
||||
<expanded>true</expanded>
|
||||
</value>
|
||||
</entry>
|
||||
</properties>
|
||||
</scripts>
|
||||
<scripts id="9db873e7-4bf4-4731-bc9a-ac5c4f82865b">
|
||||
<classRef type="TS">
|
||||
<className>CloseDialog</className>
|
||||
<packageName>custom</packageName>
|
||||
</classRef>
|
||||
<enabled>true</enabled>
|
||||
<expanded>true</expanded>
|
||||
<removed>true</removed>
|
||||
</scripts>
|
||||
<scripts id="760dcf67-e50f-431d-a665-f3c02ae0ce49">
|
||||
<classRef type="TS">
|
||||
<className>HideDialog</className>
|
||||
<packageName>component.complex.common</packageName>
|
||||
</classRef>
|
||||
<enabled>true</enabled>
|
||||
<expanded>true</expanded>
|
||||
<removed>true</removed>
|
||||
</scripts>
|
||||
</children>
|
||||
<children id="1a8e985e-76a6-4d4b-8219-68690601d79a">
|
||||
<prototypeId>98594cec-0a9b-4cef-af09-e1b71cb2ad9e</prototypeId>
|
||||
<componentRootId>1a8e985e-76a6-4d4b-8219-68690601d79a</componentRootId>
|
||||
<name>AC_close</name>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="1d700a6b-96bb-4c9b-96d5-231017316f05"/>
|
||||
<scripts id="37dff5c8-1599-4984-b107-c44a87b6da2e">
|
||||
<properties>
|
||||
<entry>
|
||||
<key>eventRefs</key>
|
||||
<value>
|
||||
<item id="ef0186f7-e820-4fa3-b898-c162e87ed5e4" removed="false">
|
||||
<value>
|
||||
<complex>
|
||||
<entry>
|
||||
<key>behavior</key>
|
||||
<value>
|
||||
<simple>{"objectId":"47094714-1ba4-4291-ae11-2114191430e4","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>thenActions</key>
|
||||
<value>
|
||||
<item id="e7f36f41-9f70-48f5-99a5-71ced67162a1" removed="false">
|
||||
<value>
|
||||
<complex>
|
||||
<entry>
|
||||
<key>behavior</key>
|
||||
<value>
|
||||
<simple>{"objectId":"a4a2c535-9511-4732-b355-0e7cd52e7cfa","packageName":"component","className":"Dialog","type":"TS"}</simple>
|
||||
</value>
|
||||
</entry>
|
||||
<entry>
|
||||
<key>method</key>
|
||||
<value>
|
||||
<simple>"hide"</simple>
|
||||
</value>
|
||||
</entry>
|
||||
</complex>
|
||||
</value>
|
||||
</item>
|
||||
</value>
|
||||
</entry>
|
||||
</properties>
|
||||
</scripts>
|
||||
<scripts id="77e34bc1-55a6-4dde-8abd-c539762cd3b8"/>
|
||||
</children>
|
||||
</children>
|
||||
</rootObject>
|
||||
</xmlComponent>
|
||||
|
|
@ -0,0 +1,340 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<xmlComponent>
|
||||
<id>d36ffcdc-2024-49bf-a8f5-a4664d69fd75</id>
|
||||
<name>SignButtonV2</name>
|
||||
<category>buttons</category>
|
||||
<icon>META-INF/components/icons/buttons/SignButton.png</icon>
|
||||
<localization>META-INF/components/localization/buttons/sign-button</localization>
|
||||
<documentation>component/buttons/Кнопка_подписи.html</documentation>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.182.0</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.182.0</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
<rootObject id="bb068d3b-40da-49f6-ae9e-fb669c490836">
|
||||
<prototypeId>9d1b5af1-0b8f-4b1b-b9a5-c2e6acf72d91</prototypeId>
|
||||
<componentRootId>bb068d3b-40da-49f6-ae9e-fb669c490836</componentRootId>
|
||||
<name>SignButtonV2</name>
|
||||
<container>true</container>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="bf098f19-480e-44e4-9084-aa42955c4d0f"/>
|
||||
<scripts id="72befe90-1915-483f-b88c-d1ec5d4bdc8e"/>
|
||||
<scripts id="87f3fefa-b77b-4137-aab6-b2bcd83ce380"/>
|
||||
<scripts id="ef21ca22-3f81-4484-ba6f-58d670c12d4f"/>
|
||||
<scripts id="277e6fbc-9e2e-4080-bf20-5d8be18e6764"/>
|
||||
<children id="a7d26a23-760e-444f-89ca-82fd5d5b02bf">
|
||||
<prototypeId>d7d54cfb-26b5-4dba-b56f-b6247183c24d</prototypeId>
|
||||
<componentRootId>a7d26a23-760e-444f-89ca-82fd5d5b02bf</componentRootId>
|
||||
<name>Горизонтальный контейнер</name>
|
||||
<container>true</container>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="bf098f19-480e-44e4-9084-aa42955c4d0f"/>
|
||||
<scripts id="b6068710-0f31-48ec-8e03-c0c1480a40c0"/>
|
||||
<scripts id="fe04d7fb-6c5b-46c4-b723-667732d81f4f"/>
|
||||
<scripts id="5c566210-2a60-4048-a2d1-84c7dd023248"/>
|
||||
<scripts id="3171b2e1-b4af-4335-95fa-1b2592604b84"/>
|
||||
<children id="8362c808-f6d7-4ca0-a441-4574025c1607">
|
||||
<prototypeId>fd7e47b9-dce1-4d14-9f3a-580c79f59579</prototypeId>
|
||||
<componentRootId>8362c808-f6d7-4ca0-a441-4574025c1607</componentRootId>
|
||||
<name>SignButton</name>
|
||||
<container>false</container>
|
||||
<removed>true</removed>
|
||||
</children>
|
||||
<children id="9528f637-2eac-42b7-8f7e-c2fe3003e6ac">
|
||||
<prototypeId>fd7e47b9-dce1-4d14-9f3a-580c79f59579</prototypeId>
|
||||
<componentRootId>9528f637-2eac-42b7-8f7e-c2fe3003e6ac</componentRootId>
|
||||
<name>Кнопка "Подписать"</name>
|
||||
<container>false</container>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="f35a1ca5-d363-4030-9e7f-5f8d5942b08e">
|
||||
<removed>true</removed>
|
||||
</scripts>
|
||||
<scripts id="abf12295-7776-4e0b-8845-bfaca4301e0c">
|
||||
<removed>true</removed>
|
||||
</scripts>
|
||||
<scripts id="fa2f7c85-b2b6-4a3f-b386-b59936ca7025">
|
||||
<classRef type="TS">
|
||||
<className>SignButtonV2</className>
|
||||
<packageName>webbpm.electronic_sign_v2</packageName>
|
||||
</classRef>
|
||||
<enabled>true</enabled>
|
||||
<expanded>true</expanded>
|
||||
<properties>
|
||||
<entry>
|
||||
<key>caption</key>
|
||||
<value>
|
||||
<simple>"Подписать"</simple>
|
||||
</value>
|
||||
</entry>
|
||||
<entry>
|
||||
<key>visible</key>
|
||||
<value>
|
||||
<simple>true</simple>
|
||||
</value>
|
||||
</entry>
|
||||
<entry>
|
||||
<key>completeTaskAfterSigning</key>
|
||||
<value>
|
||||
<complex/>
|
||||
<simple>false</simple>
|
||||
</value>
|
||||
</entry>
|
||||
<entry>
|
||||
<key>allowResign</key>
|
||||
<value>
|
||||
<simple>false</simple>
|
||||
</value>
|
||||
</entry>
|
||||
</properties>
|
||||
</scripts>
|
||||
<scripts id="293c10b7-9efa-4c0c-8686-bce6cddfcdfa">
|
||||
<classRef type="JAVA">
|
||||
<className>SignButtonRpcServiceV2</className>
|
||||
<packageName>ru.cg.webbpm.electronic_sign_v2.rpc</packageName>
|
||||
</classRef>
|
||||
<enabled>true</enabled>
|
||||
<expanded>true</expanded>
|
||||
</scripts>
|
||||
<scripts id="bf098f19-480e-44e4-9084-aa42955c4d0f">
|
||||
<removed>true</removed>
|
||||
</scripts>
|
||||
</children>
|
||||
<children id="e9905e1e-983b-41d7-b089-f1aac02c74a6">
|
||||
<prototypeId>fd7e47b9-dce1-4d14-9f3a-580c79f59579</prototypeId>
|
||||
<componentRootId>e9905e1e-983b-41d7-b089-f1aac02c74a6</componentRootId>
|
||||
<name>Кнопка "Показать подписываемые данные"</name>
|
||||
<container>false</container>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="488d1759-b42f-4c21-b9c1-79568f0a5484">
|
||||
<classRef type="TS">
|
||||
<className>DisplayDataForSignButton</className>
|
||||
<packageName>webbpm.electronic_sign</packageName>
|
||||
</classRef>
|
||||
<enabled>true</enabled>
|
||||
<expanded>true</expanded>
|
||||
<properties>
|
||||
<entry>
|
||||
<key>caption</key>
|
||||
<value>
|
||||
<simple>"Показать подписываемые данные"</simple>
|
||||
</value>
|
||||
</entry>
|
||||
<entry>
|
||||
<key>dialog</key>
|
||||
<value>
|
||||
<simple>{"objectId":"419f924b-9d80-4c47-bd72-64a313fa47bd","packageName":"component","className":"Dialog","type":"TS"}</simple>
|
||||
</value>
|
||||
</entry>
|
||||
<entry>
|
||||
<key>disabled</key>
|
||||
<value>
|
||||
<simple>false</simple>
|
||||
</value>
|
||||
</entry>
|
||||
<entry>
|
||||
<key>signButton</key>
|
||||
<value>
|
||||
<simple>{"objectId":"9528f637-2eac-42b7-8f7e-c2fe3003e6ac","packageName":"webbpm.electronic_sign_v2","className":"SignButtonV2","type":"TS"}</simple>
|
||||
</value>
|
||||
</entry>
|
||||
<entry>
|
||||
<key>visible</key>
|
||||
<value>
|
||||
<simple>true</simple>
|
||||
</value>
|
||||
</entry>
|
||||
</properties>
|
||||
</scripts>
|
||||
<scripts id="bf098f19-480e-44e4-9084-aa42955c4d0f">
|
||||
<removed>true</removed>
|
||||
</scripts>
|
||||
<scripts id="47d6cdd5-c878-4e2c-8cfa-20486695e761">
|
||||
<classRef type="TS">
|
||||
<className>DisplayDataForSignButton</className>
|
||||
<packageName>webbpm.electronic_sign</packageName>
|
||||
</classRef>
|
||||
<enabled>true</enabled>
|
||||
<expanded>true</expanded>
|
||||
<removed>true</removed>
|
||||
</scripts>
|
||||
</children>
|
||||
<children id="7cef1c78-715f-47da-be0d-3b7d6112f8ac">
|
||||
<prototypeId>fd7e47b9-dce1-4d14-9f3a-580c79f59579</prototypeId>
|
||||
<componentRootId>7cef1c78-715f-47da-be0d-3b7d6112f8ac</componentRootId>
|
||||
<name>Button</name>
|
||||
<container>false</container>
|
||||
<removed>true</removed>
|
||||
</children>
|
||||
</children>
|
||||
<children id="5879fd21-2437-4d2a-9aac-0f0b877d5c50">
|
||||
<prototypeId>86f297f1-ab3d-40e0-ac2f-89cc944b7f0a</prototypeId>
|
||||
<componentRootId>5879fd21-2437-4d2a-9aac-0f0b877d5c50</componentRootId>
|
||||
<name>Диалог</name>
|
||||
<container>true</container>
|
||||
<removed>true</removed>
|
||||
</children>
|
||||
<children id="419f924b-9d80-4c47-bd72-64a313fa47bd">
|
||||
<prototypeId>86f297f1-ab3d-40e0-ac2f-89cc944b7f0a</prototypeId>
|
||||
<componentRootId>419f924b-9d80-4c47-bd72-64a313fa47bd</componentRootId>
|
||||
<name>Диалог</name>
|
||||
<container>true</container>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="cf4526a1-96ab-4820-8aa9-62fb54c2b64c">
|
||||
<properties>
|
||||
<entry>
|
||||
<key>title</key>
|
||||
<value>
|
||||
<simple>"Подписываемые данные"</simple>
|
||||
</value>
|
||||
</entry>
|
||||
</properties>
|
||||
</scripts>
|
||||
<scripts id="48d405ee-5991-4027-bfee-113a895bf8f8"/>
|
||||
<scripts id="b463917a-16fc-42db-9c92-9c1027e9232e"/>
|
||||
<scripts id="24a13b10-fec4-420e-aa2e-5af0ec41326a"/>
|
||||
<scripts id="5f57bb31-85b0-4692-9f1f-d6369dea6e95"/>
|
||||
<children id="0f6ed470-9870-4d2d-bf90-4c4f472a8bc5">
|
||||
<prototypeId>ba24d307-0b91-4299-ba82-9d0b52384ff2</prototypeId>
|
||||
<componentRootId>0f6ed470-9870-4d2d-bf90-4c4f472a8bc5</componentRootId>
|
||||
<name>Текст</name>
|
||||
<container>false</container>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="cf4526a1-96ab-4820-8aa9-62fb54c2b64c"/>
|
||||
<scripts id="737b67e2-295f-4356-a1e1-9419344d8c85"/>
|
||||
<scripts id="a6ccccd9-354c-4725-9d34-c716cf626048"/>
|
||||
<scripts id="d38c1af5-2bfe-41cd-ab0f-67040f498127"/>
|
||||
<scripts id="f203f156-be32-4131-9c86-4d6bac6d5d56">
|
||||
<enabled>false</enabled>
|
||||
</scripts>
|
||||
</children>
|
||||
<children id="c57dd867-40e8-4cb2-bd2c-0b9347279663">
|
||||
<prototypeId>fd7e47b9-dce1-4d14-9f3a-580c79f59579</prototypeId>
|
||||
<componentRootId>c57dd867-40e8-4cb2-bd2c-0b9347279663</componentRootId>
|
||||
<name>Закрыть</name>
|
||||
<container>false</container>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="bf098f19-480e-44e4-9084-aa42955c4d0f">
|
||||
<properties>
|
||||
<entry>
|
||||
<key>caption</key>
|
||||
<value>
|
||||
<simple>"Закрыть"</simple>
|
||||
</value>
|
||||
</entry>
|
||||
<entry>
|
||||
<key>cssClasses</key>
|
||||
<value>
|
||||
<item id="8e8e0ee3-f6f6-4943-bbec-0071ec0ef07f" removed="false">
|
||||
<value>
|
||||
<simple>"align-center"</simple>
|
||||
</value>
|
||||
</item>
|
||||
</value>
|
||||
</entry>
|
||||
</properties>
|
||||
</scripts>
|
||||
<scripts id="9db873e7-4bf4-4731-bc9a-ac5c4f82865b">
|
||||
<classRef type="TS">
|
||||
<className>CloseDialog</className>
|
||||
<packageName>custom</packageName>
|
||||
</classRef>
|
||||
<enabled>true</enabled>
|
||||
<expanded>true</expanded>
|
||||
<removed>true</removed>
|
||||
</scripts>
|
||||
<scripts id="760dcf67-e50f-431d-a665-f3c02ae0ce49">
|
||||
<classRef type="TS">
|
||||
<className>HideDialog</className>
|
||||
<packageName>component.complex.common</packageName>
|
||||
</classRef>
|
||||
<enabled>true</enabled>
|
||||
<expanded>true</expanded>
|
||||
<removed>true</removed>
|
||||
</scripts>
|
||||
</children>
|
||||
<children id="7be7bde8-ed17-46e7-a80e-271573ba57d1">
|
||||
<prototypeId>98594cec-0a9b-4cef-af09-e1b71cb2ad9e</prototypeId>
|
||||
<componentRootId>7be7bde8-ed17-46e7-a80e-271573ba57d1</componentRootId>
|
||||
<name>AC_close</name>
|
||||
<container>false</container>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="1d700a6b-96bb-4c9b-96d5-231017316f05"/>
|
||||
<scripts id="37dff5c8-1599-4984-b107-c44a87b6da2e">
|
||||
<properties>
|
||||
<entry>
|
||||
<key>eventRefs</key>
|
||||
<value>
|
||||
<item id="ef0186f7-e820-4fa3-b898-c162e87ed5e4" removed="false">
|
||||
<value>
|
||||
<complex>
|
||||
<entry>
|
||||
<key>behavior</key>
|
||||
<value>
|
||||
<simple>{"objectId":"c57dd867-40e8-4cb2-bd2c-0b9347279663","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="e7f36f41-9f70-48f5-99a5-71ced67162a1" removed="false">
|
||||
<value>
|
||||
<complex>
|
||||
<entry>
|
||||
<key>behavior</key>
|
||||
<value>
|
||||
<simple>{"objectId":"419f924b-9d80-4c47-bd72-64a313fa47bd","packageName":"component","className":"Dialog","type":"TS"}</simple>
|
||||
</value>
|
||||
</entry>
|
||||
<entry>
|
||||
<key>method</key>
|
||||
<value>
|
||||
<simple>"hide"</simple>
|
||||
</value>
|
||||
</entry>
|
||||
<entry>
|
||||
<key>value</key>
|
||||
<value>
|
||||
<simple>null</simple>
|
||||
</value>
|
||||
</entry>
|
||||
</complex>
|
||||
</value>
|
||||
</item>
|
||||
</value>
|
||||
</entry>
|
||||
</properties>
|
||||
</scripts>
|
||||
<scripts id="77e34bc1-55a6-4dde-8abd-c539762cd3b8"/>
|
||||
</children>
|
||||
</children>
|
||||
</rootObject>
|
||||
</xmlComponent>
|
||||
|
|
@ -8,11 +8,11 @@
|
|||
<documentation>component/buttons/Кнопка_запуска_бизнес-процесса.html</documentation>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<studioVersion>3.182.0</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.178.2</value>
|
||||
<value>3.182.0</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@
|
|||
<documentation>component/buttons/reporting/Кнопка_печати_из_графа_сущности.html</documentation>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<studioVersion>3.182.0</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.178.2</value>
|
||||
<value>3.182.0</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@
|
|||
<documentation>component/buttons/reporting/Кнопка_печати_отчета_из_формы.html</documentation>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<studioVersion>3.182.0</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.178.2</value>
|
||||
<value>3.182.0</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@
|
|||
<documentation>component/containers/Сворачиваемая_панель.html</documentation>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<studioVersion>3.182.0</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.178.2</value>
|
||||
<value>3.182.0</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@
|
|||
<documentation>component/containers/Диалог.html</documentation>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<studioVersion>3.182.0</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.178.2</value>
|
||||
<value>3.182.0</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@
|
|||
<documentation>component/containers/Контейнер_с_кнопками.html</documentation>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<studioVersion>3.182.0</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.178.2</value>
|
||||
<value>3.182.0</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@
|
|||
<documentation>component/containers/Группа_полей.html</documentation>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<studioVersion>3.182.0</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.178.2</value>
|
||||
<value>3.182.0</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@
|
|||
<documentation>component/containers/Набор_фильтров.html</documentation>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<studioVersion>3.182.0</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.178.2</value>
|
||||
<value>3.182.0</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@
|
|||
<documentation>component/containers/Форма.html</documentation>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<studioVersion>3.182.0</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.178.2</value>
|
||||
<value>3.182.0</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@
|
|||
<documentation>component/containers/Горизонтальный_контейнер.html</documentation>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<studioVersion>3.182.0</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.178.2</value>
|
||||
<value>3.182.0</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@
|
|||
<documentation>component/containers/Контейнер_вкладок.html</documentation>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<studioVersion>3.182.0</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.178.2</value>
|
||||
<value>3.182.0</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@
|
|||
<documentation>component/containers/Вкладка.html</documentation>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<studioVersion>3.182.0</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.178.2</value>
|
||||
<value>3.182.0</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@
|
|||
<documentation>component/containers/Вертикальный_контейнер.html</documentation>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<studioVersion>3.182.0</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.178.2</value>
|
||||
<value>3.182.0</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@
|
|||
<documentation>component/containers/Окно.html</documentation>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<studioVersion>3.182.0</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.178.2</value>
|
||||
<value>3.182.0</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@
|
|||
<documentation>component/editable-grids/EditableGrid.html</documentation>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<studioVersion>3.182.0</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.178.2</value>
|
||||
<value>3.182.0</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -7,11 +7,11 @@
|
|||
<localization>META-INF/components/localization/editable-grids/autocomplete</localization>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<studioVersion>3.182.0</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.178.2</value>
|
||||
<value>3.182.0</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -7,11 +7,11 @@
|
|||
<localization>META-INF/components/localization/editable-grids/check-box</localization>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<studioVersion>3.182.0</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.178.2</value>
|
||||
<value>3.182.0</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -7,11 +7,11 @@
|
|||
<localization>META-INF/components/localization/editable-grids/combo-box</localization>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<studioVersion>3.182.0</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.178.2</value>
|
||||
<value>3.182.0</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -7,11 +7,11 @@
|
|||
<localization>META-INF/components/localization/editable-grids/date-time-picker</localization>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<studioVersion>3.182.0</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.178.2</value>
|
||||
<value>3.182.0</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -7,11 +7,11 @@
|
|||
<localization>META-INF/components/localization/editable-grids/money-field</localization>
|
||||
<internal>true</internal>
|
||||
<versions>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<studioVersion>3.182.0</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.178.2</value>
|
||||
<value>3.182.0</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -7,11 +7,11 @@
|
|||
<localization>META-INF/components/localization/editable-grids/number-field</localization>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<studioVersion>3.182.0</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.178.2</value>
|
||||
<value>3.182.0</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -7,11 +7,11 @@
|
|||
<localization>META-INF/components/localization/editable-grids/one-to-many</localization>
|
||||
<internal>true</internal>
|
||||
<versions>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<studioVersion>3.182.0</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.178.2</value>
|
||||
<value>3.182.0</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -7,11 +7,11 @@
|
|||
<localization>META-INF/components/localization/editable-grids/one-to-many</localization>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<studioVersion>3.182.0</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.178.2</value>
|
||||
<value>3.182.0</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -6,11 +6,11 @@
|
|||
<localization>META-INF/components/localization/editable-grids/read-only</localization>
|
||||
<internal>true</internal>
|
||||
<versions>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<studioVersion>3.182.0</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.178.2</value>
|
||||
<value>3.182.0</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -5,11 +5,11 @@
|
|||
<category>editable-grids</category>
|
||||
<internal>true</internal>
|
||||
<versions>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<studioVersion>3.182.0</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.178.2</value>
|
||||
<value>3.182.0</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@
|
|||
<documentation>Статичный_выпадающий_список_колонки_таблицы.html</documentation>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<studioVersion>3.182.0</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.178.2</value>
|
||||
<value>3.182.0</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -7,11 +7,11 @@
|
|||
<localization>META-INF/components/localization/editable-grids/text-area</localization>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<studioVersion>3.182.0</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.178.2</value>
|
||||
<value>3.182.0</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -7,11 +7,11 @@
|
|||
<localization>META-INF/components/localization/editable-grids/text-field</localization>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<studioVersion>3.182.0</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.178.2</value>
|
||||
<value>3.182.0</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -7,11 +7,11 @@
|
|||
<localization>META-INF/components/localization/editable-grids/time-picker</localization>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<studioVersion>3.182.0</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.178.2</value>
|
||||
<value>3.182.0</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@
|
|||
<documentation>component/fields/ФИАС.html</documentation>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<studioVersion>3.182.0</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.178.2</value>
|
||||
<value>3.182.0</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@
|
|||
<documentation>component/fields/Поле_ввода_с_подбором_значения.html</documentation>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<studioVersion>3.182.0</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.178.2</value>
|
||||
<value>3.182.0</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@
|
|||
<documentation>component/fields/Флаг.html</documentation>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<studioVersion>3.182.0</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.178.2</value>
|
||||
<value>3.182.0</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@
|
|||
<documentation>component/fields/Выпадающий_список.html</documentation>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<studioVersion>3.182.0</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.178.2</value>
|
||||
<value>3.182.0</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@
|
|||
<documentation>component/fields/Дата.html</documentation>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<studioVersion>3.182.0</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.178.2</value>
|
||||
<value>3.182.0</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@
|
|||
<documentation>component/fields/EditableOneToMany.html</documentation>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<studioVersion>3.182.0</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.178.2</value>
|
||||
<value>3.182.0</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@
|
|||
<documentation>component/fields/Файл.html</documentation>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<studioVersion>3.182.0</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.178.2</value>
|
||||
<value>3.182.0</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue