Merge branch 'audit-log-update' into 'master'

Add datetime to Audit Log entries.

Closes #1134

See merge request allianceauth/allianceauth!1115
This commit is contained in:
Basraah 2019-03-12 09:53:43 +00:00
commit 4ea824fe71
7 changed files with 83 additions and 29 deletions

View File

@ -0,0 +1,19 @@
# Generated by Django 2.0.8 on 2018-12-07 08:56
import datetime
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('groupmanagement', '0010_authgroup_states'),
]
operations = [
migrations.AddField(
model_name='requestlog',
name='date',
field=models.DateTimeField(default=datetime.datetime(2018, 12, 7, 8, 56, 33, 846342)),
),
]

View File

@ -4,6 +4,7 @@ from django.db import models
from django.db.models.signals import post_save from django.db.models.signals import post_save
from django.dispatch import receiver from django.dispatch import receiver
from allianceauth.authentication.models import State from allianceauth.authentication.models import State
from datetime import datetime
class GroupRequest(models.Model): class GroupRequest(models.Model):
@ -30,6 +31,7 @@ class RequestLog(models.Model):
request_info = models.CharField(max_length=254) request_info = models.CharField(max_length=254)
action = models.BooleanField(default=0) action = models.BooleanField(default=0)
request_actor = models.ForeignKey(User, on_delete=models.CASCADE) request_actor = models.ForeignKey(User, on_delete=models.CASCADE)
date = models.DateTimeField(auto_now_add=datetime.utcnow())
def requestor(self): def requestor(self):
return self.request_info.split(":")[0] return self.request_info.split(":")[0]

View File

@ -3,38 +3,60 @@
{% load i18n %} {% load i18n %}
{% block page_title %}{{ group }} {% trans "Audit Log" %}{% endblock page_title %} {% block page_title %}{{ group }} {% trans "Audit Log" %}{% endblock page_title %}
{% block extra_css %}{% endblock extra_css %}
{% block content %} {% block content %}
<div class="col-lg-12"> <div class="col-lg-12">
<br> <br>
{% include 'groupmanagement/menu.html' %} {% include 'groupmanagement/menu.html' %}
<div> <div>
{% if entries %}
<h3>{{ group }} Audit Log</h3> <h3>{{ group }} Audit Log</h3>
<table class="table"> <p> All times displayed are EVE/UTC.</p>
<tr> {% if entries %}
<th class="text-center">{% trans "Requestor" %}</th> <div class="table-responsive">
<th class="text-center">{% trans "Main Character" %}</th> <table class="table table-striped" id="log-entries">
<th class="text-center">{% trans "Group" %}</th> <thead>
<th class="text-center">{% trans "Type" %}</th> <th class="text-center" scope="col">{% trans "Date/Time" %}</th>
<th class="text-center">{% trans "Action" %}</th> <th class="text-center" scope="col">{% trans "Requestor" %}</th>
<th class="text-center">{% trans "Actor" %}</th> <th class="text-center" scope="col">{% trans "Main Character" %}</th>
</tr> <th class="text-center" scope="col">{% trans "Group" %}</th>
<th class="text-center" scope="col">{% trans "Type" %}</th>
<th class="text-center" scope="col">{% trans "Action" %}</th>
<th class="text-center" scope="col">{% trans "Actor" %}</th>
</thead>
<tbody>
{% for entry in entries %} {% for entry in entries %}
<tr> <tr>
<td class="text-center">{{ entry.date }}</td>
<td class="text-center">{{ entry.requestor }}</td> <td class="text-center">{{ entry.requestor }}</td>
<td class="text-center">{{ entry.req_char }}</td> <td class="text-center">{{ entry.req_char }}</td>
<td class="text-center">{{ entry.group }}</td> <td class="text-center">{{ entry.group }}</td>
<td class="text-center">{{ entry.type_to_str }}</td> <td class="text-center">{{ entry.type_to_str }}</td>
{% if entry.request_type is None %}
<td class="text-center"> Removed</td>
{% else %}
<td class="text-center">{{ entry.action_to_str }}</td> <td class="text-center">{{ entry.action_to_str }}</td>
{% endif %}
<td class="text-center">{{ entry.request_actor }}</td> <td class="text-center">{{ entry.request_actor }}</td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody>
</table> </table>
</div>
{% else %} {% else %}
<div class="alert alert-warning text-center">{% trans "No entries found." %}</div> <div class="alert alert-warning text-center">{% trans "No entries found for this group." %}</div>
{% endif %} {% endif %}
</div> </div>
</div> </div>
{% endblock content %} {% endblock %}
{% block extra_javascript %}
{% include 'bundles/datatables-js.html' %}
{% endblock %}
{% block extra_css %}
{% include 'bundles/datatables-css.html' %}
{% endblock %}
{% block extra_script %}
$(document).ready(function(){
$('#log-entries').DataTable();
});
{% endblock %}

View File

@ -12,7 +12,7 @@ urlpatterns = [
name='membership'), name='membership'),
url(r'^membership/(\w+)/$', views.group_membership_list, url(r'^membership/(\w+)/$', views.group_membership_list,
name='membership_list'), name='membership_list'),
url(r'^membership/(\w+)/audit/', views.group_membership_audit, name="audit_log"), url(r'^membership/(\w+)/audit/$', views.group_membership_audit, name="audit_log"),
url(r'^membership/(\w+)/remove/(\w+)/$', views.group_membership_remove, url(r'^membership/(\w+)/remove/(\w+)/$', views.group_membership_remove,
name='membership_remove'), name='membership_remove'),
url(r'^request_add/(\w+)', views.group_request_add, url(r'^request_add/(\w+)', views.group_request_add,

View File

@ -5,6 +5,7 @@ from django.contrib.auth.decorators import login_required
from django.contrib.auth.decorators import user_passes_test from django.contrib.auth.decorators import user_passes_test
from django.contrib.auth.models import Group from django.contrib.auth.models import Group
from django.core.exceptions import ObjectDoesNotExist, PermissionDenied from django.core.exceptions import ObjectDoesNotExist, PermissionDenied
from django.core.paginator import Paginator, EmptyPage
from django.db.models import Count from django.db.models import Count
from django.http import Http404 from django.http import Http404
from django.shortcuts import render, redirect, get_object_or_404 from django.shortcuts import render, redirect, get_object_or_404
@ -83,10 +84,9 @@ def group_membership_audit(request, group_id):
except ObjectDoesNotExist: except ObjectDoesNotExist:
raise Http404("Group does not exist") raise Http404("Group does not exist")
render_items = {'group': group.name}
entries = RequestLog.objects.filter(group=group) entries = RequestLog.objects.filter(group=group).order_by('-date')
render_items['entries'] = entries
render_items = {'entries': entries, 'group': group.name}
return render(request, 'groupmanagement/audit.html', context=render_items) return render(request, 'groupmanagement/audit.html', context=render_items)

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

View File

@ -66,6 +66,17 @@ Clicking on the blue eye will take you to the group member management screen. He
![Group overview](/_static/images/features/group-member-management.png) ![Group overview](/_static/images/features/group-member-management.png)
### Group Audit Log
Whenever a user Joins, Leaves, or is Removed from a group, this is logged. To find the audit log for a given group, click the light-blue button to the right of the Group Member Management (blue eye) button.
These logs contain the Date and Time the action was taken (in EVE/UTC), the user which submitted the request being acted upon (requestor), the user's main character, the type of request (join, leave or removed), the action taken (accept, reject or remove), and the user that took the action (actor).
![Audit Log Example](/_static/images/features/group_audit_log.png)
```eval_rst
.. note::
There is no tracking for "Open" groups as members are able to freely join/leave these groups.
```
## Group Leaders ## Group Leaders