Blame progit/ui/login.py

Pierre-Yves Chibon e5fe0e
#-*- coding: utf-8 -*-
Pierre-Yves Chibon e5fe0e
Pierre-Yves Chibon e5fe0e
"""
Pierre-Yves Chibon e5fe0e
 (c) 2014 - 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>
Pierre-Yves Chibon e5fe0e
Pierre-Yves Chibon e5fe0e
"""
Pierre-Yves Chibon e5fe0e
Pierre-Yves Chibon e5fe0e
Pierre-Yves Chibon e5fe0e
import hashlib
Pierre-Yves Chibon e5fe0e
import datetime
Pierre-Yves Chibon e5fe0e
import urlparse
Pierre-Yves Chibon e5fe0e
Pierre-Yves Chibon e5fe0e
import flask
Pierre-Yves Chibon e5fe0e
from sqlalchemy.exc import SQLAlchemyError
Pierre-Yves Chibon e5fe0e
Pierre-Yves Chibon e5fe0e
import progit.login_forms as forms
Pierre-Yves Chibon e5fe0e
import progit.lib
Pierre-Yves Chibon e5fe0e
import progit.notify
Pierre-Yves Chibon e5fe0e
from progit import APP, SESSION, is_admin
Pierre-Yves Chibon 9647e1
from progit.ui.admin import admin_required
Pierre-Yves Chibon e5fe0e
import progit.model as model
Pierre-Yves Chibon e5fe0e
Pierre-Yves Chibon e5fe0e
Pierre-Yves Chibon e5fe0e
@APP.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 e5fe0e
        if progit.lib.get_user(SESSION, username):
Pierre-Yves Chibon e5fe0e
            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 e5fe0e
        if progit.lib.get_user_by_email(SESSION, email):
Pierre-Yves Chibon e5fe0e
            flask.flash('Email address already taken.', 'error')
Pierre-Yves Chibon e5fe0e
            return flask.redirect(flask.request.url)
Pierre-Yves Chibon e5fe0e
Pierre-Yves Chibon e5fe0e
        password = '%s%s' % (
Pierre-Yves Chibon e5fe0e
            form.password.data, APP.config.get('PASSWORD_SEED', None))
Pierre-Yves Chibon e5fe0e
        form.password.data = hashlib.sha512(password).hexdigest()
Pierre-Yves Chibon e5fe0e
Pierre-Yves Chibon e5fe0e
        token = progit.lib.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 e5fe0e
        SESSION.add(user)
Pierre-Yves Chibon e5fe0e
        SESSION.flush()
Pierre-Yves Chibon e5fe0e
Pierre-Yves Chibon e5fe0e
        emails = [email.email for email in user.emails]
Pierre-Yves Chibon e5fe0e
        if form.email_address.data not in emails:
Pierre-Yves Chibon e5fe0e
            useremail = model.UserEmail(
Pierre-Yves Chibon e5fe0e
                user_id=user.id,
Pierre-Yves Chibon e5fe0e
                email=form.email_address.data)
Pierre-Yves Chibon e5fe0e
            SESSION.add(useremail)
Pierre-Yves Chibon e5fe0e
            SESSION.flush()
Pierre-Yves Chibon e5fe0e
Pierre-Yves Chibon e5fe0e
        try:
Pierre-Yves Chibon e5fe0e
            SESSION.flush()
Pierre-Yves Chibon e5fe0e
            send_confirmation_email(user)
Pierre-Yves Chibon e5fe0e
            flask.flash(
Pierre-Yves Chibon e5fe0e
                'User created, please check your email to activate the '
Pierre-Yves Chibon e5fe0e
                'account')
Pierre-Yves Chibon e5fe0e
        except SQLAlchemyError as err:
Pierre-Yves Chibon e5fe0e
            SESSION.rollback()
Pierre-Yves Chibon e5fe0e
            flask.flash('Could not create user.')
Pierre-Yves Chibon e5fe0e
            APP.logger.debug('Could not create user.')
Pierre-Yves Chibon e5fe0e
            APP.logger.exception(err)
Pierre-Yves Chibon e5fe0e
Pierre-Yves Chibon e5fe0e
        SESSION.commit()
Pierre-Yves Chibon e5fe0e
Pierre-Yves Chibon e5fe0e
        return flask.redirect(flask.url_for('auth_login'))
Pierre-Yves Chibon e5fe0e
Pierre-Yves Chibon e5fe0e
    return flask.render_template(
Pierre-Yves Chibon e5fe0e
        'login/user_new.html',
Pierre-Yves Chibon e5fe0e
        form=form,
Pierre-Yves Chibon e5fe0e
    )
Pierre-Yves Chibon e5fe0e
Pierre-Yves Chibon e5fe0e
Pierre-Yves Chibon e5fe0e
@APP.route('/dologin', methods=['POST'])
Pierre-Yves Chibon e5fe0e
def do_login():
Pierre-Yves Chibon e5fe0e
    """ Lo the user in user.
Pierre-Yves Chibon e5fe0e
    """
Pierre-Yves Chibon e5fe0e
    form = forms.LoginForm()
Pierre-Yves Chibon e5fe0e
    next_url = flask.request.args.get('next_url')
Pierre-Yves Chibon e5fe0e
    if not next_url or next_url == 'None':
Pierre-Yves Chibon e5fe0e
        next_url = flask.url_for('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 e5fe0e
        password = '%s%s' % (
Pierre-Yves Chibon e5fe0e
            form.password.data, APP.config.get('PASSWORD_SEED', None))
Pierre-Yves Chibon e5fe0e
        password = hashlib.sha512(password).hexdigest()
Pierre-Yves Chibon e5fe0e
Pierre-Yves Chibon e5fe0e
        user_obj = progit.lib.get_user(SESSION, username)
Pierre-Yves Chibon e5fe0e
        if not user_obj or user_obj.password != password:
Pierre-Yves Chibon e5fe0e
            flask.flash('Username or password invalid.', 'error')
Pierre-Yves Chibon e5fe0e
            return flask.redirect(flask.url_for('auth_login'))
Pierre-Yves Chibon e5fe0e
        elif user_obj.token:
Pierre-Yves Chibon e5fe0e
            flask.flash(
Pierre-Yves Chibon e5fe0e
                'Invalid user, did you confirm the creation with the url '
Pierre-Yves Chibon e5fe0e
                'provided by email?', 'error')
Pierre-Yves Chibon e5fe0e
            return flask.redirect(flask.url_for('auth_login'))
Pierre-Yves Chibon e5fe0e
        else:
Pierre-Yves Chibon e5fe0e
            visit_key = progit.lib.id_generator(40)
Pierre-Yves Chibon e5fe0e
            expiry = datetime.datetime.now() + APP.config.get(
Pierre-Yves Chibon e5fe0e
                'PERMANENT_SESSION_LIFETIME')
Pierre-Yves Chibon e5fe0e
            session = model.ProgitUserVisit(
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 e5fe0e
            SESSION.add(session)
Pierre-Yves Chibon e5fe0e
            try:
Pierre-Yves Chibon e5fe0e
                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 e5fe0e
                flask.flash('Welcome %s' % user_obj.username)
Pierre-Yves Chibon e5fe0e
            except SQLAlchemyError, err:  # pragma: no cover
Pierre-Yves Chibon e5fe0e
                flask.flash(
Pierre-Yves Chibon e5fe0e
                    'Could not set the session in the db, '
Pierre-Yves Chibon e5fe0e
                    'please report this error to an admin', 'error')
Pierre-Yves Chibon e5fe0e
                APP.logger.exception(err)
Pierre-Yves Chibon e5fe0e
Pierre-Yves Chibon e5fe0e
        return flask.redirect(next_url)
Pierre-Yves Chibon e5fe0e
    else:
Pierre-Yves Chibon e5fe0e
        flask.flash('Insufficient information provided', 'error')
Pierre-Yves Chibon e5fe0e
    return flask.redirect(flask.url_for('auth_login'))
Pierre-Yves Chibon e5fe0e
Pierre-Yves Chibon e5fe0e
Pierre-Yves Chibon e5fe0e
@APP.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 e5fe0e
    user_obj = progit.lib.get_user_by_token(SESSION, token)
Pierre-Yves Chibon e5fe0e
    if not user_obj:
Pierre-Yves Chibon e5fe0e
        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 e5fe0e
        SESSION.add(user_obj)
Pierre-Yves Chibon e5fe0e
Pierre-Yves Chibon e5fe0e
        try:
Pierre-Yves Chibon e5fe0e
            SESSION.commit()
Pierre-Yves Chibon e5fe0e
            flask.flash('Email confirmed, account activated')
Pierre-Yves Chibon e5fe0e
            return flask.redirect(flask.url_for('auth_login'))
Pierre-Yves Chibon e5fe0e
        except SQLAlchemyError, err:  # pragma: no cover
Pierre-Yves Chibon e5fe0e
            flask.flash(
Pierre-Yves Chibon e5fe0e
                'Could not set the account as active in the db, '
Pierre-Yves Chibon e5fe0e
                'please report this error to an admin', 'error')
Pierre-Yves Chibon e5fe0e
            APP.logger.exception(err)
Pierre-Yves Chibon e5fe0e
Pierre-Yves Chibon e5fe0e
    return flask.redirect(flask.url_for('index'))
Pierre-Yves Chibon e5fe0e
Pierre-Yves Chibon e5fe0e
Pierre-Yves Chibon e5fe0e
@APP.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 e5fe0e
        user_obj = progit.lib.get_user(SESSION, username)
Pierre-Yves Chibon e5fe0e
        if not user_obj:
Pierre-Yves Chibon e5fe0e
            flask.flash('Username invalid.', 'error')
Pierre-Yves Chibon e5fe0e
            return flask.redirect(flask.url_for('auth_login'))
Pierre-Yves Chibon e5fe0e
        elif user_obj.token:
Pierre-Yves Chibon e5fe0e
            flask.flash(
Pierre-Yves Chibon e5fe0e
                'Invalid user, did you confirm the creation with the url '
Pierre-Yves Chibon e5fe0e
                'provided by email? Or did you already ask for a password '
Pierre-Yves Chibon e5fe0e
                'change?', 'error')
Pierre-Yves Chibon e5fe0e
            return flask.redirect(flask.url_for('auth_login'))
Pierre-Yves Chibon e5fe0e
Pierre-Yves Chibon e5fe0e
        token = progit.lib.id_generator(40)
Pierre-Yves Chibon e5fe0e
        user_obj.token = token
Pierre-Yves Chibon e5fe0e
        SESSION.add(user_obj)
Pierre-Yves Chibon e5fe0e
Pierre-Yves Chibon e5fe0e
        try:
Pierre-Yves Chibon e5fe0e
            SESSION.commit()
Pierre-Yves Chibon e5fe0e
            send_lostpassword_email(user_obj)
Pierre-Yves Chibon e5fe0e
            flask.flash(
Pierre-Yves Chibon e5fe0e
                'Check your email to finish changing your password')
Pierre-Yves Chibon e5fe0e
        except SQLAlchemyError as err:
Pierre-Yves Chibon e5fe0e
            SESSION.rollback()
Pierre-Yves Chibon e5fe0e
            flask.flash(
Pierre-Yves Chibon e5fe0e
                'Could not set the token allowing changing a password.',
Pierre-Yves Chibon e5fe0e
                'error')
Pierre-Yves Chibon e5fe0e
            APP.logger.debug('Password lost change - Error setting token.')
Pierre-Yves Chibon e5fe0e
            APP.logger.exception(err)
Pierre-Yves Chibon e5fe0e
Pierre-Yves Chibon e5fe0e
        return flask.redirect(flask.url_for('auth_login'))
Pierre-Yves Chibon e5fe0e
Pierre-Yves Chibon e5fe0e
    return flask.render_template(
Pierre-Yves Chibon e5fe0e
        'login/password_change.html',
Pierre-Yves Chibon e5fe0e
        form=form,
Pierre-Yves Chibon e5fe0e
    )
Pierre-Yves Chibon e5fe0e
Pierre-Yves Chibon e5fe0e
Pierre-Yves Chibon e5fe0e
@APP.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 e5fe0e
    user_obj = progit.lib.get_user_by_token(SESSION, token)
Pierre-Yves Chibon e5fe0e
    if not user_obj:
Pierre-Yves Chibon e5fe0e
        flask.flash('No user associated with this token.', 'error')
Pierre-Yves Chibon e5fe0e
        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 e5fe0e
            'Invalid user, this user never asked for a password change',
Pierre-Yves Chibon e5fe0e
            'error')
Pierre-Yves Chibon e5fe0e
        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
Pierre-Yves Chibon e5fe0e
        password = '%s%s' % (
Pierre-Yves Chibon e5fe0e
            form.password.data, APP.config.get('PASSWORD_SEED', None))
Pierre-Yves Chibon e5fe0e
        user_obj.password = hashlib.sha512(password).hexdigest()
Pierre-Yves Chibon e5fe0e
        user_obj.token = None
Pierre-Yves Chibon e5fe0e
        SESSION.add(user_obj)
Pierre-Yves Chibon e5fe0e
Pierre-Yves Chibon e5fe0e
        try:
Pierre-Yves Chibon e5fe0e
            SESSION.commit()
Pierre-Yves Chibon e5fe0e
            flask.flash(
Pierre-Yves Chibon e5fe0e
                'Password changed')
Pierre-Yves Chibon e5fe0e
        except SQLAlchemyError as err:
Pierre-Yves Chibon e5fe0e
            SESSION.rollback()
Pierre-Yves Chibon e5fe0e
            flask.flash('Could not set the new password.', 'error')
Pierre-Yves Chibon e5fe0e
            APP.logger.debug(
Pierre-Yves Chibon e5fe0e
                'Password lost change - Error setting password.')
Pierre-Yves Chibon e5fe0e
            APP.logger.exception(err)
Pierre-Yves Chibon e5fe0e
Pierre-Yves Chibon e5fe0e
        return flask.redirect(flask.url_for('auth_login'))
Pierre-Yves Chibon e5fe0e
Pierre-Yves Chibon e5fe0e
    return flask.render_template(
Pierre-Yves Chibon e5fe0e
        'login/password_reset.html',
Pierre-Yves Chibon e5fe0e
        form=form,
Pierre-Yves Chibon e5fe0e
        token=token,
Pierre-Yves Chibon e5fe0e
    )
Pierre-Yves Chibon e5fe0e
Pierre-Yves Chibon e5fe0e
Pierre-Yves Chibon e5fe0e
#
Pierre-Yves Chibon 9647e1
# Admin endpoint specific to local login
Pierre-Yves Chibon 9647e1
#
Pierre-Yves Chibon 9647e1
Pierre-Yves Chibon 9647e1
@APP.route('/admin/groups', methods=['GET', 'POST'])
Pierre-Yves Chibon 9647e1
@admin_required
Pierre-Yves Chibon 9647e1
def admin_groups():
Pierre-Yves Chibon 9647e1
    """ List of the groups present in the system
Pierre-Yves Chibon 9647e1
    """
Pierre-Yves Chibon 9647e1
    # Add new group if asked
Pierre-Yves Chibon 9647e1
    form = forms.NewGroupForm()
Pierre-Yves Chibon 9647e1
    if form.validate_on_submit():
Pierre-Yves Chibon 9647e1
Pierre-Yves Chibon 9647e1
        grp = model.ProgitGroup()
Pierre-Yves Chibon 9647e1
        form.populate_obj(obj=grp)
Pierre-Yves Chibon 9647e1
        SESSION.add(grp)
Pierre-Yves Chibon 9647e1
        try:
Pierre-Yves Chibon 9647e1
            SESSION.flush()
Pierre-Yves Chibon 9647e1
        except SQLAlchemyError as err:
Pierre-Yves Chibon 9647e1
            SESSION.rollback()
Pierre-Yves Chibon 9647e1
            flask.flash('Could not create group.')
Pierre-Yves Chibon 9647e1
            APP.logger.debug('Could not create group.')
Pierre-Yves Chibon 9647e1
            APP.logger.exception(err)
Pierre-Yves Chibon 9647e1
Pierre-Yves Chibon 9647e1
        flask.flash('Group `%s` created.' % grp.group_name)
Pierre-Yves Chibon 9647e1
        SESSION.commit()
Pierre-Yves Chibon 9647e1
Pierre-Yves Chibon 9647e1
    groups = progit.lib.get_groups(SESSION)
Pierre-Yves Chibon 9647e1
Pierre-Yves Chibon 9647e1
    return flask.render_template(
Pierre-Yves Chibon 9647e1
        'login/admin_groups.html',
Pierre-Yves Chibon 9647e1
        groups=groups,
Pierre-Yves Chibon 9647e1
        form=form,
Pierre-Yves Chibon 40de1d
        conf_form=forms.ConfirmationForm(),
Pierre-Yves Chibon 9647e1
    )
Pierre-Yves Chibon 9647e1
Pierre-Yves Chibon 9647e1
Pierre-Yves Chibon 1c93fc
@APP.route('/admin/group/<group>', methods=['GET', 'POST'])</group>
Pierre-Yves Chibon 1c93fc
@admin_required
Pierre-Yves Chibon 1c93fc
def admin_group(group):
Pierre-Yves Chibon 1c93fc
    """ List of the users in a certain group
Pierre-Yves Chibon 1c93fc
    """
Pierre-Yves Chibon 1c93fc
    group_obj = progit.lib.get_group(SESSION, group)
Pierre-Yves Chibon 1c93fc
Pierre-Yves Chibon 1c93fc
    if not group_obj:
Pierre-Yves Chibon 1c93fc
        flask.flash('No group `%s` found' % groupname, 'error')
Pierre-Yves Chibon 1c93fc
        return flask.redirect(flask.url_for('.admin_groups'))
Pierre-Yves Chibon 1c93fc
Pierre-Yves Chibon 1c93fc
    # Add new user to the group if asked
Pierre-Yves Chibon 1c93fc
    form = forms.LostPasswordForm()
Pierre-Yves Chibon 1c93fc
    if form.validate_on_submit():
Pierre-Yves Chibon 1c93fc
        user = progit.lib.get_user(SESSION, form.username.data)
Pierre-Yves Chibon 1c93fc
        if not user:
Pierre-Yves Chibon 1c93fc
            flask.flash('No user `%s` found' % form.username.data, 'error')
Pierre-Yves Chibon 1c93fc
            return flask.redirect(flask.url_for('.admin_group', group=group))
Pierre-Yves Chibon 1c93fc
Pierre-Yves Chibon 1c93fc
        grp = model.ProgitUserGroup(
Pierre-Yves Chibon 1c93fc
            group_id = group_obj.id,
Pierre-Yves Chibon 1c93fc
            user_id = user.id
Pierre-Yves Chibon 1c93fc
        )
Pierre-Yves Chibon 1c93fc
        SESSION.add(grp)
Pierre-Yves Chibon 1c93fc
        try:
Pierre-Yves Chibon 1c93fc
            SESSION.flush()
Pierre-Yves Chibon 1c93fc
        except SQLAlchemyError as err:
Pierre-Yves Chibon 1c93fc
            SESSION.rollback()
Pierre-Yves Chibon 1c93fc
            flask.flash(
Pierre-Yves Chibon 1c93fc
                'Could not add user `%s` to group `%s`.' % (
Pierre-Yves Chibon 1c93fc
                    user.user, group_obj.group),
Pierre-Yves Chibon 1c93fc
                'error')
Pierre-Yves Chibon 1c93fc
            APP.logger.debug(
Pierre-Yves Chibon 1c93fc
                'Could not add user `%s` to group `%s`.' % (
Pierre-Yves Chibon 1c93fc
                    user.user, group_obj.group))
Pierre-Yves Chibon 1c93fc
            APP.logger.exception(err)
Pierre-Yves Chibon 1c93fc
Pierre-Yves Chibon 1c93fc
        flask.flash('User `%s` added.' % user.user)
Pierre-Yves Chibon 1c93fc
        SESSION.commit()
Pierre-Yves Chibon 1c93fc
Pierre-Yves Chibon 1c93fc
    users = progit.lib.get_users_by_group(SESSION, group)
Pierre-Yves Chibon 1c93fc
Pierre-Yves Chibon 1c93fc
    return flask.render_template(
Pierre-Yves Chibon 1c93fc
        'login/admin_users.html',
Pierre-Yves Chibon 1c93fc
        form=form,
Pierre-Yves Chibon 1eab4f
        conf_form=forms.ConfirmationForm(),
Pierre-Yves Chibon 1c93fc
        group=group_obj,
Pierre-Yves Chibon 1c93fc
        users=users,
Pierre-Yves Chibon 1c93fc
    )
Pierre-Yves Chibon 1c93fc
Pierre-Yves Chibon 1c93fc
Pierre-Yves Chibon 4e4b82
@APP.route('/admin/group/<group>/<user>/delete', methods=['POST'])</user></group>
Pierre-Yves Chibon 4e4b82
@admin_required
Pierre-Yves Chibon 4e4b82
def admin_group_user_delete(user, group):
Pierre-Yves Chibon 4e4b82
    """ Delete an user from a certain group
Pierre-Yves Chibon 4e4b82
    """
Pierre-Yves Chibon 4e4b82
    # Add new user to the group if asked
Pierre-Yves Chibon 4e4b82
    form = forms.ConfirmationForm()
Pierre-Yves Chibon 4e4b82
    if form.validate_on_submit():
Pierre-Yves Chibon 4e4b82
        group_obj = progit.lib.get_group(SESSION, group)
Pierre-Yves Chibon 4e4b82
Pierre-Yves Chibon 4e4b82
        if not group_obj:
Pierre-Yves Chibon 4e4b82
            flask.flash('No group `%s` found' % groupname, 'error')
Pierre-Yves Chibon 4e4b82
            return flask.redirect(flask.url_for('.admin_groups'))
Pierre-Yves Chibon 4e4b82
Pierre-Yves Chibon 4e4b82
        user = progit.lib.get_user(SESSION, user)
Pierre-Yves Chibon 4e4b82
        if not user:
Pierre-Yves Chibon 4e4b82
            flask.flash('No user `%s` found' % user, 'error')
Pierre-Yves Chibon 4e4b82
            return flask.redirect(flask.url_for('.admin_groups'))
Pierre-Yves Chibon 4e4b82
Pierre-Yves Chibon 4e4b82
        user_grp = progit.lib.get_user_group(SESSION, user.id, group_obj.id)
Pierre-Yves Chibon 4e4b82
        SESSION.delete(user_grp)
Pierre-Yves Chibon 4e4b82
Pierre-Yves Chibon 4e4b82
        SESSION.commit()
Pierre-Yves Chibon 4e4b82
        flask.flash(
Pierre-Yves Chibon 4e4b82
            'User `%s` removed from the group `%s`' % (user.user, group))
Pierre-Yves Chibon 4e4b82
Pierre-Yves Chibon 4e4b82
    return flask.redirect(flask.url_for('.admin_group', group=group))
Pierre-Yves Chibon 4e4b82
Pierre-Yves Chibon 40de1d
Pierre-Yves Chibon 40de1d
@APP.route('/admin/group/<group>/delete', methods=['POST'])</group>
Pierre-Yves Chibon 40de1d
@admin_required
Pierre-Yves Chibon 40de1d
def admin_group_delete(group):
Pierre-Yves Chibon 40de1d
    """ Delete a certain group
Pierre-Yves Chibon 40de1d
    """
Pierre-Yves Chibon 40de1d
    # Add new user to the group if asked
Pierre-Yves Chibon 40de1d
    form = forms.ConfirmationForm()
Pierre-Yves Chibon 40de1d
    if form.validate_on_submit():
Pierre-Yves Chibon 40de1d
        group_obj = progit.lib.get_group(SESSION, group)
Pierre-Yves Chibon 40de1d
Pierre-Yves Chibon 40de1d
        if not group_obj:
Pierre-Yves Chibon 40de1d
            flask.flash('No group `%s` found' % groupname, 'error')
Pierre-Yves Chibon 40de1d
            return flask.redirect(flask.url_for('.admin_groups'))
Pierre-Yves Chibon 40de1d
Pierre-Yves Chibon 40de1d
        SESSION.delete(group_obj)
Pierre-Yves Chibon 40de1d
Pierre-Yves Chibon 40de1d
        SESSION.commit()
Pierre-Yves Chibon 40de1d
        flask.flash(
Pierre-Yves Chibon 40de1d
            'Group `%s` has been deleted' % (group))
Pierre-Yves Chibon 40de1d
Pierre-Yves Chibon 40de1d
    return flask.redirect(flask.url_for('.admin_groups'))
Pierre-Yves Chibon 40de1d
Pierre-Yves Chibon 40de1d
Pierre-Yves Chibon 9647e1
#
Pierre-Yves Chibon e5fe0e
# Methods specific to local login.
Pierre-Yves Chibon e5fe0e
#
Pierre-Yves Chibon e5fe0e
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 e5fe0e
    url = APP.config.get('APPLICATION_URL', flask.request.url_root)
Pierre-Yves Chibon e5fe0e
Pierre-Yves Chibon e5fe0e
    url = urlparse.urljoin(
Pierre-Yves Chibon e5fe0e
        url or flask.request.url_root,
Pierre-Yves Chibon e5fe0e
        flask.url_for('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 e5fe0e
Thank you for registering on progit 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 e5fe0e
Your progit admin.
Pierre-Yves Chibon e5fe0e
""" % (
Pierre-Yves Chibon e5fe0e
        {
Pierre-Yves Chibon e5fe0e
            'username': user.username,
Pierre-Yves Chibon e5fe0e
            'url': url,
Pierre-Yves Chibon e5fe0e
        })
Pierre-Yves Chibon e5fe0e
Pierre-Yves Chibon e5fe0e
    progit.notify.send_email(
Pierre-Yves Chibon e5fe0e
        text=message,
Pierre-Yves Chibon e5fe0e
        subject='[Progit] 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 e5fe0e
    url = APP.config.get('APPLICATION_URL', flask.request.url_root)
Pierre-Yves Chibon e5fe0e
Pierre-Yves Chibon e5fe0e
    url = urlparse.urljoin(
Pierre-Yves Chibon e5fe0e
        url or flask.request.url_root,
Pierre-Yves Chibon e5fe0e
        flask.url_for('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 e5fe0e
Your progit admin.
Pierre-Yves Chibon e5fe0e
""" % (
Pierre-Yves Chibon e5fe0e
        {
Pierre-Yves Chibon e5fe0e
            'username': user.username,
Pierre-Yves Chibon e5fe0e
            'url': url,
Pierre-Yves Chibon e5fe0e
            'ip': flask.request.remote_addr,
Pierre-Yves Chibon e5fe0e
        })
Pierre-Yves Chibon e5fe0e
Pierre-Yves Chibon e5fe0e
    progit.notify.send_email(
Pierre-Yves Chibon e5fe0e
        text=message,
Pierre-Yves Chibon e5fe0e
        subject='[Progit] 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
    flask.flash('You have been logged out')
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 e5fe0e
    cookie_name = APP.config.get('PROGIT_COOKIE_NAME', 'progit')
Pierre-Yves Chibon e5fe0e
    session_id = None
Pierre-Yves Chibon e5fe0e
    user = None
Pierre-Yves Chibon e5fe0e
Pierre-Yves Chibon e5fe0e
    if cookie_name and cookie_name in flask.request.cookies:
Pierre-Yves Chibon e5fe0e
        sessionid = flask.request.cookies[cookie_name]
Pierre-Yves Chibon e5fe0e
        session = progit.lib.get_session_by_visitkey(SESSION, sessionid)
Pierre-Yves Chibon e5fe0e
        if session and session.user:
Pierre-Yves Chibon e5fe0e
            now = datetime.datetime.now()
Pierre-Yves Chibon e5fe0e
            new_expiry = now + APP.config.get('PERMANENT_SESSION_LIFETIME')
Pierre-Yves Chibon e5fe0e
            if now > session.expiry:
Pierre-Yves Chibon e5fe0e
                flask.flash('Session timed-out', 'error')
Pierre-Yves Chibon e5fe0e
            elif APP.config.get('CHECK_SESSION_IP', True) \
Pierre-Yves Chibon e5fe0e
                    and session.user_ip != flask.request.remote_addr:
Pierre-Yves Chibon e5fe0e
                flask.flash('Session expired', 'error')
Pierre-Yves Chibon e5fe0e
            else:
Pierre-Yves Chibon e5fe0e
                session_id = session.visit_key
Pierre-Yves Chibon e5fe0e
                user = session.user
Pierre-Yves Chibon e5fe0e
Pierre-Yves Chibon e5fe0e
                session.expiry = new_expiry
Pierre-Yves Chibon e5fe0e
                SESSION.add(session)
Pierre-Yves Chibon e5fe0e
                try:
Pierre-Yves Chibon e5fe0e
                    SESSION.commit()
Pierre-Yves Chibon e5fe0e
                except SQLAlchemyError, err:  # pragma: no cover
Pierre-Yves Chibon e5fe0e
                    flask.flash(
Pierre-Yves Chibon e5fe0e
                        'Could not prolong the session in the db, '
Pierre-Yves Chibon e5fe0e
                        'please report this error to an admin', 'error')
Pierre-Yves Chibon e5fe0e
                    APP.logger.exception(err)
Pierre-Yves Chibon e5fe0e
Pierre-Yves Chibon e5fe0e
    flask.g.fas_session_id = session_id
Pierre-Yves Chibon e5fe0e
    flask.g.fas_user = user
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 e5fe0e
    cookie_name = APP.config.get('PROGIT_COOKIE_NAME', 'progit')
Pierre-Yves Chibon e5fe0e
    secure = APP.config.get('PROGIT_COOKIE_REQUIRES_HTTPS', True)
Pierre-Yves Chibon e5fe0e
Pierre-Yves Chibon e5fe0e
    response.set_cookie(
Pierre-Yves Chibon e5fe0e
        key=cookie_name,
Pierre-Yves Chibon e5fe0e
        value=flask.g.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