Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/common/types/apiKey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ if (policySchemas.length === 0) {
})
}

const policyUnion = policySchemas.length > 0
export const policyUnion = policySchemas.length > 0
? z.discriminatedUnion("name", policySchemas as [typeof policySchemas[0], ...typeof policySchemas])
: z.never();

Expand Down
73 changes: 62 additions & 11 deletions src/ui/pages/apiKeys/ManageKeysTable.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import {
Alert,
Badge,
Button,
Center,
Checkbox,
Code,
CopyButton,
Group,
JsonInput,
List,
Modal,
MultiSelect,
Expand All @@ -18,6 +20,7 @@ import { DateTimePicker } from "@mantine/dates";
import {
IconAlertCircle,
IconEye,
IconHandStop,
IconPlus,
IconTrash,
} from "@tabler/icons-react";
Expand All @@ -26,13 +29,15 @@ import {
apiKeyAllowedRoles,
ApiKeyMaskedEntry,
ApiKeyPostBody,
policyUnion,
} from "@common/types/apiKey";
import { useAuth } from "@ui/components/AuthContext";
import { notifications } from "@mantine/notifications";
import pluralize from "pluralize";
import dayjs from "dayjs";
import { AppRoles } from "@common/roles";
import { BlurredTextDisplay } from "../../components/BlurredTextDisplay";
import { z } from "zod";

const HumanFriendlyDate = ({ date }: { date: number }) => {
return (
Expand Down Expand Up @@ -131,8 +136,8 @@ export const OrgApiKeyTable: React.FC<OrgApiKeyTableProps> = ({
await fetchKeys();
} catch (e) {
notifications.show({
title: "Create failed",
message: "Unable to create API key.",
title: "Unable to create API key.",
message: "Please try again or contact support.",
color: "red",
});
}
Expand Down Expand Up @@ -188,6 +193,7 @@ export const OrgApiKeyTable: React.FC<OrgApiKeyTableProps> = ({
const [roles, setRoles] = useState<AppRoles[]>([]);
const [description, setDescription] = useState("");
const [expiresAt, setExpiresAt] = useState<Date | null>(null);
const [policyDocument, setPolicyDocument] = useState("");

return (
<>
Expand Down Expand Up @@ -309,17 +315,62 @@ export const OrgApiKeyTable: React.FC<OrgApiKeyTableProps> = ({
clearable
mt="md"
/>
<JsonInput
label="Policy Document (optional)"
description={
<Alert
icon={<IconHandStop />}
title="Advanced Feature"
color="orange"
>
Errors in this field will prevent your API key from working!
Please consult the API documentation for instructions.
</Alert>
}
value={policyDocument}
onChange={setPolicyDocument}
placeholder={`[
{
"name": "EventsHostRestrictionPolicy",
"params": {
"host": [
"ACM"
]
}
}
]`}
validationError="Invalid JSON"
formatOnBlur
autosize
minRows={6}
/>
<Group justify="flex-end" mt="lg">
<Button
onClick={() =>
handleCreate({
roles,
description,
expiresAt: expiresAt
? Math.floor(expiresAt.getTime() / 1000)
: undefined,
})
}
onClick={() => {
let parsedPolicyDocument = undefined;
try {
if (policyDocument && policyDocument.trim() !== "") {
parsedPolicyDocument = z
.array(policyUnion)
.parse(JSON.parse(policyDocument));
}
handleCreate({
roles,
description,
expiresAt: expiresAt
? Math.floor(expiresAt.getTime() / 1000)
: undefined,
restrictions: parsedPolicyDocument,
});
} catch (e) {
console.error(e);
notifications.show({
title: "Invalid policy document!",
message: "Please correct the policy document and try again.",
color: "red",
});
}
}}
disabled={roles.length === 0 || description.trim() === ""}
>
Create
Expand Down
Loading