From 026a0722357d74b143ed2d974ad2d871a56041b3 Mon Sep 17 00:00:00 2001 From: Andrew Dickinson Date: Mon, 20 Apr 2020 09:30:27 -0400 Subject: Add Project History Page (#553) Co-Authored-By: Glandos All project activity can be tracked, using SQLAlchemy-continuum. IP addresses can optionally be recorded. --- ihatemoney/web.py | 49 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) (limited to 'ihatemoney/web.py') diff --git a/ihatemoney/web.py b/ihatemoney/web.py index 8e0bca6..744d1bf 100644 --- a/ihatemoney/web.py +++ b/ihatemoney/web.py @@ -31,6 +31,7 @@ from flask import ( from flask_babel import get_locale, gettext as _ from flask_mail import Message from sqlalchemy import orm +from sqlalchemy_continuum import Operation from werkzeug.exceptions import NotFound from werkzeug.security import check_password_hash, generate_password_hash @@ -46,7 +47,8 @@ from ihatemoney.forms import ( get_billform_for, UploadForm, ) -from ihatemoney.models import db, Project, Person, Bill +from ihatemoney.history import get_history_queries, get_history +from ihatemoney.models import db, Project, Person, Bill, LoggingMode from ihatemoney.utils import ( Redirect303, list_of_dicts2json, @@ -404,6 +406,12 @@ def edit_project(): return redirect(url_for("main.list_bills")) else: edit_form.name.data = g.project.name + + if g.project.logging_preference != LoggingMode.DISABLED: + edit_form.project_history.data = True + if g.project.logging_preference == LoggingMode.RECORD_IP: + edit_form.ip_recording.data = True + edit_form.contact_email.data = g.project.contact_email return render_template( @@ -742,6 +750,45 @@ def settle_bill(): return render_template("settle_bills.html", bills=bills, current_view="settle_bill") +@main.route("//history") +def history(): + """Query for the version entries associated with this project.""" + history = get_history(g.project, human_readable_names=True) + + any_ip_addresses = any(event["ip"] for event in history) + + return render_template( + "history.html", + current_view="history", + history=history, + any_ip_addresses=any_ip_addresses, + LoggingMode=LoggingMode, + OperationType=Operation, + current_log_pref=g.project.logging_preference, + ) + + +@main.route("//erase_history", methods=["POST"]) +def erase_history(): + """Erase all history entries associated with this project.""" + for query in get_history_queries(g.project): + query.delete(synchronize_session="fetch") + + db.session.commit() + return redirect(url_for(".history")) + + +@main.route("//strip_ip_addresses", methods=["POST"]) +def strip_ip_addresses(): + """Strip ip addresses from history entries associated with this project.""" + for query in get_history_queries(g.project): + for version_object in query.all(): + version_object.transaction.remote_addr = None + + db.session.commit() + return redirect(url_for(".history")) + + @main.route("//statistics") def statistics(): """Compute what each member has paid and spent and display it""" -- cgit v1.1