@xeonr/platform-ui 0.3.20 → 0.4.0
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 +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -1
- package/dist/kit/ApiKeyForm.d.ts +71 -0
- package/dist/kit/ApiKeyForm.d.ts.map +1 -0
- package/dist/kit/ApiKeyForm.js +105 -0
- package/dist/kit/ApiKeyForm.js.map +1 -0
- package/dist/kit/ApiKeys.d.ts +79 -0
- package/dist/kit/ApiKeys.d.ts.map +1 -0
- package/dist/kit/ApiKeys.js +198 -0
- package/dist/kit/ApiKeys.js.map +1 -0
- package/dist/kit/Button.d.ts +1 -1
- package/dist/kit/Button.d.ts.map +1 -1
- package/dist/kit/Button.js.map +1 -1
- package/dist/kit/Combobox.d.ts +17 -1
- package/dist/kit/Combobox.d.ts.map +1 -1
- package/dist/kit/Combobox.js +12 -3
- package/dist/kit/Combobox.js.map +1 -1
- package/dist/kit/MultiCombobox.d.ts +19 -1
- package/dist/kit/MultiCombobox.d.ts.map +1 -1
- package/dist/kit/MultiCombobox.js +32 -9
- package/dist/kit/MultiCombobox.js.map +1 -1
- package/dist/kit/Sparkline.d.ts +57 -0
- package/dist/kit/Sparkline.d.ts.map +1 -0
- package/dist/kit/Sparkline.js +109 -0
- package/dist/kit/Sparkline.js.map +1 -0
- package/dist/kit/Text.d.ts +5 -0
- package/dist/kit/Text.d.ts.map +1 -1
- package/dist/kit/Text.js +12 -2
- package/dist/kit/Text.js.map +1 -1
- package/dist/kit/Tooltip.d.ts +41 -0
- package/dist/kit/Tooltip.d.ts.map +1 -0
- package/dist/kit/Tooltip.js +129 -0
- package/dist/kit/Tooltip.js.map +1 -0
- package/dist/theme/paint.d.ts +43 -0
- package/dist/theme/paint.d.ts.map +1 -0
- package/dist/theme/paint.js +109 -0
- package/dist/theme/paint.js.map +1 -0
- package/dist/theme/tokens.d.ts +10 -0
- package/dist/theme/tokens.d.ts.map +1 -1
- package/dist/theme/tokens.js +43 -0
- package/dist/theme/tokens.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { BRAND, GRAD, GRAD_90, cssVariables, globalCss, v } from "./theme/tokens.ts";
|
|
2
2
|
export { AppThemeProvider, useTheme, useThemeMaybe, type ThemePref, type AppThemeProviderProps } from "./theme/ThemeProvider.tsx";
|
|
3
3
|
export { brandCss, brandRamp, type BrandRamp } from "./theme/brand.ts";
|
|
4
|
+
export { tokenValue, useTokenColours, useSeriesColours, SERIES_TOKENS, seriesToken } from "./theme/paint.ts";
|
|
4
5
|
export { Icon, extendIcons, type IconName } from "./kit/Icon.tsx";
|
|
5
6
|
export { AppButton, IconButton, ButtonRow, type AppButtonProps } from "./kit/Button.tsx";
|
|
6
7
|
export { StatusPill, Tag, LiveDot, InitialsTile, RemovableTag, type Tone } from "./kit/Badge.tsx";
|
|
@@ -17,7 +18,7 @@ export { LogSurface, LogPanel, type LogLine } from "./kit/LogView.tsx";
|
|
|
17
18
|
export { KVGrid } from "./kit/KV.tsx";
|
|
18
19
|
export { SecretField, CopyIcon, Digest } from "./kit/Secret.tsx";
|
|
19
20
|
export { ToastProvider, useToast, toastError, type ToastKind } from "./kit/Toast.tsx";
|
|
20
|
-
export { Mono, Num, Hint, InlineHint, Cell, InlineLink, Muted, Faint, InlineCode, Prose, Ago, toDate, relative, } from "./kit/Text.tsx";
|
|
21
|
+
export { Mono, Num, Hint, InlineHint, Cell, InlineLink, Muted, Faint, InlineCode, Prose, Ago, toDate, relative, type TextTone, } from "./kit/Text.tsx";
|
|
21
22
|
export { RowList, ListRow, RowActions, SelectableList, Breadcrumbs } from "./kit/List.tsx";
|
|
22
23
|
export { FilterBar, FilterField, Chip, EditableChip } from "./kit/Chip.tsx";
|
|
23
24
|
export { StatGrid, StatTile, StatValue, Meter } from "./kit/Stat.tsx";
|
|
@@ -41,4 +42,7 @@ export { Dot, LevelBars, PersonChip, initials } from "./kit/Marker.tsx";
|
|
|
41
42
|
export { CommentList, Comment, CommentComposer } from "./kit/Comment.tsx";
|
|
42
43
|
export { Board, BoardCardLine, BoardCardTitle, BoardCardFoot, type BoardLane } from "./kit/Board.tsx";
|
|
43
44
|
export { EditableTitle } from "./kit/Editable.tsx";
|
|
45
|
+
export { Tooltip, type TooltipProps } from "./kit/Tooltip.tsx";
|
|
46
|
+
export { Sparkline, SparkRow, type SparklineProps } from "./kit/Sparkline.tsx";
|
|
47
|
+
export { ApiKeys, keyHint, type ApiKeysProps, type ApiKeyRow, type ApiKeyBindingRow, type ApiKeyOwnerKind, type ApiKeyResourceMode, type ApiKeyScopePreset, type ApiKeyResourceTypeSpec, type ApiKeyCreateInput, type ApiKeyUpdateInput, } from "./kit/ApiKeys.tsx";
|
|
44
48
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,mBAAmB,CAAC;AACrF,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,aAAa,EAAE,KAAK,SAAS,EAAE,KAAK,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAKlI,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -9,6 +9,12 @@ export { AppThemeProvider, useTheme, useThemeMaybe } from "./theme/ThemeProvider
|
|
|
9
9
|
// this for anything mounting the shell; `brandCss` is for SSR hosts that inline
|
|
10
10
|
// the sheet themselves.
|
|
11
11
|
export { brandCss, brandRamp } from "./theme/brand.js";
|
|
12
|
+
// Token values as concrete colours, for the surfaces that cannot use var() —
|
|
13
|
+
// a <canvas>, or a charting library configured through JS. Added for the
|
|
14
|
+
// Lantern adoption (2026-10-13): every console with a uPlot chart had
|
|
15
|
+
// hardcoded its axis and series colours, which is how a chart ends up
|
|
16
|
+
// unreadable in whichever theme its author did not have open.
|
|
17
|
+
export { tokenValue, useTokenColours, useSeriesColours, SERIES_TOKENS, seriesToken } from "./theme/paint.js";
|
|
12
18
|
// Kit: the same names and props container-platform/ui and functions/ui use,
|
|
13
19
|
// so adopting the package is an import-path change.
|
|
14
20
|
export { Icon, extendIcons } from "./kit/Icon.js";
|
|
@@ -67,6 +73,16 @@ export { Dot, LevelBars, PersonChip, initials } from "./kit/Marker.js";
|
|
|
67
73
|
export { CommentList, Comment, CommentComposer } from "./kit/Comment.js";
|
|
68
74
|
export { Board, BoardCardLine, BoardCardTitle, BoardCardFoot } from "./kit/Board.js";
|
|
69
75
|
export { EditableTitle } from "./kit/Editable.js";
|
|
76
|
+
// Added for the Lantern adoption (2026-10-13): the hover explanation the kit
|
|
77
|
+
// had been doing with the native `title` attribute, and the cell-sized series
|
|
78
|
+
// every list of entities-with-a-trend wants.
|
|
79
|
+
export { Tooltip } from "./kit/Tooltip.js";
|
|
80
|
+
export { Sparkline, SparkRow } from "./kit/Sparkline.js";
|
|
81
|
+
// Added for centralised API keys (2026-10-13, CON-23): the one keys screen
|
|
82
|
+
// every product shows for the keys auth holds on its behalf, and the portal's
|
|
83
|
+
// read-only view across products. API-agnostic — the host maps its wire type
|
|
84
|
+
// to ApiKeyRow and supplies the callbacks.
|
|
85
|
+
export { ApiKeys, keyHint, } from "./kit/ApiKeys.js";
|
|
70
86
|
// The markdown surface is `@xeonr/platform-ui/markdown` — its own entry point,
|
|
71
87
|
// so react-markdown stays an optional peer.
|
|
72
88
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,iEAAiE;AACjE,EAAE;AACF,2EAA2E;AAC3E,sEAAsE;AACtE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,mBAAmB,CAAC;AACrF,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,aAAa,EAA8C,MAAM,0BAA2B,CAAC;AAClI,4EAA4E;AAC5E,6EAA6E;AAC7E,gFAAgF;AAChF,wBAAwB;AACxB,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAkB,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
export type ApiKeyResourceMode = "app_wide" | "bound";
|
|
3
|
+
export interface ApiKeyScopePreset {
|
|
4
|
+
id: string;
|
|
5
|
+
label: string;
|
|
6
|
+
description?: string | undefined;
|
|
7
|
+
scopes: string[];
|
|
8
|
+
}
|
|
9
|
+
export interface ApiKeyResourceTypeSpec {
|
|
10
|
+
/** the type as auth knows it, e.g. 'bucket' */
|
|
11
|
+
type: string;
|
|
12
|
+
/** the type as a person reads it, e.g. 'Bucket' */
|
|
13
|
+
label: string;
|
|
14
|
+
/** host-provided picker; the form renders one per binding row */
|
|
15
|
+
Picker: React.ComponentType<{
|
|
16
|
+
value: string;
|
|
17
|
+
onChange: (id: string, label?: string) => void;
|
|
18
|
+
disabled?: boolean | undefined;
|
|
19
|
+
}>;
|
|
20
|
+
/** per-resource level choices (read / read+write) */
|
|
21
|
+
scopePresets: ApiKeyScopePreset[];
|
|
22
|
+
}
|
|
23
|
+
export interface ApiKeyCreateInput {
|
|
24
|
+
name: string;
|
|
25
|
+
description?: string | undefined;
|
|
26
|
+
scopes: string[];
|
|
27
|
+
resourceMode: ApiKeyResourceMode;
|
|
28
|
+
bindings: {
|
|
29
|
+
resourceType: string;
|
|
30
|
+
resourceId: string;
|
|
31
|
+
scopes: string[];
|
|
32
|
+
}[];
|
|
33
|
+
expiresAt?: Date | undefined;
|
|
34
|
+
}
|
|
35
|
+
export interface ApiKeyUpdateInput {
|
|
36
|
+
name?: string | undefined;
|
|
37
|
+
description?: string | undefined;
|
|
38
|
+
scopes?: string[] | undefined;
|
|
39
|
+
bindings?: ApiKeyCreateInput["bindings"] | undefined;
|
|
40
|
+
/** null clears the expiry; undefined leaves it alone */
|
|
41
|
+
expiresAt?: Date | null | undefined;
|
|
42
|
+
}
|
|
43
|
+
/** What the form starts from when editing — the subset of a row it can change. */
|
|
44
|
+
export interface ApiKeyFormInitial {
|
|
45
|
+
name: string;
|
|
46
|
+
description?: string | undefined;
|
|
47
|
+
scopes: string[];
|
|
48
|
+
resourceMode: ApiKeyResourceMode;
|
|
49
|
+
bindings: {
|
|
50
|
+
resourceType: string;
|
|
51
|
+
resourceId: string;
|
|
52
|
+
resourceLabel?: string | undefined;
|
|
53
|
+
scopes: string[];
|
|
54
|
+
}[];
|
|
55
|
+
}
|
|
56
|
+
export declare function ApiKeyForm({ mode, initial, scopePresets, resourceTypes, fixedMode, ownerLabel, lifetimeDays, allowNoExpiry, busy, error, onCreate, onUpdate, onCancel, }: {
|
|
57
|
+
mode: "create" | "edit";
|
|
58
|
+
initial?: ApiKeyFormInitial | undefined;
|
|
59
|
+
scopePresets?: ApiKeyScopePreset[] | undefined;
|
|
60
|
+
resourceTypes?: ApiKeyResourceTypeSpec[] | undefined;
|
|
61
|
+
fixedMode?: ApiKeyResourceMode | undefined;
|
|
62
|
+
ownerLabel?: string | undefined;
|
|
63
|
+
lifetimeDays?: number[] | undefined;
|
|
64
|
+
allowNoExpiry?: boolean | undefined;
|
|
65
|
+
busy?: boolean | undefined;
|
|
66
|
+
error?: ReactNode | undefined;
|
|
67
|
+
onCreate?: ((input: ApiKeyCreateInput) => void) | undefined;
|
|
68
|
+
onUpdate?: ((input: ApiKeyUpdateInput) => void) | undefined;
|
|
69
|
+
onCancel: () => void;
|
|
70
|
+
}): import("react").JSX.Element;
|
|
71
|
+
//# sourceMappingURL=ApiKeyForm.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ApiKeyForm.d.ts","sourceRoot":"","sources":["../../src/kit/ApiKeyForm.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo, useState } from "react";
|
|
3
|
+
import styled from "styled-components";
|
|
4
|
+
import { v } from "../theme/tokens.js";
|
|
5
|
+
import { AppButton } from "./Button.js";
|
|
6
|
+
import { CheckRow, Field, FormGrid, InlineError, Input, Segmented, Select, TextArea } from "./Form.js";
|
|
7
|
+
import { RepeaterRows } from "./Blocks.js";
|
|
8
|
+
import { Hint } from "./Text.js";
|
|
9
|
+
import { Stack } from "./Layout.js";
|
|
10
|
+
const DEFAULT_LIFETIMES = [30, 90, 365];
|
|
11
|
+
const KEEP = "__keep__";
|
|
12
|
+
const NEVER = "__never__";
|
|
13
|
+
const OwnerLine = styled.div `
|
|
14
|
+
display: flex;
|
|
15
|
+
align-items: center;
|
|
16
|
+
gap: 8px;
|
|
17
|
+
padding: 8px 10px;
|
|
18
|
+
border-radius: ${v.rCtl};
|
|
19
|
+
background: ${v.surface2};
|
|
20
|
+
border: 1px solid ${v.line};
|
|
21
|
+
font-size: 12.5px;
|
|
22
|
+
b { font-weight: 600; }
|
|
23
|
+
span { color: ${v.muted}; }
|
|
24
|
+
`;
|
|
25
|
+
const sameSet = (a, b) => a.length === b.length && a.every((s) => b.includes(s));
|
|
26
|
+
const union = (presets, ids) => [...new Set(presets.filter((p) => ids.includes(p.id)).flatMap((p) => p.scopes))];
|
|
27
|
+
/** The presets whose scopes a key already carries, so an edit starts checked. */
|
|
28
|
+
function presetsCovering(presets, scopes) {
|
|
29
|
+
return presets.filter((p) => p.scopes.length > 0 && p.scopes.every((s) => scopes.includes(s))).map((p) => p.id);
|
|
30
|
+
}
|
|
31
|
+
function lifetimeLabel(days) {
|
|
32
|
+
if (days % 365 === 0)
|
|
33
|
+
return days === 365 ? "1 year" : `${days / 365} years`;
|
|
34
|
+
if (days % 30 === 0 && days >= 60)
|
|
35
|
+
return `${days / 30} months`;
|
|
36
|
+
return `${days} days`;
|
|
37
|
+
}
|
|
38
|
+
export function ApiKeyForm({ mode, initial, scopePresets = [], resourceTypes = [], fixedMode, ownerLabel, lifetimeDays = DEFAULT_LIFETIMES, allowNoExpiry = true, busy, error, onCreate, onUpdate, onCancel, }) {
|
|
39
|
+
const canBind = resourceTypes.length > 0;
|
|
40
|
+
const [name, setName] = useState(initial?.name ?? "");
|
|
41
|
+
const [description, setDescription] = useState(initial?.description ?? "");
|
|
42
|
+
const [presetIds, setPresetIds] = useState(() => presetsCovering(scopePresets, initial?.scopes ?? []));
|
|
43
|
+
const [resourceMode, setResourceMode] = useState(fixedMode ?? initial?.resourceMode ?? (canBind ? "bound" : "app_wide"));
|
|
44
|
+
const [bindings, setBindings] = useState(() => (initial?.bindings ?? []).map((b) => {
|
|
45
|
+
const spec = resourceTypes.find((t) => t.type === b.resourceType);
|
|
46
|
+
const preset = spec?.scopePresets.find((p) => sameSet(p.scopes, b.scopes));
|
|
47
|
+
return { resourceType: b.resourceType, resourceId: b.resourceId, resourceLabel: b.resourceLabel, presetId: preset?.id ?? "" };
|
|
48
|
+
}));
|
|
49
|
+
const firstLifetime = lifetimeDays[0];
|
|
50
|
+
const [lifetime, setLifetime] = useState(mode === "edit" ? KEEP : firstLifetime !== undefined ? String(firstLifetime) : NEVER);
|
|
51
|
+
const [problem, setProblem] = useState(null);
|
|
52
|
+
const bound = resourceMode === "bound" && canBind;
|
|
53
|
+
const modeLocked = !!fixedMode || !canBind;
|
|
54
|
+
// Scopes a bound key carries at key level, before the per-binding ones.
|
|
55
|
+
const keyScopes = useMemo(() => union(scopePresets, presetIds), [scopePresets, presetIds]);
|
|
56
|
+
const togglePreset = (id, on) => setPresetIds((ids) => (on ? [...ids, id] : ids.filter((x) => x !== id)));
|
|
57
|
+
const blankBinding = () => {
|
|
58
|
+
const t = resourceTypes[0];
|
|
59
|
+
return { resourceType: t.type, resourceId: "", presetId: t.scopePresets[0]?.id ?? "" };
|
|
60
|
+
};
|
|
61
|
+
const submit = () => {
|
|
62
|
+
const trimmed = name.trim();
|
|
63
|
+
if (!trimmed)
|
|
64
|
+
return setProblem("Give the key a name.");
|
|
65
|
+
if (!bound && scopePresets.length > 0 && presetIds.length === 0)
|
|
66
|
+
return setProblem("Choose at least one scope.");
|
|
67
|
+
const wire = [];
|
|
68
|
+
if (bound) {
|
|
69
|
+
if (bindings.length === 0)
|
|
70
|
+
return setProblem("A bound key needs at least one resource.");
|
|
71
|
+
for (const b of bindings) {
|
|
72
|
+
const spec = resourceTypes.find((t) => t.type === b.resourceType);
|
|
73
|
+
const preset = spec?.scopePresets.find((p) => p.id === b.presetId);
|
|
74
|
+
if (!b.resourceId)
|
|
75
|
+
return setProblem(`Choose a ${spec?.label.toLowerCase() ?? "resource"} for every binding.`);
|
|
76
|
+
if (!preset)
|
|
77
|
+
return setProblem(`Choose an access level for ${b.resourceLabel ?? b.resourceId}.`);
|
|
78
|
+
wire.push({ resourceType: b.resourceType, resourceId: b.resourceId, scopes: preset.scopes });
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
setProblem(null);
|
|
82
|
+
const desc = description.trim() || undefined;
|
|
83
|
+
if (mode === "create") {
|
|
84
|
+
const expiresAt = lifetime === NEVER ? undefined : new Date(Date.now() + Number(lifetime) * 86_400_000);
|
|
85
|
+
onCreate?.({ name: trimmed, description: desc, scopes: keyScopes, resourceMode: bound ? "bound" : "app_wide", bindings: wire, expiresAt });
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
const expiresAt = lifetime === KEEP ? undefined : lifetime === NEVER ? null : new Date(Date.now() + Number(lifetime) * 86_400_000);
|
|
89
|
+
onUpdate?.({
|
|
90
|
+
name: trimmed, description: desc ?? "", scopes: keyScopes,
|
|
91
|
+
bindings: bound ? wire : [],
|
|
92
|
+
...(expiresAt !== undefined ? { expiresAt } : {}),
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
return (_jsxs(Stack, { "$gap": 14, children: [_jsxs(FormGrid, { "$cols": 2, children: [_jsx(Field, { label: "Name", span: 2, children: _jsx(Input, { autoFocus: true, value: name, placeholder: "e.g. ci-deploy", maxLength: 64, onChange: (e) => setName(e.target.value) }) }), _jsx(Field, { label: "Description", hint: "Optional \u2014 what the key is for, for whoever finds it later.", span: 2, children: _jsx(TextArea, { value: description, maxLength: 512, onChange: (e) => setDescription(e.target.value) }) }), mode === "create" && ownerLabel ? (_jsx(Field, { label: "Belongs to", span: 2, children: _jsxs(OwnerLine, { children: [_jsx("b", { children: ownerLabel }), _jsx("span", { children: "\u2014 the key can never do more than its owner can." })] }) })) : null, !modeLocked ? (_jsx(Field, { label: "Reach", span: 2, hint: bound ? "Only the resources listed below, plus any key-level scopes." : "Everything the owner can reach, with the scopes below.", children: _jsx(Segmented, { options: [{ value: "app_wide", label: "App-wide" }, { value: "bound", label: "Bound to resources" }], value: resourceMode, onChange: setResourceMode }) })) : null, scopePresets.length > 0 ? (_jsx(Field, { label: bound ? "Key-level scopes" : "Scopes", span: 2, children: _jsx(Stack, { "$gap": 8, children: scopePresets.map((p) => (_jsx(CheckRow, { checked: presetIds.includes(p.id), onChange: (on) => togglePreset(p.id, on), label: p.label, desc: p.description ?? p.scopes.join(", "), title: p.scopes.join(" ") }, p.id))) }) })) : null, bound ? (_jsx(Field, { label: "Resources", span: 2, children: _jsx(RepeaterRows, { rows: bindings, onChange: setBindings, blank: blankBinding, addLabel: "Add resource", addVariant: "button", removeLabel: "Remove binding", emptyLabel: "No resources yet \u2014 the key cannot reach anything until one is added.", columns: resourceTypes.length > 1 ? "minmax(0, 1fr) minmax(0, 2fr) minmax(0, 1fr)" : "minmax(0, 2fr) minmax(0, 1fr)", max: 50, render: (row, patch) => {
|
|
97
|
+
const spec = resourceTypes.find((t) => t.type === row.resourceType) ?? resourceTypes[0];
|
|
98
|
+
const Picker = spec.Picker;
|
|
99
|
+
return (_jsxs(_Fragment, { children: [resourceTypes.length > 1 ? (_jsx(Select, { "aria-label": "Resource type", value: row.resourceType, disabled: busy, onChange: (e) => {
|
|
100
|
+
const next = resourceTypes.find((t) => t.type === e.target.value) ?? spec;
|
|
101
|
+
patch({ resourceType: next.type, resourceId: "", presetId: next.scopePresets[0]?.id ?? "" });
|
|
102
|
+
}, children: resourceTypes.map((t) => _jsx("option", { value: t.type, children: t.label }, t.type)) })) : null, _jsx(Picker, { value: row.resourceId, disabled: busy, onChange: (id, label) => patch({ ...row, resourceId: id, resourceLabel: label }) }), _jsxs(Select, { "aria-label": "Access level", value: row.presetId, disabled: busy, onChange: (e) => patch({ ...row, presetId: e.target.value }), children: [row.presetId ? null : _jsx("option", { value: "", children: "Access level\u2026" }), spec.scopePresets.map((p) => _jsx("option", { value: p.id, title: p.scopes.join(" "), children: p.label }, p.id))] })] }));
|
|
103
|
+
} }) })) : null, _jsx(Field, { label: mode === "edit" ? "Expiry" : "Lifetime", span: 2, hint: mode === "create" ? "Rotate by creating a new key before this one expires." : undefined, children: _jsxs(Select, { value: lifetime, disabled: busy, onChange: (e) => setLifetime(e.target.value), children: [mode === "edit" ? _jsx("option", { value: KEEP, children: "Keep current expiry" }) : null, lifetimeDays.map((d) => _jsx("option", { value: String(d), children: lifetimeLabel(d) }, d)), allowNoExpiry ? _jsx("option", { value: NEVER, children: "No expiry" }) : null] }) })] }), bound && keyScopes.length === 0 && bindings.length > 0 ? (_jsx(Hint, { "$size": 11.5, children: "The key reaches only the resources above; it carries no scopes of its own." })) : null, problem || error ? _jsx(InlineError, { style: { marginTop: 0 }, children: problem ?? error }) : null, _jsxs("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8 }, children: [_jsx(AppButton, { variant: "quiet", onClick: onCancel, disabled: busy, children: "Cancel" }), _jsx(AppButton, { variant: "grad", icon: mode === "create" ? "key" : "save", loading: busy, onClick: submit, children: mode === "create" ? "Create key" : "Save changes" })] })] }));
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=ApiKeyForm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ApiKeyForm.js","sourceRoot":"","sources":["../../src/kit/ApiKeyForm.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { type ApiKeyCreateInput, type ApiKeyResourceMode, type ApiKeyResourceTypeSpec, type ApiKeyScopePreset, type ApiKeyUpdateInput } from "./ApiKeyForm.tsx";
|
|
2
|
+
export type { ApiKeyCreateInput, ApiKeyResourceMode, ApiKeyResourceTypeSpec, ApiKeyScopePreset, ApiKeyUpdateInput };
|
|
3
|
+
/**
|
|
4
|
+
* ApiKeys: the one screen every product shows for the keys auth holds on its
|
|
5
|
+
* behalf — and the portal's view across products. API-agnostic: the host maps
|
|
6
|
+
* its wire type to `ApiKeyRow`, resolves owner labels, and supplies the
|
|
7
|
+
* callbacks. Omit `onCreate` for a read-only list (the portal never mints a
|
|
8
|
+
* key; only a product can vouch for the resources one is bound to).
|
|
9
|
+
*/
|
|
10
|
+
export type ApiKeyOwnerKind = "user" | "service_account" | "team" | "resource";
|
|
11
|
+
export interface ApiKeyBindingRow {
|
|
12
|
+
resourceType: string;
|
|
13
|
+
resourceId: string;
|
|
14
|
+
resourceLabel?: string | undefined;
|
|
15
|
+
scopes: string[];
|
|
16
|
+
effectiveScopes?: string[] | undefined;
|
|
17
|
+
}
|
|
18
|
+
export interface ApiKeyRow {
|
|
19
|
+
/** the key's URN */
|
|
20
|
+
id: string;
|
|
21
|
+
name: string;
|
|
22
|
+
description?: string | undefined;
|
|
23
|
+
/** rendered as `xk_<keyPrefix>…`, or `<legacyPrefix><keyPrefix>…` for an imported key */
|
|
24
|
+
keyPrefix: string;
|
|
25
|
+
legacyPrefix?: string | undefined;
|
|
26
|
+
applicationSlug?: string | undefined;
|
|
27
|
+
applicationName?: string | undefined;
|
|
28
|
+
/** the label is resolved by the host — "You", a team name, "bucket media" */
|
|
29
|
+
owner: {
|
|
30
|
+
kind: ApiKeyOwnerKind;
|
|
31
|
+
label: string;
|
|
32
|
+
};
|
|
33
|
+
identityless: boolean;
|
|
34
|
+
resourceMode: ApiKeyResourceMode;
|
|
35
|
+
/** key-level scopes as granted; a granted scope absent from effectiveScopes is drawn muted */
|
|
36
|
+
scopes: string[];
|
|
37
|
+
effectiveScopes?: string[] | undefined;
|
|
38
|
+
bindings: ApiKeyBindingRow[];
|
|
39
|
+
expiresAt?: Date | undefined;
|
|
40
|
+
lastUsedAt?: Date | undefined;
|
|
41
|
+
revokedAt?: Date | undefined;
|
|
42
|
+
createdAt: Date;
|
|
43
|
+
createdByLabel?: string | undefined;
|
|
44
|
+
}
|
|
45
|
+
export interface ApiKeysProps {
|
|
46
|
+
rows: ApiKeyRow[];
|
|
47
|
+
loading?: boolean | undefined;
|
|
48
|
+
includeRevoked: boolean;
|
|
49
|
+
onIncludeRevokedChange: (v: boolean) => void;
|
|
50
|
+
/** omit for a read-only view (the auth portal) */
|
|
51
|
+
onCreate?: ((input: ApiKeyCreateInput) => Promise<{
|
|
52
|
+
secret: string;
|
|
53
|
+
key: ApiKeyRow;
|
|
54
|
+
}>) | undefined;
|
|
55
|
+
onUpdate?: ((id: string, input: ApiKeyUpdateInput) => Promise<ApiKeyRow>) | undefined;
|
|
56
|
+
/** offered only when there is no onUpdate — the edit form renames too */
|
|
57
|
+
onRename?: ((id: string, name: string) => Promise<void>) | undefined;
|
|
58
|
+
onRevoke: (id: string) => Promise<void>;
|
|
59
|
+
/** key-level scope choices in the create/edit forms */
|
|
60
|
+
scopePresets?: ApiKeyScopePreset[] | undefined;
|
|
61
|
+
/** resource types a key may be bound to; absent → only app-wide keys can be created */
|
|
62
|
+
resourceTypes?: ApiKeyResourceTypeSpec[] | undefined;
|
|
63
|
+
/** fixed mode for created keys; absent → the person picks */
|
|
64
|
+
mode?: ApiKeyResourceMode | undefined;
|
|
65
|
+
/** who new keys belong to, shown in the create form */
|
|
66
|
+
ownerLabel?: string | undefined;
|
|
67
|
+
/** lifetime options in days; absent → 30, 90, 365. A required expiry is `allowNoExpiry={false}` */
|
|
68
|
+
lifetimeDays?: number[] | undefined;
|
|
69
|
+
allowNoExpiry?: boolean | undefined;
|
|
70
|
+
/** one table per application (the portal's view across products) */
|
|
71
|
+
groupByApplication?: boolean | undefined;
|
|
72
|
+
/** the revocation propagation note under the secret and in the revoke dialog */
|
|
73
|
+
revokeNote?: string | undefined;
|
|
74
|
+
emptyTitle?: string | undefined;
|
|
75
|
+
emptyBody?: string | undefined;
|
|
76
|
+
}
|
|
77
|
+
export declare const keyHint: (k: ApiKeyRow) => string;
|
|
78
|
+
export declare function ApiKeys({ rows, loading, includeRevoked, onIncludeRevokedChange, onCreate, onUpdate, onRename, onRevoke, scopePresets, resourceTypes, mode, ownerLabel, lifetimeDays, allowNoExpiry, groupByApplication, revokeNote, emptyTitle, emptyBody, }: ApiKeysProps): import("react").JSX.Element;
|
|
79
|
+
//# sourceMappingURL=ApiKeys.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ApiKeys.d.ts","sourceRoot":"","sources":["../../src/kit/ApiKeys.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo, useState } from "react";
|
|
3
|
+
import styled from "styled-components";
|
|
4
|
+
import { AppButton, IconButton } from "./Button.js";
|
|
5
|
+
import { StatusPill, Tag } from "./Badge.js";
|
|
6
|
+
import { DataTable } from "./DataTable.js";
|
|
7
|
+
import { EmptyState } from "./EmptyState.js";
|
|
8
|
+
import { ConfirmDialog, EntityModal, PromptDialog } from "./Modal.js";
|
|
9
|
+
import { Toggle } from "./Form.js";
|
|
10
|
+
import { Icon } from "./Icon.js";
|
|
11
|
+
import { Menu, MenuItem } from "./Menu.js";
|
|
12
|
+
import { SecretField } from "./Secret.js";
|
|
13
|
+
import { Ago, Cell, Faint, Hint } from "./Text.js";
|
|
14
|
+
import { Callout } from "./Blocks.js";
|
|
15
|
+
import { SectionHead } from "./Panel.js";
|
|
16
|
+
import { Row, Stack } from "./Layout.js";
|
|
17
|
+
import { ApiKeyForm, } from "./ApiKeyForm.js";
|
|
18
|
+
const DEFAULT_REVOKE_NOTE = "Revoked keys stop working within 30 seconds.";
|
|
19
|
+
const SOON_MS = 7 * 86_400_000;
|
|
20
|
+
const KIND_LABEL = {
|
|
21
|
+
user: "user", service_account: "service account", team: "team", resource: "resource",
|
|
22
|
+
};
|
|
23
|
+
const STATUS = {
|
|
24
|
+
active: { label: "Active", tone: "ok" },
|
|
25
|
+
soon: { label: "Expires soon", tone: "warn" },
|
|
26
|
+
expired: { label: "Expired", tone: "warn" },
|
|
27
|
+
revoked: { label: "Revoked", tone: "mut" },
|
|
28
|
+
};
|
|
29
|
+
function statusOf(k, now = Date.now()) {
|
|
30
|
+
if (k.revokedAt)
|
|
31
|
+
return "revoked";
|
|
32
|
+
if (k.expiresAt) {
|
|
33
|
+
const t = k.expiresAt.getTime();
|
|
34
|
+
if (t <= now)
|
|
35
|
+
return "expired";
|
|
36
|
+
if (t - now < SOON_MS)
|
|
37
|
+
return "soon";
|
|
38
|
+
}
|
|
39
|
+
return "active";
|
|
40
|
+
}
|
|
41
|
+
export const keyHint = (k) => `${k.legacyPrefix ?? "xk_"}${k.keyPrefix}…`;
|
|
42
|
+
const Tags = styled.span `
|
|
43
|
+
display: inline-flex;
|
|
44
|
+
flex-wrap: wrap;
|
|
45
|
+
gap: 4px;
|
|
46
|
+
max-width: 280px;
|
|
47
|
+
`;
|
|
48
|
+
// A granted scope the owner cannot currently exercise: still on the key, so
|
|
49
|
+
// still shown, but drawn as the dead letter it is.
|
|
50
|
+
const Ineffective = styled(Tag) `
|
|
51
|
+
opacity: 0.45;
|
|
52
|
+
border-style: dashed;
|
|
53
|
+
text-decoration: line-through;
|
|
54
|
+
`;
|
|
55
|
+
const Owner = styled.span `
|
|
56
|
+
display: inline-flex;
|
|
57
|
+
align-items: center;
|
|
58
|
+
gap: 6px;
|
|
59
|
+
min-width: 0;
|
|
60
|
+
> span:last-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
61
|
+
`;
|
|
62
|
+
const Bar = styled(Row) `
|
|
63
|
+
justify-content: space-between;
|
|
64
|
+
margin-bottom: 12px;
|
|
65
|
+
`;
|
|
66
|
+
// The application heading over each group: the Stack already spaces groups,
|
|
67
|
+
// so the kit heading's own top margin would double it.
|
|
68
|
+
const GroupHead = styled(SectionHead) `
|
|
69
|
+
margin: 0 0 8px;
|
|
70
|
+
`;
|
|
71
|
+
function ScopeTags({ scopes, effective, empty }) {
|
|
72
|
+
if (scopes.length === 0)
|
|
73
|
+
return _jsx(Faint, { children: empty });
|
|
74
|
+
return (_jsx(Tags, { children: scopes.map((s) => effective && !effective.includes(s)
|
|
75
|
+
? _jsx(Ineffective, { title: "not currently effective", children: s }, s)
|
|
76
|
+
: _jsx(Tag, { title: s, children: s }, s)) }));
|
|
77
|
+
}
|
|
78
|
+
function bindingLabel(b) {
|
|
79
|
+
return b.resourceLabel ?? `${b.resourceType} ${b.resourceId}`;
|
|
80
|
+
}
|
|
81
|
+
export function ApiKeys({ rows, loading, includeRevoked, onIncludeRevokedChange, onCreate, onUpdate, onRename, onRevoke, scopePresets, resourceTypes, mode, ownerLabel, lifetimeDays, allowNoExpiry, groupByApplication, revokeNote = DEFAULT_REVOKE_NOTE, emptyTitle = "No API keys", emptyBody, }) {
|
|
82
|
+
const [creating, setCreating] = useState(false);
|
|
83
|
+
const [editing, setEditing] = useState(null);
|
|
84
|
+
const [renaming, setRenaming] = useState(null);
|
|
85
|
+
const [revoking, setRevoking] = useState(null);
|
|
86
|
+
const [minted, setMinted] = useState(null);
|
|
87
|
+
const [busy, setBusy] = useState(false);
|
|
88
|
+
const [formError, setFormError] = useState(null);
|
|
89
|
+
const [lastError, setLastError] = useState(null);
|
|
90
|
+
const fail = (e) => String(e?.message ?? e);
|
|
91
|
+
const run = async (work, inForm) => {
|
|
92
|
+
setBusy(true);
|
|
93
|
+
setLastError(null);
|
|
94
|
+
if (inForm)
|
|
95
|
+
setFormError(null);
|
|
96
|
+
try {
|
|
97
|
+
return await work();
|
|
98
|
+
}
|
|
99
|
+
catch (e) {
|
|
100
|
+
(inForm ? setFormError : setLastError)(fail(e));
|
|
101
|
+
return undefined;
|
|
102
|
+
}
|
|
103
|
+
finally {
|
|
104
|
+
setBusy(false);
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
const create = async (input) => {
|
|
108
|
+
if (!onCreate)
|
|
109
|
+
return;
|
|
110
|
+
const out = await run(() => onCreate(input), true);
|
|
111
|
+
if (out) {
|
|
112
|
+
setCreating(false);
|
|
113
|
+
setMinted(out);
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
const update = async (input) => {
|
|
117
|
+
if (!onUpdate || !editing)
|
|
118
|
+
return;
|
|
119
|
+
const out = await run(() => onUpdate(editing.id, input), true);
|
|
120
|
+
if (out)
|
|
121
|
+
setEditing(null);
|
|
122
|
+
};
|
|
123
|
+
// Rename and revoke close either way: a failure has nothing to correct in a
|
|
124
|
+
// one-field dialog, so it is reported above the table instead.
|
|
125
|
+
const rename = async (name) => {
|
|
126
|
+
if (!onRename || !renaming)
|
|
127
|
+
return;
|
|
128
|
+
await run(() => onRename(renaming.id, name), false);
|
|
129
|
+
setRenaming(null);
|
|
130
|
+
};
|
|
131
|
+
const revoke = async () => {
|
|
132
|
+
if (!revoking)
|
|
133
|
+
return;
|
|
134
|
+
await run(() => onRevoke(revoking.id), false);
|
|
135
|
+
setRevoking(null);
|
|
136
|
+
};
|
|
137
|
+
const columns = useMemo(() => [
|
|
138
|
+
{
|
|
139
|
+
key: "name", head: "Key",
|
|
140
|
+
sortBy: (k) => k.name,
|
|
141
|
+
render: (k) => (_jsx(Cell, { title: k.name, sub: keyHint(k), ...(k.description ? { tooltip: k.description } : {}) })),
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
key: "owner", head: "Owner", hideBelow: 720,
|
|
145
|
+
sortBy: (k) => `${k.owner.kind} ${k.owner.label}`,
|
|
146
|
+
render: (k) => (_jsxs(Owner, { title: k.identityless ? "Identityless: the key acts as itself, on behalf of its owner" : "The key acts as its owner", children: [_jsx(Tag, { "$tone": k.identityless ? "mut" : "brand", children: KIND_LABEL[k.owner.kind] }), _jsx("span", { children: k.owner.label })] })),
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
key: "reach", head: "Reach", hideBelow: 960,
|
|
150
|
+
render: (k) => k.resourceMode === "app_wide" ? (_jsx(Faint, { children: "App-wide" })) : (_jsxs(Tags, { children: [k.bindings.slice(0, 3).map((b) => (_jsx(Tag, { title: `${bindingLabel(b)}: ${b.scopes.join(" ")}`, children: bindingLabel(b) }, `${b.resourceType}:${b.resourceId}`))), k.bindings.length > 3 ? _jsxs(Tag, { title: k.bindings.slice(3).map(bindingLabel).join(", "), children: ["+", k.bindings.length - 3] }) : null, k.bindings.length === 0 ? _jsx(Faint, { children: "No resources" }) : null] })),
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
key: "scopes", head: "Scopes", hideBelow: 1100,
|
|
154
|
+
render: (k) => _jsx(ScopeTags, { scopes: k.scopes, effective: k.effectiveScopes, empty: k.resourceMode === "bound" ? "Per resource" : "None" }),
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
key: "status", head: "Status", width: "150px",
|
|
158
|
+
sortBy: (k) => statusOf(k),
|
|
159
|
+
render: (k) => {
|
|
160
|
+
const s = statusOf(k);
|
|
161
|
+
return (_jsxs(Stack, { "$gap": 3, children: [_jsx(StatusPill, { "$tone": STATUS[s].tone, children: STATUS[s].label }), _jsx(Hint, { "$size": 11, style: { margin: 0 }, children: s === "revoked" ? _jsxs(_Fragment, { children: ["revoked ", _jsx(Ago, { at: k.revokedAt })] }) : k.expiresAt ? _jsxs(_Fragment, { children: ["expires ", _jsx(Ago, { at: k.expiresAt })] }) : "never expires" })] }));
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
key: "used", head: "Last used", width: "120px", hideBelow: 820,
|
|
166
|
+
sortBy: (k) => k.lastUsedAt?.getTime(),
|
|
167
|
+
render: (k) => (k.lastUsedAt ? _jsx(Ago, { at: k.lastUsedAt }) : _jsx(Faint, { children: "never" })),
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
key: "actions", head: "", width: "48px", align: "right",
|
|
171
|
+
render: (k) => (_jsxs(Menu, { width: 180, trigger: () => _jsx(IconButton, { "aria-label": "Key actions", title: "Actions", children: _jsx(Icon, { name: "more" }) }), children: [onUpdate ? _jsx(MenuItem, { icon: "edit", disabled: !!k.revokedAt, onClick: () => { setFormError(null); setEditing(k); }, children: "Edit" }) : null, !onUpdate && onRename ? _jsx(MenuItem, { icon: "edit", disabled: !!k.revokedAt, onClick: () => setRenaming(k), children: "Rename" }) : null, _jsx(MenuItem, { icon: "ban", danger: true, disabled: !!k.revokedAt, onClick: () => setRevoking(k), children: "Revoke\u2026" })] })),
|
|
172
|
+
},
|
|
173
|
+
], [onUpdate, onRename]);
|
|
174
|
+
const groups = useMemo(() => {
|
|
175
|
+
if (!groupByApplication)
|
|
176
|
+
return [{ id: "", label: "", rows }];
|
|
177
|
+
const by = new Map();
|
|
178
|
+
for (const k of rows) {
|
|
179
|
+
const id = k.applicationSlug ?? "";
|
|
180
|
+
const g = by.get(id) ?? { id, label: k.applicationName ?? k.applicationSlug ?? "Other", rows: [] };
|
|
181
|
+
g.rows.push(k);
|
|
182
|
+
by.set(id, g);
|
|
183
|
+
}
|
|
184
|
+
const out = [...by.values()].sort((a, b) => a.label.localeCompare(b.label));
|
|
185
|
+
// nothing to group yet (still loading, or genuinely empty): one table, so
|
|
186
|
+
// the skeleton or the empty state has somewhere to be
|
|
187
|
+
return out.length > 0 ? out : [{ id: "", label: "", rows: [] }];
|
|
188
|
+
}, [rows, groupByApplication]);
|
|
189
|
+
const createButton = onCreate ? (_jsx(AppButton, { variant: "grad", icon: "key", onClick: () => { setFormError(null); setCreating(true); }, children: "Create key" })) : null;
|
|
190
|
+
const empty = (_jsx(EmptyState, { icon: "key", title: emptyTitle, desc: emptyBody ?? (onCreate ? "Create a key to call the API without signing in." : "Keys products issue for you show up here."), action: createButton, compact: true }));
|
|
191
|
+
const search = (k) => `${k.name} ${keyHint(k)} ${k.owner.label} ${k.applicationName ?? ""} ${k.scopes.join(" ")}`;
|
|
192
|
+
return (_jsxs("div", { children: [_jsxs(Bar, { children: [_jsx(Toggle, { checked: includeRevoked, onChange: onIncludeRevokedChange, label: "Show revoked" }), createButton] }), lastError ? _jsx(Callout, { tone: "crit", title: "That did not go through", children: lastError }) : null, _jsx(Stack, { "$gap": 18, children: groups.map((g) => (_jsxs("div", { children: [groupByApplication && g.label ? _jsx(GroupHead, { children: g.label }) : null, _jsx(DataTable, { columns: columns, rows: g.rows, rowKey: (k) => k.id, loading: loading, empty: empty, defaultSort: { key: "name" }, ...(groupByApplication ? {} : { search, searchPlaceholder: "Filter keys…" }) })] }, g.id))) }), creating && onCreate ? (_jsx(EntityModal, { title: "Create API key", icon: "key", size: "lg", onClose: () => { if (!busy)
|
|
193
|
+
setCreating(false); }, children: _jsx(ApiKeyForm, { mode: "create", scopePresets: scopePresets, resourceTypes: resourceTypes, fixedMode: mode, ownerLabel: ownerLabel, lifetimeDays: lifetimeDays, allowNoExpiry: allowNoExpiry, busy: busy, error: formError, onCreate: create, onCancel: () => setCreating(false) }) })) : null, editing && onUpdate ? (_jsx(EntityModal, { title: "Edit API key", sub: keyHint(editing), icon: "key", size: "lg", onClose: () => { if (!busy)
|
|
194
|
+
setEditing(null); }, children: _jsx(ApiKeyForm, { mode: "edit", initial: editing, scopePresets: scopePresets, resourceTypes: resourceTypes, fixedMode: editing.resourceMode, lifetimeDays: lifetimeDays, allowNoExpiry: allowNoExpiry, busy: busy, error: formError, onUpdate: update, onCancel: () => setEditing(null) }) })) : null, minted ? (_jsx(EntityModal, { title: "API key created", sub: minted.key.name, icon: "key", size: "md", dismissable: false, onClose: () => setMinted(null), children: _jsxs(Stack, { children: [_jsx(Callout, { tone: "warn", title: "Copy it now", children: "This is the only time the secret is shown. Lose it and the only way back is a new key." }), _jsx(SecretField, { value: minted.secret, revealed: true, noReveal: true }), _jsx(Hint, { "$size": 11.5, style: { margin: 0 }, children: revokeNote }), _jsx(Row, { style: { justifyContent: "flex-end" }, children: _jsx(AppButton, { variant: "grad", icon: "check", onClick: () => setMinted(null), children: "I have copied it" }) })] }) })) : null, renaming ? (_jsx(PromptDialog, { title: "Rename key", sub: keyHint(renaming), label: "Name", initial: renaming.name, actionLabel: "Rename", busy: busy, validate: (name) => (name.trim().length > 64 ? "At most 64 characters." : null), onSubmit: (name) => void rename(name), onClose: () => { if (!busy)
|
|
195
|
+
setRenaming(null); } })) : null, revoking ? (_jsx(ConfirmDialog, { title: `Revoke ${revoking.name}?`, body: _jsxs(_Fragment, { children: ["Anything presenting ", _jsx("b", { children: keyHint(revoking) }), " is refused from then on. ", revokeNote, " The key stays in the list for the audit trail."] }), actionLabel: "Revoke key", typedValue: revoking.name, busy: busy, onConfirm: () => void revoke(), onClose: () => { if (!busy)
|
|
196
|
+
setRevoking(null); } })) : null] }));
|
|
197
|
+
}
|
|
198
|
+
//# sourceMappingURL=ApiKeys.js.map
|