<commit_before># -*- coding: utf-8 -*-
"""
    edacc.views.accounts
    --------------------

    This module defines request handler functions for user account management
    such as registration, login and solver submission.

    :copyright: (c) 2010 by <NAME>.
    :license: MIT, see LICENSE for details.
"""

import itertools
import random
import hashlib
import zipfile
import tempfile
import datetime
from cStringIO import StringIO

from flask import Module
from flask import render_template as render, g
from flask import Response, abort, request, session, url_for, redirect, flash
from flaskext.mail import Message
from werkzeug import Headers, secure_filename

from edacc import utils, models, forms, config
from edacc.views.helpers import require_phase, require_competition, \
                                require_login, password_hash, redirect_ssl, require_admin
from edacc.web import mail

accounts = Module(__name__)


#def render(*args, **kwargs):
#    from tidylib import tidy_document
#    res = render_template(*args, **kwargs)
#    doc, errs = tidy_document(res)
#    return doc


@accounts.route('/<database>/register/', methods=['GET', 'POST'])
@require_phase(phases=(2,))
@require_competition
@redirect_ssl
def register(database):
    """ User registration """
    db = models.get_database(database) or abort(404)
    form = forms.RegistrationForm()

    errors = []
    if form.validate_on_submit():
        if db.session.query(db.User).filter_by(email=form.email.data) \
                                    .count() > 0:
            errors.append("An account with this email address already exists. Please check your e-mail account for the activation link.")

        try:
            captcha = map(int, form.captcha.data.split())
            if not utils.satisfies(captcha, session['captcha']):
                errors.append("Wrong solution to the captcha challenge.")
        except:
            errors.append("Wrong format of the solution")

        if not errors:
            user = db.User()
            user.lastname = form.lastname.data
            user.firstname = form.firstname.data
            user.password = password_hash(form.password.data)
            user.email = form.email.data
            user.postal_address = form.address.data
            user.affiliation = form.affiliation.data
            user.verified = False

            hash = hashlib.sha256()
            hash.update(config.SECRET_KEY)
            hash.update(user.email)
            hash.update(str(datetime.datetime.now()))
            hash.update(user.password)
            user.activation_hash = hash.hexdigest()

            db.session.add(user)
            try:
                db.session.commit()
            except Exception:
                db.session.rollback()
                errors.append('Error while trying to save the account to the database. Please \
                              contact an administrator.')
                return render('/accounts/register.html', database=database,
                              db=db, errors=errors, form=form)

            session.pop('captcha', None)

            msg = Message("[" + db.label + "] Account activation",
                          recipients=[user.email])
            msg.body = "Dear " + user.firstname + " " + user.lastname + ",\n\n" + \
                       "Please use the following link to activate your account:\n" + \
                       request.url_root[:-1] + url_for('accounts.activate', database=database, activation_hash=user.activation_hash)
            mail.send(msg)
            flash("Account created successfully. An e-mail has been sent to your account with an activation link.")
            return redirect(url_for('frontend.experiments_index',
                                    database=database))

    # Save captcha to the session. The user will have to provide a solution for
    # the same captcha that was given to him.
    random.seed()
    f = utils.random_formula(2, 3)
    while not utils.SAT(f):
        f = utils.random_formula(2, 3)
    session['captcha'] = f

    return render('/accounts/register.html', database=database, db=db,
                  errors=errors, form=form)

@accounts.route('/<database>/activate/<activation_hash>')
@require_phase(phases=(2,))
@require_competition
def activate(database, activation_hash):
    db = models.get_database(database) or abort(404)
    user = db.session.query(db.User).filter_by(activation_hash=activation_hash).first() or abort(404)
    user.activation_hash = ""
    try:
        db.session.commit()
        user = db.session.query(db.User).filter_by(email=user.email).first()
        msg = Message("[" + db.label + "][Admin] Account was activated",
            recipients=[config.DEFAULT_MAIL_SENDER])
        msg.body = ("The following account was just activated by a user:\n\n" + \
                   "Last name: %s\n" \
                   "First name: %s\n" \
                   "E-mail: %s\n" \
                   "Postal address: %s\n" \
                   "Affiliation: %s\n\n\n\n" \
                   "Use the following link to verify this user: " + request.url_root[:-1] + url_for('accounts.verify_user', database=database, user_id=user.idUser)) \
                    % (user.lastname, user.firstname, user.email, user.postal_address, user.affiliation)
        mail.send(msg)
        flash('Account activated. You will be able to log in when your account was verified by an administrator.')
    except Exception as e:
        db.session.rollback()
        print e
        flash('Could not activate account. Please contact an administrator.')
    return redirect(url_for('frontend.experiments_index',
        database=database))

@accounts.route('/<database>/verify-user/<int:user_id>/')
@require_competition
@require_admin
def verify_user(database, user_id):
    db = models.get_database(database) or abort(404)
    user = db.session.query(db.User).get(user_id) or abort(404)
    user.verified = True
    try:
        db.session.commit()
        msg = Message("[" + db.label + "] Account verified",
            recipients=[user.email])
        msg.body = "Dear " + user.firstname + " " + user.lastname + ",\n\n" +\
                   "Your account was verified and you can now log in."
        mail.send(msg)
        flash('Verified the account.')
    except Exception as e:
        db.session.rollback()
        flash("Couldn't update verification status of user or send the notification mail: " + str(e))

    return redirect(url_for('frontend.experiments_index',
        database=database))

@accounts.route('/<database>/login/', methods=['GET', 'POST'])
@require_competition
@redirect_ssl
def login(database):
    """ User login form and handling for a specific database. Users can
        only be logged in to one database at a time
    """
    db = models.get_database(database) or abort(404)
    form = forms.LoginForm()

    error = None
    if form.validate_on_submit():
        user = db.session.query(db.User).filter_by(email=form.email.data).first()
        if user is None:
            error = "Invalid password or username."
        else:<commit_msg>convenience URL in e-mail<commit_after># -*- coding: utf-8 -*-
"""
    edacc.views.accounts
    --------------------

    This module defines request handler functions for user account management
    such as registration, login and solver submission.

    :copyright: (c) 2010 by <NAME>.
    :license: MIT, see LICENSE for details.
"""

import itertools
import random
import hashlib
import zipfile
import tempfile
import datetime
from cStringIO import StringIO

from flask import Module
from flask import render_template as render, g
from flask import Response, abort, request, session, url_for, redirect, flash
from flaskext.mail import Message
from werkzeug import Headers, secure_filename

from edacc import utils, models, forms, config
from edacc.views.helpers import require_phase, require_competition, \
                                require_login, password_hash, redirect_ssl, require_admin
from edacc.web import mail

accounts = Module(__name__)


#def render(*args, **kwargs):
#    from tidylib import tidy_document
#    res = render_template(*args, **kwargs)
#    doc, errs = tidy_document(res)
#    return doc


@accounts.route('/<database>/register/', methods=['GET', 'POST'])
@require_phase(phases=(2,))
@require_competition
@redirect_ssl
def register(database):
    """ User registration """
    db = models.get_database(database) or abort(404)
    form = forms.RegistrationForm()

    errors = []
    if form.validate_on_submit():
        if db.session.query(db.User).filter_by(email=form.email.data) \
                                    .count() > 0:
            errors.append("An account with this email address already exists. Please check your e-mail account for the activation link.")

        try:
            captcha = map(int, form.captcha.data.split())
            if not utils.satisfies(captcha, session['captcha']):
                errors.append("Wrong solution to the captcha challenge.")
        except:
            errors.append("Wrong format of the solution")

        if not errors:
            user = db.User()
            user.lastname = form.lastname.data
            user.firstname = form.firstname.data
            user.password = password_<PASSWORD>(form.password.data)
            user.email = form.email.data
            user.postal_address = form.address.data
            user.affiliation = form.affiliation.data
            user.verified = False

            hash = hashlib.sha256()
            hash.update(config.SECRET_KEY)
            hash.update(user.email)
            hash.update(str(datetime.datetime.now()))
            hash.update(user.password)
            user.activation_hash = hash.hexdigest()

            db.session.add(user)
            try:
                db.session.commit()
            except Exception:
                db.session.rollback()
                errors.append('Error while trying to save the account to the database. Please \
                              contact an administrator.')
                return render('/accounts/register.html', database=database,
                              db=db, errors=errors, form=form)

            session.pop('captcha', None)

            msg = Message("[" + db.label + "] Account activation",
                          recipients=[user.email])
            msg.body = "Dear " + user.firstname + " " + user.lastname + ",\n\n" + \
                       "Please use the following link to activate your account:\n" + \
                       request.url_root[:-1] + url_for('accounts.activate', database=database, activation_hash=user.activation_hash)
            mail.send(msg)
            flash("Account created successfully. An e-mail has been sent to your account with an activation link.")
            return redirect(url_for('frontend.experiments_index',
                                    database=database))

    # Save captcha to the session. The user will have to provide a solution for
    # the same captcha that was given to him.
    random.seed()
    f = utils.random_formula(2, 3)
    while not utils.SAT(f):
        f = utils.random_formula(2, 3)
    session['captcha'] = f

    return render('/accounts/register.html', database=database, db=db,
                  errors=errors, form=form)

@accounts.route('/<database>/activate/<activation_hash>')
@require_phase(phases=(2,))
@require_competition
def activate(database, activation_hash):
    db = models.get_database(database) or abort(404)
    user = db.session.query(db.User).filter_by(activation_hash=activation_hash).first() or abort(404)
    user.activation_hash = ""
    try:
        db.session.commit()
        user = db.session.query(db.User).filter_by(email=user.email).first()
        msg = Message("[" + db.label + "][Admin] Account was activated",
            recipients=[config.DEFAULT_MAIL_SENDER])
        msg.body = ("The following account was just activated by a user:\n\n" + \
                   "Last name: %s\n" \
                   "First name: %s\n" \
                   "E-mail: %s\n" \
                   "Postal address: %s\n" \
                   "Affiliation: %s\n\n\n\n" \
                   "Use the following link to verify this user: " + request.url_root[:-1] + url_for('accounts.verify_user', database=database, user_id=user.idUser)) \
                    % (user.lastname, user.firstname, user.email, user.postal_address, user.affiliation)
        mail.send(msg)
        flash('Account activated. You will be able to log in when your account was verified by an administrator.')
    except Exception as e:
        db.session.rollback()
        print e
        flash('Could not activate account. Please contact an administrator.')
    return redirect(url_for('frontend.experiments_index',
        database=database))

@accounts.route('/<database>/verify-user/<int:user_id>/')
@require_competition
@require_admin
def verify_user(database, user_id):
    db = models.get_database(database) or abort(404)
    user = db.session.query(db.User).get(user_id) or abort(404)
    user.verified = True
    try:
        db.session.commit()
        msg = Message("[" + db.label + "] Account verified",
            recipients=[user.email])
        msg.body = "Dear " + user.firstname + " " + user.lastname + ",\n\n" +\
                   "Your account was verified and you can now log in:\n" +\
                   request.url_root[:-1] + url_for('accounts.login', database=database)
        mail.send(msg)
        flash('Verified the account.')
    except Exception as e:
        db.session.rollback()
        flash("Couldn't update verification status of user or send the notification mail: " + str(e))

    return redirect(url_for('frontend.experiments_index',
        database=database))

@accounts.route('/<database>/login/', methods=['GET', 'POST'])
@require_competition
@redirect_ssl
def login(database):
    """ User login form and handling for a specific database. Users can
        only be logged in to one database at a time
    """
    db = models.get_database(database) or abort(404)
    form = forms.LoginForm()

    error = None
    if form.validate_on_submit():
        user = db.session.query(db.User).filter_by(email=form.email.data).first()
        if user is None:
            error = "Invalid password or username."
        else:
{'fraction_non_alphanumeric': 0.11454204047569372, 'fraction_numerical': 0.004937756450379025, 'mean_word_length': 2.384325723699694, 'pattern_counts': {'":': 0, '<': 18, '<?xml version=': 0, '>': 20, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7212785', 'n_tokens_mistral': 4085, 'n_tokens_neox': 3939, 'n_words': 1063}