@ianua/ianus-dataverse-react-fluentui8 1.0.7 → 1.0.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.
package/dist/index.d.ts CHANGED
@@ -16,11 +16,10 @@ interface ILicenseClaims {
16
16
  prd: string;
17
17
  sub: string;
18
18
  env: IEnvironmentIdentifier[];
19
- required_roles: string[];
20
19
  iat: number;
21
20
  nbf: number;
22
21
  exp?: number;
23
- custom: Record<string, any>;
22
+ cus: Record<string, any>;
24
23
  iss_meta: IMeta;
25
24
  aud_meta: IMeta;
26
25
  pub_meta: IMeta;
@@ -56,13 +55,48 @@ type LicenseValidationSuccess = {
56
55
  };
57
56
  type LicenseValidationResult = LicenseValidationError | LicenseValidationSuccess;
58
57
 
58
+ type EnvironmentType = "entra" | "dataverse";
59
59
  interface IIanusGuardProps {
60
+ /**
61
+ * The external publisher Guid found on the publisher's Ianus Guard portal form
62
+ */
60
63
  publisherId: string;
64
+ /**
65
+ * The external product Guid found on the product's Ianus Guard portal form
66
+ */
61
67
  productId: string;
68
+ /**
69
+ * One or multiple public keys, found on the product's Ianus Guard portal form or your own generated public key
70
+ */
62
71
  publicKeys: string[];
63
- environmentType: string;
72
+ /**
73
+ * Type of environment you're currently evaluating against
74
+ */
75
+ environmentType: EnvironmentType;
76
+ /**
77
+ * Identifier for the current environment. For entra this is the Tenant ID, for dataverse this is the Organization ID. For dataverse you can pass the WebApi object to fetch it automatically
78
+ */
64
79
  environmentIdentifier: string | ComponentFramework.WebApi;
80
+ /**
81
+ * Data provider for retrieving licenses in the current environment. Either a dataset or the WebApi object
82
+ */
65
83
  dataProvider: ComponentFramework.WebApi | ComponentFramework.PropertyTypes.DataSet;
84
+ /**
85
+ * Data provider for retrieving licenses in the current environment. Only needed in canvas apps. PCFs can query offline data using the primary (webAPI) data provider.
86
+ */
87
+ offlineDataProvider?: ComponentFramework.PropertyTypes.DataSet;
88
+ /**
89
+ * When using user-based licensing, usage permission is derived by having read permission to a defined 'usage-entity'. Pass the result of the license check here, if read is allowed, pass true, otherwise false.
90
+ * Pass null while you're fetching the permission.
91
+ * For canvas apps, use the DataSourceInfo PowerFX function, for PCFs use pcfContext.utils.getEntityMetadata for loading the metadata followed by pcfContext.utils.hasEntityPrivilege for getting the permission result.
92
+ */
93
+ usagePermission?: boolean | null;
94
+ /**
95
+ * Optionally pass a callback which is called when a license validation result was generated
96
+ *
97
+ * @param result The result of this validation run
98
+ * @returns Returned data will not be processed in any way
99
+ */
66
100
  onLicenseValidated?: (result: LicenseValidationResult) => unknown;
67
101
  }
68
102
  declare const isWebApi: (dataProvider: ComponentFramework.WebApi | ComponentFramework.PropertyTypes.DataSet | string) => dataProvider is ComponentFramework.WebApi;
@@ -76,10 +110,14 @@ type Action = {
76
110
  } | {
77
111
  type: "setLicenseDialogVisible";
78
112
  payload: boolean;
113
+ } | {
114
+ type: "setDebugDialogVisible";
115
+ payload: boolean;
79
116
  };
80
117
  type IanusLicenseStateProps = {
81
118
  license?: DataverseLicenseValidationResult;
82
119
  licenseDialogVisible?: boolean;
120
+ debugDialogVisible?: boolean;
83
121
  };
84
122
  type IanusLicenseDispatch = (action: Action) => void;
85
123
  declare const IanusLicenseDispatch: React.Context<IanusLicenseDispatch | undefined>;
@@ -96,6 +134,7 @@ interface ILicenseDialogProps {
96
134
  publisherId: string;
97
135
  productId: string;
98
136
  dataProvider: ComponentFramework.WebApi | ComponentFramework.PropertyTypes.DataSet;
137
+ offlineDataProvider?: ComponentFramework.PropertyTypes.DataSet;
99
138
  onSubmit: () => void;
100
139
  onCancel: () => void;
101
140
  }
@@ -106,4 +145,4 @@ declare const removeCurlyBrackets: (input: string | undefined | null) => string
106
145
  declare const base64url_decode: (value: string) => ArrayBuffer;
107
146
  declare const validateLicense: (publisherId: string, productId: string, environmentType: string, environmentIdentifier: string, publicKeys: string[], licenseKey: string | undefined) => Promise<LicenseValidationResult>;
108
147
 
109
- export { type DataverseLicenseValidationError, type DataverseLicenseValidationResult, type DataverseLicenseValidationSuccess, type IEnvironmentIdentifier, type IIanusGuardProps, type IIanusProviderProps, type ILicenseClaims, type ILicenseDialogProps, type IMeta, IanusGuard, IanusLicenseDispatch, type IanusLicenseStateProps, IanusLicenseStateProvider, IanusProvider, LicenseDialog, type LicenseValidationError, type LicenseValidationResult, type LicenseValidationSuccess, acquireLicenses, base64url_decode, isDataset, isWebApi, removeCurlyBrackets, useLicenseContext, useLicenseDispatch, useLicenseState, validateLicense };
148
+ export { type DataverseLicenseValidationError, type DataverseLicenseValidationResult, type DataverseLicenseValidationSuccess, type EnvironmentType, type IEnvironmentIdentifier, type IIanusGuardProps, type IIanusProviderProps, type ILicenseClaims, type ILicenseDialogProps, type IMeta, IanusGuard, IanusLicenseDispatch, type IanusLicenseStateProps, IanusLicenseStateProvider, IanusProvider, LicenseDialog, type LicenseValidationError, type LicenseValidationResult, type LicenseValidationSuccess, acquireLicenses, base64url_decode, isDataset, isWebApi, removeCurlyBrackets, useLicenseContext, useLicenseDispatch, useLicenseState, validateLicense };
package/dist/index.js CHANGED
@@ -84,7 +84,7 @@ __export(index_exports, {
84
84
  module.exports = __toCommonJS(index_exports);
85
85
 
86
86
  // src/IanusGuard.tsx
87
- var React3 = __toESM(require("react"));
87
+ var React4 = __toESM(require("react"));
88
88
  var import_MessageBar = require("@fluentui/react/lib/MessageBar");
89
89
  var import_Button = require("@fluentui/react/lib/Button");
90
90
  var import_Spinner = require("@fluentui/react/lib/Spinner");
@@ -242,6 +242,9 @@ function stateReducer(state, action) {
242
242
  case "setLicenseDialogVisible": {
243
243
  return __spreadProps(__spreadValues({}, state), { licenseDialogVisible: action.payload });
244
244
  }
245
+ case "setDebugDialogVisible": {
246
+ return __spreadProps(__spreadValues({}, state), { debugDialogVisible: action.payload });
247
+ }
245
248
  }
246
249
  }
247
250
  var IanusLicenseState = React.createContext(void 0);
@@ -277,8 +280,8 @@ var dialogContentProps = {
277
280
  type: import_react.DialogType.largeHeader,
278
281
  title: "License"
279
282
  };
280
- var LicenseDialog = ({ publisherId, productId, dataProvider, onCancel, onSubmit }) => {
281
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v;
283
+ var LicenseDialog = ({ publisherId, productId, dataProvider, offlineDataProvider, onCancel, onSubmit }) => {
284
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x;
282
285
  const [licenseState, licenseDispatch] = useLicenseContext();
283
286
  const [submitBlocked, setSubmitBlocked] = React2.useState(true);
284
287
  const [licenseKeyInput, setLicenseKeyInput] = React2.useState((_a = licenseState.license) == null ? void 0 : _a.licenseKey);
@@ -287,13 +290,15 @@ var LicenseDialog = ({ publisherId, productId, dataProvider, onCancel, onSubmit
287
290
  React2.useEffect(() => {
288
291
  (() => __async(null, null, function* () {
289
292
  if (!licenseId) {
290
- const licenses = yield acquireLicenses(publisherId, productId, dataProvider);
293
+ const onlineLicenses = yield acquireLicenses(publisherId, productId, dataProvider);
294
+ const offlineLicenses = offlineDataProvider != null ? yield acquireLicenses(publisherId, productId, offlineDataProvider) : [];
295
+ const licenses = onlineLicenses.length ? onlineLicenses : offlineLicenses;
291
296
  if (licenses.length > 0) {
292
297
  setLicenseId(licenses[0].ian_licenseid);
293
298
  }
294
299
  }
295
300
  }))();
296
- }, [dataProvider, licenseId, productId, publisherId]);
301
+ }, [dataProvider, licenseId, offlineDataProvider, productId, publisherId]);
297
302
  const tryToExtractDisplayNames = (licenseKey) => {
298
303
  var _a2, _b2;
299
304
  if (!licenseKey) {
@@ -320,7 +325,7 @@ var LicenseDialog = ({ publisherId, productId, dataProvider, onCancel, onSubmit
320
325
  }
321
326
  };
322
327
  const onSubmitClick = () => __async(null, null, function* () {
323
- var _a2, _b2;
328
+ var _a2, _b2, _c2;
324
329
  try {
325
330
  setSubmitBlocked(true);
326
331
  const displayNames = tryToExtractDisplayNames(licenseKeyInput);
@@ -341,6 +346,14 @@ var LicenseDialog = ({ publisherId, productId, dataProvider, onCancel, onSubmit
341
346
  yield dataProvider.records[licenseId].setValue("ian_name", name);
342
347
  yield dataProvider.records[licenseId].setValue("ian_key", licenseKeyInput);
343
348
  yield dataProvider.records[licenseId].save();
349
+ dataProvider.refresh();
350
+ } else {
351
+ const newLicense = yield dataProvider.newRecord();
352
+ yield newLicense.setValue("ian_name", name);
353
+ yield newLicense.setValue("ian_identifier", identifier);
354
+ yield newLicense.setValue("ian_key", licenseKeyInput);
355
+ yield newLicense.save();
356
+ dataProvider.refresh();
344
357
  }
345
358
  }
346
359
  } else {
@@ -359,11 +372,12 @@ var LicenseDialog = ({ publisherId, productId, dataProvider, onCancel, onSubmit
359
372
  yield newLicense.setValue("ian_identifier", identifier);
360
373
  yield newLicense.setValue("ian_key", licenseKeyInput);
361
374
  yield newLicense.save();
375
+ dataProvider.refresh();
362
376
  }
363
377
  }
364
378
  onSubmit();
365
379
  } catch (e) {
366
- setError(e == null ? void 0 : e.message);
380
+ setError((_c2 = e == null ? void 0 : e.message) != null ? _c2 : JSON.stringify(e));
367
381
  } finally {
368
382
  setSubmitBlocked(false);
369
383
  }
@@ -393,31 +407,105 @@ var LicenseDialog = ({ publisherId, productId, dataProvider, onCancel, onSubmit
393
407
  setLicenseKeyInput(v != null ? v : "");
394
408
  setSubmitBlocked(false);
395
409
  }, required: true }),
396
- !!((_c = licenseState.license) == null ? void 0 : _c.isValid) && /* @__PURE__ */ React2.createElement(import_react.Text, null, /* @__PURE__ */ React2.createElement("br", null), /* @__PURE__ */ React2.createElement("h3", null, "License Information"), /* @__PURE__ */ React2.createElement("p", null, /* @__PURE__ */ React2.createElement("span", { style: { fontWeight: "bold" } }, "License Publisher: "), " ", /* @__PURE__ */ React2.createElement("span", { title: (_e = (_d = licenseState.license) == null ? void 0 : _d.claims) == null ? void 0 : _e.pub }, (_h = (_g = (_f = licenseState.license) == null ? void 0 : _f.claims) == null ? void 0 : _g.pub_meta) == null ? void 0 : _h.name)), /* @__PURE__ */ React2.createElement("p", null, /* @__PURE__ */ React2.createElement("span", { style: { fontWeight: "bold" } }, "Licensed Product: "), " ", /* @__PURE__ */ React2.createElement("span", { title: (_i = licenseState.license) == null ? void 0 : _i.claims.aud }, (_l = (_k = (_j = licenseState.license) == null ? void 0 : _j.claims) == null ? void 0 : _k.prd_meta) == null ? void 0 : _l.name)), /* @__PURE__ */ React2.createElement("p", null, /* @__PURE__ */ React2.createElement("span", { style: { fontWeight: "bold" } }, "Licensed Customer: "), " ", /* @__PURE__ */ React2.createElement("span", { title: (_m = licenseState.license) == null ? void 0 : _m.claims.sub }, (_p = (_o = (_n = licenseState.license) == null ? void 0 : _n.claims) == null ? void 0 : _o.sub_meta) == null ? void 0 : _p.name)), /* @__PURE__ */ React2.createElement("p", null, /* @__PURE__ */ React2.createElement("span", { style: { fontWeight: "bold" } }, "Licensed Dataverse Environment: "), " ", /* @__PURE__ */ React2.createElement("span", null, (_s = (_r = (_q = licenseState.license) == null ? void 0 : _q.claims) == null ? void 0 : _r.env) == null ? void 0 : _s.map((e) => `${e.identifier} (${e.name})`).join(", "))), /* @__PURE__ */ React2.createElement("p", null, /* @__PURE__ */ React2.createElement("span", { style: { fontWeight: "bold" } }, "License expires after: "), " ", /* @__PURE__ */ React2.createElement("span", null, !((_u = (_t = licenseState.license) == null ? void 0 : _t.claims) == null ? void 0 : _u.exp) ? "Never" : new Date(((_v = licenseState.license) == null ? void 0 : _v.claims.exp) * 1e3).toISOString()))),
410
+ !!((_c = licenseState.license) == null ? void 0 : _c.isValid) && /* @__PURE__ */ React2.createElement(import_react.Text, null, /* @__PURE__ */ React2.createElement("br", null), /* @__PURE__ */ React2.createElement("h3", null, "License Information"), /* @__PURE__ */ React2.createElement("p", null, /* @__PURE__ */ React2.createElement("span", { style: { fontWeight: "bold" } }, "License Publisher: "), " ", /* @__PURE__ */ React2.createElement("span", { title: (_e = (_d = licenseState.license) == null ? void 0 : _d.claims) == null ? void 0 : _e.pub }, (_h = (_g = (_f = licenseState.license) == null ? void 0 : _f.claims) == null ? void 0 : _g.pub_meta) == null ? void 0 : _h.name)), /* @__PURE__ */ React2.createElement("p", null, /* @__PURE__ */ React2.createElement("span", { style: { fontWeight: "bold" } }, "Licensed Product: "), " ", /* @__PURE__ */ React2.createElement("span", { title: (_i = licenseState.license) == null ? void 0 : _i.claims.aud }, (_l = (_k = (_j = licenseState.license) == null ? void 0 : _j.claims) == null ? void 0 : _k.prd_meta) == null ? void 0 : _l.name)), /* @__PURE__ */ React2.createElement("p", null, /* @__PURE__ */ React2.createElement("span", { style: { fontWeight: "bold" } }, "Licensed Customer: "), " ", /* @__PURE__ */ React2.createElement("span", { title: (_m = licenseState.license) == null ? void 0 : _m.claims.sub }, (_p = (_o = (_n = licenseState.license) == null ? void 0 : _n.claims) == null ? void 0 : _o.sub_meta) == null ? void 0 : _p.name)), /* @__PURE__ */ React2.createElement("p", null, /* @__PURE__ */ React2.createElement("span", { style: { fontWeight: "bold" } }, "Licensed Dataverse Environment: "), " ", /* @__PURE__ */ React2.createElement("span", null, (_s = (_r = (_q = licenseState.license) == null ? void 0 : _q.claims) == null ? void 0 : _r.env) == null ? void 0 : _s.map((e) => `${e.identifier} (${e.name})`).join(", "))), /* @__PURE__ */ React2.createElement("p", null, /* @__PURE__ */ React2.createElement("span", { style: { fontWeight: "bold" } }, "License expires after: "), " ", /* @__PURE__ */ React2.createElement("span", null, !((_u = (_t = licenseState.license) == null ? void 0 : _t.claims) == null ? void 0 : _u.exp) ? "Never" : new Date(((_v = licenseState.license) == null ? void 0 : _v.claims.exp) * 1e3).toISOString())), ((_x = (_w = licenseState.license) == null ? void 0 : _w.claims) == null ? void 0 : _x.cus) && /* @__PURE__ */ React2.createElement("p", null, /* @__PURE__ */ React2.createElement("span", { style: { fontWeight: "bold" } }, "Custom claims: "), " ", /* @__PURE__ */ React2.createElement("span", null, JSON.stringify(licenseState.license.claims.cus)))),
397
411
  /* @__PURE__ */ React2.createElement(import_react.DialogFooter, null, /* @__PURE__ */ React2.createElement(import_react.PrimaryButton, { onClick: onSubmitClick, text: "Submit", disabled: !licenseKeyInput || submitBlocked }), /* @__PURE__ */ React2.createElement(import_react.DefaultButton, { onClick: onCancel, text: "Cancel" }))
398
412
  );
399
413
  };
400
414
 
415
+ // src/DebugDialog.tsx
416
+ var React3 = __toESM(require("react"));
417
+ var import_react2 = require("@fluentui/react");
418
+ var modalProps2 = {
419
+ isBlocking: false,
420
+ styles: {
421
+ main: {
422
+ width: "80vw !important",
423
+ maxWidth: "80vw !important",
424
+ height: "auto",
425
+ maxHeight: "90vh",
426
+ overflowY: "auto",
427
+ overflowX: "auto"
428
+ }
429
+ }
430
+ };
431
+ var dialogContentProps2 = {
432
+ type: import_react2.DialogType.largeHeader,
433
+ title: "Debug"
434
+ };
435
+ var DebugDialog = ({ publisherId, productId, dataProvider, offlineDataProvider, onDismiss }) => {
436
+ const [licenseState, licenseDispatch] = useLicenseContext();
437
+ const licenseColumns = [
438
+ { key: "id", name: "Id", fieldName: "ian_licenseid", minWidth: 100, maxWidth: 200, isResizable: true },
439
+ { key: "name", name: "Name", fieldName: "ian_name", minWidth: 100, maxWidth: 200, isResizable: true },
440
+ { key: "identifier", name: "Identifier", fieldName: "ian_identifier", minWidth: 100, maxWidth: 200, isResizable: true },
441
+ { key: "key", name: "Key", fieldName: "ian_key", minWidth: 100, maxWidth: 200, isResizable: true }
442
+ ];
443
+ const mapRecordsToItems = React3.useCallback(
444
+ (dataset) => dataset.sortedRecordIds.map((id) => {
445
+ const record = dataset.records[id];
446
+ return {
447
+ ian_licenseid: record.getRecordId(),
448
+ ian_name: record.getValue("ian_name"),
449
+ ian_identifier: record.getValue("ian_identifier"),
450
+ ian_key: record.getValue("ian_key")
451
+ };
452
+ }),
453
+ []
454
+ );
455
+ return /* @__PURE__ */ React3.createElement(
456
+ import_react2.Dialog,
457
+ {
458
+ hidden: !(licenseState == null ? void 0 : licenseState.debugDialogVisible),
459
+ onDismiss,
460
+ dialogContentProps: dialogContentProps2,
461
+ modalProps: modalProps2
462
+ },
463
+ /* @__PURE__ */ React3.createElement("p", null, /* @__PURE__ */ React3.createElement(import_react2.Text, null, /* @__PURE__ */ React3.createElement("b", null, "Target license identifier:"), " ", publisherId, "_", productId), /* @__PURE__ */ React3.createElement("br", null), /* @__PURE__ */ React3.createElement("br", null), isDataset(dataProvider) && /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(import_react2.Text, null, /* @__PURE__ */ React3.createElement("b", null, "Licenses in data provider:"), " ", dataProvider.sortedRecordIds.length), /* @__PURE__ */ React3.createElement("br", null), /* @__PURE__ */ React3.createElement(
464
+ import_react2.DetailsList,
465
+ {
466
+ items: mapRecordsToItems(dataProvider),
467
+ columns: licenseColumns,
468
+ setKey: "dataProviderList",
469
+ layoutMode: import_react2.DetailsListLayoutMode.fixedColumns,
470
+ selectionMode: 0
471
+ }
472
+ ), /* @__PURE__ */ React3.createElement("br", null)), offlineDataProvider && isDataset(offlineDataProvider) && /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(import_react2.Text, null, /* @__PURE__ */ React3.createElement("b", null, "Licenses in offline data provider:"), " ", offlineDataProvider.sortedRecordIds.length), /* @__PURE__ */ React3.createElement("br", null), /* @__PURE__ */ React3.createElement(
473
+ import_react2.DetailsList,
474
+ {
475
+ items: mapRecordsToItems(offlineDataProvider),
476
+ columns: licenseColumns,
477
+ setKey: "offlineDataProviderList",
478
+ layoutMode: import_react2.DetailsListLayoutMode.fixedColumns,
479
+ selectionMode: 0
480
+ }
481
+ ), /* @__PURE__ */ React3.createElement("br", null))),
482
+ /* @__PURE__ */ React3.createElement(import_react2.DialogFooter, null, /* @__PURE__ */ React3.createElement(import_react2.PrimaryButton, { onClick: onDismiss, text: "Close" }))
483
+ );
484
+ };
485
+
401
486
  // src/IanusGuard.tsx
402
487
  var isWebApi = (dataProvider) => {
403
- return dataProvider.retrieveMultipleRecords !== void 0;
488
+ return (dataProvider == null ? void 0 : dataProvider.retrieveMultipleRecords) !== void 0;
404
489
  };
405
490
  var isDataset = (dataProvider) => {
406
- return dataProvider.records !== void 0;
491
+ return (dataProvider == null ? void 0 : dataProvider.sortedRecordIds) !== void 0;
407
492
  };
408
493
  var acquireLicenses = (publisherId, productId, dataProvider) => __async(null, null, function* () {
494
+ var _a;
409
495
  const licenseIdentifier = `${publisherId}_${productId}`;
410
496
  if (isWebApi(dataProvider)) {
411
497
  const response = yield dataProvider.retrieveMultipleRecords("ian_license", `?$filter=ian_identifier eq '${licenseIdentifier}' and statecode eq 0`);
412
498
  return response.entities;
413
499
  } else if (isDataset(dataProvider)) {
414
- if (dataProvider.records.length) {
415
- const record = dataProvider.records[0];
416
- if (record.getNamedReference().etn !== "ian_license") {
500
+ const recordValues = Object.values((_a = dataProvider.records) != null ? _a : {});
501
+ if (recordValues.length) {
502
+ const record = recordValues[0];
503
+ const recordReference = record.getNamedReference();
504
+ if (recordReference.etn && recordReference.etn !== "ian_license") {
417
505
  throw new Error("You need to pass the 'ian_license' entity as data source for LicenseDataset when using a dataset as value");
418
506
  }
419
507
  }
420
- return Object.values(dataProvider.records).filter((r) => r.getValue("ian_identifier") === licenseIdentifier).map((r) => ({ ian_licenseid: r.getValue("ian_licenseid"), ian_identifier: r.getValue("ian_identifier"), ian_key: r.getValue("ian_key") }));
508
+ return recordValues.filter((r) => r.getValue("ian_identifier") === licenseIdentifier).map((r) => ({ ian_licenseid: r.getValue("ian_licenseid"), ian_identifier: r.getValue("ian_identifier"), ian_key: r.getValue("ian_key") }));
421
509
  } else {
422
510
  throw new Error(`The 'dataProvider' prop must be either of type ComponentFramework.WebApi or ComponentFramework.PropertyTypes.Dataset. You passed '${typeof dataProvider}'.`);
423
511
  }
@@ -441,14 +529,10 @@ var fetchOrganizationIdFromWebApi = (webApi) => __async(null, null, function* ()
441
529
  const organization = results.entities[0];
442
530
  return organization.organizationid;
443
531
  });
444
- var IanusGuard = ({ publisherId, productId, publicKeys, environmentType, environmentIdentifier, dataProvider, onLicenseValidated, children }) => {
445
- var _a, _b, _c, _d;
532
+ var IanusGuard = ({ publisherId, productId, publicKeys, environmentType, environmentIdentifier, dataProvider, offlineDataProvider, usagePermission, onLicenseValidated, children }) => {
533
+ var _a, _b, _c, _d, _e;
446
534
  const [licenseState, licenseDispatch] = useLicenseContext();
447
- const onSettingsFinally = () => {
448
- licenseDispatch({ type: "setLicenseDialogVisible", payload: false });
449
- initLicenseValidation();
450
- };
451
- const runValidation = React3.useCallback(() => __async(null, null, function* () {
535
+ const runValidation = React4.useCallback(() => __async(null, null, function* () {
452
536
  try {
453
537
  if (!productId) {
454
538
  return {
@@ -464,7 +548,9 @@ var IanusGuard = ({ publisherId, productId, publicKeys, environmentType, environ
464
548
  reason: "No public key found, pass a valid public key as prop!"
465
549
  };
466
550
  }
467
- const licenses = yield acquireLicenses(publisherId, productId, dataProvider);
551
+ const onlineLicenses = yield acquireLicenses(publisherId, productId, dataProvider);
552
+ const offlineLicenses = offlineDataProvider != null ? yield acquireLicenses(publisherId, productId, offlineDataProvider) : [];
553
+ const licenses = onlineLicenses.length ? onlineLicenses : offlineLicenses;
468
554
  if (!licenses.length) {
469
555
  return {
470
556
  isValid: false,
@@ -476,7 +562,7 @@ var IanusGuard = ({ publisherId, productId, publicKeys, environmentType, environ
476
562
  return {
477
563
  isValid: false,
478
564
  isTerminalError: true,
479
- reason: `Multiple active licenses for '${publisherId}_${productId}' found, please make sure there is only one active license`
565
+ reason: `Multiple active licenses for '${publisherId}_${productId}' found, please make sure there is only one active license. If on mobile canvas app, check for data updates in the device status / connection dialog and then clear cache.`
480
566
  };
481
567
  }
482
568
  const licenseRecord = licenses[0];
@@ -493,14 +579,66 @@ var IanusGuard = ({ publisherId, productId, publicKeys, environmentType, environ
493
579
  reason: e == null ? void 0 : e.message
494
580
  };
495
581
  }
496
- }), [dataProvider, environmentIdentifier, environmentType, productId, publicKeys, publisherId]);
497
- const initLicenseValidation = React3.useCallback(() => __async(null, null, function* () {
582
+ }), [dataProvider, environmentIdentifier, environmentType, offlineDataProvider, productId, publicKeys, publisherId]);
583
+ const initLicenseValidation = React4.useCallback(() => __async(null, null, function* () {
498
584
  const result = yield runValidation();
499
585
  licenseDispatch({ type: "setLicense", payload: result });
500
586
  updateResultIfDefined(result, onLicenseValidated);
501
587
  }), [licenseDispatch, onLicenseValidated, runValidation]);
502
- React3.useEffect(() => {
503
- if (!isDataset(dataProvider) || !dataProvider.error && !dataProvider.loading && dataProvider.paging.totalResultCount >= 0) {
588
+ const onSettingsFinally = React4.useCallback(() => {
589
+ licenseDispatch({ type: "setLicenseDialogVisible", payload: false });
590
+ initLicenseValidation();
591
+ }, [initLicenseValidation, licenseDispatch]);
592
+ const onDebugFinally = React4.useCallback(() => {
593
+ licenseDispatch({ type: "setDebugDialogVisible", payload: false });
594
+ }, [licenseDispatch]);
595
+ const dataTotalResultCount = isDataset(dataProvider) ? dataProvider.paging.totalResultCount : void 0;
596
+ const dataIsLoading = isDataset(dataProvider) ? dataProvider.loading : void 0;
597
+ const dataHasError = isDataset(dataProvider) ? dataProvider.error : void 0;
598
+ const dataProviderState = React4.useMemo(() => {
599
+ if (!isDataset(dataProvider)) {
600
+ return "webapi";
601
+ } else {
602
+ return `dataset-${dataTotalResultCount}-${dataIsLoading}-${dataHasError}`;
603
+ }
604
+ }, [dataProvider, dataHasError, dataIsLoading, dataTotalResultCount]);
605
+ const offlineDataTotalResultCount = offlineDataProvider != null ? offlineDataProvider.paging.totalResultCount : void 0;
606
+ const offlineDataIsLoading = offlineDataProvider != null ? offlineDataProvider.loading : void 0;
607
+ const offlineDataHasError = offlineDataProvider != null ? offlineDataProvider.error : void 0;
608
+ const offlineDataProviderState = React4.useMemo(() => {
609
+ if (offlineDataProvider == null) {
610
+ return "unused";
611
+ } else {
612
+ return `dataset-${offlineDataTotalResultCount}-${offlineDataIsLoading}-${offlineDataHasError}`;
613
+ }
614
+ }, [offlineDataHasError, offlineDataIsLoading, offlineDataProvider, offlineDataTotalResultCount]);
615
+ const dataProviderSignature = React4.useMemo(() => {
616
+ if (isDataset(dataProvider) && dataProvider.records) {
617
+ return Object.values(dataProvider.records).map((r) => `${r.getRecordId()}-${r.getValue("ian_identifier")}-${r.getValue("ian_key")}`).join("|");
618
+ }
619
+ return "";
620
+ }, [dataProvider]);
621
+ const offlineDataProviderSignature = React4.useMemo(() => {
622
+ if (offlineDataProvider && offlineDataProvider.records) {
623
+ return Object.values(offlineDataProvider.records).map((r) => `${r.getRecordId()}-${r.getValue("ian_identifier")}-${r.getValue("ian_key")}`).join("|");
624
+ }
625
+ return "";
626
+ }, [offlineDataProvider]);
627
+ React4.useEffect(() => {
628
+ console.log(`Starting license evaluation at ${(/* @__PURE__ */ new Date()).toISOString()}`);
629
+ console.log(`DataProvider state: ${dataProviderState}`);
630
+ console.log(`DataProvider signature: ${dataProviderSignature}`);
631
+ console.log(`Offline DataProvider state: ${offlineDataProviderState}`);
632
+ console.log(`Offline DataProvider signature: ${offlineDataProviderSignature}`);
633
+ if (usagePermission != null && !usagePermission) {
634
+ const result = {
635
+ isValid: false,
636
+ isTerminalError: true,
637
+ reason: "Your user is not enabled for using this product"
638
+ };
639
+ licenseDispatch({ type: "setLicense", payload: result });
640
+ updateResultIfDefined(result, onLicenseValidated);
641
+ } else if (!isDataset(dataProvider) || !dataProvider.error && !dataProvider.loading && dataProvider.paging.totalResultCount >= 0 || offlineDataProvider != null && !offlineDataProvider.error && !offlineDataProvider.loading && offlineDataProvider.paging.totalResultCount >= 0) {
504
642
  initLicenseValidation();
505
643
  } else if (dataProvider.error) {
506
644
  const result = {
@@ -511,8 +649,8 @@ var IanusGuard = ({ publisherId, productId, publicKeys, environmentType, environ
511
649
  licenseDispatch({ type: "setLicense", payload: result });
512
650
  updateResultIfDefined(result, onLicenseValidated);
513
651
  }
514
- }, [dataProvider, initLicenseValidation, licenseDispatch, onLicenseValidated]);
515
- return ((_a = licenseState.license) == null ? void 0 : _a.isValid) ? /* @__PURE__ */ React3.createElement(React3.Fragment, null, licenseState.licenseDialogVisible && /* @__PURE__ */ React3.createElement(LicenseDialog, { publisherId, productId, dataProvider, onSubmit: onSettingsFinally, onCancel: onSettingsFinally }), children) : /* @__PURE__ */ React3.createElement("div", { style: { display: "flex", width: "100%", height: "100%", flex: "1" } }, licenseState.licenseDialogVisible && /* @__PURE__ */ React3.createElement(LicenseDialog, { publisherId, productId, dataProvider, onSubmit: onSettingsFinally, onCancel: onSettingsFinally }), /* @__PURE__ */ React3.createElement("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", flex: 1 } }, ((_b = licenseState.license) == null ? void 0 : _b.isValid) === false && /* @__PURE__ */ React3.createElement(
652
+ }, [dataProvider, dataProviderState, dataProviderSignature, initLicenseValidation, licenseDispatch, usagePermission, onLicenseValidated, offlineDataProvider, offlineDataProviderState, offlineDataProviderSignature]);
653
+ return ((_a = licenseState.license) == null ? void 0 : _a.isValid) ? /* @__PURE__ */ React4.createElement(React4.Fragment, null, licenseState.licenseDialogVisible && /* @__PURE__ */ React4.createElement(LicenseDialog, { publisherId, productId, dataProvider, offlineDataProvider, onSubmit: onSettingsFinally, onCancel: onSettingsFinally }), children) : /* @__PURE__ */ React4.createElement("div", { style: { display: "flex", width: "100%", height: "100%", flex: "1" } }, licenseState.licenseDialogVisible && /* @__PURE__ */ React4.createElement(LicenseDialog, { publisherId, productId, dataProvider, offlineDataProvider, onSubmit: onSettingsFinally, onCancel: onSettingsFinally }), licenseState.debugDialogVisible && /* @__PURE__ */ React4.createElement(DebugDialog, { publisherId, productId, dataProvider, offlineDataProvider, onDismiss: onDebugFinally }), /* @__PURE__ */ React4.createElement("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", flex: 1 } }, ((_b = licenseState.license) == null ? void 0 : _b.isValid) === false && /* @__PURE__ */ React4.createElement(
516
654
  import_MessageBar.MessageBar,
517
655
  {
518
656
  messageBarType: import_MessageBar.MessageBarType.error,
@@ -522,17 +660,17 @@ var IanusGuard = ({ publisherId, productId, publicKeys, environmentType, environ
522
660
  licenseDispatch({ type: "setLicense", payload: void 0 });
523
661
  initLicenseValidation();
524
662
  },
525
- actions: /* @__PURE__ */ React3.createElement("div", null, !((_c = licenseState.license) == null ? void 0 : _c.isTerminalError) && /* @__PURE__ */ React3.createElement(import_Button.MessageBarButton, { onClick: () => licenseDispatch({ type: "setLicenseDialogVisible", payload: true }) }, "Set License"))
663
+ actions: /* @__PURE__ */ React4.createElement("div", null, !((_c = licenseState.license) == null ? void 0 : _c.isTerminalError) && /* @__PURE__ */ React4.createElement(import_Button.MessageBarButton, { onClick: () => licenseDispatch({ type: "setLicenseDialogVisible", payload: true }) }, "Set License"), !((_d = licenseState.license) == null ? void 0 : _d.isTerminalError) && /* @__PURE__ */ React4.createElement(import_Button.MessageBarButton, { onClick: () => licenseDispatch({ type: "setDebugDialogVisible", payload: true }) }, "Debug"))
526
664
  },
527
665
  "An error occured, please try again. Error information: ",
528
- (_d = licenseState.license) == null ? void 0 : _d.reason
529
- ), !licenseState.license && /* @__PURE__ */ React3.createElement(import_Spinner.Spinner, { styles: { root: { width: "auto" } }, label: "Loading..." })));
666
+ (_e = licenseState.license) == null ? void 0 : _e.reason
667
+ ), !licenseState.license && /* @__PURE__ */ React4.createElement(import_Spinner.Spinner, { styles: { root: { width: "auto" } }, label: "Loading..." })));
530
668
  };
531
669
 
532
670
  // src/IanusProvider.tsx
533
- var React4 = __toESM(require("react"));
671
+ var React5 = __toESM(require("react"));
534
672
  var IanusProvider = (props) => {
535
- return /* @__PURE__ */ React4.createElement(IanusLicenseStateProvider, null, /* @__PURE__ */ React4.createElement(IanusGuard, __spreadValues({}, props)));
673
+ return /* @__PURE__ */ React5.createElement(IanusLicenseStateProvider, null, /* @__PURE__ */ React5.createElement(IanusGuard, __spreadValues({}, props)));
536
674
  };
537
675
 
538
676
  // ../../../../ianus-core/GuidTools.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ianua/ianus-dataverse-react-fluentui8",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
4
4
  "description": "Client-side validation for Ianus Guard licenses in Dataverse using react and FluentUi v8",
5
5
  "scripts": {
6
6
  "build": "tsup"