Skip to content

Commit 507e694

Browse files
Merge pull request #14729 from nextcloud/feature/add-share-permissions
Feature - Add Custom Share Permissions
2 parents 419a14f + 3d2feb2 commit 507e694

40 files changed

Lines changed: 3713 additions & 1402 deletions

app/schemas/com.nextcloud.client.database.NextcloudDatabase/90.json

Lines changed: 1355 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 268 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,268 @@
1+
/*
2+
* Nextcloud - Android Client
3+
*
4+
* SPDX-FileCopyrightText: 2025 Alper Ozturk <alper.ozturk@nextcloud.com>
5+
* SPDX-License-Identifier: AGPL-3.0-or-later
6+
*/
7+
8+
package com.nextcloud.utils
9+
10+
import com.google.gson.Gson
11+
import com.owncloud.android.datamodel.quickPermission.QuickPermissionType
12+
import com.owncloud.android.lib.resources.shares.OCShare
13+
import com.owncloud.android.lib.resources.shares.ShareType
14+
import com.owncloud.android.lib.resources.shares.attributes.ShareAttributes
15+
import com.owncloud.android.ui.fragment.util.SharePermissionManager
16+
import junit.framework.TestCase.assertEquals
17+
import junit.framework.TestCase.assertFalse
18+
import junit.framework.TestCase.assertNotNull
19+
import junit.framework.TestCase.assertTrue
20+
import org.junit.Test
21+
22+
@Suppress("TooManyFunctions")
23+
class SharePermissionManagerTest {
24+
25+
private fun createShare(sharePermission: Int, isFolder: Boolean = false, attributesJson: String? = null): OCShare {
26+
return if (isFolder) {
27+
OCShare("/test")
28+
.apply {
29+
permissions = sharePermission
30+
attributes = attributesJson
31+
shareType = ShareType.INTERNAL
32+
sharedDate = 1188206955
33+
shareWith = "User 1"
34+
sharedWithDisplayName = "User 1"
35+
}
36+
} else {
37+
OCShare("/test.png")
38+
.apply {
39+
permissions = sharePermission
40+
attributes = attributesJson
41+
shareType = ShareType.INTERNAL
42+
sharedDate = 1188206955
43+
shareWith = "User 1"
44+
sharedWithDisplayName = "User 1"
45+
}
46+
}.apply {
47+
this.isFolder = isFolder
48+
}
49+
}
50+
51+
// region Permission change tests
52+
@Test
53+
fun testTogglePermissionShouldAddPermissionFlagWhenChecked() {
54+
val initialPermission = OCShare.READ_PERMISSION_FLAG
55+
val updatedPermission =
56+
SharePermissionManager.togglePermission(true, initialPermission, OCShare.UPDATE_PERMISSION_FLAG)
57+
val updatedShare = createShare(updatedPermission)
58+
assertTrue(SharePermissionManager.isCustomPermission(updatedShare))
59+
}
60+
61+
@Test
62+
fun testTogglePermissionShouldRemovePermissionFlagWhenUnchecked() {
63+
val initialPermission = OCShare.READ_PERMISSION_FLAG + OCShare.UPDATE_PERMISSION_FLAG
64+
val updatedPermission =
65+
SharePermissionManager.togglePermission(false, initialPermission, OCShare.UPDATE_PERMISSION_FLAG)
66+
val updatedShare = createShare(updatedPermission)
67+
assertTrue(SharePermissionManager.isViewOnly(updatedShare))
68+
}
69+
// endregion
70+
71+
// region HasPermissions tests
72+
@Test
73+
fun testHasPermissionShouldReturnTrueIfPermissionPresent() {
74+
val permission = OCShare.READ_PERMISSION_FLAG + OCShare.UPDATE_PERMISSION_FLAG
75+
assertTrue(SharePermissionManager.hasPermission(permission, OCShare.UPDATE_PERMISSION_FLAG))
76+
}
77+
78+
@Test
79+
fun testHasPermissionShouldReturnFalseIfPermissionNotPresent() {
80+
val permission = OCShare.READ_PERMISSION_FLAG
81+
assertFalse(SharePermissionManager.hasPermission(permission, OCShare.UPDATE_PERMISSION_FLAG))
82+
}
83+
// endregion
84+
85+
// region Helper Method Tests
86+
@Test
87+
fun testCanEditShouldReturnTrueIfAllPermissionsPresent() {
88+
val share = createShare(OCShare.MAXIMUM_PERMISSIONS_FOR_FOLDER, isFolder = true)
89+
assertTrue(SharePermissionManager.canEdit(share))
90+
}
91+
92+
@Test
93+
fun testCanEditShouldReturnFalseIfPermissionsAreInsufficient() {
94+
val share = createShare(OCShare.READ_PERMISSION_FLAG)
95+
assertFalse(SharePermissionManager.canEdit(share))
96+
}
97+
98+
@Test
99+
fun testIsViewOnlyShouldReturnTrueIfOnlyReadPermissionSet() {
100+
val share = createShare(OCShare.READ_PERMISSION_FLAG)
101+
assertTrue(SharePermissionManager.isViewOnly(share))
102+
}
103+
104+
@Test
105+
fun testIsFileRequestShouldReturnTrueIfOnlyCreatePermissionSetOnFolder() {
106+
val share = createShare(OCShare.CREATE_PERMISSION_FLAG, isFolder = true)
107+
assertTrue(SharePermissionManager.isFileRequest(share))
108+
}
109+
110+
@Test
111+
fun testIsFileRequestShouldReturnFalseIfOnlyCreatePermissionSetOnFile() {
112+
val share = createShare(OCShare.CREATE_PERMISSION_FLAG)
113+
assertFalse(SharePermissionManager.isFileRequest(share))
114+
}
115+
116+
@Test
117+
fun testIsSecureFileDropShouldReturnTrueIfReadAndCreatePermissionsPresent() {
118+
val permission = OCShare.READ_PERMISSION_FLAG + OCShare.CREATE_PERMISSION_FLAG
119+
val share = createShare(permission)
120+
assertTrue(SharePermissionManager.isSecureFileDrop(share))
121+
}
122+
123+
@Test
124+
fun testCanReshareShouldReturnTrueIfSharePermissionIsPresent() {
125+
val share = createShare(OCShare.SHARE_PERMISSION_FLAG)
126+
assertTrue(SharePermissionManager.canReshare(share))
127+
}
128+
129+
@Test
130+
fun testGetMaximumPermissionForFolder() {
131+
assertEquals(
132+
OCShare.MAXIMUM_PERMISSIONS_FOR_FOLDER,
133+
SharePermissionManager.getMaximumPermission(isFolder = true)
134+
)
135+
}
136+
137+
@Test
138+
fun testGetMaximumPermissionForFile() {
139+
assertEquals(
140+
OCShare.MAXIMUM_PERMISSIONS_FOR_FILE,
141+
SharePermissionManager.getMaximumPermission(isFolder = false)
142+
)
143+
}
144+
// endregion
145+
146+
// region GetSelectedTypeTests
147+
@Test
148+
fun testGetSelectedTypeShouldReturnCanEditWhenFullPermissionsGiven() {
149+
val share = createShare(OCShare.MAXIMUM_PERMISSIONS_FOR_FILE)
150+
assertEquals(QuickPermissionType.CAN_EDIT, SharePermissionManager.getSelectedType(share, encrypted = false))
151+
}
152+
153+
@Test
154+
fun testGetSelectedTypeShouldReturnSecureFileDropWhenEncryptedAndReadCreateGiven() {
155+
val permission = OCShare.READ_PERMISSION_FLAG + OCShare.CREATE_PERMISSION_FLAG
156+
val share = createShare(permission)
157+
assertEquals(
158+
QuickPermissionType.SECURE_FILE_DROP,
159+
SharePermissionManager.getSelectedType(share, encrypted = true)
160+
)
161+
}
162+
163+
@Test
164+
fun testGetSelectedTypeShouldReturnFileRequestWhenCreatePermissionGiven() {
165+
val share = createShare(OCShare.CREATE_PERMISSION_FLAG, isFolder = true)
166+
assertEquals(QuickPermissionType.FILE_REQUEST, SharePermissionManager.getSelectedType(share, encrypted = false))
167+
}
168+
169+
@Test
170+
fun testGetSelectedTypeShouldReturnViewOnlyWhenReadPermissionGiven() {
171+
val share = createShare(OCShare.READ_PERMISSION_FLAG)
172+
assertEquals(QuickPermissionType.VIEW_ONLY, SharePermissionManager.getSelectedType(share, encrypted = false))
173+
}
174+
175+
@Test
176+
fun testGetSelectedTypeShouldReturnCustomPermissionOnlyWhenCustomPermissionGiven() {
177+
val share = createShare(OCShare.READ_PERMISSION_FLAG + OCShare.UPDATE_PERMISSION_FLAG)
178+
assertEquals(
179+
QuickPermissionType.CUSTOM_PERMISSIONS,
180+
SharePermissionManager.getSelectedType(share, encrypted = false)
181+
)
182+
}
183+
184+
@Test
185+
fun testGetSelectedTypeShouldReturnNoneOnlyWhenNoPermissionGiven() {
186+
val share = createShare(OCShare.NO_PERMISSION)
187+
assertEquals(
188+
QuickPermissionType.NONE,
189+
SharePermissionManager.getSelectedType(share, encrypted = false)
190+
)
191+
}
192+
// endregion
193+
194+
// region CustomPermissions Tests
195+
@Test
196+
fun testIsCustomPermissionShouldReturnFalseWhenNoPermissionsGiven() {
197+
val permission = OCShare.NO_PERMISSION
198+
val share = createShare(permission, isFolder = false)
199+
assertFalse(SharePermissionManager.isCustomPermission(share))
200+
}
201+
202+
@Test
203+
fun testIsCustomPermissionShouldReturnFalseWhenNoReadPermissionsGiven() {
204+
val permission = OCShare.SHARE_PERMISSION_FLAG + OCShare.UPDATE_PERMISSION_FLAG
205+
val share = createShare(permission, isFolder = false)
206+
assertFalse(SharePermissionManager.isCustomPermission(share))
207+
}
208+
209+
@Test
210+
fun testIsCustomPermissionShouldReturnTrueWhenUpdatePermissionsGivenOnFile() {
211+
val permission = OCShare.READ_PERMISSION_FLAG + OCShare.UPDATE_PERMISSION_FLAG
212+
val share = createShare(permission, isFolder = false)
213+
assertTrue(SharePermissionManager.isCustomPermission(share))
214+
}
215+
216+
@Test
217+
fun testIsCustomPermissionShouldReturnTrueWhenUpdateAndSharePermissionsGivenOnFile() {
218+
val permission = OCShare.READ_PERMISSION_FLAG + OCShare.UPDATE_PERMISSION_FLAG + OCShare.SHARE_PERMISSION_FLAG
219+
val share = createShare(permission, isFolder = false)
220+
assertTrue(SharePermissionManager.isCustomPermission(share))
221+
}
222+
223+
@Test
224+
fun testIsCustomPermissionShouldReturnFalseWhenCreatePermissionsGivenOnFile() {
225+
val permission = OCShare.READ_PERMISSION_FLAG + OCShare.CREATE_PERMISSION_FLAG
226+
val share = createShare(permission, isFolder = false)
227+
assertFalse(SharePermissionManager.isCustomPermission(share))
228+
}
229+
230+
@Test
231+
fun testIsCustomPermissionShouldReturnFalseWhenDeletePermissionsGivenOnFile() {
232+
val permission = OCShare.READ_PERMISSION_FLAG + OCShare.DELETE_PERMISSION_FLAG
233+
val share = createShare(permission, isFolder = false)
234+
assertFalse(SharePermissionManager.isCustomPermission(share))
235+
}
236+
237+
@Test
238+
fun testIsCustomPermissionShouldReturnTrueWhenCreatePermissionsGivenOnFolder() {
239+
val permission = OCShare.READ_PERMISSION_FLAG + OCShare.CREATE_PERMISSION_FLAG
240+
val share = createShare(permission, isFolder = true)
241+
assertTrue(SharePermissionManager.isCustomPermission(share))
242+
}
243+
244+
@Test
245+
fun testIsCustomPermissionShouldReturnTrueWhenMixedPermissionsOnFile() {
246+
val permission = OCShare.READ_PERMISSION_FLAG + OCShare.UPDATE_PERMISSION_FLAG
247+
val share = createShare(permission, isFolder = false)
248+
assertTrue(SharePermissionManager.isCustomPermission(share))
249+
}
250+
// endregion
251+
252+
// region Attributes Tests
253+
@Test
254+
fun testToggleAllowDownloadAndSyncShouldCreateAttributeJsonIfNoneExists() {
255+
val json = SharePermissionManager.toggleAllowDownloadAndSync(true, null)
256+
assertNotNull(json)
257+
val downloadAttribute = ShareAttributes.createDownloadAttributes(true)
258+
val expectedJson = Gson().toJson(listOf(downloadAttribute))
259+
assertEquals(json, expectedJson)
260+
}
261+
262+
@Test
263+
fun testIsAllowDownloadAndSyncEnabledShouldReturnFalseIfAttributeIsMissing() {
264+
val share = createShare(OCShare.READ_PERMISSION_FLAG, attributesJson = null)
265+
assertFalse(SharePermissionManager.isAllowDownloadAndSyncEnabled(share))
266+
}
267+
// endregion
268+
}

0 commit comments

Comments
 (0)