Merge branch 'release/1.0.0' into develop

This commit is contained in:
Zaripov Emil 2024-09-23 13:54:11 +03:00
commit 278b96ed4b
127 changed files with 14410 additions and 8694 deletions

View file

@ -1,18 +1,23 @@
FROM tomee:8.0.15-jre17-webprofile
FROM maven:3-openjdk-17-slim AS build
RUN apt update \
&& apt upgrade -y \
&& curl -fsSL https://deb.nodesource.com/setup_14.x | bash - \
&& apt install -y git nodejs \
&& rm -rf /var/lib/apt/lists/*
RUN \
rm -rf /usr/local/tomee/webapps/ROOT && \
echo "fias.enable=false" >> /usr/local/tomee/conf/catalina.properties && \
echo "webbpm.jbpm.hibernate_statistics.enabled=false" >> /usr/local/tomee/conf/catalina.properties && \
echo "webbpm.mode=production" >> /usr/local/tomee/conf/catalina.properties && \
echo "authentication.method=form" >> /usr/local/tomee/conf/catalina.properties && \
echo "webbpm.cache.hazelcast.hosts=127.0.0.1" >> /usr/local/tomee/conf/catalina.properties && \
echo "webbpm.cache.hazelcast.outbound_port_definitions=5801-5820" >> /usr/local/tomee/conf/catalina.properties && \
echo "gar.enable=false" >> /usr/local/tomee/conf/catalina.properties && \
echo "reset_password.mail.template.path=mail/reset_password.html" >> /usr/local/tomee/conf/catalina.properties && \
echo "security.password.regex=^(?=.*[a-zA-Z])(?=.*[0-9])[a-zA-Z0-9]+$" >> /usr/local/tomee/conf/catalina.properties && \
echo "bpmn.enable=false" >> /usr/local/tomee/conf/catalina.properties
COPY config/context.xml /usr/local/tomee/conf/
#COPY config/tomcat-users.xml /usr/local/tomee/conf/
COPY frontend/dist/ /usr/local/tomee/webapps/ROOT
COPY backend/target/*.war /usr/local/tomee/webapps/fl.war
WORKDIR /app
COPY . .
RUN mvn clean && mvn package -T4C
FROM gitlab.micord.ru:5050/common/base/webbpm/webbpm-tomcat-cprocsp:8.0.15-jre17-webprofile
ARG ADMIN_PASSWORD=Secr3t
COPY config/tomcat/tomee /usr/local/tomee
RUN rm -rf /usr/local/tomee/webapps/ROOT \
&& cat /usr/local/tomee/conf/webbpm.properties >> /usr/local/tomee/conf/catalina.properties \
&& sed -i -r "s/<must-be-changed>/$ADMIN_PASSWORD/g" /usr/local/tomee/conf/tomcat-users.xml
COPY --from=build /app/backend/libs/ /usr/local/tomee/lib/
COPY --from=build /app/frontend/target/*.war /usr/local/tomee/webapps/ROOT.war
COPY --from=build /app/backend/target/*.war /usr/local/tomee/webapps/fl.war

30
Dockerfile.old Normal file
View file

@ -0,0 +1,30 @@
FROM maven:3-openjdk-17-slim AS build
RUN apt update \
&& apt upgrade -y \
&& curl -fsSL https://deb.nodesource.com/setup_14.x | bash - \
&& apt install -y git nodejs \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY . .
RUN mvn clean && mvn package -T4C
FROM gitlab.micord.ru:5050/common/base/webbpm/webbpm-tomcat-cprocsp:8.0.15-jre17-webprofile
RUN \
rm -rf /usr/local/tomee/webapps/ROOT && \
echo "fias.enable=false" >> /usr/local/tomee/conf/catalina.properties && \
echo "webbpm.jbpm.hibernate_statistics.enabled=false" >> /usr/local/tomee/conf/catalina.properties && \
echo "webbpm.mode=production" >> /usr/local/tomee/conf/catalina.properties && \
echo "authentication.method=form" >> /usr/local/tomee/conf/catalina.properties && \
echo "webbpm.cache.hazelcast.hosts=127.0.0.1" >> /usr/local/tomee/conf/catalina.properties && \
echo "webbpm.cache.hazelcast.outbound_port_definitions=5801-5820" >> /usr/local/tomee/conf/catalina.properties && \
echo "gar.enable=false" >> /usr/local/tomee/conf/catalina.properties && \
echo "reset_password.mail.template.path=mail/reset_password.html" >> /usr/local/tomee/conf/catalina.properties && \
echo "security.password.regex=^(?=.*[a-zA-Z])(?=.*[0-9])[a-zA-Z0-9]+$" >> /usr/local/tomee/conf/catalina.properties && \
echo "bpmn.enable=false" >> /usr/local/tomee/conf/catalina.properties
COPY config/context.xml /usr/local/tomee/conf/
#COPY config/tomcat-users.xml /usr/local/tomee/conf/
COPY --from=build /app/backend/libs/ /usr/local/tomee/lib/
COPY --from=build /app/frontend/target/*.war /usr/local/tomee/webapps/ROOT.war
COPY --from=build /app/backend/target/*.war /usr/local/tomee/webapps/fl.war

BIN
backend/libs/JCP.jar Normal file

Binary file not shown.

View file

@ -15,10 +15,18 @@
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-jwt</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
@ -232,9 +240,24 @@
<groupId>ru.cg.webbpm.packages.base</groupId>
<artifactId>backend</artifactId>
</dependency>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
</dependency>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java-util</artifactId>
</dependency>
</dependencies>
<build>
<finalName>${parent.artifactId}</finalName>
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.6.2</version>
</extension>
</extensions>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
@ -263,6 +286,22 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<configuration>
<protocArtifact>com.google.protobuf:protoc:4.27.3:exe:${os.detected.classifier}</protocArtifact>
<protoSourceRoot>${project.parent.basedir}/backend/src/main/resources</protoSourceRoot>
<outputDirectory>${project.parent.basedir}/backend/target/generated-sources/java/protobuf</outputDirectory>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>

View file

@ -25,6 +25,7 @@ import org.springframework.web.servlet.config.annotation.EnableWebMvc;
*/
@Configuration
@ComponentScan(basePackages = {
"ervu_lkrp_fl",
"service",
"dao",
"bpmn",

View file

@ -1,35 +0,0 @@
package dto.jivoprofile;
import ru.cg.webbpm.modules.webkit.annotations.Model;
@Model
public class JivoProfileDto {
public String username;
public String email;
public String phone;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
}

View file

@ -0,0 +1,16 @@
package ru.micord.ervu.component.field;
import model.FieldData;
import ru.cg.webbpm.modules.webkit.beans.Behavior;
/**
* @author gulnaz
*/
public abstract class BaseFieldLoadComponent<T> extends Behavior {
public BaseFieldLoadComponent() {
}
public abstract FieldData loadFrom(T dto);
}

View file

@ -0,0 +1,33 @@
package ru.micord.ervu.component.field;
import java.util.Arrays;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import ru.micord.ervu.component.formatter.FieldFormatter;
import model.FieldData;
import ru.cg.webbpm.modules.standard_annotations.validation.NotNull;
/**
* @author gulnaz
*/
public class SubpoenaFieldLoadComponent extends BaseFieldLoadComponent<Map<String, Object>> {
@NotNull
public String fieldId;
public FieldFormatter<Object, Object>[] formatters;
@Override
public FieldData loadFrom(Map<String, Object> dto) {
AtomicReference<Object> valueRef = new AtomicReference<>(dto.get(fieldId));
if (formatters != null) {
Arrays.stream(formatters).forEach(formatter -> {
valueRef.set(formatter.format(valueRef.get()));
});
}
return new FieldData(getObjectId(), valueRef.get());
}
}

View file

@ -0,0 +1,9 @@
package ru.micord.ervu.component.formatter;
/**
* @author gulnaz
*/
public interface FieldFormatter<T, R> {
T format(R value);
}

View file

@ -0,0 +1,22 @@
package ru.micord.ervu.component.formatter;
import java.time.format.DateTimeFormatter;
import ru.cg.webbpm.modules.standard_annotations.validation.NotNull;
import static ru.micord.ervu.util.DateUtil.convertToLocalDate;
import static ru.micord.ervu.util.DateUtil.convertToString;
/**
* @author gulnaz
*/
public class LocalDateFormatter implements FieldFormatter<String, String> {
@NotNull
public String format;
@Override
public String format(String value) {
return convertToString(convertToLocalDate(value), DateTimeFormatter.ofPattern(format));
}
}

View file

@ -0,0 +1,58 @@
package ru.micord.ervu.controller;
import com.google.protobuf.InvalidProtocolBufferException;
import org.apache.kafka.common.utils.Bytes;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import ru.micord.ervu.converter.SummonsResponseDataConverter;
import ru.micord.ervu.dto.SubpoenaRequestDto;
import ru.micord.ervu.dto.SubpoenaResponseDto;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import proto.ervu.rp.summons.SummonsResponseData;
import ru.micord.ervu.kafka.service.ReplyingKafkaService;
import ru.micord.ervu.security.webbpm.jwt.service.JwtTokenService;
/**
* @author gulnaz
*/
@RestController
public class ErvuDataController {
private final JwtTokenService jwtTokenService;
private final ReplyingKafkaService<Object, Bytes> replyingKafkaService;
private final SummonsResponseDataConverter converter;
@Value("${ervu.kafka.recruit.request.topic}")
private String recruitRequestTopic;
@Value("${ervu.kafka.recruit.reply.topic}")
private String recruitReplyTopic;
public ErvuDataController(
JwtTokenService jwtTokenService,
@Qualifier("subpoena") ReplyingKafkaService<Object, Bytes> replyingKafkaService,
SummonsResponseDataConverter converter) {
this.jwtTokenService = jwtTokenService;
this.replyingKafkaService = replyingKafkaService;
this.converter = converter;
}
@PostMapping(
value = "/get-data",
produces = MediaType.APPLICATION_JSON_VALUE
)
public SubpoenaResponseDto getData() {
SubpoenaRequestDto subpoenaRequestDto = new SubpoenaRequestDto(jwtTokenService.getErvuId());
byte[] reply = replyingKafkaService.sendMessageAndGetReply(recruitRequestTopic,
recruitReplyTopic, subpoenaRequestDto).get();
try {
SummonsResponseData responseData = SummonsResponseData.parseFrom(reply);
return converter.convert(responseData);
}
catch (InvalidProtocolBufferException e) {
throw new RuntimeException("Failed to parse data", e);
}
}
}

View file

@ -0,0 +1,102 @@
package ru.micord.ervu.converter;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import ru.micord.ervu.dto.SubpoenaResponseDto;
import ru.micord.ervu.util.DateUtil;
import org.springframework.stereotype.Component;
import proto.ervu.rp.summons.MeasuresTemporary;
import proto.ervu.rp.summons.ResponseDataAddress;
import proto.ervu.rp.summons.SummonsInfo;
import proto.ervu.rp.summons.SummonsResponseData;
import static ru.micord.ervu.util.DateUtil.convertToLocalDate;
import static java.util.Objects.requireNonNull;
/**
* @author gulnaz
*/
@Component
public class SummonsResponseDataConverter {
private static final String RESIDENCE_ADDRESS_CODE = "_1";
private static final String STAY_ADDRESS_CODE = "_2";
private static final String ACTUAL_ADDRESS_CODE = "_3";
public SubpoenaResponseDto convert(SummonsResponseData responseData) {
SubpoenaResponseDto.Builder builder = new SubpoenaResponseDto.Builder()
.personName(responseData.getFirstName(), responseData.getMiddleName(),
responseData.getLastName()
)
.birthDate(responseData.getBirthDate())
.docType(responseData.getType())
.docNumber(responseData.getSeries(), responseData.getNumber())
.issueDate(responseData.getIssueDate())
.issueOrg(responseData.getIssueOrg())
.issueIdCode(responseData.getIssueIdCode())
.residenceAddress(getAddressByCode(responseData.getAddressesList(), RESIDENCE_ADDRESS_CODE))
.stayAddress(getAddressByCode(responseData.getAddressesList(), STAY_ADDRESS_CODE))
.actualAddress(getAddressByCode(responseData.getAddressesList(), ACTUAL_ADDRESS_CODE));
Optional<SummonsInfo> summonsInfoOpt = responseData.getSummonsInfosList().stream()
// get last subpoena
.max(Comparator.comparing(
s -> requireNonNull(convertToLocalDate(s.getPlacementDateSummons()))));
if (summonsInfoOpt.isPresent()) {
SummonsInfo summonsInfo = summonsInfoOpt.get();
builder.seriesAndNumber(summonsInfo.getSummonsSeries(), summonsInfo.getSummonsNumber())
.visitDateTime(summonsInfo.getVisitDate(), summonsInfo.getVisitTime())
.militaryCommissariatName(summonsInfo.getMilitaryCommissariatName())
.militaryCommissariatAddress(summonsInfo.getMilitaryCommissariatAddress())
.militaryCommissar(summonsInfo.getMilitaryComissar(),
summonsInfo.getMilitaryComissarFirstName(),
summonsInfo.getMilitaryComissarMiddleName()
)
.placementDateSummons(summonsInfo.getPlacementDateSummons())
.reasonName(summonsInfo.getReasonName())
.summonsStatusName(summonsInfo.getSummonsStatusName())
.deliveryTypeSummonsName(summonsInfo.getDeliveryTypeSummonsName())
.estimatedDateSummons(summonsInfo.getEstimatedDateSummons())
.recruitmentStatusCode(
Integer.parseInt(responseData.getRecruitmentInfo().getRecruitmentStatusCode()))
.recruitmentStartDate(responseData.getRecruitmentInfo().getRecruitmentStart())
.daysToAppearance((int) ChronoUnit.DAYS.between(
LocalDate.now(), DateUtil.convertToLocalDate(summonsInfo.getEstimatedDateSummons())))
.otherRestrictionCount(-1);
summonsInfo.getMeasuresTemporaryPackagesList()
.stream()
// get last package
.max(Comparator.comparing(
mp -> requireNonNull(convertToLocalDate(mp.getPackageStartDate()))))
.ifPresent(
measuresTemporaryPackage -> {
List<MeasuresTemporary> temporariesList = measuresTemporaryPackage.getMeasuresTemporariesList();
temporariesList.forEach(measuresTemporary ->
builder.addRestriction(measuresTemporary.getMeasureName(),
measuresTemporary.getStartDate()
));
if (!temporariesList.isEmpty()) {
MeasuresTemporary firstMeasure = temporariesList.get(0);
builder.firstRestrictionName(firstMeasure.getMeasureName());
builder.firstRestrictionStartDate(firstMeasure.getStartDate());
}
builder.otherRestrictionCount(temporariesList.size() - 1);
});
}
return builder.build();
}
private String getAddressByCode(List<ResponseDataAddress> addresses, String code) {
return addresses.stream()
.filter(responseDataAddress -> responseDataAddress.getAddressCode().equals(code))
.findFirst()
.map(ResponseDataAddress::getAddressReg)
.orElse("");
}
}

View file

@ -0,0 +1,7 @@
package ru.micord.ervu.dto;
/**
* @author gulnaz
*/
public record ExtractRequestDto(String ervuId, String formatExtractRegistry) {
}

View file

@ -0,0 +1,7 @@
package ru.micord.ervu.dto;
/**
* @author gulnaz
*/
public record FileData(String fileName, String fileType, byte[] file) {
}

View file

@ -0,0 +1,7 @@
package ru.micord.ervu.dto;
/**
* @author gulnaz
*/
public record Restriction(String name, String startDate) {
}

View file

@ -0,0 +1,7 @@
package ru.micord.ervu.dto;
/**
* @author ya.kuznetsova
*/
public record SubpoenaRequestDto(String ervuId) {
}

View file

@ -0,0 +1,200 @@
package ru.micord.ervu.dto;
import java.util.ArrayList;
import java.util.List;
import static ru.micord.ervu.util.DateUtil.convertToLocalDate;
import static ru.micord.ervu.util.DateUtil.convertToString;
/**
* @author gulnaz
*/
public record SubpoenaResponseDto(String personName, String birthDate, String docType, String docNumber,
String issueDate, String issueOrg, String issueIdCode,
String residenceAddress, String actualAddress, String stayAddress,
String seriesAndNumber, String visitDateTime,
String militaryCommissariatName, String militaryCommissariatAddress,
String militaryCommissar, String placementDateSummons, String reasonName,
String summonsStatusName, String deliveryTypeSummonsName,
String estimatedDateSummons, List<Restriction> restrictions,
String firstRestrictionName, String firstRestrictionStartDate,
int otherRestrictionCount, int recruitmentStatusCode,
String recruitmentStartDate, int daysToAppearance) {
public static final class Builder {
String personName;
String birthDate;
String docType;
String docNumber;
String issueDate;
String issueOrg;
String issueIdCode;
String residenceAddress;
String actualAddress;
String stayAddress;
String seriesAndNumber;
String visitDateTime;
String militaryCommissariatName;
String militaryCommissariatAddress;
String militaryCommissar;
String placementDateSummons;
String reasonName;
String summonsStatusName;
String deliveryTypeSummonsName;
String estimatedDateSummons;
List<Restriction> restrictions;
String firstRestrictionName;
String firstRestrictionStartDate;
int otherRestrictionCount;
int recruitmentStatusCode;
String recruitmentStartDate;
int daysToAppearance;
public Builder() {
this.restrictions = new ArrayList<>();
}
public Builder personName(String firstName, String middleName, String lastName) {
this.personName = lastName + " " + firstName + " " + middleName;
return this;
}
public Builder birthDate(String birthDate) {
this.birthDate = birthDate;
return this;
}
public Builder docType(String docType) {
this.docNumber = docType;
return this;
}
public Builder docNumber(String series, String number) {
this.docNumber = series + " " + number;
return this;
}
public Builder issueDate(String issueDate) {
this.issueDate = issueDate;
return this;
}
public Builder issueOrg(String issueOrg) {
this.issueOrg = issueOrg;
return this;
}
public Builder issueIdCode(String issueIdCode) {
this.issueIdCode = issueIdCode;
return this;
}
public Builder residenceAddress(String residenceAddress) {
this.residenceAddress = residenceAddress;
return this;
}
public Builder actualAddress(String actualAddress) {
this.actualAddress = actualAddress;
return this;
}
public Builder stayAddress(String stayAddress) {
this.stayAddress = stayAddress;
return this;
}
public Builder seriesAndNumber(String series, String number) {
this.seriesAndNumber = series + " " + number;
return this;
}
public Builder visitDateTime(String date, String time) {
this.visitDateTime = convertToString(convertToLocalDate(date)) + " в " + time;
return this;
}
public Builder militaryCommissariatName(String militaryCommissariatName) {
this.militaryCommissariatName = militaryCommissariatName;
return this;
}
public Builder militaryCommissariatAddress(String militaryCommissariatAddress) {
this.militaryCommissariatAddress = militaryCommissariatAddress;
return this;
}
public Builder militaryCommissar(String militaryComissar, String militaryComissarFirstName,
String militaryComissarMiddleName) {
this.militaryCommissar = militaryComissar + " " + militaryComissarFirstName + " "
+ militaryComissarMiddleName;
return this;
}
public Builder placementDateSummons(String placementDateSummons) {
this.placementDateSummons = placementDateSummons;
return this;
}
public Builder reasonName(String reasonName) {
this.reasonName = reasonName;
return this;
}
public Builder summonsStatusName(String summonsStatusName) {
this.summonsStatusName = summonsStatusName;
return this;
}
public Builder deliveryTypeSummonsName(String deliveryTypeSummonsName) {
this.deliveryTypeSummonsName = deliveryTypeSummonsName;
return this;
}
public Builder estimatedDateSummons(String estimatedDateSummons) {
this.estimatedDateSummons = estimatedDateSummons;
return this;
}
public void addRestriction(String name, String date) {
this.restrictions.add(new Restriction(name, convertToString(convertToLocalDate(date))));
}
public void firstRestrictionName(String name) {
this.firstRestrictionName = name;
}
public void firstRestrictionStartDate(String date) {
this.firstRestrictionStartDate = date;
}
public Builder otherRestrictionCount(int count) {
this.otherRestrictionCount = count;
return this;
}
public Builder recruitmentStatusCode(int recruitmentStatusCode) {
this.recruitmentStatusCode = recruitmentStatusCode;
return this;
}
public Builder recruitmentStartDate(String recruitmentStartDate) {
this.recruitmentStartDate = recruitmentStartDate;
return this;
}
public Builder daysToAppearance(int days) {
this.daysToAppearance = days;
return this;
}
public SubpoenaResponseDto build() {
return new SubpoenaResponseDto(personName, birthDate, docType, docNumber, issueDate, issueOrg,
issueIdCode, residenceAddress, actualAddress, stayAddress, seriesAndNumber, visitDateTime,
militaryCommissariatName, militaryCommissariatAddress, militaryCommissar,
placementDateSummons, reasonName, summonsStatusName, deliveryTypeSummonsName,
estimatedDateSummons, restrictions, firstRestrictionName, firstRestrictionStartDate,
otherRestrictionCount, recruitmentStatusCode, recruitmentStartDate, daysToAppearance);
}
}
}

View file

@ -0,0 +1,164 @@
package ru.micord.ervu.kafka;
import org.apache.kafka.clients.CommonClientConfigs;
import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.common.config.SaslConfigs;
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;
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.ReplyingKafkaTemplate;
import org.springframework.kafka.support.serializer.JsonSerializer;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
@Configuration
@EnableKafka
public class ReplyingKafkaConfig {
@Value("${ervu.kafka.bootstrap.servers}")
private String bootstrapServers;
@Value("${ervu.kafka.security.protocol}")
private String securityProtocol;
@Value("${ervu.kafka.doc.login.module}")
private String loginModule;
@Value("${ervu.kafka.username}")
private String username;
@Value("${ervu.kafka.password}")
private String password;
@Value("${ervu.kafka.sasl.mechanism}")
private String saslMechanism;
@Value("${ervu.kafka.reply.topic}")
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;
@Value("${ervu.kafka.group.id}")
private String groupId;
@Value("${ervu.kafka.reply.timeout:30}")
private long replyTimeout;
@Bean
public ProducerFactory<String, String> producerFactory() {
Map<String, Object> configProps = producerConfig();
configProps.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
return new DefaultKafkaProducerFactory<>(configProps);
}
@Bean
public ProducerFactory<String, Object> subpoenaProducerFactory() {
Map<String, Object> configProps = producerConfig();
configProps.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, JsonSerializer.class);
return new DefaultKafkaProducerFactory<>(configProps);
}
private Map<String, Object> producerConfig() {
Map<String, Object> configProps = new HashMap<>();
configProps.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);
configProps.put(CommonClientConfigs.SECURITY_PROTOCOL_CONFIG, securityProtocol);
configProps.put(SaslConfigs.SASL_JAAS_CONFIG, loginModule + " required username=\""
+ username + "\" password=\"" + password + "\";");
configProps.put(SaslConfigs.SASL_MECHANISM, saslMechanism);
configProps.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
return configProps;
}
@Bean
public ConsumerFactory<String, String> consumerFactory() {
Map<String, Object> configProps = consumerConfig();
configProps.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
return new DefaultKafkaConsumerFactory<>(configProps);
}
@Bean
public ConsumerFactory<String, Bytes> subpoenaConsumerFactory() {
Map<String, Object> configProps = consumerConfig();
configProps.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, BytesDeserializer.class);
return new DefaultKafkaConsumerFactory<>(configProps);
}
private Map<String, Object> consumerConfig() {
Map<String, Object> configProps = new HashMap<>();
configProps.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);
configProps.put(CommonClientConfigs.SECURITY_PROTOCOL_CONFIG, securityProtocol);
configProps.put(SaslConfigs.SASL_JAAS_CONFIG, loginModule + " required username=\""
+ username + "\" password=\"" + password + "\";");
configProps.put(SaslConfigs.SASL_MECHANISM, saslMechanism);
configProps.put(ConsumerConfig.GROUP_ID_CONFIG, groupId);
configProps.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
return configProps;
}
@Bean
public ConcurrentKafkaListenerContainerFactory<String, String> kafkaListenerContainerFactory() {
ConcurrentKafkaListenerContainerFactory<String, String> factory = new ConcurrentKafkaListenerContainerFactory<>();
factory.setConsumerFactory(consumerFactory());
return factory;
}
@Bean
public ConcurrentKafkaListenerContainerFactory<String, Bytes> subpoenaKafkaListenerContainerFactory() {
ConcurrentKafkaListenerContainerFactory<String, Bytes> factory = new ConcurrentKafkaListenerContainerFactory<>();
factory.setConsumerFactory(subpoenaConsumerFactory());
return factory;
}
@Bean
public ConcurrentMessageListenerContainer<String, String> replyContainer(
ConcurrentKafkaListenerContainerFactory<String, String> kafkaListenerContainerFactory) {
ConcurrentMessageListenerContainer<String, String> container =
kafkaListenerContainerFactory.createContainer(replyTopic);
container.getContainerProperties().setGroupId(groupId);
return container;
}
@Bean
public ConcurrentMessageListenerContainer<String, Bytes> subpoenaReplyContainer(
ConcurrentKafkaListenerContainerFactory<String, Bytes> personKafkaListenerContainerFactory) {
ConcurrentMessageListenerContainer<String, Bytes> container =
personKafkaListenerContainerFactory.createContainer(recruitReplyTopic,
subpoenaExtractReplyTopic, registryExtractReplyTopic);
container.getContainerProperties().setGroupId(groupId);
return container;
}
@Bean
@Qualifier("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));
return replyingKafkaTemplate;
}
@Bean
@Qualifier("subpoena")
public ReplyingKafkaTemplate<String, Object, Bytes> subpoenaReplyingKafkaTemplate(
ProducerFactory<String, Object> personProducerFactory,
ConcurrentMessageListenerContainer<String, Bytes> personReplyContainer) {
ReplyingKafkaTemplate<String, Object, Bytes> replyingKafkaTemplate =
new ReplyingKafkaTemplate<>(personProducerFactory, personReplyContainer);
replyingKafkaTemplate.setCorrelationHeaderName("messageId");
replyingKafkaTemplate.setDefaultReplyTimeout(Duration.ofSeconds(replyTimeout));
return replyingKafkaTemplate;
}
}

View file

@ -0,0 +1,43 @@
package ru.micord.ervu.kafka.model;
import java.io.Serializable;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
/**
* @author Eduard Tihomirov
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class Document implements Serializable {
private static final long serialVersionUID = 1L;
private String series;
private String number;
private String issueDate;
public String getSeries() {
return series;
}
public void setSeries(String series) {
this.series = series;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public String getIssueDate() {
return issueDate;
}
public void setIssueDate(String issueDate) {
this.issueDate = issueDate;
}
}

View file

@ -0,0 +1,33 @@
package ru.micord.ervu.kafka.model;
import java.io.Serializable;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
/**
* @author Eduard Tihomirov
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class ErrorData implements Serializable {
private static final long serialVersionUID = 1L;
private String code;
private String name;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View file

@ -0,0 +1,73 @@
package ru.micord.ervu.kafka.model;
import java.io.Serializable;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
/**
* @author Eduard Tihomirov
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class Person implements Serializable {
private static final long serialVersionUID = 1L;
private String lastName;
private String firstName;
private String middleName;
private String birthDate;
private String snils;
private Document document;
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getMiddleName() {
return middleName;
}
public void setMiddleName(String middleName) {
this.middleName = middleName;
}
public String getBirthDate() {
return birthDate;
}
public void setBirthDate(String birthDate) {
this.birthDate = birthDate;
}
public String getSnils() {
return snils;
}
public void setSnils(String snils) {
this.snils = snils;
}
public Document getDocument() {
return document;
}
public void setDocument(Document document) {
this.document = document;
}
}

View file

@ -0,0 +1,33 @@
package ru.micord.ervu.kafka.model;
import java.io.Serializable;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
/**
* @author Eduard Tihomirov
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class Response implements Serializable {
private static final long serialVersionUID = 1L;
private String ervuId;
private ErrorData errorData;
public String getErvuId() {
return ervuId;
}
public void setErvuId(String ervuId) {
this.ervuId = ervuId;
}
public ErrorData getErrorData() {
return errorData;
}
public void setErrorData(ErrorData errorData) {
this.errorData = errorData;
}
}

View file

@ -0,0 +1,8 @@
package ru.micord.ervu.kafka.service;
public interface ReplyingKafkaService<T, V> {
V sendMessageAndGetReply(String requestTopic,
String replyTopic,
T requestMessage);
}

View file

@ -0,0 +1,36 @@
package ru.micord.ervu.kafka.service.impl;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.springframework.kafka.requestreply.ReplyingKafkaTemplate;
import org.springframework.kafka.requestreply.RequestReplyFuture;
import ru.micord.ervu.kafka.service.ReplyingKafkaService;
/**
* @author gulnaz
*/
public abstract class BaseReplyingKafkaService<T, V> implements ReplyingKafkaService<T, V> {
@Override
public V sendMessageAndGetReply(String requestTopic, String replyTopic, T requestMessage) {
RequestReplyFuture<String, T, V> replyFuture = getTemplate().sendAndReceive(
getProducerRecord(requestTopic, replyTopic, requestMessage));
try {
return Optional.ofNullable(replyFuture.get())
.map(ConsumerRecord::value)
.orElseThrow(() -> new RuntimeException("Kafka return result is null"));
}
catch (InterruptedException | ExecutionException e) {
throw new RuntimeException("Failed to get kafka response", e);
}
}
protected abstract ReplyingKafkaTemplate<String, T, V> getTemplate();
protected abstract ProducerRecord<String, T> getProducerRecord(String requestTopic,
String replyTopic, T requestMessage);
}

View file

@ -0,0 +1,36 @@
package ru.micord.ervu.kafka.service.impl;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.kafka.common.header.internals.RecordHeader;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.kafka.requestreply.ReplyingKafkaTemplate;
import org.springframework.kafka.support.KafkaHeaders;
import org.springframework.stereotype.Service;
/**
* @author Eduard Tihomirov
*/
@Service
@Qualifier("person")
public class PersonReplyingKafkaService extends BaseReplyingKafkaService<String, String> {
private final ReplyingKafkaTemplate<String, String, String> replyingKafkaTemplate;
public PersonReplyingKafkaService(@Qualifier("person")
ReplyingKafkaTemplate<String, String, String> replyingKafkaTemplate) {
this.replyingKafkaTemplate = replyingKafkaTemplate;
}
@Override
protected ReplyingKafkaTemplate<String, String, String> getTemplate() {
return replyingKafkaTemplate;
}
@Override
protected ProducerRecord<String, String> getProducerRecord(String requestTopic, String replyTopic,
String requestMessage) {
ProducerRecord<String, String> record = new ProducerRecord<>(requestTopic, requestMessage);
record.headers().add(new RecordHeader(KafkaHeaders.REPLY_TOPIC, replyTopic.getBytes()));
return record;
}
}

View file

@ -0,0 +1,51 @@
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;
import org.apache.kafka.common.utils.Bytes;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.kafka.requestreply.ReplyingKafkaTemplate;
import org.springframework.kafka.support.KafkaHeaders;
import org.springframework.stereotype.Service;
import ru.micord.ervu.dto.SubpoenaRequestDto;
/**
* @author gulnaz
*/
@Service
@Qualifier("subpoena")
public class SubpoenaReplyingKafkaService extends BaseReplyingKafkaService<Object, Bytes> {
private final ReplyingKafkaTemplate<String, Object, Bytes> replyingKafkaTemplate;
@Value("${ervu.kafka.recruit.header.class}")
private String recruitHeaderClass;
@Value("${ervu.kafka.extract.header.class}")
private String extractHeaderClass;
public SubpoenaReplyingKafkaService(@Qualifier("subpoena")
ReplyingKafkaTemplate<String, Object, Bytes> replyingKafkaTemplate) {
this.replyingKafkaTemplate = replyingKafkaTemplate;
}
@Override
protected ReplyingKafkaTemplate<String, Object, Bytes> getTemplate() {
return replyingKafkaTemplate;
}
@Override
protected ProducerRecord<String, Object> getProducerRecord(String requestTopic, String replyTopic,
Object requestMessage) {
ProducerRecord<String, Object> record = new ProducerRecord<>(requestTopic,
UUID.randomUUID().toString(), requestMessage);
record.headers().add(new RecordHeader(KafkaHeaders.REPLY_TOPIC, replyTopic.getBytes()));
String headerClass = requestMessage instanceof SubpoenaRequestDto
? recruitHeaderClass : extractHeaderClass;
record.headers().add("class", headerClass.getBytes(StandardCharsets.UTF_8));
return record;
}
}

View file

@ -0,0 +1,10 @@
package ru.micord.ervu.property.grid;
/**
* @author gulnaz
*/
public class StaticColumn {
public String column;
public String type;
}

View file

@ -0,0 +1,88 @@
package ru.micord.ervu.property.grid;
import java.util.Collection;
import java.util.Collections;
import component.field.dataconvert.DataConverter;
import component.field.dataconvert.DataConverterProvider;
import component.field.persist.filter.AbstractFilterComponent;
import component.grid.model.PinnedType;
import property.grid.Column;
import property.grid.Formatter;
import utils.GridUtils;
import ru.cg.webbpm.modules.database.bean.AggregationFunction;
import ru.cg.webbpm.modules.database.bean.entity_graph.EntityColumn;
import ru.cg.webbpm.modules.standard_annotations.editor.Visible;
import ru.cg.webbpm.modules.webkit.annotations.Exclude;
import ru.cg.webbpm.modules.webkit.annotations.Model;
/**
* @author gulnaz
*/
@Model
public class StaticGridColumn extends AbstractFilterComponent<Object, Object>
implements Column {
public StaticColumn field;
public String displayName;
public String headerTooltip;
@Visible(predicate = "displayPopup != true")
public String columnTooltip;
public Integer width;
public boolean widthFixed;
public boolean autoHeight;
public boolean hidden;
public boolean sortable;
public boolean disableHiding;
public PinnedType pinned;
public boolean filter;
@Exclude
public Formatter<?, ?> formatter;
public AggregationFunction aggregationFunction;
@Exclude
public Formatter<?, ?> aggregationFormatter;
@Exclude
public Formatter<?, ?> exportFileFormatter;
public boolean displayPopup;
public boolean suppressHeaderMenu;
public EntityColumn getField() {
return GridUtils.toEntityColumn(field.column);
}
@Override
public String getDisplayName() {
return displayName;
}
public Collection<EntityColumn> getEntityColumns() {
return Collections.singleton(getField());
}
public AggregationFunction getAggregationFunction() {
return this.aggregationFunction;
}
public Formatter<?, ?> getFormatter() {
return this.formatter;
}
public Formatter<?, ?> getAggregationFormatter() {
return this.aggregationFormatter;
}
public Formatter<?, ?> getExportFormatter() {
return exportFileFormatter;
}
public Object convertData(Object rawValue) {
if (this.dataConverter != null) {
return this.dataConverter.convertValueForSave(rawValue);
}
else {
DataConverter converter = DataConverterProvider.getDataConverter(rawValue.getClass());
return converter.convertValueForSave(rawValue);
}
}
}

View file

@ -0,0 +1,62 @@
package ru.micord.ervu.security;
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.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.authentication.UsernamePasswordAuthenticationFilter;
import ru.micord.ervu.security.webbpm.jwt.filter.JwtAuthenticationFilter;
import ru.micord.ervu.security.webbpm.jwt.UnauthorizedEntryPoint;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private JwtAuthenticationFilter jwtAuthenticationFilter;
@Override
protected void configure(HttpSecurity http) throws Exception {
httpConfigure(http);
http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
}
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())
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
public AuthenticationEntryPoint entryPoint() {
return new UnauthorizedEntryPoint();
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
public JwtAuthenticationFilter jwtAuthenticationFilter() throws Exception {
JwtAuthenticationFilter jwtAuthenticationFilter = new JwtAuthenticationFilter("/**",
entryPoint()
);
jwtAuthenticationFilter.setAuthenticationManager(authenticationManagerBean());
return jwtAuthenticationFilter;
}
}

View file

@ -0,0 +1,89 @@
package ru.micord.ervu.security.esia.config;
import java.util.Arrays;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
* @author Eduard Tihomirov
*/
@Component
public class EsiaConfig {
@Value("${esia.scopes}")
private String esiaScopes;
@Value("${esia.base.uri}")
private String esiaBaseUri;
@Value("${esia.client.id}")
private String clientId;
@Value("${esia.redirect.url}")
private String redirectUrl;
@Value("${sign.url}")
private String signUrl;
@Value("${esia.client.cert.hash}")
private String clientCertHash;
@Value("${esia.request.timeout:60}")
private long requestTimeout;
@Value("${esia.connection.timeout:30}")
private long connectionTimeout;
@Value("${esia.logout.url:idp/ext/Logout}")
private String esiaLogoutUrl;
@Value("${esia.code.url:aas/oauth2/v3/te}")
private String esiaCodeUrl;
@Value("${esia.token.url:aas/oauth2/v3/te}")
private String esiaTokenUrl;
public String getEsiaScopes() {
String[] scopeItems = esiaScopes.split(",");
return String.join(" ", Arrays.stream(scopeItems).map(String::trim).toArray(String[]::new));
}
public String getClientId() {
return clientId;
}
public String getRedirectUrl() {
return redirectUrl;
}
public String getEsiaBaseUri() {
return esiaBaseUri;
}
public String getSignUrl() {
return signUrl;
}
public String getClientCertHash() {return clientCertHash;}
public long getRequestTimeout() {
return requestTimeout;
}
public long getConnectionTimeout() {
return connectionTimeout;
}
public String getEsiaLogoutUrl() {
return esiaLogoutUrl;
}
public String getEsiaCodeUrl() {
return esiaCodeUrl;
}
public String getEsiaTokenUrl() {
return esiaTokenUrl;
}
}

View file

@ -0,0 +1,92 @@
package ru.micord.ervu.security.esia.controller;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
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.*;
/**
* @author Eduard Tihomirov
*/
@RestController
public class EsiaController {
@Autowired
private EsiaAuthService esiaAuthService;
@Autowired
private PersonalDataService personalDataService;
@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) {
return esiaAuthService.getEsiaTokensByCode(code, request, response);
}
@RequestMapping(value = "/esia/refresh")
public void refreshToken(HttpServletRequest request, HttpServletResponse response) {
esiaAuthService.getEsiaTokensByRefreshToken(request, response);
}
@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;
}
PersonModel personModel = personalDataService.getPersonModel(accessToken);
PersonDataModel personDataModel = new PersonDataModel();
personDataModel.birthDate = personModel.getBirthDate().toString();
personDataModel.fullname = personModel.getLastName() + " " + personModel.getFirstName() + " "
+ personModel.getMiddleName();
personDataModel.snils = personModel.getSnils();
personDataModel.seriesAndNumber =
personModel.getPassportModel().getSeries() + " " + personModel.getPassportModel()
.getNumber();
personDataModel.issueDate = personModel.getPassportModel().getIssueDate().toString();
personDataModel.issuedBy = personModel.getPassportModel().getIssuedBy();
personDataModel.issueId = personModel.getPassportModel().getIssueId();
return personDataModel;
}
@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;
}
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);
}
}

View file

@ -0,0 +1,97 @@
package ru.micord.ervu.security.esia.model;
import java.io.Serializable;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* @author Eduard Tihomirov
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class EsiaAccessToken implements Serializable {
private static final long serialVersionUID = -8580344482588383113L;
private Long exp;
private String scope;
private String iss;
private Long nbf;
@JsonProperty("urn:esia:sid")
private String sid;
@JsonProperty("urn:esia:sbj_id")
private String sbj_id;
private String client_id;
private Long iat;
public Long getExp() {
return exp;
}
public void setExp(Long exp) {
this.exp = exp;
}
public String getScope() {
return scope;
}
public void setScope(String scope) {
this.scope = scope;
}
public String getIss() {
return iss;
}
public void setIss(String iss) {
this.iss = iss;
}
public Long getNbf() {
return nbf;
}
public void setNbf(Long nbf) {
this.nbf = nbf;
}
public String getSid() {
return sid;
}
public void setSid(String sid) {
this.sid = sid;
}
public String getSbj_id() {
return sbj_id;
}
public void setSbj_id(String sbj_id) {
this.sbj_id = sbj_id;
}
public String getClient_id() {
return client_id;
}
public void setClient_id(String client_id) {
this.client_id = client_id;
}
public Long getIat() {
return iat;
}
public void setIat(Long iat) {
this.iat = iat;
}
}

View file

@ -0,0 +1,94 @@
package ru.micord.ervu.security.esia.model;
import java.io.Serializable;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
/**
* @author Eduard Tihomirov
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class EsiaTokenResponse implements Serializable {
private static final long serialVersionUID = 7655328287602576975L;
private String id_token;
private String access_token;
private String refresh_token;
private String state;
private String token_type;
private Long expires_in;
private String error;
private String error_description;
public String getId_token() {
return id_token;
}
public void setId_token(String id_token) {
this.id_token = id_token;
}
public String getAccess_token() {
return access_token;
}
public void setAccess_token(String access_token) {
this.access_token = access_token;
}
public String getRefresh_token() {
return refresh_token;
}
public void setRefresh_token(String refresh_token) {
this.refresh_token = refresh_token;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getToken_type() {
return token_type;
}
public void setToken_type(String token_type) {
this.token_type = token_type;
}
public Long getExpires_in() {
return expires_in;
}
public void setExpires_in(Long expires_in) {
this.expires_in = expires_in;
}
public String getError() {
return error;
}
public void setError(String error) {
this.error = error;
}
public String getError_description() {
return error_description;
}
public void setError_description(String error_description) {
this.error_description = error_description;
}
}

View file

@ -0,0 +1,42 @@
package ru.micord.ervu.security.esia.model;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
/**
* Данные HTML-формы для POST с Content-Type=application/x-www-form-urlencoded.
*/
public class FormUrlencoded {
// todo: private final Map<String, List<String>> ...
private final Map<String, String> formData = new HashMap<>();
/**
* Устанавливает параметр в форму.
*/
public FormUrlencoded setParameter(String name, String value) {
if (name != null) formData.put(name, value);
return this;
}
/**
* Собирает из формы и возвращает строку в виде application/x-www-form-urlencoded.
*/
public String toFormUrlencodedString() {
final StringBuilder sb = new StringBuilder();
formData.forEach((key, value) -> {
if (key != null) key = URLEncoder.encode(key, StandardCharsets.UTF_8);
if (value != null) value = URLEncoder.encode(value, StandardCharsets.UTF_8);
if (sb.length() > 0) sb.append("&");
sb.append(key).append("=").append(value);
});
return sb.toString();
}
@Override
public String toString() {
return toFormUrlencodedString();
}
}

View file

@ -0,0 +1,67 @@
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;
/**
* @author Eduard Tihomirov
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class PassportModel implements Serializable {
public static final long serialVersionUID = 1L;
private String series;
private String number;
@JsonFormat(pattern = "dd.MM.yyyy")
private Date issueDate;
private String issueId;
private String issuedBy;
public String getSeries() {
return series;
}
public void setSeries(String series) {
this.series = series;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public Date getIssueDate() {
return issueDate;
}
public void setIssueDate(Date issueDate) {
this.issueDate = issueDate;
}
public String getIssueId() {
return issueId;
}
public void setIssueId(String issueId) {
this.issueId = issueId;
}
public String getIssuedBy() {
return issuedBy;
}
public void setIssuedBy(String issuedBy) {
this.issuedBy = issuedBy;
}
}

View file

@ -0,0 +1,24 @@
package ru.micord.ervu.security.esia.model;
import ru.cg.webbpm.modules.webkit.annotations.Model;
/**
* @author Eduard Tihomirov
*/
@Model
public class PersonDataModel {
public String fullname;
public String birthDate;
public String snils;
public String seriesAndNumber;
public String issueDate;
public String issueId;
public String issuedBy;
}

View file

@ -0,0 +1,105 @@
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;
/**
* @author Eduard Tihomirov
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class PersonModel implements Serializable {
private static final long serialVersionUID = 1L;
private String prnsId;
private String rIdDoc;
private String lastName;
private String firstName;
private String middleName;
@JsonFormat(pattern = "dd.MM.yyyy")
private Date birthDate;
private String snils;
private PassportModel passportModel;
public String getPrnsId() {
return prnsId;
}
public void setPrnsId(String prnsId) {
this.prnsId = prnsId;
}
public String getrIdDoc() {
return rIdDoc;
}
public void setrIdDoc(String rIdDoc) {
this.rIdDoc = rIdDoc;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getMiddleName() {
return middleName;
}
public void setMiddleName(String middleName) {
this.middleName = middleName;
}
public Date getBirthDate() {
return birthDate;
}
public void setBirthDate(Date birthDate) {
this.birthDate = birthDate;
}
public String getSnils() {
return snils;
}
public void setSnils(String snils) {
this.snils = snils;
}
public PassportModel getPassportModel() {
return passportModel;
}
public void setPassportModel(PassportModel passportModel) {
this.passportModel = passportModel;
}
@Override
public String toString() {
return firstName + " " + middleName + " " + lastName + " " + birthDate + " " + snils + " "
+ passportModel.getNumber() + " " + passportModel.getSeries() + " "
+ passportModel.getIssuedBy() + " " + passportModel.getIssueId() + " "
+ passportModel.getIssueDate();
}
}

View file

@ -0,0 +1,426 @@
package ru.micord.ervu.security.esia.service;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URL;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Base64;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
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 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.config.EsiaConfig;
import ru.micord.ervu.security.esia.model.FormUrlencoded;
import ru.micord.ervu.security.esia.model.EsiaAccessToken;
import ru.micord.ervu.security.esia.model.EsiaTokenResponse;
import ru.micord.ervu.security.esia.model.PersonModel;
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.service.JwtTokenService;
import ru.micord.ervu.security.webbpm.jwt.model.Token;
/**
* @author Eduard Tihomirov
*/
@Service
public class EsiaAuthService {
@Value("${cookie.path:#{null}}")
private String path;
@Autowired
private ObjectMapper objectMapper;
@Autowired
private EsiaConfig esiaConfig;
@Autowired
private JwtTokenService jwtTokenService;
@Autowired
@Qualifier("person")
private ReplyingKafkaService<String, String> replyingKafkaService;
@Autowired
private PersonalDataService personalDataService;
@Value("${ervu.kafka.reply.topic}")
private String requestReplyTopic;
@Value("${ervu.kafka.request.topic}")
private String requestTopic;
public String generateAuthCodeUrl() {
try {
String clientId = esiaConfig.getClientId();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy.MM.dd HH:mm:ss xx");
ZonedDateTime dt = ZonedDateTime.now();
String timestamp = dt.format(formatter);
String state = UUID.randomUUID().toString();
String redirectUrl = esiaConfig.getRedirectUrl();
String redirectUrlEncoded = redirectUrl.replaceAll(":", "%3A")
.replaceAll("/", "%2F");
String scope = esiaConfig.getEsiaScopes();
Map<String, String> parameters = new LinkedHashMap<String, String>();
parameters.put("client_id", clientId);
parameters.put("scope", scope);
parameters.put("timestamp", timestamp);
parameters.put("state", state);
parameters.put("redirect_uri", esiaConfig.getRedirectUrl());
String clientSecret = signMap(parameters);
String responseType = "code";
String authUrl = esiaConfig.getEsiaBaseUri() + esiaConfig.getEsiaCodeUrl();
URL url = new URL(authUrl);
Map<String, String> params = mapOf("scope", scope,
"timestamp", urlEncode(timestamp),
"state", state,
"client_id", clientId,
"client_secret", clientSecret,
"response_type", responseType,
"redirect_uri", redirectUrlEncoded,
"client_certificate_hash", esiaConfig.getClientCertHash());
return makeRequest(url, params);
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
private static Map<String, String> mapOf(String... params) {
if (params.length % 2 != 0) {
throw new IllegalArgumentException("Invalid params count");
}
Map<String, String> map = new LinkedHashMap<>(params.length / 2);
for (int i = 0; i < params.length / 2; i++) {
map.put(params[i * 2], params[i * 2 + 1]);
}
return map;
}
private static String urlEncode(String s) {
try {
return URLEncoder.encode(s, "UTF-8")
.replace("+", "%20");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
private static String makeRequest(URL url, Map<String, String> params) {
StringBuilder uriBuilder = new StringBuilder(url.toString());
uriBuilder.append('?');
for (Map.Entry<String, String> node : params.entrySet()) {
uriBuilder.append(node.getKey()).append('=').append(node.getValue()).append("&");
}
return uriBuilder.toString();
}
public boolean getEsiaTokensByCode(String esiaAuthCode, HttpServletRequest request, HttpServletResponse response) {
try {
String clientId = esiaConfig.getClientId();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy.MM.dd HH:mm:ss xx");
ZonedDateTime dt = ZonedDateTime.now();
String timestamp = dt.format(formatter);
String state = UUID.randomUUID().toString();
String redirectUrl = esiaConfig.getRedirectUrl();
String scope = esiaConfig.getEsiaScopes();
Map<String, String> parameters = new LinkedHashMap<String, String>();
parameters.put("client_id", clientId);
parameters.put("scope", scope);
parameters.put("timestamp", timestamp);
parameters.put("state", state);
parameters.put("redirect_uri", redirectUrl);
parameters.put("code", esiaAuthCode);
String clientSecret = signMap(parameters);
String authUrl = esiaConfig.getEsiaBaseUri() + esiaConfig.getEsiaTokenUrl();
String postBody = new FormUrlencoded()
.setParameter("client_id", clientId)
.setParameter("code", esiaAuthCode)
.setParameter("grant_type", "authorization_code")
.setParameter("client_secret", clientSecret)
.setParameter("state", state)
.setParameter("redirect_uri", redirectUrl)
.setParameter("scope", scope)
.setParameter("timestamp", timestamp)
.setParameter("token_type", "Bearer")
.setParameter("client_certificate_hash", esiaConfig.getClientCertHash())
.toFormUrlencodedString();
HttpRequest postReq = HttpRequest.newBuilder(URI.create(authUrl))
.header(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded")
.POST(HttpRequest.BodyPublishers.ofString(postBody))
.timeout(Duration.ofSeconds(esiaConfig.getRequestTimeout()))
.build();
HttpResponse<String> postResp = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(esiaConfig.getConnectionTimeout()))
.build()
.send(postReq, HttpResponse.BodyHandlers.ofString());
String responseString = postResp.body();
EsiaTokenResponse tokenResponse = objectMapper.readValue(responseString, EsiaTokenResponse.class);
if (tokenResponse != null && tokenResponse.getError() != null) {
throw new RuntimeException(tokenResponse.getError_description());
}
String cookiePath = null;
if (path != null) {
cookiePath = path;
}
else {
cookiePath = request.getContextPath();
}
String accessToken = tokenResponse.getAccess_token();
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("is_auth", "true");
isAuth.setPath(cookiePath);
isAuth.setMaxAge(tokenResponse.getExpires_in().intValue());
response.addCookie(isAuth);
return true;
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
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 clientId = esiaConfig.getClientId();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy.MM.dd HH:mm:ss xx");
ZonedDateTime dt = ZonedDateTime.now();
String timestamp = dt.format(formatter);
String state = UUID.randomUUID().toString();
String redirectUrl = esiaConfig.getRedirectUrl();
Map<String, String> parameters = new LinkedHashMap<String, String>();
parameters.put("client_id", clientId);
parameters.put("scope", esiaConfig.getEsiaScopes());
parameters.put("timestamp", timestamp);
parameters.put("state", state);
parameters.put("redirect_uri", esiaConfig.getRedirectUrl());
parameters.put("refresh_token", refreshToken);
String clientSecret = signMap(parameters);
String authUrl = esiaConfig.getEsiaBaseUri() + esiaConfig.getEsiaTokenUrl();
String postBody = new FormUrlencoded()
.setParameter("client_id", clientId)
.setParameter("refresh_token", refreshToken)
.setParameter("grant_type", "refresh_token")
.setParameter("client_secret", clientSecret)
.setParameter("state", state)
.setParameter("redirect_uri", redirectUrl)
.setParameter("scope", esiaConfig.getEsiaScopes())
.setParameter("timestamp", timestamp)
.setParameter("token_type", "Bearer")
.setParameter("client_certificate_hash", esiaConfig.getClientCertHash())
.toFormUrlencodedString();
HttpRequest postReq = HttpRequest.newBuilder(URI.create(authUrl))
.header(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded")
.POST(HttpRequest.BodyPublishers.ofString(postBody))
.timeout(Duration.ofSeconds(esiaConfig.getRequestTimeout()))
.build();
HttpResponse<String> postResp = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(esiaConfig.getConnectionTimeout()))
.build()
.send(postReq, HttpResponse.BodyHandlers.ofString());
String responseString = postResp.body();
EsiaTokenResponse tokenResponse = objectMapper.readValue(responseString, EsiaTokenResponse.class);
if (tokenResponse != null && tokenResponse.getError() != null) {
throw new RuntimeException(tokenResponse.getError_description());
}
String accessToken = tokenResponse.getAccess_token();
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("is_auth", "true");
isAuth.setMaxAge(tokenResponse.getExpires_in().intValue());
isAuth.setPath(cookiePath);
response.addCookie(isAuth);
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
private String signMap(Map<String, String> paramsToSign) {
try {
StringBuilder toSign = new StringBuilder();
for (String s : paramsToSign.values()) {
toSign.append(s);
}
String requestBody = toSign.toString();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(esiaConfig.getSignUrl()))
.header("Content-Type", "text/plain")
.POST(HttpRequest.BodyPublishers.ofString(requestBody, StandardCharsets.UTF_8))
.build();
HttpResponse<String> response = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(esiaConfig.getConnectionTimeout()))
.build()
.send(request, HttpResponse.BodyHandlers.ofString());
errorHandler(response);
return response.body();
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
private void errorHandler(HttpResponse httpResponse) {
if (httpResponse.statusCode() != 200) {
throw new RuntimeException(httpResponse.statusCode() + " " + httpResponse.body());
}
}
public String logout(HttpServletRequest request, HttpServletResponse response) {
try {
Cookie[] cookies = request.getCookies();
if (cookies != null)
for (Cookie cookie : cookies) {
if (cookie.getName().equals("auth_token") || cookie.getName().equals("refresh_token")
|| cookie.getName().equals("access_token") || cookie.getName().equals("is_auth")) {
cookie.setValue("");
cookie.setMaxAge(0);
response.addCookie(cookie);
}
}
String logoutUrl = esiaConfig.getEsiaBaseUri() + esiaConfig.getEsiaLogoutUrl();
String redirectUrl = esiaConfig.getRedirectUrl();
URL url = new URL(logoutUrl);
Map<String, String> params = mapOf(
"client_id", esiaConfig.getClientId(),
"redirect_url", redirectUrl);
return makeRequest(url, params);
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
public String getErvuId(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();
}
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
private Person copyToPerson(PersonModel personModel) {
Person person = new Person();
person.setBirthDate(personModel.getBirthDate().toString());
person.setFirstName(personModel.getFirstName());
person.setLastName(personModel.getLastName());
person.setSnils(personModel.getSnils());
person.setMiddleName(personModel.getMiddleName());
Document document = new Document();
document.setNumber(personModel.getPassportModel().getNumber());
document.setSeries(personModel.getPassportModel().getSeries());
document.setIssueDate(personModel.getPassportModel().getIssueDate().toString());
return person;
}
}

View file

@ -0,0 +1,91 @@
package ru.micord.ervu.security.esia.service;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import java.util.Base64;
import com.fasterxml.jackson.databind.ObjectMapper;
import ru.micord.ervu.security.esia.config.EsiaConfig;
import ru.micord.ervu.security.esia.model.EsiaAccessToken;
import ru.micord.ervu.security.esia.model.PassportModel;
import ru.micord.ervu.security.esia.model.PersonModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Service;
/**
* @author Eduard Tihomirov
*/
@Service
public class EsiaPersonalDataService implements PersonalDataService {
@Autowired
private EsiaConfig esiaConfig;
@Autowired
private ObjectMapper objectMapper;
@Override
public PersonModel getPersonModel(String accessToken) {
try {
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 prnsId = esiaAccessToken.getSbj_id();
PersonModel personModel = getPersonData(prnsId, accessToken);
personModel.setPassportModel(
getPassportModel(prnsId, accessToken, personModel.getrIdDoc()));
personModel.setPrnsId(prnsId);
return personModel;
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
private PassportModel getPassportModel(String prsnId, String accessToken, String docId) {
try {
String url = esiaConfig.getEsiaBaseUri() + "rs/prns/" + prsnId;
HttpRequest getReqDoc = HttpRequest.newBuilder(URI.create(url + "/docs/" + docId))
.header(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded")
.header("Authorization", "Bearer ".concat(accessToken))
.GET()
.timeout(Duration.ofSeconds(esiaConfig.getRequestTimeout()))
.build();
HttpResponse<String> getRespDoc = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(esiaConfig.getConnectionTimeout()))
.build()
.send(getReqDoc, HttpResponse.BodyHandlers.ofString());
return objectMapper.readValue(getRespDoc.body(), PassportModel.class);
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
private PersonModel getPersonData(String prsnId, String accessToken) {
try {
String url = esiaConfig.getEsiaBaseUri() + "rs/prns/";
HttpRequest getReq = HttpRequest.newBuilder(URI.create(url + prsnId))
.header(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded")
.header("Authorization", "Bearer ".concat(accessToken))
.GET()
.timeout(Duration.ofSeconds(esiaConfig.getRequestTimeout()))
.build();
HttpResponse<String> getResp = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(esiaConfig.getConnectionTimeout()))
.build()
.send(getReq, HttpResponse.BodyHandlers.ofString());
return objectMapper.readValue(getResp.body(), PersonModel.class);
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
}

View file

@ -0,0 +1,11 @@
package ru.micord.ervu.security.esia.service;
import ru.micord.ervu.security.esia.model.PersonModel;
/**
* @author Eduard Tihomirov
*/
public interface PersonalDataService {
PersonModel getPersonModel(String accessToken);
}

View file

@ -0,0 +1,77 @@
package ru.micord.ervu.security.webbpm.jwt;
import java.util.Collection;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.SpringSecurityCoreVersion;
/**
* @author zamaliev
*/
public class JwtAuthentication implements Authentication {
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
private final String userAccountId;
private final Authentication authentication;
private final String token;
public JwtAuthentication(Authentication authentication, String userAccountId, String token) {
this.userAccountId = userAccountId;
this.authentication = authentication;
this.token = token;
}
public JwtAuthentication(Authentication authentication, String userAccountId) {
this(authentication, userAccountId, null);
}
public String getUserAccountId() {
return userAccountId;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return authentication.getAuthorities();
}
@Override
public Object getCredentials() {
return authentication.getCredentials();
}
@Override
public Object getDetails() {
return authentication.getDetails();
}
@Override
public Object getPrincipal() {
return authentication.getPrincipal();
}
@Override
public boolean isAuthenticated() {
if (authentication == null) {
return false;
}
else {
return authentication.isAuthenticated();
}
}
@Override
public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
authentication.setAuthenticated(isAuthenticated);
}
@Override
public String getName() {
return authentication.getName();
}
public String getToken() {
return this.token;
}
}

View file

@ -0,0 +1,57 @@
package ru.micord.ervu.security.webbpm.jwt;
import io.jsonwebtoken.ExpiredJwtException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.CredentialsExpiredException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.stereotype.Component;
import ru.micord.ervu.security.webbpm.jwt.model.Token;
import ru.micord.ervu.security.webbpm.jwt.service.JwtTokenService;
@Component
public class JwtAuthenticationProvider implements AuthenticationProvider {
private final JwtTokenService jwtTokenService;
@Autowired
public JwtAuthenticationProvider(JwtTokenService jwtTokenService) {
this.jwtTokenService = jwtTokenService;
}
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
JwtAuthentication jwtAuthentication = (JwtAuthentication) authentication;
String tokenStr = jwtAuthentication.getToken();
Token token;
try {
token = jwtTokenService.getToken(tokenStr);
}
catch (ExpiredJwtException e) {
throw new CredentialsExpiredException("The access token is expired and not valid anymore.",
e
);
}
catch (Exception e) {
throw new BadCredentialsException("Authentication Failed.", e);
}
if (!jwtTokenService.isValid(token)) {
throw new BadCredentialsException("Auth token is not valid for user " + token.getUserAccountId());
}
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
new UsernamePasswordAuthenticationToken(token.getUserAccountId(), null);
return new JwtAuthentication(usernamePasswordAuthenticationToken, token.getUserAccountId());
}
@Override
public boolean supports(Class<?> aClass) {
return JwtAuthentication.class.isAssignableFrom(aClass);
}
}

View file

@ -0,0 +1,29 @@
package ru.micord.ervu.security.webbpm.jwt;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
/**
* {@link AuthenticationEntryPoint} that rejects all requests with an unauthorized error message.
*/
public class UnauthorizedEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception) throws IOException {
//for correct work with cross domain request
if ("OPTIONS".equals(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
}
else {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED,
"Unauthorized: Authentication token was either missing or invalid."
);
}
}
}

View file

@ -0,0 +1,84 @@
package ru.micord.ervu.security.webbpm.jwt.filter;
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;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.CredentialsExpiredException;
import org.springframework.security.core.Authentication;
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 ru.micord.ervu.security.webbpm.jwt.JwtAuthentication;
/**
* @author Flyur Karimov
*/
public class JwtAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
private final AuthenticationEntryPoint entryPoint;
public JwtAuthenticationFilter(String securityPath, AuthenticationEntryPoint entryPoint) {
super(securityPath);
this.entryPoint = entryPoint;
}
@Override
public Authentication attemptAuthentication(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse) throws AuthenticationException {
String token = extractAuthTokenFromRequest(httpServletRequest);
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null) {
authentication = new JwtAuthentication(null, null, token);
}
try {
authentication = getAuthenticationManager().authenticate(authentication);
}
catch (CredentialsExpiredException e) {
httpServletResponse.setStatus(401);
LOGGER.warn(e.getMessage());
}
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 {
SecurityContextHolder.getContext().setAuthentication(authentication);
chain.doFilter(request, response);
}
@Override
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;
}
}

View file

@ -0,0 +1,37 @@
package ru.micord.ervu.security.webbpm.jwt.model;
import java.util.Date;
public class Token {
private final String userAccountId;
private final String issuer;
private final Date expirationDate;
private final String value;
public Token(String userAccountId, String issuer, Date expirationDate, String value) {
this.userAccountId = userAccountId;
this.issuer = issuer;
this.expirationDate = expirationDate;
this.value = value;
}
public String getUserAccountId() {
return userAccountId;
}
public String getIssuer() {
return issuer;
}
public Date getExpirationDate() {
return expirationDate;
}
public boolean isExpired() {
return expirationDate.before(new Date());
}
public String getValue() {
return value;
}
}

View file

@ -0,0 +1,87 @@
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 io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
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.webbpm.jwt.model.Token;
import ru.cg.webbpm.modules.resources.api.ResourceMetadataUtils;
/**
* @author Flyur Karimov
*/
@Component
public class JwtTokenService {
private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
@Value("${webbpm.security.token.issuer:}")
private final String tokenIssuerName =
ResourceMetadataUtils.PROJECT_GROUP_ID + "." + ResourceMetadataUtils.PROJECT_ARTIFACT_ID;
private final SecretKey SIGNING_KEY;
@Autowired
public JwtTokenService(@Value("${webbpm.security.token.secret.key:ZjE5ZjMxNmYtODViZC00ZTQ5LWIxZmYtOGEzYzE3Yjc1MDVk}")
String secretKey) {
byte[] encodedKey = Base64.getDecoder().decode(secretKey);
this.SIGNING_KEY = Keys.hmacShaKeyFor(encodedKey);
}
public Token createAccessToken(String userAccountId, Long expiresIn, String ervuId) {
Date expirationDate = new Date(System.currentTimeMillis() + 1000L * expiresIn);
String value = Jwts.builder()
.setSubject(userAccountId + ":" + ervuId)
.setIssuer(tokenIssuerName)
.setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(expirationDate)
.signWith(SIGNING_KEY)
.compact();
return new Token(userAccountId + ":" + ervuId, tokenIssuerName, expirationDate, value);
}
public boolean isValid(Token token) {
if (!tokenIssuerName.equals(token.getIssuer())) {
LOGGER.warn("Unknown token issuer {}", token.getIssuer());
return false;
}
if (token.isExpired()) {
LOGGER.info("Token {} is expired ", token.getValue());
return false;
}
return true;
}
public Token getToken(String token) {
Claims claims = Jwts.parser()
.setSigningKey(SIGNING_KEY)
.parseClaimsJws(token)
.getBody();
return new Token(claims.getSubject(), claims.getIssuer(), claims.getExpiration(), token);
}
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];
}
}

View file

@ -0,0 +1,67 @@
package ru.micord.ervu.service.form;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import ru.micord.ervu.component.field.BaseFieldLoadComponent;
import model.BpmnVariableForSave;
import model.FieldData;
import service.container.AbstractFormService;
import utils.FormUtils;
import ru.cg.webbpm.modules.database.bean.entity_graph.EntityColumn;
/**
* @author gulnaz
*/
public class LoadFormService extends AbstractFormService {
@Override
protected Object saveDataById(Object o, List<FieldData> list) {
throw new UnsupportedOperationException();
}
@Override
protected Map<EntityColumn, Object> getValuesForSave(Object o, List<FieldData> list) {
throw new UnsupportedOperationException();
}
@Override
protected List<FieldData> loadData(Object dto, List<String> loadableComponentIds) {
List<FieldData> fieldData = new ArrayList<>();
FormUtils.getFormComponents(this, BaseFieldLoadComponent.class)
.forEach(component -> {
FieldData data = component.loadFrom(dto);
fieldData.add(data);
});
return fieldData;
}
@Override
public Object saveData(String s, List<FieldData> list, Boolean aBoolean,
List<BpmnVariableForSave> list1) throws Exception {
throw new UnsupportedOperationException();
}
@Override
public List<FieldData> loadData() {
throw new UnsupportedOperationException();
}
@Override
public Object deleteData(Object o) {
throw new UnsupportedOperationException();
}
@Override
public Object deleteData(String s, List<BpmnVariableForSave> list) {
throw new UnsupportedOperationException();
}
@Override
public Object parseId(String s) {
return null;
}
}

View file

@ -0,0 +1,70 @@
package ru.micord.ervu.service.rpc;
import com.google.protobuf.InvalidProtocolBufferException;
import org.apache.kafka.common.utils.Bytes;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import ru.micord.ervu.dto.FileData;
import ru.micord.ervu.dto.ExtractRequestDto;
import rtl.pgs.ervu.proto.ExtractRegistry;
import rtl.pgs.ervu.proto.ResponseData;
import ru.micord.ervu.kafka.service.ReplyingKafkaService;
import ru.micord.ervu.security.webbpm.jwt.service.JwtTokenService;
import ru.cg.webbpm.modules.standard_annotations.validation.NotNull;
import ru.cg.webbpm.modules.webkit.annotations.RpcCall;
import ru.cg.webbpm.modules.webkit.annotations.RpcService;
import ru.cg.webbpm.modules.webkit.beans.Behavior;
/**
* @author gulnaz
*/
@RpcService
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}")
private String registryExtractReplyTopic;
@NotNull()
public String formatExtractRegistry;
public ExtractRpcService(
JwtTokenService jwtTokenService,
@Qualifier("subpoena") ReplyingKafkaService<Object, Bytes> replyingKafkaService) {
this.jwtTokenService = jwtTokenService;
this.replyingKafkaService = replyingKafkaService;
}
@RpcCall
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();
try {
ResponseData responseData = ResponseData.parseFrom(reply);
ExtractRegistry extractRegistry = responseData.getDataRegistryInformation()
.getExtractRegistry();
return new FileData(extractRegistry.getFileName(), extractRegistry.getFileType(),
extractRegistry.getFile().toByteArray());
}
catch (InvalidProtocolBufferException e) {
throw new RuntimeException("Failed to parse data", e);
}
}
}

View file

@ -0,0 +1,26 @@
package ru.micord.ervu.service.rpc;
import java.util.List;
import model.FieldData;
import service.container.FormService;
import ru.cg.webbpm.modules.standard_annotations.validation.NotNull;
import ru.cg.webbpm.modules.webkit.annotations.RpcCall;
import ru.cg.webbpm.modules.webkit.annotations.RpcService;
import ru.cg.webbpm.modules.webkit.beans.Behavior;
/**
* @author gulnaz
*/
@RpcService
public class LoadFormRpcService extends Behavior {
@NotNull
public FormService formService;
@RpcCall
public List<FieldData> loadData(Object dto) {
return formService.loadData(dto);
}
}

View file

@ -0,0 +1,30 @@
package ru.micord.ervu.util;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import org.springframework.util.StringUtils;
/**
* @author gulnaz
*/
public final class DateUtil {
private static final DateTimeFormatter DEFAULT_FORMATTER = DateTimeFormatter.ofPattern("dd.MM.yyyy");
private DateUtil() {}
public static LocalDate convertToLocalDate(String date) {
return StringUtils.hasText(date)
? LocalDate.parse(date, DateTimeFormatter.ISO_LOCAL_DATE)
: null;
}
public static String convertToString(LocalDate date) {
return date == null ? "" : date.format(DEFAULT_FORMATTER);
}
public static String convertToString(LocalDate date, DateTimeFormatter formatter) {
return date == null ? "" : date.format(formatter);
}
}

View file

@ -1,25 +0,0 @@
package ru.micord.security;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
@EnableWebSecurity
//@EnableAuthorizationServer
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeHttpRequests()
.antMatchers("/**")
.permitAll();
return http.build();
}
}

View file

@ -0,0 +1,34 @@
syntax = "proto3";
package rtl.pgs.ervu;
import "google/protobuf/timestamp.proto";
option java_multiple_files = true;
option java_outer_classname = "LkrpResponse";
option java_package = "rtl.pgs.ervu.proto";
message ExtractRegistry {
string fileName = 1;
string fileType = 2;
string fileDatetime = 3;
bytes file = 4;
};
message DataRegistryInformation {
ExtractRegistry extractRegistry = 1;
};
message ResponseData {
string lastName = 1;
string firstName = 2;
string middleName = 3;
string birthDate = 5;
string type = 4;
string series = 6;
string number = 7;
string issueDate = 8;
string issueOrg = 9;
string issueIdCode = 10;
string idERN = 11;
DataRegistryInformation dataRegistryInformation = 12;
};

View file

@ -0,0 +1,107 @@
syntax = "proto3";
package proto.ervu.rp.summons;
option java_multiple_files = true;
option java_outer_classname = "SummonsResponse";
message Sig {
string name = 1;
bytes file = 2;
}
message SummonsDocumentCopy {
string name = 1;
bytes file = 2;
}
message DocumentsSummons {
SummonsDocumentCopy summonsDocumentCopy = 1;
Sig sig = 2;
}
message MeasuresTemporary {
bool useFact = 1;
string startDate = 2;
string measureCode = 3;
string measureName = 4;
bool measureStatus = 5;
}
message MeasuresTemporaryPackage {
bool useFactPackage = 1;
string measureNumber = 2;
string militaryCommissariatName = 3;
string applicationPackageStartDate = 4;
string packageStartDate = 5;
bool packageMeasureStatus = 6;
repeated MeasuresTemporary measuresTemporaries = 7;
}
message SummonsInfo {
string summonsId = 1;
bool summonsUseFact = 2;
string summonsSeries = 3;
string summonsNumber = 4;
string reasonCode = 5;
string reasonName = 6;
string militaryCommissariatName = 7;
string militaryCommissariatAddress = 8;
string visitDate = 9;
string visitTime = 10;
bool validityPeriodSummons = 11;
string summonsStatusCode = 12;
string summonsStatusName = 13;
string placementDateSummons = 14;
string estimatedDateSummons = 15;
string deliveryTypeSummonsCode = 16;
string deliveryTypeSummonsName = 17;
string militaryComissar = 18;
string militaryComissarFirstName = 19;
string militaryComissarMiddleName = 20;
repeated MeasuresTemporaryPackage measuresTemporaryPackages = 21;
repeated DocumentsSummons documentsSummons = 22;
}
message RecruitmentInfo {
string militaryCommissariatCode = 1;
string militaryCommissariatName = 2;
string recruitmentStatusCode = 3;
string recruitmentStatusName = 4;
string recruitmentStart = 5;
string recruitmentReasonCode = 6;
string recruitmentReasonName = 7;
bool recruitmentDocStatus = 8;
string recruitmentDocDate = 9;
}
message ResponseDataAddress {
string addressCode = 1;
string addressTypeName = 2;
string addressReg = 3;
string addressRegDateStart = 4;
string addressRegDateEnd = 5;
}
message SummonsResponseData {
string lastName = 1;
string firstName = 2;
string middleName = 3;
string birthDate = 4;
string type = 5;
string series = 6;
string number = 7;
string issueDate = 8;
string issueOrg = 9;
string issueIdCode = 10;
bool status = 11;
string idERN = 12;
repeated ResponseDataAddress addresses = 13;
RecruitmentInfo recruitmentInfo = 14;
repeated SummonsInfo summonsInfos = 15;
};
message SummonsErrorResponseData {
string code = 1;
string name = 2;
}

View file

@ -0,0 +1,10 @@
<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>

31
config/micord.env Normal file
View file

@ -0,0 +1,31 @@
TZ=Europe/Moscow
# App datasource
DB_APP_USERNAME=ervu-lkrp-fl
DB_APP_PASSWORD=ervu-lkrp-fl
DB_APP_HOST=10.10.31.119
DB_APP_PORT=5432
DB_APP_NAME=ervu-lkrp-fl
ESIA_SCOPES=snils, fullname, birthdate, id_doc
ESIA_BASE_URI=https://esia-portal1.test.gosuslugi.ru/
ESIA_CLIENT_ID=MNSV89
ESIA_REDIRECT_URL=https://lkrp-dev.micord.ru/fl/
SIGN_URL=https://ervu-sign-dev.k8s.micord.ru/sign
ESIA_CLIENT_CERT_HASH=04508B4B0B58776A954A0E15F574B4E58799D74C61EE020B3330716C203E3BDD
ERVU_KAFKA_BOOTSTRAP_SERVERS=localhost:9092
ERVU_KAFKA_REPLY_TOPIC=ervu.lkpr.person.search.response
ERVU_KAFKA_GROUP_ID=1
ERVU_KAFKA_REQUEST_TOPIC=ervu.lkpr.person.search.request
ERVU_KAFKA_REPLY_TIMEOUT=30
ERVU_KAFKA_SEND_SECURITY_PROTOCOL=SASL_PLAINTEXT
ERVU_KAFKA_SASL_MECHANISM=SCRAM-SHA-256
ERVU_KAFKA_SEND_USERNAME=user1
ERVU_KAFKA_SEND_PASSWORD=Blfi9d2OFG
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

View file

@ -28,3 +28,27 @@ xa-data-source add \
/system-property=security.password.regex:add(value="^((?=(.*\\d){1,})(?=.*[a-zа-яё])(?=.*[A-ZА-ЯЁ]).{8,})$")
/system-property=fias.enable:add(value=false)
/system-property=bpmn.enable:add(value=false)
/system-property=esia.scopes:add(value="snils, fullname, birthdate, id_doc")
/system-property=esia.base.uri:add(value="https://esia-portal1.test.gosuslugi.ru/")
/system-property=esia.client.id:add(value="MNSV89")
/system-property=esia.redirect.url:add(value="https://lkrp-dev.micord.ru/fl/")
/system-property=sign.url:add(value="https://ervu-sign-dev.k8s.micord.ru/sign")
/system-property=esia.client.cert.hash:add(value="04508B4B0B58776A954A0E15F574B4E58799D74C61EE020B3330716C203E3BDD")
/system-property=ervu.kafka.bootstrap.servers:add(value="localhost:9092")
/system-property=ervu.kafka.reply.topic:add(value="ervu.lkpr.person.search.response")
/system-property=ervu.kafka.group.id:add(value="1")
/system-property=ervu.kafka.request.topic:add(value="ervu.lkpr.person.search.request")
/system-property=ervu.kafka.reply.timeout:add(value="30")
/system-property=ervu.kafka.security.protocol:add(value="SASL_PLAINTEXT")
/system-property=ervu.kafka.doc.login.module:add(value="org.apache.kafka.common.security.scram.ScramLoginModule")
/system-property=ervu.kafka.sasl.mechanism:add(value="SCRAM-SHA-256")
/system-property=ervu.kafka.username:add(value="user1")
/system-property=ervu.kafka.password:add(value="Blfi9d2OFG")
/system-property=ervu.kafka.recruit.request.topic:add(value="ervu.recruit.info.request")
/system-property=ervu.kafka.recruit.reply.topic:add(value="ervu.recruit.info.response")
/system-property=ervu.kafka.recruit.header.class:add(value="Request@urn://rostelekom.ru/RP-SummonsTR/1.0.5")
/system-property=ervu.kafka.subpoena.extract.request.topic:add(value="ervu.subpoena.info.request")
/system-property=ervu.kafka.subpoena.extract.reply.topic:add(value="ervu.subpoena.info.response")
/system-property=ervu.kafka.registry.extract.request.topic:add(value="ervu.extract.info.request")
/system-property=ervu.kafka.registry.extract.reply.topic:add(value="ervu.extract.info.response")
/system-property=ervu.kafka.extract.header.class:add(value="Request@urn://rostelekom.ru/ERVU-extractFromRegistryTR/1.0.3")

View file

@ -54,6 +54,32 @@
<property name="security.password.regex" value="^((?=(.*\d){1,})(?=.*[a-zа-яё])(?=.*[A-ZА-ЯЁ]).{8,})$"/>
<property name="fias.enable" value="false"/>
<property name="com.arjuna.ats.arjuna.allowMultipleLastResources" value="true"/>
<property name="esia.scopes" value="snils, fullname, birthdate, id_doc"/>
<property name="esia.base.uri" value="https://esia-portal1.test.gosuslugi.ru/"/>
<property name="esia.client.id" value="MNSV89"/>
<property name="esia.redirect.url" value="https://lkrp.micord.ru"/>
<property name="sign.url" value="https://ervu-sign-dev.k8s.micord.ru/sign"/>
<property name="esia.client.cert.hash" value="04508B4B0B58776A954A0E15F574B4E58799D74C61EE020B3330716C203E3BDD"/>
<property name="bpmn.enable" value="false"/>
<property name="ervu.kafka.bootstrap.servers" value="localhost:9092"/>
<property name="ervu.kafka.reply.topic" value="ervu.lkpr.person.search.response"/>
<property name="ervu.kafka.group.id" value="1"/>
<property name="ervu.kafka.request.topic" value="ervu.lkpr.person.search.request"/>
<property name="ervu.kafka.reply.timeout" value="30"/>
<property name="bpmn.enable" value="false"/>
<property name="ervu.kafka.security.protocol" value="SASL_PLAINTEXT"/>
<property name="ervu.kafka.doc.login.module" value="org.apache.kafka.common.security.scram.ScramLoginModule"/>
<property name="ervu.kafka.sasl.mechanism" value="SCRAM-SHA-256"/>
<property name="ervu.kafka.username" value="user1"/>
<property name="ervu.kafka.password" value="Blfi9d2OFG"/>
<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"/>
</system-properties>
<management>
<audit-log>
@ -557,4 +583,4 @@
<remote-destination host="${jboss.mail.server.host:localhost}" port="${jboss.mail.server.port:25}"/>
</outbound-socket-binding>
</socket-binding-group>
</server>
</server>

View file

@ -0,0 +1,9 @@
#!/usr/bin/env bash
export JAVA_OPTS="$JAVA_OPTS \
-Ddb.app.host=${DB_APP_HOST:-db} \
-Ddb.app.port=${DB_APP_PORT:-5432} \
-Ddb.app.name=${DB_APP_NAME:-app} \
-Ddb.app.username=${DB_APP_USERNAME:-app_user} \
-Ddb.app.password=${DB_APP_PASSWORD:-apppassword} \
"

View file

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- The contents of this file will be loaded for each web application -->
<Context>
<!-- Default set of monitored resources. If one of these changes, the -->
<!-- web application will be reloaded. -->
<WatchedResource>WEB-INF/web.xml</WatchedResource>
<WatchedResource>WEB-INF/tomcat-web.xml</WatchedResource>
<WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>
<!-- Uncomment this to disable session persistence across Tomcat restarts -->
<!--
<Manager pathname="" />
-->
<Resource name="java:/webbpm/AppDS" auth="Container"
type="javax.sql.DataSource" driverClassName="org.postgresql.Driver"
url="jdbc:postgresql://${db.app.host}:${db.app.port}/${db.app.name}"
username="${db.app.username}" password="${db.app.password}" maxTotal="20" maxIdle="10" maxWaitMillis="-1"/>
</Context>

View file

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<tomcat-users xmlns="http://tomcat.apache.org/xml"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://tomcat.apache.org/xml tomcat-users.xsd"
version="1.0">
<!--
By default, no user is included in the "manager-gui" role required
to operate the "/manager/html" web application. If you wish to use this app,
you must define such a user - the username and password are arbitrary.
Built-in Tomcat manager roles:
- manager-gui - allows access to the HTML GUI and the status pages
- manager-script - allows access to the HTTP API and the status pages
- manager-jmx - allows access to the JMX proxy and the status pages
- manager-status - allows access to the status pages only
The users below are wrapped in a comment and are therefore ignored. If you
wish to configure one or more of these users for use with the manager web
application, do not forget to remove the <!.. ..> that surrounds them. You
will also need to set the passwords to something appropriate.
-->
<user username="admin" password="<must-be-changed>" roles="manager-gui"/>
</tomcat-users>

View file

@ -0,0 +1,15 @@
# WebBPM properties
authentication.method=form
bpmn.enable=false
fias.enable=false
gar.enable=false
reset_password.mail.template.path=mail/reset_password.html
security.password.regex=^(?=.*[a-zA-Z])(?=.*[0-9])[a-zA-Z0-9]+$
webbpm.mode=production
webbpm.jbpm.hibernate_statistics.enabled=false
webbpm.cache.hazelcast.hosts=127.0.0.1
webbpm.cache.hazelcast.outbound_port_definitions=5801-5820

View file

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<Context antiResourceLocking="false" privileged="true" >
<CookieProcessor className="org.apache.tomcat.util.http.Rfc6265CookieProcessor"
sameSiteCookies="strict" />
<!--
<Valve className="org.apache.catalina.valves.RemoteAddrValve"
allow="d+\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1" />
-->
<Manager sessionAttributeValueClassNameFilter="java\.lang\.(?:Boolean|Integer|Long|Number|String)|org\.apache\.catalina\.filters\.CsrfPreventionFilter\$LruCache(?:\$1)?|java\.util\.(?:Linked)?HashMap"/>
</Context>

View file

@ -5,7 +5,7 @@
"filter_cleanup_check_period_minutes": 30,
"auth_method": "form",
"enable.version.in.url": "%enable.version.in.url%",
"backend.context": "fl",
"backend.context": "fl/fl",
"guard.confirm_exit": false,
"message_service_error_timeout": "",
"message_service_warning_timeout": "",

View file

@ -1 +1 @@
%project.version%
%project.version%

View file

@ -0,0 +1,5 @@
<button class="user-info" ngbDropdownToggle *ngIf="getIsAuth()">{{getUserFullname()}}</button>
<div ngbDropdownMenu *ngIf="getIsAuth()">
<a routerLink="/mydata" class="data">Мои данные</a>
<button ngbDropdownItem class="exit" (click)="logout()">Выйти</button>
</div>

View file

@ -0,0 +1,10 @@
<form [id]="getObjectId()"
name="form"
[class.disabled]="!isEnabled()"
novalidate
[ngbTooltip]="tooltip | emptyIfNull"
data-isolate-form>
<div>
<ng-content></ng-content>
</div>
</form>

View file

@ -0,0 +1,53 @@
<div class="grid"
[ngbTooltip]="tooltip | emptyIfNull">
<ag-grid-angular [ngClass]="theme"
[ngStyle]="style"
[columnDefs]="columnDefs"
[defaultColDef]="defaultColDef"
[headerHeight]="headerHeight"
[rowHeight]="rowHeight"
[rowSelection]="rowSelection"
[rowMultiSelectWithClick]="isRowMultiSelectWithClick()"
[suppressRowClickSelection]="isSuppressRowClickSelection()"
[suppressLoadingOverlay]="isSuppressLoadingOverlay()"
[suppressNoRowsOverlay]="isSuppressNoRowsOverlay()"
[rowClassRules]="rowClassRules"
[rowModelType]="getRowModelType()"
[datasource]="datasource"
[maxConcurrentDatasourceRequests]="maxConcurrentDatasourceRequests"
[blockLoadDebounceMillis]="blockLoadDebounceMillis"
[cacheBlockSize]="getBlockSize()"
[pagination]="pagination"
[paginationPageSize]="fetchSize"
[maxBlocksInCache]="0"
[getRowId]="getRowIdFunc()"
[isRowSelectable]="isRowSelectableFunc()"
[pinnedBottomRowData]="pinnedBottomRowData"
[suppressDragLeaveHidesColumns]="true"
[suppressCopyRowsToClipboard]="true"
[processCellForClipboard]="processCellForClipboard"
[allowContextMenuWithControlKey]="allowContextMenuWithControlKey"
[localeText]="localeText"
[enableCellTextSelection]="enableCellTextSelection"
[overlayLoadingTemplate]="getLoadingOverlayTemplate()"
[overlayNoRowsTemplate]="getNoRowsOverlayTemplate()"
[tooltipShowDelay]="tooltipDelay"
[accentedSort]="true"
(gridReady)="onGridReady($event)"
(cellClicked)="onCellClicked($event)"
(rowClicked)="onRowClicked($event)"
(rowDoubleClicked)="onRowDoubleClicked($event)"
(selectionChanged)="onSelectionChanged($event)"
(sortChanged)="onSortChanged($event)"
(bodyScroll)="onBodyScroll($event)"
(columnResized)="onColumnResized($event)"
(columnMoved)="onColumnMoved($event)"
(columnVisible)="onColumnVisibilityChanged($event)"
(filterChanged)="columnFilterChanged($event)"
(componentStateChanged)="componentStateChanged($event)">
</ag-grid-angular>
<div [hidden]="true">
<ng-content></ng-content>
</div>
</div>

View file

@ -0,0 +1,61 @@
import {
AbstractButton,
AnalyticalScope,
Behavior,
Event,
Visible
} from "@webbpm/base-package";
import {ExtractRpcService} from "../../../generated/ru/micord/ervu/service/rpc/ExtractRpcService";
@AnalyticalScope(AbstractButton)
export class ExtractLoadService extends Behavior {
@Visible("false")
public successEvent: Event<boolean> = new Event<boolean>();
@Visible("false")
public errorEvent: Event<boolean> = new Event<boolean>();
private button: AbstractButton;
private rpc: ExtractRpcService;
private onClickFunction: Function;
initialize() {
super.initialize();
this.button = this.getScript(AbstractButton);
this.rpc = this.getScript(ExtractRpcService);
this.onClickFunction = () => {
this.rpc.getExtract()
.then(fileData => {
const newBlob = new Blob([fileData['file']],
{ type: fileData['fileType'] });
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveBlob(newBlob);
}
else {
const data = window.URL.createObjectURL(newBlob);
const link = document.createElement("a");
link.href = data;
link.download = fileData['fileName'];
link.click();
URL.revokeObjectURL(data);
link.remove();
this.successEvent.trigger();
}
})
.catch(() => {
this.errorEvent.trigger();
});
}
}
bindEvents() {
super.bindEvents();
this.button.addClickListener(this.onClickFunction);
}
unbindEvents() {
super.unbindEvents();
this.button.removeClickListener(this.onClickFunction);
}
}

View file

@ -0,0 +1,54 @@
import {Form} from "@webbpm/base-package";
import {ChangeDetectionStrategy, Component} from "@angular/core";
import {ErvuDataService} from "../../../modules/app/service/ervu-data.service";
import {Subscription} from "rxjs";
import {LoadFormRpcService} from "../../../generated/ru/micord/ervu/service/rpc/LoadFormRpcService";
@Component({
moduleId: module.id,
selector: 'load-form',
templateUrl: './../../../../../src/resources/template/component/container/Form.html',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class LoadForm extends Form {
private formRpcService: LoadFormRpcService;
private ervuDataService: ErvuDataService;
private subscription: Subscription;
private valuesData: string;
initialize() {
super.initialize();
this.formRpcService = this.getScript(LoadFormRpcService);
this.ervuDataService = this.injector.get(ErvuDataService);
this.subscription = this.ervuDataService.message.subscribe(value => {
if (value) {
this.valuesData = value;
this.loadData();
}
});
}
loadData(): Promise<any> {
return this.formRpcService
.loadData(this.valuesData)
.then(fieldDataList => this.setData(fieldDataList))
.catch(reason => {
throw new Error(reason);
});
}
saveData(): Promise<any> {
return;
}
deleteData(): Promise<void> {
return;
}
ngOnDestroy() {
super.ngOnDestroy();
this.subscription.unsubscribe();
}
}

View file

@ -0,0 +1,107 @@
import {
GridColumnIdUtils,
GridRow, GridRowModelType,
GridV2, GridV2Column, NotNull
} from "@webbpm/base-package";
import {ChangeDetectionStrategy, Component} from "@angular/core";
import {
ColDef,
ICellRendererParams,
ITooltipParams,
ValueFormatterParams,
ValueGetterParams
} from "ag-grid-community";
import {ErvuDataService} from "../../../modules/app/service/ervu-data.service";
import {Subscription} from "rxjs";
import {StaticColumnInitializer} from "./StaticColumnInitializer";
import {StaticGridColumn} from "../../../generated/ru/micord/ervu/property/grid/StaticGridColumn";
@Component({
moduleId: module.id,
selector: 'in-memory-static-grid',
templateUrl: './../../../../../src/resources/template/component/grid/GridV2.html',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class InMemoryStaticGrid extends GridV2 {
@NotNull()
public dataList: string;
private subscription: Subscription;
getRowModelType(): string {
return GridRowModelType.CLIENT_SIDE;
}
protected initGrid() {
super.initGrid();
this.subscription = this.injector.get(ErvuDataService).message.subscribe(value => {
this.rowData = value ? value[this.dataList] : null;
});
}
getColumns(): any[] {
return this.getScriptsInChildren(GridV2Column)
.map(columnV2 => columnV2.getScript(StaticGridColumn));
}
protected columnV2ToColumnDef(column: GridV2Column): ColDef {
let gridColumn = column.getScript(StaticGridColumn);
let colDef = this.columnToColumnDef(gridColumn);
if (column.renderer) {
colDef.cellRenderer = (params: ICellRendererParams) => column.renderer.render(params);
}
if (column.valueGetter) {
colDef.valueGetter = (params: ValueGetterParams) => column.valueGetter.get(params);
}
if (column.tooltipValueGetter) {
if (gridColumn.columnTooltip) {
throw new Error("Only one type of tooltip should be specified: tooltipValueGetter or columnTooltip");
}
colDef.tooltipValueGetter = (params: ITooltipParams) => column.tooltipValueGetter.get(params);
}
column.setGridRef(this);
column.setColDef(colDef);
return colDef;
}
protected columnToColumnDef(column: any): ColDef {
let colDef = StaticColumnInitializer.columnToColumnDef(this, column);
let columnComp = column.context;
colDef['columnUid'] = columnComp.getObjectId();
if (columnComp.cellCssClassRulesProvider) {
colDef.cellClassRules = columnComp.cellCssClassRulesProvider.getRules();
}
if (columnComp.valueFormatter) {
colDef.valueFormatter = (params?: ValueFormatterParams) => {
return columnComp.valueFormatter.format(params);
}
}
return colDef;
}
public load(): void {
this.onLoadStart();
let rows: GridRow[] = [];
if (this.rowData) {
this.rowData.forEach((data, i) => {
let row: GridRow = new GridRow();
row[GridColumnIdUtils.ROW_UID] = i;
this.getColumns().forEach(col => {
let column = col.field.column;
row[column] = data[column];
})
rows.push(row);
})
}
this.getGridApi().setRowData(rows);
this.onLoadEnd();
}
ngOnDestroy() {
super.ngOnDestroy();
this.subscription.unsubscribe();
}
}

View file

@ -0,0 +1,116 @@
import {ColDef, ICellRendererFunc, SuppressKeyboardEventParams} from "ag-grid-community";
import {
DateTimeUtil,
DefaultTooltip,
GridCellTooltipUtils,
GridColumnComparatorUtils,
GridColumnFilterUtils,
GridColumnKeyboardUtils,
GridSettingHeader,
GridValueFormatterUtils,
GridValueRendererUtils,
PinnedType
} from "@webbpm/base-package";
import {Moment} from "moment";
import moment from "moment-timezone";
import {StaticGridColumn} from "../../../generated/ru/micord/ervu/property/grid/StaticGridColumn";
export class StaticColumnInitializer {
public static columnToColumnDef(gridRef: any, column: StaticGridColumn) {
const columnDef: ColDef = {};
columnDef.headerName = column.displayName ? column.displayName : '';
columnDef.headerClass = "custom-header";
columnDef.width = column.width;
columnDef.suppressSizeToFit = column.widthFixed;
columnDef.hide = column.hidden;
columnDef.resizable = !column.widthFixed;
columnDef.headerComponentParams = {"disable_hiding": column.disableHiding || false};
columnDef.lockVisible = column.disableHiding;
columnDef.headerComponent = GridSettingHeader;
columnDef.headerTooltip = column.headerTooltip ? column.headerTooltip : column.displayName;
columnDef.suppressMenu = column.suppressHeaderMenu;
if (column.pinned) {
columnDef.pinned = column.pinned == PinnedType.LEFT ? 'left' : 'right';
}
columnDef['gridComp'] = this;
columnDef.sortable = column.sortable;
if (column.sortable == null) {
columnDef.sortable = true;
}
if (column.autoHeight) {
columnDef.autoHeight = column.autoHeight;
columnDef.cellClass = 'ag-grid-cell-wrap-text';
}
if (column.field) {
columnDef.field = column.field.column;
let type = column.field.type;
if (type != null) {
if (gridRef.floatingFilter && column.filter !== false) {
columnDef.floatingFilter = gridRef.floatingFilter;
columnDef.filter = GridColumnFilterUtils.columnFilter(type);
if (columnDef.filter === 'agDateColumnFilter') {
columnDef.filterParams = {
comparator: function (filterLocalDateAtMidnight, cellValue) {
if (!cellValue) {
return -1;
}
let filterMoment: Moment = moment.utc(filterLocalDateAtMidnight)
.add(-filterLocalDateAtMidnight.getTimezoneOffset(), 'm');
let cellMoment: Moment = DateTimeUtil.parseToMidnightUTC(cellValue);
if (filterMoment.isSame(cellMoment)) {
return 0;
}
if (cellMoment.isBefore(filterMoment)) {
return -1;
}
if (cellMoment.isAfter(filterMoment)) {
return 1;
}
},
browserDatePicker: true,
};
}
}
if (gridRef.getRowModelType() == "clientSide") {
columnDef.comparator = GridColumnComparatorUtils.columnComparator(type);
}
columnDef.valueFormatter = GridValueFormatterUtils.columnFormatter(type);
columnDef.cellRenderer = gridRef.createRenderer(column);
}
columnDef.suppressKeyboardEvent = (params: SuppressKeyboardEventParams) => {
return GridColumnKeyboardUtils.suppressHomeAndEndKeyboardEvent(params);
}
}
if (column.displayPopup) {
const renderer: ICellRendererFunc = columnDef.cellRenderer as ICellRendererFunc;
columnDef.cellRenderer = GridValueRendererUtils.tooltipValueRenderer(renderer);
}
else if (column.columnTooltip) {
columnDef.tooltipComponent = DefaultTooltip;
columnDef.tooltipValueGetter = GridCellTooltipUtils.fixedValueTooltip(column.columnTooltip);
}
else if (!gridRef.suppressColumnTooltip) {
columnDef.tooltipComponent = DefaultTooltip;
columnDef.tooltipValueGetter = GridCellTooltipUtils.defaultFormattedTooltip(
column.field ? column.field.type : null);
}
return columnDef;
}
}

View file

@ -0,0 +1,18 @@
import {
AnalyticalScope, GridCellValueRenderer,
GridV2Column,
NotNull
} from "@webbpm/base-package";
import {ICellRendererParams} from "ag-grid-community";
@AnalyticalScope(GridV2Column)
export class ValueWithPrefixRenderer implements GridCellValueRenderer {
@NotNull()
public label: string;
render(params: ICellRendererParams): HTMLElement | string {
let value = params.valueFormatted ? params.valueFormatted : params.value;
return `${this.label} ${value}`;
}
}

View file

@ -0,0 +1,62 @@
import {NotNull, TextFormatter, Visible} from "@webbpm/base-package";
// A text formatter for integer values appending a prefix and/or suffix
// depending on the last digit of the value
export class NumberPrefixSuffixTextFormatter implements TextFormatter {
@NotNull()
public hasPrefix: boolean;
@Visible("hasPrefix == true")
@NotNull("hasPrefix == true")
public oneDigitPrefix: string;
@Visible("hasPrefix == true")
@NotNull("hasPrefix == true")
public otherDigitPrefix: string;
@NotNull()
public hasSuffix: boolean;
@Visible("hasSuffix == true")
@NotNull("hasSuffix == true")
public oneDigitSuffix: string;
@Visible("hasSuffix == true")
@NotNull("hasSuffix == true")
public fromTwoToFourDigitSuffix: string;
@Visible("hasSuffix == true")
@NotNull("hasSuffix == true")
public otherDigitSuffix: string;
private excludedNumbers: number[] = [11, 12, 13, 14];
format(value: string): string {
if (value) {
let number = Number.parseInt(value);
let lastDigit = Math.abs(number) % 10;
let lastDigits = Math.abs(number) % 100;
let prefix = "";
if (this.hasPrefix) {
prefix = (this.excludedNumbers.includes(lastDigits)
? this.oneDigitPrefix
: lastDigit == 1
? this.oneDigitPrefix
: this.otherDigitPrefix) + " ";
}
let suffix = "";
if (this.hasSuffix) {
suffix = " " + (this.excludedNumbers.includes(lastDigits)
? this.otherDigitSuffix
: lastDigit == 1
? this.oneDigitSuffix
: lastDigit > 1 && lastDigit < 5
? this.fromTwoToFourDigitSuffix
: this.otherDigitSuffix);
}
return prefix + value + suffix;
}
return value;
}
}

View file

@ -0,0 +1,28 @@
import {NotNull, TextFormatter, Visible} from "@webbpm/base-package";
export class PrefixSuffixTextFormatter implements TextFormatter {
@NotNull()
public hasPrefix: boolean;
@Visible("hasPrefix == true")
@NotNull("hasPrefix == true")
public prefix: string;
@NotNull()
public hasSuffix: boolean;
@Visible("hasSuffix == true")
@NotNull("hasSuffix == true")
public suffix: string;
format(value: string): string {
if (value) {
let prefix = this.hasPrefix ? this.prefix + " " : "";
let suffix = this.hasSuffix ? " " + this.suffix : "";
return prefix + value + suffix;
}
return value;
}
}

View file

@ -0,0 +1,7 @@
import {Behavior, NotNull} from "@webbpm/base-package";
export class PersonData extends Behavior{
@NotNull()
public personDataId: string;
}

View file

@ -0,0 +1,33 @@
import {AnalyticalScope, Behavior, Container, ControlWithValue} from "@webbpm/base-package";
import {HttpClient} from "@angular/common/http";
import {PersonData} from "./PersonData";
import {CookieService} from "ngx-cookie";
import {PersonDataModel} from "../generated/ru/micord/ervu/security/esia/model/PersonDataModel";
@AnalyticalScope(Container)
export class PersonDataRoot extends Behavior{
private container: Container;
initialize() {
super.initialize();
this.container = this.getScript(Container);
let personScripts: PersonData[] = this.container.getScriptsInThisAndChildren(PersonData);
let httpClient = this.injector.get(HttpClient);
let cookieService = this.injector.get(CookieService);
if (cookieService.get("is_auth")) {
httpClient.get<PersonDataModel>("esia/person")
.toPromise()
.then(personModel => {
if (personModel == null) {
return;
}
for (let person of personScripts) {
let control: ControlWithValue = person.getScriptInObject(person.getObjectId(),
'component.ControlWithValue');
control.setValue(personModel[person.personDataId]);
}
});
}
}
}

View file

@ -1,6 +1,7 @@
import {NgModule} from "@angular/core";
import {RouterModule, Routes} from "@angular/router";
import {AccessDeniedComponent} from "./component/access-denied.component";
import {AuthGuard} from "../security/guard/auth.guard";
import {ConfirmExitGuard} from "@webbpm/base-package";
const appRoutes: Routes = [
@ -13,17 +14,17 @@ const appRoutes: Routes = [
{
path: 'mydata',
loadChildren: 'generated-sources/page-mydata.module#PagemydataModule',
canActivate: [ConfirmExitGuard],
canActivate: [AuthGuard],
},
{
path: 'restriction',
loadChildren: 'generated-sources/page-restriction.module#PagerestrictionModule',
canActivate: [ConfirmExitGuard],
canActivate: [AuthGuard],
},
{
path: 'subpoena',
loadChildren: 'generated-sources/page-subpoena.module#PagesubpoenaModule',
canActivate: [ConfirmExitGuard],
canActivate: [AuthGuard],
},
];

View file

@ -20,15 +20,21 @@ import {InternationalPhoneNumberModule} from "ngx-international-phone-number";
import {AppProgressIndicationComponent} from "./component/app-progress-indication.component";
import {AppProgressIndicationService} from "./service/app-progress-indication.service";
import {TextWithDialogLinks} from "../../ervu/component/textwithdialoglinks/TextWithDialogLinks";
import {LogOutComponent} from "./component/logout.component";
import {LoadForm} from "../../ervu/component/container/LoadForm";
import {InMemoryStaticGrid} from "../../ervu/component/grid/InMemoryStaticGrid";
registerLocaleData(localeRu);
export const DIRECTIVES = [
forwardRef(() => AppHeaderComponent),
forwardRef(() => AppFooterComponent),
forwardRef(() => ApplicationVersionComponent),
forwardRef(() => LogOutComponent),
forwardRef(() => AccessDeniedComponent),
forwardRef(() => AppProgressIndicationComponent),
forwardRef(() => TextWithDialogLinks)
forwardRef(() => TextWithDialogLinks),
forwardRef(() => LoadForm),
forwardRef(() => InMemoryStaticGrid)
];
@NgModule({

View file

@ -1,5 +1,12 @@
import {ChangeDetectionStrategy, Component} from "@angular/core";
import {
ChangeDetectionStrategy,
Component,
OnDestroy
} from "@angular/core";
import {Router} from "@angular/router";
import {UserService, Session} from "@webbpm/base-package";
import {Observable, Subscription} from "rxjs";
import {ErvuDataService} from "../service/ervu-data.service";
@Component({
moduleId: module.id,
@ -7,9 +14,25 @@ import {Router} from "@angular/router";
templateUrl: "../../../../../src/resources/template/app/component/app_header.html",
changeDetection: ChangeDetectionStrategy.OnPush
})
export class AppHeaderComponent {
export class AppHeaderComponent implements OnDestroy{
public currentSession: Observable<Session>;
public subscription: Subscription;
constructor(protected router: Router) {
constructor(protected userService: UserService, protected router: Router,
protected ervuDataService: ErvuDataService) {
// this.currentSession = this.userService.getCurrentSession();
// this.subscription = this.currentSession.subscribe(session => {
// if (session) {
// this.ervuDataService.getData();
// }
// }
// );
//TODO
this.ervuDataService.getData();
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}

View file

@ -0,0 +1,43 @@
import {ChangeDetectorRef, Component, OnInit} from "@angular/core";
import {HttpClient} from "@angular/common/http";
import {CookieService} from "ngx-cookie";
@Component({
moduleId: module.id,
selector: "[log-out]",
templateUrl: "../../../../../src/resources/template/app/component/log_out.html"
})
export class LogOutComponent implements OnInit{
private userFullname: string;
constructor(private httpClient: HttpClient,
private cookieService: CookieService, private cd: ChangeDetectorRef) {
}
ngOnInit(): void {
let isAuth = this.getIsAuth();
if (isAuth) {
Promise.all([
this.httpClient.get<string>("esia/userfullname").toPromise(),
]).then(([userFullname]) => {
this.userFullname = userFullname;
this.cd.markForCheck();
});
}
}
public logout(): void {
this.httpClient.get<string>("esia/logout").toPromise().then(url => {
window.open(url, "_self");
})
}
public getUserFullname(): string {
return this.userFullname;
}
public getIsAuth(): boolean {
return this.cookieService.get("is_auth") != null;
}
}

View file

@ -0,0 +1,28 @@
import {Injectable} from "@angular/core";
import {BehaviorSubject} from "rxjs";
import {HttpClient} from "@angular/common/http";
@Injectable({providedIn:'root'})
export class ErvuDataService {
public message = new BehaviorSubject<any>(null);
constructor(private httpClient: HttpClient) {
}
public getData(): any {
this.httpClient
.post("get-data", null,
{
headers: {
"Content-type": "application/json"
},
observe: "response"
})
.toPromise()
.then(res => this.message.next(res.body))
.catch((reason) => {
throw new Error("Failed to get data: " + reason)
});
}
}

View file

@ -0,0 +1,61 @@
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";
@Injectable({providedIn:'root'})
export abstract class AuthGuard implements CanActivate {
protected constructor(
protected router: Router,
private httpClient: HttpClient,
private cookieService: CookieService
) {
}
public canActivate(route: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
let hasAccess: Promise<boolean> | boolean = this.checkAccess();
return Promise.resolve(hasAccess).then((isAccess) => {
let url = new URL(window.location.href);
let params = new URLSearchParams(url.search);
let code = params.get('code');
let error = params.get('error');
let errorDescription = params.get('error_description');
if (isAccess) {
return true;
}
else if (error) {
throw new Error(error + ', error description =' + errorDescription);
}
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)
);
return false;
}
else {
this.httpClient.get<string>("esia/url")
.toPromise()
.then(url => window.open(url, "_self"));
return true;
}
}).catch((reason) => {
console.error(reason);
return false
});
}
private checkAccess(): Promise<boolean> | boolean {
return this.getIsAuth() != null;
};
public getIsAuth(): string {
return this.cookieService.get('is_auth');
}
}

View file

@ -1,14 +1,12 @@
import {NgModule} from "@angular/core";
import {RouterModule, Routes} from "@angular/router";
import {
ConfirmExitGuard
} from "@webbpm/base-package";
import {AuthGuard} from "../security/guard/auth.guard";
const webbpmRoutes: Routes = [
{
path: '',
loadChildren: 'generated-sources/page-lkfl.module#PagelkflModule',
canActivate: [ConfirmExitGuard],
canActivate: [AuthGuard],
pathMatch: 'full',
},
{

21
pom.xml
View file

@ -16,6 +16,7 @@
</scm>
<properties>
<spring-security-kerberos.version>1.0.1.RELEASE</spring-security-kerberos.version>
<spring-kafka.version>2.6.13</spring-kafka.version>
<org.bouncycastle.version>1.60</org.bouncycastle.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<enable.version.in.url>false</enable.version.in.url>
@ -314,6 +315,11 @@
<artifactId>spring-security-kerberos-web</artifactId>
<version>${spring-security-kerberos.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
<version>${spring-kafka.version}</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
@ -350,6 +356,16 @@
<artifactId>slf4j-simple</artifactId>
<version>1.7.28</version>
</dependency>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>4.27.3</version>
</dependency>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java-util</artifactId>
<version>4.27.3</version>
</dependency>
</dependencies>
</dependencyManagement>
<repositories>
@ -437,6 +453,11 @@
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.6.1</version>
</plugin>
</plugins>
</pluginManagement>
<plugins>

View file

@ -0,0 +1,134 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xmlComponent>
<id>63a04163-fae6-49c4-aa1a-c028e7594640</id>
<name>InMemoryStaticGrid</name>
<category>grids</category>
<internal>false</internal>
<versions>
<studioVersion>3.178.0</studioVersion>
<packageVersions>
<entry>
<key>ru.cg.webbpm.packages.base.resources</key>
<value>3.178.2</value>
</entry>
</packageVersions>
</versions>
<rootObject id="bee4e324-a660-4d99-bbc4-9fc2b084a5fc">
<prototypeId>16071adb-3bdf-4c33-b29b-886876016415</prototypeId>
<componentRootId>bee4e324-a660-4d99-bbc4-9fc2b084a5fc</componentRootId>
<name>InMemoryStaticGrid</name>
<container>true</container>
<childrenReordered>false</childrenReordered>
<scripts id="07201df9-ff33-4c71-9aae-a2cfdd028234">
<enabled>false</enabled>
<removed>true</removed>
</scripts>
<scripts id="1996166f-7922-4f28-a571-9646d956ef37">
<enabled>false</enabled>
<removed>true</removed>
</scripts>
<scripts id="fe8cfe1c-5381-411e-aee6-cf4b38fcea07">
<classRef type="TS">
<className>InMemoryStaticGrid</className>
<packageName>ervu.component.grid</packageName>
</classRef>
<enabled>true</enabled>
<expanded>true</expanded>
<properties>
<entry>
<key>autoStretchColumns</key>
<value>
<simple>true</simple>
</value>
</entry>
<entry>
<key>clientSideColumnFilters</key>
<value>
<simple>true</simple>
</value>
</entry>
<entry>
<key>cssClasses</key>
<value>
<item id="d9ad41b8-be83-40b9-b462-3bb932c354bf" removed="true"/>
<item id="66b90acf-e1e2-47bf-bda2-53721f642483" removed="true"/>
<expanded>false</expanded>
</value>
</entry>
<entry>
<key>enableCellTextSelection</key>
<value>
<simple>true</simple>
</value>
</entry>
<entry>
<key>floatingFilter</key>
<value>
<simple>false</simple>
</value>
</entry>
<entry>
<key>headerHeight</key>
<value>
<simple>null</simple>
</value>
</entry>
<entry>
<key>loadOnInit</key>
<value>
<simple>false</simple>
</value>
</entry>
<entry>
<key>loadingOverlayMessage</key>
<value>
<simple>"Загрузка ограничений"</simple>
</value>
</entry>
<entry>
<key>loadingOverlayType</key>
<value>
<simple>"TEXT_OVERLAY"</simple>
</value>
</entry>
<entry>
<key>noRowsOverlayMessage</key>
<value>
<simple>"Нет ограничений"</simple>
</value>
</entry>
<entry>
<key>rowClickSelectionType</key>
<value>
<simple>"SINGLE_SELECT_CLICK"</simple>
</value>
</entry>
<entry>
<key>rowModelType</key>
<value>
<simple>null</simple>
</value>
</entry>
<entry>
<key>showRowNumber</key>
<value>
<simple>false</simple>
</value>
</entry>
<entry>
<key>theme</key>
<value>
<simple>"BALHAM"</simple>
</value>
</entry>
<entry>
<key>visible</key>
<value>
<simple>true</simple>
</value>
</entry>
</properties>
</scripts>
<scripts id="be8fe0e1-4909-4224-8664-be55168595c6"/>
</rootObject>
</xmlComponent>

View file

@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xmlComponent>
<id>85b698a2-15ec-420f-98c5-c88d126b41e5</id>
<name>LoadForm</name>
<category>containers</category>
<internal>false</internal>
<versions>
<studioVersion>3.178.0</studioVersion>
<packageVersions>
<entry>
<key>ru.cg.webbpm.packages.base.resources</key>
<value>3.178.2</value>
</entry>
</packageVersions>
</versions>
<rootObject id="e8095a58-164a-46b5-b477-fe2ce685dad5">
<prototypeId>be95ef58-ee04-413f-be0f-e8cd4af25faf</prototypeId>
<componentRootId>e8095a58-164a-46b5-b477-fe2ce685dad5</componentRootId>
<name>LoadForm</name>
<container>true</container>
<childrenReordered>false</childrenReordered>
<scripts id="bf098f19-480e-44e4-9084-aa42955c4d0f">
<enabled>false</enabled>
<removed>true</removed>
</scripts>
<scripts id="c0bf7050-bd39-426a-8f1e-1600bbd4b9bb">
<enabled>false</enabled>
<removed>true</removed>
</scripts>
<scripts id="57779237-6bd7-4f73-ab62-efc79cc249b9">
<enabled>true</enabled>
<removed>true</removed>
</scripts>
<scripts id="ad6ccafe-914e-4e13-a351-88bf107a5007">
<removed>true</removed>
</scripts>
<scripts id="9ad247a3-9c46-4f12-9949-b1c905bd73bc"/>
<scripts id="79188cdc-d646-433e-9751-1482b9247ee6"/>
<scripts id="0f6e16d9-2380-4d49-900c-be8c221ef394">
<classRef type="TS">
<className>LoadForm</className>
<packageName>ervu.component.container</packageName>
</classRef>
<enabled>true</enabled>
<expanded>true</expanded>
<properties>
<entry>
<key>loadOnStart</key>
<value>
<simple>false</simple>
</value>
</entry>
<entry>
<key>visible</key>
<value>
<simple>true</simple>
</value>
</entry>
</properties>
</scripts>
<scripts id="e7a22d20-f502-4c58-a798-57b023606541">
<classRef type="JAVA">
<className>LoadFormRpcService</className>
<packageName>ru.micord.ervu.service.rpc</packageName>
</classRef>
<enabled>true</enabled>
<expanded>true</expanded>
</scripts>
</rootObject>
</xmlComponent>

View file

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xmlComponent>
<id>d78a169c-8d7d-471a-bc80-909b617f85f0</id>
<name>StaticGridColumn</name>
<category>grids</category>
<internal>false</internal>
<versions>
<studioVersion>3.178.0</studioVersion>
<packageVersions>
<entry>
<key>ru.cg.webbpm.packages.base.resources</key>
<value>3.178.2</value>
</entry>
</packageVersions>
</versions>
<rootObject id="c556264f-221b-4af8-9e64-f380a67c41ec">
<prototypeId>364c8faa-5e56-46cd-9203-d2ec6ef2dc74</prototypeId>
<componentRootId>c556264f-221b-4af8-9e64-f380a67c41ec</componentRootId>
<name>StaticGridColumn</name>
<container>false</container>
<childrenReordered>false</childrenReordered>
<scripts id="9c5c7a86-dc40-4b30-a5a7-5e7b4c7ea1e1"/>
<scripts id="fd653fca-12f9-4e35-baa4-b6b5dd3f6d59">
<removed>true</removed>
<enabled>false</enabled>
</scripts>
<scripts id="0a01c185-920b-4328-a82d-277f917b185e">
<classRef type="JAVA">
<className>StaticGridColumn</className>
<packageName>ru.micord.ervu.property.grid</packageName>
</classRef>
<enabled>true</enabled>
<expanded>true</expanded>
</scripts>
</rootObject>
</xmlComponent>

View file

@ -1,27 +0,0 @@
import old.*;
import org.junit.platform.suite.api.SelectClasses;
import org.junit.platform.suite.api.Suite;
import tests.AuthoritiesIT;
import tests.LoginIT;
import tests.OrganizationsIT;
import tests.ProcessesIT;
/**
* @author gulnaz
*/
@Suite
@SelectClasses({
AuthoritiesIT.class,
LoginIT.class,
OrganizationsIT.class,
ProcessesIT.class,
AdminGroupIT.class,
AdminRoleIT.class,
AdminUserIT.class,
JWTokensIT.class
})
public class SuiteAdmin {
SuiteAdmin() {
}
}

View file

@ -1,332 +0,0 @@
package old;
import com.google.common.collect.Comparators;
import old.core.Browser;
import old.core.BrowserArgumentProvider;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.TestInfo;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ArgumentsSource;
import old.page.AdminGroupPage;
import old.page.AdminUserPage;
import java.util.Arrays;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* @author kote
*/
public class AdminGroupIT extends BaseComponentIT {
private static final String GROUP_ACCESS_LEVEL = "user access level";
private static final String ROLE = "BPMN User";
private static final String ROLE_2 = "BPMN Admin";
private static final String ROLE_3 = "BPMN Superuser";
private static final String COL_ID = "group$name";
private static final String COL_ID_CREATED = "group$created";
private static final String COL_ID_UPDATED = "group$updated";
private static final String BPMN_ADMIN_ROLE_ID = "aa14ba1d-0b61-4e33-8474-7c2d98944b12";
private static final String BPMN_USER_ROLE_ID = "767ae8cf-af01-44d4-86ef-fcb143373407";
private static final String BPMN_SUPERUSER_ROLE_ID = "2569ba58-1f8f-43ea-8b2c-0d373cf501fe";
private AdminGroupPage adminGroupPage;
private String oldName;
private String groupId;
private String roleId;
public AdminGroupIT() {
super();
}
@AfterEach
public void afterEachTest(TestInfo testInfo) {
String testName = testInfo.getTestMethod().toString();
if (testName.contains("User")) {
EXECUTION_MANAGER.deleteTestUser(name);
}
if (testName.contains("edit")) {
EXECUTION_MANAGER.deleteTestGroup(oldName);
}
if (testName.contains("linked")) {
EXECUTION_MANAGER.deleteUserGroupRole(name, groupId, roleId);
}
if (testName.contains("Sorting")) {
String groupIdToDelete = EXECUTION_MANAGER.getGroupIdByName(name);
EXECUTION_MANAGER.deleteLinkedRolesFromGroup(groupIdToDelete);
}
EXECUTION_MANAGER.deleteTestGroup(name);
}
@ParameterizedTest
@ArgumentsSource(BrowserArgumentProvider.class)
public void createGroup(Browser browser) {
openBrowserAndAdminPage(browser);
adminGroupPage.clickCreateButton();
adminGroupPage.waitForPageLoad();
adminGroupPage.waitForVisibilityOf(adminGroupPage.nameField);
adminGroupPage.typeText(adminGroupPage.nameField, name);
adminGroupPage.typeAndSelectLevel(GROUP_ACCESS_LEVEL);
adminGroupPage.addRole(ROLE, false);
adminGroupPage.clickSaveButton();
String dateOfCreation = adminGroupPage.getLocalDate();
adminGroupPage.waitForPageLoad();
adminGroupPage.searchGroup(name);
assertEquals(1, adminGroupPage.getListOfGroupsNamesFromTable(name).size());
assertTrue(adminGroupPage.getActionTime(COL_ID, name, COL_ID_CREATED).getText().contains(dateOfCreation));
}
@ParameterizedTest
@ArgumentsSource(BrowserArgumentProvider.class)
public void searchGroup(Browser browser) {
openBrowserAndAdminPage(browser);
EXECUTION_MANAGER.createTestGroup(name, ACCESS_LEVEL_ID);
adminGroupPage.searchGroup(name);
adminGroupPage.waitForPageLoad();
assertEquals(1, adminGroupPage.getListOfGroupsNamesFromTable(name).size());
}
@ParameterizedTest
@ArgumentsSource(BrowserArgumentProvider.class)
public void editGroup(Browser browser) {
openBrowserAndAdminPage(browser);
oldName = "old" + name;
EXECUTION_MANAGER.createTestGroup(oldName, ACCESS_LEVEL_ID);
adminGroupPage.chooseGroup(oldName);
adminGroupPage.clickEditButton();
adminGroupPage.waitForVisibilityOf(adminGroupPage.nameField);
adminGroupPage.typeText(adminGroupPage.nameField, name);
adminGroupPage.addRole(ROLE, false);
adminGroupPage.clickSaveButton();
adminGroupPage.searchGroup(oldName);
assertEquals(0, adminGroupPage.getListOfGroupsNamesFromTable(oldName).size());
adminGroupPage.chooseGroup(name);
assertEquals(1, adminGroupPage.getListOfGroupsNamesFromTable(name).size());
String timeOfCreate = adminGroupPage.getActionTime(COL_ID, name, COL_ID_CREATED).getText();
String timeOfUpdate = adminGroupPage.getActionTime(COL_ID, name, COL_ID_UPDATED).getText();
assertNotEquals(timeOfCreate, timeOfUpdate);
adminGroupPage.clickEditButton();
assertTrue(adminGroupPage.hasRolesInTable(AdminGroupPage.GroupPageGrids.ADDED_ROLES_GRID, ROLE));
}
@ParameterizedTest
@ArgumentsSource(BrowserArgumentProvider.class)
public void deleteGroup(Browser browser) {
openBrowserAndAdminPage(browser);
EXECUTION_MANAGER.createTestGroup(name, ACCESS_LEVEL_ID);
adminGroupPage.chooseGroup(name);
adminGroupPage.deleteGroup();
assertTrue(adminGroupPage.isGridEmpty());
}
@ParameterizedTest
@ArgumentsSource(BrowserArgumentProvider.class)
public void linkedRolesTable(Browser browser) {
openBrowserAndAdminPage(browser);
roleId = EXECUTION_MANAGER.generateId();
groupId = EXECUTION_MANAGER.generateId();
EXECUTION_MANAGER.createBindGroupRole(name, groupId, ACCESS_LEVEL_ID, roleId);
adminGroupPage.chooseGroup(name);
assertEquals(1, adminGroupPage.getListOfRolesFromLinkedTable().size());
assertEquals(name, adminGroupPage.getListOfRolesFromLinkedTable().get(0).getText());
}
@ParameterizedTest
@ArgumentsSource(BrowserArgumentProvider.class)
public void attachRemoveRoleToGroup(Browser browser) {
openBrowserAndAdminPage(browser);
EXECUTION_MANAGER.createTestGroup(name, ACCESS_LEVEL_ID);
adminGroupPage.chooseGroup(name);
assertTrue(adminGroupPage.getListOfRolesFromLinkedTable().isEmpty());
adminGroupPage.clickEditButton();
assertFalse(adminGroupPage.getListOfRolesToAdd().isEmpty());
assertTrue(adminGroupPage.getListOfAddedRoles().isEmpty());
adminGroupPage.addRole(ROLE, false);
assertFalse(adminGroupPage.getWebElementTexts(adminGroupPage.getListOfRolesToAdd()).contains(ROLE));
assertTrue(adminGroupPage.getWebElementTexts(adminGroupPage.getListOfAddedRoles()).contains(ROLE));
assertEquals(1, adminGroupPage.getListOfAddedRoles().size());
adminGroupPage.clickSaveButton();
adminGroupPage.chooseGroup(name);
assertEquals(1, adminGroupPage.getListOfRolesFromLinkedTable().size());
assertTrue(adminGroupPage.getWebElementTexts(adminGroupPage.getListOfRolesFromLinkedTable()).contains(ROLE));
adminGroupPage.clickEditButton();
adminGroupPage.removeRole(ROLE);
assertTrue(adminGroupPage.getWebElementTexts(adminGroupPage.getListOfRolesToAdd()).contains(ROLE));
assertTrue(adminGroupPage.getListOfAddedRoles().isEmpty());
adminGroupPage.clickSaveButton();
adminGroupPage.chooseGroup(name);
assertTrue(adminGroupPage.getListOfRolesFromLinkedTable().isEmpty());
}
@ParameterizedTest
@ArgumentsSource(BrowserArgumentProvider.class)
public void attachRemoveAllRolesToGroup(Browser browser) {
openBrowserAndAdminPage(browser);
EXECUTION_MANAGER.createTestGroup(name, ACCESS_LEVEL_ID);
List<String> roleNames = EXECUTION_MANAGER.getRoleNamesFromUserRole();
List<String> expectedRoles = Arrays.asList(ROLE, ROLE_2, ROLE_3);
adminGroupPage.chooseGroup(name);
adminGroupPage.clickEditButton();
assertFalse(adminGroupPage.getListOfRolesToAdd().isEmpty());
assertTrue(adminGroupPage.getListOfAddedRoles().isEmpty());
adminGroupPage.addAllRoles();
assertTrue(adminGroupPage.isAvailableGridEmpty(roleNames));
assertFalse(adminGroupPage.getListOfAddedRoles().isEmpty());
/*
Нет возможности проверить сохранение привязки всех ролей к группе из-за создания/удаление ролей
параллельными тестами.
*/
adminGroupPage.removeAllRoles();
assertFalse(adminGroupPage.getListOfRolesToAdd().isEmpty());
assertTrue(adminGroupPage.getListOfAddedRoles().isEmpty());
adminGroupPage.addRole(ROLE, false);
adminGroupPage.addRole(ROLE_2, false);
adminGroupPage.addRole(ROLE_3, false);
adminGroupPage.clickSaveButton();
adminGroupPage.chooseGroup(name);
assertEquals(expectedRoles.size(), adminGroupPage.getListOfRolesFromLinkedTable().size());
assertTrue(adminGroupPage.getWebElementTexts(adminGroupPage.getListOfRolesFromLinkedTable())
.containsAll(expectedRoles));
adminGroupPage.clickEditButton();
adminGroupPage.removeAllRoles();
adminGroupPage.clickSaveButton();
adminGroupPage.chooseGroup(name);
assertTrue(adminGroupPage.getListOfRolesFromLinkedTable().isEmpty());
}
@ParameterizedTest
@ArgumentsSource(BrowserArgumentProvider.class)
public void addNewGroupToUser(Browser browser) {
openBrowserAndAdminPage(browser);
String userName = name;
EXECUTION_MANAGER.createUser(userName, ORGANIZATION_ID);
adminGroupPage.clickCreateButton();
adminGroupPage.waitForPageLoad();
adminGroupPage.waitForVisibilityOf(adminGroupPage.nameField);
adminGroupPage.typeText(adminGroupPage.nameField, name);
adminGroupPage.typeAndSelectLevel(GROUP_ACCESS_LEVEL);
adminGroupPage.clickSaveButton();
AdminUserPage adminUserPage = inboxPage.startAdminUser();
adminUserPage.searchUser(userName);
adminUserPage.clickOnUserInTable(userName);
adminUserPage.clickEditButton();
adminUserPage.fillPassAndEmail(userName, userName + "@test.ru");
adminUserPage.bindGroup(name);
assertTrue(adminUserPage.getWebElementTexts(adminUserPage.getListOfAddedGroups()).contains(name));
adminUserPage.clickSaveButton();
adminUserPage.searchUser(userName);
adminUserPage.clickOnUserInTable(userName);
assertEquals(1, adminUserPage.getListOfGroupsFromTable().size());
assertEquals(name, adminUserPage.getListOfGroupsFromTable().get(0).getText());
}
@Disabled("dev WEBBPMNEXT-7837")
@ParameterizedTest
@ArgumentsSource(BrowserArgumentProvider.class)
public void groupRolesGridsSorting(Browser browser) {
openBrowserAndAdminPage(browser);
EXECUTION_MANAGER.createGroupBindRoles(name, ACCESS_LEVEL_ID, BPMN_ADMIN_ROLE_ID,
BPMN_USER_ROLE_ID, BPMN_SUPERUSER_ROLE_ID);
//main group page sorting
List<String> groupNamesNatural = adminGroupPage.getWebElementTexts(adminGroupPage.getListOfGroupNames());
assertTrue(Comparators.isInOrder(groupNamesNatural, String.CASE_INSENSITIVE_ORDER),
"Grid wasn't sorted");
adminGroupPage.changeGroupPageGridSort(AdminGroupPage.GroupPageGrids.GROUP_NAMES_GRID);
List<String> groupNamesReverse = adminGroupPage.getWebElementTexts(adminGroupPage.getListOfGroupNames());
assertTrue(Comparators.isInOrder(groupNamesReverse, String.CASE_INSENSITIVE_ORDER.reversed()),
"Grid wasn't sorted");
adminGroupPage.chooseGroup(name);
List<String> linkedRolesNatural = adminGroupPage.getWebElementTexts(adminGroupPage.getListOfRolesFromLinkedTable());
assertTrue(Comparators.isInOrder(linkedRolesNatural, String.CASE_INSENSITIVE_ORDER),
"Grid wasn't sorted");
adminGroupPage.changeGroupPageGridSort(AdminGroupPage.GroupPageGrids.LINKED_ROLES_GRID);
List<String> linkedRolesReverse = adminGroupPage.getWebElementTexts(adminGroupPage.getListOfRolesFromLinkedTable());
assertTrue(Comparators.isInOrder(linkedRolesReverse, String.CASE_INSENSITIVE_ORDER.reversed()),
"Grid wasn't sorted");
//edit group page sorting
adminGroupPage.clickEditButton();
List<String> availableToAddRolesNatural = adminGroupPage.getWebElementTexts(adminGroupPage.getListOfRolesToAdd());
assertTrue(Comparators.isInOrder(availableToAddRolesNatural, String.CASE_INSENSITIVE_ORDER),
"Grid wasn't sorted");
adminGroupPage.changeGroupPageGridSort(AdminGroupPage.GroupPageGrids.ROLES_TO_ADD_GRID);
List<String> availableToAddRolesReverse = adminGroupPage.getWebElementTexts(adminGroupPage.getListOfRolesToAdd());
assertTrue(Comparators.isInOrder(availableToAddRolesReverse,
String.CASE_INSENSITIVE_ORDER.reversed()), "Grid wasn't sorted");
adminGroupPage.removeAllRoles();
List<String> addedRolesNatural = adminGroupPage.getWebElementTexts(adminGroupPage.getListOfAddedRoles());
assertTrue(Comparators.isInOrder(addedRolesNatural, String.CASE_INSENSITIVE_ORDER),
"Grid wasn't sorted");
adminGroupPage.changeGroupPageGridSort(AdminGroupPage.GroupPageGrids.ADDED_ROLES_GRID);
List<String> addedRolesReverse = adminGroupPage.getWebElementTexts(adminGroupPage.getListOfAddedRoles());
assertTrue(Comparators.isInOrder(addedRolesReverse, String.CASE_INSENSITIVE_ORDER.reversed()),
"Grid wasn't sorted");
//create group page sorting
adminGroupPage.cancelAction();
adminGroupPage.clickCreateButton();
List<String> rolesToAddNatural = adminGroupPage.getWebElementTexts(adminGroupPage.getListOfRolesToAdd());
assertTrue(Comparators.isInOrder(rolesToAddNatural, String.CASE_INSENSITIVE_ORDER),
"Grid wasn't sorted");
adminGroupPage.changeGroupPageGridSort(AdminGroupPage.GroupPageGrids.ROLES_TO_ADD_GRID);
List<String> rolesToAddReverse = adminGroupPage.getWebElementTexts(adminGroupPage.getListOfRolesToAdd());
assertTrue(Comparators.isInOrder(rolesToAddReverse, String.CASE_INSENSITIVE_ORDER.reversed()),
"Grid wasn't sorted");
adminGroupPage.removeAllRoles();
List<String> addedRolesNaturalSort = adminGroupPage.getWebElementTexts(adminGroupPage.getListOfAddedRoles());
assertTrue(Comparators.isInOrder(addedRolesNaturalSort, String.CASE_INSENSITIVE_ORDER),
"Grid wasn't sorted");
adminGroupPage.changeGroupPageGridSort(AdminGroupPage.GroupPageGrids.ADDED_ROLES_GRID);
List<String> addedRolesReverseSort = adminGroupPage.getWebElementTexts(adminGroupPage.getListOfAddedRoles());
assertTrue(Comparators.isInOrder(addedRolesReverseSort, String.CASE_INSENSITIVE_ORDER.reversed()),
"Grid wasn't sorted");
}
private void openBrowserAndAdminPage(Browser browser) {
openBrowserAndLoginForAdmin(browser);
initAdminName();
adminGroupPage = inboxPage.startAdminGroup();
}
}

View file

@ -1,184 +0,0 @@
package old;
import com.google.common.collect.Comparators;
import old.core.Browser;
import old.core.BrowserArgumentProvider;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.TestInfo;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ArgumentsSource;
import org.openqa.selenium.WebElement;
import old.page.AdminGroupPage;
import old.page.AdminRolePage;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* @author kote
*/
public class AdminRoleIT extends BaseComponentIT {
private static final String COL_ID = "role$name";
private static final String COL_ID_CREATED = "role$created";
private static final String COL_ID_UPDATED = "role$updated";
private AdminRolePage adminRolePage;
private String oldName;
public AdminRoleIT() {
super();
}
@AfterEach
public void afterEachTest(TestInfo testInfo) {
String testName = testInfo.getTestMethod().toString();
if (testName.contains("Group")) {
EXECUTION_MANAGER.deleteTestGroup(name);
}
if (testName.contains("edit")) {
EXECUTION_MANAGER.deleteTestRole(oldName);
}
if (testName.contains("Sorting")) {
String roleId = EXECUTION_MANAGER.getRoleIdByName(name);
EXECUTION_MANAGER.deleteLinkedGroupsFromRole(roleId);
}
EXECUTION_MANAGER.deleteTestRole(name);
}
@ParameterizedTest
@ArgumentsSource(BrowserArgumentProvider.class)
public void createRole(Browser browser) {
openBrowserAndAdminPage(browser);
adminRolePage.clickCreateButton();
adminRolePage.typeText(adminRolePage.nameField, name);
adminRolePage.clickSaveButton();
String dateOfCreation = adminRolePage.getLocalDate();
adminRolePage.searchRole(name);
assertEquals(1, adminRolePage.getListOfRolesNamesFromTable(name).size());
assertTrue(adminRolePage.getActionTime(COL_ID, name, COL_ID_CREATED).getText().contains(dateOfCreation));
}
@ParameterizedTest
@ArgumentsSource(BrowserArgumentProvider.class)
public void searchRole(Browser browser) {
openBrowserAndAdminPage(browser);
EXECUTION_MANAGER.createTestRole(name);
adminRolePage.searchRole(name);
assertEquals(1, adminRolePage.getListOfRolesNamesFromTable(name).size());
}
@ParameterizedTest
@ArgumentsSource(BrowserArgumentProvider.class)
public void editRole(Browser browser) {
openBrowserAndAdminPage(browser);
oldName = "old" + name;
EXECUTION_MANAGER.createTestRole(oldName);
adminRolePage.chooseRole(oldName);
adminRolePage.clickEditButton();
adminRolePage.typeText(adminRolePage.nameField, name);
adminRolePage.clickSaveButton();
adminRolePage.searchRole(oldName);
assertEquals(0, adminRolePage.getListOfRolesNamesFromTable(oldName).size());
adminRolePage.searchRole(name);
assertEquals(1, adminRolePage.getListOfRolesNamesFromTable(name).size());
String timeOfCreate = adminRolePage.getActionTime(COL_ID, name, COL_ID_CREATED).getText();
String timeOfUpdate = adminRolePage.getActionTime(COL_ID, name, COL_ID_UPDATED).getText();
assertNotEquals(timeOfCreate, timeOfUpdate);
}
@ParameterizedTest
@ArgumentsSource(BrowserArgumentProvider.class)
public void deleteRole(Browser browser) {
openBrowserAndAdminPage(browser);
EXECUTION_MANAGER.createTestRole(name);
adminRolePage.waitForPageLoad();
adminRolePage.chooseRole(name);
adminRolePage.deleteRole();
assertEquals(0, adminRolePage.getListOfRolesNamesFromTable(name).size());
}
@ParameterizedTest
@ArgumentsSource(BrowserArgumentProvider.class)
public void roleGroupGridContainsAttachedGroup(Browser browser) {
openBrowserAndAdminPage(browser);
String roleId = EXECUTION_MANAGER.generateId();
String groupId = EXECUTION_MANAGER.generateId();
EXECUTION_MANAGER.createBindGroupRole(name, groupId, ACCESS_LEVEL_ID, roleId);
adminRolePage.chooseRole(name);
WebElement gridLinkedGroup = adminRolePage.getListOfRoleLinkedGroups().get(0);
adminRolePage.waitForTextToBePresentInElement(gridLinkedGroup, name);
assertEquals(1, adminRolePage.getListOfRoleLinkedGroups().size());
assertEquals(adminRolePage.getListOfRoleLinkedGroups().get(0).getText(), name);
}
@ParameterizedTest
@ArgumentsSource(BrowserArgumentProvider.class)
public void addNewRoleToGroup(Browser browser) {
openBrowserAndAdminPage(browser);
String groupName = name;
EXECUTION_MANAGER.createTestGroup(groupName, ACCESS_LEVEL_ID);
adminRolePage.clickCreateButton();
adminRolePage.typeText(adminRolePage.nameField, name);
adminRolePage.clickSaveButton();
AdminGroupPage adminGroupPage = inboxPage.startAdminGroup();
adminGroupPage.chooseGroup(groupName);
adminGroupPage.clickEditButton();
adminGroupPage.bindRole(name);
assertTrue(adminGroupPage.hasRolesInTable(AdminGroupPage.GroupPageGrids.ADDED_ROLES_GRID, name));
adminGroupPage.clickSaveButton();
adminGroupPage.chooseGroup(groupName);
adminGroupPage.clickEditButton();
assertTrue(adminGroupPage.hasRolesInTable(AdminGroupPage.GroupPageGrids.ADDED_ROLES_GRID, name));
}
@Disabled("dev WEBBPMNEXT-7837")
@ParameterizedTest
@ArgumentsSource(BrowserArgumentProvider.class)
public void roleGroupsGridSorting(Browser browser) {
openBrowserAndAdminPage(browser);
EXECUTION_MANAGER.createRoleBindGroups(name, BPMN_ADMIN_GROUP_ID, BPMN_USER_GROUP_ID, BPMN_SUPERUSER_GROUP_ID);
List<String> roleNamesNatural = adminRolePage.getWebElementTexts(adminRolePage.getListOfRoles());
assertTrue(Comparators.isInOrder(roleNamesNatural, String.CASE_INSENSITIVE_ORDER),
"Grid wasn't sorted");
adminRolePage.changeRolePageGridSort(AdminRolePage.RolePageGrids.ROLE_NAMES_GRID);
List<String> roleNamesReverse = adminRolePage.getWebElementTexts(adminRolePage.getListOfRoles());
assertTrue(Comparators.isInOrder(roleNamesReverse, String.CASE_INSENSITIVE_ORDER.reversed()),
"Grid wasn't sorted");
adminRolePage.chooseRole(name);
List<String> linkedGroupsNatural = adminRolePage.getWebElementTexts(adminRolePage.getListOfRoleLinkedGroups());
assertTrue(Comparators.isInOrder(linkedGroupsNatural, String.CASE_INSENSITIVE_ORDER),
"Grid wasn't sorted");
adminRolePage.changeRolePageGridSort(AdminRolePage.RolePageGrids.GROUP_NAMES_GRID);
List<String> linkedGroupsReverse = adminRolePage.getWebElementTexts(adminRolePage.getListOfRoleLinkedGroups());
assertTrue(Comparators.isInOrder(linkedGroupsReverse, String.CASE_INSENSITIVE_ORDER.reversed()),
"Grid wasn't sorted");
}
private void openBrowserAndAdminPage(Browser browser) {
openBrowserAndLoginForAdmin(browser);
initAdminName();
adminRolePage = inboxPage.startAdminRole();
}
}

View file

@ -1,370 +0,0 @@
package old;
import com.google.common.collect.Comparators;
import old.core.Browser;
import old.core.BrowserArgumentProvider;
import org.apache.commons.lang.RandomStringUtils;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.TestInfo;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ArgumentsSource;
import old.page.AdminUserPage;
import java.util.Arrays;
import java.util.List;
import static org.apache.commons.lang.StringUtils.containsIgnoreCase;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* @author kote
*/
public class AdminUserIT extends BaseComponentIT {
private AdminUserPage adminUserPage;
private String oldName;
private String email;
private static final String USER_PASSWORD = "test";
private static final String USER_PASSWORD_2 = "test2";
private static final String ORGANIZATION = "Default";
private static final String FULL_ORGANIZATION_NAME = "Default Organization";
private static final String BPMN_ADMIN_GROUP = "BPMN Admin";
private static final String BPMN_USER_GROUP = "BPMN User";
private static final String BPMN_SUPERUSER_GROUP = "BPMN Superuser";
private static final String SECURITY_GROUP = "Security Admin";
public AdminUserIT() {
super();
}
@AfterEach
public void afterEachTest(TestInfo testInfo) {
String testName = testInfo.getTestMethod().toString();
if (testName.contains("edit")) {
EXECUTION_MANAGER.deleteTestUser(oldName);
}
if (containsIgnoreCase(testName, "sorting")) {
String userAccId = EXECUTION_MANAGER.getUserAccountIdByName(name);
EXECUTION_MANAGER.deleteUserLinkedGroups(userAccId);
}
if (containsIgnoreCase(testName, "visibility")) {
String userAccountId = EXECUTION_MANAGER.getUserAccountIdByName(name);
EXECUTION_MANAGER.deleteUserLinkedGroups(userAccountId);
}
EXECUTION_MANAGER.deleteTestUser(name);
}
@ParameterizedTest
@ArgumentsSource(BrowserArgumentProvider.class)
public void createUser(Browser browser) {
openBrowserAndAdminPage(browser);
adminUserPage.clickCreateButton();
adminUserPage.waitForVisibilityOf(adminUserPage.lastNameField);
adminUserPage.fillUserFullName(name);
email = randomEmail();
adminUserPage.fillUserCredentials(name, USER_PASSWORD, email, ORGANIZATION, FULL_ORGANIZATION_NAME);
adminUserPage.addGroup(BPMN_ADMIN_GROUP);
adminUserPage.clickSaveButton();
assertTrue(EXECUTION_MANAGER.hasUserByData(name, email));
adminUserPage.searchUser(name);
adminUserPage.clickOnUserInTable(name);
assertEquals(1, adminUserPage.getListOfGroupsFromTable().size());
assertEquals(BPMN_ADMIN_GROUP, adminUserPage.getListOfGroupsFromTable().get(0).getText());
}
@ParameterizedTest
@ArgumentsSource(BrowserArgumentProvider.class)
public void searchUser(Browser browser) {
openBrowserAndAdminPage(browser);
EXECUTION_MANAGER.createUser(name, ORGANIZATION_ID);
adminUserPage.searchUser(name);
assertEquals(1, adminUserPage.getListOfLastNamesFromTable().size());
assertEquals(1, adminUserPage.getListOfFirstNamesFromTable().size());
assertEquals(1, adminUserPage.getListOfMiddleNamesFromTable().size());
assertEquals(name, adminUserPage.getListOfLastNamesFromTable().get(0).getText());
assertEquals(name, adminUserPage.getListOfFirstNamesFromTable().get(0).getText());
assertEquals(name, adminUserPage.getListOfMiddleNamesFromTable().get(0).getText());
}
@ParameterizedTest
@ArgumentsSource(BrowserArgumentProvider.class)
public void editUser(Browser browser) {
openBrowserAndAdminPage(browser);
EXECUTION_MANAGER.createUser(name, ORGANIZATION_ID);
adminUserPage.searchUser(name);
adminUserPage.clickOnUserInTable(name);
adminUserPage.clickEditButton();
adminUserPage.waitForVisibilityOf(adminUserPage.lastNameField);
oldName = name;
name = name + "_edited";
adminUserPage.fillUserFullName(name);
email = randomEmail();
adminUserPage.fillPassAndEmail(USER_PASSWORD_2, email);
adminUserPage.addGroup(BPMN_USER_GROUP);
adminUserPage.clickSaveButton();
adminUserPage.waitForVisibilityOf(adminUserPage.filterPanel);
adminUserPage.searchUser(name);
assertEquals(1, adminUserPage.getListOfLastNamesFromTable().size());
assertEquals(1, adminUserPage.getListOfFirstNamesFromTable().size());
assertEquals(1, adminUserPage.getListOfMiddleNamesFromTable().size());
assertNotEquals(oldName, adminUserPage.getListOfLastNamesFromTable().get(0).getText());
assertNotEquals(oldName, adminUserPage.getListOfFirstNamesFromTable().get(0).getText());
assertNotEquals(oldName, adminUserPage.getListOfMiddleNamesFromTable().get(0).getText());
assertTrue(EXECUTION_MANAGER.hasUserByData(name, email));
adminUserPage.clickOnUserInTable(name);
assertEquals(1, adminUserPage.getListOfGroupsFromTable().size());
assertEquals(BPMN_USER_GROUP, adminUserPage.getListOfGroupsFromTable().get(0).getText());
}
@ParameterizedTest
@ArgumentsSource(BrowserArgumentProvider.class)
public void deleteUser(Browser browser) {
openBrowserAndAdminPage(browser);
EXECUTION_MANAGER.createUser(name, ORGANIZATION_ID);
adminUserPage.searchUser(name);
adminUserPage.clickOnUserInTable(name);
adminUserPage.deleteUser();
assertTrue(adminUserPage.getListOfLastNamesFromTable().isEmpty());
assertTrue(adminUserPage.getListOfFirstNamesFromTable().isEmpty());
assertTrue(adminUserPage.getListOfMiddleNamesFromTable().isEmpty());
}
@ParameterizedTest
@ArgumentsSource(BrowserArgumentProvider.class)
public void attachRemoveGroup(Browser browser) {
openBrowserAndAdminPage(browser);
EXECUTION_MANAGER.createUser(name, ORGANIZATION_ID);
adminUserPage.searchUser(name);
adminUserPage.clickOnUserInTable(name);
assertTrue(adminUserPage.getListOfGroupsFromTable().isEmpty());
adminUserPage.clickEditButton();
assertFalse(adminUserPage.getListOfAvailableGroupsToAdd().isEmpty());
assertTrue(adminUserPage.getListOfAddedGroups().isEmpty());
adminUserPage.addGroup(BPMN_ADMIN_GROUP);
assertFalse(adminUserPage.getWebElementTexts(adminUserPage.getListOfAvailableGroupsToAdd()).contains(BPMN_ADMIN_GROUP));
assertEquals(BPMN_ADMIN_GROUP, adminUserPage.getListOfAddedGroups().get(0).getText());
assertEquals(1, adminUserPage.getListOfAddedGroups().size());
adminUserPage.clickSaveButton();
adminUserPage.searchUser(name);
adminUserPage.clickOnUserInTable(name);
assertEquals(1, adminUserPage.getListOfGroupsFromTable().size());
assertEquals(BPMN_ADMIN_GROUP, adminUserPage.getListOfGroupsFromTable().get(0).getText());
adminUserPage.clickEditButton();
adminUserPage.removeGroup(BPMN_ADMIN_GROUP);
assertTrue(adminUserPage.getWebElementTexts(adminUserPage.getListOfAvailableGroupsToAdd()).contains(BPMN_ADMIN_GROUP));
assertTrue(adminUserPage.getListOfAddedGroups().isEmpty());
adminUserPage.clickSaveButton();
adminUserPage.searchUser(name);
adminUserPage.clickOnUserInTable(name);
assertTrue(adminUserPage.getListOfGroupsFromTable().isEmpty());
}
@ParameterizedTest
@ArgumentsSource(BrowserArgumentProvider.class)
public void attachRemoveAllGroups(Browser browser) {
openBrowserAndAdminPage(browser);
EXECUTION_MANAGER.createUser(name, ORGANIZATION_ID);
List<String> groupNamesFromTable = EXECUTION_MANAGER.getGroupNamesFromUserGroup();
List<String> expectedGroups = Arrays.asList(BPMN_ADMIN_GROUP, BPMN_USER_GROUP,
BPMN_SUPERUSER_GROUP);
adminUserPage.searchUser(name);
adminUserPage.clickOnUserInTable(name);
assertTrue(adminUserPage.getListOfGroupsFromTable().isEmpty());
adminUserPage.clickEditButton();
assertFalse(adminUserPage.getListOfAvailableGroupsToAdd().isEmpty());
assertTrue(adminUserPage.getListOfAddedGroups().isEmpty());
adminUserPage.addAllGroups();
assertTrue(adminUserPage.isAvailableGridEmpty(groupNamesFromTable));
assertFalse(adminUserPage.getListOfAddedGroups().isEmpty());
adminUserPage.removeAllGroups();
assertFalse(adminUserPage.getListOfAvailableGroupsToAdd().isEmpty());
assertTrue(adminUserPage.getListOfAddedGroups().isEmpty());
adminUserPage.addGroup(BPMN_ADMIN_GROUP);
adminUserPage.addGroup(BPMN_USER_GROUP);
adminUserPage.addGroup(BPMN_SUPERUSER_GROUP);
adminUserPage.clickSaveButton();
adminUserPage.searchUser(name);
adminUserPage.clickOnUserInTable(name);
assertEquals(3, adminUserPage.getListOfGroupsFromTable().size());
assertTrue(adminUserPage.getWebElementTexts(adminUserPage.getListOfGroupsFromTable()).containsAll(expectedGroups));
adminUserPage.clickEditButton();
adminUserPage.removeAllGroups();
adminUserPage.clickSaveButton();
adminUserPage.searchUser(name);
adminUserPage.clickOnUserInTable(name);
assertTrue(adminUserPage.getListOfGroupsFromTable().isEmpty());
}
@ParameterizedTest
@ArgumentsSource(BrowserArgumentProvider.class)
public void accessLevelGroupVisibility(Browser browser) {
openBrowserAndAdminPage(browser);
EXECUTION_MANAGER.createUserBindGroups(name, ORGANIZATION_ID, SECURITY_ADMIN_GROUP_ID);
adminUserPage.searchUser(name);
adminUserPage.clickOnUserInTable(name);
assertTrue(adminUserPage.getWebElementTexts(adminUserPage.getListOfGroupsFromTable()).contains(SECURITY_GROUP));
adminUserPage.clickEditButton();
assertFalse(adminUserPage.getWebElementTexts(adminUserPage.getListOfAvailableGroupsToAdd()).contains(SECURITY_GROUP));
assertTrue(adminUserPage.getWebElementTexts(adminUserPage.getListOfAddedGroups()).contains(SECURITY_GROUP));
adminUserPage.logout();
initQaAdminCredentials();
login(login, password);
adminUserPage = inboxPage.startAdminUser();
adminUserPage.searchUser(name);
adminUserPage.clickOnUserInTable(name);
assertFalse(adminUserPage.getWebElementTexts(adminUserPage.getListOfGroupsFromTable()).contains(SECURITY_GROUP));
adminUserPage.clickEditButton();
assertFalse(adminUserPage.getWebElementTexts(adminUserPage.getListOfAvailableGroupsToAdd()).contains(SECURITY_GROUP));
assertFalse(adminUserPage.getWebElementTexts(adminUserPage.getListOfAddedGroups()).contains(SECURITY_GROUP));
}
@Disabled("dev WEBBPMNEXT-7837")
@ParameterizedTest
@ArgumentsSource(BrowserArgumentProvider.class)
public void userAdminPageGroupsGridSorting(Browser browser) {
openBrowserAndAdminPage(browser);
EXECUTION_MANAGER.createUserBindGroups(name, ORGANIZATION_ID, BPMN_ADMIN_GROUP_ID,
BPMN_USER_GROUP_ID, BPMN_SUPERUSER_GROUP_ID);
//User page sorting
List<String> lastNamesNatural = adminUserPage.getWebElementTexts(adminUserPage.getListOfLastNamesFromTable());
assertTrue(Comparators.isInOrder(lastNamesNatural, String.CASE_INSENSITIVE_ORDER),
"Grid wasn't sorted");
adminUserPage.changeUserPageGridsSort(AdminUserPage.UsersPageGrids.USERS_GRID);
List<String> lastNamesReverse = adminUserPage.getWebElementTexts(adminUserPage.getListOfLastNamesFromTable());
assertTrue(Comparators.isInOrder(lastNamesReverse, String.CASE_INSENSITIVE_ORDER.reversed()),
"Grid wasn't sorted");
adminUserPage.searchUser(name);
adminUserPage.clickOnUserInTable(name);
List<String> userLinkedGroupsNatural = adminUserPage.getWebElementTexts(adminUserPage.getListOfGroupsFromTable());
assertTrue(Comparators.isInOrder(userLinkedGroupsNatural, String.CASE_INSENSITIVE_ORDER),
"Grid wasn't sorted");
adminUserPage.changeUserPageGridsSort(AdminUserPage.UsersPageGrids.LINKED_GROUPS_GRID);
List<String> userLinkedGroupsReverse = adminUserPage.getWebElementTexts(adminUserPage.getListOfGroupsFromTable());
assertTrue(Comparators.isInOrder(userLinkedGroupsReverse, String.CASE_INSENSITIVE_ORDER.reversed()),
"Grid wasn't sorted");
//Edit user page sorting
adminUserPage.clickEditButton();
List<String> availableToAddGroupsNatural = adminUserPage.getWebElementTexts(adminUserPage.getListOfAvailableGroupsToAdd());
assertTrue(Comparators.isInOrder(availableToAddGroupsNatural, String.CASE_INSENSITIVE_ORDER),
"Grid wasn't sorted");
adminUserPage.changeUserPageGridsSort(AdminUserPage.UsersPageGrids.GROUPS_TO_ADD_GRID);
List<String> availableGroupsToAddReverse = adminUserPage.getWebElementTexts(adminUserPage.getListOfAvailableGroupsToAdd());
assertTrue(Comparators.isInOrder(availableGroupsToAddReverse, String.CASE_INSENSITIVE_ORDER.reversed()),
"Grid wasn't sorted");
List<String> addedGroupsNatural = adminUserPage.getWebElementTexts(adminUserPage.getListOfAddedGroups());
assertTrue(Comparators.isInOrder(addedGroupsNatural, String.CASE_INSENSITIVE_ORDER),
"Grid wasn't sorted");
adminUserPage.changeUserPageGridsSort(AdminUserPage.UsersPageGrids.ADDED_GROUPS_GRID);
List<String> addedGroupsReverse = adminUserPage.getWebElementTexts(adminUserPage.getListOfAddedGroups());
assertTrue(Comparators.isInOrder(addedGroupsReverse, String.CASE_INSENSITIVE_ORDER.reversed()),
"Grid wasn't sorted");
//Create user page sorting
adminUserPage.cancelAction();
adminUserPage.clickCreateButton();
List<String> groupsToAddNatural = adminUserPage.getWebElementTexts(adminUserPage.getListOfAvailableGroupsToAdd());
assertTrue(Comparators.isInOrder(groupsToAddNatural, String.CASE_INSENSITIVE_ORDER),
"Grid wasn't sorted");
adminUserPage.changeUserPageGridsSort(AdminUserPage.UsersPageGrids.GROUPS_TO_ADD_GRID);
List<String> groupsToAddReverse = adminUserPage.getWebElementTexts(adminUserPage.getListOfAvailableGroupsToAdd());
assertTrue(Comparators.isInOrder(groupsToAddReverse, String.CASE_INSENSITIVE_ORDER.reversed()),
"Grid wasn't sorted");
adminUserPage.addAllGroups();
List<String> addedGroupsInCreateFormNatural = adminUserPage.getWebElementTexts(adminUserPage.getListOfAddedGroups());
assertTrue(Comparators.isInOrder(addedGroupsInCreateFormNatural, String.CASE_INSENSITIVE_ORDER),
"Grid wasn't sorted");
adminUserPage.changeUserPageGridsSort(AdminUserPage.UsersPageGrids.ADDED_GROUPS_GRID);
List<String> addedGroupsInCreatedFormReverse = adminUserPage.getWebElementTexts(adminUserPage.getListOfAddedGroups());
assertTrue(Comparators.isInOrder(addedGroupsInCreatedFormReverse, String.CASE_INSENSITIVE_ORDER.reversed()),
"Grid wasn't sorted");
}
private void openBrowserAndAdminPage(Browser browser) {
openBrowserAndLoginForAdmin(browser);
initAdminName();
adminUserPage = inboxPage.startAdminUser();
}
private String randomEmail() {
String random1 = String.valueOf(20000 + (int) (Math.random() * 20000));
String random2 = String.valueOf(20000 + (int) (Math.random() * 20000));
return random1 + "@" + random2 + ".ru";
}
/*@ParameterizedTest
@ArgumentsSource(BrowserArgumentProvider.class)
public void addNewOrgToUser(Browser browser) {
openBrowserAndAdminPage(browser);
EXECUTION_MANAGER.createTestOrg(name);
EXECUTION_MANAGER.createUser(name, ORGANIZATION_ID);
organizationPage.clickCreateButton();
organizationPage.waitOrgEditingPageLoading();
organizationPage.fillOrgNameAndCode(name2);
organizationPage.chooseParentOrg(DEFAULT_ORG);
organizationPage.clickSaveButton();
AdminUserPage adminUserPage = inboxPage.startAdminUser();
adminUserPage.searchUser(name);
adminUserPage.clickOnUserInTable(name);
adminUserPage.clickEditButton();
adminUserPage.chooseUserOrganization(name2);
adminUserPage.fillPass(name);
adminUserPage.clickSaveButton();
}
private void openBrowserAndAdminPage(Browser browser) {
openBrowserAndLoginForAdmin(browser);
initAdminName();
name2 = name.substring(0, 3) + "2" + name.substring(3);
name3 = name.substring(0, 3) + "3" + name.substring(3);
organizationPage = inboxPage.startAdminOrganization();
assertFalse(isElementEnabled(DELETE_BUTTON));
}*/
}

View file

@ -1,141 +0,0 @@
package old;
import old.core.BaseTest;
import old.core.Browser;
import org.junit.jupiter.api.AfterEach;
import org.openqa.selenium.By;
import org.openqa.selenium.TimeoutException;
import org.openqa.selenium.support.PageFactory;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import old.page.InboxPage;
import old.page.LoginPage;
import old.page.ProcessesPage;
import old.util.ExecutionManager;
import old.util.PropertyManager;
import java.io.IOException;
import java.util.Properties;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static old.page.BaseComponentPage.getLoginHeaderBy;
import static old.page.BaseComponentPage.getProgressBar;
import static old.util.DataUtil.BASE_PART_FOR_USER;
/**
* @author gulnaz
*/
public abstract class BaseComponentIT extends BaseTest {
protected static final String ACCESS_LEVEL_ID = "a6bf4b31-6648-4095-b269-2a950b548a10";
protected static final String ORGANIZATION_ID = "3516544f-64c5-4883-9047-28bcce74d1be";
protected static final String SECURITY_ADMIN_GROUP_ID = "84c5c1e2-081e-45e1-a874-d6bb232e57ad";
protected static final String BPMN_ADMIN_GROUP_ID = "ddfdc772-7aee-492f-be7d-7e95ea2f45b3";
protected static final String BPMN_USER_GROUP_ID = "62cd890b-99f7-47a8-be60-e330186b17a0";
protected static final String BPMN_SUPERUSER_GROUP_ID = "273d8bbd-0e82-4064-a548-850e9aa61756";
protected static ExecutionManager EXECUTION_MANAGER = new ExecutionManager();
protected InboxPage inboxPage;
protected ProcessesPage processPage;
protected String login;
protected String password;
protected String name;
private Properties config;
final Logger logger = LoggerFactory.getLogger(getClass());
BaseComponentIT() {
super();
initCredentialsConfig();
initCredentials();
}
@AfterEach
public void exit() {
if (processPage != null) {
assertTrue(processPage.thereIsNoError());
}
}
public void openBrowserAndLoginForAdmin(Browser browser) {
initDriver(browser);
initDemoCredentials();
login(login, password);
}
public void openBrowserAndLoginForJbpm(Browser browser) {
initDriver(browser);
initQaAdminCredentials();
login(login, password);
}
private void initCredentialsConfig() {
try {
config = PropertyManager.getProperties();
}
catch (IOException e) {
throw new RuntimeException("Failed to get properties. " + e);
}
}
protected void initCredentials() {
login = config.getProperty("login");
password = config.getProperty("password");
}
protected void initDemoCredentials() {
login = config.getProperty("demo_login");
password = config.getProperty("demo_password");
}
protected void initQaAdminCredentials() {
login = config.getProperty("qa_admin_login");
password = config.getProperty("qa_admin_password");
}
void login(String login, String password) {
WebDriverWait wait = getExplicitWait(getDefaultTimeout());
wait.until(ExpectedConditions.invisibilityOfElementLocated(getProgressBar()));
wait.until(ExpectedConditions.visibilityOfElementLocated(getLoginHeaderBy()));
LoginPage loginPage = PageFactory.initElements(driver, LoginPage.class);
try {
inboxPage = loginPage.login(login, password);
}
catch (TimeoutException e) {
throw new RuntimeException("Failed to login", e);
}
}
void initAdminName() {
initName(BASE_PART_FOR_USER);
}
void initName(String basePart) {
String random = String.valueOf(20000 + (int) (Math.random() * 20000));
name = basePart + "-" + random;
logger.info(name + " record has been initialized");
}
protected boolean isElementEnabled (String xpath){
return driver.findElement(By.xpath(String.format(xpath))).isEnabled();
}
protected LoginPage getLoginPage() {
return PageFactory.initElements(driver, LoginPage.class);
}
public void openBrowserAndLogin(Browser browser) {
initDriver(browser);
login(login, password);
}
protected InboxPage getInboxPage() {
return PageFactory.initElements(driver, InboxPage.class);
}
}

View file

@ -1,322 +0,0 @@
package old;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.*;
import javax.crypto.SecretKey;
import old.core.Browser;
import old.core.BrowserArgumentProvider;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ArgumentsSource;
import org.openqa.selenium.Cookie;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.remote.Augmenter;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.support.PageFactory;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import old.page.InboxPage;
import old.util.PropertyManager;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static old.page.BaseComponentPage.getLoginHeaderBy;
/**
* @author gulnaz
*/
public class JWTokensIT extends BaseComponentIT {
private static final String SURNAME = "demo";
private static final String SECRET_KEY = "ZjE5ZjMxNmYtODViZC00ZTQ5LWIxZmYtOGEzYzE3Yjc1MDVk}";
private static final SecretKey SIGNING_KEY;
private static final String ACCESS_TOKEN = "Access-token";
private static final String DEMO_GROUP_ID = "22ee608b-dd9d-4633-906d-7c4efca231a0";
private static final String PROCESS_NAME = "test_process";
private static final Logger LOGGER = LoggerFactory.getLogger(JWTokensIT.class);
private static PasswordEncoder passwordEncoder = new BCryptPasswordEncoder(11);
private Properties config;
private WebDriver newDriver;
private Set<Cookie> cookies;
static {
byte[] encodedKey = Base64.getMimeDecoder().decode(SECRET_KEY);
SIGNING_KEY = Keys.hmacShaKeyFor(encodedKey);
}
public JWTokensIT() throws IOException {
super();
config = PropertyManager.getProperties();
}
@AfterEach
public void afterEachTest() {
if (newDriver != null) {
newDriver.close();
}
EXECUTION_MANAGER.deleteTestUser(login);
}
@Override
protected void initCredentials() {
initAdminName();
login = name;
password = login;
String encodedPassword = passwordEncoder.encode(password);
EXECUTION_MANAGER.insertUser(login, encodedPassword, login + "@test.ru", ORGANIZATION_ID,
DEMO_GROUP_ID
);
}
private void pasteDeadAccessToken() {
String deadAccessToken = createDeadAccessToken(config.getProperty("login"));
Cookie cookie = driver.manage().getCookieNamed(ACCESS_TOKEN);
driver.manage().deleteCookie(cookie);
addCookie(driver, cookie, deadAccessToken);
}
private void addCookie(WebDriver driver, Cookie cookie, String value) {
driver.manage().addCookie(
new Cookie.Builder(cookie.getName(), value)
.expiresOn(cookie.getExpiry())
.path(cookie.getPath())
.build()
);
}
private String createDeadAccessToken(String username) {
return Jwts.builder()
.setSubject(username)
.setIssuer("ru.cg.webbpm.components")
.setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(
new Date(System.currentTimeMillis() - 3600 * 1000)
)
.signWith(SIGNING_KEY)
.compact();
}
private void reopenApp() throws MalformedURLException {
int attempts = 0;
while (attempts++ < 5) {
try {
newDriver = new Augmenter().augment(new RemoteWebDriver(getGridURL(), options));
break;
}
catch (WebDriverException ignored) {
LOGGER.info("The driver did not start on " + attempts + " attempt");
}
}
newDriver.get(applicationUrl);
cookies.forEach(cookie -> addCookie(newDriver, cookie, cookie.getValue()));
newDriver.get(applicationUrl); // reopen app again
inboxPage = PageFactory.initElements(newDriver, InboxPage.class);
inboxPage.waitForPageLoad();
}
private void initDriverAndLogin(Browser browser) {
initDriver(browser);
login(login, password);
inboxPage.waitForVisibilityOf(inboxPage.adminList);
}
@ParameterizedTest
@ArgumentsSource(BrowserArgumentProvider.class)
public void refreshPageWithAliveAccessToken(Browser browser) {
initDriverAndLogin(browser);
inboxPage.refreshPage();
assertTrue(inboxPage.getEmailInputsFrom(driver).isEmpty());
}
@ParameterizedTest
@ArgumentsSource(BrowserArgumentProvider.class)
public void goToPageWithAliveAccessToken(Browser browser) {
initDriverAndLogin(browser);
inboxPage.startAdminUser();
inboxPage.waitForPageLoad();
assertTrue(inboxPage.getEmailInputsFrom(driver).isEmpty());
}
@ParameterizedTest
@ArgumentsSource(BrowserArgumentProvider.class)
public void filterWithAliveAccessToken(Browser browser) {
initDriverAndLogin(browser);
inboxPage.startAdminUser();
inboxPage.waitForPageLoad();
inboxPage.waitProgressBarNotVisible();
inboxPage.searchUser(SURNAME);
assertTrue(inboxPage.getEmailInputsFrom(driver).isEmpty());
}
@ParameterizedTest
@ArgumentsSource(BrowserArgumentProvider.class)
public void refreshPageWithDeadAccessToken(Browser browser) {
initDriverAndLogin(browser);
pasteDeadAccessToken();
inboxPage.refreshPage();
assertTrue(inboxPage.getEmailInputsFrom(driver).isEmpty());
}
@ParameterizedTest
@ArgumentsSource(BrowserArgumentProvider.class)
public void goToPageWithDeadAccessToken(Browser browser) {
initDriverAndLogin(browser);
pasteDeadAccessToken();
inboxPage.startAdminUser();
inboxPage.waitForPageLoad();
assertTrue(inboxPage.getEmailInputsFrom(driver).isEmpty());
}
@Disabled("qa WEBBPMNEXT-9052")
@ParameterizedTest
@ArgumentsSource(BrowserArgumentProvider.class)
public void filterWithDeadAccessToken(Browser browser) {
initDriverAndLogin(browser);
inboxPage.startAdminUser();
inboxPage.waitProgressBarNotVisible();
pasteDeadAccessToken();
inboxPage.searchUser(SURNAME);
inboxPage.waitForPageLoad();
assertTrue(inboxPage.getEmailInputsFrom(driver).isEmpty());
}
@ParameterizedTest
@ArgumentsSource(BrowserArgumentProvider.class)
public void refreshPageWithDeadRefreshToken(Browser browser) {
initDriverAndLogin(browser);
driver.manage().deleteAllCookies();
inboxPage.refreshPage();
assertFalse(inboxPage.getEmailInputsFrom(driver).isEmpty());
}
@ParameterizedTest
@ArgumentsSource(BrowserArgumentProvider.class)
public void goToPageWithDeadRefreshToken(Browser browser) {
initDriverAndLogin(browser);
processPage = inboxPage.startProcess(PROCESS_NAME);
processPage.waitForInitializationOf(processPage.exitButton);
driver.manage().deleteAllCookies();
processPage.exitButton.click();
inboxPage.waitForPageLoad();
assertFalse(inboxPage.getEmailInputsFrom(driver).isEmpty());
}
@ParameterizedTest
@ArgumentsSource(BrowserArgumentProvider.class)
public void filterWithDeadRefreshToken(Browser browser) {
initDriverAndLogin(browser);
inboxPage.startAdminUser();
inboxPage.waitProgressBarNotVisible();
driver.manage().deleteAllCookies();
inboxPage.waitForPageLoad();
inboxPage.searchUser(SURNAME);
inboxPage.waitForPageLoad();
assertFalse(inboxPage.getEmailInputsFrom(driver).isEmpty());
}
@Disabled("dev WEBBPMNEXT-9052") //включить после решения задачи
@ParameterizedTest
@ArgumentsSource(BrowserArgumentProvider.class)
public void checkTwoAuthorizedUsersCase(Browser browser) {
initDriverAndLogin(browser);
String firstTab = driver.getWindowHandle();
cookies = driver.manage().getCookies();
inboxPage.exitApp();
getExplicitWait(getDefaultTimeout()).until(
ExpectedConditions.visibilityOfElementLocated(getLoginHeaderBy()));
((JavascriptExecutor) driver).executeScript("window.open();");
List<String> windowHandles = new ArrayList<>(driver.getWindowHandles());
driver.switchTo().window(windowHandles.get(1));
driver.get(applicationUrl);
login(login, password);
driver.switchTo().window(firstTab);
driver.get(applicationUrl);
cookies.forEach(cookie -> addCookie(driver, cookie, cookie.getValue()));
pasteDeadAccessToken();
inboxPage.refreshPage();
inboxPage.waitEmailInput();
assertFalse(inboxPage.getEmailInputsFrom(driver).isEmpty());
}
@ParameterizedTest
@ArgumentsSource(BrowserArgumentProvider.class)
public void filterWithNoAccessToken(Browser browser) {
initDriverAndLogin(browser);
inboxPage.startAdminUser();
inboxPage.waitProgressBarNotVisible();
driver.manage().deleteCookieNamed(ACCESS_TOKEN);
inboxPage.searchUser(SURNAME);
assertTrue(inboxPage.getEmailInputsFrom(driver).isEmpty());
}
@ParameterizedTest
@ArgumentsSource(BrowserArgumentProvider.class)
public void reopenWithAliveAccessToken(Browser browser) throws MalformedURLException {
initDriverAndLogin(browser);
//don't close browser in the end, we'll do that explicitly
setCloseBrowser(false);
cookies = driver.manage().getCookies();
driver.close();
driver = null;
reopenApp();
assertTrue(inboxPage.getEmailInputsFrom(newDriver).isEmpty());
}
@ParameterizedTest
@ArgumentsSource(BrowserArgumentProvider.class)
public void reopenWithDeadAccessToken(Browser browser) throws MalformedURLException {
initDriverAndLogin(browser);
//don't close browser in the end, we'll do that explicitly
setCloseBrowser(false);
pasteDeadAccessToken();
cookies = driver.manage().getCookies();
driver.close();
driver = null;
reopenApp();
assertTrue(inboxPage.getEmailInputsFrom(newDriver).isEmpty());
}
@ParameterizedTest
@ArgumentsSource(BrowserArgumentProvider.class)
public void refreshWithNoSession(Browser browser) {
initDriverAndLogin(browser);
((JavascriptExecutor) driver).executeScript(
String.format("window.localStorage.clear();")); //clear localStorage
inboxPage.refreshPage();
assertTrue(inboxPage.getEmailInputsFrom(driver).isEmpty());
}
}

View file

@ -1,404 +0,0 @@
package old.core;
import java.time.Duration;
import java.util.List;
import java.util.function.Supplier;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.support.PageFactory;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
/**
* @author evgeny
*/
@SuppressWarnings("UnusedDeclaration")
public abstract class BasePage {
private static final Duration DEFAULT_TIMEOUT = Duration.ofSeconds(20);
private static final int PROGRESS_VISIBILITY_TIMEOUT_MS = 700;
private static final By ERROR = By.xpath("//div[contains(@class, 'toast-error')]");
private static final By INPUT_IS_ACTIVE = By.xpath("//div[contains(@class, 'input-active')]");
protected static final By PROGRESS_BAR = By.xpath("//div[@class='progress']");
protected final WebDriver driver;
protected final String uri;
public BasePage(WebDriver driver, String uri) {
this.driver = driver;
this.uri = uri;
// Check that we're on the right page.
if (!isAtUri(uri))
throw new IllegalStateException("This is not the '" + uri + "' page");
PageFactory.initElements(driver, this);
}
protected Duration getDefaultTimeout() {
return DEFAULT_TIMEOUT;
}
public static By getProgressBar() {
return PROGRESS_BAR;
}
public static By getErrorBy() {
return ERROR;
}
public boolean isAtUri(String uri) {
if (((RemoteWebDriver) driver).getCapabilities().getBrowserName().equalsIgnoreCase("internet explorer")) {
return true;
}
else {
return waitForCorrectUrl(uri, getDefaultTimeout());
}
}
/**
* Ожидание того, что URL текущей страницы содержит определенный текст.
*
* @param uri адрес текущей страницы
* @param timeout timeout ожидания
* @return <code>true</code> при корректном url
*/
private boolean waitForCorrectUrl(String uri, Duration timeout) {
return new WebDriverWait(driver, timeout).until(ExpectedConditions.urlContains(uri));
}
/**
* Ожидание видимости элемента, присутствующего в DOM.
* Видимость означает не только то, что элемент отобразился, но и то, что высота и ширина элемента больше 0.
*
* @param webElement элемент, который присутствует в DOM
* @param timeout timeout ожидания
* @return веб-элемент, как только он видим
*/
public WebElement waitForVisibilityOf(WebElement webElement, Duration timeout) {
return new WebDriverWait(driver, timeout).until(ExpectedConditions.visibilityOf(webElement));
}
/**
* Ожидание видимости элемента, присутствующего в DOM.
* Видимость означает не только то, что элемент отобразился, но и то, что высота и ширина элемента больше 0.
*
* @param webElement элемент, который присутствует в DOM
* @return веб-элемент, как только он видим
*/
public WebElement waitForVisibilityOf(WebElement webElement) {
return waitForVisibilityOf(webElement, getDefaultTimeout());
}
/**
* Ожидание появления элемента в DOM и его видимости.
* Видимость означает не только то, что элемент отобразился, но и то, что высота и ширина элемента больше 0.
*
* @param locator локатор, по которому находится элемент
* @param timeout timeout ожидания
* @return веб-элемент, как только он найден и видим
*/
public WebElement waitForVisibilityOfElementLocated(By locator, Duration timeout) {
return new WebDriverWait(driver, timeout).until(ExpectedConditions.visibilityOfElementLocated(locator));
}
/**
* Ожидание появления элемента в DOM и его видимости.
* Видимость означает не только то, что элемент отобразился, но и то, что высота и ширина элемента больше 0.
*
* @param locator локатор, по которому находится элемент
* @return веб-элемент, как только он найден и видим
*/
public WebElement waitForVisibilityOfElementLocated(By locator) {
return waitForVisibilityOfElementLocated(locator, getDefaultTimeout());
}
/**
* Ожидание появления элемента в DOM и его видимости.
* Видимость означает не только то, что элемент отобразился, но и то, что высота и ширина элемента больше 0.
*
* @param locator локатор, по которому находится элемент
* @param timeout timeout ожидания
* @param sleep длительность между опросами
* @return веб-элемент, как только он найден и видим
*/
public WebElement waitForVisibilityOfElementLocated(By locator, Duration timeout, Duration sleep) {
return new WebDriverWait(driver, timeout, sleep).until(ExpectedConditions.visibilityOfElementLocated(locator));
}
/**
* Ожидание того, что элемент невидим или не представлен в DOM.
*
* @param locator локатор, по которому находится элемент
* @param timeout timeout ожидания
* @return <code>true</code>, когда элемент невидим или не найден в DOM
*/
public boolean waitForInvisibilityOfElementLocated(By locator, Duration timeout) {
return new WebDriverWait(driver, timeout).until(ExpectedConditions.invisibilityOfElementLocated(locator));
}
/**
* Ожидание того, что элемент невидим или не представлен в DOM.
*
* @param locator локатор, по которому находится элемент
* @return <code>true</code>, когда элемент невидим или не найден в DOM
*/
public boolean waitForInvisibilityOfElementLocated(By locator) {
return waitForInvisibilityOfElementLocated(locator, getDefaultTimeout());
}
/**
* Ожидание того, что элемент больше не прикреплен к DOM
*
* @param webElement проверяемый элемент
* @param timeout timeout ожидания
* @return <code>true</code>, когда элемент больше не прикреплен к DOM
*/
public boolean waitForStalenessOf(WebElement webElement, Duration timeout) {
return new WebDriverWait(driver, timeout).until(ExpectedConditions.stalenessOf(webElement));
}
/**
* Ожидание того, что элемент больше не прикреплен к DOM
*
* @param webElement проверяемый элемент
* @return <code>true</code>, когда элемент больше не прикреплен к DOM
*/
public boolean waitForStalenessOf(WebElement webElement) {
return waitForStalenessOf(webElement, getDefaultTimeout());
}
/**
* Ожидание наличия текста в элементе, соответствующем указанному локатору.
*
* @param locator локатор, по которому находится элемент
* @param text проверяемый текст
* @param timeout timeout ожидания
* @return <code>true</code> при наличии текста в элементе
*/
public boolean waitForTextToBePresentInElementLocated(By locator, String text, Duration timeout) {
return new WebDriverWait(driver, timeout).until(ExpectedConditions.textToBePresentInElementLocated(locator, text));
}
/**
* Ожидание наличия текста в элементе, соответствующем указанному локатору.
*
* @param locator локатор, по которому находится элемент
* @param text проверяемый текст
* @return <code>true</code> при наличии текста в элементе
*/
public boolean waitForTextToBePresentInElementLocated(By locator, String text) {
return waitForTextToBePresentInElementLocated(locator, text, getDefaultTimeout());
}
/**
* Ожидание наличия текста в определенном элементе
*
* @param webElement проверяемый элемент
* @param text проверяемый текст
* @param timeout timeout ожидания
* @return <code>true</code> при наличии текста в элементе
*/
public boolean waitForTextToBePresentInElement(WebElement webElement, String text, Duration timeout) {
return new WebDriverWait(driver, timeout).until(ExpectedConditions.textToBePresentInElement(webElement, text));
}
/**
* Ожидание наличия текста в определенном элементе
*
* @param webElement проверяемый элемент
* @param text проверяемый текст
* @return <code>true</code> при наличии текста в элементе
*/
public boolean waitForTextToBePresentInElement(WebElement webElement, String text) {
return waitForTextToBePresentInElement(webElement, text, getDefaultTimeout());
}
/**
* Ожидание видимости и доступности присутствующего в DOM элемента для нажатия.
*
* @param webElement проверяемый элемент
* @param timeout timeout ожидания
* @return веб-элемент, как только он доступен для нажатия
*/
public WebElement waitForElementToBeClickable(WebElement webElement, Duration timeout) {
return new WebDriverWait(driver, timeout).until(ExpectedConditions.elementToBeClickable(webElement));
}
/**
* Ожидание видимости и доступности присутствующего в DOM элемента для нажатия.
*
* @param webElement проверяемый элемент
* @return веб-элемент, как только он доступен для нажатия
*/
public WebElement waitForElementToBeClickable(WebElement webElement) {
return waitForElementToBeClickable(webElement, getDefaultTimeout());
}
/**
* Ожидание появления элемента в DOM, видимости и доступности элемента для нажатия.
*
* @param locator локатор, по которому находится элемент
* @param timeout timeout ожидания
* @return веб-элемент, как только он доступен для нажатия
*/
public WebElement waitForElementToBeClickable(By locator, Duration timeout) {
return new WebDriverWait(driver, timeout).until(ExpectedConditions.elementToBeClickable(locator));
}
/**
* Ожидание появления элемента в DOM, видимости и доступности элемента для нажатия.
*
* @param locator локатор, по которому находится элемент
* @return веб-элемент, как только он доступен для нажатия
*/
public WebElement waitForElementToBeClickable(By locator) {
return waitForElementToBeClickable(locator, getDefaultTimeout());
}
/**
* Ожидание определенного количества элементов с указанным локатором.
*
* @param locator локатор, по которому находится элемент
* @param number ожидаемое число элементов
* @param timeout timeout ожидания
* @return список элементов с определенным количеством
*/
public List<WebElement> waitForNumberOfElementsToBe(By locator, int number, Duration timeout) {
return new WebDriverWait(driver, timeout).until(ExpectedConditions.numberOfElementsToBe(locator, number));
}
/**
* Ожидание определенного количества элементов с указанным локатором.
*
* @param locator локатор, по которому находится элемент
* @param number ожидаемое число элементов
* @return список элементов с определенным количеством
*/
public List<WebElement> waitForNumberOfElementsToBe(By locator, int number) {
return waitForNumberOfElementsToBe(locator, number, getDefaultTimeout());
}
/**
* Ожидание того, что как минимум один элемент с указанным локатором представлен на странице.
* Полезно, когда нужно подождать динамический элемент.
*
* @param locator локатор, по которому находится элемент
* @param timeout timeout ожидания
* @return список элементов с указанным локатором
*/
public List<WebElement> waitForPresenceOfAllElementsLocatedBy(By locator, Duration timeout) {
return new WebDriverWait(driver, timeout).until(ExpectedConditions.presenceOfAllElementsLocatedBy(locator));
}
/**
* Ожидание того, что как минимум один элемент с указанным локатором представлен на странице.
* Полезно, когда нужно подождать динамический элемент.
*
* @param locator локатор, по которому находится элемент
* @return список элементов с указанным локатором
*/
public List<WebElement> waitForPresenceOfAllElementsLocatedBy(By locator) {
return waitForPresenceOfAllElementsLocatedBy(locator, getDefaultTimeout());
}
/**
* Ожидание того, что указзнный элемент содержит атрибут с определенным значением
*
* @param webElement проверяемый элемент
* @param attribute проверяемый атрибут
* @param value проверяемое значение
* @param timeout timeout ожидания
* @return <code>true</code> при наличии значения в атрибуте
*/
public boolean waitForAttributeContains(WebElement webElement, String attribute, String value, Duration timeout) {
return new WebDriverWait(driver, timeout).until(ExpectedConditions.attributeContains(webElement, attribute, value));
}
/**
* Ожидание того, что указзнный элемент содержит атрибут с определенным значением
*
* @param webElement проверяемый элемент
* @param attribute проверяемый атрибут
* @param value проверяемое значение
* @return <code>true</code> при наличии значения в атрибуте
*/
public boolean waitForAttributeContains(WebElement webElement, String attribute, String value) {
return waitForAttributeContains(webElement, attribute, value, getDefaultTimeout());
}
public void sleep(long millis) {
BaseTest.sleep(millis);
}
private void waitForCondition(Supplier<Boolean> condition, long timeOutInMillis) {
long startTime = System.currentTimeMillis();
while (!condition.get()) {
if (System.currentTimeMillis() - startTime >= timeOutInMillis) {
break;
}
sleep(100);
}
}
private void waitProgressBarVisible(long timeOutInMillis) {
waitForCondition(
() -> driver.findElements(PROGRESS_BAR).size() > 0,
timeOutInMillis
);
}
//ожидается, что последний инпут, по которому был клик, выбран
public void waitForInputFieldSelected() {
waitForNumberOfElementsToBe(INPUT_IS_ACTIVE, 1);
}
//ожидается пока пропадет прогресс бар
public void waitProgressBarNotVisible(Duration timeout) {
waitForInvisibilityOfElementLocated(PROGRESS_BAR, timeout);
}
//ожидается пока пропадет прогресс бар с таймаутом по умолчанию
public void waitProgressBarNotVisible() {
waitForInvisibilityOfElementLocated(PROGRESS_BAR, getDefaultTimeout());
}
//проверяется отсутствие ошибок
public boolean thereIsNoError() {
return getErrors().isEmpty();
}
//получить первую ошибку
public WebElement getError() {
return getErrors().get(0);
}
//получить все ошибки
public List<WebElement> getErrors() {
waitForCondition(
() -> driver.findElements(ERROR).size() > 0,
500
);
return driver.findElements(ERROR);
}
//переключиться на другую вкладку
public void goToAnotherTab(String tab) {
waitProgressBarNotVisible(Duration.ofSeconds(10));
driver.switchTo().window(tab);
}
//обновить страницу
public void refreshPage() {
driver.navigate().refresh();
waitProgressBarNotVisible();
}
public void waitForPageLoad() {
waitProgressBarNotVisible();
waitProgressBarVisible(PROGRESS_VISIBILITY_TIMEOUT_MS);
waitProgressBarNotVisible();
}
}

View file

@ -1,273 +0,0 @@
package old.core;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Optional;
import java.util.TimeZone;
import java.util.logging.Level;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.TestInfo;
import org.junit.jupiter.api.extension.AfterTestExecutionCallback;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.RegisterExtension;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.TimeoutException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.logging.LogEntry;
import org.openqa.selenium.logging.LogType;
import org.openqa.selenium.logging.LoggingPreferences;
import org.openqa.selenium.remote.AbstractDriverOptions;
import org.openqa.selenium.remote.LocalFileDetector;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import static old.core.BasePage.getErrorBy;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author gulnaz
*/
public abstract class BaseTest {
protected static final String gridUrl;
protected static final String applicationUrl;
private static final Logger LOGGER = LoggerFactory.getLogger(BaseTest.class);
private static final String UNDERSCORE = "_";
private static final Duration DEFAULT_TIMEOUT = Duration.ofSeconds(20);
private static final Duration TIMEOUT = Duration.ofSeconds(3);
private static final int WINDOW_WIDTH = 945;
@RegisterExtension
protected ScreenWatcher screenWatcher = new ScreenWatcher();
protected WebDriver driver;
protected AbstractDriverOptions options;
private boolean closeBrowser = true;
private TestInfo testInfo;
static {
gridUrl = System.getProperty("selenium.grid.url");
applicationUrl = System.getProperty("application.url");
LOGGER.info("application.url: {}", applicationUrl);
LOGGER.info("grid.url: {}", gridUrl);
}
@BeforeEach
void beforeEach(TestInfo testInfo) {
this.testInfo = testInfo;
}
@AfterEach
void tearDown() {
if (closeBrowser && driver != null) {
driver.quit();
}
}
public static void sleep(long millis) {
try {
Thread.sleep(millis);
}
catch (InterruptedException e) {
throw new RuntimeException("Something went wrong...", e);
}
}
public URL getGridURL() throws MalformedURLException {
return new URL(gridUrl);
}
protected void initDriver(Browser browser) {
System.setProperty("webdriver.http.factory", "jdk-http-client");
try {
options = browser.getOptions().newInstance();
}
catch (InstantiationException | IllegalAccessException e) {
throw new RuntimeException("Failed to create capabilities", e);
}
options.setCapability("selenoid:options", new HashMap<String, Object>() {
{
put("enableLog", Boolean.valueOf(System.getProperty("enableLog")));
put("enableVNC", Boolean.valueOf(System.getProperty("enableVNC")));
put("enableVideo", Boolean.valueOf(System.getProperty("enableVideo")));
put("sessionTimeout", "3m");
put("logName", getFileName(testInfo.getTestClass(), testInfo.getTestMethod(), testInfo.getDisplayName() + ".log"));
put("videoName", getFileName(testInfo.getTestClass(), testInfo.getTestMethod(), testInfo.getDisplayName() + ".mp4"));
}
});
if (System.getProperty("enableLog") != null && browser == Browser.CHROME) {
LoggingPreferences logPrefs = new LoggingPreferences();
logPrefs.enable(LogType.BROWSER, Level.ALL);
logPrefs.enable(LogType.CLIENT, Level.ALL);
logPrefs.enable(LogType.DRIVER, Level.ALL);
logPrefs.enable(LogType.PERFORMANCE, Level.ALL);
logPrefs.enable(LogType.PROFILER, Level.ALL);
logPrefs.enable(LogType.SERVER, Level.ALL);
options.setCapability("goog:loggingPrefs", logPrefs);
}
LOGGER.info("try to create RemoteWebDriver, " + testInfo.getDisplayName());
int attempts = 0;
while (attempts++ < 5) {
try {
URL gridUrl = getGridURL();
driver = new RemoteWebDriver(gridUrl, options);
break;
}
catch (WebDriverException ignored) {
LOGGER.info("The driver did not start on " + attempts + " attempt");
}
catch (MalformedURLException e) {
throw new RuntimeException("Invalid grid URL", e);
}
}
if (driver == null) {
throw new RuntimeException("Failed to create driver for " + testInfo.getDisplayName());
}
LOGGER.info("RemoteWebDriver created, " + testInfo.getDisplayName());
// Configure to upload local files to remote Selenium instance
((RemoteWebDriver) driver).setFileDetector(new LocalFileDetector());
driver.manage().window().maximize();
//TODO после обновления selenium (4.9.0 <) необходимо перепроверить maximize()
if (getWindowWidth(driver) < WINDOW_WIDTH) { //.maximize() не срабатывает с первого раза
driver.manage().window().maximize();
}
driver.manage().window().maximize();
driver.get(applicationUrl);
assertTrue(waitForCorrectWindowWidth(),
String.format("browser window size is less than and not equal to as expected: expected - %dpx, actual - %dpx",
WINDOW_WIDTH, driver.manage().window().getSize().getWidth()));
assertTrue(getExplicitWait(TIMEOUT)
.until(ExpectedConditions.invisibilityOfElementLocated(getErrorBy())),
"an error occurred while opening application");
}
private int getWindowWidth(WebDriver webDriver) {
return webDriver.manage().window().getSize().getWidth();
}
protected Duration getDefaultTimeout() {
return DEFAULT_TIMEOUT;
}
protected WebDriverWait getExplicitWait(Duration timeout) {
return new WebDriverWait(driver, timeout);
}
protected void setCloseBrowser(boolean closeBrowser) {
this.closeBrowser = closeBrowser;
}
private boolean waitForCorrectWindowWidth() {
try {
return getExplicitWait(TIMEOUT)
.until(webDriver -> webDriver.manage().window().getSize().getWidth() >= WINDOW_WIDTH);
}
catch (TimeoutException ignored) {
return false;
}
}
private String getFileName(Optional<Class<?>> testClass, Optional<Method> testMethod, String displayName) {
String fileName = "";
if (testClass.isPresent()) {
fileName = testClass.get().getSimpleName() + UNDERSCORE;
}
if (testMethod.isPresent()) {
fileName += testMethod.get().getName() + UNDERSCORE;
}
fileName += displayName;
return fileName;
}
private String getFileName(ExtensionContext context) {
return getFileName(context.getTestClass(), context.getTestMethod(), context.getDisplayName());
}
public class ScreenWatcher implements AfterTestExecutionCallback {
private static final String PATH = "target";
private static final String EXTENSION = "jpg";
private File scrFile;
@Override
public void afterTestExecution(ExtensionContext context) throws Exception {
LOGGER.info("afterTestExecution");
boolean failed = context.getExecutionException().isPresent();
if (!failed) {
if (scrFile != null)
scrFile.delete();
}
else {
LOGGER.info("test failed");
if (driver == null)
return;
saveScreen(getFileName(context));
for (String type : driver.manage().logs().getAvailableLogTypes()) {
List<LogEntry> logEntries = driver.manage().logs().get(type).getAll();
if (logEntries.isEmpty()) {
continue;
}
LOGGER.info("Logging browser messages for type: " + type);
for (LogEntry entry : logEntries) {
LocalDateTime localdateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(entry.getTimestamp()), TimeZone.getDefault().toZoneId());
String dateTime = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(localdateTime);
LOGGER.warn(dateTime + " " + entry.getLevel() + " " + entry.getMessage());
}
LOGGER.info("Logged browser messages for type: " + type);
}
}
}
public void saveScreen(String fileName) {
try {
TakesScreenshot takesScreenshot = (TakesScreenshot) driver;
scrFile = takesScreenshot.getScreenshotAs(OutputType.FILE);
Path destFile = Paths.get("", PATH, fileName + "." + EXTENSION);
Files.copy(scrFile.toPath(), destFile, StandardCopyOption.REPLACE_EXISTING);
}
catch (IOException e) {
throw new RuntimeException("Failed to capture screen", e);
}
}
}
}

Some files were not shown because too many files have changed in this diff Show more