Skip to content

Commit f4b0341

Browse files
authored
Merge pull request #2908 from nextcloud/backport/2903/stable26
[stable26] properly distinguish between inherited and unset permissions
2 parents e67d8ad + 25dadc1 commit f4b0341

File tree

6 files changed

+57
-26
lines changed

6 files changed

+57
-26
lines changed

β€Žappinfo/info.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Folders can be configured from *Group folders* in the admin settings.
1010
After a folder is created, the admin can give access to the folder to one or more groups, control their write/sharing permissions and assign a quota for the folder.
1111
1212
Note: Encrypting the contents of group folders is currently not supported.]]></description>
13-
<version>14.0.8</version>
13+
<version>14.0.9</version>
1414
<licence>agpl</licence>
1515
<author>Robin Appelman</author>
1616
<namespace>GroupFolders</namespace>

β€Žlib/DAV/ACLPlugin.php

+8-3
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ public function propFind(PropFind $propFind, INode $node): void {
133133

134134
ksort($rulesByPath);
135135
$inheritedPermissionsByMapping = [];
136+
$inheritedMaskByMapping = [];
136137
$mappings = [];
137138
foreach ($rulesByPath as $rules) {
138139
foreach ($rules as $rule) {
@@ -144,18 +145,22 @@ public function propFind(PropFind $propFind, INode $node): void {
144145
if (!isset($inheritedPermissionsByMapping[$mappingKey])) {
145146
$inheritedPermissionsByMapping[$mappingKey] = Constants::PERMISSION_ALL;
146147
}
148+
if (!isset($inheritedMaskByMapping[$mappingKey])) {
149+
$inheritedMaskByMapping[$mappingKey] = 0;
150+
}
147151
$inheritedPermissionsByMapping[$mappingKey] = $rule->applyPermissions($inheritedPermissionsByMapping[$mappingKey]);
152+
$inheritedMaskByMapping[$mappingKey] |= $rule->getMask();
148153
}
149154
}
150155

151-
return array_map(function ($mapping, $permissions) use ($fileInfo) {
156+
return array_map(function ($mapping, $permissions, $mask) use ($fileInfo) {
152157
return new Rule(
153158
$mapping,
154159
$fileInfo->getId(),
155-
Constants::PERMISSION_ALL,
160+
$mask,
156161
$permissions
157162
);
158-
}, $mappings, $inheritedPermissionsByMapping);
163+
}, $mappings, $inheritedPermissionsByMapping, $inheritedMaskByMapping);
159164
});
160165

161166
$propFind->handle(self::GROUP_FOLDER_ID, function () use ($fileInfo) {

β€Žsrc/client.js

+7
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,13 @@ class AclDavService {
218218
inheritedAclsById[id] = acl
219219
if (aclsById[id] == null) {
220220
aclsById[id] = acl
221+
222+
aclsById[id].inheritedMask = acl.mask
223+
aclsById[id].inheritedPermissions = acl.permissions
224+
aclsById[id].mask = 0
225+
} else {
226+
aclsById[id].inheritedMask = acl.mask
227+
aclsById[id].inheritedPermissions = acl.permissions
221228
}
222229
}
223230
return {

β€Žsrc/components/AclStateButton.vue

+16-7
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,12 @@
3535
<div v-else>
3636
<NcActions :aria-label="label" :v-tooltip="label">
3737
<template #icon>
38-
<component :is="icon" :size="16" />
38+
<component :is="icon" :size="16" :class="{inherited: isInherited}" />
3939
</template>
4040
<NcActionRadio name="state"
41-
:checked="state === STATES.INHERIT_ALLOW || state === STATES.INHERIT_DENY"
41+
:checked="state === STATES.INHERIT_ALLOW || state === STATES.INHERIT_DENY || state === STATES.INHERIT_DEFAULT"
4242
:disabled="disabled"
43-
@change="$emit('update', STATES.INHERIT_ALLOW)">
43+
@change="$emit('update', STATES.INHERIT_DEFAULT)">
4444
{{ t('groupfolders', 'Inherit permission') }}
4545
</NcActionRadio>
4646
<NcActionRadio name="state"
@@ -62,17 +62,19 @@
6262
<script>
6363
import Check from 'vue-material-design-icons/Check.vue'
6464
import Cancel from 'vue-material-design-icons/Cancel.vue'
65+
import Minus from 'vue-material-design-icons/Minus.vue'
6566
import NcButton from '@nextcloud/vue/dist/Components/NcButton.js'
6667
import NcPopoverMenu from '@nextcloud/vue/dist/Components/NcPopoverMenu.js'
6768
import NcActions from '@nextcloud/vue/dist/Components/NcActions.js'
6869
import NcActionRadio from '@nextcloud/vue/dist/Components/NcActionRadio.js'
6970
import Tooltip from '@nextcloud/vue/dist/Directives/Tooltip.js'
7071

71-
const STATES = {
72+
export const STATES = {
7273
INHERIT_DENY: 0,
7374
INHERIT_ALLOW: 1,
74-
SELF_DENY: 2,
75-
SELF_ALLOW: 3,
75+
INHERIT_DEFAULT: 2,
76+
SELF_DENY: 3,
77+
SELF_ALLOW: 4,
7678
}
7779

7880
export default {
@@ -113,10 +115,15 @@ export default {
113115
},
114116
computed: {
115117
isAllowed() {
116-
return this.state & 1
118+
return this.state === STATES.INHERIT_ALLOW || this.state === STATES.SELF_ALLOW || this.state === STATES.INHERIT_DEFAULT
119+
},
120+
isInherited() {
121+
return this.state === STATES.INHERIT_ALLOW || this.state === STATES.INHERIT_DENY || this.state === STATES.INHERIT_DEFAULT
117122
},
118123
icon() {
119124
switch (this.state) {
125+
case STATES.INHERIT_DEFAULT:
126+
return Minus
120127
case STATES.INHERIT_ALLOW:
121128
case STATES.SELF_ALLOW:
122129
return Check
@@ -126,6 +133,8 @@ export default {
126133
},
127134
label() {
128135
switch (this.state) {
136+
case STATES.INHERIT_DEFAULT:
137+
return t('groupfolders', 'Unset')
129138
case STATES.INHERIT_DENY:
130139
return t('groupfolders', 'Denied (Inherited permission)')
131140
case STATES.INHERIT_ALLOW:

β€Žsrc/components/SharingSidebarView.vue

+23-15
Original file line numberDiff line numberDiff line change
@@ -83,31 +83,31 @@
8383
{{ getFullDisplayName(item.mappingDisplayName, item.mappingType) }}
8484
</td>
8585
<td class="state-column">
86-
<AclStateButton :state="getState(OC.PERMISSION_READ, item.permissions, item.mask)"
86+
<AclStateButton :state="getState(OC.PERMISSION_READ, item)"
8787
:inherited="item.inherited"
8888
:disabled="loading"
8989
@update="changePermission(item, OC.PERMISSION_READ, $event)" />
9090
</td>
9191
<td class="state-column">
92-
<AclStateButton :state="getState(OC.PERMISSION_UPDATE, item.permissions, item.mask)"
92+
<AclStateButton :state="getState(OC.PERMISSION_UPDATE, item)"
9393
:inherited="item.inherited"
9494
:disabled="loading"
9595
@update="changePermission(item, OC.PERMISSION_UPDATE, $event)" />
9696
</td>
9797
<td v-if="model.type === 'dir'" class="state-column">
98-
<AclStateButton :state="getState(OC.PERMISSION_CREATE, item.permissions, item.mask)"
98+
<AclStateButton :state="getState(OC.PERMISSION_CREATE, item)"
9999
:inherited="item.inherited"
100100
:disabled="loading"
101101
@update="changePermission(item, OC.PERMISSION_CREATE, $event)" />
102102
</td>
103103
<td class="state-column">
104-
<AclStateButton :state="getState(OC.PERMISSION_DELETE, item.permissions, item.mask)"
104+
<AclStateButton :state="getState(OC.PERMISSION_DELETE, item)"
105105
:inherited="item.inherited"
106106
:disabled="loading"
107107
@update="changePermission(item, OC.PERMISSION_DELETE, $event)" />
108108
</td>
109109
<td class="state-column">
110-
<AclStateButton :state="getState(OC.PERMISSION_SHARE, item.permissions, item.mask)"
110+
<AclStateButton :state="getState(OC.PERMISSION_SHARE, item)"
111111
:inherited="item.inherited"
112112
:disabled="loading"
113113
@update="changePermission(item, OC.PERMISSION_SHARE, $event)" />
@@ -161,7 +161,7 @@
161161
import Vue from 'vue'
162162
import axios from '@nextcloud/axios'
163163
import { generateUrl } from '@nextcloud/router'
164-
import AclStateButton from './AclStateButton.vue'
164+
import AclStateButton, { STATES } from './AclStateButton.vue'
165165
import Rule from './../model/Rule.js'
166166
import BinaryTools from './../BinaryTools.js'
167167
import client from './../client.js'
@@ -211,8 +211,8 @@ export default {
211211
isAdmin() {
212212
return this.aclCanManage
213213
},
214-
isInherited() {
215-
return (permission, permissions, mask) => {
214+
isNotInherited() {
215+
return (permission, mask) => {
216216
return (permission & ~mask) === 0
217217
}
218218
},
@@ -222,10 +222,18 @@ export default {
222222
}
223223
},
224224
getState() {
225-
return (permission, permissions, mask) => {
226-
const inheritance = this.isInherited(permission, permissions, mask) << 1
227-
const permitted = this.isAllowed(permission, permissions)
228-
return inheritance | permitted
225+
return (permission, item) => {
226+
const permitted = this.isAllowed(permission, item.permissions)
227+
if (this.isNotInherited(permission, item.mask)) {
228+
return permitted ? STATES.SELF_ALLOW : STATES.SELF_DENY
229+
} else {
230+
const inheritPermitted = this.isAllowed(permission, item.inheritedPermissions)
231+
if (this.isNotInherited(permission, item.inheritedMask)) {
232+
return inheritPermitted ? STATES.INHERIT_ALLOW : STATES.INHERIT_DENY
233+
} else {
234+
return STATES.INHERIT_DEFAULT
235+
}
236+
}
229237
}
230238
},
231239
},
@@ -330,13 +338,13 @@ export default {
330338
},
331339
changePermission(item, permission, $event) {
332340
const index = this.list.indexOf(item)
333-
const inherit = ($event < 2)
334-
const allow = ($event & (0b01)) === 1
341+
const inherit = $event === STATES.INHERIT_ALLOW || $event === STATES.INHERIT_DENY || $event === STATES.INHERIT_DEFAULT
342+
const allow = $event === STATES.SELF_ALLOW
335343
const bit = BinaryTools.firstHigh(permission)
336344
item = item.clone()
337345
if (inherit) {
338346
item.mask = BinaryTools.clear(item.mask, bit)
339-
// TODO check if: we can ignore permissions, since they are inherited
347+
// we can ignore permissions, since they are inherited
340348
} else {
341349
item.mask = BinaryTools.set(item.mask, bit)
342350
if (allow) {

β€Žsrc/model/Rule.js

+2
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ export default class Rule {
3838
this.mask = mask
3939
this.permissions = permissions
4040
this.inherited = inherited
41+
this.inheritedMask = 0
42+
this.inheritedPermissions = 31
4143
}
4244

4345
getProperties() {

0 commit comments

Comments
Β (0)