From 6965775ad3215a2d253c458833a879fa428ca4dd Mon Sep 17 00:00:00 2001 From: Zaripov Emil Date: Mon, 23 Dec 2024 10:02:17 +0300 Subject: [PATCH 01/20] set version 1.9.3-SNAPSHOT --- backend/pom.xml | 2 +- distribution/pom.xml | 2 +- frontend/pom.xml | 2 +- pom.xml | 2 +- resources/pom.xml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/backend/pom.xml b/backend/pom.xml index c89fc2c9..f8f94703 100644 --- a/backend/pom.xml +++ b/backend/pom.xml @@ -5,7 +5,7 @@ ru.micord.ervu.lkrp ul - 1.9.2-SNAPSHOT + 1.9.3-SNAPSHOT ru.micord.ervu.lkrp.ul backend diff --git a/distribution/pom.xml b/distribution/pom.xml index 8117ae4a..0343de2b 100644 --- a/distribution/pom.xml +++ b/distribution/pom.xml @@ -4,7 +4,7 @@ ru.micord.ervu.lkrp ul - 1.9.2-SNAPSHOT + 1.9.3-SNAPSHOT ru.micord.ervu.lkrp.ul diff --git a/frontend/pom.xml b/frontend/pom.xml index 5e343729..c7e92b8c 100644 --- a/frontend/pom.xml +++ b/frontend/pom.xml @@ -4,7 +4,7 @@ ru.micord.ervu.lkrp ul - 1.9.2-SNAPSHOT + 1.9.3-SNAPSHOT ru.micord.ervu.lkrp.ul diff --git a/pom.xml b/pom.xml index 0d97a95f..64a0513c 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 ru.micord.ervu.lkrp ul - 1.9.2-SNAPSHOT + 1.9.3-SNAPSHOT pom backend diff --git a/resources/pom.xml b/resources/pom.xml index e2bf5fa1..31c9f342 100644 --- a/resources/pom.xml +++ b/resources/pom.xml @@ -4,7 +4,7 @@ ru.micord.ervu.lkrp ul - 1.9.2-SNAPSHOT + 1.9.3-SNAPSHOT ru.micord.ervu.lkrp.ul From 18df83f0e27c37b67039af7a59ed355e12ab0f3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A5=D0=B0=D0=BB=D1=82=D0=BE=D0=B1=D0=B8=D0=BD=20=D0=95?= =?UTF-8?q?=D0=B2=D0=B3=D0=B5=D0=BD=D0=B8=D0=B9?= Date: Mon, 23 Dec 2024 10:13:42 +0300 Subject: [PATCH 02/20] DEVOPS-1892: added cache settings moved from angie to nginx --- config/Dockerfile | 4 +- config/angie.conf | 84 ----------------------------- config/nginx.conf | 134 +++++++++++++++++++++++++++------------------- 3 files changed, 82 insertions(+), 140 deletions(-) delete mode 100644 config/angie.conf diff --git a/config/Dockerfile b/config/Dockerfile index 17207ebb..f73f53f9 100644 --- a/config/Dockerfile +++ b/config/Dockerfile @@ -1,6 +1,6 @@ ARG BUILDER_IMAGE=registry.altlinux.org/basealt/altsp:c10f1 ARG BACKEND_IMAGE=repo.micord.ru/alt/alt-tomcat:c10f1-9.0.59-20240903 -ARG FRONTEND_IMAGE=docker.angie.software/angie:latest +ARG FRONTEND_IMAGE=nginx:1.24-alpine-slim FROM $BUILDER_IMAGE AS builder @@ -45,5 +45,5 @@ COPY --from=builder /app/frontend/target/frontend*.war /var/lib/tomcat/webapps/R FROM $FRONTEND_IMAGE AS frontend -COPY config/angie.conf /etc/angie/angie.conf +COPY config/nginx.conf /etc/nginx/nginx.conf COPY --from=builder /app/frontend/dist /frontend diff --git a/config/angie.conf b/config/angie.conf deleted file mode 100644 index 18b7f405..00000000 --- a/config/angie.conf +++ /dev/null @@ -1,84 +0,0 @@ -include /etc/angie/modules-enabled.d/*.conf; - -worker_processes 10; - -error_log /var/log/angie/error.log; - -events { - worker_connections 1024; -} - -include /etc/angie/conf-enabled.d/*.conf; - -http { - include /etc/angie/mime.types; - default_type application/octet-stream; - - sendfile on; - - gzip on; - - # text/html doesn't need to be defined there, it's compressed always - gzip_types text/plain text/css text/xml application/x-javascript application/atom+xml; - - # gzip_comp_level 9; - include /etc/angie/sites-enabled.d/*.conf; - - log_format angie_main - '$remote_addr - $remote_user [$time_local] $request ' - '"$status" $body_bytes_sent "$http_referer" ' - '"$http_user_agent" "$http_x_forwarded_for" ' - '"$request_filename" "$gzip_ratio" $upstream_response_time server: $host : $document_root $fastcgi_script_name '; - - server { - listen 80 default; - - access_log /var/log/angie/access.log angie_main; - error_log /var/log/angie/error.log error; - - charset utf-8; - - client_max_body_size 32m; - - ## - # `gzip` Settings - # - # - gzip on; - gzip_disable "msie6"; - - gzip_vary on; - gzip_proxied any; - gzip_comp_level 6; - gzip_buffers 16 8k; - gzip_http_version 1.1; - gzip_min_length 256; - gzip_types - application/atom+xml - application/geo+json - application/javascript - application/x-javascript - application/json - application/ld+json - application/manifest+json - application/rdf+xml - application/rss+xml - application/xhtml+xml - application/xml - font/eot - font/otf - font/ttf - image/svg+xml - text/css - text/javascript - text/plain - text/xml; - - location / { - root /frontend; - index index.html; - expires -1; - try_files $uri $uri/ $uri/index.html; - } - } -} diff --git a/config/nginx.conf b/config/nginx.conf index 4dd7864e..93bb7ad5 100644 --- a/config/nginx.conf +++ b/config/nginx.conf @@ -11,74 +11,100 @@ events { include /etc/nginx/conf-enabled.d/*.conf; http { - include /etc/nginx/mime.types; + include /etc/nginx/mime.types; default_type application/octet-stream; - sendfile on; + sendfile on; - gzip on; + gzip on; - # text/html doesn't need to be defined there, it's compressed always - gzip_types text/plain text/css text/xml application/x-javascript application/atom+xml; + # text/html doesn't need to be defined there, it's compressed always + gzip_types text/plain text/css text/xml application/x-javascript application/atom+xml; - # gzip_comp_level 9; - include /etc/nginx/sites-enabled.d/*.conf; + # gzip_comp_level 9; + include /etc/nginx/sites-enabled.d/*.conf; - log_format nginx_main - '$remote_addr - $remote_user [$time_local] $request ' - '"$status" $body_bytes_sent "$http_referer" ' - '"$http_user_agent" "$http_x_forwarded_for" ' - '"$request_filename" "$gzip_ratio" $upstream_response_time server: $host : $document_root $fastcgi_script_name '; + log_format nginx_main + '$remote_addr - $remote_user [$time_local] $request ' + '"$status" $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for" ' + '"$request_filename" "$gzip_ratio" $upstream_response_time server: $host : $document_root $fastcgi_script_name '; - server { - listen 80 default; + server { + listen 80 default; access_log /var/log/nginx/access.log nginx_main; - error_log /var/log/nginx/error.log error; + error_log /var/log/nginx/error.log error; - charset utf-8; + charset utf-8; - client_max_body_size 32m; + client_max_body_size 32m; - ## - # `gzip` Settings - # - # - gzip on; - gzip_disable "msie6"; + ## + # `gzip` Settings + # + # + gzip on; + gzip_disable "msie6"; - gzip_vary on; - gzip_proxied any; - gzip_comp_level 6; - gzip_buffers 16 8k; - gzip_http_version 1.1; - gzip_min_length 256; - gzip_types - application/atom+xml + gzip_vary on; + gzip_proxied any; + gzip_comp_level 6; + gzip_buffers 16 8k; + gzip_http_version 1.1; + gzip_min_length 256; + gzip_types + application/atom+xml application/geo+json application/javascript - application/x-javascript - application/json - application/ld+json - application/manifest+json - application/rdf+xml - application/rss+xml - application/xhtml+xml - application/xml - font/eot - font/otf - font/ttf - image/svg+xml - text/css - text/javascript - text/plain - text/xml; + application/x-javascript + application/json + application/ld+json + application/manifest+json + application/rdf+xml + application/rss+xml + application/xhtml+xml + application/xml + font/eot + font/otf + font/ttf + image/svg+xml + text/css + text/javascript + text/plain + text/xml; - location / { - root /frontend; - index index.html; - expires -1; - try_files $uri $uri/ $uri/index.html; - } - } + location / { + root /frontend; + index index.html; + try_files $uri @index; + + # Media: images, icons, video, audio, HTC + location ~* \.(?:jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|mp3|ogg|ogv|webm|htc|woff2|woff|ttf)$ { + expires 1M; + access_log off; + # max-age must be in seconds + add_header Cache-Control "max-age=2629746, public"; + } + # CSS and Javascript + location ~* \.(?:css|js)$ { + expires 1y; + access_log off; + add_header Cache-Control "max-age=31556952, public"; + } + } + + location @index { + root /frontend; + add_header Cache-Control no-cache; + expires 0; + try_files /index.html =404; + } + + location = /health { + access_log off; + add_header 'Content-Type' 'application/json'; + return 200 '{"status":"UP"}'; + } + } } From 60615ff8ea931bd85607a37d1682a3908efc3440 Mon Sep 17 00:00:00 2001 From: Zaripov Emil Date: Tue, 24 Dec 2024 11:26:40 +0300 Subject: [PATCH 03/20] fix --- frontend/home.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/home.html b/frontend/home.html index f3d6eb92..b613bfba 100644 --- a/frontend/home.html +++ b/frontend/home.html @@ -31,7 +31,7 @@
-
Личный кабинет для ведения воинского учета в организациях
+
Личный кабинет для ведения воинского учета в организациях
Кому доступен личный кабинет?
From 9cd29fc3353988694a67202f8b9e225fd803a8c5 Mon Sep 17 00:00:00 2001 From: Eduard Tihomirov Date: Tue, 24 Dec 2024 20:09:17 +0300 Subject: [PATCH 04/20] SUPPORT-8755: Fix --- .../micord/ervu/security/esia/token/TokensStore.java | 11 ++++++++++- .../webbpm/jwt/filter/JwtAuthenticationFilter.java | 2 ++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/backend/src/main/java/ru/micord/ervu/security/esia/token/TokensStore.java b/backend/src/main/java/ru/micord/ervu/security/esia/token/TokensStore.java index 2c93fc1c..613a0c1a 100644 --- a/backend/src/main/java/ru/micord/ervu/security/esia/token/TokensStore.java +++ b/backend/src/main/java/ru/micord/ervu/security/esia/token/TokensStore.java @@ -3,6 +3,8 @@ package ru.micord.ervu.security.esia.token; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import org.springframework.security.authentication.CredentialsExpiredException; + /** * @author Eduard Tihomirov */ @@ -18,7 +20,14 @@ public class TokensStore { } public static String getAccessToken(String prnOid) { - return accessTokensMap.get(prnOid).getAccessToken(); + ExpiringToken token = accessTokensMap.get(prnOid); + if (token == null) { + throw new CredentialsExpiredException("No access token for prnOid: " + prnOid); + } + else if (token.isExpired()) { + throw new CredentialsExpiredException("Access token expired for prnOid: " + prnOid); + } + return token.getAccessToken(); } public static void removeExpiredAccessToken() { diff --git a/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/filter/JwtAuthenticationFilter.java b/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/filter/JwtAuthenticationFilter.java index 0d359cd2..882bfcc0 100644 --- a/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/filter/JwtAuthenticationFilter.java +++ b/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/filter/JwtAuthenticationFilter.java @@ -17,6 +17,7 @@ import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; import org.springframework.security.web.util.matcher.RequestMatcher; +import ru.micord.ervu.security.esia.token.TokensStore; import ru.micord.ervu.security.webbpm.jwt.JwtAuthentication; import ru.micord.ervu.security.webbpm.jwt.helper.SecurityHelper; import ru.micord.ervu.security.webbpm.jwt.model.Token; @@ -68,6 +69,7 @@ public class JwtAuthenticationFilter extends AbstractAuthenticationProcessingFil if (!token.getHasRole()) { throw new CredentialsExpiredException("Invalid token. User has no required role"); } + TokensStore.getAccessToken(token.getUserAccountId()); } } catch (CredentialsExpiredException e) { From 1059730066f4fce4e1ab6d48818087a93250003f Mon Sep 17 00:00:00 2001 From: Eduard Tihomirov Date: Tue, 24 Dec 2024 20:26:13 +0300 Subject: [PATCH 05/20] SUPPORT-8755: Fix --- .../micord/ervu/security/esia/token/TokensStore.java | 10 +++++++--- .../webbpm/jwt/filter/JwtAuthenticationFilter.java | 5 ++++- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/backend/src/main/java/ru/micord/ervu/security/esia/token/TokensStore.java b/backend/src/main/java/ru/micord/ervu/security/esia/token/TokensStore.java index 613a0c1a..20dd5415 100644 --- a/backend/src/main/java/ru/micord/ervu/security/esia/token/TokensStore.java +++ b/backend/src/main/java/ru/micord/ervu/security/esia/token/TokensStore.java @@ -20,14 +20,18 @@ public class TokensStore { } public static String getAccessToken(String prnOid) { + return accessTokensMap.get(prnOid).getAccessToken(); + } + + public static boolean validateAccessToken(String prnOid) { ExpiringToken token = accessTokensMap.get(prnOid); if (token == null) { - throw new CredentialsExpiredException("No access token for prnOid: " + prnOid); + throw new CredentialsExpiredException("No ESIA access token for prnOid: " + prnOid); } else if (token.isExpired()) { - throw new CredentialsExpiredException("Access token expired for prnOid: " + prnOid); + throw new CredentialsExpiredException("ESIA access token expired for prnOid: " + prnOid); } - return token.getAccessToken(); + return token.getAccessToken() != null; } public static void removeExpiredAccessToken() { diff --git a/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/filter/JwtAuthenticationFilter.java b/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/filter/JwtAuthenticationFilter.java index 882bfcc0..c397b2b4 100644 --- a/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/filter/JwtAuthenticationFilter.java +++ b/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/filter/JwtAuthenticationFilter.java @@ -69,7 +69,10 @@ public class JwtAuthenticationFilter extends AbstractAuthenticationProcessingFil if (!token.getHasRole()) { throw new CredentialsExpiredException("Invalid token. User has no required role"); } - TokensStore.getAccessToken(token.getUserAccountId()); + boolean hasEsiaAccessToken = TokensStore.validateAccessToken(token.getUserAccountId()); + if (!hasEsiaAccessToken) { + throw new CredentialsExpiredException("ESIA access token is null"); + } } } catch (CredentialsExpiredException e) { From e7c23ff3a1e90d2d8a87259a10f0b48615ff98ee Mon Sep 17 00:00:00 2001 From: Eduard Tihomirov Date: Tue, 24 Dec 2024 20:29:01 +0300 Subject: [PATCH 06/20] SUPPORT-8755: Fix --- .../security/webbpm/jwt/filter/JwtAuthenticationFilter.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/filter/JwtAuthenticationFilter.java b/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/filter/JwtAuthenticationFilter.java index c397b2b4..c619bb76 100644 --- a/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/filter/JwtAuthenticationFilter.java +++ b/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/filter/JwtAuthenticationFilter.java @@ -69,8 +69,8 @@ public class JwtAuthenticationFilter extends AbstractAuthenticationProcessingFil if (!token.getHasRole()) { throw new CredentialsExpiredException("Invalid token. User has no required role"); } - boolean hasEsiaAccessToken = TokensStore.validateAccessToken(token.getUserAccountId()); - if (!hasEsiaAccessToken) { + boolean esiaAccessTokenIsValid = TokensStore.validateAccessToken(token.getUserAccountId()); + if (!esiaAccessTokenIsValid) { throw new CredentialsExpiredException("ESIA access token is null"); } } From 289607887656134b528f5c3fc273e31b121bcce5 Mon Sep 17 00:00:00 2001 From: Eduard Tihomirov Date: Tue, 24 Dec 2024 20:45:05 +0300 Subject: [PATCH 07/20] SUPPORT-8755: Fix --- .../fileupload/EmployeeInfoFileUploadService.java | 4 ++-- .../security/esia/service/EsiaAuthService.java | 14 +++++++------- .../{TokensStore.java => EsiaTokensStore.java} | 7 +++---- .../esia/token/TokensClearShedulerService.java | 4 ++-- .../webbpm/jwt/filter/JwtAuthenticationFilter.java | 8 ++------ .../webbpm/jwt/service/JwtTokenService.java | 6 +++--- 6 files changed, 19 insertions(+), 24 deletions(-) rename backend/src/main/java/ru/micord/ervu/security/esia/token/{TokensStore.java => EsiaTokensStore.java} (93%) diff --git a/backend/src/main/java/ervu/service/fileupload/EmployeeInfoFileUploadService.java b/backend/src/main/java/ervu/service/fileupload/EmployeeInfoFileUploadService.java index f8ffeaa1..b99a0840 100644 --- a/backend/src/main/java/ervu/service/fileupload/EmployeeInfoFileUploadService.java +++ b/backend/src/main/java/ervu/service/fileupload/EmployeeInfoFileUploadService.java @@ -24,7 +24,7 @@ import org.springframework.kafka.annotation.KafkaListener; import org.springframework.kafka.core.KafkaTemplate; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; -import ru.micord.ervu.security.esia.token.TokensStore; +import ru.micord.ervu.security.esia.token.EsiaTokensStore; import ru.micord.ervu.security.esia.model.EmployeeModel; import ru.micord.ervu.security.esia.model.PersonModel; import ru.micord.ervu.security.esia.service.UlDataService; @@ -85,7 +85,7 @@ public class EmployeeInfoFileUploadService { String[] ids = token.getUserAccountId().split(":"); String userId = ids[0]; String ervuId = ids[1]; - String accessToken = TokensStore.getAccessToken(userId); + String accessToken = EsiaTokensStore.getAccessToken(userId); EmployeeModel employeeModel = ulDataService.getEmployeeModel(accessToken); PersonModel personModel = employeeModel.getPerson(); String departureDateTime = now.format(DateTimeFormatter.ofPattern(FORMAT)); diff --git a/backend/src/main/java/ru/micord/ervu/security/esia/service/EsiaAuthService.java b/backend/src/main/java/ru/micord/ervu/security/esia/service/EsiaAuthService.java index 9828481c..55aff54f 100644 --- a/backend/src/main/java/ru/micord/ervu/security/esia/service/EsiaAuthService.java +++ b/backend/src/main/java/ru/micord/ervu/security/esia/service/EsiaAuthService.java @@ -22,7 +22,7 @@ import javax.servlet.http.HttpServletResponse; import com.fasterxml.jackson.databind.ObjectMapper; import ervu.service.okopf.OkopfService; import org.springframework.security.authentication.AuthenticationManager; -import ru.micord.ervu.security.esia.token.TokensStore; +import ru.micord.ervu.security.esia.token.EsiaTokensStore; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.HttpStatus; @@ -214,8 +214,8 @@ public class EsiaAuthService { String prnOid = esiaAccessToken.getSbj_id(); String ervuId = getErvuId(esiaAccessTokenStr, prnOid); Long expiresIn = tokenResponse.getExpires_in(); - TokensStore.addAccessToken(prnOid, esiaAccessTokenStr, expiresIn); - TokensStore.addRefreshToken(prnOid, esiaRefreshTokenStr, expiresIn); + EsiaTokensStore.addAccessToken(prnOid, esiaAccessTokenStr, expiresIn); + EsiaTokensStore.addRefreshToken(prnOid, esiaRefreshTokenStr, expiresIn); Token token = jwtTokenService.createAccessToken(esiaAccessToken.getSbj_id(), expiresIn, ervuId, hasRole); int expiry = tokenResponse.getExpires_in().intValue(); Cookie accessCookie = securityHelper.createAccessCookie(token.getValue(), expiry); @@ -302,8 +302,8 @@ public class EsiaAuthService { EsiaAccessToken esiaAccessToken = ulDataService.readToken(esiaAccessTokenStr); String prnOid = esiaAccessToken.getSbj_id(); Long expiresIn = tokenResponse.getExpires_in(); - TokensStore.addAccessToken(prnOid, esiaAccessTokenStr, expiresIn); - TokensStore.addRefreshToken(prnOid, esiaNewRefreshToken, expiresIn); + EsiaTokensStore.addAccessToken(prnOid, esiaAccessTokenStr, expiresIn); + EsiaTokensStore.addRefreshToken(prnOid, esiaNewRefreshToken, expiresIn); String ervuId = getErvuId(esiaAccessTokenStr, prnOid); Token token = jwtTokenService.createAccessToken(esiaAccessToken.getSbj_id(), expiresIn, ervuId, true); int expiry = tokenResponse.getExpires_in().intValue(); @@ -361,8 +361,8 @@ public class EsiaAuthService { try { securityHelper.clearAccessCookies(response); String userId = jwtTokenService.getUserAccountId(request); - TokensStore.removeAccessToken(userId); - TokensStore.removeRefreshToken(userId); + EsiaTokensStore.removeAccessToken(userId); + EsiaTokensStore.removeRefreshToken(userId); String logoutUrl = esiaConfig.getEsiaBaseUri() + esiaConfig.getEsiaLogoutUrl(); String redirectUrl = esiaConfig.getRedirectUrl(); URL url = new URL(logoutUrl); diff --git a/backend/src/main/java/ru/micord/ervu/security/esia/token/TokensStore.java b/backend/src/main/java/ru/micord/ervu/security/esia/token/EsiaTokensStore.java similarity index 93% rename from backend/src/main/java/ru/micord/ervu/security/esia/token/TokensStore.java rename to backend/src/main/java/ru/micord/ervu/security/esia/token/EsiaTokensStore.java index 20dd5415..61f818d9 100644 --- a/backend/src/main/java/ru/micord/ervu/security/esia/token/TokensStore.java +++ b/backend/src/main/java/ru/micord/ervu/security/esia/token/EsiaTokensStore.java @@ -8,7 +8,7 @@ import org.springframework.security.authentication.CredentialsExpiredException; /** * @author Eduard Tihomirov */ -public class TokensStore { +public class EsiaTokensStore { private static final Map accessTokensMap = new ConcurrentHashMap<>(); private static final Map refreshTokensMap = new ConcurrentHashMap<>(); @@ -23,15 +23,14 @@ public class TokensStore { return accessTokensMap.get(prnOid).getAccessToken(); } - public static boolean validateAccessToken(String prnOid) { + public static void validateAccessToken(String prnOid) { ExpiringToken token = accessTokensMap.get(prnOid); - if (token == null) { + if (token == null || token.getAccessToken() == null) { throw new CredentialsExpiredException("No ESIA access token for prnOid: " + prnOid); } else if (token.isExpired()) { throw new CredentialsExpiredException("ESIA access token expired for prnOid: " + prnOid); } - return token.getAccessToken() != null; } public static void removeExpiredAccessToken() { diff --git a/backend/src/main/java/ru/micord/ervu/security/esia/token/TokensClearShedulerService.java b/backend/src/main/java/ru/micord/ervu/security/esia/token/TokensClearShedulerService.java index 46652958..89c9db4c 100644 --- a/backend/src/main/java/ru/micord/ervu/security/esia/token/TokensClearShedulerService.java +++ b/backend/src/main/java/ru/micord/ervu/security/esia/token/TokensClearShedulerService.java @@ -14,7 +14,7 @@ public class TokensClearShedulerService { @SchedulerLock(name = "clearToken") @Transactional public void load() { - TokensStore.removeExpiredRefreshToken(); - TokensStore.removeExpiredAccessToken(); + EsiaTokensStore.removeExpiredRefreshToken(); + EsiaTokensStore.removeExpiredAccessToken(); } } diff --git a/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/filter/JwtAuthenticationFilter.java b/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/filter/JwtAuthenticationFilter.java index c619bb76..3e888f85 100644 --- a/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/filter/JwtAuthenticationFilter.java +++ b/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/filter/JwtAuthenticationFilter.java @@ -7,7 +7,6 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import io.jsonwebtoken.ExpiredJwtException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.security.authentication.CredentialsExpiredException; @@ -17,7 +16,7 @@ import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; import org.springframework.security.web.util.matcher.RequestMatcher; -import ru.micord.ervu.security.esia.token.TokensStore; +import ru.micord.ervu.security.esia.token.EsiaTokensStore; import ru.micord.ervu.security.webbpm.jwt.JwtAuthentication; import ru.micord.ervu.security.webbpm.jwt.helper.SecurityHelper; import ru.micord.ervu.security.webbpm.jwt.model.Token; @@ -69,10 +68,7 @@ public class JwtAuthenticationFilter extends AbstractAuthenticationProcessingFil if (!token.getHasRole()) { throw new CredentialsExpiredException("Invalid token. User has no required role"); } - boolean esiaAccessTokenIsValid = TokensStore.validateAccessToken(token.getUserAccountId()); - if (!esiaAccessTokenIsValid) { - throw new CredentialsExpiredException("ESIA access token is null"); - } + EsiaTokensStore.validateAccessToken(token.getUserAccountId()); } } catch (CredentialsExpiredException e) { diff --git a/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/service/JwtTokenService.java b/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/service/JwtTokenService.java index b04c226c..fc7f5874 100644 --- a/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/service/JwtTokenService.java +++ b/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/service/JwtTokenService.java @@ -14,7 +14,7 @@ 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.esia.token.TokensStore; +import ru.micord.ervu.security.esia.token.EsiaTokensStore; import ru.micord.ervu.security.webbpm.jwt.model.Token; import ru.cg.webbpm.modules.resources.api.ResourceMetadataUtils; @@ -79,11 +79,11 @@ public class JwtTokenService { } public String getAccessToken(HttpServletRequest request) { - return TokensStore.getAccessToken(getUserAccountId(request)); + return EsiaTokensStore.getAccessToken(getUserAccountId(request)); } public String getRefreshToken(HttpServletRequest request) { - return TokensStore.getRefreshToken(getUserAccountId(request)); + return EsiaTokensStore.getRefreshToken(getUserAccountId(request)); } public String getUserAccountId(HttpServletRequest request) { From f55048458698e8d22d2dfc6c3c5541752a4a1b2a Mon Sep 17 00:00:00 2001 From: Eduard Tihomirov Date: Wed, 25 Dec 2024 10:39:36 +0300 Subject: [PATCH 08/20] SUPPORT-8755: Fix --- .../micord/ervu/security/SecurityConfig.java | 5 +-- .../security/esia/token/EsiaTokensStore.java | 13 +++++-- .../webbpm/jwt/JwtAuthenticationProvider.java | 30 +++++++++++---- .../jwt/filter/JwtAuthenticationFilter.java | 38 ++++++++----------- .../webbpm/jwt/service/JwtTokenService.java | 2 +- 5 files changed, 50 insertions(+), 38 deletions(-) diff --git a/backend/src/main/java/ru/micord/ervu/security/SecurityConfig.java b/backend/src/main/java/ru/micord/ervu/security/SecurityConfig.java index 5f088eaa..bfc8d16a 100644 --- a/backend/src/main/java/ru/micord/ervu/security/SecurityConfig.java +++ b/backend/src/main/java/ru/micord/ervu/security/SecurityConfig.java @@ -105,10 +105,9 @@ public class SecurityConfig { @Bean public JwtAuthenticationFilter jwtAuthenticationFilter(SecurityHelper securityHelper, - AuthenticationManager manager, - JwtTokenService jwtTokenService) { + AuthenticationManager manager) { JwtAuthenticationFilter jwtAuthenticationFilter = new JwtAuthenticationFilter( - new JwtMatcher("/**", PERMIT_ALL), entryPoint(), securityHelper, jwtTokenService); + new JwtMatcher("/**", PERMIT_ALL), entryPoint(), securityHelper); jwtAuthenticationFilter.setAuthenticationManager(manager); return jwtAuthenticationFilter; } diff --git a/backend/src/main/java/ru/micord/ervu/security/esia/token/EsiaTokensStore.java b/backend/src/main/java/ru/micord/ervu/security/esia/token/EsiaTokensStore.java index 61f818d9..f1384900 100644 --- a/backend/src/main/java/ru/micord/ervu/security/esia/token/EsiaTokensStore.java +++ b/backend/src/main/java/ru/micord/ervu/security/esia/token/EsiaTokensStore.java @@ -1,14 +1,18 @@ package ru.micord.ervu.security.esia.token; +import java.lang.invoke.MethodHandles; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.security.authentication.CredentialsExpiredException; /** * @author Eduard Tihomirov */ public class EsiaTokensStore { + private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); private static final Map accessTokensMap = new ConcurrentHashMap<>(); private static final Map refreshTokensMap = new ConcurrentHashMap<>(); @@ -23,14 +27,17 @@ public class EsiaTokensStore { return accessTokensMap.get(prnOid).getAccessToken(); } - public static void validateAccessToken(String prnOid) { + public static boolean validateAccessToken(String prnOid) { ExpiringToken token = accessTokensMap.get(prnOid); if (token == null || token.getAccessToken() == null) { - throw new CredentialsExpiredException("No ESIA access token for prnOid: " + prnOid); + LOGGER.error("No ESIA access token for prnOid: " + prnOid); + return false; } else if (token.isExpired()) { - throw new CredentialsExpiredException("ESIA access token expired for prnOid: " + prnOid); + LOGGER.error("ESIA access token expired for prnOid: " + prnOid); + return false; } + return true; } public static void removeExpiredAccessToken() { diff --git a/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/JwtAuthenticationProvider.java b/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/JwtAuthenticationProvider.java index f709679f..d33e0987 100644 --- a/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/JwtAuthenticationProvider.java +++ b/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/JwtAuthenticationProvider.java @@ -2,6 +2,8 @@ package ru.micord.ervu.security.webbpm.jwt; import java.util.Collections; +import javax.servlet.http.HttpServletRequest; + import io.jsonwebtoken.ExpiredJwtException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.authentication.AuthenticationProvider; @@ -11,9 +13,13 @@ import org.springframework.security.authentication.UsernamePasswordAuthenticatio import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.context.request.RequestContextHolder; import ru.micord.ervu.security.webbpm.jwt.model.Token; import ru.micord.ervu.security.webbpm.jwt.service.JwtTokenService; +import static org.springframework.web.context.request.RequestAttributes.REFERENCE_REQUEST; + @Component public class JwtAuthenticationProvider implements AuthenticationProvider { @@ -42,16 +48,24 @@ public class JwtAuthenticationProvider implements AuthenticationProvider { throw new BadCredentialsException("Authentication Failed.", e); } - if (!jwtTokenService.isValid(token)) { - throw new BadCredentialsException("Auth token is not valid for user " + token.getUserAccountId()); + if (jwtTokenService.isValid(token)) { + RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); + HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference( + REFERENCE_REQUEST); + + if (request != null && (request.getRequestURI() + .endsWith("esia/logout") || token.getHasRole())) { + UsernamePasswordAuthenticationToken pwdToken = + UsernamePasswordAuthenticationToken.authenticated(token.getUserAccountId(), null, + Collections.emptyList() + ); + + return new JwtAuthentication(pwdToken, token.getUserAccountId(), token.getValue()); + } } - UsernamePasswordAuthenticationToken pwdToken = - UsernamePasswordAuthenticationToken.authenticated(token.getUserAccountId(), null, - Collections.emptyList() - ); - - return new JwtAuthentication(pwdToken, token.getUserAccountId(), token.getValue()); + throw new BadCredentialsException( + "Auth token is not valid for user " + token.getUserAccountId()); } @Override diff --git a/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/filter/JwtAuthenticationFilter.java b/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/filter/JwtAuthenticationFilter.java index 3e888f85..d7d9b341 100644 --- a/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/filter/JwtAuthenticationFilter.java +++ b/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/filter/JwtAuthenticationFilter.java @@ -9,17 +9,14 @@ 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 org.springframework.security.web.util.matcher.RequestMatcher; -import ru.micord.ervu.security.esia.token.EsiaTokensStore; import ru.micord.ervu.security.webbpm.jwt.JwtAuthentication; import ru.micord.ervu.security.webbpm.jwt.helper.SecurityHelper; -import ru.micord.ervu.security.webbpm.jwt.model.Token; import ru.micord.ervu.security.webbpm.jwt.service.JwtTokenService; import static ru.micord.ervu.security.webbpm.jwt.util.SecurityUtil.extractAuthToken; @@ -36,22 +33,24 @@ public class JwtAuthenticationFilter extends AbstractAuthenticationProcessingFil private final SecurityHelper securityHelper; - private final JwtTokenService jwtTokenService; - public JwtAuthenticationFilter(RequestMatcher requestMatcher, AuthenticationEntryPoint entryPoint, - SecurityHelper securityHelper, - JwtTokenService jwtTokenService) { + SecurityHelper securityHelper) { super(requestMatcher); this.entryPoint = entryPoint; this.securityHelper = securityHelper; - this.jwtTokenService = jwtTokenService; } @Override public Authentication attemptAuthentication(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws AuthenticationException { + String browser = httpServletRequest.getHeader("User-Agent"); + + if (browser == null || !browser.contains("YaBrowser") || !browser.contains("Chromium GOST")) { + LOGGER.error("Invalid browser. Use YaBrowser or Chromium GOST"); + return clearCookieAndSetStatus(httpServletResponse); + } String tokenStr = extractAuthToken(httpServletRequest); Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (authentication == null) { @@ -59,23 +58,10 @@ public class JwtAuthenticationFilter extends AbstractAuthenticationProcessingFil } try { authentication = getAuthenticationManager().authenticate(authentication); - String browser = httpServletRequest.getHeader("User-Agent"); - if (browser == null || !browser.contains("YaBrowser") || !browser.contains("Chromium GOST")) { - throw new CredentialsExpiredException("Invalid browser. Use YaBrowser or Chromium GOST"); - } - if (!httpServletRequest.getRequestURI().endsWith("esia/logout")) { - Token token = jwtTokenService.getToken(tokenStr); - if (!token.getHasRole()) { - throw new CredentialsExpiredException("Invalid token. User has no required role"); - } - EsiaTokensStore.validateAccessToken(token.getUserAccountId()); - } } - catch (CredentialsExpiredException e) { - securityHelper.clearAccessCookies(httpServletResponse); - httpServletResponse.setStatus(401); + catch (AuthenticationException e) { LOGGER.warn(e.getMessage()); - return null; + return clearCookieAndSetStatus(httpServletResponse); } return authentication; } @@ -97,4 +83,10 @@ public class JwtAuthenticationFilter extends AbstractAuthenticationProcessingFil SecurityContextHolder.clearContext(); entryPoint.commence(request, response, exception); } + + private Authentication clearCookieAndSetStatus(HttpServletResponse httpServletResponse) { + securityHelper.clearAccessCookies(httpServletResponse); + httpServletResponse.setStatus(401); + return null; + } } diff --git a/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/service/JwtTokenService.java b/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/service/JwtTokenService.java index fc7f5874..d4332ebb 100644 --- a/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/service/JwtTokenService.java +++ b/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/service/JwtTokenService.java @@ -66,7 +66,7 @@ public class JwtTokenService { LOGGER.info("Token {} is expired ", token.getValue()); return false; } - return true; + return EsiaTokensStore.validateAccessToken(token.getUserAccountId()); } public Token getToken(String token) { From f671dfa1944967b5cb7295b207a11a9b806136dc Mon Sep 17 00:00:00 2001 From: Eduard Tihomirov Date: Wed, 25 Dec 2024 12:45:54 +0300 Subject: [PATCH 09/20] SUPPORT-8755: Fix --- .../ervu/security/webbpm/jwt/JwtAuthenticationProvider.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/JwtAuthenticationProvider.java b/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/JwtAuthenticationProvider.java index d33e0987..f497a4c9 100644 --- a/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/JwtAuthenticationProvider.java +++ b/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/JwtAuthenticationProvider.java @@ -52,9 +52,11 @@ public class JwtAuthenticationProvider implements AuthenticationProvider { RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference( REFERENCE_REQUEST); + if (request == null) { + throw new IllegalStateException("No request found in request attributes"); + } - if (request != null && (request.getRequestURI() - .endsWith("esia/logout") || token.getHasRole())) { + if (request.getRequestURI().endsWith("esia/logout") || token.getHasRole()) { UsernamePasswordAuthenticationToken pwdToken = UsernamePasswordAuthenticationToken.authenticated(token.getUserAccountId(), null, Collections.emptyList() From 3c4ea9b3dd0eb9b16de1c258100b31950a78e310 Mon Sep 17 00:00:00 2001 From: Eduard Tihomirov Date: Wed, 25 Dec 2024 16:48:05 +0300 Subject: [PATCH 10/20] fix --- .../ervu/security/webbpm/jwt/service/JwtTokenService.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/service/JwtTokenService.java b/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/service/JwtTokenService.java index d4332ebb..62686b82 100644 --- a/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/service/JwtTokenService.java +++ b/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/service/JwtTokenService.java @@ -66,7 +66,8 @@ public class JwtTokenService { LOGGER.info("Token {} is expired ", token.getValue()); return false; } - return EsiaTokensStore.validateAccessToken(token.getUserAccountId()); + String[] ids = token.getUserAccountId().split(":"); + return EsiaTokensStore.validateAccessToken(ids[0]); } public Token getToken(String token) { From 21ad3e91920324f551bab72abd3e91b02a859b26 Mon Sep 17 00:00:00 2001 From: Eduard Tihomirov Date: Thu, 26 Dec 2024 10:23:29 +0300 Subject: [PATCH 11/20] SUPPORT-8755: Fix --- .../security/webbpm/jwt/filter/JwtAuthenticationFilter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/filter/JwtAuthenticationFilter.java b/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/filter/JwtAuthenticationFilter.java index d7d9b341..630a4fc6 100644 --- a/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/filter/JwtAuthenticationFilter.java +++ b/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/filter/JwtAuthenticationFilter.java @@ -47,7 +47,7 @@ public class JwtAuthenticationFilter extends AbstractAuthenticationProcessingFil throws AuthenticationException { String browser = httpServletRequest.getHeader("User-Agent"); - if (browser == null || !browser.contains("YaBrowser") || !browser.contains("Chromium GOST")) { + if (browser == null || (!browser.contains("YaBrowser") && !browser.contains("Chromium GOST"))) { LOGGER.error("Invalid browser. Use YaBrowser or Chromium GOST"); return clearCookieAndSetStatus(httpServletResponse); } From 5d78f06673e401d45d9329445a5cd5a63b15ad54 Mon Sep 17 00:00:00 2001 From: Zaripov Emil Date: Thu, 26 Dec 2024 10:56:59 +0300 Subject: [PATCH 12/20] set version 1.9.4-SNAPSHOT --- backend/pom.xml | 2 +- distribution/pom.xml | 2 +- frontend/pom.xml | 2 +- pom.xml | 2 +- resources/pom.xml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/backend/pom.xml b/backend/pom.xml index f8f94703..7b69c2de 100644 --- a/backend/pom.xml +++ b/backend/pom.xml @@ -5,7 +5,7 @@ ru.micord.ervu.lkrp ul - 1.9.3-SNAPSHOT + 1.9.4-SNAPSHOT ru.micord.ervu.lkrp.ul backend diff --git a/distribution/pom.xml b/distribution/pom.xml index 0343de2b..1631972c 100644 --- a/distribution/pom.xml +++ b/distribution/pom.xml @@ -4,7 +4,7 @@ ru.micord.ervu.lkrp ul - 1.9.3-SNAPSHOT + 1.9.4-SNAPSHOT ru.micord.ervu.lkrp.ul diff --git a/frontend/pom.xml b/frontend/pom.xml index c7e92b8c..0e080579 100644 --- a/frontend/pom.xml +++ b/frontend/pom.xml @@ -4,7 +4,7 @@ ru.micord.ervu.lkrp ul - 1.9.3-SNAPSHOT + 1.9.4-SNAPSHOT ru.micord.ervu.lkrp.ul diff --git a/pom.xml b/pom.xml index 64a0513c..9fa2459f 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 ru.micord.ervu.lkrp ul - 1.9.3-SNAPSHOT + 1.9.4-SNAPSHOT pom backend diff --git a/resources/pom.xml b/resources/pom.xml index 31c9f342..cc48dba7 100644 --- a/resources/pom.xml +++ b/resources/pom.xml @@ -4,7 +4,7 @@ ru.micord.ervu.lkrp ul - 1.9.3-SNAPSHOT + 1.9.4-SNAPSHOT ru.micord.ervu.lkrp.ul From b9ca2b5abafe51ed7498005f6479acd749a725a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A0=D0=B0=D1=83=D1=84=20=D0=9B=D0=B0=D1=82=D1=8B=D0=BF?= =?UTF-8?q?=D0=BE=D0=B2?= Date: Fri, 27 Dec 2024 02:21:26 +0300 Subject: [PATCH 13/20] SUPPORT-8831: add grid columns filters changed event + AC for button visibility --- .../ervu/component/grid/InMemoryStaticGrid.ts | 15 +- .../business-model/Журнал взаимодействия.page | 201 ++++++++++++++++++ 2 files changed, 215 insertions(+), 1 deletion(-) diff --git a/frontend/src/ts/ervu/component/grid/InMemoryStaticGrid.ts b/frontend/src/ts/ervu/component/grid/InMemoryStaticGrid.ts index c9ff00c5..5d64be8f 100644 --- a/frontend/src/ts/ervu/component/grid/InMemoryStaticGrid.ts +++ b/frontend/src/ts/ervu/component/grid/InMemoryStaticGrid.ts @@ -1,4 +1,5 @@ import { + Event, GridColumnIdUtils, GridRow, GridRowModelType, @@ -7,7 +8,7 @@ import { } from "@webbpm/base-package"; import {ChangeDetectionStrategy, Component} from "@angular/core"; import { - ColDef, + ColDef, FilterChangedEvent, ICellRendererParams, ITooltipParams, ValueFormatterParams, @@ -24,6 +25,8 @@ import {StaticGridColumn} from "../../../generated/ru/micord/ervu/property/grid/ changeDetection: ChangeDetectionStrategy.OnPush }) export class InMemoryStaticGrid extends GridV2 { + @Visible("false") + public filterChangeEvent: Event = new Event(); private rpcService: InMemoryStaticGridRpcService; @@ -109,4 +112,14 @@ export class InMemoryStaticGrid extends GridV2 { public getRowDataSize(): number { return this.rowData ? this.rowData.length : 0; } + + @Visible() + public hasFilterModel(): boolean { + return !!this.getGridApi().getFilterModel(); + } + + public columnFilterChanged(event: FilterChangedEvent) { + this.filterChangeEvent.trigger(event); + super.columnFilterChanged(event); + } } diff --git a/resources/src/main/resources/business-model/Журнал взаимодействия.page b/resources/src/main/resources/business-model/Журнал взаимодействия.page index afe5cb02..7b306f3b 100644 --- a/resources/src/main/resources/business-model/Журнал взаимодействия.page +++ b/resources/src/main/resources/business-model/Журнал взаимодействия.page @@ -307,6 +307,12 @@ + + visible + +false + + @@ -431,6 +437,41 @@ + + + + + behavior + + {"objectId":"26242dda-11df-42f0-be93-9fe67ccc016e","packageName":"component.button","className":"Button","type":"TS"} + + + + method + + "setVisible" + + + + value + + + + staticValue + + + boolean + + +false + + + + + + + + @@ -584,6 +625,166 @@ + + + + + + + + 98594cec-0a9b-4cef-af09-e1b71cb2ad9e + dec5e904-4f52-444e-8478-d873461616d6 + AC - Кнопка visibility + false + false + + + + eventRefs + + + + + + behavior + + {"objectId":"bbaf33d7-0679-440b-a394-cb805ce80300","packageName":"ervu.component.grid","className":"InMemoryStaticGrid","type":"TS"} + + + + propertyName + + "filterChangeEvent" + + + + + + + + + ifCondition + + + + conditions + + + + + + _isGroupSelected + +false + + + + one + + + + conditionFirstPart + + + + objectValue + + + +behavior + + {"objectId":"bbaf33d7-0679-440b-a394-cb805ce80300","packageName":"ervu.component.grid","className":"InMemoryStaticGrid","type":"TS"} + + + +method + + "hasFilterModel" + + + + + + + + + + conditionSecondPart + + + + staticValue + + + boolean + + + true + + + + + + + operation + + "EQUALS" + + + + + + + + + + + + logicalOperation + + null + + + + + + + thenActions + + + + + + behavior + + {"objectId":"26242dda-11df-42f0-be93-9fe67ccc016e","packageName":"component.button","className":"Button","type":"TS"} + + + + method + + "setVisible" + + + + value + + + + staticValue + + + boolean + + +true + + + + + + + From dabc1a9ec9aa3d519aee5c3eb30999d14e8bbe02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A0=D0=B0=D1=83=D1=84=20=D0=9B=D0=B0=D1=82=D1=8B=D0=BF?= =?UTF-8?q?=D0=BE=D0=B2?= Date: Fri, 27 Dec 2024 12:37:52 +0300 Subject: [PATCH 14/20] SUPPORT-8831: fix for review (1) --- .../src/ts/ervu/component/grid/InMemoryStaticGrid.ts | 9 ++++++--- .../resources/business-model/Журнал взаимодействия.page | 4 ++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/frontend/src/ts/ervu/component/grid/InMemoryStaticGrid.ts b/frontend/src/ts/ervu/component/grid/InMemoryStaticGrid.ts index 5d64be8f..acd12c33 100644 --- a/frontend/src/ts/ervu/component/grid/InMemoryStaticGrid.ts +++ b/frontend/src/ts/ervu/component/grid/InMemoryStaticGrid.ts @@ -25,8 +25,9 @@ import {StaticGridColumn} from "../../../generated/ru/micord/ervu/property/grid/ changeDetection: ChangeDetectionStrategy.OnPush }) export class InMemoryStaticGrid extends GridV2 { + // todo: remove on updating platform version up to 3.188 @Visible("false") - public filterChangeEvent: Event = new Event(); + public columnFiltersChanged: Event = new Event(); private rpcService: InMemoryStaticGridRpcService; @@ -113,13 +114,15 @@ export class InMemoryStaticGrid extends GridV2 { return this.rowData ? this.rowData.length : 0; } + // todo: remove on updating platform version up to 3.188 @Visible() - public hasFilterModel(): boolean { + public hasColumnFilters(): boolean { return !!this.getGridApi().getFilterModel(); } + // todo: remove on updating platform version up to 3.188 public columnFilterChanged(event: FilterChangedEvent) { - this.filterChangeEvent.trigger(event); + this.columnFiltersChanged.trigger(event); super.columnFilterChanged(event); } } diff --git a/resources/src/main/resources/business-model/Журнал взаимодействия.page b/resources/src/main/resources/business-model/Журнал взаимодействия.page index 7b306f3b..0e674a9d 100644 --- a/resources/src/main/resources/business-model/Журнал взаимодействия.page +++ b/resources/src/main/resources/business-model/Журнал взаимодействия.page @@ -654,7 +654,7 @@ propertyName - "filterChangeEvent" + "columnFiltersChanged" @@ -699,7 +699,7 @@ method - "hasFilterModel" + "hasColumnFilters" From 61a2c3b5e3b9efefafb941fc452defc3a11f1a24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A0=D0=B0=D1=83=D1=84=20=D0=9B=D0=B0=D1=82=D1=8B=D0=BF?= =?UTF-8?q?=D0=BE=D0=B2?= Date: Fri, 27 Dec 2024 15:57:11 +0300 Subject: [PATCH 15/20] SUPPORT-8831: fix the ACes --- .../business-model/Журнал взаимодействия.page | 405 +++++++++++------- 1 file changed, 250 insertions(+), 155 deletions(-) diff --git a/resources/src/main/resources/business-model/Журнал взаимодействия.page b/resources/src/main/resources/business-model/Журнал взаимодействия.page index 0e674a9d..0737adeb 100644 --- a/resources/src/main/resources/business-model/Журнал взаимодействия.page +++ b/resources/src/main/resources/business-model/Журнал взаимодействия.page @@ -308,9 +308,214 @@ - visible + disabled -false +true + + + + + + + 98594cec-0a9b-4cef-af09-e1b71cb2ad9e + 2332e342-cb03-48cf-9745-e1bfbad545d2 + AC обновление текста + false + false + + + + eventRefs + + + + + + behavior + + {"objectId":"9b7c3369-e1fe-44f6-88f9-f8d9c83b30dc","packageName":"component.field","className":"NumberField","type":"TS"} + + + + propertyName + + "valueChangeEvent" + + + + + + + + + ifCondition + + + + logicalOperation + + null + + + + + + + thenActions + + + + + + behavior + + {"objectId":"7f891535-8dde-4e00-8064-584cad7ffcfd","packageName":"component","className":"Text","type":"TS"} + + + + method + + "setValue" + + + + value + + + + objectValue + + + + argument + + null + + + + behavior + + {"objectId":"9b7c3369-e1fe-44f6-88f9-f8d9c83b30dc","packageName":"component.field","className":"NumberField","type":"TS"} + + + + method + + "getTextValue" + + + + + + + + + + + + + + + + + + 98594cec-0a9b-4cef-af09-e1b71cb2ad9e + 7f600c0d-ad59-46ad-9aa8-037fdfaaac14 + AC установка количества + false + false + + + + eventRefs + + + + + + behavior + + {"objectId":"bbaf33d7-0679-440b-a394-cb805ce80300","packageName":"ervu.component.grid","className":"InMemoryStaticGrid","type":"TS"} + + + + propertyName + + "gridLoaded" + + + + + + + + + ifCondition + + + + logicalOperation + + null + + + + + + + thenActions + + + + + + behavior + + {"objectId":"9b7c3369-e1fe-44f6-88f9-f8d9c83b30dc","packageName":"component.field","className":"NumberField","type":"TS"} + + + + method + + "setValue" + + + + value + + + + objectValue + + + + argument + + null + + + + behavior + + {"objectId":"bbaf33d7-0679-440b-a394-cb805ce80300","packageName":"ervu.component.grid","className":"InMemoryStaticGrid","type":"TS"} + + + + method + + "getRowDataSize" + + + + + + + + + + + + @@ -319,7 +524,7 @@ 98594cec-0a9b-4cef-af09-e1b71cb2ad9e 6022b88c-7c96-4961-9a03-042d71e4ac16 - Обработка событий + AC нажатие кнопки false false @@ -437,7 +642,26 @@ - + + + + + + + + + + 98594cec-0a9b-4cef-af09-e1b71cb2ad9e + dec5e904-4f52-444e-8478-d873461616d6 + AC доступность кнопки + false + false + + + + elseActions + + @@ -449,7 +673,7 @@ method - "setVisible" + "setEnabled" @@ -472,25 +696,12 @@ - - - - - - - 98594cec-0a9b-4cef-af09-e1b71cb2ad9e - 7f600c0d-ad59-46ad-9aa8-037fdfaaac14 - Action Controller - false - false - - eventRefs - + @@ -508,141 +719,7 @@ - - - - ifCondition - - - - logicalOperation - - null - - - - - - - thenActions - - - - - - behavior - - {"objectId":"9b7c3369-e1fe-44f6-88f9-f8d9c83b30dc","packageName":"component.field","className":"NumberField","type":"TS"} - - - - method - - "setValue" - - - - value - - - - objectValue - - - - argument - - null - - - - behavior - - {"objectId":"bbaf33d7-0679-440b-a394-cb805ce80300","packageName":"ervu.component.grid","className":"InMemoryStaticGrid","type":"TS"} - - - - method - - "getRowDataSize" - - - - - - - - - - - - - - - - behavior - - {"objectId":"7f891535-8dde-4e00-8064-584cad7ffcfd","packageName":"component","className":"Text","type":"TS"} - - - - method - - "setValue" - - - - value - - - - objectValue - - - - argument - - null - - - - behavior - - {"objectId":"9b7c3369-e1fe-44f6-88f9-f8d9c83b30dc","packageName":"component.field","className":"NumberField","type":"TS"} - - - - method - - "getTextValue" - - - - - - - - - - - - - - - - - - 98594cec-0a9b-4cef-af09-e1b71cb2ad9e - dec5e904-4f52-444e-8478-d873461616d6 - AC - Кнопка visibility - false - false - - - - eventRefs - - + @@ -659,6 +736,24 @@ + + + + + + behavior + + {"objectId":"9b7c3369-e1fe-44f6-88f9-f8d9c83b30dc","packageName":"component.field","className":"NumberField","type":"TS"} + + + + propertyName + + "valueChangeEvent" + + + + @@ -763,7 +858,7 @@ method - "setVisible" + "setEnabled" From 52f50266490c868ce645e58dbda17a8fa9f4fa16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A0=D0=B0=D1=83=D1=84=20=D0=9B=D0=B0=D1=82=D1=8B=D0=BF?= =?UTF-8?q?=D0=BE=D0=B2?= Date: Fri, 27 Dec 2024 17:42:26 +0300 Subject: [PATCH 16/20] SUPPORT-8831: button enable changed to visible --- .../resources/business-model/Журнал взаимодействия.page | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/resources/src/main/resources/business-model/Журнал взаимодействия.page b/resources/src/main/resources/business-model/Журнал взаимодействия.page index 0737adeb..fb880393 100644 --- a/resources/src/main/resources/business-model/Журнал взаимодействия.page +++ b/resources/src/main/resources/business-model/Журнал взаимодействия.page @@ -308,9 +308,9 @@ - disabled + visible -true +false @@ -673,7 +673,7 @@ method - "setEnabled" + "setVisible" @@ -858,7 +858,7 @@ method - "setEnabled" + "setVisible" From d45d25baaf95092ce36b413d202d3e8fd087f855 Mon Sep 17 00:00:00 2001 From: kochetkov Date: Fri, 27 Dec 2024 19:47:47 +0300 Subject: [PATCH 17/20] SUPPORT-8830 fixes --- .../ervu/security/LogoutSuccessHandler.java | 4 +- .../ervu/security/esia/config/EsiaConfig.java | 7 ++ .../esia/service/EsiaAuthService.java | 20 ++--- .../webbpm/jwt/helper/SecurityHelper.java | 90 ++++++++++++++----- .../webbpm/jwt/util/SecurityUtil.java | 24 ----- config.md | 8 +- config/micord.env | 1 + frontend/index.webpack.html | 3 + .../template/app/component/log_out.html | 7 +- .../modules/app/component/logout.component.ts | 39 +++++--- 10 files changed, 127 insertions(+), 76 deletions(-) diff --git a/backend/src/main/java/ru/micord/ervu/security/LogoutSuccessHandler.java b/backend/src/main/java/ru/micord/ervu/security/LogoutSuccessHandler.java index 9993b234..3867b41a 100644 --- a/backend/src/main/java/ru/micord/ervu/security/LogoutSuccessHandler.java +++ b/backend/src/main/java/ru/micord/ervu/security/LogoutSuccessHandler.java @@ -25,9 +25,7 @@ public class LogoutSuccessHandler public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException { String url = esiaAuthService.logout(request, response); - response.setStatus(HttpServletResponse.SC_OK); - response.getWriter().write(url); - response.getWriter().flush(); + response.sendRedirect(url); CsrfToken csrfToken = this.csrfTokenRepository.generateToken(request); this.csrfTokenRepository.saveToken(csrfToken, request, response); } diff --git a/backend/src/main/java/ru/micord/ervu/security/esia/config/EsiaConfig.java b/backend/src/main/java/ru/micord/ervu/security/esia/config/EsiaConfig.java index b35991d5..2207f686 100644 --- a/backend/src/main/java/ru/micord/ervu/security/esia/config/EsiaConfig.java +++ b/backend/src/main/java/ru/micord/ervu/security/esia/config/EsiaConfig.java @@ -29,6 +29,9 @@ public class EsiaConfig { @Value("${esia.redirect.url}") private String redirectUrl; + @Value("${esia.logout.redirect.url}") + private String logoutRedirectUrl; + @Value("${sign.url}") private String signUrl; @@ -101,6 +104,10 @@ public class EsiaConfig { return esiaTokenUrl; } + public String getLogoutRedirectUrl() { + return logoutRedirectUrl; + } + public String getEsiaUploadDataRole() { return esiaUploadDataRole; } diff --git a/backend/src/main/java/ru/micord/ervu/security/esia/service/EsiaAuthService.java b/backend/src/main/java/ru/micord/ervu/security/esia/service/EsiaAuthService.java index 55aff54f..de323ab4 100644 --- a/backend/src/main/java/ru/micord/ervu/security/esia/service/EsiaAuthService.java +++ b/backend/src/main/java/ru/micord/ervu/security/esia/service/EsiaAuthService.java @@ -15,7 +15,6 @@ import java.util.Arrays; 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; @@ -120,7 +119,7 @@ public class EsiaAuthService { "obj_type", "B L F A", "client_certificate_hash", esiaConfig.getClientCertHash()); - return makeRequest(url, params); + return buildUrl(url, params); } catch (Exception e) { throw new RuntimeException(e); @@ -143,12 +142,13 @@ public class EsiaAuthService { .replace("+", "%20"); } - private static String makeRequest(URL url, Map params) { + private static String buildUrl(URL url, Map params) { StringBuilder uriBuilder = new StringBuilder(url.toString()); uriBuilder.append('?'); for (Map.Entry node : params.entrySet()) { uriBuilder.append(node.getKey()).append('=').append(node.getValue()).append("&"); } + uriBuilder.deleteCharAt(uriBuilder.length() - 1); return uriBuilder.toString(); } @@ -218,8 +218,7 @@ public class EsiaAuthService { EsiaTokensStore.addRefreshToken(prnOid, esiaRefreshTokenStr, expiresIn); Token token = jwtTokenService.createAccessToken(esiaAccessToken.getSbj_id(), expiresIn, ervuId, hasRole); int expiry = tokenResponse.getExpires_in().intValue(); - Cookie accessCookie = securityHelper.createAccessCookie(token.getValue(), expiry); - response.addCookie(accessCookie); + securityHelper.addAccessCookies(response,token.getValue(), expiry); UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(token.getUserAccountId(), null); SecurityContext context = SecurityContextHolder.createEmptyContext(); @@ -228,8 +227,6 @@ public class EsiaAuthService { authenticationManager.authenticate(jwtAuthentication); context.setAuthentication(jwtAuthentication); SecurityContextHolder.setContext(context); - Cookie authMarkerCookie = securityHelper.createAuthMarkerCookie("true", expiry); - response.addCookie(authMarkerCookie); if (!hasRole) { LOGGER.error("The user with id = " + prnOid + " does not have the required role"); return new ResponseEntity<>( @@ -307,8 +304,7 @@ public class EsiaAuthService { String ervuId = getErvuId(esiaAccessTokenStr, prnOid); Token token = jwtTokenService.createAccessToken(esiaAccessToken.getSbj_id(), expiresIn, ervuId, true); int expiry = tokenResponse.getExpires_in().intValue(); - Cookie accessCookie = securityHelper.createAccessCookie(token.getValue(), expiry); - response.addCookie(accessCookie); + securityHelper.addAccessCookies(response, token.getValue(), expiry); UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(token.getUserAccountId(), null); SecurityContext context = SecurityContextHolder.createEmptyContext(); @@ -317,8 +313,6 @@ public class EsiaAuthService { authenticationManager.authenticate(jwtAuthentication); context.setAuthentication(jwtAuthentication); SecurityContextHolder.setContext(context); - Cookie authMarkerCookie = securityHelper.createAuthMarkerCookie("true", expiry); - response.addCookie(authMarkerCookie); } catch (Exception e) { throw new RuntimeException(e); @@ -364,12 +358,12 @@ public class EsiaAuthService { EsiaTokensStore.removeAccessToken(userId); EsiaTokensStore.removeRefreshToken(userId); String logoutUrl = esiaConfig.getEsiaBaseUri() + esiaConfig.getEsiaLogoutUrl(); - String redirectUrl = esiaConfig.getRedirectUrl(); + String redirectUrl = esiaConfig.getLogoutRedirectUrl(); URL url = new URL(logoutUrl); Map params = mapOf( "client_id", esiaConfig.getClientId(), "redirect_url", redirectUrl); - return makeRequest(url, params); + return buildUrl(url, params); } catch (Exception e) { throw new RuntimeException(e); diff --git a/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/helper/SecurityHelper.java b/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/helper/SecurityHelper.java index 0a222c79..9c966f60 100644 --- a/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/helper/SecurityHelper.java +++ b/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/helper/SecurityHelper.java @@ -1,43 +1,89 @@ 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 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_TOKEN; -import static ru.micord.ervu.security.webbpm.jwt.util.SecurityUtil.createCookie; public final class SecurityHelper { @Value("${cookie.path:#{null}}") 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) { - Cookie tokenCookie = createCookie(AUTH_TOKEN, null, null); - tokenCookie.setMaxAge(0); - tokenCookie.setPath(accessCookiePath); - tokenCookie.setHttpOnly(true); - response.addCookie(tokenCookie); + ResponseCookie emptyAuthToken = createCookie(AUTH_TOKEN, null, accessCookiePath) + .maxAge(0).build(); + addResponseCookie(response, emptyAuthToken); - Cookie markerCookie = createCookie(AUTH_MARKER, null, null); - markerCookie.setMaxAge(0); - markerCookie.setPath("/"); - response.addCookie(markerCookie); + ResponseCookie emptyAuthMarker = createCookie(AUTH_MARKER, null, "/") + .maxAge(0) + .secure(false) + .httpOnly(false) + .build(); + addResponseCookie(response, emptyAuthMarker); } - public Cookie createAccessCookie(String cookieValue, int expiry) { - Cookie authToken = createCookie(SecurityUtil.AUTH_TOKEN, cookieValue, accessCookiePath); - authToken.setPath(accessCookiePath); - authToken.setMaxAge(expiry); - return authToken; + private void addResponseCookie(HttpServletResponse response, ResponseCookie cookie) { + response.addHeader(HttpHeaders.SET_COOKIE, cookie.toString()); } - public Cookie createAuthMarkerCookie(String cookieValue, int expiry) { - Cookie marker = createCookie(AUTH_MARKER, cookieValue, "/"); - marker.setMaxAge(expiry); - marker.setHttpOnly(false); - return marker; + public void addAccessCookies(HttpServletResponse response, String cookieValue, int expiry) { + ResponseCookie authTokenCookie = createCookie(AUTH_TOKEN, cookieValue, accessCookiePath) + .maxAge(expiry) + .build(); + 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); } } diff --git a/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/util/SecurityUtil.java b/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/util/SecurityUtil.java index b2314e37..a190a852 100644 --- a/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/util/SecurityUtil.java +++ b/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/util/SecurityUtil.java @@ -1,16 +1,10 @@ package ru.micord.ervu.security.webbpm.jwt.util; -import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; -import org.springframework.web.context.request.RequestAttributes; -import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.util.WebUtils; -import static org.springframework.web.context.request.RequestAttributes.REFERENCE_REQUEST; - public final class SecurityUtil { public static final String AUTH_TOKEN = "auth_token"; @@ -20,24 +14,6 @@ public final class SecurityUtil { //empty } - public static Cookie createCookie(String name, String value, String path) { - String cookieValue = value != null ? URLEncoder.encode(value, StandardCharsets.UTF_8) : null; - Cookie cookie = new Cookie(name, cookieValue); - RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); - HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference( - REFERENCE_REQUEST); - - if (path != null) { - cookie.setPath(path); - } - else { - cookie.setPath(request.getContextPath()); - } - cookie.setHttpOnly(true); - - return cookie; - } - public static String extractAuthToken(HttpServletRequest httpRequest) { Cookie cookie = WebUtils.getCookie(httpRequest, AUTH_TOKEN); return cookie != null ? cookie.getValue() : null; diff --git a/config.md b/config.md index 850d2b34..ac6fc555 100644 --- a/config.md +++ b/config.md @@ -768,9 +768,13 @@ JBPM использует 3 корневых категории логирова - `ESIA_CLIENT_ID` - – идентификатор системы-клиента (мнемоника системы в ЕСИА указанная прописными буквами) - `ESIA_REDIRECT_URL` - ссылка, по которой должен быть направлен пользователь после того, как ЕСИА даст разрешение на доступ к ресурсу. -Важно: ESIA_REDIRECT_URL должна содержать полный адрес вплоть до последнего слэша +Важно: `ESIA_REDIRECT_URL` должна содержать полный адрес вплоть до последнего слэша - 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 - неправильное значение параметра - `ESIA_UPLOAD_DATA_ROLE` - мнемоника группы, для роли "Сотрудник, ответственный за военно-учетную работу". - `SIGN_URL` - url для подписания с помощью КриптоПро секрета клиента, необходимого для аутентификации через ЕСИА. @@ -813,4 +817,4 @@ JBPM использует 3 корневых категории логирова - `ERVU_KAFKA_JOURNAL_REPLY_TOPIC` - топик для чтения данных по журналу взаимодействия - `ERVU_KAFKA_EXCERPT_REQUEST_TOPIC` - топик для записи запроса для получения выписки по журналу взаимодействия - `ERVU_KAFKA_EXCERPT_REPLY_TOPIC` - топик для чтения выписки по журналу взаимодействия. Содержит ссылку на S3 с файлом выписки -- `DB.JOURNAL.EXCLUDED.STATUSES` - статусы файла, которые необходимо исключить при получении данных по журналу взаимодействия из базы данных приложения \ No newline at end of file +- `DB.JOURNAL.EXCLUDED.STATUSES` - статусы файла, которые необходимо исключить при получении данных по журналу взаимодействия из базы данных приложения diff --git a/config/micord.env b/config/micord.env index 2a3c14e9..d1d0200d 100644 --- a/config/micord.env +++ b/config/micord.env @@ -24,6 +24,7 @@ ESIA_ORG_SCOPE_URL=http://esia.gosuslugi.ru/ ESIA_BASE_URI=https://esia-portal1.test.gosuslugi.ru/ ESIA_CLIENT_ID=MNSV89 ESIA_REDIRECT_URL=https://lkrp-dev.micord.ru/ul/ +ESIA_LOGOUT_REDIRECT_URL=https://lkrp-dev.micord.ru/ul/home.html ESIA_UPLOAD_DATA_ROLE=MNSV89_UPLOAD_DATA SIGN_URL=https://ervu-sign-dev.k8s.micord.ru/sign ESIA_CLIENT_CERT_HASH=04508B4B0B58776A954A0E15F574B4E58799D74C61EE020B3330716C203E3BDD diff --git a/frontend/index.webpack.html b/frontend/index.webpack.html index 54801a3c..7b846a88 100644 --- a/frontend/index.webpack.html +++ b/frontend/index.webpack.html @@ -4,6 +4,9 @@ Личный кабинет юр.лица + + diff --git a/frontend/src/resources/template/app/component/log_out.html b/frontend/src/resources/template/app/component/log_out.html index 996c245f..12503171 100644 --- a/frontend/src/resources/template/app/component/log_out.html +++ b/frontend/src/resources/template/app/component/log_out.html @@ -1,7 +1,10 @@ +
{{getOrgUnitName()}}
Данные организации - +
- + diff --git a/frontend/src/ts/modules/app/component/logout.component.ts b/frontend/src/ts/modules/app/component/logout.component.ts index 0ac178ae..deee5d42 100644 --- a/frontend/src/ts/modules/app/component/logout.component.ts +++ b/frontend/src/ts/modules/app/component/logout.component.ts @@ -1,23 +1,46 @@ -import {ChangeDetectorRef, Component, OnInit} from "@angular/core"; -import {Router} from "@angular/router"; -import {HttpClient} from "@angular/common/http"; +import {ChangeDetectorRef, Component, DoCheck, OnInit} from "@angular/core"; +import {HttpClient, HttpXsrfTokenExtractor} from "@angular/common/http"; import {AuthenticationService} from "../../security/authentication.service"; +import {AppConfigService} from "@webbpm/base-package"; @Component({ moduleId: module.id, selector: "[log-out]", 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 orgUnitName: string; + csrfValue: any; + formAction: any; - constructor(private router: Router, private httpClient: HttpClient, - private authenticationService: AuthenticationService, private cd: ChangeDetectorRef) { + constructor(private httpClient: HttpClient, + private authenticationService: AuthenticationService, + 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 { + this.csrfValue = this.tokenExtractor.getToken(); let isAuth = this.authenticationService.isAuthenticated(); if (isAuth) { Promise.all([ @@ -31,10 +54,6 @@ export class LogOutComponent implements OnInit{ } } - public logout(): void { - this.authenticationService.logout(); - } - public getUserFullname(): string { return this.userFullname; } From 8ed21d6e8b187b166de8d3a2f233755a66779c74 Mon Sep 17 00:00:00 2001 From: Eduard Tihomirov Date: Sat, 28 Dec 2024 15:02:49 +0300 Subject: [PATCH 18/20] SUPPORT-8819: Fix --- .../main/resources/business-model/Личный кабинет юр лица.page | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/src/main/resources/business-model/Личный кабинет юр лица.page b/resources/src/main/resources/business-model/Личный кабинет юр лица.page index bd76c2ff..9547206b 100644 --- a/resources/src/main/resources/business-model/Личный кабинет юр лица.page +++ b/resources/src/main/resources/business-model/Личный кабинет юр лица.page @@ -10438,7 +10438,7 @@ initialValue - "Информацию о статусе приема сведений можно отслеживать в \u003ca href\u003d\"/#/filesentlog\"\u003eЖурнале взаимодействий с Реестром ВУ\u003c/a\u003e" + "Информацию о статусе приема сведений можно отслеживать в \u003ca href\u003d\"./#/filesentlog\"\u003eЖурнале взаимодействий с Реестром ВУ\u003c/a\u003e" From 1c357c97dced8930aed28f9975bd78dbf0938f42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A0=D0=B0=D1=83=D1=84=20=D0=9B=D0=B0=D1=82=D1=8B=D0=BF?= =?UTF-8?q?=D0=BE=D0=B2?= Date: Sat, 28 Dec 2024 16:05:52 +0300 Subject: [PATCH 19/20] SUPPORT-8831: fix the method of filter existence --- .../ervu/component/grid/InMemoryStaticGrid.ts | 14 +++- .../business-model/Журнал взаимодействия.page | 73 ++++++++++--------- 2 files changed, 50 insertions(+), 37 deletions(-) diff --git a/frontend/src/ts/ervu/component/grid/InMemoryStaticGrid.ts b/frontend/src/ts/ervu/component/grid/InMemoryStaticGrid.ts index acd12c33..0d614dcb 100644 --- a/frontend/src/ts/ervu/component/grid/InMemoryStaticGrid.ts +++ b/frontend/src/ts/ervu/component/grid/InMemoryStaticGrid.ts @@ -117,7 +117,19 @@ export class InMemoryStaticGrid extends GridV2 { // todo: remove on updating platform version up to 3.188 @Visible() public hasColumnFilters(): boolean { - return !!this.getGridApi().getFilterModel(); + const filterModel = this.getGridApi().getFilterModel(); + if (filterModel) { + const keys = Object.keys(filterModel); + if (keys.length > 0) { + keys.forEach(key => { + const model = filterModel[key]; + if (model) { + return true; + } + }); + } + } + return false; } // todo: remove on updating platform version up to 3.188 diff --git a/resources/src/main/resources/business-model/Журнал взаимодействия.page b/resources/src/main/resources/business-model/Журнал взаимодействия.page index fb880393..33005c43 100644 --- a/resources/src/main/resources/business-model/Журнал взаимодействия.page +++ b/resources/src/main/resources/business-model/Журнал взаимодействия.page @@ -642,6 +642,41 @@
+ + + + + behavior + + {"objectId":"26242dda-11df-42f0-be93-9fe67ccc016e","packageName":"component.button","className":"Button","type":"TS"} + + + + method + + "setVisible" + + + + value + + + + staticValue + + + boolean + + +false + + + + + + + + @@ -701,24 +736,7 @@ eventRefs - - - - - behavior - - {"objectId":"bbaf33d7-0679-440b-a394-cb805ce80300","packageName":"ervu.component.grid","className":"InMemoryStaticGrid","type":"TS"} - - - - propertyName - - "gridLoaded" - - - - - + @@ -737,24 +755,7 @@ - - - - - behavior - - {"objectId":"9b7c3369-e1fe-44f6-88f9-f8d9c83b30dc","packageName":"component.field","className":"NumberField","type":"TS"} - - - - propertyName - - "valueChangeEvent" - - - - - + From c2ab31331a3ea8de8644359dc980348971090ef7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A0=D0=B0=D1=83=D1=84=20=D0=9B=D0=B0=D1=82=D1=8B=D0=BF?= =?UTF-8?q?=D0=BE=D0=B2?= Date: Sat, 28 Dec 2024 23:31:03 +0300 Subject: [PATCH 20/20] SUPPORT-8831: fix the method of filter existence (2) --- .../ts/ervu/component/grid/InMemoryStaticGrid.ts | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/frontend/src/ts/ervu/component/grid/InMemoryStaticGrid.ts b/frontend/src/ts/ervu/component/grid/InMemoryStaticGrid.ts index 0d614dcb..0d4b7db6 100644 --- a/frontend/src/ts/ervu/component/grid/InMemoryStaticGrid.ts +++ b/frontend/src/ts/ervu/component/grid/InMemoryStaticGrid.ts @@ -117,19 +117,8 @@ export class InMemoryStaticGrid extends GridV2 { // todo: remove on updating platform version up to 3.188 @Visible() public hasColumnFilters(): boolean { - const filterModel = this.getGridApi().getFilterModel(); - if (filterModel) { - const keys = Object.keys(filterModel); - if (keys.length > 0) { - keys.forEach(key => { - const model = filterModel[key]; - if (model) { - return true; - } - }); - } - } - return false; + const filterModel: { [key: string]: any; } = this.gridApi.getFilterModel(); + return !!filterModel && Object.keys(filterModel).length > 0; } // todo: remove on updating platform version up to 3.188