|
|
@@ -7,6 +7,11 @@ import { createStore } from "solid-js/store"
|
|
|
import { formatDateUTC, formatDateForTable } from "./common"
|
|
|
import styles from "./key-section.module.css"
|
|
|
import { Actor } from "@opencode-ai/console-core/actor.js"
|
|
|
+import { and, Database, eq, isNull, sql } from "@opencode-ai/console-core/drizzle/index.js"
|
|
|
+import { KeyTable } from "@opencode-ai/console-core/schema/key.sql.js"
|
|
|
+import { UserTable } from "@opencode-ai/console-core/schema/user.sql.js"
|
|
|
+import { AccountTable } from "@opencode-ai/console-core/schema/account.sql.js"
|
|
|
+import { User } from "@opencode-ai/console-core/user.js"
|
|
|
|
|
|
const removeKey = action(async (form: FormData) => {
|
|
|
"use server"
|
|
|
@@ -108,11 +113,6 @@ export function KeySection() {
|
|
|
const params = useParams()
|
|
|
const keys = createAsync(() => listKeys(params.id))
|
|
|
|
|
|
- function formatKey(key: string) {
|
|
|
- if (key.length <= 11) return key
|
|
|
- return `${key.slice(0, 7)}...${key.slice(-4)}`
|
|
|
- }
|
|
|
-
|
|
|
return (
|
|
|
<section class={styles.root}>
|
|
|
<div data-slot="section-title">
|
|
|
@@ -134,7 +134,8 @@ export function KeySection() {
|
|
|
<tr>
|
|
|
<th>Name</th>
|
|
|
<th>Key</th>
|
|
|
- <th>Created</th>
|
|
|
+ <th>Created By</th>
|
|
|
+ <th>Last Used</th>
|
|
|
<th></th>
|
|
|
</tr>
|
|
|
</thead>
|
|
|
@@ -147,24 +148,27 @@ export function KeySection() {
|
|
|
<tr>
|
|
|
<td data-slot="key-name">{key.name}</td>
|
|
|
<td data-slot="key-value">
|
|
|
- <button
|
|
|
- data-color="ghost"
|
|
|
- disabled={copied()}
|
|
|
- onClick={async () => {
|
|
|
- await navigator.clipboard.writeText(key.key)
|
|
|
- setCopied(true)
|
|
|
- setTimeout(() => setCopied(false), 1000)
|
|
|
- }}
|
|
|
- title="Copy API key"
|
|
|
- >
|
|
|
- <span>{formatKey(key.key)}</span>
|
|
|
- <Show when={copied()} fallback={<IconCopy style={{ width: "14px", height: "14px" }} />}>
|
|
|
- <IconCheck style={{ width: "14px", height: "14px" }} />
|
|
|
- </Show>
|
|
|
- </button>
|
|
|
+ <Show when={key.key} fallback={<span>{key.keyDisplay}</span>}>
|
|
|
+ <button
|
|
|
+ data-color="ghost"
|
|
|
+ disabled={copied()}
|
|
|
+ onClick={async () => {
|
|
|
+ await navigator.clipboard.writeText(key.key!)
|
|
|
+ setCopied(true)
|
|
|
+ setTimeout(() => setCopied(false), 1000)
|
|
|
+ }}
|
|
|
+ title="Copy API key"
|
|
|
+ >
|
|
|
+ <span>{key.keyDisplay}</span>
|
|
|
+ <Show when={copied()} fallback={<IconCopy style={{ width: "14px", height: "14px" }} />}>
|
|
|
+ <IconCheck style={{ width: "14px", height: "14px" }} />
|
|
|
+ </Show>
|
|
|
+ </button>
|
|
|
+ </Show>
|
|
|
</td>
|
|
|
- <td data-slot="key-date" title={formatDateUTC(key.timeCreated)}>
|
|
|
- {formatDateForTable(key.timeCreated)}
|
|
|
+ <td data-slot="key-user-email">{key.email}</td>
|
|
|
+ <td data-slot="key-last-used" title={key.timeUsed ? formatDateUTC(key.timeUsed) : undefined}>
|
|
|
+ {key.timeUsed ? formatDateForTable(key.timeUsed) : "-"}
|
|
|
</td>
|
|
|
<td data-slot="key-actions">
|
|
|
<form action={removeKey} method="post">
|