From 1656abfe5ce4ec313a0c27d1c4d1e11fe3e20ac0 Mon Sep 17 00:00:00 2001 From: mouday Date: Sat, 21 Sep 2024 14:24:32 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81=E7=94=A8=E6=88=B7=E6=B3=A8?= =?UTF-8?q?=E5=86=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- domain_admin/api/auth_api.py | 18 +- domain_admin/config/env_config.py | 2 +- domain_admin/config/runtime_config.py | 3 + domain_admin/router/api_map.py | 2 +- domain_admin/service/async_task_service.py | 5 +- domain_admin/service/auth_service.py | 51 ++++- domain_admin/service/notify_service.py | 22 +++ domain_admin/templates/code-email.html | 210 +++++++++++++++++++++ domain_admin/utils/cache_util.py | 24 +++ requirements/production.txt | 3 +- tests/service/auth_service_test.py | 3 + 11 files changed, 328 insertions(+), 15 deletions(-) create mode 100644 domain_admin/templates/code-email.html create mode 100644 domain_admin/utils/cache_util.py diff --git a/domain_admin/api/auth_api.py b/domain_admin/api/auth_api.py index 6e5fcddd13..aed3762df3 100644 --- a/domain_admin/api/auth_api.py +++ b/domain_admin/api/auth_api.py @@ -19,18 +19,18 @@ def login(): return {'token': token} -def register(): +def login_by_email(): """ - 用户注册 + 邮箱登录 :return: """ - raise AppException('暂未开放') - username = request.json['username'] - password = request.json['password'] - password_repeat = request.json['password_repeat'] + email = request.json['email'] + code = request.json['code'] - auth_service.register(username, password, password_repeat) + token = auth_service.login_by_email(email, code) + + return {'token': token} def send_code(): @@ -38,6 +38,6 @@ def send_code(): 发送验证码 :return: """ - username = request.json['username'] + email = request.json['email'] - # auth_service.register() + auth_service.send_verify_code_async(email) diff --git a/domain_admin/config/env_config.py b/domain_admin/config/env_config.py index c921a0fabe..f4d34b7fb8 100644 --- a/domain_admin/config/env_config.py +++ b/domain_admin/config/env_config.py @@ -35,4 +35,4 @@ ALLOW_COMMANDS = [cmd.strip() for cmd in env.str("ALLOW_COMMANDS", '').split(';') if cmd.strip()] # ENABLED_REGISTER -ENABLED_REGISTER = env.str("ENABLED_REGISTER", 'false') +ENABLED_REGISTER = env.bool("ENABLED_REGISTER", False) diff --git a/domain_admin/config/runtime_config.py b/domain_admin/config/runtime_config.py index f9df508784..05fc3def8c 100644 --- a/domain_admin/config/runtime_config.py +++ b/domain_admin/config/runtime_config.py @@ -34,6 +34,9 @@ # acme_dir ACME_DIR = os.path.join(DATABASE_DIR, 'acme') +# cache_dir +CACHE_DIR = os.path.join(DATABASE_DIR, 'cache') + # sqlite 数据库 SQLITE_DATABASE_PATH = os.path.join(DATABASE_DIR, 'database.db') diff --git a/domain_admin/router/api_map.py b/domain_admin/router/api_map.py index 66065b0b89..d7b46bb9e6 100644 --- a/domain_admin/router/api_map.py +++ b/domain_admin/router/api_map.py @@ -25,7 +25,7 @@ # 登录注册 "/api/login": auth_api.login, - "/api/register": auth_api.register, + "/api/loginByEmail": auth_api.login_by_email, "/api/sendCode": auth_api.send_code, # 域名(SSL证书) diff --git a/domain_admin/service/async_task_service.py b/domain_admin/service/async_task_service.py index 58fc422a62..e66495298f 100644 --- a/domain_admin/service/async_task_service.py +++ b/domain_admin/service/async_task_service.py @@ -44,7 +44,10 @@ def async_task_decorator(task_name): def outer_wrapper(func): @wraps(func) def wrapper(*args, **kwargs): - current_user_id = g.user_id + if hasattr(g, 'user_id'): + current_user_id = g.user_id + else: + current_user_id = 0 # before async_task_row = AsyncTaskModel.create( diff --git a/domain_admin/service/auth_service.py b/domain_admin/service/auth_service.py index 676290b835..33b4dbf813 100644 --- a/domain_admin/service/auth_service.py +++ b/domain_admin/service/auth_service.py @@ -11,8 +11,8 @@ from domain_admin.enums.role_enum import RoleEnum, ROLE_PERMISSION from domain_admin.enums.status_enum import StatusEnum from domain_admin.model.user_model import UserModel -from domain_admin.service import token_service -from domain_admin.utils import bcrypt_util +from domain_admin.service import token_service, notify_service, async_task_service +from domain_admin.utils import bcrypt_util, cache_util, validate_util, secret_util from domain_admin.utils.flask_ext.app_exception import AppException @@ -124,3 +124,50 @@ def has_role_permission(current_role, need_permission): current_permission = item['permission'] return need_permission in current_permission + + +@async_task_service.async_task_decorator("发送邮箱验证码") +def send_verify_code_async(email): + send_verify_code(email) + + +def send_verify_code(email): + if not validate_util.is_email(email): + raise AppException('邮箱格式不正确') + + code = secret_util.get_random_password() + + cache_util.set_value(key=email, value=code, expire=5 * 60) + + notify_service.send_email_to_user( + template='code-email.html', + subject='验证码', + data={'code': code}, + email_list=[email] + ) + + +def login_by_email(email, code): + if not validate_util.is_email(email): + raise AppException('邮箱格式不正确') + + cache_code = cache_util.get_value(email) + + if cache_code and code == cache_code: + pass + else: + raise AppException('验证码不正确') + + user_row = UserModel.select().where( + UserModel.username == email + ).get_or_none() + + if not user_row: + user_row = UserModel.create( + username=email, + password='' + ) + + return token_service.encode_token({ + 'user_id': user_row.id + }) diff --git a/domain_admin/service/notify_service.py b/domain_admin/service/notify_service.py index acafa9f8b7..6b99019370 100644 --- a/domain_admin/service/notify_service.py +++ b/domain_admin/service/notify_service.py @@ -487,6 +487,28 @@ def notify_user_by_email( subject, data, email_list, +): + """ + 通过邮件通知用户证书到期 + :param template: str + :param subject: str + :param data: Dict + :param email_list: List[str] + :return: + """ + send_email_to_user( + template, + subject, + data, + email_list + ) + + +def send_email_to_user( + template, + subject, + data, + email_list, ): """ 通过邮件通知用户证书到期 diff --git a/domain_admin/templates/code-email.html b/domain_admin/templates/code-email.html new file mode 100644 index 0000000000..c2fb6b02e5 --- /dev/null +++ b/domain_admin/templates/code-email.html @@ -0,0 +1,210 @@ +{# 查询域名证书到期情况 #} + + + + + + + + +
+
+
+ + + + + + + + +
+ +

+
+ + + + + + + + +

+
+ +
您的验证码为:
+ +
{{ code }}
+ +
欢迎注册Domain Admin。
+
+
+
+

+ 此致
Domain Admin团队 +

+
+
+
+ + + + + + + + +
+

+ 此为系统邮件,请勿回复。 +

+

+ Copyright © 2023 Domain Admin +

+

+ All Rights Reserved Domain Admin 版权所有 +

+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/domain_admin/utils/cache_util.py b/domain_admin/utils/cache_util.py new file mode 100644 index 0000000000..306db49212 --- /dev/null +++ b/domain_admin/utils/cache_util.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +""" +cache_util.py +""" +from diskcache import Cache + +from domain_admin.config import CACHE_DIR + +# 指定文件夹 +cache = Cache(CACHE_DIR) + + +def set_value(key, value, expire=None): + """ + 存,单位:秒s + """ + cache.set(key=key, value=value, expire=expire) + + +def get_value(key): + """ + 取 + """ + return cache.get(key=key) diff --git a/requirements/production.txt b/requirements/production.txt index aeecdaf09c..2c917cb875 100644 --- a/requirements/production.txt +++ b/requirements/production.txt @@ -24,4 +24,5 @@ tencentcloud-sdk-python alibabacloud_cdn20180510==4.0.0 alibabacloud_cas20200407==1.4.0 alibabacloud_dcdn20180115==2.4.0 -oss2 \ No newline at end of file +oss2 +diskcache \ No newline at end of file diff --git a/tests/service/auth_service_test.py b/tests/service/auth_service_test.py index 8e91f3cab5..8dfa29fa34 100644 --- a/tests/service/auth_service_test.py +++ b/tests/service/auth_service_test.py @@ -21,3 +21,6 @@ def test_has_role_permission(self): assert auth_service.has_role_permission(current_role=RoleEnum.ADMIN, need_permission=RoleEnum.ADMIN) is True assert auth_service.has_role_permission(current_role=RoleEnum.USER, need_permission=RoleEnum.USER) is True assert auth_service.has_role_permission(current_role=RoleEnum.USER, need_permission=None) is True + + def test_send_verify_code(self): + auth_service.send_verify_code('xxx@qq.com')