auth.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. from flask import Blueprint, render_template, redirect, flash, url_for, request, abort, current_app, g
  2. from flask_login import login_required, login_user, current_user, logout_user
  3. from flask_wtf import FlaskForm
  4. from wtforms import (EmailField,
  5. StringField,
  6. PasswordField,
  7. BooleanField,
  8. SelectMultipleField,
  9. SelectField,
  10. SubmitField,
  11. ValidationError)
  12. from wtforms.validators import DataRequired, Length, Regexp, EqualTo
  13. import app
  14. from object.user import User
  15. from send_email import send_msg
  16. from configure import conf
  17. auth = Blueprint("auth", __name__)
  18. class AuthField(FlaskForm):
  19. @staticmethod
  20. def email_field(name: str, description: str):
  21. return EmailField(name, description=description,
  22. validators=[
  23. DataRequired(f"必须填写{name}"),
  24. Length(1, 20, message=f"{name}长度1-20个字符"),
  25. Regexp(r"^[a-zA-Z0-9_\.]+@[a-zA-Z0-9_]+(\.[a-zA-Z0-9_\.]+)+$",
  26. message=f"{name}不满足正则表达式")])
  27. @staticmethod
  28. def passwd_field(name: str, description: str):
  29. return PasswordField(name, description=description,
  30. validators=[
  31. DataRequired(f"必须填写{name}"),
  32. Length(8, 32, message=f"{name}长度为8-32位")])
  33. @staticmethod
  34. def passwd_again_field(name: str, description: str, passwd: str = "passwd"):
  35. return PasswordField(f"重复{name}", description=description,
  36. validators=[
  37. DataRequired(message=f"必须再次填写{name}"),
  38. EqualTo(passwd, message=f"两次输入的{name}不相同")])
  39. class EmailPasswd(AuthField):
  40. email = AuthField.email_field("邮箱", "用户邮箱")
  41. passwd = AuthField.passwd_field("密码", "用户密码")
  42. class LoginForm(EmailPasswd):
  43. remember = BooleanField("记住我")
  44. submit = SubmitField("登录")
  45. class RegisterForm(EmailPasswd):
  46. passwd_again = AuthField.passwd_again_field("密码", "用户密码")
  47. submit = SubmitField("注册")
  48. def validate_email(self, field):
  49. if User(field.data).info[2] != -1:
  50. raise ValidationError("邮箱已被注册")
  51. def validate_passwd_again(self, field):
  52. if field.data != self.passwd.data:
  53. raise ValidationError("两次输入的密码不一样")
  54. class ChangePasswdForm(AuthField):
  55. old_passwd = AuthField.passwd_field("旧密码", "用户原密码")
  56. passwd = AuthField.passwd_field("新密码", "用户新密码")
  57. passwd_again = AuthField.passwd_again_field("新密码", "用户新密码")
  58. submit = SubmitField("修改密码")
  59. def validate_passwd(self, field):
  60. if field.data == self.old_passwd.data:
  61. raise ValidationError("新旧密码不能相同")
  62. class DeleteUserForm(AuthField):
  63. email = AuthField.email_field("邮箱", "用户邮箱")
  64. submit = SubmitField("删除用户")
  65. def __init__(self):
  66. super(DeleteUserForm, self).__init__()
  67. self.email_user = None
  68. def validate_email(self, field):
  69. if User(field.data).info[2] == -1:
  70. raise ValidationError("邮箱用户不存在")
  71. class CreateRoleForm(AuthField):
  72. name = StringField("角色名称", validators=[DataRequired()])
  73. authority = SelectMultipleField("权限", coerce=str, choices=User.RoleAuthorize)
  74. submit = SubmitField("创建角色")
  75. class RoleForm(AuthField):
  76. name = SelectField("角色名称", validators=[DataRequired()], coerce=int)
  77. def __init__(self):
  78. super(RoleForm, self).__init__()
  79. self.name_res = []
  80. self.name_choices = []
  81. for i in User.get_role_list():
  82. self.name_res.append(i[0])
  83. self.name_choices.append((i[0], i[1]))
  84. self.name.choices = self.name_choices
  85. def validate_name(self, field):
  86. if field.data not in self.name_res:
  87. raise ValidationError("角色不存在")
  88. class DeleteRoleForm(RoleForm):
  89. submit = SubmitField("删除角色")
  90. class SetRoleForm(RoleForm):
  91. email = AuthField.email_field("邮箱", "用户邮箱")
  92. submit = SubmitField("设置角色")
  93. def __init__(self):
  94. super(SetRoleForm, self).__init__()
  95. self.email_user = None
  96. def validate_email(self, field):
  97. if User(field.data).info[2] == -1:
  98. raise ValidationError("邮箱用户不存在")
  99. @auth.route('/user/yours')
  100. @login_required
  101. def yours_page():
  102. msg_count, comment_count, blog_count = current_user.count
  103. app.HBlogFlask.print_load_page_log("user info")
  104. return render_template("auth/yours.html", msg_count=msg_count, comment_count=comment_count, blog_count=blog_count)
  105. @auth.route('/user/login', methods=["GET", "POST"])
  106. def login_page():
  107. if current_user.is_authenticated:
  108. app.HBlogFlask.print_user_not_allow_opt_log("login")
  109. return redirect(url_for("auth.yours_page"))
  110. form = LoginForm()
  111. if form.validate_on_submit():
  112. user = User(form.email.data)
  113. if user.info[2] != -1 and user.check_passwd(form.passwd.data):
  114. login_user(user, form.remember.data)
  115. next_page = request.args.get("next")
  116. if next_page is None or not next_page.startswith('/'):
  117. next_page = url_for('base.index_page')
  118. flash("登陆成功")
  119. app.HBlogFlask.print_user_opt_success_log(f"login {form.email.data}")
  120. return redirect(next_page)
  121. flash("账号或密码错误")
  122. app.HBlogFlask.print_user_opt_fail_log(f"login {form.email.data}")
  123. return redirect(url_for("auth.login_page"))
  124. app.HBlogFlask.print_load_page_log("user login")
  125. return render_template("auth/login.html", form=form)
  126. @auth.route('/user/register', methods=["GET", "POST"])
  127. def register_page():
  128. if current_user.is_authenticated:
  129. app.HBlogFlask.print_user_not_allow_opt_log("register")
  130. return redirect(url_for("auth.yours_page"))
  131. form = RegisterForm()
  132. if form.validate_on_submit():
  133. token = User.creat_token(form.email.data, form.passwd.data)
  134. register_url = conf["URL_NAME"] + url_for("auth.confirm_page", token=token)
  135. hblog: app.Hblog = current_app
  136. send_msg("注册确认", hblog.mail, form.email.data, "register", register_url=register_url)
  137. flash("注册提交成功, 请进入邮箱点击确认注册链接")
  138. app.HBlogFlask.print_import_user_opt_success_log(f"register {form.email.data}")
  139. return redirect(url_for("base.index_page"))
  140. app.HBlogFlask.print_load_page_log("user register")
  141. return render_template("auth/register.html", RegisterForm=form)
  142. @auth.route('/user/confirm')
  143. def confirm_page():
  144. token = request.args.get("token", None)
  145. if token is None:
  146. app.HBlogFlask.print_user_opt_fail_log(f"Confirm (bad token)")
  147. abort(404)
  148. return
  149. token = User.load_token(token)
  150. if token is None:
  151. app.HBlogFlask.print_user_opt_fail_log(f"Confirm (bad token)")
  152. abort(404)
  153. return
  154. if User(token[0]).info[2] != -1:
  155. app.HBlogFlask.print_user_opt_fail_log(f"Confirm (bad token)")
  156. abort(404)
  157. return
  158. User.create(token[0], token[1])
  159. current_app.logger.info(f"{token[0]} confirm success")
  160. app.HBlogFlask.print_import_user_opt_success_log(f"confirm {token[0]}")
  161. flash(f"用户{token[0]}认证完成")
  162. return redirect(url_for("base.index_page"))
  163. @auth.route('/user/logout')
  164. @login_required
  165. def logout_page():
  166. app.HBlogFlask.print_import_user_opt_success_log(f"logout")
  167. logout_user()
  168. flash("退出登录成功")
  169. return redirect(url_for("base.index_page"))
  170. @auth.route('/user/set/passwd', methods=['GET', 'POST'])
  171. @login_required
  172. def change_passwd_page():
  173. form = ChangePasswdForm()
  174. if form.validate_on_submit():
  175. if current_user.change_passwd(form.passwd.data):
  176. app.HBlogFlask.print_user_opt_success_log(f"change passwd")
  177. flash("密码修改成功")
  178. else:
  179. app.HBlogFlask.print_user_opt_error_log(f"change passwd")
  180. flash("密码修改失败")
  181. return redirect(url_for("auth.yours_page"))
  182. app.HBlogFlask.print_load_page_log("user change passwd")
  183. return render_template("auth/passwd.html", ChangePasswdForm=form)
  184. @auth.route('/user/delete', methods=['GET', 'POST'])
  185. @login_required
  186. @app.role_required("DeleteUser", "delete user")
  187. def delete_user_page():
  188. form = DeleteUserForm()
  189. if form.validate_on_submit():
  190. user = form.email_user
  191. if user.delete():
  192. app.HBlogFlask.print_sys_opt_success_log(f"{current_user.email} delete user {form.email.data} success")
  193. flash("用户删除成功")
  194. else:
  195. app.HBlogFlask.print_sys_opt_fail_log(f"{current_user.email} delete user {form.email.data} fail")
  196. flash("用户删除失败")
  197. return redirect(url_for("auth.delete_user_page"))
  198. app.HBlogFlask.print_load_page_log("delete user")
  199. return render_template("auth/delete.html", DeleteUserForm=form)
  200. @auth.route('/role', methods=['GET'])
  201. @login_required
  202. @app.role_required("ConfigureSystem", "load role setting")
  203. def role_page():
  204. app.HBlogFlask.print_load_page_log("role setting")
  205. return render_template("auth/role.html",
  206. CreateRoleForm=CreateRoleForm(),
  207. DeleteRoleForm=DeleteRoleForm(),
  208. SetRoleForm=SetRoleForm())
  209. @auth.route('/role/create', methods=['POST'])
  210. @login_required
  211. @app.form_required(CreateRoleForm, "create role")
  212. @app.role_required("ConfigureSystem", "create role")
  213. def role_create_page():
  214. form: CreateRoleForm = g.form
  215. name = form.name.data
  216. if User.create_role(name, form.authority.data):
  217. app.HBlogFlask.print_sys_opt_success_log(f"Create role success: {name}")
  218. flash("角色创建成功")
  219. else:
  220. app.HBlogFlask.print_sys_opt_success_log(f"Create role fail: {name}")
  221. flash("角色创建失败")
  222. return redirect(url_for("auth.role_page"))
  223. @auth.route('/role/delete', methods=['POST'])
  224. @login_required
  225. @app.form_required(DeleteRoleForm, "delete role")
  226. @app.role_required("ConfigureSystem", "delete role")
  227. def role_delete_page():
  228. form: DeleteRoleForm = g.form
  229. if User.delete_role(form.name.data):
  230. app.HBlogFlask.print_sys_opt_success_log(f"Delete role success: {form.name.data}")
  231. flash("角色删除成功")
  232. else:
  233. app.HBlogFlask.print_sys_opt_fail_log(f"Delete role fail: {form.name.data}")
  234. flash("角色删除失败")
  235. return redirect(url_for("auth.role_page"))
  236. @auth.route('/role/set', methods=['POST'])
  237. @login_required
  238. @app.form_required(SetRoleForm, "assign user a role")
  239. @app.role_required("ConfigureSystem", "assign user a role")
  240. def role_set_page():
  241. form: SetRoleForm = g.form
  242. user = form.email_user
  243. if user.set_user_role(form.name.data):
  244. app.HBlogFlask.print_sys_opt_success_log(f"Role assign {form.email.data} -> {form.name.data}")
  245. flash("角色设置成功")
  246. else:
  247. app.HBlogFlask.print_sys_opt_fail_log(f"Role assign {form.email.data} -> {form.name.data}")
  248. flash("角色设置失败")
  249. return redirect(url_for("auth.role_page"))
  250. @auth.context_processor
  251. def inject_base():
  252. return {"top_nav": ["", "", "", "", "", "active"]}