Skip to content
Snippets Groups Projects
Commit a19fe661 authored by Martin Mareš's avatar Martin Mareš
Browse files

Registrace: Workflow pro ověření e-mailu

parent 8ac4df73
Branches
No related tags found
1 merge request!138Zpracování nedoručenek
......@@ -264,6 +264,17 @@ def send_confirm_change_email(user: db.User, rr: db.RegRequest) -> bool:
'''.format(confirm_url('e', rr.email_token))), override_email=rr.email, rr=rr)
def send_confirm_validate_email(user: db.User, rr: db.RegRequest) -> bool:
return send_user_email(user, 'Potvrzení e-mailové adresy', textwrap.dedent('''\
Pro potvrzení e-mailové adresy k účtu v Odevzdávacím systému Matematické
olympiády následujte tento odkaz:
{}
Váš OSMO
'''.format(confirm_url('v', rr.email_token))), rr=rr)
def send_join_notify_email(dest: db.User, who: db.User, contest: db.Contest) -> bool:
round = contest.round
place = contest.place
......
......
......@@ -452,6 +452,11 @@ class Reg2:
RegStatus.expired: 'Vypršela platnost kódu pro obnovení hesla, požádejte prosím o obnovu znovu.',
RegStatus.already_spent: 'Tento odkaz na obnovení hesla byl již využit.',
},
db.RegReqType.validate_email: {
RegStatus.new: 'Chybný potvrzovací kód. Zkontrolujte, že jste odkaz z e-mailu zkopírovali správně.',
RegStatus.expired: 'Vypršela platnost potvrzovacího kódu, požádejte prosím o potvrzení e-mailu znovu.',
RegStatus.already_spent: 'Tento odkaz na potvrzení funkčnosti e-mailu byl již využit.',
},
}
def __init__(self, token: Optional[str], expected_type: db.RegReqType):
......@@ -554,6 +559,12 @@ class Reg2:
self.spend_request_and_commit()
return True
def validate_email(self) -> None:
user = self.rr.user
app.logger.info(f'Reg2: Uživatel #{user.user_id} potvrzuje email <{user.email}>')
mo.users.reset_user_dsn(user)
self.spend_request_and_commit()
def change_passwd(self, new_passwd: str):
sess = db.get_session()
user = self.rr.user
......@@ -608,7 +619,7 @@ def confirm_reg():
return render_template('acct_reg2.html', form=form)
class ConfirmEmailForm(FlaskForm):
class ConfirmEmailChangeForm(FlaskForm):
orig_email = wtforms.StringField('Původní e-mail', render_kw={"disabled": "disabled"})
new_email = wtforms.StringField('Nový e-mail', render_kw={"disabled": "disabled"})
submit = wtforms.SubmitField('Potvrdit změnu')
......@@ -617,13 +628,13 @@ class ConfirmEmailForm(FlaskForm):
# URL je explicitně uvedeno v mo.email.confirm_url
@app.route('/acct/confirm/e', methods=('GET', 'POST'))
def confirm_email():
def confirm_email_change():
reg2 = Reg2(request.args.get('token'), db.RegReqType.change_email)
if reg2.status != RegStatus.ok:
reg2.flash_message()
return redirect(url_for('user_settings'))
form = ConfirmEmailForm()
form = ConfirmEmailChangeForm()
if form.validate_on_submit():
if form.submit.data:
if reg2.change_email():
......@@ -638,7 +649,38 @@ def confirm_email():
form.orig_email.data = reg2.rr.user.email
form.new_email.data = reg2.rr.email
return render_template('acct_confirm_email.html', form=form)
return render_template('acct_confirm_email_change.html', form=form)
class ConfirmEmailValidityForm(FlaskForm):
email = wtforms.StringField('E-mail', render_kw={"disabled": "disabled"})
submit = wtforms.SubmitField('Potvrdit')
cancel = wtforms.SubmitField('Zrušit požadavek')
# URL je explicitně uvedeno v mo.email.confirm_url
@app.route('/acct/confirm/v', methods=('GET', 'POST'))
def confirm_email_validity():
reg2 = Reg2(request.args.get('token'), db.RegReqType.validate_email)
if reg2.status != RegStatus.ok:
reg2.flash_message()
return redirect(url_for('user_settings'))
form = ConfirmEmailValidityForm()
if form.validate_on_submit():
if form.submit.data:
reg2.validate_email()
flash('E-mail potvrzen.', 'success')
return redirect(url_for('index'))
elif form.cancel.data:
reg2.spend_request_and_commit()
flash('Požadavek na potvrzení e-mailu zrušen.', 'success')
return redirect(url_for('user_settings'))
reg2.flash_message()
form.email.data = reg2.rr.user.email
return render_template('acct_confirm_email_validity.html', form=form)
class CancelResetForm(FlaskForm):
......@@ -687,6 +729,49 @@ def user_dsn():
return render_template('acct_dsn.html', user=user, dsns=dsns)
class ValidateEmailForm(FlaskForm):
submit = wtforms.SubmitField('Ověřit e-mail')
@app.route('/acct/settings/validate-email', methods=('GET', 'POST'))
@app.route('/acct/settings/validate-email/wait', endpoint='user_validate_email_wait')
def user_validate_email():
sess = db.get_session()
user = g.user
if not user:
raise NeedLoginError()
if mo.users.email_is_fake(user.email):
flash('Tento účet nemá platnou e-mailovou adresu.', 'danger')
return redirect(url_for('user_settings'))
if user.dsn is None:
flash('Tento účet už má ověřenou e-mailovou adresu.', 'success')
return redirect(url_for('user_settings'))
if request.endpoint != 'user_validate_email_wait':
form = ValidateEmailForm()
if form.validate_on_submit():
ok = True
rr = mo.users.new_reg_request(db.RegReqType.validate_email, request.remote_addr)
if rr:
rr.user_id = user.user_id
sess.add(rr)
sess.commit()
app.logger.info(f'Validace e-mailu: Požadavek pro uživatele #{user.user_id}')
mo.email.send_confirm_validate_email(user, rr)
else:
app.logger.info('Validace e-mailu: Rate limit')
flash('Příliš mnoho požadavků na validaci e-mailu. Počkejte prosím chvíli a zkuste to znovu.', 'danger')
ok = False
if ok:
return redirect(url_for('user_validate_email_wait'))
else:
form = None
return render_template('acct_validate_email.html', form=form)
if getattr(config, 'INSECURE_TEST_LOGIN', False):
@app.route('/test-login/<email>')
def test_login(email: str):
......
......
{% extends "base.html" %}
{% import "bootstrap/wtf.html" as wtf %}
{% block title %}Potvrzení platnosti e-mailu{% endblock %}
{% block body %}
{{ wtf.quick_form(form, form_type='horizontal', button_map={'submit': 'primary'}) }}
{% endblock %}
{% extends "base.html" %}
{% import "bootstrap/wtf.html" as wtf %}
{% block title %}Ověření e-mailové adresy{% endblock %}
{% block body %}
{% if form %}
<p>
Abychom ověřili platnosti vaši e-mailové adresy, pošleme na ni e-mail.
Až přijde, klikněte na odkaz v něm obsažený.
</p>
{{ wtf.quick_form(form, form_type='simple', button_map={'submit': 'primary'}) }}
{% else %}
<p>
Vyčkejte prosím, až vám přijde e-mail.
</p>
<p>
Pakliže nepřichází:
</p>
<div class="btn-group">
<a class='btn btn-default' href='{{ url_for('user_settings_personal') }}'>Změnit e-mail</a>
<a class='btn btn-default' href="{{ url_for('user_settings') }}">Zpět na nastavení účtu</a>
</div>
{% endif %}
{% endblock %}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment