1import{j as e}from"./vendor-ui-DNBdI4Ha.js";import{r}from"./vendor-react-52Io9c9Z.js";import{u as P,b as g}from"./vendor-query-6SQeGrfO.js";import{C as v,a as k,b as y,d as N,c as b}from"./card-B4pQQJzg.js";import{a as W,co as X,w as u,Q as Y,aa as w,aq as a,a9 as Q,ar as d,cs as Z,J as _,L as ee,ae as S,af as C,cp as F}from"./index-RlmAM5G5.js";import{S as E}from"./switch-CrW11c0S.js";import{S as O}from"./save-DZkQLNcN.js";import{T as se}from"./triangle-alert-DEbPPTKI.js";import{T as te}from"./trash-2-CSJfEHg0.js";import"./vendor-other-DiuCbciQ.js";import"./index-1mJH378g.js";function pe(){const{toast:l}=W(),{ensureStepUp:m}=X(),n=r.useRef(!1),T=r.useRef(!1),[i,M]=r.useState(null),[c,L]=r.useState(null),[G,U]=r.useState(!1),[$,D]=r.useState(!1),{data:R,isLoading:z}=P({queryKey:["/api/admin/settings/security"]}),{data:A,isLoading:J}=P({queryKey:["/api/admin/settings/risk"]}),{data:I,isLoading:V}=P({queryKey:["/api/admin/security/blocked-ips"]}),[x,H]=r.useState(""),[K,B]=r.useState(""),p=g({mutationFn:async({ipAddress:s,reason:t})=>{await S("POST","/api/admin/security/blocked-ips",{ipAddress:s,reason:t})},onSuccess:()=>{C.invalidateQueries({queryKey:["/api/admin/security/blocked-ips"]}),H(""),B(""),l({title:"IP blocked successfully"})},onError:(s,t)=>{if(s instanceof F&&!n.current){n.current=!0,m(s.require2fa,s.maxAgeMinutes).then(()=>p.mutate(t)).catch(()=>{}).finally(()=>{n.current=!1});return}l({title:"Error",description:s.message||"Failed to block IP",variant:"destructive"})}}),q=g({mutationFn:async s=>{await S("DELETE",`/api/admin/security/blocked-ips/${s}`)},onSuccess:()=>{C.invalidateQueries({queryKey:["/api/admin/security/blocked-ips"]}),l({title:"IP unblocked successfully"})},onError:(s,t)=>{if(s instanceof F&&!n.current){n.current=!0,m(s.require2fa,s.maxAgeMinutes).then(()=>q.mutate(t)).catch(()=>{}).finally(()=>{n.current=!1});return}l({title:"Error",description:"Failed to unblock IP",variant:"destructive"})}});r.useEffect(()=>{R&&!i&&M(R)},[R]),r.useEffect(()=>{A&&!c&&L(A)},[A]);const h=g({mutationFn:async s=>{await S("PUT","/api/admin/settings/security",s)},onSuccess:()=>{C.invalidateQueries({queryKey:["/api/admin/settings/security"]}),U(!1),l({title:"Settings saved",description:"Security policies have been updated."})},onError:(s,t)=>{if(s instanceof F&&!n.current){n.current=!0,m(s.require2fa,s.maxAgeMinutes).then(()=>h.mutate(t)).catch(()=>{}).finally(()=>{n.current=!1});return}l({title:"Error",description:"Failed to save settings.",variant:"destructive"})}}),f=g({mutationFn:async s=>{await S("PUT","/api/admin/settings/risk",s)},onSuccess:()=>{C.invalidateQueries({queryKey:["/api/admin/settings/risk"]}),D(!1),l({title:"Settings saved",description:"Risk policies have been updated."})},onError:(s,t)=>{if(s instanceof F&&!T.current){T.current=!0,m(s.require2fa,s.maxAgeMinutes).then(()=>f.mutate(t)).catch(()=>{}).finally(()=>{T.current=!1});return}l({title:"Error",description:"Failed to save risk settings.",variant:"destructive"})}});function o(s,t){i&&(M({...i,[s]:t}),U(!0))}function j(s,t){c&&(L({...c,[s]:t}),D(!0))}return z||J||!i?e.jsx("div",{className:"flex items-center justify-center py-12",children:e.jsx(u,{className:"h-6 w-6 animate-spin text-muted-foreground"})}):e.jsxs("div",{className:"max-w-3xl mx-auto p-6 space-y-6",children:[e.jsxs("div",{className:"flex items-center justify-between gap-4 flex-wrap",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(Y,{className:"h-6 w-6 text-muted-foreground"}),e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-semibold","data-testid":"text-policies-title",children:"Security Policies"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Configure authentication and access controls"})]})]}),G&&e.jsxs(w,{onClick:()=>h.mutate(i),disabled:h.isPending,"data-testid":"button-save-policies",children:[h.isPending?e.jsx(u,{className:"h-4 w-4 animate-spin mr-2"}):e.jsx(O,{className:"h-4 w-4 mr-2"}),"Save Changes"]})]}),e.jsxs(v,{children:[e.jsxs(k,{children:[e.jsx(y,{children:"Authentication"}),e.jsx(N,{children:"Configure how users authenticate"})]}),e.jsxs(b,{className:"space-y-6",children:[e.jsxs("div",{className:"flex items-center justify-between gap-4",children:[e.jsxs("div",{children:[e.jsx(a,{className:"text-sm font-medium",children:"Require 2FA for Admins"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Admin users must set up two-factor authentication"})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[!i.require2faForAdmins&&e.jsxs(Q,{variant:"outline",className:"text-amber-600 border-amber-300",children:[e.jsx(se,{className:"h-3 w-3 mr-1"}),"Not enforced"]}),e.jsx(E,{checked:i.require2faForAdmins,onCheckedChange:s=>o("require2faForAdmins",s),"data-testid":"switch-require-2fa"})]})]}),e.jsxs("div",{className:"flex items-center justify-between gap-4",children:[e.jsxs("div",{children:[e.jsx(a,{className:"text-sm font-medium",children:"Email OTP"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Send one-time codes via email for verification"})]}),e.jsx(E,{checked:i.emailOtpEnabled,onCheckedChange:s=>o("emailOtpEnabled",s),"data-testid":"switch-email-otp"})]}),e.jsxs("div",{className:"flex items-center justify-between gap-4",children:[e.jsxs("div",{children:[e.jsx(a,{className:"text-sm font-medium",children:"Require Device Approval for Admins"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"New devices must be approved before admin access"})]}),e.jsx(E,{checked:i.requireDeviceApprovalForAdmins,onCheckedChange:s=>o("requireDeviceApprovalForAdmins",s),"data-testid":"switch-device-approval"})]})]})]}),e.jsxs(v,{children:[e.jsxs(k,{children:[e.jsx(y,{children:"Account Lockout"}),e.jsx(N,{children:"Configure brute-force protection settings"})]}),e.jsx(b,{className:"space-y-4",children:e.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(a,{htmlFor:"lockoutThreshold",className:"text-sm font-medium",children:"Failed Attempts Before Lockout"}),e.jsx(d,{id:"lockoutThreshold",type:"number",min:1,max:20,value:i.lockoutThreshold,onChange:s=>o("lockoutThreshold",parseInt(s.target.value)||5),"data-testid":"input-lockout-threshold"})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(a,{htmlFor:"lockoutMinutes",className:"text-sm font-medium",children:"Lockout Duration (minutes)"}),e.jsx(d,{id:"lockoutMinutes",type:"number",min:1,max:120,value:i.lockoutMinutes,onChange:s=>o("lockoutMinutes",parseInt(s.target.value)||15),"data-testid":"input-lockout-minutes"})]})]})})]}),c&&e.jsxs(v,{children:[e.jsxs(k,{className:"flex flex-row items-center justify-between gap-4 flex-wrap",children:[e.jsxs("div",{children:[e.jsxs(y,{className:"flex items-center gap-2",children:[e.jsx(Z,{className:"h-5 w-5"}),"Risk Scoring"]}),e.jsx(N,{children:"Configure session risk detection thresholds"})]}),$&&e.jsxs(w,{onClick:()=>f.mutate(c),disabled:f.isPending,"data-testid":"button-save-risk",children:[f.isPending?e.jsx(u,{className:"h-4 w-4 animate-spin mr-2"}):e.jsx(O,{className:"h-4 w-4 mr-2"}),"Save Risk Settings"]})]}),e.jsxs(b,{className:"space-y-4",children:[e.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(a,{htmlFor:"riskForceStepUpScore",className:"text-sm font-medium",children:"Force Step-Up Threshold"}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Risk score that forces re-verification (0-100)"}),e.jsx(d,{id:"riskForceStepUpScore",type:"number",min:10,max:100,value:c.riskForceStepUpScore,onChange:s=>j("riskForceStepUpScore",parseInt(s.target.value)||50),"data-testid":"input-risk-force-score"})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(a,{htmlFor:"riskForceStepUpMinutes",className:"text-sm font-medium",children:"Forced Duration (minutes)"}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"How long the forced step-up lasts"}),e.jsx(d,{id:"riskForceStepUpMinutes",type:"number",min:5,max:120,value:c.riskForceStepUpMinutes,onChange:s=>j("riskForceStepUpMinutes",parseInt(s.target.value)||30),"data-testid":"input-risk-force-minutes"})]})]}),e.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(a,{htmlFor:"riskTtlHigh",className:"text-sm font-medium",children:"TTL at High Risk (minutes)"}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Max verification window when score is 50+"}),e.jsx(d,{id:"riskTtlHigh",type:"number",min:1,max:30,value:c.riskTtlHigh,onChange:s=>j("riskTtlHigh",parseInt(s.target.value)||5),"data-testid":"input-risk-ttl-high"})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(a,{htmlFor:"riskTtlCritical",className:"text-sm font-medium",children:"TTL at Critical Risk (minutes)"}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Max verification window when score is 80+"}),e.jsx(d,{id:"riskTtlCritical",type:"number",min:1,max:10,value:c.riskTtlCritical,onCh
1ange:s=>j("riskTtlCritical",parseInt(s.target.value)||2),"data-testid":"input-risk-ttl-critical"})]})]})]})]}),e.jsxs(v,{children:[e.jsxs(k,{children:[e.jsxs(y,{className:"flex items-center gap-2",children:[e.jsx(_,{className:"h-5 w-5"}),"Global Firewall"]}),e.jsx(N,{children:"Explicitly drop requests from abusive nodes entirely across all domains"})]}),e.jsxs(b,{className:"space-y-4",children:[e.jsxs("div",{className:"flex items-end gap-3",children:[e.jsxs("div",{className:"flex-1 space-y-1",children:[e.jsx(a,{htmlFor:"blockIp",className:"text-sm",children:"IP Address"}),e.jsx(d,{id:"blockIp",placeholder:"203.0.113.0",value:x,onChange:s=>H(s.target.value),"data-testid":"input-block-ip"})]}),e.jsxs("div",{className:"flex-1 space-y-1",children:[e.jsx(a,{htmlFor:"blockReason",className:"text-sm",children:"Reason (Optional)"}),e.jsx(d,{id:"blockReason",placeholder:"Repeated login failures",value:K,onChange:s=>B(s.target.value),"data-testid":"input-block-reason"})]}),e.jsxs(w,{onClick:()=>{x.trim()&&p.mutate({ipAddress:x.trim(),reason:K.trim()})},disabled:!x.trim()||p.isPending,"data-testid":"button-block-ip",children:[p.isPending?e.jsx(u,{className:"h-4 w-4 animate-spin mr-2"}):e.jsx(ee,{className:"h-4 w-4 mr-2"}),"Block IP"]})]}),e.jsxs("div",{className:"space-y-2 mt-6",children:[e.jsx("h4",{className:"text-sm font-medium",children:"Currently Blocked IPs"}),V?e.jsx("div",{className:"flex items-center justify-center py-4",children:e.jsx(u,{className:"h-4 w-4 animate-spin text-muted-foreground"})}):!I||I.length===0?e.jsx("p",{className:"text-sm text-muted-foreground py-2 text-center border rounded-md",children:"No IPs are currently blocked globally."}):e.jsx("div",{className:"border rounded-md divide-y",children:I.map(s=>e.jsxs("div",{className:"flex items-center justify-between p-3","data-testid":`row-blocked-ip-${s.id}`,children:[e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"font-mono text-sm",children:s.ipAddress}),s.reason&&e.jsx(Q,{variant:"secondary",className:"text-[10px]",children:s.reason})]}),e.jsxs("span",{className:"text-xs text-muted-foreground",children:["Blocked ",new Date(s.createdAt).toLocaleDateString()]})]}),e.jsx(w,{variant:"ghost",size:"icon",onClick:()=>q.mutate(s.id),disabled:q.isPending,"data-testid":`button-unblock-ip-${s.id}`,children:e.jsx(te,{className:"h-4 w-4 text-destructive"})})]},s.id))})]})]})]})]})}export{pe as default};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.