Skip to content

Commit

Permalink
Up roles defaults (#7965)
Browse files Browse the repository at this point in the history
  • Loading branch information
diocas authored Feb 10, 2023
1 parent 824c190 commit bc05a41
Show file tree
Hide file tree
Showing 10 changed files with 73 additions and 31 deletions.
7 changes: 7 additions & 0 deletions changelog/unreleased/enhancement-optional-roles
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Enhancement: Optional Contributor role and configurable resharing permissions

We've added 2 new capabilities that modify the sharing Roles:
- `files_sharing.resharing_default` (default true): wether the resharing bit should be added to the normal roles (viewer, editor, etc) by default when re-sharing is enabled systemwise. If default is set false, users can still set resharing in the custom permissions role.
- `files_sharing.public.can_contribute` (default true): enables or disables the Contributor role for public links

https://github.com/owncloud/web/pull/7965
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ import {
useCapabilityFilesSharingAllowCustomPermissions,
useCapabilityFilesSharingCanDenyAccess,
useCapabilityFilesSharingResharing,
useCapabilityFilesSharingResharingDefault,
useCapabilityShareJailEnabled,
useStore
} from 'web-pkg/src/composables'
Expand Down Expand Up @@ -124,6 +125,7 @@ export default defineComponent({
return {
resource: inject<Resource>('resource'),
hasResharing: useCapabilityFilesSharingResharing(store),
resharingDefault: useCapabilityFilesSharingResharingDefault(store),
hasShareJail: useCapabilityShareJailEnabled(store),
hasRoleCustomPermissions: useCapabilityFilesSharingAllowCustomPermissions(store),
hasRoleDenyAccess: useCapabilityFilesSharingCanDenyAccess(store),
Expand Down Expand Up @@ -302,7 +304,9 @@ export default defineComponent({
const bitmask = this.selectedRole.hasCustomPermissions
? SharePermissions.permissionsToBitmask(this.customPermissions)
: SharePermissions.permissionsToBitmask(
this.selectedRole.permissions(this.hasResharing || this.resourceIsSpace)
this.selectedRole.permissions(
(this.hasResharing && this.resharingDefault) || this.resourceIsSpace
)
)
let path = this.resource.path
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,10 @@ import { DateTime } from 'luxon'
import EditDropdown from './EditDropdown.vue'
import RoleDropdown from './RoleDropdown.vue'
import { SharePermissions, ShareTypes } from 'web-client/src/helpers/share'
import { useCapabilityFilesSharingResharing } from 'web-pkg/src/composables'
import {
useCapabilityFilesSharingResharing,
useCapabilityFilesSharingResharingDefault
} from 'web-pkg/src/composables'
import { extractDomSelector } from 'web-client/src/helpers/resource'
import { defineComponent } from 'vue'
import * as uuid from 'uuid'
Expand Down Expand Up @@ -138,6 +141,7 @@ export default defineComponent({
setup() {
return {
hasResharing: useCapabilityFilesSharingResharing(),
resharingDefault: useCapabilityFilesSharingResharingDefault(),
...useGraphClient()
}
},
Expand Down Expand Up @@ -357,7 +361,9 @@ export default defineComponent({
const bitmask = role.hasCustomPermissions
? SharePermissions.permissionsToBitmask(permissions)
: SharePermissions.permissionsToBitmask(
role.permissions(this.hasResharing || this.isAnySpaceShareType)
role.permissions(
(this.hasResharing && this.resharingDefault) || this.isAnySpaceShareType
)
)
const changeMethod = this.isAnySpaceShareType ? this.changeSpaceMember : this.changeShare
changeMethod({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,10 @@
>
<span class="oc-flex oc-flex-middle">
<oc-icon :name="role.icon" class="oc-pl-s oc-pr-m" />
<role-item :role="role" :allow-share-permission="allowSharePermission" />
<role-item
:role="role"
:allow-share-permission="allowSharePermission && resharingDefault"
/>
</span>
<span class="oc-flex">
<oc-icon v-if="isSelectedRole(role)" name="check" />
Expand Down Expand Up @@ -117,6 +120,7 @@ import { defineComponent, inject, PropType } from 'vue'
import {
useCapabilityFilesSharingAllowCustomPermissions,
useCapabilityFilesSharingCanDenyAccess,
useCapabilityFilesSharingResharingDefault,
useStore
} from 'web-pkg/src/composables'
import { Resource } from 'web-client'
Expand Down Expand Up @@ -152,7 +156,8 @@ export default defineComponent({
resource: inject<Resource>('resource'),
incomingParentShare: inject<Resource>('incomingParentShare'),
hasRoleDenyAccess: useCapabilityFilesSharingCanDenyAccess(store),
hasRoleCustomPermissions: useCapabilityFilesSharingAllowCustomPermissions(store)
hasRoleCustomPermissions: useCapabilityFilesSharingAllowCustomPermissions(store),
resharingDefault: useCapabilityFilesSharingResharingDefault(store)
}
},
data() {
Expand Down Expand Up @@ -214,7 +219,7 @@ export default defineComponent({
return this.resource.type === 'space'
},
defaultCustomPermissions() {
return [...this.selectedRole.permissions(this.allowSharePermission)]
return [...this.selectedRole.permissions(this.allowSharePermission && this.resharingDefault)]
}
},
Expand Down Expand Up @@ -263,7 +268,7 @@ export default defineComponent({
return
}
this.selectedRole = role
this.customPermissions = role.permissions(this.allowSharePermission)
this.customPermissions = role.permissions(this.allowSharePermission && this.resharingDefault)
this.publishChange()
},
Expand All @@ -281,7 +286,7 @@ export default defineComponent({
this.selectedRole = PeopleShareRoles.getByBitmask(
bitmask,
this.resource.isFolder,
this.allowSharePermission
this.allowSharePermission && this.resharingDefault
)
this.publishChange()
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ import {
useCapabilityShareJailEnabled,
useCapabilityFilesSharingResharing,
useCapabilityFilesSharingPublicCanEdit,
useCapabilityFilesSharingPublicCanContribute,
useCapabilityFilesSharingPublicAlias
} from 'web-pkg/src/composables'
import { shareViaLinkHelp, shareViaIndirectLinkHelp } from '../../../helpers/contextualHelpers'
Expand Down Expand Up @@ -153,6 +154,7 @@ export default defineComponent({
hasShareJail: useCapabilityShareJailEnabled(),
hasResharing: useCapabilityFilesSharingResharing(),
hasPublicLinkEditing: useCapabilityFilesSharingPublicCanEdit(),
hasPublicLinkContribute: useCapabilityFilesSharingPublicCanContribute(),
hasPublicLinkAliasSupport: useCapabilityFilesSharingPublicAlias(),
indirectLinkListCollapsed,
linkListCollapsed
Expand Down Expand Up @@ -561,6 +563,7 @@ export default defineComponent({
this.incomingParentShare.permissions,
this.resource.isFolder,
this.hasPublicLinkEditing,
this.hasPublicLinkContribute,
this.hasPublicLinkAliasSupport,
!!link.password
)
Expand All @@ -569,6 +572,7 @@ export default defineComponent({
return LinkShareRoles.list(
this.resource.isFolder,
this.hasPublicLinkEditing,
this.hasPublicLinkContribute,
this.hasPublicLinkAliasSupport,
!!link.password
)
Expand Down
5 changes: 4 additions & 1 deletion packages/web-app-files/src/store/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ import { Language } from 'vue3-gettext'
import { DavProperty } from 'web-client/src/webdav/constants'

const allowSharePermissions = (getters) => {
return get(getters, `capabilities.files_sharing.resharing`, true)
return (
get(getters, `capabilities.files_sharing.resharing`, true) &&
get(getters, `capabilities.files_sharing.resharing_default`, true)
)
}

export default {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
import { mockDeep } from 'jest-mock-extended'
import { Resource } from 'web-client'

const availableRoleOptions = LinkShareRoles.list(false, true, true)
const availableRoleOptions = LinkShareRoles.list(false, true, true, true)

const exampleLink = {
name: 'Example link',
Expand Down
32 changes: 14 additions & 18 deletions packages/web-client/src/helpers/share/role.ts
Original file line number Diff line number Diff line change
Expand Up @@ -356,54 +356,50 @@ export abstract class PeopleShareRoles {
}

export abstract class LinkShareRoles {
static readonly all = [
linkRoleViewerFile,
linkRoleViewerFolder,
linkRoleContributorFolder,
linkRoleEditorFolder,
linkRoleUploaderFolder
]

static list(
isFolder: boolean,
canEditFile = false,
canContribute = false,
hasAliasLinks = false,
hasPassword = false
): ShareRole[] {
return [
...(hasAliasLinks && !hasPassword ? [linkRoleInternalFile, linkRoleInternalFolder] : []),
...this.all,
linkRoleViewerFile,
linkRoleViewerFolder,
...(canContribute ? [linkRoleContributorFolder] : []),
linkRoleEditorFolder,
linkRoleUploaderFolder,
...(canEditFile ? [linkRoleEditorFile] : [])
].filter((r) => r.folder === isFolder)
}

static getByBitmask(bitmask: number, isFolder: boolean): ShareRole {
return [...this.all, linkRoleEditorFile, linkRoleInternalFile, linkRoleInternalFolder] // Always return all roles
.find((r) => r.folder === isFolder && r.bitmask(false) === bitmask)
return this.list(isFolder, true, true, true, false).find((r) => r.bitmask(false) === bitmask)
}

/**
* Filter all roles that have either exactly the permissions from the bitmask or a subset of them.
* @param bitmask
* @param isFolder
* @param canEditFile
* @param canContribute
* @param hasAliasLinks
* @param hasPassword
*/
static filterByBitmask(
bitmask: number,
isFolder: boolean,
canEditFile = false,
canContribute = false,
hasAliasLinks = false,
hasPassword = false
): ShareRole[] {
return [
...(hasAliasLinks && !hasPassword ? [linkRoleInternalFile, linkRoleInternalFolder] : []),
...this.all,
...(canEditFile ? [linkRoleEditorFile] : [])
].filter((r) => {
return r.folder === isFolder && bitmask === (bitmask | r.bitmask(false))
})
return this.list(isFolder, canEditFile, canContribute, hasAliasLinks, hasPassword).filter(
(r) => {
return bitmask === (bitmask | r.bitmask(false))
}
)
}
}

Expand Down
15 changes: 12 additions & 3 deletions packages/web-client/tests/unit/helpers/share/role.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@ import {
linkRoleContributorFolder,
linkRoleEditorFolder,
linkRoleUploaderFolder,
linkRoleInternalFile,
linkRoleInternalFolder,
linkRoleViewerFile,
linkRoleViewerFolder,
LinkShareRoles,
linkRoleEditorFile,
peopleRoleCustomFile,
peopleRoleCustomFolder,
peopleRoleEditorFile,
Expand Down Expand Up @@ -219,18 +222,24 @@ describe('roles', () => {
'all folder related share roles',
{
folder: true,
result: LinkShareRoles.all.filter((r) => r.folder === true)
result: [
linkRoleInternalFolder,
linkRoleViewerFolder,
linkRoleContributorFolder,
linkRoleEditorFolder,
linkRoleUploaderFolder
]
}
],
[
'all file related share roles',
{
folder: false,
result: LinkShareRoles.all.filter((r) => r.folder === false)
result: [linkRoleInternalFile, linkRoleViewerFile, linkRoleEditorFile]
}
]
])('%s', (name: string, { folder, result }) => {
expect(LinkShareRoles.list(folder)).toEqual(result)
expect(LinkShareRoles.list(folder, true, true, true, false)).toEqual(result)
})
})
describe('getByBitmask', () => {
Expand Down
8 changes: 8 additions & 0 deletions packages/web-pkg/src/composables/capability/useCapability.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ export const useCapabilityFilesSharingResharing = createCapabilityComposable(
'files_sharing.resharing',
true
)
export const useCapabilityFilesSharingResharingDefault = createCapabilityComposable(
'files_sharing.resharing_default',
true
)

export const useCapabilitySpacesEnabled = createCapabilityComposable('spaces.enabled', false)
export const useCapabilityProjectSpacesEnabled = createCapabilityComposable(
Expand Down Expand Up @@ -69,6 +73,10 @@ export const useCapabilityFilesSharingPublicCanEdit = createCapabilityComposable
'files_sharing.public.can_edit',
false
)
export const useCapabilityFilesSharingPublicCanContribute = createCapabilityComposable(
'files_sharing.public.can_contribute',
true
)
export const useCapabilityFilesSharingPublicAlias = createCapabilityComposable(
'files_sharing.public.alias',
false
Expand Down

0 comments on commit bc05a41

Please sign in to comment.