login code via email
This commit is contained in:
parent
c5e0dd5432
commit
6f21b5ad7d
7 changed files with 114 additions and 7 deletions
|
@ -358,6 +358,7 @@ TEMPLATES = [
|
|||
WSGI_APPLICATION = "boofilsic.wsgi.application"
|
||||
|
||||
SESSION_COOKIE_NAME = "neodbsid"
|
||||
SESSION_COOKIE_AGE = 90 * 24 * 60 * 60 # 90 days
|
||||
|
||||
AUTHENTICATION_BACKENDS = [
|
||||
"mastodon.auth.OAuth2Backend",
|
||||
|
|
52
common/templates/common/verify.html
Normal file
52
common/templates/common/verify.html
Normal file
|
@ -0,0 +1,52 @@
|
|||
{% load static %}
|
||||
{% load i18n %}
|
||||
{% load l10n %}
|
||||
{% load admin_url %}
|
||||
{% load mastodon %}
|
||||
{% load oauth_token %}
|
||||
{% load truncate %}
|
||||
{% load thumb %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{{ site_name }}</title>
|
||||
{% include "common_libs.html" %}
|
||||
</head>
|
||||
<body>
|
||||
{% include "_header.html" %}
|
||||
<main class="container">
|
||||
<article>
|
||||
<header>
|
||||
<h3>验证邮件已发送</h3>
|
||||
</header>
|
||||
请点击邮件中的登录链接,或输入收到的验证码:
|
||||
<style type="text/css">
|
||||
.otp input {
|
||||
font-family: monospace;
|
||||
font-weight: bolder;
|
||||
letter-spacing: 2em;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
<form action="{% url 'users:verify_code' %}" method="post">
|
||||
<div class="otp">
|
||||
<input name="code"
|
||||
maxlength="5"
|
||||
value=""
|
||||
autocomplete="one-time-code"
|
||||
autocapitalize="none"
|
||||
autocorrect="off"
|
||||
required
|
||||
pattern="^[a-zA-Z0-9]{5}$" />
|
||||
<small>{{ error }}</small>
|
||||
</div>
|
||||
<input type="submit" value="提交" />
|
||||
{% csrf_token %}
|
||||
</form>
|
||||
</article>
|
||||
</main>
|
||||
{% include "_footer.html" %}
|
||||
</body>
|
||||
</html>
|
|
@ -4,7 +4,7 @@ dateparser
|
|||
discord.py
|
||||
django~=4.2.11
|
||||
django-anymail
|
||||
django-auditlog>=3.0.0-beta.4
|
||||
django-auditlog>=3.0.0
|
||||
django-bleach
|
||||
django-compressor
|
||||
django-cors-headers
|
||||
|
|
|
@ -16,6 +16,7 @@ from django.db.models import Count, Q
|
|||
from django.shortcuts import get_object_or_404, redirect, render
|
||||
from django.urls import reverse
|
||||
from django.utils import timezone
|
||||
from django.utils.baseconv import base62
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.views.decorators.http import require_http_methods
|
||||
from loguru import logger
|
||||
|
@ -86,18 +87,24 @@ def connect(request):
|
|||
{"msg": _("无效的电子邮件地址")},
|
||||
)
|
||||
user = User.objects.filter(email__iexact=login_email).first()
|
||||
code = base62.encode(random.randint(pow(62, 4), pow(62, 5) - 1))
|
||||
cache.set(f"login_{code}", login_email, timeout=60 * 15)
|
||||
request.session["login_email"] = login_email
|
||||
action = "login" if user else "register"
|
||||
django_rq.get_queue("mastodon").enqueue(
|
||||
send_verification_link,
|
||||
user.pk if user else 0,
|
||||
"login" if user else "register",
|
||||
action,
|
||||
login_email,
|
||||
code,
|
||||
)
|
||||
return render(
|
||||
request,
|
||||
"common/info.html",
|
||||
"common/verify.html",
|
||||
{
|
||||
"msg": _("验证邮件已发送"),
|
||||
"secondary_msg": _("请查阅收件箱"),
|
||||
"action": action,
|
||||
},
|
||||
)
|
||||
login_domain = (
|
||||
|
@ -284,7 +291,7 @@ class RegistrationForm(forms.ModelForm):
|
|||
return email
|
||||
|
||||
|
||||
def send_verification_link(user_id, action, email):
|
||||
def send_verification_link(user_id, action, email, code=""):
|
||||
s = {"i": user_id, "e": email, "a": action}
|
||||
v = TimestampSigner().sign_object(s)
|
||||
if action == "verify":
|
||||
|
@ -292,9 +299,13 @@ def send_verification_link(user_id, action, email):
|
|||
url = settings.SITE_INFO["site_url"] + "/account/verify_email?c=" + v
|
||||
msg = f"你好,\n请点击以下链接验证你的电子邮件地址 {email}\n{url}\n\n如果你没有注册过本站,请忽略此邮件。"
|
||||
elif action == "login":
|
||||
subject = f'{settings.SITE_INFO["site_name"]} - {_("登录")}'
|
||||
subject = f'{settings.SITE_INFO["site_name"]} - {_("登录")} {code}'
|
||||
url = settings.SITE_INFO["site_url"] + "/account/login/email?c=" + v
|
||||
msg = f"你好,\n请点击以下链接登录{email}账号\n{url}\n\n如果你没有请求登录本站,请忽略此邮件;如果你确信账号存在安全风险,请更改注册邮件地址或与我们联系。"
|
||||
msg = (
|
||||
"你好,\n请"
|
||||
+ f"在登录界面输入如下验证码:\n\n{code}\n\n或"
|
||||
+ f"点击以下链接登录{email}账号\n{url}\n\n如果你没有请求登录本站,请忽略此邮件;如果你确信账号存在安全风险,请更改注册邮件地址或与我们联系。"
|
||||
)
|
||||
elif action == "register":
|
||||
subject = f'{settings.SITE_INFO["site_name"]} - {_("注册新账号")}'
|
||||
url = settings.SITE_INFO["site_url"] + "/account/register_email?c=" + v
|
||||
|
@ -320,6 +331,36 @@ def send_verification_link(user_id, action, email):
|
|||
logger.error(e)
|
||||
|
||||
|
||||
@require_http_methods(["POST"])
|
||||
def verify_code(request):
|
||||
code = request.POST.get("code")
|
||||
if not code:
|
||||
return render(
|
||||
request,
|
||||
"common/verify.html",
|
||||
{
|
||||
"error": _("无效的验证码"),
|
||||
},
|
||||
)
|
||||
login_email = cache.get(f"login_{code}")
|
||||
if not login_email or request.session.get("login_email") != login_email:
|
||||
return render(
|
||||
request,
|
||||
"common/verify.html",
|
||||
{
|
||||
"error": _("无效的验证码"),
|
||||
},
|
||||
)
|
||||
cache.delete(f"login_{code}")
|
||||
user = User.objects.filter(email__iexact=login_email).first()
|
||||
if user:
|
||||
resp = login_existing_user(request, user)
|
||||
else:
|
||||
resp = register_new_user(request, username=None, email=login_email)
|
||||
resp.set_cookie("mastodon_domain", "@")
|
||||
return resp
|
||||
|
||||
|
||||
def verify_email(request):
|
||||
error = ""
|
||||
try:
|
||||
|
|
|
@ -31,6 +31,10 @@ _RESERVED_USERNAMES = [
|
|||
"oauth2_login",
|
||||
"__",
|
||||
"admin",
|
||||
"administrator",
|
||||
"system",
|
||||
"user",
|
||||
"users",
|
||||
"api",
|
||||
"me",
|
||||
]
|
||||
|
|
|
@ -85,7 +85,6 @@
|
|||
id="loginButton"
|
||||
disabled />
|
||||
</div>
|
||||
<script type="text/javascript">if (Cookies.get('mastodon_domain')) $('#domain').val(Cookies.get('mastodon_domain'));</script>
|
||||
{{ sites|json_script:"sites-data" }}
|
||||
<script>
|
||||
function switch_login(){
|
||||
|
@ -129,6 +128,15 @@
|
|||
}
|
||||
}
|
||||
});
|
||||
var d = Cookies.get('mastodon_domain');
|
||||
if (d) {
|
||||
if (d == "@") {
|
||||
$('select').val('email');
|
||||
switch_login()
|
||||
} else {
|
||||
$('#domain').val(Cookies.get('mastodon_domain'));
|
||||
}
|
||||
}
|
||||
</script>
|
||||
{% else %}
|
||||
<select name="domain">
|
||||
|
|
|
@ -8,6 +8,7 @@ urlpatterns = [
|
|||
path("login/oauth", connect_redirect_back, name="login_oauth"),
|
||||
path("login/email", verify_email, name="login_email"),
|
||||
path("verify_email", verify_email, name="verify_email"),
|
||||
path("verify_code", verify_code, name="verify_code"),
|
||||
path("register_email", verify_email, name="register_email"),
|
||||
path("register", register, name="register"),
|
||||
path("connect", connect, name="connect"),
|
||||
|
|
Loading…
Add table
Reference in a new issue