@camstack/ui-library 0.1.47 → 0.1.48
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/composites/scope-picker.d.ts +3 -3
- package/dist/generated/system-hooks.d.ts +10 -0
- package/dist/index.cjs +219 -45
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +215 -46
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -17,9 +17,9 @@ interface ScopePickerProps {
|
|
|
17
17
|
export declare function ScopePicker({ value, onChange, clampToParent, emptyHint }: ScopePickerProps): React.ReactElement;
|
|
18
18
|
/**
|
|
19
19
|
* Validation helper. The wire schema (`TokenScopeSchema`) requires every
|
|
20
|
-
* scope to carry a non-empty target and `access.length >= 1`.
|
|
21
|
-
* before passing the picker output to a mutate call so the
|
|
22
|
-
* clean inline error instead of a tRPC ZodError.
|
|
20
|
+
* scope to carry a non-empty target/targets and `access.length >= 1`.
|
|
21
|
+
* Use this before passing the picker output to a mutate call so the
|
|
22
|
+
* user sees a clean inline error instead of a tRPC ZodError.
|
|
23
23
|
*/
|
|
24
24
|
export declare function validateScopes(scopes: readonly TokenScope[]): string | null;
|
|
25
25
|
export {};
|
|
@@ -903,6 +903,16 @@ export declare const useUserManagementRevokeScopedToken: typeof trpc.userManagem
|
|
|
903
903
|
export declare const useUserManagementValidateScopedToken: typeof trpc.userManagement.validateScopedToken.useQuery;
|
|
904
904
|
/** Generated alias around `trpc.userManagement.listScopedTokens.useQuery`. */
|
|
905
905
|
export declare const useUserManagementListScopedTokens: typeof trpc.userManagement.listScopedTokens.useQuery;
|
|
906
|
+
/** Generated alias around `trpc.userManagement.setupTotp.useMutation`. */
|
|
907
|
+
export declare const useUserManagementSetupTotp: typeof trpc.userManagement.setupTotp.useMutation;
|
|
908
|
+
/** Generated alias around `trpc.userManagement.confirmTotp.useMutation`. */
|
|
909
|
+
export declare const useUserManagementConfirmTotp: typeof trpc.userManagement.confirmTotp.useMutation;
|
|
910
|
+
/** Generated alias around `trpc.userManagement.disableTotp.useMutation`. */
|
|
911
|
+
export declare const useUserManagementDisableTotp: typeof trpc.userManagement.disableTotp.useMutation;
|
|
912
|
+
/** Generated alias around `trpc.userManagement.getTotpStatus.useQuery`. */
|
|
913
|
+
export declare const useUserManagementGetTotpStatus: typeof trpc.userManagement.getTotpStatus.useQuery;
|
|
914
|
+
/** Generated alias around `trpc.userManagement.verifyTotp.useMutation`. */
|
|
915
|
+
export declare const useUserManagementVerifyTotp: typeof trpc.userManagement.verifyTotp.useMutation;
|
|
906
916
|
/** Generated alias around `trpc.webrtcSession.listStreams.useQuery`. */
|
|
907
917
|
export declare const useWebrtcSessionListStreams: typeof trpc.webrtcSession.listStreams.useQuery;
|
|
908
918
|
/** Generated alias around `trpc.webrtcSession.createSession.useMutation`. */
|
package/dist/index.cjs
CHANGED
|
@@ -16519,6 +16519,16 @@ var useUserManagementRevokeScopedToken = trpc.userManagement.revokeScopedToken.u
|
|
|
16519
16519
|
var useUserManagementValidateScopedToken = trpc.userManagement.validateScopedToken.useQuery;
|
|
16520
16520
|
/** Generated alias around `trpc.userManagement.listScopedTokens.useQuery`. */
|
|
16521
16521
|
var useUserManagementListScopedTokens = trpc.userManagement.listScopedTokens.useQuery;
|
|
16522
|
+
/** Generated alias around `trpc.userManagement.setupTotp.useMutation`. */
|
|
16523
|
+
var useUserManagementSetupTotp = trpc.userManagement.setupTotp.useMutation;
|
|
16524
|
+
/** Generated alias around `trpc.userManagement.confirmTotp.useMutation`. */
|
|
16525
|
+
var useUserManagementConfirmTotp = trpc.userManagement.confirmTotp.useMutation;
|
|
16526
|
+
/** Generated alias around `trpc.userManagement.disableTotp.useMutation`. */
|
|
16527
|
+
var useUserManagementDisableTotp = trpc.userManagement.disableTotp.useMutation;
|
|
16528
|
+
/** Generated alias around `trpc.userManagement.getTotpStatus.useQuery`. */
|
|
16529
|
+
var useUserManagementGetTotpStatus = trpc.userManagement.getTotpStatus.useQuery;
|
|
16530
|
+
/** Generated alias around `trpc.userManagement.verifyTotp.useMutation`. */
|
|
16531
|
+
var useUserManagementVerifyTotp = trpc.userManagement.verifyTotp.useMutation;
|
|
16522
16532
|
/** Generated alias around `trpc.webrtcSession.listStreams.useQuery`. */
|
|
16523
16533
|
var useWebrtcSessionListStreams = trpc.webrtcSession.listStreams.useQuery;
|
|
16524
16534
|
/** Generated alias around `trpc.webrtcSession.createSession.useMutation`. */
|
|
@@ -23013,23 +23023,20 @@ function KebabMenu({ items, header, triggerClassName, title = "More actions" })
|
|
|
23013
23023
|
* <ScopePicker> — operator-facing editor for a `TokenScope[]` value.
|
|
23014
23024
|
*
|
|
23015
23025
|
* Two consumers: the user-scope editor on `/system/users` (admin grants
|
|
23016
|
-
* a baseline scope set to a
|
|
23017
|
-
*
|
|
23018
|
-
*
|
|
23026
|
+
* a baseline scope set to a non-admin user) and the scoped-token create
|
|
23027
|
+
* modal on `/system/api-keys` (a caller carves out a subset of THEIR
|
|
23028
|
+
* scopes for a `cst_*` token).
|
|
23019
23029
|
*
|
|
23020
|
-
*
|
|
23021
|
-
* -
|
|
23022
|
-
*
|
|
23023
|
-
* -
|
|
23024
|
-
*
|
|
23025
|
-
*
|
|
23026
|
-
*
|
|
23027
|
-
* rejected by the server-side Zod schema (`access.min(1)`).
|
|
23030
|
+
* Row shapes per scope `type`:
|
|
23031
|
+
* - category → target: 'device' | 'system'
|
|
23032
|
+
* - capability → target: cap name from `KNOWN_CAP_NAMES`
|
|
23033
|
+
* - addon → target: addon id from `useAddonsList`
|
|
23034
|
+
* - device → targets: readonly deviceId[] (multi-select)
|
|
23035
|
+
*
|
|
23036
|
+
* `access` is always 3 independent checkboxes (view / create / delete).
|
|
23028
23037
|
*
|
|
23029
23038
|
* `clampToParent` narrows the target dropdown + access checkboxes to
|
|
23030
|
-
* what the CALLER possesses
|
|
23031
|
-
* the UI, mirroring the structural check in `createScopedToken`.
|
|
23032
|
-
* Admins should pass `null` to allow everything.
|
|
23039
|
+
* what the CALLER possesses. Admins pass `null` to allow everything.
|
|
23033
23040
|
*/
|
|
23034
23041
|
var ACCESS_OPTIONS = [
|
|
23035
23042
|
{
|
|
@@ -23051,6 +23058,8 @@ var ACCESS_OPTIONS = [
|
|
|
23051
23058
|
hint: "Destructive ops (delete/revoke/reset/…)"
|
|
23052
23059
|
}
|
|
23053
23060
|
];
|
|
23061
|
+
/** Static targets for the `category` scope type (auto-grow categories). */
|
|
23062
|
+
var CATEGORY_CHOICES = ["device", "system"];
|
|
23054
23063
|
function defaultRow() {
|
|
23055
23064
|
return {
|
|
23056
23065
|
type: "capability",
|
|
@@ -23058,11 +23067,36 @@ function defaultRow() {
|
|
|
23058
23067
|
access: ["view"]
|
|
23059
23068
|
};
|
|
23060
23069
|
}
|
|
23061
|
-
|
|
23062
|
-
|
|
23070
|
+
/**
|
|
23071
|
+
* Collect the union of device targets a parent grants. Used to clamp
|
|
23072
|
+
* the device picker so a child grant can't refer to a deviceId the
|
|
23073
|
+
* caller themselves doesn't have.
|
|
23074
|
+
*/
|
|
23075
|
+
function parentDeviceTargets(parent) {
|
|
23076
|
+
if (parent == null) return [];
|
|
23077
|
+
const out = /* @__PURE__ */ new Set();
|
|
23078
|
+
for (const s of parent) if (s.type === "device") for (const t of s.targets) out.add(t);
|
|
23079
|
+
return [...out];
|
|
23080
|
+
}
|
|
23081
|
+
function clampedSingleTargets(type, parent, addonChoices, capChoices) {
|
|
23082
|
+
let universe;
|
|
23083
|
+
switch (type) {
|
|
23084
|
+
case "addon":
|
|
23085
|
+
universe = addonChoices;
|
|
23086
|
+
break;
|
|
23087
|
+
case "capability":
|
|
23088
|
+
universe = capChoices;
|
|
23089
|
+
break;
|
|
23090
|
+
case "category":
|
|
23091
|
+
universe = CATEGORY_CHOICES.map((c) => ({
|
|
23092
|
+
value: c,
|
|
23093
|
+
label: c
|
|
23094
|
+
}));
|
|
23095
|
+
break;
|
|
23096
|
+
}
|
|
23063
23097
|
if (parent == null) return universe;
|
|
23064
|
-
const allowed = new Set(parent.filter((s) => s.type === type).map((s) => s.target));
|
|
23065
|
-
return universe.filter((t) => allowed.has(t));
|
|
23098
|
+
const allowed = new Set(parent.filter((s) => s.type !== "device" && s.type === type).map((s) => s.target));
|
|
23099
|
+
return universe.filter((t) => allowed.has(t.value));
|
|
23066
23100
|
}
|
|
23067
23101
|
function clampedAccessForRow(row, parent) {
|
|
23068
23102
|
if (parent == null) return [
|
|
@@ -23070,7 +23104,12 @@ function clampedAccessForRow(row, parent) {
|
|
|
23070
23104
|
"create",
|
|
23071
23105
|
"delete"
|
|
23072
23106
|
];
|
|
23073
|
-
const matches = parent.filter((s) =>
|
|
23107
|
+
const matches = parent.filter((s) => {
|
|
23108
|
+
if (s.type !== row.type) return false;
|
|
23109
|
+
if (s.type === "device" && row.type === "device") return s.targets.some((t) => row.targets.includes(t));
|
|
23110
|
+
if (s.type !== "device" && row.type !== "device") return s.target === row.target;
|
|
23111
|
+
return false;
|
|
23112
|
+
});
|
|
23074
23113
|
if (matches.length === 0) return [];
|
|
23075
23114
|
const out = /* @__PURE__ */ new Set();
|
|
23076
23115
|
for (const m of matches) for (const a of m.access) out.add(a);
|
|
@@ -23078,17 +23117,75 @@ function clampedAccessForRow(row, parent) {
|
|
|
23078
23117
|
}
|
|
23079
23118
|
function ScopePicker({ value, onChange, clampToParent, emptyHint }) {
|
|
23080
23119
|
const { data: addons } = useAddonsList();
|
|
23081
|
-
const
|
|
23082
|
-
const
|
|
23120
|
+
const { data: devices } = useDeviceManagerListAll({});
|
|
23121
|
+
const addonChoices = (0, react.useMemo)(() => (addons ?? []).map((a) => ({
|
|
23122
|
+
value: a.manifest.id,
|
|
23123
|
+
label: a.manifest.id
|
|
23124
|
+
})).sort((a, b) => a.label.localeCompare(b.label)), [addons]);
|
|
23125
|
+
const capChoices = (0, react.useMemo)(() => [..._camstack_types.KNOWN_CAP_NAMES].sort().map((c) => ({
|
|
23126
|
+
value: c,
|
|
23127
|
+
label: c
|
|
23128
|
+
})), []);
|
|
23129
|
+
const deviceChoices = (0, react.useMemo)(() => (devices ?? []).map((d) => ({
|
|
23130
|
+
value: String(d.id),
|
|
23131
|
+
label: `${d.name} (#${d.id} · ${d.addonId})`
|
|
23132
|
+
})).sort((a, b) => a.label.localeCompare(b.label)), [devices]);
|
|
23133
|
+
const parentDeviceClamp = (0, react.useMemo)(() => clampToParent == null ? null : parentDeviceTargets(clampToParent), [clampToParent]);
|
|
23134
|
+
/**
|
|
23135
|
+
* Build a fresh scope row when `type` changes. The discriminated union
|
|
23136
|
+
* forces us to re-construct the object per variant so the resulting
|
|
23137
|
+
* shape matches one of the four union members exactly.
|
|
23138
|
+
*/
|
|
23139
|
+
const rebuildForType = (next, access) => {
|
|
23140
|
+
const accessArr = [...access];
|
|
23141
|
+
switch (next) {
|
|
23142
|
+
case "category": return {
|
|
23143
|
+
type: "category",
|
|
23144
|
+
target: "device",
|
|
23145
|
+
access: accessArr
|
|
23146
|
+
};
|
|
23147
|
+
case "capability": return {
|
|
23148
|
+
type: "capability",
|
|
23149
|
+
target: "",
|
|
23150
|
+
access: accessArr
|
|
23151
|
+
};
|
|
23152
|
+
case "addon": return {
|
|
23153
|
+
type: "addon",
|
|
23154
|
+
target: "",
|
|
23155
|
+
access: accessArr
|
|
23156
|
+
};
|
|
23157
|
+
case "device": return {
|
|
23158
|
+
type: "device",
|
|
23159
|
+
targets: [],
|
|
23160
|
+
access: accessArr
|
|
23161
|
+
};
|
|
23162
|
+
}
|
|
23163
|
+
};
|
|
23083
23164
|
const update = (idx, patch) => {
|
|
23084
23165
|
onChange(value.map((s, i) => {
|
|
23085
23166
|
if (i !== idx) return s;
|
|
23086
|
-
|
|
23087
|
-
|
|
23088
|
-
|
|
23167
|
+
if (patch.type !== void 0 && patch.type !== s.type) return rebuildForType(patch.type, patch.access ?? s.access);
|
|
23168
|
+
const access = [...patch.access ?? s.access];
|
|
23169
|
+
if (s.type === "device") return {
|
|
23170
|
+
type: "device",
|
|
23171
|
+
targets: [...patch.targets ?? s.targets],
|
|
23172
|
+
access
|
|
23173
|
+
};
|
|
23174
|
+
if (s.type === "category") return {
|
|
23175
|
+
type: "category",
|
|
23176
|
+
target: patch.target ?? s.target,
|
|
23177
|
+
access
|
|
23178
|
+
};
|
|
23179
|
+
if (s.type === "capability") return {
|
|
23180
|
+
type: "capability",
|
|
23181
|
+
target: patch.target ?? s.target,
|
|
23182
|
+
access
|
|
23183
|
+
};
|
|
23184
|
+
return {
|
|
23185
|
+
type: "addon",
|
|
23186
|
+
target: patch.target ?? s.target,
|
|
23187
|
+
access
|
|
23089
23188
|
};
|
|
23090
|
-
if (patch.type !== void 0 && patch.type !== s.type) next.target = "";
|
|
23091
|
-
return next;
|
|
23092
23189
|
}));
|
|
23093
23190
|
};
|
|
23094
23191
|
const removeAt = (idx) => {
|
|
@@ -23105,24 +23202,39 @@ function ScopePicker({ value, onChange, clampToParent, emptyHint }) {
|
|
|
23105
23202
|
children: emptyHint
|
|
23106
23203
|
}),
|
|
23107
23204
|
value.map((row, idx) => {
|
|
23108
|
-
const targetChoices = clampedTargetsForType(row.type, clampToParent, addonChoices, capChoices);
|
|
23109
23205
|
const allowedAccess = clampedAccessForRow(row, clampToParent);
|
|
23110
23206
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
23111
|
-
className: "flex flex-wrap items-
|
|
23207
|
+
className: "flex flex-wrap items-start gap-1.5 rounded border border-border bg-surface px-2 py-1.5",
|
|
23112
23208
|
children: [
|
|
23113
23209
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
23114
23210
|
value: row.type,
|
|
23115
23211
|
onChange: (e) => update(idx, { type: e.target.value }),
|
|
23116
23212
|
className: "rounded border border-border bg-background px-2 py-1 text-[11px] focus:outline-none focus:ring-1 focus:ring-primary",
|
|
23117
|
-
children: [
|
|
23118
|
-
|
|
23119
|
-
|
|
23120
|
-
|
|
23121
|
-
|
|
23122
|
-
|
|
23123
|
-
|
|
23213
|
+
children: [
|
|
23214
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
23215
|
+
value: "category",
|
|
23216
|
+
children: "category"
|
|
23217
|
+
}),
|
|
23218
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
23219
|
+
value: "capability",
|
|
23220
|
+
children: "capability"
|
|
23221
|
+
}),
|
|
23222
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
23223
|
+
value: "addon",
|
|
23224
|
+
children: "addon"
|
|
23225
|
+
}),
|
|
23226
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
23227
|
+
value: "device",
|
|
23228
|
+
children: "device"
|
|
23229
|
+
})
|
|
23230
|
+
]
|
|
23124
23231
|
}),
|
|
23125
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
23232
|
+
row.type === "device" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DeviceTargetPicker, {
|
|
23233
|
+
value: row.targets,
|
|
23234
|
+
choices: deviceChoices,
|
|
23235
|
+
clampToParent: parentDeviceClamp,
|
|
23236
|
+
onChange: (targets) => update(idx, { targets })
|
|
23237
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
23126
23238
|
value: row.target,
|
|
23127
23239
|
onChange: (e) => update(idx, { target: e.target.value }),
|
|
23128
23240
|
className: "flex-1 min-w-[160px] rounded border border-border bg-background px-2 py-1 text-[11px] font-mono focus:outline-none focus:ring-1 focus:ring-primary",
|
|
@@ -23133,10 +23245,10 @@ function ScopePicker({ value, onChange, clampToParent, emptyHint }) {
|
|
|
23133
23245
|
row.type,
|
|
23134
23246
|
" —"
|
|
23135
23247
|
]
|
|
23136
|
-
}),
|
|
23137
|
-
value: t,
|
|
23138
|
-
children: t
|
|
23139
|
-
}, t))]
|
|
23248
|
+
}), clampedSingleTargets(row.type, clampToParent, addonChoices, capChoices).map((t) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
23249
|
+
value: t.value,
|
|
23250
|
+
children: t.label
|
|
23251
|
+
}, t.value))]
|
|
23140
23252
|
}),
|
|
23141
23253
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
23142
23254
|
className: "flex items-center gap-1",
|
|
@@ -23184,16 +23296,73 @@ function ScopePicker({ value, onChange, clampToParent, emptyHint }) {
|
|
|
23184
23296
|
]
|
|
23185
23297
|
});
|
|
23186
23298
|
}
|
|
23299
|
+
function DeviceTargetPicker({ value, choices, clampToParent, onChange }) {
|
|
23300
|
+
const [pendingAdd, setPendingAdd] = (0, react.useState)("");
|
|
23301
|
+
const visibleChoices = (0, react.useMemo)(() => {
|
|
23302
|
+
const filtered = clampToParent == null ? choices : choices.filter((c) => clampToParent.includes(c.value));
|
|
23303
|
+
const taken = new Set(value);
|
|
23304
|
+
return filtered.filter((c) => !taken.has(c.value));
|
|
23305
|
+
}, [
|
|
23306
|
+
choices,
|
|
23307
|
+
clampToParent,
|
|
23308
|
+
value
|
|
23309
|
+
]);
|
|
23310
|
+
const labelFor = (id) => choices.find((c) => c.value === id)?.label ?? `#${id}`;
|
|
23311
|
+
const handleAdd = (id) => {
|
|
23312
|
+
if (!id) return;
|
|
23313
|
+
onChange([...value, id]);
|
|
23314
|
+
setPendingAdd("");
|
|
23315
|
+
};
|
|
23316
|
+
const handleRemove = (id) => {
|
|
23317
|
+
onChange(value.filter((v) => v !== id));
|
|
23318
|
+
};
|
|
23319
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
23320
|
+
className: "flex-1 min-w-[160px] flex flex-wrap items-center gap-1",
|
|
23321
|
+
children: [
|
|
23322
|
+
value.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
23323
|
+
className: "text-[10px] text-foreground-subtle italic px-1",
|
|
23324
|
+
children: "no devices selected"
|
|
23325
|
+
}),
|
|
23326
|
+
value.map((id) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
23327
|
+
className: "inline-flex items-center gap-1 rounded bg-primary/10 px-1.5 py-0.5 text-[10px] font-mono text-primary",
|
|
23328
|
+
children: [labelFor(id), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
23329
|
+
type: "button",
|
|
23330
|
+
onClick: () => handleRemove(id),
|
|
23331
|
+
className: "hover:text-danger transition-colors",
|
|
23332
|
+
title: "Remove device",
|
|
23333
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(X, { className: "h-2.5 w-2.5" })
|
|
23334
|
+
})]
|
|
23335
|
+
}, id)),
|
|
23336
|
+
visibleChoices.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
23337
|
+
value: pendingAdd,
|
|
23338
|
+
onChange: (e) => handleAdd(e.target.value),
|
|
23339
|
+
className: "rounded border border-border bg-background px-1.5 py-0.5 text-[10px] focus:outline-none focus:ring-1 focus:ring-primary",
|
|
23340
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
23341
|
+
value: "",
|
|
23342
|
+
children: "+ add device…"
|
|
23343
|
+
}), visibleChoices.map((c) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
|
|
23344
|
+
value: c.value,
|
|
23345
|
+
children: c.label
|
|
23346
|
+
}, c.value))]
|
|
23347
|
+
})
|
|
23348
|
+
]
|
|
23349
|
+
});
|
|
23350
|
+
}
|
|
23187
23351
|
/**
|
|
23188
23352
|
* Validation helper. The wire schema (`TokenScopeSchema`) requires every
|
|
23189
|
-
* scope to carry a non-empty target and `access.length >= 1`.
|
|
23190
|
-
* before passing the picker output to a mutate call so the
|
|
23191
|
-
* clean inline error instead of a tRPC ZodError.
|
|
23353
|
+
* scope to carry a non-empty target/targets and `access.length >= 1`.
|
|
23354
|
+
* Use this before passing the picker output to a mutate call so the
|
|
23355
|
+
* user sees a clean inline error instead of a tRPC ZodError.
|
|
23192
23356
|
*/
|
|
23193
23357
|
function validateScopes(scopes) {
|
|
23194
23358
|
for (const s of scopes) {
|
|
23195
|
-
if (s.
|
|
23196
|
-
|
|
23359
|
+
if (s.type === "device") {
|
|
23360
|
+
if (s.targets.length === 0) return `Scope device: pick at least one device`;
|
|
23361
|
+
} else if (s.target.trim().length === 0) return `Scope ${s.type}: pick a target`;
|
|
23362
|
+
if (s.access.length === 0) {
|
|
23363
|
+
const targetDesc = s.type === "device" ? `[${s.targets.join(",")}]` : s.target;
|
|
23364
|
+
return `Scope ${s.type}:${targetDesc}: pick at least one access`;
|
|
23365
|
+
}
|
|
23197
23366
|
}
|
|
23198
23367
|
return null;
|
|
23199
23368
|
}
|
|
@@ -24555,10 +24724,13 @@ exports.useTurnOrchestratorGetAllServers = useTurnOrchestratorGetAllServers;
|
|
|
24555
24724
|
exports.useTurnOrchestratorListProviders = useTurnOrchestratorListProviders;
|
|
24556
24725
|
exports.useTurnOrchestratorSetProviderEnabled = useTurnOrchestratorSetProviderEnabled;
|
|
24557
24726
|
exports.useTurnProviderGetTurnServers = useTurnProviderGetTurnServers;
|
|
24727
|
+
exports.useUserManagementConfirmTotp = useUserManagementConfirmTotp;
|
|
24558
24728
|
exports.useUserManagementCreateApiKey = useUserManagementCreateApiKey;
|
|
24559
24729
|
exports.useUserManagementCreateScopedToken = useUserManagementCreateScopedToken;
|
|
24560
24730
|
exports.useUserManagementCreateUser = useUserManagementCreateUser;
|
|
24561
24731
|
exports.useUserManagementDeleteUser = useUserManagementDeleteUser;
|
|
24732
|
+
exports.useUserManagementDisableTotp = useUserManagementDisableTotp;
|
|
24733
|
+
exports.useUserManagementGetTotpStatus = useUserManagementGetTotpStatus;
|
|
24562
24734
|
exports.useUserManagementListApiKeys = useUserManagementListApiKeys;
|
|
24563
24735
|
exports.useUserManagementListScopedTokens = useUserManagementListScopedTokens;
|
|
24564
24736
|
exports.useUserManagementListUsers = useUserManagementListUsers;
|
|
@@ -24566,10 +24738,12 @@ exports.useUserManagementResetPassword = useUserManagementResetPassword;
|
|
|
24566
24738
|
exports.useUserManagementRevokeApiKey = useUserManagementRevokeApiKey;
|
|
24567
24739
|
exports.useUserManagementRevokeScopedToken = useUserManagementRevokeScopedToken;
|
|
24568
24740
|
exports.useUserManagementSetUserScopes = useUserManagementSetUserScopes;
|
|
24741
|
+
exports.useUserManagementSetupTotp = useUserManagementSetupTotp;
|
|
24569
24742
|
exports.useUserManagementUpdateUser = useUserManagementUpdateUser;
|
|
24570
24743
|
exports.useUserManagementValidateApiKey = useUserManagementValidateApiKey;
|
|
24571
24744
|
exports.useUserManagementValidateCredentials = useUserManagementValidateCredentials;
|
|
24572
24745
|
exports.useUserManagementValidateScopedToken = useUserManagementValidateScopedToken;
|
|
24746
|
+
exports.useUserManagementVerifyTotp = useUserManagementVerifyTotp;
|
|
24573
24747
|
exports.useWebrtcSessionCloseSession = useWebrtcSessionCloseSession;
|
|
24574
24748
|
exports.useWebrtcSessionCreateSession = useWebrtcSessionCreateSession;
|
|
24575
24749
|
exports.useWebrtcSessionHandleAnswer = useWebrtcSessionHandleAnswer;
|