authscape 1.0.706 → 1.0.710

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.
@@ -1,4 +1,4 @@
1
- import React, {useState, useRef, useEffect} from 'react';
1
+ import React, { useState, useRef, useEffect } from 'react';
2
2
  import { ToastContainer, toast } from 'react-toastify';
3
3
  import { ThemeProvider } from '@mui/material/styles';
4
4
  import Head from "next/head";
@@ -7,538 +7,196 @@ import axios from 'axios';
7
7
  import querystring from "query-string";
8
8
  import Router from 'next/router';
9
9
  import GA4React from 'ga-4-react';
10
- import { create } from 'zustand'
10
+ import { create } from 'zustand';
11
11
  import { clarity } from 'react-microsoft-clarity';
12
12
  import { authService } from 'authscape';
13
13
 
14
- export function AuthScapeApp ({Component, layout, loadingLayout, pageProps, muiTheme = {}, store={}, enforceLoggedIn = false, enableAuth = true, enableConsentDialog = false}) {
15
-
16
- const [frontEndLoadedState, setFrontEndLoadedState] = useState(false);
17
- const [concentState, setConcentState] = useState(false);
18
-
19
- const [isLoadingShow, setIsLoadingShow] = useState(false);
20
-
21
- const [signedInUserState, setSignedInUserState] = useState(null);
22
-
23
- const loadingAuth = useRef(false);
24
- const frontEndLoaded = useRef(false);
25
- const signedInUser = useRef(null);
26
- const queryCodeUsed = useRef(null);
27
-
28
- const ga4React = useRef(null);
29
-
30
- const searchParams = useSearchParams();
31
- const queryRef = searchParams.get('ref');
32
- const queryCode = searchParams.get('code');
33
-
34
- const pathname = usePathname();
35
-
36
- const handleConsentAccepted = (prefs) => {
37
- console.log("Consent accepted:", prefs);
38
- setConcentState(prefs);
39
- };
40
-
41
- const handleConsentRejected = () => {
42
- console.log("Consent rejected");
43
- setConcentState(null);
44
- // disable analytics scripts, etc.
45
- };
46
-
47
- const signInValidator = async (queryCode) => {
48
-
49
- if (queryCodeUsed.current != queryCode)
50
- {
51
- queryCodeUsed.current = queryCode;
52
- }
53
- else
54
- {
55
- return;
56
- }
57
-
58
- let codeVerifier = window.localStorage.getItem("verifier");
59
- if (queryCode != null && codeVerifier != null)
60
- {
61
- const headers = {'Content-Type': 'application/x-www-form-urlencoded'}
62
-
63
- let queryString = querystring.stringify({
64
- code: queryCode,
65
- grant_type: "authorization_code",
66
- redirect_uri: window.location.origin + "/signin-oidc",
67
- client_id: process.env.client_id,
68
- client_secret: process.env.client_secret,
69
- code_verifier: codeVerifier
70
- });
71
-
72
- try
73
- {
74
- let response = await axios.post(process.env.authorityUri + '/connect/token', queryString, {
75
- headers: headers
76
- });
77
-
78
- let domainHost = window.location.hostname.split('.').slice(-2).join('.');
79
- window.localStorage.removeItem("verifier");
80
-
81
- await setCookie('access_token', response.data.access_token, {
82
- maxAge: 60 * 60 * 24 * 365, // 1 year,
83
- path: '/',
84
- domain: domainHost,
85
- secure: true
86
- });
87
-
88
- await setCookie('expires_in', response.data.expires_in, {
89
- maxAge: 60 * 60 * 24 * 365, // 1 year,
90
- path: '/',
91
- domain: domainHost,
92
- secure: true
93
- });
94
-
95
- await setCookie('refresh_token', response.data.refresh_token, {
96
- maxAge: 60 * 60 * 24 * 365, // 1 year,
97
- path: '/',
98
- domain: domainHost,
99
- secure: true
100
- });
101
-
102
- // await setCookie(null, "access_token", response.data.access_token,
103
- // {
104
- // maxAge: 2147483647,
105
- // path: '/',
106
- // domain: domainHost,
107
- // secure: true
108
- // });
109
-
110
- // await setCookie(null, "expires_in", response.data.expires_in,
111
- // {
112
- // maxAge: 2147483647,
113
- // path: '/',
114
- // domain: domainHost,
115
- // secure: true
116
- // });
117
-
118
- // await setCookie(null, "refresh_token", response.data.refresh_token,
119
- // {
120
- // maxAge: 2147483647,
121
- // path: '/',
122
- // domain: domainHost,
123
- // secure: true
124
- // });
125
-
126
-
127
- let redirectUri = localStorage.getItem("redirectUri")
128
- localStorage.clear();
129
- if (redirectUri != null)
130
- {
131
- window.location.href = redirectUri;
132
- }
133
- else
134
- {
135
- window.location.href = "/";
136
- }
137
- }
138
- catch(exp)
139
- {
140
- //alert(exp)
141
- }
142
- }
14
+ export function AuthScapeApp({
15
+ Component,
16
+ layout,
17
+ loadingLayout,
18
+ pageProps,
19
+ muiTheme = {},
20
+ store = {},
21
+ enforceLoggedIn = false,
22
+ enableAuth = true
23
+ }) {
24
+ const [frontEndLoadedState, setFrontEndLoadedState] = useState(false);
25
+ const [isLoadingShow, setIsLoadingShow] = useState(false);
26
+ const [signedInUserState, setSignedInUserState] = useState(null);
27
+
28
+ const loadingAuth = useRef(false);
29
+ const signedInUser = useRef(null);
30
+ const queryCodeUsed = useRef(null);
31
+ const ga4React = useRef(null);
32
+
33
+ const searchParams = useSearchParams();
34
+ const queryCode = searchParams.get('code');
35
+ const pathname = usePathname();
36
+
37
+ // ---------- PKCE Sign-in ----------
38
+ const signInValidator = async (queryCode) => {
39
+ if (queryCodeUsed.current === queryCode) return;
40
+ queryCodeUsed.current = queryCode;
41
+
42
+ const codeVerifier = window.localStorage.getItem("verifier");
43
+ if (!queryCode || !codeVerifier) return;
44
+
45
+ const headers = { 'Content-Type': 'application/x-www-form-urlencoded' };
46
+
47
+ const queryString = querystring.stringify({
48
+ code: queryCode,
49
+ grant_type: "authorization_code",
50
+ redirect_uri: window.location.origin + "/signin-oidc",
51
+ client_id: process.env.client_id,
52
+ client_secret: process.env.client_secret,
53
+ code_verifier: codeVerifier
54
+ });
55
+
56
+ try {
57
+ const response = await axios.post(process.env.authorityUri + '/connect/token', queryString, { headers });
58
+ const domainHost = window.location.hostname.split('.').slice(-2).join('.');
59
+
60
+ window.localStorage.removeItem("verifier");
61
+
62
+ await setCookie('access_token', response.data.access_token, {
63
+ maxAge: 60 * 60 * 24 * 365,
64
+ path: '/',
65
+ domain: domainHost,
66
+ secure: true
67
+ });
68
+ await setCookie('expires_in', response.data.expires_in, {
69
+ maxAge: 60 * 60 * 24 * 365,
70
+ path: '/',
71
+ domain: domainHost,
72
+ secure: true
73
+ });
74
+ await setCookie('refresh_token', response.data.refresh_token, {
75
+ maxAge: 60 * 60 * 24 * 365,
76
+ path: '/',
77
+ domain: domainHost,
78
+ secure: true
79
+ });
80
+
81
+ const redirectUri = localStorage.getItem("redirectUri");
82
+ localStorage.clear();
83
+ window.location.href = redirectUri || "/";
84
+ } catch (exp) {
85
+ console.error("PKCE sign-in failed", exp);
143
86
  }
144
-
145
- async function initGA(G) {
146
- if (!GA4React.isInitialized() && G && process.browser) {
147
- ga4React.current = new GA4React(G, { debug_mode: !process.env.production });
148
-
149
- try {
150
-
151
- await ga4React.current.initialize();
152
-
153
- } catch (error) {
154
- console.error(error);
155
- }
156
- }
157
- }
158
-
159
- const logEvent = (category, action, label) => {
160
-
161
- if (ga4React != null && ga4React.current != null && ga4React != "")
162
- {
163
- ga4React.current.event(action, label, category);
164
- }
165
-
166
- if (process.env.enableDatabaseAnalytics == "true")
167
- {
168
- let userId = null;
169
- let locationId = null;
170
- let companyId = null;
171
-
172
- var host = window.location.protocol + "//" + window.location.host;
173
-
174
- if (signedInUser.current != null)
175
- {
176
- userId = signedInUser.current.id;
177
- locationId = signedInUser.current.locationId;
178
- companyId = signedInUser.current.companyId;
179
- }
180
-
181
- apiService().post("/Analytics/Event", {
182
- userId: userId,
183
- locationId: locationId,
184
- companyId: companyId,
185
- uri: window.location.pathname,
186
- category: category,
187
- action: action,
188
- label: label,
189
- host: host
190
- });
191
- }
87
+ };
88
+
89
+ // ---------- GA + Clarity ----------
90
+ async function initGA(G) {
91
+ if (!GA4React.isInitialized() && G && typeof window !== "undefined") {
92
+ ga4React.current = new GA4React(G, { debug_mode: !process.env.production });
93
+ try {
94
+ await ga4React.current.initialize();
95
+ } catch (error) {
96
+ console.error(error);
97
+ }
192
98
  }
99
+ }
193
100
 
194
- const databaseDrivenPageView = (pathName) => {
195
-
196
- if (process.env.enableDatabaseAnalytics == "true")
197
- {
198
- let userId = null;
199
- let locationId = null;
200
- let companyId = null;
201
-
202
- var host = window.location.protocol + "//" + window.location.host;
203
-
204
- if (signedInUser.current != null)
205
- {
206
- userId = signedInUser.current.id;
207
- locationId = signedInUser.current.locationId;
208
- companyId = signedInUser.current.companyId;
209
- }
210
-
211
- if (pathName == "/signin-oidc")
212
- {
213
- return;
214
- }
215
-
216
- apiService().post("/Analytics/PageView", {
217
- userId: userId,
218
- locationId: locationId,
219
- companyId: companyId,
220
- uri: pathName,
221
- host: host
222
- });
223
-
224
- }
101
+ const logEvent = (category, action, label) => {
102
+ if (ga4React.current) {
103
+ ga4React.current.event(action, label, category);
225
104
  }
226
-
227
- useEffect(() => {
228
-
229
- let enableAnalytics = false;
230
- const stored = localStorage.getItem("gdpr-consent");
231
- if (stored) {
232
- const prefs = JSON.parse(stored);
233
- if (prefs.analytics)
234
- {
235
- enableAnalytics = true;
236
- }
237
- }
238
-
239
- if ((frontEndLoadedState && !enableConsentDialog) || (frontEndLoadedState && enableConsentDialog && enableAnalytics))
240
- {
241
- if (pageProps.googleAnalytics4Code != null)
242
- {
243
- initGA(pageProps.googleAnalytics4Code);
244
- }
245
- else if (process.env.googleAnalytics4 != "")
246
- {
247
- initGA(process.env.googleAnalytics4);
248
- }
249
-
250
- if (pageProps.microsoftClarityCode != null)
251
- {
252
- clarity.init(pageProps.microsoftClarityCode);
253
-
254
- if (signedInUser.current != null && clarity.hasStarted())
255
- {
256
- clarity.identify('USER_ID', { userProperty: signedInUser.current.id.toString() });
257
- }
258
- }
259
- else if (process.env.microsoftClarityTrackingCode != "") // if there isn't a private label tracking code use the one built in the app
260
- {
261
- clarity.init(process.env.microsoftClarityTrackingCode);
262
-
263
- if (signedInUser.current != null && clarity.hasStarted())
264
- {
265
- clarity.identify('USER_ID', { userProperty: signedInUser.current.id.toString() });
266
- }
267
- }
268
-
269
- databaseDrivenPageView(window.location.pathname);
270
- Router.events.on('routeChangeComplete', () => {
271
-
272
- if (ga4React != null && ga4React != "")
273
- {
274
- try
275
- {
276
- ga4React.current.pageview(window.location.pathname);
277
- }
278
- catch(exp) {}
279
- }
280
-
281
- databaseDrivenPageView(window.location.pathname);
282
- });
283
-
284
- if (pageProps.hubspotTrackingCode != null && pageProps.hubspotTrackingCode != "")
285
- {
286
- const script = document.createElement("script");
287
- script.src = pageProps.hubspotTrackingCode;
288
- script.async = true;
289
- script.defer = true;
290
- script.id = "hs-script-loader";
291
- document.body.appendChild(script);
292
- }
293
- }
294
-
295
- }, [frontEndLoadedState, concentState]);
296
-
297
- const validateUserSignedIn = async () => {
298
-
299
- loadingAuth.current = true;
300
-
301
- if (enableAuth)
302
- {
303
- let usr = await apiService().GetCurrentUser();
304
- if (usr != null)
305
- {
306
- signedInUser.current = usr;
307
- }
308
- }
309
-
105
+ };
106
+
107
+ const databaseDrivenPageView = (pathName) => {
108
+ if (process.env.enableDatabaseAnalytics !== "true") return;
109
+ if (pathName === "/signin-oidc") return;
110
+
111
+ const host = window.location.protocol + "//" + window.location.host;
112
+
113
+ apiService().post("/Analytics/PageView", {
114
+ userId: signedInUser.current?.id,
115
+ locationId: signedInUser.current?.locationId,
116
+ companyId: signedInUser.current?.companyId,
117
+ uri: pathName,
118
+ host
119
+ });
120
+ };
121
+
122
+ // ---------- Auth + Tracking Init ----------
123
+ useEffect(() => {
124
+ if (queryCode) {
125
+ signInValidator(queryCode);
126
+ } else if (!loadingAuth.current) {
127
+ loadingAuth.current = true;
128
+ if (enableAuth) {
129
+ apiService().GetCurrentUser().then((usr) => {
130
+ signedInUser.current = usr;
131
+ setSignedInUserState(usr);
132
+ setFrontEndLoadedState(true);
133
+ });
134
+ } else {
310
135
  setFrontEndLoadedState(true);
311
- frontEndLoaded.current = true;
312
- setSignedInUserState(signedInUser.current);
313
- }
314
-
315
- if (queryCode != null)
316
- {
317
- signInValidator(queryCode);
318
- }
319
- else
320
- {
321
- if (!loadingAuth.current)
322
- {
323
- validateUserSignedIn();
324
- }
325
- }
326
-
327
- useEffect(() => {
328
-
329
- if (signedInUserState == null && enforceLoggedIn && pathname != "/signin-oidc" && frontEndLoadedState == true)
330
- {
331
- authService().login();
332
- }
333
-
334
- }, [signedInUserState, enforceLoggedIn, frontEndLoadedState]);
335
-
336
-
337
- const setIsLoading = (isLoading) => {
338
- setIsLoadingShow(isLoading);
339
- }
340
-
341
- const logPurchase = (transactionId, amount, tax, items) => {
342
-
343
- if (ga4React != null && ga4React != "")
344
- {
345
- ga4React.current.gtag("event", "purchase", {
346
- transaction_id: transactionId,
347
- value: amount,
348
- tax: tax,
349
- currency: "USD",
350
- items: items
351
- });
352
- }
353
- }
354
-
355
- const setToastMessage = (message, options = null) => {
356
-
357
- if (options != null)
358
- {
359
- toast(message, options);
360
- }
361
- else
362
- {
363
- toast(message);
364
- }
136
+ }
365
137
  }
138
+ }, [queryCode, enableAuth]);
366
139
 
367
- const setInfoToastMessage = (message, options = null) => {
368
- if (options != null)
369
- {
370
- toast.info(message, options);
371
- }
372
- else
373
- {
374
- toast.info(message);
375
- }
376
- }
377
-
378
- const setSuccessToastMessage = (message, options = null) => {
379
- if (options != null)
380
- {
381
- toast.success(message, options);
382
- }
383
- else
384
- {
385
- toast.success(message);
386
- }
387
- }
140
+ // ---------- Analytics Init ----------
141
+ useEffect(() => {
142
+ if (!frontEndLoadedState) return;
388
143
 
389
- const setWarnToastMessage = (message, options = null) => {
390
- if (options != null)
391
- {
392
- toast.warn(message, options);
393
- }
394
- else
395
- {
396
- toast.warn(message);
397
- }
144
+ if (pageProps.googleAnalytics4Code) {
145
+ initGA(pageProps.googleAnalytics4Code);
146
+ } else if (process.env.googleAnalytics4) {
147
+ initGA(process.env.googleAnalytics4);
398
148
  }
399
149
 
400
- const setErrorToastMessage = (message, options = null) => {
401
- if (options != null)
402
- {
403
- toast.error(message, options);
404
- }
405
- else
406
- {
407
- toast.error(message);
408
- }
150
+ if (pageProps.microsoftClarityCode) {
151
+ clarity.init(pageProps.microsoftClarityCode);
152
+ } else if (process.env.microsoftClarityTrackingCode) {
153
+ clarity.init(process.env.microsoftClarityTrackingCode);
409
154
  }
410
-
411
-
412
- const GetSignedInUser = () => {
413
-
414
- if (signedInUser != null)
415
- {
416
- let _signedInUser = signedInUser.current;
417
155
 
418
- if (_signedInUser != null)
419
- {
420
- _signedInUser.hasRole = function(name) {
156
+ databaseDrivenPageView(window.location.pathname);
421
157
 
422
- if (_signedInUser.roles != null)
423
- {
424
- if (_signedInUser.roles.find(r => r.name === name) != null)
425
- {
426
- return true;
427
- }
428
- else
429
- {
430
- return false;
431
- }
432
- }
433
- };
158
+ Router.events.on('routeChangeComplete', (url) => {
159
+ ga4React.current?.pageview(url);
160
+ databaseDrivenPageView(url);
161
+ });
162
+ }, [frontEndLoadedState]);
434
163
 
435
- _signedInUser.hasRoleId = function(id) {
436
-
437
- if (_signedInUser.roles != null)
438
- {
439
- if (_signedInUser.roles.find(r => r.id === id) != null)
440
- {
441
- return true;
442
- }
443
- else
444
- {
445
- return false;
446
- }
447
- }
448
- };
449
-
450
- _signedInUser.hasPermission = function(name) {
451
-
452
- if (_signedInUser.permissions != null)
453
- {
454
- if (_signedInUser.permissions.find(r => r === name) != null)
455
- {
456
- return true;
457
- }
458
- else
459
- {
460
- return false;
461
- }
462
- }
463
- };
464
- }
465
-
466
- return _signedInUser;
467
- }
468
- else
469
- {
470
- return null;
471
- }
164
+ // ---------- Enforce Login ----------
165
+ useEffect(() => {
166
+ if (enforceLoggedIn && pathname !== "/signin-oidc" && frontEndLoadedState && !signedInUserState) {
167
+ authService().login();
472
168
  }
473
-
474
-
475
- const useStore = create((set) => (store));
476
-
477
- return (
478
- <>
479
- <Head>
480
- <meta name="viewport" content="width=device-width, initial-scale=0.86, maximum-scale=5.0, minimum-scale=0.86"></meta>
481
-
482
- {/* {(pageProps != null && pageProps.oemCompanyId != null) ?
483
- <>
484
- <link
485
- href={process.env.apiUri + "/api/PrivateLabel/GetDataFromRecord?oemCompanyId=" + pageProps.oemCompanyId}
486
- rel="stylesheet"
487
- />
488
- </>
489
- :
490
- <>
491
- <link rel="icon" href="/favicon.ico" />
492
- </>
493
- } */}
494
-
495
- </Head>
496
-
497
- {enableConsentDialog &&
498
- <GDPRConsentDialog
499
- onAccept={handleConsentAccepted}
500
- onReject={handleConsentRejected}
501
- enableAnalytics={true}
502
- enableMarketing={false}
503
- // additionalPrivacyFeatures={[
504
- // {id: "danceParty", title: "Dance Party", description: "Hello world this is about the feature", checked: true },
505
- // {id: "frog", title: "Able to see Frogs", description: "Frogs will appear on your screen", checked: true }
506
- // ]}
507
- />
508
- }
509
-
510
- <ThemeProvider theme={muiTheme}>
511
- {frontEndLoadedState != null && frontEndLoadedState && pathname != "/signin-oidc" &&
512
- <>
513
- {layout != null && layout({
514
- children: <Component {...pageProps} currentUser={GetSignedInUser()} loadedUser={frontEndLoadedState} setIsLoading={setIsLoading} logEvent={logEvent} logPurchase={logPurchase} store={useStore} setToastMessage={setToastMessage} setInfoToastMessage={setInfoToastMessage} setSuccessToastMessage={setSuccessToastMessage} setWarnToastMessage={setWarnToastMessage} setErrorToastMessage={setErrorToastMessage} />,
515
- currentUser: GetSignedInUser(),
516
- logEvent: logEvent,
517
- setIsLoading: setIsLoading,
518
- toast: toast,
519
- store: useStore,
520
- setToastMessage: setToastMessage,
521
- pageProps: pageProps,
522
- setInfoToastMessage: setInfoToastMessage,
523
- setSuccessToastMessage: setSuccessToastMessage,
524
- setWarnToastMessage: setWarnToastMessage,
525
- setErrorToastMessage: setErrorToastMessage
526
- })}
527
-
528
- {layout == null &&
529
- <Component {...pageProps} currentUser={GetSignedInUser()} loadedUser={frontEndLoadedState} setIsLoading={setIsLoading} logEvent={logEvent} logPurchase={logPurchase} store={useStore} setToastMessage={setToastMessage} setInfoToastMessage={setInfoToastMessage} setSuccessToastMessage={setSuccessToastMessage} setWarnToastMessage={setWarnToastMessage} setErrorToastMessage={setErrorToastMessage} />
530
- }
531
- </>
532
- }
533
- <ToastContainer />
534
-
535
- </ThemeProvider>
536
-
537
- {loadingLayout &&
538
- <>
539
- {loadingLayout(isLoadingShow)}
540
- </>
541
- }
542
- </>
543
- )
544
- }
169
+ }, [signedInUserState, enforceLoggedIn, frontEndLoadedState, pathname]);
170
+
171
+ const GetSignedInUser = () => signedInUser.current;
172
+
173
+ const useStore = create((set) => (store));
174
+
175
+ // ---------- Render ----------
176
+ const pageContent = layout
177
+ ? layout({
178
+ children: <Component {...pageProps} currentUser={GetSignedInUser()} loadedUser={frontEndLoadedState} setIsLoading={setIsLoadingShow} logEvent={logEvent} store={useStore} toast={toast} />,
179
+ currentUser: GetSignedInUser(),
180
+ setIsLoading: setIsLoadingShow,
181
+ logEvent,
182
+ toast,
183
+ store: useStore,
184
+ pageProps
185
+ })
186
+ : <Component {...pageProps} currentUser={GetSignedInUser()} loadedUser={frontEndLoadedState} setIsLoading={setIsLoadingShow} logEvent={logEvent} store={useStore} toast={toast} />;
187
+
188
+ return (
189
+ <>
190
+ <Head>
191
+ <meta name="viewport" content="width=device-width, initial-scale=0.86, maximum-scale=5.0, minimum-scale=0.86" />
192
+ </Head>
193
+
194
+ <ThemeProvider theme={muiTheme}>
195
+ {pageContent}
196
+ <ToastContainer />
197
+ </ThemeProvider>
198
+
199
+ {loadingLayout && loadingLayout(isLoadingShow)}
200
+ </>
201
+ );
202
+ }