Skip to content

Commit

Permalink
feat(projectHistoryLogs): record logs for cloned permissions TASK-944 (
Browse files Browse the repository at this point in the history
…#5302)

### 📣 Summary
Record logs when permissions are cloned from one project to another.


### 👀 Preview steps


Feature/no-change template:
1. ℹ️ have an account and at least 2 projects
2. From a terminal, run
```
curl -X PATCH -H 'Authorization: Token <your token>' -H 'Content-type: application/json' localhost/api/v2/assets/<project_1_uid>/permission_assignments/clone/ -d '{"clone_from": "<project_2_uid>"}'
```
4. Go to
`localhost/api/v2/audit-logs/?](http://localhost/api/v2/audit-logs/?q=log_type:project-history
AND metadata__asset_uid:<project_1_uid>&format=json
5. 🟢 There should be a new project history log that looks like
```
app_label:	"kpi",
model_name:	"asset",
user:	"http://localhost/api/v2/users/<user>/?format=json",
user_uid:	"<user_uid>",
username:	"<username>",
action:	"clone-permissions",
metadata: {	
    source:	"curl (Other)"
    asset_uid:	"<project_1_uid>"
    ip_address:	"172.18.0.1"
    cloned_from:	"<project_2_uid>"
    log_subtype:	"permission"
},
date_created:	"2024-12-02T15:21:20Z",
log_type:	"project-history",
```

### 💭 Notes
Uses the AuditLoggedModelViewSet base class
  • Loading branch information
rgraber authored Dec 3, 2024
1 parent f07c031 commit 7acd5aa
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 0 deletions.
1 change: 1 addition & 0 deletions kobo/apps/audit_log/audit_actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ class AuditAction(models.TextChoices):
ALLOW_ANONYMOUS_SUBMISSIONS = 'allow-anonymous-submissions'
ARCHIVE = 'archive'
AUTH = 'auth'
CLONE_PERMISSIONS = 'clone-permissions'
CONNECT_PROJECT = 'connect-project'
CREATE = 'create'
DELETE = 'delete'
Expand Down
22 changes: 22 additions & 0 deletions kobo/apps/audit_log/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
ACCESS_LOG_SUBMISSION_AUTH_TYPE,
ACCESS_LOG_SUBMISSION_GROUP_AUTH_TYPE,
ACCESS_LOG_UNKNOWN_AUTH_TYPE,
CLONE_ARG_NAME,
PERM_ADD_SUBMISSIONS,
PERM_VIEW_ASSET,
PERM_VIEW_SUBMISSIONS,
Expand Down Expand Up @@ -354,6 +355,7 @@ def create_from_request(cls, request):
'asset-permission-assignment-bulk-assignments': cls.create_from_permissions_request, # noqa
'asset-permission-assignment-detail': cls.create_from_permissions_request,
'asset-permission-assignment-list': cls.create_from_permissions_request,
'asset-permission-assignment-clone': cls.handle_cloned_permissions,
}
url_name = request.resolver_match.url_name
method = url_name_to_action.get(url_name, None)
Expand Down Expand Up @@ -801,3 +803,23 @@ def handle_anonymous_user_permissions(
action=AuditAction.MODIFY_USER_PERMISSIONS,
)
)

@classmethod
def handle_cloned_permissions(cls, request):
initial_data = getattr(request, 'initial_data', None)
if initial_data is None:
return
asset_uid = request.resolver_match.kwargs['parent_lookup_asset']
asset_id = initial_data['asset.id']
ProjectHistoryLog.objects.create(
object_id=asset_id,
action=AuditAction.CLONE_PERMISSIONS,
user=request.user,
metadata={
'asset_uid': asset_uid,
'log_subtype': PROJECT_HISTORY_LOG_PERMISSION_SUBTYPE,
'ip_address': get_client_ip(request),
'source': get_human_readable_client_user_agent(request),
'cloned_from': request._data[CLONE_ARG_NAME],
},
)
15 changes: 15 additions & 0 deletions kobo/apps/audit_log/tests/test_project_history_logs.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from kobo.apps.hook.models import Hook
from kobo.apps.kobo_auth.shortcuts import User
from kpi.constants import (
CLONE_ARG_NAME,
PERM_ADD_SUBMISSIONS,
PERM_CHANGE_SUBMISSIONS,
PERM_PARTIAL_SUBMISSIONS,
Expand Down Expand Up @@ -1287,3 +1288,17 @@ def test_no_logs_if_bulk_request_fails(self):
format='json',
)
self.assertEqual(ProjectHistoryLog.objects.count(), 0)

def test_clone_permissions_creates_logs(self):
second_asset = Asset.objects.get(pk=2)
log_metadata = self._base_project_history_log_test(
method=self.client.patch,
url=reverse(
'api_v2:asset-permission-assignment-clone',
kwargs={'parent_lookup_asset': self.asset.uid},
),
request_data={CLONE_ARG_NAME: second_asset.uid},
expected_action=AuditAction.CLONE_PERMISSIONS,
expected_subtype=PROJECT_HISTORY_LOG_PERMISSION_SUBTYPE,
)
self.assertEqual(log_metadata['cloned_from'], second_asset.uid)
1 change: 1 addition & 0 deletions kpi/views/v2/asset_permission_assignment.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ def clone(self, request, *args, **kwargs):
source_asset_uid = self.request.data[CLONE_ARG_NAME]
source_asset = get_object_or_404(Asset, uid=source_asset_uid)
user = request.user
request._request.initial_data = {'asset.id': self.asset.id}

if user.has_perm(PERM_MANAGE_ASSET, self.asset) and user.has_perm(
PERM_VIEW_ASSET, source_asset
Expand Down

0 comments on commit 7acd5aa

Please sign in to comment.