Commit: 9c24ca4

Commit Details

SHA9c24ca40dbca995b0007e09659176f7c90e13392
Tree4c630341b69f778f78daa19bfebcc1bfdebe1836
Author<f69e50@finnacloud.com> 1766442705 +0300
Committer<f69e50@finnacloud.com> 1766442705 +0300
Message
add CI configuration and test script for Jenkins build
GPG Signature
-----BEGIN PGP SIGNATURE-----

iQJSBAABCAA8FiEEWJb139mJI+vZ81KkoAIVSUsXI0oFAmlJxtEeHHNvcGhpYS5l
cmFzbGFuQGZpbm5hY2xvdWQuY29tAAoJEKACFUlLFyNKwOEP/RJdPEnaGlYKr4zE
NkU5vATgzcYMHxCO6p3T6JqsfHsvv2d65vedOJ8LsSHFtT9AN/yXqZKV2722R5CG
WLsPzbVYJSXexKVZ8D7Zpf+DTu+/OAlWUE+XHMm+bJYVpDmqUo0ak/qX6vz6VYtW
bSRPMtM9g8WZKZqbBxLK7Sg1IkYFsFjEWmvn6mbD9C7k/0y4Sxp6Xee26xAx1sdI
+srAjwFgF+wJw0OAQoBA2jykTOiib93n9gdc9wbgl4AYUvdcaX3Hxv8LTl3Bu88N
2rqaL+OmjXtkFkEAiBaruvZZCt+aqp14gTgOM0wcLp1I1FP7uOFNOg0F0zSUawzY
Fuw3w6CKebkpbixGfxtJqrLl1IbPAhd92TxRVerZbDEnWpXW3a9HoGWRu5KFX/ny
ww+8M53ziWFNcHqpIyI5adRjG74C+5MdvC04J0/Sh1X8mykWcjE96Wu2/iRY9XQe
07I94ZVO0RaBSjSUnIItfhAgBXi03nzx+ZPw2tM4VHosn2zZjpzT8+KNQ0EXYhuT
AzgqcOKV94ZkM+48ZePvUFXsJxhMSkpXIQxGWWBnU9gjm3QAUsuCyqZGKXgVY9Vo
mDlLBl83Nhx+/7V8AFJO2gUmaph9YB01p3SMDfE++lLqX1BwdguFVrQib30OsRnq
e86d/6MrRABKf+FjtaulHY9+e8LS
=9ZJj
-----END PGP SIGNATURE-----

✓ Verified

File: src/main/resources/static/js/csrf.js

1 // CSRF Token Management
2 let csrfToken = null;
3 let tokenPromise = null;
4
5 // Get CSRF token from server (force refresh if needed)
6 async function getCsrfToken(forceRefresh = false) {
7 // If forcing refresh, clear existing token
8 if (forceRefresh) {
9 csrfToken = null;
10 tokenPromise = null;
11 }
12
13 // Return existing token if available and not forcing refresh
14 if (csrfToken && !forceRefresh) {
15 return csrfToken;
16 }
17
18 // If a request is already in progress, wait for it
19 if (tokenPromise) {
20 return tokenPromise;
21 }
22
23 // Fetch new token
24 tokenPromise = (async () => {
25 try {
26 const response = await fetch('/api/csrf-token', {
27 credentials: 'include' // Include cookies
28 });
29 const data = await response.json();
30
31 if (data.success) {
32 csrfToken = data.csrfToken;
33 tokenPromise = null;
34 return csrfToken;
35 }
36 } catch (error) {
37 console.error('Error fetching CSRF token:', error);
38 tokenPromise = null;
39 }
40
41 return null;
42 })();
43
44 return tokenPromise;
45 }
46
47 // Refresh CSRF token (alias for force refresh)
48 async function refreshCsrfToken() {
49 return await getCsrfToken(true);
50 }
51
52 // Add CSRF token to fetch request
53 async function fetchWithCsrf(url, options = {}) {
54 const method = options.method || 'GET';
55 const stateChangingMethods = ['POST', 'PUT', 'PATCH', 'DELETE'];
56
57 // For state-changing requests, always get a fresh token first
58 if (stateChangingMethods.includes(method.toUpperCase())) {
59 // Always refresh token before state-changing requests
60 // This ensures we have a valid token even if the previous one was invalidated
61 await refreshCsrfToken();
62 } else if (!csrfToken) {
63 // For GET requests, only fetch if we don't have a token
64 await getCsrfToken();
65 }
66
67 // Add CSRF token to headers
68 const headers = {
69 ...options.headers,
70 'X-CSRF-Token': csrfToken || ''
71 };
72
73 const response = await fetch(url, {
74 ...options,
75 headers,
76 credentials: 'include' // Include cookies
77 });
78
79 // After state-changing requests, always refresh the token
80 // The server invalidates the used token, so we need a new one for the next request
81 if (stateChangingMethods.includes(method.toUpperCase())) {
82 // Try to get new token from response header (server sends it)
83 const newToken = response.headers.get('X-New-CSRF-Token');
84 if (newToken) {
85 csrfToken = newToken;
86 } else {
87 // If no header (or header not accessible), refresh token immediately
88 // This ensures we always have a fresh token for the next request
89 try {
90 await refreshCsrfToken();
91 } catch (err) {
92 console.error('Error refreshing CSRF token:', err);
93 }
94 }
95 }
96
97 return response;
98 }
99
100 // Initialize CSRF token on page load
101 if (document.readyState === 'loading') {
102 document.addEventListener('DOMContentLoaded', async () => {
103 await getCsrfToken();
104 });
105 } else {
106 // DOM already loaded
107 getCsrfToken();
108 }
109
110 // Make functions globally available
111 window.getCsrfToken = getCsrfToken;
112 window.refreshCsrfToken = refreshCsrfToken;
113 window.fetchWithCsrf = fetchWithCsrf;
114
115
116