From 402aefe5f6c55ee7f10eae9ee526032b054ea8e9 Mon Sep 17 00:00:00 2001 From: David Christofas Date: Mon, 20 Jun 2022 17:25:25 +0200 Subject: [PATCH] add acting user to the audit log --- changelog/unreleased/audit-service.md | 6 ++ extensions/audit/pkg/service/service_test.go | 94 +++++++++++--------- extensions/audit/pkg/types/constants.go | 90 ++++++++++--------- extensions/audit/pkg/types/conversion.go | 50 +++++------ extensions/graph/pkg/service/v0/groups.go | 13 ++- extensions/graph/pkg/service/v0/password.go | 7 +- extensions/graph/pkg/service/v0/users.go | 13 ++- 7 files changed, 154 insertions(+), 119 deletions(-) create mode 100644 changelog/unreleased/audit-service.md diff --git a/changelog/unreleased/audit-service.md b/changelog/unreleased/audit-service.md new file mode 100644 index 0000000000..f49d02eabb --- /dev/null +++ b/changelog/unreleased/audit-service.md @@ -0,0 +1,6 @@ +Enhancement: add acting user to the audit log + +Added the acting user to the events in the audit log. + +https://github.com/owncloud/ocis/issues/3753 +https://github.com/owncloud/ocis/pull/3992 diff --git a/extensions/audit/pkg/service/service_test.go b/extensions/audit/pkg/service/service_test.go index 5de097bedf..ae64f43a2c 100644 --- a/extensions/audit/pkg/service/service_test.go +++ b/extensions/audit/pkg/service/service_test.go @@ -162,6 +162,7 @@ var testCases = []struct { }, { Alias: "LinkRemoved - id", SystemEvent: events.LinkRemoved{ + Executant: userID("sharing-userid"), ShareID: linkID("shareid"), ShareToken: "", }, @@ -170,9 +171,9 @@ var testCases = []struct { require.NoError(t, json.Unmarshal(b, &ev)) // AuditEvent fields - checkBaseAuditEvent(t, ev.AuditEvent, "", "", "public link id:'shareid' was removed", "file_unshared") + checkBaseAuditEvent(t, ev.AuditEvent, "sharing-userid", "", "user 'sharing-userid' removed public link with id:'shareid'", "file_unshared") // AuditEventSharing fields - checkSharingAuditEvent(t, ev.AuditEventSharing, "", "", "shareid") + checkSharingAuditEvent(t, ev.AuditEventSharing, "", "sharing-userid", "shareid") // AuditEventShareUpdated fields require.Equal(t, "", ev.ItemType) // not implemented atm require.Equal(t, "link", ev.ShareType) @@ -181,6 +182,7 @@ var testCases = []struct { }, { Alias: "LinkRemoved - token", SystemEvent: events.LinkRemoved{ + Executant: userID("sharing-userid"), ShareID: nil, ShareToken: "token-123", }, @@ -189,9 +191,9 @@ var testCases = []struct { require.NoError(t, json.Unmarshal(b, &ev)) // AuditEvent fields - checkBaseAuditEvent(t, ev.AuditEvent, "", "", "public link id:'token-123' was removed", "file_unshared") + checkBaseAuditEvent(t, ev.AuditEvent, "sharing-userid", "", "user 'sharing-userid' removed public link with id:'token-123'", "file_unshared") // AuditEventSharing fields - checkSharingAuditEvent(t, ev.AuditEventSharing, "", "", "token-123") + checkSharingAuditEvent(t, ev.AuditEventSharing, "", "sharing-userid", "token-123") // AuditEventShareUpdated fields require.Equal(t, "", ev.ItemType) // not implemented atm require.Equal(t, "link", ev.ShareType) @@ -297,51 +299,55 @@ var testCases = []struct { }, { Alias: "File created", SystemEvent: events.FileUploaded{ - Ref: reference("sto-123", "iid-123", "./item"), - Owner: userID("uid-123"), // NOTE: owner not yet implemented in reva + Executant: userID("uid-123"), + Ref: reference("sto-123", "iid-123", "./item"), + Owner: userID("uid-123"), // NOTE: owner not yet implemented in reva }, CheckAuditEvent: func(t *testing.T, b []byte) { ev := types.AuditEventFileCreated{} require.NoError(t, json.Unmarshal(b, &ev)) // AuditEvent fields - checkBaseAuditEvent(t, ev.AuditEvent, "uid-123", "", "File 'sto-123!iid-123/item' was created", "file_create") + checkBaseAuditEvent(t, ev.AuditEvent, "uid-123", "", "user 'uid-123' created file 'sto-123!iid-123/item'", "file_create") // AuditEventSharing fields checkFilesAuditEvent(t, ev.AuditEventFiles, "sto-123!iid-123/item", "uid-123", "./item") }, }, { Alias: "File read", SystemEvent: events.FileDownloaded{ - Ref: reference("sto-123", "iid-123", "./item"), - Owner: userID("uid-123"), // NOTE: owner not yet implemented in reva + Executant: userID("uid-123"), + Ref: reference("sto-123", "iid-123", "./item"), + Owner: userID("uid-123"), // NOTE: owner not yet implemented in reva }, CheckAuditEvent: func(t *testing.T, b []byte) { ev := types.AuditEventFileRead{} require.NoError(t, json.Unmarshal(b, &ev)) // AuditEvent fields - checkBaseAuditEvent(t, ev.AuditEvent, "uid-123", "", "File 'sto-123!iid-123/item' was read", "file_read") + checkBaseAuditEvent(t, ev.AuditEvent, "uid-123", "", "user 'uid-123' read file 'sto-123!iid-123/item'", "file_read") // AuditEventSharing fields checkFilesAuditEvent(t, ev.AuditEventFiles, "sto-123!iid-123/item", "uid-123", "./item") }, }, { Alias: "File trashed", SystemEvent: events.ItemTrashed{ - Ref: reference("sto-123", "iid-123", "./item"), - Owner: userID("uid-123"), // NOTE: owner not yet implemented in reva + Executant: userID("uid-123"), + Ref: reference("sto-123", "iid-123", "./item"), + Owner: userID("uid-123"), // NOTE: owner not yet implemented in reva }, CheckAuditEvent: func(t *testing.T, b []byte) { ev := types.AuditEventFileDeleted{} require.NoError(t, json.Unmarshal(b, &ev)) // AuditEvent fields - checkBaseAuditEvent(t, ev.AuditEvent, "uid-123", "", "File 'sto-123!iid-123/item' was trashed", "file_delete") + checkBaseAuditEvent(t, ev.AuditEvent, "uid-123", "", "user 'uid-123' trashed file 'sto-123!iid-123/item'", "file_delete") // AuditEventSharing fields checkFilesAuditEvent(t, ev.AuditEventFiles, "sto-123!iid-123/item", "uid-123", "./item") }, }, { Alias: "File renamed", SystemEvent: events.ItemMoved{ + Executant: userID("uid-123"), Ref: reference("sto-123", "iid-123", "./item"), OldReference: reference("sto-123", "iid-123", "./anotheritem"), Owner: userID("uid-123"), // NOTE: owner not yet implemented in reva @@ -351,7 +357,7 @@ var testCases = []struct { require.NoError(t, json.Unmarshal(b, &ev)) // AuditEvent fields - checkBaseAuditEvent(t, ev.AuditEvent, "uid-123", "", "File 'sto-123!iid-123/item' was moved from './anotheritem' to './item'", "file_rename") + checkBaseAuditEvent(t, ev.AuditEvent, "uid-123", "", "user 'uid-123' moved file 'sto-123!iid-123/item' from './anotheritem' to './item'", "file_rename") // AuditEventSharing fields checkFilesAuditEvent(t, ev.AuditEventFiles, "sto-123!iid-123/item", "uid-123", "./item") // AuditEventFileRenamed fields @@ -361,21 +367,23 @@ var testCases = []struct { }, { Alias: "File purged", SystemEvent: events.ItemPurged{ - Ref: reference("sto-123", "iid-123", "./item"), - Owner: userID("uid-123"), // NOTE: owner not yet implemented in reva + Executant: userID("uid-123"), + Ref: reference("sto-123", "iid-123", "./item"), + Owner: userID("uid-123"), // NOTE: owner not yet implemented in reva }, CheckAuditEvent: func(t *testing.T, b []byte) { ev := types.AuditEventFilePurged{} require.NoError(t, json.Unmarshal(b, &ev)) // AuditEvent fields - checkBaseAuditEvent(t, ev.AuditEvent, "uid-123", "", "File 'sto-123!iid-123/item' was removed from trashbin", "file_trash_delete") + checkBaseAuditEvent(t, ev.AuditEvent, "uid-123", "", "user 'uid-123' removed file 'sto-123!iid-123/item' from trashbin", "file_trash_delete") // AuditEventSharing fields checkFilesAuditEvent(t, ev.AuditEventFiles, "sto-123!iid-123/item", "uid-123", "./item") }, }, { Alias: "File restored", SystemEvent: events.ItemRestored{ + Executant: userID("uid-123"), Ref: reference("sto-123", "iid-123", "./item"), Owner: userID("uid-123"), // NOTE: owner not yet implemented in reva OldReference: reference("sto-123", "sto-123!iid-123/item", "./oldpath"), @@ -386,7 +394,7 @@ var testCases = []struct { require.NoError(t, json.Unmarshal(b, &ev)) // AuditEvent fields - checkBaseAuditEvent(t, ev.AuditEvent, "uid-123", "", "File 'sto-123!iid-123/item' was restored from trashbin to './item'", "file_trash_restore") + checkBaseAuditEvent(t, ev.AuditEvent, "uid-123", "", "user 'uid-123' restored file 'sto-123!iid-123/item' from trashbin to './item'", "file_trash_restore") // AuditEventSharing fields checkFilesAuditEvent(t, ev.AuditEventFiles, "sto-123!iid-123/item", "uid-123", "./item") // AuditEventFileRestored fields @@ -396,16 +404,17 @@ var testCases = []struct { }, { Alias: "File version restored", SystemEvent: events.FileVersionRestored{ - Ref: reference("sto-123", "iid-123", "./item"), - Owner: userID("uid-123"), // NOTE: owner not yet implemented in reva - Key: "v1", + Executant: userID("uid-123"), + Ref: reference("sto-123", "iid-123", "./item"), + Owner: userID("uid-123"), // NOTE: owner not yet implemented in reva + Key: "v1", }, CheckAuditEvent: func(t *testing.T, b []byte) { ev := types.AuditEventFileVersionRestored{} require.NoError(t, json.Unmarshal(b, &ev)) // AuditEvent fields - checkBaseAuditEvent(t, ev.AuditEvent, "uid-123", "", "File 'sto-123!iid-123/item' was restored in version 'v1'", "file_version_restore") + checkBaseAuditEvent(t, ev.AuditEvent, "uid-123", "", "user 'uid-123' restored file 'sto-123!iid-123/item' in version 'v1'", "file_version_restore") // AuditEventSharing fields checkFilesAuditEvent(t, ev.AuditEventFiles, "sto-123!iid-123/item", "uid-123", "./item") // AuditEventFileRestored fields @@ -415,20 +424,21 @@ var testCases = []struct { }, { Alias: "Space created", SystemEvent: events.SpaceCreated{ - ID: &provider.StorageSpaceId{OpaqueId: "space-123"}, - Owner: userID("uid-123"), - Root: resourceID("sto-123", "iid-123"), - Name: "test-space", - Type: "project", - Quota: nil, // Quota not interesting atm - MTime: timestamp(10e9), + Executant: userID("uid-123"), + ID: &provider.StorageSpaceId{OpaqueId: "space-123"}, + Owner: userID("uid-123"), + Root: resourceID("sto-123", "iid-123"), + Name: "test-space", + Type: "project", + Quota: nil, // Quota not interesting atm + MTime: timestamp(10e9), }, CheckAuditEvent: func(t *testing.T, b []byte) { ev := types.AuditEventSpaceCreated{} require.NoError(t, json.Unmarshal(b, &ev)) // AuditEvent fields - checkBaseAuditEvent(t, ev.AuditEvent, "", "2286-11-20T17:46:40Z", "Space 'space-123' with name 'test-space' was created", "space_created") + checkBaseAuditEvent(t, ev.AuditEvent, "", "2286-11-20T17:46:40Z", "user 'uid-123' created a space 'space-123' with name 'test-space'", "space_created") // AuditEventSpaces fields checkSpacesAuditEvent(t, ev.AuditEventSpaces, "space-123") // AuditEventFileRestored fields @@ -440,16 +450,17 @@ var testCases = []struct { }, { Alias: "Space renamed", SystemEvent: events.SpaceRenamed{ - ID: &provider.StorageSpaceId{OpaqueId: "space-123"}, - Owner: userID("uid-123"), - Name: "new-name", + Executant: userID("uid-123"), + ID: &provider.StorageSpaceId{OpaqueId: "space-123"}, + Owner: userID("uid-123"), + Name: "new-name", }, CheckAuditEvent: func(t *testing.T, b []byte) { ev := types.AuditEventSpaceRenamed{} require.NoError(t, json.Unmarshal(b, &ev)) // AuditEvent fields - checkBaseAuditEvent(t, ev.AuditEvent, "", "", "Space 'space-123' was renamed to 'new-name'", "space_renamed") + checkBaseAuditEvent(t, ev.AuditEvent, "", "", "user 'uid-123' renamed space 'space-123' to 'new-name'", "space_renamed") // AuditEventSpaces fields checkSpacesAuditEvent(t, ev.AuditEventSpaces, "space-123") // AuditEventSpaceRenamed fields @@ -458,42 +469,45 @@ var testCases = []struct { }, { Alias: "Space disabled", SystemEvent: events.SpaceDisabled{ - ID: &provider.StorageSpaceId{OpaqueId: "space-123"}, + Executant: userID("uid-123"), + ID: &provider.StorageSpaceId{OpaqueId: "space-123"}, }, CheckAuditEvent: func(t *testing.T, b []byte) { ev := types.AuditEventSpaceDisabled{} require.NoError(t, json.Unmarshal(b, &ev)) // AuditEvent fields - checkBaseAuditEvent(t, ev.AuditEvent, "", "", "Space 'space-123' was disabled", "space_disabled") + checkBaseAuditEvent(t, ev.AuditEvent, "", "", "user 'uid-123' disabled the space 'space-123'", "space_disabled") // AuditEventSpaces fields checkSpacesAuditEvent(t, ev.AuditEventSpaces, "space-123") }, }, { Alias: "Space enabled", SystemEvent: events.SpaceEnabled{ - ID: &provider.StorageSpaceId{OpaqueId: "space-123"}, + Executant: userID("uid-123"), + ID: &provider.StorageSpaceId{OpaqueId: "space-123"}, }, CheckAuditEvent: func(t *testing.T, b []byte) { ev := types.AuditEventSpaceEnabled{} require.NoError(t, json.Unmarshal(b, &ev)) // AuditEvent fields - checkBaseAuditEvent(t, ev.AuditEvent, "", "", "Space 'space-123' was (re-) enabled", "space_enabled") + checkBaseAuditEvent(t, ev.AuditEvent, "", "", "user 'uid-123' (re-) enabled the space 'space-123'", "space_enabled") // AuditEventSpaces fields checkSpacesAuditEvent(t, ev.AuditEventSpaces, "space-123") }, }, { Alias: "Space deleted", SystemEvent: events.SpaceDeleted{ - ID: &provider.StorageSpaceId{OpaqueId: "space-123"}, + Executant: userID("uid-123"), + ID: &provider.StorageSpaceId{OpaqueId: "space-123"}, }, CheckAuditEvent: func(t *testing.T, b []byte) { ev := types.AuditEventSpaceDeleted{} require.NoError(t, json.Unmarshal(b, &ev)) // AuditEvent fields - checkBaseAuditEvent(t, ev.AuditEvent, "", "", "Space 'space-123' was deleted", "space_deleted") + checkBaseAuditEvent(t, ev.AuditEvent, "", "", "user 'uid-123' deleted the space 'space-123'", "space_deleted") // AuditEventSpaces fields checkSpacesAuditEvent(t, ev.AuditEventSpaces, "space-123") }, diff --git a/extensions/audit/pkg/types/constants.go b/extensions/audit/pkg/types/constants.go index 69423d57db..29d9197242 100644 --- a/extensions/audit/pkg/types/constants.go +++ b/extensions/audit/pkg/types/constants.go @@ -75,8 +75,8 @@ func MessageShareRemoved(sharer, shareid, itemid string) string { } // MessageLinkRemoved returns the human readable string that describes the action -func MessageLinkRemoved(shareid string) string { - return fmt.Sprintf("public link id:'%s' was removed", shareid) +func MessageLinkRemoved(executant, shareid string) string { + return fmt.Sprintf("user '%s' removed public link with id:'%s'", executant, shareid) } // MessageShareAccepted returns the human readable string that describes the action @@ -95,87 +95,89 @@ func MessageLinkAccessed(linkid string, success bool) string { } // MessageContainerCreated returns the human readable string that describes the action -func MessageContainerCreated(item string) string { - return fmt.Sprintf("Folder '%s' was created", item) +func MessageContainerCreated(executant, item string) string { + return fmt.Sprintf("user '%s' created folder '%s'", executant, item) } // MessageFileCreated returns the human readable string that describes the action -func MessageFileCreated(item string) string { - return fmt.Sprintf("File '%s' was created", item) +func MessageFileCreated(executant, item string) string { + return fmt.Sprintf("user '%s' created file '%s'", executant, item) } // MessageFileRead returns the human readable string that describes the action -func MessageFileRead(item string) string { - return fmt.Sprintf("File '%s' was read", item) +func MessageFileRead(executant, item string) string { + return fmt.Sprintf("user '%s' read file '%s'", executant, item) } // MessageFileTrashed returns the human readable string that describes the action -func MessageFileTrashed(item string) string { - return fmt.Sprintf("File '%s' was trashed", item) +func MessageFileTrashed(executant, item string) string { + return fmt.Sprintf("user '%s' trashed file '%s'", executant, item) } // MessageFileRenamed returns the human readable string that describes the action -func MessageFileRenamed(item, oldpath, newpath string) string { - return fmt.Sprintf("File '%s' was moved from '%s' to '%s'", item, oldpath, newpath) +func MessageFileRenamed(executant, item, oldpath, newpath string) string { + return fmt.Sprintf("user '%s' moved file '%s' from '%s' to '%s'", executant, item, oldpath, newpath) } // MessageFilePurged returns the human readable string that describes the action -func MessageFilePurged(item string) string { - return fmt.Sprintf("File '%s' was removed from trashbin", item) +func MessageFilePurged(executant, item string) string { + return fmt.Sprintf("user '%s' removed file '%s' from trashbin", executant, item) } // MessageFileRestored returns the human readable string that describes the action -func MessageFileRestored(item, path string) string { - return fmt.Sprintf("File '%s' was restored from trashbin to '%s'", item, path) +func MessageFileRestored(executant, item, path string) string { + return fmt.Sprintf("user '%s' restored file '%s' from trashbin to '%s'", executant, item, path) } // MessageFileVersionRestored returns the human readable string that describes the action -func MessageFileVersionRestored(item string, version string) string { - return fmt.Sprintf("File '%s' was restored in version '%s'", item, version) +func MessageFileVersionRestored(executant, item, version string) string { + return fmt.Sprintf("user '%s' restored file '%s' in version '%s'", executant, item, version) } // MessageSpaceCreated returns the human readable string that describes the action -func MessageSpaceCreated(spaceID string, name string) string { - return fmt.Sprintf("Space '%s' with name '%s' was created", spaceID, name) +func MessageSpaceCreated(executant, spaceID, name string) string { + return fmt.Sprintf("user '%s' created a space '%s' with name '%s'", executant, spaceID, name) } // MessageSpaceRenamed returns the human readable string that describes the action -func MessageSpaceRenamed(spaceID string, name string) string { - return fmt.Sprintf("Space '%s' was renamed to '%s'", spaceID, name) +func MessageSpaceRenamed(executant, spaceID, name string) string { + return fmt.Sprintf("user '%s' renamed space '%s' to '%s'", executant, spaceID, name) } // MessageSpaceDisabled returns the human readable string that describes the action -func MessageSpaceDisabled(spaceID string) string { - return fmt.Sprintf("Space '%s' was disabled", spaceID) +func MessageSpaceDisabled(executant, spaceID string) string { + return fmt.Sprintf("user '%s' disabled the space '%s'", executant, spaceID) } // MessageSpaceEnabled returns the human readable string that describes the action -func MessageSpaceEnabled(spaceID string) string { - return fmt.Sprintf("Space '%s' was (re-) enabled", spaceID) +func MessageSpaceEnabled(executant, spaceID string) string { + return fmt.Sprintf("user '%s' (re-) enabled the space '%s'", executant, spaceID) } // MessageSpaceDeleted returns the human readable string that describes the action -func MessageSpaceDeleted(spaceID string) string { - return fmt.Sprintf("Space '%s' was deleted", spaceID) +func MessageSpaceDeleted(executant, spaceID string) string { + return fmt.Sprintf("user '%s' deleted the space '%s'", executant, spaceID) } // MessageUserCreated returns the human readable string that describes the action -func MessageUserCreated(userID string) string { - return fmt.Sprintf("User '%s' was created", userID) +func MessageUserCreated(executant, userID string) string { + return fmt.Sprintf("user '%s' created the user '%s'", executant, userID) } // MessageUserDeleted returns the human readable string that describes the action -func MessageUserDeleted(userID string) string { - return fmt.Sprintf("User '%s' was deleted", userID) +func MessageUserDeleted(executant, userID string) string { + return fmt.Sprintf("user '%s' deleted the user '%s'", executant, userID) } // MessageUserFeatureChanged returns the human readable string that describes the action -func MessageUserFeatureChanged(userID string, features []events.UserFeature) string { - // Result is: "User %username%'s feature changed: %featurename%=%featurevalue% %featurename%=%featurevalue%" +func MessageUserFeatureChanged(executant, userID string, features []events.UserFeature) string { + // Result is: "user '%executant%' changed user %username%'s features: %featurename%=%featurevalue% %featurename%=%featurevalue%" var sb strings.Builder - sb.WriteString("User ") + sb.WriteString("user '") + sb.WriteString(executant) + sb.WriteString("' changed user ") sb.WriteString(userID) - sb.WriteString("'s feature changed: ") + sb.WriteString("'s features:") for _, f := range features { sb.WriteString(f.Name) sb.WriteRune('=') @@ -186,21 +188,21 @@ func MessageUserFeatureChanged(userID string, features []events.UserFeature) str } // MessageGroupCreated returns the human readable string that describes the action -func MessageGroupCreated(groupID string) string { - return fmt.Sprintf("Group '%s' was created", groupID) +func MessageGroupCreated(executant, groupID string) string { + return fmt.Sprintf("user '%s' created group '%s'", executant, groupID) } // MessageGroupDeleted returns the human readable string that describes the action -func MessageGroupDeleted(groupID string) string { - return fmt.Sprintf("Group '%s' was deleted", groupID) +func MessageGroupDeleted(executant, groupID string) string { + return fmt.Sprintf("user '%s' deleted group '%s'", executant, groupID) } // MessageGroupMemberAdded returns the human readable string that describes the action -func MessageGroupMemberAdded(userID, groupID string) string { - return fmt.Sprintf("User '%s' was added to group '%s'", userID, groupID) +func MessageGroupMemberAdded(executant, userID, groupID string) string { + return fmt.Sprintf("user '%s' added user '%s' was added to group '%s'", executant, userID, groupID) } // MessageGroupMemberRemoved returns the human readable string that describes the action -func MessageGroupMemberRemoved(userID, groupID string) string { - return fmt.Sprintf("User '%s' was removed from group '%s'", userID, groupID) +func MessageGroupMemberRemoved(executant, userID, groupID string) string { + return fmt.Sprintf("user '%s' added user '%s' was removed from group '%s'", executant, userID, groupID) } diff --git a/extensions/audit/pkg/types/conversion.go b/extensions/audit/pkg/types/conversion.go index 862cf73f49..413bc212b4 100644 --- a/extensions/audit/pkg/types/conversion.go +++ b/extensions/audit/pkg/types/conversion.go @@ -48,12 +48,12 @@ func SharingAuditEvent(shareid string, fileid string, uid string, base AuditEven // ShareCreated converts a ShareCreated Event to an AuditEventShareCreated func ShareCreated(ev events.ShareCreated) AuditEventShareCreated { uid := ev.Sharer.OpaqueId - with, typ := extractGrantee(ev.GranteeUserID, ev.GranteeGroupID) - base := BasicAuditEvent(uid, formatTime(ev.CTime), MessageShareCreated(uid, ev.ItemID.OpaqueId, with), ActionShareCreated) + grantee, typ := extractGrantee(ev.GranteeUserID, ev.GranteeGroupID) + base := BasicAuditEvent(uid, formatTime(ev.CTime), MessageShareCreated(uid, ev.ItemID.OpaqueId, grantee), ActionShareCreated) return AuditEventShareCreated{ AuditEventSharing: SharingAuditEvent("", ev.ItemID.OpaqueId, uid, base), ShareOwner: uid, - ShareWith: with, + ShareWith: grantee, ShareType: typ, // NOTE: those values are not in the event and can therefore not be filled at the moment @@ -150,14 +150,14 @@ func ShareRemoved(ev events.ShareRemoved) AuditEventShareRemoved { // LinkRemoved converts a LinkRemoved event to an AuditEventShareRemoved func LinkRemoved(ev events.LinkRemoved) AuditEventShareRemoved { - uid, sid, typ := "", "", "link" + uid, sid, typ := ev.Executant.OpaqueId, "", "link" if ev.ShareID != nil { sid = ev.ShareID.GetOpaqueId() } else { sid = ev.ShareToken } - base := BasicAuditEvent(uid, "", MessageLinkRemoved(sid), ActionShareRemoved) + base := BasicAuditEvent(uid, "", MessageLinkRemoved(uid, sid), ActionShareRemoved) return AuditEventShareRemoved{ AuditEventSharing: SharingAuditEvent(sid, "", uid, base), ShareWith: "", @@ -235,7 +235,7 @@ func FilesAuditEvent(base AuditEvent, itemid, owner, path string) AuditEventFile // ContainerCreated converts a ContainerCreated event to an AuditEventContainerCreated func ContainerCreated(ev events.ContainerCreated) AuditEventContainerCreated { iid, path, uid := extractFileDetails(ev.Ref, ev.Owner) - base := BasicAuditEvent(uid, "", MessageContainerCreated(iid), ActionContainerCreated) + base := BasicAuditEvent(uid, "", MessageContainerCreated(ev.Executant.OpaqueId, iid), ActionContainerCreated) return AuditEventContainerCreated{ AuditEventFiles: FilesAuditEvent(base, iid, uid, path), } @@ -244,7 +244,7 @@ func ContainerCreated(ev events.ContainerCreated) AuditEventContainerCreated { // FileUploaded converts a FileUploaded event to an AuditEventFileCreated func FileUploaded(ev events.FileUploaded) AuditEventFileCreated { iid, path, uid := extractFileDetails(ev.Ref, ev.Owner) - base := BasicAuditEvent(uid, "", MessageFileCreated(iid), ActionFileCreated) + base := BasicAuditEvent(uid, "", MessageFileCreated(ev.Executant.OpaqueId, iid), ActionFileCreated) return AuditEventFileCreated{ AuditEventFiles: FilesAuditEvent(base, iid, uid, path), } @@ -253,7 +253,7 @@ func FileUploaded(ev events.FileUploaded) AuditEventFileCreated { // FileDownloaded converts a FileDownloaded event to an AuditEventFileRead func FileDownloaded(ev events.FileDownloaded) AuditEventFileRead { iid, path, uid := extractFileDetails(ev.Ref, ev.Owner) - base := BasicAuditEvent(uid, "", MessageFileRead(iid), ActionFileRead) + base := BasicAuditEvent(uid, "", MessageFileRead(ev.Executant.OpaqueId, iid), ActionFileRead) return AuditEventFileRead{ AuditEventFiles: FilesAuditEvent(base, iid, uid, path), } @@ -268,7 +268,7 @@ func ItemMoved(ev events.ItemMoved) AuditEventFileRenamed { oldpath = ev.OldReference.GetPath() } - base := BasicAuditEvent(uid, "", MessageFileRenamed(iid, oldpath, path), ActionFileRenamed) + base := BasicAuditEvent(uid, "", MessageFileRenamed(ev.Executant.OpaqueId, iid, oldpath, path), ActionFileRenamed) return AuditEventFileRenamed{ AuditEventFiles: FilesAuditEvent(base, iid, uid, path), OldPath: oldpath, @@ -278,7 +278,7 @@ func ItemMoved(ev events.ItemMoved) AuditEventFileRenamed { // ItemTrashed converts a ItemTrashed event to an AuditEventFileDeleted func ItemTrashed(ev events.ItemTrashed) AuditEventFileDeleted { iid, path, uid := extractFileDetails(ev.Ref, ev.Owner) - base := BasicAuditEvent(uid, "", MessageFileTrashed(iid), ActionFileTrashed) + base := BasicAuditEvent(uid, "", MessageFileTrashed(ev.Executant.OpaqueId, iid), ActionFileTrashed) return AuditEventFileDeleted{ AuditEventFiles: FilesAuditEvent(base, iid, uid, path), } @@ -287,7 +287,7 @@ func ItemTrashed(ev events.ItemTrashed) AuditEventFileDeleted { // ItemPurged converts a ItemPurged event to an AuditEventFilePurged func ItemPurged(ev events.ItemPurged) AuditEventFilePurged { iid, path, uid := extractFileDetails(ev.Ref, ev.Owner) - base := BasicAuditEvent(uid, "", MessageFilePurged(iid), ActionFilePurged) + base := BasicAuditEvent(uid, "", MessageFilePurged(ev.Executant.OpaqueId, iid), ActionFilePurged) return AuditEventFilePurged{ AuditEventFiles: FilesAuditEvent(base, iid, uid, path), } @@ -302,7 +302,7 @@ func ItemRestored(ev events.ItemRestored) AuditEventFileRestored { oldpath = ev.OldReference.GetPath() } - base := BasicAuditEvent(uid, "", MessageFileRestored(iid, path), ActionFileRestored) + base := BasicAuditEvent(uid, "", MessageFileRestored(ev.Executant.OpaqueId, iid, path), ActionFileRestored) return AuditEventFileRestored{ AuditEventFiles: FilesAuditEvent(base, iid, uid, path), OldPath: oldpath, @@ -312,7 +312,7 @@ func ItemRestored(ev events.ItemRestored) AuditEventFileRestored { // FileVersionRestored converts a FileVersionRestored event to an AuditEventFileVersionRestored func FileVersionRestored(ev events.FileVersionRestored) AuditEventFileVersionRestored { iid, path, uid := extractFileDetails(ev.Ref, ev.Owner) - base := BasicAuditEvent(uid, "", MessageFileVersionRestored(iid, ev.Key), ActionFileVersionRestored) + base := BasicAuditEvent(uid, "", MessageFileVersionRestored(ev.Executant.OpaqueId, iid, ev.Key), ActionFileVersionRestored) return AuditEventFileVersionRestored{ AuditEventFiles: FilesAuditEvent(base, iid, uid, path), Key: ev.Key, @@ -331,7 +331,7 @@ func SpacesAuditEvent(base AuditEvent, spaceID string) AuditEventSpaces { func SpaceCreated(ev events.SpaceCreated) AuditEventSpaceCreated { sid := ev.ID.GetOpaqueId() iid, _, owner := extractFileDetails(&provider.Reference{ResourceId: ev.Root}, ev.Owner) - base := BasicAuditEvent("", formatTime(ev.MTime), MessageSpaceCreated(sid, ev.Name), ActionSpaceCreated) + base := BasicAuditEvent("", formatTime(ev.MTime), MessageSpaceCreated(ev.Executant.OpaqueId, sid, ev.Name), ActionSpaceCreated) return AuditEventSpaceCreated{ AuditEventSpaces: SpacesAuditEvent(base, sid), Owner: owner, @@ -344,7 +344,7 @@ func SpaceCreated(ev events.SpaceCreated) AuditEventSpaceCreated { // SpaceRenamed converts a SpaceRenamed event to an AuditEventSpaceRenamed func SpaceRenamed(ev events.SpaceRenamed) AuditEventSpaceRenamed { sid := ev.ID.GetOpaqueId() - base := BasicAuditEvent("", "", MessageSpaceRenamed(sid, ev.Name), ActionSpaceRenamed) + base := BasicAuditEvent("", "", MessageSpaceRenamed(ev.Executant.OpaqueId, sid, ev.Name), ActionSpaceRenamed) return AuditEventSpaceRenamed{ AuditEventSpaces: SpacesAuditEvent(base, sid), NewName: ev.Name, @@ -354,7 +354,7 @@ func SpaceRenamed(ev events.SpaceRenamed) AuditEventSpaceRenamed { // SpaceDisabled converts a SpaceDisabled event to an AuditEventSpaceDisabled func SpaceDisabled(ev events.SpaceDisabled) AuditEventSpaceDisabled { sid := ev.ID.GetOpaqueId() - base := BasicAuditEvent("", "", MessageSpaceDisabled(sid), ActionSpaceDisabled) + base := BasicAuditEvent("", "", MessageSpaceDisabled(ev.Executant.OpaqueId, sid), ActionSpaceDisabled) return AuditEventSpaceDisabled{ AuditEventSpaces: SpacesAuditEvent(base, sid), } @@ -363,7 +363,7 @@ func SpaceDisabled(ev events.SpaceDisabled) AuditEventSpaceDisabled { // SpaceEnabled converts a SpaceEnabled event to an AuditEventSpaceEnabled func SpaceEnabled(ev events.SpaceEnabled) AuditEventSpaceEnabled { sid := ev.ID.GetOpaqueId() - base := BasicAuditEvent("", "", MessageSpaceEnabled(sid), ActionSpaceEnabled) + base := BasicAuditEvent("", "", MessageSpaceEnabled(ev.Executant.OpaqueId, sid), ActionSpaceEnabled) return AuditEventSpaceEnabled{ AuditEventSpaces: SpacesAuditEvent(base, sid), } @@ -372,7 +372,7 @@ func SpaceEnabled(ev events.SpaceEnabled) AuditEventSpaceEnabled { // SpaceDeleted converts a SpaceDeleted event to an AuditEventSpaceDeleted func SpaceDeleted(ev events.SpaceDeleted) AuditEventSpaceDeleted { sid := ev.ID.GetOpaqueId() - base := BasicAuditEvent("", "", MessageSpaceDeleted(sid), ActionSpaceDeleted) + base := BasicAuditEvent("", "", MessageSpaceDeleted(ev.Executant.OpaqueId, sid), ActionSpaceDeleted) return AuditEventSpaceDeleted{ AuditEventSpaces: SpacesAuditEvent(base, sid), } @@ -380,7 +380,7 @@ func SpaceDeleted(ev events.SpaceDeleted) AuditEventSpaceDeleted { // UserCreated converts a UserCreated event to an AuditEventUserCreated func UserCreated(ev events.UserCreated) AuditEventUserCreated { - base := BasicAuditEvent("", "", MessageUserCreated(ev.UserID), ActionUserCreated) + base := BasicAuditEvent("", "", MessageUserCreated(ev.Executant.OpaqueId, ev.UserID), ActionUserCreated) return AuditEventUserCreated{ AuditEvent: base, UserID: ev.UserID, @@ -389,7 +389,7 @@ func UserCreated(ev events.UserCreated) AuditEventUserCreated { // UserDeleted converts a UserDeleted event to an AuditEventUserDeleted func UserDeleted(ev events.UserDeleted) AuditEventUserDeleted { - base := BasicAuditEvent("", "", MessageUserDeleted(ev.UserID), ActionUserDeleted) + base := BasicAuditEvent("", "", MessageUserDeleted(ev.Executant.OpaqueId, ev.UserID), ActionUserDeleted) return AuditEventUserDeleted{ AuditEvent: base, UserID: ev.UserID, @@ -398,7 +398,7 @@ func UserDeleted(ev events.UserDeleted) AuditEventUserDeleted { // UserFeatureChanged converts a UserFeatureChanged event to an AuditEventUserFeatureChanged func UserFeatureChanged(ev events.UserFeatureChanged) AuditEventUserFeatureChanged { - msg := MessageUserFeatureChanged(ev.UserID, ev.Features) + msg := MessageUserFeatureChanged(ev.Executant.OpaqueId, ev.UserID, ev.Features) base := BasicAuditEvent("", "", msg, ActionUserFeatureChanged) return AuditEventUserFeatureChanged{ AuditEvent: base, @@ -409,7 +409,7 @@ func UserFeatureChanged(ev events.UserFeatureChanged) AuditEventUserFeatureChang // GroupCreated converts a GroupCreated event to an AuditEventGroupCreated func GroupCreated(ev events.GroupCreated) AuditEventGroupCreated { - base := BasicAuditEvent("", "", MessageGroupCreated(ev.GroupID), ActionGroupCreated) + base := BasicAuditEvent("", "", MessageGroupCreated(ev.Executant.OpaqueId, ev.GroupID), ActionGroupCreated) return AuditEventGroupCreated{ AuditEvent: base, GroupID: ev.GroupID, @@ -418,7 +418,7 @@ func GroupCreated(ev events.GroupCreated) AuditEventGroupCreated { // GroupDeleted converts a GroupDeleted event to an AuditEventGroupDeleted func GroupDeleted(ev events.GroupDeleted) AuditEventGroupDeleted { - base := BasicAuditEvent("", "", MessageGroupDeleted(ev.GroupID), ActionGroupDeleted) + base := BasicAuditEvent("", "", MessageGroupDeleted(ev.Executant.OpaqueId, ev.GroupID), ActionGroupDeleted) return AuditEventGroupDeleted{ AuditEvent: base, GroupID: ev.GroupID, @@ -427,7 +427,7 @@ func GroupDeleted(ev events.GroupDeleted) AuditEventGroupDeleted { // GroupMemberAdded converts a GroupMemberAdded event to an AuditEventGroupMemberAdded func GroupMemberAdded(ev events.GroupMemberAdded) AuditEventGroupMemberAdded { - msg := MessageGroupMemberAdded(ev.GroupID, ev.UserID) + msg := MessageGroupMemberAdded(ev.Executant.OpaqueId, ev.GroupID, ev.UserID) base := BasicAuditEvent("", "", msg, ActionGroupMemberAdded) return AuditEventGroupMemberAdded{ AuditEvent: base, @@ -438,7 +438,7 @@ func GroupMemberAdded(ev events.GroupMemberAdded) AuditEventGroupMemberAdded { // GroupMemberRemoved converts a GroupMemberRemoved event to an AuditEventGroupMemberRemove func GroupMemberRemoved(ev events.GroupMemberRemoved) AuditEventGroupMemberRemoved { - msg := MessageGroupMemberRemoved(ev.GroupID, ev.UserID) + msg := MessageGroupMemberRemoved(ev.Executant.OpaqueId, ev.GroupID, ev.UserID) base := BasicAuditEvent("", "", msg, ActionGroupMemberRemoved) return AuditEventGroupMemberRemoved{ AuditEvent: base, diff --git a/extensions/graph/pkg/service/v0/groups.go b/extensions/graph/pkg/service/v0/groups.go index 3fef37505e..6d19bd7b48 100644 --- a/extensions/graph/pkg/service/v0/groups.go +++ b/extensions/graph/pkg/service/v0/groups.go @@ -13,6 +13,7 @@ import ( libregraph "github.com/owncloud/libre-graph-api-go" "github.com/owncloud/ocis/v2/extensions/graph/pkg/service/v0/errorcode" + ctxpkg "github.com/cs3org/reva/v2/pkg/ctx" "github.com/cs3org/reva/v2/pkg/events" "github.com/go-chi/chi/v5" "github.com/go-chi/render" @@ -83,7 +84,8 @@ func (g Graph) PostGroup(w http.ResponseWriter, r *http.Request) { } if grp != nil && grp.Id != nil { - g.publishEvent(events.GroupCreated{GroupID: *grp.Id}) + currentUser := ctxpkg.ContextMustGetUser(r.Context()) + g.publishEvent(events.GroupCreated{Executant: currentUser.Id, GroupID: *grp.Id}) } render.Status(r, http.StatusOK) render.JSON(w, r, grp) @@ -202,7 +204,8 @@ func (g Graph) DeleteGroup(w http.ResponseWriter, r *http.Request) { return } - g.publishEvent(events.GroupDeleted{GroupID: groupID}) + currentUser := ctxpkg.ContextMustGetUser(r.Context()) + g.publishEvent(events.GroupDeleted{Executant: currentUser.Id, GroupID: groupID}) render.Status(r, http.StatusNoContent) render.NoContent(w, r) } @@ -286,7 +289,8 @@ func (g Graph) PostGroupMember(w http.ResponseWriter, r *http.Request) { return } - g.publishEvent(events.GroupMemberAdded{GroupID: groupID, UserID: id}) + currentUser := ctxpkg.ContextMustGetUser(r.Context()) + g.publishEvent(events.GroupMemberAdded{Executant: currentUser.Id, GroupID: groupID, UserID: id}) render.Status(r, http.StatusNoContent) render.NoContent(w, r) } @@ -330,7 +334,8 @@ func (g Graph) DeleteGroupMember(w http.ResponseWriter, r *http.Request) { } return } - g.publishEvent(events.GroupMemberRemoved{GroupID: groupID, UserID: memberID}) + currentUser := ctxpkg.ContextMustGetUser(r.Context()) + g.publishEvent(events.GroupMemberRemoved{Executant: currentUser.Id, GroupID: groupID, UserID: memberID}) render.Status(r, http.StatusNoContent) render.NoContent(w, r) } diff --git a/extensions/graph/pkg/service/v0/password.go b/extensions/graph/pkg/service/v0/password.go index 51da7b41ba..c94b969f34 100644 --- a/extensions/graph/pkg/service/v0/password.go +++ b/extensions/graph/pkg/service/v0/password.go @@ -8,6 +8,7 @@ import ( "github.com/CiscoM31/godata" gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1" cs3rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" + ctxpkg "github.com/cs3org/reva/v2/pkg/ctx" revactx "github.com/cs3org/reva/v2/pkg/ctx" "github.com/cs3org/reva/v2/pkg/events" "github.com/go-chi/render" @@ -84,11 +85,13 @@ func (g Graph) ChangeOwnPassword(w http.ResponseWriter, r *http.Request) { return } + currentUser := ctxpkg.ContextMustGetUser(r.Context()) g.publishEvent( events.UserFeatureChanged{ - UserID: u.Id.OpaqueId, + Executant: currentUser.Id, + UserID: u.Id.OpaqueId, Features: []events.UserFeature{ - events.UserFeature{Name: "password", Value: "***"}, + {Name: "password", Value: "***"}, }, }, ) diff --git a/extensions/graph/pkg/service/v0/users.go b/extensions/graph/pkg/service/v0/users.go index 7e28020194..d567e3e98f 100644 --- a/extensions/graph/pkg/service/v0/users.go +++ b/extensions/graph/pkg/service/v0/users.go @@ -11,6 +11,7 @@ import ( "strings" "github.com/CiscoM31/godata" + ctxpkg "github.com/cs3org/reva/v2/pkg/ctx" revactx "github.com/cs3org/reva/v2/pkg/ctx" "github.com/cs3org/reva/v2/pkg/events" "github.com/go-chi/chi/v5" @@ -140,7 +141,8 @@ func (g Graph) PostUser(w http.ResponseWriter, r *http.Request) { return } - g.publishEvent(events.UserCreated{UserID: *u.Id}) + currentUser := ctxpkg.ContextMustGetUser(r.Context()) + g.publishEvent(events.UserCreated{Executant: currentUser.Id, UserID: *u.Id}) render.Status(r, http.StatusOK) render.JSON(w, r, u) @@ -197,7 +199,8 @@ func (g Graph) DeleteUser(w http.ResponseWriter, r *http.Request) { } } - g.publishEvent(events.UserDeleted{UserID: userID}) + currentUser := ctxpkg.ContextMustGetUser(r.Context()) + g.publishEvent(events.UserDeleted{Executant: currentUser.Id, UserID: userID}) render.Status(r, http.StatusNoContent) render.NoContent(w, r) @@ -247,10 +250,12 @@ func (g Graph) PatchUser(w http.ResponseWriter, r *http.Request) { } } + currentUser := ctxpkg.ContextMustGetUser(r.Context()) g.publishEvent( events.UserFeatureChanged{ - UserID: nameOrID, - Features: features, + Executant: currentUser.Id, + UserID: nameOrID, + Features: features, }, ) render.Status(r, http.StatusOK)