add audit logs

revamp
lza_menace 2 years ago
parent 143d08f2f7
commit 3094205362

@ -3,7 +3,7 @@ from os import makedirs
import click
from flask import Blueprint, url_for, current_app
from suchwow.models import Post, Profile, Comment, Notification, db, Moderator, Ban
from suchwow.models import Post, Profile, Comment, Notification, db, Moderator, Ban, AuditEvent
from suchwow.utils.helpers import get_latest_tipped_posts
from suchwow.utils.helpers import get_top_posters, get_top_posts
from suchwow.reddit import make_post
@ -20,7 +20,7 @@ def init():
makedirs(f"{config.DATA_FOLDER}/{i}", exist_ok=True)
# init db
db.create_tables([Post, Profile, Comment, Notification, Moderator, Ban])
db.create_tables([Post, Profile, Comment, Notification, Moderator, Ban, AuditEvent])
@bp.cli.command("post_reddit")

@ -143,3 +143,12 @@ class Ban(Model):
class Meta:
database = db
class AuditEvent(Model):
id = AutoField()
user = ForeignKeyField(Profile)
timestamp = DateTimeField(default=datetime.now)
action = CharField()
class Meta:
database = db

@ -1,8 +1,8 @@
from flask import Blueprint, render_template, redirect, url_for, flash, request
from suchwow.models import Post, Profile, Moderator, Ban, get_ban_reason
from suchwow.models import AuditEvent, Post, Profile, Moderator, Ban, get_ban_reason
from suchwow.utils.decorators import moderator_required
from suchwow.utils.helpers import get_session_user
from suchwow.utils.helpers import get_session_user, audit_event
from suchwow import config
@ -48,6 +48,7 @@ def manage_mods():
flash('Cannot delete super admin you son-of-a-bitch.', 'is-danger')
else:
m.delete_instance()
audit_event(f'Deleted {to_delete} from mods')
flash(f'Removed {to_delete} from mods!', 'is-success')
return redirect(url_for('mod.manage_mods'))
if request.method == 'POST':
@ -61,6 +62,7 @@ def manage_mods():
else:
m = Moderator(username=to_add)
m.save()
audit_event(f'Added {to_add} to mods')
flash(f'Added {to_add} to mods!', 'is-success')
mods = Profile.select().join(Moderator, on=(Profile.username == Moderator.username))
return render_template('mod/manage.html', mods=mods)
@ -80,6 +82,7 @@ def manage_bans():
flash('Cannot ban super admin you son-of-a-bitch.', 'is-danger')
else:
ban.delete_instance()
audit_event(f'Removed ban on {to_delete}')
flash(f'Unbanned {to_delete}!', 'is-success')
return redirect(url_for('mod.manage_bans'))
if request.method == 'POST':
@ -98,9 +101,14 @@ def manage_bans():
reason = get_ban_reason()
ban = Ban(user=u, reason=reason)
ban.save()
audit_event(f'Banned {to_add} ({reason})')
flash(f'Banned {to_add}!', 'is-success')
bans = Ban.select()
return render_template('mod/bans.html', bans=bans)
# audit trail of activity
# view wallet rpc logs
@bp.route('/mods/logs')
@moderator_required
def view_logs():
events = AuditEvent.select().order_by(AuditEvent.timestamp.desc()).limit(50)
return render_template('mod/logs.html', logs=events)

@ -2,6 +2,7 @@ from datetime import datetime, timedelta
from os import path, remove
from io import BytesIO
from base64 import b64encode
from sys import audit
from qrcode import make as qrcode_make
from flask import render_template, Blueprint, request, session, flash
from flask import send_from_directory, redirect, url_for, current_app
@ -12,8 +13,7 @@ from suchwow import config
from suchwow.models import Post, Profile, Comment, Ban
from suchwow.utils.decorators import login_required, profile_required, moderator_required
from suchwow.utils.helpers import allowed_file, is_moderator, get_session_user
from suchwow.utils.helpers import rw_cache, post_webhook
from suchwow.reddit import make_post
from suchwow.utils.helpers import post_webhook, audit_event
from suchwow.discord import post_discord_webhook
@ -57,7 +57,6 @@ def create():
submitter = get_session_user()
u = Profile.filter(username=submitter)
banned = Ban.filter(user=u).first()
print(banned)
if banned:
flash(f"You can't post: {banned.reason}", "is-danger")
return redirect("/")
@ -105,7 +104,7 @@ def create():
post.save()
post.save_thumbnail()
url = url_for('post.read', id=post.id, _external=True)
post_webhook(f"New post :doge2: [{post.id}]({url}) by `{submitter}` :neckbeard:")
audit_event(f'Created new post {post.id}')
flash("New post created and pending approval!", "is-success")
return redirect(url_for("main.index"))
return render_template("post/create.html")
@ -119,11 +118,10 @@ def approve(id):
if not post.approved:
post.approved = True
post.save()
post_webhook(f"Post [{post.id}]({url}) approved :white_check_mark: by `{get_session_user()}` :fieri_parrot:")
flash("Approved", "is-success")
audit_event(f'Approved post {post.id}')
if current_app.config["DEBUG"] is False:
post_discord_webhook(post)
post_webhook(f"Post [{post.id}]({url}) submitted :dab_parrot: to Discord.")
return redirect(url_for("mod.pending_posts"))
else:
flash("You can't approve this", "is-success")
@ -141,8 +139,8 @@ def delete(id):
save_path_base = path.join(current_app.config["DATA_FOLDER"], "uploads")
save_path = path.join(save_path_base, post.image_name)
remove(save_path)
audit_event(f'Deleted post {post.id}')
post.delete_instance()
post_webhook(f"Post {post.id} deleted :dumpsterfire: by `{user}` :godmode:")
flash("Deleted that shit, brah!", "is-success")
if is_mod:
return redirect(url_for("mod.pending_posts"))

@ -0,0 +1,29 @@
{% extends 'base.html' %}
{% block content %}
<div class="container" style="text-align:center;">
<h1 class="title">Manage Mods</h1>
<nav class="breadcrumb is-centered" aria-label="breadcrumbs">
<ul>
<li><a href="/">Home</a></li>
<li><a href="{{ url_for('mod.main') }}">Mods</a></li>
</ul>
</nav>
<section class="section">
{% for log in logs %}
<article class="message" style="width: 40%; margin: 1em auto;">
<div class="message-header">
<p>{{ log.user.username }} - {{ log.timestamp | humanize }} </p>
</div>
<div class="message-body">
{{ log.action }}
</div>
</article>
{% endfor %}
</section>
</div>
{% endblock %}
{% block footer %}{% endblock %}

@ -52,7 +52,7 @@
</a>
</li>
<li>
<a>
<a href="{{ url_for('mod.view_logs') }}">
<span class="icon is-small"></span>
<span>View Logs</span>
</a>

@ -1,10 +1,12 @@
import pickle
from os import path, remove
from os import path
from datetime import datetime, timedelta
from requests import post as r_post
from json import dumps
from requests import post as r_post
from flask import session, current_app
from suchwow.models import Moderator, Post
from suchwow.models import Moderator, Post, AuditEvent, Profile
from suchwow.wownero import Wallet, from_atomic
from suchwow import config
@ -20,6 +22,14 @@ def is_moderator(username):
else:
return False
def get_profile():
p = Profile.filter(username=get_session_user()).first()
return p
def audit_event(event):
e = AuditEvent(user=get_profile(), action=event)
e.save()
def get_session_user():
if "auth" not in session or not session["auth"]:
return None

Loading…
Cancel
Save