@@ -93,13 +103,14 @@
diff --git a/packages/web-app-admin-settings/src/components/Users/GroupsModal.vue b/packages/web-app-admin-settings/src/components/Users/GroupsModal.vue
index ef6ce6f8997..1728b25e331 100644
--- a/packages/web-app-admin-settings/src/components/Users/GroupsModal.vue
+++ b/packages/web-app-admin-settings/src/components/Users/GroupsModal.vue
@@ -8,7 +8,7 @@
@confirm="$emit('confirm', { users, groups: selectedOptions })"
>
- {
const { memberOf: selectedGroups } = unref(editUser)
- return props.groups.filter((g) => !selectedGroups.some((s) => s.id === g.id))
+ return props.groups.filter(
+ (g) => !selectedGroups.some((s) => s.id === g.id) && !g.groupTypes?.includes('ReadOnly')
+ )
})
const isLoginInputDisabled = computed(() => currentUser.uuid === (props.user as User).id)
diff --git a/packages/web-app-admin-settings/src/composables/actions/groups/useGroupActionsDelete.ts b/packages/web-app-admin-settings/src/composables/actions/groups/useGroupActionsDelete.ts
index 08601efa5db..a22ad109756 100644
--- a/packages/web-app-admin-settings/src/composables/actions/groups/useGroupActionsDelete.ts
+++ b/packages/web-app-admin-settings/src/composables/actions/groups/useGroupActionsDelete.ts
@@ -86,7 +86,7 @@ export const useGroupActionsDelete = ({ store }: { store?: Store }) => {
},
handler,
isEnabled: ({ resources }) => {
- return !!resources.length
+ return !!resources.length && !resources.some((r) => r.groupTypes?.includes('ReadOnly'))
},
componentType: 'button',
class: 'oc-groups-actions-delete-trigger'
diff --git a/packages/web-app-admin-settings/src/composables/actions/groups/useGroupActionsEdit.ts b/packages/web-app-admin-settings/src/composables/actions/groups/useGroupActionsEdit.ts
index 976cb1777a0..bcc39b31da7 100644
--- a/packages/web-app-admin-settings/src/composables/actions/groups/useGroupActionsEdit.ts
+++ b/packages/web-app-admin-settings/src/composables/actions/groups/useGroupActionsEdit.ts
@@ -14,7 +14,7 @@ export const useGroupActionsEdit = () => {
label: () => $gettext('Edit'),
handler: () => eventBus.publish(SideBarEventTopics.openWithPanel, 'EditPanel'),
isEnabled: ({ resources }) => {
- return resources.length > 0
+ return resources.length === 1 && !resources[0].groupTypes?.includes('ReadOnly')
},
componentType: 'button',
class: 'oc-groups-actions-edit-trigger'
diff --git a/packages/web-app-admin-settings/src/views/Groups.vue b/packages/web-app-admin-settings/src/views/Groups.vue
index 69ae4b1d5b5..29937f35210 100644
--- a/packages/web-app-admin-settings/src/views/Groups.vue
+++ b/packages/web-app-admin-settings/src/views/Groups.vue
@@ -185,7 +185,9 @@ export default defineComponent({
title: this.$gettext('Edit group'),
component: EditPanel,
default: false,
- enabled: this.selectedGroups.length === 1,
+ enabled:
+ this.selectedGroups.length === 1 &&
+ !this.selectedGroups[0].groupTypes?.includes('ReadOnly'),
componentAttrs: {
group: this.selectedGroups.length === 1 ? this.selectedGroups[0] : null,
onConfirm: this.editGroup
diff --git a/packages/web-app-admin-settings/src/views/Users.vue b/packages/web-app-admin-settings/src/views/Users.vue
index 0670c81bb21..97106569bb0 100644
--- a/packages/web-app-admin-settings/src/views/Users.vue
+++ b/packages/web-app-admin-settings/src/views/Users.vue
@@ -111,7 +111,7 @@
(addToGroupsModalIsOpen = false)"
@confirm="addUsersToGroups"
@@ -119,7 +119,7 @@
(removeFromGroupsModalIsOpen = false)"
@confirm="removeUsersFromGroups"
@@ -180,7 +180,7 @@ import {
useUserActionsAddToGroups
} from '../composables/actions/users'
import { configurationManager } from 'web-pkg'
-import { Drive } from 'web-client/src/generated'
+import { Drive, Group } from 'web-client/src/generated'
export default defineComponent({
name: 'UsersView',
@@ -505,6 +505,10 @@ export default defineComponent({
}
}
+ const writableGroups = computed(() => {
+ return unref(groups).filter((g) => !g.groupTypes?.includes('ReadOnly'))
+ })
+
return {
...useSideBar(),
maxQuota: useCapabilitySpacesMaxQuota(),
@@ -533,7 +537,8 @@ export default defineComponent({
spaceQuotaUpdated,
selectedPersonalDrives,
addUsersToGroups,
- removeUsersFromGroups
+ removeUsersFromGroups,
+ writableGroups
}
},
computed: {
diff --git a/packages/web-app-admin-settings/tests/unit/components/Users/GroupSelect.spec.ts b/packages/web-app-admin-settings/tests/unit/components/Users/GroupSelect.spec.ts
index ac59af4be13..1159d13727b 100644
--- a/packages/web-app-admin-settings/tests/unit/components/Users/GroupSelect.spec.ts
+++ b/packages/web-app-admin-settings/tests/unit/components/Users/GroupSelect.spec.ts
@@ -3,28 +3,33 @@ import { defaultPlugins, shallowMount } from 'web-test-helpers'
import { mock } from 'jest-mock-extended'
import { Group } from 'web-client/src/generated'
-const groupMock = mock({ id: '1' })
+const groupMock = mock({ id: '1', groupTypes: [] })
describe('GroupSelect', () => {
it('renders the select input', () => {
const { wrapper } = getWrapper()
expect(wrapper.html()).toMatchSnapshot()
})
+ it('correctly maps the read-only state', () => {
+ const groupMock = mock({ id: '1', groupTypes: ['ReadOnly'] })
+ const { wrapper } = getWrapper(groupMock)
+ expect(wrapper.vm.selectedOptions[0].readonly).toBeTruthy()
+ })
it('emits "selectedOptionChange" on update', () => {
- const group = mock({ id: '2' })
+ const group = mock({ id: '2', groupTypes: [] })
const { wrapper } = getWrapper()
wrapper.vm.onUpdate(group)
expect(wrapper.emitted().selectedOptionChange).toBeTruthy()
- expect(wrapper.vm.selectedOption).toEqual(group)
+ expect(wrapper.vm.selectedOptions).toEqual(group)
})
})
-function getWrapper() {
+function getWrapper(group = groupMock) {
return {
wrapper: shallowMount(GroupSelect, {
props: {
- selectedGroups: [groupMock],
- groupOptions: [groupMock]
+ selectedGroups: [group],
+ groupOptions: [group]
},
global: {
plugins: [...defaultPlugins()]
diff --git a/packages/web-app-admin-settings/tests/unit/components/Users/SideBar/EditPanel.spec.ts b/packages/web-app-admin-settings/tests/unit/components/Users/SideBar/EditPanel.spec.ts
index ce15ef32e87..b35932d2ed6 100644
--- a/packages/web-app-admin-settings/tests/unit/components/Users/SideBar/EditPanel.spec.ts
+++ b/packages/web-app-admin-settings/tests/unit/components/Users/SideBar/EditPanel.spec.ts
@@ -12,8 +12,8 @@ import { Group } from 'web-client/src/generated'
import { AxiosResponse } from 'axios'
const availableGroupOptions = [
- mock({ id: '1', displayName: 'group1' }),
- mock({ id: '2', displayName: 'group2' })
+ mock({ id: '1', displayName: 'group1', groupTypes: [] }),
+ mock({ id: '2', displayName: 'group2', groupTypes: [] })
]
const selectors = {
groupSelectStub: 'group-select-stub'
@@ -132,9 +132,24 @@ describe('EditPanel', () => {
expect(wrapper.vm.invalidFormData).toBeTruthy()
})
})
+
+ describe('group select', () => {
+ it('takes all available groups', () => {
+ const { wrapper } = getWrapper()
+ expect(wrapper.findComponent('group-select-stub').props('groupOptions').length).toBe(
+ availableGroupOptions.length
+ )
+ })
+ it('filters out read-only groups', () => {
+ const { wrapper } = getWrapper({
+ groups: [mock({ id: '1', displayName: 'group1', groupTypes: ['ReadOnly'] })]
+ })
+ expect(wrapper.findComponent('group-select-stub').props('groupOptions').length).toBe(0)
+ })
+ })
})
-function getWrapper({ selectedGroups = [] } = {}) {
+function getWrapper({ selectedGroups = [], groups = availableGroupOptions } = {}) {
const mocks = defaultComponentMocks()
const storeOptions = defaultStoreMockOptions
const store = createStore(storeOptions)
@@ -151,7 +166,7 @@ function getWrapper({ selectedGroups = [] } = {}) {
memberOf: selectedGroups
},
roles: [{ id: '1', displayName: 'admin' }],
- groups: availableGroupOptions
+ groups
},
global: {
mocks,
diff --git a/packages/web-app-admin-settings/tests/unit/components/Users/__snapshots__/GroupSelect.spec.ts.snap b/packages/web-app-admin-settings/tests/unit/components/Users/__snapshots__/GroupSelect.spec.ts.snap
index 3970db1b321..22e1cc0d7fa 100644
--- a/packages/web-app-admin-settings/tests/unit/components/Users/__snapshots__/GroupSelect.spec.ts.snap
+++ b/packages/web-app-admin-settings/tests/unit/components/Users/__snapshots__/GroupSelect.spec.ts.snap
@@ -2,6 +2,6 @@
exports[`GroupSelect renders the select input 1`] = `
-
+
`;
diff --git a/packages/web-app-admin-settings/tests/unit/views/Groups.spec.ts b/packages/web-app-admin-settings/tests/unit/views/Groups.spec.ts
index bf21ae4d9da..278ec07f048 100644
--- a/packages/web-app-admin-settings/tests/unit/views/Groups.spec.ts
+++ b/packages/web-app-admin-settings/tests/unit/views/Groups.spec.ts
@@ -14,7 +14,7 @@ const selectors = { batchActionsStub: 'batch-actions-stub' }
const getClientServiceMock = () => {
const clientService = mockDeep()
clientService.graphAuthenticated.groups.listGroups.mockImplementation(() =>
- mockAxiosResolve({ value: [{ id: '1', name: 'users' }] })
+ mockAxiosResolve({ value: [{ id: '1', name: 'users', groupTypes: [] }] })
)
return clientService
}
@@ -85,25 +85,36 @@ describe('Groups view', () => {
})
describe('computed method "sideBarAvailablePanels"', () => {
- it('should contain EditPanel when one group is selected', () => {
- const { wrapper } = getWrapper()
- wrapper.vm.selectedGroups = [{ id: '1' }]
- expect(
- wrapper.vm.sideBarAvailablePanels.find((panel) => panel.app === 'EditPanel').enabled
- ).toBeTruthy()
+ describe('EditPanel', () => {
+ it('should be available when one group is selected', () => {
+ const { wrapper } = getWrapper()
+ wrapper.vm.selectedGroups = [{ id: '1' }]
+ expect(
+ wrapper.vm.sideBarAvailablePanels.find((panel) => panel.app === 'EditPanel')
+ ).toBeTruthy()
+ })
+ it('should not be available when multiple groups are selected', () => {
+ const { wrapper } = getWrapper()
+ wrapper.vm.selectedGroups = [{ id: '1' }, { id: '2' }]
+ expect(
+ wrapper.vm.sideBarAvailablePanels.find((panel) => panel.app === 'EditPanel')
+ ).toBeFalsy()
+ })
+ it('should not be available when one read-only group is selected', () => {
+ const { wrapper } = getWrapper()
+ wrapper.vm.selectedGroups = [{ id: '1', groupTypes: ['ReadOnly'] }]
+ expect(
+ wrapper.vm.sideBarAvailablePanels.find((panel) => panel.app === 'EditPanel')
+ ).toBeFalsy()
+ })
})
- it('should contain DetailsPanel when no group is selected', () => {
- const { wrapper } = getWrapper()
- expect(
- wrapper.vm.sideBarAvailablePanels.find((panel) => panel.app === 'DetailsPanel').enabled
- ).toBeTruthy()
- })
- it('should not contain EditPanel multiple groups are selected', () => {
- const { wrapper } = getWrapper()
- wrapper.vm.selectedGroups = [{ id: '1' }, { id: '2' }]
- expect(
- wrapper.vm.sideBarAvailablePanels.find((panel) => panel.app === 'EditPanel')
- ).toBeFalsy()
+ describe('DetailsPanel', () => {
+ it('should contain DetailsPanel when no group is selected', () => {
+ const { wrapper } = getWrapper()
+ expect(
+ wrapper.vm.sideBarAvailablePanels.find((panel) => panel.app === 'DetailsPanel')
+ ).toBeTruthy()
+ })
})
})