update GroupList with protected permissions

This commit is contained in:
Axolotle 2020-11-03 20:14:56 +01:00
parent b263961d50
commit d347a283ec
3 changed files with 35 additions and 37 deletions

View file

@ -6,14 +6,14 @@
<icon :iname="searchIcon" v-if="searchIcon" /> <icon :iname="searchIcon" v-if="searchIcon" />
</b-input-group-prepend> </b-input-group-prepend>
<b-form-input <b-form-input
id="selectize" :class="visible ? null : 'collapsed'" :class="visible ? null : 'collapsed'"
aria-controls="collapse" :aria-expanded="visible ? 'true' : 'false'" aria-controls="collapse" :aria-expanded="visible ? 'true' : 'false'"
@focus="onInputFocus" @blur="onInputBlur" @keydown="onInputKeydown" @focus="onInputFocus" @blur="onInputBlur" @keydown="onInputKeydown"
v-model="search" ref="input" v-model="search" ref="input"
/> />
</b-input-group> </b-input-group>
<b-collapse id="collapse" ref="collapse" v-model="visible"> <b-collapse ref="collapse" v-model="visible">
<b-list-group tabindex="-1" @mouseover="onChoiceListOver" v-if="visible"> <b-list-group tabindex="-1" @mouseover="onChoiceListOver" v-if="visible">
<b-list-group-item <b-list-group-item
v-for="(item, index) in filteredChoices" :key="item" v-for="(item, index) in filteredChoices" :key="item"

View file

@ -9,6 +9,7 @@
<icon :iname="itemIcon" /> {{ item | filter(format) }} <icon :iname="itemIcon" /> {{ item | filter(format) }}
</b-button> </b-button>
<b-button <b-button
v-if="!removable || removable(item)"
class="remove-btn" variant="warning" class="remove-btn" variant="warning"
@click="onRemove(item)" @click="onRemove(item)"
@blur="onItemDeleteBlur" @blur="onItemDeleteBlur"
@ -43,7 +44,8 @@ export default {
choices: { type: Array, required: true }, choices: { type: Array, required: true },
searchIcon: { type: String, default: 'search' }, searchIcon: { type: String, default: 'search' },
ariaLabel: { type: String, required: true }, ariaLabel: { type: String, required: true },
format: { type: Function, default: null } format: { type: Function, default: null },
removable: { type: Function, default: null }
}, },
data: () => ({ data: () => ({

View file

@ -15,9 +15,9 @@
</div> </div>
<!-- PRIMARY GROUPS CARDS --> <!-- PRIMARY GROUPS CARDS -->
<template v-if="primaryGroups"> <template v-if="normalGroups">
<b-card <b-card
v-for="(group, name, index) in filteredPrimaryGroups" :key="name" v-for="(group, name, index) in filteredGroups" :key="name"
no-body no-body
> >
<b-card-header class="d-flex align-items-center"> <b-card-header class="d-flex align-items-center">
@ -76,7 +76,8 @@
:selected="group.permissions" :selected="group.permissions"
:aria-label="$t('group_add_permission')" :aria-label="$t('group_add_permission')"
:format="formatPermission" :format="formatPermission"
@change="onPermissionChanged({ ...$event, name, groupType: 'primary' })" :removable="name === 'visitors' ? removable : null"
@change="onPermissionChanged({ ...$event, name, groupType: 'normal' })"
/> />
</b-col> </b-col>
</b-row> </b-row>
@ -155,14 +156,15 @@ export default {
data: () => ({ data: () => ({
search: '', search: '',
primaryGroups: undefined, permissions: undefined,
normalGroups: undefined,
userGroups: undefined, userGroups: undefined,
groupToDelete: undefined groupToDelete: undefined
}), }),
computed: { computed: {
filteredPrimaryGroups () { filteredGroups () {
const groups = this.primaryGroups const groups = this.normalGroups
if (!groups) return if (!groups) return
const search = this.search.toLowerCase() const search = this.search.toLowerCase()
const filtered = {} const filtered = {}
@ -193,6 +195,7 @@ export default {
methods: { methods: {
onPermissionChanged ({ item, index, name, groupType, action }) { onPermissionChanged ({ item, index, name, groupType, action }) {
console.log(groupType)
const uri = 'users/permissions/' + item const uri = 'users/permissions/' + item
const data = { [action]: name } const data = { [action]: name }
const from = action === 'add' ? 'availablePermissions' : 'permissions' const from = action === 'add' ? 'availablePermissions' : 'permissions'
@ -209,8 +212,8 @@ export default {
const from = action === 'add' ? 'availableMembers' : 'members' const from = action === 'add' ? 'availableMembers' : 'members'
const to = action === 'add' ? 'members' : 'availableMembers' const to = action === 'add' ? 'members' : 'availableMembers'
this.$store.dispatch('PUT', { uri, data }).then(() => { this.$store.dispatch('PUT', { uri, data }).then(() => {
this.primaryGroups[name][from].splice(index, 1) this.normalGroups[name][from].splice(index, 1)
this.primaryGroups[name][to].push(item) this.normalGroups[name][to].push(item)
}) })
}, },
@ -219,18 +222,12 @@ export default {
}, },
// FIXME Find a way to pass a filter to a component // FIXME Find a way to pass a filter to a component
formatPermission: text => { formatPermission (name) {
let result = text.replace('.main', '') return this.permissions[name].label
if (result.includes('.')) { },
result = result.replace('.', ' (') + ')'
} removable (name) {
if (result === 'mail') return 'E-mail' return this.permissions[name].protected === false
else if (result === 'xmpp') return 'XMPP'
else {
return result.replace(/\w\S*/g, txt => {
return txt.charAt(0).toUpperCase() + txt.substring(1).toLowerCase()
})
}
}, },
deleteGroup () { deleteGroup () {
@ -238,7 +235,7 @@ export default {
this.$store.dispatch('DELETE', this.$store.dispatch('DELETE',
{ uri: 'users/groups', param: groupname, storeKey: 'groups' } { uri: 'users/groups', param: groupname, storeKey: 'groups' }
).then(() => { ).then(() => {
Vue.delete(this.primaryGroups, groupname) Vue.delete(this.groups, groupname)
}) })
this.groupToDelete = undefined this.groupToDelete = undefined
} }
@ -248,22 +245,20 @@ export default {
this.$store.dispatch('FETCH_ALL', [ this.$store.dispatch('FETCH_ALL', [
{ uri: 'users' }, { uri: 'users' },
{ uri: 'users/groups?full&include_primary_groups', storeKey: 'groups' }, { uri: 'users/groups?full&include_primary_groups', storeKey: 'groups' },
{ uri: 'users/permissions?short', storeKey: 'permissions' } { uri: 'users/permissions?full', storeKey: 'permissions' }
]).then(([users, groups, permissions]) => { ]).then(([users, allGroups, permissions]) => {
// Do not use computed properties to get values from the store here to avoid auto // Do not use computed properties to get values from the store here to avoid auto
// updates while modifying values. // updates while modifying values.
const normalGroups = {}
// pre-format the stored data for rendering
const primaryGroups = {}
const userGroups = {} const userGroups = {}
const userNames = Object.keys(users) const userNames = Object.keys(users)
for (const groupName in groups) {
for (const groupName in allGroups) {
// copy the group to unlink it from the store // copy the group to unlink it from the store
const group = { ...groups[groupName] } const group = { ...allGroups[groupName] }
group.availablePermissions = permissions.filter(perm => { group.availablePermissions = Object.keys(permissions).filter(perm => {
// Remove 'email' and 'xmpp' in visitors's permission choice list // Remove 'email', 'xmpp' and protected permissions in visitors's permission choice list
if (groupName === 'visitors' && ['mail.main', 'xmpp.main'].includes(perm)) { if (groupName === 'visitors' && (['mail.main', 'xmpp.main'].includes(perm) || permissions[perm].protected)) {
return false return false
} }
return !group.permissions.includes(perm) return !group.permissions.includes(perm)
@ -285,10 +280,11 @@ export default {
return !group.members.includes(name) return !group.members.includes(name)
}) })
} }
primaryGroups[groupName] = group normalGroups[groupName] = group
} }
this.primaryGroups = primaryGroups this.permissions = permissions
this.normalGroups = normalGroups
this.userGroups = userGroups this.userGroups = userGroups
}) })
}, },