Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Django Admin -> Changes to replace Admin API #4473

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/offboarding.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ assignees: ''
- [ ] Remove from active Figma projects
- [ ] Remove from Mural
- [ ] Remove from Zendesk [here](https://fac-gov.zendesk.com/admin/people/team/members).
- [ ] Remove from the list of staff users in the Django Admin app [here](https://app.fac.gov/admin/users/staffuser/).
- [ ] Remove email from the list of Django Admin users in [staffusers.json](../../backend/config/staffusers.json).
- [ ] Check for and remove admin access in the FAC application: this may include designated permissions and/or checked-in API access ([for example](https://github.com/GSA-TTS/FAC/blob/fb0e7bdf1cb1807291e6b6eef068e97b4574078c/backend/support/api/admin_api_v1_1_0/create_access_tables.sql#L21))

## For GitHub contributors
Expand Down
5 changes: 4 additions & 1 deletion .github/ISSUE_TEMPLATE/onboarding.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ Note: If you're not able to do any of these yourself, you're still responsible f
- [ ] [Add as a form manager to the touchpoints recruitment intercept](https://touchpoints.app.cloud.gov/admin/forms/9412c559/permissions)

**For engineers, also...**
- [ ] Make sure you have a `login.gov` account and have logged into the FAC application at least once.
- [ ] Then, add your email to the `readonly` list in [staffusers.json](../../backend/config/staffusers.json).
- [ ] [Add as a member of the FAC group in New Relic](https://one.newrelic.com/admin-portal/organizations/users-list) (@GSA-TTS/fac-admins can do this)

**For product leads/owners, also...**
Expand All @@ -88,5 +90,6 @@ Note: If you're not able to do any of these yourself, you're still responsible f
- [ ] Also give them the `Maintainer` role in [the FAC-team team in GitHub](https://github.com/orgs/GSA-TTS/teams/fac-team/members).

**For helpdesk, also...**
- [ ] Add them to the list of staff users for [Django Admin](https://app.fac.gov/admin/users/staffuser/).
- [ ] Make sure you have a `login.gov` account and have logged into the FAC application at least once.
- [ ] Then, add your email to the `helpdesk` list in [staffusers.json](../../backend/config/staffusers.json).
- [ ] Give them access to the [Help Desk](https://fac-gov.zendesk.com/admin/people/team/members) as a team member.
21 changes: 21 additions & 0 deletions backend/config/staffusers.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"readonly": [
"[email protected]",
"[email protected]",
"[email protected]"
],
"helpdesk": [
"[email protected]",
"[email protected]",
"[email protected]",
"[email protected]",
"[email protected]",
"[email protected]",
"[email protected]",
"[email protected]",
"[email protected]"
],
"superuser": [
"[email protected]"
]
}
51 changes: 40 additions & 11 deletions backend/dissemination/admin.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from django.contrib import admin

from dissemination.models import (
AdditionalEin,
AdditionalUei,
Expand All @@ -11,7 +10,9 @@
Note,
Passthrough,
SecondaryAuditor,
TribalApiAccessKeyIds,
)
import datetime


class AdditionalEinAdmin(admin.ModelAdmin):
Expand All @@ -35,7 +36,7 @@ def has_view_permission(self, request, obj=None):
"additional_ein",
)

search_fields = ("report_id",)
search_fields = ("report_id__report_id", "additional_ein")


class AdditionalUeiAdmin(admin.ModelAdmin):
Expand All @@ -59,7 +60,7 @@ def has_view_permission(self, request, obj=None):
"additional_uei",
)

search_fields = ("report_id",)
search_fields = ("report_id__report_id", "additional_uei")


class CapTextAdmin(admin.ModelAdmin):
Expand All @@ -83,7 +84,7 @@ def has_view_permission(self, request, obj=None):
"finding_ref_number",
)

search_fields = ("report_id",)
search_fields = ("report_id__report_id", "finding_ref_number")


class FederalAwardAdmin(admin.ModelAdmin):
Expand All @@ -107,7 +108,10 @@ def has_view_permission(self, request, obj=None):
"award_reference",
)

search_fields = ("report_id",)
search_fields = (
"report_id__report_id",
"award_reference",
)


class FindingAdmin(admin.ModelAdmin):
Expand All @@ -132,7 +136,7 @@ def has_view_permission(self, request, obj=None):
"reference_number",
)

search_fields = ("report_id",)
search_fields = ("report_id__report_id", "award_reference", "reference_number")


class FindingTextAdmin(admin.ModelAdmin):
Expand All @@ -156,7 +160,7 @@ def has_view_permission(self, request, obj=None):
"finding_ref_number",
)

search_fields = ("report_id",)
search_fields = ("report_id__report_id", "finding_ref_number")


class GeneralAdmin(admin.ModelAdmin):
Expand All @@ -181,7 +185,7 @@ def has_view_permission(self, request, obj=None):
"date_created",
)

search_fields = ("report_id",)
search_fields = ("report_id", "auditee_name", "date_created")


class NoteAdmin(admin.ModelAdmin):
Expand All @@ -205,7 +209,7 @@ def has_view_permission(self, request, obj=None):
"note_title",
)

search_fields = ("report_id",)
search_fields = ("report_id__report_id", "note_title")


class PassThroughAdmin(admin.ModelAdmin):
Expand All @@ -230,7 +234,7 @@ def has_view_permission(self, request, obj=None):
"passthrough_id",
)

search_fields = ("report_id",)
search_fields = ("report_id__report_id", "award_reference", "passthrough_id")


class SecondaryAuditorAdmin(admin.ModelAdmin):
Expand All @@ -254,7 +258,31 @@ def has_view_permission(self, request, obj=None):
"auditor_ein",
)

search_fields = ("report_id",)
search_fields = ("report_id__report_id", "auditor_ein")


class TribalApiAccessKeyIdsAdmin(admin.ModelAdmin):

list_display = (
"email",
"key_id",
"date_added",
)

search_fields = (
"email",
"key_id",
)

fields = [
"email",
"key_id",
]

def save_model(self, request, obj, form, change):
obj.email = obj.email.lower()
obj.date_added = datetime.date.today()
super().save_model(request, obj, form, change)


admin.site.register(AdditionalEin, AdditionalEinAdmin)
Expand All @@ -267,3 +295,4 @@ def has_view_permission(self, request, obj=None):
admin.site.register(Note, NoteAdmin)
admin.site.register(Passthrough, PassThroughAdmin)
admin.site.register(SecondaryAuditor, SecondaryAuditorAdmin)
admin.site.register(TribalApiAccessKeyIds, TribalApiAccessKeyIdsAdmin)
5 changes: 5 additions & 0 deletions backend/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ gonogo "curation_audit_tracking_init"
seed_cog_baseline
gonogo "seed_cog_baseline"

#####
# CREATE STAFF USERS
# Prepares staff users for Django admin
python manage.py create_staffusers

#####
# LAUNCH THE APP
# We will have died long ago if things didn't work.
Expand Down
103 changes: 103 additions & 0 deletions backend/support/admin.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,25 @@
from django.contrib import admin
from django.contrib.admin.models import LogEntry, ADDITION, CHANGE, DELETION
from django.db.models.signals import post_save, post_delete
from django.dispatch import receiver

from audit.models import SingleAuditChecklist
from dissemination.models import TribalApiAccessKeyIds
from users.models import UserPermission
from .models import CognizantBaseline, CognizantAssignment, AssignmentTypeCode

import json
from datetime import date


class DateEncoder(json.JSONEncoder):
"""Encode date types in admin logs."""

def default(self, obj):
if isinstance(obj, date):
return obj.isoformat()
return super().default(obj)


class SupportAdmin(admin.ModelAdmin):
def has_module_permission(self, request, obj=None):
Expand Down Expand Up @@ -106,3 +123,89 @@ def has_change_permission(self, request, obj=None):

def has_add_permission(self, request, obj=None):
return request.user.is_staff


@admin.register(LogEntry)
class LogEntryAdmin(SupportAdmin):
"""
Displays the changelog for actions made from the Admin Panel.
"""

date_hierarchy = "action_time"
ordering = ["-action_time"]
list_display = [
"action_time",
"staff_user",
"record_affected",
"event",
"content",
]
search_fields = (
"action_time",
"user__email",
"object_repr",
"action_flag",
"change_message",
)

def staff_user(self, obj):
return obj.user.email

def record_affected(self, obj):
return obj.object_repr

def event(self, obj):
if obj.action_flag == ADDITION:
return "Created"
elif obj.action_flag == DELETION:
return "Deleted"
elif obj.action_flag == CHANGE:
res = "Updated"
if obj.change_message:
_json = json.loads(obj.change_message)[0]
if "changed" in _json:
res = "Updated\n"
for field in _json["changed"]["fields"]:
res += f"\n- {field}"
return res
return "-"

def content(self, obj):
if obj.change_message:
_json = json.loads(obj.change_message)[0]
if "content" in _json:
return _json["content"]
return "-"


@receiver([post_delete, post_save], sender=LogEntry)
def add_custom_field_to_log(sender, instance, created, **kwargs):
"""
Modify content of the log depending on what model(s) were changed.
"""

if created:
model_class = instance.content_type.model_class()
qset = model_class.objects.filter(pk=instance.object_id)
if qset.exists():
obj = qset.first()

# update content of record after save occurred.
change_message_json = json.loads(instance.change_message)

if model_class == UserPermission:
change_message_json[0]["content"] = list(
qset.values("email", "permission__slug")
)
elif model_class == TribalApiAccessKeyIds:
change_message_json[0]["content"] = list(qset.values("email", "key_id"))
else:
change_message_json[0]["content"] = list(qset.values("id"))

# record still exists.
if obj:
change_message_json[0]["id"] = obj.pk

# write changes to instance.
instance.change_message = json.dumps(change_message_json, cls=DateEncoder)
instance.save()
33 changes: 28 additions & 5 deletions backend/users/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,38 @@ class PermissionAdmin(admin.ModelAdmin):

@admin.register(User)
class UserAdmin(admin.ModelAdmin):
list_display = ["email", "can_read_tribal", "last_login", "date_joined"]
list_filter = ["is_staff", "is_superuser"]
exclude = ["groups", "user_permissions", "password"]
list_display = [
"email",
"can_read_tribal",
"last_login",
"date_joined",
"assigned_groups",
]
list_filter = ["is_staff", "is_superuser", "groups"]
exclude = ["user_permissions", "password"]
readonly_fields = ["date_joined", "last_login"]
search_fields = ("email", "username")

def can_read_tribal(self, obj):
return _can_read_tribal(obj)

def assigned_groups(self, obj):
return ", ".join([g.name for g in obj.groups.all()])


@admin.register(UserPermission)
class UserPermissionAdmin(admin.ModelAdmin):
list_display = ["user", "email", "permission"]
search_fields = ("email", "permission", "user")
fields = ["email", "permission"]

def save_model(self, request, obj, form, change):
obj.email = obj.email.lower()
try:
obj.user = User.objects.get(email=obj.email)
except User.DoesNotExist:
pass
super().save_model(request, obj, form, change)


@admin.register(StaffUserLog)
Expand All @@ -57,8 +75,7 @@ def has_delete_permission(self, request, obj=None):
class StaffUserAdmin(admin.ModelAdmin):
list_display = [
"staff_email",
"added_by_email",
"date_added",
"privilege",
]
fields = [
"staff_email",
Expand Down Expand Up @@ -91,3 +108,9 @@ def has_add_permission(self, request, obj=None):

def has_delete_permission(self, request, obj=None):
return request.user.is_superuser

def privilege(self, obj):
user = User.objects.get(email=obj.staff_email, is_staff=True)
if user.is_superuser:
return "Superuser"
return ", ".join([g.name for g in user.groups.all()])
Loading