@redacto.io/consent-sdk-react-native 5.0.0-beta.6 → 5.0.0-beta.8
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/README.md +75 -0
- package/dist/{chunk-UVRSRLYW.mjs → chunk-B2TXWC2C.mjs} +4 -0
- package/dist/index.d.mts +28 -2
- package/dist/index.d.ts +28 -2
- package/dist/index.js +141 -51
- package/dist/index.mjs +140 -52
- package/dist/privacy-center.d.mts +81 -4
- package/dist/privacy-center.d.ts +81 -4
- package/dist/privacy-center.js +1277 -572
- package/dist/privacy-center.mjs +1247 -544
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -64,6 +64,81 @@ pnpm add @tanstack/react-query i18next react-i18next dayjs \
|
|
|
64
64
|
|
|
65
65
|
> **Note:** `react-native-svg` must be linked for native builds. Follow the [react-native-svg setup guide](https://github.com/software-mansion/react-native-svg#installation).
|
|
66
66
|
|
|
67
|
+
## Sandbox Mode (No Backend Required)
|
|
68
|
+
|
|
69
|
+
Sandbox mode lets you build and test a full consent PoC — **notice → Privacy Center → DSAR** — straight from your app, with **no backend and no token minting**. Instead of your server generating a JWT, you paste a **static sandbox token** into the SDK. Everything you create is recorded as test data, isolated from your live records.
|
|
70
|
+
|
|
71
|
+
Going live is a config swap, not a rewrite: drop the sandbox props and pass a real JWT (see [Backend Server Setup](#backend-server-setup)).
|
|
72
|
+
|
|
73
|
+
### 1. Get your sandbox credentials
|
|
74
|
+
|
|
75
|
+
In the **Redacto Dashboard → API Keys → Sandbox** tab, copy:
|
|
76
|
+
|
|
77
|
+
- your **Sandbox token** (a static string; it never expires and needs no refresh)
|
|
78
|
+
- your **Organization ID** and **Workspace ID** (shown under *Workspace identifiers* on the same page)
|
|
79
|
+
|
|
80
|
+
### 2. Collect consent
|
|
81
|
+
|
|
82
|
+
Pass the sandbox `token`, org/workspace, and a test identity (`email`, `mobile`, or `ucic`). No `accessToken` is needed:
|
|
83
|
+
|
|
84
|
+
```tsx
|
|
85
|
+
import { RedactoNoticeConsent } from "@redacto.io/consent-sdk-react-native";
|
|
86
|
+
|
|
87
|
+
<RedactoNoticeConsent
|
|
88
|
+
noticeId={NOTICE_UUID}
|
|
89
|
+
token={SANDBOX_TOKEN}
|
|
90
|
+
organisationUuid={ORG_UUID}
|
|
91
|
+
workspaceUuid={WORKSPACE_UUID}
|
|
92
|
+
email="test.user@example.com" // or `mobile`, or `ucic`
|
|
93
|
+
onAccept={() => console.log("consent recorded (test)")}
|
|
94
|
+
onDecline={() => {}}
|
|
95
|
+
/>;
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### 3. Manage consent & raise a DSAR
|
|
99
|
+
|
|
100
|
+
Point the Privacy Center at the same sandbox token and test identity. The same test user can now review the consent from step 2, withdraw it, and file a DSAR — end to end, all as test data:
|
|
101
|
+
|
|
102
|
+
```tsx
|
|
103
|
+
import { RedactoPrivacyCenter } from "@redacto.io/consent-sdk-react-native/privacy-center";
|
|
104
|
+
|
|
105
|
+
<RedactoPrivacyCenter
|
|
106
|
+
baseUrl={BASE_URL}
|
|
107
|
+
slug="acme-co"
|
|
108
|
+
token={SANDBOX_TOKEN}
|
|
109
|
+
organisationUuid={ORG_UUID}
|
|
110
|
+
workspaceUuid={WORKSPACE_UUID}
|
|
111
|
+
email="test.user@example.com" // or `mobile`, or `ucic`
|
|
112
|
+
onError={(error) => {
|
|
113
|
+
console.error(error);
|
|
114
|
+
return false;
|
|
115
|
+
}}
|
|
116
|
+
/>;
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Sandbox props
|
|
120
|
+
|
|
121
|
+
Both `RedactoNoticeConsent` and `RedactoPrivacyCenter` accept the same sandbox props:
|
|
122
|
+
|
|
123
|
+
| Prop | Required | Description |
|
|
124
|
+
| --------------------------- | ------------ | ----------------------------------------------------------------------------------- |
|
|
125
|
+
| `token` | Yes | Static sandbox token from the Dashboard. Its presence activates sandbox mode. |
|
|
126
|
+
| `organisationUuid` | Yes | Organization ID from the Dashboard. |
|
|
127
|
+
| `workspaceUuid` | Yes | Workspace ID from the Dashboard. |
|
|
128
|
+
| `email` / `mobile` / `ucic` | One required | The test subject. Precedence when more than one is set: `ucic` > `email` > `mobile`. |
|
|
129
|
+
|
|
130
|
+
### How it works
|
|
131
|
+
|
|
132
|
+
- The SDK sends the sandbox token as an `X-Consent-Token` header and the test identity inside each request (query params on reads, body on writes) — no JWT decode, no token refresh (a `401` fails fast).
|
|
133
|
+
- The server records everything under `environment=test`, namespaced so sandbox data never mixes with — or reads — your live records.
|
|
134
|
+
- Sandbox always talks to the consent server; it never routes to the Go ledger.
|
|
135
|
+
|
|
136
|
+
### Going live
|
|
137
|
+
|
|
138
|
+
Sandbox and production use the same components. To ship, remove the sandbox props and pass a real `accessToken` / `refreshToken` (JWT) minted by your backend — see [Backend Server Setup](#backend-server-setup) below. New records are then written as `environment=live`.
|
|
139
|
+
|
|
140
|
+
> Sandbox is available on `RedactoNoticeConsent` and `RedactoPrivacyCenter`. The inline widget (`RedactoNoticeConsentInline`) is JWT-only.
|
|
141
|
+
|
|
67
142
|
## Backend Server Setup
|
|
68
143
|
|
|
69
144
|
The SDK never talks to Redacto with your CMS API key directly — your backend acts as a token broker. Obtain your **CMS-API-Key** from the Redacto Dashboard, store it in your backend's environment, and expose two endpoints to your mobile app:
|
|
@@ -49,8 +49,12 @@ function toLanguageCode(lang) {
|
|
|
49
49
|
return (_c = (_b = (_a = codeByLabel.get(trimmed)) != null ? _a : codeByName.get(lower)) != null ? _b : codeByLower.get(lower)) != null ? _c : trimmed;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
// src/shared/sandbox.ts
|
|
53
|
+
var SANDBOX_TOKEN_HEADER = "X-Consent-Token";
|
|
54
|
+
|
|
52
55
|
export {
|
|
53
56
|
__require,
|
|
57
|
+
SANDBOX_TOKEN_HEADER,
|
|
54
58
|
languageOptions,
|
|
55
59
|
toLanguageCode
|
|
56
60
|
};
|
package/dist/index.d.mts
CHANGED
|
@@ -28,8 +28,34 @@ type Settings$1 = {
|
|
|
28
28
|
|
|
29
29
|
type Props$1 = Readonly<{
|
|
30
30
|
noticeId: string;
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
/**
|
|
32
|
+
* JWT access token. Optional so sandbox integrations (see `token`) can
|
|
33
|
+
* omit it. Required in the normal JWT flow.
|
|
34
|
+
*/
|
|
35
|
+
accessToken?: string;
|
|
36
|
+
/** JWT refresh token. Optional; accepted for source-compat, currently unused. */
|
|
37
|
+
refreshToken?: string;
|
|
38
|
+
/**
|
|
39
|
+
* Sandbox PoC: a pasted static token. When set, the SDK runs against the
|
|
40
|
+
* sandbox with no JWT — it sends the single `X-Consent-Token` header, carries
|
|
41
|
+
* the acting identity (`email` || `mobile` || `ucic`) in each request's own
|
|
42
|
+
* payload, takes org/workspace from `organisationUuid`/`workspaceUuid`, and
|
|
43
|
+
* does no token refresh.
|
|
44
|
+
*/
|
|
45
|
+
token?: string;
|
|
46
|
+
/** Sandbox test subject email (carried in the request payload when set). */
|
|
47
|
+
email?: string;
|
|
48
|
+
/** Sandbox test subject mobile (fallback subject when `email` is absent). */
|
|
49
|
+
mobile?: string;
|
|
50
|
+
/**
|
|
51
|
+
* Sandbox UCIC: the client's own user id / org_user_id, e.g. a UUID or
|
|
52
|
+
* customer code; optional third identifier alongside email/mobile.
|
|
53
|
+
*/
|
|
54
|
+
ucic?: string;
|
|
55
|
+
/** Sandbox org UUID (replaces the JWT-decoded org in sandbox mode). */
|
|
56
|
+
organisationUuid?: string;
|
|
57
|
+
/** Sandbox workspace UUID (replaces the JWT-decoded workspace in sandbox mode). */
|
|
58
|
+
workspaceUuid?: string;
|
|
33
59
|
baseUrl?: string;
|
|
34
60
|
/** Go ledger base URL — serves check-consent and the consent write; omit to use the legacy consent server. */
|
|
35
61
|
ledgerBaseUrl?: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -28,8 +28,34 @@ type Settings$1 = {
|
|
|
28
28
|
|
|
29
29
|
type Props$1 = Readonly<{
|
|
30
30
|
noticeId: string;
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
/**
|
|
32
|
+
* JWT access token. Optional so sandbox integrations (see `token`) can
|
|
33
|
+
* omit it. Required in the normal JWT flow.
|
|
34
|
+
*/
|
|
35
|
+
accessToken?: string;
|
|
36
|
+
/** JWT refresh token. Optional; accepted for source-compat, currently unused. */
|
|
37
|
+
refreshToken?: string;
|
|
38
|
+
/**
|
|
39
|
+
* Sandbox PoC: a pasted static token. When set, the SDK runs against the
|
|
40
|
+
* sandbox with no JWT — it sends the single `X-Consent-Token` header, carries
|
|
41
|
+
* the acting identity (`email` || `mobile` || `ucic`) in each request's own
|
|
42
|
+
* payload, takes org/workspace from `organisationUuid`/`workspaceUuid`, and
|
|
43
|
+
* does no token refresh.
|
|
44
|
+
*/
|
|
45
|
+
token?: string;
|
|
46
|
+
/** Sandbox test subject email (carried in the request payload when set). */
|
|
47
|
+
email?: string;
|
|
48
|
+
/** Sandbox test subject mobile (fallback subject when `email` is absent). */
|
|
49
|
+
mobile?: string;
|
|
50
|
+
/**
|
|
51
|
+
* Sandbox UCIC: the client's own user id / org_user_id, e.g. a UUID or
|
|
52
|
+
* customer code; optional third identifier alongside email/mobile.
|
|
53
|
+
*/
|
|
54
|
+
ucic?: string;
|
|
55
|
+
/** Sandbox org UUID (replaces the JWT-decoded org in sandbox mode). */
|
|
56
|
+
organisationUuid?: string;
|
|
57
|
+
/** Sandbox workspace UUID (replaces the JWT-decoded workspace in sandbox mode). */
|
|
58
|
+
workspaceUuid?: string;
|
|
33
59
|
baseUrl?: string;
|
|
34
60
|
/** Go ledger base URL — serves check-consent and the consent write; omit to use the legacy consent server. */
|
|
35
61
|
ledgerBaseUrl?: string;
|
package/dist/index.js
CHANGED
|
@@ -43,6 +43,67 @@ var import_react_native_svg3 = __toESM(require("react-native-svg"));
|
|
|
43
43
|
// src/RedactoNoticeConsent/api/index.ts
|
|
44
44
|
var import_jwt_decode = require("jwt-decode");
|
|
45
45
|
|
|
46
|
+
// src/shared/sandbox.ts
|
|
47
|
+
var SANDBOX_TOKEN_HEADER = "X-Consent-Token";
|
|
48
|
+
|
|
49
|
+
// src/RedactoNoticeConsent/api/sandbox.ts
|
|
50
|
+
var resolveSandboxAuth = (params) => {
|
|
51
|
+
var _a, _b, _c, _d, _e;
|
|
52
|
+
const token = (_a = params.token) == null ? void 0 : _a.trim();
|
|
53
|
+
if (!token) {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
const organisationUuid = (_b = params.organisationUuid) == null ? void 0 : _b.trim();
|
|
57
|
+
const workspaceUuid = (_c = params.workspaceUuid) == null ? void 0 : _c.trim();
|
|
58
|
+
const ucic = (_d = params.sandboxUcic) == null ? void 0 : _d.trim();
|
|
59
|
+
const subject = (_e = params.sandboxSubject) == null ? void 0 : _e.trim();
|
|
60
|
+
if (!organisationUuid || !workspaceUuid) {
|
|
61
|
+
throw new Error(
|
|
62
|
+
"Sandbox mode requires organisationUuid and workspaceUuid props"
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
if (!ucic && !subject) {
|
|
66
|
+
throw new Error("Sandbox mode requires a UCIC, email, or mobile");
|
|
67
|
+
}
|
|
68
|
+
return { token, ucic, subject: subject != null ? subject : "", organisationUuid, workspaceUuid };
|
|
69
|
+
};
|
|
70
|
+
var resolveRequestAuth = (accessToken, sandboxParams, decodeTokenSafely2) => {
|
|
71
|
+
const sandbox = resolveSandboxAuth(sandboxParams);
|
|
72
|
+
if (sandbox) {
|
|
73
|
+
return {
|
|
74
|
+
organisationUuid: sandbox.organisationUuid,
|
|
75
|
+
workspaceUuid: sandbox.workspaceUuid,
|
|
76
|
+
sandbox
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
const decodedToken = accessToken ? decodeTokenSafely2(accessToken) : null;
|
|
80
|
+
if (!decodedToken) {
|
|
81
|
+
throw new Error("Invalid access token");
|
|
82
|
+
}
|
|
83
|
+
const { organisation_uuid, workspace_uuid } = decodedToken;
|
|
84
|
+
if (!organisation_uuid || !workspace_uuid) {
|
|
85
|
+
throw new Error("Invalid token: missing organization or workspace UUID");
|
|
86
|
+
}
|
|
87
|
+
return {
|
|
88
|
+
organisationUuid: organisation_uuid,
|
|
89
|
+
workspaceUuid: workspace_uuid,
|
|
90
|
+
sandbox: null
|
|
91
|
+
};
|
|
92
|
+
};
|
|
93
|
+
var buildAuthHeaders = (accessToken, sandbox) => {
|
|
94
|
+
if (sandbox) {
|
|
95
|
+
return { [SANDBOX_TOKEN_HEADER]: sandbox.token };
|
|
96
|
+
}
|
|
97
|
+
return { Authorization: `Bearer ${accessToken}` };
|
|
98
|
+
};
|
|
99
|
+
var sandboxBodyIdentity = (sandbox) => {
|
|
100
|
+
if (sandbox.ucic) {
|
|
101
|
+
return { org_user_id: sandbox.ucic };
|
|
102
|
+
}
|
|
103
|
+
return sandbox.subject.includes("@") ? { primary_email: sandbox.subject } : { primary_mobile: sandbox.subject };
|
|
104
|
+
};
|
|
105
|
+
var sandboxQueryIdentity = (sandbox) => sandboxBodyIdentity(sandbox);
|
|
106
|
+
|
|
46
107
|
// src/constants.ts
|
|
47
108
|
var DEFAULT_CONSENT_API_BASE_URL = "https://api.redacto.io/consent";
|
|
48
109
|
|
|
@@ -125,21 +186,19 @@ var fetchConsentContent = async ({
|
|
|
125
186
|
specific_uuid,
|
|
126
187
|
validate_against = "all",
|
|
127
188
|
include_fully_consented_data = false,
|
|
128
|
-
signal
|
|
189
|
+
signal,
|
|
190
|
+
...sandboxParams
|
|
129
191
|
}) => {
|
|
130
|
-
if (!noticeId || !
|
|
131
|
-
throw new Error("noticeId
|
|
132
|
-
}
|
|
133
|
-
const decodedToken = decodeTokenSafely(accessToken);
|
|
134
|
-
if (!decodedToken) {
|
|
135
|
-
throw new Error("Invalid access token");
|
|
192
|
+
if (!noticeId || !validate_against) {
|
|
193
|
+
throw new Error("noticeId is required");
|
|
136
194
|
}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
throw new Error("Invalid token: missing organization or workspace UUID");
|
|
195
|
+
if (!accessToken && !sandboxParams.token) {
|
|
196
|
+
throw new Error("accessToken or token is required");
|
|
140
197
|
}
|
|
198
|
+
const { organisationUuid: ORGANISATION_UUID, workspaceUuid: WORKSPACE_UUID, sandbox } = resolveRequestAuth(accessToken, sandboxParams, decodeTokenSafely);
|
|
141
199
|
const apiBaseUrl = baseUrl || DEFAULT_CONSENT_API_BASE_URL;
|
|
142
|
-
const
|
|
200
|
+
const cacheIdentity = sandbox ? `sandbox:${sandbox.organisationUuid}:${sandbox.workspaceUuid}:${sandbox.ucic || sandbox.subject}` : accessToken;
|
|
201
|
+
const cacheKey = `${cacheIdentity}-${noticeId}-${validate_against}-${language}-${specific_uuid || ""}-${include_fully_consented_data}`;
|
|
143
202
|
if (validate_against === "all" && !specific_uuid) {
|
|
144
203
|
const cachedData = getCachedData(cacheKey);
|
|
145
204
|
if (cachedData) {
|
|
@@ -156,10 +215,15 @@ var fetchConsentContent = async ({
|
|
|
156
215
|
if (include_fully_consented_data) {
|
|
157
216
|
url.searchParams.append("include_fully_consented_data", "true");
|
|
158
217
|
}
|
|
218
|
+
if (sandbox) {
|
|
219
|
+
for (const [key, value] of Object.entries(sandboxQueryIdentity(sandbox))) {
|
|
220
|
+
url.searchParams.append(key, value);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
159
223
|
const response = await fetch(url.toString(), {
|
|
160
224
|
method: "GET",
|
|
161
225
|
headers: {
|
|
162
|
-
|
|
226
|
+
...buildAuthHeaders(accessToken, sandbox),
|
|
163
227
|
"Accept-Language": language,
|
|
164
228
|
"Content-Type": "application/json"
|
|
165
229
|
},
|
|
@@ -199,20 +263,17 @@ var submitConsentEvent = async ({
|
|
|
199
263
|
guardianVerificationReference,
|
|
200
264
|
selfDeclaredAdult,
|
|
201
265
|
language,
|
|
202
|
-
signal
|
|
266
|
+
signal,
|
|
267
|
+
...sandboxParams
|
|
203
268
|
}) => {
|
|
204
|
-
if (!noticeUuid || !
|
|
205
|
-
throw new Error("noticeUuid
|
|
206
|
-
}
|
|
207
|
-
const decodedToken = decodeTokenSafely(accessToken);
|
|
208
|
-
if (!decodedToken) {
|
|
209
|
-
throw new Error("Invalid access token");
|
|
269
|
+
if (!noticeUuid || !Array.isArray(purposes)) {
|
|
270
|
+
throw new Error("noticeUuid and purposes array are required");
|
|
210
271
|
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
throw new Error("Invalid token: missing organization or workspace UUID");
|
|
272
|
+
if (!accessToken && !sandboxParams.token) {
|
|
273
|
+
throw new Error("accessToken or token is required");
|
|
214
274
|
}
|
|
215
|
-
const
|
|
275
|
+
const { organisationUuid: ORGANISATION_UUID, workspaceUuid: WORKSPACE_UUID, sandbox } = resolveRequestAuth(accessToken, sandboxParams, decodeTokenSafely);
|
|
276
|
+
const apiBaseUrl = (sandbox ? null : ledgerBaseUrl) || baseUrl || DEFAULT_CONSENT_API_BASE_URL;
|
|
216
277
|
const validatedPurposes = purposes.map((purpose) => {
|
|
217
278
|
if (!purpose.uuid) {
|
|
218
279
|
throw new Error("Invalid purpose data: missing uuid");
|
|
@@ -238,15 +299,16 @@ var submitConsentEvent = async ({
|
|
|
238
299
|
self_declared_adult: selfDeclaredAdult,
|
|
239
300
|
language: toLanguageCode(language)
|
|
240
301
|
};
|
|
302
|
+
const requestBody = sandbox ? { ...payload, ...sandboxBodyIdentity(sandbox) } : payload;
|
|
241
303
|
const response = await fetch(
|
|
242
304
|
`${apiBaseUrl}/public/organisations/${ORGANISATION_UUID}/workspaces/${WORKSPACE_UUID}/submit-consent`,
|
|
243
305
|
{
|
|
244
306
|
method: "POST",
|
|
245
307
|
headers: {
|
|
246
|
-
|
|
308
|
+
...buildAuthHeaders(accessToken, sandbox),
|
|
247
309
|
"Content-Type": "application/json"
|
|
248
310
|
},
|
|
249
|
-
body: JSON.stringify(
|
|
311
|
+
body: JSON.stringify(requestBody),
|
|
250
312
|
signal
|
|
251
313
|
}
|
|
252
314
|
);
|
|
@@ -272,28 +334,30 @@ var submitConsentEvent = async ({
|
|
|
272
334
|
var fetchTTSAudioUrls = async ({
|
|
273
335
|
accessToken,
|
|
274
336
|
baseUrl,
|
|
337
|
+
ledgerBaseUrl,
|
|
275
338
|
noticeUuid,
|
|
276
339
|
language,
|
|
277
|
-
signal
|
|
340
|
+
signal,
|
|
341
|
+
...sandboxParams
|
|
278
342
|
}) => {
|
|
279
|
-
if (!accessToken || !noticeUuid || !language) {
|
|
280
|
-
throw new Error("accessToken, noticeUuid, and language are required");
|
|
281
|
-
}
|
|
282
|
-
const decodedToken = decodeTokenSafely(accessToken);
|
|
283
|
-
if (!decodedToken) {
|
|
284
|
-
throw new Error("Invalid access token");
|
|
285
|
-
}
|
|
286
|
-
const { organisation_uuid: ORGANISATION_UUID, workspace_uuid: WORKSPACE_UUID } = decodedToken;
|
|
287
|
-
if (!ORGANISATION_UUID || !WORKSPACE_UUID) {
|
|
288
|
-
throw new Error("Invalid token: missing organization or workspace UUID");
|
|
343
|
+
if (!accessToken && !sandboxParams.token || !noticeUuid || !language) {
|
|
344
|
+
throw new Error("accessToken (or token), noticeUuid, and language are required");
|
|
289
345
|
}
|
|
290
|
-
const
|
|
346
|
+
const { organisationUuid: ORGANISATION_UUID, workspaceUuid: WORKSPACE_UUID, sandbox } = resolveRequestAuth(accessToken, sandboxParams, decodeTokenSafely);
|
|
347
|
+
const apiBaseUrl = (sandbox ? null : ledgerBaseUrl) || baseUrl || DEFAULT_CONSENT_API_BASE_URL;
|
|
291
348
|
const normalizedLanguage = language === "en" || language === "EN" ? "English" : language;
|
|
292
|
-
const url =
|
|
293
|
-
|
|
349
|
+
const url = new URL(
|
|
350
|
+
`${apiBaseUrl}/public/organisations/${ORGANISATION_UUID}/workspaces/${WORKSPACE_UUID}/notices/${noticeUuid}/audio/${encodeURIComponent(normalizedLanguage)}`
|
|
351
|
+
);
|
|
352
|
+
if (sandbox) {
|
|
353
|
+
for (const [key, value] of Object.entries(sandboxQueryIdentity(sandbox))) {
|
|
354
|
+
url.searchParams.append(key, value);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
const response = await fetch(url.toString(), {
|
|
294
358
|
method: "GET",
|
|
295
359
|
headers: {
|
|
296
|
-
|
|
360
|
+
...buildAuthHeaders(accessToken, sandbox),
|
|
297
361
|
Accept: "application/json",
|
|
298
362
|
"Content-Type": "application/json"
|
|
299
363
|
},
|
|
@@ -1800,6 +1864,12 @@ var RedactoNoticeConsent = ({
|
|
|
1800
1864
|
noticeId,
|
|
1801
1865
|
accessToken,
|
|
1802
1866
|
refreshToken: _refreshToken,
|
|
1867
|
+
token,
|
|
1868
|
+
email,
|
|
1869
|
+
mobile,
|
|
1870
|
+
ucic,
|
|
1871
|
+
organisationUuid,
|
|
1872
|
+
workspaceUuid,
|
|
1803
1873
|
baseUrl,
|
|
1804
1874
|
ledgerBaseUrl,
|
|
1805
1875
|
settings,
|
|
@@ -1815,6 +1885,16 @@ var RedactoNoticeConsent = ({
|
|
|
1815
1885
|
}) => {
|
|
1816
1886
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u;
|
|
1817
1887
|
const { isMobile } = useResponsive();
|
|
1888
|
+
const sandboxParams = (0, import_react2.useMemo)(
|
|
1889
|
+
() => ({
|
|
1890
|
+
token,
|
|
1891
|
+
sandboxUcic: ucic,
|
|
1892
|
+
sandboxSubject: email || mobile,
|
|
1893
|
+
organisationUuid,
|
|
1894
|
+
workspaceUuid
|
|
1895
|
+
}),
|
|
1896
|
+
[token, ucic, email, mobile, organisationUuid, workspaceUuid]
|
|
1897
|
+
);
|
|
1818
1898
|
const [content, setContent] = (0, import_react2.useState)(null);
|
|
1819
1899
|
const [isLoading, setIsLoading] = (0, import_react2.useState)(true);
|
|
1820
1900
|
const [isSubmitting, setIsSubmitting] = (0, import_react2.useState)(false);
|
|
@@ -1869,20 +1949,22 @@ var RedactoNoticeConsent = ({
|
|
|
1869
1949
|
setIsLoading(true);
|
|
1870
1950
|
setErrorMessage(null);
|
|
1871
1951
|
try {
|
|
1952
|
+
const noticeBaseUrl = ledgerBaseUrl && !applicationId && !token ? ledgerBaseUrl : baseUrl;
|
|
1872
1953
|
const data = await fetchConsentContent({
|
|
1873
1954
|
noticeId,
|
|
1874
1955
|
accessToken,
|
|
1875
|
-
baseUrl,
|
|
1956
|
+
baseUrl: noticeBaseUrl,
|
|
1876
1957
|
language: "English",
|
|
1877
1958
|
validate_against: validateAgainst,
|
|
1878
1959
|
include_fully_consented_data: includeFullyConsentedData,
|
|
1879
1960
|
specific_uuid: applicationId,
|
|
1880
|
-
signal: abortControllerRef.current.signal
|
|
1961
|
+
signal: abortControllerRef.current.signal,
|
|
1962
|
+
...sandboxParams
|
|
1881
1963
|
});
|
|
1882
1964
|
const activeConfig2 = data.detail.active_config;
|
|
1883
1965
|
let purposeSelections = data.detail.purpose_selections;
|
|
1884
1966
|
let reconsentRequired = data.detail.reconsent_required || false;
|
|
1885
|
-
if (ledgerBaseUrl && !applicationId) {
|
|
1967
|
+
if (accessToken && ledgerBaseUrl && !applicationId && !token) {
|
|
1886
1968
|
const ledgerStatus = await fetchNoticeConsentStatus({
|
|
1887
1969
|
accessToken,
|
|
1888
1970
|
ledgerBaseUrl,
|
|
@@ -1959,7 +2041,7 @@ var RedactoNoticeConsent = ({
|
|
|
1959
2041
|
} finally {
|
|
1960
2042
|
setIsLoading(false);
|
|
1961
2043
|
}
|
|
1962
|
-
}, [noticeId, accessToken, baseUrl, ledgerBaseUrl, validateAgainst, includeFullyConsentedData, applicationId, onAccept, onError]);
|
|
2044
|
+
}, [noticeId, accessToken, sandboxParams, token, baseUrl, ledgerBaseUrl, validateAgainst, includeFullyConsentedData, applicationId, onAccept, onError]);
|
|
1963
2045
|
(0, import_react2.useEffect)(() => {
|
|
1964
2046
|
hasBootstrappedLanguageRef.current = false;
|
|
1965
2047
|
}, [noticeId, accessToken]);
|
|
@@ -1980,8 +2062,10 @@ var RedactoNoticeConsent = ({
|
|
|
1980
2062
|
const data = await fetchTTSAudioUrls({
|
|
1981
2063
|
accessToken,
|
|
1982
2064
|
baseUrl,
|
|
2065
|
+
ledgerBaseUrl,
|
|
1983
2066
|
noticeUuid: content.detail.active_config.notice_uuid,
|
|
1984
|
-
language: selectedLanguage
|
|
2067
|
+
language: selectedLanguage,
|
|
2068
|
+
...sandboxParams
|
|
1985
2069
|
});
|
|
1986
2070
|
const urls = {
|
|
1987
2071
|
notice_text: data.detail.notice_text_audio_url,
|
|
@@ -2035,7 +2119,7 @@ var RedactoNoticeConsent = ({
|
|
|
2035
2119
|
setTtsAudioUrls({});
|
|
2036
2120
|
setIsTTSAvailable(false);
|
|
2037
2121
|
}
|
|
2038
|
-
}, [content, accessToken, baseUrl, selectedLanguage]);
|
|
2122
|
+
}, [content, accessToken, sandboxParams, baseUrl, ledgerBaseUrl, selectedLanguage]);
|
|
2039
2123
|
const clearPlaybackWatchers = (0, import_react2.useCallback)(() => {
|
|
2040
2124
|
if (playbackSubscriptionRef.current) {
|
|
2041
2125
|
playbackSubscriptionRef.current.remove();
|
|
@@ -2376,7 +2460,8 @@ var RedactoNoticeConsent = ({
|
|
|
2376
2460
|
meta_data: applicationId ? { specific_uuid: applicationId } : void 0,
|
|
2377
2461
|
guardianVerificationReference: verificationReferenceRef.current || void 0,
|
|
2378
2462
|
selfDeclaredAdult: selfDeclaredAdult || void 0,
|
|
2379
|
-
language: selectedLanguage
|
|
2463
|
+
language: selectedLanguage,
|
|
2464
|
+
...sandboxParams
|
|
2380
2465
|
});
|
|
2381
2466
|
await stopAudio();
|
|
2382
2467
|
clearApiCache();
|
|
@@ -2391,7 +2476,7 @@ var RedactoNoticeConsent = ({
|
|
|
2391
2476
|
} finally {
|
|
2392
2477
|
setIsSubmitting(false);
|
|
2393
2478
|
}
|
|
2394
|
-
}, [content, accessToken, baseUrl, ledgerBaseUrl, applicationId, selectedPurposes, selectedDataElements, selectedLanguage, stopAudio, onAccept, onError]);
|
|
2479
|
+
}, [content, accessToken, sandboxParams, baseUrl, ledgerBaseUrl, applicationId, selectedPurposes, selectedDataElements, selectedLanguage, selfDeclaredAdult, stopAudio, onAccept, onError]);
|
|
2395
2480
|
const handleDecline = (0, import_react2.useCallback)(() => {
|
|
2396
2481
|
stopAudio();
|
|
2397
2482
|
stopPolling();
|
|
@@ -2993,14 +3078,16 @@ var fetchConsentContent2 = async ({
|
|
|
2993
3078
|
org_uuid,
|
|
2994
3079
|
workspace_uuid,
|
|
2995
3080
|
notice_uuid,
|
|
3081
|
+
accessToken,
|
|
2996
3082
|
baseUrl,
|
|
2997
3083
|
language = "en",
|
|
2998
3084
|
specific_uuid,
|
|
2999
3085
|
signal
|
|
3000
3086
|
}) => {
|
|
3001
3087
|
const apiBaseUrl = baseUrl || DEFAULT_CONSENT_API_BASE_URL;
|
|
3088
|
+
const noticesUrl = `${apiBaseUrl}/public/organisations/${org_uuid}/workspaces/${workspace_uuid}/notices`;
|
|
3002
3089
|
const url = new URL(
|
|
3003
|
-
`${
|
|
3090
|
+
accessToken ? `${noticesUrl}/${notice_uuid}` : `${noticesUrl}/get-notice/${notice_uuid}`
|
|
3004
3091
|
);
|
|
3005
3092
|
if (specific_uuid) {
|
|
3006
3093
|
url.searchParams.append("specific_uuid", specific_uuid);
|
|
@@ -3009,7 +3096,8 @@ var fetchConsentContent2 = async ({
|
|
|
3009
3096
|
method: "GET",
|
|
3010
3097
|
headers: {
|
|
3011
3098
|
"Content-Type": "application/json",
|
|
3012
|
-
"Accept-Language": language
|
|
3099
|
+
"Accept-Language": language,
|
|
3100
|
+
...accessToken ? { Authorization: `Bearer ${accessToken}` } : {}
|
|
3013
3101
|
},
|
|
3014
3102
|
signal
|
|
3015
3103
|
});
|
|
@@ -3450,11 +3538,13 @@ var RedactoConsentInlineComponent = ({
|
|
|
3450
3538
|
const fetchNotice = (0, import_react3.useCallback)(async (signal) => {
|
|
3451
3539
|
setIsLoading(true);
|
|
3452
3540
|
setFetchError(null);
|
|
3541
|
+
setHasAlreadyConsented(false);
|
|
3453
3542
|
try {
|
|
3454
3543
|
const consentContentData = await fetchConsentContent2({
|
|
3455
3544
|
org_uuid,
|
|
3456
3545
|
workspace_uuid,
|
|
3457
3546
|
notice_uuid,
|
|
3547
|
+
accessToken,
|
|
3458
3548
|
baseUrl,
|
|
3459
3549
|
language,
|
|
3460
3550
|
specific_uuid: applicationId,
|
|
@@ -3504,7 +3594,7 @@ var RedactoConsentInlineComponent = ({
|
|
|
3504
3594
|
setIsLoading(false);
|
|
3505
3595
|
}
|
|
3506
3596
|
}
|
|
3507
|
-
}, [org_uuid, workspace_uuid, notice_uuid, baseUrl, language, applicationId, onError]);
|
|
3597
|
+
}, [org_uuid, workspace_uuid, notice_uuid, accessToken, baseUrl, language, applicationId, onError]);
|
|
3508
3598
|
(0, import_react3.useEffect)(() => {
|
|
3509
3599
|
const controller = new AbortController();
|
|
3510
3600
|
void fetchNotice(controller.signal);
|