@redacto.io/consent-sdk-react 10.0.0-beta.8 → 10.0.0-beta.9

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.
Files changed (30) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/{chunk-6A665OPR.mjs → chunk-OGL6OC3A.mjs} +4 -0
  3. package/dist/index.d.mts +29 -3
  4. package/dist/index.d.ts +29 -3
  5. package/dist/index.js +162 -56
  6. package/dist/index.mjs +161 -57
  7. package/dist/privacy-center.d.mts +51 -10
  8. package/dist/privacy-center.d.ts +51 -10
  9. package/dist/privacy-center.js +250 -70
  10. package/dist/privacy-center.mjs +249 -71
  11. package/package.json +1 -1
  12. package/src/RedactoNoticeConsent/RedactoNoticeConsent.tsx +55 -5
  13. package/src/RedactoNoticeConsent/api/index.ts +78 -48
  14. package/src/RedactoNoticeConsent/api/sandbox.ts +150 -0
  15. package/src/RedactoNoticeConsent/api/types.ts +57 -11
  16. package/src/RedactoNoticeConsent/types.ts +28 -2
  17. package/src/RedactoPrivacyCenter/RedactoPrivacyCenter.tsx +37 -2
  18. package/src/RedactoPrivacyCenter/api/client.ts +116 -24
  19. package/src/RedactoPrivacyCenter/api/fetcher.ts +24 -9
  20. package/src/RedactoPrivacyCenter/components/Form.tsx +55 -30
  21. package/src/RedactoPrivacyCenter/components/SelectUserGate.tsx +8 -0
  22. package/src/RedactoPrivacyCenter/components/groupHelpers.ts +42 -6
  23. package/src/RedactoPrivacyCenter/context/AuthContext.tsx +131 -39
  24. package/src/RedactoPrivacyCenter/context/types.ts +38 -0
  25. package/src/RedactoPrivacyCenter/lib/constants.ts +12 -5
  26. package/src/RedactoPrivacyCenter/lib/sandbox.ts +104 -0
  27. package/src/RedactoPrivacyCenter/lib/types.ts +20 -0
  28. package/src/RedactoPrivacyCenter/lib/utils.ts +15 -0
  29. package/src/shared/sandbox.ts +6 -0
  30. package/tests/Form.test.tsx +142 -5
@@ -8164,6 +8164,36 @@ var useOrganization = () => {
8164
8164
  // src/RedactoPrivacyCenter/context/DataAvailabilityContext.tsx
8165
8165
  var import_react5 = require("react");
8166
8166
 
8167
+ // src/shared/sandbox.ts
8168
+ var SANDBOX_TOKEN_HEADER = "X-Consent-Token";
8169
+
8170
+ // src/RedactoPrivacyCenter/lib/sandbox.ts
8171
+ var sandboxConfig = null;
8172
+ var setSandboxConfig = (config) => {
8173
+ sandboxConfig = config;
8174
+ };
8175
+ var getSandboxConfig = () => sandboxConfig;
8176
+ var isSandboxMode = () => sandboxConfig !== null;
8177
+ var sandboxAuthHeaders = () => {
8178
+ if (!sandboxConfig) {
8179
+ return null;
8180
+ }
8181
+ return {
8182
+ [SANDBOX_TOKEN_HEADER]: sandboxConfig.token
8183
+ };
8184
+ };
8185
+ var sandboxBodyIdentity = () => {
8186
+ if (!sandboxConfig) {
8187
+ return null;
8188
+ }
8189
+ if (sandboxConfig.ucic) {
8190
+ return { org_user_id: sandboxConfig.ucic };
8191
+ }
8192
+ return sandboxConfig.subject.includes("@") ? { primary_email: sandboxConfig.subject } : { primary_mobile: sandboxConfig.subject };
8193
+ };
8194
+ var sandboxQueryIdentity = () => sandboxBodyIdentity();
8195
+ var sandboxContact = () => sandboxConfig ? sandboxConfig.ucic || sandboxConfig.subject : null;
8196
+
8167
8197
  // src/RedactoPrivacyCenter/api/fetcher.ts
8168
8198
  var ApiError = class _ApiError extends Error {
8169
8199
  constructor(message, options = {}) {
@@ -8210,11 +8240,18 @@ async function apiFetch(url, options = {}) {
8210
8240
  }
8211
8241
  }
8212
8242
  if (getAuthToken) {
8213
- const token = await getAuthToken();
8214
- if (token) {
8215
- const trimmedToken = token.trim();
8216
- requestHeaders.set("X-Auth-Token", trimmedToken);
8217
- requestHeaders.set("x-auth-token", trimmedToken);
8243
+ const sandboxHeaders = sandboxAuthHeaders();
8244
+ if (sandboxHeaders) {
8245
+ Object.entries(sandboxHeaders).forEach(([key, value]) => {
8246
+ requestHeaders.set(key, value);
8247
+ });
8248
+ } else {
8249
+ const token = await getAuthToken();
8250
+ if (token) {
8251
+ const trimmedToken = token.trim();
8252
+ requestHeaders.set("X-Auth-Token", trimmedToken);
8253
+ requestHeaders.set("x-auth-token", trimmedToken);
8254
+ }
8218
8255
  }
8219
8256
  }
8220
8257
  const fetchOptionsFinal = {
@@ -8953,6 +8990,7 @@ var MAX_REFRESH_BACKOFF_MS = 3e5;
8953
8990
  var REFRESH_TOKEN_STORAGE_KEY = "redacto_pc_refresh_token";
8954
8991
  var LEGACY_REFRESH_TOKEN_COOKIE = "refresh_token";
8955
8992
  var FORM_PICKER_GROUP_LIMIT = 100;
8993
+ var LEGACY_PRODUCT_GROUP_UUID = "__legacy_flat_purposes__";
8956
8994
  var POLL_INTERVAL = 3e4;
8957
8995
  var NOTIFICATION_PAGE_SIZE = 10;
8958
8996
  var NOTIFICATION_DROPDOWN_LIMIT = 5;
@@ -9180,6 +9218,9 @@ var getInitialState = (slug) => {
9180
9218
  };
9181
9219
  var checkAndRefreshAuth = async (expectedSlug, organizationId, workspaceId, consentClient) => {
9182
9220
  if (typeof window === "undefined") return false;
9221
+ if (getSandboxConfig()) {
9222
+ return true;
9223
+ }
9183
9224
  const accessToken = sessionStorage.getItem("access_token");
9184
9225
  const email = sessionStorage.getItem("email");
9185
9226
  const orgSlug = sessionStorage.getItem("pc_org_slug");
@@ -9290,6 +9331,10 @@ var signOutPrivacyCenter = () => {
9290
9331
  };
9291
9332
  var ensureValidToken = async (organizationId, workspaceId, slug, authContext, consentClient) => {
9292
9333
  if (typeof window === "undefined") return null;
9334
+ const sandbox = getSandboxConfig();
9335
+ if (sandbox) {
9336
+ return sandbox.token;
9337
+ }
9293
9338
  const accessToken = (authContext == null ? void 0 : authContext.accessToken) || sessionStorage.getItem("access_token");
9294
9339
  if (accessToken && typeof accessToken === "string" && accessToken.trim() !== "" && !isJwtExpired(accessToken, TOKEN_EXPIRY_BUFFER_SECONDS)) {
9295
9340
  return accessToken;
@@ -9865,6 +9910,45 @@ function useCurrentLanguage() {
9865
9910
  var import_react3 = require("react");
9866
9911
  var import_jsx_runtime3 = require("react/jsx-runtime");
9867
9912
  var AuthContext = (0, import_react3.createContext)(null);
9913
+ var seedSessionStorage = (data) => {
9914
+ if (typeof window === "undefined") {
9915
+ return;
9916
+ }
9917
+ if (data.accessToken) sessionStorage.setItem("access_token", data.accessToken);
9918
+ if (data.orgId) sessionStorage.setItem("pc_org_id", data.orgId);
9919
+ if (data.workspaceId) sessionStorage.setItem("pc_workspace_id", data.workspaceId);
9920
+ if (data.slug) sessionStorage.setItem("pc_org_slug", data.slug);
9921
+ if (data.contact) sessionStorage.setItem("email", data.contact);
9922
+ };
9923
+ var configureSandbox = (props) => {
9924
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
9925
+ const token = (_a = props.token) == null ? void 0 : _a.trim();
9926
+ if (!token) {
9927
+ setSandboxConfig(null);
9928
+ return false;
9929
+ }
9930
+ const organisationUuid = (_c = (_b = props.organisationUuid) == null ? void 0 : _b.trim()) != null ? _c : "";
9931
+ const workspaceUuid = (_e = (_d = props.workspaceUuid) == null ? void 0 : _d.trim()) != null ? _e : "";
9932
+ const ucic = (_g = (_f = props.sandboxUcic) == null ? void 0 : _f.trim()) != null ? _g : "";
9933
+ const subject = (_i = (_h = props.sandboxSubject) == null ? void 0 : _h.trim()) != null ? _i : "";
9934
+ const slug = (_k = (_j = props.slug) == null ? void 0 : _j.trim()) != null ? _k : "";
9935
+ setSandboxConfig({
9936
+ token,
9937
+ ucic: ucic || void 0,
9938
+ subject,
9939
+ organisationUuid,
9940
+ workspaceUuid,
9941
+ slug
9942
+ });
9943
+ seedSessionStorage({
9944
+ accessToken: token,
9945
+ orgId: organisationUuid,
9946
+ workspaceId: workspaceUuid,
9947
+ slug,
9948
+ contact: ucic || subject
9949
+ });
9950
+ return true;
9951
+ };
9868
9952
  var syncJwtDataToSessionStorage = (accessToken) => {
9869
9953
  if (typeof window === "undefined") return;
9870
9954
  const decoded = decodeJwtToken(accessToken);
@@ -9872,44 +9956,49 @@ var syncJwtDataToSessionStorage = (accessToken) => {
9872
9956
  return;
9873
9957
  }
9874
9958
  const contact = resolveContactFromJwt(decoded) || sessionStorage.getItem("email") || (typeof localStorage !== "undefined" ? localStorage.getItem("userEmail") : null);
9875
- if (contact && typeof contact === "string") {
9876
- sessionStorage.setItem("email", contact);
9877
- }
9878
- const orgUuid = decoded.organisation_uuid;
9879
- if (orgUuid && typeof orgUuid === "string") {
9880
- sessionStorage.setItem("pc_org_id", orgUuid);
9881
- }
9882
- const workspaceUuid = decoded.workspace_uuid;
9883
- if (workspaceUuid && typeof workspaceUuid === "string") {
9884
- sessionStorage.setItem("pc_workspace_id", workspaceUuid);
9885
- }
9886
- const orgSlug = decoded.organisation_slug;
9887
- if (orgSlug && typeof orgSlug === "string") {
9888
- sessionStorage.setItem("pc_org_slug", orgSlug);
9889
- }
9959
+ seedSessionStorage({
9960
+ orgId: typeof decoded.organisation_uuid === "string" ? decoded.organisation_uuid : void 0,
9961
+ workspaceId: typeof decoded.workspace_uuid === "string" ? decoded.workspace_uuid : void 0,
9962
+ slug: typeof decoded.organisation_slug === "string" ? decoded.organisation_slug : void 0,
9963
+ contact: typeof contact === "string" ? contact : void 0
9964
+ });
9890
9965
  };
9891
- var AuthProvider = ({
9892
- children,
9893
- accessToken: initialAccessToken,
9894
- refreshToken: initialRefreshToken,
9895
- onError
9896
- }) => {
9966
+ var AuthProvider = (props) => {
9967
+ const {
9968
+ children,
9969
+ accessToken: initialAccessToken,
9970
+ refreshToken: initialRefreshToken,
9971
+ token: sandboxToken,
9972
+ sandboxUcic,
9973
+ sandboxSubject,
9974
+ organisationUuid,
9975
+ workspaceUuid,
9976
+ slug,
9977
+ onError
9978
+ } = props;
9979
+ const [sandboxActive] = (0, import_react3.useState)(() => configureSandbox(props));
9897
9980
  const [accessToken, setAccessToken] = (0, import_react3.useState)(() => {
9981
+ if (sandboxActive) {
9982
+ return sandboxToken != null ? sandboxToken : "";
9983
+ }
9898
9984
  if (initialAccessToken && typeof initialAccessToken === "string" && initialAccessToken.trim() !== "") {
9899
9985
  if (typeof window !== "undefined") {
9900
9986
  sessionStorage.setItem("access_token", initialAccessToken);
9901
9987
  syncJwtDataToSessionStorage(initialAccessToken);
9902
9988
  }
9903
9989
  }
9904
- return initialAccessToken;
9990
+ return initialAccessToken != null ? initialAccessToken : "";
9905
9991
  });
9906
9992
  const [refreshToken, setRefreshToken] = (0, import_react3.useState)(() => {
9993
+ if (sandboxActive) {
9994
+ return "";
9995
+ }
9907
9996
  if (initialRefreshToken && typeof initialRefreshToken === "string" && initialRefreshToken.trim() !== "") {
9908
9997
  if (typeof window !== "undefined") {
9909
9998
  setRefreshTokenCookie(initialRefreshToken);
9910
9999
  }
9911
10000
  }
9912
- return initialRefreshToken;
10001
+ return initialRefreshToken != null ? initialRefreshToken : "";
9913
10002
  });
9914
10003
  const [sessionExpired, setSessionExpired] = (0, import_react3.useState)(false);
9915
10004
  const markSessionExpired = (0, import_react3.useCallback)(() => setSessionExpired(true), []);
@@ -9918,6 +10007,9 @@ var AuthProvider = ({
9918
10007
  return () => setSessionExpiredListener(null);
9919
10008
  }, [markSessionExpired]);
9920
10009
  (0, import_react3.useEffect)(() => {
10010
+ if (sandboxActive) {
10011
+ return;
10012
+ }
9921
10013
  if (initialAccessToken && typeof initialAccessToken === "string" && initialAccessToken.trim() !== "") {
9922
10014
  setAccessToken(initialAccessToken);
9923
10015
  if (typeof window !== "undefined") {
@@ -9925,8 +10017,11 @@ var AuthProvider = ({
9925
10017
  syncJwtDataToSessionStorage(initialAccessToken);
9926
10018
  }
9927
10019
  }
9928
- }, [initialAccessToken]);
10020
+ }, [initialAccessToken, sandboxActive]);
9929
10021
  (0, import_react3.useEffect)(() => {
10022
+ if (sandboxActive) {
10023
+ return;
10024
+ }
9930
10025
  if (initialRefreshToken && typeof initialRefreshToken === "string" && initialRefreshToken.trim() !== "") {
9931
10026
  setRefreshToken(initialRefreshToken);
9932
10027
  setSessionExpired(false);
@@ -9934,7 +10029,14 @@ var AuthProvider = ({
9934
10029
  setRefreshTokenCookie(initialRefreshToken);
9935
10030
  }
9936
10031
  }
9937
- }, [initialRefreshToken]);
10032
+ }, [initialRefreshToken, sandboxActive]);
10033
+ (0, import_react3.useEffect)(() => {
10034
+ if (!sandboxActive) {
10035
+ return;
10036
+ }
10037
+ configureSandbox(props);
10038
+ return () => setSandboxConfig(null);
10039
+ }, [sandboxActive, sandboxToken, sandboxUcic, sandboxSubject, organisationUuid, workspaceUuid, slug]);
9938
10040
  const updateTokens = (0, import_react3.useCallback)((newAccessToken, newRefreshToken) => {
9939
10041
  setAccessToken(newAccessToken);
9940
10042
  if (newRefreshToken) {
@@ -9971,7 +10073,8 @@ var import_react4 = require("react");
9971
10073
 
9972
10074
  // src/RedactoPrivacyCenter/api/client.ts
9973
10075
  function createConsentClient(baseUrl, ledgerBaseUrl) {
9974
- const useLedger = Boolean(ledgerBaseUrl);
10076
+ const ledgerConfigured = Boolean(ledgerBaseUrl);
10077
+ const useLedger = () => ledgerConfigured && !isSandboxMode();
9975
10078
  const ledgerBase = (ledgerBaseUrl != null ? ledgerBaseUrl : "").replace(/\/$/, "");
9976
10079
  async function privacyCenterApiFetch(url, options) {
9977
10080
  const { authToken, getAuthToken, headers = {}, ...fetchOptions } = options;
@@ -9996,11 +10099,18 @@ function createConsentClient(baseUrl, ledgerBaseUrl) {
9996
10099
  );
9997
10100
  }
9998
10101
  }
9999
- const token = authToken || (getAuthToken ? await getAuthToken() : null);
10000
- if (token) {
10001
- const trimmedToken = token.trim();
10002
- const bearerToken = trimmedToken.startsWith("Bearer ") ? trimmedToken : `Bearer ${trimmedToken}`;
10003
- requestHeaders.set("Authorization", bearerToken);
10102
+ const sandboxHeaders = sandboxAuthHeaders();
10103
+ if (sandboxHeaders) {
10104
+ Object.entries(sandboxHeaders).forEach(([key, value]) => {
10105
+ requestHeaders.set(key, value);
10106
+ });
10107
+ } else {
10108
+ const token = authToken || (getAuthToken ? await getAuthToken() : null);
10109
+ if (token) {
10110
+ const trimmedToken = token.trim();
10111
+ const bearerToken = trimmedToken.startsWith("Bearer ") ? trimmedToken : `Bearer ${trimmedToken}`;
10112
+ requestHeaders.set("Authorization", bearerToken);
10113
+ }
10004
10114
  }
10005
10115
  const fetchOptionsFinal = {
10006
10116
  ...fetchOptions,
@@ -10066,7 +10176,7 @@ function createConsentClient(baseUrl, ledgerBaseUrl) {
10066
10176
  return `${baseUrl}/organisations/${baseRequest.organisationUuid}/workspaces/${baseRequest.workspaceUuid}/dsar/privacy-center${path}`;
10067
10177
  }
10068
10178
  function ledgerUrl(baseRequest, path) {
10069
- if (!useLedger) {
10179
+ if (!useLedger()) {
10070
10180
  throw new Error("ledgerUrl called without a configured ledgerBaseUrl");
10071
10181
  }
10072
10182
  return `${ledgerBase}/public/organisations/${baseRequest.organisationUuid}/workspaces/${baseRequest.workspaceUuid}${path}`;
@@ -10075,11 +10185,30 @@ function createConsentClient(baseUrl, ledgerBaseUrl) {
10075
10185
  return privacyCenterUrl(baseRequest, `/cases/${caseUuid}${path}`);
10076
10186
  }
10077
10187
  function notificationUrl(baseRequest, path = "") {
10078
- return privacyCenterUrl(baseRequest, `/notifications${path}`);
10188
+ const identitySuffix = sandboxIdentitySuffix();
10189
+ if (!identitySuffix) {
10190
+ return privacyCenterUrl(baseRequest, `/notifications${path}`);
10191
+ }
10192
+ const separator = path.includes("?") ? `&${identitySuffix.slice(1)}` : identitySuffix;
10193
+ return privacyCenterUrl(baseRequest, `/notifications${path}${separator}`);
10079
10194
  }
10080
10195
  function resolveAuthToken(authToken, baseRequest) {
10081
10196
  return authToken || baseRequest.authToken;
10082
10197
  }
10198
+ function appendSandboxIdentity(queryParams) {
10199
+ const identity = sandboxQueryIdentity();
10200
+ if (identity) {
10201
+ Object.entries(identity).forEach(([key, value]) => {
10202
+ queryParams.append(key, value);
10203
+ });
10204
+ }
10205
+ }
10206
+ function sandboxIdentitySuffix() {
10207
+ const queryParams = new URLSearchParams();
10208
+ appendSandboxIdentity(queryParams);
10209
+ const queryString = queryParams.toString();
10210
+ return queryString ? `?${queryString}` : "";
10211
+ }
10083
10212
  return {
10084
10213
  /**
10085
10214
  * Get form data (privacy center)
@@ -10111,18 +10240,20 @@ function createConsentClient(baseUrl, ledgerBaseUrl) {
10111
10240
  async createCaseRequest(baseRequest, payload, authToken, options) {
10112
10241
  const url = privacyCenterUrl(baseRequest, "/case");
10113
10242
  const { useSessionAuth = false, getAuthToken, ...fetchOptions } = options || {};
10243
+ const contact = sandboxContact();
10244
+ const requestPayload = contact && payload && typeof payload === "object" ? { ...payload, contact } : payload;
10114
10245
  if (useSessionAuth) {
10115
10246
  return apiFetch(url, {
10116
10247
  ...fetchOptions,
10117
10248
  method: "POST",
10118
- body: JSON.stringify(payload),
10249
+ body: JSON.stringify(requestPayload),
10119
10250
  getAuthToken
10120
10251
  });
10121
10252
  }
10122
10253
  return privacyCenterApiFetch(url, {
10123
10254
  ...fetchOptions,
10124
10255
  method: "POST",
10125
- body: JSON.stringify(payload),
10256
+ body: JSON.stringify(requestPayload),
10126
10257
  authToken: resolveAuthToken(authToken, baseRequest)
10127
10258
  });
10128
10259
  },
@@ -10203,9 +10334,10 @@ function createConsentClient(baseUrl, ledgerBaseUrl) {
10203
10334
  if (params.status) queryParams.append("status", params.status);
10204
10335
  if (params.product_uuid) queryParams.append("product_uuid", params.product_uuid);
10205
10336
  if (params.language) queryParams.append("language", params.language);
10337
+ appendSandboxIdentity(queryParams);
10206
10338
  const queryString = queryParams.toString();
10207
10339
  const suffix = `/user-consents${queryString ? `?${queryString}` : ""}`;
10208
- const url = useLedger ? ledgerUrl(baseRequest, suffix) : privacyCenterUrl(baseRequest, suffix);
10340
+ const url = useLedger() ? ledgerUrl(baseRequest, suffix) : privacyCenterUrl(baseRequest, suffix);
10209
10341
  return privacyCenterApiFetch(url, {
10210
10342
  ...options,
10211
10343
  method: "GET",
@@ -10225,9 +10357,10 @@ function createConsentClient(baseUrl, ledgerBaseUrl) {
10225
10357
  if (params.search) queryParams.append("search", params.search);
10226
10358
  if (params.language) queryParams.append("language", params.language);
10227
10359
  if (params.nominator_uuid) queryParams.append("nominator_uuid", params.nominator_uuid);
10360
+ appendSandboxIdentity(queryParams);
10228
10361
  const queryString = queryParams.toString();
10229
10362
  const suffix = `/user-consents/${productUuid}/purposes${queryString ? `?${queryString}` : ""}`;
10230
- const url = useLedger ? ledgerUrl(baseRequest, suffix) : privacyCenterUrl(baseRequest, suffix);
10363
+ const url = useLedger() ? ledgerUrl(baseRequest, suffix) : privacyCenterUrl(baseRequest, suffix);
10231
10364
  return privacyCenterApiFetch(url, {
10232
10365
  ...options,
10233
10366
  method: "GET",
@@ -10251,7 +10384,7 @@ function createConsentClient(baseUrl, ledgerBaseUrl) {
10251
10384
  * used with its `{ purpose_uuid, contact, ... }` payload.
10252
10385
  */
10253
10386
  async manageConsent(baseRequest, purposeId, contact, status, authToken, options, nominatorContact, dataElementUuids, productUuid, noticeUuid, dataElements, language) {
10254
- if (!useLedger) {
10387
+ if (!useLedger()) {
10255
10388
  const url2 = privacyCenterUrl(baseRequest, `/manage-consent?status=${status}`);
10256
10389
  const body2 = { purpose_uuid: purposeId, contact };
10257
10390
  if (nominatorContact) {
@@ -10319,6 +10452,7 @@ function createConsentClient(baseUrl, ledgerBaseUrl) {
10319
10452
  if (offset !== void 0) queryParams.append("offset", offset.toString());
10320
10453
  if (limit !== void 0) queryParams.append("limit", limit.toString());
10321
10454
  if (language) queryParams.append("language", language);
10455
+ appendSandboxIdentity(queryParams);
10322
10456
  const queryString = queryParams.toString();
10323
10457
  const url = privacyCenterUrl(baseRequest, `/activities${queryString ? `?${queryString}` : ""}`);
10324
10458
  return privacyCenterApiFetch(url, {
@@ -10368,7 +10502,7 @@ function createConsentClient(baseUrl, ledgerBaseUrl) {
10368
10502
  if (params.language) queryParams.append("language", params.language);
10369
10503
  const queryString = queryParams.toString();
10370
10504
  const receiptsSuffix = `/receipts${queryString ? `?${queryString}` : ""}`;
10371
- const url = useLedger ? ledgerUrl(baseRequest, receiptsSuffix) : privacyCenterUrl(baseRequest, receiptsSuffix);
10505
+ const url = useLedger() ? ledgerUrl(baseRequest, receiptsSuffix) : privacyCenterUrl(baseRequest, receiptsSuffix);
10372
10506
  return privacyCenterApiFetch(url, {
10373
10507
  ...options,
10374
10508
  method: "GET",
@@ -10383,11 +10517,16 @@ function createConsentClient(baseUrl, ledgerBaseUrl) {
10383
10517
  * and the Authorization header must be sent (anchor navigation wouldn't carry it).
10384
10518
  */
10385
10519
  async getReceiptPdf(baseRequest, receiptUuid, authToken) {
10386
- const url = useLedger ? ledgerUrl(baseRequest, `/receipts/${receiptUuid}/download`) : privacyCenterUrl(baseRequest, `/receipts/${receiptUuid}/pdf`);
10520
+ const url = useLedger() ? ledgerUrl(baseRequest, `/receipts/${receiptUuid}/download`) : privacyCenterUrl(baseRequest, `/receipts/${receiptUuid}/pdf`);
10387
10521
  const token = resolveAuthToken(authToken, baseRequest);
10388
10522
  const requestHeaders = new Headers();
10389
10523
  requestHeaders.set("Accept", "application/pdf");
10390
- if (token) {
10524
+ const sandboxHeaders = sandboxAuthHeaders();
10525
+ if (sandboxHeaders) {
10526
+ Object.entries(sandboxHeaders).forEach(([key, value]) => {
10527
+ requestHeaders.set(key, value);
10528
+ });
10529
+ } else if (token) {
10391
10530
  const trimmedToken = token.trim();
10392
10531
  requestHeaders.set(
10393
10532
  "Authorization",
@@ -10418,6 +10557,7 @@ function createConsentClient(baseUrl, ledgerBaseUrl) {
10418
10557
  if (offset !== void 0) queryParams.append("offset", offset.toString());
10419
10558
  if (limit !== void 0) queryParams.append("limit", limit.toString());
10420
10559
  if (language) queryParams.append("language", language);
10560
+ appendSandboxIdentity(queryParams);
10421
10561
  const queryString = queryParams.toString();
10422
10562
  const url = privacyCenterUrl(baseRequest, `/cases?${queryString}`);
10423
10563
  return privacyCenterApiFetch(url, {
@@ -10430,7 +10570,7 @@ function createConsentClient(baseUrl, ledgerBaseUrl) {
10430
10570
  * Get messages for a case (privacy center)
10431
10571
  */
10432
10572
  async getCaseMessages(baseRequest, caseUuid, authToken) {
10433
- const url = caseUrl(baseRequest, caseUuid, "/messages");
10573
+ const url = caseUrl(baseRequest, caseUuid, `/messages${sandboxIdentitySuffix()}`);
10434
10574
  return privacyCenterApiFetch(url, {
10435
10575
  authToken: resolveAuthToken(authToken, baseRequest)
10436
10576
  });
@@ -10439,7 +10579,7 @@ function createConsentClient(baseUrl, ledgerBaseUrl) {
10439
10579
  * Send a message on a case (privacy center)
10440
10580
  */
10441
10581
  async sendCaseMessage(baseRequest, caseUuid, body, documentUuids, authToken) {
10442
- const url = caseUrl(baseRequest, caseUuid, "/messages");
10582
+ const url = caseUrl(baseRequest, caseUuid, `/messages${sandboxIdentitySuffix()}`);
10443
10583
  return privacyCenterApiFetch(url, {
10444
10584
  method: "POST",
10445
10585
  body: JSON.stringify({ body, document_uuids: documentUuids }),
@@ -10450,7 +10590,7 @@ function createConsentClient(baseUrl, ledgerBaseUrl) {
10450
10590
  * Upload a document on a case (multipart/form-data, privacy center)
10451
10591
  */
10452
10592
  async uploadCaseDocument(baseRequest, caseUuid, file, authToken) {
10453
- const url = caseUrl(baseRequest, caseUuid, "/upload-document");
10593
+ const url = caseUrl(baseRequest, caseUuid, `/upload-document${sandboxIdentitySuffix()}`);
10454
10594
  const formData = new FormData();
10455
10595
  formData.append("file", file, file.name);
10456
10596
  formData.append("payload", JSON.stringify({ metadata: null }));
@@ -15239,6 +15379,10 @@ var SelectUserGate = ({ children }) => {
15239
15379
  const tokenOrgUserId = ((_d = (_c = decodeJwtToken(accessToken)) == null ? void 0 : _c.user_data) == null ? void 0 : _d.org_user_id) || "";
15240
15380
  (0, import_react32.useEffect)(() => {
15241
15381
  let cancelled = false;
15382
+ if (isSandboxMode()) {
15383
+ setPhase("resolved");
15384
+ return;
15385
+ }
15242
15386
  if (!organizationId || !workspaceId || !accessToken) {
15243
15387
  setPhase("resolved");
15244
15388
  return;
@@ -18982,23 +19126,36 @@ var consentGroupToFormProductGroup = (group) => {
18982
19126
  };
18983
19127
  };
18984
19128
  var purposeItemToFormPurpose = (purpose) => {
18985
- var _a, _b;
19129
+ var _a, _b, _c, _d, _e, _f;
18986
19130
  return {
18987
- uuid: purpose.purpose_uuid,
18988
- purpose_uuid: purpose.purpose_uuid,
19131
+ // The ledger keys purposes as `purpose_uuid`; the legacy Python
19132
+ // user-consents payload keys some of them as `uuid`. Accept either so the
19133
+ // picker and the submitted `purpose_uuid` resolve on both backends.
19134
+ uuid: (_b = (_a = purpose.purpose_uuid) != null ? _a : purpose.uuid) != null ? _b : "",
19135
+ purpose_uuid: (_d = (_c = purpose.purpose_uuid) != null ? _c : purpose.uuid) != null ? _d : "",
18989
19136
  name: purpose.name,
18990
- description: (_a = purpose.description) != null ? _a : "",
19137
+ description: (_e = purpose.description) != null ? _e : "",
18991
19138
  industries: "",
18992
19139
  selected: false,
18993
19140
  given_consent: false,
18994
19141
  status: purpose.status,
18995
19142
  validity: null,
18996
19143
  enabled: true,
18997
- data_elements: ((_b = purpose.data_elements) != null ? _b : []).map(
19144
+ data_elements: ((_f = purpose.data_elements) != null ? _f : []).map(
18998
19145
  consentDataElementToFormDataElement
18999
19146
  )
19000
19147
  };
19001
19148
  };
19149
+ var legacyFlatGroup = (form, label) => {
19150
+ var _a;
19151
+ return {
19152
+ product_uuid: LEGACY_PRODUCT_GROUP_UUID,
19153
+ product_name: label,
19154
+ product_description: null,
19155
+ nominator: null,
19156
+ purposes: ((_a = form.purposes) != null ? _a : []).map((wrapper) => wrapper == null ? void 0 : wrapper.purpose).filter((purpose) => Boolean(purpose))
19157
+ };
19158
+ };
19002
19159
  var consentDataElementToFormDataElement = (element) => ({
19003
19160
  uuid: element.uuid,
19004
19161
  name: element.name,
@@ -20155,7 +20312,7 @@ function Form({
20155
20312
  const [isSubmitted, setIsSubmitted] = (0, import_react44.useState)(false);
20156
20313
  const { t } = (0, import_react_i18next35.useTranslation)();
20157
20314
  const { accessToken, refreshToken, onError, updateTokens } = useAuth();
20158
- const { consentClient, baseUrl, ledgerBaseUrl } = useBaseUrl();
20315
+ const { consentClient, baseUrl } = useBaseUrl();
20159
20316
  const organizationId = organization == null ? void 0 : organization.uuid;
20160
20317
  const workspaceId = (_a = organization == null ? void 0 : organization.workspaces[0]) == null ? void 0 : _a.uuid;
20161
20318
  const authContext = (0, import_react44.useMemo)(() => ({
@@ -20217,8 +20374,19 @@ function Form({
20217
20374
  if (!data) {
20218
20375
  return [];
20219
20376
  }
20220
- return [...(_a2 = data.direct_groups) != null ? _a2 : [], ...(_b2 = data.nominated_groups) != null ? _b2 : []];
20221
- }, [data]);
20377
+ const groups = [
20378
+ ...(_a2 = data.direct_groups) != null ? _a2 : [],
20379
+ ...(_b2 = data.nominated_groups) != null ? _b2 : []
20380
+ ];
20381
+ if (groups.length > 0) {
20382
+ return groups;
20383
+ }
20384
+ const flatGroup = legacyFlatGroup(data, t("yourData"));
20385
+ if (buildGroupPurposes(flatGroup).length === 0) {
20386
+ return [];
20387
+ }
20388
+ return [flatGroup];
20389
+ }, [data, t]);
20222
20390
  const skipProductStep = allGroups.length === 1;
20223
20391
  const selectedGroup = (0, import_react44.useMemo)(() => {
20224
20392
  var _a2, _b2;
@@ -20236,10 +20404,10 @@ function Form({
20236
20404
  },
20237
20405
  []
20238
20406
  );
20239
- const withLedgerPickerGroups = (0, import_react44.useCallback)(
20407
+ const withUserConsentPickerGroups = (0, import_react44.useCallback)(
20240
20408
  async (form, language) => {
20241
20409
  var _a2, _b2;
20242
- if (!ledgerBaseUrl || isPopup || isCaseManagementContext || !organizationId || !workspaceId) {
20410
+ if (isPopup || isCaseManagementContext || !organizationId || !workspaceId) {
20243
20411
  return form;
20244
20412
  }
20245
20413
  const consents = await fetchUserConsents({
@@ -20254,19 +20422,18 @@ function Form({
20254
20422
  nominatedLimit: FORM_PICKER_GROUP_LIMIT,
20255
20423
  language
20256
20424
  });
20257
- if (!consents) {
20425
+ const direct = (_a2 = consents == null ? void 0 : consents.direct) != null ? _a2 : [];
20426
+ const nominated = (_b2 = consents == null ? void 0 : consents.nominated) != null ? _b2 : [];
20427
+ if (direct.length === 0 && nominated.length === 0) {
20258
20428
  return form;
20259
20429
  }
20260
20430
  return {
20261
20431
  ...form,
20262
- direct_groups: ((_a2 = consents.direct) != null ? _a2 : []).map(consentGroupToFormProductGroup),
20263
- nominated_groups: ((_b2 = consents.nominated) != null ? _b2 : []).map(
20264
- consentGroupToFormProductGroup
20265
- )
20432
+ direct_groups: direct.map(consentGroupToFormProductGroup),
20433
+ nominated_groups: nominated.map(consentGroupToFormProductGroup)
20266
20434
  };
20267
20435
  },
20268
20436
  [
20269
- ledgerBaseUrl,
20270
20437
  isPopup,
20271
20438
  isCaseManagementContext,
20272
20439
  organizationId,
@@ -20303,7 +20470,7 @@ function Form({
20303
20470
  toast.info(t("translationNotAvailable"));
20304
20471
  return;
20305
20472
  }
20306
- setData(await withLedgerPickerGroups(translatedFormData, langValue));
20473
+ setData(await withUserConsentPickerGroups(translatedFormData, langValue));
20307
20474
  if (translatedFormData.grievance_options) {
20308
20475
  const currentGrievanceSelections = { ...selectedGrievances };
20309
20476
  setGrievanceOptions(translatedFormData.grievance_options);
@@ -20319,7 +20486,7 @@ function Form({
20319
20486
  } finally {
20320
20487
  setIsTranslating(false);
20321
20488
  }
20322
- }, [organizationId, workspaceId, data, formData.contact, isPopup, isCaseManagementContext, authContext, consentClient, selectedGrievances, t, withLedgerPickerGroups]);
20489
+ }, [organizationId, workspaceId, data, formData.contact, isPopup, isCaseManagementContext, authContext, consentClient, selectedGrievances, t, withUserConsentPickerGroups]);
20323
20490
  (0, import_react44.useEffect)(() => {
20324
20491
  if (!skipProductStep) {
20325
20492
  setSelectedProductKey(null);
@@ -20425,7 +20592,7 @@ function Form({
20425
20592
  console.warn("No purposes with data elements found in API response");
20426
20593
  }
20427
20594
  }
20428
- const pickerData = await withLedgerPickerGroups(
20595
+ const pickerData = await withUserConsentPickerGroups(
20429
20596
  displayData,
20430
20597
  langParam || void 0
20431
20598
  );
@@ -20449,7 +20616,7 @@ function Form({
20449
20616
  }
20450
20617
  };
20451
20618
  void initializePrivacyCenterForm();
20452
- }, [organizationId, workspaceId, isPopup, authContext, consentClient, withLedgerPickerGroups]);
20619
+ }, [organizationId, workspaceId, isPopup, authContext, consentClient, withUserConsentPickerGroups]);
20453
20620
  const getEnglishDataElementName = (0, import_react44.useCallback)((translatedName) => {
20454
20621
  var _a2, _b2, _c2;
20455
20622
  if (!((_a2 = englishDataRef.current) == null ? void 0 : _a2.purposes)) {
@@ -20511,7 +20678,8 @@ function Form({
20511
20678
  return;
20512
20679
  }
20513
20680
  const isProductScoped = isProductScopedRequestType(requestType);
20514
- const anchorGroup = isProductScoped ? selectedGroup : null;
20681
+ const isLegacyFlatSelection = (selectedGroup == null ? void 0 : selectedGroup.product_uuid) === LEGACY_PRODUCT_GROUP_UUID;
20682
+ const anchorGroup = isProductScoped && !isLegacyFlatSelection ? selectedGroup : null;
20515
20683
  const requestDetails = {
20516
20684
  purposes: [],
20517
20685
  correction_data: [],
@@ -27967,6 +28135,12 @@ function RedactoPrivacyCenter({
27967
28135
  slug,
27968
28136
  accessToken,
27969
28137
  refreshToken,
28138
+ token,
28139
+ email,
28140
+ mobile,
28141
+ ucic,
28142
+ organisationUuid,
28143
+ workspaceUuid,
27970
28144
  onError,
27971
28145
  initialPage = "consent-manager",
27972
28146
  onBack
@@ -27976,6 +28150,12 @@ function RedactoPrivacyCenter({
27976
28150
  {
27977
28151
  accessToken,
27978
28152
  refreshToken,
28153
+ token,
28154
+ sandboxUcic: ucic,
28155
+ sandboxSubject: email || mobile,
28156
+ organisationUuid,
28157
+ workspaceUuid,
28158
+ slug,
27979
28159
  onError,
27980
28160
  children: /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(NavigationProvider, { initialPage, children: /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(PageChromeProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(PrivacyCenterLayout, { slug, onBack, children: /* @__PURE__ */ (0, import_jsx_runtime92.jsx)(PrivacyCenterHomePage, {}) }) }) })
27981
28161
  }