Fix: move keys and model-load routes under /api/v1/admin prefix
CI / test (push) Failing after 12m38s

Routes now consistently under admin session auth:
- /api/v1/admin/keys (GET, POST, DELETE)
- /api/v1/admin/models/:name/load (POST)

Rebuilt frontend assets.
This commit is contained in:
2026-07-31 17:17:23 -04:00
parent 4d34c6d31a
commit ddc73957cb
18 changed files with 62 additions and 58 deletions
+6
View File
@@ -0,0 +1,6 @@
import{d as A,q as P,c as a,a as e,b as p,e as x,x as g,g as c,t as o,F as h,i as C,w as I,f as T,v as V,r,s as k,o as l}from"./index-DGy3EgY7.js";import{P as $}from"./plus-DEUh38TR.js";import{c as j}from"./createLucideIcon-C8BmASko.js";import{T as D}from"./trash-2-LJ7Ux6P7.js";/**
* @license lucide-vue-next v0.460.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const F=j("CopyIcon",[["rect",{width:"14",height:"14",x:"8",y:"8",rx:"2",ry:"2",key:"17jyea"}],["path",{d:"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2",key:"zix9uf"}]]),L={class:"flex items-center justify-between mb-6"},M={key:0,class:"text-text-muted"},S={key:1,class:"card mb-6 bg-success/5 border-success/20"},B={class:"flex items-center justify-between"},q={class:"mt-4 p-3 bg-background rounded-lg font-mono text-sm break-all"},z={class:"card"},U={class:"table"},E={class:"font-mono text-text-muted"},O=["onClick"],Y={key:1,class:"badge badge-info"},G={key:0},H={key:2,class:"fixed inset-0 bg-black/50 flex items-center justify-center z-50"},J={class:"card w-full max-w-md"},Q={class:"mb-4"},R={class:"flex gap-3 justify-end"},se=A({__name:"ApiKeys",setup(W){const m=r([]),y=r(!0),u=r(!1),d=r(""),i=r(null),v=r(!1);async function b(){y.value=!0;try{const s=await k.get("/api/v1/admin/keys");m.value=s.data}catch(s){console.error("Failed to fetch keys:",s)}finally{y.value=!1}}async function _(){try{const s=await k.post("/api/v1/admin/keys",{name:d.value});i.value=s.data,u.value=!1,d.value="",await b()}catch(s){console.error("Failed to create key:",s)}}async function K(s){if(confirm("Are you sure you want to revoke this key?"))try{await k.delete(`/api/v1/admin/keys/${s}`),await b()}catch(t){console.error("Failed to revoke key:",t)}}async function N(s){await navigator.clipboard.writeText(s),v.value=!0,setTimeout(()=>v.value=!1,2e3)}function w(s){return s?new Date(s).toLocaleString():"Never"}return P(b),(s,t)=>(l(),a("div",null,[e("div",L,[t[6]||(t[6]=e("h1",{class:"text-2xl font-bold"},"API Keys",-1)),e("button",{onClick:t[0]||(t[0]=n=>u.value=!0),class:"btn btn-primary"},[p(x($),{class:"w-4 h-4 mr-2"}),t[5]||(t[5]=g(" New Key ",-1))])]),y.value?(l(),a("div",M,"Loading...")):c("",!0),i.value?(l(),a("div",S,[e("div",B,[t[7]||(t[7]=e("div",null,[e("h3",{class:"font-semibold text-success"},"API Key Created"),e("p",{class:"text-sm text-text-muted mt-1"}," Copy this key now. You won't be able to see it again. ")],-1)),e("button",{onClick:t[1]||(t[1]=n=>N(i.value.key)),class:"btn btn-secondary"},[p(x(F),{class:"w-4 h-4 mr-2"}),g(" "+o(v.value?"Copied!":"Copy"),1)])]),e("div",q,o(i.value.key),1),e("button",{onClick:t[2]||(t[2]=n=>i.value=null),class:"mt-4 text-sm text-text-muted hover:text-text"}," Close ")])):c("",!0),e("div",z,[e("table",U,[t[9]||(t[9]=e("thead",null,[e("tr",null,[e("th",null,"Name"),e("th",null,"Prefix"),e("th",null,"Scopes"),e("th",null,"Owner"),e("th",null,"Created"),e("th",null,"Last Used"),e("th",null,"Actions")])],-1)),e("tbody",null,[(l(!0),a(h,null,C(m.value,n=>(l(),a("tr",{key:n.id},[e("td",null,o(n.name),1),e("td",E,o(n.key_prefix)+"...",1),e("td",null,[(l(!0),a(h,null,C(n.scopes,f=>(l(),a("span",{key:f,class:"badge mr-1"},o(f),1))),128))]),e("td",null,o(n.owner_label||"-"),1),e("td",null,o(w(n.created_at)),1),e("td",null,o(w(n.last_used_at)),1),e("td",null,[n.is_admin?(l(),a("span",Y,"Admin")):(l(),a("button",{key:0,onClick:f=>K(n.id),class:"btn btn-danger btn-sm"},[p(x(D),{class:"w-4 h-4"})],8,O))])]))),128)),m.value.length===0?(l(),a("tr",G,[...t[8]||(t[8]=[e("td",{colspan:"7",class:"text-center text-text-muted py-8"}," No API keys yet. Create one to get started. ",-1)])])):c("",!0)])])]),u.value?(l(),a("div",H,[e("div",J,[t[12]||(t[12]=e("h2",{class:"text-lg font-semibold mb-4"},"Create API Key",-1)),e("form",{onSubmit:I(_,["prevent"])},[e("div",Q,[t[10]||(t[10]=e("label",{class:"block text-sm font-medium mb-2"},"Key Name",-1)),T(e("input",{"onUpdate:modelValue":t[3]||(t[3]=n=>d.value=n),type:"text",class:"input",placeholder:"My API Key",required:""},null,512),[[V,d.value]])]),e("div",R,[e("button",{type:"button",onClick:t[4]||(t[4]=n=>u.value=!1),class:"btn btn-secondary"}," Cancel "),t[11]||(t[11]=e("button",{type:"submit",class:"btn btn-primary"},"Create",-1))])],32)])])):c("",!0)]))}});export{se as default};