Skip to content

Commit

Permalink
Show read-only user-attributes as locked (#8868)
Browse files Browse the repository at this point in the history
  • Loading branch information
Jan authored Apr 20, 2023
1 parent e66c36d commit c36227b
Show file tree
Hide file tree
Showing 7 changed files with 55 additions and 51 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Enhancement: Respect user read-only configuration by the server

The user edit dialog in the user management will respect the server's FRONTEND_READONLY_USER_ATTRIBUTES configuration,
recent fields will be disabled and will have a lock icon to visualize, that those fields are read-only.

https://github.com/owncloud/web/pull/8868
https://github.com/owncloud/web/issues/8840

Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
:label="$gettext('User name')"
:error-message="formData.userName.errorMessage"
:fix-message-line="true"
:read-only="isInputFieldReadOnly('user.onPremisesSamAccountName')"
@update:model-value="validateUserName"
/>
<oc-text-input
Expand All @@ -19,6 +20,7 @@
:label="$gettext('First and last name')"
:error-message="formData.displayName.errorMessage"
:fix-message-line="true"
:read-only="isInputFieldReadOnly('user.displayName')"
@update:model-value="validateDisplayName"
/>
<oc-text-input
Expand All @@ -29,6 +31,7 @@
:error-message="formData.email.errorMessage"
type="email"
:fix-message-line="true"
:read-only="isInputFieldReadOnly('user.mail')"
@change="validateEmail"
/>
<oc-text-input
Expand All @@ -39,6 +42,7 @@
type="password"
:fix-message-line="true"
placeholder="●●●●●●●●"
:read-only="isInputFieldReadOnly('user.passwordProfile')"
@update:model-value="onUpdatePassword"
/>
<div class="oc-mb-s">
Expand All @@ -49,6 +53,7 @@
option-label="displayName"
:options="translatedRoleOptions"
:clearable="false"
:read-only="isInputFieldReadOnly('user.appRoleAssignments')"
@update:model-value="onUpdateRole"
/>
<div class="oc-text-input-message"></div>
Expand All @@ -61,6 +66,7 @@
:label="$gettext('Login')"
:options="loginOptions"
:clearable="false"
:read-only="isInputFieldReadOnly('user.accountEnabled')"
@update:model-value="onUpdateLogin"
/>

Expand All @@ -71,15 +77,16 @@
:key="'quota-select-' + user.id"
:disabled="isQuotaInputDisabled"
class="oc-mb-s"
:title="$gettext('Personal quota')"
:label="$gettext('Personal quota')"
:total-quota="editUser.drive?.quota?.total || 0"
:max-quota="maxQuota"
:fix-message-line="true"
:description-message="
isQuotaInputDisabled
isQuotaInputDisabled && !isInputFieldReadOnly('drive.quota')
? $gettext('To set an individual quota, the user needs to have logged in once.')
: ''
"
:read-only="isInputFieldReadOnly('drive.quota')"
@selected-option-change="changeSelectedQuotaOption"
/>
<group-select
Expand Down Expand Up @@ -109,7 +116,7 @@ import GroupSelect from '../GroupSelect.vue'
import QuotaSelect from 'web-pkg/src/components/QuotaSelect.vue'
import { cloneDeep } from 'lodash-es'
import { AppRole, AppRoleAssignment, Group, User } from 'web-client/src/generated'
import { MaybeRef, useClientService, useStore } from 'web-pkg'
import { MaybeRef, useCapabilityReadOnlyUserAttributes, useClientService, useStore } from 'web-pkg'
import { useCapabilitySpacesMaxQuota } from 'web-pkg/src/composables'
export default defineComponent({
Expand Down Expand Up @@ -161,11 +168,15 @@ export default defineComponent({
(g) => !selectedGroups.some((s) => s.id === g.id) && !g.groupTypes?.includes('ReadOnly')
)
})
const isLoginInputDisabled = computed(() => currentUser.uuid === (props.user as User).id)
const readOnlyUserAttributes = useCapabilityReadOnlyUserAttributes()
const isInputFieldReadOnly = (key) => {
return unref(readOnlyUserAttributes).includes(key)
}
return {
maxQuota: useCapabilitySpacesMaxQuota(),
isInputFieldReadOnly,
isLoginInputDisabled,
editUser,
formData,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,18 @@ describe('EditPanel', () => {
expect(groupOptions.length).toBe(1)
expect(groupOptions[0].id).toEqual(availableGroupOptions[1].id)
})

describe('method "isInputFieldReadOnly"', () => {
it('should be true if included in capability ReadOnlyUserAttributes list', () => {
const { wrapper } = getWrapper({ readOnlyUserAttributes: ['user.displayName'] })
expect(wrapper.vm.isInputFieldReadOnly('user.displayName')).toBeTruthy()
})
it('should be false if not included in capability ReadOnlyUserAttributes list', () => {
const { wrapper } = getWrapper()
expect(wrapper.vm.isInputFieldReadOnly('user.displayName')).toBeFalsy()
})
})

describe('method "revertChanges"', () => {
it('should revert changes on property editUser', () => {
const { wrapper } = getWrapper()
Expand Down Expand Up @@ -159,9 +171,18 @@ describe('EditPanel', () => {
})
})

function getWrapper({ selectedGroups = [], groups = availableGroupOptions } = {}) {
function getWrapper({
readOnlyUserAttributes = [],
selectedGroups = [],
groups = availableGroupOptions
} = {}) {
const mocks = defaultComponentMocks()
const storeOptions = defaultStoreMockOptions
storeOptions.getters.capabilities.mockReturnValue({
graph: {
read_only_user_attributes: readOnlyUserAttributes
}
})
const store = createStore(storeOptions)
return {
mocks,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ exports[`EditPanel renders all available inputs 1`] = `
<oc-select-stub clearable="false" disabled="false" filter="[Function]" fixmessageline="false" id="login-input" label="Login" loading="false" model-value="[object Object]" multiple="false" optionlabel="label" options="[object Object],[object Object]" readonly="false" searchable="true"></oc-select-stub>
<div class="oc-text-input-message"></div>
</div>
<quota-select-stub class="oc-mb-s" descriptionmessage="" disabled="false" fixmessageline="true" id="quota-select-form" maxquota="0" title="Personal quota" totalquota="0"></quota-select-stub>
<quota-select-stub class="oc-mb-s" description-message="" disabled="false" fix-message-line="true" id="quota-select-form" label="Personal quota" maxquota="0" read-only="false" totalquota="0"></quota-select-stub>
<group-select-stub class="oc-mb-s" groupoptions="undefined,undefined" selectedgroups=""></group-select-stub>
</div>
<compare-save-dialog-stub class="edit-compare-save-dialog oc-mb-l" compareobject="[object Object]" confirmbuttondisabled="false" originalobject="[object Object]"></compare-save-dialog-stub>
Expand Down
46 changes: 2 additions & 44 deletions packages/web-pkg/src/components/QuotaSelect.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,17 @@
ref="select"
:model-value="selectedOption"
:selectable="optionSelectable"
:disabled="disabled"
taggable
push-tags
:clearable="false"
:options="options"
:create-option="createOption"
option-label="displayValue"
:label="title"
:fix-message-line="fixMessageLine"
:error-message="errorMessage"
:warning-message="warningMessage"
:description-message="descriptionMessage"
v-bind="$attrs"
@update:model-value="onUpdate"
>
<template #selected-option="{ displayValue }">
<oc-icon v-if="$attrs['read-only']" name="lock" class="oc-mr-xs" size="small" />
<span v-text="displayValue" />
</template>
<template #search="{ attributes, events }">
Expand All @@ -40,51 +36,13 @@ import { formatFileSize } from 'web-pkg'
export default {
name: 'QuotaSelect',
props: {
title: {
type: String,
required: true
},
totalQuota: {
type: Number,
default: 0
},
maxQuota: {
type: Number,
default: 0
},
disabled: {
type: Boolean,
default: false
},
/**
* Whether or not vertical space below the input should be reserved for a one line message,
* so that content actually appearing there doesn't shift the layout.
*/
fixMessageLine: {
type: Boolean,
default: false
},
/**
* A warning message which is shown below the select.
*/
warningMessage: {
type: String,
default: null
},
/**
* An error message which is shown below the select.
*/
errorMessage: {
type: String,
default: null
},
/**
* A description text which is shown below the select field.
*/
descriptionMessage: {
type: String,
default: null
}
},
emits: ['selectedOptionChange'],
Expand Down
2 changes: 1 addition & 1 deletion packages/web-pkg/src/components/Spaces/QuotaModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<template #content>
<quota-select
id="quota-select-batch-action-form"
:title="$gettext('Quota')"
:label="$gettext('Quota')"
:total-quota="selectedOption"
:max-quota="maxQuota"
@selected-option-change="changeSelectedQuotaOption"
Expand Down
6 changes: 6 additions & 0 deletions packages/web-pkg/src/composables/capability/useCapability.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,18 @@ export const useCapabilityFilesSharingResharingDefault = createCapabilityComposa

export const useCapabilitySpacesEnabled = createCapabilityComposable('spaces.enabled', false)
export const useCapabilitySpacesMaxQuota = createCapabilityComposable('spaces.max_quota', 0)

export const useCapabilityProjectSpacesEnabled = createCapabilityComposable(
'spaces.projects',
false
)
export const useCapabilityShareJailEnabled = createCapabilityComposable('spaces.share_jail', false)

export const useCapabilityReadOnlyUserAttributes = createCapabilityComposable(
'graph.read_only_user_attributes',
[]
)

export const useCapabilityFilesFavorites = createCapabilityComposable('files.favorites', false)

export const useCapabilityFilesTusSupportHttpMethodOverride = createCapabilityComposable<boolean>(
Expand Down

0 comments on commit c36227b

Please sign in to comment.