all: implement black as code formatter
This commit is contained in:
@ -2,4 +2,4 @@
|
||||
|
||||
from passbook.lib.admin import admin_autoregister
|
||||
|
||||
admin_autoregister('passbook_audit')
|
||||
admin_autoregister("passbook_audit")
|
||||
|
||||
@ -11,7 +11,16 @@ class EventSerializer(ModelSerializer):
|
||||
class Meta:
|
||||
|
||||
model = Event
|
||||
fields = ['pk', 'user', 'action', 'date', 'app', 'context', 'request_ip', 'created', ]
|
||||
fields = [
|
||||
"pk",
|
||||
"user",
|
||||
"action",
|
||||
"date",
|
||||
"app",
|
||||
"context",
|
||||
"request_ip",
|
||||
"created",
|
||||
]
|
||||
|
||||
|
||||
class EventViewSet(ReadOnlyModelViewSet):
|
||||
|
||||
@ -7,10 +7,10 @@ from django.apps import AppConfig
|
||||
class PassbookAuditConfig(AppConfig):
|
||||
"""passbook audit app"""
|
||||
|
||||
name = 'passbook.audit'
|
||||
label = 'passbook_audit'
|
||||
verbose_name = 'passbook Audit'
|
||||
mountpoint = 'audit/'
|
||||
name = "passbook.audit"
|
||||
label = "passbook_audit"
|
||||
verbose_name = "passbook Audit"
|
||||
mountpoint = "audit/"
|
||||
|
||||
def ready(self):
|
||||
import_module('passbook.audit.signals')
|
||||
import_module("passbook.audit.signals")
|
||||
|
||||
@ -18,20 +18,55 @@ class Migration(migrations.Migration):
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='AuditEntry',
|
||||
name="AuditEntry",
|
||||
fields=[
|
||||
('uuid', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
|
||||
('action', models.TextField(choices=[('login', 'login'), ('login_failed', 'login_failed'), ('logout', 'logout'), ('authorize_application', 'authorize_application'), ('suspicious_request', 'suspicious_request'), ('sign_up', 'sign_up'), ('password_reset', 'password_reset'), ('invitation_created', 'invitation_created'), ('invitation_used', 'invitation_used')])),
|
||||
('date', models.DateTimeField(auto_now_add=True)),
|
||||
('app', models.TextField()),
|
||||
('context', django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=dict)),
|
||||
('request_ip', models.GenericIPAddressField()),
|
||||
('created', models.DateTimeField(auto_now_add=True)),
|
||||
('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)),
|
||||
(
|
||||
"uuid",
|
||||
models.UUIDField(
|
||||
default=uuid.uuid4,
|
||||
editable=False,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
),
|
||||
),
|
||||
(
|
||||
"action",
|
||||
models.TextField(
|
||||
choices=[
|
||||
("login", "login"),
|
||||
("login_failed", "login_failed"),
|
||||
("logout", "logout"),
|
||||
("authorize_application", "authorize_application"),
|
||||
("suspicious_request", "suspicious_request"),
|
||||
("sign_up", "sign_up"),
|
||||
("password_reset", "password_reset"),
|
||||
("invitation_created", "invitation_created"),
|
||||
("invitation_used", "invitation_used"),
|
||||
]
|
||||
),
|
||||
),
|
||||
("date", models.DateTimeField(auto_now_add=True)),
|
||||
("app", models.TextField()),
|
||||
(
|
||||
"context",
|
||||
django.contrib.postgres.fields.jsonb.JSONField(
|
||||
blank=True, default=dict
|
||||
),
|
||||
),
|
||||
("request_ip", models.GenericIPAddressField()),
|
||||
("created", models.DateTimeField(auto_now_add=True)),
|
||||
(
|
||||
"user",
|
||||
models.ForeignKey(
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.SET_NULL,
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Audit Entry',
|
||||
'verbose_name_plural': 'Audit Entries',
|
||||
"verbose_name": "Audit Entry",
|
||||
"verbose_name_plural": "Audit Entries",
|
||||
},
|
||||
),
|
||||
]
|
||||
|
||||
@ -8,12 +8,9 @@ class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('passbook_audit', '0001_initial'),
|
||||
("passbook_audit", "0001_initial"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameModel(
|
||||
old_name='AuditEntry',
|
||||
new_name='Event',
|
||||
),
|
||||
migrations.RenameModel(old_name="AuditEntry", new_name="Event",),
|
||||
]
|
||||
|
||||
@ -8,17 +8,33 @@ import passbook.audit.models
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('passbook_audit', '0002_auto_20191028_0829'),
|
||||
("passbook_audit", "0002_auto_20191028_0829"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='event',
|
||||
options={'verbose_name': 'Audit Event', 'verbose_name_plural': 'Audit Events'},
|
||||
name="event",
|
||||
options={
|
||||
"verbose_name": "Audit Event",
|
||||
"verbose_name_plural": "Audit Events",
|
||||
},
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='event',
|
||||
name='action',
|
||||
field=models.TextField(choices=[('LOGIN', 'login'), ('LOGIN_FAILED', 'login_failed'), ('LOGOUT', 'logout'), ('AUTHORIZE_APPLICATION', 'authorize_application'), ('SUSPICIOUS_REQUEST', 'suspicious_request'), ('SIGN_UP', 'sign_up'), ('PASSWORD_RESET', 'password_reset'), ('INVITE_CREATED', 'invitation_created'), ('INVITE_USED', 'invitation_used'), ('CUSTOM', 'custom')]),
|
||||
model_name="event",
|
||||
name="action",
|
||||
field=models.TextField(
|
||||
choices=[
|
||||
("LOGIN", "login"),
|
||||
("LOGIN_FAILED", "login_failed"),
|
||||
("LOGOUT", "logout"),
|
||||
("AUTHORIZE_APPLICATION", "authorize_application"),
|
||||
("SUSPICIOUS_REQUEST", "suspicious_request"),
|
||||
("SIGN_UP", "sign_up"),
|
||||
("PASSWORD_RESET", "password_reset"),
|
||||
("INVITE_CREATED", "invitation_created"),
|
||||
("INVITE_USED", "invitation_used"),
|
||||
("CUSTOM", "custom"),
|
||||
]
|
||||
),
|
||||
),
|
||||
]
|
||||
|
||||
@ -6,17 +6,14 @@ from django.db import migrations, models
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('passbook_audit', '0003_auto_20191205_1407'),
|
||||
("passbook_audit", "0003_auto_20191205_1407"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='event',
|
||||
name='request_ip',
|
||||
),
|
||||
migrations.RemoveField(model_name="event", name="request_ip",),
|
||||
migrations.AddField(
|
||||
model_name='event',
|
||||
name='client_ip',
|
||||
model_name="event",
|
||||
name="client_ip",
|
||||
field=models.GenericIPAddressField(null=True),
|
||||
),
|
||||
]
|
||||
|
||||
@ -18,19 +18,20 @@ from passbook.lib.utils.http import get_client_ip
|
||||
|
||||
LOGGER = get_logger()
|
||||
|
||||
|
||||
class EventAction(Enum):
|
||||
"""All possible actions to save into the audit log"""
|
||||
|
||||
LOGIN = 'login'
|
||||
LOGIN_FAILED = 'login_failed'
|
||||
LOGOUT = 'logout'
|
||||
AUTHORIZE_APPLICATION = 'authorize_application'
|
||||
SUSPICIOUS_REQUEST = 'suspicious_request'
|
||||
SIGN_UP = 'sign_up'
|
||||
PASSWORD_RESET = 'password_reset' # noqa # nosec
|
||||
INVITE_CREATED = 'invitation_created'
|
||||
INVITE_USED = 'invitation_used'
|
||||
CUSTOM = 'custom'
|
||||
LOGIN = "login"
|
||||
LOGIN_FAILED = "login_failed"
|
||||
LOGOUT = "logout"
|
||||
AUTHORIZE_APPLICATION = "authorize_application"
|
||||
SUSPICIOUS_REQUEST = "suspicious_request"
|
||||
SIGN_UP = "sign_up"
|
||||
PASSWORD_RESET = "password_reset" # noqa # nosec
|
||||
INVITE_CREATED = "invitation_created"
|
||||
INVITE_USED = "invitation_used"
|
||||
CUSTOM = "custom"
|
||||
|
||||
@staticmethod
|
||||
def as_choices():
|
||||
@ -41,7 +42,9 @@ class EventAction(Enum):
|
||||
class Event(UUIDModel):
|
||||
"""An individual audit log event"""
|
||||
|
||||
user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, on_delete=models.SET_NULL)
|
||||
user = models.ForeignKey(
|
||||
settings.AUTH_USER_MODEL, null=True, on_delete=models.SET_NULL
|
||||
)
|
||||
action = models.TextField(choices=EventAction.as_choices())
|
||||
date = models.DateTimeField(auto_now_add=True)
|
||||
app = models.TextField()
|
||||
@ -56,28 +59,30 @@ class Event(UUIDModel):
|
||||
return request.resolver_match.app_name
|
||||
|
||||
@staticmethod
|
||||
def new(action: EventAction,
|
||||
app: Optional[str] = None,
|
||||
_inspect_offset: int = 1,
|
||||
**kwargs) -> 'Event':
|
||||
def new(
|
||||
action: EventAction,
|
||||
app: Optional[str] = None,
|
||||
_inspect_offset: int = 1,
|
||||
**kwargs,
|
||||
) -> "Event":
|
||||
"""Create new Event instance from arguments. Instance is NOT saved."""
|
||||
if not isinstance(action, EventAction):
|
||||
raise ValueError(f"action must be EventAction instance but was {type(action)}")
|
||||
raise ValueError(
|
||||
f"action must be EventAction instance but was {type(action)}"
|
||||
)
|
||||
if not app:
|
||||
app = getmodule(stack()[_inspect_offset][0]).__name__
|
||||
event = Event(
|
||||
action=action.value,
|
||||
app=app,
|
||||
context=kwargs)
|
||||
event = Event(action=action.value, app=app, context=kwargs)
|
||||
LOGGER.debug("Created Audit event", action=action, context=kwargs)
|
||||
return event
|
||||
|
||||
def from_http(self, request: HttpRequest,
|
||||
user: Optional[settings.AUTH_USER_MODEL] = None) -> 'Event':
|
||||
def from_http(
|
||||
self, request: HttpRequest, user: Optional[settings.AUTH_USER_MODEL] = None
|
||||
) -> "Event":
|
||||
"""Add data from a Django-HttpRequest, allowing the creation of
|
||||
Events independently from requests.
|
||||
`user` arguments optionally overrides user from requests."""
|
||||
if hasattr(request, 'user'):
|
||||
if hasattr(request, "user"):
|
||||
if isinstance(request.user, AnonymousUser):
|
||||
self.user = get_anonymous_user()
|
||||
else:
|
||||
@ -85,7 +90,7 @@ class Event(UUIDModel):
|
||||
if user:
|
||||
self.user = user
|
||||
# User 255.255.255.255 as fallback if IP cannot be determined
|
||||
self.client_ip = get_client_ip(request) or '255.255.255.255'
|
||||
self.client_ip = get_client_ip(request) or "255.255.255.255"
|
||||
# If there's no app set, we get it from the requests too
|
||||
if not self.app:
|
||||
self.app = Event._get_app_from_request(request)
|
||||
@ -94,10 +99,12 @@ class Event(UUIDModel):
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
if not self._state.adding:
|
||||
raise ValidationError("you may not edit an existing %s" % self._meta.model_name)
|
||||
raise ValidationError(
|
||||
"you may not edit an existing %s" % self._meta.model_name
|
||||
)
|
||||
return super().save(*args, **kwargs)
|
||||
|
||||
class Meta:
|
||||
|
||||
verbose_name = _('Audit Event')
|
||||
verbose_name_plural = _('Audit Events')
|
||||
verbose_name = _("Audit Event")
|
||||
verbose_name_plural = _("Audit Events")
|
||||
|
||||
@ -3,8 +3,7 @@ from django.contrib.auth.signals import user_logged_in, user_logged_out
|
||||
from django.dispatch import receiver
|
||||
|
||||
from passbook.audit.models import Event, EventAction
|
||||
from passbook.core.signals import (invitation_created, invitation_used,
|
||||
user_signed_up)
|
||||
from passbook.core.signals import invitation_created, invitation_used, user_signed_up
|
||||
|
||||
|
||||
@receiver(user_logged_in)
|
||||
@ -32,11 +31,15 @@ def on_user_signed_up(sender, request, user, **_):
|
||||
# pylint: disable=unused-argument
|
||||
def on_invitation_created(sender, request, invitation, **_):
|
||||
"""Log Invitation creation"""
|
||||
Event.new(EventAction.INVITE_CREATED, invitation_uuid=invitation.uuid.hex).from_http(request)
|
||||
Event.new(
|
||||
EventAction.INVITE_CREATED, invitation_uuid=invitation.uuid.hex
|
||||
).from_http(request)
|
||||
|
||||
|
||||
@receiver(invitation_used)
|
||||
# pylint: disable=unused-argument
|
||||
def on_invitation_used(sender, request, invitation, **_):
|
||||
"""Log Invitation usage"""
|
||||
Event.new(EventAction.INVITE_USED, invitation_uuid=invitation.uuid.hex).from_http(request)
|
||||
Event.new(EventAction.INVITE_USED, invitation_uuid=invitation.uuid.hex).from_http(
|
||||
request
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user