key-details-dialog.tsx 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. import { FileKey } from 'lucide-react'
  2. import { useMemo } from 'react'
  3. import {
  4. Button,
  5. DialogFooter,
  6. DialogHeader,
  7. DialogSection,
  8. DialogSectionSeparator,
  9. DialogTitle,
  10. Input,
  11. Label,
  12. Textarea,
  13. } from 'ui'
  14. import CopyButton from '@/components/ui/CopyButton'
  15. import { JWTSigningKey } from '@/data/jwt-signing-keys/jwt-signing-keys-query'
  16. export function KeyDetailsDialog({
  17. selectedKey,
  18. restURL,
  19. onClose,
  20. }: {
  21. selectedKey: JWTSigningKey
  22. restURL: string
  23. onClose: () => void
  24. }) {
  25. const jwksURL = useMemo(() => new URL('/auth/v1/.well-known/jwks.json', restURL), [restURL])
  26. const jwks = useMemo(
  27. () => JSON.stringify({ keys: [selectedKey.public_jwk] }, null, 2),
  28. [selectedKey]
  29. )
  30. return (
  31. <>
  32. <DialogHeader>
  33. <DialogTitle>Key Details</DialogTitle>
  34. </DialogHeader>
  35. <DialogSectionSeparator />
  36. <DialogSection className="flex flex-col gap-6">
  37. <div className="flex flex-col gap-2">
  38. <Label htmlFor="key-id">Key ID</Label>
  39. <Input id="key-id" value={selectedKey.id} readOnly />
  40. </div>
  41. <div className="flex flex-col gap-2">
  42. <Label htmlFor="discovery-url">Discovery URL</Label>
  43. <Input id="discovery-url" value={jwksURL.href} readOnly />
  44. </div>
  45. <div className="flex flex-col gap-2">
  46. <Label htmlFor="jwk" className="flex flex-row gap-2 items-center">
  47. <FileKey className="size-4 text-foreground-light" />
  48. Public key set (JSON Web Key Set format)
  49. </Label>
  50. <div className="relative">
  51. <Textarea className="font-mono text-sm pr-10" rows={8} value={jwks} readOnly />
  52. <CopyButton
  53. type="default"
  54. iconOnly
  55. text={jwks}
  56. className="absolute top-2 right-2"
  57. copyLabel="Copy JWKS"
  58. />
  59. </div>
  60. </div>
  61. </DialogSection>
  62. <DialogFooter>
  63. <Button onClick={() => onClose()}>OK</Button>
  64. </DialogFooter>
  65. </>
  66. )
  67. }