コード例 #1
0
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)
    if user.verified:
        flash('User already verified.')
        return redirect(
            url_for('frontend.experiments_index', database=database))

    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))
コード例 #2
0
ファイル: accounts.py プロジェクト: ChunHungLiu/edacc_web
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" \
                    "Affiliation type: %s\n" \
                    "Country: %s\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, user.affiliation_type,
        user.country)
        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))
コード例 #3
0
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" \
                    "Affiliation type: %s\n" \
                    "Country: %s\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, user.affiliation_type,
        user.country)
        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))
コード例 #4
0
def reset_password(database):
    db = models.get_database(database) or abort(404)
    form = forms.ResetPasswordForm()

    if form.validate_on_submit():
        # find user by lower case email address
        user = db.session.query(
            db.User).filter_by(email=form.email.data.lower()).first()
        if not user or not user.verified:
            if not user: flash('No account with this e-mail address exists.')
            if user and not user.verified:
                flash('Account was not verified yet.')
            return render('/accounts/reset_password.html',
                          db=db,
                          database=database,
                          form=form)

        hash = hashlib.sha256()
        hash.update(config.SECRET_KEY)
        hash.update(user.email)
        hash.update(str(datetime.datetime.now()))
        hash.update(user.password)
        # reuse the activation hash (user should be activated at this point already)
        user.activation_hash = 'pw_reset_' + hash.hexdigest()

        try:
            db.session.commit()

            msg = Message("[" + db.label + "] Password reset instructions",
                          recipients=[user.email])
            msg.body = "Dear " + user.firstname + " " + user.lastname + ",\n\n" + \
                       "If you did not use the password reset link on the website ignore this mail.\n\n" + \
                       "To reset your password please use the following link:\n" + \
                       request.url_root[:-1] + url_for('accounts.change_password', database=database,
                                                       reset_hash=hash.hexdigest())
            mail.send(msg)

            flash(
                'E-mail was sent. Please refer to the mail for further instructions.'
            )
        except Exception as e:
            print e
            flash(
                'Could not send reset mail. Please contact an administrator.')

    return render('/accounts/reset_password.html',
                  db=db,
                  database=database,
                  form=form)
コード例 #5
0
def submit_benchmarks(database):
    db = models.get_database(database) or abort(404)
    form = forms.BenchmarksForm()

    if form.validate_on_submit():
        upload_dir = os.path.join(config.UPLOAD_FOLDER, database,
                                  str(g.User.idUser))
        move_dir = os.path.join(config.UPLOAD_FOLDER, database,
                                secure_filename(form.category.data),
                                str(g.User.idUser))
        try:
            os.makedirs(upload_dir, mode=0700)
        except:
            pass
        try:
            os.makedirs(move_dir, mode=0700)
        except:
            pass

        try:
            for file in session.get('benchmarks', list()):
                try:
                    os.rename(os.path.join(upload_dir, file),
                              os.path.join(move_dir, file))
                except Exception as ex:
                    print ex

            flash('Benchmark submission successful.')
            try:
                msg = Message("[" + db.label + "][Admin] Benchmarks submitted",
                              recipients=[config.DEFAULT_MAIL_SENDER])
                msg.body = (
                    "The user %s %s with id %d just submitted some benchmarks"
                    % (g.User.firstname, g.User.lastname, g.User.idUser))
                mail.send(msg)
            except:
                pass
            session.pop('benchmarks', None)
            return redirect(
                url_for('frontend.experiments_index', database=database))

        except Exception as ex:
            print ex
            flash('Error occured when trying to move the uploaded files.')

    return render('/accounts/submit_benchmarks.html',
                  db=db,
                  database=database,
                  form=form)
コード例 #6
0
ファイル: accounts.py プロジェクト: ChunHungLiu/edacc_web
def submit_benchmarks(database):
    db = models.get_database(database) or abort(404)
    form = forms.BenchmarksForm()

    if form.validate_on_submit():
        upload_dir = os.path.join(config.UPLOAD_FOLDER, database, str(g.User.idUser))
        move_dir = os.path.join(config.UPLOAD_FOLDER, database, secure_filename(form.category.data), str(g.User.idUser))
        try:
            os.makedirs(upload_dir, mode=0700)
        except:
            pass
        try:
            os.makedirs(move_dir, mode=0700)
        except:
            pass

        try:
            for file in session.get('benchmarks', list()):
                try:
                    os.rename(os.path.join(upload_dir, file), os.path.join(move_dir, file))
                except Exception as ex:
                    print ex

            flash('Benchmark submission successful.')
            try:
                msg = Message("[" + db.label + "][Admin] Benchmarks submitted",
                              recipients=[config.DEFAULT_MAIL_SENDER])
                msg.body = ("The user %s %s with id %d just submitted some benchmarks" % (
                g.User.firstname, g.User.lastname, g.User.idUser))
                mail.send(msg)
            except:
                pass
            session.pop('benchmarks', None)
            return redirect(url_for('frontend.experiments_index', database=database))

        except Exception as ex:
            print ex
            flash('Error occured when trying to move the uploaded files.')

    return render('/accounts/submit_benchmarks.html', db=db, database=database, form=form)
コード例 #7
0
ファイル: accounts.py プロジェクト: ChunHungLiu/edacc_web
def reset_password(database):
    db = models.get_database(database) or abort(404)
    form = forms.ResetPasswordForm()

    if form.validate_on_submit():
        # find user by lower case email address
        user = db.session.query(db.User).filter_by(email=form.email.data.lower()).first()
        if not user or not user.verified:
            if not user: flash('No account with this e-mail address exists.')
            if user and not user.verified: flash('Account was not verified yet.')
            return render('/accounts/reset_password.html', db=db, database=database, form=form)

        hash = hashlib.sha256()
        hash.update(config.SECRET_KEY)
        hash.update(user.email)
        hash.update(str(datetime.datetime.now()))
        hash.update(user.password)
        # reuse the activation hash (user should be activated at this point already)
        user.activation_hash = 'pw_reset_' + hash.hexdigest()

        try:
            db.session.commit()

            msg = Message("[" + db.label + "] Password reset instructions",
                          recipients=[user.email])
            msg.body = "Dear " + user.firstname + " " + user.lastname + ",\n\n" + \
                       "If you did not use the password reset link on the website ignore this mail.\n\n" + \
                       "To reset your password please use the following link:\n" + \
                       request.url_root[:-1] + url_for('accounts.change_password', database=database,
                                                       reset_hash=hash.hexdigest())
            mail.send(msg)

            flash('E-mail was sent. Please refer to the mail for further instructions.')
        except Exception as e:
            print e
            flash('Could not send reset mail. Please contact an administrator.')

    return render('/accounts/reset_password.html', db=db, database=database, form=form)
コード例 #8
0
ファイル: accounts.py プロジェクト: ChunHungLiu/edacc_web
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)
    if user.verified:
        flash('User already verified.')
        return redirect(url_for('frontend.experiments_index',
                                database=database))

    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))
コード例 #9
0
ファイル: accounts.py プロジェクト: ChunHungLiu/edacc_web
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.lower()) \
            .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.lower() # store email in lower case for easier password reset etc
            user.postal_address = form.address.data
            user.affiliation = form.affiliation.data
            user.verified = False
            user.accepted_terms = form.accepted_terms.data
            user.affiliation_type = form.affiliation_type.data
            user.country = form.country.data

            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)
コード例 #10
0
ファイル: accounts.py プロジェクト: ChunHungLiu/edacc_web
def submit_solver(database, id=None):
    """ Form to submit solvers to a database """
    db = models.get_database(database) or abort(404)

    # Disallow submissions of new solvers in phase 4
    if db.competition_phase() == 4 and id is None:
        abort(401)

    if id is not None:
        solver = db.session.query(db.Solver).get(id) or abort(404)
        if solver.user.idUser != g.User.idUser: abort(401)
        if db.competition_phase() == 4 and solver.competition_frozen:
            flash(
                'This solver was found to be compatible with our execution environment, i.e. has no crashed test runs or test runs with unknown result, and can not be updated anymore. Please contact the organizers if there\'s a reason to submit a new version.')
            return redirect(url_for('accounts.list_solvers',
                                    database=database, user_id=g.User.idUser))

        solver_binary = solver.binaries[0] if solver.binaries else None
        form = forms.SolverForm(request.form, solver)
        if request.method == 'GET':
            form.parameters.data = utils.parameter_template(solver)
            form.description_pdf.data = ''
            form.binary.data = ''
            form.code.data = ''
            if solver_binary:
                form.run_command.data = solver_binary.runCommand
                form.run_path.data = solver_binary.runPath
    else:
        form = forms.SolverForm()

    form.competition_categories.query = db.session.query(db.CompetitionCategory).all()

    error = None
    if form.validate_on_submit():
        valid = True # assume valid, try to falsify with the following checks

        name = form.name.data
        description = form.description.data
        version = form.version.data
        authors = form.authors.data
        parameters = form.parameters.data
        run_path = form.run_path.data

        if id is None and db.session.query(db.Solver) \
            .filter_by(name=name, version=version) \
            .first() is not None:
            error = 'Solver with this name and version already exists'
            valid = False

        if id is None and not form.code.data and not form.binary.data:
            error = 'Please provide either a binary or the code (or both).'
            valid = False

        bin = None
        if (id is None or (id is not None and form.binary.data)) and form.binary.data:
            # if this is a new solver or a resubmission with new binary update binary
            bin = request.files[form.binary.name].stream.read()
            hash = hashlib.md5()
            hash.update(bin)

            # save the binary in the FS as log
            store_path = os.path.join(config.UPLOAD_FOLDER, 'solvers',
                                      secure_filename(str(g.User.idUser) + '-' + g.User.lastname), 'bin')
            try:
                os.makedirs(store_path)
            except:
                pass
            with open(os.path.join(store_path, hash.hexdigest()), 'wb') as f:
                f.write(bin)

            if not form.binary.data.filename.endswith('.zip'):
                tmpfile = StringIO()
                zip_file = zipfile.ZipFile(tmpfile, 'w', compression=zipfile.ZIP_DEFLATED)
                zip_file.writestr(form.binary.data.filename, bin)
                zip_file.close()
                tmpfile.seek(0)
                bin = tmpfile.read()
                run_path = form.binary.data.filename
            else:
                if not run_path:
                    error = 'Since your binary is a .zip file, please provide the path of the executable within the archive'
                    valid = False

        code = None
        if id is None or (id is not None and form.code.data):
            code = request.files[form.code.name].stream.read()
            code_hash = hashlib.md5()
            code_hash.update(code)

            # save the code in the FS as log
            store_path = os.path.join(config.UPLOAD_FOLDER, 'solvers',
                                      secure_filename(str(g.User.idUser) + '-' + g.User.lastname), 'code')
            try:
                os.makedirs(store_path)
            except:
                pass
            with open(os.path.join(store_path, code_hash.hexdigest()), 'wb') as f:
                f.write(code)

        description_pdf = None
        if id is None or (id is not None and form.description_pdf.data):
            description_pdf = request.files[form.description_pdf.name].stream.read()
        if id is None and not description_pdf:
            valid = False
            error = "Please provide a description pdf."

        params = utils.parse_parameters(parameters)

        if valid:
            if id is None:
                solver = db.Solver()
                if bin:
                    solver_binary = db.SolverBinary()
                    solver_binary.solver = solver
                else:
                    solver_binary = None
            else:
                if solver_binary:
                    for solver_config in solver_binary.solver_configurations:
                        for pi in solver_config.parameter_instances: db.session.delete(pi)
                        db.session.commit()
                        db.session.delete(solver_config)
                    db.session.commit()
                if not solver_binary and bin:
                    solver_binary = db.SolverBinary()
                    solver_binary.solver = solver

            solver.name = name
            solver.description = description
            solver.authors = authors
            solver.user = g.User
            solver.version = version
            solver.competition_categories = form.competition_categories.data
            if solver_binary:
                solver_binary.binaryName = name
                solver_binary.runPath = run_path
                solver_binary.version = version
                solver_binary.runCommand = form.run_command.data
            if bin:
                # new or updated binary
                solver_binary.binaryArchive = bin
                solver_binary.md5 = hash.hexdigest()
            if code:
                # new or updated code
                solver.code = code
            if description_pdf:
                # new or updated description pdf
                solver.description_pdf = description_pdf

            db.session.add(solver)
            if bin:
                db.session.add(solver_binary)

            # on resubmissions delete old parameters
            if id is not None:
                for p in solver.parameters:
                    db.session.delete(p)
                db.session.commit()

            for p in params:
                param = db.Parameter()
                param.name = None if p[0] == '' else p[0]
                param.prefix = None if p[1] == '' else p[1]
                param.defaultValue = p[2] or ''
                param.hasValue = not p[3] # p[3] actually means 'is boolean'
                param.order = int(p[4])
                param.space = p[5]
                param.solver = solver
                db.session.add(param)
            try:
                db.session.commit()
                if code:
                    msg = Message("[" + db.label + "][Admin] Code submitted",
                                  recipients=[config.DEFAULT_MAIL_SENDER])
                    msg.body = ("The user %s %s just submitted code for the solver with id %d" % (
                    g.User.firstname, g.User.lastname, solver.idSolver))
                    mail.send(msg)
            except Exception as e:
                print e
                db.session.rollback()
                flash("Couldn't save solver to the database. Please contact an administrator for support.")
                return render('/accounts/submit_solver.html', database=database,
                              error=error, db=db, id=id, form=form)

            flash(
                'Solver submitted successfully. If you provided a binary, test jobs will be generated within the next minute. You will be notified by email once they are computed. Please check the Results page at any time for the computation progress.')
            return redirect(url_for('accounts.list_solvers',
                                    database=database, user_id=g.User.idUser))

    return render('/accounts/submit_solver.html', database=database, error=error,
                  db=db, id=id, form=form)
コード例 #11
0
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.lower()) \
            .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.lower(
            )  # store email in lower case for easier password reset etc
            user.postal_address = form.address.data
            user.affiliation = form.affiliation.data
            user.verified = False
            user.accepted_terms = form.accepted_terms.data
            user.affiliation_type = form.affiliation_type.data
            user.country = form.country.data

            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)
コード例 #12
0
def submit_solver(database, id=None):
    """ Form to submit solvers to a database """
    db = models.get_database(database) or abort(404)

    # Disallow submissions of new solvers in phase 4
    if db.competition_phase() == 4 and id is None:
        abort(401)

    if id is not None:
        solver = db.session.query(db.Solver).get(id) or abort(404)
        if solver.user.idUser != g.User.idUser: abort(401)
        if db.competition_phase() == 4 and solver.competition_frozen:
            flash(
                'This solver was found to be compatible with our execution environment, i.e. has no crashed test runs or test runs with unknown result, and can not be updated anymore. Please contact the organizers if there\'s a reason to submit a new version.'
            )
            return redirect(
                url_for('accounts.list_solvers',
                        database=database,
                        user_id=g.User.idUser))

        solver_binary = solver.binaries[0] if solver.binaries else None
        form = forms.SolverForm(request.form, solver)
        if request.method == 'GET':
            form.parameters.data = utils.parameter_template(solver)
            form.description_pdf.data = ''
            form.binary.data = ''
            form.code.data = ''
            if solver_binary:
                form.run_command.data = solver_binary.runCommand
                form.run_path.data = solver_binary.runPath
    else:
        form = forms.SolverForm()

    form.competition_categories.query = db.session.query(
        db.CompetitionCategory).all()

    error = None
    if form.validate_on_submit():
        valid = True  # assume valid, try to falsify with the following checks

        name = form.name.data
        description = form.description.data
        version = form.version.data
        authors = form.authors.data
        parameters = form.parameters.data
        run_path = form.run_path.data

        if id is None and db.session.query(db.Solver) \
            .filter_by(name=name, version=version) \
            .first() is not None:
            error = 'Solver with this name and version already exists'
            valid = False

        if id is None and not form.code.data and not form.binary.data:
            error = 'Please provide either a binary or the code (or both).'
            valid = False

        bin = None
        if (id is None or
            (id is not None and form.binary.data)) and form.binary.data:
            # if this is a new solver or a resubmission with new binary update binary
            bin = request.files[form.binary.name].stream.read()
            hash = hashlib.md5()
            hash.update(bin)

            # save the binary in the FS as log
            store_path = os.path.join(
                config.UPLOAD_FOLDER, 'solvers',
                secure_filename(str(g.User.idUser) + '-' + g.User.lastname),
                'bin')
            try:
                os.makedirs(store_path)
            except:
                pass
            with open(os.path.join(store_path, hash.hexdigest()), 'wb') as f:
                f.write(bin)

            if not form.binary.data.filename.endswith('.zip'):
                tmpfile = StringIO()
                zip_file = zipfile.ZipFile(tmpfile,
                                           'w',
                                           compression=zipfile.ZIP_DEFLATED)
                zip_file.writestr(form.binary.data.filename, bin)
                zip_file.close()
                tmpfile.seek(0)
                bin = tmpfile.read()
                run_path = form.binary.data.filename
            else:
                if not run_path:
                    error = 'Since your binary is a .zip file, please provide the path of the executable within the archive'
                    valid = False

        code = None
        if id is None or (id is not None and form.code.data):
            code = request.files[form.code.name].stream.read()
            code_hash = hashlib.md5()
            code_hash.update(code)

            # save the code in the FS as log
            store_path = os.path.join(
                config.UPLOAD_FOLDER, 'solvers',
                secure_filename(str(g.User.idUser) + '-' + g.User.lastname),
                'code')
            try:
                os.makedirs(store_path)
            except:
                pass
            with open(os.path.join(store_path, code_hash.hexdigest()),
                      'wb') as f:
                f.write(code)

        description_pdf = None
        if id is None or (id is not None and form.description_pdf.data):
            description_pdf = request.files[
                form.description_pdf.name].stream.read()
        if id is None and not description_pdf:
            valid = False
            error = "Please provide a description pdf."

        params = utils.parse_parameters(parameters)

        if valid:
            if id is None:
                solver = db.Solver()
                if bin:
                    solver_binary = db.SolverBinary()
                    solver_binary.solver = solver
                else:
                    solver_binary = None
            else:
                if solver_binary:
                    for solver_config in solver_binary.solver_configurations:
                        for pi in solver_config.parameter_instances:
                            db.session.delete(pi)
                        db.session.commit()
                        db.session.delete(solver_config)
                    db.session.commit()
                if not solver_binary and bin:
                    solver_binary = db.SolverBinary()
                    solver_binary.solver = solver

            solver.name = name
            solver.description = description
            solver.authors = authors
            solver.user = g.User
            solver.version = version
            solver.competition_categories = form.competition_categories.data
            if solver_binary:
                solver_binary.binaryName = name
                solver_binary.runPath = run_path
                solver_binary.version = version
                solver_binary.runCommand = form.run_command.data
            if bin:
                # new or updated binary
                solver_binary.binaryArchive = bin
                solver_binary.md5 = hash.hexdigest()
            if code:
                # new or updated code
                solver.code = code
            if description_pdf:
                # new or updated description pdf
                solver.description_pdf = description_pdf

            db.session.add(solver)
            if bin:
                db.session.add(solver_binary)

            # on resubmissions delete old parameters
            if id is not None:
                for p in solver.parameters:
                    db.session.delete(p)
                db.session.commit()

            for p in params:
                param = db.Parameter()
                param.name = None if p[0] == '' else p[0]
                param.prefix = None if p[1] == '' else p[1]
                param.defaultValue = p[2] or ''
                param.hasValue = not p[3]  # p[3] actually means 'is boolean'
                param.order = int(p[4])
                param.space = p[5]
                param.solver = solver
                db.session.add(param)
            try:
                db.session.commit()
                if code:
                    msg = Message("[" + db.label + "][Admin] Code submitted",
                                  recipients=[config.DEFAULT_MAIL_SENDER])
                    msg.body = (
                        "The user %s %s just submitted code for the solver with id %d"
                        % (g.User.firstname, g.User.lastname, solver.idSolver))
                    mail.send(msg)
            except Exception as e:
                print e
                db.session.rollback()
                flash(
                    "Couldn't save solver to the database. Please contact an administrator for support."
                )
                return render('/accounts/submit_solver.html',
                              database=database,
                              error=error,
                              db=db,
                              id=id,
                              form=form)

            flash(
                'Solver submitted successfully. If you provided a binary, test jobs will be generated within the next minute. You will be notified by email once they are computed. Please check the Results page at any time for the computation progress.'
            )
            return redirect(
                url_for('accounts.list_solvers',
                        database=database,
                        user_id=g.User.idUser))

    return render('/accounts/submit_solver.html',
                  database=database,
                  error=error,
                  db=db,
                  id=id,
                  form=form)