@redacto.io/consent-sdk-react-native 5.0.0-beta.6 → 5.0.0-beta.7
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 +136 -49
- package/dist/index.mjs +135 -50
- package/dist/privacy-center.d.mts +46 -4
- package/dist/privacy-center.d.ts +46 -4
- package/dist/privacy-center.js +207 -39
- package/dist/privacy-center.mjs +206 -40
- 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
|
|
192
|
+
if (!noticeId || !validate_against) {
|
|
193
|
+
throw new Error("noticeId is required");
|
|
132
194
|
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
throw new Error("Invalid access token");
|
|
136
|
-
}
|
|
137
|
-
const { organisation_uuid: ORGANISATION_UUID, workspace_uuid: WORKSPACE_UUID } = decodedToken;
|
|
138
|
-
if (!ORGANISATION_UUID || !WORKSPACE_UUID) {
|
|
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
|
|
269
|
+
if (!noticeUuid || !Array.isArray(purposes)) {
|
|
270
|
+
throw new Error("noticeUuid and purposes array are required");
|
|
206
271
|
}
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
throw new Error("Invalid access token");
|
|
272
|
+
if (!accessToken && !sandboxParams.token) {
|
|
273
|
+
throw new Error("accessToken or token is required");
|
|
210
274
|
}
|
|
211
|
-
const {
|
|
212
|
-
|
|
213
|
-
throw new Error("Invalid token: missing organization or workspace UUID");
|
|
214
|
-
}
|
|
215
|
-
const apiBaseUrl = ledgerBaseUrl || baseUrl || DEFAULT_CONSENT_API_BASE_URL;
|
|
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
|
);
|
|
@@ -274,26 +336,27 @@ var fetchTTSAudioUrls = async ({
|
|
|
274
336
|
baseUrl,
|
|
275
337
|
noticeUuid,
|
|
276
338
|
language,
|
|
277
|
-
signal
|
|
339
|
+
signal,
|
|
340
|
+
...sandboxParams
|
|
278
341
|
}) => {
|
|
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");
|
|
342
|
+
if (!accessToken && !sandboxParams.token || !noticeUuid || !language) {
|
|
343
|
+
throw new Error("accessToken (or token), noticeUuid, and language are required");
|
|
289
344
|
}
|
|
345
|
+
const { organisationUuid: ORGANISATION_UUID, workspaceUuid: WORKSPACE_UUID, sandbox } = resolveRequestAuth(accessToken, sandboxParams, decodeTokenSafely);
|
|
290
346
|
const apiBaseUrl = baseUrl || DEFAULT_CONSENT_API_BASE_URL;
|
|
291
347
|
const normalizedLanguage = language === "en" || language === "EN" ? "English" : language;
|
|
292
|
-
const url =
|
|
293
|
-
|
|
348
|
+
const url = new URL(
|
|
349
|
+
`${apiBaseUrl}/public/organisations/${ORGANISATION_UUID}/workspaces/${WORKSPACE_UUID}/notices/${noticeUuid}/audio/${encodeURIComponent(normalizedLanguage)}`
|
|
350
|
+
);
|
|
351
|
+
if (sandbox) {
|
|
352
|
+
for (const [key, value] of Object.entries(sandboxQueryIdentity(sandbox))) {
|
|
353
|
+
url.searchParams.append(key, value);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
const response = await fetch(url.toString(), {
|
|
294
357
|
method: "GET",
|
|
295
358
|
headers: {
|
|
296
|
-
|
|
359
|
+
...buildAuthHeaders(accessToken, sandbox),
|
|
297
360
|
Accept: "application/json",
|
|
298
361
|
"Content-Type": "application/json"
|
|
299
362
|
},
|
|
@@ -1800,6 +1863,12 @@ var RedactoNoticeConsent = ({
|
|
|
1800
1863
|
noticeId,
|
|
1801
1864
|
accessToken,
|
|
1802
1865
|
refreshToken: _refreshToken,
|
|
1866
|
+
token,
|
|
1867
|
+
email,
|
|
1868
|
+
mobile,
|
|
1869
|
+
ucic,
|
|
1870
|
+
organisationUuid,
|
|
1871
|
+
workspaceUuid,
|
|
1803
1872
|
baseUrl,
|
|
1804
1873
|
ledgerBaseUrl,
|
|
1805
1874
|
settings,
|
|
@@ -1815,6 +1884,16 @@ var RedactoNoticeConsent = ({
|
|
|
1815
1884
|
}) => {
|
|
1816
1885
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u;
|
|
1817
1886
|
const { isMobile } = useResponsive();
|
|
1887
|
+
const sandboxParams = (0, import_react2.useMemo)(
|
|
1888
|
+
() => ({
|
|
1889
|
+
token,
|
|
1890
|
+
sandboxUcic: ucic,
|
|
1891
|
+
sandboxSubject: email || mobile,
|
|
1892
|
+
organisationUuid,
|
|
1893
|
+
workspaceUuid
|
|
1894
|
+
}),
|
|
1895
|
+
[token, ucic, email, mobile, organisationUuid, workspaceUuid]
|
|
1896
|
+
);
|
|
1818
1897
|
const [content, setContent] = (0, import_react2.useState)(null);
|
|
1819
1898
|
const [isLoading, setIsLoading] = (0, import_react2.useState)(true);
|
|
1820
1899
|
const [isSubmitting, setIsSubmitting] = (0, import_react2.useState)(false);
|
|
@@ -1877,12 +1956,13 @@ var RedactoNoticeConsent = ({
|
|
|
1877
1956
|
validate_against: validateAgainst,
|
|
1878
1957
|
include_fully_consented_data: includeFullyConsentedData,
|
|
1879
1958
|
specific_uuid: applicationId,
|
|
1880
|
-
signal: abortControllerRef.current.signal
|
|
1959
|
+
signal: abortControllerRef.current.signal,
|
|
1960
|
+
...sandboxParams
|
|
1881
1961
|
});
|
|
1882
1962
|
const activeConfig2 = data.detail.active_config;
|
|
1883
1963
|
let purposeSelections = data.detail.purpose_selections;
|
|
1884
1964
|
let reconsentRequired = data.detail.reconsent_required || false;
|
|
1885
|
-
if (ledgerBaseUrl && !applicationId) {
|
|
1965
|
+
if (accessToken && ledgerBaseUrl && !applicationId && !token) {
|
|
1886
1966
|
const ledgerStatus = await fetchNoticeConsentStatus({
|
|
1887
1967
|
accessToken,
|
|
1888
1968
|
ledgerBaseUrl,
|
|
@@ -1959,7 +2039,7 @@ var RedactoNoticeConsent = ({
|
|
|
1959
2039
|
} finally {
|
|
1960
2040
|
setIsLoading(false);
|
|
1961
2041
|
}
|
|
1962
|
-
}, [noticeId, accessToken, baseUrl, ledgerBaseUrl, validateAgainst, includeFullyConsentedData, applicationId, onAccept, onError]);
|
|
2042
|
+
}, [noticeId, accessToken, sandboxParams, token, baseUrl, ledgerBaseUrl, validateAgainst, includeFullyConsentedData, applicationId, onAccept, onError]);
|
|
1963
2043
|
(0, import_react2.useEffect)(() => {
|
|
1964
2044
|
hasBootstrappedLanguageRef.current = false;
|
|
1965
2045
|
}, [noticeId, accessToken]);
|
|
@@ -1981,7 +2061,8 @@ var RedactoNoticeConsent = ({
|
|
|
1981
2061
|
accessToken,
|
|
1982
2062
|
baseUrl,
|
|
1983
2063
|
noticeUuid: content.detail.active_config.notice_uuid,
|
|
1984
|
-
language: selectedLanguage
|
|
2064
|
+
language: selectedLanguage,
|
|
2065
|
+
...sandboxParams
|
|
1985
2066
|
});
|
|
1986
2067
|
const urls = {
|
|
1987
2068
|
notice_text: data.detail.notice_text_audio_url,
|
|
@@ -2035,7 +2116,7 @@ var RedactoNoticeConsent = ({
|
|
|
2035
2116
|
setTtsAudioUrls({});
|
|
2036
2117
|
setIsTTSAvailable(false);
|
|
2037
2118
|
}
|
|
2038
|
-
}, [content, accessToken, baseUrl, selectedLanguage]);
|
|
2119
|
+
}, [content, accessToken, sandboxParams, baseUrl, selectedLanguage]);
|
|
2039
2120
|
const clearPlaybackWatchers = (0, import_react2.useCallback)(() => {
|
|
2040
2121
|
if (playbackSubscriptionRef.current) {
|
|
2041
2122
|
playbackSubscriptionRef.current.remove();
|
|
@@ -2376,7 +2457,8 @@ var RedactoNoticeConsent = ({
|
|
|
2376
2457
|
meta_data: applicationId ? { specific_uuid: applicationId } : void 0,
|
|
2377
2458
|
guardianVerificationReference: verificationReferenceRef.current || void 0,
|
|
2378
2459
|
selfDeclaredAdult: selfDeclaredAdult || void 0,
|
|
2379
|
-
language: selectedLanguage
|
|
2460
|
+
language: selectedLanguage,
|
|
2461
|
+
...sandboxParams
|
|
2380
2462
|
});
|
|
2381
2463
|
await stopAudio();
|
|
2382
2464
|
clearApiCache();
|
|
@@ -2391,7 +2473,7 @@ var RedactoNoticeConsent = ({
|
|
|
2391
2473
|
} finally {
|
|
2392
2474
|
setIsSubmitting(false);
|
|
2393
2475
|
}
|
|
2394
|
-
}, [content, accessToken, baseUrl, ledgerBaseUrl, applicationId, selectedPurposes, selectedDataElements, selectedLanguage, stopAudio, onAccept, onError]);
|
|
2476
|
+
}, [content, accessToken, sandboxParams, baseUrl, ledgerBaseUrl, applicationId, selectedPurposes, selectedDataElements, selectedLanguage, selfDeclaredAdult, stopAudio, onAccept, onError]);
|
|
2395
2477
|
const handleDecline = (0, import_react2.useCallback)(() => {
|
|
2396
2478
|
stopAudio();
|
|
2397
2479
|
stopPolling();
|
|
@@ -2993,14 +3075,16 @@ var fetchConsentContent2 = async ({
|
|
|
2993
3075
|
org_uuid,
|
|
2994
3076
|
workspace_uuid,
|
|
2995
3077
|
notice_uuid,
|
|
3078
|
+
accessToken,
|
|
2996
3079
|
baseUrl,
|
|
2997
3080
|
language = "en",
|
|
2998
3081
|
specific_uuid,
|
|
2999
3082
|
signal
|
|
3000
3083
|
}) => {
|
|
3001
3084
|
const apiBaseUrl = baseUrl || DEFAULT_CONSENT_API_BASE_URL;
|
|
3085
|
+
const noticesUrl = `${apiBaseUrl}/public/organisations/${org_uuid}/workspaces/${workspace_uuid}/notices`;
|
|
3002
3086
|
const url = new URL(
|
|
3003
|
-
`${
|
|
3087
|
+
accessToken ? `${noticesUrl}/${notice_uuid}` : `${noticesUrl}/get-notice/${notice_uuid}`
|
|
3004
3088
|
);
|
|
3005
3089
|
if (specific_uuid) {
|
|
3006
3090
|
url.searchParams.append("specific_uuid", specific_uuid);
|
|
@@ -3009,7 +3093,8 @@ var fetchConsentContent2 = async ({
|
|
|
3009
3093
|
method: "GET",
|
|
3010
3094
|
headers: {
|
|
3011
3095
|
"Content-Type": "application/json",
|
|
3012
|
-
"Accept-Language": language
|
|
3096
|
+
"Accept-Language": language,
|
|
3097
|
+
...accessToken ? { Authorization: `Bearer ${accessToken}` } : {}
|
|
3013
3098
|
},
|
|
3014
3099
|
signal
|
|
3015
3100
|
});
|
|
@@ -3450,11 +3535,13 @@ var RedactoConsentInlineComponent = ({
|
|
|
3450
3535
|
const fetchNotice = (0, import_react3.useCallback)(async (signal) => {
|
|
3451
3536
|
setIsLoading(true);
|
|
3452
3537
|
setFetchError(null);
|
|
3538
|
+
setHasAlreadyConsented(false);
|
|
3453
3539
|
try {
|
|
3454
3540
|
const consentContentData = await fetchConsentContent2({
|
|
3455
3541
|
org_uuid,
|
|
3456
3542
|
workspace_uuid,
|
|
3457
3543
|
notice_uuid,
|
|
3544
|
+
accessToken,
|
|
3458
3545
|
baseUrl,
|
|
3459
3546
|
language,
|
|
3460
3547
|
specific_uuid: applicationId,
|
|
@@ -3504,7 +3591,7 @@ var RedactoConsentInlineComponent = ({
|
|
|
3504
3591
|
setIsLoading(false);
|
|
3505
3592
|
}
|
|
3506
3593
|
}
|
|
3507
|
-
}, [org_uuid, workspace_uuid, notice_uuid, baseUrl, language, applicationId, onError]);
|
|
3594
|
+
}, [org_uuid, workspace_uuid, notice_uuid, accessToken, baseUrl, language, applicationId, onError]);
|
|
3508
3595
|
(0, import_react3.useEffect)(() => {
|
|
3509
3596
|
const controller = new AbortController();
|
|
3510
3597
|
void fetchNotice(controller.signal);
|