Merge branch 'feature/SUPPORT-8427_new' into feature/SUPPORT-8471_load_classifier
# Conflicts: # config/patches/default.cli # config/standalone/dev/standalone.xml # pom.xml
This commit is contained in:
commit
91d842d25b
246 changed files with 3517 additions and 6487 deletions
22
Dockerfile
Normal file
22
Dockerfile
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
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
|
||||
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/frontend/target/*.war /usr/local/tomee/webapps/ROOT.war
|
||||
COPY --from=build /app/backend/target/*.war /usr/local/tomee/webapps/ul.war
|
||||
18
Dockerfile.old
Normal file
18
Dockerfile.old
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
FROM tomee: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 frontend/dist/ /usr/local/tomee/webapps/ROOT
|
||||
COPY backend/target/*.war /usr/local/tomee/webapps/ul.war
|
||||
|
|
@ -3,11 +3,11 @@
|
|||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>ervu_lkrp_ul</groupId>
|
||||
<artifactId>ervu_lkrp_ul</artifactId>
|
||||
<groupId>ru.micord.ervu.lkrp</groupId>
|
||||
<artifactId>ul</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<groupId>ervu_lkrp_ul.ervu_lkrp_ul</groupId>
|
||||
<groupId>ru.micord.ervu.lkrp.ul</groupId>
|
||||
<artifactId>backend</artifactId>
|
||||
<packaging>war</packaging>
|
||||
<dependencies>
|
||||
|
|
@ -19,13 +19,17 @@
|
|||
<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>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ervu_lkrp_ul.ervu_lkrp_ul</groupId>
|
||||
<groupId>ru.micord.ervu.lkrp.ul</groupId>
|
||||
<artifactId>resources</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
|
@ -107,30 +111,6 @@
|
|||
<groupId>ru.cg.webbpm.modules</groupId>
|
||||
<artifactId>inject</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.cg.webbpm.modules.bpmn</groupId>
|
||||
<artifactId>bpmn-workflow-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.cg.webbpm.modules.bpmn</groupId>
|
||||
<artifactId>bpmn-workflow-jbpm-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.cg.webbpm.modules.bpmn</groupId>
|
||||
<artifactId>bpmn-workflow-jbpm</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.cg.webbpm.modules.bpmn</groupId>
|
||||
<artifactId>bpmn-beans</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.cg.webbpm.modules.bpmn</groupId>
|
||||
<artifactId>bpmn-variable-condition-adapter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.cg.webbpm.modules.bpmn</groupId>
|
||||
<artifactId>bpmn-deploy</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.cg.webbpm.modules</groupId>
|
||||
<artifactId>webkit-rpc</artifactId>
|
||||
|
|
@ -184,22 +164,6 @@
|
|||
<groupId>ru.cg.webbpm.modules.core</groupId>
|
||||
<artifactId>metrics</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.cg.webbpm.modules.webkit</groupId>
|
||||
<artifactId>active-users-tracker</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.cg.webbpm.modules.security</groupId>
|
||||
<artifactId>security-beans</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.cg.webbpm.modules.security</groupId>
|
||||
<artifactId>security-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.cg.webbpm.modules.security</groupId>
|
||||
<artifactId>security-esia</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.cg.webbpm.modules.reporting</groupId>
|
||||
<artifactId>reporting-api</artifactId>
|
||||
|
|
@ -236,14 +200,6 @@
|
|||
<groupId>ru.cg.webbpm.modules</groupId>
|
||||
<artifactId>webkit-base</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.cg.webbpm.modules.security</groupId>
|
||||
<artifactId>security-db-synchronization-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.cg.webbpm.modules.security</groupId>
|
||||
<artifactId>security-db-synchronization-ldap-impl</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>xerces</groupId>
|
||||
<artifactId>xercesImpl</artifactId>
|
||||
|
|
@ -260,14 +216,6 @@
|
|||
<groupId>org.apache.tika</groupId>
|
||||
<artifactId>tika-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security.kerberos</groupId>
|
||||
<artifactId>spring-security-kerberos-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security.kerberos</groupId>
|
||||
<artifactId>spring-security-kerberos-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcprov-jdk15on</artifactId>
|
||||
|
|
@ -294,6 +242,7 @@
|
|||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<finalName>${parent.artifactId}</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
|
|
@ -327,16 +276,6 @@
|
|||
<profiles>
|
||||
<profile>
|
||||
<id>studio</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
<configuration>
|
||||
<warName>${project.artifactId}</warName>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>ru.cg.webbpm.modules.resources</groupId>
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import org.springframework.context.annotation.Bean;
|
|||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.EnableAspectJAutoProxy;
|
||||
import org.springframework.context.annotation.FilterType;
|
||||
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
|
||||
import org.springframework.retry.annotation.EnableRetry;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
|
|
@ -31,13 +32,12 @@ import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
|||
"i18n",
|
||||
"errorhandling",
|
||||
"database",
|
||||
"security",
|
||||
"component.addresses",
|
||||
"gen",
|
||||
"ru.cg",
|
||||
"ru.micord",
|
||||
"ervu",
|
||||
"esia"
|
||||
"ru.micord"
|
||||
}, excludeFilters = {
|
||||
@ComponentScan.Filter(type = FilterType.REGEX, pattern = "security.WebSecurityConfig")
|
||||
})
|
||||
@EnableAspectJAutoProxy(proxyTargetClass = true)
|
||||
@EnableWebMvc
|
||||
|
|
|
|||
|
|
@ -1,34 +0,0 @@
|
|||
package controller;
|
||||
|
||||
import dto.jivoprofile.JivoProfileDto;
|
||||
import org.hsqldb.lib.StringUtil;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import ru.cg.webbpm.modules.security.api.model.User;
|
||||
import ru.cg.webbpm.modules.security.api.service.UserService;
|
||||
|
||||
@RestController
|
||||
public class ProfileController {
|
||||
|
||||
private UserService userService;
|
||||
|
||||
public ProfileController(UserService userService) {
|
||||
this.userService = userService;
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/profile/jivo/{userId}", method = RequestMethod.GET)
|
||||
public JivoProfileDto profile(@PathVariable("userId") String userId) {
|
||||
|
||||
if (StringUtil.isEmpty(userId)) {
|
||||
return new JivoProfileDto();
|
||||
}
|
||||
|
||||
User user = userService.get(userId);
|
||||
|
||||
JivoProfileDto profileDto = new JivoProfileDto();
|
||||
profileDto.setUsername(user.firstName());
|
||||
profileDto.setEmail(user.email());
|
||||
profileDto.setPhone(user.phone());
|
||||
return profileDto;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +1,10 @@
|
|||
package ervu.service.fileupload;
|
||||
|
||||
import ervu.service.fileupload.model.*;
|
||||
import esia.model.MillitaryRegistrationPersonModel;
|
||||
import esia.model.OrganizationModel;
|
||||
import esia.service.UlDataService;
|
||||
import ervu.service.fileupload.model.EmployeeInfoKafkaMessage;
|
||||
import ervu.service.fileupload.model.FileInfo;
|
||||
import ervu.service.fileupload.model.OrgInfo;
|
||||
import ervu.service.fileupload.model.SenderInfo;
|
||||
import ru.micord.ervu.security.esia.service.UlDataService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
|
|
@ -31,35 +32,38 @@ public class EmployeeInfoKafkaMessageService {
|
|||
);
|
||||
}
|
||||
|
||||
//TODO: refactor SUPPORT-8381
|
||||
private OrgInfo getOrgInfo() {
|
||||
OrganizationModel organizationModel = ulDataService.getOrganizationModel();
|
||||
return new OrgInfo(
|
||||
organizationModel.getShortName(),
|
||||
organizationModel.getLeg(),
|
||||
organizationModel.getLegName(),
|
||||
organizationModel.getOgrn(),
|
||||
organizationModel.getInn(),
|
||||
organizationModel.getKpp()
|
||||
);
|
||||
// OrganizationModel organizationModel = ulDataService.getOrganizationModel();
|
||||
// return new OrgInfo(
|
||||
// organizationModel.getShortName(),
|
||||
// organizationModel.getLeg(),
|
||||
// organizationModel.getLegName(),
|
||||
// organizationModel.getOgrn(),
|
||||
// organizationModel.getInn(),
|
||||
// organizationModel.getKpp()
|
||||
// );
|
||||
return null;
|
||||
}
|
||||
|
||||
private SenderInfo getSenderInfo() {
|
||||
MillitaryRegistrationPersonModel personModel = ulDataService.getPersonModel();
|
||||
return new SenderInfo(
|
||||
personModel.getLastName(),
|
||||
personModel.getFirstName(),
|
||||
personModel.getMiddleName(),
|
||||
personModel.getBirthday(),
|
||||
personModel.getRoleCode(),
|
||||
personModel.getRoleName(),
|
||||
personModel.getSnils(),
|
||||
personModel.getIdERN(),
|
||||
new PassportInfo(
|
||||
personModel.getPassportSeries(),
|
||||
personModel.getPassportNumber(),
|
||||
personModel.getPassportIssueDate()
|
||||
)
|
||||
);
|
||||
// MillitaryRegistrationPersonModel personModel = ulDataService.getPersonModel();
|
||||
// return new SenderInfo(
|
||||
// personModel.getLastName(),
|
||||
// personModel.getFirstName(),
|
||||
// personModel.getMiddleName(),
|
||||
// personModel.getBirthday(),
|
||||
// personModel.getRoleCode(),
|
||||
// personModel.getRoleName(),
|
||||
// personModel.getSnils(),
|
||||
// personModel.getIdERN(),
|
||||
// new PassportInfo(
|
||||
// personModel.getPassportSeries(),
|
||||
// personModel.getPassportNumber(),
|
||||
// personModel.getPassportIssueDate()
|
||||
// )
|
||||
// );
|
||||
return null;
|
||||
}
|
||||
|
||||
private FileInfo getFileInfo(String fileNameBase, String fileName,
|
||||
|
|
|
|||
|
|
@ -1,31 +0,0 @@
|
|||
package esia.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author Eduard Tihomirov
|
||||
*/
|
||||
public class ChiefPersonModel extends PersonModel {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String position;
|
||||
|
||||
private String brhOid;
|
||||
|
||||
public String getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
public void setPosition(String position) {
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
public String getBrhOid() {
|
||||
return brhOid;
|
||||
}
|
||||
|
||||
public void setBrhOid(String brhOid) {
|
||||
this.brhOid = brhOid;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
package esia.model;
|
||||
|
||||
/**
|
||||
* @author Eduard Tihomirov
|
||||
*/
|
||||
public class MillitaryRegistrationPersonModel extends PersonModel {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String email;
|
||||
|
||||
private String mobileNumber;
|
||||
private String roleCode;
|
||||
private String roleName;
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public String getMobileNumber() {
|
||||
return mobileNumber;
|
||||
}
|
||||
|
||||
public void setMobileNumber(String mobileNumber) {
|
||||
this.mobileNumber = mobileNumber;
|
||||
}
|
||||
|
||||
public String getRoleCode() {
|
||||
return roleCode;
|
||||
}
|
||||
|
||||
public void setRoleCode(String roleCode) {
|
||||
this.roleCode = roleCode;
|
||||
}
|
||||
|
||||
public String getRoleName() {
|
||||
return roleName;
|
||||
}
|
||||
|
||||
public void setRoleName(String roleName) {
|
||||
this.roleName = roleName;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,140 +0,0 @@
|
|||
package esia.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author Eduard Tihomirov
|
||||
*/
|
||||
public class OrganizationModel implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String orgOid;
|
||||
|
||||
private String fullName;
|
||||
|
||||
private String shortName;
|
||||
|
||||
private String inn;
|
||||
|
||||
private String ogrn;
|
||||
|
||||
private String leg;
|
||||
private String legName;
|
||||
|
||||
private String kpp;
|
||||
|
||||
private String ulAddress;
|
||||
|
||||
private String actualAddress;
|
||||
|
||||
private String zipCode;
|
||||
|
||||
private String mobile;
|
||||
|
||||
private String email;
|
||||
|
||||
public String getOrgOid() {
|
||||
return orgOid;
|
||||
}
|
||||
|
||||
public void setOrgOid(String orgOid) {
|
||||
this.orgOid = orgOid;
|
||||
}
|
||||
|
||||
public String getFullName() {
|
||||
return fullName;
|
||||
}
|
||||
|
||||
public void setFullName(String fullName) {
|
||||
this.fullName = fullName;
|
||||
}
|
||||
|
||||
public String getShortName() {
|
||||
return shortName;
|
||||
}
|
||||
|
||||
public void setShortName(String shortName) {
|
||||
this.shortName = shortName;
|
||||
}
|
||||
|
||||
public String getInn() {
|
||||
return inn;
|
||||
}
|
||||
|
||||
public void setInn(String inn) {
|
||||
this.inn = inn;
|
||||
}
|
||||
|
||||
public String getOgrn() {
|
||||
return ogrn;
|
||||
}
|
||||
|
||||
public void setOgrn(String ogrn) {
|
||||
this.ogrn = ogrn;
|
||||
}
|
||||
|
||||
public String getLeg() {
|
||||
return leg;
|
||||
}
|
||||
|
||||
public void setLeg(String leg) {
|
||||
this.leg = leg;
|
||||
}
|
||||
|
||||
public String getKpp() {
|
||||
return kpp;
|
||||
}
|
||||
|
||||
public void setKpp(String kpp) {
|
||||
this.kpp = kpp;
|
||||
}
|
||||
|
||||
public String getUlAddress() {
|
||||
return ulAddress;
|
||||
}
|
||||
|
||||
public void setUlAddress(String ulAddress) {
|
||||
this.ulAddress = ulAddress;
|
||||
}
|
||||
|
||||
public String getActualAddress() {
|
||||
return actualAddress;
|
||||
}
|
||||
|
||||
public void setActualAddress(String actualAddress) {
|
||||
this.actualAddress = actualAddress;
|
||||
}
|
||||
|
||||
public String getZipCode() {
|
||||
return zipCode;
|
||||
}
|
||||
|
||||
public void setZipCode(String zipCode) {
|
||||
this.zipCode = zipCode;
|
||||
}
|
||||
|
||||
public String getMobile() {
|
||||
return mobile;
|
||||
}
|
||||
|
||||
public void setMobile(String mobile) {
|
||||
this.mobile = mobile;
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public String getLegName() {
|
||||
return legName;
|
||||
}
|
||||
|
||||
public void setLegName(String legName) {
|
||||
this.legName = legName;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,115 +0,0 @@
|
|||
package esia.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author Eduard Tihomirov
|
||||
*/
|
||||
public class PersonModel implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String prsId;
|
||||
|
||||
private String orgOid;
|
||||
|
||||
private String lastName;
|
||||
|
||||
private String firstName;
|
||||
|
||||
private String middleName;
|
||||
private String birthday;
|
||||
private String snils;
|
||||
private String idERN;
|
||||
private String passportSeries;
|
||||
private String passportNumber;
|
||||
private String passportIssueDate;
|
||||
|
||||
public String getPrsId() {
|
||||
return prsId;
|
||||
}
|
||||
|
||||
public void setPrsId(String prsId) {
|
||||
this.prsId = prsId;
|
||||
}
|
||||
|
||||
public String getOrgOid() {
|
||||
return orgOid;
|
||||
}
|
||||
|
||||
public void setOrgOid(String orgOid) {
|
||||
this.orgOid = orgOid;
|
||||
}
|
||||
|
||||
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 getBirthday() {
|
||||
return birthday;
|
||||
}
|
||||
|
||||
public void setBirthday(String birthday) {
|
||||
this.birthday = birthday;
|
||||
}
|
||||
|
||||
public String getSnils() {
|
||||
return snils;
|
||||
}
|
||||
|
||||
public void setSnils(String snils) {
|
||||
this.snils = snils;
|
||||
}
|
||||
|
||||
public String getIdERN() {
|
||||
return idERN;
|
||||
}
|
||||
|
||||
public void setIdERN(String idERN) {
|
||||
this.idERN = idERN;
|
||||
}
|
||||
|
||||
public String getPassportSeries() {
|
||||
return passportSeries;
|
||||
}
|
||||
|
||||
public void setPassportSeries(String passportSeries) {
|
||||
this.passportSeries = passportSeries;
|
||||
}
|
||||
|
||||
public String getPassportNumber() {
|
||||
return passportNumber;
|
||||
}
|
||||
|
||||
public void setPassportNumber(String passportNumber) {
|
||||
this.passportNumber = passportNumber;
|
||||
}
|
||||
|
||||
public String getPassportIssueDate() {
|
||||
return passportIssueDate;
|
||||
}
|
||||
|
||||
public void setPassportIssueDate(String passportIssueDate) {
|
||||
this.passportIssueDate = passportIssueDate;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
package esia.service;
|
||||
|
||||
import esia.model.ChiefPersonModel;
|
||||
import esia.model.MillitaryRegistrationPersonModel;
|
||||
import esia.model.OrganizationModel;
|
||||
|
||||
/**
|
||||
* @author Eduard Tihomirov
|
||||
*/
|
||||
public interface UlDataService {
|
||||
|
||||
MillitaryRegistrationPersonModel getPersonModel();
|
||||
|
||||
ChiefPersonModel getChiefPersonModel();
|
||||
|
||||
OrganizationModel getOrganizationModel();
|
||||
}
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
package esia.service.impl;
|
||||
|
||||
import esia.model.ChiefPersonModel;
|
||||
import esia.model.MillitaryRegistrationPersonModel;
|
||||
import esia.model.OrganizationModel;
|
||||
import esia.service.UlDataService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* @author Alexandr Shalaginov
|
||||
*/
|
||||
// TODO: 22.07.2024 delete this after real realisation of UlDataService
|
||||
@Service
|
||||
public class DummyUlDataServiceImpl implements UlDataService {
|
||||
@Override
|
||||
public MillitaryRegistrationPersonModel getPersonModel() {
|
||||
MillitaryRegistrationPersonModel personModel = new MillitaryRegistrationPersonModel();
|
||||
personModel.setPrsId("PrsId");
|
||||
personModel.setOrgOid("OrgOid");
|
||||
personModel.setLastName("Максимов");
|
||||
personModel.setFirstName("Геннадий");
|
||||
personModel.setMiddleName("Валентинович");
|
||||
personModel.setBirthday("18.11.1966");
|
||||
personModel.setSnils("56114152149");
|
||||
personModel.setIdERN("111666898287");
|
||||
personModel.setPassportSeries("1151");
|
||||
personModel.setPassportNumber("166971");
|
||||
personModel.setPassportIssueDate("13.10.2004");
|
||||
personModel.setEmail("Email");
|
||||
personModel.setMobileNumber("");
|
||||
personModel.setRoleCode("admin_123");
|
||||
personModel.setRoleName("Администратор 123");
|
||||
return personModel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChiefPersonModel getChiefPersonModel() {
|
||||
return new ChiefPersonModel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public OrganizationModel getOrganizationModel() {
|
||||
OrganizationModel organizationModel = new OrganizationModel();
|
||||
organizationModel.setOrgOid("OrgOid");
|
||||
organizationModel.setFullName("FullName");
|
||||
organizationModel.setShortName("Звезда");
|
||||
organizationModel.setInn("123456789012");
|
||||
organizationModel.setOgrn("1234567890123");
|
||||
organizationModel.setLeg("2");
|
||||
organizationModel.setLegName("Общество с ограниченной ответственностью");
|
||||
organizationModel.setKpp("123456789012");
|
||||
organizationModel.setUlAddress("UlAddress");
|
||||
organizationModel.setActualAddress("ActualAddress");
|
||||
organizationModel.setZipCode("ZipCode");
|
||||
organizationModel.setMobile("Mobile");
|
||||
organizationModel.setEmail("Email");
|
||||
return organizationModel;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
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:#{null}}")
|
||||
private String esiaScopes;
|
||||
|
||||
@Value("${esia-org-scopes:#{null}}")
|
||||
private String esiaOrgScopes;
|
||||
|
||||
@Value("${esia-org-scope-url:#{null}}")
|
||||
private String orgScopeUrl;
|
||||
|
||||
@Value("${esia-uri.base-uri:#{null}}")
|
||||
private String esiaBaseUri;
|
||||
|
||||
@Value("${esia-uri.code-path:#{null}}")
|
||||
private String esiaCodePath;
|
||||
|
||||
@Value("${esia-uri.token-path:#{null}}")
|
||||
private String esiaTokenPath;
|
||||
|
||||
@Value("${esia-client-id:#{null}}")
|
||||
private String clientId;
|
||||
|
||||
@Value("${esia-redirect-url:#{null}}")
|
||||
private String redirectUrl;
|
||||
|
||||
@Value("${sign-url:#{null}}")
|
||||
private String signUrl;
|
||||
|
||||
@Value("${esia-uri.logout:#{null}}")
|
||||
private String logoutUrl;
|
||||
|
||||
@Value("${client-cert-hash:#{null}}")
|
||||
private String clientCertHash;
|
||||
|
||||
@Value("${esia.request-timeout:60}")
|
||||
private long requestTimeout;
|
||||
|
||||
@Value("${esia.connection-timeout:30}")
|
||||
private long connectionTimeout;
|
||||
|
||||
public String getEsiaCodeUri() {
|
||||
return esiaCodePath;
|
||||
}
|
||||
|
||||
public String getEsiaTokenUri() {
|
||||
return esiaTokenPath;
|
||||
}
|
||||
|
||||
public String getEsiaOrgScopes() {
|
||||
String[] scopeItems = esiaOrgScopes.split(",");
|
||||
return String.join(" ", Arrays.stream(scopeItems).map(item -> orgScopeUrl + item.trim()).toArray(String[]::new));
|
||||
}
|
||||
|
||||
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 getLogoutUrl() {
|
||||
return logoutUrl;
|
||||
}
|
||||
|
||||
public String getClientCertHash() {return clientCertHash;}
|
||||
|
||||
public long getRequestTimeout() {
|
||||
return requestTimeout;
|
||||
}
|
||||
|
||||
public long getConnectionTimeout() {
|
||||
return connectionTimeout;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
package ru.micord.ervu.security.esia.controller;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import ru.micord.ervu.security.esia.model.OrgInfoModel;
|
||||
import ru.micord.ervu.security.esia.service.EsiaAuthService;
|
||||
import ru.micord.ervu.security.esia.service.EsiaDataService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* @author Eduard Tihomirov
|
||||
*/
|
||||
@RestController
|
||||
public class EsiaController {
|
||||
|
||||
@Autowired
|
||||
private EsiaAuthService esiaAuthService;
|
||||
|
||||
@Autowired
|
||||
private EsiaDataService esiaDataService;
|
||||
|
||||
@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, HttpServletResponse response) {
|
||||
return esiaAuthService.getEsiaTokensByCode(code, response);
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/esia/refresh")
|
||||
public void refreshToken(HttpServletRequest request, HttpServletResponse response) {
|
||||
esiaAuthService.getEsiaTokensByRefreshToken(request, response);
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/esia/org")
|
||||
public OrgInfoModel getOrgInfo(HttpServletRequest request) {
|
||||
return esiaDataService.getOrgInfo(request);
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/esia/userfullname")
|
||||
public String getUserFullname(HttpServletRequest request) {
|
||||
return esiaDataService.getUserFullname(request);
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/esia/orgunitname")
|
||||
public String getOrgUnitName(HttpServletRequest request) {
|
||||
return esiaDataService.getOrgUnitName(request);
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/esia/logout")
|
||||
public String logout(HttpServletRequest request, HttpServletResponse response) {
|
||||
return esiaAuthService.logout(request, response);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,134 @@
|
|||
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 AddressModel implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String type;
|
||||
|
||||
private String zipCode;
|
||||
|
||||
private String countryId;
|
||||
|
||||
private String addressStr;
|
||||
|
||||
private String region;
|
||||
|
||||
private String city;
|
||||
|
||||
private String street;
|
||||
|
||||
private String house;
|
||||
|
||||
private String building;
|
||||
|
||||
private String frame;
|
||||
|
||||
private String flat;
|
||||
|
||||
private String fiasCode;
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getZipCode() {
|
||||
return zipCode;
|
||||
}
|
||||
|
||||
public void setZipCode(String zipCode) {
|
||||
this.zipCode = zipCode;
|
||||
}
|
||||
|
||||
public String getCountryId() {
|
||||
return countryId;
|
||||
}
|
||||
|
||||
public void setCountryId(String countryId) {
|
||||
this.countryId = countryId;
|
||||
}
|
||||
|
||||
public String getAddressStr() {
|
||||
return addressStr;
|
||||
}
|
||||
|
||||
public void setAddressStr(String addressStr) {
|
||||
this.addressStr = addressStr;
|
||||
}
|
||||
|
||||
public String getRegion() {
|
||||
return region;
|
||||
}
|
||||
|
||||
public void setRegion(String region) {
|
||||
this.region = region;
|
||||
}
|
||||
|
||||
public String getCity() {
|
||||
return city;
|
||||
}
|
||||
|
||||
public void setCity(String city) {
|
||||
this.city = city;
|
||||
}
|
||||
|
||||
public String getStreet() {
|
||||
return street;
|
||||
}
|
||||
|
||||
public void setStreet(String street) {
|
||||
this.street = street;
|
||||
}
|
||||
|
||||
public String getHouse() {
|
||||
return house;
|
||||
}
|
||||
|
||||
public void setHouse(String house) {
|
||||
this.house = house;
|
||||
}
|
||||
|
||||
public String getBuilding() {
|
||||
return building;
|
||||
}
|
||||
|
||||
public void setBuilding(String building) {
|
||||
this.building = building;
|
||||
}
|
||||
|
||||
public String getFrame() {
|
||||
return frame;
|
||||
}
|
||||
|
||||
public void setFrame(String frame) {
|
||||
this.frame = frame;
|
||||
}
|
||||
|
||||
public String getFlat() {
|
||||
return flat;
|
||||
}
|
||||
|
||||
public void setFlat(String flat) {
|
||||
this.flat = flat;
|
||||
}
|
||||
|
||||
public String getFiasCode() {
|
||||
return fiasCode;
|
||||
}
|
||||
|
||||
public void setFiasCode(String fiasCode) {
|
||||
this.fiasCode = fiasCode;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
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 Addresses implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private AddressModel[] elements;
|
||||
|
||||
public AddressModel[] getElements() {
|
||||
return elements;
|
||||
}
|
||||
|
||||
public void setElements(AddressModel[] elements) {
|
||||
this.elements = elements;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
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 BrhsModel implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String brhOid;
|
||||
|
||||
private String name;
|
||||
|
||||
private String kpp;
|
||||
|
||||
private String leg;
|
||||
|
||||
private Addresses addresses;
|
||||
|
||||
private Contacts contacts;
|
||||
|
||||
public String getBrhOid() {
|
||||
return brhOid;
|
||||
}
|
||||
|
||||
public void setBrhOid(String brhOid) {
|
||||
this.brhOid = brhOid;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getKpp() {
|
||||
return kpp;
|
||||
}
|
||||
|
||||
public void setKpp(String kpp) {
|
||||
this.kpp = kpp;
|
||||
}
|
||||
|
||||
public String getLeg() {
|
||||
return leg;
|
||||
}
|
||||
|
||||
public void setLeg(String leg) {
|
||||
this.leg = leg;
|
||||
}
|
||||
|
||||
public Addresses getAddresses() {
|
||||
return addresses;
|
||||
}
|
||||
|
||||
public void setAddresses(Addresses addresses) {
|
||||
this.addresses = addresses;
|
||||
}
|
||||
|
||||
public Contacts getContacts() {
|
||||
return contacts;
|
||||
}
|
||||
|
||||
public void setContacts(Contacts contacts) {
|
||||
this.contacts = contacts;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
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 ContactModel implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String type;
|
||||
|
||||
private String value;
|
||||
|
||||
private String vrfStu;
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getVrfStu() {
|
||||
return vrfStu;
|
||||
}
|
||||
|
||||
public void setVrfStu(String vrfStu) {
|
||||
this.vrfStu = vrfStu;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
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 Contacts implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private ContactModel[] elements;
|
||||
|
||||
public ContactModel[] getElements() {
|
||||
return elements;
|
||||
}
|
||||
|
||||
public void setElements(ContactModel[] elements) {
|
||||
this.elements = elements;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
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 EmployeeModel implements Serializable {
|
||||
|
||||
private String prnOid;
|
||||
|
||||
private String orgOid;
|
||||
|
||||
private Boolean chief;
|
||||
|
||||
private Boolean blocked;
|
||||
|
||||
private String position;
|
||||
|
||||
private PersonModel person;
|
||||
|
||||
public String getPrnOid() {
|
||||
return prnOid;
|
||||
}
|
||||
|
||||
public void setPrnOid(String prnOid) {
|
||||
this.prnOid = prnOid;
|
||||
}
|
||||
|
||||
public String getOrgOid() {
|
||||
return orgOid;
|
||||
}
|
||||
|
||||
public void setOrgOid(String orgOid) {
|
||||
this.orgOid = orgOid;
|
||||
}
|
||||
|
||||
public Boolean getChief() {
|
||||
return chief;
|
||||
}
|
||||
|
||||
public void setChief(Boolean chief) {
|
||||
this.chief = chief;
|
||||
}
|
||||
|
||||
public Boolean getBlocked() {
|
||||
return blocked;
|
||||
}
|
||||
|
||||
public void setBlocked(Boolean blocked) {
|
||||
this.blocked = blocked;
|
||||
}
|
||||
|
||||
public String getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
public void setPosition(String position) {
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
public PersonModel getPerson() {
|
||||
return person;
|
||||
}
|
||||
|
||||
public void setPerson(PersonModel person) {
|
||||
this.person = person;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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 OrgInfoModel {
|
||||
public String empFullname;
|
||||
public String fullName;
|
||||
public String shortName;
|
||||
public String olgAddress;
|
||||
public String opsAddress;
|
||||
public String chiefFullname;
|
||||
public String chiefPosition;
|
||||
public String ogrn;
|
||||
public String kpp;
|
||||
public String inn;
|
||||
public String empPosition;
|
||||
public String mobile;
|
||||
public String email;
|
||||
public String userRoles;
|
||||
}
|
||||
|
|
@ -0,0 +1,174 @@
|
|||
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 OrganizationModel implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String oid;
|
||||
|
||||
private String fullName;
|
||||
|
||||
private String shortName;
|
||||
|
||||
private String type;
|
||||
|
||||
private String inn;
|
||||
|
||||
private String ogrn;
|
||||
|
||||
private String leg;
|
||||
|
||||
private String kpp;
|
||||
|
||||
private Addresses addresses;
|
||||
|
||||
private Contacts contacts;
|
||||
|
||||
private Long staffCount;
|
||||
|
||||
private Long branchesCount;
|
||||
|
||||
private BrhsModel[] brhs;
|
||||
|
||||
private Boolean isLiquidated;
|
||||
|
||||
private String agencyTerRange;
|
||||
|
||||
private String agencyType;
|
||||
|
||||
public String getOid() {
|
||||
return oid;
|
||||
}
|
||||
|
||||
public void setOid(String oid) {
|
||||
this.oid = oid;
|
||||
}
|
||||
|
||||
public String getFullName() {
|
||||
return fullName;
|
||||
}
|
||||
|
||||
public void setFullName(String fullName) {
|
||||
this.fullName = fullName;
|
||||
}
|
||||
|
||||
public String getShortName() {
|
||||
return shortName;
|
||||
}
|
||||
|
||||
public void setShortName(String shortName) {
|
||||
this.shortName = shortName;
|
||||
}
|
||||
|
||||
public String getInn() {
|
||||
return inn;
|
||||
}
|
||||
|
||||
public void setInn(String inn) {
|
||||
this.inn = inn;
|
||||
}
|
||||
|
||||
public String getOgrn() {
|
||||
return ogrn;
|
||||
}
|
||||
|
||||
public void setOgrn(String ogrn) {
|
||||
this.ogrn = ogrn;
|
||||
}
|
||||
|
||||
public String getLeg() {
|
||||
return leg;
|
||||
}
|
||||
|
||||
public void setLeg(String leg) {
|
||||
this.leg = leg;
|
||||
}
|
||||
|
||||
public String getKpp() {
|
||||
return kpp;
|
||||
}
|
||||
|
||||
public void setKpp(String kpp) {
|
||||
this.kpp = kpp;
|
||||
}
|
||||
|
||||
public Addresses getAddresses() {
|
||||
return addresses;
|
||||
}
|
||||
|
||||
public void setAddresses(Addresses addresses) {
|
||||
this.addresses = addresses;
|
||||
}
|
||||
|
||||
public Contacts getContacts() {
|
||||
return contacts;
|
||||
}
|
||||
|
||||
public void setContacts(Contacts contacts) {
|
||||
this.contacts = contacts;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public Long getStaffCount() {
|
||||
return staffCount;
|
||||
}
|
||||
|
||||
public void setStaffCount(Long staffCount) {
|
||||
this.staffCount = staffCount;
|
||||
}
|
||||
|
||||
public Long getBranchesCount() {
|
||||
return branchesCount;
|
||||
}
|
||||
|
||||
public void setBranchesCount(Long branchesCount) {
|
||||
this.branchesCount = branchesCount;
|
||||
}
|
||||
|
||||
public BrhsModel[] getBrhs() {
|
||||
return brhs;
|
||||
}
|
||||
|
||||
public void setBrhs(BrhsModel[] brhs) {
|
||||
this.brhs = brhs;
|
||||
}
|
||||
|
||||
public Boolean getIsLiquidated() {
|
||||
return isLiquidated;
|
||||
}
|
||||
|
||||
public void setIsLiquidated(Boolean liquidated) {
|
||||
isLiquidated = liquidated;
|
||||
}
|
||||
|
||||
public String getAgencyTerRange() {
|
||||
return agencyTerRange;
|
||||
}
|
||||
|
||||
public void setAgencyTerRange(String agencyTerRange) {
|
||||
this.agencyTerRange = agencyTerRange;
|
||||
}
|
||||
|
||||
public String getAgencyType() {
|
||||
return agencyType;
|
||||
}
|
||||
|
||||
public void setAgencyType(String agencyType) {
|
||||
this.agencyType = agencyType;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
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;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
|
||||
import org.springframework.data.elasticsearch.annotations.DateFormat;
|
||||
import org.springframework.data.elasticsearch.annotations.Field;
|
||||
import org.springframework.data.elasticsearch.annotations.FieldType;
|
||||
|
||||
/**
|
||||
* @author Eduard Tihomirov
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class PassportModel implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String series;
|
||||
|
||||
private String number;
|
||||
|
||||
@Field(type = FieldType.Date, store = true, format = DateFormat.basic_date)
|
||||
@JsonSerialize(using = LocalDateSerializer.class)
|
||||
@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;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
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 orgOid;
|
||||
|
||||
private String lastName;
|
||||
|
||||
private String firstName;
|
||||
|
||||
private String middleName;
|
||||
|
||||
@JsonFormat(pattern = "dd.MM.yyyy")
|
||||
private Date birthDate;
|
||||
|
||||
private String gender;
|
||||
|
||||
private String citizenship;
|
||||
|
||||
private String snils;
|
||||
|
||||
private String inn;
|
||||
|
||||
private String birthPlace;
|
||||
|
||||
//Данные не доступны при входе юр лицом
|
||||
private String email;
|
||||
|
||||
//Данные не доступны при входе юр лицом
|
||||
private String mobileNumber;
|
||||
|
||||
public String getOrgOid() {
|
||||
return orgOid;
|
||||
}
|
||||
|
||||
public void setOrgOid(String orgOid) {
|
||||
this.orgOid = orgOid;
|
||||
}
|
||||
|
||||
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 getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public String getMobileNumber() {
|
||||
return mobileNumber;
|
||||
}
|
||||
|
||||
public void setMobileNumber(String mobileNumber) {
|
||||
this.mobileNumber = mobileNumber;
|
||||
}
|
||||
|
||||
public Date getBirthDate() {
|
||||
return birthDate;
|
||||
}
|
||||
|
||||
public void setBirthDate(Date birthDate) {
|
||||
this.birthDate = birthDate;
|
||||
}
|
||||
|
||||
public String getGender() {
|
||||
return gender;
|
||||
}
|
||||
|
||||
public void setGender(String gender) {
|
||||
this.gender = gender;
|
||||
}
|
||||
|
||||
public String getCitizenship() {
|
||||
return citizenship;
|
||||
}
|
||||
|
||||
public void setCitizenship(String citizenship) {
|
||||
this.citizenship = citizenship;
|
||||
}
|
||||
|
||||
public String getSnils() {
|
||||
return snils;
|
||||
}
|
||||
|
||||
public void setSnils(String snils) {
|
||||
this.snils = snils;
|
||||
}
|
||||
|
||||
public String getInn() {
|
||||
return inn;
|
||||
}
|
||||
|
||||
public void setInn(String inn) {
|
||||
this.inn = inn;
|
||||
}
|
||||
|
||||
public String getBirthPlace() {
|
||||
return birthPlace;
|
||||
}
|
||||
|
||||
public void setBirthPlace(String birthPlace) {
|
||||
this.birthPlace = birthPlace;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,360 @@
|
|||
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.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 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 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 {
|
||||
|
||||
@Autowired
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
@Autowired
|
||||
private EsiaConfig esiaConfig;
|
||||
|
||||
@Autowired
|
||||
private UlDataService ulDataService;
|
||||
|
||||
@Autowired
|
||||
private JwtTokenService jwtTokenService;
|
||||
|
||||
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();
|
||||
String scopeOrg = esiaConfig.getEsiaOrgScopes();
|
||||
|
||||
Map<String, String> parameters = new LinkedHashMap<String, String>();
|
||||
parameters.put("client_id", clientId);
|
||||
parameters.put("scope", scope);
|
||||
parameters.put("scope_org", scopeOrg);
|
||||
parameters.put("timestamp", timestamp);
|
||||
parameters.put("state", state);
|
||||
parameters.put("redirect_uri", esiaConfig.getRedirectUrl());
|
||||
|
||||
String clientSecret = signMap(parameters);
|
||||
|
||||
String responseType = "code";
|
||||
|
||||
String authUrl = esiaConfig.getEsiaCodeUri();
|
||||
|
||||
URL url = new URL(authUrl);
|
||||
Map<String, String> params = mapOf("scope", scope,
|
||||
"scope_org", scopeOrg.replaceAll(":", "%3A")
|
||||
.replaceAll("/", "%2F"),
|
||||
"timestamp", urlEncode(timestamp),
|
||||
"state", state,
|
||||
"client_id", clientId,
|
||||
"client_secret", clientSecret,
|
||||
"response_type", responseType,
|
||||
"redirect_uri", redirectUrlEncoded,
|
||||
"obj_type", "B L F A",
|
||||
"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, 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();
|
||||
String scopeOrg = esiaConfig.getEsiaOrgScopes();
|
||||
|
||||
Map<String, String> parameters = new LinkedHashMap<String, String>();
|
||||
parameters.put("client_id", clientId);
|
||||
parameters.put("scope", scope);
|
||||
parameters.put("scope_org", scopeOrg);
|
||||
parameters.put("timestamp", timestamp);
|
||||
parameters.put("state", state);
|
||||
parameters.put("redirect_uri", redirectUrl);
|
||||
parameters.put("code", esiaAuthCode);
|
||||
|
||||
String clientSecret = signMap(parameters);
|
||||
String authUrl = esiaConfig.getEsiaTokenUri();
|
||||
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("scope_org", scopeOrg)
|
||||
.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();
|
||||
boolean hasRole = ulDataService.checkRole(accessToken);
|
||||
if (!hasRole) {
|
||||
throw new RuntimeException("The user does not have the required role");
|
||||
}
|
||||
Cookie cookie = new Cookie("access_token", accessToken);
|
||||
cookie.setHttpOnly(true);
|
||||
cookie.setPath("/");
|
||||
response.addCookie(cookie);
|
||||
|
||||
String refreshToken = tokenResponse.getRefresh_token();
|
||||
Cookie cookieRefresh = new Cookie("refresh_token", refreshToken);
|
||||
cookieRefresh.setHttpOnly(true);
|
||||
cookieRefresh.setPath("/");
|
||||
response.addCookie(cookieRefresh);
|
||||
|
||||
EsiaAccessToken esiaAccessToken = ulDataService.readToken(accessToken);
|
||||
Token token = jwtTokenService.createAccessToken(esiaAccessToken.getSbj_id(), tokenResponse.getExpires_in());
|
||||
Cookie authToken = new Cookie("auth_token", token.getValue());
|
||||
authToken.setPath("/");
|
||||
authToken.setHttpOnly(true);
|
||||
response.addCookie(authToken);
|
||||
SecurityContextHolder.getContext()
|
||||
.setAuthentication(
|
||||
new UsernamePasswordAuthenticationToken(esiaAccessToken.getSbj_id(), null));
|
||||
|
||||
Cookie isAuth = new Cookie("is_auth", "true");
|
||||
isAuth.setPath("/");
|
||||
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();
|
||||
String scope = esiaConfig.getEsiaScopes();
|
||||
String scopeOrg = esiaConfig.getEsiaOrgScopes();
|
||||
|
||||
Map<String, String> parameters = new LinkedHashMap<String, String>();
|
||||
parameters.put("client_id", clientId);
|
||||
parameters.put("scope", scope);
|
||||
parameters.put("scope_org", scopeOrg);
|
||||
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.getEsiaTokenUri();
|
||||
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", scope)
|
||||
.setParameter("scope_org", scopeOrg)
|
||||
.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);
|
||||
cookie.setPath("/");
|
||||
response.addCookie(cookie);
|
||||
|
||||
String newRefreshToken = tokenResponse.getRefresh_token();
|
||||
Cookie cookieRefresh = new Cookie("refresh_token", newRefreshToken);
|
||||
cookieRefresh.setHttpOnly(true);
|
||||
cookieRefresh.setPath("/");
|
||||
response.addCookie(cookieRefresh);
|
||||
EsiaAccessToken esiaAccessToken = ulDataService.readToken(accessToken);
|
||||
Token token = jwtTokenService.createAccessToken(esiaAccessToken.getSbj_id(), tokenResponse.getExpires_in());
|
||||
Cookie authToken = new Cookie("auth_token", token.getValue());
|
||||
authToken.setPath("/");
|
||||
authToken.setHttpOnly(true);
|
||||
response.addCookie(authToken);
|
||||
SecurityContextHolder.getContext()
|
||||
.setAuthentication(
|
||||
new UsernamePasswordAuthenticationToken(esiaAccessToken.getSbj_id(), null));
|
||||
|
||||
Cookie isAuth = new Cookie("is_auth", "true");
|
||||
isAuth.setPath("/");
|
||||
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.setPath("/");
|
||||
cookie.setMaxAge(0);
|
||||
response.addCookie(cookie);
|
||||
}
|
||||
}
|
||||
String logoutUrl = esiaConfig.getLogoutUrl();
|
||||
String redirectUrl = esiaConfig.getRedirectUrl();
|
||||
String redirectUrlEncoded = redirectUrl.replaceAll(":", "%3A")
|
||||
.replaceAll("/", "%2F");
|
||||
URL url = new URL(logoutUrl);
|
||||
Map<String, String> params = mapOf(
|
||||
"client_id", esiaConfig.getClientId(),
|
||||
"redirect_uri", redirectUrlEncoded);
|
||||
return makeRequest(url, params);
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
package ru.micord.ervu.security.esia.service;
|
||||
|
||||
import java.util.Arrays;
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import ru.micord.ervu.security.esia.model.*;
|
||||
|
||||
/**
|
||||
* @author Eduard Tihomirov
|
||||
*/
|
||||
@Service
|
||||
public class EsiaDataService {
|
||||
|
||||
@Autowired
|
||||
private UlDataService ulDataService;
|
||||
|
||||
public OrgInfoModel getOrgInfo(HttpServletRequest request) {
|
||||
String accessToken = getAccessToken(request);
|
||||
if (accessToken == null) {
|
||||
return null;
|
||||
}
|
||||
OrganizationModel organizationModel = ulDataService.getOrganizationModel(accessToken);
|
||||
EmployeeModel chiefEmployeeModel = ulDataService.getChiefEmployeeModel(accessToken);
|
||||
EmployeeModel employeeModel = ulDataService.getEmployeeModel(accessToken);
|
||||
OrgInfoModel orgInfoModel = new OrgInfoModel();
|
||||
|
||||
orgInfoModel.empFullname =
|
||||
employeeModel.getPerson().getLastName() + " " + employeeModel.getPerson().getFirstName()
|
||||
+ " " + employeeModel.getPerson().getMiddleName();
|
||||
orgInfoModel.empPosition = employeeModel.getPosition();
|
||||
orgInfoModel.fullName = organizationModel.getFullName();
|
||||
orgInfoModel.shortName = organizationModel.getShortName();
|
||||
Addresses addresses = organizationModel.getAddresses();
|
||||
if (addresses != null) {
|
||||
Arrays.stream(addresses.getElements()).forEach(addressModel -> {
|
||||
if (addressModel.getType().equals("OLG")) {
|
||||
orgInfoModel.olgAddress = addressModel.getAddressStr();
|
||||
}
|
||||
else if (addressModel.getType().equals("OPS")) {
|
||||
orgInfoModel.opsAddress = addressModel.getAddressStr();
|
||||
}
|
||||
} );
|
||||
}
|
||||
orgInfoModel.chiefFullname =
|
||||
chiefEmployeeModel.getPerson().getLastName() + " " + chiefEmployeeModel.getPerson()
|
||||
.getFirstName() + " " + chiefEmployeeModel.getPerson().getMiddleName();
|
||||
orgInfoModel.chiefPosition = chiefEmployeeModel.getPosition();
|
||||
orgInfoModel.ogrn = organizationModel.getOgrn();
|
||||
orgInfoModel.kpp = organizationModel.getKpp();
|
||||
orgInfoModel.inn = organizationModel.getInn();
|
||||
Contacts contacts = organizationModel.getContacts();
|
||||
if (contacts != null) {
|
||||
Arrays.stream(contacts.getElements()).forEach(contactModel -> {
|
||||
if (contactModel.getType().equals("OPH") && contactModel.getVrfStu().equals("VERIFIED")) {
|
||||
orgInfoModel.mobile = contactModel.getValue();
|
||||
}
|
||||
else if (contactModel.getType().equals("OEM") && contactModel.getVrfStu().equals("VERIFIED")) {
|
||||
orgInfoModel.email = contactModel.getValue();
|
||||
}
|
||||
} );
|
||||
}
|
||||
orgInfoModel.userRoles = ulDataService.getAllUserRoles(accessToken);
|
||||
return orgInfoModel;
|
||||
}
|
||||
|
||||
public String getOrgUnitName(HttpServletRequest request) {
|
||||
String accessToken = getAccessToken(request);
|
||||
if (accessToken == null) {
|
||||
return null;
|
||||
}
|
||||
OrganizationModel organizationModel = ulDataService.getOrganizationModel(accessToken);
|
||||
return organizationModel.getFullName();
|
||||
}
|
||||
|
||||
public String getUserFullname(HttpServletRequest request) {
|
||||
String accessToken = getAccessToken(request);
|
||||
if (accessToken == null) {
|
||||
return null;
|
||||
}
|
||||
EsiaAccessToken esiaAccessToken = ulDataService.readToken(accessToken);
|
||||
PersonModel personModel = ulDataService.getPersonData(esiaAccessToken.getSbj_id(), accessToken);
|
||||
return personModel.getLastName() + " " + personModel.getFirstName().charAt(0) + ". " + personModel.getMiddleName().charAt(0) + ".";
|
||||
}
|
||||
|
||||
private String getAccessToken(HttpServletRequest request) {
|
||||
Cookie[] cookies = request.getCookies();
|
||||
if (cookies != null) {
|
||||
for (Cookie cookie : cookies) {
|
||||
if (cookie.getName().equals("access_token")) {
|
||||
return cookie.getValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
package ru.micord.ervu.security.esia.service;
|
||||
|
||||
import ru.micord.ervu.security.esia.model.EmployeeModel;
|
||||
import ru.micord.ervu.security.esia.model.EsiaAccessToken;
|
||||
import ru.micord.ervu.security.esia.model.OrganizationModel;
|
||||
import ru.micord.ervu.security.esia.model.PersonModel;
|
||||
|
||||
/**
|
||||
* @author Eduard Tihomirov
|
||||
*/
|
||||
public interface UlDataService {
|
||||
|
||||
boolean checkRole(String accessToken);
|
||||
|
||||
EmployeeModel getEmployeeModel(String accessToken);
|
||||
|
||||
EmployeeModel getChiefEmployeeModel(String accessToken);
|
||||
|
||||
OrganizationModel getOrganizationModel(String accessToken);
|
||||
|
||||
PersonModel getPersonData(String prnsId, String accessToken);
|
||||
|
||||
EsiaAccessToken readToken(String accessToken);
|
||||
|
||||
String getAllUserRoles(String accessToken);
|
||||
}
|
||||
|
|
@ -0,0 +1,257 @@
|
|||
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.Arrays;
|
||||
import java.util.Base64;
|
||||
import java.util.Optional;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import ru.micord.ervu.security.esia.config.EsiaConfig;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.stereotype.Service;
|
||||
import ru.micord.ervu.security.esia.model.*;
|
||||
|
||||
/**
|
||||
* @author Eduard Tihomirov
|
||||
*/
|
||||
@Service
|
||||
public class UlDataServiceImpl implements UlDataService {
|
||||
|
||||
@Autowired
|
||||
private EsiaConfig esiaConfig;
|
||||
|
||||
@Autowired
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
@Override
|
||||
public EmployeeModel getEmployeeModel(String accessToken) {
|
||||
EsiaAccessToken esiaAccessToken = readToken(accessToken);
|
||||
String scope = esiaAccessToken.getScope();
|
||||
String orgOid = scope.substring(scope.indexOf('=') + 1, scope.indexOf(' '));
|
||||
String prnsId = esiaAccessToken.getSbj_id();
|
||||
EmployeeModel employeeModel = getEmplData(prnsId, orgOid, accessToken);
|
||||
return employeeModel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmployeeModel getChiefEmployeeModel(String accessToken) {
|
||||
try {
|
||||
EsiaAccessToken esiaAccessToken = readToken(accessToken);
|
||||
String scope = esiaAccessToken.getScope();
|
||||
String orgOid = scope.substring(scope.indexOf('=') + 1, scope.indexOf(' '));
|
||||
String url = esiaConfig.getEsiaBaseUri() + "rs/orgs/" + orgOid + "/emps?embed=(elements)";
|
||||
HttpRequest getReq = HttpRequest.newBuilder(URI.create(url))
|
||||
.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());
|
||||
errorHandler(getResp);
|
||||
EmployeeModel[] employeeModels = objectMapper.readValue(
|
||||
objectMapper.readTree(getResp.body()).get("elements").toString(), EmployeeModel[].class);
|
||||
Optional<EmployeeModel> chief = Arrays.stream(employeeModels)
|
||||
.filter(employee -> employee.getChief().equals(true) && employee.getBlocked().equals(false))
|
||||
.findFirst();
|
||||
if (chief.isPresent()) {
|
||||
EmployeeModel chiefModel = chief.get();
|
||||
PersonModel personModel = getPersonData(chiefModel.getPrnOid(), accessToken);
|
||||
chiefModel.setPerson(personModel);
|
||||
return chiefModel;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public OrganizationModel getOrganizationModel(String accessToken) {
|
||||
EsiaAccessToken esiaAccessToken = readToken(accessToken);
|
||||
String scope = esiaAccessToken.getScope();
|
||||
String orgOid = scope.substring(scope.indexOf('=') + 1, scope.indexOf(' '));
|
||||
OrganizationModel organizationModel = getOrgModel(orgOid, accessToken);
|
||||
return organizationModel;
|
||||
}
|
||||
|
||||
private EmployeeModel getEmplData(String prnsId, String orgOid, String accessToken) {
|
||||
try {
|
||||
String url = esiaConfig.getEsiaBaseUri() + "rs/orgs/" + orgOid + "/emps/" + prnsId + "?embed=(elements.person)";
|
||||
HttpRequest getReq = HttpRequest.newBuilder(URI.create(url))
|
||||
.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());
|
||||
errorHandler(getResp);
|
||||
return objectMapper.readValue(getResp.body(), EmployeeModel.class);
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PersonModel getPersonData(String prnsId, String accessToken) {
|
||||
try {
|
||||
String url = esiaConfig.getEsiaBaseUri() + "rs/prns/" + prnsId;
|
||||
HttpRequest getReq = HttpRequest.newBuilder(URI.create(url))
|
||||
.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());
|
||||
errorHandler(getResp);
|
||||
return objectMapper.readValue(getResp.body(), PersonModel.class);
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public EsiaAccessToken readToken(String accessToken) {
|
||||
try {
|
||||
byte[] decodedBytes = Base64.getDecoder()
|
||||
.decode(
|
||||
accessToken.substring(accessToken.indexOf('.') + 1, accessToken.lastIndexOf('.'))
|
||||
.replace('-', '+')
|
||||
.replace('_', '/'));
|
||||
String decodedString = new String(decodedBytes);
|
||||
EsiaAccessToken esiaAccessToken = objectMapper.readValue(decodedString,
|
||||
EsiaAccessToken.class
|
||||
);
|
||||
return esiaAccessToken;
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private OrganizationModel getOrgModel(String orgOid, String accessToken) {
|
||||
try {
|
||||
String url = esiaConfig.getEsiaBaseUri() + "rs/orgs/" + orgOid;
|
||||
HttpRequest getReq = HttpRequest.newBuilder(URI.create(url + "?embed=(contacts.elements,addresses.elements)"))
|
||||
.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());
|
||||
errorHandler(getResp);
|
||||
OrganizationModel organizationModel = objectMapper.readValue(getResp.body(),
|
||||
OrganizationModel.class
|
||||
);
|
||||
HttpRequest getReqBrhs = HttpRequest.newBuilder(
|
||||
URI.create(url + "/brhs?embed=(elements,addresses.elements,contacts.elements)"))
|
||||
.header(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded")
|
||||
.header("Authorization", "Bearer ".concat(accessToken))
|
||||
.GET()
|
||||
.timeout(Duration.ofSeconds(esiaConfig.getRequestTimeout()))
|
||||
.build();
|
||||
HttpResponse<String> getRespBrhs = HttpClient.newBuilder()
|
||||
.connectTimeout(Duration.ofSeconds(esiaConfig.getConnectionTimeout()))
|
||||
.build()
|
||||
.send(getReqBrhs, HttpResponse.BodyHandlers.ofString());
|
||||
errorHandler(getRespBrhs);
|
||||
BrhsModel[] brhsModels = objectMapper.readValue(
|
||||
objectMapper.readTree(getRespBrhs.body()).get("elements").toString(), BrhsModel[].class);
|
||||
organizationModel.setBrhs(brhsModels);
|
||||
return organizationModel;
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void errorHandler(HttpResponse httpResponse) {
|
||||
if (httpResponse.statusCode() != 200) {
|
||||
throw new RuntimeException(httpResponse.statusCode() + " " + httpResponse.body());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkRole(String accessToken) {
|
||||
try {
|
||||
EsiaAccessToken esiaAccessToken = readToken(accessToken);
|
||||
String scope = esiaAccessToken.getScope();
|
||||
String orgOid = scope.substring(scope.indexOf('=') + 1, scope.indexOf(' '));
|
||||
String prnsId = esiaAccessToken.getSbj_id();
|
||||
String url = esiaConfig.getEsiaBaseUri() + "rs/orgs/" + orgOid + "/emps/" + prnsId + "/grps?embed=(elements)";
|
||||
HttpRequest getReq = HttpRequest.newBuilder(URI.create(url))
|
||||
.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());
|
||||
errorHandler(getResp);
|
||||
if (getResp.body().contains("MNSV89_UPLOAD_DATA")) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAllUserRoles(String accessToken) {
|
||||
try {
|
||||
EsiaAccessToken esiaAccessToken = readToken(accessToken);
|
||||
String scope = esiaAccessToken.getScope();
|
||||
String orgOid = scope.substring(scope.indexOf('=') + 1, scope.indexOf(' '));
|
||||
String prnsId = esiaAccessToken.getSbj_id();
|
||||
String url = esiaConfig.getEsiaBaseUri() + "rs/orgs/" + orgOid + "/emps/" + prnsId + "/grps?embed=(elements)";
|
||||
HttpRequest getReq = HttpRequest.newBuilder(URI.create(url))
|
||||
.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());
|
||||
errorHandler(getResp);
|
||||
JsonNode rootNode = objectMapper.readTree(getResp.body());
|
||||
JsonNode elementsNode = rootNode.path("elements");
|
||||
StringBuilder names = new StringBuilder();
|
||||
for (JsonNode element : elementsNode) {
|
||||
String name = element.path("name").asText();
|
||||
names.append(name).append("\n");
|
||||
}
|
||||
return names.toString();
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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."
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
package ru.micord.ervu.security.webbpm.jwt.service;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.util.Base64;
|
||||
import java.util.Date;
|
||||
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.stereotype.Component;
|
||||
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:#{null}}")
|
||||
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) {
|
||||
|
||||
Date expirationDate = new Date(System.currentTimeMillis() + 1000L * expiresIn);
|
||||
String value = Jwts.builder()
|
||||
.setSubject(userAccountId)
|
||||
.setIssuer(tokenIssuerName)
|
||||
.setIssuedAt(new Date(System.currentTimeMillis()))
|
||||
.setExpiration(expirationDate)
|
||||
.signWith(SIGNING_KEY)
|
||||
.compact();
|
||||
return new Token(userAccountId, 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);
|
||||
}
|
||||
}
|
||||
|
|
@ -41,4 +41,4 @@ RUN chmod -R +x patches && \
|
|||
ENV SERVER_START=true
|
||||
COPY --chown=jboss *.ear $JBOSS_HOME/standalone/deployments/
|
||||
|
||||
HEALTHCHECK --timeout=3s --start-period=3600s CMD curl --fail 127.0.0.1:8080/backend/version || exit 1
|
||||
HEALTHCHECK --timeout=3s --start-period=3600s CMD curl --fail 127.0.0.1:8080/ul/version || exit 1
|
||||
|
|
|
|||
36
config/context.xml
Normal file
36
config/context.xml
Normal 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://10.10.31.119:5432/ervu-lkrp-ul"
|
||||
username="ervu-lkrp-ul" password="ervu-lkrp-ul" maxTotal="20" maxIdle="10" maxWaitMillis="-1"/>
|
||||
</Context>
|
||||
|
|
@ -16,41 +16,6 @@ xa-data-source add \
|
|||
--query-timeout=300 \
|
||||
--xa-datasource-properties=ServerName=${env.DB_APP_HOST:db},PortNumber=${env.DB_APP_PORT:5432},DatabaseName=${env.DB_APP_NAME:app}
|
||||
|
||||
xa-data-source add \
|
||||
--name=JBPMDS \
|
||||
--enabled=true \
|
||||
--driver-name=postgresql \
|
||||
--jndi-name=java:jboss/datasources/jbpmDS \
|
||||
--user-name=${env.DB_JBPM_USERNAME:jbpm} \
|
||||
--password=${env.DB_JBPM_PASSWORD:jbpmpassword} \
|
||||
--use-ccm=true \
|
||||
--valid-connection-checker-class-name=org.jboss.jca.adapters.jdbc.extensions.postgres.PostgreSQLValidConnectionChecker \
|
||||
--validate-on-match=false \
|
||||
--background-validation=true \
|
||||
--background-validation-millis=5000 \
|
||||
--exception-sorter-class-name=org.jboss.jca.adapters.jdbc.extensions.postgres.PostgreSQLExceptionSorter \
|
||||
--statistics-enabled=true \
|
||||
--max-pool-size=50 \
|
||||
--query-timeout=300 \
|
||||
--xa-datasource-properties=ServerName=${env.DB_JBPM_HOST:db},PortNumber=${env.DB_JBPM_PORT:5432},DatabaseName=${env.DB_JBPM_NAME:jbpm}
|
||||
|
||||
xa-data-source add \
|
||||
--name=SECURITYDS \
|
||||
--enabled=true \
|
||||
--driver-name=postgresql \
|
||||
--jndi-name=java:/webbpm/security-ds \
|
||||
--user-name=${env.DB_SEC_USERNAME:security_user} \
|
||||
--password=${env.DB_SEC_PASSWORD:secpassword} \
|
||||
--max-pool-size=70 \
|
||||
--valid-connection-checker-class-name=org.jboss.jca.adapters.jdbc.extensions.postgres.PostgreSQLValidConnectionChecker \
|
||||
--validate-on-match=false \
|
||||
--background-validation=true \
|
||||
--background-validation-millis=5000 \
|
||||
--exception-sorter-class-name=org.jboss.jca.adapters.jdbc.extensions.postgres.PostgreSQLExceptionSorter \
|
||||
--statistics-enabled=true \
|
||||
--query-timeout=300 \
|
||||
--xa-datasource-properties=ServerName=${env.DB_SEC_HOST:db},PortNumber=${env.DB_SEC_PORT:5432},DatabaseName=${env.DB_SEC_NAME:app}
|
||||
|
||||
/system-property=ldap.mapping.login.param:add(value=${env.WEBBPM_LDAP_LOGIN_ATTR:uid})
|
||||
/system-property=ldap.mapping.org.code.param:add(value=${env.WEBBPM_LDAP_ORGANIZATION_ATTR:ou})
|
||||
/system-property=jboss.as.management.blocking.timeout:add(value=900)
|
||||
|
|
@ -62,6 +27,7 @@ xa-data-source add \
|
|||
/system-property=gar.enable:add(value=false)
|
||||
/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=file.webdav.upload.url:add(value="https://ervu-webdav.k8s.micord.ru")
|
||||
/system-property=file.webdav.upload.username:add(value="test")
|
||||
/system-property=file.webdav.upload.password:add(value="test")
|
||||
|
|
@ -74,6 +40,17 @@ xa-data-source add \
|
|||
/system-property=ervu.fileupload.max_file_size:add(value="5242880")
|
||||
/system-property=ervu.fileupload.max_request_size:add(value="6291456")
|
||||
/system-property=ervu.fileupload.file_size_threshold:add(value="0")
|
||||
/system-property=esia-scopes:add(value="fullname, snils, id_doc, birthdate, usr_org, openid")
|
||||
/system-property=esia-org-scopes:add(value="org_fullname, org_shortname, org_brhs, org_brhs_ctts, org_brhs_addrs, org_type, org_ogrn, org_inn, org_leg, org_kpp, org_ctts, org_addrs, org_grps, org_emps")
|
||||
/system-property=esia-org-scope-url:add(value="http://esia.gosuslugi.ru/")
|
||||
/system-property=esia-uri.base-uri:add(value="https://esia-portal1.test.gosuslugi.ru/")
|
||||
/system-property=esia-uri.code-path:add(value="https://esia-portal1.test.gosuslugi.ru/aas/oauth2/v2/ac")
|
||||
/system-property=esia-uri.token-path:add(value="https://esia-portal1.test.gosuslugi.ru/aas/oauth2/v3/te")
|
||||
/system-property=esia-client-id:add(value="MNSV89")
|
||||
/system-property=esia-redirect-url:add(value="https://lkrp-dev.micord.ru/ul/")
|
||||
/system-property=sign-url:add(value="https://ervu-sign-dev.k8s.micord.ru/sign")
|
||||
/system-property=esia-uri.logout:add(value="https://esia-portal1.test.gosuslugi.ru/idp/ext/Logout")
|
||||
/system-property=client-cert-hash:add(value="04508B4B0B58776A954A0E15F574B4E58799D74C61EE020B3330716C203E3BDD")
|
||||
/system-property=ervu.cron.load.enable(value="true")
|
||||
/system-property=ervu.cron.load.time(value="0 0 */1 * * *")
|
||||
/system-property=ervu.esnsi.classifier.url.load(value="https://esnsi.gosuslugi.ru/rest/ext/v1/classifiers/11465/file?extension=JSON&encoding=UTF_8"")
|
||||
|
|
|
|||
|
|
@ -66,6 +66,17 @@
|
|||
<property name="ervu.fileupload.max_file_size" value="5242880"/>
|
||||
<property name="ervu.fileupload.max_request_size" value="6291456"/>
|
||||
<property name="ervu.fileupload.file_size_threshold" value="0"/>
|
||||
<property name="esia-scopes" value="fullname, snils, id_doc, birthdate, usr_org, openid"/>
|
||||
<property name="esia-org-scopes" value="org_fullname, org_shortname, org_brhs, org_brhs_ctts, org_brhs_addrs, org_type, org_ogrn, org_inn, org_leg, org_kpp, org_ctts, org_addrs, org_grps, org_emps"/>
|
||||
<property name="esia-org-scope-url" value="http://esia.gosuslugi.ru/"/>
|
||||
<property name="esia-uri.base-uri" value="https://esia-portal1.test.gosuslugi.ru/"/>
|
||||
<property name="esia-uri.code-path" value="https://esia-portal1.test.gosuslugi.ru/aas/oauth2/v2/ac"/>
|
||||
<property name="esia-uri.token-path" value="https://esia-portal1.test.gosuslugi.ru/aas/oauth2/v3/te"/>
|
||||
<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="sesia-uri.logout" value="https://esia-portal1.test.gosuslugi.ru/idp/ext/Logout"/>
|
||||
<property name="client-cert-hash" value="04508B4B0B58776A954A0E15F574B4E58799D74C61EE020B3330716C203E3BDD"/>
|
||||
<property name="ervu.cron.load.time" value="0 0 */1 * * *"/>
|
||||
<property name="ervu.esnsi.classifier.url.load" value="https://esnsi.gosuslugi.ru/rest/ext/v1/classifiers/11465/file?extension=JSON&encoding=UTF_8"/>
|
||||
</system-properties>
|
||||
|
|
|
|||
9
config/tomcat/tomee/bin/setenv.sh
Executable file
9
config/tomcat/tomee/bin/setenv.sh
Executable 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} \
|
||||
"
|
||||
36
config/tomcat/tomee/conf/context.xml
Normal file
36
config/tomcat/tomee/conf/context.xml
Normal 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>
|
||||
39
config/tomcat/tomee/conf/tomcat-users.xml
Normal file
39
config/tomcat/tomee/conf/tomcat-users.xml
Normal 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>
|
||||
15
config/tomcat/tomee/conf/webbpm.properties
Normal file
15
config/tomcat/tomee/conf/webbpm.properties
Normal 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
|
||||
26
config/tomcat/tomee/webapps/manager/META-INF/context.xml
Normal file
26
config/tomcat/tomee/webapps/manager/META-INF/context.xml
Normal 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>
|
||||
|
|
@ -2,27 +2,27 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>ervu_lkrp_ul</groupId>
|
||||
<artifactId>ervu_lkrp_ul</artifactId>
|
||||
<groupId>ru.micord.ervu.lkrp</groupId>
|
||||
<artifactId>ul</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<groupId>ervu_lkrp_ul.ervu_lkrp_ul</groupId>
|
||||
<groupId>ru.micord.ervu.lkrp.ul</groupId>
|
||||
<artifactId>distribution</artifactId>
|
||||
<packaging>ear</packaging>
|
||||
|
||||
<properties>
|
||||
<backendContext>/backend</backendContext>
|
||||
<backendContext>/ul</backendContext>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>ervu_lkrp_ul.ervu_lkrp_ul</groupId>
|
||||
<groupId>ru.micord.ervu.lkrp.ul</groupId>
|
||||
<artifactId>backend</artifactId>
|
||||
<type>war</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ervu_lkrp_ul.ervu_lkrp_ul</groupId>
|
||||
<groupId>ru.micord.ervu.lkrp.ul</groupId>
|
||||
<artifactId>frontend</artifactId>
|
||||
<type>war</type>
|
||||
</dependency>
|
||||
|
|
@ -37,16 +37,16 @@
|
|||
<configuration>
|
||||
<modules>
|
||||
<webModule>
|
||||
<groupId>ervu_lkrp_ul.ervu_lkrp_ul</groupId>
|
||||
<groupId>ru.micord.ervu.lkrp.ul</groupId>
|
||||
<artifactId>frontend</artifactId>
|
||||
<contextRoot>/</contextRoot>
|
||||
<bundleFileName>frontend.war</bundleFileName>
|
||||
</webModule>
|
||||
<webModule>
|
||||
<groupId>ervu_lkrp_ul.ervu_lkrp_ul</groupId>
|
||||
<groupId>ru.micord.ervu.lkrp.ul</groupId>
|
||||
<artifactId>backend</artifactId>
|
||||
<contextRoot>${backendContext}</contextRoot>
|
||||
<bundleFileName>backend.war</bundleFileName>
|
||||
<bundleFileName>ul.war</bundleFileName>
|
||||
</webModule>
|
||||
</modules>
|
||||
</configuration>
|
||||
|
|
@ -59,7 +59,7 @@
|
|||
<profile>
|
||||
<id>enable-version-in-url</id>
|
||||
<properties>
|
||||
<backendContext>/backend-${project.version}</backendContext>
|
||||
<backendContext>/ul-${project.version}</backendContext>
|
||||
</properties>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
|
|
|||
8
frontend/package-lock.json
generated
8
frontend/package-lock.json
generated
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"name": "webbpm-frontend",
|
||||
"name": "ervu_lkrp_ul",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
|
|
@ -1624,9 +1624,9 @@
|
|||
}
|
||||
},
|
||||
"@webbpm/base-package": {
|
||||
"version": "3.177.0",
|
||||
"resolved": "https://repo.micord.ru/repository/npm-all/@webbpm/base-package/-/base-package-3.177.0.tgz",
|
||||
"integrity": "sha512-YgjHHcIR0m/QHujiU17e4NmGmSRxUg88G609KkTGh8XreTXbpYwRxo+3Vr5ttfjk0ND1NMWt6L2TlTLlaCgpkQ==",
|
||||
"version": "3.178.2",
|
||||
"resolved": "https://repo.micord.ru/repository/npm-all/@webbpm/base-package/-/base-package-3.178.2.tgz",
|
||||
"integrity": "sha512-ShqAmiaGCvrg7ffrhntshwcZJVW8cK10JsMy/OT36p7iK6B/IR0YCJZZ+GIhakLo0CZsEokhcpKBdORvfOI55g==",
|
||||
"requires": {
|
||||
"tslib": "^1.9.0"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"name": "webbpm-frontend",
|
||||
"name": "ervu_lkrp_ul",
|
||||
"version": "1.0.0",
|
||||
"scripts": {
|
||||
"lite": "node ./node_modules/lite-server/bin/lite-server",
|
||||
|
|
@ -27,7 +27,7 @@
|
|||
"@angular/platform-browser-dynamic": "7.2.15",
|
||||
"@angular/router": "7.2.15",
|
||||
"@ng-bootstrap/ng-bootstrap": "4.1.1",
|
||||
"@webbpm/base-package": "3.177.0",
|
||||
"@webbpm/base-package": "3.178.2",
|
||||
"ag-grid-angular": "29.0.0-micord.4",
|
||||
"ag-grid-community": "29.0.0-micord.4",
|
||||
"angular-calendar": "0.28.28",
|
||||
|
|
|
|||
|
|
@ -2,12 +2,12 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>ervu_lkrp_ul</groupId>
|
||||
<artifactId>ervu_lkrp_ul</artifactId>
|
||||
<groupId>ru.micord.ervu.lkrp</groupId>
|
||||
<artifactId>ul</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<groupId>ervu_lkrp_ul.ervu_lkrp_ul</groupId>
|
||||
<groupId>ru.micord.ervu.lkrp.ul</groupId>
|
||||
<artifactId>frontend</artifactId>
|
||||
<packaging>war</packaging>
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
});
|
||||
</script>
|
||||
</head>
|
||||
<body preview-container id="webbpm-angular-application-container ervu_lkrp_ul" class="webbpm">
|
||||
<body preview-container id="webbpm-angular-application-container" class="webbpm ervu_lkrp_ul">
|
||||
<div class="loader"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
"filter_cleanup_check_period_minutes": 30,
|
||||
"auth_method": "form",
|
||||
"enable.version.in.url": "%enable.version.in.url%",
|
||||
"backend.context": "ul",
|
||||
"guard.confirm_exit": false,
|
||||
"message_service_error_timeout": "",
|
||||
"message_service_warning_timeout": "",
|
||||
|
|
|
|||
|
|
@ -1,34 +0,0 @@
|
|||
<div *ngIf="(currentSession | async)?.authorities.includes('BPMN.ADMIN.PROCESS_INSTANCE.LIST') ||
|
||||
(currentSession | async)?.authorities.includes('USER_MANAGEMENT.USER.LIST') ||
|
||||
(currentSession | async)?.authorities.includes('USER_MANAGEMENT.GROUP.LIST') ||
|
||||
(currentSession | async)?.authorities.includes('USER_MANAGEMENT.ROLE.LIST') ||
|
||||
(currentSession | async)?.authorities.includes('USER_MANAGEMENT.ORG_UNIT.LIST') ||
|
||||
(currentSession | async)?.authorities.includes('USER_MANAGEMENT.AUTHORITY.LIST')" ngbDropdown class="nav-item" [placement]="placement">
|
||||
<button class="nav-link bi bi-gear-fill" id="adminDropdownMenu" ngbDropdownToggle title="Администрирование"></button>
|
||||
<div ngbDropdownMenu aria-labelledby="adminDropdownMenu">
|
||||
<button *ngIf="(currentSession | async)?.authorities.includes('BPMN.ADMIN.PROCESS_INSTANCE.LIST')"
|
||||
routerLink="/process/instance" ngbDropdownItem>
|
||||
Экземпляры процессов
|
||||
</button>
|
||||
<button *ngIf="(currentSession | async)?.authorities.includes('USER_MANAGEMENT.USER.LIST')"
|
||||
routerLink="/user-management/users" ngbDropdownItem>
|
||||
Пользователи
|
||||
</button>
|
||||
<button *ngIf="(currentSession | async)?.authorities.includes('USER_MANAGEMENT.GROUP.LIST')"
|
||||
routerLink="/user-management/groups" ngbDropdownItem>
|
||||
Группы
|
||||
</button>
|
||||
<button *ngIf="(currentSession | async)?.authorities.includes('USER_MANAGEMENT.ROLE.LIST')"
|
||||
routerLink="/user-management/roles" ngbDropdownItem>
|
||||
Роли
|
||||
</button>
|
||||
<button *ngIf="(currentSession | async)?.authorities.includes('USER_MANAGEMENT.ORG_UNIT.LIST')"
|
||||
routerLink="/user-management/org-units" ngbDropdownItem>
|
||||
Организации
|
||||
</button>
|
||||
<button *ngIf="(currentSession | async)?.authorities.includes('USER_MANAGEMENT.AUTHORITY.LIST')"
|
||||
routerLink="/user-management/authorities" ngbDropdownItem>
|
||||
Безопасность действий
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -1,17 +1,10 @@
|
|||
<nav class="header" *ngIf="currentSession | async as session" id="webbpm-header">
|
||||
<nav class="header" id="webbpm-header">
|
||||
<div class="header-logo">
|
||||
<div class="logo"><a routerLink="/"></a></div>
|
||||
<div class="main-page"><a routerLink="/">Главная</a></div>
|
||||
<div class="header-menu-left"><a routerLink="/filesentlog">Журнал взаимодействий</a></div>
|
||||
</div>
|
||||
<div class="header-menu">
|
||||
<!--
|
||||
<process *ngIf="session.authorities.includes('BPMN.USER.START_PROCESS')"></process>
|
||||
<div *ngIf="session.authorities.includes('BPMN.USER.TASK_LIST')">
|
||||
<button class="nav-link bi bi-file-text-fill" (click)="openTaskList()" title="Задачи"></button>
|
||||
</div>
|
||||
<admin-menu [placement]="'bottom'"></admin-menu>
|
||||
-->
|
||||
<div ngbDropdown class="logout" log-out></div>
|
||||
</div>
|
||||
</nav>
|
||||
|
|
|
|||
|
|
@ -1,27 +0,0 @@
|
|||
<div class="confirm">
|
||||
<div class="form-logo">
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="info">
|
||||
<div>
|
||||
<h2>Подтверждение почты</h2>
|
||||
|
||||
<div *ngIf="verificationStatus.toString() === 'VERIFYING'">
|
||||
Подтверждение...
|
||||
</div>
|
||||
<div *ngIf="verificationStatus.toString() === 'VERIFIED'">
|
||||
<div class="alert alert-success">
|
||||
Адрес электронной почты успешно подтвержден
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="verificationStatus.toString() === 'FAILED'">
|
||||
<div class="alert alert-danger">{{ errorMessage }}</div>
|
||||
</div>
|
||||
|
||||
<div *ngIf="(currentSession | async) == null">
|
||||
<a href="#/login"><span class="fa fa-lock"></span>Войти</a><br/>
|
||||
<a href="#/registration">Зарегистрироваться</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -1,11 +1,6 @@
|
|||
<button class="user-info" ngbDropdownToggle *ngIf="currentSession | async as session">{{session.fullUserName}}</button>
|
||||
<div ngbDropdownMenu *ngIf="currentSession | async as session">
|
||||
<!--
|
||||
<div class="user-info">
|
||||
<div class="user-login">{{session.username}}</div>
|
||||
</div>
|
||||
-->
|
||||
<button class="user-info" ngbDropdownToggle *ngIf="getIsAuth()">{{getUserFullname()}}</button>
|
||||
<div ngbDropdownMenu *ngIf="getIsAuth()">
|
||||
<div class="user-department">{{getOrgUnitName()}}</div>
|
||||
<a routerLink="/mydata" class="data">Данные организации</a>
|
||||
<button ngbDropdownItem class="exit" *ngIf="isLogoutButtonVisible()" (click)="logout()">Выйти</button>
|
||||
<button ngbDropdownItem class="exit" (click)="logout()">Выйти</button>
|
||||
</div>
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
<div class="form-signin">
|
||||
<form #formComponent="ngForm">
|
||||
<div class="alert alert-success" [hidden]="!confirmationSent">На ваш почтовый адрес было отправлено письмо. Подтвердите почту, чтобы войти в систему
|
||||
</div>
|
||||
<div class="alert alert-danger" [hidden]="!errorMessage">{{errorMessage}}</div>
|
||||
|
||||
<div class="logo">
|
||||
<h2>Воинский учет в организациях</h2>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="input-group">
|
||||
<input type="text" name="username" class="form-control" placeholder=" " required autofocus [(ngModel)]="username" maxlength="100">
|
||||
<label>Логин</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="input-group">
|
||||
<input
|
||||
[type]="passwordType ? 'text' : 'password'"
|
||||
name="password"
|
||||
class="form-control field-password-view"
|
||||
placeholder=" " required
|
||||
[(ngModel)]="password"
|
||||
maxlength="100"
|
||||
>
|
||||
<label>Пароль</label>
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text">
|
||||
<i
|
||||
(click)="togglePasswordType()"
|
||||
class="fa"
|
||||
[ngClass]="{
|
||||
'fa-eye': passwordType,
|
||||
'fa-eye-slash': !passwordType
|
||||
}"
|
||||
></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="msg-text"><a href="#/reset-password">Восстановить пароль</a></div>
|
||||
</div>
|
||||
<div class="btn-box">
|
||||
<!--<esia-login-button></esia-login-button>-->
|
||||
<button type="submit" class="btn btn-primary" (click)="formComponent.form.valid && login()">Войти</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
|
@ -1,103 +0,0 @@
|
|||
<div class="form-signup">
|
||||
<div class="form-logo">
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="form-new-password">
|
||||
<form #formComponent="ngForm">
|
||||
<div [hidden]="!errorMessage" class="alert alert-danger">{{ errorMessage }}</div>
|
||||
<p class="has-account">Вспомнили пароль?
|
||||
<a href="#/login"><span class="fa fa-lock"></span>Войти</a></p>
|
||||
|
||||
<p class="has-account">Задайте новый пароль</p>
|
||||
|
||||
<div class="row">
|
||||
<label>Пароль</label>
|
||||
<div class="input-group">
|
||||
<input
|
||||
#passwordInput="ngModel"
|
||||
[(ngModel)]="password"
|
||||
[type]="passwordType ? 'text' : 'password'"
|
||||
class="form-control"
|
||||
maxlength="32"
|
||||
minlength="6"
|
||||
name="password"
|
||||
pattern="^(?=.*[a-zA-Z])(?=.*[0-9])[a-zA-Z0-9]+$"
|
||||
required
|
||||
(change)="validPasswords()"
|
||||
>
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text">
|
||||
<i
|
||||
(click)="togglePasswordType()"
|
||||
class="fa"
|
||||
[ngClass]="{
|
||||
'fa-eye': passwordType,
|
||||
'fa-eye-slash': !passwordType
|
||||
}"
|
||||
></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="passwordInput.invalid && (passwordInput.dirty || passwordInput.touched)">
|
||||
<div *ngIf="passwordInput.errors.required" class="msg-alert">Поле обязательно
|
||||
</div>
|
||||
<div *ngIf="passwordInput.errors.minlength" class="msg-alert">Пароль должен
|
||||
содержать как минимум 6 символов
|
||||
</div>
|
||||
<div *ngIf="passwordInput.errors.pattern" class="msg-alert">Пароль должен
|
||||
содержать заглавные и прописные буквы и как минимум 1 цифру
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<label>Подтверждение пароля</label>
|
||||
<div class="input-group">
|
||||
<input
|
||||
#confirmPasswordInput="ngModel"
|
||||
[(ngModel)]="confirmPassword"
|
||||
[type]="confirmPasswordType ? 'text' : 'password'"
|
||||
class="form-control"
|
||||
maxlength="32"
|
||||
minlength="6"
|
||||
name="confirmPassword"
|
||||
pattern="^(?=.*[a-zA-Z])(?=.*[0-9])[a-zA-Z0-9]+$"
|
||||
required
|
||||
(change)="validPasswords()"
|
||||
>
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text">
|
||||
<i
|
||||
(click)="toggleConfirmPasswordType()"
|
||||
class="fa"
|
||||
[ngClass]="{
|
||||
'fa-eye': confirmPasswordType,
|
||||
'fa-eye-slash': !confirmPasswordType
|
||||
}"
|
||||
></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="confirmPasswordInput.invalid && (confirmPasswordInput.dirty || confirmPasswordInput.touched)">
|
||||
<div *ngIf="confirmPasswordInput.errors.required" class="msg-alert">Поле обязательно
|
||||
</div>
|
||||
<div *ngIf="confirmPasswordInput.errors.minlength" class="msg-alert">Пароль должен
|
||||
содержать как минимум 6 символов
|
||||
</div>
|
||||
<div *ngIf="confirmPasswordInput.errors.pattern" class="msg-alert">Пароль должен
|
||||
содержать заглавные и прописные буквы и как минимум 1 цифру
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="reset-password-btn-box">
|
||||
<button
|
||||
(click)="formComponent.form.valid && validPasswords() && changePassword()"
|
||||
[disabled]="!formComponent.form.valid && !validPasswords()"
|
||||
class="btn btn-primary"
|
||||
type="submit"
|
||||
>
|
||||
Изменить пароль
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
<div ngbDropdown class="nav-item">
|
||||
<button class="nav-link bi bi-clipboard-plus-fill" id="startProcessDropdownMenu" ngbDropdownToggle title="Создать"></button>
|
||||
<div ngbDropdownMenu aria-labelledby="startProcessDropdownMenu">
|
||||
<div class="dropdown-menu-inner">
|
||||
<div *ngFor="let process of processList">
|
||||
<button (click)="startProcess(process.processDefId)" ngbDropdownItem>
|
||||
{{ process.name }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
</div><!-- TODO: move to directive or something else -->
|
||||
|
|
@ -1,121 +0,0 @@
|
|||
<div class="form-signup">
|
||||
<div class="form-logo">
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="form-register">
|
||||
<form #formComponent="ngForm">
|
||||
<div [hidden]="!errorMessage" class="alert alert-danger">{{ errorMessage }}</div>
|
||||
<h2>Регистрация</h2>
|
||||
<p class="has-account">Уже зарегистрированы?
|
||||
<a href="#/login"><span class="fa fa-lock"></span>Войти</a></p>
|
||||
|
||||
<div class="row">
|
||||
<label>Имя</label>
|
||||
<input
|
||||
#name="ngModel"
|
||||
[(ngModel)]="username"
|
||||
class="form-control"
|
||||
maxlength="100"
|
||||
name="username"
|
||||
required
|
||||
type="text"
|
||||
>
|
||||
<div *ngIf="name.invalid && (name.dirty || name.touched)">
|
||||
<div *ngIf="name.errors.required" class="msg-alert">Поле обязательно</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<label>Адрес эл. почты</label>
|
||||
<input
|
||||
#emailInput="ngModel"
|
||||
[(ngModel)]="email"
|
||||
class="form-control"
|
||||
email
|
||||
maxlength="100"
|
||||
name="email"
|
||||
required
|
||||
type="email"
|
||||
>
|
||||
<div *ngIf="emailInput.invalid && (emailInput.dirty || emailInput.touched)">
|
||||
<div *ngIf="emailInput.errors.required" class="msg-alert">Поле обязательно</div>
|
||||
<div *ngIf="emailInput.errors.email" class="msg-alert">Неверный формат адреса
|
||||
эл. почты
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<label>Номер телефона</label>
|
||||
<international-phone-number
|
||||
#phoneInput="ngModel"
|
||||
[(ngModel)]="phoneNumber"
|
||||
[defaultCountry]="'ru'"
|
||||
[pattern]="'^\\+(?!7 ?\\d{11})[0-9 ]+$'"
|
||||
maxlength="20"
|
||||
minlength="8"
|
||||
name="phoneNumber"
|
||||
placeholder="+79991112233"
|
||||
(focusout)="phoneInputFocusOut()"
|
||||
required
|
||||
></international-phone-number>
|
||||
<div *ngIf="phoneInput.invalid && (phoneInput.dirty || phoneIsTouched)">
|
||||
<div *ngIf="phone.selectedCountry">
|
||||
<div *ngIf="phoneHasOnlyDialCode()" class="msg-alert">Поле обязательно</div>
|
||||
<div *ngIf="!phoneHasOnlyDialCode()" class="msg-alert">Введите корректный номер</div>
|
||||
</div>
|
||||
<div *ngIf="!phone.selectedCountry">
|
||||
<div *ngIf="phoneInput.errors.required" class="msg-alert">Поле обязательно</div>
|
||||
<div *ngIf="!phoneInput.errors.required" class="msg-alert">Введите код страны</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<label>Пароль</label>
|
||||
<div class="input-group">
|
||||
<input
|
||||
#passwordInput="ngModel"
|
||||
[(ngModel)]="password"
|
||||
[type]="fieldType ? 'text' : 'password'"
|
||||
class="form-control"
|
||||
maxlength="32"
|
||||
minlength="8"
|
||||
name="password"
|
||||
[pattern]="passwordPattern"
|
||||
required
|
||||
>
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text">
|
||||
<i
|
||||
(click)="toggleFieldType()"
|
||||
class="fa"
|
||||
[ngClass]="{
|
||||
'fa-eye': fieldType,
|
||||
'fa-eye-slash': !fieldType
|
||||
}"
|
||||
></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="passwordInput.invalid && (passwordInput.dirty || passwordInput.touched)">
|
||||
<div *ngIf="passwordInput.errors.required" class="msg-alert">Поле обязательно
|
||||
</div>
|
||||
<div *ngIf="passwordInput.errors.minlength" class="msg-alert">Пароль должен
|
||||
содержать как минимум 8 символов
|
||||
</div>
|
||||
<div *ngIf="passwordInput.errors.pattern" class="msg-alert" [innerText]="passwordPatternErrorMessage">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="register-btn-box">
|
||||
<button
|
||||
(click)="formComponent.form.valid && register()"
|
||||
[disabled]="!formComponent.form.valid"
|
||||
class="btn btn-primary"
|
||||
type="submit"
|
||||
>
|
||||
Зарегистрироваться
|
||||
</button>
|
||||
</div>
|
||||
<div *ngIf="consent" [innerHTML]="consent" class="consent"></div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
<div class="form-signup">
|
||||
<div class="form-logo">
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="form-reset-password">
|
||||
<form #formComponent="ngForm">
|
||||
<div [hidden]="!errorMessage" class="alert alert-danger">{{ errorMessage }}</div>
|
||||
<p class="has-account">Вспомнили пароль?
|
||||
<a href="#/login"><span class="fa fa-lock"></span>Войти</a></p>
|
||||
|
||||
<p class="has-account">Укажите адрес эл. почты, который был указан при регистрации,
|
||||
на него пришлем временный пароль. Пароль сможете поменять в личном кабинете.
|
||||
</p>
|
||||
|
||||
<div class="row">
|
||||
<input
|
||||
#emailInput="ngModel"
|
||||
[(ngModel)]="email"
|
||||
class="form-control"
|
||||
email
|
||||
maxlength="100"
|
||||
name="email"
|
||||
required
|
||||
type="email"
|
||||
>
|
||||
<label>Адрес эл. почты</label>
|
||||
<div *ngIf="emailInput.invalid && (emailInput.dirty || emailInput.touched)" class="msg-text">
|
||||
<div *ngIf="emailInput.errors.required" class="msg-alert">Поле обязательно</div>
|
||||
<div *ngIf="emailInput.errors.email" class="msg-alert">Неверный формат адреса эл. почты
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="btn-box">
|
||||
<button
|
||||
(click)="formComponent.form.valid && resetPassword()"
|
||||
[disabled]="!formComponent.form.valid"
|
||||
class="btn btn-primary"
|
||||
type="submit"
|
||||
>
|
||||
Восстановить
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
<div id="page">
|
||||
<router-outlet></router-outlet>
|
||||
</div>
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
<div class="inner">
|
||||
<div class="task-list">
|
||||
<div class="task-list-tree-panel">
|
||||
<div class="task-list-filter">
|
||||
<ul>
|
||||
<li>Фильтры</li>
|
||||
<li>
|
||||
<label>
|
||||
<input type="radio" name="task-filter" value="All" [(ngModel)]="showMode" (ngModelChange)="filterVisibleTasks()">
|
||||
<span>Все [{{tasks.length}}]</span>
|
||||
</label></li>
|
||||
<li class="ontime">
|
||||
<label>
|
||||
<input type="radio" name="task-filter" value="OnTime" [(ngModel)]="showMode" (ngModelChange)="filterVisibleTasks()">
|
||||
<span><div></div>Без превышения срока [{{onTimeTasks.length}}]</span>
|
||||
</label></li>
|
||||
<li class="overdue">
|
||||
<label>
|
||||
<input type="radio" name="task-filter" value="Overdue" [(ngModel)]="showMode" (ngModelChange)="filterVisibleTasks()">
|
||||
<span><div></div>С превышением срока [{{overdueTasks.length}}]</span>
|
||||
</label></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="task-list-workplace">
|
||||
<div class="alert alert-danger" [hidden]="!errorMessage">{{errorMessage}}</div>
|
||||
<div class="table task-tbl">
|
||||
<div class="thead">
|
||||
<div class="tr">
|
||||
<div class="th">Процесс</div>
|
||||
<div class="th">Версия</div>
|
||||
<div class="th">Задача</div>
|
||||
<div class="th">Дата создания</div>
|
||||
<div class="th">Срок</div>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngFor="let task of visibleTasks"
|
||||
class="tr" [ngClass]="{'task-overdue': isOverdue(task), 'task-ontime': isOnTime(task)}"
|
||||
(click)="startTask(task)">
|
||||
<div class="td">{{ task.processName }}</div>
|
||||
<div class="td">{{ task.processVersion }}</div>
|
||||
<div class="td task">{{ task.name }}</div>
|
||||
<div class="td">{{ task.createdOn | date:'dd.MM.yyyy HH:mm:ss' }}</div>
|
||||
<div class="td">{{ task.expirationTime | date:'dd.MM.yyyy HH:mm:ss' }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
<div class="task-not-found-page">
|
||||
<div class="task-not-found-container">
|
||||
<div>:(</div>
|
||||
<div><h2>Ошибка</h2>
|
||||
Данная задача не существует.<br/>
|
||||
Перейти к <a (click)="goToTaskList()" tabindex>списку задач</a></div>
|
||||
</div>
|
||||
</div>
|
||||
7
frontend/src/ts/esia/OrgData.ts
Normal file
7
frontend/src/ts/esia/OrgData.ts
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
import {Behavior, NotNull} from "@webbpm/base-package";
|
||||
|
||||
export class OrgData extends Behavior{
|
||||
|
||||
@NotNull()
|
||||
public dataId: string;
|
||||
}
|
||||
33
frontend/src/ts/esia/OrgDataRoot.ts
Normal file
33
frontend/src/ts/esia/OrgDataRoot.ts
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
import {AnalyticalScope, Behavior, Container, ControlWithValue} from "@webbpm/base-package";
|
||||
import {HttpClient} from "@angular/common/http";
|
||||
import {OrgData} from "./OrgData";
|
||||
import {OrgInfoModel} from "../generated/ru/micord/ervu/security/esia/model/OrgInfoModel";
|
||||
import {CookieService} from "ngx-cookie";
|
||||
|
||||
@AnalyticalScope(Container)
|
||||
export class OrgDataRoot extends Behavior{
|
||||
|
||||
private container: Container;
|
||||
|
||||
initialize() {
|
||||
super.initialize();
|
||||
this.container = this.getScript(Container);
|
||||
let orgScripts: OrgData[] = this.container.getScriptsInThisAndChildren(OrgData);
|
||||
let httpClient = this.injector.get(HttpClient);
|
||||
let cookieService = this.injector.get(CookieService);
|
||||
if (cookieService.get("is_auth")) {
|
||||
httpClient.get<OrgInfoModel>("esia/org")
|
||||
.toPromise()
|
||||
.then(orgInfoModel => {
|
||||
if (orgInfoModel == null) {
|
||||
return;
|
||||
}
|
||||
for (let orgData of orgScripts) {
|
||||
let control: ControlWithValue = orgData.getScriptInObject(orgData.getObjectId(),
|
||||
'component.ControlWithValue');
|
||||
control.setValue(orgInfoModel[orgData.dataId]);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,73 +1,24 @@
|
|||
import {NgModule} from "@angular/core";
|
||||
import {RouterModule, Routes} from "@angular/router";
|
||||
import {AccessDeniedComponent} from "./component/access-denied.component";
|
||||
import {LoginComponent} from "./component/login.component";
|
||||
import {AuthenticationGuard, ConfirmExitGuard, SignedInGuard, ProcessInstanceRouteResolver} from "@webbpm/base-package";
|
||||
import {RegisterComponent} from "./component/register.component";
|
||||
import {ConfirmUserEmailComponent} from "./component/confirm-user-email.component";
|
||||
import {ResetPasswordComponent} from "./component/reset-password.component";
|
||||
import {NewPasswordComponent} from "./component/new-password.component";
|
||||
import {TaskListComponent} from "./component/task-list.component";
|
||||
import {AuthGuard} from "../security/guard/auth.guard";
|
||||
import {ConfirmExitGuard} from "@webbpm/base-package";
|
||||
|
||||
const appRoutes: Routes = [
|
||||
{
|
||||
path: 'login',
|
||||
component: LoginComponent,
|
||||
canActivate: [SignedInGuard]
|
||||
},
|
||||
{
|
||||
path: 'access-denied',
|
||||
component: AccessDeniedComponent,
|
||||
canActivate: [AuthenticationGuard, ConfirmExitGuard]
|
||||
},
|
||||
{
|
||||
path: 'registration',
|
||||
component: RegisterComponent,
|
||||
canActivate: [SignedInGuard]
|
||||
},
|
||||
{
|
||||
path: 'confirm',
|
||||
component: ConfirmUserEmailComponent
|
||||
},
|
||||
{
|
||||
path: 'reset-password',
|
||||
component: ResetPasswordComponent
|
||||
},
|
||||
{
|
||||
path: 'new-password',
|
||||
component: NewPasswordComponent
|
||||
},
|
||||
{
|
||||
path: 'process',
|
||||
canActivate: [AuthenticationGuard, ConfirmExitGuard],
|
||||
children: [
|
||||
{
|
||||
path: 'instance',
|
||||
loadChildren: 'generated-sources/page-process-instance-list.module#PageprocessinstancelistModule',
|
||||
resolve: {
|
||||
processInstanceId: ProcessInstanceRouteResolver
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'instance/:processInstanceId',
|
||||
loadChildren: 'generated-sources/page-process-instance.module#PageprocessinstanceModule',
|
||||
resolve: {
|
||||
processInstanceId: ProcessInstanceRouteResolver
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'tasks',
|
||||
component: TaskListComponent,
|
||||
}
|
||||
]
|
||||
canActivate: [ConfirmExitGuard],
|
||||
},
|
||||
{
|
||||
path: 'mydata',
|
||||
loadChildren: 'generated-sources/page-mydata.module#PagemydataModule',
|
||||
canActivate: [AuthGuard],
|
||||
},
|
||||
{
|
||||
path: 'filesentlog',
|
||||
loadChildren: 'generated-sources/page-filesentlog.module#PagefilesentlogModule',
|
||||
canActivate: [AuthGuard],
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -11,25 +11,16 @@ import {
|
|||
ProgressIndicationService,
|
||||
SecurityModule
|
||||
} from "@webbpm/base-package";
|
||||
import {AdminMenuComponent} from "./component/admin-menu.component";
|
||||
import {AppHeaderComponent} from "./component/app-header.component";
|
||||
import {AppFooterComponent} from "./component/app-footer.component";
|
||||
import {LogOutComponent} from "./component/logout.component";
|
||||
import {LoginComponent} from "./component/login.component";
|
||||
import {AccessDeniedComponent} from "./component/access-denied.component";
|
||||
import {ApplicationVersionComponent} from "./component/application-version.component";
|
||||
import {RouterModule} from "@angular/router";
|
||||
import {RegisterComponent} from "./component/register.component";
|
||||
import {ConfirmUserEmailComponent} from "./component/confirm-user-email.component";
|
||||
import {InternationalPhoneNumberModule} from "ngx-international-phone-number";
|
||||
import {ResetPasswordComponent} from "./component/reset-password.component";
|
||||
import {NewPasswordComponent} from "./component/new-password.component";
|
||||
import {AppProgressIndicationComponent} from "./component/app-progress-indication.component";
|
||||
import {AppProgressIndicationService} from "./service/app-progress-indication.service";
|
||||
import {TaskListComponent} from "./component/task-list.component";
|
||||
import {ProcessListComponent} from "./component/process-list.component";
|
||||
import {TaskComponent} from "./component/task.component";
|
||||
import {TaskNotFoundComponent} from "./component/task-not-found.component";
|
||||
|
||||
import {FileUploadModule} from "ng2-file-upload";
|
||||
import {ErvuFileUpload} from "../../ervu/component/fileupload/ErvuFileUpload";
|
||||
|
||||
|
|
@ -37,20 +28,10 @@ registerLocaleData(localeRu);
|
|||
export const DIRECTIVES = [
|
||||
forwardRef(() => AppHeaderComponent),
|
||||
forwardRef(() => AppFooterComponent),
|
||||
forwardRef(() => AdminMenuComponent),
|
||||
forwardRef(() => ApplicationVersionComponent),
|
||||
forwardRef(() => LogOutComponent),
|
||||
forwardRef(() => LoginComponent),
|
||||
forwardRef(() => AccessDeniedComponent),
|
||||
forwardRef(() => RegisterComponent),
|
||||
forwardRef(() => ConfirmUserEmailComponent),
|
||||
forwardRef(() => ResetPasswordComponent),
|
||||
forwardRef(() => NewPasswordComponent),
|
||||
forwardRef(() => AppProgressIndicationComponent),
|
||||
forwardRef(() => TaskListComponent),
|
||||
forwardRef(() => ProcessListComponent),
|
||||
forwardRef(() => TaskComponent),
|
||||
forwardRef(() => TaskNotFoundComponent),
|
||||
forwardRef(() => ErvuFileUpload)
|
||||
];
|
||||
|
||||
|
|
@ -78,7 +59,7 @@ export const DIRECTIVES = [
|
|||
{ provide: ProgressIndicationService, useClass: AppProgressIndicationService }
|
||||
],
|
||||
bootstrap: [],
|
||||
entryComponents: [AppProgressIndicationComponent, TaskNotFoundComponent]
|
||||
entryComponents: [AppProgressIndicationComponent]
|
||||
})
|
||||
export class AppModule {
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,23 +0,0 @@
|
|||
import {ChangeDetectionStrategy, Component, Input} from "@angular/core";
|
||||
import {UserService, Session} from "@webbpm/base-package";
|
||||
import {NgbDropdownConfig, Placement} from "@ng-bootstrap/ng-bootstrap";
|
||||
import {Observable} from "rxjs";
|
||||
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
selector: 'admin-menu',
|
||||
templateUrl: '../../../../../src/resources/template/app/component/admin_menu.html',
|
||||
providers: [NgbDropdownConfig],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class AdminMenuComponent {
|
||||
|
||||
@Input()
|
||||
public placement: Placement = 'bottom';
|
||||
public currentSession: Observable<Session>;
|
||||
|
||||
constructor(protected userService: UserService, public config: NgbDropdownConfig) {
|
||||
this.config.placement = this.placement;
|
||||
this.currentSession = this.userService.getCurrentSession();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,5 @@
|
|||
import {ChangeDetectionStrategy, Component} from "@angular/core";
|
||||
import {Router} from "@angular/router";
|
||||
import {UserService, Session} from "@webbpm/base-package";
|
||||
import {Observable} from "rxjs";
|
||||
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
|
|
@ -11,14 +9,6 @@ import {Observable} from "rxjs";
|
|||
})
|
||||
export class AppHeaderComponent {
|
||||
|
||||
public currentSession: Observable<Session>;
|
||||
|
||||
constructor(protected userService: UserService,
|
||||
protected router: Router) {
|
||||
this.currentSession = this.userService.getCurrentSession();
|
||||
}
|
||||
|
||||
public openTaskList(): void {
|
||||
this.router.navigateByUrl("/process/tasks");
|
||||
constructor(protected router: Router) {
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,51 +0,0 @@
|
|||
import {ActivatedRoute, Router} from "@angular/router";
|
||||
import {ChangeDetectionStrategy, ChangeDetectorRef, Component, Input} from "@angular/core";
|
||||
import {Session, UserService} from "@webbpm/base-package";
|
||||
import {Observable} from "rxjs";
|
||||
|
||||
enum VerificationStatus {
|
||||
VERIFYING = "VERIFYING",
|
||||
VERIFIED = "VERIFIED",
|
||||
FAILED = "FAILED"
|
||||
}
|
||||
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
selector: "confirm",
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
templateUrl: "../../../../../src/resources/template/app/component/confirm-user-email.html"
|
||||
})
|
||||
export class ConfirmUserEmailComponent {
|
||||
public verificationStatus = VerificationStatus.VERIFYING;
|
||||
public currentSession: Observable<Session>;
|
||||
|
||||
@Input()
|
||||
public errorMessage: string;
|
||||
|
||||
constructor(private router: Router, private userService: UserService,
|
||||
private route: ActivatedRoute, private cd: ChangeDetectorRef) {
|
||||
this.currentSession = this.userService.getCurrentSession();
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
const link: string = this.route.snapshot.queryParamMap.get("link");
|
||||
// remove link from url to prevent http referer leakage
|
||||
this.router.navigate([], { relativeTo: this.route, replaceUrl: true });
|
||||
this.userService.confirm(
|
||||
link,
|
||||
(reason) => {
|
||||
this.verificationStatus = VerificationStatus.FAILED;
|
||||
if (reason.status === 404) {
|
||||
this.errorMessage = 'Ссылка недействительна. Требуется повторная регистрация.';
|
||||
}
|
||||
else {
|
||||
this.errorMessage = 'Произошла ошибка, обратитесь в службу технической поддержки!';
|
||||
}
|
||||
this.cd.markForCheck();
|
||||
})
|
||||
.then(() => {
|
||||
this.verificationStatus = VerificationStatus.VERIFIED;
|
||||
this.cd.markForCheck();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
import {Component, Input} from "@angular/core";
|
||||
import {ActivatedRoute, Router} from "@angular/router";
|
||||
import {UserService, Credentials} from "@webbpm/base-package";
|
||||
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
selector: "login",
|
||||
templateUrl: "../../../../../src/resources/template/app/component/login.html"
|
||||
})
|
||||
export class LoginComponent {
|
||||
|
||||
@Input()
|
||||
public username: string;
|
||||
|
||||
@Input()
|
||||
public password: string;
|
||||
public passwordType: boolean;
|
||||
|
||||
@Input()
|
||||
public errorMessage: string;
|
||||
|
||||
@Input()
|
||||
public confirmationSent: boolean;
|
||||
|
||||
constructor(private router: Router, private userService: UserService,
|
||||
private route: ActivatedRoute) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.confirmationSent = this.route.snapshot.queryParamMap.get('confirmationSent') === 'true';
|
||||
this.router.navigate([], { relativeTo: this.route, replaceUrl: true });
|
||||
}
|
||||
|
||||
public login(): void {
|
||||
let credentials: Credentials = new Credentials();
|
||||
credentials.username = this.username;
|
||||
credentials.password = this.password;
|
||||
|
||||
this.userService.login(credentials, "Password")
|
||||
.then(() => this.router.navigateByUrl("/"),
|
||||
(reason: any) => {
|
||||
switch (reason.status) {
|
||||
case 401: {
|
||||
this.errorMessage = "Неправильный логин или пароль";
|
||||
break;
|
||||
}
|
||||
case 404: {
|
||||
this.errorMessage = "Приложение стартует. Пожалуйста, подождите...";
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
this.errorMessage =
|
||||
"Произошла неизвестная ошибка, обратитесь в службу технической поддержки!";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public goToRegister(): void {
|
||||
this.router.navigateByUrl("/register");
|
||||
}
|
||||
|
||||
togglePasswordType(): void {
|
||||
this.passwordType = !this.passwordType;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,37 +1,52 @@
|
|||
import {Component} from "@angular/core";
|
||||
import {UserService, Session, AuthenticationMethodService} from "@webbpm/base-package";
|
||||
import {Observable} from "rxjs";
|
||||
import {Component, OnInit} from "@angular/core";
|
||||
import {Router} from "@angular/router";
|
||||
import {HttpClient} from "@angular/common/http";
|
||||
import {CookieService} from "ngx-cookie";
|
||||
import {Deferred} from "@webbpm/base-package";
|
||||
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
selector: "[log-out]",
|
||||
templateUrl: "../../../../../src/resources/template/app/component/log_out.html"
|
||||
})
|
||||
export class LogOutComponent {
|
||||
export class LogOutComponent implements OnInit{
|
||||
|
||||
public currentSession: Observable<Session>;
|
||||
private userFullname: string;
|
||||
private orgUnitName: string;
|
||||
|
||||
constructor(private userService: UserService, private authenticationMethodService: AuthenticationMethodService) {
|
||||
this.currentSession = userService.getCurrentSession();
|
||||
|
||||
constructor(private router: Router, private httpClient: HttpClient,
|
||||
private cookieService: CookieService) {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
let isAuth = this.getIsAuth();
|
||||
if (isAuth) {
|
||||
Promise.all([
|
||||
this.httpClient.get<string>("esia/userfullname").toPromise(),
|
||||
this.httpClient.get<string>("esia/orgunitname").toPromise()
|
||||
]).then(([userFullname, orgUnitName]) => {
|
||||
this.userFullname = userFullname;
|
||||
this.orgUnitName = orgUnitName;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public logout(): void {
|
||||
this.userService.logout();
|
||||
this.httpClient.get<string>("esia/logout").toPromise().then(url => {
|
||||
window.open(url, "_self");
|
||||
})
|
||||
}
|
||||
|
||||
public getCurrentUserName(): string {
|
||||
return this.userService.getCurrentUserName();
|
||||
public getUserFullname(): string {
|
||||
return this.userFullname;
|
||||
}
|
||||
|
||||
public getFullUserName(): string {
|
||||
return this.userService.getFullUserName();
|
||||
}
|
||||
|
||||
public isLogoutButtonVisible(): boolean {
|
||||
return this.authenticationMethodService.isFormAuth();
|
||||
public getIsAuth(): boolean {
|
||||
return this.cookieService.get("is_auth") != null;
|
||||
}
|
||||
|
||||
public getOrgUnitName(): string {
|
||||
return this.userService.getOrgUnitName();
|
||||
return this.orgUnitName;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,79 +0,0 @@
|
|||
import {ActivatedRoute, Router} from "@angular/router";
|
||||
import {Component, Input} from "@angular/core";
|
||||
import {Session, UserPasswordResetRequestDto, UserService} from "@webbpm/base-package";
|
||||
import {Observable} from "rxjs";
|
||||
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
selector: "newPassword",
|
||||
templateUrl: "../../../../../src/resources/template/app/component/new_password.html"
|
||||
})
|
||||
export class NewPasswordComponent {
|
||||
public currentSession: Observable<Session>;
|
||||
|
||||
private token: string;
|
||||
|
||||
@Input()
|
||||
public password: string;
|
||||
public passwordType: boolean;
|
||||
|
||||
@Input()
|
||||
public confirmPassword: string;
|
||||
public confirmPasswordType: boolean;
|
||||
|
||||
@Input()
|
||||
public errorMessage: string;
|
||||
|
||||
constructor(private router: Router, private userService: UserService,
|
||||
private route: ActivatedRoute) {
|
||||
this.currentSession = this.userService.getCurrentSession();
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.token = this.route.snapshot.queryParamMap.get("token");
|
||||
|
||||
this.router.navigate([], {relativeTo: this.route, replaceUrl: true});
|
||||
|
||||
if (this.token == undefined || this.token === '') {
|
||||
this.errorMessage = 'Ссылка недействительна. Требуется повторить восстановление пароля.';
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public changePassword(): void {
|
||||
let dto: UserPasswordResetRequestDto = new UserPasswordResetRequestDto();
|
||||
dto.password = this.password;
|
||||
dto.passwordConfirm = this.confirmPassword;
|
||||
this.userService.changePassword(dto, this.token)
|
||||
.then(() => this.router.navigateByUrl("/"),
|
||||
() => {
|
||||
this.errorMessage =
|
||||
'Произошла неизвестная ошибка, обратитесь в службу технической поддержки!';
|
||||
});
|
||||
}
|
||||
|
||||
togglePasswordType(): void {
|
||||
this.passwordType = !this.passwordType;
|
||||
}
|
||||
|
||||
toggleConfirmPasswordType(): void {
|
||||
this.confirmPasswordType = !this.confirmPasswordType;
|
||||
}
|
||||
|
||||
validPasswords(): boolean {
|
||||
if (this.password === undefined || this.confirmPassword === undefined) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let eq = this.password === this.confirmPassword;
|
||||
if (!eq) {
|
||||
this.errorMessage = 'Введенные пароли не совпадают. Убедитесь, что данные, ' +
|
||||
'введенные в поле "Подтверждение пароля", совпадают с теми, ' +
|
||||
'которые указаны в поле "Пароль".';
|
||||
}
|
||||
else {
|
||||
this.errorMessage = '';
|
||||
}
|
||||
return eq;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
import {ChangeDetectionStrategy, ChangeDetectorRef, Component, Input} from "@angular/core";
|
||||
import {Process, TaskService, ProcessDefinitionResource, ProcessService} from "@webbpm/base-package";
|
||||
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
selector: 'process',
|
||||
templateUrl: '../../../../../src/resources/template/app/component/process_list.html',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class ProcessListComponent {
|
||||
|
||||
@Input()
|
||||
public processList: Process[];
|
||||
@Input()
|
||||
public errorMessage: string;
|
||||
|
||||
constructor(private processDefinitionResource: ProcessDefinitionResource,
|
||||
private taskService: TaskService,
|
||||
private cd: ChangeDetectorRef,
|
||||
private processService: ProcessService) {
|
||||
this.processList = [];
|
||||
this.loadProcessList();
|
||||
}
|
||||
|
||||
loadProcessList() {
|
||||
this.processDefinitionResource.list().then(
|
||||
(processList) => {
|
||||
this.processList = processList;
|
||||
this.cd.markForCheck();
|
||||
},
|
||||
() => {
|
||||
this.errorMessage = "Error load process list";
|
||||
this.cd.markForCheck();
|
||||
})
|
||||
}
|
||||
|
||||
startProcess(processDefinitionId: string) {
|
||||
this.processService.start(processDefinitionId, null).then(
|
||||
(processInstanceId: number) => {
|
||||
this.taskService.startAndOpenNextTask(processInstanceId);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
import {Component, Input, ViewChild} from "@angular/core";
|
||||
import {AppConfigService, UserDto, UserService} from "@webbpm/base-package";
|
||||
import {Router} from "@angular/router";
|
||||
import {PhoneNumberComponent} from "ngx-international-phone-number";
|
||||
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
selector: "register",
|
||||
templateUrl: "../../../../../src/resources/template/app/component/register.html"
|
||||
})
|
||||
export class RegisterComponent {
|
||||
|
||||
public passwordPattern: string;
|
||||
public passwordPatternErrorMessage: string;
|
||||
public errorMessage: string;
|
||||
|
||||
@Input()
|
||||
public username: string;
|
||||
|
||||
@Input()
|
||||
public email: string;
|
||||
@ViewChild(PhoneNumberComponent)
|
||||
public phone: PhoneNumberComponent;
|
||||
public phoneNumber: string;
|
||||
|
||||
public phoneIsTouched: boolean = false;
|
||||
@Input()
|
||||
public password: string;
|
||||
|
||||
public fieldType: boolean;
|
||||
|
||||
@Input()
|
||||
public consent: string;
|
||||
|
||||
constructor(private router: Router, private userService: UserService,private appConfigService: AppConfigService) {
|
||||
this.passwordPattern = appConfigService.getParamValue("password_pattern");
|
||||
this.passwordPatternErrorMessage = appConfigService.getParamValue("password_pattern_error");
|
||||
}
|
||||
|
||||
public register(): void {
|
||||
let user: UserDto = new UserDto();
|
||||
user.username = this.username;
|
||||
user.email = this.email;
|
||||
user.name = this.username;
|
||||
user.phone = this.phone.value;
|
||||
user.password = this.password;
|
||||
|
||||
this.userService.register(user)
|
||||
.then(() => this.router.navigateByUrl("/login?confirmationSent=true"),
|
||||
(reason: any) => {
|
||||
if (reason.status === 409) {
|
||||
this.errorMessage = 'Пользователь с данным почтовым адресом уже существует';
|
||||
}
|
||||
else {
|
||||
this.errorMessage = 'Произошла неизвестная ошибка, обратитесь в службу технической поддержки!';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
toggleFieldType(): void {
|
||||
this.fieldType = !this.fieldType;
|
||||
}
|
||||
|
||||
phoneHasOnlyDialCode(): boolean {
|
||||
return this.phone.phoneNumber.trim() === this.phone.getSelectedCountryDialCode().trim()
|
||||
}
|
||||
|
||||
phoneInputFocusOut(): void {
|
||||
this.phoneIsTouched = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
import {Component, Input} from "@angular/core";
|
||||
import {UserService} from "@webbpm/base-package";
|
||||
import {Router} from "@angular/router";
|
||||
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
selector: "resetPassword",
|
||||
templateUrl: "../../../../../src/resources/template/app/component/reset_password.html"
|
||||
})
|
||||
export class ResetPasswordComponent {
|
||||
|
||||
@Input()
|
||||
public email: string;
|
||||
|
||||
@Input()
|
||||
public errorMessage: string;
|
||||
|
||||
constructor(private router: Router, private userService: UserService) {
|
||||
}
|
||||
|
||||
resetPassword(): void {
|
||||
|
||||
this.userService.resetPassword(this.email)
|
||||
.then(() => this.router.navigateByUrl("/"),
|
||||
(reason: any) => {
|
||||
this.errorMessage =
|
||||
'Произошла неизвестная ошибка, обратитесь в службу технической поддержки!';
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -1,121 +0,0 @@
|
|||
import {Component, Input} from "@angular/core";
|
||||
import {Task, TaskService, TaskStatus, TaskReference, TaskResource, ProcessVariable, UserService, RolesService, ProcessService} from "@webbpm/base-package";
|
||||
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
selector: "task-list",
|
||||
templateUrl: "../../../../../src/resources/template/app/component/task_list.html"
|
||||
})
|
||||
export class TaskListComponent {
|
||||
@Input()
|
||||
public tasks: Task[];
|
||||
|
||||
@Input()
|
||||
public onTimeTasks: Task[];
|
||||
|
||||
@Input()
|
||||
public overdueTasks: Task[];
|
||||
|
||||
@Input()
|
||||
public visibleTasks: Task[];
|
||||
|
||||
@Input()
|
||||
public showMode: string;
|
||||
|
||||
@Input()
|
||||
public errorMessage: string;
|
||||
|
||||
@Input()
|
||||
public roles: string[];
|
||||
|
||||
constructor(private taskService: TaskService,
|
||||
private $taskResource: TaskResource,
|
||||
private userService: UserService,
|
||||
private rolesService: RolesService,
|
||||
private processService: ProcessService) {
|
||||
this.tasks = [];
|
||||
this.onTimeTasks = [];
|
||||
this.overdueTasks = [];
|
||||
this.visibleTasks = [];
|
||||
this.roles = [];
|
||||
this.showMode = 'All';
|
||||
|
||||
this.rolesService.getRoles().then((roles: string[]) => {
|
||||
this.roles = roles;
|
||||
});
|
||||
|
||||
this.loadTasks();
|
||||
}
|
||||
|
||||
private loadTasks(): void {
|
||||
this.$taskResource.list()
|
||||
.then(
|
||||
(tasks: Task[]) => this.initTasks(tasks),
|
||||
() => this.errorMessage = "Error load tasks"
|
||||
);
|
||||
}
|
||||
|
||||
public startTask(task: Task): Promise<any> {
|
||||
let taskRef: TaskReference = new TaskReference();
|
||||
taskRef.processInstanceId = task.processInstanceId;
|
||||
taskRef.taskId = task.id;
|
||||
|
||||
if (task.status == TaskStatus.InProgress) {
|
||||
return this.taskService.openTask(taskRef);
|
||||
}
|
||||
else if (task.status == TaskStatus.Reserved || task.status == TaskStatus.Ready) {
|
||||
return this.taskService.startAndOpenTask(taskRef);
|
||||
}
|
||||
}
|
||||
|
||||
private initTasks(tasks: Task[]): void {
|
||||
this.tasks = tasks;
|
||||
this.filterOnTimeTasks();
|
||||
this.filterOverdueTasks();
|
||||
this.filterVisibleTasks();
|
||||
}
|
||||
|
||||
public isVisible(task: Task): boolean {
|
||||
return this.showMode == 'All' ||
|
||||
this.showMode == 'OnTime' && !this.isOverdue(task) ||
|
||||
this.showMode == 'Overdue' && this.isOverdue(task);
|
||||
}
|
||||
|
||||
public isOverdue(task: Task): boolean {
|
||||
if (!task.expirationTime) {
|
||||
return false;
|
||||
}
|
||||
return new Date(task.expirationTime).getTime() <= new Date().getTime();
|
||||
}
|
||||
|
||||
public isOnTime(task: Task): boolean {
|
||||
return !this.isOverdue(task);
|
||||
}
|
||||
|
||||
public startProcess(processDefinitionId: string, processVars?: Array<ProcessVariable | any>) {
|
||||
this.processService.start(processDefinitionId, processVars).then(
|
||||
(processInstanceId: number) => {
|
||||
this.taskService.startAndOpenNextTask(processInstanceId);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public filterOnTimeTasks() {
|
||||
this.onTimeTasks = this.tasks
|
||||
.filter((task: Task) => this.isOnTime(task));
|
||||
}
|
||||
|
||||
public filterOverdueTasks() {
|
||||
this.overdueTasks = this.tasks
|
||||
.filter((task: Task) => this.isOverdue(task));
|
||||
}
|
||||
|
||||
public filterVisibleTasks() {
|
||||
this.visibleTasks = this.tasks
|
||||
.filter((task: Task) => this.isVisible(task));
|
||||
}
|
||||
|
||||
public hasRole(role: string) {
|
||||
return this.roles.includes(role);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
import {ChangeDetectionStrategy, Component} from "@angular/core";
|
||||
import {Router} from "@angular/router";
|
||||
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
selector: 'task-not-found',
|
||||
templateUrl: '../../../../../src/resources/template/app/component/task_not_found.html',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class TaskNotFoundComponent {
|
||||
|
||||
constructor(private router: Router) {
|
||||
}
|
||||
|
||||
goToTaskList() {
|
||||
return this.router.navigateByUrl("/process/tasks");
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
import {Component} from "@angular/core";
|
||||
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
selector: "[task]",
|
||||
templateUrl: "../../../../../src/resources/template/app/component/task.html"
|
||||
})
|
||||
export class TaskComponent {
|
||||
}
|
||||
|
|
@ -1,298 +0,0 @@
|
|||
import {Injectable, OnDestroy} from "@angular/core";
|
||||
import {HttpClient} from "@angular/common/http";
|
||||
import {UserService, AppConfigService, Session} from "@webbpm/base-package";
|
||||
import {
|
||||
JivoProfileDto
|
||||
} from "../../../generated/dto/jivoprofile/JivoProfileDto";
|
||||
import {Observable, Subscription} from "rxjs";
|
||||
|
||||
declare function jivo_InitProfile(name, email, phone);
|
||||
|
||||
declare function jivo_ClearHistory();
|
||||
|
||||
@Injectable()
|
||||
export class AppJivoChatWidgetService implements OnDestroy {
|
||||
|
||||
public static LIVE_CHAT_WIDGET_API_URL: string = "jivo_chat_widget_api_url";
|
||||
public static LIVE_CHAT_WIDGET_ENABLE: string = "jivo_chat_widget_enabled";
|
||||
public static LIVE_CHAT_WIDGET_DEFAULT_VALUE: boolean = false;
|
||||
|
||||
private JIVO_CSS: string = `
|
||||
/* hide the original widget - that there were no two labels on the screen*/
|
||||
#jivo_chat_widget{
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* the default style - for offline messages if no one is online */
|
||||
#jivo_custom_widget{
|
||||
position: fixed;
|
||||
z-index: 300000;
|
||||
cursor: pointer;
|
||||
|
||||
display: block;
|
||||
right: 60px;
|
||||
bottom: 10px;
|
||||
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAABmJLR0QA/wD/AP+gvaeTAAAI1UlEQVR4nO2ca5AUVxXH/+f29MzsEkDiWkQeZRLKKgsIC6EqlJgHpCKG6G6mezL5kCqTaBmifkiV5AMp83A1QavUpEiq/BC0SqxUIjo7D2ah1oohPBQSKYnJApZgECGy4ZUlIbLz6O57/DBb5e6Ghe7e7t7H3N/HmXPPOff+p2/PvX36AgqFQqFQKBQKhUKhUCgUCoVCoVAoFAqFQqEYJ9BYJ+AWzmS0/mp1pq7rsyTwWSHlDAiRBNBEUiYBgIWoAChDyooU4rwA3rcsq7c5kThN2awztj1wx7gUpJzJXCdsexmIbhBEC5j5BgCfA6D5dOkAOE5EByTzIQA9Usq/NBWL/w4s6YAYF4JwJvMZS8o2MK8AsALA3IhCnwCwC8w79FhsK2WzZyOKOyJjJgi3t8+0YrF7wWyC6Bb4//UHhQNgN4jyupS/p0LhzFgkEbkgtVRqKYRYA+B+AMmo47ukRkRbAGyM5XLbCeCoAkciCANUS6dNYn4KwKIoYgbIOwz8MJ7PF6MQJnRBKqbZLoCnMfGEGM47gvmJWKGwNcwgoQnSb5pzdGADA+mwYowFTLRVCvFIUzZ7LAz/ImiHDJBlmo/GgMOTTQwAIOavaY5z0Eqn13IIP+hAHXJbW0tN1zcR8NUg/Y5jXtM17euUzZ4KymFggtRSqaUkRImBWUH5nAgQcJKJ2uK53N+C8BfIlGUZxu0ger3RxAAABmaDebdlGHcG4W/UglRN02CibhBNCyKhCcpVTLSlYprto3U0qinLMozbmOgPGL8LvKipkBCr9M7OP/l14FuQaiYznxxnL4Dpfn1MSojOM7A8kcv9w09zX1MWr16dIMd5BUqMT8I8g5iz/OCDvmYNX4JYzc0/BdDqp22DsNC6cOEnfhp6nrJqqdRiCLEfISwqJxkSUt4ULxb3e2nkfVCF+Jmvdo2HGBgrj408YBnG7QDu8BqkgVlpGcZtXhp4EoSJ1njLR8FED3mxd30P4UzmastxTkKtObxS0avVWbRt23k3xq6vkJptr0K4YljM/CMbmKtrWgJSLgOweyRjBk4x0X16uTxdt+1pzHwvAScv4/9NEuJLermctGx7NhE9AaAaeC8+SbKWTH7ZrbFrQYhoub983MHMmUSh8IPmfP4/WLDAjheL+/RFi1YS0HUJ8w9s216ayOV+i+7uj3HjjRcThUI2pmlLGLjUzutruqbdrHd27sWyZdaUUqlXz+XWkxDtiOIpoJSux87LPWSZj1xcQUApUShs6b/77rk103zb6ump1NLp56ijQ1qa9h3UCxAGNaAnp5RKvXY6fZdlmmesAwfOVQ3DpGz2LBE9Nsw9Sym/TdmsUzWMZ6yennLNMA5VUql5emfnqwB+F1a/BuXreuzcXyHAHH/ZXBkGdgBATNPWor7g1MH8vWo6vaA5mz0J5sND7KXcCQCS+VkALWCeQUQbAMARYscw9yeSxeLRcip1LRE9DiAOovlC09bVO0bD7QOHPJQ1uRaEgU/7S+fKEHNiIMZHgz52JPN/6waUuJQ9htp/BAAk5RBbBhIAkCTqB2AN+rze9v++QsPL2LkShNes0THQsTBgohR3dIi4bT8L5t+AaD+YH2rK54/XUqnFAOYNszcAgJm/BebtAHYBeAAANCnNwbYEXGMZxhepUDjDRA8A+CuAV+KVyo8HHsEaYfVrEMmBMbwirv/21kzzQ4S4mUjA9/V8fsj+D6dSn7KEeB3AkmHmVQAr4vn8m0NyTKeXgPnPAJqHWDP/XQdupULhgyH2hvEIiJ4PrBMjczGez1/lxtCLIEcAfN53Si4goETMv5RCnAXzYgKeZGD2COYWM28QwDYQsQTuJGAtRriSGThF9XKktwTR1cz8zQiLMI7H8/lr3Rh6EWQnAE/bAIoBmHfGC4WVbky93NR9PwVrdBjY49bWtSAC+KO/dBQa0RtubV0LEmtpeQPMF/yl1ND0adOmbXdr7H5huHGjBeBXvlJqbF6mTZsqbo09bb87sdjzGLS4UlwRyUQvemngSZCmbPYEgM2eUmpkmF9K5HKHvDTx/ChWB9aByNXefoNTdmKxp7w28iwI5fPvQ8pHvbZrQNYNzCie8FUoxwDVTLOrgarcPcFEW+O5XLufN658VY8QwPFy+T4APX7aT3KOxGu1b/h9/c13OQ91d1+wbHs1gPf8+phsENDrSPkV6uo659fHqOqrppRKvcx8FwG9o/EzSTgtiVaP9jCCURe8JQqFg5am3YTGnr6OSaJbErncqMcgsDeoBsqEtgC4OSifE4Q9OrMZ1EEDgZWEUjbbp/f1rSTmx9AYq3kG0Qt6S8vKIE99COW1aOuee5azlC8BuD4M/+OAY8T8sF4oBL4DHkrRtN7ZuVfXtFZmXg+gP4wYY0SVgWd0TVsQhhhABCc59JvmnFj90en9mLhV8zaYX5bMTyeLxaNhBors8BnLMO5kou6o4gVEFcybpRDrk7ncP6MIGIsiCAA4sdi7wpkQh7oBwL8IeDGmab+O+gytyAQRUn43qlg+OQEgT8y5WGvrXurokGORRDTHM9Xrq04AmBpFPJd8SPXCjV0s5U69WHwrynOxRiKSK6SmaY8Ts1cxjoD5BSa6hup/n68HcB2AmR79nAXRKWJ+VwIHwXwAwMF4a+vhsboKLkf452WlUvOEEIfgrRT1oG7bd1CpdHr4F9zW1lxJJlvItpOCeSrFYlPJtpugacRAjYGP4Ti2I8S5ZLl8irq7o3gHJDBCv0I0IZ5jL2IQva0LsYry+UveTKmrqx/1+X5SEuq6oGaaDzPg+vwPAgq6ECvGw+mgY0VoU1bVMBYS0T4ATS7ML4J5XbxQ+EVY+UwUQrlCOJOZTvU3k9yIsdkGvqDEqBP4PYQzmSbLcUogmn8ZsxoRbWHH+Xm8WNwXdA4TmUAF4fb2qZbjFAHceomvzxCwh4GSrmklymb7gow9WQhUEFvTFgLoIuZXIYTFzH0kxHu2bR8dj+esKxQKhUKhUCgUCoVCoVAoFAqFQqFQKBQKhUJxGf4HQacsFGPlFpMAAAAASUVORK5CYII=');
|
||||
background-size: 60px 60px;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
#jivo_custom_widget:hover{
|
||||
bottom: 13px;
|
||||
}
|
||||
|
||||
/* if there are operators online - show other label*/
|
||||
#jivo_custom_widget.jivo_online{
|
||||
height: 60px;
|
||||
width: 60px;
|
||||
background-size: 60px 60px;
|
||||
background-repeat: no-repeat;
|
||||
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAABmJLR0QA/wD/AP+gvaeTAAAI/ElEQVR4nO2cbXBU1RnH/8+5m2wgAoLYZDcJbHZj2wGsOMzIlFYFx1K0hal0ygdnqtNOlbYfmJpkE8SXWYug7CaIzPiBtjNtx9FBnFoS6ehYUcCClharCB3B3Wxe7yaAYG0DSfbe8/RDsBNSAvfe3Lt52fP7kmT3f57nufe/59yce88eQKFQKBQKhUKhUCgUCoVCoVAoFAqFQqFQKBTjBBrrAiyzi7WKdEdJAXxBFhwQLGZCcBEDU8BcBAAg6iPgAiT1SZLnSFImC0PvqKzowRoyx/gILDEuDZmb6K70wVwMphslYT4YNxJhLgDNYUiTGW0gfCQYxwE+aprir60PB1rdrNsNxoUhVZsz10ufXElESxlYCqAiR6nbCdjP4LdFVuxJbgiczlHeERkzQyq39ZSIAWONJFpNwK1w/ul3CxOEA8z8ioC2KxUtPTUWReTckEiDvkhKPEiE+wAU5Tq/RQaI0MTMv2qpDe4FEecqcW4MYaZwIrMaRI8D/LWc5HSPDwl4IlUb2J0LYzw3pLKxaxVJsXECGjGcD8Hi0Za60j1eJvHMkKotneVSiG0Avu9VjjGBeI/J2rq2aGnai/DC9YjMVNmQqZFCnMBkMwMAmL6rQR4LJ/RqMLv+gXY14Jcb9NkG43cAvuNm3HHMm5J9P2yt+1K3WwFdMyTSoC8CUzODg27FnCB0CcErkzVl/3AjmCtDViTRfQcz3spDMwCgTEo6EInrK9wINmpDIgn9HoZ8DcB0F+qZqFzDhKbKxq5Vow00qiErFM/cLohfx/id4OWaPmYsT9cF33EawLEhVQ2ZeZL5EIAZTmNMUs5JwpLW2uDHTho7GrKqtn/il8wvQplxOWYKxsuhWNrRqOHIELO/OA7gJidt84QFotj/lJOGtoesULxzoSBxBF5MKicXkgi3pGqDR+w0sn1SBYmEk3Z5iGAgYbuRHXEk0X0HgDvtJslbGMtC8cztdprYMkQSP2ivIoUAP2BHb/kaUr61Y1ahqXVBzTns0mcY2WD7w3PPWRFb7iF+UyyHt2ZkwfxLIWXFlN5zfpa0GMCBK+i7QXyv8PtnFMiC6cy0BkDXSGJifo8Ef0P4e4uy0ihj4FEA/W4fxGUo0nyF37Iq9lkVShJLiL17YCbAP0jWlTUBAGIsUE+HEeNl4eLu3QCvHKpl4FNDGos66ufoYCY8AUKMXq7anNknC/gogNJh4d9MhYIrsIZMxFggRjqATZVx/W9EeB0eP6gj5iUAdlnRWu4hBF7suKKrxWZqTkbLmiKNXRXhhP5BuDjTF47rWxEj6dOMnwEwh+kf66ifo4fjmbvDDZlT4eLMmXCDvjq5IXCaiNYPC8+CtZ9iDZmRhP5kuDhzIZzQj1fFeyLpuuAbAL3k1XH9r14b5866IUzlzsq5Okz8NgCwpGoMTjgLQHio6unM/JPVFV0ATgzVm8z7LhbVCGA2gJlgbAMANgZjDaE9WVeSCj2VCTHwCIBCAPOYzHoAIPo/veswkeVlTZYNYfB1zsqxFN1/8ee/hrxomj7+z8Xf/UPVRPKLv4fqB38X5iXaL9pqPjoPIDsk56Be8nC9F1g+d5YMWbSDCzDspLgJMb6HGIsCWdjIwO8BHAH4gXRtsC0U71wIIDJUL0D3AABB/ARMewnYLxj3DwYTq4eFL61KdH49FS09BeL7AfwdwItZw9gMZmIxGMtjii6ew6ti+WIWTuifwdubiRtaosFL7v+EnklfS4b/LQJuHqbtl0Isba0pfW/oi1WNXTdLSX8BMHWY/p+FWXnbxxvKPx36YiShr2PgWdeOYGR6W6LBa6wI7RhyEsANjkuyADE1M+jXknBag1zIwGMAykaQZxm8jVn8iQQzMVYAqMbIPbkbRBsl0fvC5Fkg/jFytwijrSUaDFkRWjYkktD3MWDrNoBiEAb2paPBZVa0li/qkuH4KVi+I4CDNrSWlX92VI0CDHrXqtayIbOmBd4F8LmjivKbs7K3b69VsWVDjqylLIDfOCopj2GiF1pjlX1W9fYeNJl4FpdMrhRXQWoGdthpYMuQlvXBdgJ22qspf2Hg+eT6wHE7bWw/ijV8BfUALN3bz3MukInH7TaybUjbQ9dnAK6x2y7fIOb6lvXBdtvtHGVjpnBD5lXkzyp3exDvaakJrnLyjStnq0eIWPj99wJ01FH7yc1JH+hHTr/+5ng5T3LddZ9nZfYuAB1OY0w2CKRLg759sjZ4xmmMUa2v6qifoxPE3QTSRxNnUsDokTDuGu1mBKNe8JaKlh7TNOOWPB++0oB5azpaMepz4NrD/YvLhJoAfNOtmBOEgwSx2q2NBlxbEtpZXXF2Tm9gGcDrkR+zeWZg+8zpgWVu7vrgyfKXSGPXEmnS80QIexF/HJBm4rXp2jLX74B7smg6VVN2aGqx7yYCNgE470WOMaKfGU8OaOZ8L8wAcrCTQ9WWznKp0UYw3YeJu2reYOAFjbWNybqSlJeJcrb5TCSur2DCa7nK5xL9DOwkNje11FV8kouElpeSjj6TmYQ51jswWYMZLQK8gwzx21zvoZUzQ9jQfj4+tksbkXYAr4Dwh3Rv4BBiJMeiiJycotAz6WuF4W8HMC0X+SzyGUDvMGG/AO9L1QTez+W+WCORkx6iGYWPsH0zTjLTdoBLiRAm5jCDKkEosRnnNBjdICQZOAamjyTzsbYLgROX9IJam1E9wvv/suI9EUnmcdhbinqMC7Q7078o6Rn+RjCmTy0qwmwUyCJiMY2YpjFhCksQSA5IaP/WSBoSOKMV9nYn192Qi++AuIbnPYQht8KeGR+ILC1PRksuezHVY8HzGBzvJyWezgsiCX0tE9vZ/+OPMIuWjofdQccKz4asSKJ7AUMeBjDFgryXmerTdYHnvKpnouBJDwk/fXYGQ74ES2bQTiHlV5UZg7h+DSnf2jEFZl8zgHlXkA0QoUma1JCuDxx2u4aJjKuGfGXL6WlZc2A3gNsu8/YpAAeJqbnfZzR3VlecdTP3ZMFVQ0zRvwAQrwL8BkBZYjrLmtkhB7TUeNxnXaFQKBQKhUKhUCgUCoVCoVAoFAqFQqFQKBSKK/Bf/RI0U2U6gOkAAAAASUVORK5CYII=');
|
||||
}`;
|
||||
|
||||
private JIVO_JS: string = `
|
||||
/* Callback function that is called immediately after JivoChat is loaded */
|
||||
function jivo_onLoadCallback() {
|
||||
window.jivo_cstm_widget = document.createElement('div');
|
||||
jivo_cstm_widget.setAttribute('id', 'jivo_custom_widget');
|
||||
document.body.appendChild(jivo_cstm_widget);
|
||||
|
||||
/* Adds handlers click on the icon - to maximize the window when clicked */
|
||||
jivo_cstm_widget.onclick = function () {
|
||||
jivo_api.open();
|
||||
}
|
||||
|
||||
/* Change the CSS class if there are agents online */
|
||||
if (jivo_config.chat_mode === "online") {
|
||||
jivo_cstm_widget.setAttribute("class", "jivo_online");
|
||||
}
|
||||
|
||||
/* Show the user a shortcut */
|
||||
window.jivo_cstm_widget.style.display = 'block';
|
||||
}
|
||||
|
||||
/*
|
||||
Callback function jivo_onOpen and jivo_onClose called whenever the chat window JivoChat
|
||||
is expanded or collapsed by the user or by the proactive invitations rule.
|
||||
*/
|
||||
function jivo_onOpen() {
|
||||
/* If chat is deployed - hide shortcut */
|
||||
if (jivo_cstm_widget)
|
||||
jivo_cstm_widget.style.display = 'none';
|
||||
}
|
||||
|
||||
function jivo_onClose() {
|
||||
/* If chat is minimized - show label */
|
||||
if (jivo_cstm_widget)
|
||||
jivo_cstm_widget.style.display = 'block';
|
||||
}
|
||||
|
||||
function jivo_ClearHistory() {
|
||||
jivo_api.clearHistory();
|
||||
jivo_api.close();
|
||||
}
|
||||
|
||||
function jivo_InitProfile(name, email, phone) {
|
||||
let chatMode = jivo_api.chatMode();
|
||||
|
||||
let args = {
|
||||
name: name ? name : '',
|
||||
email: email ? email : '',
|
||||
phone: phone ? phone : ''
|
||||
};
|
||||
|
||||
if (chatMode === 'offline') {
|
||||
jivo_api.sendOfflineMessage(args);
|
||||
}
|
||||
else {
|
||||
jivo_api.setContactInfo(args);
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
private currentUserName: string;
|
||||
private currentEmail: string;
|
||||
private currentPhone: string;
|
||||
|
||||
private jsLoaded = false;
|
||||
private jivoWidgetApiUrl: string;
|
||||
|
||||
private currentSession: Observable<Session>;
|
||||
private currentSessionSubscription: Subscription;
|
||||
private session: Session;
|
||||
private sessionInitJivoChatWidget: boolean;
|
||||
|
||||
constructor(private httpClient: HttpClient,
|
||||
private appConfigService: AppConfigService,
|
||||
private userService: UserService) {
|
||||
|
||||
this.currentSession = userService.getCurrentSession();
|
||||
this.currentSessionSubscription =
|
||||
this.currentSession.subscribe(val => {
|
||||
|
||||
if (!this.sessionInitJivoChatWidget || !this.session) {
|
||||
this.initJivoChatWidget();
|
||||
this.sessionInitJivoChatWidget = true;
|
||||
}
|
||||
|
||||
if (this.session && !val) {
|
||||
// logout
|
||||
this.clearJivoProfile();
|
||||
this.session = null;
|
||||
this.sessionInitJivoChatWidget = false;
|
||||
}
|
||||
|
||||
if (val) {
|
||||
this.session = val;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private initJivoChatWidget() {
|
||||
let liveChatWidgetEnabled = this.getValueFromAppConfig(
|
||||
AppJivoChatWidgetService.LIVE_CHAT_WIDGET_ENABLE,
|
||||
AppJivoChatWidgetService.LIVE_CHAT_WIDGET_DEFAULT_VALUE);
|
||||
|
||||
if (liveChatWidgetEnabled) {
|
||||
this.jivoWidgetApiUrl = this.getValueFromAppConfig(
|
||||
AppJivoChatWidgetService.LIVE_CHAT_WIDGET_API_URL,
|
||||
'');
|
||||
|
||||
if (!this.jivoWidgetApiUrl) {
|
||||
throw new Error(
|
||||
`The configuration file does not contain the 'Jivo API url'. Please check that '${AppJivoChatWidgetService.LIVE_CHAT_WIDGET_API_URL}' has data`);
|
||||
}
|
||||
|
||||
let userId = this.userService.getCurrentUserId();
|
||||
if (userId) {
|
||||
this.clearJivoProfile();
|
||||
this.httpClient.get('profile/jivo/' + userId)
|
||||
.toPromise()
|
||||
.then((profile: JivoProfileDto) => {
|
||||
|
||||
this.currentUserName = profile.username;
|
||||
this.currentEmail = profile.email;
|
||||
this.currentPhone = profile.phone;
|
||||
|
||||
let initProfileFunction = () => this.initProfile(this.currentUserName,
|
||||
this.currentEmail,
|
||||
this.currentPhone);
|
||||
this.loadScripts(initProfileFunction);
|
||||
});
|
||||
}
|
||||
else {
|
||||
let initProfileFunction = () => this.initProfile(this.currentUserName, this.currentEmail,
|
||||
this.currentPhone);
|
||||
this.loadScripts(initProfileFunction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private clearJivoProfile() {
|
||||
this.clearProfileData();
|
||||
try {
|
||||
jivo_ClearHistory();
|
||||
}
|
||||
catch (ignore) {
|
||||
}
|
||||
}
|
||||
|
||||
private clearProfileData() {
|
||||
this.currentUserName = '';
|
||||
this.currentEmail = '';
|
||||
this.currentPhone = '';
|
||||
}
|
||||
|
||||
private loadScripts(initProfileFunction): void {
|
||||
let afterLoadMainJs = () => {
|
||||
this.loadScriptJsContent('jivoCustomJs', this.JIVO_JS, initProfileFunction);
|
||||
}
|
||||
this.loadScript('jivoWidget', this.jivoWidgetApiUrl, true, afterLoadMainJs);
|
||||
this.loadStyleContent('jivoCustomCss', this.JIVO_CSS);
|
||||
}
|
||||
|
||||
private initProfile(username: string, email: string, phone: string): void {
|
||||
try {
|
||||
jivo_InitProfile(username, email, phone);
|
||||
}
|
||||
catch (e) {
|
||||
if (e instanceof ReferenceError) {
|
||||
if (!this.jsLoaded) {
|
||||
this.jsLoaded = true;
|
||||
setTimeout(() => {
|
||||
jivo_InitProfile(username, email, phone);
|
||||
}, 3000);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private loadScript(elementId, js, async, callback): void {
|
||||
let jivoJsLink = document.getElementById(elementId);
|
||||
if (!jivoJsLink) {
|
||||
let node = document.createElement('script');
|
||||
node.src = js;
|
||||
node.type = 'text/javascript';
|
||||
node.id = elementId;
|
||||
node.async = async;
|
||||
node.charset = 'utf-8';
|
||||
if (callback) {
|
||||
node.onload = function () {
|
||||
callback();
|
||||
};
|
||||
}
|
||||
document.getElementsByTagName('head')[0].appendChild(node);
|
||||
}
|
||||
else {
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private loadScriptJsContent(elementId, js, callback): void {
|
||||
let jivoJs = document.getElementById(elementId);
|
||||
if (!jivoJs) {
|
||||
let node = document.createElement('script');
|
||||
node.innerHTML = js;
|
||||
node.type = 'text/javascript';
|
||||
node.id = elementId;
|
||||
node.charset = 'utf-8';
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
document.getElementsByTagName('head')[0].appendChild(node);
|
||||
}
|
||||
else {
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private loadStyleContent(elementId, styleCss): void {
|
||||
let jivoCss = document.getElementById(elementId);
|
||||
if (!jivoCss) {
|
||||
const style = document.createElement('style');
|
||||
style.id = elementId;
|
||||
style.innerHTML = styleCss;
|
||||
document.getElementsByTagName('head')[0].appendChild(style);
|
||||
}
|
||||
}
|
||||
|
||||
private getValueFromAppConfig(key, defaultValue) {
|
||||
let enabled = this.appConfigService.getParamValue(key);
|
||||
if (enabled === undefined) {
|
||||
return defaultValue;
|
||||
}
|
||||
return enabled;
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.currentSessionSubscription.unsubscribe();
|
||||
}
|
||||
|
||||
}
|
||||
61
frontend/src/ts/modules/security/guard/auth.guard.ts
Normal file
61
frontend/src/ts/modules/security/guard/auth.guard.ts
Normal 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, "_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');
|
||||
}
|
||||
}
|
||||
|
|
@ -8,7 +8,6 @@ import {
|
|||
Router
|
||||
} from "@angular/router";
|
||||
import {ProgressIndicationService} from "@webbpm/base-package";
|
||||
import {AppJivoChatWidgetService} from "../../app/service/app-jivo-chat.service";
|
||||
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
|
|
@ -20,8 +19,7 @@ export class WebbpmComponent {
|
|||
public footerVisible: boolean = true;
|
||||
|
||||
constructor(private router: Router,
|
||||
private progressIndicationService: ProgressIndicationService,
|
||||
private appJivoChatWidgetService: AppJivoChatWidgetService) {
|
||||
private progressIndicationService: ProgressIndicationService) {
|
||||
router.events.subscribe((event: Event) => {
|
||||
if (event instanceof NavigationStart) {
|
||||
progressIndicationService.showProgressBar();
|
||||
|
|
|
|||
|
|
@ -1,88 +0,0 @@
|
|||
import {RouterModule, Routes} from "@angular/router";
|
||||
import {NgModule} from "@angular/core";
|
||||
import {
|
||||
AuthenticationGuard,
|
||||
ConfirmExitGuard
|
||||
} from "@webbpm/base-package";
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: 'user-management',
|
||||
canActivate: [AuthenticationGuard],
|
||||
children: [
|
||||
{
|
||||
path: 'users',
|
||||
loadChildren: 'generated-sources/page-user-management-users.module#PageusermanagementusersModule',
|
||||
canActivate: [ConfirmExitGuard]
|
||||
},
|
||||
{
|
||||
path: 'users/new',
|
||||
loadChildren: 'generated-sources/page-user-management-user-create.module#PageusermanagementusercreateModule',
|
||||
canActivate: [ConfirmExitGuard]
|
||||
},
|
||||
{
|
||||
path: 'users/:id',
|
||||
loadChildren: 'generated-sources/page-user-management-user-edit.module#PageusermanagementusereditModule',
|
||||
canActivate: [ConfirmExitGuard]
|
||||
},
|
||||
{
|
||||
path: 'org-units',
|
||||
loadChildren: 'generated-sources/page-user-management-org-units.module#PageusermanagementorgunitsModule',
|
||||
canActivate: [ConfirmExitGuard]
|
||||
},
|
||||
{
|
||||
path: 'org-units/new',
|
||||
loadChildren: 'generated-sources/page-user-management-org-unit.module#PageusermanagementorgunitModule',
|
||||
canActivate: [ConfirmExitGuard]
|
||||
},
|
||||
{
|
||||
path: 'org-units/:id',
|
||||
loadChildren: 'generated-sources/page-user-management-org-unit.module#PageusermanagementorgunitModule',
|
||||
canActivate: [ConfirmExitGuard]
|
||||
},
|
||||
{
|
||||
path: 'roles',
|
||||
loadChildren: 'generated-sources/page-user-management-roles.module#PageusermanagementrolesModule',
|
||||
canActivate: [ConfirmExitGuard]
|
||||
},
|
||||
{
|
||||
path: 'roles/new',
|
||||
loadChildren: 'generated-sources/page-user-management-role.module#PageusermanagementroleModule',
|
||||
canActivate: [ConfirmExitGuard]
|
||||
},
|
||||
{
|
||||
path: 'roles/:id',
|
||||
loadChildren: 'generated-sources/page-user-management-role.module#PageusermanagementroleModule',
|
||||
canActivate: [ConfirmExitGuard]
|
||||
},
|
||||
{
|
||||
path: 'groups',
|
||||
loadChildren: 'generated-sources/page-user-management-groups.module#PageusermanagementgroupsModule',
|
||||
canActivate: [ConfirmExitGuard]
|
||||
},
|
||||
{
|
||||
path: 'groups/new',
|
||||
loadChildren: 'generated-sources/page-user-management-group-create.module#PageusermanagementgroupcreateModule',
|
||||
canActivate: [ConfirmExitGuard]
|
||||
},
|
||||
{
|
||||
path: 'groups/:id',
|
||||
loadChildren: 'generated-sources/page-user-management-group-edit.module#PageusermanagementgroupeditModule',
|
||||
canActivate: [ConfirmExitGuard]
|
||||
},
|
||||
{
|
||||
path: 'authorities',
|
||||
loadChildren: 'generated-sources/page-user-management-authorities.module#PageusermanagementauthoritiesModule',
|
||||
canActivate: [ConfirmExitGuard]
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class UserManagementRoutingModule {
|
||||
|
||||
}
|
||||
|
|
@ -1,38 +1,14 @@
|
|||
import {NgModule} from "@angular/core";
|
||||
import {RouterModule, Routes} from "@angular/router";
|
||||
import {HomeComponent} from "./component/home.component";
|
||||
import {
|
||||
AuthenticationGuard,
|
||||
HistoryLocationGuard,
|
||||
TaskPageRouteResolver,
|
||||
ConfirmExitGuard
|
||||
} from "@webbpm/base-package";
|
||||
import {DYNAMIC_ROUTING} from "../../page.routing";
|
||||
import {TaskComponent} from "./../app/component/task.component";
|
||||
import {TaskNotFoundComponent} from "./../app/component/task-not-found.component";
|
||||
import {AuthGuard} from "../security/guard/auth.guard";
|
||||
|
||||
const webbpmRoutes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
loadChildren: 'generated-sources/page-lkul.module#PagelkulModule',
|
||||
canActivate: [AuthenticationGuard, ConfirmExitGuard],
|
||||
canActivate: [AuthGuard],
|
||||
pathMatch: 'full',
|
||||
},
|
||||
{
|
||||
path: 'process/:processInstanceId/task/:taskId',
|
||||
component: TaskComponent,
|
||||
children: DYNAMIC_ROUTING,
|
||||
canActivate: [HistoryLocationGuard],
|
||||
resolve: {
|
||||
taskPage: TaskPageRouteResolver
|
||||
},
|
||||
runGuardsAndResolvers: "always"
|
||||
},
|
||||
{
|
||||
path: 'process/task-not-found',
|
||||
component: TaskNotFoundComponent,
|
||||
canActivate: [AuthenticationGuard]
|
||||
},
|
||||
{
|
||||
path: '**',
|
||||
redirectTo: '',
|
||||
|
|
|
|||
|
|
@ -13,13 +13,8 @@ import {
|
|||
BpmnModule,
|
||||
ComponentsModule,
|
||||
CoreModule,
|
||||
SecurityModule,
|
||||
} from "@webbpm/base-package";
|
||||
import {TaskParamsProvider} from "@webbpm/base-package";
|
||||
import {ProcessInstanceParamsProvider} from "@webbpm/base-package";
|
||||
import {AppRoutingModule} from "../app/app-routing.module";
|
||||
import {AppJivoChatWidgetService} from "../app/service/app-jivo-chat.service";
|
||||
import {UserManagementRoutingModule} from "./user-management-routing.module";
|
||||
import {GlobalErrorHandler} from "./handler/global-error.handler.prod";
|
||||
import {DEFAULT_HTTP_INTERCEPTOR_PROVIDERS} from "./interceptor/default-interceptors.prod";
|
||||
|
||||
|
|
@ -31,11 +26,9 @@ let IMPORTS = [
|
|||
ToastNoAnimationModule.forRoot(),
|
||||
AgGridModule,
|
||||
AppRoutingModule,
|
||||
UserManagementRoutingModule,
|
||||
BpmnModule,
|
||||
CoreModule,
|
||||
ComponentsModule,
|
||||
SecurityModule,
|
||||
AppModule,
|
||||
WebbpmRoutingModule
|
||||
];
|
||||
|
|
@ -48,9 +41,6 @@ let IMPORTS = [
|
|||
],
|
||||
exports: [],
|
||||
providers: [
|
||||
TaskParamsProvider,
|
||||
ProcessInstanceParamsProvider,
|
||||
AppJivoChatWidgetService,
|
||||
{provide: ErrorHandler, useClass: GlobalErrorHandler},
|
||||
DEFAULT_HTTP_INTERCEPTOR_PROVIDERS
|
||||
],
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>ru.cg.webbpm.packages.base</groupId>
|
||||
<artifactId>resources</artifactId>
|
||||
<version>3.177.0</version>
|
||||
<version>3.178.2</version>
|
||||
<organization>
|
||||
<name>Micord</name>
|
||||
</organization>
|
||||
|
|
@ -28,13 +28,13 @@
|
|||
<jooq.version>3.19.3</jooq.version>
|
||||
<jupiter.version>5.10.2</jupiter.version>
|
||||
<enforcer.manageVersions>true</enforcer.manageVersions>
|
||||
<webbpm-platform.version>3.177.0</webbpm-platform.version>
|
||||
<webbpm-platform.version>3.178.2</webbpm-platform.version>
|
||||
<h2.version>1.4.200</h2.version>
|
||||
<build.timestamp>0812074142</build.timestamp>
|
||||
<build.timestamp>0829133121</build.timestamp>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<junit.platform.version>1.10.0</junit.platform.version>
|
||||
<enforcer.manageExclusions>true</enforcer.manageExclusions>
|
||||
<revision>3.177.0</revision>
|
||||
<revision>3.178.2</revision>
|
||||
<metadata.ts.filename>typescript.metadata.json</metadata.ts.filename>
|
||||
<package.repository.url>https://repo.micord.ru</package.repository.url>
|
||||
<maven.build.timestamp.format>MMddHHmmss</maven.build.timestamp.format>
|
||||
|
|
@ -47,19 +47,19 @@
|
|||
<dependency>
|
||||
<groupId>ru.cg.webbpm.packages.base</groupId>
|
||||
<artifactId>converters</artifactId>
|
||||
<version>3.177.0</version>
|
||||
<version>3.178.2</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.cg.webbpm.packages.base</groupId>
|
||||
<artifactId>backend</artifactId>
|
||||
<version>3.177.0</version>
|
||||
<version>3.178.2</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.cg.webbpm.packages.base</groupId>
|
||||
<artifactId>frontend</artifactId>
|
||||
<version>3.177.0</version>
|
||||
<version>3.178.2</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@
|
|||
<ul>
|
||||
|
||||
<li>Образец внешней ссылки: <code>https://www.wildberries.ru/catalog/${sku}/detail.aspx</code></li>
|
||||
<li>Образец внутренней ссылки: <code>products/ru.cg.webbpm.packages.base:resources:jar:3.177.0</code></li>
|
||||
<li>Образец внутренней ссылки: <code>products/ru.cg.webbpm.packages.base:resources:jar:3.178.2</code></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
|
|
|
|||
|
|
@ -4,17 +4,17 @@
|
|||
<description>Base webbpm package</description>
|
||||
<groupId>ru.cg.webbpm.packages.base</groupId>
|
||||
<artifactId>resources</artifactId>
|
||||
<version>3.177.0</version>
|
||||
<studioVersion>3.177.0</studioVersion>
|
||||
<version>3.178.2</version>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
|
||||
<backendModule>
|
||||
<groupId>ru.cg.webbpm.packages.base</groupId>
|
||||
<artifactId>backend</artifactId>
|
||||
<version>3.177.0</version>
|
||||
<version>3.178.2</version>
|
||||
</backendModule>
|
||||
<frontendModule>
|
||||
<packageName>@webbpm/base-package</packageName>
|
||||
<version>3.177.0</version>
|
||||
<version>3.178.2</version>
|
||||
</frontendModule>
|
||||
</packageInfo>
|
||||
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@
|
|||
<documentation>component/buttons/Кнопка.html</documentation>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.177.0</studioVersion>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.177.0</value>
|
||||
<value>3.178.2</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@
|
|||
<documentation>component/buttons/Кнопка_отмены.html</documentation>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.177.0</studioVersion>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.177.0</value>
|
||||
<value>3.178.2</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@
|
|||
<documentation>component/buttons/Кнопка_очистки_фильтра.html</documentation>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.177.0</studioVersion>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.177.0</value>
|
||||
<value>3.178.2</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@
|
|||
<documentation>component/buttons/Кнопка_удаления.html</documentation>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.177.0</studioVersion>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.177.0</value>
|
||||
<value>3.178.2</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@
|
|||
<documentation>component/buttons/Кнопка_загрузки.html</documentation>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.177.0</studioVersion>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.177.0</value>
|
||||
<value>3.178.2</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@
|
|||
<documentation>component/buttons/Кнопка_вызова_ошибки.html</documentation>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.177.0</studioVersion>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.177.0</value>
|
||||
<value>3.178.2</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -7,11 +7,11 @@
|
|||
<documentation>component/buttons/Кнопка_выполнения_бизнес-процесса.html</documentation>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.177.0</studioVersion>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.177.0</value>
|
||||
<value>3.178.2</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@
|
|||
<documentation>component/buttons/Кнопка_выполнения_SQL.html</documentation>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.177.0</studioVersion>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.177.0</value>
|
||||
<value>3.178.2</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@
|
|||
<documentation>component/buttons/Кнопка_для_фильтрации.html</documentation>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.177.0</studioVersion>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.177.0</value>
|
||||
<value>3.178.2</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@
|
|||
<documentation>component/buttons/Кнопка_навигации.html</documentation>
|
||||
<internal>false</internal>
|
||||
<versions>
|
||||
<studioVersion>3.177.0</studioVersion>
|
||||
<studioVersion>3.178.2</studioVersion>
|
||||
<packageVersions>
|
||||
<entry>
|
||||
<key>ru.cg.webbpm.packages.base.resources</key>
|
||||
<value>3.177.0</value>
|
||||
<value>3.178.2</value>
|
||||
</entry>
|
||||
</packageVersions>
|
||||
</versions>
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue