paskia 0.9.1__py3-none-any.whl → 0.10.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. paskia/_version.py +2 -2
  2. paskia/db/jsonl.py +2 -2
  3. paskia/db/logging.py +130 -45
  4. paskia/db/operations.py +8 -4
  5. paskia/fastapi/__main__.py +12 -6
  6. paskia/fastapi/admin.py +2 -2
  7. paskia/fastapi/api.py +7 -3
  8. paskia/fastapi/authz.py +3 -8
  9. paskia/fastapi/logging.py +64 -21
  10. paskia/fastapi/mainapp.py +2 -1
  11. paskia/fastapi/remote.py +11 -37
  12. paskia/fastapi/ws.py +12 -35
  13. paskia/fastapi/wschat.py +55 -2
  14. paskia/fastapi/wsutil.py +2 -7
  15. paskia/frontend-build/auth/admin/index.html +6 -6
  16. paskia/frontend-build/auth/assets/AccessDenied-C29NZI95.css +1 -0
  17. paskia/frontend-build/auth/assets/AccessDenied-DAdzg_MJ.js +12 -0
  18. paskia/frontend-build/auth/assets/{RestrictedAuth-CvR33_Z0.css → RestrictedAuth-BOdNrlQB.css} +1 -1
  19. paskia/frontend-build/auth/assets/{RestrictedAuth-DsJXicIw.js → RestrictedAuth-BSusdAfp.js} +1 -1
  20. paskia/frontend-build/auth/assets/_plugin-vue_export-helper-D2l53SUz.js +49 -0
  21. paskia/frontend-build/auth/assets/_plugin-vue_export-helper-DYJ24FZK.css +1 -0
  22. paskia/frontend-build/auth/assets/admin-BeFvGyD6.js +1 -0
  23. paskia/frontend-build/auth/assets/{admin-DzzjSg72.css → admin-CmNtuH3s.css} +1 -1
  24. paskia/frontend-build/auth/assets/{auth-C7k64Wad.css → auth-BKq4T2K2.css} +1 -1
  25. paskia/frontend-build/auth/assets/auth-DvHf8hgy.js +1 -0
  26. paskia/frontend-build/auth/assets/{forward-DmqVHZ7e.js → forward-C86Jm_Uq.js} +1 -1
  27. paskia/frontend-build/auth/assets/reset-B8PlNXuP.css +1 -0
  28. paskia/frontend-build/auth/assets/reset-D71FG0VL.js +1 -0
  29. paskia/frontend-build/auth/assets/{restricted-D3AJx3_6.js → restricted-CW0drE_k.js} +1 -1
  30. paskia/frontend-build/auth/index.html +6 -6
  31. paskia/frontend-build/auth/restricted/index.html +5 -5
  32. paskia/frontend-build/int/forward/index.html +5 -5
  33. paskia/frontend-build/int/reset/index.html +4 -4
  34. {paskia-0.9.1.dist-info → paskia-0.10.0.dist-info}/METADATA +1 -1
  35. paskia-0.10.0.dist-info/RECORD +60 -0
  36. paskia/frontend-build/auth/assets/AccessDenied-DPkUS8LZ.css +0 -1
  37. paskia/frontend-build/auth/assets/AccessDenied-Fmeb6EtF.js +0 -8
  38. paskia/frontend-build/auth/assets/_plugin-vue_export-helper-BTzJAQlS.css +0 -1
  39. paskia/frontend-build/auth/assets/_plugin-vue_export-helper-nhjnO_bd.js +0 -2
  40. paskia/frontend-build/auth/assets/admin-CPE1pLMm.js +0 -1
  41. paskia/frontend-build/auth/assets/auth-YIZvPlW_.js +0 -1
  42. paskia/frontend-build/auth/assets/reset-Chtv69AT.css +0 -1
  43. paskia/frontend-build/auth/assets/reset-s20PATTN.js +0 -1
  44. paskia-0.9.1.dist-info/RECORD +0 -60
  45. {paskia-0.9.1.dist-info → paskia-0.10.0.dist-info}/WHEEL +0 -0
  46. {paskia-0.9.1.dist-info → paskia-0.10.0.dist-info}/entry_points.txt +0 -0
@@ -1 +0,0 @@
1
- import{_ as re,r as k,c as I,b as p,d as m,e as o,f as T,t as A,F as C,i as X,j as ke,C as te,B as G,D as ie,l as Se,L as $e,y as H,x as ae,E as De,H as P,A as Ye,k as z,h as ne,v as oe,z as ge,o as We,a as Ze,q as Qe,u as Xe,w as _e,J as et,K as tt}from"./_plugin-vue_export-helper-nhjnO_bd.js";import{u as Oe,U as st,_ as nt,a as ot,R as at,N as me,M as it,b as rt,L as lt,A as fe,B as ut,c as dt}from"./AccessDenied-Fmeb6EtF.js";import"./helpers-DzjFIx78.js";const ct={key:0},mt=["onClick"],ft=["onClick"],gt={class:"role-names"},vt={class:"center"},yt={key:0,class:"center"},pt=["onClick"],ht={key:0,class:"permissions-section"},bt={class:"matrix-scroll"},wt=["title"],$t=["title"],Dt={class:"display-text"},kt=["checked","onChange"],St={class:"perm-name-cell"},Ot={class:"perm-title"},Rt={class:"display-text"},Ct=["onClick"],At={class:"perm-id-info"},Ut={class:"id-text"},Et={class:"perm-domain"},Mt={class:"perm-members center"},Pt={class:"perm-actions center"},qt=["onClick"],xt={__name:"AdminOverview",props:{info:Object,orgs:Array,permissions:Array,permissionSummary:Object,navigationDisabled:{type:Boolean,default:!1}},emits:["createOrg","openOrg","updateOrg","deleteOrg","toggleOrgPermission","openDialog","deletePermission","renamePermissionDisplay","navigateOut"],setup(n,{expose:J,emit:Y}){const S=n,L=Y,E=k(null),c=k(null),y=k(null),q=k(null),N=k(null),K=k(null),x=I(()=>[...S.orgs].sort((r,t)=>{const s=r.display_name.localeCompare(t.display_name);return s!==0?s:r.uuid.localeCompare(t.uuid)})),w=I(()=>[...S.permissions].sort((r,t)=>r.scope.localeCompare(t.scope))),F=I(()=>S.info?.ctx.permissions.includes("auth:admin")),$=I(()=>S.info?.ctx.permissions.includes("auth:org:admin"));function _(r){return r.roles.slice().sort((t,s)=>t.display_name.localeCompare(s.display_name)).map(t=>t.display_name).join(", ")}function Z(r,t){if(S.navigationDisabled)return;const s=G(r);if(!s)return;const D=r.target,l=D.closest("tr");if(!l)return;const d=l.closest("tbody");if(!d)return;const h=Array.from(d.querySelectorAll("tr")),R=h.indexOf(l);if(R===-1)return;if(s==="left"||s==="right"){r.preventDefault();const M=Array.from(l.querySelectorAll("a, button:not([disabled])")),B=M.indexOf(D);if(B===-1)return;s==="left"&&B>0?M[B-1].focus():s==="right"&&B<M.length-1&&M[B+1].focus();return}let V=R;if(s==="up"&&R>0)V=R-1;else if(s==="down"&&R<h.length-1)V=R+1;else if(s==="up"&&R===0){r.preventDefault(),t==="org"?te(c.value,{itemSelector:"button"}):t==="perm"&&te(N.value,{itemSelector:"button"});return}else if(s==="down"&&R===h.length-1){if(r.preventDefault(),t==="org"&&F.value&&q.value){const M=q.value.querySelector('input[type="checkbox"]');M?M.focus():te(N.value,{itemSelector:"button"})}return}if(V!==R){r.preventDefault();const B=h[V].querySelector("a, button:not([disabled])");B&&B.focus()}}function ee(r){if(S.navigationDisabled)return;const t=G(r);if(t){if(r.preventDefault(),t==="left"||t==="right")ie(c.value,r.target,t,{itemSelector:"button"});else if(t==="up")L("navigateOut","up");else if(t==="down"){const s=y.value?.querySelector("tbody tr a, tbody tr button:not([disabled])");s&&s.focus()}}}function g(r){if(S.navigationDisabled)return;const t=G(r);if(!t)return;const s=r.target;if(s.tagName!=="INPUT")return;r.preventDefault();const D=Array.from(q.value.querySelectorAll('input[type="checkbox"]')),l=D.indexOf(s);if(l===-1)return;const d=x.value.length,h=w.value.length;if(d===0||h===0)return;const R=Math.floor(l/d),V=l%d;let M=l;if(t==="left")V>0&&(M=l-1);else if(t==="right")V<d-1&&(M=l+1);else if(t==="up")if(R>0)M=l-d;else{const le=y.value?.querySelector("tbody tr:last-child")?.querySelector("a, button:not([disabled])");le&&le.focus();return}else if(t==="down")if(R<h-1)M=l+d;else{te(N.value,{itemSelector:"button"});return}M!==l&&D[M]&&D[M].focus()}function u(r){if(S.navigationDisabled)return;const t=G(r);if(t){if(r.preventDefault(),t==="left"||t==="right")ie(N.value,r.target,t,{itemSelector:"button"});else if(t==="up"){const s=q.value?.querySelectorAll('input[type="checkbox"]');if(s?.length){const D=x.value.length,d=(w.value.length-1)*D;s[d]?s[d].focus():s[0].focus()}else{const l=y.value?.querySelector("tbody tr:last-child")?.querySelector("a, button:not([disabled])");l&&l.focus()}}else if(t==="down"){const s=K.value?.querySelector("tbody tr button:not([disabled])");s&&s.focus()}}}function f(){if(F.value)te(c.value,{itemSelector:"button"});else{const r=y.value?.querySelector("tbody tr a, tbody tr button:not([disabled])");r&&r.focus()}}return J({focusFirstElement:f}),(r,t)=>(m(),p(C,null,[o("div",{class:"permissions-section",ref_key:"orgSection",ref:E},[o("h2",null,A(F.value?"Organizations":"Your Organizations"),1),o("div",{class:"actions",ref_key:"orgActionsRef",ref:c,onKeydown:ee},[F.value?(m(),p("button",{key:0,onClick:t[0]||(t[0]=s=>r.$emit("createOrg"))},"+ Create Org")):T("",!0)],544),o("table",{class:"org-table",ref_key:"orgTableRef",ref:y,onKeydown:t[1]||(t[1]=s=>Z(s,"org"))},[o("thead",null,[o("tr",null,[t[4]||(t[4]=o("th",null,"Name",-1)),t[5]||(t[5]=o("th",null,"Roles",-1)),t[6]||(t[6]=o("th",null,"Members",-1)),F.value?(m(),p("th",ct,"Actions")):T("",!0)])]),o("tbody",null,[(m(!0),p(C,null,X(x.value,s=>(m(),p("tr",{key:s.uuid},[o("td",null,[o("a",{href:"#org/{{o.uuid}}",onClick:Se(D=>r.$emit("openOrg",s),["prevent"])},A(s.display_name),9,mt),F.value||$.value?(m(),p("button",{key:0,onClick:D=>r.$emit("updateOrg",s),class:"icon-btn edit-org-btn","aria-label":"Rename organization",title:"Rename organization"},"✏️",8,ft)):T("",!0)]),o("td",gt,A(_(s)),1),o("td",vt,A(s.roles.reduce((D,l)=>D+l.users.length,0)),1),F.value?(m(),p("td",yt,[o("button",{onClick:D=>r.$emit("deleteOrg",s),class:"icon-btn delete-icon","aria-label":"Delete organization",title:"Delete organization"},"❌",8,pt)])):T("",!0)]))),128))])],544)],512),F.value?(m(),p("div",ht,[t[10]||(t[10]=o("h2",null,"Permissions",-1)),o("div",{class:"matrix-wrapper",ref_key:"permMatrixRef",ref:q,onKeydown:g},[o("div",bt,[o("div",{class:"perm-matrix-grid",style:ke({gridTemplateColumns:"minmax(180px, 1fr) "+x.value.map(()=>"2.2rem").join(" ")})},[t[7]||(t[7]=o("div",{class:"grid-head perm-head"},"Permission",-1)),(m(!0),p(C,null,X(x.value,s=>(m(),p("div",{key:"head-"+s.uuid,class:"grid-head org-head",title:s.display_name},[o("span",null,A(s.display_name),1)],8,wt))),128)),(m(!0),p(C,null,X(w.value,s=>(m(),p(C,{key:s.uuid},[o("div",{class:"perm-name",title:s.scope},[o("span",Dt,A(s.display_name),1)],8,$t),(m(!0),p(C,null,X(x.value,D=>(m(),p("div",{key:D.uuid+"-"+s.uuid,class:"matrix-cell"},[o("input",{type:"checkbox",checked:D.permissions.includes(s.uuid),onChange:l=>r.$emit("toggleOrgPermission",D,s.uuid,l.target.checked)},null,40,kt)]))),128))],64))),128))],4)]),t[8]||(t[8]=o("p",{class:"matrix-hint muted"},"Toggle which permissions each organization can grant to its members.",-1))],544),o("div",{class:"actions",ref_key:"permActionsRef",ref:N,onKeydown:u},[F.value?(m(),p("button",{key:0,onClick:t[2]||(t[2]=s=>r.$emit("openDialog","perm-create",{display_name:"",scope:"",domain:""}))},"+ Create Permission")):T("",!0)],544),o("table",{class:"org-table",ref_key:"permTableRef",ref:K,onKeydown:t[3]||(t[3]=s=>Z(s,"perm"))},[t[9]||(t[9]=o("thead",null,[o("tr",null,[o("th",{scope:"col"},"Permission"),o("th",{scope:"col"},"Domain"),o("th",{scope:"col",class:"center"},"Members"),o("th",{scope:"col",class:"center"},"Actions")])],-1)),o("tbody",null,[(m(!0),p(C,null,X(w.value,s=>(m(),p("tr",{key:s.uuid},[o("td",St,[o("div",Ot,[o("span",Rt,A(s.display_name),1),o("button",{onClick:D=>r.$emit("renamePermissionDisplay",s),class:"icon-btn edit-display-btn","aria-label":"Edit permission",title:"Edit permission"},"✏️",8,Ct)]),o("div",At,[o("span",Ut,A(s.scope),1)])]),o("td",Et,A(s.domain||"—"),1),o("td",Mt,A(n.permissionSummary[s.uuid]?.userCount||0),1),o("td",Pt,[o("button",{onClick:D=>r.$emit("deletePermission",s),class:"icon-btn delete-icon","aria-label":"Delete permission",title:"Delete permission"},"❌",8,qt)])]))),128))])],544)])):T("",!0)],64))}},Nt=re(xt,[["__scopeId","data-v-56228c4a"]]),Tt=["title"],Lt={class:"org-name"},Ft={class:"matrix-scroll"},It=["title"],Kt=["title"],Bt=["checked","onChange"],zt=["onDrop"],Vt=["onKeydown"],jt=["title"],Ht=["onClick"],Gt={class:"role-actions"},Jt=["onClick"],Yt=["onDragstart","onClick","onKeydown","title"],Wt={class:"name"},Zt={class:"meta"},Qt=["onKeydown"],Xt=["onClick"],_t={__name:"AdminOrgDetail",props:{selectedOrg:Object,permissions:Array,navigationDisabled:{type:Boolean,default:!1}},emits:["updateOrg","createRole","updateRole","deleteRole","createUserInRole","openUser","toggleRolePermission","onRoleDragOver","onRoleDrop","onUserDragStart","navigateOut"],setup(n,{expose:J,emit:Y}){const S=n,L=Y,E=k(null),c=k(null),y=k(null),q=I(()=>[...S.selectedOrg.roles].sort((g,u)=>{const f=g.display_name.toLowerCase(),r=u.display_name.toLowerCase();return f!==r?f.localeCompare(r):g.uuid.localeCompare(u.uuid)})),N=I(()=>{const g=new Set(S.selectedOrg.permissions||[]);return S.permissions.filter(u=>g.has(u.uuid))});function K(g,u,f){L("toggleRolePermission",g,u,f)}function x(g){if(S.navigationDisabled)return;const u=G(g);if(u){if(g.preventDefault(),u==="left"||u==="right")ie(E.value,g.target,u,{itemSelector:"button"});else if(u==="up")L("navigateOut","up");else if(u==="down"){const f=c.value?.querySelector('input[type="checkbox"]');f?f.focus():Z()}}}function w(g){if(S.navigationDisabled)return;const u=G(g);if(!u)return;const f=g.target;if(f.tagName!=="INPUT")return;g.preventDefault();const r=Array.from(c.value.querySelectorAll('input[type="checkbox"]')),t=r.indexOf(f);if(t===-1)return;const s=q.value.length,D=S.selectedOrg.permissions.length,l=Math.floor(t/s),d=t%s;let h=t;if(u==="left"&&d>0)h=t-1;else if(u==="right"&&d<s-1)h=t+1;else if(u==="up"&&l>0)h=t-s;else if(u==="down"&&l<D-1)h=t+s;else if(u==="up"&&l===0){const R=E.value?.querySelector("button");R&&R.focus();return}else if(u==="down"&&l===D-1){Z();return}h!==t&&r[h]&&r[h].focus()}function F(g){if(S.navigationDisabled)return;const u=G(g);if(!u)return;const f=g.target;if(!f.classList.contains("user-chip"))return;const r=f.closest(".user-list");if(!r)return;const t=Array.from(r.querySelectorAll(".user-chip")),s=t.indexOf(f);if(s!==-1){if(u==="up"&&s>0){g.preventDefault(),t[s-1].focus();return}else if(u==="down"&&s<t.length-1){g.preventDefault(),t[s+1].focus();return}if(u==="up"&&s===0){g.preventDefault();const l=r.closest(".role-column")?.querySelector(".role-header button");l&&l.focus();return}if(!(u==="down"&&s===t.length-1)&&(u==="left"||u==="right")){g.preventDefault();const D=Array.from(y.value?.querySelectorAll(".role-column")||[]),l=r.closest(".role-column"),d=D.indexOf(l);let h=u==="left"?d-1:d+1;if(h>=0&&h<D.length){const R=D[h],V=R.querySelectorAll(".user-chip"),M=Math.min(s,V.length-1);if(V[M])V[M].focus();else{const B=R.querySelector(".plus-btn");B&&B.focus()}}else if(u==="left"&&d===0){const R=c.value?.querySelector('input[type="checkbox"]:last-of-type');R&&R.focus()}}}}function $(g,u){if(S.navigationDisabled)return;const f=G(g);if(!f)return;const r=Array.from(y.value?.querySelectorAll(".role-column")||[]);if(f==="left"||f==="right"){g.preventDefault();const t=g.currentTarget.querySelectorAll("button:not([disabled])"),s=Array.from(t).indexOf(g.target);if(f==="left"&&s>0)t[s-1].focus();else if(f==="right"&&s<t.length-1)t[s+1].focus();else if(f==="left"&&s===0&&u>0){const l=r[u-1]?.querySelectorAll(".role-header button");l?.length&&l[l.length-1].focus()}else if(f==="right"&&s===t.length-1&&u<r.length-1){const l=r[u+1]?.querySelector(".role-header button");l&&l.focus()}}else if(f==="up"){g.preventDefault();const t=c.value?.querySelectorAll('input[type="checkbox"]');if(t?.length){const s=q.value.length,l=(S.selectedOrg.permissions.length-1)*s+u;t[l]?t[l].focus():t[t.length-1].focus()}else{const s=E.value?.querySelector("button");s&&s.focus()}}else if(f==="down"){g.preventDefault();const s=r[u]?.querySelector(".user-chip");s&&s.focus()}}function _(g,u){if(S.navigationDisabled)return;const f=G(g);if(!f)return;const r=Array.from(y.value?.querySelectorAll(".role-column")||[]);if(f==="up"){g.preventDefault();const s=r[u]?.querySelector(".role-header button");s&&s.focus()}else if(f==="left"&&u>0){g.preventDefault();const t=r[u-1],s=t?.querySelector(".empty-role button"),D=t?.querySelector(".user-chip:last-child");s?s.focus():D&&D.focus()}else if(f==="right"&&u<r.length-1){g.preventDefault();const t=r[u+1],s=t?.querySelector(".empty-role button"),D=t?.querySelector(".user-chip");s?s.focus():D&&D.focus()}}function Z(){const u=y.value?.querySelector(".role-column")?.querySelector(".role-header button");u&&u.focus()}function ee(){const g=E.value?.querySelector("button");g&&g.focus()}return J({focusFirstElement:ee}),(g,u)=>(m(),p(C,null,[o("h2",{class:"org-title",ref_key:"orgTitleRef",ref:E,onKeydown:x,title:n.selectedOrg.uuid},[o("span",Lt,A(n.selectedOrg.display_name),1),o("button",{onClick:u[0]||(u[0]=f=>g.$emit("updateOrg",n.selectedOrg)),class:"icon-btn","aria-label":"Rename organization",title:"Rename organization"},"✏️")],40,Tt),o("div",{class:"matrix-wrapper",ref_key:"permMatrixRef",ref:c,onKeydown:w},[o("div",Ft,[o("div",{class:"perm-matrix-grid",style:ke({gridTemplateColumns:"minmax(180px, 1fr) "+q.value.map(()=>"2.2rem").join(" ")+" 2.2rem"})},[u[5]||(u[5]=o("div",{class:"grid-head perm-head"},"Permission",-1)),(m(!0),p(C,null,X(q.value,f=>(m(),p("div",{key:"head-"+f.uuid,class:"grid-head role-head",title:f.display_name},[o("span",null,A(f.display_name),1)],8,It))),128)),o("div",{class:"grid-head role-head add-role-head",title:"Add role",onClick:u[1]||(u[1]=f=>g.$emit("createRole",n.selectedOrg)),role:"button",tabindex:"0",onKeydown:u[2]||(u[2]=$e(f=>g.$emit("createRole",n.selectedOrg),["enter"]))},"➕",32),(m(!0),p(C,null,X(N.value,f=>(m(),p(C,{key:f.uuid},[o("div",{class:"perm-name",title:f.scope},A(f.display_name),9,Kt),(m(!0),p(C,null,X(q.value,r=>(m(),p("div",{key:r.uuid+"-"+f.uuid,class:"matrix-cell"},[o("input",{type:"checkbox",checked:r.permissions.includes(f.uuid),onChange:t=>K(r,f.uuid,t.target.checked)},null,40,Bt)]))),128)),u[4]||(u[4]=o("div",{class:"matrix-cell add-role-cell"},null,-1))],64))),128))],4)]),u[6]||(u[6]=o("p",{class:"matrix-hint muted"},"Toggle which permissions each role grants.",-1))],544),o("div",{class:"roles-grid",ref_key:"rolesGridRef",ref:y},[(m(!0),p(C,null,X(q.value,(f,r)=>(m(),p("div",{key:f.uuid,class:"role-column",onDragover:u[3]||(u[3]=t=>g.$emit("onRoleDragOver",t)),onDrop:t=>g.$emit("onRoleDrop",t,n.selectedOrg,f)},[o("div",{class:"role-header",onKeydown:t=>$(t,r)},[o("strong",{class:"role-name",title:f.uuid},[o("span",null,A(f.display_name),1),o("button",{onClick:t=>g.$emit("updateRole",f),class:"icon-btn","aria-label":"Edit role",title:"Edit role"},"✏️",8,Ht)],8,jt),o("div",Gt,[o("button",{onClick:t=>g.$emit("createUserInRole",n.selectedOrg,f),class:"plus-btn","aria-label":"Add user",title:"Add user"},"➕",8,Jt)])],40,Vt),f.users.length>0?(m(),p("ul",{key:0,class:"user-list",onKeydown:F},[(m(!0),p(C,null,X(f.users.slice().sort((t,s)=>{const D=t.display_name.toLowerCase(),l=s.display_name.toLowerCase();return D!==l?D.localeCompare(l):t.uuid.localeCompare(s.uuid)}),t=>(m(),p("li",{key:t.uuid,class:"user-chip",tabindex:"0",draggable:"true",onDragstart:s=>g.$emit("onUserDragStart",s,t,n.selectedOrg.uuid),onClick:s=>g.$emit("openUser",t),onKeydown:$e(s=>g.$emit("openUser",t),["enter"]),title:t.uuid},[o("span",Wt,A(t.display_name),1),o("span",Zt,A(t.last_seen?new Date(t.last_seen).toLocaleDateString():"—"),1)],40,Yt))),128))],32)):(m(),p("div",{key:1,class:"empty-role",onKeydown:t=>_(t,r)},[u[7]||(u[7]=o("p",{class:"empty-text muted"},"No members",-1)),o("button",{onClick:t=>g.$emit("deleteRole",f),class:"icon-btn delete-icon","aria-label":"Delete empty role",title:"Delete role"},"❌",8,Xt)],40,Qt))],40,zt))),128))],512)],64))}},es=re(_t,[["__scopeId","data-v-f76fbbc3"]]),ts={class:"user-detail"},ss={key:0,class:"error small"},ns=["disabled"],os={class:"section-block","data-section":"registered-passkeys"},as={class:"section-body"},is={__name:"AdminUserDetail",props:{selectedUser:Object,userDetail:Object,selectedOrg:Object,loading:Boolean,showRegModal:Boolean,navigationDisabled:{type:Boolean,default:!1}},emits:["generateUserRegistrationLink","goOverview","openOrg","onUserNameSaved","closeRegModal","editUserName","refreshUserDetail","navigateOut"],setup(n,{expose:J,emit:Y}){const S=n,L=Y,E=Oe(),c=k({}),y=k(null),q=k(null),N=k(null),K=k(null),x=k(null),w=k(null),F=k(null),$=I(()=>S.showRegModal);function _(){E.showMessage(`📋 Link copied! Send it to ${S.selectedUser.display_name}.`),L("closeRegModal")}function Z(){L("editUserName",S.selectedUser)}async function ee(l){try{const d=await P(`/auth/api/admin/orgs/${S.selectedUser.org}/users/${S.selectedUser.uuid}/credentials/${l.credential}`,{method:"DELETE"});d.status==="ok"?L("onUserNameSaved"):console.error("Failed to delete credential",d)}catch(d){console.error("Delete credential error",d)}}async function g(l){const d=l?.id;if(d){c.value={...c.value,[d]:!0};try{const h=await P(`/auth/api/admin/orgs/${S.selectedUser.org}/users/${S.selectedUser.uuid}/sessions/${d}`,{method:"DELETE"});if(h.status==="ok"){if(h.current_session_terminated){sessionStorage.clear(),location.reload();return}L("refreshUserDetail"),E.showMessage("Session terminated","success",2500)}else E.showMessage(h.detail||"Failed to terminate session","error")}catch(h){console.error("Terminate session error",h),E.showMessage(h.message||"Failed to terminate session","error")}finally{const h={...c.value};delete h[d],c.value=h}}}function u(l){if($.value||S.navigationDisabled)return;const d=G(l);d&&(l.preventDefault(),d==="left"||d==="right"?ie(N.value,l.target,d,{itemSelector:".mini-btn"}):d==="up"?L("navigateOut","up"):d==="down"&&te(K.value,{itemSelector:"button"}))}function f(l){if($.value||S.navigationDisabled)return;const d=G(l);d&&(l.preventDefault(),d==="left"||d==="right"?ie(K.value,l.target,d,{itemSelector:"button"}):d==="up"?te(N.value,{itemSelector:".mini-btn"}):d==="down"&&x.value?.$el?.focus())}function r(l){$.value||S.navigationDisabled||(l==="up"?te(K.value,{itemSelector:"button"}):l==="down"&&De(w.value?.$el,0,{itemSelector:".session-group"}))}function t(l){if(!($.value||S.navigationDisabled)){if(l==="up")x.value?.$el?.focus();else if(l==="down"){const d=F.value?.querySelector("button");d&&d.focus()}}}function s(l){if($.value||S.navigationDisabled)return;const d=G(l);d&&(l.preventDefault(),d==="up"&&De(w.value?.$el,-1,{itemSelector:".session-group"}))}function D(){te(N.value,{itemSelector:".mini-btn"})}return J({focusFirstElement:D}),(l,d)=>(m(),p("div",ts,[o("div",{ref_key:"userInfoRef",ref:N,onKeydown:u},[n.userDetail&&!n.userDetail.error?(m(),H(st,{key:0,name:n.userDetail.display_name||n.selectedUser.display_name,visits:n.userDetail.visits,"created-at":n.userDetail.created_at,"last-seen":n.userDetail.last_seen,loading:n.loading,"org-display-name":n.userDetail.org.display_name,"role-name":n.userDetail.role,"update-endpoint":`/auth/api/admin/orgs/${n.selectedUser.org}/users/${n.selectedUser.uuid}/display-name`,onSaved:d[0]||(d[0]=h=>l.$emit("onUserNameSaved")),onEditName:Z},null,8,["name","visits","created-at","last-seen","loading","org-display-name","role-name","update-endpoint"])):T("",!0)],544),n.userDetail?.error?(m(),p("div",ss,A(n.userDetail.error),1)):T("",!0),n.userDetail&&!n.userDetail.error?(m(),p(C,{key:1},[o("div",{class:"registration-actions",ref_key:"regActionsRef",ref:K,onKeydown:f},[o("button",{class:"btn-secondary reg-token-btn",onClick:d[1]||(d[1]=h=>l.$emit("generateUserRegistrationLink",n.selectedUser)),disabled:n.loading},"Generate Registration Token",8,ns),d[6]||(d[6]=o("p",{class:"matrix-hint muted"}," Generate a one-time registration link so this user can register or add another passkey. Copy the link from the dialog and send it to the user, or have the user scan the QR code on their device. ",-1))],544),o("section",os,[d[7]||(d[7]=o("div",{class:"section-header"},[o("h2",null,"Registered Passkeys")],-1)),o("div",as,[ae(nt,{ref_key:"credentialListRef",ref:x,credentials:n.userDetail.credentials,"aaguid-info":n.userDetail.aaguid_info,"allow-delete":!0,"hovered-credential-uuid":y.value,"hovered-session-credential-uuid":q.value?.credential,"navigation-disabled":$.value,onDelete:ee,onCredentialHover:d[2]||(d[2]=h=>y.value=h),onNavigateOut:r},null,8,["credentials","aaguid-info","hovered-credential-uuid","hovered-session-credential-uuid","navigation-disabled"])])]),ae(ot,{ref_key:"sessionListRef",ref:w,sessions:n.userDetail.sessions||[],"terminating-sessions":c.value,"hovered-credential-uuid":y.value,"navigation-disabled":$.value,"empty-message":"This user has no active sessions.","section-description":"View and manage the active sessions for this user.",onTerminate:g,onSessionHover:d[3]||(d[3]=h=>q.value=h),onNavigateOut:t},null,8,["sessions","terminating-sessions","hovered-credential-uuid","navigation-disabled"])],64)):T("",!0),o("div",{class:"actions ancillary-actions",ref_key:"backButtonRef",ref:F,onKeydown:s},[n.selectedOrg?(m(),p("button",{key:0,onClick:d[4]||(d[4]=h=>l.$emit("openOrg",n.selectedOrg)),class:"icon-btn",title:"Back to Org"},"↩️")):T("",!0)],544),n.showRegModal?(m(),H(at,{key:2,endpoint:`/auth/api/admin/orgs/${n.selectedUser.org}/users/${n.selectedUser.uuid}/create-link`,"user-name":n.userDetail?.display_name||n.selectedUser.display_name,onClose:d[5]||(d[5]=h=>l.$emit("closeRegModal")),onCopied:_},null,8,["endpoint","user-name"])):T("",!0)]))}},rs=re(is,[["__scopeId","data-v-0b259926"]]),ls={class:"modal-title"},us={key:0},ds={key:2},cs={class:"small muted"},ms=["placeholder","pattern"],fs={class:"small muted"},gs={key:7},vs={key:8,class:"error small"},ys={key:9,class:"modal-actions"},ps=["disabled"],hs=["disabled"],bs={__name:"AdminDialogs",props:{dialog:Object,PERMISSION_ID_PATTERN:String,settings:Object},emits:["submitDialog","closeDialog"],setup(n,{emit:J}){const Y=n,S=new Set(["org-update","role-update","user-update-name"]),L=I(()=>Y.settings?.rp_id||"the configured domain");return(E,c)=>n.dialog.type?(m(),H(it,{key:0,onClose:c[14]||(c[14]=y=>E.$emit("closeDialog"))},{default:Ye(()=>[o("h3",ls,[n.dialog.type==="org-create"?(m(),p(C,{key:0},[z("Create Organization")],64)):n.dialog.type==="org-update"?(m(),p(C,{key:1},[z("Rename Organization")],64)):n.dialog.type==="role-create"?(m(),p(C,{key:2},[z("Create Role")],64)):n.dialog.type==="role-update"?(m(),p(C,{key:3},[z("Edit Role")],64)):n.dialog.type==="user-create"?(m(),p(C,{key:4},[z("Add User To Role")],64)):n.dialog.type==="user-update-name"?(m(),p(C,{key:5},[z("Edit User Name")],64)):n.dialog.type==="perm-create"||n.dialog.type==="perm-display"?(m(),p(C,{key:6},[z(A(n.dialog.type==="perm-create"?"Create Permission":"Edit Permission"),1)],64)):n.dialog.type==="confirm"?(m(),p(C,{key:7},[z("Confirm")],64)):T("",!0)]),o("form",{onSubmit:c[13]||(c[13]=Se(y=>E.$emit("submitDialog"),["prevent"])),class:"modal-form"},[n.dialog.type==="org-create"?(m(),p("label",us,[c[15]||(c[15]=z("Name ",-1)),ne(o("input",{ref:"nameInput","onUpdate:modelValue":c[0]||(c[0]=y=>n.dialog.data.name=y),required:""},null,512),[[oe,n.dialog.data.name]])])):n.dialog.type==="org-update"?(m(),H(me,{key:1,label:"Organization Name",modelValue:n.dialog.data.name,"onUpdate:modelValue":c[1]||(c[1]=y=>n.dialog.data.name=y),busy:n.dialog.busy,error:n.dialog.error,onCancel:c[2]||(c[2]=y=>E.$emit("closeDialog"))},null,8,["modelValue","busy","error"])):n.dialog.type==="role-create"?(m(),p("label",ds,[c[16]||(c[16]=z("Role Name ",-1)),ne(o("input",{"onUpdate:modelValue":c[3]||(c[3]=y=>n.dialog.data.name=y),placeholder:"Role name",required:""},null,512),[[oe,n.dialog.data.name]])])):n.dialog.type==="role-update"?(m(),H(me,{key:3,label:"Role Name",modelValue:n.dialog.data.name,"onUpdate:modelValue":c[4]||(c[4]=y=>n.dialog.data.name=y),busy:n.dialog.busy,error:n.dialog.error,onCancel:c[5]||(c[5]=y=>E.$emit("closeDialog"))},null,8,["modelValue","busy","error"])):n.dialog.type==="user-create"?(m(),p(C,{key:4},[o("p",cs,"Role: "+A(n.dialog.data.role.display_name),1),o("label",null,[c[17]||(c[17]=z("Display Name ",-1)),ne(o("input",{"onUpdate:modelValue":c[6]||(c[6]=y=>n.dialog.data.name=y),placeholder:"User display name",required:""},null,512),[[oe,n.dialog.data.name]])])],64)):n.dialog.type==="user-update-name"?(m(),H(me,{key:5,label:"Display Name",modelValue:n.dialog.data.name,"onUpdate:modelValue":c[7]||(c[7]=y=>n.dialog.data.name=y),busy:n.dialog.busy,error:n.dialog.error,onCancel:c[8]||(c[8]=y=>E.$emit("closeDialog"))},null,8,["modelValue","busy","error"])):n.dialog.type==="perm-create"||n.dialog.type==="perm-display"?(m(),p(C,{key:6},[o("label",null,[c[18]||(c[18]=z("Display Name ",-1)),ne(o("input",{ref:"displayNameInput","onUpdate:modelValue":c[9]||(c[9]=y=>n.dialog.data.display_name=y),required:""},null,512),[[oe,n.dialog.data.display_name]])]),o("label",null,[c[19]||(c[19]=z("Permission Scope ",-1)),ne(o("input",{"onUpdate:modelValue":c[10]||(c[10]=y=>n.dialog.data.scope=y),placeholder:n.dialog.type==="perm-create"?"yourapp:permission":n.dialog.data.permission.scope,required:"",pattern:n.PERMISSION_ID_PATTERN,title:"Allowed: A-Za-z0-9:._~-","data-form-type":"other"},null,8,ms),[[oe,n.dialog.data.scope]])]),c[21]||(c[21]=o("p",{class:"small muted"},"E.g. yourapp:reports. Changing the scope name may break deployed applications.",-1)),o("label",null,[c[20]||(c[20]=z("Domain Scope ",-1)),ne(o("input",{"onUpdate:modelValue":c[11]||(c[11]=y=>n.dialog.data.domain=y),placeholder:"e.g. app.example.com","data-form-type":"other"},null,512),[[oe,n.dialog.data.domain]])]),o("p",fs,"If set, this permission is effective only on the specified domain, which can be "+A(L.value)+" or its subdomain.",1)],64)):n.dialog.type==="confirm"?(m(),p("p",gs,A(n.dialog.data.message),1)):T("",!0),n.dialog.error&&!ge(S).has(n.dialog.type)?(m(),p("div",vs,A(n.dialog.error),1)):T("",!0),ge(S).has(n.dialog.type)?T("",!0):(m(),p("div",ys,[o("button",{type:"button",class:"btn-secondary",onClick:c[12]||(c[12]=y=>E.$emit("closeDialog")),disabled:n.dialog.busy}," Cancel ",8,ps),o("button",{type:"submit",class:"btn-primary",disabled:n.dialog.busy},A(n.dialog.type==="confirm"?"OK":"Save"),9,hs)]))],32)]),_:1})):T("",!0)}},ws=re(bs,[["__scopeId","data-v-8d16c6cc"]]),$s={class:"app-shell admin-shell"},Ds={class:"app-main"},ks={key:4,class:"view-root view-root--wide view-admin"},Ss={class:"view-header"},Os={class:"section-block admin-section"},Rs={class:"section-body admin-section-body"},Cs={class:"admin-panels"},As="^[A-Za-z0-9:._~-]+$",Us={__name:"AdminApp",setup(n){const J=k(null),Y=k(!0),S=k("Loading..."),L=k(!1),E=k(!1),c=k(null),y=k([]),q=k([]),N=k(null),K=k(null),x=k(null),w=Oe(),F=k(null);k(null),k(""),k(null),k("");const $=k({type:null,data:null,busy:!1,error:""}),_=k(null),Z=k(null),ee=k(null),g=k(null),u=k(null),f=I(()=>$.value.type!==null||ue.value),r=I(()=>J.value?.ctx.permissions.includes("auth:admin")),t=I(()=>J.value?.ctx.permissions.includes("auth:org:admin"));function s(e){if(!F.value)return;const a=e.target.closest(".org-add-menu"),i=e.target.closest(".add-org-btn");!a&&!i&&(F.value=null)}We(async()=>{document.addEventListener("click",s),window.addEventListener("hashchange",d),await w.loadSettings(),w.settings?.rp_name&&(document.title=w.settings.rp_name+" Admin"),await B()}),Ze(()=>{document.removeEventListener("click",s),window.removeEventListener("hashchange",d)});const D=I(()=>{const e={};for(const i of y.value){const v={uuid:i.uuid,display_name:i.display_name},b=new Set(i.permissions||[]);for(const O of i.permissions||[])e[O]||(e[O]={orgs:[],orgSet:new Set,userCount:0}),e[O].orgSet.has(i.uuid)||(e[O].orgs.push(v),e[O].orgSet.add(i.uuid));for(const O of i.roles)for(const U of O.permissions)b.has(U)&&(e[U]||(e[U]={orgs:[],orgSet:new Set,userCount:0}),e[U].orgSet.has(i.uuid)||(e[U].orgs.push(v),e[U].orgSet.add(i.uuid)),e[U].userCount+=O.users.length)}const a={};for(const[i,v]of Object.entries(e))a[i]={orgs:v.orgs.sort((b,O)=>b.display_name.localeCompare(O.display_name)),userCount:v.userCount};return a});function l(e){Q("perm-display",{permission:e,scope:e.scope,display_name:e.display_name,domain:e.domain||""})}function d(){const e=window.location.hash||"";N.value=null,K.value=null,e.startsWith("#org/")?N.value=e.slice(5):e.startsWith("#user/")&&(K.value=e.slice(6))}async function h(){const e=await P("/auth/api/admin/orgs");y.value=e.map(a=>{const i=a.roles.map(b=>({...b,org:a.uuid,users:[]})),v=Object.fromEntries(i.map(b=>[b.display_name,b]));for(const b of a.users||[])v[b.role]&&v[b.role].users.push(b);return{...a,roles:i}})}async function R(){q.value=await P("/auth/api/admin/permissions")}async function V(){const e=await P("/auth/api/validate",{method:"POST"});J.value=e,L.value=!0}function M(){J.value=null,y.value=[],q.value=[],x.value=null,L.value=!1}async function B(){Y.value=!0,S.value="Loading...",c.value=null;try{await Promise.all([h(),R()]),await V(),!r.value&&t.value&&y.value.length===1&&(!window.location.hash||window.location.hash==="#overview")?(N.value=y.value[0].uuid,window.location.hash=`#org/${N.value}`,w.showMessage(`Navigating to ${y.value[0].display_name} Administration`,"info",3e3)):d()}catch(e){M(),e.name==="AuthCancelledError"?E.value=!0:c.value=e.message}finally{Y.value=!1}}function le(){Q("org-create",{})}function ve(e){Q("org-update",{org:e,name:e.display_name})}function Ce(e){Q("user-update-name",{user:e,name:e.display_name})}async function ye(e){await P(`/auth/api/admin/orgs/${e}`,{method:"DELETE"}),await Promise.all([h(),R()])}function Ae(e){if(e.roles.reduce((b,O)=>b+O.users.length,0)===0){ye(e.uuid).then(()=>{w.showMessage(`Organization "${e.display_name}" deleted.`,"success",2500)}).catch(b=>{w.showMessage(b.message||"Failed to delete organization","error")});return}const v=e.roles.filter(b=>b.users.length>0).map(b=>`${b.users.length} ${b.display_name}`).join(", ");Q("confirm",{message:`Delete organization "${e.display_name}", including accounts of ${v})?`,action:async()=>{await ye(e.uuid)}})}function Ue(e,a){Q("user-create",{org:e,role:a})}async function Ee(e,a,i){if(a.role!==i)try{await P(`/auth/api/admin/orgs/${e.uuid}/users/${a.uuid}/role`,{method:"PATCH",body:{role:i}}),await h()}catch(v){w.showMessage(v.message||"Failed to update user role")}}function Me(e,a,i){e.dataTransfer.effectAllowed="move",e.dataTransfer.setData("text/plain",JSON.stringify({user_uuid:a.uuid,org:i}))}function Pe(e){e.preventDefault(),e.dataTransfer.dropEffect="move"}function qe(e,a,i){e.preventDefault();try{const v=JSON.parse(e.dataTransfer.getData("text/plain"));if(v.org!==a.uuid)return;const b=a.roles.flatMap(O=>O.users).find(O=>O.uuid===v.user_uuid);b&&Ee(a,b,i.display_name)}catch{}}function xe(e){Q("role-create",{org:e})}function Ne(e){Q("role-update",{role:e,name:e.display_name})}function Te(e){P(`/auth/api/admin/orgs/${e.org}/roles/${e.uuid}`,{method:"DELETE"}).then(()=>{w.showMessage(`Role "${e.display_name}" deleted.`,"success",2500),h()}).catch(a=>{w.showMessage(a.message||"Failed to delete role","error")})}async function Le(e,a,i){const v=[...e.permissions],b=i?[...e.permissions,a]:e.permissions.filter(O=>O!==a);e.permissions=b;try{const O=i?"POST":"DELETE";await P(`/auth/api/admin/orgs/${e.org}/roles/${e.uuid}/permissions/${a}`,{method:O}),await h()}catch(O){w.showMessage(O.message||"Failed to update role permission"),e.permissions=v}}async function pe(e){const a=new URLSearchParams({permission_uuid:e});await P(`/auth/api/admin/permission?${a.toString()}`,{method:"DELETE"}),await R()}function Fe(e){const a=D.value[e.uuid]?.userCount||0;let i=0;for(const O of y.value)for(const U of O.roles)U.permissions.includes(e.uuid)&&i++;if(i===0){pe(e.uuid).then(()=>{w.showMessage(`Permission "${e.display_name}" deleted.`,"success",2500)}).catch(O=>{w.showMessage(O.message||"Failed to delete permission","error")});return}const v=[];i>0&&v.push(`${i} role${i!==1?"s":""}`),a>0&&v.push(`${a} user${a!==1?"s":""}`);const b=v.join(", ");Q("confirm",{message:`Delete permission "${e.display_name}" (${b})?`,action:async()=>{await pe(e.uuid)}})}const se=I(()=>y.value.find(e=>e.uuid===N.value)||null);function he(e){window.location.hash=`#org/${e.uuid}`}function Ie(){window.location.hash="#overview"}function Ke(e){window.location.hash=`#user/${e.uuid}`}const j=I(()=>{if(!K.value)return null;for(const e of y.value)for(const a of e.roles){const i=a.users.find(v=>v.uuid===K.value);if(i)return{...i,org:e.uuid,role_display_name:a.display_name}}return null}),Be=I(()=>j.value?"Admin: User":se.value?"Admin: Org":(w.settings?.rp_name||"Master")+" Admin"),ze=I(()=>{const e=[{label:"Auth",href:Qe()},{label:"Admin",href:Xe()}];let a=null;j.value&&(a=y.value.find(v=>v.uuid===j.value.org)||null);const i=se.value||a;return i&&e.push({label:i.display_name,href:`#org/${i.uuid}`}),j.value&&e.push({label:j.value.display_name,href:`#user/${j.value.uuid}`}),e});_e(j,async e=>{if(!e){x.value=null;return}try{x.value=await P(`/auth/api/admin/orgs/${e.org}/users/${e.uuid}`)}catch(a){x.value={error:a.message}}});const ue=k(!1);function Ve(e){ue.value=!0}async function je(e,a,i){const v=e.permissions.includes(a);if(i&&v||!i&&!v)return;const b=i?[...e.permissions,a]:e.permissions.filter(U=>U!==a),O=[...e.permissions];e.permissions=b;try{const U=new URLSearchParams({permission_uuid:a});await P(`/auth/api/admin/orgs/${e.uuid}/permission?${U.toString()}`,{method:i?"POST":"DELETE"}),await h()}catch(U){w.showMessage(U.message||"Failed to update organization permission","error"),e.permissions=O}}function Q(e,a){const i=document.activeElement;if(_.value=i,e==="confirm"&&i){const v=i.closest("tr");if(v){const b=v.closest("tbody");if(b){const O=Array.from(b.querySelectorAll("tr")),U=O.indexOf(v);$.value.focusContext={tbody:b,index:U,total:O.length,selector:"button:not([disabled]), a"}}}}$.value={...$.value,type:e,data:a,busy:!1,error:""}}function W(){const e=_.value,a=$.value.focusContext;$.value={type:null,data:null,busy:!1,error:""},He(e,a),_.value=null}function He(e,a){if(!e)return;if(document.body.contains(e)&&!e.disabled){e.focus();return}if(a?.tbody&&a.selector){const b=Array.from(a.tbody.querySelectorAll("tr"));if(b.length>0){const O=Math.min(a.index,b.length-1),de=b[O]?.querySelector(a.selector);if(de){de.focus();return}}}const i=document.querySelector(".admin-panels");if(!i)return;const v=i.querySelector('button:not([disabled]), a, input:not([disabled]), [tabindex="0"]');v&&v.focus()}function Ge(e){if(f.value)return;const a=G(e);a&&a==="down"&&(e.preventDefault(),ee.value?ee.value.focusFirstElement?.():g.value?g.value.focusFirstElement?.():u.value&&u.value.focusFirstElement?.())}function ce(e){f.value||e==="up"&&Z.value?.focusCurrent?.()}async function be(){if(await h(),j.value)try{x.value=await P(`/auth/api/admin/orgs/${j.value.org}/users/${j.value.uuid}`)}catch(e){w.showMessage(e.message||"Failed to reload user","error")}}async function we(){await be(),w.showMessage("User renamed","success",1500)}async function Je(){if(!(!$.value.type||$.value.busy)){$.value.busy=!0,$.value.error="";try{const e=$.value.type;if(e==="org-create"){const a=$.value.data.name?.trim();if(!a)throw new Error("Name required");W(),P("/auth/api/admin/orgs",{method:"POST",body:{display_name:a,permissions:[]}}).then(()=>{w.showMessage(`Organization "${a}" created.`,"success",2500),Promise.all([h(),R()])}).catch(i=>{w.showMessage(i.message||"Failed to create organization","error")});return}else if(e==="org-update"){const{org:a}=$.value.data,i=$.value.data.name?.trim();if(!i)throw new Error("Name required");W(),P(`/auth/api/admin/orgs/${a.uuid}`,{method:"PATCH",body:{display_name:i}}).then(()=>{w.showMessage(`Organization renamed to "${i}".`,"success",2500),h()}).catch(v=>{w.showMessage(v.message||"Failed to update organization","error")});return}else if(e==="role-create"){const{org:a}=$.value.data,i=$.value.data.name?.trim();if(!i)throw new Error("Name required");W(),P(`/auth/api/admin/orgs/${a.uuid}/roles`,{method:"POST",body:{display_name:i,permissions:[]}}).then(()=>{w.showMessage(`Role "${i}" created.`,"success",2500),h()}).catch(v=>{w.showMessage(v.message||"Failed to create role","error")});return}else if(e==="role-update"){const{role:a}=$.value.data,i=$.value.data.name?.trim();if(!i)throw new Error("Name required");W(),P(`/auth/api/admin/orgs/${a.org}/roles/${a.uuid}`,{method:"PATCH",body:{display_name:i}}).then(()=>{w.showMessage(`Role renamed to "${i}".`,"success",2500),h()}).catch(v=>{w.showMessage(v.message||"Failed to update role","error")});return}else if(e==="user-create"){const{org:a,role:i}=$.value.data,v=$.value.data.name?.trim();if(!v)throw new Error("Name required");W(),P(`/auth/api/admin/orgs/${a.uuid}/users`,{method:"POST",body:{display_name:v,role:i.display_name}}).then(()=>{w.showMessage(`User "${v}" added to ${i.display_name} role.`,"success",2500),h()}).catch(b=>{w.showMessage(b.message||"Failed to add user","error")});return}else if(e==="user-update-name"){const{user:a}=$.value.data,i=$.value.data.name?.trim();if(!i)throw new Error("Name required");W(),P(`/auth/api/admin/orgs/${a.org}/users/${a.uuid}/display-name`,{method:"PATCH",body:{display_name:i}}).then(()=>{w.showMessage(`User renamed to "${i}".`,"success",2500),we()}).catch(v=>{w.showMessage(v.message||"Failed to update user name","error")});return}else if(e==="perm-display"){const{permission:a}=$.value.data,i=$.value.data.scope?.trim(),v=$.value.data.display_name?.trim(),b=$.value.data.domain?.trim()||"";if(!v)throw new Error("Display name required");if(!i)throw new Error("Scope required");W();const O=a.domain||"";if(i===a.scope&&v===a.display_name&&b===O)return;const U=new URLSearchParams({permission_uuid:a.uuid});i!==a.scope&&U.set("scope",i),v!==a.display_name&&U.set("display_name",v),b!==O&&U.set("domain",b||""),P(`/auth/api/admin/permission?${U.toString()}`,{method:"PATCH"}).then(()=>{w.showMessage(`Permission "${v}" updated.`,"success",2500),R()}).catch(de=>{w.showMessage(de.message||"Failed to update permission","error")});return}else if(e==="perm-create"){const a=$.value.data.scope?.trim();if(!a)throw new Error("Scope required");const i=$.value.data.display_name?.trim();if(!i)throw new Error("Display name required");const v=$.value.data.domain?.trim()||"";W(),P("/auth/api/admin/permissions",{method:"POST",body:{scope:a,display_name:i,domain:v||void 0}}).then(()=>{w.showMessage(`Permission "${i}" created.`,"success",2500),R()}).catch(b=>{w.showMessage(b.message||"Failed to create permission","error")});return}else if(e==="confirm"){const a=$.value.data.action;if(W(),a)try{await a()}catch(i){w.showMessage(i.message||"Action failed","error")}return}W()}catch(e){$.value.error=e.message||"Error"}finally{$.value.busy=!1}}}return(e,a)=>(m(),p("div",$s,[ae(rt),o("main",Ds,[Y.value?(m(),H(lt,{key:0,message:S.value},null,8,["message"])):E.value?(m(),H(fe,{key:1})):c.value?(m(),H(fe,{key:2,icon:"⚠️",title:"Error",message:c.value},null,8,["message"])):L.value&&!r.value&&!t.value?(m(),H(fe,{key:3,icon:"⛔",message:"You do not have admin permissions for this application."})):L.value&&(r.value||t.value)?(m(),p("section",ks,[o("header",Ss,[o("h1",null,A(Be.value),1),ae(ut,{ref_key:"breadcrumbsRef",ref:Z,entries:ze.value,onKeydown:Ge},null,8,["entries"])]),o("section",Os,[o("div",Rs,[o("div",Cs,[!j.value&&!se.value&&(r.value||t.value)?(m(),H(Nt,{key:0,ref_key:"adminOverviewRef",ref:ee,info:J.value,orgs:y.value,permissions:q.value,"navigation-disabled":f.value,"permission-summary":D.value,onCreateOrg:le,onOpenOrg:he,onUpdateOrg:ve,onDeleteOrg:Ae,onToggleOrgPermission:je,onOpenDialog:Q,onDeletePermission:Fe,onRenamePermissionDisplay:l,onNavigateOut:ce},null,8,["info","orgs","permissions","navigation-disabled","permission-summary"])):j.value?(m(),H(rs,{key:1,ref_key:"adminUserDetailRef",ref:u,"selected-user":j.value,"user-detail":x.value,"selected-org":se.value,loading:Y.value,"show-reg-modal":ue.value,"navigation-disabled":f.value,onGenerateUserRegistrationLink:Ve,onGoOverview:Ie,onOpenOrg:he,onOnUserNameSaved:we,onRefreshUserDetail:be,onEditUserName:Ce,onCloseRegModal:a[0]||(a[0]=i=>ue.value=!1),onNavigateOut:ce},null,8,["selected-user","user-detail","selected-org","loading","show-reg-modal","navigation-disabled"])):se.value?(m(),H(es,{key:2,ref_key:"adminOrgDetailRef",ref:g,"selected-org":se.value,permissions:q.value,"navigation-disabled":f.value,onUpdateOrg:ve,onCreateRole:xe,onUpdateRole:Ne,onDeleteRole:Te,onCreateUserInRole:Ue,onOpenUser:Ke,onToggleRolePermission:Le,onOnRoleDragOver:Pe,onNavigateOut:ce,onOnRoleDrop:qe,onOnUserDragStart:Me},null,8,["selected-org","permissions","navigation-disabled"])):T("",!0)])])])])):T("",!0)]),ae(ws,{dialog:$.value,"permission-id-pattern":As,settings:ge(w).settings,onSubmitDialog:Je,onCloseDialog:W},null,8,["dialog","settings"])]))}},Es=re(Us,[["__scopeId","data-v-1d1c1f6a"]]),Re=et(Es);Re.use(dt());Re.mount("#admin-app");tt();
@@ -1 +0,0 @@
1
- import{_ as Me,r as f,w as Ze,c as C,o as Ee,n as ye,a as Be,b as _,d as v,e as a,f as N,g as $e,h as lt,F as de,i as rt,j as Le,t as $,k as K,v as it,l as Je,m as ut,s as ct,p as dt,q as ft,u as vt,x as oe,y as J,z as b,A as ze,B as fe,C as We,D as we,E as Ae,G as ht,H as Pe,I as pt,J as gt,K as mt}from"./_plugin-vue_export-helper-nhjnO_bd.js";import{u as _e,B as yt,U as Ge,_ as wt,a as bt,N as _t,M as kt,R as It,L as xt,b as St,A as Ct,c as $t}from"./AccessDenied-Fmeb6EtF.js";import{i as Fe,a as X,g as je,b as Oe,c as qe,s as Ye}from"./pow-2N9bxgAo.js";import{g as be}from"./helpers-DzjFIx78.js";const Lt={class:"pairing-entry"},Wt={key:0,class:"input-row"},At={class:"slot-word"},Pt={class:"typed-prefix"},Mt={class:"hint-suffix"},Et={key:0,class:"cursor-overlay",style:{"--cursor-pos":0,"--word-len":0}},Bt=["placeholder"],Dt={key:0,class:"processing-status"},Nt={class:"processing-icon"},Tt={key:1,class:"device-info"},Vt={class:"device-permit-text"},Ut={class:"device-meta"},Ht={key:0,class:"error-message",style:{"margin-top":"0.5rem"}},Kt={class:"button-row",style:{"margin-top":"0.75rem",display:"flex",gap:"0.5rem"}},Rt=["disabled"],zt=["disabled"],Ft={__name:"RemoteAuthPermit",props:{title:{type:String,default:"Help Another Device Sign In"},description:{type:String,default:"Enter the code shown on the device that needs to sign in."},placeholder:{type:String,default:"Enter three words"},action:{type:String,default:"login"}},emits:["completed","error","cancelled","back","register","deviceInfoVisible"],setup(ae,{expose:o,emit:A}){const L=A,k=f(!1),x=f(null),D=f(null);let c=null,V=null;try{V=_e()}catch{}const P=f(null),R=f(null),i=f(""),M=f(!1),E=f(""),y=f(null),p=f("");Ze(y,e=>{L("deviceInfoVisible",!!e)});const d=f(!1),h=f(!1),g=f(0),O=f(0),G=f(0),le=f(!1),ve=f(!1);let ee=0,te=!1,Y=null,se=null,z=null,F=null,T=null,Z=null;function ne(e,s="info",t=3e3){V&&V.showMessage(e,s,t)}async function re(){try{const e=await ut();D.value=e}catch(e){console.warn("Unable to load settings",e)}}function ie(e,s){if(!e||s<0)return{word:"",start:0,end:0};let t=s,u=s;for(;t>0&&/[a-zA-Z]/.test(e[t-1]);)t--;for(;u<e.length&&/[a-zA-Z]/.test(e[u]);)u++;return{word:e.slice(t,u),start:t,end:u}}function Q(e){return e.trim().split(/[.\s]+/).filter(s=>s.length>0)}function B(e){const s=Q(e),t=[];for(const u of s){let r=u.toLowerCase();for(;r.length>0&&t.length<3;){let S=null;for(let w=Math.min(r.length,6);w>=3;w--){const I=r.slice(0,w);if(X(I)){S=I;break}}if(S)t.push(S),r=r.slice(S.length);else{t.push(r);break}}if(t.length>=3)break}return t}function he(e){const s=/[.\s]$/.test(e),t=B(e);return s?t.length:Math.max(0,t.length-1)}function pe(e){if(!e)return{valid:!0,segments:[]};const s=[],t=/[.\s]$/.test(e);let u,r=/([a-zA-Z]+)|([.\s]+)/g;for(;(u=r.exec(e))!==null;)u[1]?s.push({text:u[1],isWord:!0,start:u.index}):u[2]&&s.push({text:u[2],isWord:!1,start:u.index});const S=s.filter(I=>I.isWord);let w=!0;return S.forEach((I,U)=>{const W=U===S.length-1,q=I.text.toLowerCase();W&&!t?I.invalid=!Fe(q):I.invalid=!X(q),I.invalid&&(w=!1)}),{valid:w,segments:s}}C(()=>{const{segments:e}=pe(i.value);return e.map(s=>({text:s.text,invalid:s.invalid||!1}))});function ke(e){return pe(e).valid}function Ie(e){return B(e).length>0&&B(e).every(s=>X(s))}function ge(e){if(/[.\s]$/.test(e))return"";const t=e.match(/[a-zA-Z]+$/);return t?t[0].toLowerCase():""}function xe(e,s){if(!e||s===0)return{wordIndex:0,charIndex:0};const t=e.slice(0,s),u=/[.\s]$/.test(t),r=B(t);if(r.length===0)return{wordIndex:0,charIndex:0};if(u)return{wordIndex:Math.min(r.length,2),charIndex:0};const S=r[r.length-1],w=r.length-1;B(e);const I=S.length;return w<2&&!ve.value&&X(S)?{wordIndex:w+1,charIndex:0}:{wordIndex:Math.min(w,2),charIndex:I}}function ue(e,s){if(!e||s===0)return{wordIndex:0,charIndex:0};const t=e.slice(0,s),u=/[.\s]$/.test(t),r=B(t);if(r.length===0)return{wordIndex:0,charIndex:0};if(u)return{wordIndex:Math.min(r.length,2),charIndex:0};const S=r[r.length-1],w=r.length-1;return{wordIndex:Math.min(w,2),charIndex:S.length}}const l=C(()=>{const e=B(i.value),s=[],t=ge(i.value),u=p.value,r=/[.\s]$/.test(i.value),S=O.value!==G.value,w=ue(i.value,Math.min(O.value,G.value)),I=ue(i.value,Math.max(O.value,G.value)),U=S?ue(i.value,g.value):xe(i.value,g.value);for(let W=0;W<3;W++){const q=U.wordIndex===W;let j=-1,H=-1;if(S&&(W>w.wordIndex&&W<I.wordIndex?(j=0,H=e[W]?.length??0):W===w.wordIndex&&W===I.wordIndex?(j=w.charIndex,H=I.charIndex):W===w.wordIndex?(j=w.charIndex,H=e[W]?.length??0):W===I.wordIndex&&(j=0,H=I.charIndex)),W<e.length){const me=e[W].toLowerCase(),Ke=W===e.length-1,Re=Ke&&!r?!Fe(me):!X(me);if(Ke&&!r&&u&&t){const at=u.length;s.push({text:"",typedPrefix:t,hintSuffix:u.slice(t.length),invalid:Re,hasCursor:q,cursorCharIndex:q?U.charIndex:-1,wordLen:at,selectionStartChar:j,selectionEndChar:H})}else s.push({text:me,invalid:Re,hasCursor:q,cursorCharIndex:q?U.charIndex:-1,wordLen:me.length,selectionStartChar:j,selectionEndChar:H})}else s.push({text:"",invalid:!1,hasCursor:q,cursorCharIndex:0,wordLen:0,selectionStartChar:j,selectionEndChar:H})}return s}),n=C(()=>O.value!==G.value),m=C(()=>{const e=B(i.value);return e.length===3&&e.every(s=>X(s))});function De(e){return B(e).join(".")}function Xe(){if(!Y||z)return;const e=qe(Y);z=Ye(e,se).then(s=>{F=s,z=null})}async function Ne(){if(F){const s=F;return F=null,s}if(z){await z;const s=F;return F=null,s}if(!Y)throw new Error("No PoW challenge available");const e=qe(Y);return await Ye(e,se)}function Te(e){e?.challenge&&(Y=e.challenge,se=e.work,F=null,z=null,Xe())}async function Se(){if(!(c||te)){te=!0;try{const e=D.value?.auth_host,s="/auth/ws/remote-auth/permit",t=e&&location.host!==e?`//${e}${s}`:s;c=await dt(t);const u=await c.receive_json();if(u.status&&u.detail)throw new Error(u.detail);if(!u.pow?.challenge)throw new Error("Server did not send PoW challenge");Te(u.pow)}catch(e){throw console.error("WebSocket connection error:",e),c=null,e}finally{te=!1}}}function et(e){if(e.key==="Tab"||e.key===" "||e.key==="Escape"){nt(e);return}setTimeout(Ve,0)}function Ve(){const e=P.value,s=e?.selectionStart??i.value.length,t=e?.selectionEnd??s,r=(e?.selectionDirection??"none")==="backward"?s:t;ve.value=r<ee,ee=r,g.value=r,G.value=t,O.value=s}function tt(){g.value=P.value?.selectionStart??i.value.length;const{word:e,end:s}=ie(i.value,g.value);if(he(i.value)>=3||!e||e.length<1||g.value!==s){p.value="";return}const u=je(e.toLowerCase());u&&u!==e.toLowerCase()?p.value=u:p.value=""}function Ue(){if(!p.value)return!1;const{word:e,start:s,end:t}=ie(i.value,g.value);if(!e)return!1;const u=i.value.slice(0,s),w=B(u).length===2?"":" ",I=i.value.slice(t);i.value=u+p.value+w+I.trimStart();const U=s+p.value.length+w.length;return ye(()=>{P.value?.setSelectionRange(U,U),g.value=U}),p.value="",!0}function ce(){g.value=P.value?.selectionStart??i.value.length;const e=g.value,t=i.value.slice(0,e).match(/([a-zA-Z]+) $/);if(t){const r=t[1].toLowerCase(),S=je(r);if(S&&S!==r&&!X(r)){const w=e-t[0].length,I=i.value.slice(0,w),U=i.value.slice(e),j=B(I).length===2?"":" ";i.value=I+S+j+U;const H=w+S.length+j.length;ye(()=>{P.value?.setSelectionRange(H,H),g.value=H})}}tt(),T&&(clearTimeout(T),T=null),y.value=null,x.value=null,h.value=!1,d.value=!ke(i.value);const u=B(i.value);if(u.length>=1&&!c&&!te&&Se(),u.length===3){if(!Ie(i.value))return;T=setTimeout(()=>{st()},150)}}async function st(){if(!(M.value||k.value||!m.value||De(i.value)===Z&&y.value)){M.value=!0,E.value="pow",x.value=null,h.value=!1;try{if(await Se(),!c)throw new Error("Failed to connect");const s=await Ne(),t=Oe(s),u=De(i.value);if(!m.value)return;E.value="server",c.send_json({code:u,pow:t});const r=await c.receive_json();if(Te(r.pow),typeof r.status=="number"&&r.status>=400){ne(r.detail||"Request failed","error"),h.value=!0,y.value=null,Z=null;return}r.status==="found"&&r.host?(y.value={host:r.host,user_agent_pretty:r.user_agent_pretty,client_ip:r.client_ip,action:r.action||"login"},Z=u,ye(()=>{R.value?.focus()})):(ne("Unexpected response from server","error"),h.value=!0,y.value=null,Z=null)}catch(s){console.error("Lookup error:",s),ne(s.message||"Lookup failed","error"),h.value=!0,y.value=null,Z=null,c&&(c.close(),c=null)}finally{M.value=!1,E.value=""}}}function nt(e){if(e.key==="Escape"){i.value="",ce(),e.preventDefault();return}if(e.key==="Tab"){if(p.value&&Ue()){e.preventDefault(),ce();return}i.value.trim()&&e.preventDefault();return}e.key===" "&&p.value&&Ue()&&(e.preventDefault(),ce())}async function ot(){if(!(!y.value||k.value)){k.value=!0,x.value=null;try{if(c||await Se(),!c)throw new Error("Failed to connect");const e=await Ne(),s=Oe(e);c.send_json({authenticate:!0,pow:s});const t=await c.receive_json();if(typeof t.status=="number"&&t.status>=400)throw new Error(t.detail||"Authentication failed");if(!t.optionsJSON)throw new Error(t.detail||"Failed to get authentication options");const u=await ct(t);c.send_json(u);const r=await c.receive_json();if(typeof r.status=="number"&&r.status>=400)throw new Error(r.detail||"Authentication failed");if(r.status==="success")ne("Device authenticated successfully!","success",3e3),L("completed"),Ce();else throw new Error(r.detail||"Authentication failed")}catch(e){console.error("Pairing error:",e);const s=e.name==="NotAllowedError"?"Passkey authentication was cancelled":e.message||"Authentication failed";x.value=s,L("error",s)}finally{k.value=!1,c&&(c.close(),c=null)}}}async function He(){if(c){try{c.send_json({deny:!0}),await new Promise(e=>setTimeout(e,100))}catch(e){console.error("Error sending deny message:",e)}c.close(),c=null}Ce()}function Ce(){i.value="",x.value=null,h.value=!1,y.value=null,M.value=!1,E.value="",p.value="",d.value=!1,Z=null,c&&(c.close(),c=null),Y=null,se=null,z=null,F=null}return Ee(async()=>{await re(),ye(()=>{g.value=P.value?.selectionStart??0})}),Be(()=>{T&&(clearTimeout(T),T=null),c&&(c.close(),c=null)}),o({reset:Ce,deny:He,code:i,handleInput:ce,loading:k,error:x}),(e,s)=>(v(),_("div",Lt,[a("form",{onSubmit:Je(ot,["prevent"]),class:"pairing-form"},[y.value?y.value?(v(),_("div",Tt,[a("p",Vt,[K("Permit "+$(y.value.action==="register"?"registration":"login")+" to ",1),a("strong",null,$(y.value.host),1)]),a("p",Ut,$(y.value.user_agent_pretty),1),x.value?(v(),_("p",Ht,$(x.value),1)):N("",!0),a("div",Kt,[a("button",{type:"button",class:"btn-secondary",disabled:k.value,onClick:He,style:{flex:"1"}}," Deny ",8,Rt),a("button",{ref_key:"submitBtnRef",ref:R,type:"submit",disabled:k.value,class:"btn-primary",style:{flex:"1"}},$(k.value?"Authenticating…":"Authorize"),9,zt)])])):N("",!0):(v(),_("div",Wt,[a("div",{class:$e(["input-wrapper",{"has-error":h.value,"is-complete":y.value&&!h.value,focused:le.value,"has-selection":n.value}])},[a("div",{class:$e(["slot-machine",{"has-error":h.value,"is-complete":y.value&&!h.value}]),"aria-hidden":"true"},[(v(!0),_(de,null,rt(l.value,(t,u)=>(v(),_("div",{key:u,class:$e(["slot-reel",{"invalid-word":t.invalid,empty:!t.text&&!t.typedPrefix}])},[a("div",At,[t.selectionStartChar>=0&&t.selectionEndChar>t.selectionStartChar?(v(),_("span",{key:0,class:"selection-overlay",style:Le({"--sel-start":t.selectionStartChar,"--sel-end":t.selectionEndChar,"--word-len":t.wordLen})},null,4)):N("",!0),t.typedPrefix?(v(),_(de,{key:1},[a("span",Pt,$(t.typedPrefix),1),a("span",Mt,$(t.hintSuffix),1),t.hasCursor?(v(),_("span",{key:0,class:"cursor-overlay",style:Le({"--cursor-pos":t.cursorCharIndex,"--word-len":t.wordLen})},null,4)):N("",!0)],64)):t.text?(v(),_(de,{key:2},[K($(t.text)+" ",1),t.hasCursor?(v(),_("span",{key:0,class:"cursor-overlay",style:Le({"--cursor-pos":t.cursorCharIndex,"--word-len":t.wordLen})},null,4)):N("",!0)],64)):(v(),_(de,{key:3},[t.hasCursor?(v(),_("span",Et)):N("",!0)],64))])],2))),128))],2),lt(a("input",{ref_key:"inputRef",ref:P,"onUpdate:modelValue":s[0]||(s[0]=t=>i.value=t),type:"text",placeholder:ae.placeholder,autocomplete:"off",autocapitalize:"none",autocorrect:"off",spellcheck:"false",class:"pairing-input hidden-input",onInput:ce,onKeydown:et,onMouseup:Ve,onFocus:s[1]||(s[1]=t=>le.value=!0),onBlur:s[2]||(s[2]=t=>le.value=!1)},null,40,Bt),[[it,i.value]])],2),E.value?(v(),_("div",Dt,[a("span",Nt,$(E.value==="pow"?"🔐":"📡"),1),s[3]||(s[3]=a("span",{class:"processing-spinner-small"},null,-1))])):N("",!0)]))],32)]))}},jt=Me(Ft,[["__scopeId","data-v-77a073d9"]]),Ot={class:"view-root","data-view":"profile"},qt={class:"view-header"},Yt={class:"remote-auth-inline"},Zt={key:0,class:"remote-auth-label"},Jt={class:"section-block"},Gt={class:"section-body"},Qt={class:"section-block"},Xt=["disabled"],es=["disabled"],ts=["disabled"],ss={key:0,class:"logout-note"},ns={key:1,class:"logout-note"},os={__name:"ProfileView",setup(ae){const o=_e(),A=f(null),L=f(!1),k=f(!1),x=f(""),D=f(!1),c=f(null),V=f(null),P=f(!1),R=f(null),i=f(null),M=f(null),E=f(null),y=f(null),p=f(null),d=f(null),h=f(null),g=C(()=>L.value||k.value);Ze(L,l=>{l&&(x.value=o.userInfo?.ctx.user.display_name??"")}),Ee(()=>{A.value=setInterval(()=>{o.userInfo&&(o.userInfo={...o.userInfo})},6e4)}),Be(()=>{A.value&&clearInterval(A.value)});const O=async()=>{try{await ht.register(null,null,()=>{o.showMessage("Adding new passkey...","info")}),await o.loadUserInfo(),o.showMessage("New passkey added successfully!","success",3e3)}catch(l){console.error("Failed to add new passkey:",l),o.showMessage(l.message,"error")}},G=()=>{o.showMessage("The other device is now signed in!","success",4e3),setTimeout(()=>R.value?.reset(),3e3)},le=l=>{l.includes("cancelled")||o.showMessage(l,"error",4e3)},ve=()=>{o.showMessage("📋 Link copied! Send it to your other device."),k.value=!1},ee=l=>{We(l,{primarySelector:".btn-primary",itemSelector:"button"})},te=l=>{if(g.value)return;const n=fe(l);n&&n==="down"&&(l.preventDefault(),We(h.value,{primarySelector:".mini-btn",itemSelector:".mini-btn, .pairing-input"}))},Y=l=>{if(g.value)return;const n=fe(l);if(!n)return;l.preventDefault(),n==="left"||n==="right"?we(h.value,l.target,n,{itemSelector:".mini-btn, .pairing-input"}):n==="up"?p.value?.focusCurrent?.():n==="down"&&i.value?.$el?.focus()},se=l=>{g.value||(l==="down"||l==="right"?ee(M.value):(l==="up"||l==="left")&&We(h.value,{primarySelector:".mini-btn",itemSelector:".mini-btn, .pairing-input"}))},z=l=>{if(g.value)return;const n=fe(l);n&&(l.preventDefault(),n==="left"||n==="right"?we(M.value,l.target,n,{itemSelector:"button"}):n==="up"?Ae(i.value?.$el,0,{itemSelector:".credential-item"}):n==="down"&&Ae(E.value?.$el,0,{itemSelector:".session-group"}))},F=l=>{g.value||(l==="up"?ee(M.value):l==="down"&&ee(y.value))},T=l=>{if(g.value)return;const n=fe(l);n&&(l.preventDefault(),n==="left"||n==="right"?we(y.value,l.target,n,{itemSelector:"button"}):n==="up"&&Ae(E.value?.$el,-1,{itemSelector:".session-group"}))},Z=async l=>{const n=l?.credential;if(n)try{await o.deleteCredential(n),o.showMessage("Passkey deleted! You should also remove it from your password manager or device.","success",3e3)}catch(m){o.showMessage(`Failed to delete passkey: ${m.message}`,"error")}},ne=C(()=>o.settings?.rp_name||"this service"),re=C(()=>o.userInfo?.sessions||[]),ie=C(()=>re.value.find(n=>n.is_current)?.host||"this host"),Q=f({}),B=async l=>{const n=l?.id;if(n){Q.value={...Q.value,[n]:!0};try{await o.terminateSession(n)}catch(m){o.showMessage(m.message||"Failed to terminate session","error",5e3)}finally{const m={...Q.value};delete m[n],Q.value=m}}},he=async()=>{await o.logoutEverywhere()},pe=async()=>{await o.logout()},ke=()=>{x.value=o.userInfo?.ctx.user.display_name??"",L.value=!0},Ie=C(()=>{const l=o.userInfo?.ctx.permissions;return l.includes("auth:admin")||l.includes("auth:org:admin")}),ge=C(()=>re.value.length>1),xe=C(()=>{const l=[{label:"Auth",href:ft()}];return Ie.value&&l.push({label:"Admin",href:vt()}),l}),ue=async()=>{const l=x.value.trim();if(!l){o.showMessage("Name cannot be empty","error");return}try{D.value=!0,await Pe("/auth/api/user/display-name",{method:"PATCH",body:{display_name:l}}),L.value=!1,await o.loadUserInfo(),o.showMessage("Name updated successfully!","success",3e3)}catch(n){o.showMessage(n.message||"Failed to update name","error")}finally{D.value=!1}};return(l,n)=>(v(),_("section",Ot,[a("header",qt,[n[10]||(n[10]=a("h1",null,"User Profile",-1)),oe(yt,{ref_key:"breadcrumbs",ref:p,entries:xe.value,onKeydown:te},null,8,["entries"]),n[11]||(n[11]=a("p",{class:"view-lede"},"Account dashboard for managing credentials and authenticating with other devices.",-1))]),a("section",{class:"section-block",ref_key:"userInfoSection",ref:h},[b(o).userInfo?.ctx?(v(),J(Ge,{key:0,ref_key:"userBasicInfo",ref:d,name:b(o).userInfo.ctx.user.display_name,visits:b(o).userInfo.visits,"created-at":b(o).userInfo.created_at,"last-seen":b(o).userInfo.last_seen,loading:b(o).isLoading,"update-endpoint":"/auth/api/user/display-name",onSaved:n[1]||(n[1]=m=>b(o).loadUserInfo()),onEditName:ke,onKeydown:Y},{default:ze(()=>[a("div",Yt,[P.value?N("",!0):(v(),_("label",Zt,"Code words:")),oe(jt,{ref_key:"pairingEntry",ref:R,title:"",description:"",onCompleted:G,onError:le,onDeviceInfoVisible:n[0]||(n[0]=m=>P.value=m)},null,512)]),n[12]||(n[12]=a("p",{class:"remote-auth-description"},"Provided by another device requesting remote auth.",-1))]),_:1},8,["name","visits","created-at","last-seen","loading"])):N("",!0)],512),a("section",Jt,[n[13]||(n[13]=a("div",{class:"section-header"},[a("h2",null,"Your Passkeys"),a("p",{class:"section-description"},[K("Ideally have at least two passkeys in case you lose one. More than one user can be registered on the same device, giving you a choice at login. "),a("a",{href:"https://bitwarden.com/pricing/",target:"_blank",rel:"noopener noreferrer"},"Bitwarden"),K(" can sync one passkey to all your devices. Other secure options include "),a("b",null,"local passkeys"),K(", as well as hardware keys such as "),a("a",{href:"https://www.yubico.com",target:"_blank",rel:"noopener noreferrer"},"YubiKey"),K(". Cloud sync via Google, Microsoft or iCloud is discouraged.")])],-1)),a("div",Gt,[oe(wt,{ref_key:"credentialList",ref:i,credentials:b(o).userInfo?.credentials||[],"aaguid-info":b(o).userInfo?.aaguid_info||{},loading:b(o).isLoading,"hovered-credential-uuid":c.value,"hovered-session-credential-uuid":V.value?.credential,"navigation-disabled":g.value,"allow-delete":"",onDelete:Z,onCredentialHover:n[2]||(n[2]=m=>c.value=m),onNavigateOut:se},null,8,["credentials","aaguid-info","loading","hovered-credential-uuid","hovered-session-credential-uuid","navigation-disabled"]),a("div",{class:"button-row",ref_key:"credentialButtons",ref:M},[a("button",{onClick:O,class:"btn-primary",onKeydown:z},"Register New",32),a("button",{onClick:n[3]||(n[3]=m=>k.value=!0),class:"btn-secondary",onKeydown:z},"Another Device",32)],512)])]),oe(bt,{ref_key:"sessionList",ref:E,sessions:re.value,"terminating-sessions":Q.value,"hovered-credential-uuid":c.value,"navigation-disabled":g.value,onTerminate:B,onSessionHover:n[4]||(n[4]=m=>V.value=m),onNavigateOut:F,"section-description":"You are currently signed in to the following sessions. If you don't recognize something, consider deleting not only the session but the associated passkey you suspect is compromised, as only this terminates all linked sessions and prevents logging in again."},null,8,["sessions","terminating-sessions","hovered-credential-uuid","navigation-disabled"]),L.value?(v(),J(kt,{key:0,onClose:n[7]||(n[7]=m=>L.value=!1)},{default:ze(()=>[n[14]||(n[14]=a("h3",null,"Edit Display Name",-1)),a("form",{onSubmit:Je(ue,["prevent"]),class:"modal-form"},[oe(_t,{label:"Display Name",modelValue:x.value,"onUpdate:modelValue":n[5]||(n[5]=m=>x.value=m),busy:D.value,onCancel:n[6]||(n[6]=m=>L.value=!1)},null,8,["modelValue","busy"])],32)]),_:1})):N("",!0),a("section",Qt,[a("div",{class:"button-row",ref_key:"logoutButtons",ref:y},[a("button",{type:"button",class:"btn-secondary",onClick:n[8]||(n[8]=(...m)=>b(be)&&b(be)(...m)),onKeydown:T}," Back ",32),ge.value?(v(),_(de,{key:1},[a("button",{onClick:pe,class:"btn-danger",disabled:b(o).isLoading,onKeydown:T},"Logout",40,es),a("button",{onClick:he,class:"btn-danger",disabled:b(o).isLoading,onKeydown:T},"All",40,ts)],64)):(v(),_("button",{key:0,onClick:he,class:"btn-danger",disabled:b(o).isLoading,onKeydown:T},"Logout",40,Xt))],512),ge.value?(v(),_("p",ns,[n[16]||(n[16]=a("strong",null,"Logout",-1)),K(" this session on "+$(ie.value)+", or ",1),n[17]||(n[17]=a("strong",null,"All",-1)),K(" sessions across all sites and devices for "+$(ne.value)+". You'll need to log in again with your passkey afterwards.",1)])):(v(),_("p",ss,[n[15]||(n[15]=a("strong",null,"Logout",-1)),K(" from "+$(ie.value)+".",1)]))]),k.value?(v(),J(It,{key:1,endpoint:"/auth/api/user/create-link",onClose:n[9]||(n[9]=m=>k.value=!1),onCopied:ve})):N("",!0)]))}},as=Me(os,[["__scopeId","data-v-89d5d936"]]),ls={class:"view-root host-view","data-view":"host-profile"},rs={class:"view-header"},is={class:"view-lede"},us={class:"section-body"},cs={key:1,class:"empty-state"},ds={class:"section-block"},fs={class:"section-body host-actions"},vs=["disabled"],hs=["disabled"],ps={class:"note"},gs={__name:"HostProfileView",props:{initializing:{type:Boolean,default:!1}},setup(ae){const o=_e(),A=window.location.host,L=f(null),k=f(null),x=C(()=>o.userInfo?.ctx||null),D=C(()=>x.value?.org.display_name??""),c=C(()=>x.value?.role.display_name??""),V=C(()=>{const p=o.settings?.rp_name;return p?`${p} account`:"Account overview"}),P=C(()=>`You're signed in to ${A}.`),R=C(()=>o.settings?.auth_host||""),i=C(()=>{const p=R.value;if(!p)return"";let d=o.settings?.ui_base_path??"/auth/";return d.startsWith("/")||(d=`/${d}`),d.endsWith("/")||(d=`${d}/`),`${window.location.protocol||"https:"}//${p}${d}`}),M=()=>{i.value&&(window.location.href=i.value)},E=async()=>{await o.logout()},y=p=>{const d=fe(p);d&&(p.preventDefault(),(d==="left"||d==="right")&&we(k.value,p.target,d,{itemSelector:"button"}))};return(p,d)=>(v(),_("section",ls,[a("header",rs,[a("h1",null,$(V.value),1),a("p",is,$(P.value),1)]),a("section",{class:"section-block",ref_key:"userInfoSection",ref:L},[a("div",us,[x.value?(v(),J(Ge,{key:0,name:x.value.user.display_name,visits:b(o).userInfo?.visits||0,"created-at":b(o).userInfo?.created_at,"last-seen":b(o).userInfo?.last_seen,"org-display-name":D.value,"role-name":c.value,"can-edit":!1},null,8,["name","visits","created-at","last-seen","org-display-name","role-name"])):(v(),_("p",cs,$(ae.initializing?"Loading your account…":"No active session found."),1))])],512),a("section",ds,[a("div",fs,[a("div",{class:"button-row",ref_key:"buttonRow",ref:k,onKeydown:y},[a("button",{type:"button",class:"btn-secondary",onClick:d[0]||(d[0]=(...h)=>b(be)&&b(be)(...h))}," Back "),a("button",{type:"button",class:"btn-danger",disabled:b(o).isLoading,onClick:E},$(b(o).isLoading?"Signing out…":"Logout"),9,vs),i.value?(v(),_("button",{key:0,type:"button",class:"btn-primary",disabled:b(o).isLoading,onClick:M}," Full Profile ",8,hs)):N("",!0)],544),a("p",ps,[d[1]||(d[1]=a("strong",null,"Logout",-1)),K(" from "+$(b(A))+", or access your ",1),d[2]||(d[2]=a("strong",null,"Full Profile",-1)),K(" at "+$(R.value)+" (you may need to sign in again).",1)])])])]))}},ms=Me(gs,[["__scopeId","data-v-237999a2"]]),ys={class:"app-shell"},ws={class:"app-main"},bs={__name:"App",setup(ae){const o=_e(),A=f("loading"),L=f("Loading...");function k(d){if(!d)return null;const h=d.trim().toLowerCase();return h?h.replace(/:80$/,"").replace(/:443$/,""):null}const x=C(()=>{const d=o.settings?.auth_host;if(!d)return!1;const h=k(window.location.host),g=k(d);return h!==g});let D=null,c=null;function V(){o.userInfo=null,A.value="terminal"}async function P(){try{return o.userInfo=await Pe("/auth/api/user-info",{method:"POST"}),A.value="profile",y(),!0}catch{return o.userInfo=null,!1}}async function R(){i();const d=await pt("login");c=document.createElement("iframe"),c.id="auth-iframe",c.title="Authentication",c.allow="publickey-credentials-get; publickey-credentials-create",c.src=d,document.body.appendChild(c),L.value="Authentication required..."}function i(){c&&(c.remove(),c=null)}function M(d){const h=d.data;if(h?.type)switch(h.type){case"auth-success":i(),A.value="loading",L.value="Loading user profile...",P();break;case"auth-error":h.cancelled?console.log("Authentication cancelled by user"):o.showMessage(h.message||"Authentication failed","error",5e3);break;case"auth-cancelled":console.log("Authentication cancelled");break;case"auth-back":i(),V();break;case"auth-close-request":i();break}}async function E(){try{await Pe("/auth/api/validate",{method:"POST"})}catch{p(),V()}}function y(){p(),D=setInterval(E,120*1e3)}function p(){D&&(clearInterval(D),D=null)}return Ee(async()=>{window.addEventListener("message",M),await o.loadSettings();const d=o.settings?.rp_name;if(d){const g=o.settings?.auth_host,O=g&&k(window.location.host)!==k(g);document.title=O?`${d} · Account summary`:d}await P()||R()}),Be(()=>{window.removeEventListener("message",M),p(),i()}),(d,h)=>(v(),_("div",ys,[oe(St),a("main",ws,[A.value==="profile"&&x.value?(v(),J(ms,{key:0})):A.value==="profile"?(v(),J(as,{key:1})):A.value==="loading"?(v(),J(xt,{key:2,message:L.value},null,8,["message"])):A.value==="terminal"?(v(),J(Ct,{key:3})):N("",!0)])]))}},Qe=gt(bs);Qe.use($t());Qe.mount("#app");mt();
@@ -1 +0,0 @@
1
- .center[data-v-7ca316fc]{text-align:center}.button-row.center[data-v-7ca316fc]{display:flex;justify-content:center}.section-body[data-v-7ca316fc]{gap:1.25rem}.name-edit span[data-v-7ca316fc]{color:var(--color-text-muted);font-size:.9rem}
@@ -1 +0,0 @@
1
- import{_ as C,O as E,r as i,c as h,a4 as b,o as F,b as c,d as u,f as N,e as t,t as m,g as $,h as z,v as K,L as V,m as D,H as x,a5 as I,a6 as U,G,J as H,K as J}from"./_plugin-vue_export-helper-nhjnO_bd.js";const L={class:"app-shell"},O={key:0,class:"global-status",style:{display:"block"}},j={class:"view-root"},Y={class:"surface surface--tight",style:{"max-width":"560px",margin:"0 auto",width:"100%"}},q={class:"view-header",style:{"text-align":"center"}},Q={class:"view-lede"},W={key:0,class:"section-block"},X={key:1,class:"section-block"},Z={key:2,class:"section-block"},ee={class:"section-body"},se={class:"name-edit"},te=["disabled"],ae=["disabled"],ne={__name:"ResetApp",setup(ie){const o=E({show:!1,message:"",type:"info"}),d=i(!0),n=i(!1),l=i(""),T=i(null),g=i(null),f=i(""),y=i("");let p=null;const P=h(()=>g.value?.token_type||"your enrollment"),R=h(()=>d.value?"Preparing your secure enrollment…":v.value?`Finish up ${P.value}. You may edit the name below if needed, and it will be saved to your passkey.`:"This authentication link is no longer valid.");h(()=>b());const v=h(()=>!!(l.value&&g.value));function r(e,s="info",a=3e3){o.show=!0,o.message=e,o.type=s,p&&clearTimeout(p),a>0&&(p=setTimeout(()=>{o.show=!1},a))}async function S(){try{const e=await D();T.value=e,e?.rp_name&&(document.title=`${e.rp_name} · Passkey Setup`)}catch(e){console.warn("Unable to load settings",e)}}async function B(){if(l.value)try{g.value=await x("/auth/api/token-info",{method:"GET",headers:{Authorization:`Bearer ${l.value}`}}),f.value=g.value.display_name}catch(e){console.error("Failed to load token info",e);const s=e instanceof I?e.data?.detail||"The authentication link is invalid or expired.":U(e);y.value=s}}async function _(){if(!v.value||n.value)return;n.value=!0,r("Starting passkey registration…","info");let e;try{const s=f.value.trim()||null;e=await G.register(l.value,s)}catch(s){n.value=!1;const a=s?.message||"Passkey registration cancelled",w=a==="Passkey registration cancelled";r(w?a:`Registration failed: ${a}`,w?"info":"error",4e3);return}try{await A(e)}catch(s){n.value=!1;const a=s?.message||"Failed to establish session";r(a,"error",4e3);return}r("Passkey registered successfully!","success",800),setTimeout(()=>{n.value=!1,k()},800)}async function A(e){if(!e?.session_token)throw new Error("Registration response missing session_token");return await x("/auth/api/set-session",{method:"POST",headers:{Authorization:`Bearer ${e.session_token}`}})}function k(){const e=b.value||"/auth/";window.location.pathname!==e&&history.replaceState(null,"",e),window.location.reload()}function M(){const e=window.location.pathname.split("/").filter(Boolean);if(!e.length)return"";const s=e[e.length-1],a=e.slice(0,-1);return a.length>1||a.length===1&&a[0]!=="auth"||!s.includes(".")?"":s}return F(async()=>{if(l.value=M(),await S(),!l.value){const e="Reset link is missing or malformed.";y.value=e,r(e,"error",0),d.value=!1;return}await B(),d.value=!1}),(e,s)=>(u(),c("div",L,[o.show?(u(),c("div",O,[t("div",{class:$(["status",o.type])},m(o.message),3)])):N("",!0),t("main",j,[t("div",Y,[t("header",q,[s[1]||(s[1]=t("h1",null,"🔑 Registration",-1)),t("p",Q,m(R.value),1)]),d.value?(u(),c("section",W,[...s[2]||(s[2]=[t("div",{class:"section-body center"},[t("p",null,"Loading reset details…")],-1)])])):v.value?(u(),c("section",Z,[t("div",ee,[t("label",se,[s[3]||(s[3]=t("span",null,"👤 Name",-1)),z(t("input",{type:"text","onUpdate:modelValue":s[0]||(s[0]=a=>f.value=a),disabled:n.value,maxlength:"64",onKeyup:V(_,["enter"])},null,40,te),[[K,f.value]])]),t("button",{class:"btn-primary",disabled:n.value,onClick:_},m(n.value?"Registering…":"Register Passkey"),9,ae)])])):(u(),c("section",X,[t("div",{class:"section-body center"},[t("div",{class:"button-row center",style:{"justify-content":"center"}},[t("button",{class:"btn-secondary",onClick:k},"Return to sign-in")])])]))])])]))}},oe=C(ne,[["__scopeId","data-v-7ca316fc"]]);H(oe).mount("#app");J();
@@ -1,60 +0,0 @@
1
- paskia/__init__.py,sha256=6eopO87IOFA2zfOuqt8Jj8Tdtp93HBMOgUBtTzMRweM,57
2
- paskia/_version.py,sha256=LwGndsRSpclYq-j3wgRr2nzOXwUYj0Jtg7Kof7R0BEw,704
3
- paskia/authsession.py,sha256=7TGZuJw4RLsRJ-pemii6zRXTR-wdLx3nFVItytKFz5s,1259
4
- paskia/bootstrap.py,sha256=FShAMvLmLxQ4HfE9yz1ZB6EO9fC-lQroesU4dC58VO8,3875
5
- paskia/config.py,sha256=BdGzQ3Ja1enSTHmkDkBDGQk_JluT3VaK3Y7AqB5xMlk,723
6
- paskia/globals.py,sha256=ip03kLoS_27cNIgXTVcXNoeQDjTAC_IILuXaHKShTws,1712
7
- paskia/remoteauth.py,sha256=IyC1Z9YTYjPi4h8B0UwwoWfxaheEgyfksbKraOrAcqA,12418
8
- paskia/sansio.py,sha256=LQRdV1kW_aGwDWC8fhyEvqWPwKZVx_8qzQv65et6utg,9727
9
- paskia/aaguid/__init__.py,sha256=I5HMkAwiyLKKlkZOb9z5s2xGApXIbhbBuuX3IhW2y8E,1047
10
- paskia/aaguid/combined_aaguid.json,sha256=CaZ96AiwdAjBnyVZnJ1eolAHxUQMB2H6mDgZkorYg_A,4124722
11
- paskia/db/__init__.py,sha256=BGiCFZFX4xMsFn6aKvuV7X7VL-NoA-URdl2493EfRXE,3220
12
- paskia/db/background.py,sha256=hj3hXoEpneVWhrAHZvoL09DVVaqOTqe-n9RIJZbbEos,3546
13
- paskia/db/jsonl.py,sha256=LvrdGlfkChZGWTmB3eblnoSsgQ5Oulm2aDtWmF4RpHQ,9934
14
- paskia/db/logging.py,sha256=akbYSsqSrkXGAEyhWQCGCYKl61zMsIQf35QMHjddYcQ,7503
15
- paskia/db/migrations.py,sha256=XHHC0LbxXBN6gldiKm4PhDVqEqroMN1E8tz0LEqGPbQ,957
16
- paskia/db/operations.py,sha256=Zm60HSraQEDAW3i4PjR7ouu5Y_qd7gWSBG8nT-ujDro,26275
17
- paskia/db/structs.py,sha256=G6udtoomKmB8wijO6x1AObX9Oas66gBmJ_YxIiDLO6E,14060
18
- paskia/fastapi/__init__.py,sha256=NFsTX1qytoyZKiur7RDTa2fxiOWHrop5CAAx8rqK9E0,58
19
- paskia/fastapi/__main__.py,sha256=AULbSTfQcRUYejocFxJlzCdx0VW7zx4KznBy0n-pJms,7775
20
- paskia/fastapi/admin.py,sha256=xzMhqSEokFSOlNETdRZ9ZNu3bwiaEKo3T34Byisiq_c,30303
21
- paskia/fastapi/api.py,sha256=zmSRt0CZG6YyMrQGgXBuxZmpOfNVpiMJ9dPrW1Y28sM,9125
22
- paskia/fastapi/auth_host.py,sha256=Y5w9Mz6jyq0hj7SX8LfwebaesUOLGcWzGW9lsmw5WOo,3242
23
- paskia/fastapi/authz.py,sha256=6s2TGkb3C7qWTXHOaMj613NiqMfztqM5QENuSb2IjO8,3529
24
- paskia/fastapi/logging.py,sha256=oED1CWcAYFsm6eo1pBZ-GbbMstlMrJmSFloqPuu8mQU,6858
25
- paskia/fastapi/mainapp.py,sha256=wZS0Jo75Y1mesvrJp1lWKpdHzdNjjlFinzA-idezYaQ,5005
26
- paskia/fastapi/remote.py,sha256=062r1fWlgUafetyKu_ZDlQ8jdR4nGJWvndry9puRfVQ,18855
27
- paskia/fastapi/reset.py,sha256=MuZqhOF68P9kGq5zKPV19FjTIvhZQ423YowzHKcVjlc,3573
28
- paskia/fastapi/response.py,sha256=gTPNJtS92HfQYey2DMMN8oM1YazNSj6tjBBuFJuuBhc,611
29
- paskia/fastapi/session.py,sha256=BRnlgR8pTY7o0f7qFnkdyepS2fKEAgqwT9Hj951sZJM,1479
30
- paskia/fastapi/user.py,sha256=1vi1usiH8IFqqmLkwq2CLoy-x46VTlUnsiNglndajV8,4599
31
- paskia/fastapi/ws.py,sha256=JBaKfD39z5Ow-2zuZ5U7sbeH_QqzhUHYrl6JVn0XhF0,4503
32
- paskia/fastapi/wschat.py,sha256=eUtVTGyxVIG2DOZIpjeYGgJRBpU5LnWfTT66vIsKaOA,1818
33
- paskia/fastapi/wsutil.py,sha256=qZobEP8Ca4jLtauCC9VEiMSVyg6tTkfxsSZHmXrXPQM,3094
34
- paskia/frontend-build/auth/index.html,sha256=PhNRnHQSaQCIyiSl8fZqidC-PIGMe_KWLJokw0N8628,936
35
- paskia/frontend-build/auth/admin/index.html,sha256=jiCkfwVKDRT-nmz1OEwWzZBw8tNMXGnNjIfaIBXJ4fE,862
36
- paskia/frontend-build/auth/assets/AccessDenied-DPkUS8LZ.css,sha256=s7BvCBUV8YZQA1riEuXFvBGcm8dRr6QNZ1VJMBWoKPA,7941
37
- paskia/frontend-build/auth/assets/AccessDenied-Fmeb6EtF.js,sha256=6ZgY9gSDDLtQUq0k4N5YWlpqpGyQW9r_X9ocWgSHuVM,51702
38
- paskia/frontend-build/auth/assets/RestrictedAuth-CvR33_Z0.css,sha256=jOnmoy1hon9QwzoY9tHmhd-0zUye9v9-bv5zPku82GY,5397
39
- paskia/frontend-build/auth/assets/RestrictedAuth-DsJXicIw.js,sha256=YctOv9_npORcB8kdudZs2iEf2yKhWJkLPTZTkvu-qB8,9761
40
- paskia/frontend-build/auth/assets/_plugin-vue_export-helper-BTzJAQlS.css,sha256=GpCu32ZoXHmL_8wVVa0Yja8dtKpaJSRyfitYAURx4Yc,12796
41
- paskia/frontend-build/auth/assets/_plugin-vue_export-helper-nhjnO_bd.js,sha256=6UQZRGDUU0m_cRZd_QKtt-4C1-3H2MtocoRR89is2AI,84746
42
- paskia/frontend-build/auth/assets/admin-CPE1pLMm.js,sha256=EgB9vPz_8Zey0klCLnAaQgPANnLrAXWnar64oZFZiqM,41005
43
- paskia/frontend-build/auth/assets/admin-DzzjSg72.css,sha256=X8K-ycZwZ3gXNdB8YFMxdGpRD8uS_Qeq0_awx9eJ-VY,7599
44
- paskia/frontend-build/auth/assets/auth-C7k64Wad.css,sha256=x1CKaX0MmuunxZvew4ArCusqTYNrNjLv4JW2bnvZhDg,4333
45
- paskia/frontend-build/auth/assets/auth-YIZvPlW_.js,sha256=pSJnxtX9ALwKNAu0rL7LAfr0zZIxy_Y--Qn5UllyMng,25209
46
- paskia/frontend-build/auth/assets/forward-DmqVHZ7e.js,sha256=rfiUg6N9ez9WuZA-pWf0CViV7j4-UoWqH3riFDr81xE,782
47
- paskia/frontend-build/auth/assets/helpers-DzjFIx78.js,sha256=w_IsCBn3QwidsuwQhVRycd8Fa53lvbgRGGojTBXVlUc,940
48
- paskia/frontend-build/auth/assets/pow-2N9bxgAo.js,sha256=7AfzW5lcTefPI6YGXrYao1b56L7v5Bon9Y9N40yHsaE,9447
49
- paskia/frontend-build/auth/assets/reset-Chtv69AT.css,sha256=1iFB1F8va7Ktdn7YxAMyNU8keFcaalmo25mCCM5QQys,238
50
- paskia/frontend-build/auth/assets/reset-s20PATTN.js,sha256=Fo4u2Kz58spVVJ2BmV3Q_HPG8x5jysL5_0KDYQbVRac,3976
51
- paskia/frontend-build/auth/assets/restricted-D3AJx3_6.js,sha256=H7L5F3nW6btinOZPgi8U_yLkxBO93L_rTeDMUWx7-Ow,1023
52
- paskia/frontend-build/auth/restricted/index.html,sha256=6RPwe3edRPjM2-TLp87S9C170NM0gGYufboL_sp7q-k,785
53
- paskia/frontend-build/int/forward/index.html,sha256=iA5lgiEgLxszNEdvTi7jMawKkhSTWydU8idRs0LLKlw,870
54
- paskia/frontend-build/int/reset/index.html,sha256=E6ylRX8-OupR3eBUPSzFRH1_rXVft93esAY0zaoVFBQ,612
55
- paskia/migrate/__init__.py,sha256=r2s99mbHfvlzQJ1V3xnxZOwIyMEMxEXDtFqFj7sJC2U,9916
56
- paskia/migrate/sql.py,sha256=5HNEUnPP0kqis69URJ5keE4JNbwqWe8oYXwf-zKheLI,14333
57
- paskia-0.9.1.dist-info/METADATA,sha256=Ivym2LhgRqG8wPZ1RyT4mM5wFYCTdwmP5MzplugNUE0,4261
58
- paskia-0.9.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
59
- paskia-0.9.1.dist-info/entry_points.txt,sha256=vvx6RYetgd61I2ODqQPHqrKHgCfuo08w_T35yDlHenE,93
60
- paskia-0.9.1.dist-info/RECORD,,