Repository: owncloud/ocis
Pull request #3993 (2022-06-20 15:26:11)

Add the acting user to the events in the audit log.
Added the acting user to the events in the audit log.

C0rby: I need to add checks for the executant since it can be nil.
sonarcloud[bot]: Kudos, SonarCloud Quality Gate passed!&nbsp; &nbsp; [![Quality Gate passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/passed-16px.png 'Quality Gate passed')](https://sonarcloud.io/dashboard?id=owncloud_ocis&pullRequest=3993)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3993&resolved=false&types=BUG) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3993&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3993&resolved=false&types=BUG)  
[![Vulnerability](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/vulnerability-16px.png 'Vulnerability')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3993&resolved=false&types=VULNERABILITY) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3993&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3993&resolved=false&types=VULNERABILITY)  
[![Security Hotspot](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/security_hotspot-16px.png 'Security Hotspot')](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=3993&resolved=false&types=SECURITY_HOTSPOT) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=3993&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=3993&resolved=false&types=SECURITY_HOTSPOT)  
[![Code Smell](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/code_smell-16px.png 'Code Smell')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3993&resolved=false&types=CODE_SMELL) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3993&resolved=false&types=CODE_SMELL) [1 Code Smell](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=3993&resolved=false&types=CODE_SMELL)

[![6.7%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/0-16px.png '6.7%')](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=3993&metric=new_coverage&view=list) [6.7% Coverage](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=3993&metric=new_coverage&view=list)  
[![0.0%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/3-16px.png '0.0%')](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=3993&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=3993&metric=new_duplicated_lines_density&view=list)


ownclouders: :boom: Acceptance test [<strong>localApiTests-apiSpaces-ocis</strong>](https://drone.owncloud.com/owncloud/ocis/12653/38/1) failed. Further test are cancelled...
<!-- id: pr-3993 -->


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7128ffaab0f..b285d982716 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -108,7 +108,6 @@ The following sections list the changes for unreleased.
    https://github.com/owncloud/ocis/pull/3944
    https://github.com/owncloud/ocis/pull/3975
    https://github.com/owncloud/ocis/pull/3982
-   https://github.com/owncloud/ocis/pull/4000
 # Changelog for [2.0.0-beta.3] (2022-06-08)
 
 The following sections list the changes for 2.0.0-beta.3.
diff --git a/changelog/unreleased/audit-service.md b/changelog/unreleased/audit-service.md
new file mode 100644
index 00000000000..f49d02eabb2
--- /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/changelog/unreleased/update-reva-beta.4.md b/changelog/unreleased/update-reva-beta.4.md
index 909083b0291..d609a728984 100644
--- a/changelog/unreleased/update-reva-beta.4.md
+++ b/changelog/unreleased/update-reva-beta.4.md
@@ -5,4 +5,3 @@ TBD
 https://github.com/owncloud/ocis/pull/3944
 https://github.com/owncloud/ocis/pull/3975
 https://github.com/owncloud/ocis/pull/3982
-https://github.com/owncloud/ocis/pull/4000
diff --git a/extensions/audit/pkg/types/constants.go b/extensions/audit/pkg/types/constants.go
index 69423d57dba..29d91972429 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 3cbfeaa329f..14cea5a0157 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.GetOpaqueId(), "", "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:         "",
@@ -234,8 +234,8 @@ 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.Executant)
-	base := BasicAuditEvent(uid, "", MessageContainerCreated(iid), ActionContainerCreated)
+	iid, path, uid := extractFileDetails(ev.Ref, ev.Owner)
+	base := BasicAuditEvent(uid, "", MessageContainerCreated(ev.Executant.GetOpaqueId(), 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.GetOpaqueId(), 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.GetOpaqueId(), 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.GetOpaqueId(), 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.GetOpaqueId(), 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.GetOpaqueId(), 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.GetOpaqueId(), 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.GetOpaqueId(), 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.GetOpaqueId(), 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.GetOpaqueId(), 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.GetOpaqueId(), 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.GetOpaqueId(), 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.GetOpaqueId(), 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.GetOpaqueId(), 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.GetOpaqueId(), 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.GetOpaqueId(), 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.GetOpaqueId(), 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.GetOpaqueId(), 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.GetOpaqueId(), 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.GetOpaqueId(), ev.GroupID, ev.UserID)
 	base := BasicAuditEvent("", "", msg, ActionGroupMemberRemoved)
 	return AuditEventGroupMemberRemoved{
 		AuditEvent: base,
@@ -480,18 +480,18 @@ func formatTime(t *types.Timestamp) string {
 }
 
 func updateType(u string) string {
-	switch {
-	case u == "permissions":
+	switch u {
+	case "permissions":
 		return ActionSharePermissionUpdated
-	case u == "displayname":
+	case "displayname":
 		return ActionShareDisplayNameUpdated
-	case u == "TYPE_PERMISSIONS":
+	case "TYPE_PERMISSIONS":
 		return ActionSharePermissionUpdated
-	case u == "TYPE_DISPLAYNAME":
+	case "TYPE_DISPLAYNAME":
 		return ActionShareDisplayNameUpdated
-	case u == "TYPE_PASSWORD":
+	case "TYPE_PASSWORD":
 		return ActionSharePasswordUpdated
-	case u == "TYPE_EXPIRATION":
+	case "TYPE_EXPIRATION":
 		return ActionShareExpirationUpdated
 	default:
 		fmt.Println("Unknown update type", u)
diff --git a/extensions/graph/pkg/service/v0/groups.go b/extensions/graph/pkg/service/v0/groups.go
index 3fef37505ee..6d19bd7b480 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 51da7b41ba5..c94b969f34c 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 7e280201944..d567e3e98fe 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)
diff --git a/go.mod b/go.mod
index 84a6cceeaee..1f056f94dfa 100644
--- a/go.mod
+++ b/go.mod
@@ -10,7 +10,7 @@ require (
 	github.com/blevesearch/bleve_index_api v1.0.2
 	github.com/coreos/go-oidc/v3 v3.2.0
 	github.com/cs3org/go-cs3apis v0.0.0-20220512100524-551800f020d8
-	github.com/cs3org/reva/v2 v2.5.2-0.20220621092317-04f64d9da591
+	github.com/cs3org/reva/v2 v2.5.2-0.20220617144643-4758360f5d55
 	github.com/disintegration/imaging v1.6.2
 	github.com/go-chi/chi/v5 v5.0.7
 	github.com/go-chi/cors v1.2.1
diff --git a/go.sum b/go.sum
index 969bfd41cc2..b844dbae0c2 100644
--- a/go.sum
+++ b/go.sum
@@ -294,8 +294,8 @@ github.com/crewjam/httperr v0.2.0/go.mod h1:Jlz+Sg/XqBQhyMjdDiC+GNNRzZTD7x39Gu3p
 github.com/crewjam/saml v0.4.6 h1:XCUFPkQSJLvzyl4cW9OvpWUbRf0gE7VUpU8ZnilbeM4=
 github.com/crewjam/saml v0.4.6/go.mod h1:ZBOXnNPFzB3CgOkRm7Nd6IVdkG+l/wF+0ZXLqD96t1A=
 github.com/cs3org/cato v0.0.0-20200828125504-e418fc54dd5e/go.mod h1:XJEZ3/EQuI3BXTp/6DUzFr850vlxq11I6satRtz0YQ4=
-github.com/cs3org/reva/v2 v2.5.2-0.20220621092317-04f64d9da591 h1:uorP+QgVZqMnsmDDAIhE9guwi2kjr4mmHNRvKHh5GI0=
-github.com/cs3org/reva/v2 v2.5.2-0.20220621092317-04f64d9da591/go.mod h1:zAHqzr36X4lIalonDQeNbwrIXjn66C38lp5A+MTRS1c=
+github.com/cs3org/reva/v2 v2.5.2-0.20220617144643-4758360f5d55 h1:N1E8H+pgrDW//X315BniqmvDYYPoMBkbJZhQEQ3Y+98=
+github.com/cs3org/reva/v2 v2.5.2-0.20220617144643-4758360f5d55/go.mod h1:zAHqzr36X4lIalonDQeNbwrIXjn66C38lp5A+MTRS1c=
 github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8 h1:Z9lwXumT5ACSmJ7WGnFl+OMLLjpz5uR2fyz7dC255FI=
 github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8/go.mod h1:4abs/jPXcmJzYoYGF91JF9Uq9s/KL5n1jvFDix8KcqY=
 github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4=


Test patch:
diff --git a/extensions/audit/pkg/service/service_test.go b/extensions/audit/pkg/service/service_test.go
index 5de097bedf4..ae64f43a2c3 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")
 		},