app.auth.views 源代码

# -*- coding:utf-8 -*-

from flask import render_template, url_for, redirect, request, flash
from flask_login import login_user, login_required, logout_user, current_user

from .form import LoginForm, RegistrantionForm, ChangeEmailForm, ChangePasswordForm, PasswordResetForm, PasswordResetRequestForm
from ..email import send_email
from ..models import User
from . import auth
from .. import db


@auth.before_app_request
[文档]def before_request(): """ .. note:: 处理程序中过滤未确认的账户 同时满足以下 3 个条件时, `before_app_request` 处理程序会拦截请求。 1.用户已登录( `current_user.is_authenticated()` 必须返回 `True` )。 2.用户的账户还未确认。 3.请求的端点(使用 request.endpoint 获取)不在认证蓝本中。 访问认证路由要获取权限,因为这些路由的作用是让用户确认账户或执行其他账户管理操作。 """ if current_user.is_authenticated \ and not current_user.confirmed \ and request.endpoint[:5] != 'auth.' \ and request.endpoint != 'static': return redirect(url_for('auth.unconfirmed'))
@auth.route('/unconfirmed')
[文档]def unconfirmed(): """ 用户未完成验证 """ if current_user.is_anonymous or current_user.confirmed: return redirect(url_for('main.index')) return render_template('auth/unconfirmed.html')
@auth.route('/login', methods=['GET', 'POST'])
[文档]def login(): """ .. note:: 登录 用户访问未授权的 URL 时会显示登录表单, Flask-Login会把原地址保存在查询字符串的 next 参数中。 这个参数可从 request.args 字典中读取, 如果查询字符串中没有 next 参数,则重定向到首页。 """ form = LoginForm() if form.validate_on_submit(): user = User.query.filter_by(email=form.email.data).first() if user is not None and user.verify_password(form.password.data): login_user(user, form.remember_me.data) return redirect(request.args.get('next') or url_for('main.index')) flash('用户名或密码有误!') return render_template('auth/login.html', form=form)
@auth.route('/logout') @login_required
[文档]def logout(): """ 退出账号 """ logout_user() flash("您已成功退出系统.") return redirect(url_for('main.index'))
@auth.route('/register', methods=['GET', 'POST'])
[文档]def register(): """ .. note:: 注册 提交注册表单,通过验证后,系统就使用用户填写的信息在数据库中添加一个新用户。 """ form = RegistrantionForm() if form.validate_on_submit(): user = User(email=form.email.data, username=form.username.data, password=form.password.data) db.session.add(user) # 提交数据库之后才能赋予新用户 id 值,而确认令牌需要用到 id ,所以不能延后提交 db.session.commit() token = user.generate_confirmation_token() send_email(user.email, "验证您的账户", 'auth/email/confirm', user=user, token=token) flash('一封验证邮件已发送到您的邮箱,请登录邮箱进行验证!') return redirect(url_for('main.index')) return render_template('auth/register.html', form=form)
@auth.route('/confirm/<token>') @login_required
[文档]def confirm(token): """ .. note:: 确认用户的账户 先检查已登录的用户是否已经确认过,如果确认过,则重定向到首页, 因为很显然此时不用做什么操作。 这样处理可以避免用户不小心多次点击确认令牌带来的额外工作。 由于令牌确认完全在 User 模型中完成,所以视图函数只需调用 confirm() 方法即可, 然后再根据确认结果显示不同的 Flash 消息。 确认成功后, User 模型中 confirmed 属性的值会被修改并添加到会话中, 请求处理完后,这两个操作被提交到数据库。 """ if current_user.confirmed: return redirect(url_for('main.index')) if current_user.confirm(token): flash('您已验证该账号,感谢使用!') else: flash('验证链接已失效!') return redirect(url_for('main.index'))
@auth.route('/confirm') @login_required
[文档]def resend_confirmation(): """ 重新发送账户确认邮件 """ token = current_user.generate_confirmation_token() send_email(current_user.email, '验证您的账户', 'auth/email/confirm', user=current_user, token=token) flash('一封新的验证邮件已发送到您的邮箱,请登录邮箱进行验证!.') return redirect(url_for('main.index'))
@auth.route('/change-password', methods=['GET', 'POST']) @login_required
[文档]def change_password(): """ 修改密码 """ form = ChangePasswordForm() if form.validate_on_submit(): if current_user.verify_password(form.old_password.data): current_user.password = form.password.data db.session.add(current_user) flash('您的密码已被修改!') return redirect(url_for('main.index')) else: flash('密码错误!') return render_template("auth/change_password.html", form=form)
@auth.route('/reset', methods=['GET', 'POST'])
[文档]def password_reset_request(): """ 重置密码请求 """ if not current_user.is_anonymous: return redirect(url_for('main.index')) form = PasswordResetRequestForm() if form.validate_on_submit(): user = User.query.filter_by(email=form.email.data).first() if user: token = user.generate_reset_token() send_email(user.email, '重置密码', 'auth/email/reset_password', user=user, token=token, next=request.args.get('next')) flash('一封验证重置密码请求的邮件已发送到您的邮箱,请登录邮箱进行验证!') return redirect(url_for('auth.login')) return render_template('auth/reset_password.html', form=form)
@auth.route('/reset/<token>', methods=['GET', 'POST'])
[文档]def password_reset(token): """ 重置密码 """ if not current_user.is_anonymous: return redirect(url_for('main.index')) form = PasswordResetForm() if form.validate_on_submit(): user = User.query.filter_by(email=form.email.data).first() if user is None: return redirect(url_for('main.index')) if user.reset_password(token, form.password.data): flash('您的密码已修改!') return redirect(url_for('auth.login')) else: return redirect(url_for('main.index')) return render_template('auth/reset_password.html', form=form)
@auth.route('/change-email', methods=['GET', 'POST']) @login_required
[文档]def change_email_request(): """ 修改邮箱请求 """ form = ChangeEmailForm() if form.validate_on_submit(): if current_user.verify_password(form.password.data): new_email = form.email.data token = current_user.generate_email_change_token(new_email) send_email(new_email, '验证您的邮箱地址', 'auth/email/change_email', user=current_user, token=token) flash('一封验证重置邮箱请求的邮件已发送到您的邮箱,请登录邮箱进行验证!') return redirect(url_for('main.index')) else: flash('邮箱或密码有误!') return render_template("auth/change_email.html", form=form)
@auth.route('/change-email/<token>') @login_required
[文档]def change_email(token): """ 修改邮箱 """ if current_user.change_email(token): flash('您的邮箱已修改!') else: flash('非法请求!') return redirect(url_for('main.index'))