Commit: 4617f76

Commit Details

SHA4617f76246bf039920879ae5497436d31494ed7c
Treee78bcb155880b8c167af124554a6db724c41264e
Author<f69e50@finnacloud.com> 1766442953 +0300
Committer<f69e50@finnacloud.com> 1766442953 +0300
Message
rename branch from main to master oops
GPG Signature
-----BEGIN PGP SIGNATURE-----

iQJSBAABCAA8FiEEWJb139mJI+vZ81KkoAIVSUsXI0oFAmlJx8keHHNvcGhpYS5l
cmFzbGFuQGZpbm5hY2xvdWQuY29tAAoJEKACFUlLFyNK2BQP/3EfkXtKsmQoqa4E
e9jdO5BKWUnHwF31PdpxExXwoogkZg2hSjSc0jB9htAKSbQspx+Pst7f9yj2Gf2u
ENGTEQHqqVeLEve2IPc1YJ+F+yedI3NE2PCZJ0+rh1/S14vQTT0kWMSqs6d8Te4K
x4hiTNNjfWidOXQ1vHMXl9iUnevmnko8XqNe3aBZ3JUSRLhhCvehsiPwSjfKGqB8
Sm9i1Y/HaTizFfl4WG5f6MppDgzV2I7Bm/c6K1oDIviO/Wken5vk4TXgLUWDfHJ5
d9m9gh4N9unX4Ivf5G22JVRzxPgox0Y0yFQwpj4IqQ9LzjT2Vz2s+hXoV6HZkfUW
BCLc/6oRmImcSflxOgV/TGaZrvysQ0pz32H8lyLoOI1QAS3o4u1icPFjfHlc5298
zpjGAqPjlVEx4Sjghrow4pb7sb/OyFihTwfjxlLgVfR4tXfb/l5rRt2f9vsm1HJB
qc9F/Qqc6xpb9ECyYZtuuCMToS0MRNkqy2KifrvOaKi2EznhcJu2VcLmjQJookFY
meevIkRenUvjwbs+aoDOa76HmycWkw1NtTtE9M+NSZ9SCBOD+Gp1rqO66z758bUQ
NmISh50GPDiZw5AKDrtsygWRZumLbrWHBleHm935V5O3gYkEKo9kb40Zf2sDsvlS
/wXQCTVz3XuSby3pyaMGgd3ol6gk
=YOD1
-----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