注册码生成以及用户注册
This commit is contained in:
@@ -42,6 +42,10 @@
|
||||
<button id="loginBtn" type="submit">登录</button>
|
||||
<div id="error" class="error"></div>
|
||||
</form>
|
||||
<div class="hint" style="text-align:center; margin-top:12px;">
|
||||
还没有账号?
|
||||
<a href="/accounts/register/" style="color:#2d8cf0; text-decoration:none;">去注册</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="{% static 'accounts/login.js' %}"></script>
|
||||
|
||||
62
accounts/templates/accounts/register.html
Normal file
62
accounts/templates/accounts/register.html
Normal file
@@ -0,0 +1,62 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>用户注册</title>
|
||||
<style>
|
||||
body { font-family: system-ui, -apple-system, Segoe UI, Roboto, sans-serif; background: #f5f6fa; }
|
||||
.container { max-width: 400px; margin: 10vh auto; padding: 24px; background: #fff; border-radius: 10px; box-shadow: 0 8px 24px rgba(0,0,0,0.08); }
|
||||
h1 { font-size: 20px; margin: 0 0 16px; }
|
||||
label { display:block; margin: 12px 0 6px; color:#333; }
|
||||
input { width:100%; padding:10px 12px; border:1px solid #dcdde1; border-radius:6px; }
|
||||
button { width:100%; margin-top:16px; padding:10px 12px; background:#2d8cf0; color:#fff; border:none; border-radius:6px; cursor:pointer; }
|
||||
button:disabled { background:#9bbcf0; cursor:not-allowed; }
|
||||
.error { color:#d93025; margin-top:10px; min-height:20px; }
|
||||
.hint { color:#888; font-size:12px; margin-top:10px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>注册新用户</h1>
|
||||
<form id="regForm">
|
||||
{% csrf_token %}
|
||||
<label for="code">注册码</label>
|
||||
<input id="code" name="code" type="text" required />
|
||||
<label for="email">邮箱</label>
|
||||
<input id="email" name="email" type="email" required />
|
||||
<label for="username">用户名</label>
|
||||
<input id="username" name="username" type="text" required />
|
||||
<label for="password">密码</label>
|
||||
<input id="password" name="password" type="password" required />
|
||||
<label for="confirm">确认密码</label>
|
||||
<input id="confirm" name="confirm" type="password" required />
|
||||
<button id="regBtn" type="submit">注册</button>
|
||||
<div id="error" class="error"></div>
|
||||
</form>
|
||||
<div class="hint">仅允许持有管理员提供注册码的学生注册</div>
|
||||
</div>
|
||||
<script>
|
||||
function getCookie(name){const v=`; ${document.cookie}`;const p=v.split(`; ${name}=`);if(p.length===2) return p.pop().split(';').shift();}
|
||||
document.getElementById('regForm').addEventListener('submit',async(e)=>{
|
||||
e.preventDefault();
|
||||
const err=document.getElementById('error'); err.textContent='';
|
||||
const code=(document.getElementById('code').value||'').trim();
|
||||
const email=(document.getElementById('email').value||'').trim();
|
||||
const username=(document.getElementById('username').value||'').trim();
|
||||
const password=document.getElementById('password').value||'';
|
||||
const confirm=document.getElementById('confirm').value||'';
|
||||
if(!code||!email||!username||!password){err.textContent='请填写所有字段';return;}
|
||||
if(password!==confirm){err.textContent='两次密码不一致';return;}
|
||||
const btn=document.getElementById('regBtn'); btn.disabled=true;
|
||||
try{
|
||||
const csrftoken=getCookie('csrftoken');
|
||||
const resp=await fetch('/accounts/register/submit/',{method:'POST',credentials:'same-origin',headers:{'Content-Type':'application/json','X-CSRFToken':csrftoken||''},body:JSON.stringify({code,email,username,password})});
|
||||
const data=await resp.json();
|
||||
if(!resp.ok||!data.ok){throw new Error(data.message||'注册失败');}
|
||||
window.location.href=data.redirect_url;
|
||||
}catch(e){err.textContent=e.message||'发生错误';}
|
||||
finally{btn.disabled=false;}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -9,4 +9,6 @@ urlpatterns = [
|
||||
path("session-key/", views.set_session_key, name="set_session_key"),
|
||||
path("login/secure-submit/", views.secure_login_submit, name="secure_login_submit"),
|
||||
path("logout/", views.logout, name="logout"),
|
||||
path("register/", views.register_page, name="register"),
|
||||
path("register/submit/", views.register_submit, name="register_submit"),
|
||||
]
|
||||
@@ -13,6 +13,7 @@ from django.conf import settings
|
||||
|
||||
from .es_client import get_user_by_username
|
||||
from .crypto import get_public_key_spki_b64, rsa_oaep_decrypt_b64, aes_gcm_decrypt_b64, verify_password
|
||||
from elastic.es_connect import get_registration_code, get_user_by_username as es_get_user_by_username, get_all_users as es_get_all_users, write_user_data
|
||||
|
||||
|
||||
@require_http_methods(["GET"])
|
||||
@@ -157,4 +158,54 @@ def logout(request):
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return resp
|
||||
return resp
|
||||
|
||||
@require_http_methods(["GET"])
|
||||
@ensure_csrf_cookie
|
||||
def register_page(request):
|
||||
return render(request, "accounts/register.html")
|
||||
|
||||
@require_http_methods(["POST"])
|
||||
@csrf_protect
|
||||
def register_submit(request):
|
||||
try:
|
||||
payload = json.loads(request.body.decode("utf-8"))
|
||||
except json.JSONDecodeError:
|
||||
return HttpResponseBadRequest("Invalid JSON")
|
||||
code = (payload.get("code") or "").strip()
|
||||
email = (payload.get("email") or "").strip()
|
||||
username = (payload.get("username") or "").strip()
|
||||
password = (payload.get("password") or "")
|
||||
if not code or not email or not username or not password:
|
||||
return HttpResponseBadRequest("Missing fields")
|
||||
rc = get_registration_code(code)
|
||||
if not rc:
|
||||
return JsonResponse({"ok": False, "message": "注册码无效"}, status=400)
|
||||
try:
|
||||
exp = rc.get("expires_at")
|
||||
now = __import__("datetime").datetime.now(__import__("datetime").timezone.utc)
|
||||
if hasattr(exp, 'isoformat'):
|
||||
exp_dt = exp
|
||||
else:
|
||||
exp_dt = __import__("datetime").datetime.fromisoformat(str(exp))
|
||||
if exp_dt <= now:
|
||||
return JsonResponse({"ok": False, "message": "注册码已过期"}, status=400)
|
||||
except Exception:
|
||||
pass
|
||||
existing = es_get_user_by_username(username)
|
||||
if existing:
|
||||
return JsonResponse({"ok": False, "message": "用户名已存在"}, status=409)
|
||||
users = es_get_all_users()
|
||||
next_id = (max([int(u.get("user_id", 0)) for u in users]) + 1) if users else 1
|
||||
ok = write_user_data({
|
||||
"user_id": next_id,
|
||||
"username": username,
|
||||
"password": password,
|
||||
"permission": 1,
|
||||
"email": email,
|
||||
"key": rc.get("keys") or [],
|
||||
"manage_key": rc.get("manage_keys") or [],
|
||||
})
|
||||
if not ok:
|
||||
return JsonResponse({"ok": False, "message": "注册失败"}, status=500)
|
||||
return JsonResponse({"ok": True, "redirect_url": "/accounts/login/"})
|
||||
Reference in New Issue
Block a user