Ejemplo n.º 1
0
def reject_tag(tag_request_id):
    """Reject a tag request."""
    tag_request = TagRequest.query.get_or_404(tag_request_id)
    redirect_url = generate_next(url_for('requests.tag_request_index'))
    tag_request.rejected = True
    db.session.commit()
    return redirect(redirect_url)
Ejemplo n.º 2
0
def delete_annotation(annotation_id):
    """Delete an annotation. Like, full on remove it from the system.

    This route will be eliminated. Or it's security priveleges changed. The
    purpose of this route is for two different scenarios:

    1. The annotation is useless/spam/etc. and should be eliminated.
    2. The annotation is dangerous (illegal content, copyright violation, etc.)

    My inclination is to keep it for the latter, but use other methods for the
    former.
    """
    form = AreYouSureForm()
    annotation = Annotation.query.get_or_404(annotation_id)
    redirect_url = generate_next(
        url_for('main.text_annotations', text_url=annotation.text.url))
    if form.validate_on_submit():
        for e in annotation.all_edits:
            e.tags = []
        db.session.delete(annotation)
        db.session.commit()
        flash(f"Annotation [{annotation_id}] deleted.")
        return redirect(redirect_url)
    text = """If you click submit the annotation, all of the edits to the
    annotation, all of the votes to the edits, all of the votes to the
    annotation, and all of the reputation changes based on the annotation, will
    be deleted permanently.

    This is not something to take lightly. Unless there is illegal content
    associated with the annotation, you really ought to simply deactivate it.
    """
    return render_template('forms/delete_check.html',
                           title=f"Delete [{annotation_id}]",
                           form=form,
                           text=text)
Ejemplo n.º 3
0
def delete_edit(edit_id):
    """This annotation is to delete an *edit* to an annotation because it
    contains illegal content.
    """
    form = AreYouSureForm()
    edit = Edit.query.get_or_404(edit_id)
    redirect_url = generate_next(
        url_for('main.edit_history', annotation_id=edit.annotation_id))
    if form.validate_on_submit():
        if edit.current:
            edit.previous.current = True
        else:
            for e in edit.annotation.all_edits.order_by(Edit.num.desc()).all():
                if e.num > edit.num:
                    e.num -= 1
        flash(f"Edit #{edit.num} of [{edit.annotation_id}] deleted.")
        db.session.delete(edit)
        db.session.commit()
        return redirect(redirect_url)
    text = """If you click submit the edit, all of the votes for the edit, and
    all of the reputation changes based on the edit being approved will be
    deleted. The edit numbers of all the subsequent edits will be decremented by
    one. It will therefore be as though the edit never even existed.

    The only reason for this is if there is illegal content in the edit.
    """
    return render_template('forms/delete_check.html',
                           title=f"Delete edit #{edit.num} of "
                           f"[{edit.annotation_id}]",
                           form=form,
                           text=text)
Ejemplo n.º 4
0
def vote():
    """This pretty much covers voting! Love it."""
    entity_cls = classes.get(request.args.get('entity'), None)
    entity_id = request.args.get('id').strip(lowercase)
    if not entity_cls:
        abort(404)
    if not issubclass(entity_cls, classes['VotableMixin']):
        abort(501)
    entity = entity_cls.query.get_or_404(entity_id)
    redirect_url = generate_next(entity.url)
    if isinstance(entity, classes['Annotation']) and not entity.active:
        flash("You cannot vote on deactivated annotations.")
        return redirect(redirect_url)
    if isinstance(entity, classes['Edit'])\
            and not entity.annotation.active\
            and not current_user.is_authorized(
                'review_deactivated_annotation_edits'):
        flash("You cannot vote on deactivated annotations edits.")
        return redirect(redirect_url)
    up = True if request.args.get('up').lower() == 'true' else False
    if up:
        entity.upvote(current_user)
    else:
        entity.downvote(current_user)
    db.session.commit()
    return redirect(redirect_url)
Ejemplo n.º 5
0
def register():
    redirect_url = generate_next(url_for('main.index'))
    if current_user.is_authenticated:
        return redirect(redirect_url)
    form = RegistrationForm()
    if form.validate_on_submit():
        token = request.args.get('token')
        email = jwt.decode(token,
                           current_app.config['SECRET_KEY'],
                           algorithms=['HS256'])['email'] if token else None
        if form.website.data.strip() != '':
            return redirect(redirect_url)
        if current_app.config['HASH_REGISTRATION'] and email != form.email.data:
            flash("Registration is currently invite only. Either you have "
                  "submitted an invalid invite token, or no invite token at "
                  "all. Public registration will begin soon. Please have "
                  "patience. Alternatively, if you recieved an email token, "
                  "please contact your administrator for a fresh one.")
            return redirect(redirect_url)
        user = User(displayname=form.displayname.data, email=form.email.data)
        user.set_password(form.password.data)
        db.session.add(user)
        db.session.commit()
        flash("Congratulations, you are now a registered user!")
        login_user(user)
        return redirect(redirect_url)
    return render_template('forms/register.html', title="Register", form=form)
Ejemplo n.º 6
0
def flag_comment(annotation_id, comment_id, flag_id):
    """Flag an annotation."""
    comment = Comment.query.get_or_404(comment_id)
    redirect_url = generate_next(comment.url)
    flag = CommentFlag.enum_cls.query.get_or_404(flag_id)
    CommentFlag.flag(comment, flag, current_user)
    db.session.commit()
    flash(f"Comment {comment.id} flagged \"{flag.enum}\"")
    return redirect(redirect_url)
Ejemplo n.º 7
0
def mark_all_user_flags(user_id):
    """Mark all user flags resolved or unresolved."""
    user = User.query.get_or_404(user_id)
    redirect_url = generate_next(url_for('admin.user_flags', user_id=user.id))
    for flag in user.active_flags:
        flag.resolve(current_user)
    flash("All active user flags resolved.")
    db.session.commit()
    return redirect(redirect_url)
Ejemplo n.º 8
0
def flag_user(flag_id, user_id):
    """To flag a user."""
    user = User.query.get_or_404(user_id)
    flag = UserFlag.enum_cls.query.get_or_404(flag_id)
    redirect_url = generate_next(url_for('user.profile', user_id=user.id))
    UserFlag.flag(user, flag, current_user)
    db.session.commit()
    flash(f"User {user.displayname} flagged \"{flag.enum}\"")
    return redirect(redirect_url)
Ejemplo n.º 9
0
def lock_user(user_id):
    """Lock a user account."""
    user = User.query.get_or_404(user_id)
    redirect_url = generate_next(url_for('user.profile', user_id=user.id))
    user.locked = not user.locked
    db.session.commit()
    if user.locked:
        flash(f"User account {user.displayname} locked.")
    else:
        flash(f"User account {user.displayname} unlocked.")
    return redirect(redirect_url)
Ejemplo n.º 10
0
def flag_annotation(flag_id, annotation_id):
    """Flag an annotation."""
    annotation = Annotation.query.get_or_404(annotation_id)
    redirect_url = generate_next(annotation.url)
    if not annotation.active:
        current_user.authorize('view_deactivated_annotations')
    flag = AnnotationFlag.enum_cls.query.get_or_404(flag_id)
    AnnotationFlag.flag(annotation, flag, current_user)
    db.session.commit()
    flash(f"Annotation {annotation.id} flagged \"{flag.enum}\"")
    return redirect(redirect_url)
Ejemplo n.º 11
0
def edit_line(line_id):
    """Edit a line. Purely for administrators. Perhaps to be made more robust.
    """
    line = Line.query.get_or_404(line_id)
    form = LineForm()
    redirect_url = generate_next(line.url)
    if form.validate_on_submit() and form.line.data is not None:
        line.body = form.line.data
        db.session.commit()
        flash("Line updated.")
        return redirect(redirect_url)
    form.line.data = line.body
    return render_template('forms/line.html', title="Edit Line", form=form)
Ejemplo n.º 12
0
def mark_user_flag(flag_id):
    """Mark a specific user flag resolved or unresolved."""
    flag = UserFlag.query.get_or_404(flag_id)
    redirect_url = generate_next(
        url_for('admin.user_flags', user_id=flag.user_id))
    if flag.time_resolved:
        flag.unresolve()
        flash("Flag unresolved.")
    else:
        flag.resolve(current_user)
        flash("Flag resolved.")
    db.session.commit()
    return redirect(redirect_url)
Ejemplo n.º 13
0
def create_tag():
    """Create a new tag."""
    tag_request = None
    redirect_url = generate_next(url_for('requests.tag_request_index'))
    form = TagForm()
    if form.validate_on_submit():
        if form.tag.data is not None and form.description.data is not None:
            tag = Tag(tag=form.tag.data, description=form.description.data)
            db.session.add(tag)
            db.session.commit()
            flash("Tag created.")
            return redirect(redirect_url)
    return render_template('forms/tag.html', title="Create Tag", form=form)
Ejemplo n.º 14
0
def mark_all_annotation_flags(annotation_id):
    """Resolve all flags for a given annotation. This route will be deprecated
    after the annotation flag democratization overhaul."""
    annotation = Annotation.query.get_or_404(annotation_id)
    if not annotation.active:
        current_user.authorize('resolve_deactivated_annotation_flags')
    redirect_url = generate_next(
        url_for('admin.annotation_flags', annotation_id=annotation_id))
    for flag in annotation.active_flags:
        flag.resolve(current_user)
    db.session.commit()
    flash("All flags marked resolved.")
    return redirect(redirect_url)
Ejemplo n.º 15
0
def annotate(text_url, edition_num, toc_id, first_line, last_line):
    """Create an annotation."""
    fl, ll = line_check(int(first_line), int(last_line))
    form = AnnotationForm()
    text = Text.get_by_url(text_url).first_or_404()
    edition = (text.primary if not edition_num else Edition.query.filter(
        Edition.text_id == text.id, Edition.num == edition_num).first_or_404())
    toc = TOC.query.get_or_404(toc_id)
    lines = toc.lines.filter(Line.num >= fl, Line.num <= ll).all()
    if lines is None:
        abort(404)
    redirect_url = generate_next(lines[0].url)
    context = toc.lines.filter(Line.num >= int(fl) - 3,
                               Line.num <= int(ll) + 3).all()

    if form.validate_on_submit():
        fl, ll = line_check(form.first_line.data, form.last_line.data)
        allgood, tags = process_tags(form.tags.data)
        if not allgood:
            return render_template('forms/annotation.html',
                                   title=text.title,
                                   form=form,
                                   text=text,
                                   edition=edition,
                                   lines=lines,
                                   context=context)
        annotation = Annotation(edition=edition,
                                toc=toc,
                                annotator=current_user,
                                fl=fl,
                                ll=ll,
                                fc=form.first_char_idx.data,
                                lc=form.last_char_idx.data,
                                body=form.annotation.data,
                                tags=tags)
        db.session.add(annotation)
        db.session.commit()
        flash("Annotation Submitted")
        return redirect(redirect_url)
    else:
        form.first_line.data = first_line
        form.last_line.data = last_line
        form.first_char_idx.data = 0
        form.last_char_idx.data = -1
    return render_template('forms/annotation.html',
                           title=f"Annotating {text.title}",
                           form=form,
                           toc=toc,
                           edition=edition,
                           lines=lines,
                           context=context)
Ejemplo n.º 16
0
def follow_user(user_id):
    """Follow a user."""
    user = User.query.get_or_404(user_id)
    redirect_url = generate_next(user.url)
    if user == current_user:
        flash("You can't follow yourself.")
        return redirect(redirect_url)
    followed = current_user.followed_users
    if user in followed:
        followed.remove(user)
    else:
        followed.append(user)
    db.session.commit()
    return redirect(redirect_url)
Ejemplo n.º 17
0
def deactivate_annotation(annotation_id):
    """This route will deactivate (or reactivate) an annotation. Requires the
    'deactivate_annotations' right.
    """
    annotation = Annotation.query.get_or_404(annotation_id)
    annotation.active = not annotation.active
    db.session.commit()

    if annotation.active:
        flash(f"Annotation {annotation.id} reactivated")
    else:
        flash(f"Annotation {annotation.id} deactivated.")

    redirect_url = generate_next(
        url_for('main.annotation', annotation_id=annotation_id))
    return redirect(redirect_url)
Ejemplo n.º 18
0
def mark_annotation_flag(flag_id):
    """Resolve/Unresolve an annotation flag. This system needs to be overhauled.
    """
    flag = AnnotationFlag.query.get_or_404(flag_id)
    redirect_url = generate_next(
        url_for('admin.annotation_flags', annotation_id=flag.annotation_id))
    if flag.time_resolved:
        flag.unresolve()
        flash(f"Flag {flag.enum.enum} on annotation [{flag.entity.id}] marked "
              "unresolved.")
    else:
        flag.resolve(current_user)
        flash(f"Flag {flag.enum.enum} on annotation [{flag.entity.id}] marked "
              "resolved.")
    db.session.commit()
    return redirect(redirect_url)
Ejemplo n.º 19
0
def follow():
    entity_cls = classes.get(request.args.get('entity'), None)
    entity_id = request.args.get('id').strip(lowercase)
    if not entity_cls:
        abort(404)
    if not issubclass(entity_cls, classes['FollowableMixin']):
        abort(501)
    entity = entity_cls.query.get_or_404(entity_id)
    redirect_url = generate_next(entity.url)
    followings = getattr(current_user,
                         f'followed_{entity_cls.__name__.lower()}s')
    if entity in followings:
        followings.remove(entity)
    else:
        followings.append(entity)
    db.session.commit()
    return redirect(redirect_url)
Ejemplo n.º 20
0
def edit_wiki(wiki_id):
    """Edit a wiki."""
    form = WikiForm()
    wiki = Wiki.query.get_or_404(wiki_id)
    redirect_url = generate_next(wiki.entity.url)

    if wiki.edit_pending:
        flash("That wiki is locked from a pending edit.")
        return redirect(redirect_url)
    if form.validate_on_submit():
        wiki.edit(current_user, body=form.wiki.data, reason=form.reason.data)
        db.session.commit()
        return redirect(redirect_url)

    form.wiki.data = wiki.current.body
    return render_template('forms/wiki.html',
                           title="Edit wiki",
                           form=form,
                           wiki=wiki)
Ejemplo n.º 21
0
def login():
    redirect_url = generate_next(url_for('main.index'))
    if current_user.is_authenticated:
        return redirect(redirect_url)
    form = LoginForm()

    if form.validate_on_submit():
        user = User.query.filter_by(email=form.email.data).first()
        if user and user.locked:
            flash("That account is locked.")
            return redirect(url_for('main.login', next=redirect_url))
        elif user is None or not user.check_password(form.password.data):
            flash("Invalid email or password")
            return redirect(url_for('main.login', next=redirect_url))
        login_user(user, remember=form.remember_me.data)

        return redirect(redirect_url)

    return render_template('forms/login.html', title="Sign In", form=form)
Ejemplo n.º 22
0
def delete_comment(annotation_id, comment_id):
    """Delete a comment."""
    form = AreYouSureForm()
    comment = Comment.query.get_or_404(comment_id)
    redirect_url = generate_next(comment.url)

    if form.validate_on_submit():
        comment.body = "[deleted]"
        db.session.commit()
        flash(f"Comment deleted.")
        return redirect(redirect_url)
    text = """This is to delete a comment. The only reason to delete a comment
is if it is illegal content.

It doesn't actually "delete" the comment, it just obliterates the content.
    """
    return render_template('forms/delete_check.html',
                           title=f"Delete Comment {comment_id}",
                           form=form,
                           text=text)
Ejemplo n.º 23
0
def delete_profile_check():
    """Delete the user's profile (i.e., anonymize)."""
    form = AreYouSureForm()
    redirect_url = generate_next(
        url_for('user.profile', user_id=current_user.id))
    if form.validate_on_submit():
        current_user.displayname = f'x_user{current_user.id}'
        current_user.email = '{current_user.id}'
        current_user.password_hash = '***'
        current_user.about_me = ''
        db.session.commit()
        logout_user()
        flash("Account anonymized.")
        return redirect(redirect_url)

    text = f"""You have clicked the link to delete your account. This page
serves as a double check to make sure that you’re really sure you want to delete
your account. You will not be able to undo this. Annopedia is not like Facebook.
We don’t secretly keep your personal information so you can reactivate your
account later on. If you delete it, it’s done.

Please note, however, that the account itself will not be expunged from our
database. Annopedia is a collaborative effort, and we therefore reserve the
right to retain all of your contributions. This deletion is an anonymization of
your account. Your display name, email address, and about me will all be erased
and anonymized. Every interaction you have ever made with the site will be
associated with an account which cannot be logged into and whose display name
will be `x_user_{current_user.id}` But you will never be able to log back in
and retrieve your account.

If you’re really sure about this, click the button “Yes, I’m sure.” Otherwise,
press back in your browser, or _close_ your browser, or even pull the power cord
from the back of your computer. Because if you click “Yes, I’m sure,” then your
account is gone."""
    return render_template('forms/delete_check.html',
                           title="Are you sure?",
                           form=form,
                           text=text)
Ejemplo n.º 24
0
def edit(annotation_id):
    annotation = Annotation.query.get_or_404(annotation_id)
    form = AnnotationForm()
    redirect_url = generate_next(
        url_for('main.annotation', annotation_id=annotation_id))
    if (annotation.locked
            and not current_user.is_authorized('edit_locked_annotations')):
        flash("That annotation is locked from editing.")
        return redirect(redirect_url)
    elif annotation.edit_pending:
        flash("There is an edit still pending peer review.")
        return redirect(redirect_url)
    elif not annotation.active:
        current_user.authorize('edit_deactivated_annotations')

    lines = annotation.HEAD.lines
    context = annotation.HEAD.context
    if form.validate_on_submit():
        fl, ll = line_check(form.first_line.data, form.last_line.data)

        tagsuccess, tags = process_tags(form.tags.data)
        try:
            editsuccess = annotation.edit(editor=current_user,
                                          reason=form.reason.data,
                                          fl=fl,
                                          ll=ll,
                                          fc=form.first_char_idx.data,
                                          lc=form.last_char_idx.data,
                                          body=form.annotation.data,
                                          tags=tags)
        except Exception as e:
            print(e)
            editsuccess = False

        # rerender the template with the work already filled
        if not (editsuccess and tagsuccess):
            db.session.rollback()
            return render_template('forms/annotation.html',
                                   form=form,
                                   title=annotation.text.title,
                                   lines=lines,
                                   text=annotation.text,
                                   edition=annotation.edition,
                                   annotation=annotation,
                                   context=context)
        else:
            db.session.commit()
        return redirect(redirect_url)

    elif not annotation.edit_pending:
        tag_strings = []
        for t in annotation.HEAD.tags:
            tag_strings.append(t.tag)
        form.first_line.data = annotation.HEAD.first_line_num
        form.last_line.data = annotation.HEAD.last_line_num
        form.first_char_idx.data = annotation.HEAD.first_char_idx
        form.last_char_idx.data = annotation.HEAD.last_char_idx
        form.annotation.data = annotation.HEAD.body
        form.tags.data = ' '.join(tag_strings)
    return render_template('forms/annotation.html',
                           form=form,
                           title=f"Edit Annotation {annotation.id}",
                           edition=annotation.edition,
                           lines=lines,
                           annotation=annotation,
                           context=context)
Ejemplo n.º 25
0
def not_found_error(error):
    """My 404"""
    redirect_url = generate_next(url_for("index"))
    return render_template("errors/404.html", redirect_url=redirect_url), 404
Ejemplo n.º 26
0
def forbidden_error(error):
    """My 403 error, for when someone goes somewhere they're not supposed to go.
    """
    redirect_url = generate_next(url_for("index"))
    return render_template("errors/403.html", redirect_url=redirect_url), 403
Ejemplo n.º 27
0
def internal_error(error):
    """My 500, for internal server error, which I see too much of too often."""
    db.session.rollback()
    redirect_url = generate_next(url_for("index"))
    return render_template("errors/500.html", redirect_url=redirect_url), 500
Ejemplo n.º 28
0
def logout():
    redirect_url = generate_next(url_for('main.index'))
    logout_user()
    return redirect(redirect_url)
Ejemplo n.º 29
0
def upvote_wiki_edit(wiki_id, edit_id):
    edit = WikiEdit.query.get_or_404(edit_id)
    redirect_url = generate_next(edit.wiki.entity.url)
    edit.upvote(current_user)
    db.session.commit()
    return redirect(redirect_url)