安全增强: - 新增 SSRF、XXE、模板注入、敏感路径探测检测规则 - security/constants.py: 添加新的威胁类型和检测模式 - security/threat_detector.py: 实现新检测逻辑 删除密码重置申请功能: - 移除 /api/password_resets 相关API - 删除 password_reset_requests 数据库表 - 前端移除密码重置申请页面和菜单 - 用户只能通过邮��找回密码,未绑定邮箱需联系管理员 登录提醒全局开关: - email_service.py: 添加 login_alert_enabled 字段 - routes/api_auth.py: 检查开关状态再发送登录提醒 - EmailPage.vue: 添加新设备登录提醒开关 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2 lines
7.7 KiB
JavaScript
2 lines
7.7 KiB
JavaScript
import{_ as Z,r as j,a as n,c as ee,o as ae,b as S,d as a,w as t,e as g,u as te,f,g as v,h as k,i as w,j as z,k as d,E as i}from"./index-CEOd73lG.js";import{f as le,l as oe,g as H,a as se,r as ne}from"./auth-WsWSY0rn.js";const re={class:"auth-wrap"},ie={class:"captcha-row"},ue=["src"],ce={class:"links"},de={class:"foot"},pe={class:"captcha-row"},me=["src"],fe={class:"captcha-row"},ve=["src"],ge={__name:"LoginPage",setup(ye){const A=te(),r=j({username:"",password:"",captcha:""}),_=n(!1),C=n(""),F=n(""),I=n(!1),y=n(!1),N=n(!1),h=n(!1),b=n(!1),p=j({username:"",captcha:""}),x=n(""),T=n(""),K=n(!1),V=n(""),m=j({email:"",captcha:""}),U=n(""),P=n(""),M=n(!1),D=ee(()=>!!N.value);async function E(){try{const l=await H();F.value=l?.session_id||"",C.value=l?.captcha_image||"",r.captcha=""}catch{F.value="",C.value=""}}async function B(){try{const l=await H();T.value=l?.session_id||"",x.value=l?.captcha_image||"",p.captcha=""}catch{T.value="",x.value=""}}async function R(){try{const l=await H();P.value=l?.session_id||"",U.value=l?.captcha_image||"",m.captcha=""}catch{P.value="",U.value=""}}async function O(){if(!r.username.trim()||!r.password.trim()){i.error("用户名和密码不能为空");return}if(_.value&&!r.captcha.trim()){i.error("请输入验证码");return}I.value=!0;try{await oe({username:r.username.trim(),password:r.password,captcha_session:F.value,captcha:r.captcha.trim(),need_captcha:_.value}),i.success("登录成功,正在跳转..."),setTimeout(()=>{window.location.href="/app"},300)}catch(l){const e=l?.response?.status,s=l?.response?.data,u=s?.error||s?.message||"登录失败";i.error(u),s?.need_captcha?(_.value=!0,await E()):_.value&&e===400&&await E()}finally{I.value=!1}}async function G(){h.value=!0,V.value="",p.username="",p.captcha="",y.value&&await B()}async function J(){if(V.value="",!y.value){i.warning("邮件功能未启用,请联系管理员重置密码。");return}const l=p.username.trim();if(!l){i.error("请输入用户名");return}if(!p.captcha.trim()){i.error("请输入验证码");return}K.value=!0;try{const e=await se({username:l,captcha_session:T.value,captcha:p.captcha.trim()});i.success(e?.message||"已发送重置邮件"),setTimeout(()=>{h.value=!1},800)}catch(e){const s=e?.response?.data,u=s?.error||"发送失败";s?.code==="email_not_bound"?V.value=u:i.error(u),await B()}finally{K.value=!1}}async function Q(){b.value=!0,m.email="",m.captcha="",await R()}async function W(){const l=m.email.trim();if(!l){i.error("请输入邮箱");return}if(!m.captcha.trim()){i.error("请输入验证码");return}M.value=!0;try{const e=await ne({email:l,captcha_session:P.value,captcha:m.captcha.trim()});i.success(e?.message||"验证邮件已发送,请查收"),setTimeout(()=>{b.value=!1},800)}catch(e){const s=e?.response?.data;i.error(s?.error||"发送失败"),await R()}finally{M.value=!1}}function X(){A.push("/register")}return ae(async()=>{try{const l=await le();y.value=!!l?.email_enabled,N.value=!!l?.register_verify_enabled}catch{y.value=!1,N.value=!1}}),(l,e)=>{const s=g("el-input"),u=g("el-form-item"),c=g("el-button"),$=g("el-form"),Y=g("el-card"),L=g("el-alert"),q=g("el-dialog");return f(),S("div",re,[a(Y,{shadow:"never",class:"auth-card","body-style":{padding:"22px"}},{default:t(()=>[e[17]||(e[17]=v("div",{class:"brand"},[v("div",{class:"brand-title"},"知识管理平台"),v("div",{class:"brand-sub app-muted"},"用户登录")],-1)),a($,{"label-position":"top"},{default:t(()=>[a(u,{label:"用户名"},{default:t(()=>[a(s,{modelValue:r.username,"onUpdate:modelValue":e[0]||(e[0]=o=>r.username=o),placeholder:"请输入用户名",autocomplete:"username"},null,8,["modelValue"])]),_:1}),a(u,{label:"密码"},{default:t(()=>[a(s,{modelValue:r.password,"onUpdate:modelValue":e[1]||(e[1]=o=>r.password=o),type:"password","show-password":"",placeholder:"请输入密码",autocomplete:"current-password",onKeyup:z(O,["enter"])},null,8,["modelValue"])]),_:1}),_.value?(f(),k(u,{key:0,label:"验证码"},{default:t(()=>[v("div",ie,[a(s,{modelValue:r.captcha,"onUpdate:modelValue":e[2]||(e[2]=o=>r.captcha=o),placeholder:"请输入验证码",onKeyup:z(O,["enter"])},null,8,["modelValue"]),C.value?(f(),S("img",{key:0,class:"captcha-img",src:C.value,alt:"验证码",title:"点击刷新",onClick:E},null,8,ue)):w("",!0),a(c,{onClick:E},{default:t(()=>[...e[11]||(e[11]=[d("刷新",-1)])]),_:1})])]),_:1})):w("",!0)]),_:1}),v("div",ce,[a(c,{text:"",type:"primary",onClick:G},{default:t(()=>[...e[12]||(e[12]=[d("忘记密码?",-1)])]),_:1}),D.value?(f(),k(c,{key:0,text:"",type:"primary",onClick:Q},{default:t(()=>[...e[13]||(e[13]=[d("重发验证邮件",-1)])]),_:1})):w("",!0)]),a(c,{type:"primary",class:"submit-btn",loading:I.value,onClick:O},{default:t(()=>[...e[14]||(e[14]=[d("登录",-1)])]),_:1},8,["loading"]),v("div",de,[e[16]||(e[16]=v("span",{class:"app-muted"},"还没有账号?",-1)),a(c,{link:"",type:"primary",onClick:X},{default:t(()=>[...e[15]||(e[15]=[d("立即注册",-1)])]),_:1})])]),_:1}),a(q,{modelValue:h.value,"onUpdate:modelValue":e[6]||(e[6]=o=>h.value=o),title:"找回密码",width:"min(560px, 92vw)"},{footer:t(()=>[a(c,{onClick:e[5]||(e[5]=o=>h.value=!1)},{default:t(()=>[...e[19]||(e[19]=[d("取消",-1)])]),_:1}),a(c,{type:"primary",loading:K.value,disabled:!y.value,onClick:J},{default:t(()=>[...e[20]||(e[20]=[d(" 发送重置邮件 ",-1)])]),_:1},8,["loading","disabled"])]),default:t(()=>[y.value?(f(),k(L,{key:1,type:"info",closable:!1,title:"通过邮箱找回密码",description:"输入用户名并完成验证码,我们将向该账号绑定的邮箱发送重置链接。","show-icon":""})):(f(),k(L,{key:0,type:"warning",closable:!1,title:"邮件功能未启用",description:"无法通过邮箱找回密码,请联系管理员重置密码。","show-icon":""})),V.value?(f(),k(L,{key:2,type:"warning",closable:!1,title:"无法通过邮箱找回密码",description:V.value,"show-icon":"",class:"alert"},null,8,["description"])):w("",!0),a($,{"label-position":"top",class:"dialog-form"},{default:t(()=>[a(u,{label:"用户名"},{default:t(()=>[a(s,{modelValue:p.username,"onUpdate:modelValue":e[3]||(e[3]=o=>p.username=o),placeholder:"请输入用户名"},null,8,["modelValue"])]),_:1}),a(u,{label:"验证码"},{default:t(()=>[v("div",pe,[a(s,{modelValue:p.captcha,"onUpdate:modelValue":e[4]||(e[4]=o=>p.captcha=o),placeholder:"请输入验证码"},null,8,["modelValue"]),x.value?(f(),S("img",{key:0,class:"captcha-img",src:x.value,alt:"验证码",title:"点击刷新",onClick:B},null,8,me)):w("",!0),a(c,{onClick:B},{default:t(()=>[...e[18]||(e[18]=[d("刷新",-1)])]),_:1})])]),_:1})]),_:1})]),_:1},8,["modelValue"]),a(q,{modelValue:b.value,"onUpdate:modelValue":e[10]||(e[10]=o=>b.value=o),title:"重发验证邮件",width:"min(520px, 92vw)"},{footer:t(()=>[a(c,{onClick:e[9]||(e[9]=o=>b.value=!1)},{default:t(()=>[...e[22]||(e[22]=[d("取消",-1)])]),_:1}),a(c,{type:"primary",loading:M.value,onClick:W},{default:t(()=>[...e[23]||(e[23]=[d("发送",-1)])]),_:1},8,["loading"])]),default:t(()=>[a(L,{type:"info",closable:!1,title:"用于注册邮箱验证:请输入邮箱并完成验证码。","show-icon":""}),a($,{"label-position":"top",class:"dialog-form"},{default:t(()=>[a(u,{label:"邮箱"},{default:t(()=>[a(s,{modelValue:m.email,"onUpdate:modelValue":e[7]||(e[7]=o=>m.email=o),placeholder:"name@example.com"},null,8,["modelValue"])]),_:1}),a(u,{label:"验证码"},{default:t(()=>[v("div",fe,[a(s,{modelValue:m.captcha,"onUpdate:modelValue":e[8]||(e[8]=o=>m.captcha=o),placeholder:"请输入验证码"},null,8,["modelValue"]),U.value?(f(),S("img",{key:0,class:"captcha-img",src:U.value,alt:"验证码",title:"点击刷新",onClick:R},null,8,ve)):w("",!0),a(c,{onClick:R},{default:t(()=>[...e[21]||(e[21]=[d("刷新",-1)])]),_:1})])]),_:1})]),_:1})]),_:1},8,["modelValue"])])}}},he=Z(ge,[["__scopeId","data-v-c04a6b1b"]]);export{he as default};
|