|
Pierre-Yves Chibon |
33b534 |
# -*- coding: utf-8 -*-
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
e5fe0e |
"""
|
|
Pierre-Yves Chibon |
4635b5 |
(c) 2014-2017 - Copyright Red Hat Inc
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
e5fe0e |
Authors:
|
|
Pierre-Yves Chibon |
e5fe0e |
Pierre-Yves Chibon <pingou@pingoured.fr></pingou@pingoured.fr>
|
|
farhaanbukhsh |
96d198 |
Farhaan Bukhsh <farhaan.bukhsh@gmail.com></farhaan.bukhsh@gmail.com>
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
e5fe0e |
"""
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
67d1cc |
from __future__ import unicode_literals, absolute_import
|
|
Aurélien Bompard |
831553 |
|
|
Pierre-Yves Chibon |
e5fe0e |
import datetime
|
|
Pierre-Yves Chibon |
4635b5 |
import logging
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
e5fe0e |
import flask
|
|
Aurélien Bompard |
831553 |
import six
|
|
Pierre-Yves Chibon |
e5fe0e |
from sqlalchemy.exc import SQLAlchemyError
|
|
Aurélien Bompard |
831553 |
from six.moves.urllib.parse import urljoin
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
fe5017 |
import pagure.login_forms as forms
|
|
Pierre-Yves Chibon |
fe5017 |
import pagure.lib.login
|
|
Pierre-Yves Chibon |
fe5017 |
import pagure.lib.model as model
|
|
Pierre-Yves Chibon |
cf98be |
import pagure.lib.model_base
|
|
Pierre-Yves Chibon |
fe5017 |
import pagure.lib.notify
|
|
Pierre-Yves Chibon |
930073 |
import pagure.lib.query
|
|
Pierre-Yves Chibon |
b130e5 |
from pagure.utils import login_required
|
|
farhaanbukhsh |
4166a2 |
from pagure.lib.login import generate_hashed_value, check_password
|
|
Pierre-Yves Chibon |
b130e5 |
from pagure.ui import UI_NS
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
farhaanbukhsh |
7bec18 |
|
|
Pierre-Yves Chibon |
4635b5 |
_log = logging.getLogger(__name__)
|
|
Pierre-Yves Chibon |
4635b5 |
|
|
Pierre-Yves Chibon |
4635b5 |
|
|
Pierre-Yves Chibon |
9c2953 |
@UI_NS.route("/user/new/", methods=["GET", "POST"])
|
|
Pierre-Yves Chibon |
9c2953 |
@UI_NS.route("/user/new", methods=["GET", "POST"])
|
|
Pierre-Yves Chibon |
e5fe0e |
def new_user():
|
|
Pierre-Yves Chibon |
e5fe0e |
""" Create a new user.
|
|
Pierre-Yves Chibon |
e5fe0e |
"""
|
|
Pierre-Yves Chibon |
e5fe0e |
form = forms.NewUserForm()
|
|
Pierre-Yves Chibon |
e5fe0e |
if form.validate_on_submit():
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
e5fe0e |
username = form.user.data
|
|
Pierre-Yves Chibon |
930073 |
if pagure.lib.query.search_user(flask.g.session, username=username):
|
|
Pierre-Yves Chibon |
9c2953 |
flask.flash("Username already taken.", "error")
|
|
Pierre-Yves Chibon |
e5fe0e |
return flask.redirect(flask.request.url)
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
e5fe0e |
email = form.email_address.data
|
|
Pierre-Yves Chibon |
930073 |
if pagure.lib.query.search_user(flask.g.session, email=email):
|
|
Pierre-Yves Chibon |
9c2953 |
flask.flash("Email address already taken.", "error")
|
|
Pierre-Yves Chibon |
e5fe0e |
return flask.redirect(flask.request.url)
|
|
farhaanbukhsh |
3d73ea |
|
|
farhaanbukhsh |
cfd1ff |
form.password.data = generate_hashed_value(form.password.data)
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
fe5017 |
token = pagure.lib.login.id_generator(40)
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
e5fe0e |
user = model.User()
|
|
Pierre-Yves Chibon |
e5fe0e |
user.token = token
|
|
Pierre-Yves Chibon |
e5fe0e |
form.populate_obj(obj=user)
|
|
Pierre-Yves Chibon |
f2ade5 |
user.default_email = form.email_address.data
|
|
Pierre-Yves Chibon |
b130e5 |
flask.g.session.add(user)
|
|
Pierre-Yves Chibon |
b130e5 |
flask.g.session.flush()
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
e5fe0e |
try:
|
|
Pierre-Yves Chibon |
930073 |
pagure.lib.query.add_email_to_user(
|
|
Karsten Hopp |
5c0db6 |
flask.g.session, user, form.email_address.data
|
|
Karsten Hopp |
5c0db6 |
)
|
|
Pierre-Yves Chibon |
b130e5 |
flask.g.session.commit()
|
|
Pierre-Yves Chibon |
e5fe0e |
send_confirmation_email(user)
|
|
Pierre-Yves Chibon |
e5fe0e |
flask.flash(
|
|
Pierre-Yves Chibon |
9c2953 |
"User created, please check your email to activate the "
|
|
Pierre-Yves Chibon |
9c2953 |
"account"
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Karsten Hopp |
5c0db6 |
except pagure.exceptions.PagureException as err:
|
|
Karsten Hopp |
5c0db6 |
flask.flash(str(err), "error")
|
|
Karsten Hopp |
5c0db6 |
_log.exception(err)
|
|
Pierre-Yves Chibon |
4635b5 |
except SQLAlchemyError: # pragma: no cover
|
|
Pierre-Yves Chibon |
b130e5 |
flask.g.session.rollback()
|
|
Pierre-Yves Chibon |
9c2953 |
flask.flash("Could not create user.")
|
|
Pierre-Yves Chibon |
9c2953 |
_log.exception("Could not create user.")
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
9c2953 |
return flask.redirect(flask.url_for("auth_login"))
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
9c2953 |
return flask.render_template("login/user_new.html", form=form)
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
9c2953 |
@UI_NS.route("/dologin", methods=["POST"])
|
|
Pierre-Yves Chibon |
e5fe0e |
def do_login():
|
|
chocos10 |
6e4a4f |
""" Log in the user.
|
|
Pierre-Yves Chibon |
e5fe0e |
"""
|
|
Pierre-Yves Chibon |
2f87ac |
logout()
|
|
Pierre-Yves Chibon |
2f87ac |
|
|
Pierre-Yves Chibon |
e5fe0e |
form = forms.LoginForm()
|
|
Pierre-Yves Chibon |
9c2953 |
next_url = flask.request.form.get("next_url")
|
|
Pierre-Yves Chibon |
9c2953 |
if not next_url or next_url == "None":
|
|
Pierre-Yves Chibon |
9c2953 |
next_url = flask.url_for("ui_ns.index")
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
e5fe0e |
if form.validate_on_submit():
|
|
Pierre-Yves Chibon |
e5fe0e |
username = form.username.data
|
|
Pierre-Yves Chibon |
930073 |
user_obj = pagure.lib.query.search_user(
|
|
Pierre-Yves Chibon |
930073 |
flask.g.session, username=username
|
|
Pierre-Yves Chibon |
930073 |
)
|
|
Pierre-Yves Chibon |
b2efea |
if not user_obj:
|
|
Pierre-Yves Chibon |
9c2953 |
flask.flash("Username or password invalid.", "error")
|
|
Pierre-Yves Chibon |
9c2953 |
return flask.redirect(flask.url_for("auth_login"))
|
|
farhaanbukhsh |
9ec0cf |
|
|
Pierre-Yves Chibon |
7da30c |
try:
|
|
Pierre-Yves Chibon |
7da30c |
password_checks = check_password(
|
|
Pierre-Yves Chibon |
9c2953 |
form.password.data,
|
|
Pierre-Yves Chibon |
9c2953 |
user_obj.password,
|
|
Pierre-Yves Chibon |
9c2953 |
seed=pagure.config.config.get("PASSWORD_SEED", None),
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Pierre-Yves Chibon |
7da30c |
except pagure.exceptions.PagureException as err:
|
|
Pierre-Yves Chibon |
4635b5 |
_log.exception(err)
|
|
Pierre-Yves Chibon |
9c2953 |
flask.flash("Username or password of invalid format.", "error")
|
|
Pierre-Yves Chibon |
9c2953 |
return flask.redirect(flask.url_for("auth_login"))
|
|
farhaanbukhsh |
9ec0cf |
|
|
farhaanbukhsh |
61f9f5 |
if not password_checks:
|
|
Pierre-Yves Chibon |
9c2953 |
flask.flash("Username or password invalid.", "error")
|
|
Pierre-Yves Chibon |
9c2953 |
return flask.redirect(flask.url_for("auth_login"))
|
|
farhaanbukhsh |
9ec0cf |
|
|
Pierre-Yves Chibon |
e5fe0e |
elif user_obj.token:
|
|
Pierre-Yves Chibon |
e5fe0e |
flask.flash(
|
|
Pierre-Yves Chibon |
9c2953 |
"Invalid user, did you confirm the creation with the url "
|
|
Pierre-Yves Chibon |
9c2953 |
"provided by email?",
|
|
Pierre-Yves Chibon |
9c2953 |
"error",
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Pierre-Yves Chibon |
9c2953 |
return flask.redirect(flask.url_for("auth_login"))
|
|
Pierre-Yves Chibon |
7da30c |
|
|
Pierre-Yves Chibon |
e5fe0e |
else:
|
|
Aurélien Bompard |
831553 |
password = user_obj.password
|
|
Aurélien Bompard |
619e2a |
if not isinstance(password, six.text_type):
|
|
Pierre-Yves Chibon |
9c2953 |
password = password.decode("utf-8")
|
|
Pierre-Yves Chibon |
9c2953 |
if not password.startswith("$2$"):
|
|
farhaanbukhsh |
cfd1ff |
user_obj.password = generate_hashed_value(form.password.data)
|
|
Pierre-Yves Chibon |
b130e5 |
flask.g.session.add(user_obj)
|
|
Pierre-Yves Chibon |
b130e5 |
flask.g.session.flush()
|
|
farhaanbukhsh |
3d73ea |
|
|
Pierre-Yves Chibon |
fe5017 |
visit_key = pagure.lib.login.id_generator(40)
|
|
Pierre-Yves Chibon |
3c4913 |
now = datetime.datetime.utcnow()
|
|
Pierre-Yves Chibon |
3c4913 |
expiry = now + datetime.timedelta(days=30)
|
|
Pierre-Yves Chibon |
fe5017 |
session = model.PagureUserVisit(
|
|
Pierre-Yves Chibon |
e5fe0e |
user_id=user_obj.id,
|
|
Pierre-Yves Chibon |
e5fe0e |
user_ip=flask.request.remote_addr,
|
|
Pierre-Yves Chibon |
e5fe0e |
visit_key=visit_key,
|
|
Pierre-Yves Chibon |
e5fe0e |
expiry=expiry,
|
|
Pierre-Yves Chibon |
e5fe0e |
)
|
|
Pierre-Yves Chibon |
b130e5 |
flask.g.session.add(session)
|
|
Pierre-Yves Chibon |
e5fe0e |
try:
|
|
Pierre-Yves Chibon |
b130e5 |
flask.g.session.commit()
|
|
Pierre-Yves Chibon |
e5fe0e |
flask.g.fas_user = user_obj
|
|
Pierre-Yves Chibon |
e5fe0e |
flask.g.fas_session_id = visit_key
|
|
Pierre-Yves Chibon |
049180 |
flask.g.fas_user.login_time = now
|
|
Pierre-Yves Chibon |
9c2953 |
flask.flash("Welcome %s" % user_obj.username)
|
|
Pierre-Yves Chibon |
fa97f7 |
except SQLAlchemyError as err: # pragma: no cover
|
|
Pierre-Yves Chibon |
e5fe0e |
flask.flash(
|
|
Pierre-Yves Chibon |
9c2953 |
"Could not set the session in the db, "
|
|
Pierre-Yves Chibon |
9c2953 |
"please report this error to an admin",
|
|
Pierre-Yves Chibon |
9c2953 |
"error",
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Pierre-Yves Chibon |
4635b5 |
_log.exception(err)
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
e5fe0e |
return flask.redirect(next_url)
|
|
Pierre-Yves Chibon |
e5fe0e |
else:
|
|
Pierre-Yves Chibon |
9c2953 |
flask.flash("Insufficient information provided", "error")
|
|
Pierre-Yves Chibon |
9c2953 |
return flask.redirect(flask.url_for("auth_login"))
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
9c2953 |
@UI_NS.route("/confirm/<token>/")</token>
|
|
Pierre-Yves Chibon |
9c2953 |
@UI_NS.route("/confirm/<token>")</token>
|
|
Pierre-Yves Chibon |
e5fe0e |
def confirm_user(token):
|
|
Pierre-Yves Chibon |
e5fe0e |
""" Confirm a user account.
|
|
Pierre-Yves Chibon |
e5fe0e |
"""
|
|
Pierre-Yves Chibon |
930073 |
user_obj = pagure.lib.query.search_user(flask.g.session, token=token)
|
|
Pierre-Yves Chibon |
e5fe0e |
if not user_obj:
|
|
Pierre-Yves Chibon |
9c2953 |
flask.flash("No user associated with this token.", "error")
|
|
Pierre-Yves Chibon |
e5fe0e |
else:
|
|
Pierre-Yves Chibon |
e5fe0e |
user_obj.token = None
|
|
Pierre-Yves Chibon |
b130e5 |
flask.g.session.add(user_obj)
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
e5fe0e |
try:
|
|
Pierre-Yves Chibon |
b130e5 |
flask.g.session.commit()
|
|
Pierre-Yves Chibon |
9c2953 |
flask.flash("Email confirmed, account activated")
|
|
Pierre-Yves Chibon |
9c2953 |
return flask.redirect(flask.url_for("auth_login"))
|
|
Pierre-Yves Chibon |
fa97f7 |
except SQLAlchemyError as err: # pragma: no cover
|
|
Pierre-Yves Chibon |
e5fe0e |
flask.flash(
|
|
Pierre-Yves Chibon |
9c2953 |
"Could not set the account as active in the db, "
|
|
Pierre-Yves Chibon |
9c2953 |
"please report this error to an admin",
|
|
Pierre-Yves Chibon |
9c2953 |
"error",
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Pierre-Yves Chibon |
4635b5 |
_log.exception(err)
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
9c2953 |
return flask.redirect(flask.url_for("ui_ns.index"))
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
9c2953 |
@UI_NS.route("/password/lost/", methods=["GET", "POST"])
|
|
Pierre-Yves Chibon |
9c2953 |
@UI_NS.route("/password/lost", methods=["GET", "POST"])
|
|
Pierre-Yves Chibon |
e5fe0e |
def lost_password():
|
|
Pierre-Yves Chibon |
e5fe0e |
""" Method to allow a user to change his/her password assuming the email
|
|
Pierre-Yves Chibon |
e5fe0e |
is not compromised.
|
|
Pierre-Yves Chibon |
e5fe0e |
"""
|
|
Pierre-Yves Chibon |
e5fe0e |
form = forms.LostPasswordForm()
|
|
Pierre-Yves Chibon |
e5fe0e |
if form.validate_on_submit():
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
e5fe0e |
username = form.username.data
|
|
Pierre-Yves Chibon |
930073 |
user_obj = pagure.lib.query.search_user(
|
|
Pierre-Yves Chibon |
930073 |
flask.g.session, username=username
|
|
Pierre-Yves Chibon |
930073 |
)
|
|
Pierre-Yves Chibon |
e5fe0e |
if not user_obj:
|
|
Pierre-Yves Chibon |
9c2953 |
flask.flash("Username invalid.", "error")
|
|
Pierre-Yves Chibon |
9c2953 |
return flask.redirect(flask.url_for("auth_login"))
|
|
Pierre-Yves Chibon |
e5fe0e |
elif user_obj.token:
|
|
Pierre-Yves Chibon |
96de3a |
current_time = datetime.datetime.utcnow()
|
|
Pierre-Yves Chibon |
9c2953 |
invalid_period = user_obj.updated_on + datetime.timedelta(
|
|
Pierre-Yves Chibon |
9c2953 |
minutes=3
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Vivek Anand |
c50fff |
if current_time < invalid_period:
|
|
Pierre-Yves Chibon |
53e4c2 |
flask.flash(
|
|
Pierre-Yves Chibon |
9c2953 |
"An email was sent to you less than 3 minutes ago, "
|
|
Pierre-Yves Chibon |
9c2953 |
"did you check your spam folder? Otherwise, "
|
|
Pierre-Yves Chibon |
9c2953 |
"try again after some time.",
|
|
Pierre-Yves Chibon |
9c2953 |
"error",
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Pierre-Yves Chibon |
9c2953 |
return flask.redirect(flask.url_for("auth_login"))
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
fe5017 |
token = pagure.lib.login.id_generator(40)
|
|
Pierre-Yves Chibon |
e5fe0e |
user_obj.token = token
|
|
Pierre-Yves Chibon |
b130e5 |
flask.g.session.add(user_obj)
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
e5fe0e |
try:
|
|
Pierre-Yves Chibon |
b130e5 |
flask.g.session.commit()
|
|
Pierre-Yves Chibon |
e5fe0e |
send_lostpassword_email(user_obj)
|
|
Pierre-Yves Chibon |
9c2953 |
flask.flash("Check your email to finish changing your password")
|
|
Pierre-Yves Chibon |
4635b5 |
except SQLAlchemyError: # pragma: no cover
|
|
Pierre-Yves Chibon |
b130e5 |
flask.g.session.rollback()
|
|
Pierre-Yves Chibon |
e5fe0e |
flask.flash(
|
|
Pierre-Yves Chibon |
9c2953 |
"Could not set the token allowing changing a password.",
|
|
Pierre-Yves Chibon |
9c2953 |
"error",
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Pierre-Yves Chibon |
9c2953 |
_log.exception("Password lost change - Error setting token.")
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
9c2953 |
return flask.redirect(flask.url_for("auth_login"))
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
9c2953 |
return flask.render_template("login/password_change.html", form=form)
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
9c2953 |
@UI_NS.route("/password/reset/<token>/", methods=["GET", "POST"])</token>
|
|
Pierre-Yves Chibon |
9c2953 |
@UI_NS.route("/password/reset/<token>", methods=["GET", "POST"])</token>
|
|
Pierre-Yves Chibon |
e5fe0e |
def reset_password(token):
|
|
Pierre-Yves Chibon |
e5fe0e |
""" Method to allow a user to reset his/her password.
|
|
Pierre-Yves Chibon |
e5fe0e |
"""
|
|
Pierre-Yves Chibon |
e5fe0e |
form = forms.ResetPasswordForm()
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
930073 |
user_obj = pagure.lib.query.search_user(flask.g.session, token=token)
|
|
Pierre-Yves Chibon |
e5fe0e |
if not user_obj:
|
|
Pierre-Yves Chibon |
9c2953 |
flask.flash("No user associated with this token.", "error")
|
|
Pierre-Yves Chibon |
9c2953 |
return flask.redirect(flask.url_for("auth_login"))
|
|
Pierre-Yves Chibon |
e5fe0e |
elif not user_obj.token:
|
|
Pierre-Yves Chibon |
e5fe0e |
flask.flash(
|
|
Pierre-Yves Chibon |
9c2953 |
"Invalid user, this user never asked for a password change",
|
|
Pierre-Yves Chibon |
9c2953 |
"error",
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Pierre-Yves Chibon |
9c2953 |
return flask.redirect(flask.url_for("auth_login"))
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
e5fe0e |
if form.validate_on_submit():
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
farhaanbukhsh |
cfd1ff |
user_obj.password = generate_hashed_value(form.password.data)
|
|
farhaanbukhsh |
9ec0cf |
|
|
Pierre-Yves Chibon |
e5fe0e |
user_obj.token = None
|
|
Pierre-Yves Chibon |
b130e5 |
flask.g.session.add(user_obj)
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
e5fe0e |
try:
|
|
Pierre-Yves Chibon |
b130e5 |
flask.g.session.commit()
|
|
Pierre-Yves Chibon |
9c2953 |
flask.flash("Password changed")
|
|
Pierre-Yves Chibon |
4635b5 |
except SQLAlchemyError: # pragma: no cover
|
|
Pierre-Yves Chibon |
b130e5 |
flask.g.session.rollback()
|
|
Pierre-Yves Chibon |
9c2953 |
flask.flash("Could not set the new password.", "error")
|
|
Pierre-Yves Chibon |
9c2953 |
_log.exception("Password lost change - Error setting password.")
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
9c2953 |
return flask.redirect(flask.url_for("auth_login"))
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
e5fe0e |
return flask.render_template(
|
|
Pierre-Yves Chibon |
9c2953 |
"login/password_reset.html", form=form, token=token
|
|
Pierre-Yves Chibon |
e5fe0e |
)
|
|
Pierre-Yves Chibon |
9c2953 |
|
|
Pierre-Yves Chibon |
9c2953 |
|
|
farhaanbukhsh |
19ad5f |
#
|
|
farhaanbukhsh |
19ad5f |
# Methods specific to local login.
|
|
farhaanbukhsh |
19ad5f |
#
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
9c2953 |
@UI_NS.route("/password/change/", methods=["GET", "POST"])
|
|
Pierre-Yves Chibon |
9c2953 |
@UI_NS.route("/password/change", methods=["GET", "POST"])
|
|
Pierre-Yves Chibon |
cf7f54 |
@login_required
|
|
farhaanbukhsh |
19ad5f |
def change_password():
|
|
farhaanbukhsh |
646231 |
""" Method to change the password for local auth users.
|
|
farhaanbukhsh |
646231 |
"""
|
|
farhaanbukhsh |
19ad5f |
|
|
farhaanbukhsh |
646231 |
form = forms.ChangePasswordForm()
|
|
Pierre-Yves Chibon |
930073 |
user_obj = pagure.lib.query.search_user(
|
|
Pierre-Yves Chibon |
9c2953 |
flask.g.session, username=flask.g.fas_user.username
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
farhaanbukhsh |
cfd1ff |
|
|
farhaanbukhsh |
646231 |
if not user_obj:
|
|
Pierre-Yves Chibon |
c6cc5c |
flask.abort(404, description="User not found")
|
|
Pierre-Yves Chibon |
7da30c |
|
|
farhaanbukhsh |
646231 |
if form.validate_on_submit():
|
|
farhaanbukhsh |
0b007c |
|
|
Pierre-Yves Chibon |
7da30c |
try:
|
|
Pierre-Yves Chibon |
7da30c |
password_checks = check_password(
|
|
Pierre-Yves Chibon |
9c2953 |
form.old_password.data,
|
|
Pierre-Yves Chibon |
9c2953 |
user_obj.password,
|
|
Pierre-Yves Chibon |
9c2953 |
seed=pagure.config.config.get("PASSWORD_SEED", None),
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Pierre-Yves Chibon |
7da30c |
except pagure.exceptions.PagureException as err:
|
|
Pierre-Yves Chibon |
4635b5 |
_log.exception(err)
|
|
Pierre-Yves Chibon |
7da30c |
flask.flash(
|
|
Pierre-Yves Chibon |
9c2953 |
"Could not update your password, either user or password "
|
|
Pierre-Yves Chibon |
9c2953 |
"could not be checked",
|
|
Pierre-Yves Chibon |
9c2953 |
"error",
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Pierre-Yves Chibon |
9c2953 |
return flask.redirect(flask.url_for("auth_login"))
|
|
farhaanbukhsh |
9ec0cf |
|
|
Pierre-Yves Chibon |
7da30c |
if password_checks:
|
|
farhaanbukhsh |
cfd1ff |
user_obj.password = generate_hashed_value(form.password.data)
|
|
Pierre-Yves Chibon |
b130e5 |
flask.g.session.add(user_obj)
|
|
farhaanbukhsh |
646231 |
|
|
farhaanbukhsh |
9ec0cf |
else:
|
|
farhaanbukhsh |
9ec0cf |
flask.flash(
|
|
Pierre-Yves Chibon |
9c2953 |
"Could not update your password, either user or password "
|
|
Pierre-Yves Chibon |
9c2953 |
"could not be checked",
|
|
Pierre-Yves Chibon |
9c2953 |
"error",
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Pierre-Yves Chibon |
9c2953 |
return flask.redirect(flask.url_for("auth_login"))
|
|
farhaanbukhsh |
9ec0cf |
|
|
farhaanbukhsh |
646231 |
try:
|
|
Pierre-Yves Chibon |
b130e5 |
flask.g.session.commit()
|
|
Pierre-Yves Chibon |
9c2953 |
flask.flash("Password changed")
|
|
Pierre-Yves Chibon |
4635b5 |
except SQLAlchemyError: # pragma: no cover
|
|
Pierre-Yves Chibon |
b130e5 |
flask.g.session.rollback()
|
|
Pierre-Yves Chibon |
9c2953 |
flask.flash("Could not set the new password.", "error")
|
|
Pierre-Yves Chibon |
9c2953 |
_log.exception("Password change - Error setting new password.")
|
|
farhaanbukhsh |
646231 |
|
|
Pierre-Yves Chibon |
9c2953 |
return flask.redirect(flask.url_for("auth_login"))
|
|
farhaanbukhsh |
646231 |
|
|
Pierre-Yves Chibon |
9c2953 |
return flask.render_template("login/password_recover.html", form=form)
|
|
farhaanbukhsh |
646231 |
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
e5fe0e |
def send_confirmation_email(user):
|
|
Pierre-Yves Chibon |
e5fe0e |
""" Sends the confirmation email asking the user to confirm its email
|
|
Pierre-Yves Chibon |
e5fe0e |
address.
|
|
Pierre-Yves Chibon |
e5fe0e |
"""
|
|
Pierre-Yves Chibon |
e5fe0e |
if not user.emails:
|
|
Pierre-Yves Chibon |
e5fe0e |
return
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
9c2953 |
url = pagure.config.config.get("APP_URL", flask.request.url_root)
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Aurélien Bompard |
831553 |
url = urljoin(
|
|
Pierre-Yves Chibon |
e5fe0e |
url or flask.request.url_root,
|
|
Pierre-Yves Chibon |
9c2953 |
flask.url_for("ui_ns.confirm_user", token=user.token),
|
|
Pierre-Yves Chibon |
e5fe0e |
)
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
e5fe0e |
message = """ Dear %(username)s,
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
fe5017 |
Thank you for registering on pagure at %(url)s.
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
e5fe0e |
To finish your registration, please click on the following link or copy/paste
|
|
Pierre-Yves Chibon |
e5fe0e |
it in your browser:
|
|
Pierre-Yves Chibon |
e5fe0e |
%(url)s
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
e5fe0e |
You account will not be activated until you finish this step.
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
e5fe0e |
Sincerely,
|
|
Pierre-Yves Chibon |
fe5017 |
Your pagure admin.
|
|
Pierre-Yves Chibon |
9c2953 |
""" % (
|
|
Pierre-Yves Chibon |
9c2953 |
{"username": user.username, "url": url}
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
4f9c76 |
pagure.lib.notify.send_email(
|
|
Pierre-Yves Chibon |
e5fe0e |
text=message,
|
|
Pierre-Yves Chibon |
9c2953 |
subject="Confirm your user account",
|
|
Pierre-Yves Chibon |
e5fe0e |
to_mail=user.emails[0].email,
|
|
Pierre-Yves Chibon |
e5fe0e |
)
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
e5fe0e |
def send_lostpassword_email(user):
|
|
Pierre-Yves Chibon |
e5fe0e |
""" Sends the email with the information on how to reset his/her password
|
|
Pierre-Yves Chibon |
e5fe0e |
to the user.
|
|
Pierre-Yves Chibon |
e5fe0e |
"""
|
|
Pierre-Yves Chibon |
e5fe0e |
if not user.emails:
|
|
Pierre-Yves Chibon |
e5fe0e |
return
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
9c2953 |
url = pagure.config.config.get("APP_URL", flask.request.url_root)
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Aurélien Bompard |
831553 |
url = urljoin(
|
|
Pierre-Yves Chibon |
e5fe0e |
url or flask.request.url_root,
|
|
Pierre-Yves Chibon |
9c2953 |
flask.url_for("ui_ns.reset_password", token=user.token),
|
|
Pierre-Yves Chibon |
e5fe0e |
)
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
e5fe0e |
message = """ Dear %(username)s,
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
e5fe0e |
The IP address %(ip)s has requested a password change for this account.
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
e5fe0e |
If you wish to change your password, please click on the following link or
|
|
Pierre-Yves Chibon |
e5fe0e |
copy/paste it in your browser:
|
|
Pierre-Yves Chibon |
e5fe0e |
%(url)s
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
e5fe0e |
If you did not request this change, please inform an admin immediately!
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
e5fe0e |
Sincerely,
|
|
Pierre-Yves Chibon |
fe5017 |
Your pagure admin.
|
|
Pierre-Yves Chibon |
9c2953 |
""" % (
|
|
Pierre-Yves Chibon |
9c2953 |
{
|
|
Pierre-Yves Chibon |
9c2953 |
"username": user.username,
|
|
Pierre-Yves Chibon |
9c2953 |
"url": url,
|
|
Pierre-Yves Chibon |
9c2953 |
"ip": flask.request.remote_addr,
|
|
Pierre-Yves Chibon |
9c2953 |
}
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
4f9c76 |
pagure.lib.notify.send_email(
|
|
Pierre-Yves Chibon |
e5fe0e |
text=message,
|
|
Pierre-Yves Chibon |
9c2953 |
subject="Confirm your password change",
|
|
Pierre-Yves Chibon |
e5fe0e |
to_mail=user.emails[0].email,
|
|
Pierre-Yves Chibon |
e5fe0e |
)
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
e5fe0e |
def logout():
|
|
Pierre-Yves Chibon |
e5fe0e |
""" Log the user out by expiring the user's session.
|
|
Pierre-Yves Chibon |
e5fe0e |
"""
|
|
Pierre-Yves Chibon |
e5fe0e |
flask.g.fas_session_id = None
|
|
Pierre-Yves Chibon |
e5fe0e |
flask.g.fas_user = None
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
e5fe0e |
def _check_session_cookie():
|
|
Pierre-Yves Chibon |
e5fe0e |
""" Set the user into flask.g if the user is logged in.
|
|
Pierre-Yves Chibon |
e5fe0e |
"""
|
|
Pierre-Yves Chibon |
9c2953 |
if not hasattr(flask.g, "session") or not flask.g.session:
|
|
Pierre-Yves Chibon |
cf98be |
flask.g.session = pagure.lib.model_base.create_session(
|
|
Pierre-Yves Chibon |
9c2953 |
flask.current_app.config["DB_URL"]
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Pierre-Yves Chibon |
44158d |
|
|
Pierre-Yves Chibon |
9c2953 |
cookie_name = pagure.config.config.get("SESSION_COOKIE_NAME", "pagure")
|
|
Pierre-Yves Chibon |
9c2953 |
cookie_name = "%s_local_cookie" % cookie_name
|
|
Pierre-Yves Chibon |
e5fe0e |
session_id = None
|
|
Pierre-Yves Chibon |
e5fe0e |
user = None
|
|
Pierre-Yves Chibon |
ad29d4 |
login_time = None
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
e5fe0e |
if cookie_name and cookie_name in flask.request.cookies:
|
|
Pierre-Yves Chibon |
42edf0 |
sessionid = flask.request.cookies.get(cookie_name)
|
|
Pierre-Yves Chibon |
10406f |
visit_session = pagure.lib.login.get_session_by_visitkey(
|
|
Pierre-Yves Chibon |
9c2953 |
flask.g.session, sessionid
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Pierre-Yves Chibon |
10406f |
if visit_session and visit_session.user:
|
|
Pierre-Yves Chibon |
e5fe0e |
now = datetime.datetime.now()
|
|
Pierre-Yves Chibon |
10406f |
if now > visit_session.expiry:
|
|
Pierre-Yves Chibon |
9c2953 |
flask.flash("Session timed-out", "error")
|
|
Pierre-Yves Chibon |
9c2953 |
elif (
|
|
Pierre-Yves Chibon |
9c2953 |
pagure.config.config.get("CHECK_SESSION_IP", True)
|
|
Pierre-Yves Chibon |
9c2953 |
and visit_session.user_ip != flask.request.remote_addr
|
|
Pierre-Yves Chibon |
9c2953 |
):
|
|
Pierre-Yves Chibon |
9c2953 |
flask.flash("Session expired", "error")
|
|
Pierre-Yves Chibon |
e5fe0e |
else:
|
|
Pierre-Yves Chibon |
3c4913 |
new_expiry = now + datetime.timedelta(days=30)
|
|
Pierre-Yves Chibon |
10406f |
session_id = visit_session.visit_key
|
|
Pierre-Yves Chibon |
10406f |
user = visit_session.user
|
|
Pierre-Yves Chibon |
10406f |
login_time = visit_session.created
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
10406f |
visit_session.expiry = new_expiry
|
|
Pierre-Yves Chibon |
10406f |
flask.g.session.add(visit_session)
|
|
Pierre-Yves Chibon |
e5fe0e |
try:
|
|
Pierre-Yves Chibon |
b130e5 |
flask.g.session.commit()
|
|
Pierre-Yves Chibon |
fa97f7 |
except SQLAlchemyError as err: # pragma: no cover
|
|
Pierre-Yves Chibon |
e5fe0e |
flask.flash(
|
|
Pierre-Yves Chibon |
9c2953 |
"Could not prolong the session in the db, "
|
|
Pierre-Yves Chibon |
9c2953 |
"please report this error to an admin",
|
|
Pierre-Yves Chibon |
9c2953 |
"error",
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Pierre-Yves Chibon |
4635b5 |
_log.exception(err)
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
e5fe0e |
flask.g.fas_session_id = session_id
|
|
Pierre-Yves Chibon |
ad29d4 |
if user:
|
|
Pierre-Yves Chibon |
bcc20e |
flask.g.fas_user = user
|
|
Pierre-Yves Chibon |
2e412e |
flask.g.fas_user.email = user.default_email
|
|
Pierre-Yves Chibon |
bcc20e |
flask.g.authenticated = pagure.utils.authenticated()
|
|
Pierre-Yves Chibon |
ad29d4 |
flask.g.fas_user.login_time = login_time
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
e5fe0e |
def _send_session_cookie(response):
|
|
Pierre-Yves Chibon |
e5fe0e |
""" Set the session cookie if the user is authenticated. """
|
|
Pierre-Yves Chibon |
9c2953 |
cookie_name = pagure.config.config.get("SESSION_COOKIE_NAME", "pagure")
|
|
Pierre-Yves Chibon |
9c2953 |
secure = pagure.config.config.get("SESSION_COOKIE_SECURE", True)
|
|
Pierre-Yves Chibon |
e5fe0e |
|
|
Pierre-Yves Chibon |
e5fe0e |
response.set_cookie(
|
|
Pierre-Yves Chibon |
9c2953 |
key="%s_local_cookie" % cookie_name,
|
|
Pierre-Yves Chibon |
9c2953 |
value=flask.g.get("fas_session_id") or "",
|
|
Pierre-Yves Chibon |
e5fe0e |
secure=secure,
|
|
Pierre-Yves Chibon |
e5fe0e |
httponly=True,
|
|
Pierre-Yves Chibon |
e5fe0e |
)
|
|
Pierre-Yves Chibon |
e5fe0e |
return response
|