codevdesign 1.0.74 → 1.0.76

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.
@@ -5,26 +5,59 @@ class RafraichisseurToken {
5
5
  private popupAffiche = false
6
6
  private timerId: number | null = null
7
7
  private nomTemoin = 'csqc_jeton_secure_expiration'
8
- private urlPortail = ''
8
+ private urlPortailSeConnecter = ''
9
+ private urlPortailRafraichir = ''
10
+ private urlPortailDeconnecte = ''
9
11
  private refreshPromise: Promise<void> | null = null
12
+ public loggerTrace = false
10
13
 
11
14
  // 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)
15
+ public async demarrer(
16
+ nomTemoin: string,
17
+ urlPortailSeConnecter: string,
18
+ urlPortailRafraichir: string,
19
+ urlPortailDeconnecte: string,
20
+ ): Promise<void> {
21
+ window.rafraichisseurToken = this
22
+ if (this.loggerTrace) {
23
+ console.log('Nom témoin', nomTemoin)
24
+ console.log('URL portail se connecter', urlPortailSeConnecter)
25
+ console.log('URL portail rafraichir', urlPortailRafraichir)
26
+ console.log('URL portail déconnecte', urlPortailDeconnecte)
27
+ }
28
+
29
+ if (nomTemoin == null || nomTemoin === '') {
30
+ console.warn('[RafraichisseurToken] nomTemoin invalide, rafraichisseur de token désactivé')
31
+ return
32
+ }
33
+ if (urlPortailSeConnecter == null || urlPortailSeConnecter === '') {
34
+ console.warn('[RafraichisseurToken] urlPortailSeConnecter invalide, rafraichisseur de token désactivé')
35
+ return
36
+ }
37
+ if (urlPortailRafraichir == null || urlPortailRafraichir === '') {
38
+ console.warn('[RafraichisseurToken] urlPortailRafraichir invalide, rafraichisseur de token désactivé')
39
+ return
40
+ }
41
+ if (urlPortailDeconnecte == null || urlPortailDeconnecte === '') {
42
+ console.warn('[RafraichisseurToken] urlPortailDeconnecte invalide, rafraichisseur de token désactivé')
43
+ return
44
+ }
45
+ this.nomTemoin = nomTemoin
46
+ this.urlPortailSeConnecter = urlPortailSeConnecter.replace(/\/+$/, '')
47
+ this.urlPortailRafraichir = urlPortailRafraichir.replace(/\/+$/, '')
48
+ this.urlPortailDeconnecte = urlPortailDeconnecte.replace(/\/+$/, '')
49
+
50
+ await this.verifierJeton()
18
51
  if (this.timerId != null) return
19
52
  this.timerId = window.setInterval(() => {
20
- this.verifierJeton(nomTemoin as string, urlPortail)
53
+ this.verifierJeton()
21
54
  }, this.intervalleEnSecondes * 1000)
22
55
  }
23
56
 
24
57
  public attendreRefreshSiNecessaire(force = false): Promise<void> {
25
58
  if (this.refreshPromise) return this.refreshPromise
26
- if (force || !this.estJetonValide(this.nomTemoin)) {
27
- this.refreshPromise = this.rafraichir(this.nomTemoin, this.urlPortail).finally(() => {
59
+ if (force || !this.estJetonValide()) {
60
+ this.refreshPromise = this.rafraichir().finally(() => {
28
61
  this.refreshPromise = null
29
62
  })
30
63
  return this.refreshPromise
@@ -40,28 +73,30 @@ class RafraichisseurToken {
40
73
  }
41
74
  }
42
75
 
43
- public existeJeton = (nomTemoin: string) => {
44
- return this.estJetonValide(nomTemoin)
76
+ public existeJeton = () => {
77
+ return this.estJetonValide()
45
78
  }
46
79
 
47
- private async verifierJeton(nomTemoin: string, urlPortail: string): Promise<void> {
48
- if (this.popupAffiche) return
80
+ private async verifierJeton(): Promise<void> {
81
+ if (this.loggerTrace) console.log('[RafraichisseurToken] Vérification du jeton...')
82
+ if (this.popupAffiche) {
83
+ if (this.loggerTrace) console.log('[RafraichisseurToken] Popup affiché, vérification du jeton ignorée')
84
+ return
85
+ }
49
86
 
50
- if (!this.estJetonValide(nomTemoin)) {
87
+ if (!this.estJetonValide()) {
51
88
  if (!this.refreshPromise) {
52
- this.refreshPromise = this.rafraichir(nomTemoin, urlPortail).finally(() => {
89
+ this.refreshPromise = this.rafraichir().finally(() => {
53
90
  this.refreshPromise = null
54
91
  })
55
92
  }
56
93
  }
57
94
  }
58
95
 
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
-
62
-
96
+ private estJetonValide(): boolean {
97
+ if (this.popupAffiche) return true //On fait semblant que c'est valide pour ne pas provoquer un autre affichage du popup.
63
98
 
64
- const tokenEncode = this.lireCookie(nomTemoin)
99
+ const tokenEncode = this.lireCookie()
65
100
  if (!tokenEncode) {
66
101
  return false
67
102
  }
@@ -87,12 +122,11 @@ class RafraichisseurToken {
87
122
  return true
88
123
  }
89
124
 
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
125
+ private async rafraichir(): Promise<void> {
126
+ if (this.loggerTrace) console.log('[RafraichisseurToken] rafraichir() appelé')
127
+
94
128
  this.popupAffiche = true // bloquer tout nouveau tick pendant le refresh
95
- const url = this.getRefreshUrl(urlPortail)
129
+ const url = this.getRefreshUrl()
96
130
  const controller = new AbortController()
97
131
  const timeout = setTimeout(() => controller.abort(), 10_000)
98
132
 
@@ -107,18 +141,18 @@ class RafraichisseurToken {
107
141
  })
108
142
 
109
143
  // 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)
144
+ if (this.loggerTrace) console.log('[RafraichisseurToken] fetch réponse type:', resp.type, 'status:', resp.status)
111
145
  if (resp.type === 'opaqueredirect' || resp.status === 302) {
112
- this.estDeconnecteAzure(urlPortail)
146
+ this.estDeconnecteAzure()
113
147
  return
114
148
  }
115
149
 
116
150
  // OK ou No Content: le cookie devrait être réécrit
117
151
  if (resp.status === 200 || resp.status === 204) {
118
- const jeton = this.lireCookie(nomCookie)
152
+ const jeton = this.lireCookie()
119
153
  if (!jeton) {
120
- // console.log('[RafraichisseurToken] 200 mais cookie absent → iframe')
121
- this.rafraichirParIframe(nomCookie, urlPortail)
154
+ if (this.loggerTrace) console.log('[RafraichisseurToken] 200 mais cookie absent → iframe')
155
+ this.rafraichirParIframe()
122
156
  } else {
123
157
  this.popupAffiche = false // succès, reprendre la surveillance
124
158
  }
@@ -127,8 +161,8 @@ class RafraichisseurToken {
127
161
 
128
162
  // non auth / expiré (401, 419) + IIS timeout (440)
129
163
  if (resp.status === 401 || resp.status === 419 || resp.status === 440) {
130
- // console.log('[RafraichisseurToken] statut auth → iframe')
131
- this.rafraichirParIframe(nomCookie, urlPortail)
164
+ if (this.loggerTrace) console.log('[RafraichisseurToken] statut auth → iframe')
165
+ this.rafraichirParIframe()
132
166
  return
133
167
  }
134
168
 
@@ -143,10 +177,10 @@ class RafraichisseurToken {
143
177
  }
144
178
  }
145
179
 
146
- private rafraichirParIframe(nomCookie: string, urlPortail: string): void {
180
+ private rafraichirParIframe(): void {
147
181
  this.popupAffiche = true // bloquer le timer pendant que l'iframe tente l'auth
148
182
  let iframe = document.createElement('iframe')
149
- const url = this.getRefreshUrl(urlPortail)
183
+ const url = this.getRefreshUrl()
150
184
  iframe.src = `${url}?urlRetour=${encodeURI(window.location.href)}`
151
185
  iframe.id = 'idRafrToken'
152
186
  iframe.style.display = 'none'
@@ -161,13 +195,15 @@ class RafraichisseurToken {
161
195
  }, 15_000)
162
196
 
163
197
  iframe.onload = () => {
198
+ if (this.loggerTrace) console.log('[RafraichisseurToken] iframe onload, vérification du jeton...')
164
199
  clearTimeout(iframeTimeout)
165
200
  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)
201
+
202
+ const jeton = this.lireCookie()
169
203
  if (jeton == null || jeton === '') {
170
- this.estDeconnecteAzure(urlPortail)
204
+ if (this.loggerTrace)
205
+ console.log('[RafraichisseurToken] iframe onload, jeton toujours absent → déconnecté Azure')
206
+ this.estDeconnecteAzure()
171
207
  } else {
172
208
  this.popupAffiche = false // cookie recréé avec succès, reprendre la surveillance
173
209
  }
@@ -177,28 +213,27 @@ class RafraichisseurToken {
177
213
  }
178
214
  }
179
215
 
180
- private estDeconnecteAzure(urlPortail: string): void {
216
+ private estDeconnecteAzure(): void {
181
217
  //on envoie au portail, pas le choix
182
- urlPortail = urlPortail.replace(/\/+$/, '')
183
218
  const retour = encodeURI(window.location.href)
184
- window.open(`${urlPortail}/home/SeConnecter?urlRetour=${retour}`, '_self')
219
+
220
+ window.open(`${this.urlPortailSeConnecter}?urlRetour=${retour}`, '_self')
185
221
  return
186
222
  }
187
223
 
188
- public deconnecterPortail(urlPortail: string): void {
189
- urlPortail = urlPortail.replace(/\/+$/, '')
190
- window.location.replace(`${urlPortail}/deconnecte?urlRetour=${encodeURIComponent(window.location.href)}`)
224
+ public deconnecterPortail(): void {
225
+ window.location.replace(`${this.urlPortailDeconnecte}?urlRetour=${encodeURIComponent(window.location.href)}`)
191
226
  }
192
227
 
193
- private lireCookie(nom: string): string | null {
228
+ private lireCookie(): string | null {
194
229
  if (!document.cookie) return null
195
230
  const cookies = document.cookie.split(';').map(c => c.trim())
196
231
  for (const cookie of cookies) {
197
- if (cookie.startsWith(`${nom}=`)) {
232
+ if (cookie.startsWith(`${this.nomTemoin}=`)) {
198
233
  try {
199
- return decodeURIComponent(cookie.substring(nom.length + 1))
234
+ return decodeURIComponent(cookie.substring(this.nomTemoin.length + 1))
200
235
  } catch {
201
- return cookie.substring(nom.length + 1)
236
+ return cookie.substring(this.nomTemoin.length + 1)
202
237
  }
203
238
  }
204
239
  }
@@ -222,11 +257,11 @@ class RafraichisseurToken {
222
257
 
223
258
  private reloadSiErreurReseau(): void {
224
259
  const CLE = 'rafraichisseur_dernierReload'
225
- // console.log('[RafraichisseurToken] reload si erreur')
260
+ if (this.loggerTrace) console.log('[RafraichisseurToken] reload si erreur')
226
261
  const maintenant = Date.now()
227
262
  const dernierReload = Number(sessionStorage.getItem(CLE) ?? 0)
228
263
  if (maintenant - dernierReload > 30_000) {
229
- // console.log('[RafraichisseurToken] Écriture sessionStorage:', CLE, maintenant)
264
+ if (this.loggerTrace) console.log('[RafraichisseurToken] Écriture sessionStorage:', CLE, maintenant)
230
265
  sessionStorage.setItem(CLE, String(maintenant))
231
266
 
232
267
  globalThis.location.reload()
@@ -236,12 +271,24 @@ class RafraichisseurToken {
236
271
  }
237
272
 
238
273
  // URL refresh selon env (dev = proxy Vite ; prod = portail)
239
- private getRefreshUrl(urlPortail: string): string {
274
+ private getRefreshUrl(): string {
240
275
  if (import.meta.env.MODE === 'development') return '/portail-refresh'
241
- return urlPortail + '/home/Refresh'
276
+ return this.urlPortailRafraichir
277
+ }
278
+ }
279
+
280
+ declare global {
281
+ interface Window {
282
+ rafraichisseurToken: RafraichisseurToken
242
283
  }
243
284
  }
244
285
 
245
286
  // Instance
246
287
  const rafraichisseurToken = new RafraichisseurToken()
247
288
  export default rafraichisseurToken
289
+
290
+ declare global {
291
+ interface Window {
292
+ rafraichisseurToken: RafraichisseurToken
293
+ }
294
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codevdesign",
3
- "version": "1.0.74",
3
+ "version": "1.0.76",
4
4
  "description": "Composants Vuetify 3 pour les projets Codev",
5
5
  "files": [
6
6
  "./**/*.vue",