Добавлена возможность повторной отправки подтверждения регистрации

This commit is contained in:
2021-08-14 22:33:17 +03:00
parent cff187f449
commit ff792aedc1
6 changed files with 180 additions and 100 deletions

View File

@@ -26,6 +26,9 @@ app.config.update(db_settings)
mail_settings = config_data["mail_settings"]
app.config.update(mail_settings)
auth_settings = config_data["auth_settings"]
app.config.update(auth_settings)
db.init_app(app)
mail.init_app(app)

View File

@@ -21,6 +21,145 @@ from .mails import send_async_email
auth = Blueprint("auth", __name__)
def generate_confirmation_token(email):
serializer = URLSafeTimedSerializer(current_app.config["SECRET_KEY"])
return serializer.dumps(
email, salt=current_app.config["SECURITY_PASSWORD_SALT"]
)
def send_confirmation_email(email):
token = generate_confirmation_token(email)
confirm_url = url_for("auth.confirm_email", token=token, _external=True)
try:
send_async_email(
subject="Подтверждение регистрации",
recipients=[email],
html=render_template(
"mail/confirmation_mail.html", confirm_url=confirm_url
),
)
except:
return False
return True
@auth.route("/signup", methods=["GET", "POST"])
def signup():
if current_user.is_authenticated:
return redirect(url_for("main.index"))
elif request.method == "GET":
return render_template("signup.html")
elif request.method == "POST":
email = request.form.get("email")
username = request.form.get("username")
password = request.form.get("password")
user = User.query.filter_by(email=email).first()
if user:
flash(
Markup(
f"Указанная почта уже используется<br><a href='{url_for('auth.login')}'>Перейти к странице входа</a>"
),
"is-danger",
)
return redirect(url_for("auth.signup"))
user = User.query.filter_by(username=username).first()
if user:
flash("Указанное имя уже используется", "is-danger")
return redirect(url_for("auth.signup"))
new_user = User(
email=email,
password=password,
username=username,
)
db.session.add(new_user)
db.session.commit()
confirmation_email_sending = send_confirmation_email(new_user.email)
if confirmation_email_sending:
flash(
"На вашу почту была выслана ссылка для подтверждения регистрации",
"is-success",
)
else:
flash(
"Что-то пошло не так, свяжитесь с администратором",
"is-danger",
)
return redirect(url_for("auth.login"))
@auth.route("/resend_confirmation", methods=["GET", "POST"])
def resend_confirmation():
if current_user.is_authenticated and current_user.is_confirmed:
return redirect(url_for("main.index"))
elif request.method == "GET":
return render_template("resend_confirmation.html")
elif request.method == "POST":
email = request.form.get("email")
confirmation_email_sending = send_confirmation_email(email)
if confirmation_email_sending:
flash(
"На вашу почту была выслана новая ссылка для подтверждения регистрации",
"is-success",
)
else:
flash(
"Что-то пошло не так, свяжитесь с администратором",
"is-danger",
)
return redirect(url_for("auth.login"))
def confirm_token(token, expiration):
serializer = URLSafeTimedSerializer(current_app.config["SECRET_KEY"])
try:
email = serializer.loads(
token,
salt=current_app.config["SECURITY_PASSWORD_SALT"],
max_age=expiration,
)
except:
return False
return email
@auth.route("/confirm/<token>")
def confirm_email(token):
try:
email = confirm_token(token, current_app.config["TOKEN_EXPIRATION"])
except:
flash("Ссылка подтверждения невалидна или устарела", "is-danger")
user = User.query.filter_by(email=email).first_or_404()
if user.is_confirmed:
flash("Аккаунт уже подтвержден", "is-success")
else:
user.is_confirmed = True
db.session.commit()
flash("Ваш аккаунт подвтержден!", "is-success")
return redirect(url_for("auth.login"))
@auth.route("/login", methods=["GET", "POST"])
def login():
@@ -42,7 +181,9 @@ def login():
return redirect(url_for("auth.login"))
elif not user.is_confirmed:
flash(
"Аккаунт еще не активирован. Пожалуйста, проверьте вашу почту",
Markup(
f"Аккаунт еще не активирован. Пожалуйста, проверьте вашу почту<br><a href='{url_for('auth.resend_confirmation')}'>Повторная отправка подвтерждения регистрации</a>"
),
"is-warning",
)
return redirect(url_for("auth.login"))
@@ -56,104 +197,6 @@ def login():
return redirect(url_for("main.profile"))
@auth.route("/signup", methods=["GET", "POST"])
def signup():
if current_user.is_authenticated:
return redirect(url_for("main.index"))
elif request.method == "GET":
return render_template("signup.html")
elif request.method == "POST":
email = request.form.get("email")
username = request.form.get("username")
password = request.form.get("password")
user = User.query.filter_by(email=email).first()
if user:
login_url = url_for("auth.login")
flash(
Markup(
f"Указанная почта уже используется.<br><a href='{login_url}'>Перейти к странице входа</a>"
),
"is-danger",
)
return redirect(url_for("auth.signup"))
user = User.query.filter_by(username=username).first()
if user:
flash("Указанное имя уже используется", "is-danger")
return redirect(url_for("auth.signup"))
new_user = User(
email=email,
password=password,
username=username,
)
db.session.add(new_user)
db.session.commit()
token = generate_confirmation_token(new_user.email)
confirm_url = url_for(
"auth.confirm_email", token=token, _external=True
)
send_async_email(
subject="Подтверждение регистрации",
recipients=[new_user.email],
html=render_template(
"mail/confirmation_mail.html", confirm_url=confirm_url
),
)
flash(
"На вашу почту была выслана ссылка для подтверждения регистрации",
"is-success",
)
return redirect(url_for("auth.login"))
def generate_confirmation_token(email):
serializer = URLSafeTimedSerializer(current_app.config["SECRET_KEY"])
return serializer.dumps(
email, salt=current_app.config["SECURITY_PASSWORD_SALT"]
)
def confirm_token(token, expiration=3600):
serializer = URLSafeTimedSerializer(current_app.config["SECRET_KEY"])
try:
email = serializer.loads(
token,
salt=current_app.config["SECURITY_PASSWORD_SALT"],
max_age=expiration,
)
except:
return False
return email
@auth.route("/confirm/<token>")
def confirm_email(token):
try:
email = confirm_token(token)
except:
flash("Ссылка подтверждения невалидна или устарела", "is-danger")
user = User.query.filter_by(email=email).first_or_404()
if user.is_confirmed:
flash("Аккаунт уже подтвержден", "is-success")
else:
user.is_confirmed = True
db.session.commit()
flash("Ваш аккаунт подвтержден!", "is-success")
return redirect(url_for("auth.login"))
@auth.route("/logout")
def logout():
logout_user()

View File

@@ -15,5 +15,8 @@
"MAIL_USE_SSL": true,
"MAIL_USERNAME": "yourmail@gmail.com",
"MAIL_PASSWORD": "yourpass"
},
"auth_settings": {
"TOKEN_EXPIRATION": "3600"
}
}

View File

@@ -1,6 +1,7 @@
{% extends "base.html" %}
{% block content %}
<div class="container has-text-centered">
<section class="hero is-medium">
<div class="hero-body">
@@ -13,4 +14,5 @@
</div>
</section>
</div>
{% endblock %}

View File

@@ -0,0 +1,29 @@
{% extends "base.html" %}
{% block content %}
<section class="hero is-medium">
<div class="hero-body">
<div class="column is-4 is-offset-4">
<form class="box" method="POST" action="/resend_confirmation" >
<h3 class="title">Повторная отправка подтверждения регистрации</h3>
<div class="field">
<label class="label">Введите email, который был указан при регистрации</label>
<p class="control has-icons-left">
<input class="input" type="email" name="email" placeholder="yourmail@example.com" required>
<span class="icon is-small is-left">
<i class="fas fa-envelope"></i>
</span>
</p>
</div>
<div class="field">
<p class="control">
<button class="button is-success is-outlined is-fullwidth" type="submit">Отправить подтверждение</button>
</p>
</div>
</form>
</div>
</div>
</section>
{% endblock %}

View File

@@ -10,7 +10,7 @@
<div class="field">
<label class="label">Email</label>
<p class="control has-icons-left">
<input class="input" type="email" name="email" placeholder="you@mail.com" required>
<input class="input" type="email" name="email" placeholder="yourmail@mail.com" required>
<span class="icon is-small is-left">
<i class="fas fa-envelope"></i>
</span>