@redacto.io/consent-sdk-react-native 4.0.1-beta.0 → 5.0.0-beta.0
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.
- package/dist/index.d.mts +5 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +186 -10
- package/dist/index.mjs +186 -10
- package/dist/privacy-center.d.mts +38 -7
- package/dist/privacy-center.d.ts +38 -7
- package/dist/privacy-center.js +109 -25
- package/dist/privacy-center.mjs +109 -25
- package/package.json +5 -3
package/dist/index.d.mts
CHANGED
|
@@ -31,6 +31,8 @@ type Props$1 = Readonly<{
|
|
|
31
31
|
accessToken: string;
|
|
32
32
|
refreshToken: string;
|
|
33
33
|
baseUrl?: string;
|
|
34
|
+
/** Go ledger base URL — serves check-consent and the consent write; omit to use the legacy consent server. */
|
|
35
|
+
ledgerBaseUrl?: string;
|
|
34
36
|
settings?: Partial<Settings$1>;
|
|
35
37
|
language?: string;
|
|
36
38
|
blockUI?: boolean;
|
|
@@ -77,6 +79,7 @@ declare const RedactoConsentInline: React__default.NamedExoticComponent<Readonly
|
|
|
77
79
|
accessToken?: string;
|
|
78
80
|
refreshToken?: string;
|
|
79
81
|
baseUrl?: string;
|
|
82
|
+
ledgerBaseUrl?: string;
|
|
80
83
|
settings?: Partial<Settings>;
|
|
81
84
|
language?: string;
|
|
82
85
|
onAccept?: () => void;
|
|
@@ -93,6 +96,8 @@ type Props = Readonly<{
|
|
|
93
96
|
accessToken?: string;
|
|
94
97
|
refreshToken?: string;
|
|
95
98
|
baseUrl?: string;
|
|
99
|
+
/** Go ledger base URL — serves check-consent and the consent write; omit to use the legacy consent server. */
|
|
100
|
+
ledgerBaseUrl?: string;
|
|
96
101
|
settings?: Partial<Settings>;
|
|
97
102
|
language?: string;
|
|
98
103
|
onAccept?: () => void;
|
package/dist/index.d.ts
CHANGED
|
@@ -31,6 +31,8 @@ type Props$1 = Readonly<{
|
|
|
31
31
|
accessToken: string;
|
|
32
32
|
refreshToken: string;
|
|
33
33
|
baseUrl?: string;
|
|
34
|
+
/** Go ledger base URL — serves check-consent and the consent write; omit to use the legacy consent server. */
|
|
35
|
+
ledgerBaseUrl?: string;
|
|
34
36
|
settings?: Partial<Settings$1>;
|
|
35
37
|
language?: string;
|
|
36
38
|
blockUI?: boolean;
|
|
@@ -77,6 +79,7 @@ declare const RedactoConsentInline: React__default.NamedExoticComponent<Readonly
|
|
|
77
79
|
accessToken?: string;
|
|
78
80
|
refreshToken?: string;
|
|
79
81
|
baseUrl?: string;
|
|
82
|
+
ledgerBaseUrl?: string;
|
|
80
83
|
settings?: Partial<Settings>;
|
|
81
84
|
language?: string;
|
|
82
85
|
onAccept?: () => void;
|
|
@@ -93,6 +96,8 @@ type Props = Readonly<{
|
|
|
93
96
|
accessToken?: string;
|
|
94
97
|
refreshToken?: string;
|
|
95
98
|
baseUrl?: string;
|
|
99
|
+
/** Go ledger base URL — serves check-consent and the consent write; omit to use the legacy consent server. */
|
|
100
|
+
ledgerBaseUrl?: string;
|
|
96
101
|
settings?: Partial<Settings>;
|
|
97
102
|
language?: string;
|
|
98
103
|
onAccept?: () => void;
|
package/dist/index.js
CHANGED
|
@@ -147,6 +147,7 @@ var fetchConsentContent = async ({
|
|
|
147
147
|
var submitConsentEvent = async ({
|
|
148
148
|
accessToken,
|
|
149
149
|
baseUrl,
|
|
150
|
+
ledgerBaseUrl,
|
|
150
151
|
noticeUuid,
|
|
151
152
|
purposes,
|
|
152
153
|
declined,
|
|
@@ -166,7 +167,7 @@ var submitConsentEvent = async ({
|
|
|
166
167
|
if (!ORGANISATION_UUID || !WORKSPACE_UUID) {
|
|
167
168
|
throw new Error("Invalid token: missing organization or workspace UUID");
|
|
168
169
|
}
|
|
169
|
-
const apiBaseUrl = baseUrl || DEFAULT_CONSENT_API_BASE_URL;
|
|
170
|
+
const apiBaseUrl = ledgerBaseUrl || baseUrl || DEFAULT_CONSENT_API_BASE_URL;
|
|
170
171
|
const validatedPurposes = purposes.map((purpose) => {
|
|
171
172
|
if (!purpose.uuid) {
|
|
172
173
|
throw new Error("Invalid purpose data: missing uuid");
|
|
@@ -415,6 +416,122 @@ var verifyGuardianStatus = async ({
|
|
|
415
416
|
};
|
|
416
417
|
};
|
|
417
418
|
|
|
419
|
+
// src/shared/notice-consent-status.ts
|
|
420
|
+
var import_jwt_decode2 = require("jwt-decode");
|
|
421
|
+
var decodeNoticeConsentToken = (token) => {
|
|
422
|
+
try {
|
|
423
|
+
return (0, import_jwt_decode2.jwtDecode)(token);
|
|
424
|
+
} catch {
|
|
425
|
+
return null;
|
|
426
|
+
}
|
|
427
|
+
};
|
|
428
|
+
var fetchNoticeConsentStatusForScope = async ({
|
|
429
|
+
accessToken,
|
|
430
|
+
ledgerBaseUrl,
|
|
431
|
+
organisationUuid,
|
|
432
|
+
workspaceUuid,
|
|
433
|
+
noticeUuid,
|
|
434
|
+
signal
|
|
435
|
+
}) => {
|
|
436
|
+
if (!accessToken || !ledgerBaseUrl || !organisationUuid || !workspaceUuid || !noticeUuid) {
|
|
437
|
+
return null;
|
|
438
|
+
}
|
|
439
|
+
try {
|
|
440
|
+
const response = await fetch(
|
|
441
|
+
`${ledgerBaseUrl}/public/organisations/${organisationUuid}/workspaces/${workspaceUuid}/notices/${noticeUuid}/check-consent`,
|
|
442
|
+
{
|
|
443
|
+
method: "POST",
|
|
444
|
+
headers: {
|
|
445
|
+
Authorization: `Bearer ${accessToken}`,
|
|
446
|
+
"Content-Type": "application/json"
|
|
447
|
+
},
|
|
448
|
+
body: "{}",
|
|
449
|
+
signal
|
|
450
|
+
}
|
|
451
|
+
);
|
|
452
|
+
if (!response.ok) {
|
|
453
|
+
return null;
|
|
454
|
+
}
|
|
455
|
+
const data = await response.json();
|
|
456
|
+
const body = data && typeof data === "object" && "detail" in data && data.detail ? data.detail : data;
|
|
457
|
+
if (!body || !Array.isArray(body.purposes)) {
|
|
458
|
+
return null;
|
|
459
|
+
}
|
|
460
|
+
return body;
|
|
461
|
+
} catch {
|
|
462
|
+
return null;
|
|
463
|
+
}
|
|
464
|
+
};
|
|
465
|
+
var fetchNoticeConsentStatus = async ({
|
|
466
|
+
accessToken,
|
|
467
|
+
ledgerBaseUrl,
|
|
468
|
+
noticeUuid,
|
|
469
|
+
signal
|
|
470
|
+
}) => {
|
|
471
|
+
if (!accessToken || !ledgerBaseUrl || !noticeUuid) {
|
|
472
|
+
return null;
|
|
473
|
+
}
|
|
474
|
+
const decodedToken = decodeNoticeConsentToken(accessToken);
|
|
475
|
+
if (!decodedToken) {
|
|
476
|
+
return null;
|
|
477
|
+
}
|
|
478
|
+
const {
|
|
479
|
+
organisation_uuid: ORGANISATION_UUID,
|
|
480
|
+
workspace_uuid: WORKSPACE_UUID
|
|
481
|
+
} = decodedToken;
|
|
482
|
+
if (!ORGANISATION_UUID || !WORKSPACE_UUID) {
|
|
483
|
+
return null;
|
|
484
|
+
}
|
|
485
|
+
return fetchNoticeConsentStatusForScope({
|
|
486
|
+
accessToken,
|
|
487
|
+
ledgerBaseUrl,
|
|
488
|
+
organisationUuid: ORGANISATION_UUID,
|
|
489
|
+
workspaceUuid: WORKSPACE_UUID,
|
|
490
|
+
noticeUuid,
|
|
491
|
+
signal
|
|
492
|
+
});
|
|
493
|
+
};
|
|
494
|
+
var isNoticeFullyConsented = (status) => status.consented && status.all_mandatory_active;
|
|
495
|
+
var buildLedgerConsentOverlay = (status, configPurposes) => {
|
|
496
|
+
var _a, _b;
|
|
497
|
+
const byUuid = new Map(status.purposes.map((p) => [p.uuid, p]));
|
|
498
|
+
const hasHistory = status.purposes.some(
|
|
499
|
+
(p) => (p.status || "INACTIVE") !== "INACTIVE"
|
|
500
|
+
);
|
|
501
|
+
if (!hasHistory) {
|
|
502
|
+
return null;
|
|
503
|
+
}
|
|
504
|
+
const purpose_selections = {};
|
|
505
|
+
for (const cp of configPurposes) {
|
|
506
|
+
const lp = byUuid.get(cp.uuid);
|
|
507
|
+
const purposeStatus = (lp == null ? void 0 : lp.status) || "INACTIVE";
|
|
508
|
+
const selectedByUuid = new Map(
|
|
509
|
+
((lp == null ? void 0 : lp.data_elements) || []).map((de) => [de.uuid, de.selected])
|
|
510
|
+
);
|
|
511
|
+
const data_elements = {};
|
|
512
|
+
for (const de of cp.data_elements) {
|
|
513
|
+
data_elements[de.uuid] = {
|
|
514
|
+
selected: (_a = selectedByUuid.get(de.uuid)) != null ? _a : false,
|
|
515
|
+
enabled: de.enabled,
|
|
516
|
+
required: de.required
|
|
517
|
+
};
|
|
518
|
+
}
|
|
519
|
+
purpose_selections[cp.uuid] = {
|
|
520
|
+
selected: (_b = lp == null ? void 0 : lp.selected) != null ? _b : false,
|
|
521
|
+
status: purposeStatus,
|
|
522
|
+
needs_reconsent: purposeStatus !== "ACTIVE",
|
|
523
|
+
data_elements
|
|
524
|
+
};
|
|
525
|
+
}
|
|
526
|
+
const reconsent_required = configPurposes.some(
|
|
527
|
+
(cp) => {
|
|
528
|
+
var _a2;
|
|
529
|
+
return (((_a2 = purpose_selections[cp.uuid]) == null ? void 0 : _a2.status) || "INACTIVE") !== "ACTIVE";
|
|
530
|
+
}
|
|
531
|
+
);
|
|
532
|
+
return { reconsent_required, purpose_selections };
|
|
533
|
+
};
|
|
534
|
+
|
|
418
535
|
// src/RedactoNoticeConsent/components/Checkbox.tsx
|
|
419
536
|
var import_react_native = require("react-native");
|
|
420
537
|
var import_react_native_svg = __toESM(require("react-native-svg"));
|
|
@@ -1638,6 +1755,7 @@ var RedactoNoticeConsent = ({
|
|
|
1638
1755
|
accessToken,
|
|
1639
1756
|
refreshToken: _refreshToken,
|
|
1640
1757
|
baseUrl,
|
|
1758
|
+
ledgerBaseUrl,
|
|
1641
1759
|
settings,
|
|
1642
1760
|
language = "en",
|
|
1643
1761
|
blockUI = false,
|
|
@@ -1697,6 +1815,7 @@ var RedactoNoticeConsent = ({
|
|
|
1697
1815
|
const abortControllerRef = (0, import_react2.useRef)(null);
|
|
1698
1816
|
const hasBootstrappedLanguageRef = (0, import_react2.useRef)(false);
|
|
1699
1817
|
const fetchContent = (0, import_react2.useCallback)(async () => {
|
|
1818
|
+
var _a2, _b2;
|
|
1700
1819
|
if (abortControllerRef.current) {
|
|
1701
1820
|
abortControllerRef.current.abort();
|
|
1702
1821
|
}
|
|
@@ -1715,8 +1834,23 @@ var RedactoNoticeConsent = ({
|
|
|
1715
1834
|
signal: abortControllerRef.current.signal
|
|
1716
1835
|
});
|
|
1717
1836
|
const activeConfig2 = data.detail.active_config;
|
|
1718
|
-
|
|
1719
|
-
|
|
1837
|
+
let purposeSelections = data.detail.purpose_selections;
|
|
1838
|
+
let reconsentRequired = data.detail.reconsent_required || false;
|
|
1839
|
+
if (ledgerBaseUrl && !applicationId) {
|
|
1840
|
+
const ledgerStatus = await fetchNoticeConsentStatus({
|
|
1841
|
+
accessToken,
|
|
1842
|
+
ledgerBaseUrl,
|
|
1843
|
+
noticeUuid: noticeId,
|
|
1844
|
+
signal: (_a2 = abortControllerRef.current) == null ? void 0 : _a2.signal
|
|
1845
|
+
});
|
|
1846
|
+
if (ledgerStatus) {
|
|
1847
|
+
const overlay = buildLedgerConsentOverlay(ledgerStatus, activeConfig2.purposes);
|
|
1848
|
+
reconsentRequired = (_b2 = overlay == null ? void 0 : overlay.reconsent_required) != null ? _b2 : false;
|
|
1849
|
+
purposeSelections = overlay == null ? void 0 : overlay.purpose_selections;
|
|
1850
|
+
data.detail.purpose_selections = purposeSelections;
|
|
1851
|
+
data.detail.reconsent_required = reconsentRequired;
|
|
1852
|
+
}
|
|
1853
|
+
}
|
|
1720
1854
|
const noticeIsMinor = data.detail.is_minor || false;
|
|
1721
1855
|
setIsMinor(noticeIsMinor);
|
|
1722
1856
|
const initialCollapsed = {};
|
|
@@ -1729,9 +1863,9 @@ var RedactoNoticeConsent = ({
|
|
|
1729
1863
|
const purposeSelected = sel ? sel.selected : false;
|
|
1730
1864
|
initialPurposeState[purpose.uuid] = purposeSelected;
|
|
1731
1865
|
purpose.data_elements.forEach((el) => {
|
|
1732
|
-
var
|
|
1866
|
+
var _a3, _b3, _c2;
|
|
1733
1867
|
const combinedId = `${purpose.uuid}-${el.uuid}`;
|
|
1734
|
-
const elementSel = (_c2 = (
|
|
1868
|
+
const elementSel = (_c2 = (_b3 = (_a3 = sel == null ? void 0 : sel.data_elements) == null ? void 0 : _a3[el.uuid]) == null ? void 0 : _b3.selected) != null ? _c2 : false;
|
|
1735
1869
|
initialDataElementState[combinedId] = elementSel;
|
|
1736
1870
|
initialDataElementSelectionsMap[combinedId] = elementSel;
|
|
1737
1871
|
});
|
|
@@ -1779,7 +1913,7 @@ var RedactoNoticeConsent = ({
|
|
|
1779
1913
|
} finally {
|
|
1780
1914
|
setIsLoading(false);
|
|
1781
1915
|
}
|
|
1782
|
-
}, [noticeId, accessToken, baseUrl, validateAgainst, includeFullyConsentedData, applicationId, onAccept, onError]);
|
|
1916
|
+
}, [noticeId, accessToken, baseUrl, ledgerBaseUrl, validateAgainst, includeFullyConsentedData, applicationId, onAccept, onError]);
|
|
1783
1917
|
(0, import_react2.useEffect)(() => {
|
|
1784
1918
|
hasBootstrappedLanguageRef.current = false;
|
|
1785
1919
|
}, [noticeId, accessToken]);
|
|
@@ -2182,6 +2316,7 @@ var RedactoNoticeConsent = ({
|
|
|
2182
2316
|
await submitConsentEvent({
|
|
2183
2317
|
accessToken,
|
|
2184
2318
|
baseUrl,
|
|
2319
|
+
ledgerBaseUrl,
|
|
2185
2320
|
noticeUuid: activeConfig2.notice_uuid,
|
|
2186
2321
|
purposes: activeConfig2.purposes.map((purpose) => ({
|
|
2187
2322
|
...purpose,
|
|
@@ -2209,7 +2344,7 @@ var RedactoNoticeConsent = ({
|
|
|
2209
2344
|
} finally {
|
|
2210
2345
|
setIsSubmitting(false);
|
|
2211
2346
|
}
|
|
2212
|
-
}, [content, accessToken, baseUrl, applicationId, selectedPurposes, selectedDataElements, stopAudio, onAccept, onError]);
|
|
2347
|
+
}, [content, accessToken, baseUrl, ledgerBaseUrl, applicationId, selectedPurposes, selectedDataElements, stopAudio, onAccept, onError]);
|
|
2213
2348
|
const handleDecline = (0, import_react2.useCallback)(() => {
|
|
2214
2349
|
stopAudio();
|
|
2215
2350
|
stopPolling();
|
|
@@ -2857,13 +2992,14 @@ var submitConsentEvent2 = async ({
|
|
|
2857
2992
|
workspace_uuid,
|
|
2858
2993
|
accessToken,
|
|
2859
2994
|
baseUrl,
|
|
2995
|
+
ledgerBaseUrl,
|
|
2860
2996
|
noticeUuid,
|
|
2861
2997
|
purposes,
|
|
2862
2998
|
declined,
|
|
2863
2999
|
meta_data
|
|
2864
3000
|
}) => {
|
|
2865
3001
|
var _a, _b;
|
|
2866
|
-
const apiBaseUrl = baseUrl || DEFAULT_CONSENT_API_BASE_URL;
|
|
3002
|
+
const apiBaseUrl = ledgerBaseUrl || baseUrl || DEFAULT_CONSENT_API_BASE_URL;
|
|
2867
3003
|
const payload = {
|
|
2868
3004
|
notice_uuid: noticeUuid,
|
|
2869
3005
|
purposes: purposes.map((purpose) => {
|
|
@@ -3185,6 +3321,7 @@ var RedactoConsentInlineComponent = ({
|
|
|
3185
3321
|
notice_uuid,
|
|
3186
3322
|
accessToken,
|
|
3187
3323
|
baseUrl,
|
|
3324
|
+
ledgerBaseUrl,
|
|
3188
3325
|
language = "en",
|
|
3189
3326
|
onAccept,
|
|
3190
3327
|
onDecline: _onDecline,
|
|
@@ -3203,6 +3340,9 @@ var RedactoConsentInlineComponent = ({
|
|
|
3203
3340
|
const [selectedPurposes, setSelectedPurposes] = (0, import_react3.useState)({});
|
|
3204
3341
|
const [selectedDataElements, setSelectedDataElements] = (0, import_react3.useState)({});
|
|
3205
3342
|
const [hasAlreadyConsented, setHasAlreadyConsented] = (0, import_react3.useState)(false);
|
|
3343
|
+
const [isCheckingConsent, setIsCheckingConsent] = (0, import_react3.useState)(
|
|
3344
|
+
Boolean(ledgerBaseUrl) && !applicationId
|
|
3345
|
+
);
|
|
3206
3346
|
const [fetchError, setFetchError] = (0, import_react3.useState)(null);
|
|
3207
3347
|
const [errorMessage, setErrorMessage] = (0, import_react3.useState)(null);
|
|
3208
3348
|
const [isLanguageDropdownOpen, setIsLanguageDropdownOpen] = (0, import_react3.useState)(false);
|
|
@@ -3323,6 +3463,40 @@ var RedactoConsentInlineComponent = ({
|
|
|
3323
3463
|
controller.abort();
|
|
3324
3464
|
};
|
|
3325
3465
|
}, [fetchNotice]);
|
|
3466
|
+
(0, import_react3.useEffect)(() => {
|
|
3467
|
+
if (!ledgerBaseUrl || applicationId) {
|
|
3468
|
+
return;
|
|
3469
|
+
}
|
|
3470
|
+
if (!accessToken || !content) {
|
|
3471
|
+
return;
|
|
3472
|
+
}
|
|
3473
|
+
let active = true;
|
|
3474
|
+
const controller = new AbortController();
|
|
3475
|
+
const checkLedgerConsent = async () => {
|
|
3476
|
+
try {
|
|
3477
|
+
const ledgerStatus = await fetchNoticeConsentStatusForScope({
|
|
3478
|
+
accessToken,
|
|
3479
|
+
ledgerBaseUrl,
|
|
3480
|
+
organisationUuid: org_uuid,
|
|
3481
|
+
workspaceUuid: workspace_uuid,
|
|
3482
|
+
noticeUuid: notice_uuid,
|
|
3483
|
+
signal: controller.signal
|
|
3484
|
+
});
|
|
3485
|
+
if (active && ledgerStatus && isNoticeFullyConsented(ledgerStatus)) {
|
|
3486
|
+
setHasAlreadyConsented(true);
|
|
3487
|
+
}
|
|
3488
|
+
} finally {
|
|
3489
|
+
if (active) {
|
|
3490
|
+
setIsCheckingConsent(false);
|
|
3491
|
+
}
|
|
3492
|
+
}
|
|
3493
|
+
};
|
|
3494
|
+
void checkLedgerConsent();
|
|
3495
|
+
return () => {
|
|
3496
|
+
active = false;
|
|
3497
|
+
controller.abort();
|
|
3498
|
+
};
|
|
3499
|
+
}, [ledgerBaseUrl, applicationId, accessToken, content, org_uuid, workspace_uuid, notice_uuid]);
|
|
3326
3500
|
const togglePurposeCollapse = (0, import_react3.useCallback)((purposeUuid) => {
|
|
3327
3501
|
setCollapsedPurposes((prev) => ({ ...prev, [purposeUuid]: !prev[purposeUuid] }));
|
|
3328
3502
|
}, []);
|
|
@@ -3373,6 +3547,7 @@ var RedactoConsentInlineComponent = ({
|
|
|
3373
3547
|
workspace_uuid,
|
|
3374
3548
|
accessToken: tokenToUse,
|
|
3375
3549
|
baseUrl,
|
|
3550
|
+
ledgerBaseUrl,
|
|
3376
3551
|
noticeUuid: content.notice_uuid,
|
|
3377
3552
|
purposes: content.purposes.map((purpose) => {
|
|
3378
3553
|
const hasSelectedRequiredElement = purpose.data_elements.some(
|
|
@@ -3411,6 +3586,7 @@ var RedactoConsentInlineComponent = ({
|
|
|
3411
3586
|
org_uuid,
|
|
3412
3587
|
workspace_uuid,
|
|
3413
3588
|
baseUrl,
|
|
3589
|
+
ledgerBaseUrl,
|
|
3414
3590
|
selectedDataElements,
|
|
3415
3591
|
selectedPurposes,
|
|
3416
3592
|
applicationId,
|
|
@@ -3418,7 +3594,7 @@ var RedactoConsentInlineComponent = ({
|
|
|
3418
3594
|
]
|
|
3419
3595
|
);
|
|
3420
3596
|
(0, import_react3.useEffect)(() => {
|
|
3421
|
-
if (accessToken && content && areAllRequiredElementsChecked && !isSubmitting && !hasSubmittedRef.current) {
|
|
3597
|
+
if (accessToken && content && areAllRequiredElementsChecked && !isSubmitting && !isCheckingConsent && !hasAlreadyConsented && !hasSubmittedRef.current) {
|
|
3422
3598
|
hasSubmittedRef.current = true;
|
|
3423
3599
|
const autoSubmit = async () => {
|
|
3424
3600
|
try {
|
|
@@ -3430,7 +3606,7 @@ var RedactoConsentInlineComponent = ({
|
|
|
3430
3606
|
};
|
|
3431
3607
|
autoSubmit();
|
|
3432
3608
|
}
|
|
3433
|
-
}, [accessToken, content, areAllRequiredElementsChecked, isSubmitting, handleAcceptWithToken, onError]);
|
|
3609
|
+
}, [accessToken, content, areAllRequiredElementsChecked, isSubmitting, isCheckingConsent, hasAlreadyConsented, handleAcceptWithToken, onError]);
|
|
3434
3610
|
(0, import_react3.useEffect)(() => {
|
|
3435
3611
|
if (!accessToken) {
|
|
3436
3612
|
hasSubmittedRef.current = false;
|
package/dist/index.mjs
CHANGED
|
@@ -131,6 +131,7 @@ var fetchConsentContent = async ({
|
|
|
131
131
|
var submitConsentEvent = async ({
|
|
132
132
|
accessToken,
|
|
133
133
|
baseUrl,
|
|
134
|
+
ledgerBaseUrl,
|
|
134
135
|
noticeUuid,
|
|
135
136
|
purposes,
|
|
136
137
|
declined,
|
|
@@ -150,7 +151,7 @@ var submitConsentEvent = async ({
|
|
|
150
151
|
if (!ORGANISATION_UUID || !WORKSPACE_UUID) {
|
|
151
152
|
throw new Error("Invalid token: missing organization or workspace UUID");
|
|
152
153
|
}
|
|
153
|
-
const apiBaseUrl = baseUrl || DEFAULT_CONSENT_API_BASE_URL;
|
|
154
|
+
const apiBaseUrl = ledgerBaseUrl || baseUrl || DEFAULT_CONSENT_API_BASE_URL;
|
|
154
155
|
const validatedPurposes = purposes.map((purpose) => {
|
|
155
156
|
if (!purpose.uuid) {
|
|
156
157
|
throw new Error("Invalid purpose data: missing uuid");
|
|
@@ -399,6 +400,122 @@ var verifyGuardianStatus = async ({
|
|
|
399
400
|
};
|
|
400
401
|
};
|
|
401
402
|
|
|
403
|
+
// src/shared/notice-consent-status.ts
|
|
404
|
+
import { jwtDecode as jwtDecode2 } from "jwt-decode";
|
|
405
|
+
var decodeNoticeConsentToken = (token) => {
|
|
406
|
+
try {
|
|
407
|
+
return jwtDecode2(token);
|
|
408
|
+
} catch {
|
|
409
|
+
return null;
|
|
410
|
+
}
|
|
411
|
+
};
|
|
412
|
+
var fetchNoticeConsentStatusForScope = async ({
|
|
413
|
+
accessToken,
|
|
414
|
+
ledgerBaseUrl,
|
|
415
|
+
organisationUuid,
|
|
416
|
+
workspaceUuid,
|
|
417
|
+
noticeUuid,
|
|
418
|
+
signal
|
|
419
|
+
}) => {
|
|
420
|
+
if (!accessToken || !ledgerBaseUrl || !organisationUuid || !workspaceUuid || !noticeUuid) {
|
|
421
|
+
return null;
|
|
422
|
+
}
|
|
423
|
+
try {
|
|
424
|
+
const response = await fetch(
|
|
425
|
+
`${ledgerBaseUrl}/public/organisations/${organisationUuid}/workspaces/${workspaceUuid}/notices/${noticeUuid}/check-consent`,
|
|
426
|
+
{
|
|
427
|
+
method: "POST",
|
|
428
|
+
headers: {
|
|
429
|
+
Authorization: `Bearer ${accessToken}`,
|
|
430
|
+
"Content-Type": "application/json"
|
|
431
|
+
},
|
|
432
|
+
body: "{}",
|
|
433
|
+
signal
|
|
434
|
+
}
|
|
435
|
+
);
|
|
436
|
+
if (!response.ok) {
|
|
437
|
+
return null;
|
|
438
|
+
}
|
|
439
|
+
const data = await response.json();
|
|
440
|
+
const body = data && typeof data === "object" && "detail" in data && data.detail ? data.detail : data;
|
|
441
|
+
if (!body || !Array.isArray(body.purposes)) {
|
|
442
|
+
return null;
|
|
443
|
+
}
|
|
444
|
+
return body;
|
|
445
|
+
} catch {
|
|
446
|
+
return null;
|
|
447
|
+
}
|
|
448
|
+
};
|
|
449
|
+
var fetchNoticeConsentStatus = async ({
|
|
450
|
+
accessToken,
|
|
451
|
+
ledgerBaseUrl,
|
|
452
|
+
noticeUuid,
|
|
453
|
+
signal
|
|
454
|
+
}) => {
|
|
455
|
+
if (!accessToken || !ledgerBaseUrl || !noticeUuid) {
|
|
456
|
+
return null;
|
|
457
|
+
}
|
|
458
|
+
const decodedToken = decodeNoticeConsentToken(accessToken);
|
|
459
|
+
if (!decodedToken) {
|
|
460
|
+
return null;
|
|
461
|
+
}
|
|
462
|
+
const {
|
|
463
|
+
organisation_uuid: ORGANISATION_UUID,
|
|
464
|
+
workspace_uuid: WORKSPACE_UUID
|
|
465
|
+
} = decodedToken;
|
|
466
|
+
if (!ORGANISATION_UUID || !WORKSPACE_UUID) {
|
|
467
|
+
return null;
|
|
468
|
+
}
|
|
469
|
+
return fetchNoticeConsentStatusForScope({
|
|
470
|
+
accessToken,
|
|
471
|
+
ledgerBaseUrl,
|
|
472
|
+
organisationUuid: ORGANISATION_UUID,
|
|
473
|
+
workspaceUuid: WORKSPACE_UUID,
|
|
474
|
+
noticeUuid,
|
|
475
|
+
signal
|
|
476
|
+
});
|
|
477
|
+
};
|
|
478
|
+
var isNoticeFullyConsented = (status) => status.consented && status.all_mandatory_active;
|
|
479
|
+
var buildLedgerConsentOverlay = (status, configPurposes) => {
|
|
480
|
+
var _a, _b;
|
|
481
|
+
const byUuid = new Map(status.purposes.map((p) => [p.uuid, p]));
|
|
482
|
+
const hasHistory = status.purposes.some(
|
|
483
|
+
(p) => (p.status || "INACTIVE") !== "INACTIVE"
|
|
484
|
+
);
|
|
485
|
+
if (!hasHistory) {
|
|
486
|
+
return null;
|
|
487
|
+
}
|
|
488
|
+
const purpose_selections = {};
|
|
489
|
+
for (const cp of configPurposes) {
|
|
490
|
+
const lp = byUuid.get(cp.uuid);
|
|
491
|
+
const purposeStatus = (lp == null ? void 0 : lp.status) || "INACTIVE";
|
|
492
|
+
const selectedByUuid = new Map(
|
|
493
|
+
((lp == null ? void 0 : lp.data_elements) || []).map((de) => [de.uuid, de.selected])
|
|
494
|
+
);
|
|
495
|
+
const data_elements = {};
|
|
496
|
+
for (const de of cp.data_elements) {
|
|
497
|
+
data_elements[de.uuid] = {
|
|
498
|
+
selected: (_a = selectedByUuid.get(de.uuid)) != null ? _a : false,
|
|
499
|
+
enabled: de.enabled,
|
|
500
|
+
required: de.required
|
|
501
|
+
};
|
|
502
|
+
}
|
|
503
|
+
purpose_selections[cp.uuid] = {
|
|
504
|
+
selected: (_b = lp == null ? void 0 : lp.selected) != null ? _b : false,
|
|
505
|
+
status: purposeStatus,
|
|
506
|
+
needs_reconsent: purposeStatus !== "ACTIVE",
|
|
507
|
+
data_elements
|
|
508
|
+
};
|
|
509
|
+
}
|
|
510
|
+
const reconsent_required = configPurposes.some(
|
|
511
|
+
(cp) => {
|
|
512
|
+
var _a2;
|
|
513
|
+
return (((_a2 = purpose_selections[cp.uuid]) == null ? void 0 : _a2.status) || "INACTIVE") !== "ACTIVE";
|
|
514
|
+
}
|
|
515
|
+
);
|
|
516
|
+
return { reconsent_required, purpose_selections };
|
|
517
|
+
};
|
|
518
|
+
|
|
402
519
|
// src/RedactoNoticeConsent/components/Checkbox.tsx
|
|
403
520
|
import { TouchableOpacity, View, StyleSheet } from "react-native";
|
|
404
521
|
import Svg, { Path } from "react-native-svg";
|
|
@@ -1629,6 +1746,7 @@ var RedactoNoticeConsent = ({
|
|
|
1629
1746
|
accessToken,
|
|
1630
1747
|
refreshToken: _refreshToken,
|
|
1631
1748
|
baseUrl,
|
|
1749
|
+
ledgerBaseUrl,
|
|
1632
1750
|
settings,
|
|
1633
1751
|
language = "en",
|
|
1634
1752
|
blockUI = false,
|
|
@@ -1688,6 +1806,7 @@ var RedactoNoticeConsent = ({
|
|
|
1688
1806
|
const abortControllerRef = useRef2(null);
|
|
1689
1807
|
const hasBootstrappedLanguageRef = useRef2(false);
|
|
1690
1808
|
const fetchContent = useCallback(async () => {
|
|
1809
|
+
var _a2, _b2;
|
|
1691
1810
|
if (abortControllerRef.current) {
|
|
1692
1811
|
abortControllerRef.current.abort();
|
|
1693
1812
|
}
|
|
@@ -1706,8 +1825,23 @@ var RedactoNoticeConsent = ({
|
|
|
1706
1825
|
signal: abortControllerRef.current.signal
|
|
1707
1826
|
});
|
|
1708
1827
|
const activeConfig2 = data.detail.active_config;
|
|
1709
|
-
|
|
1710
|
-
|
|
1828
|
+
let purposeSelections = data.detail.purpose_selections;
|
|
1829
|
+
let reconsentRequired = data.detail.reconsent_required || false;
|
|
1830
|
+
if (ledgerBaseUrl && !applicationId) {
|
|
1831
|
+
const ledgerStatus = await fetchNoticeConsentStatus({
|
|
1832
|
+
accessToken,
|
|
1833
|
+
ledgerBaseUrl,
|
|
1834
|
+
noticeUuid: noticeId,
|
|
1835
|
+
signal: (_a2 = abortControllerRef.current) == null ? void 0 : _a2.signal
|
|
1836
|
+
});
|
|
1837
|
+
if (ledgerStatus) {
|
|
1838
|
+
const overlay = buildLedgerConsentOverlay(ledgerStatus, activeConfig2.purposes);
|
|
1839
|
+
reconsentRequired = (_b2 = overlay == null ? void 0 : overlay.reconsent_required) != null ? _b2 : false;
|
|
1840
|
+
purposeSelections = overlay == null ? void 0 : overlay.purpose_selections;
|
|
1841
|
+
data.detail.purpose_selections = purposeSelections;
|
|
1842
|
+
data.detail.reconsent_required = reconsentRequired;
|
|
1843
|
+
}
|
|
1844
|
+
}
|
|
1711
1845
|
const noticeIsMinor = data.detail.is_minor || false;
|
|
1712
1846
|
setIsMinor(noticeIsMinor);
|
|
1713
1847
|
const initialCollapsed = {};
|
|
@@ -1720,9 +1854,9 @@ var RedactoNoticeConsent = ({
|
|
|
1720
1854
|
const purposeSelected = sel ? sel.selected : false;
|
|
1721
1855
|
initialPurposeState[purpose.uuid] = purposeSelected;
|
|
1722
1856
|
purpose.data_elements.forEach((el) => {
|
|
1723
|
-
var
|
|
1857
|
+
var _a3, _b3, _c2;
|
|
1724
1858
|
const combinedId = `${purpose.uuid}-${el.uuid}`;
|
|
1725
|
-
const elementSel = (_c2 = (
|
|
1859
|
+
const elementSel = (_c2 = (_b3 = (_a3 = sel == null ? void 0 : sel.data_elements) == null ? void 0 : _a3[el.uuid]) == null ? void 0 : _b3.selected) != null ? _c2 : false;
|
|
1726
1860
|
initialDataElementState[combinedId] = elementSel;
|
|
1727
1861
|
initialDataElementSelectionsMap[combinedId] = elementSel;
|
|
1728
1862
|
});
|
|
@@ -1770,7 +1904,7 @@ var RedactoNoticeConsent = ({
|
|
|
1770
1904
|
} finally {
|
|
1771
1905
|
setIsLoading(false);
|
|
1772
1906
|
}
|
|
1773
|
-
}, [noticeId, accessToken, baseUrl, validateAgainst, includeFullyConsentedData, applicationId, onAccept, onError]);
|
|
1907
|
+
}, [noticeId, accessToken, baseUrl, ledgerBaseUrl, validateAgainst, includeFullyConsentedData, applicationId, onAccept, onError]);
|
|
1774
1908
|
useEffect2(() => {
|
|
1775
1909
|
hasBootstrappedLanguageRef.current = false;
|
|
1776
1910
|
}, [noticeId, accessToken]);
|
|
@@ -2173,6 +2307,7 @@ var RedactoNoticeConsent = ({
|
|
|
2173
2307
|
await submitConsentEvent({
|
|
2174
2308
|
accessToken,
|
|
2175
2309
|
baseUrl,
|
|
2310
|
+
ledgerBaseUrl,
|
|
2176
2311
|
noticeUuid: activeConfig2.notice_uuid,
|
|
2177
2312
|
purposes: activeConfig2.purposes.map((purpose) => ({
|
|
2178
2313
|
...purpose,
|
|
@@ -2200,7 +2335,7 @@ var RedactoNoticeConsent = ({
|
|
|
2200
2335
|
} finally {
|
|
2201
2336
|
setIsSubmitting(false);
|
|
2202
2337
|
}
|
|
2203
|
-
}, [content, accessToken, baseUrl, applicationId, selectedPurposes, selectedDataElements, stopAudio, onAccept, onError]);
|
|
2338
|
+
}, [content, accessToken, baseUrl, ledgerBaseUrl, applicationId, selectedPurposes, selectedDataElements, stopAudio, onAccept, onError]);
|
|
2204
2339
|
const handleDecline = useCallback(() => {
|
|
2205
2340
|
stopAudio();
|
|
2206
2341
|
stopPolling();
|
|
@@ -2861,13 +2996,14 @@ var submitConsentEvent2 = async ({
|
|
|
2861
2996
|
workspace_uuid,
|
|
2862
2997
|
accessToken,
|
|
2863
2998
|
baseUrl,
|
|
2999
|
+
ledgerBaseUrl,
|
|
2864
3000
|
noticeUuid,
|
|
2865
3001
|
purposes,
|
|
2866
3002
|
declined,
|
|
2867
3003
|
meta_data
|
|
2868
3004
|
}) => {
|
|
2869
3005
|
var _a, _b;
|
|
2870
|
-
const apiBaseUrl = baseUrl || DEFAULT_CONSENT_API_BASE_URL;
|
|
3006
|
+
const apiBaseUrl = ledgerBaseUrl || baseUrl || DEFAULT_CONSENT_API_BASE_URL;
|
|
2871
3007
|
const payload = {
|
|
2872
3008
|
notice_uuid: noticeUuid,
|
|
2873
3009
|
purposes: purposes.map((purpose) => {
|
|
@@ -3189,6 +3325,7 @@ var RedactoConsentInlineComponent = ({
|
|
|
3189
3325
|
notice_uuid,
|
|
3190
3326
|
accessToken,
|
|
3191
3327
|
baseUrl,
|
|
3328
|
+
ledgerBaseUrl,
|
|
3192
3329
|
language = "en",
|
|
3193
3330
|
onAccept,
|
|
3194
3331
|
onDecline: _onDecline,
|
|
@@ -3207,6 +3344,9 @@ var RedactoConsentInlineComponent = ({
|
|
|
3207
3344
|
const [selectedPurposes, setSelectedPurposes] = useState2({});
|
|
3208
3345
|
const [selectedDataElements, setSelectedDataElements] = useState2({});
|
|
3209
3346
|
const [hasAlreadyConsented, setHasAlreadyConsented] = useState2(false);
|
|
3347
|
+
const [isCheckingConsent, setIsCheckingConsent] = useState2(
|
|
3348
|
+
Boolean(ledgerBaseUrl) && !applicationId
|
|
3349
|
+
);
|
|
3210
3350
|
const [fetchError, setFetchError] = useState2(null);
|
|
3211
3351
|
const [errorMessage, setErrorMessage] = useState2(null);
|
|
3212
3352
|
const [isLanguageDropdownOpen, setIsLanguageDropdownOpen] = useState2(false);
|
|
@@ -3327,6 +3467,40 @@ var RedactoConsentInlineComponent = ({
|
|
|
3327
3467
|
controller.abort();
|
|
3328
3468
|
};
|
|
3329
3469
|
}, [fetchNotice]);
|
|
3470
|
+
useEffect3(() => {
|
|
3471
|
+
if (!ledgerBaseUrl || applicationId) {
|
|
3472
|
+
return;
|
|
3473
|
+
}
|
|
3474
|
+
if (!accessToken || !content) {
|
|
3475
|
+
return;
|
|
3476
|
+
}
|
|
3477
|
+
let active = true;
|
|
3478
|
+
const controller = new AbortController();
|
|
3479
|
+
const checkLedgerConsent = async () => {
|
|
3480
|
+
try {
|
|
3481
|
+
const ledgerStatus = await fetchNoticeConsentStatusForScope({
|
|
3482
|
+
accessToken,
|
|
3483
|
+
ledgerBaseUrl,
|
|
3484
|
+
organisationUuid: org_uuid,
|
|
3485
|
+
workspaceUuid: workspace_uuid,
|
|
3486
|
+
noticeUuid: notice_uuid,
|
|
3487
|
+
signal: controller.signal
|
|
3488
|
+
});
|
|
3489
|
+
if (active && ledgerStatus && isNoticeFullyConsented(ledgerStatus)) {
|
|
3490
|
+
setHasAlreadyConsented(true);
|
|
3491
|
+
}
|
|
3492
|
+
} finally {
|
|
3493
|
+
if (active) {
|
|
3494
|
+
setIsCheckingConsent(false);
|
|
3495
|
+
}
|
|
3496
|
+
}
|
|
3497
|
+
};
|
|
3498
|
+
void checkLedgerConsent();
|
|
3499
|
+
return () => {
|
|
3500
|
+
active = false;
|
|
3501
|
+
controller.abort();
|
|
3502
|
+
};
|
|
3503
|
+
}, [ledgerBaseUrl, applicationId, accessToken, content, org_uuid, workspace_uuid, notice_uuid]);
|
|
3330
3504
|
const togglePurposeCollapse = useCallback2((purposeUuid) => {
|
|
3331
3505
|
setCollapsedPurposes((prev) => ({ ...prev, [purposeUuid]: !prev[purposeUuid] }));
|
|
3332
3506
|
}, []);
|
|
@@ -3377,6 +3551,7 @@ var RedactoConsentInlineComponent = ({
|
|
|
3377
3551
|
workspace_uuid,
|
|
3378
3552
|
accessToken: tokenToUse,
|
|
3379
3553
|
baseUrl,
|
|
3554
|
+
ledgerBaseUrl,
|
|
3380
3555
|
noticeUuid: content.notice_uuid,
|
|
3381
3556
|
purposes: content.purposes.map((purpose) => {
|
|
3382
3557
|
const hasSelectedRequiredElement = purpose.data_elements.some(
|
|
@@ -3415,6 +3590,7 @@ var RedactoConsentInlineComponent = ({
|
|
|
3415
3590
|
org_uuid,
|
|
3416
3591
|
workspace_uuid,
|
|
3417
3592
|
baseUrl,
|
|
3593
|
+
ledgerBaseUrl,
|
|
3418
3594
|
selectedDataElements,
|
|
3419
3595
|
selectedPurposes,
|
|
3420
3596
|
applicationId,
|
|
@@ -3422,7 +3598,7 @@ var RedactoConsentInlineComponent = ({
|
|
|
3422
3598
|
]
|
|
3423
3599
|
);
|
|
3424
3600
|
useEffect3(() => {
|
|
3425
|
-
if (accessToken && content && areAllRequiredElementsChecked && !isSubmitting && !hasSubmittedRef.current) {
|
|
3601
|
+
if (accessToken && content && areAllRequiredElementsChecked && !isSubmitting && !isCheckingConsent && !hasAlreadyConsented && !hasSubmittedRef.current) {
|
|
3426
3602
|
hasSubmittedRef.current = true;
|
|
3427
3603
|
const autoSubmit = async () => {
|
|
3428
3604
|
try {
|
|
@@ -3434,7 +3610,7 @@ var RedactoConsentInlineComponent = ({
|
|
|
3434
3610
|
};
|
|
3435
3611
|
autoSubmit();
|
|
3436
3612
|
}
|
|
3437
|
-
}, [accessToken, content, areAllRequiredElementsChecked, isSubmitting, handleAcceptWithToken, onError]);
|
|
3613
|
+
}, [accessToken, content, areAllRequiredElementsChecked, isSubmitting, isCheckingConsent, hasAlreadyConsented, handleAcceptWithToken, onError]);
|
|
3438
3614
|
useEffect3(() => {
|
|
3439
3615
|
if (!accessToken) {
|
|
3440
3616
|
hasSubmittedRef.current = false;
|