Пример #1
0
def reset():
    "Reset the password for a user account and send email."
    if utils.http_GET():
        email = flask.request.args.get("email") or ""
        email = email.lower()
        return flask.render_template("user/reset.html", email=email)

    elif utils.http_POST():
        try:
            user = get_user(email=flask.request.form["email"])
            if user is None:
                raise KeyError
            if user["status"] != constants.ENABLED:
                raise KeyError
        except KeyError:
            pass  # Silent when no user found.
        else:
            with UserSaver(user) as saver:
                saver.set_password()
            send_password_code(user, "password reset")
        # Don't advertise whether user exists or not.
        utils.flash_message(
            "An email has been sent, if a user account with the given email address exists."
        )
        return flask.redirect(flask.url_for("home"))
Пример #2
0
def create(pid, username):
    "Create a new review for the proposal for the given reviewer."
    proposal = anubis.proposal.get_proposal(pid)
    if proposal is None:
        return utils.error("No such proposal.", flask.url_for("home"))
    call = anubis.call.get_call(proposal["call"])

    try:
        if not allow_create(proposal):
            raise ValueError("You may not create a review for the proposal.")
        user = anubis.user.get_user(username=username)
        if user is None:
            raise ValueError("No such user.")
        if user["username"] not in call["reviewers"]:
            raise ValueError("User is not a reviewer in the call.")
        review = get_reviewer_review(proposal, user)
        if review is not None:
            utils.flash_message("The review already exists.")
            return flask.redirect(flask.url_for(".display",
                                                iuid=review["_id"]))
        if proposal["user"] == user["username"]:
            raise ValueError(
                "Reviewer not allowed to review their own proposal.")
        with ReviewSaver(proposal=proposal, user=user) as saver:
            pass
    except ValueError as error:
        utils.flash_error(error)
    return flask.redirect(
        flask.url_for("reviews.call_reviewer",
                      cid=proposal["call"],
                      username=username))
Пример #3
0
def enable(username):
    "Enable the given user account."
    user = get_user(username=username)
    if user is None:
        return utils.error("No such user.", flask.url_for("home"))
    with UserSaver(user) as saver:
        saver.set_status(constants.ENABLED)
        saver.set_password()
    send_password_code(user, "enabled")
    utils.flash_message("User account enabled; email sent.")
    return flask.redirect(flask.url_for(".display", username=username))
Пример #4
0
def edit(username):
    "Edit the user. Or delete the user."
    user = get_user(username=username)
    if user is None:
        return utils.error("No such user.", flask.url_for("home"))
    if not allow_edit(user):
        return utils.error("Access to user edit not allowed.")

    if utils.http_GET():
        return flask.render_template("user/edit.html",
                                     user=user,
                                     allow_change_role=allow_change_role(user))

    elif utils.http_POST():
        try:
            with UserSaver(user) as saver:
                if flask.g.am_admin:
                    email = flask.request.form.get("email")
                    saver.set_email(email, require=bool(email))
                if allow_change_role(user):
                    saver.set_role(flask.request.form.get("role"))
                    saver.set_call_creator(
                        utils.to_bool(flask.request.form.get("call_creator")))
                saver.set_givenname(flask.request.form.get("givenname"))
                saver.set_familyname(flask.request.form.get("familyname"))
                saver.set_gender(flask.request.form.get("gender"))
                saver.set_birthdate(flask.request.form.get("birthdate"))
                saver.set_degree(flask.request.form.get("degree"))
                saver.set_affiliation(
                    flask.request.form.get("affiliation")
                    or flask.request.form.get("affiliation_other"))
                saver.set_postaladdress(
                    flask.request.form.get("postaladdress"))
                saver.set_phone(flask.request.form.get("phone"))
        except ValueError as error:
            utils.flash_error(error)
        return flask.redirect(
            flask.url_for(".display", username=user["username"]))

    elif utils.http_DELETE():
        if not allow_delete(user):
            return utils.error(
                "Cannot delete the user account; admin or not empty.",
                flask.url_for(".display", username=username),
            )
        flask.g.db.delete(user)
        utils.flash_message(f"Deleted user {username}.")
        if flask.g.am_admin:
            return flask.redirect(flask.url_for(".all"))
        else:
            return flask.redirect(flask.url_for("home"))
Пример #5
0
def submit(pid):
    "Submit the proposal."
    proposal = get_proposal(pid)
    if proposal is None:
        return utils.error("No such proposal.", flask.url_for("home"))

    if utils.http_POST():
        try:
            with ProposalSaver(proposal) as saver:
                saver.set_submitted()  # Tests whether allowed or not.
        except ValueError as error:
            utils.flash_error(error)
        else:
            utils.flash_message("Proposal was submitted.")
            send_submission_email(proposal)
        return flask.redirect(flask.url_for(".display", pid=pid))
Пример #6
0
def reset_counter(cid):
    "Reset the counter of the call. Only if no proposals in it."
    call = get_call(cid)
    if not call:
        return utils.error("No such call.", flask.url_for("home"))
    if not allow_edit(call):
        return utils.error("You are not allowed to edit the call.")
    if utils.get_call_proposals_count(cid) != 0:
        return utils.error(
            "Cannot reset counter when there are" " proposals in the call."
        )

    with CallSaver(call) as saver:
        saver["counter"] = None
    utils.flash_message("Counter for proposals in call reset.")
    return flask.redirect(flask.url_for(".display", cid=call["identifier"]))
Пример #7
0
def edit(cid):
    "Edit the call, or delete it."
    call = get_call(cid)
    if not call:
        return utils.error("No such call.", flask.url_for("home"))
    if not allow_edit(call):
        return utils.error("You are not allowed to edit the call.")

    if utils.http_GET():
        return flask.render_template(
            "call/edit.html",
            call=call,
            allow_identifier_edit=allow_identifier_edit(call),
        )

    elif utils.http_POST():
        try:
            with CallSaver(call) as saver:
                saver.set_identifier(flask.request.form.get("identifier"))
                saver.set_title(flask.request.form.get("title"))
                saver["description"] = flask.request.form.get("description")
                saver["home_description"] = (
                    flask.request.form.get("home_description").strip() or None
                )
                saver["opens"] = utils.normalize_datetime(
                    flask.request.form.get("opens")
                )
                saver["closes"] = utils.normalize_datetime(
                    flask.request.form.get("closes")
                )
                saver["reviews_due"] = utils.normalize_datetime(
                    flask.request.form.get("reviews_due")
                )
                saver.edit_access(flask.request.form)
            call = saver.doc
        except ValueError as error:
            utils.flash_error(error)
        return flask.redirect(flask.url_for(".display", cid=call["identifier"]))

    elif utils.http_DELETE():
        if not allow_delete(call):
            return utils.error("You are not allowed to delete the call.")
        utils.delete(call)
        utils.flash_message(f"Deleted call {call['identifier']}:{call['title']}.")
        return flask.redirect(
            flask.url_for("calls.owner", username=flask.g.current_user["username"])
        )
Пример #8
0
def create(pid):
    "Create a decision for the proposal."
    proposal = anubis.proposal.get_proposal(pid)
    if proposal is None:
        return utils.error("No such proposal.", flask.url_for("home"))
    try:
        if not allow_create(proposal):
            raise ValueError("You may not create a decision for the proposal.")
        decision = get_decision(proposal.get("decision"))
        if decision is not None:
            utils.flash_message("The decision already exists.")
            return flask.redirect(
                flask.url_for(".display", iuid=decision["_id"]))
        with DecisionSaver(proposal=proposal) as saver:
            pass
        decision = saver.doc
        with anubis.proposal.ProposalSaver(proposal) as saver:
            saver["decision"] = decision["_id"]
    except ValueError as error:
        utils.flash_error(error)
    return flask.redirect(flask.url_for(".display", iuid=decision["_id"]))
Пример #9
0
def edit(gid):
    "Edit the grant dossier."
    grant = get_grant(gid)
    if grant is None:
        return utils.error("No such grant.")
    call = anubis.call.get_call(grant["call"])

    if utils.http_GET():
        if not allow_edit(grant):
            return utils.error(
                "You are not allowed to edit this grant dossier.")
        return flask.render_template("grant/edit.html", grant=grant, call=call)

    elif utils.http_POST():
        if not allow_edit(grant):
            return utils.error(
                "You are not allowed to edit this grant dossier.")
        try:
            with GrantSaver(doc=grant) as saver:
                saver.set_fields_values(call.get("grant", []),
                                        form=flask.request.form)
        except ValueError as error:
            return utils.error(error)
        if saver.repeat_changed:
            url = flask.url_for(".edit", gid=grant["identifier"])
        else:
            url = flask.url_for(".display", gid=grant["identifier"])
        return flask.redirect(url)

    elif utils.http_DELETE():
        if not allow_delete(grant):
            return utils.error(
                "You are not allowed to delete this grant dossier.")
        proposal = anubis.proposal.get_proposal(grant["proposal"])
        with anubis.proposal.ProposalSaver(proposal) as saver:
            saver["grant"] = None
        utils.delete(grant)
        utils.flash_message("Deleted grant dossier.")
        return flask.redirect(
            flask.url_for("proposal.display", pid=proposal["identifier"]))
Пример #10
0
def edit(iuid):
    "Edit the decision."
    try:
        decision = get_decision(iuid)
    except KeyError:
        return utils.error("No such decision.", flask.url_for("home"))
    proposal = anubis.proposal.get_proposal(decision["proposal"])
    call = anubis.call.get_call(decision["call"])

    if utils.http_GET():
        if not allow_edit(decision):
            return utils.error("You are not allowed to edit this decision.")
        return flask.render_template("decision/edit.html",
                                     decision=decision,
                                     proposal=proposal,
                                     call=call)

    elif utils.http_POST():
        if not allow_edit(decision):
            return utils.error("You are not allowed to edit this decision.")
        try:
            # NOTE: Repeat field has not been implemented for decision.
            with DecisionSaver(doc=decision) as saver:
                saver.set_verdict(form=flask.request.form)
                saver.set_fields_values(call["decision"],
                                        form=flask.request.form)
        except ValueError as error:
            return utils.error(error)
        return flask.redirect(flask.url_for(".display", iuid=decision["_id"]))

    elif utils.http_DELETE():
        if not allow_delete(decision):
            return utils.error("You are not allowed to delete this decision.")
        with anubis.proposal.ProposalSaver(proposal) as saver:
            saver["decision"] = None
        utils.delete(decision)
        utils.flash_message("Deleted decision.")
        return flask.redirect(
            flask.url_for("proposal.display", pid=proposal["identifier"]))
Пример #11
0
def create(pid):
    "Create a grant dossier for the proposal."
    proposal = anubis.proposal.get_proposal(pid)
    if proposal is None:
        return utils.error("No such proposal.")
    try:
        if not allow_create(proposal):
            raise ValueError(
                "You may not create a grant dossier for the proposal.")
        grant = get_grant_proposal(pid)
        if grant is not None:
            utils.flash_message("The grant dossier already exists.")
            return flask.redirect(
                flask.url_for(".display", gid=grant["identifier"]))
        with GrantSaver(proposal=proposal) as saver:
            pass
        grant = saver.doc
        with anubis.proposal.ProposalSaver(proposal) as saver:
            saver["grant"] = grant["identifier"]
    except ValueError as error:
        utils.flash_error(error)
    return flask.redirect(flask.url_for(".display", gid=grant["identifier"]))
Пример #12
0
def password():
    "Set the password for a user account, and login user."
    if utils.http_GET():
        return flask.render_template(
            "user/password.html",
            username=flask.request.args.get("username"),
            code=flask.request.args.get("code"),
        )

    elif utils.http_POST():
        try:
            username = flask.request.form.get("username") or ""
            if not username:
                raise ValueError("No such user or wrong code.")
            user = get_user(username=username)
            if user is None:
                raise ValueError("No such user or wrong code.")
            if flask.g.am_admin:
                code = ""
            else:
                code = flask.request.form.get("code") or ""
                if user["password"] != f"code:{code}":
                    raise ValueError("No such user or wrong code.")
            password = flask.request.form.get("password") or ""
            if len(password) < flask.current_app.config["MIN_PASSWORD_LENGTH"]:
                raise ValueError("Too short password.")
        except ValueError as error:
            return utils.error(
                error, flask.url_for(".password", username=username,
                                     code=code))
        with UserSaver(user) as saver:
            saver.set_password(password)
        utils.flash_message("Password set.")
        if flask.g.am_admin:
            return flask.redirect(flask.url_for(".all"))
        else:
            do_login(username, password)
            return flask.redirect(flask.url_for("home"))
Пример #13
0
def edit(iuid):
    "Edit the review for the proposal."
    try:
        review = get_review(iuid)
    except KeyError:
        return utils.error("No such review.", flask.url_for("home"))
    proposal = anubis.proposal.get_proposal(review["proposal"])
    call = anubis.call.get_call(review["call"])

    if utils.http_GET():
        if not allow_edit(review):
            return utils.error("You are not allowed to edit this review.")
        return flask.render_template("review/edit.html",
                                     review=review,
                                     proposal=proposal,
                                     call=call)

    elif utils.http_POST():
        if not allow_edit(review):
            return utils.error("You are not allowed to edit this review.")
        try:
            # NOTE: Repeat field has not been implemented for review.
            with ReviewSaver(doc=review) as saver:
                saver.set_fields_values(call["review"],
                                        form=flask.request.form)
        except ValueError as error:
            return utils.error(error)
        return flask.redirect(flask.url_for(".display", iuid=review["_id"]))

    elif utils.http_DELETE():
        if not allow_delete(review):
            return utils.error("You are not allowed to delete this review.")
        utils.delete(review)
        utils.flash_message("Deleted review.")
        return flask.redirect(
            flask.url_for("proposal.display", pid=review["proposal"]))
Пример #14
0
def register():
    "Register a new user account."
    if utils.http_GET():
        return flask.render_template("user/register.html",
                                     gdpr=utils.get_site_text("gdpr.md"))

    elif utils.http_POST():
        try:
            with UserSaver() as saver:
                saver.set_username(flask.request.form.get("username"))
                saver.set_email(flask.request.form.get("email"))
                if utils.to_bool(flask.request.form.get("enable")):
                    saver.set_status(constants.ENABLED)
                saver.set_role(constants.USER)
                saver.set_call_creator(False)
                saver.set_password()  # Sets code.
                saver.set_givenname(flask.request.form.get("givenname"))
                saver.set_familyname(flask.request.form.get("familyname"))
                saver.set_gender(flask.request.form.get("gender"))
                saver.set_birthdate(flask.request.form.get("birthdate"))
                saver.set_degree(flask.request.form.get("degree"))
                saver.set_affiliation(
                    flask.request.form.get("affiliation")
                    or flask.request.form.get("affiliation_other"))
                saver.set_postaladdress(
                    flask.request.form.get("postaladdress"))
                saver.set_phone(flask.request.form.get("phone"))
            user = saver.doc
        except ValueError as error:
            return utils.error(error, flask.url_for(".register"))
        # Directly enabled; send code to the user, if so instructed.
        if user["status"] == constants.ENABLED:
            if utils.to_bool(flask.request.form.get("send_email")):
                send_password_code(user, "registered")
                utils.flash_message(
                    "User account created; an email with a link"
                    " to set password has been sent.")
            else:
                utils.flash_message("User account created.")
        # Was set to 'pending'; send email to admins.
        else:
            utils.flash_message("User account created; an email will be sent"
                                " when it has been enabled by the admin.")
            admins = get_users(role=constants.ADMIN, status=constants.ENABLED)
            recipients = [u["email"] for u in admins if u["email"]]
            site = flask.current_app.config["SITE_NAME"]
            title = f"{site} user account pending"
            url = flask.url_for(".display",
                                username=user["username"],
                                _external=True)
            text = f"To enable the user account, go to {url}\n\n" "/The Anubis system"
            utils.send_email(recipients, title, text)
        if flask.g.am_admin:
            return flask.redirect(flask.url_for("user.all"))
        else:
            return flask.redirect(flask.url_for("home"))
Пример #15
0
def edit(pid):
    "Edit the proposal."
    proposal = get_proposal(pid)
    if proposal is None:
        return utils.error("No such proposal.", flask.url_for("home"))
    call = anubis.call.get_call(proposal["call"])

    if utils.http_GET():
        if not allow_edit(proposal):
            return utils.error("You are not allowed to edit this proposal.")
        return flask.render_template("proposal/edit.html",
                                     proposal=proposal,
                                     call=call)

    elif utils.http_POST():
        if not allow_edit(proposal):
            return utils.error("You are not allowed to edit this proposal.")
        try:
            with ProposalSaver(proposal) as saver:
                saver["title"] = flask.request.form.get("_title") or None
                saver.set_fields_values(call["proposal"],
                                        form=flask.request.form)
        except ValueError as error:
            return utils.error(error)

        # If a repeat field was changed, then redisplay edit page.
        if saver.repeat_changed:
            return flask.redirect(
                flask.url_for(".edit", pid=proposal["identifier"]))

        if flask.request.form.get("_save") == "submit":
            proposal = get_proposal(pid, refresh=True)  # Get up-to-date info.
            try:
                with ProposalSaver(proposal) as saver:
                    saver.set_submitted()  # Tests whether allowed or not.
            except ValueError as error:
                utils.flash_error(error)
            else:
                utils.flash_message("Proposal saved and submitted.")
                send_submission_email(proposal)

        elif allow_submit(proposal) and not proposal.get("submitted"):
            utils.flash_warning("Proposal was saved but not submitted."
                                " You must explicitly submit it!")
        return flask.redirect(
            flask.url_for(".display", pid=proposal["identifier"]))

    elif utils.http_DELETE():
        if not allow_delete(proposal):
            return utils.error("You are not allowed to delete this proposal.")
        decision = anubis.decision.get_decision(proposal.get("decision"))
        if decision:
            utils.delete(decision)
        reviews = utils.get_docs_view("reviews", "proposal",
                                      proposal["identifier"])
        for review in reviews:
            utils.delete(review)
        utils.delete(proposal)
        utils.flash_message(f"Deleted proposal {pid}.")
        if flask.g.am_admin or flask.g.am_staff:
            url = flask.url_for("proposals.call", cid=call["identifier"])
        else:
            url = flask.url_for("proposals.user", username=proposal["user"])
        return flask.redirect(url)