Repository: owncloud/ocis
Pull request #5699 (2023-03-01 15:20:39)

Userlog Service Improvements
Improves userlog service with proper messages and enhances API

ownclouders: :boom: Acceptance test [<strong>cs3ApiTests-ocis</strong>](https://drone.owncloud.com/owncloud/ocis/19671/42/1) failed. Further test are cancelled...
<!-- id: pr-5699 -->

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=5699)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&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=5699&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&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=5699&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=5699&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&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=5699&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=5699&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=5699&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=5699&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=5699&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&resolved=false&types=CODE_SMELL)

[![3.9%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/0-16px.png '3.9%')](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=5699&metric=new_coverage&view=list) [3.9% Coverage](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=5699&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=5699&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=5699&metric=new_duplicated_lines_density&view=list)


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=5699)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&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=5699&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&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=5699&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=5699&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&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=5699&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=5699&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=5699&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=5699&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=5699&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&resolved=false&types=CODE_SMELL)

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


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=5699)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&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=5699&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&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=5699&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=5699&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&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=5699&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=5699&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=5699&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=5699&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=5699&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&resolved=false&types=CODE_SMELL)

[![8.9%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/0-16px.png '8.9%')](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=5699&metric=new_coverage&view=list) [8.9% Coverage](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=5699&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=5699&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=5699&metric=new_duplicated_lines_density&view=list)


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=5699)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&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=5699&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&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=5699&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=5699&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&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=5699&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=5699&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=5699&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=5699&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=5699&resolved=false&types=CODE_SMELL) [3 Code Smells](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&resolved=false&types=CODE_SMELL)

[![8.7%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/0-16px.png '8.7%')](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=5699&metric=new_coverage&view=list) [8.7% Coverage](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=5699&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=5699&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=5699&metric=new_duplicated_lines_density&view=list)


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=5699)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&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=5699&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&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=5699&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=5699&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&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=5699&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=5699&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=5699&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=5699&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=5699&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&resolved=false&types=CODE_SMELL)

[![7.4%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/0-16px.png '7.4%')](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=5699&metric=new_coverage&view=list) [7.4% Coverage](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=5699&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=5699&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=5699&metric=new_duplicated_lines_density&view=list)


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=5699)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&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=5699&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&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=5699&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=5699&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&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=5699&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=5699&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=5699&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=5699&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=5699&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&resolved=false&types=CODE_SMELL)

[![7.4%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/0-16px.png '7.4%')](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=5699&metric=new_coverage&view=list) [7.4% Coverage](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=5699&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=5699&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=5699&metric=new_duplicated_lines_density&view=list)


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=5699)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&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=5699&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&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=5699&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=5699&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&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=5699&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=5699&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=5699&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=5699&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=5699&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&resolved=false&types=CODE_SMELL)

[![7.3%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/0-16px.png '7.3%')](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=5699&metric=new_coverage&view=list) [7.3% Coverage](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=5699&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=5699&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=5699&metric=new_duplicated_lines_density&view=list)


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=5699)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&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=5699&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&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=5699&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=5699&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&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=5699&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=5699&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=5699&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=5699&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=5699&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&resolved=false&types=CODE_SMELL)

[![7.3%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/0-16px.png '7.3%')](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=5699&metric=new_coverage&view=list) [7.3% Coverage](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=5699&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=5699&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=5699&metric=new_duplicated_lines_density&view=list)


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=5699)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&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=5699&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&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=5699&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=5699&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&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=5699&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=5699&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=5699&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=5699&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=5699&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&resolved=false&types=CODE_SMELL)

[![7.3%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/0-16px.png '7.3%')](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=5699&metric=new_coverage&view=list) [7.3% Coverage](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=5699&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=5699&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=5699&metric=new_duplicated_lines_density&view=list)


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=5699)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&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=5699&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&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=5699&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=5699&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&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=5699&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=5699&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=5699&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=5699&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=5699&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&resolved=false&types=CODE_SMELL)

[![7.3%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/0-16px.png '7.3%')](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=5699&metric=new_coverage&view=list) [7.3% Coverage](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=5699&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=5699&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=5699&metric=new_duplicated_lines_density&view=list)


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=5699)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&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=5699&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&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=5699&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=5699&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&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=5699&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=5699&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=5699&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=5699&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=5699&resolved=false&types=CODE_SMELL) [3 Code Smells](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&resolved=false&types=CODE_SMELL)

[![7.3%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/0-16px.png '7.3%')](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=5699&metric=new_coverage&view=list) [7.3% Coverage](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=5699&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=5699&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=5699&metric=new_duplicated_lines_density&view=list)


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=5699)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&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=5699&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&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=5699&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=5699&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&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=5699&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=5699&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=5699&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=5699&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=5699&resolved=false&types=CODE_SMELL) [3 Code Smells](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&resolved=false&types=CODE_SMELL)

[![7.3%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/0-16px.png '7.3%')](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=5699&metric=new_coverage&view=list) [7.3% Coverage](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=5699&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=5699&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=5699&metric=new_duplicated_lines_density&view=list)


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=5699)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&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=5699&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&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=5699&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=5699&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&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=5699&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=5699&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=5699&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=5699&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=5699&resolved=false&types=CODE_SMELL) [3 Code Smells](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&resolved=false&types=CODE_SMELL)

[![7.3%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/0-16px.png '7.3%')](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=5699&metric=new_coverage&view=list) [7.3% Coverage](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=5699&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=5699&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=5699&metric=new_duplicated_lines_density&view=list)


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=5699)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&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=5699&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&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=5699&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=5699&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&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=5699&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=5699&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=5699&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=5699&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=5699&resolved=false&types=CODE_SMELL) [3 Code Smells](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&resolved=false&types=CODE_SMELL)

[![7.3%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/0-16px.png '7.3%')](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=5699&metric=new_coverage&view=list) [7.3% Coverage](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=5699&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=5699&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=5699&metric=new_duplicated_lines_density&view=list)


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=5699)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&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=5699&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&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=5699&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=5699&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&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=5699&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=5699&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=5699&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=5699&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=5699&resolved=false&types=CODE_SMELL) [3 Code Smells](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&resolved=false&types=CODE_SMELL)

[![7.3%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/0-16px.png '7.3%')](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=5699&metric=new_coverage&view=list) [7.3% Coverage](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=5699&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=5699&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=5699&metric=new_duplicated_lines_density&view=list)


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=5699)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&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=5699&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&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=5699&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=5699&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&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=5699&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=5699&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=5699&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=5699&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=5699&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&resolved=false&types=CODE_SMELL)

[![7.3%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/0-16px.png '7.3%')](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=5699&metric=new_coverage&view=list) [7.3% Coverage](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=5699&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=5699&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=5699&metric=new_duplicated_lines_density&view=list)


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=5699)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&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=5699&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&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=5699&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=5699&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&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=5699&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=5699&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=5699&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=5699&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=5699&resolved=false&types=CODE_SMELL) [1 Code Smell](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5699&resolved=false&types=CODE_SMELL)

[![7.3%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/0-16px.png '7.3%')](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=5699&metric=new_coverage&view=list) [7.3% Coverage](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=5699&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=5699&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=5699&metric=new_duplicated_lines_density&view=list)



Patch:
diff --git a/Dockerfile b/Dockerfile
index 3777d7207ad..3f007f9c504 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -21,7 +21,7 @@ COPY ./ /ocis/
 WORKDIR /ocis/ocis
 RUN make ci-node-generate
 
-FROM owncloudci/golang:1.18 as build
+FROM owncloudci/golang:1.19 as build
 
 COPY --from=generate /ocis /ocis
 
diff --git a/changelog/unreleased/userlog-improvements.md b/changelog/unreleased/userlog-improvements.md
new file mode 100644
index 00000000000..95e4e94bc54
--- /dev/null
+++ b/changelog/unreleased/userlog-improvements.md
@@ -0,0 +1,5 @@
+Enhancement: Userlog
+
+Enhane userlog service with proper api and messages
+
+https://github.com/owncloud/ocis/pull/5699
diff --git a/services/frontend/pkg/revaconfig/config.go b/services/frontend/pkg/revaconfig/config.go
index 80570badc76..70da96c8e4b 100644
--- a/services/frontend/pkg/revaconfig/config.go
+++ b/services/frontend/pkg/revaconfig/config.go
@@ -267,6 +267,9 @@ func FrontendConfigFromStruct(cfg *config.Config) (map[string]interface{}, error
 								"share_jail": cfg.EnableShareJail,
 								"max_quota":  cfg.MaxQuota,
 							},
+							"notifications": map[string]interface{}{
+								"endpoints": []string{"list", "get", "delete"},
+							},
 						},
 						"version": map[string]interface{}{
 							"product":        "Infinite Scale",
diff --git a/services/userlog/pkg/command/server.go b/services/userlog/pkg/command/server.go
index 7ca044d297d..6f09a537159 100644
--- a/services/userlog/pkg/command/server.go
+++ b/services/userlog/pkg/command/server.go
@@ -25,36 +25,17 @@ import (
 
 // all events we care about
 var _registeredEvents = []events.Unmarshaller{
-	// file related
-	events.UploadReady{},
-	events.ContainerCreated{},
-	events.FileTouched{},
-	events.FileDownloaded{},
-	events.FileVersionRestored{},
-	events.ItemMoved{},
-	events.ItemTrashed{},
-	events.ItemPurged{},
-	events.ItemRestored{},
-
 	// space related
-	events.SpaceCreated{},
-	events.SpaceRenamed{},
-	events.SpaceEnabled{},
 	events.SpaceDisabled{},
 	events.SpaceDeleted{},
 	events.SpaceShared{},
 	events.SpaceUnshared{},
-	events.SpaceUpdated{},
 	events.SpaceMembershipExpired{},
 
 	// share related
 	events.ShareCreated{},
-	// events.ShareRemoved{}, // TODO: ShareRemoved doesn't hold sharee information
-	events.ShareUpdated{},
+	events.ShareRemoved{},
 	events.ShareExpired{},
-	events.LinkCreated{},
-	// events.LinkRemoved{}, // TODO: LinkRemoved doesn't hold sharee information
-	events.LinkUpdated{},
 }
 
 // Server is the entrypoint for the server command.
diff --git a/services/userlog/pkg/service/conversion.go b/services/userlog/pkg/service/conversion.go
new file mode 100644
index 00000000000..a3463508944
--- /dev/null
+++ b/services/userlog/pkg/service/conversion.go
@@ -0,0 +1,249 @@
+package service
+
+import (
+	"bytes"
+	"errors"
+	"text/template"
+	"time"
+
+	user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
+	collaboration "github.com/cs3org/go-cs3apis/cs3/sharing/collaboration/v1beta1"
+	storageprovider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
+	"github.com/cs3org/reva/v2/pkg/events"
+	"github.com/cs3org/reva/v2/pkg/storagespace"
+	"github.com/cs3org/reva/v2/pkg/utils"
+	ehmsg "github.com/owncloud/ocis/v2/protogen/gen/ocis/messages/eventhistory/v0"
+)
+
+var (
+	_resourceTypeSpace = "storagespace"
+	_resourceTypeShare = "share"
+)
+
+// OC10Notification is the oc10 style representation of an event
+// some fields are left out for simplicity
+type OC10Notification struct {
+	EventID        string                 `json:"notification_id"`
+	Service        string                 `json:"app"`
+	UserName       string                 `json:"user"`
+	Timestamp      string                 `json:"datetime"`
+	ResourceID     string                 `json:"object_id"`
+	ResourceType   string                 `json:"object_type"`
+	Subject        string                 `json:"subject"`
+	SubjectRaw     string                 `json:"subjectRich"`
+	Message        string                 `json:"message"`
+	MessageRaw     string                 `json:"messageRich"`
+	MessageDetails map[string]interface{} `json:"messageRichParameters"`
+}
+
+// ConvertEvent converts an eventhistory event to an OC10Notification
+func (ul *UserlogService) ConvertEvent(event *ehmsg.Event) (OC10Notification, error) {
+	etype, ok := ul.registeredEvents[event.Type]
+	if !ok {
+		// this should not happen
+		return OC10Notification{}, errors.New("eventtype not registered")
+	}
+
+	einterface, err := etype.Unmarshal(event.Event)
+	if err != nil {
+		// this shouldn't happen either
+		return OC10Notification{}, errors.New("cant unmarshal event")
+	}
+
+	switch ev := einterface.(type) {
+	default:
+		return OC10Notification{}, errors.New("unknown event type")
+	// space related
+	case events.SpaceDisabled:
+		return ul.spaceMessage(event.Id, SpaceDisabled, ev.Executant, ev.ID.GetOpaqueId(), ev.Timestamp)
+	case events.SpaceDeleted:
+		return ul.spaceDeletedMessage(event.Id, ev.Executant, ev.ID.GetOpaqueId(), ev.SpaceName, ev.Timestamp)
+	case events.SpaceShared:
+		return ul.spaceMessage(event.Id, SpaceShared, ev.Executant, ev.ID.GetOpaqueId(), ev.Timestamp)
+	case events.SpaceUnshared:
+		return ul.spaceMessage(event.Id, SpaceUnshared, ev.Executant, ev.ID.GetOpaqueId(), ev.Timestamp)
+	case events.SpaceMembershipExpired:
+		return ul.spaceMessage(event.Id, SpaceMembershipExpired, ev.SpaceOwner, ev.SpaceID.GetOpaqueId(), ev.ExpiredAt)
+
+	// share related
+	case events.ShareCreated:
+		return ul.shareMessage(event.Id, ShareCreated, ev.Executant, ev.ItemID, ev.ShareID, utils.TSToTime(ev.CTime))
+	case events.ShareExpired:
+		return ul.shareMessage(event.Id, ShareExpired, ev.ShareOwner, ev.ItemID, ev.ShareID, ev.ExpiredAt)
+	case events.ShareRemoved:
+		return ul.shareMessage(event.Id, ShareRemoved, ev.Executant, ev.ItemID, ev.ShareID, ev.Timestamp)
+	}
+}
+
+func (ul *UserlogService) spaceDeletedMessage(eventid string, executant *user.UserId, spaceid string, spacename string, ts time.Time) (OC10Notification, error) {
+	_, user, err := utils.Impersonate(executant, ul.gwClient, ul.cfg.MachineAuthAPIKey)
+	if err != nil {
+		return OC10Notification{}, err
+	}
+
+	subj, subjraw, msg, msgraw, err := ul.composeMessage(SpaceDeleted, map[string]string{
+		"username":  user.GetDisplayName(),
+		"spacename": spacename,
+	})
+	if err != nil {
+		return OC10Notification{}, err
+	}
+
+	details := ul.getDetails(user, nil, nil, nil)
+	details["space"] = map[string]string{
+		"id":   spaceid,
+		"name": spacename,
+	}
+
+	return OC10Notification{
+		EventID:        eventid,
+		Service:        ul.cfg.Service.Name,
+		UserName:       user.GetUsername(),
+		Timestamp:      ts.Format(time.RFC3339Nano),
+		ResourceID:     spaceid,
+		ResourceType:   _resourceTypeSpace,
+		Subject:        subj,
+		SubjectRaw:     subjraw,
+		Message:        msg,
+		MessageRaw:     msgraw,
+		MessageDetails: details,
+	}, nil
+}
+
+func (ul *UserlogService) spaceMessage(eventid string, eventname string, executant *user.UserId, spaceid string, ts time.Time) (OC10Notification, error) {
+	ctx, user, err := utils.Impersonate(executant, ul.gwClient, ul.cfg.MachineAuthAPIKey)
+	if err != nil {
+		return OC10Notification{}, err
+	}
+
+	space, err := ul.getSpace(ctx, spaceid)
+	if err != nil {
+		return OC10Notification{}, err
+	}
+
+	subj, subjraw, msg, msgraw, err := ul.composeMessage(eventname, map[string]string{
+		"username":  user.GetDisplayName(),
+		"spacename": space.GetName(),
+	})
+	if err != nil {
+		return OC10Notification{}, err
+	}
+
+	return OC10Notification{
+		EventID:        eventid,
+		Service:        ul.cfg.Service.Name,
+		UserName:       user.GetUsername(),
+		Timestamp:      ts.Format(time.RFC3339Nano),
+		ResourceID:     spaceid,
+		ResourceType:   _resourceTypeSpace,
+		Subject:        subj,
+		SubjectRaw:     subjraw,
+		Message:        msg,
+		MessageRaw:     msgraw,
+		MessageDetails: ul.getDetails(user, space, nil, nil),
+	}, nil
+}
+
+func (ul *UserlogService) shareMessage(eventid string, eventname string, executant *user.UserId, resourceid *storageprovider.ResourceId, shareid *collaboration.ShareId, ts time.Time) (OC10Notification, error) {
+	ctx, user, err := utils.Impersonate(executant, ul.gwClient, ul.cfg.MachineAuthAPIKey)
+	if err != nil {
+		return OC10Notification{}, err
+	}
+
+	info, err := ul.getResource(ctx, resourceid)
+	if err != nil {
+		return OC10Notification{}, err
+	}
+
+	subj, subjraw, msg, msgraw, err := ul.composeMessage(eventname, map[string]string{
+		"username":     user.GetDisplayName(),
+		"resourcename": info.GetName(),
+	})
+	if err != nil {
+		return OC10Notification{}, err
+	}
+
+	return OC10Notification{
+		EventID:        eventid,
+		Service:        ul.cfg.Service.Name,
+		UserName:       user.GetUsername(),
+		Timestamp:      ts.Format(time.RFC3339Nano),
+		ResourceID:     storagespace.FormatResourceID(*info.GetId()),
+		ResourceType:   _resourceTypeShare,
+		Subject:        subj,
+		SubjectRaw:     subjraw,
+		Message:        msg,
+		MessageRaw:     msgraw,
+		MessageDetails: ul.getDetails(user, nil, info, shareid),
+	}, nil
+}
+
+func (ul *UserlogService) composeMessage(eventname string, vars map[string]string) (string, string, string, string, error) {
+	tpl, ok := _templates[eventname]
+	if !ok {
+		return "", "", "", "", errors.New("unknown template name")
+	}
+
+	subject := ul.executeTemplate(tpl.Subject, vars)
+
+	subjectraw := ul.executeTemplate(tpl.Subject, map[string]string{
+		"username":     "{user}",
+		"spacename":    "{space}",
+		"resourcename": "{resource}",
+	})
+
+	message := ul.executeTemplate(tpl.Message, vars)
+
+	messageraw := ul.executeTemplate(tpl.Message, map[string]string{
+		"username":     "{user}",
+		"spacename":    "{space}",
+		"resourcename": "{resource}",
+	})
+
+	return subject, subjectraw, message, messageraw, nil
+
+}
+
+func (ul *UserlogService) getDetails(user *user.User, space *storageprovider.StorageSpace, item *storageprovider.ResourceInfo, shareid *collaboration.ShareId) map[string]interface{} {
+	details := make(map[string]interface{})
+
+	if user != nil {
+		details["user"] = map[string]string{
+			"id":          user.GetId().GetOpaqueId(),
+			"name":        user.GetUsername(),
+			"displayname": user.GetDisplayName(),
+		}
+	}
+
+	if space != nil {
+		details["space"] = map[string]string{
+			"id":   space.GetId().GetOpaqueId(),
+			"name": space.GetName(),
+		}
+	}
+
+	if item != nil {
+		details["resource"] = map[string]string{
+			"id":   storagespace.FormatResourceID(*item.GetId()),
+			"name": item.GetName(),
+		}
+	}
+
+	if shareid != nil {
+		details["share"] = map[string]string{
+			"id": shareid.GetOpaqueId(),
+		}
+	}
+
+	return details
+}
+
+func (ul *UserlogService) executeTemplate(tpl *template.Template, vars map[string]string) string {
+	var writer bytes.Buffer
+	if err := tpl.Execute(&writer, vars); err != nil {
+		ul.log.Error().Err(err).Str("templateName", tpl.Name()).Msg("cannot execute template")
+		return ""
+	}
+
+	return writer.String()
+}
diff --git a/services/userlog/pkg/service/http.go b/services/userlog/pkg/service/http.go
index 4ad2011ac12..725275e04d4 100644
--- a/services/userlog/pkg/service/http.go
+++ b/services/userlog/pkg/service/http.go
@@ -1,17 +1,10 @@
 package service
 
 import (
-	"context"
 	"encoding/json"
-	"errors"
-	"fmt"
 	"net/http"
-	"time"
 
-	storageprovider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
 	revactx "github.com/cs3org/reva/v2/pkg/ctx"
-	"github.com/cs3org/reva/v2/pkg/events"
-	ehmsg "github.com/owncloud/ocis/v2/protogen/gen/ocis/messages/eventhistory/v0"
 )
 
 // ServeHTTP fulfills Handler interface
@@ -37,7 +30,7 @@ func (ul *UserlogService) HandleGetEvents(w http.ResponseWriter, r *http.Request
 
 	resp := GetEventResponseOC10{}
 	for _, e := range evs {
-		noti, err := ul.convertEvent(r.Context(), e)
+		noti, err := ul.ConvertEvent(e)
 		if err != nil {
 			ul.log.Error().Err(err).Str("eventid", e.Id).Str("eventtype", e.Type).Msg("failed to convert event")
 			continue
@@ -60,14 +53,14 @@ func (ul *UserlogService) HandleDeleteEvents(w http.ResponseWriter, r *http.Requ
 		return
 	}
 
-	var ids []string
-	if err := json.NewDecoder(r.Body).Decode(&ids); err != nil {
+	var req DeleteEventsRequest
+	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
 		ul.log.Error().Err(err).Int("returned statuscode", http.StatusBadRequest).Msg("request body is malformed")
 		w.WriteHeader(http.StatusBadRequest)
 		return
 	}
 
-	if err := ul.DeleteEvents(u.GetId().GetOpaqueId(), ids); err != nil {
+	if err := ul.DeleteEvents(u.GetId().GetOpaqueId(), req.IDs); err != nil {
 		ul.log.Error().Err(err).Int("returned statuscode", http.StatusInternalServerError).Msg("delete events failed")
 		w.WriteHeader(http.StatusInternalServerError)
 		return
@@ -76,140 +69,6 @@ func (ul *UserlogService) HandleDeleteEvents(w http.ResponseWriter, r *http.Requ
 	w.WriteHeader(http.StatusOK)
 }
 
-func (ul *UserlogService) convertEvent(ctx context.Context, event *ehmsg.Event) (OC10Notification, error) {
-	etype, ok := ul.registeredEvents[event.Type]
-	if !ok {
-		// this should not happen
-		return OC10Notification{}, errors.New("eventtype not registered")
-	}
-
-	einterface, err := etype.Unmarshal(event.Event)
-	if err != nil {
-		// this shouldn't happen either
-		return OC10Notification{}, errors.New("cant unmarshal event")
-	}
-
-	noti := OC10Notification{
-		EventID:   event.Id,
-		Service:   "userlog",
-		Timestamp: time.Now().Format(time.RFC3339Nano),
-	}
-
-	// TODO: strange bug with getting space -> fix postponed to make master panic-free
-	var space storageprovider.StorageSpace
-	switch ev := einterface.(type) {
-	// file related
-	case events.UploadReady:
-		noti.UserID = ev.ExecutingUser.GetId().GetOpaqueId()
-		noti.Subject = "File uploaded"
-		noti.Message = fmt.Sprintf("File '%s' was uploaded to space '%s' by user '%s'", ev.Filename, space.GetName(), ev.ExecutingUser.GetUsername())
-	case events.ContainerCreated:
-		noti.UserID = ev.Executant.GetOpaqueId()
-		noti.Subject = "Folder created"
-		noti.Message = fmt.Sprintf("Folder '%s' was created", ev.Ref.GetPath())
-	case events.FileTouched:
-		noti.UserID = ev.Executant.GetOpaqueId()
-		noti.Subject = "File touched"
-		noti.Message = fmt.Sprintf("File '%s' was touched", ev.Ref.GetPath())
-	case events.FileDownloaded:
-		noti.UserID = ev.Executant.GetOpaqueId()
-		noti.Subject = "File downloaded"
-		noti.Message = fmt.Sprintf("File '%s' was downloaded", ev.Ref.GetPath())
-	case events.FileVersionRestored:
-		noti.UserID = ev.Executant.GetOpaqueId()
-		noti.Subject = "File version restored"
-		noti.Message = fmt.Sprintf("An older version of file '%s' was restored", ev.Ref.GetPath())
-	case events.ItemMoved:
-		noti.UserID = ev.Executant.GetOpaqueId()
-		noti.Subject = "File moved"
-		noti.Message = fmt.Sprintf("File '%s' was moved from '%s'", ev.Ref.GetPath(), ev.OldReference.GetPath())
-	case events.ItemTrashed:
-		noti.UserID = ev.Executant.GetOpaqueId()
-		noti.Subject = "File trashed"
-		noti.Message = fmt.Sprintf("File '%s' was trashed", ev.Ref.GetPath())
-	case events.ItemPurged:
-		noti.UserID = ev.Executant.GetOpaqueId()
-		noti.Subject = "File purged"
-		noti.Message = fmt.Sprintf("File '%s' was purged", ev.Ref.GetPath())
-	case events.ItemRestored:
-		noti.UserID = ev.Executant.GetOpaqueId()
-		noti.Subject = "File restored"
-		noti.Message = fmt.Sprintf("File '%s' was restored", ev.Ref.GetPath())
-
-	// space related
-	case events.SpaceCreated:
-		noti.UserID = ev.Executant.GetOpaqueId()
-		noti.Subject = "Space created"
-		noti.Message = fmt.Sprintf("Space '%s' was created", ev.Name)
-	case events.SpaceRenamed:
-		noti.UserID = ev.Executant.GetOpaqueId()
-		noti.Subject = "Space renamed"
-		noti.Message = fmt.Sprintf("Space '%s' was renamed", ev.Name)
-	case events.SpaceEnabled:
-		noti.UserID = ev.Executant.GetOpaqueId()
-		noti.Subject = "Space enabled"
-		noti.Message = fmt.Sprintf("Space '%s' was renamed", space.Name)
-	case events.SpaceDisabled:
-		noti.UserID = ev.Executant.GetOpaqueId()
-		noti.Subject = "Space disabled"
-		noti.Message = fmt.Sprintf("Space '%s' was disabled", space.Name)
-	case events.SpaceDeleted:
-		noti.UserID = ev.Executant.GetOpaqueId()
-		noti.Subject = "Space deleted"
-		noti.Message = fmt.Sprintf("Space '%s' was deleted", space.Name)
-	case events.SpaceShared:
-		noti.UserID = ev.Executant.GetOpaqueId()
-		noti.Subject = "Space shared"
-		noti.Message = fmt.Sprintf("Space '%s' was shared", space.Name)
-	case events.SpaceUnshared:
-		noti.UserID = ev.Executant.GetOpaqueId()
-		noti.Subject = "Space unshared"
-		noti.Message = fmt.Sprintf("Space '%s' was unshared", space.Name)
-	case events.SpaceUpdated:
-		noti.UserID = ev.Executant.GetOpaqueId()
-		noti.Subject = "Space updated"
-		noti.Message = fmt.Sprintf("Space '%s' was updated", space.Name)
-	case events.SpaceMembershipExpired:
-		noti.UserID = ""
-		noti.Subject = "Space membership expired"
-		noti.Message = fmt.Sprintf("A spacemembership for space '%s' has expired", space.Name)
-
-	// share related
-	case events.ShareCreated:
-		noti.UserID = ev.Executant.GetOpaqueId()
-		noti.Subject = "Share received"
-		noti.Message = fmt.Sprintf("A file was shared in space %s", space.Name)
-	case events.ShareUpdated:
-		noti.UserID = ev.Executant.GetOpaqueId()
-		noti.Subject = "Share updated"
-		noti.Message = fmt.Sprintf("A share was updated in space %s", space.Name)
-	case events.ShareExpired:
-		noti.Subject = "Share expired"
-		noti.Message = fmt.Sprintf("A share has expired in space %s", space.Name)
-	case events.LinkCreated:
-		noti.UserID = ev.Executant.GetOpaqueId()
-		noti.Subject = "Share received"
-		noti.Message = fmt.Sprintf("A link was created in space %s", space.Name)
-	case events.LinkUpdated:
-		noti.UserID = ev.Executant.GetOpaqueId()
-		noti.Subject = "Share received"
-		noti.Message = fmt.Sprintf("A link was updated in space %s", space.Name)
-	}
-
-	return noti, nil
-}
-
-// OC10Notification is the oc10 style representation of an event
-// some fields are left out for simplicity
-type OC10Notification struct {
-	EventID   string `json:"notification_id"`
-	Service   string `json:"app"`
-	Timestamp string `json:"datetime"`
-	UserID    string `json:"user"`
-	Subject   string `json:"subject"`
-	Message   string `json:"message"`
-}
-
 // GetEventResponseOC10 is the response from GET events endpoint in oc10 style
 type GetEventResponseOC10 struct {
 	OCS struct {
@@ -221,3 +80,8 @@ type GetEventResponseOC10 struct {
 		Data []OC10Notification `json:"data"`
 	} `json:"ocs"`
 }
+
+// DeleteEventsRequest is the expected body for the delete request
+type DeleteEventsRequest struct {
+	IDs []string `json:"ids"`
+}
diff --git a/services/userlog/pkg/service/service.go b/services/userlog/pkg/service/service.go
index 838f75dc9cf..3a8e8559974 100644
--- a/services/userlog/pkg/service/service.go
+++ b/services/userlog/pkg/service/service.go
@@ -25,7 +25,6 @@ import (
 // UserlogService is the service responsible for user activities
 type UserlogService struct {
 	log              log.Logger
-	ch               <-chan events.Event
 	m                *chi.Mux
 	store            store.Store
 	cfg              *config.Config
@@ -52,7 +51,6 @@ func NewUserlogService(opts ...Option) (*UserlogService, error) {
 
 	ul := &UserlogService{
 		log:              o.Logger,
-		ch:               ch,
 		m:                o.Mux,
 		store:            o.Store,
 		cfg:              o.Config,
@@ -71,80 +69,50 @@ func NewUserlogService(opts ...Option) (*UserlogService, error) {
 		r.Delete("/*", ul.HandleDeleteEvents)
 	})
 
-	go ul.MemorizeEvents()
+	go ul.MemorizeEvents(ch)
 
 	return ul, nil
 }
 
 // MemorizeEvents stores eventIDs a user wants to receive
-func (ul *UserlogService) MemorizeEvents() {
-	for event := range ul.ch {
+func (ul *UserlogService) MemorizeEvents(ch <-chan events.Event) {
+	for event := range ch {
 		// for each event we need to:
 		// I) find users eligible to receive the event
 		var (
 			users []string
 			err   error
 		)
+
 		switch e := event.Event.(type) {
 		default:
 			err = errors.New("unhandled event")
-
-		// file related
-		case events.UploadReady:
-			users, err = ul.findSpaceMembers(ul.impersonate(e.SpaceOwner), e.FileRef.GetResourceId().GetSpaceId(), viewer)
-		case events.ContainerCreated:
-			users, err = ul.findSpaceMembers(ul.impersonate(e.SpaceOwner), e.Ref.GetResourceId().GetSpaceId(), viewer)
-		case events.FileTouched:
-			users, err = ul.findSpaceMembers(ul.impersonate(e.SpaceOwner), e.Ref.GetResourceId().GetSpaceId(), viewer)
-		case events.FileDownloaded:
-			users, err = ul.findSpaceMembers(ul.impersonate(e.Executant), e.Ref.GetResourceId().GetSpaceId(), viewer) // no space owner in event
-		case events.FileVersionRestored:
-			users, err = ul.findSpaceMembers(ul.impersonate(e.SpaceOwner), e.Ref.GetResourceId().GetSpaceId(), editor)
-		case events.ItemMoved:
-			users, err = ul.findSpaceMembers(ul.impersonate(e.SpaceOwner), e.Ref.GetResourceId().GetSpaceId(), viewer)
-		case events.ItemTrashed:
-			users, err = ul.findSpaceMembers(ul.impersonate(e.SpaceOwner), e.Ref.GetResourceId().GetSpaceId(), viewer)
-		case events.ItemPurged:
-			users, err = ul.findSpaceMembers(ul.impersonate(e.Executant), e.Ref.GetResourceId().GetSpaceId(), editor) // no space owner in event
-		case events.ItemRestored:
-			users, err = ul.findSpaceMembers(ul.impersonate(e.SpaceOwner), e.Ref.GetResourceId().GetSpaceId(), viewer)
-
 		// space related // TODO: how to find spaceadmins?
-		case events.SpaceCreated:
-			users, err = ul.findSpaceMembers(ul.impersonate(e.Executant), e.ID.GetOpaqueId(), viewer)
-		case events.SpaceRenamed:
-			users, err = ul.findSpaceMembers(ul.impersonate(e.Executant), e.ID.GetOpaqueId(), viewer)
-		case events.SpaceEnabled:
-			users, err = ul.findSpaceMembers(ul.impersonate(e.Executant), e.ID.GetOpaqueId(), viewer)
 		case events.SpaceDisabled:
-			users, err = ul.findSpaceMembers(ul.impersonate(e.Executant), e.ID.GetOpaqueId(), manager)
+			users, err = ul.findSpaceMembers(ul.impersonate(e.Executant), e.ID.GetOpaqueId(), viewer)
 		case events.SpaceDeleted:
-			users, err = ul.findSpaceMembers(ul.impersonate(e.Executant), e.ID.GetOpaqueId(), manager)
+			for u, _ := range e.FinalMembers {
+				users = append(users, u)
+			}
 		case events.SpaceShared:
-			users, err = ul.findSpaceMembers(ul.impersonate(e.Executant), e.ID.GetOpaqueId(), manager)
+			users, err = ul.resolveID(ul.impersonate(e.Executant), e.GranteeUserID, e.GranteeGroupID)
 		case events.SpaceUnshared:
-			users, err = ul.findSpaceMembers(ul.impersonate(e.Executant), e.ID.GetOpaqueId(), manager)
-		case events.SpaceUpdated:
-			users, err = ul.findSpaceMembers(ul.impersonate(e.Executant), e.ID.GetOpaqueId(), manager)
+			users, err = ul.resolveID(ul.impersonate(e.Executant), e.GranteeUserID, e.GranteeGroupID)
 		case events.SpaceMembershipExpired:
-			users, err = ul.resolveShare(ul.impersonate(e.SpaceOwner), e.GranteeUserID, e.GranteeGroupID, e.SpaceID.GetOpaqueId())
+			users, err = ul.resolveID(ul.impersonate(e.SpaceOwner), e.GranteeUserID, e.GranteeGroupID)
 
 		// share related
 		case events.ShareCreated:
-			users, err = ul.resolveShare(ul.impersonate(e.Executant), e.GranteeUserID, e.GranteeGroupID, e.ItemID.GetSpaceId())
-		case events.ShareUpdated:
-			users, err = ul.resolveShare(ul.impersonate(e.Executant), e.GranteeUserID, e.GranteeGroupID, e.ItemID.GetSpaceId())
+			users, err = ul.resolveID(ul.impersonate(e.Executant), e.GranteeUserID, e.GranteeGroupID)
+		case events.ShareRemoved:
+			users, err = ul.resolveID(ul.impersonate(e.Executant), e.GranteeUserID, e.GranteeGroupID)
 		case events.ShareExpired:
-			users, err = ul.resolveShare(ul.impersonate(e.ShareOwner), e.GranteeUserID, e.GranteeGroupID, e.ItemID.GetSpaceId())
-		case events.LinkCreated:
-			users, err = ul.findSpaceMembers(ul.impersonate(e.Executant), e.ItemID.GetOpaqueId(), editor)
-		case events.LinkUpdated:
-			users, err = ul.findSpaceMembers(ul.impersonate(e.Executant), e.ItemID.GetOpaqueId(), editor)
-
+			users, err = ul.resolveID(ul.impersonate(e.ShareOwner), e.GranteeUserID, e.GranteeGroupID)
 		}
 
 		if err != nil {
-			ul.log.Error().Err(err).Interface("event", event).Msg("error gathering members for event")
+			// TODO: Find out why this errors on ci pipeline
+			ul.log.Debug().Err(err).Interface("event", event).Msg("error gathering members for event")
 			continue
 		}
 
@@ -218,20 +186,6 @@ func (ul *UserlogService) DeleteEvents(userid string, evids []string) error {
 	})
 }
 
-func (ul *UserlogService) impersonate(u *user.UserId) context.Context {
-	if u == nil {
-		ul.log.Debug().Msg("cannot impersonate nil user")
-		return nil
-	}
-
-	ctx, _, err := utils.Impersonate(u, ul.gwClient, ul.cfg.MachineAuthAPIKey)
-	if err != nil {
-		ul.log.Error().Err(err).Str("userid", u.GetOpaqueId()).Msg("failed to impersonate user")
-		return nil
-	}
-	return ctx
-}
-
 func (ul *UserlogService) addEventsToUser(userid string, eventids ...string) error {
 	return ul.alterUserEventList(userid, func(ids []string) []string {
 		return append(ids, eventids...)
@@ -318,23 +272,6 @@ func (ul *UserlogService) findSpaceMembers(ctx context.Context, spaceID string,
 	return users, nil
 }
 
-func (ul *UserlogService) getSpace(ctx context.Context, spaceID string) (*storageprovider.StorageSpace, error) {
-	res, err := ul.gwClient.ListStorageSpaces(ctx, listStorageSpaceRequest(spaceID))
-	if err != nil {
-		return nil, err
-	}
-
-	if res.GetStatus().GetCode() != rpc.Code_CODE_OK {
-		return nil, fmt.Errorf("Unexpected status code while getting space: %v", res.GetStatus().GetCode())
-	}
-
-	if len(res.StorageSpaces) == 0 {
-		return nil, fmt.Errorf("error getting storage space %s: no space returned", spaceID)
-	}
-
-	return res.StorageSpaces[0], nil
-}
-
 func (ul *UserlogService) gatherSpaceMembers(ctx context.Context, space *storageprovider.StorageSpace, hasRequiredRole permissionChecker) ([]string, error) {
 	var permissionsMap map[string]*storageprovider.ResourcePermissions
 	if err := utils.ReadJSONFromOpaque(space.GetOpaque(), "grants", &permissionsMap); err != nil {
@@ -378,49 +315,99 @@ func (ul *UserlogService) gatherSpaceMembers(ctx context.Context, space *storage
 	return users, nil
 }
 
+func (ul *UserlogService) resolveID(ctx context.Context, userid *user.UserId, groupid *group.GroupId) ([]string, error) {
+	if userid != nil {
+		return []string{userid.GetOpaqueId()}, nil
+	}
+
+	return ul.resolveGroup(ctx, groupid.GetOpaqueId())
+}
+
 // resolves the users of a group
 func (ul *UserlogService) resolveGroup(ctx context.Context, groupID string) ([]string, error) {
-	if ctx == nil {
-		return nil, errors.New("need authenticated context to resolve groups")
+	grp, err := ul.getGroup(ctx, groupID)
+	if err != nil {
+		return nil, err
 	}
 
-	r, err := ul.gwClient.GetGroup(ctx, &group.GetGroupRequest{GroupId: &group.GroupId{OpaqueId: groupID}})
+	var userIDs []string
+	for _, m := range grp.GetMembers() {
+		userIDs = append(userIDs, m.GetOpaqueId())
+	}
+
+	return userIDs, nil
+}
+
+func (ul *UserlogService) impersonate(u *user.UserId) context.Context {
+	if u == nil {
+		ul.log.Debug().Msg("cannot impersonate nil user")
+		return nil
+	}
+
+	ctx, _, err := utils.Impersonate(u, ul.gwClient, ul.cfg.MachineAuthAPIKey)
+	if err != nil {
+		ul.log.Error().Err(err).Str("userid", u.GetOpaqueId()).Msg("failed to impersonate user")
+		return nil
+	}
+	return ctx
+}
+
+func (ul *UserlogService) getSpace(ctx context.Context, spaceID string) (*storageprovider.StorageSpace, error) {
+	res, err := ul.gwClient.ListStorageSpaces(ctx, listStorageSpaceRequest(spaceID))
 	if err != nil {
 		return nil, err
 	}
 
-	if r.GetStatus().GetCode() != rpc.Code_CODE_OK {
-		return nil, fmt.Errorf("unexpected status code from gateway client: %d", r.GetStatus().GetCode())
+	if res.GetStatus().GetCode() != rpc.Code_CODE_OK {
+		return nil, fmt.Errorf("Unexpected status code while getting space: %v", res.GetStatus().GetCode())
 	}
 
-	var userIDs []string
-	for _, m := range r.GetGroup().GetMembers() {
-		userIDs = append(userIDs, m.GetOpaqueId())
+	if len(res.StorageSpaces) == 0 {
+		return nil, fmt.Errorf("error getting storage space %s: no space returned", spaceID)
 	}
 
-	return userIDs, nil
+	return res.StorageSpaces[0], nil
 }
 
-func (ul *UserlogService) resolveID(ctx context.Context, userid *user.UserId, groupid *group.GroupId) ([]string, error) {
-	if userid != nil {
-		return []string{userid.GetOpaqueId()}, nil
+func (ul *UserlogService) getUser(ctx context.Context, userid *user.UserId) (*user.User, error) {
+	getUserResponse, err := ul.gwClient.GetUser(context.Background(), &user.GetUserRequest{
+		UserId: userid,
+	})
+	if err != nil {
+		return nil, err
 	}
 
-	return ul.resolveGroup(ctx, groupid.GetOpaqueId())
+	if getUserResponse.Status.Code != rpc.Code_CODE_OK {
+		return nil, fmt.Errorf("error getting user: %s", getUserResponse.Status.Message)
+	}
+
+	return getUserResponse.GetUser(), nil
 }
 
-func (ul *UserlogService) resolveShare(ctx context.Context, userid *user.UserId, groupid *group.GroupId, spaceid string) ([]string, error) {
-	users, err := ul.resolveID(ctx, userid, groupid)
+func (ul *UserlogService) getGroup(ctx context.Context, groupid string) (*group.Group, error) {
+	r, err := ul.gwClient.GetGroup(ctx, &group.GetGroupRequest{GroupId: &group.GroupId{OpaqueId: groupid}})
 	if err != nil {
 		return nil, err
 	}
 
-	usr, err := ul.findSpaceMembers(ctx, spaceid, editor)
+	if r.GetStatus().GetCode() != rpc.Code_CODE_OK {
+		return nil, fmt.Errorf("unexpected status code from gateway client: %d", r.GetStatus().GetCode())
+	}
+
+	return r.GetGroup(), nil
+}
+
+func (ul *UserlogService) getResource(ctx context.Context, resourceid *storageprovider.ResourceId) (*storageprovider.ResourceInfo, error) {
+	res, err := ul.gwClient.Stat(ctx, &storageprovider.StatRequest{Ref: &storageprovider.Reference{ResourceId: resourceid}})
 	if err != nil {
 		return nil, err
 	}
 
-	return append(users, usr...), nil
+	if res.GetStatus().GetCode() != rpc.Code_CODE_OK {
+		return nil, fmt.Errorf("Unexpected status code while getting space: %v", res.GetStatus().GetCode())
+	}
+
+	return res.GetInfo(), nil
 }
 
 func listStorageSpaceRequest(spaceID string) *storageprovider.ListStorageSpacesRequest {
diff --git a/services/userlog/pkg/service/templates.go b/services/userlog/pkg/service/templates.go
new file mode 100644
index 00000000000..bc9bf33d2b7
--- /dev/null
+++ b/services/userlog/pkg/service/templates.go
@@ -0,0 +1,65 @@
+package service
+
+import "text/template"
+
+// the available templates
+var (
+	SpaceShared        = "space-shared"
+	SpaceSharedSubject = "Space shared"
+	SpaceSharedMessage = "{{ .username }} added you to Space {{ .spacename }}"
+
+	SpaceUnshared        = "space-unshared"
+	SpaceUnsharedSubject = "Removed from Space"
+	SpaceUnsharedMessage = "{{ .username }} removed you from Space {{ .spacename }}"
+
+	SpaceDisabled        = "space-disabled"
+	SpaceDisabledSubject = "Space disabled"
+	SpaceDisabledMessage = "{{ .username }} disabled Space {{ .spacename }}"
+
+	SpaceDeleted        = "space-deleted"
+	SpaceDeletedSubject = "Space deleted"
+	SpaceDeletedMessage = "{{ .username }} deleted Space {{ .spacename }}"
+
+	SpaceMembershipExpired        = "space-membership-expired"
+	SpaceMembershipExpiredSubject = "Membership expired"
+	SpaceMembershipExpiredMessage = "Access to Space {{ .spacename }} lost"
+
+	ShareCreated        = "item-shared"
+	ShareCreatedSubject = "Resource shared"
+	ShareCreatedMessage = "{{ .username }} shared {{ .resourcename }} with you"
+
+	ShareRemoved        = "item-unshared"
+	ShareRemovedSubject = "Resource unshared"
+	ShareRemovedMessage = "{{ .username }} unshared {{ .resourcename }} with you"
+
+	ShareExpired        = "share-expired"
+	ShareExpiredSubject = "Share expired"
+	ShareExpiredMessage = "Access to {{ .resourcename }} expired"
+)
+
+// rendered templates
+var (
+	_templates = map[string]NotificationTemplate{
+		SpaceShared:            notiTmpl(SpaceSharedSubject, SpaceSharedMessage),
+		SpaceUnshared:          notiTmpl(SpaceUnsharedSubject, SpaceUnsharedMessage),
+		SpaceDisabled:          notiTmpl(SpaceDisabledSubject, SpaceDisabledMessage),
+		SpaceDeleted:           notiTmpl(SpaceDeletedSubject, SpaceDeletedMessage),
+		SpaceMembershipExpired: notiTmpl(SpaceMembershipExpiredSubject, SpaceMembershipExpiredMessage),
+		ShareCreated:           notiTmpl(ShareCreatedSubject, ShareCreatedMessage),
+		ShareRemoved:           notiTmpl(ShareRemovedSubject, ShareRemovedMessage),
+		ShareExpired:           notiTmpl(ShareExpiredSubject, ShareExpiredMessage),
+	}
+)
+
+// NotificationTemplate is the data structure for the notifications
+type NotificationTemplate struct {
+	Subject *template.Template
+	Message *template.Template
+}
+
+func notiTmpl(subjectname string, messagename string) NotificationTemplate {
+	return NotificationTemplate{
+		Subject: template.Must(template.New("").Parse(subjectname)),
+		Message: template.Must(template.New("").Parse(messagename)),
+	}
+}


Test patch:
diff --git a/services/userlog/pkg/service/service_test.go b/services/userlog/pkg/service/service_test.go
index 724d4c7d92a..89ce6871fa2 100644
--- a/services/userlog/pkg/service/service_test.go
+++ b/services/userlog/pkg/service/service_test.go
@@ -64,7 +64,7 @@ var _ = Describe("UserlogService", func() {
 			service.GatewayClient(&gwc),
 			service.HistoryClient(&ehc),
 			service.RegisteredEvents([]events.Unmarshaller{
-				events.UploadReady{},
+				events.SpaceDisabled{},
 			}),
 		)
 		Expect(err).ToNot(HaveOccurred())
@@ -73,9 +73,11 @@ var _ = Describe("UserlogService", func() {
 
 	It("it stores, returns and deletes a couple of events", func() {
 		ids := make(map[string]struct{})
-		ids[bus.Publish(events.SpaceCreated{Executant: &user.UserId{OpaqueId: "userid"}})] = struct{}{}
-		ids[bus.Publish(events.UploadReady{SpaceOwner: &user.UserId{OpaqueId: "userid"}})] = struct{}{}
-		ids[bus.Publish(events.ContainerCreated{SpaceOwner: &user.UserId{OpaqueId: "userid"}})] = struct{}{}
+		ids[bus.Publish(events.SpaceDisabled{Executant: &user.UserId{OpaqueId: "userid"}})] = struct{}{}
+		ids[bus.Publish(events.SpaceDisabled{Executant: &user.UserId{OpaqueId: "userid"}})] = struct{}{}
+		ids[bus.Publish(events.SpaceDisabled{Executant: &user.UserId{OpaqueId: "userid"}})] = struct{}{}
+		// ids[bus.Publish(events.SpaceMembershipExpired{SpaceOwner: &user.UserId{OpaqueId: "userid"}})] = struct{}{}
+		// ids[bus.Publish(events.ShareCreated{Executant: &user.UserId{OpaqueId: "userid"}})] = struct{}{}
 
 		time.Sleep(500 * time.Millisecond)