Skip to content

Instantly share code, notes, and snippets.

@shacker
Last active April 11, 2017 06:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shacker/05bc1de527a2d7412de361ac659aecde to your computer and use it in GitHub Desktop.
Save shacker/05bc1de527a2d7412de361ac659aecde to your computer and use it in GitHub Desktop.
ORM Logging boilerplate
from dirapp.models import Log
from django.contrib import admin
class LogAdmin(admin.ModelAdmin):
search_fields = ['user__username', 'action']
list_display = ('user', 'anon_username', 'action', 'target', 'status', 'ip_addr', 'timestamp',)
list_filter = ['target', 'status']
admin.site.register(Log, LogAdmin)
from django.contrib.auth.models import User
from django.db import models
class Log(models.Model):
'''
Keep track of every action that changes data anywhere.
All activities are associated with the person who executed them.
However, some activities are done by unauthenticated users (Activate Account, Forgot Passphrase),
so we can't always FK to the user (since they don't exist in our Users table).
For those actions, we'll use a shared "anon" User record, but will also store the username
that was acted upon in a separate field.
'''
TARGET_CHOICES = (
(u'L', u'LDAP'),
(u'G', u'Google'),
(u'W', u'Workday'),
)
STATUS_CHOICES = (
(u'S', u'Success'),
(u'F', u'Failure'),
(u'I', u'Info'),
)
user = models.ForeignKey(User)
anon_username = models.CharField(blank=True, max_length=50)
action = models.CharField(max_length=255, help_text="")
target = models.CharField(max_length=1, choices=TARGET_CHOICES, blank=True)
status = models.CharField(max_length=1, choices=STATUS_CHOICES, default="S")
ip_addr = models.GenericIPAddressField(blank=True, null=True)
timestamp = models.DateTimeField(auto_now_add=True)
def __unicode__(self):
if self.user.username == "anon":
user = self.anon_username
else:
user = self.user
return "{d}: {a} in {t} (by {u})".format(
d="{:%m/%d/%y %I:%M %p}".format(self.timestamp),
u=user,
a=self.action,
t=self.get_target_display()
)
from myapp.models import Log
def log_action(request, user=None, anon_username='', action='', target='', ip_addr='', status='S'):
'''
Write a log line for every action that alters data.
Takes either a User object or an anonymous username,
an "action" string and a target system specified as "L", "G" or "W"
(see choices in the model). Default status is "Success" - pass in status: "F"
or status: "I" for failure or info.
'''
# Handle anonymous log entries - attach to 'anon' user, creating if it doesn't exist
# Django considers a non-auth user here `is_anonymous()`.
if not user or user.is_anonymous():
user, created = User.objects.get_or_create(username='anon')
ip_addr = get_client_ip(request)
Log.objects.create(
user=user, anon_username=anon_username, action=action,
target=target, ip_addr=ip_addr, status=status)
from myapp.utils import log_action
# invoke in the context of views like:
success_msg = "{u} successfully created LDAP account".format(u=request.user)
log_action(request, anon_username=username, target="L", status="S", action=success_msg)
# or
failure_msg = "{u} failed to create GMail account".format(u=request.user)
log_action(request, anon_username=username, target="G", status="F", action=failure_msg)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment