forked from cxykevin/sacn_accout_system
完成重置密码
This commit is contained in:
parent
a7c0a51b71
commit
08b822fff8
|
@ -1,7 +1,7 @@
|
||||||
from fastapi.security import OAuth2PasswordBearer
|
from fastapi.security import OAuth2PasswordBearer
|
||||||
from fastapi import FastAPI, Cookie, Response, Form
|
from fastapi import FastAPI, Cookie, Response, Form
|
||||||
from fastapi.templating import Jinja2Templates
|
from fastapi.templating import Jinja2Templates
|
||||||
from fastapi.responses import RedirectResponse
|
from fastapi.responses import RedirectResponse, HTMLResponse
|
||||||
from datetime import timedelta, datetime
|
from datetime import timedelta, datetime
|
||||||
from contextlib import asynccontextmanager
|
from contextlib import asynccontextmanager
|
||||||
from . import db
|
from . import db
|
||||||
|
@ -72,7 +72,7 @@ oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
|
||||||
def check_passwd(passwd: str):
|
def check_passwd(passwd: str):
|
||||||
if (len(passwd) < 8):
|
if (len(passwd) < 8):
|
||||||
return 1
|
return 1
|
||||||
pattern = r'^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]{8,}$'
|
pattern = r'^(?![a-zA-Z]+$)(?!\d+$)(?![^\da-zA-Z\s]+$).{8,40}$'
|
||||||
|
|
||||||
if re.match(pattern, passwd):
|
if re.match(pattern, passwd):
|
||||||
return 0
|
return 0
|
||||||
|
@ -150,12 +150,14 @@ async def login_callback(username: str = Form(), password: str = Form(), email:
|
||||||
|
|
||||||
|
|
||||||
@app.get("/api/checkemail")
|
@app.get("/api/checkemail")
|
||||||
async def login_callback(uid: str):
|
async def checkemail(uid: str):
|
||||||
if (uid not in emails):
|
if (uid not in emails):
|
||||||
return templates.TemplateResponse("checkemail.html", {"request": {}, "msg": "不存在的注册id"})
|
return templates.TemplateResponse("checkemail.html", {"request": {}, "msg": "不存在的注册id"})
|
||||||
if (emails[uid][2] < datetime.now()):
|
if (emails[uid][2] < datetime.now()):
|
||||||
del emails[uid]
|
del emails[uid]
|
||||||
return templates.TemplateResponse("checkemail.html", {"request": {}, "msg": "链接已过期"})
|
return templates.TemplateResponse("checkemail.html", {"request": {}, "msg": "链接已过期"})
|
||||||
|
if (emails[uid][1] == ""):
|
||||||
|
return templates.TemplateResponse("checkemail.html", {"request": {}, "msg": "不存在的注册id"})
|
||||||
if await db.create_user(emails[uid][0], emails[uid][1], emails[uid][3]) == 0:
|
if await db.create_user(emails[uid][0], emails[uid][1], emails[uid][3]) == 0:
|
||||||
del emails[uid]
|
del emails[uid]
|
||||||
return templates.TemplateResponse("checkemail.html", {"request": {}, "msg": "创建成功"})
|
return templates.TemplateResponse("checkemail.html", {"request": {}, "msg": "创建成功"})
|
||||||
|
@ -164,6 +166,36 @@ async def login_callback(uid: str):
|
||||||
return templates.TemplateResponse("checkemail.html", {"request": {}, "msg": "重复的用户名"})
|
return templates.TemplateResponse("checkemail.html", {"request": {}, "msg": "重复的用户名"})
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/api/resetpasswd", response_class=HTMLResponse)
|
||||||
|
async def resetpasswd(uid: str, response: Response):
|
||||||
|
if (uid not in emails):
|
||||||
|
return templates.TemplateResponse("checkemail.html", {"request": {}, "msg": "不存在的验证id"})
|
||||||
|
if (emails[uid][2] < datetime.now()):
|
||||||
|
del emails[uid]
|
||||||
|
return templates.TemplateResponse("checkemail.html", {"request": {}, "msg": "链接已过期"})
|
||||||
|
if (emails[uid][1] != ""):
|
||||||
|
return templates.TemplateResponse("checkemail.html", {"request": {}, "msg": "不存在的注册id"})
|
||||||
|
tokennow = await create_token(emails[uid][0])
|
||||||
|
tkn = uuid.uuid4().hex
|
||||||
|
apikeys[tkn] = tokens[tokennow]
|
||||||
|
response.set_cookie("session", tokennow)
|
||||||
|
return '<html><head><meta http-equiv="refresh" content="0;url=/user"><title>正在跳转</title></head><body>正在跳转</body></html>'
|
||||||
|
|
||||||
|
|
||||||
|
@app.post("/api/send_resetpasswd")
|
||||||
|
async def resetpasswd(username: str = Form()):
|
||||||
|
if (await db.check_user(username)):
|
||||||
|
email = await db.get_email(username)
|
||||||
|
tkn = uuid.uuid4().hex
|
||||||
|
emails[tkn] = (username, "", datetime.now() +
|
||||||
|
timedelta(minutes=float(ACCESS_EMAIL_EXPIRE_MINUTES)), email)
|
||||||
|
|
||||||
|
email_send_lst.append((email, ROOT+"/api/resetpasswd?uid="+tkn))
|
||||||
|
return {"msg": "验证邮件已发送到邮箱,请在10分钟内完成验证", "code": 0}
|
||||||
|
else:
|
||||||
|
return {"msg": "用户名不存在", "code": 1}
|
||||||
|
|
||||||
|
|
||||||
@app.get("/api/getinfo")
|
@app.get("/api/getinfo")
|
||||||
async def get_user_info(uid: str):
|
async def get_user_info(uid: str):
|
||||||
username = await check_apikey(uid)
|
username = await check_apikey(uid)
|
||||||
|
@ -219,6 +251,11 @@ async def login(session: Annotated[str | None, Cookie()] = None):
|
||||||
return templates.TemplateResponse("manage.html", {"request": {}})
|
return templates.TemplateResponse("manage.html", {"request": {}})
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/resetpasswd")
|
||||||
|
async def resetpasswd(response: Response):
|
||||||
|
return templates.TemplateResponse("resetpasswd.html", {"request": {}})
|
||||||
|
|
||||||
|
|
||||||
@app.get("/manager/init")
|
@app.get("/manager/init")
|
||||||
async def init(key: str):
|
async def init(key: str):
|
||||||
if (key != MANAGE_KEY):
|
if (key != MANAGE_KEY):
|
||||||
|
|
|
@ -27,15 +27,16 @@ def main(app: FastAPI, ROOT: str, apikeys: dict):
|
||||||
return Response("""
|
return Response("""
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
var signup_obj = document.getElementsByClassName(
|
var signup_obj = document.getElementsByClassName(
|
||||||
"item-signUp")[0]
|
"item-logIn")[0]
|
||||||
if(signup_obj!=undefined){
|
if(signup_obj!=undefined){
|
||||||
signup_obj.style.display = "none";
|
signup_obj.style.display = "none";
|
||||||
}
|
}
|
||||||
document.getElementsByClassName(
|
var btn_obj=document.getElementsByClassName("item-logIn")[0]
|
||||||
"item-logIn")[0].innerHTML = "<a href='"""+ROOT+"""/login?redirect_url="+window.location.href+"'>登录/注册</a>";
|
if(btn_obj != undefined){
|
||||||
|
btn_obj.innerHTML = "<a href='"""+ROOT+"""/login?redirect_url="+window.location.href+"'>注册/登录</a>"}
|
||||||
}, 500);
|
}, 500);
|
||||||
|
|
||||||
|
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
var hashs = window.location.hash
|
var hashs = window.location.hash
|
||||||
if(hashs!==""){
|
if(hashs!==""){
|
||||||
|
@ -45,17 +46,18 @@ def main(app: FastAPI, ROOT: str, apikeys: dict):
|
||||||
var key = res[0]
|
var key = res[0]
|
||||||
var xhr = new XMLHttpRequest()
|
var xhr = new XMLHttpRequest()
|
||||||
var csrf = JSON.parse(document.getElementById("flarum-json-payload").innerText)["session"]["csrfToken"]
|
var csrf = JSON.parse(document.getElementById("flarum-json-payload").innerText)["session"]["csrfToken"]
|
||||||
xhr.open('post','"""+FL_SERVER+"""/app/flarum/login?apikey='+key+'&csrftoken='+csrf);
|
xhr.open('post','/app/flarum/login?apikey='+key+'&csrftoken='+csrf);
|
||||||
xhr.onreadyStatechange = function () {
|
xhr.onreadyStatechange = function () {
|
||||||
if(xhr.readyState === 4 && xhr.status === 200) {
|
if(xhr.readyState === 4 && xhr.status === 200) {
|
||||||
console.log(xhr.responseText)
|
console.log(xhr.responseText)
|
||||||
|
window.location.hash = ""
|
||||||
|
location.reload()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
xhr.send()
|
xhr.send()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
|
||||||
""", 200, None, media_type="application/javascript")
|
""", 200, None, media_type="application/javascript")
|
||||||
|
|
||||||
@app.post("/app/flarum/login")
|
@app.post("/app/flarum/login")
|
||||||
|
|
|
@ -0,0 +1,86 @@
|
||||||
|
<html class="mdui-theme-auto">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<link rel="stylesheet" href="https://learn.study-area.org.cn/theme/css/mdui.css">
|
||||||
|
<script src="https://learn.study-area.org.cn/theme/js/mdui.global.js" type="text/javascript"></script>
|
||||||
|
<link href="https://learn.study-area.org.cn/theme/css/icons.css" rel="stylesheet">
|
||||||
|
<title>StuyAreaCN Accout System</title>
|
||||||
|
<style>
|
||||||
|
* {
|
||||||
|
font-family: Arial, Helvetica, sans-serif;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<body style="margin:0;padding:0;">
|
||||||
|
<mdui-dialog id="dialog" close-on-overlay-click>
|
||||||
|
</mdui-dialog>
|
||||||
|
<mdui-layout style="height: 100%">
|
||||||
|
<mdui-top-app-bar>
|
||||||
|
<mdui-top-app-bar-title>StudyAreaCN</mdui-top-app-bar-title>
|
||||||
|
</mdui-top-app-bar>
|
||||||
|
|
||||||
|
<mdui-navigation-drawer class="navi-drawer" id="toc-drawer">
|
||||||
|
<mdui-list>
|
||||||
|
<mdui-list-item end-icon="arrow_right" href="https://learn.study-area.org.cn"
|
||||||
|
rounded>开始学习</mdui-list-item>
|
||||||
|
<mdui-list-item end-icon="arrow_right" href="https://forum.study-area.org.cn"
|
||||||
|
rounded>讨论区</mdui-list-item>
|
||||||
|
<mdui-list-item end-icon="arrow_right"
|
||||||
|
href="https://git.hmtsai.cn/study-area-cn/study-area-cn-homepage/" rounded>查看本站源码</mdui-list-item>
|
||||||
|
</mdui-list>
|
||||||
|
</mdui-navigation-drawer>
|
||||||
|
|
||||||
|
<mdui-layout-main style="height: 100%">
|
||||||
|
<div style="width: 100%;height: 100%">
|
||||||
|
<mdui-card
|
||||||
|
style="width:30%;min-width:400px;height:60%;min-height:500px;margin: auto;display: block;transform: translate(-50%,-50%);left: 50%;top: 50%;position: absolute;"
|
||||||
|
id="cards">
|
||||||
|
<div class="header"
|
||||||
|
style="font-size: 38px;font-weight: bold;text-align: center;line-height: 160px;">
|
||||||
|
重置密码
|
||||||
|
</div>
|
||||||
|
<mdui-text-field id="username"
|
||||||
|
style="display:block;height:54px;width:90%;margin:auto;margin-bottom: 16px"
|
||||||
|
label="用户名"></mdui-text-field>
|
||||||
|
<div style="position: absolute;bottom:20px;width:100%">
|
||||||
|
<mdui-button id="loginbtn" style="width:90%;margin-right:10px;margin-left:5%"
|
||||||
|
onclick="logins()">发送邮件</mdui-button>
|
||||||
|
</div>
|
||||||
|
</mdui-card>
|
||||||
|
</div>
|
||||||
|
</mdui-layout-main>
|
||||||
|
</mdui-layout>
|
||||||
|
<script>
|
||||||
|
if (window.innerWidth > 800) {
|
||||||
|
document.getElementById("cards").style.transform = "translateY(-50%)"
|
||||||
|
document.getElementById("toc-drawer").setAttribute('open', true);
|
||||||
|
}
|
||||||
|
function logins() {
|
||||||
|
document.getElementById("loginbtn").setAttribute('loading', "");
|
||||||
|
const Http = new XMLHttpRequest();
|
||||||
|
const url = '/api/send_resetpasswd';
|
||||||
|
Http.open("POST", url);
|
||||||
|
var formData = new FormData();
|
||||||
|
formData.append('username', document.getElementById("username").value);
|
||||||
|
Http.send(formData);
|
||||||
|
|
||||||
|
Http.addEventListener('loadend', () => {
|
||||||
|
var ret = JSON.parse(Http.responseText)
|
||||||
|
if (ret.msg == "") {
|
||||||
|
const searchParams = new URLSearchParams(window.location.search);
|
||||||
|
window.location.href = "/login/?redirect_url=/user"
|
||||||
|
} else {
|
||||||
|
document.getElementById("dialog").innerHTML = ret.msg
|
||||||
|
document.getElementById("dialog").setAttribute("open", "")
|
||||||
|
}
|
||||||
|
document.getElementById("loginbtn").removeAttribute('loading');
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
Loading…
Reference in New Issue