Repository: owncloud/ocis
Pull request #8907 (2024-04-19 12:36:37)

feat: add secure view share role
## Description
Adds a new share role "Secure View". This role is applicable for files, folders and spaces and only allows viewing them (and their content).



## Related Issue
<!--- This project only accepts pull requests related to open issues -->
<!--- If suggesting a new feature or change, please discuss it in an issue first -->
<!--- If fixing a bug, there should be an issue describing it with steps to reproduce -->
<!--- Please link to the issue here: -->
- refs https://github.com/owncloud/web/issues/10765

## Types of changes
<!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: -->
- [ ] Bug fix (non-breaking change which fixes an issue)
- [x] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to change)
- [ ] Technical debt
- [ ] Tests only (no source changes)


sonarcloud[bot]: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=owncloud_ocis&pullRequest=8907) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [1 New issue](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=8907&resolved=false&inNewCodePeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=8907&metric=new_accepted_issues&view=list)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=8907&resolved=false&inNewCodePeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=8907&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=8907&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarCloud](https://sonarcloud.io/dashboard?id=owncloud_ocis&pullRequest=8907)


sonarcloud[bot]: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=owncloud_ocis&pullRequest=8907) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=8907&resolved=false&inNewCodePeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=8907&metric=new_accepted_issues&view=list)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=8907&resolved=false&inNewCodePeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=8907&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=8907&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarCloud](https://sonarcloud.io/dashboard?id=owncloud_ocis&pullRequest=8907)


sonarcloud[bot]: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=owncloud_ocis&pullRequest=8907) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=8907&resolved=false&inNewCodePeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=8907&metric=new_accepted_issues&view=list)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=8907&resolved=false&inNewCodePeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [100.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=8907&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=8907&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarCloud](https://sonarcloud.io/dashboard?id=owncloud_ocis&pullRequest=8907)


sonarcloud[bot]: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=owncloud_ocis&pullRequest=8907) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=8907&resolved=false&inNewCodePeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=8907&metric=new_accepted_issues&view=list)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=8907&resolved=false&inNewCodePeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [100.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=8907&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=8907&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarCloud](https://sonarcloud.io/dashboard?id=owncloud_ocis&pullRequest=8907)


sonarcloud[bot]: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=owncloud_ocis&pullRequest=8907) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=8907&resolved=false&inNewCodePeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=8907&metric=new_accepted_issues&view=list)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=8907&resolved=false&inNewCodePeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [100.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=8907&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=8907&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarCloud](https://sonarcloud.io/dashboard?id=owncloud_ocis&pullRequest=8907)


sonarcloud[bot]: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=owncloud_ocis&pullRequest=8907) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=8907&resolved=false&inNewCodePeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=8907&metric=new_accepted_issues&view=list)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=8907&resolved=false&inNewCodePeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [100.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=8907&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=8907&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarCloud](https://sonarcloud.io/dashboard?id=owncloud_ocis&pullRequest=8907)


sonarcloud[bot]: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=owncloud_ocis&pullRequest=8907) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=8907&resolved=false&inNewCodePeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=8907&metric=new_accepted_issues&view=list)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=8907&resolved=false&inNewCodePeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [100.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=8907&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=8907&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarCloud](https://sonarcloud.io/dashboard?id=owncloud_ocis&pullRequest=8907)



Patch:
diff --git a/changelog/unreleased/sharing-secure-view-role.md b/changelog/unreleased/sharing-secure-view-role.md
new file mode 100644
index 00000000000..a60646f94d4
--- /dev/null
+++ b/changelog/unreleased/sharing-secure-view-role.md
@@ -0,0 +1,5 @@
+Enhancement: Secure viewer share role
+
+A new share role "Secure viewer" has been added. This role is applicable for files, folders and spaces and only allows viewing them (and their content).
+
+https://github.com/owncloud/ocis/pull/8907
diff --git a/services/graph/pkg/unifiedrole/unifiedrole.go b/services/graph/pkg/unifiedrole/unifiedrole.go
index c06d3d4bb15..cd20a93ec96 100644
--- a/services/graph/pkg/unifiedrole/unifiedrole.go
+++ b/services/graph/pkg/unifiedrole/unifiedrole.go
@@ -27,6 +27,8 @@ const (
 	UnifiedRoleUploaderID = "1c996275-f1c9-4e71-abdf-a42f6495e960"
 	// UnifiedRoleManagerID Unified role manager id.
 	UnifiedRoleManagerID = "312c0871-5ef7-4b3a-85b6-0e4074c64049"
+	// UnifiedRoleSecureViewerID Unified role secure viewer id.
+	UnifiedRoleSecureViewerID = "aa97fe03-7980-45ac-9e50-b325749fd7e6"
 
 	// UnifiedRoleConditionDrive defines constraint that matches a Driveroot/Spaceroot
 	UnifiedRoleConditionDrive = "exists @Resource.Root"
@@ -60,12 +62,13 @@ var legacyNames map[string]string = map[string]string{
 	UnifiedRoleViewerID: conversions.RoleViewer,
 	// one V1 api the "spaceviewer" role was call "viewer" and the "spaceeditor" was "editor",
 	// we need to stay compatible with that
-	UnifiedRoleSpaceViewerID: "viewer",
-	UnifiedRoleSpaceEditorID: "editor",
-	UnifiedRoleEditorID:      conversions.RoleEditor,
-	UnifiedRoleFileEditorID:  conversions.RoleFileEditor,
-	UnifiedRoleUploaderID:    conversions.RoleUploader,
-	UnifiedRoleManagerID:     conversions.RoleManager,
+	UnifiedRoleSpaceViewerID:  "viewer",
+	UnifiedRoleSpaceEditorID:  "editor",
+	UnifiedRoleEditorID:       conversions.RoleEditor,
+	UnifiedRoleFileEditorID:   conversions.RoleFileEditor,
+	UnifiedRoleUploaderID:     conversions.RoleUploader,
+	UnifiedRoleManagerID:      conversions.RoleManager,
+	UnifiedRoleSecureViewerID: conversions.RoleSecureViewer,
 }
 
 // NewViewerUnifiedRole creates a viewer role.
@@ -191,6 +194,31 @@ func NewManagerUnifiedRole() *libregraph.UnifiedRoleDefinition {
 	}
 }
 
+// NewSecureViewerUnifiedRole creates a secure viewer role
+func NewSecureViewerUnifiedRole() *libregraph.UnifiedRoleDefinition {
+	r := conversions.NewSecureViewerRole()
+	return &libregraph.UnifiedRoleDefinition{
+		Id:          proto.String(UnifiedRoleSecureViewerID),
+		Description: proto.String("View only documents, images and PDFs. Watermarks will be applied."),
+		DisplayName: displayName(r),
+		RolePermissions: []libregraph.UnifiedRolePermission{
+			{
+				AllowedResourceActions: convert(r),
+				Condition:              proto.String(UnifiedRoleConditionFile),
+			},
+			{
+				AllowedResourceActions: convert(r),
+				Condition:              proto.String(UnifiedRoleConditionFolder),
+			},
+			{
+				AllowedResourceActions: convert(r),
+				Condition:              proto.String(UnifiedRoleConditionDrive),
+			},
+		},
+		LibreGraphWeight: proto.Int32(0),
+	}
+}
+
 // NewUnifiedRoleFromID returns a unified role definition from the provided id
 func NewUnifiedRoleFromID(id string) (*libregraph.UnifiedRoleDefinition, error) {
 	for _, definition := range GetBuiltinRoleDefinitionList() {
@@ -213,6 +241,7 @@ func GetBuiltinRoleDefinitionList() []*libregraph.UnifiedRoleDefinition {
 		NewFileEditorUnifiedRole(),
 		NewUploaderUnifiedRole(),
 		NewManagerUnifiedRole(),
+		NewSecureViewerUnifiedRole(),
 	}
 }
 
@@ -476,6 +505,8 @@ func displayName(role *conversions.Role) *string {
 		displayName = "Can upload"
 	case conversions.RoleManager:
 		displayName = "Can manage"
+	case conversions.RoleSecureViewer:
+		displayName = "Can view (secure)"
 	default:
 		return nil
 	}


Test patch:
diff --git a/services/graph/pkg/unifiedrole/unifiedrole_test.go b/services/graph/pkg/unifiedrole/unifiedrole_test.go
index 5b0e21ba916..b8d95e3ae75 100644
--- a/services/graph/pkg/unifiedrole/unifiedrole_test.go
+++ b/services/graph/pkg/unifiedrole/unifiedrole_test.go
@@ -31,6 +31,9 @@ var _ = Describe("unifiedroles", func() {
 		Entry(rConversions.RoleManager, rConversions.NewManagerRole(), unifiedrole.NewManagerUnifiedRole(), unifiedrole.UnifiedRoleConditionDrive),
 		Entry(rConversions.RoleSpaceViewer, rConversions.NewSpaceViewerRole(), unifiedrole.NewSpaceViewerUnifiedRole(), unifiedrole.UnifiedRoleConditionDrive),
 		Entry(rConversions.RoleSpaceEditor, rConversions.NewSpaceEditorRole(), unifiedrole.NewSpaceEditorUnifiedRole(), unifiedrole.UnifiedRoleConditionDrive),
+		Entry(rConversions.RoleSecureViewer, rConversions.NewSecureViewerRole(), unifiedrole.NewSecureViewerUnifiedRole(), unifiedrole.UnifiedRoleConditionFile),
+		Entry(rConversions.RoleSecureViewer, rConversions.NewSecureViewerRole(), unifiedrole.NewSecureViewerUnifiedRole(), unifiedrole.UnifiedRoleConditionFolder),
+		Entry(rConversions.RoleSecureViewer, rConversions.NewSecureViewerRole(), unifiedrole.NewSecureViewerUnifiedRole(), unifiedrole.UnifiedRoleConditionDrive),
 	)
 
 	DescribeTable("UnifiedRolePermissionsToCS3ResourcePermissions",
@@ -54,6 +57,7 @@ var _ = Describe("unifiedroles", func() {
 		Entry(rConversions.RoleEditor, rConversions.NewEditorRole(), unifiedrole.NewEditorUnifiedRole(), true),
 		Entry(rConversions.RoleFileEditor, rConversions.NewFileEditorRole(), unifiedrole.NewFileEditorUnifiedRole(), true),
 		Entry(rConversions.RoleManager, rConversions.NewManagerRole(), unifiedrole.NewManagerUnifiedRole(), true),
+		Entry(rConversions.RoleSecureViewer, rConversions.NewSecureViewerRole(), unifiedrole.NewSecureViewerUnifiedRole(), true),
 		Entry("no match", rConversions.NewFileEditorRole(), unifiedrole.NewManagerUnifiedRole(), false),
 	)
 
@@ -135,6 +139,7 @@ var _ = Describe("unifiedroles", func() {
 				rolesToAction(unifiedrole.NewViewerUnifiedRole()),
 				unifiedrole.UnifiedRoleConditionFolder,
 				[]*libregraph.UnifiedRoleDefinition{
+					unifiedrole.NewSecureViewerUnifiedRole(),
 					unifiedrole.NewViewerUnifiedRole(),
 				},
 			),
@@ -144,6 +149,7 @@ var _ = Describe("unifiedroles", func() {
 				rolesToAction(unifiedrole.NewViewerUnifiedRole()),
 				unifiedrole.UnifiedRoleConditionFile,
 				[]*libregraph.UnifiedRoleDefinition{
+					unifiedrole.NewSecureViewerUnifiedRole(),
 					unifiedrole.NewViewerUnifiedRole(),
 				},
 			),
@@ -153,6 +159,7 @@ var _ = Describe("unifiedroles", func() {
 				rolesToAction(unifiedrole.NewFileEditorUnifiedRole()),
 				unifiedrole.UnifiedRoleConditionFile,
 				[]*libregraph.UnifiedRoleDefinition{
+					unifiedrole.NewSecureViewerUnifiedRole(),
 					unifiedrole.NewViewerUnifiedRole(),
 					unifiedrole.NewFileEditorUnifiedRole(),
 				},
@@ -163,6 +170,7 @@ var _ = Describe("unifiedroles", func() {
 				rolesToAction(unifiedrole.NewEditorUnifiedRole()),
 				unifiedrole.UnifiedRoleConditionFolder,
 				[]*libregraph.UnifiedRoleDefinition{
+					unifiedrole.NewSecureViewerUnifiedRole(),
 					unifiedrole.NewUploaderUnifiedRole(),
 					unifiedrole.NewViewerUnifiedRole(),
 					unifiedrole.NewEditorUnifiedRole(),
@@ -174,6 +182,7 @@ var _ = Describe("unifiedroles", func() {
 				rolesToAction(unifiedrole.GetBuiltinRoleDefinitionList()...),
 				unifiedrole.UnifiedRoleConditionFile,
 				[]*libregraph.UnifiedRoleDefinition{
+					unifiedrole.NewSecureViewerUnifiedRole(),
 					unifiedrole.NewViewerUnifiedRole(),
 					unifiedrole.NewFileEditorUnifiedRole(),
 				},
@@ -184,6 +193,7 @@ var _ = Describe("unifiedroles", func() {
 				rolesToAction(unifiedrole.GetBuiltinRoleDefinitionList()...),
 				unifiedrole.UnifiedRoleConditionFolder,
 				[]*libregraph.UnifiedRoleDefinition{
+					unifiedrole.NewSecureViewerUnifiedRole(),
 					unifiedrole.NewUploaderUnifiedRole(),
 					unifiedrole.NewViewerUnifiedRole(),
 					unifiedrole.NewEditorUnifiedRole(),
@@ -195,6 +205,7 @@ var _ = Describe("unifiedroles", func() {
 				rolesToAction(unifiedrole.GetBuiltinRoleDefinitionList()...),
 				unifiedrole.UnifiedRoleConditionDrive,
 				[]*libregraph.UnifiedRoleDefinition{
+					unifiedrole.NewSecureViewerUnifiedRole(),
 					unifiedrole.NewSpaceViewerUnifiedRole(),
 					unifiedrole.NewSpaceEditorUnifiedRole(),
 					unifiedrole.NewManagerUnifiedRole(),
diff --git a/tests/TestHelpers/GraphHelper.php b/tests/TestHelpers/GraphHelper.php
index f273ff6a047..d6596c9aa49 100644
--- a/tests/TestHelpers/GraphHelper.php
+++ b/tests/TestHelpers/GraphHelper.php
@@ -1642,6 +1642,8 @@ class GraphHelper {
 				return '1c996275-f1c9-4e71-abdf-a42f6495e960';
 			case 'Manager':
 				return '312c0871-5ef7-4b3a-85b6-0e4074c64049';
+			case 'Secure viewer':
+				return 'aa97fe03-7980-45ac-9e50-b325749fd7e6';
 			default:
 				throw new \Exception('Role ' . $permissionsRole . ' not found');
 		}
@@ -1674,6 +1676,8 @@ class GraphHelper {
 				return 'Space Editor';
 			case '312c0871-5ef7-4b3a-85b6-0e4074c64049':
 				return 'Manager';
+			case 'aa97fe03-7980-45ac-9e50-b325749fd7e6':
+				return 'Secure viewer';
 			default:
 				throw new \Exception('Permission role id: ' . $permissionsRoleId . ' not found');
 		}
diff --git a/tests/acceptance/features/apiSharingNg/listPermissions.feature b/tests/acceptance/features/apiSharingNg/listPermissions.feature
index 0186ebc0bb2..003b5ac0349 100644
--- a/tests/acceptance/features/apiSharingNg/listPermissions.feature
+++ b/tests/acceptance/features/apiSharingNg/listPermissions.feature
@@ -48,8 +48,8 @@ Feature: List a sharing permissions
           },
           "@libre.graph.permissions.roles.allowedValues": {
             "type": "array",
-            "minItems": 3,
-            "maxItems": 3,
+            "minItems": 4,
+            "maxItems": 4,
             "uniqueItems": true,
             "items": {
               "oneOf": [
@@ -68,6 +68,41 @@ Feature: List a sharing permissions
                         1
                       ]
                     },
+                    "description": {
+                      "type": "string",
+                      "enum": [
+                        "View only documents, images and PDFs. Watermarks will be applied."
+                      ]
+                    },
+                    "displayName": {
+                      "type": "string",
+                      "enum": [
+                        "Can view (secure)"
+                      ]
+                    },
+                    "id": {
+                      "type": "string",
+                      "enum": [
+                        "aa97fe03-7980-45ac-9e50-b325749fd7e6"
+                      ]
+                    }
+                  }
+                },
+                {
+                  "type": "object",
+                  "required": [
+                    "@libre.graph.weight",
+                    "description",
+                    "displayName",
+                    "id"
+                  ],
+                  "properties": {
+                    "@libre.graph.weight": {
+                      "type": "integer",
+                      "enum": [
+                        2
+                      ]
+                    },
                     "description": {
                       "type": "string",
                       "enum": [
@@ -100,7 +135,7 @@ Feature: List a sharing permissions
                     "@libre.graph.weight": {
                       "type": "integer",
                       "enum": [
-                        2
+                        3
                       ]
                     },
                     "description": {
@@ -135,7 +170,7 @@ Feature: List a sharing permissions
                     "@libre.graph.weight": {
                       "type": "integer",
                       "enum": [
-                        3
+                        4
                       ]
                     },
                     "description": {
@@ -207,8 +242,8 @@ Feature: List a sharing permissions
           },
           "@libre.graph.permissions.roles.allowedValues": {
             "type": "array",
-            "minItems": 3,
-            "maxItems": 3,
+            "minItems": 4,
+            "maxItems": 4,
             "uniqueItems": true,
             "items": {
               "oneOf":  [
@@ -224,6 +259,29 @@ Feature: List a sharing permissions
                     "@libre.graph.weight": {
                       "const": 1
                     },
+                    "description": {
+                      "const": "View only documents, images and PDFs. Watermarks will be applied."
+                    },
+                    "displayName": {
+                      "const": "Can view (secure)"
+                    },
+                    "id": {
+                      "const": "aa97fe03-7980-45ac-9e50-b325749fd7e6"
+                    }
+                  }
+                },
+                {
+                  "type": "object",
+                  "required": [
+                    "@libre.graph.weight",
+                    "description",
+                    "displayName",
+                    "id"
+                  ],
+                  "properties": {
+                    "@libre.graph.weight": {
+                      "const": 2
+                    },
                     "description": {
                       "const": "View and download."
                     },
@@ -245,7 +303,7 @@ Feature: List a sharing permissions
                   ],
                   "properties": {
                     "@libre.graph.weight": {
-                      "const": 2
+                      "const": 3
                     },
                     "description": {
                       "const": "View, download, upload, edit, add and delete."
@@ -268,7 +326,7 @@ Feature: List a sharing permissions
                   ],
                   "properties": {
                     "@libre.graph.weight": {
-                      "const": 3
+                      "const": 4
                     },
                     "description": {
                       "const": "View, download, upload, edit, add, delete and manage members."
@@ -341,8 +399,8 @@ Feature: List a sharing permissions
           },
           "@libre.graph.permissions.roles.allowedValues": {
             "type": "array",
-            "minItems": 3,
-            "maxItems": 3,
+            "minItems": 4,
+            "maxItems": 4,
             "uniqueItems": true,
             "items": {
               "oneOf":  [
@@ -358,6 +416,29 @@ Feature: List a sharing permissions
                     "@libre.graph.weight": {
                       "const": 1
                     },
+                    "description": {
+                      "const": "View only documents, images and PDFs. Watermarks will be applied."
+                    },
+                    "displayName": {
+                      "const": "Can view (secure)"
+                    },
+                    "id": {
+                      "const": "aa97fe03-7980-45ac-9e50-b325749fd7e6"
+                    }
+                  }
+                },
+                {
+                  "type": "object",
+                  "required": [
+                    "@libre.graph.weight",
+                    "description",
+                    "displayName",
+                    "id"
+                  ],
+                  "properties": {
+                    "@libre.graph.weight": {
+                      "const": 2
+                    },
                     "description": {
                       "const": "View and download."
                     },
@@ -379,7 +460,7 @@ Feature: List a sharing permissions
                   ],
                   "properties": {
                     "@libre.graph.weight": {
-                      "const": 2
+                      "const": 3
                     },
                     "description": {
                       "const": "View, download, upload, edit, add and delete."
@@ -402,7 +483,7 @@ Feature: List a sharing permissions
                   ],
                   "properties": {
                     "@libre.graph.weight": {
-                      "const": 3
+                      "const": 4
                     },
                     "description": {
                       "const": "View, download, upload, edit, add, delete and manage members."
@@ -603,8 +684,8 @@ Feature: List a sharing permissions
           },
           "@libre.graph.permissions.roles.allowedValues": {
             "type": "array",
-            "minItems": 2,
-            "maxItems": 2,
+            "minItems": 3,
+            "maxItems": 3,
             "uniqueItems": true,
             "items": {
               "oneOf":[
@@ -620,6 +701,29 @@ Feature: List a sharing permissions
                     "@libre.graph.weight": {
                       "const": 1
                     },
+                    "description": {
+                      "const": "View only documents, images and PDFs. Watermarks will be applied."
+                    },
+                    "displayName": {
+                      "const": "Can view (secure)"
+                    },
+                    "id": {
+                      "const": "aa97fe03-7980-45ac-9e50-b325749fd7e6"
+                    }
+                  }
+                },
+                {
+                  "type": "object",
+                  "required": [
+                    "@libre.graph.weight",
+                    "description",
+                    "displayName",
+                    "id"
+                  ],
+                  "properties": {
+                    "@libre.graph.weight": {
+                      "const": 2
+                    },
                     "description": {
                       "const": "View and download."
                     },
@@ -641,7 +745,7 @@ Feature: List a sharing permissions
                   ],
                   "properties": {
                     "@libre.graph.weight": {
-                      "const": 2
+                      "const": 3
                     },
                     "description": {
                       "const": "View, download and edit."
@@ -706,11 +810,34 @@ Feature: List a sharing permissions
           },
           "@libre.graph.permissions.roles.allowedValues": {
             "type": "array",
-            "minItems": 3,
-            "maxItems": 3,
+            "minItems": 4,
+            "maxItems": 4,
             "uniqueItems": true,
             "items": {
               "oneOf":[
+                {
+                  "type": "object",
+                  "required": [
+                    "@libre.graph.weight",
+                    "description",
+                    "displayName",
+                    "id"
+                  ],
+                  "properties": {
+                    "@libre.graph.weight": {
+                      "const": 1
+                    },
+                    "description": {
+                      "const": "View only documents, images and PDFs. Watermarks will be applied."
+                    },
+                    "displayName": {
+                      "const": "Can view (secure)"
+                    },
+                    "id": {
+                      "const": "aa97fe03-7980-45ac-9e50-b325749fd7e6"
+                    }
+                  }
+                },
               {
                 "type": "object",
                 "required": [
@@ -721,7 +848,7 @@ Feature: List a sharing permissions
                 ],
                 "properties": {
                   "@libre.graph.weight": {
-                    "const": 1
+                    "const": 2
                   },
                   "description": {
                     "const": "View, download and upload."
@@ -744,7 +871,7 @@ Feature: List a sharing permissions
                 ],
                 "properties": {
                   "@libre.graph.weight": {
-                    "const": 2
+                    "const": 3
                   },
                   "description": {
                     "const": "View and download."
@@ -767,7 +894,7 @@ Feature: List a sharing permissions
                 ],
                 "properties": {
                   "@libre.graph.weight": {
-                    "const": 3
+                    "const": 4
                   },
                   "description": {
                     "const": "View, download, upload, edit, add and delete."
@@ -832,8 +959,8 @@ Feature: List a sharing permissions
           },
           "@libre.graph.permissions.roles.allowedValues": {
             "type": "array",
-            "minItems": 2,
-            "maxItems": 2,
+            "minItems": 3,
+            "maxItems": 3,
             "uniqueItems": true,
             "items": {
               "oneOf":[
@@ -849,6 +976,29 @@ Feature: List a sharing permissions
                   "@libre.graph.weight": {
                     "const": 1
                   },
+                  "description": {
+                    "const": "View only documents, images and PDFs. Watermarks will be applied."
+                  },
+                  "displayName": {
+                    "const": "Can view (secure)"
+                  },
+                  "id": {
+                    "const": "aa97fe03-7980-45ac-9e50-b325749fd7e6"
+                  }
+                }
+              },
+              {
+                "type": "object",
+                "required": [
+                  "@libre.graph.weight",
+                  "description",
+                  "displayName",
+                  "id"
+                ],
+                "properties": {
+                  "@libre.graph.weight": {
+                    "const": 2
+                  },
                   "description": {
                     "const": "View and download."
                   },
@@ -870,7 +1020,7 @@ Feature: List a sharing permissions
                 ],
                 "properties": {
                   "@libre.graph.weight": {
-                    "const": 2
+                    "const": 3
                   },
                   "description": {
                     "const": "View, download and edit."
@@ -955,8 +1105,8 @@ Feature: List a sharing permissions
           },
           "@libre.graph.permissions.roles.allowedValues": {
             "type": "array",
-            "minItems": 3,
-            "maxItems": 3,
+            "minItems": 4,
+            "maxItems": 4,
             "uniqueItems": true,
             "items": {
               "oneOf":  [
@@ -972,6 +1122,29 @@ Feature: List a sharing permissions
                     "@libre.graph.weight": {
                       "const": 1
                     },
+                    "description": {
+                      "const": "View only documents, images and PDFs. Watermarks will be applied."
+                    },
+                    "displayName": {
+                      "const": "Can view (secure)"
+                    },
+                    "id": {
+                      "const": "aa97fe03-7980-45ac-9e50-b325749fd7e6"
+                    }
+                  }
+                },
+                {
+                  "type": "object",
+                  "required": [
+                    "@libre.graph.weight",
+                    "description",
+                    "displayName",
+                    "id"
+                  ],
+                  "properties": {
+                    "@libre.graph.weight": {
+                      "const": 2
+                    },
                     "description": {
                       "const": "View and download."
                     },
@@ -993,7 +1166,7 @@ Feature: List a sharing permissions
                   ],
                   "properties": {
                     "@libre.graph.weight": {
-                      "const": 2
+                      "const": 3
                     },
                     "description": {
                       "const": "View, download, upload, edit, add and delete."
@@ -1016,7 +1189,7 @@ Feature: List a sharing permissions
                   ],
                   "properties": {
                     "@libre.graph.weight": {
-                      "const": 3
+                      "const": 4
                     },
                     "description": {
                       "const": "View, download, upload, edit, add, delete and manage members."
@@ -1186,8 +1359,8 @@ Feature: List a sharing permissions
           },
           "@libre.graph.permissions.roles.allowedValues": {
             "type": "array",
-            "minItems": 1,
-            "maxItems": 1,
+            "minItems": 2,
+            "maxItems": 2,
             "uniqueItems": true,
             "items": {
               "oneOf":  [
@@ -1203,6 +1376,29 @@ Feature: List a sharing permissions
                     "@libre.graph.weight": {
                       "const": 1
                     },
+                    "description": {
+                      "const": "View only documents, images and PDFs. Watermarks will be applied."
+                    },
+                    "displayName": {
+                      "const": "Can view (secure)"
+                    },
+                    "id": {
+                      "const": "aa97fe03-7980-45ac-9e50-b325749fd7e6"
+                    }
+                  }
+                },
+                {
+                  "type": "object",
+                  "required": [
+                    "@libre.graph.weight",
+                    "description",
+                    "displayName",
+                    "id"
+                  ],
+                  "properties": {
+                    "@libre.graph.weight": {
+                      "const": 2
+                    },
                     "description": {
                       "const": "View and download."
                     },