mirror of
https://github.com/Cccc-owo/CheckInApp.git
synced 2026-06-17 14:06:28 +00:00
feat: optimize Token expiration monitor
This commit is contained in:
@@ -200,6 +200,8 @@ class AuthService:
|
||||
|
||||
user.authorization = pure_token # 存储清理后的 token
|
||||
user.jwt_exp = jwt_exp
|
||||
user.token_expiring_notified = False # 重置"即将过期"提醒标志
|
||||
user.token_expired_notified = False # 重置"已过期"提醒标志
|
||||
user.updated_at = datetime.now()
|
||||
db.commit()
|
||||
db.refresh(user)
|
||||
|
||||
@@ -511,7 +511,118 @@ class EmailService:
|
||||
<p><strong>如何刷新凭证:</strong></p>
|
||||
<ol style="margin: 10px 0; padding-left: 20px;">
|
||||
<li>登录系统(扫码或密码登录)</li>
|
||||
<li>在个人设置中点击"刷新凭证"</li>
|
||||
<li>在个人设置旁的按钮中进行刷新 Token</li>
|
||||
<li>使用手机 QQ 扫描二维码完成刷新</li>
|
||||
</ol>
|
||||
|
||||
<p style="text-align: center;">
|
||||
<a href="{settings.FRONTEND_URL}/login" class="btn">立即登录刷新</a>
|
||||
</p>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<p>此邮件由系统自动发送,请勿直接回复。</p>
|
||||
<p>接龙自动打卡系统 © {datetime.now().year}</p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
|
||||
return EmailService.send_email([str(user_email)], subject, body_html)
|
||||
|
||||
@staticmethod
|
||||
def notify_token_expired(user: User) -> bool:
|
||||
"""
|
||||
通知用户 Token 已过期
|
||||
|
||||
Args:
|
||||
user: 用户对象
|
||||
|
||||
Returns:
|
||||
是否发送成功
|
||||
"""
|
||||
user_email = user.email
|
||||
if user_email is None:
|
||||
logger.info(f"用户 {user.alias} 未设置邮箱,跳过 Token 已过期通知")
|
||||
return False
|
||||
|
||||
# 构建邮件内容
|
||||
subject = f"【接龙自动打卡系统】登录凭证已过期 - {user.alias}"
|
||||
|
||||
body_html = f"""
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<style>
|
||||
body {{
|
||||
font-family: Arial, sans-serif;
|
||||
line-height: 1.6;
|
||||
color: #333;
|
||||
}}
|
||||
.container {{
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
}}
|
||||
.header {{
|
||||
background-color: #dc3545;
|
||||
color: white;
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
border-radius: 5px 5px 0 0;
|
||||
}}
|
||||
.content {{
|
||||
background-color: #f9f9f9;
|
||||
padding: 20px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 0 0 5px 5px;
|
||||
}}
|
||||
.error-box {{
|
||||
background-color: #f8d7da;
|
||||
border-left: 4px solid #dc3545;
|
||||
padding: 15px;
|
||||
margin: 15px 0;
|
||||
}}
|
||||
.footer {{
|
||||
margin-top: 20px;
|
||||
text-align: center;
|
||||
color: #999;
|
||||
font-size: 12px;
|
||||
}}
|
||||
.btn {{
|
||||
display: inline-block;
|
||||
padding: 12px 24px;
|
||||
background-color: #667eea;
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
border-radius: 5px;
|
||||
margin: 10px 0;
|
||||
}}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="header">
|
||||
<h2>❌ 登录凭证已过期</h2>
|
||||
</div>
|
||||
<div class="content">
|
||||
<p>您好,{user.alias}!</p>
|
||||
<p>您的 QQ 登录凭证已过期,系统已无法自动执行打卡任务。</p>
|
||||
|
||||
<div class="error-box">
|
||||
<strong>⚠️ 重要提示:</strong>
|
||||
<ul style="margin: 10px 0; padding-left: 20px;">
|
||||
<li>登录凭证已过期,所有自动打卡任务已暂停</li>
|
||||
<li>请尽快登录系统刷新凭证以恢复服务</li>
|
||||
<li>如果您已设置密码,可以使用密码登录后扫码刷新凭证</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<p><strong>如何刷新 Token:</strong></p>
|
||||
<ol style="margin: 10px 0; padding-left: 20px;">
|
||||
<li>登录系统(扫码或密码登录)</li>
|
||||
<li>在个人设置旁的按钮中进行刷新 Token</li>
|
||||
<li>使用手机 QQ 扫描二维码完成刷新</li>
|
||||
</ol>
|
||||
|
||||
|
||||
@@ -174,18 +174,52 @@ def check_token_expiration():
|
||||
try:
|
||||
exp_timestamp = int(user.jwt_exp)
|
||||
|
||||
# 检查是否在 30 分钟内过期(0 < 剩余时间 < 1800秒)
|
||||
# 检查 Token 状态并发送对应的提醒
|
||||
time_until_expiry = exp_timestamp - current_timestamp
|
||||
|
||||
# 情况1:Token 即将过期(过期前 30 分钟内,且还未过期)
|
||||
if 0 < time_until_expiry < 1800: # 30分钟 = 1800秒
|
||||
# 使用用户账户的邮箱发送通知
|
||||
if user.email:
|
||||
if user.email and not user.token_expiring_notified:
|
||||
logger.info(f"用户 {user.alias} 的 Token 即将过期,发送邮件提醒到 {user.email}...")
|
||||
from backend.services.email_service import EmailService
|
||||
jwt_exp_value = user.jwt_exp
|
||||
jwt_exp_str = str(jwt_exp_value) if jwt_exp_value is not None else "0"
|
||||
EmailService.notify_token_expiring(user, jwt_exp_str)
|
||||
notified_count += 1
|
||||
|
||||
# 发送"即将过期"邮件
|
||||
success = EmailService.notify_token_expiring(user, jwt_exp_str)
|
||||
|
||||
if success:
|
||||
user.token_expiring_notified = True
|
||||
db.commit()
|
||||
notified_count += 1
|
||||
logger.info(f"用户 {user.alias} 的 Token 即将过期邮件已发送并标记")
|
||||
else:
|
||||
logger.warning(f"用户 {user.alias} 的 Token 即将过期邮件发送失败")
|
||||
|
||||
# 情况2:Token 已过期(过期后 30 分钟内)
|
||||
elif -1800 < time_until_expiry <= 0: # 过期后 30 分钟内
|
||||
if user.email and not user.token_expired_notified:
|
||||
logger.info(f"用户 {user.alias} 的 Token 已过期,发送邮件提醒到 {user.email}...")
|
||||
from backend.services.email_service import EmailService
|
||||
|
||||
# 发送"已过期"邮件(可以使用不同的邮件模板或内容)
|
||||
success = EmailService.notify_token_expired(user)
|
||||
|
||||
if success:
|
||||
user.token_expired_notified = True
|
||||
db.commit()
|
||||
notified_count += 1
|
||||
logger.info(f"用户 {user.alias} 的 Token 已过期邮件已发送并标记")
|
||||
else:
|
||||
logger.warning(f"用户 {user.alias} 的 Token 已过期邮件发送失败")
|
||||
|
||||
# 情况3:Token 正常(剩余时间 > 30 分钟),重置提醒标志
|
||||
elif time_until_expiry >= 1800:
|
||||
if user.token_expiring_notified or user.token_expired_notified:
|
||||
user.token_expiring_notified = False
|
||||
user.token_expired_notified = False
|
||||
db.commit()
|
||||
logger.info(f"用户 {user.alias} 的 Token 已刷新,重置所有提醒标志")
|
||||
|
||||
except ValueError:
|
||||
logger.warning(f"用户 {user.alias} 的 jwt_exp 格式不正确: {user.jwt_exp}")
|
||||
|
||||
Reference in New Issue
Block a user