-
Notifications
You must be signed in to change notification settings - Fork 66
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
1900c1d
commit ae38834
Showing
22 changed files
with
862 additions
and
92 deletions.
There are no files selected for viewing
34 changes: 34 additions & 0 deletions
34
...n-active)/(dashboard)/env/[environmentSlug]/manage/signing-key/CreateSigningKeyButton.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
'use client'; | ||
|
||
import { Button } from '@inngest/components/Button'; | ||
import { RiAddLine } from '@remixicon/react'; | ||
import { useMutation } from 'urql'; | ||
|
||
import { graphql } from '@/gql'; | ||
|
||
const Mutation = graphql(` | ||
mutation CreateSigningKey($envID: UUID!) { | ||
createSigningKey(envID: $envID) { | ||
createdAt | ||
} | ||
} | ||
`); | ||
|
||
type Props = { | ||
disabled?: boolean; | ||
envID: string; | ||
}; | ||
|
||
export function CreateSigningKeyButton({ disabled, envID }: Props) { | ||
const [, createSigningKey] = useMutation(Mutation); | ||
|
||
return ( | ||
<Button | ||
btnAction={() => createSigningKey({ envID })} | ||
disabled={disabled} | ||
kind="primary" | ||
icon={<RiAddLine />} | ||
label="Create new signing key" | ||
/> | ||
); | ||
} |
35 changes: 35 additions & 0 deletions
35
...nv/[environmentSlug]/manage/signing-key/DeleteSigningKeyButton/DeleteSigningKeyButton.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
'use client'; | ||
|
||
import { useState } from 'react'; | ||
import { Button } from '@inngest/components/Button'; | ||
import { RiDeleteBin2Line } from '@remixicon/react'; | ||
|
||
import { DeleteSigningKeyModal } from './DeleteSigningKeyModal'; | ||
|
||
type Props = { | ||
signingKeyID: string; | ||
}; | ||
|
||
export function DeleteSigningKeyButton({ signingKeyID }: Props) { | ||
const [isModalOpen, setIsModalOpen] = useState(false); | ||
|
||
return ( | ||
<> | ||
<Button | ||
appearance="outlined" | ||
aria-label="Delete" | ||
btnAction={() => setIsModalOpen(true)} | ||
icon={<RiDeleteBin2Line />} | ||
kind="danger" | ||
size="small" | ||
tooltip="Delete" | ||
/> | ||
|
||
<DeleteSigningKeyModal | ||
isOpen={isModalOpen} | ||
onClose={() => setIsModalOpen(false)} | ||
signingKeyID={signingKeyID} | ||
/> | ||
</> | ||
); | ||
} |
93 changes: 93 additions & 0 deletions
93
...env/[environmentSlug]/manage/signing-key/DeleteSigningKeyButton/DeleteSigningKeyModal.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
import { useState } from 'react'; | ||
import { Alert } from '@inngest/components/Alert'; | ||
import { Button } from '@inngest/components/Button'; | ||
import { Modal } from '@inngest/components/Modal'; | ||
import { useMutation } from 'urql'; | ||
|
||
import { graphql } from '@/gql'; | ||
|
||
const Mutation = graphql(` | ||
mutation DeleteSigningKey($signingKeyID: UUID!) { | ||
deleteSigningKey(id: $signingKeyID) { | ||
createdAt | ||
} | ||
} | ||
`); | ||
|
||
type Props = { | ||
isOpen: boolean; | ||
onClose: () => void; | ||
signingKeyID: string; | ||
}; | ||
|
||
export function DeleteSigningKeyModal(props: Props) { | ||
const { isOpen, signingKeyID } = props; | ||
const [error, setError] = useState<string>(); | ||
const [isFetching, setIsFetching] = useState(false); | ||
const [, deleteSigningKey] = useMutation(Mutation); | ||
|
||
function onClose() { | ||
setError(undefined); | ||
props.onClose(); | ||
} | ||
|
||
async function onConfirm() { | ||
setIsFetching(true); | ||
try { | ||
const res = await deleteSigningKey( | ||
{ signingKeyID }, | ||
{ | ||
// Bust cache | ||
additionalTypenames: ['SigningKey'], | ||
} | ||
); | ||
if (res.error) { | ||
throw res.error; | ||
} | ||
|
||
onClose(); | ||
} catch (error) { | ||
if (!(error instanceof Error)) { | ||
setError('Unknown error'); | ||
return; | ||
} | ||
|
||
setError(error.message); | ||
} finally { | ||
setIsFetching(false); | ||
} | ||
} | ||
|
||
return ( | ||
<Modal className="w-full max-w-3xl" isOpen={isOpen} onClose={onClose}> | ||
<Modal.Header>Permanently delete key</Modal.Header> | ||
|
||
<Modal.Body> | ||
<p className="mb-4">Are you sure you want to permanently delete this key?</p> | ||
|
||
<Alert severity="info"> | ||
This key is inactive, so deletion will not affect communication between Inngest and your | ||
apps. | ||
</Alert> | ||
</Modal.Body> | ||
|
||
<Modal.Footer> | ||
{error && ( | ||
<Alert className="mb-6" severity="error"> | ||
{error} | ||
</Alert> | ||
)} | ||
|
||
<div className="flex justify-end gap-2"> | ||
<Button label="Close" appearance="outlined" btnAction={onClose} /> | ||
<Button | ||
btnAction={onConfirm} | ||
disabled={isFetching} | ||
kind="danger" | ||
label="Permanently delete" | ||
/> | ||
</div> | ||
</Modal.Footer> | ||
</Modal> | ||
); | ||
} |
1 change: 1 addition & 0 deletions
1
...ive)/(dashboard)/env/[environmentSlug]/manage/signing-key/DeleteSigningKeyButton/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { DeleteSigningKeyButton } from './DeleteSigningKeyButton'; |
12 changes: 10 additions & 2 deletions
12
...(organization-active)/(dashboard)/env/[environmentSlug]/manage/signing-key/InlineCode.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
32 changes: 32 additions & 0 deletions
32
...nv/[environmentSlug]/manage/signing-key/RotateSigningKeyButton/RotateSigningKeyButton.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
'use client'; | ||
|
||
import { useState } from 'react'; | ||
import { Button } from '@inngest/components/Button'; | ||
|
||
import { RotateSigningKeyModal } from './RotateSigningKeyModal'; | ||
|
||
type Props = { | ||
disabled?: boolean; | ||
envID: string; | ||
}; | ||
|
||
export function RotateSigningKeyButton({ disabled, envID }: Props) { | ||
const [isModalOpen, setIsModalOpen] = useState(false); | ||
|
||
return ( | ||
<> | ||
<Button | ||
btnAction={() => setIsModalOpen(true)} | ||
disabled={disabled} | ||
kind="danger" | ||
label="Rotate key" | ||
/> | ||
|
||
<RotateSigningKeyModal | ||
envID={envID} | ||
isOpen={isModalOpen} | ||
onClose={() => setIsModalOpen(false)} | ||
/> | ||
</> | ||
); | ||
} |
93 changes: 93 additions & 0 deletions
93
...env/[environmentSlug]/manage/signing-key/RotateSigningKeyButton/RotateSigningKeyModal.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
import { useState } from 'react'; | ||
import { Alert } from '@inngest/components/Alert'; | ||
import { Button } from '@inngest/components/Button'; | ||
import { Modal } from '@inngest/components/Modal'; | ||
import { useMutation } from 'urql'; | ||
|
||
import { graphql } from '@/gql'; | ||
import { InlineCode } from '../InlineCode'; | ||
|
||
const Mutation = graphql(` | ||
mutation RotateSigningKey($envID: UUID!) { | ||
rotateSigningKey(envID: $envID) { | ||
createdAt | ||
} | ||
} | ||
`); | ||
|
||
type Props = { | ||
envID: string; | ||
isOpen: boolean; | ||
onClose: () => void; | ||
}; | ||
|
||
export function RotateSigningKeyModal(props: Props) { | ||
const { envID, isOpen } = props; | ||
const [error, setError] = useState<string>(); | ||
const [isFetching, setIsFetching] = useState(false); | ||
const [, rotateSigningKey] = useMutation(Mutation); | ||
|
||
function onClose() { | ||
setError(undefined); | ||
props.onClose(); | ||
} | ||
|
||
async function onConfirm() { | ||
setIsFetching(true); | ||
try { | ||
const res = await rotateSigningKey( | ||
{ envID }, | ||
{ | ||
// Bust cache | ||
additionalTypenames: ['SigningKey'], | ||
} | ||
); | ||
if (res.error) { | ||
throw res.error; | ||
} | ||
|
||
setError(undefined); | ||
onClose(); | ||
} catch (error) { | ||
if (!(error instanceof Error)) { | ||
setError('Unknown error'); | ||
return; | ||
} | ||
|
||
setError(error.message); | ||
} finally { | ||
setIsFetching(false); | ||
} | ||
} | ||
|
||
return ( | ||
<Modal className="w-full max-w-3xl" isOpen={isOpen} onClose={onClose}> | ||
<Modal.Header>Rotate key</Modal.Header> | ||
|
||
<Modal.Body> | ||
<p className="mb-4"> | ||
Before rotating, ensure that all of your apps have the correct{' '} | ||
<InlineCode value="INNGEST_SIGNING_KEY" /> and{' '} | ||
<InlineCode value="INNGEST_SIGNING_KEY_FALLBACK" /> environment variables. | ||
</p> | ||
|
||
<Alert severity="warning"> | ||
This will permanently delete and replace the current key. It is irreversible. | ||
</Alert> | ||
</Modal.Body> | ||
|
||
<Modal.Footer> | ||
{error && ( | ||
<Alert className="mb-6" severity="error"> | ||
{error} | ||
</Alert> | ||
)} | ||
|
||
<div className="flex justify-end gap-2"> | ||
<Button label="Close" appearance="outlined" btnAction={onClose} /> | ||
<Button btnAction={onConfirm} disabled={isFetching} kind="danger" label="Rotate" /> | ||
</div> | ||
</Modal.Footer> | ||
</Modal> | ||
); | ||
} |
1 change: 1 addition & 0 deletions
1
...ive)/(dashboard)/env/[environmentSlug]/manage/signing-key/RotateSigningKeyButton/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { RotateSigningKeyButton } from './RotateSigningKeyButton'; |
75 changes: 75 additions & 0 deletions
75
...(organization-active)/(dashboard)/env/[environmentSlug]/manage/signing-key/SigningKey.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
import { Badge } from '@inngest/components/Badge'; | ||
import { Card } from '@inngest/components/Card'; | ||
import { RiStarFill } from '@remixicon/react'; | ||
|
||
import { Secret } from '@/components/Secret'; | ||
import { Time } from '@/components/Time'; | ||
import { DeleteSigningKeyButton } from './DeleteSigningKeyButton'; | ||
|
||
type Props = { | ||
signingKey: { | ||
createdAt: Date; | ||
decryptedValue: string; | ||
id: string; | ||
isActive: boolean; | ||
user: { | ||
email: string; | ||
name: string | null; | ||
} | null; | ||
}; | ||
}; | ||
|
||
export function SigningKey({ signingKey }: Props) { | ||
let accentColor = 'bg-emerald-600'; | ||
let controls = null; | ||
let description = null; | ||
let title = 'Current key'; | ||
|
||
if (!signingKey.isActive) { | ||
accentColor = 'bg-amber-400'; | ||
controls = ( | ||
<div className="flex gap-2"> | ||
<DeleteSigningKeyButton signingKeyID={signingKey.id} /> | ||
</div> | ||
); | ||
description = 'This key is inactive. You can activate it using rotation.'; | ||
title = 'New key'; | ||
} | ||
|
||
let pill = null; | ||
if (signingKey.createdAt > new Date(Date.now() - 24 * 60 * 60 * 1000)) { | ||
pill = ( | ||
<Badge className="border-0 bg-amber-100"> | ||
<RiStarFill className="text-amber-600" size={16} /> | ||
<span className="text-amber-600">New</span> | ||
</Badge> | ||
); | ||
} | ||
|
||
return ( | ||
<Card accentColor={accentColor} accentPosition="left" className="mb-4"> | ||
<Card.Content className="px-4 py-0"> | ||
<div className="py-4"> | ||
<div className="flex"> | ||
<div className="flex grow items-center gap-2 font-medium text-slate-950"> | ||
{title} | ||
{pill} | ||
</div> | ||
{controls && <div>{controls}</div>} | ||
</div> | ||
<p className="text-sm text-slate-500">{description}</p> | ||
</div> | ||
|
||
<Secret className="mb-4" kind="signing-key" secret={signingKey.decryptedValue} /> | ||
</Card.Content> | ||
|
||
<Card.Footer className="flex text-sm text-slate-500"> | ||
<span className="grow"> | ||
Created at <Time value={signingKey.createdAt} /> | ||
</span> | ||
|
||
{signingKey.user && <span>Created by {signingKey.user.name ?? signingKey.user.email}</span>} | ||
</Card.Footer> | ||
</Card> | ||
); | ||
} |
Oops, something went wrong.