1 line
15 KiB
JavaScript
1 line
15 KiB
JavaScript
import{a as n,j as e}from"./vendor-react-YMhRUmcb.js";import{a as E,g as k,B as F,D as I,p as M,l as Q,L as X,E as O,C as T,s as P,d as H,t as z}from"./index-D2uzyr9g.js";import{r as D}from"./features-CKIBrJL0.js";import{q as b}from"./vendor-fFnFILYR.js";import{L as v,I as N}from"./input-DL1WY4HG.js";import{T as $}from"./textarea-DfK27c18.js";import{aa as J,g as q,O as K,aE as V,aF as W,T as Z,ao as ee}from"./vendor-icons-DINCNwpk.js";import{S as se}from"./Select-So_RP28r.js";import"./vendor-router-DX94Iu-2.js";import"./vendor-tanstack-CoFNL2zy.js";import"./vendor-utils-4BWoYre8.js";import"./dropdown-DLDDI8f2.js";async function re(){try{const r=await E.get("/roles");return Array.isArray(r.data)?r.data:[]}catch(r){if(r instanceof b){if(r.response?.status===401)throw new Error("Unauthorized: Please log in to access roles");if(r.response?.status===403)throw new Error("Forbidden: You do not have permission to view roles");const s=r.response?.data?.error||r.message||"Failed to fetch roles";throw new Error(s)}throw r}}async function te(r){try{return(await E.get(`/roles/${r}`)).data}catch(s){if(s instanceof b){if(s.response?.status===401)throw new Error("Unauthorized: Please log in to access role");if(s.response?.status===403)throw new Error("Forbidden: You do not have permission to view this role");if(s.response?.status===404)throw new Error("Role not found");const t=s.response?.data?.error||s.message||"Failed to fetch role";throw new Error(t)}throw s}}async function ae(r){try{return(await E.get(`/users/${r}/roles`)).data.roles||[]}catch(s){if(s instanceof b){if(s.response?.status===401)throw new Error("Unauthorized: Please log in to access user roles");if(s.response?.status===403)throw new Error("Forbidden: You do not have permission to view user roles");if(s.response?.status===404)throw new Error("User not found");const t=s.response?.data?.error||s.message||"Failed to fetch user roles";throw new Error(t)}throw s}}async function oe(r,s){D("ROLE_MANAGEMENT");try{await E.post(`/users/${r}/roles`,s)}catch(t){if(t instanceof b){if(t.response?.status===400){const h=t.response?.data?.error||"Invalid request data";throw new Error(h)}if(t.response?.status===401)throw new Error("Unauthorized: Please log in to assign roles");if(t.response?.status===403)throw new Error("Forbidden: You do not have permission to assign roles");if(t.response?.status===404)throw new Error("User or role not found");const c=t.response?.data?.error||t.message||"Failed to assign role";throw new Error(c)}throw t}}async function ne(r){try{return(await E.post("/roles",r)).data.role}catch(s){if(s instanceof b){if(s.response?.status===400){const c=s.response?.data?.error||"Invalid role data";throw new Error(c)}if(s.response?.status===401)throw new Error("Unauthorized: Please log in to create roles");if(s.response?.status===403)throw new Error("Forbidden: You do not have permission to create roles");const t=s.response?.data?.error||s.message||"Failed to create role";throw new Error(t)}throw s}}async function Y(r,s){D("ROLE_MANAGEMENT");try{await E.put(`/roles/${r}`,s)}catch(t){if(t instanceof b){if(t.response?.status===400){const h=t.response?.data?.error||"Invalid role data";throw new Error(h)}if(t.response?.status===401)throw new Error("Unauthorized: Please log in to update roles");if(t.response?.status===403)throw new Error("Forbidden: You do not have permission to update roles");if(t.response?.status===404)throw new Error("Role not found or is a system role");const c=t.response?.data?.error||t.message||"Failed to update role";throw new Error(c)}throw t}}async function ie(r){D("ROLE_MANAGEMENT");try{await E.delete(`/roles/${r}`)}catch(s){if(s instanceof b){if(s.response?.status===400){const c=s.response?.data?.error||"Cannot delete system role";throw new Error(c)}if(s.response?.status===401)throw new Error("Unauthorized: Please log in to delete roles");if(s.response?.status===403)throw new Error("Forbidden: You do not have permission to delete roles");if(s.response?.status===404)throw new Error("Role not found");const t=s.response?.data?.error||s.message||"Failed to delete role";throw new Error(t)}throw s}}function le({onRoleCreated:r}){const[s,t]=n.useState(!1),[c,h]=n.useState(!1),[d,x]=n.useState({name:"",display_name:"",description:"",is_active:!0}),{success:m,error:u}=k(),p=async()=>{h(!0);try{await ne(d),m("Role created successfully"),t(!1),x({name:"",display_name:"",description:"",is_active:!0}),r(),x({name:"",display_name:"",description:"",is_active:!0}),r()}catch(l){const f=M(l);u(f.message)}finally{h(!1)}};return e.jsxs(e.Fragment,{children:[e.jsxs(F,{onClick:()=>t(!0),children:[e.jsx(J,{className:"h-4 w-4 mr-2"}),"Create Role"]}),e.jsx(I,{open:s,onClose:()=>t(!1),title:"Create New Role",onConfirm:p,confirmLabel:c?"Creating...":"Create Role",cancelLabel:"Cancel",children:e.jsxs("form",{onSubmit:l=>{l.preventDefault(),p()},className:"space-y-4",children:[e.jsxs("div",{children:[e.jsx(v,{htmlFor:"name",children:"Name *"}),e.jsx(N,{id:"name",value:d.name,onChange:l=>x({...d,name:l.target.value}),placeholder:"e.g., content_moderator",required:!0})]}),e.jsxs("div",{children:[e.jsx(v,{htmlFor:"display_name",children:"Display Name *"}),e.jsx(N,{id:"display_name",value:d.display_name,onChange:l=>x({...d,display_name:l.target.value}),placeholder:"e.g., Content Moderator",required:!0})]}),e.jsxs("div",{children:[e.jsx(v,{htmlFor:"description",children:"Description"}),e.jsx($,{id:"description",value:d.description,onChange:l=>x({...d,description:l.target.value}),placeholder:"Role description...",rows:3})]}),e.jsxs("div",{className:"flex items-center space-x-2",children:[e.jsx("input",{type:"checkbox",id:"is_active",checked:d.is_active,onChange:l=>x({...d,is_active:l.target.checked}),className:"rounded"}),e.jsx(v,{htmlFor:"is_active",children:"Active"})]})]})})]})}function ce({role:r,open:s,onClose:t,onRoleUpdated:c}){const[h,d]=n.useState(!1),[x,m]=n.useState(!1),[u,p]=n.useState({name:r.name,display_name:r.display_name,description:r.description,is_active:r.is_active}),{success:l,error:f}=k();n.useEffect(()=>{s&&r.id&&(m(!0),te(r.id).then(i=>{p({name:i.name,display_name:i.display_name,description:i.description,is_active:i.is_active})}).catch(i=>{const y=M(i);f(y.message)}).finally(()=>{m(!1)}))},[s,r.id,f]);const g=async()=>{d(!0);try{await Y(r.id,u),l("Role updated successfully"),t(),c()}catch(i){const y=M(i);f(y.message)}finally{d(!1)}};return e.jsx(I,{open:s,onClose:t,title:"Edit Role",onConfirm:g,confirmLabel:h?"Updating...":"Update Role",cancelLabel:"Cancel",children:x?e.jsx("div",{className:"flex justify-center py-8",children:e.jsx(q,{className:"h-8 w-8 animate-spin"})}):e.jsxs("form",{onSubmit:i=>{i.preventDefault(),g()},className:"space-y-4",children:[e.jsxs("div",{children:[e.jsx(v,{htmlFor:"edit-name",children:"Name *"}),e.jsx(N,{id:"edit-name",value:u.name,onChange:i=>p({...u,name:i.target.value}),required:!0,disabled:r.is_system}),r.is_system&&e.jsx("p",{className:"text-xs text-muted-foreground mt-1",children:"System roles cannot be renamed"})]}),e.jsxs("div",{children:[e.jsx(v,{htmlFor:"edit-display_name",children:"Display Name *"}),e.jsx(N,{id:"edit-display_name",value:u.display_name,onChange:i=>p({...u,display_name:i.target.value}),required:!0})]}),e.jsxs("div",{children:[e.jsx(v,{htmlFor:"edit-description",children:"Description"}),e.jsx($,{id:"edit-description",value:u.description,onChange:i=>p({...u,description:i.target.value}),rows:3})]}),e.jsxs("div",{className:"flex items-center space-x-2",children:[e.jsx("input",{type:"checkbox",id:"edit-is_active",checked:u.is_active,onChange:i=>p({...u,is_active:i.target.checked}),className:"rounded",disabled:r.is_system}),e.jsx(v,{htmlFor:"edit-is_active",children:"Active"}),r.is_system&&e.jsx("p",{className:"text-xs text-muted-foreground ml-2",children:"System roles are always active"})]})]})})}function de({userId:r,userName:s,availableRoles:t,open:c,onClose:h,onRoleAssigned:d}){const[x,m]=n.useState(!1),[u,p]=n.useState(!1),[l,f]=n.useState(""),[g,i]=n.useState(""),[y,U]=n.useState([]),{success:L,error:w}=k();n.useEffect(()=>{c&&r&&(p(!0),ae(r).then(o=>{U(o)}).catch(o=>{const j=M(o);Q.error("Failed to load user roles",{error:j.message,stack:o instanceof Error?o.stack:void 0,userId:r})}).finally(()=>{p(!1)}))},[c,r]);const R=async()=>{if(!l){w("Please select a role");return}m(!0);try{await oe(r,{role_id:l,expires_at:g||void 0}),L("Role assigned successfully"),h(),f(""),i(""),d(),i(""),d()}catch(o){const j=M(o);w(j.message)}finally{m(!1)}},_=t.filter(o=>!y.some(j=>j.id===o.id)),S=_.map(o=>({value:o.id,label:`${o.display_name} (${o.name})`}));return e.jsx(I,{open:c,onClose:h,title:`Assign Role${s?` to ${s}`:""}`,onConfirm:R,confirmLabel:x?"Assigning...":"Assign Role",cancelLabel:"Cancel",children:u?e.jsx("div",{className:"flex justify-center py-8",children:e.jsx(q,{className:"h-8 w-8 animate-spin"})}):e.jsxs("form",{onSubmit:R,className:"space-y-4",children:[e.jsxs("div",{children:[e.jsx(v,{htmlFor:"role-select",children:"Role *"}),_.length===0?e.jsx("div",{className:"p-2 text-sm text-muted-foreground border rounded",children:"No available roles to assign"}):e.jsx(se,{options:S,value:l,onChange:o=>f(Array.isArray(o)?o[0]:o),placeholder:"Select a role"})]}),e.jsxs("div",{children:[e.jsx(v,{htmlFor:"expires-at",children:"Expires At (optional)"}),e.jsx(N,{id:"expires-at",type:"datetime-local",value:g,onChange:o=>i(o.target.value)}),e.jsx("p",{className:"text-xs text-muted-foreground mt-1",children:"Leave empty for permanent assignment"})]}),y.length>0&&e.jsxs("div",{children:[e.jsx(v,{children:"Current Roles"}),e.jsx("div",{className:"mt-2 space-y-1",children:y.map(o=>e.jsxs("div",{className:"text-sm text-muted-foreground",children:["• ",o.display_name]},o.id))})]})]})})}function Ee(){const[r,s]=n.useState([]),[t,c]=n.useState(!0),[h,d]=n.useState(null),[x,m]=n.useState(null),[u,p]=n.useState(null),[l,f]=n.useState(0),g=n.useRef(null),[i,y]=n.useState(!1),[U,L]=n.useState(!1),[w,R]=n.useState(""),[_,S]=n.useState(""),o=async()=>{try{c(!0),d(null);const a=await re();s(a)}catch(a){d(new Error(a instanceof Error?a.message:"Failed to load roles"))}finally{c(!1)}};n.useEffect(()=>{o()},[]);const j=async a=>{const C=async()=>{await Y(a.id,{is_active:!a.is_active}),z.success(`Role ${a.is_active?"deactivated":"activated"} successfully`),o(),m(null),f(0),g.current=null};g.current=C,m(null);try{await C()}catch(A){m(new Error(A instanceof Error?A.message:"Failed to update role"))}},B=async a=>{if(a.is_system){m(new Error("Cannot delete system roles"));return}const C=async()=>{await ie(a.id),z.success("Role deleted successfully"),o(),m(null),f(0),g.current=null};g.current=C,m(null);try{await C()}catch(A){m(new Error(A instanceof Error?A.message:"Failed to delete role"))}},G=async()=>{if(!(!g.current||l>=3)){f(a=>a+1);try{await g.current()}catch{}}};return t?e.jsx("div",{className:"flex min-h-[50vh] items-center justify-center",children:e.jsx(X,{})}):h&&r.length===0?e.jsx("div",{className:"container mx-auto px-4 py-8",children:e.jsx(O,{error:h,variant:"card",severity:"error",onRetry:o})}):e.jsxs("div",{className:"container mx-auto px-4 py-8 max-w-6xl pb-24",children:[x&&e.jsx(O,{error:x,variant:"banner",severity:"error",onRetry:l<3?G:void 0,onDismiss:()=>{m(null),f(0),g.current=null}}),e.jsxs("div",{className:"mb-8 flex items-end justify-between",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-3xl font-display font-bold text-white mb-2",children:"Access Control"}),e.jsxs("p",{className:"text-muted-foreground font-mono text-xs flex items-center gap-2",children:[e.jsx(K,{className:"w-4 h-4 text-primary"})," ROLE & PERMISSION MATRIX"]})]}),e.jsx(le,{onRoleCreated:o})]}),e.jsxs("div",{className:"grid gap-6",children:[e.jsxs(T,{variant:"glass",className:"border-white/5 bg-black/40 overflow-hidden",children:[e.jsxs("div",{className:"grid grid-cols-12 gap-4 p-4 border-b border-white/5 text-xs font-bold uppercase tracking-wider text-muted-foreground",children:[e.jsx("div",{className:"col-span-3",children:"Role Identity"}),e.jsx("div",{className:"col-span-3",children:"Attributes"}),e.jsx("div",{className:"col-span-2 text-center",children:"Type"}),e.jsx("div",{className:"col-span-2 text-center",children:"Status"}),e.jsx("div",{className:"col-span-2 text-right",children:"Actions"})]}),e.jsx("div",{className:"divide-y divide-white/5",children:r.length===0?e.jsx("div",{className:"text-center py-12 text-muted-foreground",children:"No roles initialized."}):r.map(a=>e.jsxs("div",{className:"grid grid-cols-12 gap-4 p-4 items-center hover:bg-white/5 transition-colors group",children:[e.jsxs("div",{className:"col-span-3",children:[e.jsx("div",{className:"font-bold text-white group-hover:text-primary transition-colors",children:a.name}),e.jsx("div",{className:"text-xs text-muted-foreground",children:a.display_name})]}),e.jsx("div",{className:"col-span-3 text-sm text-muted-foreground truncate",title:a.description,children:a.description}),e.jsx("div",{className:"col-span-2 text-center",children:a.is_system?e.jsx(P,{variant:"primary",className:"border-primary/50 text-primary bg-primary/10",children:"SYSTEM"}):e.jsx(P,{variant:"secondary",className:"border-white/20 text-muted-foreground",children:"CUSTOM"})}),e.jsx("div",{className:"col-span-2 text-center",children:e.jsx("div",{className:H("inline-flex h-2 w-2 rounded-full",a.is_active?"bg-lime-500 shadow-[0_0_5px_var(--color-lime-500)]":"bg-red-500")})}),e.jsx("div",{className:"col-span-2 flex justify-end gap-2 opacity-60 group-hover:opacity-100 transition-opacity",children:a.is_system?e.jsx(V,{className:"w-4 h-4 text-muted-foreground"}):e.jsxs(e.Fragment,{children:[e.jsx(F,{size:"sm",variant:"ghost",onClick:()=>j(a),children:a.is_active?"Deactivate":"Activate"}),e.jsx(F,{size:"sm",variant:"ghost",onClick:()=>{p(a),y(!0)},children:e.jsx(W,{className:"w-4 h-4"})}),e.jsx(F,{size:"sm",variant:"ghost",className:"text-red-500 hover:bg-red-500/10",onClick:()=>B(a),children:e.jsx(Z,{className:"w-4 h-4"})})]})})]},a.id))})]}),e.jsxs(T,{variant:"glass",className:"p-6 border-white/5 bg-black/40",children:[e.jsxs("h3",{className:"font-bold text-white mb-4 flex items-center gap-2 text-sm uppercase tracking-widest",children:[e.jsx(ee,{className:"w-4 h-4 text-primary"})," Role Assignment"]}),e.jsxs("div",{className:"flex gap-4 items-end",children:[e.jsxs("div",{className:"flex-1 space-y-2",children:[e.jsx("label",{className:"text-xs text-muted-foreground ml-1",children:"User ID"}),e.jsx(N,{placeholder:"UID-...",value:w,onChange:a=>R(a.target.value),className:"bg-black/40 font-mono"})]}),e.jsxs("div",{className:"flex-1 space-y-2",children:[e.jsx("label",{className:"text-xs text-muted-foreground ml-1",children:"Username (Optional)"}),e.jsx(N,{placeholder:"@username",value:_,onChange:a=>S(a.target.value),className:"bg-black/40"})]}),e.jsx(F,{onClick:()=>{R(w),S(_||""),L(!0)},disabled:!w,className:"shadow-glow-cyan",children:"Assign Access"})]})]})]}),u&&e.jsx(ce,{role:u,open:i,onClose:()=>{y(!1),p(null)},onRoleUpdated:o}),e.jsx(de,{userId:w,userName:_,availableRoles:r.filter(a=>a.is_active),open:U,onClose:()=>{L(!1),R(""),S("")},onRoleAssigned:()=>{}})]})}export{Ee as RolesPage};
|