Blame pagure/ui/login.py

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