codevdesign 1.0.74 → 1.0.75

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,24 +7,38 @@ class RafraichisseurToken {
7
7
  private nomTemoin = 'csqc_jeton_secure_expiration'
8
8
  private urlPortail = ''
9
9
  private refreshPromise: Promise<void> | null = null
10
+ public loggerTrace = false
10
11
 
11
12
  // Lance une seule fois
12
- public async demarrer(nomTemoin: string | null, urlPortail: string): Promise<void> {
13
- urlPortail = urlPortail.replace(/\/+$/, '')
14
- if (nomTemoin == null || nomTemoin === '') nomTemoin = 'csqc_jeton_secure_expiration'
15
- this.nomTemoin = nomTemoin as string
16
- this.urlPortail = urlPortail
17
- await this.verifierJeton(nomTemoin as string, urlPortail)
13
+ public async demarrer(nomTemoin: string, urlPortail: string): Promise<void> {
14
+ window.rafraichisseurToken = this
15
+ if (this.loggerTrace) {
16
+ console.log('Nom témoin', nomTemoin)
17
+ console.log('URL portail', urlPortail)
18
+ }
19
+
20
+ if (nomTemoin == null || nomTemoin === '') {
21
+ console.warn('[RafraichisseurToken] nomTemoin invalide, rafraichisseur de token désactivé')
22
+ return
23
+ }
24
+ if (urlPortail == null || urlPortail === '') {
25
+ console.warn('[RafraichisseurToken] urlPortail invalide, rafraichisseur de token désactivé')
26
+ return
27
+ }
28
+ this.nomTemoin = nomTemoin
29
+ this.urlPortail = urlPortail.replace(/\/+$/, '')
30
+
31
+ await this.verifierJeton()
18
32
  if (this.timerId != null) return
19
33
  this.timerId = window.setInterval(() => {
20
- this.verifierJeton(nomTemoin as string, urlPortail)
34
+ this.verifierJeton()
21
35
  }, this.intervalleEnSecondes * 1000)
22
36
  }
23
37
 
24
38
  public attendreRefreshSiNecessaire(force = false): Promise<void> {
25
39
  if (this.refreshPromise) return this.refreshPromise
26
- if (force || !this.estJetonValide(this.nomTemoin)) {
27
- this.refreshPromise = this.rafraichir(this.nomTemoin, this.urlPortail).finally(() => {
40
+ if (force || !this.estJetonValide()) {
41
+ this.refreshPromise = this.rafraichir().finally(() => {
28
42
  this.refreshPromise = null
29
43
  })
30
44
  return this.refreshPromise
@@ -40,28 +54,30 @@ class RafraichisseurToken {
40
54
  }
41
55
  }
42
56
 
43
- public existeJeton = (nomTemoin: string) => {
44
- return this.estJetonValide(nomTemoin)
57
+ public existeJeton = () => {
58
+ return this.estJetonValide()
45
59
  }
46
60
 
47
- private async verifierJeton(nomTemoin: string, urlPortail: string): Promise<void> {
48
- if (this.popupAffiche) return
61
+ private async verifierJeton(): Promise<void> {
62
+ if (this.loggerTrace) console.log('[RafraichisseurToken] Vérification du jeton...')
63
+ if (this.popupAffiche) {
64
+ if (this.loggerTrace) console.log('[RafraichisseurToken] Popup affiché, vérification du jeton ignorée')
65
+ return
66
+ }
49
67
 
50
- if (!this.estJetonValide(nomTemoin)) {
68
+ if (!this.estJetonValide()) {
51
69
  if (!this.refreshPromise) {
52
- this.refreshPromise = this.rafraichir(nomTemoin, urlPortail).finally(() => {
70
+ this.refreshPromise = this.rafraichir().finally(() => {
53
71
  this.refreshPromise = null
54
72
  })
55
73
  }
56
74
  }
57
75
  }
58
76
 
59
- private estJetonValide(nomTemoin: string): boolean {
60
- if (this.popupAffiche || !nomTemoin) return true //On fait semblant que c'est valide pour ne pas provoquer un autre affichage du popup.
61
-
77
+ private estJetonValide(): boolean {
78
+ if (this.popupAffiche) return true //On fait semblant que c'est valide pour ne pas provoquer un autre affichage du popup.
62
79
 
63
-
64
- const tokenEncode = this.lireCookie(nomTemoin)
80
+ const tokenEncode = this.lireCookie()
65
81
  if (!tokenEncode) {
66
82
  return false
67
83
  }
@@ -87,12 +103,12 @@ class RafraichisseurToken {
87
103
  return true
88
104
  }
89
105
 
90
- private async rafraichir(nomCookie: string, urlPortail: string): Promise<void> {
91
- if (!nomCookie) return
92
- //console.log('[RafraichisseurToken] rafraichir() appelé')
93
- if (urlPortail == null || urlPortail == '') return
106
+ private async rafraichir(): Promise<void> {
107
+ if (this.loggerTrace) console.log('[RafraichisseurToken] rafraichir() appelé')
108
+
109
+ if (this.urlPortail == null || this.urlPortail == '') return
94
110
  this.popupAffiche = true // bloquer tout nouveau tick pendant le refresh
95
- const url = this.getRefreshUrl(urlPortail)
111
+ const url = this.getRefreshUrl()
96
112
  const controller = new AbortController()
97
113
  const timeout = setTimeout(() => controller.abort(), 10_000)
98
114
 
@@ -107,18 +123,18 @@ class RafraichisseurToken {
107
123
  })
108
124
 
109
125
  // redirection vers Azure AD → session expirée, l'iframe ne peut pas compléter le flow OIDC cross-site
110
- //console.log('[RafraichisseurToken] fetch réponse type:', resp.type, 'status:', resp.status)
126
+ if (this.loggerTrace) console.log('[RafraichisseurToken] fetch réponse type:', resp.type, 'status:', resp.status)
111
127
  if (resp.type === 'opaqueredirect' || resp.status === 302) {
112
- this.estDeconnecteAzure(urlPortail)
128
+ this.estDeconnecteAzure()
113
129
  return
114
130
  }
115
131
 
116
132
  // OK ou No Content: le cookie devrait être réécrit
117
133
  if (resp.status === 200 || resp.status === 204) {
118
- const jeton = this.lireCookie(nomCookie)
134
+ const jeton = this.lireCookie()
119
135
  if (!jeton) {
120
- // console.log('[RafraichisseurToken] 200 mais cookie absent → iframe')
121
- this.rafraichirParIframe(nomCookie, urlPortail)
136
+ if (this.loggerTrace) console.log('[RafraichisseurToken] 200 mais cookie absent → iframe')
137
+ this.rafraichirParIframe()
122
138
  } else {
123
139
  this.popupAffiche = false // succès, reprendre la surveillance
124
140
  }
@@ -127,8 +143,8 @@ class RafraichisseurToken {
127
143
 
128
144
  // non auth / expiré (401, 419) + IIS timeout (440)
129
145
  if (resp.status === 401 || resp.status === 419 || resp.status === 440) {
130
- // console.log('[RafraichisseurToken] statut auth → iframe')
131
- this.rafraichirParIframe(nomCookie, urlPortail)
146
+ if (this.loggerTrace) console.log('[RafraichisseurToken] statut auth → iframe')
147
+ this.rafraichirParIframe()
132
148
  return
133
149
  }
134
150
 
@@ -143,10 +159,10 @@ class RafraichisseurToken {
143
159
  }
144
160
  }
145
161
 
146
- private rafraichirParIframe(nomCookie: string, urlPortail: string): void {
162
+ private rafraichirParIframe(): void {
147
163
  this.popupAffiche = true // bloquer le timer pendant que l'iframe tente l'auth
148
164
  let iframe = document.createElement('iframe')
149
- const url = this.getRefreshUrl(urlPortail)
165
+ const url = this.getRefreshUrl()
150
166
  iframe.src = `${url}?urlRetour=${encodeURI(window.location.href)}`
151
167
  iframe.id = 'idRafrToken'
152
168
  iframe.style.display = 'none'
@@ -161,13 +177,15 @@ class RafraichisseurToken {
161
177
  }, 15_000)
162
178
 
163
179
  iframe.onload = () => {
180
+ if (this.loggerTrace) console.log('[RafraichisseurToken] iframe onload, vérification du jeton...')
164
181
  clearTimeout(iframeTimeout)
165
182
  iframe.onload = null // empêcher les re-entrées sur les redirects OIDC internes
166
- const nomSecure = nomCookie.replace('_expiration', '')
167
- const cookieAVerifier = nomSecure !== nomCookie ? nomSecure : nomCookie
168
- const jeton = this.lireCookie(cookieAVerifier)
183
+
184
+ const jeton = this.lireCookie()
169
185
  if (jeton == null || jeton === '') {
170
- this.estDeconnecteAzure(urlPortail)
186
+ if (this.loggerTrace)
187
+ console.log('[RafraichisseurToken] iframe onload, jeton toujours absent → déconnecté Azure')
188
+ this.estDeconnecteAzure()
171
189
  } else {
172
190
  this.popupAffiche = false // cookie recréé avec succès, reprendre la surveillance
173
191
  }
@@ -177,28 +195,27 @@ class RafraichisseurToken {
177
195
  }
178
196
  }
179
197
 
180
- private estDeconnecteAzure(urlPortail: string): void {
198
+ private estDeconnecteAzure(): void {
181
199
  //on envoie au portail, pas le choix
182
- urlPortail = urlPortail.replace(/\/+$/, '')
183
200
  const retour = encodeURI(window.location.href)
184
- window.open(`${urlPortail}/home/SeConnecter?urlRetour=${retour}`, '_self')
201
+
202
+ window.open(`${this.urlPortail}/home/SeConnecter?urlRetour=${retour}`, '_self')
185
203
  return
186
204
  }
187
205
 
188
- public deconnecterPortail(urlPortail: string): void {
189
- urlPortail = urlPortail.replace(/\/+$/, '')
190
- window.location.replace(`${urlPortail}/deconnecte?urlRetour=${encodeURIComponent(window.location.href)}`)
206
+ public deconnecterPortail(): void {
207
+ window.location.replace(`${this.urlPortail}/deconnecte?urlRetour=${encodeURIComponent(window.location.href)}`)
191
208
  }
192
209
 
193
- private lireCookie(nom: string): string | null {
210
+ private lireCookie(): string | null {
194
211
  if (!document.cookie) return null
195
212
  const cookies = document.cookie.split(';').map(c => c.trim())
196
213
  for (const cookie of cookies) {
197
- if (cookie.startsWith(`${nom}=`)) {
214
+ if (cookie.startsWith(`${this.nomTemoin}=`)) {
198
215
  try {
199
- return decodeURIComponent(cookie.substring(nom.length + 1))
216
+ return decodeURIComponent(cookie.substring(this.nomTemoin.length + 1))
200
217
  } catch {
201
- return cookie.substring(nom.length + 1)
218
+ return cookie.substring(this.nomTemoin.length + 1)
202
219
  }
203
220
  }
204
221
  }
@@ -222,11 +239,11 @@ class RafraichisseurToken {
222
239
 
223
240
  private reloadSiErreurReseau(): void {
224
241
  const CLE = 'rafraichisseur_dernierReload'
225
- // console.log('[RafraichisseurToken] reload si erreur')
242
+ if (this.loggerTrace) console.log('[RafraichisseurToken] reload si erreur')
226
243
  const maintenant = Date.now()
227
244
  const dernierReload = Number(sessionStorage.getItem(CLE) ?? 0)
228
245
  if (maintenant - dernierReload > 30_000) {
229
- // console.log('[RafraichisseurToken] Écriture sessionStorage:', CLE, maintenant)
246
+ if (this.loggerTrace) console.log('[RafraichisseurToken] Écriture sessionStorage:', CLE, maintenant)
230
247
  sessionStorage.setItem(CLE, String(maintenant))
231
248
 
232
249
  globalThis.location.reload()
@@ -236,12 +253,24 @@ class RafraichisseurToken {
236
253
  }
237
254
 
238
255
  // URL refresh selon env (dev = proxy Vite ; prod = portail)
239
- private getRefreshUrl(urlPortail: string): string {
256
+ private getRefreshUrl(): string {
240
257
  if (import.meta.env.MODE === 'development') return '/portail-refresh'
241
- return urlPortail + '/home/Refresh'
258
+ return this.urlPortail + '/home/Refresh'
259
+ }
260
+ }
261
+
262
+ declare global {
263
+ interface Window {
264
+ rafraichisseurToken: RafraichisseurToken
242
265
  }
243
266
  }
244
267
 
245
268
  // Instance
246
269
  const rafraichisseurToken = new RafraichisseurToken()
247
270
  export default rafraichisseurToken
271
+
272
+ declare global {
273
+ interface Window {
274
+ rafraichisseurToken: RafraichisseurToken
275
+ }
276
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codevdesign",
3
- "version": "1.0.74",
3
+ "version": "1.0.75",
4
4
  "description": "Composants Vuetify 3 pour les projets Codev",
5
5
  "files": [
6
6
  "./**/*.vue",