Merge branch 'hotfix/1.9.4'

This commit is contained in:
Zaripov Emil 2025-01-08 16:31:48 +03:00
commit 8530edcaea
19 changed files with 202 additions and 137 deletions

View file

@ -5,7 +5,7 @@
<parent> <parent>
<groupId>ru.micord.ervu.lkrp</groupId> <groupId>ru.micord.ervu.lkrp</groupId>
<artifactId>fl</artifactId> <artifactId>fl</artifactId>
<version>1.9.3-SNAPSHOT</version> <version>1.9.4-SNAPSHOT</version>
</parent> </parent>
<groupId>ru.micord.ervu.lkrp.fl</groupId> <groupId>ru.micord.ervu.lkrp.fl</groupId>
<artifactId>backend</artifactId> <artifactId>backend</artifactId>

View file

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

View file

@ -25,9 +25,7 @@ public class LogoutSuccessHandler
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws IOException { Authentication authentication) throws IOException {
String url = esiaAuthService.logout(request, response); String url = esiaAuthService.logout(request, response);
response.setStatus(HttpServletResponse.SC_OK); response.sendRedirect(url);
response.getWriter().write(url);
response.getWriter().flush();
CsrfToken csrfToken = this.csrfTokenRepository.generateToken(request); CsrfToken csrfToken = this.csrfTokenRepository.generateToken(request);
this.csrfTokenRepository.saveToken(csrfToken, request, response); this.csrfTokenRepository.saveToken(csrfToken, request, response);
} }

View file

@ -23,6 +23,9 @@ public class EsiaConfig {
@Value("${esia.redirect.url}") @Value("${esia.redirect.url}")
private String redirectUrl; private String redirectUrl;
@Value("${esia.logout.redirect.url}")
private String logoutRedirectUrl;
@Value("${sign.url}") @Value("${sign.url}")
private String signUrl; private String signUrl;
@ -86,4 +89,8 @@ public class EsiaConfig {
public String getEsiaTokenUrl() { public String getEsiaTokenUrl() {
return esiaTokenUrl; return esiaTokenUrl;
} }
public String getLogoutRedirectUrl() {
return logoutRedirectUrl;
}
} }

View file

@ -13,7 +13,6 @@ import java.time.format.DateTimeFormatter;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
@ -111,7 +110,7 @@ public class EsiaAuthService {
"redirect_uri", redirectUrlEncoded, "redirect_uri", redirectUrlEncoded,
"client_certificate_hash", esiaConfig.getClientCertHash()); "client_certificate_hash", esiaConfig.getClientCertHash());
return makeRequest(url, params); return buildUrl(url, params);
} }
catch (Exception e) { catch (Exception e) {
throw new RuntimeException(e); throw new RuntimeException(e);
@ -134,12 +133,13 @@ public class EsiaAuthService {
.replace("+", "%20"); .replace("+", "%20");
} }
private static String makeRequest(URL url, Map<String, String> params) { private static String buildUrl(URL url, Map<String, String> params) {
StringBuilder uriBuilder = new StringBuilder(url.toString()); StringBuilder uriBuilder = new StringBuilder(url.toString());
uriBuilder.append('?'); uriBuilder.append('?');
for (Map.Entry<String, String> node : params.entrySet()) { for (Map.Entry<String, String> node : params.entrySet()) {
uriBuilder.append(node.getKey()).append('=').append(node.getValue()).append("&"); uriBuilder.append(node.getKey()).append('=').append(node.getValue()).append("&");
} }
uriBuilder.deleteCharAt(uriBuilder.length() - 1);
return uriBuilder.toString(); return uriBuilder.toString();
} }
@ -204,8 +204,7 @@ public class EsiaAuthService {
Response ervuIdResponse = getErvuIdResponse(esiaAccessTokenStr); Response ervuIdResponse = getErvuIdResponse(esiaAccessTokenStr);
Token token = jwtTokenService.createAccessToken(esiaAccessToken.getSbj_id(), expiresIn, ervuIdResponse.getErvuId()); Token token = jwtTokenService.createAccessToken(esiaAccessToken.getSbj_id(), expiresIn, ervuIdResponse.getErvuId());
int expiry = tokenResponse.getExpires_in().intValue(); int expiry = tokenResponse.getExpires_in().intValue();
Cookie accessCookie = securityHelper.createAccessCookie(token.getValue(), expiry); securityHelper.addAccessCookies(response, token.getValue(), expiry);
response.addCookie(accessCookie);
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
new UsernamePasswordAuthenticationToken(token.getUserAccountId(), null); new UsernamePasswordAuthenticationToken(token.getUserAccountId(), null);
SecurityContext context = SecurityContextHolder.createEmptyContext(); SecurityContext context = SecurityContextHolder.createEmptyContext();
@ -214,8 +213,6 @@ public class EsiaAuthService {
authenticationManager.authenticate(jwtAuthentication); authenticationManager.authenticate(jwtAuthentication);
context.setAuthentication(jwtAuthentication); context.setAuthentication(jwtAuthentication);
SecurityContextHolder.setContext(context); SecurityContextHolder.setContext(context);
Cookie authMarkerCookie = securityHelper.createAuthMarkerCookie("true", expiry);
response.addCookie(authMarkerCookie);
return ResponseEntity.ok("Authentication successful"); return ResponseEntity.ok("Authentication successful");
} }
catch (Exception e) { catch (Exception e) {
@ -281,8 +278,7 @@ public class EsiaAuthService {
Response ervuIdResponse = getErvuIdResponse(esiaAccessTokenStr); Response ervuIdResponse = getErvuIdResponse(esiaAccessTokenStr);
Token token = jwtTokenService.createAccessToken(esiaAccessToken.getSbj_id(), expiresIn, ervuIdResponse.getErvuId()); Token token = jwtTokenService.createAccessToken(esiaAccessToken.getSbj_id(), expiresIn, ervuIdResponse.getErvuId());
int expiry = tokenResponse.getExpires_in().intValue(); int expiry = tokenResponse.getExpires_in().intValue();
Cookie accessCookie = securityHelper.createAccessCookie(token.getValue(), expiry); securityHelper.addAccessCookies(response, token.getValue(), expiry);
response.addCookie(accessCookie);
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
new UsernamePasswordAuthenticationToken(token.getUserAccountId(), null); new UsernamePasswordAuthenticationToken(token.getUserAccountId(), null);
SecurityContext context = SecurityContextHolder.createEmptyContext(); SecurityContext context = SecurityContextHolder.createEmptyContext();
@ -291,8 +287,6 @@ public class EsiaAuthService {
authenticationManager.authenticate(jwtAuthentication); authenticationManager.authenticate(jwtAuthentication);
context.setAuthentication(jwtAuthentication); context.setAuthentication(jwtAuthentication);
SecurityContextHolder.setContext(context); SecurityContextHolder.setContext(context);
Cookie authMarkerCookie = securityHelper.createAuthMarkerCookie("true", expiry);
response.addCookie(authMarkerCookie);
} }
catch (Exception e) { catch (Exception e) {
throw new RuntimeException(e); throw new RuntimeException(e);
@ -338,12 +332,12 @@ public class EsiaAuthService {
EsiaTokensStore.removeAccessToken(userId); EsiaTokensStore.removeAccessToken(userId);
EsiaTokensStore.removeRefreshToken(userId); EsiaTokensStore.removeRefreshToken(userId);
String logoutUrl = esiaConfig.getEsiaBaseUri() + esiaConfig.getEsiaLogoutUrl(); String logoutUrl = esiaConfig.getEsiaBaseUri() + esiaConfig.getEsiaLogoutUrl();
String redirectUrl = esiaConfig.getRedirectUrl(); String redirectUrl = esiaConfig.getLogoutRedirectUrl();
URL url = new URL(logoutUrl); URL url = new URL(logoutUrl);
Map<String, String> params = mapOf( Map<String, String> params = mapOf(
"client_id", esiaConfig.getClientId(), "client_id", esiaConfig.getClientId(),
"redirect_url", redirectUrl); "redirect_url", redirectUrl);
return makeRequest(url, params); return buildUrl(url, params);
} }
catch (Exception e) { catch (Exception e) {
throw new RuntimeException(e); throw new RuntimeException(e);

View file

@ -1,43 +1,89 @@
package ru.micord.ervu.security.webbpm.jwt.helper; package ru.micord.ervu.security.webbpm.jwt.helper;
import javax.servlet.http.Cookie; import java.net.IDN;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import ru.micord.ervu.security.webbpm.jwt.util.SecurityUtil; import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseCookie;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import static org.springframework.web.context.request.RequestAttributes.REFERENCE_REQUEST;
import static ru.micord.ervu.security.webbpm.jwt.util.SecurityUtil.AUTH_MARKER; import static ru.micord.ervu.security.webbpm.jwt.util.SecurityUtil.AUTH_MARKER;
import static ru.micord.ervu.security.webbpm.jwt.util.SecurityUtil.AUTH_TOKEN; import static ru.micord.ervu.security.webbpm.jwt.util.SecurityUtil.AUTH_TOKEN;
import static ru.micord.ervu.security.webbpm.jwt.util.SecurityUtil.createCookie;
public final class SecurityHelper { public final class SecurityHelper {
@Value("${cookie.path:#{null}}") @Value("${cookie.path:#{null}}")
private String accessCookiePath; private String accessCookiePath;
@Value("${cookie.domain:#{null}}")
private String accessCookieDomain;
@Value("${cookie.secure:false}")
private boolean accessCookieSecure;
@Value("${cookie.same.site:Lax}")
private String accessCookieSameSite;
@PostConstruct
private void init() {
if (accessCookieDomain != null) {
accessCookieDomain = IDN.toASCII(accessCookieDomain);
}
}
public void clearAccessCookies(HttpServletResponse response) { public void clearAccessCookies(HttpServletResponse response) {
Cookie tokenCookie = createCookie(AUTH_TOKEN, null, null); ResponseCookie emptyAuthToken = createCookie(AUTH_TOKEN, null, accessCookiePath)
tokenCookie.setMaxAge(0); .maxAge(0).build();
tokenCookie.setPath(accessCookiePath); addResponseCookie(response, emptyAuthToken);
tokenCookie.setHttpOnly(true);
response.addCookie(tokenCookie);
Cookie markerCookie = createCookie(AUTH_MARKER, null, null); ResponseCookie emptyAuthMarker = createCookie(AUTH_MARKER, null, "/")
markerCookie.setMaxAge(0); .maxAge(0)
markerCookie.setPath("/"); .secure(false)
response.addCookie(markerCookie); .httpOnly(false)
.build();
addResponseCookie(response, emptyAuthMarker);
} }
public Cookie createAccessCookie(String cookieValue, int expiry) { private void addResponseCookie(HttpServletResponse response, ResponseCookie cookie) {
Cookie authToken = createCookie(SecurityUtil.AUTH_TOKEN, cookieValue, accessCookiePath); response.addHeader(HttpHeaders.SET_COOKIE, cookie.toString());
authToken.setPath(accessCookiePath);
authToken.setMaxAge(expiry);
return authToken;
} }
public Cookie createAuthMarkerCookie(String cookieValue, int expiry) { public void addAccessCookies(HttpServletResponse response, String cookieValue, int expiry) {
Cookie marker = createCookie(AUTH_MARKER, cookieValue, "/"); ResponseCookie authTokenCookie = createCookie(AUTH_TOKEN, cookieValue, accessCookiePath)
marker.setMaxAge(expiry); .maxAge(expiry)
marker.setHttpOnly(false); .build();
return marker; addResponseCookie(response, authTokenCookie);
ResponseCookie authMarker = createCookie(AUTH_MARKER, "true", "/")
.maxAge(expiry)
.secure(false)
.httpOnly(false)
.build();
addResponseCookie(response, authMarker);
}
public ResponseCookie.ResponseCookieBuilder createCookie(String name, String value, String path) {
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
if (requestAttributes == null) {
throw new IllegalStateException("Must be called only in request context");
}
HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(
REFERENCE_REQUEST);
if (request == null) {
throw new IllegalStateException("Must be called only in request context");
}
String cookieValue = value != null ? URLEncoder.encode(value, StandardCharsets.UTF_8) : "";
return ResponseCookie.from(name, cookieValue)
.path(path != null ? path : request.getContextPath())
.httpOnly(true)
.domain(accessCookieDomain)
.secure(accessCookieSecure)
.sameSite(accessCookieSameSite);
} }
} }

View file

@ -1,19 +1,13 @@
package ru.micord.ervu.security.webbpm.jwt.util; package ru.micord.ervu.security.webbpm.jwt.util;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Optional; import java.util.Optional;
import javax.servlet.http.Cookie; import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.util.WebUtils; import org.springframework.web.util.WebUtils;
import ru.micord.ervu.security.webbpm.jwt.JwtAuthentication; import ru.micord.ervu.security.webbpm.jwt.JwtAuthentication;
import static org.springframework.web.context.request.RequestAttributes.REFERENCE_REQUEST;
public final class SecurityUtil { public final class SecurityUtil {
public static final String AUTH_TOKEN = "auth_token"; public static final String AUTH_TOKEN = "auth_token";
@ -23,24 +17,6 @@ public final class SecurityUtil {
//empty //empty
} }
public static Cookie createCookie(String name, String value, String path) {
String cookieValue = value != null ? URLEncoder.encode(value, StandardCharsets.UTF_8) : null;
Cookie cookie = new Cookie(name, cookieValue);
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(
REFERENCE_REQUEST);
if (path != null) {
cookie.setPath(path);
}
else {
cookie.setPath(request.getContextPath());
}
cookie.setHttpOnly(true);
return cookie;
}
public static String extractAuthToken(HttpServletRequest httpRequest) { public static String extractAuthToken(HttpServletRequest httpRequest) {
Cookie cookie = WebUtils.getCookie(httpRequest, AUTH_TOKEN); Cookie cookie = WebUtils.getCookie(httpRequest, AUTH_TOKEN);
return cookie != null ? cookie.getValue() : null; return cookie != null ? cookie.getValue() : null;

View file

@ -0,0 +1,51 @@
package ru.micord.ervu.service;
import com.google.protobuf.InvalidProtocolBufferException;
import org.apache.kafka.common.utils.Bytes;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import proto.ervu.rp.summons.SummonsResponseData;
import ru.micord.ervu.converter.SummonsResponseDataConverter;
import ru.micord.ervu.dto.SubpoenaRequestDto;
import ru.micord.ervu.dto.SubpoenaResponseDto;
import ru.micord.ervu.kafka.service.ReplyingKafkaService;
import ru.micord.ervu.security.webbpm.jwt.util.SecurityUtil;
@Service
public class SubpoenaService {
private final ReplyingKafkaService<Object, Bytes> replyingKafkaService;
private final SummonsResponseDataConverter converter;
@Value("${ervu.kafka.recruit.request.topic}")
private String recruitRequestTopic;
@Value("${ervu.kafka.recruit.reply.topic}")
private String recruitReplyTopic;
public SubpoenaService(
@Qualifier("recruit") ReplyingKafkaService<Object, Bytes> replyingKafkaService,
SummonsResponseDataConverter converter) {
this.replyingKafkaService = replyingKafkaService;
this.converter = converter;
}
public SubpoenaResponseDto getSubpoenaData() {
String ervuId = SecurityUtil.getErvuId();
if (ervuId == null) {
return new SubpoenaResponseDto.Builder().build();
}
SubpoenaRequestDto subpoenaRequestDto = new SubpoenaRequestDto(ervuId);
byte[] reply = replyingKafkaService.sendMessageAndGetReply(recruitRequestTopic,
recruitReplyTopic, subpoenaRequestDto).get();
try {
SummonsResponseData responseData = SummonsResponseData.parseFrom(reply);
return converter.convert(responseData);
}
catch (InvalidProtocolBufferException e) {
throw new RuntimeException("Failed to parse data", e);
}
}
}

View file

@ -3,6 +3,9 @@ package ru.micord.ervu.service.rpc;
import java.util.List; import java.util.List;
import model.FieldData; import model.FieldData;
import org.springframework.beans.factory.annotation.Autowired;
import ru.micord.ervu.dto.SubpoenaResponseDto;
import ru.micord.ervu.service.SubpoenaService;
import service.container.FormService; import service.container.FormService;
import ru.cg.webbpm.modules.standard_annotations.validation.NotNull; import ru.cg.webbpm.modules.standard_annotations.validation.NotNull;
@ -19,8 +22,13 @@ public class LoadFormRpcService extends Behavior {
@NotNull @NotNull
public FormService formService; public FormService formService;
//todo: Remove this shit
@Autowired
public SubpoenaService subpoenaService;
@RpcCall @RpcCall
public List<FieldData> loadData(Object dto) { public List<FieldData> loadData() {
return formService.loadData(dto); SubpoenaResponseDto subpoenaData = subpoenaService.getSubpoenaData();
return formService.loadData(subpoenaData);
} }
} }

View file

@ -760,6 +760,10 @@ JBPM использует 3 корневых категории логирова
Важно: `ESIA_REDIRECT_URL` должна содержать полный адрес вплоть до последнего слэша: Важно: `ESIA_REDIRECT_URL` должна содержать полный адрес вплоть до последнего слэша:
> - https://lkul.ervu.loc/ - правильное значение параметра > - https://lkul.ervu.loc/ - правильное значение параметра
> - https://lkul.ervu.loc - неправильное значение параметра > - https://lkul.ervu.loc - неправильное значение параметра
- `ESIA_LOGOUT_REDIRECT_URL` - ссылка, по которой должен быть направлен пользователь после logout-a
Важно: `ESIA_LOGOUT_REDIRECT_URL` должна содержать полный адрес вплоть до последнего слэша:
> - https://lkul.ervu.loc/home.html - правильное значение параметра
> - https://lkul.ervu.loc - неправильное значение параметра
- `SIGN_URL` - url для подписания с помощью КриптоПро секрета клиента, необходимого для аутентификации через ЕСИА - `SIGN_URL` - url для подписания с помощью КриптоПро секрета клиента, необходимого для аутентификации через ЕСИА
- `ESIA_CLIENT_CERT_HASH` - параметр, содержащий хэш сертификата (fingerprint сертификата) системы-клиента в hexформате - `ESIA_CLIENT_CERT_HASH` - параметр, содержащий хэш сертификата (fingerprint сертификата) системы-клиента в hexформате

View file

@ -12,6 +12,7 @@ ESIA_BASE_URI=https://esia-portal1.test.gosuslugi.ru/
ESIA_CLIENT_ID=MNSV89 ESIA_CLIENT_ID=MNSV89
ESIA_CLIENT_CERT_HASH=04508B4B0B58776A954A0E15F574B4E58799D74C61EE020B3330716C203E3BDD ESIA_CLIENT_CERT_HASH=04508B4B0B58776A954A0E15F574B4E58799D74C61EE020B3330716C203E3BDD
ESIA_REDIRECT_URL=https://lkrp-dev.micord.ru/fl/ ESIA_REDIRECT_URL=https://lkrp-dev.micord.ru/fl/
ESIA_LOGOUT_REDIRECT_URL=https://lkrp-dev.micord.ru/fl/home.html
SIGN_URL=https://ervu-sign-dev.k8s.micord.ru/sign SIGN_URL=https://ervu-sign-dev.k8s.micord.ru/sign

View file

@ -4,7 +4,7 @@
<parent> <parent>
<groupId>ru.micord.ervu.lkrp</groupId> <groupId>ru.micord.ervu.lkrp</groupId>
<artifactId>fl</artifactId> <artifactId>fl</artifactId>
<version>1.9.3-SNAPSHOT</version> <version>1.9.4-SNAPSHOT</version>
</parent> </parent>
<groupId>ru.micord.ervu.lkrp.fl</groupId> <groupId>ru.micord.ervu.lkrp.fl</groupId>

View file

@ -4,6 +4,9 @@
<title>Личный кабинет физ.лица</title> <title>Личный кабинет физ.лица</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8"> <meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self'; style-src 'unsafe-inline' 'self' data:; font-src 'self' data:; img-src 'self' data:"/>
<meta name="referrer" content="strict-origin-when-cross-origin"/>
<link rel="icon" type="image/png" href="src/resources/img/logo.png"/> <link rel="icon" type="image/png" href="src/resources/img/logo.png"/>
</head> </head>
<body webbpm class="webbpm ervu_lkrp_fl"> <body webbpm class="webbpm ervu_lkrp_fl">

View file

@ -4,7 +4,7 @@
<parent> <parent>
<groupId>ru.micord.ervu.lkrp</groupId> <groupId>ru.micord.ervu.lkrp</groupId>
<artifactId>fl</artifactId> <artifactId>fl</artifactId>
<version>1.9.3-SNAPSHOT</version> <version>1.9.4-SNAPSHOT</version>
</parent> </parent>
<groupId>ru.micord.ervu.lkrp.fl</groupId> <groupId>ru.micord.ervu.lkrp.fl</groupId>

View file

@ -1,6 +1,9 @@
<form #logoutForm method="post" [action]="formAction" hidden style="display: none">
<input type="hidden" name="_csrf" [value]="csrfValue"/>
</form>
<button class="user-info" ngbDropdownToggle *ngIf="getIsAuth()">{{getUserFullname()}}</button> <button class="user-info" ngbDropdownToggle *ngIf="getIsAuth()">{{getUserFullname()}}</button>
<div ngbDropdownMenu *ngIf="getIsAuth()"> <div ngbDropdownMenu *ngIf="getIsAuth()">
<a routerLink="/mydata" class="data">Мои данные</a> <a routerLink="/mydata" class="data">Мои данные</a>
<button ngbDropdownItem class="exit" (click)="logout()">Выйти</button> <button ngbDropdownItem class="exit" (click)="logoutForm.submit()">Выйти</button>
</div> </div>
<button class="exit" *ngIf="!getIsAuth()" (click)="logout()">Выйти</button> <button class="exit" *ngIf="!getIsAuth()" (click)="logoutForm.submit()">Выйти</button>

View file

@ -1,7 +1,6 @@
import {Form} from "@webbpm/base-package"; import {Form} from "@webbpm/base-package";
import {ChangeDetectionStrategy, Component} from "@angular/core"; import {ChangeDetectionStrategy, Component} from "@angular/core";
import {ErvuDataService} from "../../../modules/app/service/ervu-data.service"; import {ErvuDataService} from "../../../modules/app/service/ervu-data.service";
import {Subscription} from "rxjs";
import {LoadFormRpcService} from "../../../generated/ru/micord/ervu/service/rpc/LoadFormRpcService"; import {LoadFormRpcService} from "../../../generated/ru/micord/ervu/service/rpc/LoadFormRpcService";
@Component({ @Component({
@ -14,25 +13,16 @@ export class LoadForm extends Form {
private formRpcService: LoadFormRpcService; private formRpcService: LoadFormRpcService;
private ervuDataService: ErvuDataService; private ervuDataService: ErvuDataService;
private subscription: Subscription;
private valuesData: string;
initialize() { initialize() {
super.initialize(); super.initialize();
this.formRpcService = this.getScript(LoadFormRpcService); this.formRpcService = this.getScript(LoadFormRpcService);
this.ervuDataService = this.injector.get(ErvuDataService); this.ervuDataService = this.injector.get(ErvuDataService);
this.subscription = this.ervuDataService.message.subscribe(value => {
if (value) {
this.valuesData = value;
this.loadData();
}
});
} }
loadData(): Promise<any> { loadData(): Promise<any> {
return this.formRpcService return this.formRpcService
.loadData(this.valuesData) .loadData()
.then(fieldDataList => this.setData(fieldDataList)) .then(fieldDataList => this.setData(fieldDataList))
.catch(reason => { .catch(reason => {
throw new Error(reason); throw new Error(reason);
@ -49,6 +39,5 @@ export class LoadForm extends Form {
ngOnDestroy() { ngOnDestroy() {
super.ngOnDestroy(); super.ngOnDestroy();
this.subscription.unsubscribe();
} }
} }

View file

@ -1,21 +1,45 @@
import {ChangeDetectorRef, Component, OnInit} from "@angular/core"; import {ChangeDetectorRef, Component, DoCheck, OnInit} from "@angular/core";
import {HttpClient} from "@angular/common/http"; import {HttpClient, HttpXsrfTokenExtractor} from "@angular/common/http";
import {CookieService} from "ngx-cookie"; import {CookieService} from "ngx-cookie";
import {AppConfigService} from "@webbpm/base-package";
@Component({ @Component({
moduleId: module.id, moduleId: module.id,
selector: "[log-out]", selector: "[log-out]",
templateUrl: "../../../../../src/resources/template/app/component/log_out.html" templateUrl: "../../../../../src/resources/template/app/component/log_out.html"
}) })
export class LogOutComponent implements OnInit{ export class LogOutComponent implements OnInit, DoCheck{
private static readonly BACKEND_URL: string = "backend.url";
private static readonly BACKEND_CONTEXT: string = "backend.context";
private static readonly LOGOUT_URL_POSTFIX: string = "/esia/logout";
private userFullname: string; private userFullname: string;
csrfValue: any;
formAction: any;
constructor(private httpClient: HttpClient, constructor(private httpClient: HttpClient,
private cookieService: CookieService, private cd: ChangeDetectorRef) { private cookieService: CookieService,
private appConfigService: AppConfigService,
private tokenExtractor: HttpXsrfTokenExtractor,
private cd: ChangeDetectorRef) {
let backendUrl = this.appConfigService.getParamValue(LogOutComponent.BACKEND_URL);
let backendContext = this.appConfigService.getParamValue(
LogOutComponent.BACKEND_CONTEXT);
if (backendUrl) {
this.formAction = `${backendUrl}${LogOutComponent.LOGOUT_URL_POSTFIX}`;
}
else if (backendContext) {
this.formAction = `/${backendContext}${LogOutComponent.LOGOUT_URL_POSTFIX}`;
}
}
ngDoCheck(): void {
this.csrfValue = this.tokenExtractor.getToken();
} }
ngOnInit(): void { ngOnInit(): void {
this.csrfValue = this.tokenExtractor.getToken();
let isAuth = this.getIsAuth(); let isAuth = this.getIsAuth();
if (isAuth) { if (isAuth) {
Promise.all([ Promise.all([
@ -27,12 +51,6 @@ export class LogOutComponent implements OnInit{
} }
} }
logout(): Promise<any> {
return this.httpClient.post<string>('esia/logout', {}, { responseType: 'text' as 'json' }).toPromise().then(url => {
window.open(url, "_self");
});
}
public getUserFullname(): string { public getUserFullname(): string {
return this.userFullname; return this.userFullname;
} }
@ -40,4 +58,4 @@ export class LogOutComponent implements OnInit{
public getIsAuth(): boolean { public getIsAuth(): boolean {
return this.cookieService.get("webbpm.ervu-lkrp-fl") != null; return this.cookieService.get("webbpm.ervu-lkrp-fl") != null;
} }
} }

View file

@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>ru.micord.ervu.lkrp</groupId> <groupId>ru.micord.ervu.lkrp</groupId>
<artifactId>fl</artifactId> <artifactId>fl</artifactId>
<version>1.9.3-SNAPSHOT</version> <version>1.9.4-SNAPSHOT</version>
<packaging>pom</packaging> <packaging>pom</packaging>
<modules> <modules>
<module>backend</module> <module>backend</module>

View file

@ -4,7 +4,7 @@
<parent> <parent>
<groupId>ru.micord.ervu.lkrp</groupId> <groupId>ru.micord.ervu.lkrp</groupId>
<artifactId>fl</artifactId> <artifactId>fl</artifactId>
<version>1.9.3-SNAPSHOT</version> <version>1.9.4-SNAPSHOT</version>
</parent> </parent>
<groupId>ru.micord.ervu.lkrp.fl</groupId> <groupId>ru.micord.ervu.lkrp.fl</groupId>