Esempio n. 1
0
def create_auth_token():
    if not app.testing:
        app.csrf.protect()

    duration_seconds = request.form.get('duration_seconds', None)
    if duration_seconds:
        try:
            duration_seconds = int(duration_seconds)
            assert duration_seconds >= 1
        except (ValueError, AssertionError):
            abort(400, "duration_seconds must be a positive non-zero integer")

    # check user's auth. api_token and editor_id are signed together in session
    # cookie, so if api_token is valid editor_id is assumed to match. If that
    # wasn't true, users could manipulate session cookies and create tokens for
    # any user
    user_api = auth_api(session['api_token'])
    resp = user_api.auth_check()
    assert (resp.success)

    # generate token using *superuser* privs
    editor_id = session['editor']['editor_id']
    try:
        resp = priv_api.create_auth_token(editor_id,
                                          duration_seconds=duration_seconds)
    except ApiException as ae:
        app.log.info(ae)
        raise ae
    return render_template('auth_token.html', auth_token=resp.token)
Esempio n. 2
0
def generic_edit_delete(editgroup_id, entity_type, edit_id):
    # fetch editgroup (if set) or 404
    editgroup = None
    if editgroup_id:
        try:
            editgroup = api.get_editgroup(editgroup_id)
        except ApiException as ae:
            abort(ae.status)

        # check that editgroup is edit-able
        if editgroup.changelog_index != None:
            flash("Editgroup already merged")
            abort(400)

    # API on behalf of user
    user_api = auth_api(session['api_token'])

    # do the deletion
    try:
        if entity_type == 'container':
            user_api.delete_container_edit(editgroup.editgroup_id, edit_id)
        elif entity_type == 'file':
            user_api.delete_file_edit(editgroup.editgroup_id, edit_id)
        elif entity_type == 'release':
            user_api.delete_release_edit(editgroup.editgroup_id, edit_id)
        else:
            raise NotImplementedError
    except ApiException as ae:
        abort(ae.status)
    return redirect("/editgroup/{}".format(editgroup_id))
Esempio n. 3
0
def auth_account():
    # auth check on account page
    user_api = auth_api(session['api_token'])
    resp = user_api.auth_check()
    assert (resp.success)
    editor = user_api.get_editor(session['editor']['editor_id'])
    session['editor'] = editor.to_dict()
    load_user(editor.editor_id)
    return render_template('auth_account.html')
Esempio n. 4
0
def editgroup_submit(ident):
    if not app.testing:
        app.csrf.protect()
    # on behalf of user...
    user_api = auth_api(session['api_token'])
    try:
        eg = user_api.get_editgroup(str(ident))
        if eg.changelog_index:
            abort(400, "Editgroup already accepted")
        user_api.update_editgroup(eg.editgroup_id, eg, submit=True)
    except ApiException as ae:
        app.log.info(ae)
        abort(ae.status)
    return redirect('/editgroup/{}'.format(ident))
Esempio n. 5
0
def change_username():
    # show the user a list of login options
    if not 'username' in request.form:
        abort(400)
    # on behalf of user...
    user_api = auth_api(session['api_token'])
    editor = user_api.get_editor(session['editor']['editor_id'])
    editor.username = request.form['username']
    editor = user_api.update_editor(editor.editor_id, editor)
    # update our session
    session['editor'] = editor.to_dict()
    load_user(editor.editor_id)
    flash("Username updated successfully")
    return redirect('/auth/account')
Esempio n. 6
0
def change_username():
    if not app.testing:
        app.csrf.protect()
    # show the user a list of login options
    if not 'username' in request.form:
        abort(400)
    # on behalf of user...
    user_api = auth_api(session['api_token'])
    try:
        editor = user_api.get_editor(session['editor']['editor_id'])
        editor.username = request.form['username']
        editor = user_api.update_editor(editor.editor_id, editor)
    except ApiException as ae:
        app.log.info(ae)
        raise ae
    # update our session
    session['editor'] = editor.to_dict()
    load_user(editor.editor_id)
    return redirect('/auth/account')
def generic_edit_delete(editgroup_id, entity_type, edit_id):
    # fetch editgroup (if set) or 404
    editgroup = None
    if editgroup_id:
        try:
            editgroup = api.get_editgroup(editgroup_id)
        except ApiException as ae:
            abort(ae.status)

        # check that editgroup is edit-able
        if editgroup.changelog_index != None:
            flash("Editgroup already merged")
            abort(400)

    # API on behalf of user
    user_api = auth_api(session['api_token'])

    # do the deletion
    generic_entity_delete_edit(user_api, entity_type, editgroup.editgroup_id, edit_id)
    return redirect("/editgroup/{}".format(editgroup_id))
Esempio n. 8
0
def editgroup_create_annotation(ident):
    if not app.testing:
        app.csrf.protect()
    comment_markdown = request.form.get('comment_markdown')
    if not comment_markdown:
        app.log.info("empty comment field")
        abort(400)
    # on behalf of user...
    user_api = auth_api(session['api_token'])
    try:
        eg = user_api.get_editgroup(str(ident))
        if eg.changelog_index:
            abort(400, "Editgroup already accepted")
        ega = EditgroupAnnotation(
            comment_markdown=comment_markdown,
            extra=None,
        )
        user_api.create_editgroup_annotation(eg.editgroup_id, ega)
    except ApiException as ae:
        app.log.info(ae)
        raise ae
    return redirect('/editgroup/{}'.format(ident))
def generic_entity_delete(editgroup_id: Optional[str], entity_type: str, existing_ident: str):
    """
    Similar to generic_entity_edit(), but for deleting entities. This is a bit
    simpler!

    Handles both creation and update/edit paths.
    """

    # fetch editgroup (if set) or 404
    editgroup = None
    if editgroup_id:
        try:
            editgroup = api.get_editgroup(editgroup_id)
        except ApiException as ae:
            raise ae

        # check that editgroup is edit-able
        if editgroup.changelog_index != None:
            flash("Editgroup already merged")
            abort(400)

    # fetch entity (if set) or 404
    existing = None
    existing_edit = None
    if editgroup and existing_ident:
        existing, existing_edit = generic_get_editgroup_entity(editgroup, entity_type, existing_ident)
    elif existing_ident:
        existing = generic_get_entity(entity_type, existing_ident)

    # parse form (if submitted)
    status = 200
    form = EntityEditForm()

    if form.is_submitted():
        if form.validate_on_submit():
            # API on behalf of user
            user_api = auth_api(session['api_token'])
            if not editgroup:
                editgroup = form_editgroup_get_or_create(user_api, form)

            if editgroup:
                # TODO: some danger of wiping database state here is
                # "updated edit" causes, eg, a 4xx error. Better to allow
                # this in the API itself. For now, form validation *should*
                # catch most errors, and if not editor can hit back and try
                # again. This means, need to allow failure of deletion.
                if existing_edit:
                    # need to clear revision on object or this becomes just
                    # a "update pointer" edit
                    existing.revision = None
                    generic_entity_delete_edit(user_api, entity_type, editgroup.editgroup_id, existing_edit.edit_id)
                try:
                    edit = generic_entity_delete_entity(user_api, entity_type, editgroup.editgroup_id, existing.ident)
                except ApiException as ae:
                    app.log.warning(ae)
                    raise ae
                if status == 200:
                    return redirect('/editgroup/{}/{}/{}'.format(editgroup.editgroup_id, entity_type, edit.ident))
            else:
                status = 400
        elif form.errors:
            status = 400
            app.log.info("form errors (did not validate): {}".format(form.errors))

    else: # form is not submitted
        if existing:
            form = EntityTomlForm.from_entity(existing)

    editor_editgroups = api.get_editor_editgroups(session['editor']['editor_id'], limit=20)
    potential_editgroups = [e for e in editor_editgroups if e.changelog_index == None and e.submitted == None]

    if not form.is_submitted():
        # default to most recent not submitted, fallback to "create new"
        form.editgroup_id.data = ""
        if potential_editgroups:
            form.editgroup_id.data = potential_editgroups[0].editgroup_id

    return render_template("entity_delete.html", form=form, entity_type=entity_type,
        existing_ident=existing_ident, editgroup=editgroup,
        potential_editgroups=potential_editgroups), status
Esempio n. 10
0
def generic_entity_edit(editgroup_id, entity_type, existing_ident, edit_template):
    """

    existing (entity)

    Create: existing blank, ident blank, editgroup optional
    Update: ident set

    Need to handle:
    - editgroup not set (need to create one)
    - creating entity from form
    - updating an existing ident
    - updating an existing editgroup/ident

    Views:
    - /container/create
    - /container/<ident>/edit
    - /editgroup/<editgroup_id>/container/<ident>/edit

    Helpers:
    - get_editgroup_revision(editgroup, entity_type, ident) -> None or entity

    TODO: prev_rev interlock
    """

    # fetch editgroup (if set) or 404
    editgroup = None
    if editgroup_id:
        try:
            editgroup = api.get_editgroup(editgroup_id)
        except ApiException as ae:
            raise ae

        # check that editgroup is edit-able
        if editgroup.changelog_index != None:
            abort(400, "Editgroup already merged")

    # fetch entity (if set) or 404
    existing = None
    existing_edit = None
    if editgroup and existing_ident:
        existing, existing_edit = generic_get_editgroup_entity(editgroup, entity_type, existing_ident)
    elif existing_ident:
        existing = generic_get_entity(entity_type, existing_ident)

    # parse form (if submitted)
    status = 200
    if entity_type == 'container':
        form = ContainerEntityForm()
    elif entity_type == 'file':
        form = FileEntityForm()
    elif entity_type == 'release':
        form = ReleaseEntityForm()
    else:
        raise NotImplementedError

    if form.is_submitted():
        if form.validate_on_submit():
            # API on behalf of user
            user_api = auth_api(session['api_token'])
            if not editgroup:
                editgroup = form_editgroup_get_or_create(user_api, form)

            if editgroup:

                if not existing_ident: # it's a create
                    entity = form.to_entity()
                    try:
                        if entity_type == 'container':
                            edit = user_api.create_container(editgroup.editgroup_id, entity)
                        elif entity_type == 'file':
                            edit = user_api.create_file(editgroup.editgroup_id, entity)
                        elif entity_type == 'release':
                            edit = user_api.create_release(editgroup.editgroup_id, entity)
                        else:
                            raise NotImplementedError
                    except ApiException as ae:
                        app.log.warning(ae)
                        raise ae
                    return redirect('/editgroup/{}/{}/{}'.format(editgroup.editgroup_id, entity_type, edit.ident))
                else: # it's an update
                    # all the tricky logic is in the update method
                    form.update_entity(existing)
                    # do we need to try to delete the current in-progress edit first?
                    # TODO: some danger of wiping database state here is
                    # "updated edit" causes, eg, a 4xx error. Better to allow
                    # this in the API itself. For now, form validation *should*
                    # catch most errors, and if not editor can hit back and try
                    # again. This means, need to allow failure of deletion.
                    if existing_edit:
                        # need to clear revision on object or this becomes just
                        # a "update pointer" edit
                        existing.revision = None
                        try:
                            generic_entity_delete_edit(user_api, entity_type, editgroup.editgroup_id, existing_edit.edit_id)
                        except ApiException as ae:
                            if ae.status == 404:
                                pass
                            else:
                                raise ae
                    try:
                        if entity_type == 'container':
                            edit = user_api.update_container(editgroup.editgroup_id, existing.ident, existing)
                        elif entity_type == 'file':
                            edit = user_api.update_file(editgroup.editgroup_id, existing.ident, existing)
                        elif entity_type == 'release':
                            edit = user_api.update_release(editgroup.editgroup_id, existing.ident, existing)
                        else:
                            raise NotImplementedError
                    except ApiException as ae:
                        app.log.warning(ae)
                        raise ae
                    return redirect('/editgroup/{}/{}/{}'.format(editgroup.editgroup_id, entity_type, edit.ident))
            else:
                status = 400
        elif form.errors:
            status = 400
            app.log.info("form errors (did not validate): {}".format(form.errors))

    else: # form is not submitted
        if existing:
            if entity_type == 'container':
                form = ContainerEntityForm.from_entity(existing)
            elif entity_type == 'file':
                form = FileEntityForm.from_entity(existing)
            elif entity_type == 'release':
                form = ReleaseEntityForm.from_entity(existing)
            else:
                raise NotImplementedError

    editor_editgroups = api.get_editor_editgroups(session['editor']['editor_id'], limit=20)
    potential_editgroups = [e for e in editor_editgroups if e.changelog_index == None and e.submitted == None]

    if not form.is_submitted():
        # default to most recent not submitted, fallback to "create new"
        form.editgroup_id.data = ""
        if potential_editgroups:
            form.editgroup_id.data = potential_editgroups[0].editgroup_id

    return render_template(edit_template, form=form,
        existing_ident=existing_ident, editgroup=editgroup,
        potential_editgroups=potential_editgroups), status