auth.py 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. from flask import Flask, Blueprint, render_template, redirect, flash, url_for, request, abort
  2. from flask_login import login_required, login_user, current_user, logout_user
  3. from flask_mail import Mail
  4. from wtforms import StringField, PasswordField, BooleanField, SubmitField, ValidationError
  5. from wtforms.validators import DataRequired, Length, EqualTo
  6. from typing import Optional
  7. from view.base import App
  8. from core.user import User, LoaderUserError, load_user_by_email
  9. from flask_wtf import FlaskForm
  10. from send_email import send_msg
  11. auth = Blueprint("auth", __name__)
  12. app: Optional[Flask] = None
  13. mail: Optional[Mail] = None
  14. class LoginForm(FlaskForm):
  15. email = StringField("邮箱", validators=[DataRequired(), Length(1, 32)])
  16. passwd = PasswordField("密码", validators=[DataRequired(), Length(8, 32)])
  17. remember = BooleanField("记住我")
  18. submit = SubmitField("登录")
  19. class RegisterForm(FlaskForm):
  20. email = StringField("邮箱", validators=[DataRequired(), Length(1, 32)])
  21. passwd = PasswordField("密码", validators=[DataRequired(),
  22. EqualTo("passwd_again", message="两次输入密码不相同"),
  23. Length(8, 32)])
  24. passwd_again = PasswordField("重复密码", validators=[DataRequired()])
  25. submit = SubmitField("注册")
  26. def validate_email(self, field):
  27. try:
  28. load_user_by_email(field.data)
  29. except LoaderUserError:
  30. return
  31. else:
  32. raise ValidationError("Email already register")
  33. @auth.route('/yours')
  34. @login_required
  35. def yours_page():
  36. msg_count, comment_count, blog_count = current_user.count_info()
  37. return render_template("auth/yours.html", msg_count=msg_count, comment_count=comment_count, blog_count=blog_count)
  38. @auth.route('/login', methods=["GET", "POST"])
  39. def login_page():
  40. if current_user.is_authenticated:
  41. return redirect(url_for("auth.yours_page"))
  42. form = LoginForm()
  43. if form.validate_on_submit():
  44. try:
  45. user = load_user_by_email(form.email.data)
  46. except LoaderUserError:
  47. user = None
  48. if user is not None and user.check_passwd(form.passwd.data):
  49. login_user(user, form.remember.data)
  50. next_page = request.args.get("next")
  51. if next_page is None or not next_page.startswith('/'):
  52. next_page = url_for('base.index_page')
  53. flash("登陆成功")
  54. return redirect(next_page)
  55. flash("账号或密码错误")
  56. return redirect(url_for("auth.login_page"))
  57. return render_template("auth/login.html", form=form)
  58. @auth.route('/register', methods=["GET", "POST"])
  59. def register_page():
  60. if current_user.is_authenticated:
  61. return redirect(url_for("auth.yours_page"))
  62. form = RegisterForm()
  63. if form.validate_on_submit():
  64. token = User.creat_token(form.email.data, form.passwd.data)
  65. register_url = url_for("auth.confirm_page", token=token, _external=True)
  66. send_msg("注册确认", mail, form.email.data, "register", register_url=register_url)
  67. flash("注册提交成功, 请进入邮箱点击确认注册链接")
  68. return redirect(url_for("base.index_page"))
  69. return render_template("auth/register.html", RegisterForm=form)
  70. @auth.route('/confirm')
  71. def confirm_page():
  72. token = request.args.get("token", None)
  73. if token is None:
  74. abort(404)
  75. return
  76. token = User.load_token(token)
  77. if token is None:
  78. abort(404)
  79. return
  80. try:
  81. load_user_by_email(token[0])
  82. except LoaderUserError:
  83. pass
  84. else:
  85. abort(404)
  86. return
  87. User(token[0], token[1], None, None).create_user()
  88. flash(f"用户{token[0]}认证完成")
  89. return redirect(url_for("base.index_page"))
  90. @auth.route('/logout')
  91. def logout_page():
  92. logout_user()
  93. flash("退出登录成功")
  94. return redirect(url_for("base.index_page"))
  95. @auth.context_processor
  96. def inject_base():
  97. return {"top_nav": ["", "", "", "", "", "active"]}
  98. class AuthApp(App):
  99. def __init__(self, import_name):
  100. super(AuthApp, self).__init__(import_name)
  101. global app, mail
  102. app = self._app
  103. mail = self.mail
  104. app.register_blueprint(auth, url_prefix="/auth")
  105. self.login_manager.login_view = "auth.login_page"
  106. @self.login_manager.user_loader
  107. def user_loader(email: str):
  108. try:
  109. return load_user_by_email(email)
  110. except LoaderUserError:
  111. return None