summaryrefslogtreecommitdiffstats
path: root/webapp
diff options
context:
space:
mode:
authorChristian Hofmaier2019-05-20 03:56:40 +0200
committerChristian Hofmaier2019-05-20 03:56:40 +0200
commit6d83a227b052837bee36a08503a042b90e5cf1cb (patch)
tree2074a020f0243ca0553e308915b3bdaf7991d936 /webapp
parent[eventmanager] add tutorial classes + fix 'name not empty' bug (diff)
downloadbas-6d83a227b052837bee36a08503a042b90e5cf1cb.tar.gz
bas-6d83a227b052837bee36a08503a042b90e5cf1cb.tar.xz
bas-6d83a227b052837bee36a08503a042b90e5cf1cb.zip
[permissionmanager] frontend rework
- bulk call for loading childs of groups - change submit to save/create - reload site after role changes - skip blacklist when no groups selected - performance improvements - new dialog system
Diffstat (limited to 'webapp')
-rw-r--r--webapp/src/components/PermissionModule.vue69
-rw-r--r--webapp/src/components/PermissionModuleDelete.vue65
-rw-r--r--webapp/src/components/PermissionModuleEdit.vue448
-rw-r--r--webapp/src/components/PermissionModuleGrantRevoke.vue166
-rw-r--r--webapp/src/components/PermissionModuleRoleList.vue45
-rw-r--r--webapp/src/components/PermissionModuleUserList.vue26
-rw-r--r--webapp/src/store/permissions.js82
7 files changed, 338 insertions, 563 deletions
diff --git a/webapp/src/components/PermissionModule.vue b/webapp/src/components/PermissionModule.vue
index 109007c..39d9b02 100644
--- a/webapp/src/components/PermissionModule.vue
+++ b/webapp/src/components/PermissionModule.vue
@@ -21,16 +21,13 @@
<v-container fill-height>
<v-layout>
<v-flex xl10 offset-xl1 lg12>
- <v-card class="tabbar-card">
- <v-tabs :dark="tabsDark" :color="tabsColor" :slider-color="tabsSliderColor"
- grow
- v-model="tab"
- >
+ <v-card class="elevation-3">
+ <v-tabs v-model="tabs" grow :dark="tabsDark" :color="tabsColor" :slider-color="tabsSliderColor">
<v-tab><v-icon class="tabbar-tabicon">verified_user</v-icon>{{ $t('roles') }}</v-tab>
<v-tab><v-icon class="tabbar-tabicon">people</v-icon>{{ $t('users') }}</v-tab>
</v-tabs>
</v-card>
- <v-tabs-items v-model="tab" v-if="canView">
+ <v-tabs-items v-model="tabs" style="padding-bottom: 20px">
<v-tab-item>
<v-subheader>{{ $t('roles') }}</v-subheader>
<permission-module-role-list/>
@@ -40,43 +37,22 @@
<permission-module-user-list/>
</v-tab-item>
</v-tabs-items>
- <v-tabs-items v-model="tab" v-else>
- <no-permission-error/>
- </v-tabs-items>
</v-flex>
</v-layout>
- <!--- Put Dialogs here (delete Dialog, edit Dialog, revoke Dialog, grant Dialog -->
<v-dialog
- :value="$store.state.permissions.dialog"
- @input="$store.commit('permissions/setDialog', $event )"
- max-width="500px"
+ :value="dialog.show"
+ @input="setDialog({ show: $event })"
+ :max-width="dialog.type === 'delete' ? '500px' : '1200px'"
scrollable
+ persistent
+ :fullscreen="$vuetify.breakpoint.smAndDown"
>
- <v-card>
- <v-card-title class="elevation-3">
- <div>
- <div class="headline">{{ $tc('delete-role', selectedRoles.length, [selectedRoles.length]) }}</div>
- </div>
- </v-card-title>
- <v-card-text>
- {{ $tc('delete-are-you-sure', selectedRoles.length) }}
- <template v-for="item in selectedRoles">
- <div class="grey--text" :key="item.id">[{{ item.id }}] {{ item.name }} ({{ item.descr }})</div>
- </template>
- </v-card-text>
- <v-divider></v-divider>
- <v-card-actions>
- <v-spacer></v-spacer>
- <v-btn flat="flat" @click="$store.commit('permissions/setDialog', false )">{{ $t('cancel') }}</v-btn>
- <v-btn color="error" @click="$store.commit('permissions/setDialog', false ); $store.dispatch('permissions/deleteSelectedRoles')">{{ $t('delete') }}</v-btn>
- </v-card-actions>
- </v-card>
+ <permission-module-edit v-if="dialog.type === 'edit'"/>
+ <permission-module-delete v-if="dialog.type === 'delete'"/>
+ <permission-module-grant-revoke v-else-if="dialog.type === 'grant'"/>
+ <permission-module-grant-revoke v-else-if="dialog.type === 'revoke'"/>
</v-dialog>
-
- <permission-module-grant-revoke :grant="$store.state.permissions.grant"/>
- <permission-module-edit :roleId="$store.state.permissions.roleId"/>
-
</v-container>
</template>
@@ -85,8 +61,8 @@ import PermissionModuleRoleList from '@/components/PermissionModuleRoleList'
import PermissionModuleUserList from '@/components/PermissionModuleUserList'
import PermissionModuleGrantRevoke from '@/components/PermissionModuleGrantRevoke'
import PermissionModuleEdit from '@/components/PermissionModuleEdit'
-import NoPermissionError from '@/components/NoPermissionError'
-import { mapState, mapGetters } from 'vuex'
+import PermissionModuleDelete from '@/components/PermissionModuleDelete'
+import { mapState, mapGetters, mapMutations } from 'vuex'
export default {
name: 'PermissionModule',
@@ -95,31 +71,28 @@ export default {
PermissionModuleUserList,
PermissionModuleGrantRevoke,
PermissionModuleEdit,
- NoPermissionError
+ PermissionModuleDelete
},
data () {
return {
- components: ['PermissionModuleRoleList', 'PermissionModuleUserList', 'NoPermissionError'],
- tab: 0,
- canView: false
+ tabs: 0
}
},
computed: {
...mapGetters(['tabsDark', 'tabsColor', 'tabsSliderColor']),
- ...mapState('permissions', ['selectedRoles', 'selectedUsers'])
+ ...mapState('permissions', ['dialog'])
},
methods: {
+ ...mapMutations('permissions', ['setDialog'])
},
created () {
- this.$http.get('/api/permissions/permissions.*').then(response => {
- this.canView = response.data
- })
- this.$store.dispatch('permissions/loadData')
+ this.$store.dispatch('permissions/loadLists')
+ this.$store.dispatch('groups/loadLists')
+ this.$store.dispatch('users/loadData')
}
}
</script>
-<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>
diff --git a/webapp/src/components/PermissionModuleDelete.vue b/webapp/src/components/PermissionModuleDelete.vue
new file mode 100644
index 0000000..01e4957
--- /dev/null
+++ b/webapp/src/components/PermissionModuleDelete.vue
@@ -0,0 +1,65 @@
+<i18n>
+{
+ "en": {
+ "delete-are-you-sure": "Are you sure you want to delete this role? | Are you sure you want to delete these roles?",
+ "roleDeleteSuccess": "Role deleted successfully | Roles deleted successfully"
+ },
+ "de": {
+ "delete-are-you-sure": "Sind sie sicher, dass sie diese Rolle Löschen wollen? | Sind sie sicher, dass sie diese Rollen löschen wollen?",
+ "roleDeleteSuccess": "Rolle erfolgreich gelöscht | Rollen erfolgreich gelöscht"
+ }
+}
+</i18n>
+
+<template>
+ <v-card>
+ <v-card-title class="elevation-3">
+ <div class="headline">{{ $t('title') }}</div>
+ </v-card-title>
+ <v-card-text>
+ {{ $tc('delete-are-you-sure', dialog.info.length) }}
+ <template v-for="item in dialog.info">
+ <div class="grey--text" :key="item.id">{{ item.name }} ({{ item.descr }})</div>
+ </template>
+ </v-card-text>
+ <v-divider></v-divider>
+ <v-card-actions>
+ <v-spacer></v-spacer>
+ <v-btn flat="flat" @click.native="$store.commit('permissions/setDialog', { show : false } )">{{ $t('cancel') }}</v-btn>
+ <v-btn color="error" @click="deleteRoles">{{ $t('delete') }}</v-btn>
+ </v-card-actions>
+ </v-card>
+</template>
+
+<script>
+import { mapState, mapMutations } from 'vuex'
+
+export default {
+ name: 'PermissionModuleDelete',
+ data () {
+ return {
+ }
+ },
+ computed: {
+ ...mapState('permissions', ['dialog'])
+ },
+ methods: {
+ ...mapMutations('permissions', ['setDialog', 'loadRoles']),
+ async deleteRoles () {
+ var deleteIds = []
+ for (let i = 0; i < this.dialog.info.length; i++) {
+ deleteIds.push(this.dialog.info[i].id)
+ }
+ await this.$http.post('/api/roles?delete', { ids: deleteIds })
+ this.setDialog({ show: false })
+ this.$snackbar({ color: 'success', text: this.$tc('roleDeleteSuccess', [deleteIds.length]) })
+ this.$store.dispatch('permissions/loadRoles')
+ }
+ }
+}
+</script>
+
+<!-- Add "scoped" attribute to limit CSS to this component only -->
+<style scoped>
+
+</style>
diff --git a/webapp/src/components/PermissionModuleEdit.vue b/webapp/src/components/PermissionModuleEdit.vue
index f88eb4c..7da3565 100644
--- a/webapp/src/components/PermissionModuleEdit.vue
+++ b/webapp/src/components/PermissionModuleEdit.vue
@@ -36,193 +36,104 @@
</i18n>
<template>
- <v-dialog
- :value="$store.state.permissions.edit"
- @input="$store.commit('permissions/setEdit', $event)"
- max-width="1000px"
- scrollable
- persistent
- >
- <v-card>
- <v-card-title class="dialog-title">
- <v-stepper v-model="step" horizontal style="width: 100%; background: transparent;" class="elevation-3">
- <v-stepper-header>
- <v-stepper-step
- :complete="stepCompleted >= 1"
- step="1"
- :editable="stepCompleted >= 0"
- edit-icon="check"
- >
- {{ $t('role') }}
- </v-stepper-step>
- <v-divider></v-divider>
- <v-stepper-step
- :complete="stepCompleted >= 2"
- step="2"
- :editable="stepCompleted >= 1"
- edit-icon="check"
- >
- {{ $t('permissions') }}
- </v-stepper-step>
- <v-divider></v-divider>
- <v-stepper-step
- :complete="stepCompleted >= 3"
- step="3"
- :editable="stepCompleted >= 2"
- edit-icon="check"
- >
- {{ $t('groups') }}
- </v-stepper-step>
- <v-divider></v-divider>
- <v-stepper-step
- :complete="stepCompleted >= 4"
- step="4"
- :editable="stepCompleted >= 3"
- edit-icon="check"
- >
- {{ $t('blacklist') }}
- </v-stepper-step>
- <v-divider></v-divider>
- <v-stepper-step
- :complete="stepCompleted >= 5"
- step="5"
- :editable="stepCompleted >= 4"
- edit-icon="check"
- >
- {{ $t('summary') }}
- </v-stepper-step>
- </v-stepper-header>
- </v-stepper>
- </v-card-title>
- <v-card-text class="table-container">
- <v-form v-model="valid" ref="form" @submit.prevent="submit" lazy-validation>
- <v-stepper v-model="step" horizontal style="width: 100%; background: transparent" class="elevation-0">
- <v-stepper-items>
-
- <v-stepper-content step="1">
- <v-text-field
- v-model="roleName"
- :label="$t('roleName')"
- prepend-icon="label"
- class="info-input"
- color="primary"
- :rules="[() => !!roleName || $t('roleNameEmptyError')]"
- ref="roleName"
- ></v-text-field>
-
- <v-textarea
- v-model="roleDescr"
- :label="$t('description')"
- prepend-icon="description"
- class="info-input"
- color="primary"
- rows="1"
- auto-grow
- ></v-textarea>
- </v-stepper-content>
-
- <v-stepper-content step="2" class="stepper-padding-0">
- <data-table v-model="permissionsSelected" :headers="permissionHeaders" :items="permissions"/>
- </v-stepper-content>
-
- <v-stepper-content step="3" class="stepper-padding-0">
- <data-table v-model="whitelist" :headers="groupHeaders" :items="groups" logging/>
- </v-stepper-content>
+ <v-card>
+ <v-card-title style="padding: 0px; z-index: 1">
+ <v-stepper v-model="step" horizontal style="width: 100%; background: transparent;" class="elevation-3">
+ <v-stepper-header>
+ <v-stepper-step
+ :complete="stepCompleted >= 1"
+ step="1"
+ :editable="stepCompleted >= 0"
+ edit-icon="check"
+ >
+ {{ $t('role') }}
+ </v-stepper-step>
+ <v-divider></v-divider>
+ <v-stepper-step
+ :complete="stepCompleted >= 2"
+ step="2"
+ :editable="stepCompleted >= 1"
+ edit-icon="check"
+ >
+ {{ $t('permissions') }}
+ </v-stepper-step>
+ <v-divider></v-divider>
+ <v-stepper-step
+ :complete="stepCompleted >= 3"
+ step="3"
+ :editable="stepCompleted >= 2"
+ edit-icon="check"
+ >
+ {{ $t('groups') }}
+ </v-stepper-step>
+ <v-divider></v-divider>
+ <v-stepper-step
+ :complete="stepCompleted >= 4"
+ step="4"
+ :editable="stepCompleted >= 3"
+ edit-icon="check"
+ >
+ {{ $t('blacklist') }}
+ </v-stepper-step>
+ </v-stepper-header>
+ </v-stepper>
+ </v-card-title>
+ <v-card-text class="pa-0">
+ <v-form v-model="valid" ref="form" @submit.prevent="submit" lazy-validation>
+ <v-stepper v-model="step" horizontal style="width: 100%; background: transparent" class="elevation-0">
+ <v-stepper-items>
+ <v-stepper-content step="1">
+ <v-layout row wrap>
+ <v-flex xs12 md5>
+ <v-text-field
+ :value="name"
+ @change="name = $event"
+ :label="$t('roleName')"
+ prepend-icon="label"
+ color="primary"
+ :rules="[v => !!v || $t('roleNameEmptyError')]"
+ ref="name"
+ ></v-text-field>
+ </v-flex>
+ <v-flex xs12 md5 offset-md1>
+ <v-textarea
+ :value="description"
+ @change="description = $event"
+ :label="$t('description')"
+ prepend-icon="description"
+ color="primary"
+ rows="1"
+ auto-grow
+ ></v-textarea>
+ </v-flex>
+ </v-layout>
+ </v-stepper-content>
- <v-stepper-content step="4" class="stepper-padding-0">
- <data-table v-model="blacklist" :headers="groupHeaders" :items="blacklistGroups"/>
- </v-stepper-content>
+ <v-stepper-content step="2" class="stepper-padding-0">
+ <data-table v-model="permissions" :headers="permissionHeaders" :items="permissionsList"/>
+ </v-stepper-content>
- <v-stepper-content step="5">
- <v-text-field
- v-model="roleName"
- :label="$t('roleName')"
- prepend-icon="label"
- class="info-input"
- color="primary"
- :rules="[() => !!roleName || $t('roleNameEmptyError')]"
- ref="roleName"
- disabled
- ></v-text-field>
+ <v-stepper-content step="3" class="stepper-padding-0">
+ <data-table v-model="groups" :headers="groupHeaders" :items="groupList" logging/>
+ </v-stepper-content>
- <v-textarea
- v-model="roleDescr"
- :label="$t('description')"
- prepend-icon="description"
- class="info-input"
- color="primary"
- rows="1"
- auto-grow
- disabled
- ></v-textarea>
- <v-layout row wrap>
- <v-flex xs12 sm6>
- <div>
- <v-subheader inset>{{ $t('permissions') }}</v-subheader>
- <v-divider class="list-header-margin"></v-divider>
- <RecycleScroller
- :items="permissionsSelected"
- :item-size="48"
- page-mode
- >
- <div slot-scope="{ item }" class="list-item">
- <div class="list-item-header">{{ item.name }}</div>
- <div class="list-item-subheader">{{ item.descr }}</div>
- </div>
- </RecycleScroller>
- </div>
- </v-flex>
- <v-flex xs12 sm6>
- <div>
- <v-subheader inset>{{ $t('groups') }}</v-subheader>
- <v-divider class="list-header-margin"></v-divider>
- <RecycleScroller
- :items="whitelist"
- :item-size="48"
- page-mode
- >
- <div slot-scope="{ item }" class="list-item">
- <div class="list-item-header">{{ item.id }} {{ item.name }}</div>
- <div class="list-item-subheader">{{ item.description }}</div>
- </div>
- </RecycleScroller>
- </div>
- </v-flex>
- <v-flex xs12 sm6>
- <div>
- <v-subheader inset>{{ $t('blacklist') }}</v-subheader>
- <v-divider class="list-header-margin"></v-divider>
- <RecycleScroller
- :items="blacklist"
- :item-size="48"
- page-mode
- >
- <div slot-scope="{ item }" class="list-item">
- <div class="list-item-header">{{ item.id }} {{ item.name }}</div>
- <div class="list-item-subheader">{{ item.description }}</div>
- </div>
- </RecycleScroller>
- </div>
- </v-flex>
- </v-layout>
- </v-stepper-content>
-
- </v-stepper-items>
- </v-stepper>
- </v-form>
- </v-card-text>
- <v-divider></v-divider>
- <v-card-actions>
- <v-spacer></v-spacer>
- <v-btn flat @click.native="$store.commit('permissions/setEdit', false )">{{ $t('cancel') }}</v-btn>
- <v-btn color="primary" v-show="step == 1" @click.native="completeStepOne()">{{ $t('continue') }}</v-btn>
- <v-btn color="primary" v-show="step == 2" @click.native="completeStepTwo()">{{ $t('continue') }}</v-btn>
- <v-btn color="primary" v-show="step == 3" @click.native="completeStepThree()">{{ $t('continue') }}</v-btn>
- <v-btn color="primary" v-show="step == 4" @click.native="completeStepFour()">{{ $t('continue') }}</v-btn>
- <v-btn class="success" v-show="step == 5" @click="submit" type="submit">{{ $t('submit') }}</v-btn>
- </v-card-actions>
- </v-card>
- </v-dialog>
+ <v-stepper-content step="4" class="stepper-padding-0">
+ <data-table v-model="blacklist" :headers="groupHeaders" :items="blacklistList"/>
+ </v-stepper-content>
+ </v-stepper-items>
+ </v-stepper>
+ </v-form>
+ </v-card-text>
+ <v-divider></v-divider>
+ <v-card-actions>
+ <v-spacer></v-spacer>
+ <v-btn flat @click.native="$store.commit('permissions/setDialog', { show : false } )">{{ $t('cancel') }}</v-btn>
+ <v-btn :color="dialog.info.id ? 'primary' : 'success'" @click="submit" type="submit">{{ dialog.info.id ? $t('save') : $t('create') }}</v-btn>
+ <v-btn color="primary" v-show="step == 1" @click.native="completeStepOne()">{{ $t('continue') }}</v-btn>
+ <v-btn color="primary" v-show="step == 2" @click.native="completeStepTwo()">{{ $t('continue') }}</v-btn>
+ <v-btn color="primary" v-show="step == 3 && groups.length > 0" @click.native="completeStepThree()">{{ $t('continue') }}</v-btn>
+ </v-card-actions>
+ </v-card>
</template>
<script>
@@ -231,7 +142,6 @@ import { mapState } from 'vuex'
export default {
name: 'PermissionModuleEdit',
- props: ['roleId'],
components: {
DataTable
},
@@ -240,9 +150,9 @@ export default {
valid: true,
step: 1,
stepCompleted: 0,
- blacklistGroups: [],
- permissionsSelected: [],
- whitelist: [],
+ blacklistList: [],
+ permissions: [],
+ groups: [],
blacklist: [],
permissionHeaders: [
{ text: this.$t('name'), key: 'name' },
@@ -254,58 +164,34 @@ export default {
{ text: this.$t('name'), key: 'name' },
{ text: this.$t('description'), key: 'description' }
],
- roleName: '',
- roleDescr: ''
+ name: '',
+ description: ''
}
},
methods: {
- submit (event) {
+ async submit (event) {
+ await this.loadChilds()
if (this.$refs.form.validate()) {
- const filteredPermissions = this.permissionsSelected.map(x => x.id)
- const filteredGroups = this.whitelist.map(x => x.id)
- const filteredBlacklist = this.blacklist.map(x => x.id)
- this.$http.post('/api/roles' + (this.roleId === 0 ? '' : '/' + this.roleId), {
- id: this.roleId,
- name: this.roleName,
- descr: this.roleDescr,
- permissions: filteredPermissions,
- groups: filteredGroups,
- blacklist: filteredBlacklist
- }).then(response => {
- this.$snackbar({ color: 'success', text: this.$t('roleSavedSuccess') })
- this.$store.dispatch('permissions/loadRoleData')
- this.$store.dispatch('permissions/loadUserData')
- this.$store.commit('permissions/setEdit', false)
- }).catch(error => {
- console.log(error)
+ const url = this.dialog.info.id === undefined ? '/api/roles' : '/api/roles/' + this.dialog.info.id
+ await this.$http.post(url, {
+ name: this.name,
+ description: this.description,
+ permissions: this.permissions.map(x => x.id),
+ groups: this.groups.map(x => x.id),
+ blacklist: this.blacklist.map(x => x.id)
})
+ this.$snackbar({ color: 'success', text: this.$t('roleSavedSuccess') })
+ this.$store.dispatch('permissions/loadRoles')
+ this.$store.dispatch('users/loadData')
+ this.$store.commit('permissions/setDialog', { show: false })
+ } else {
+ this.$snackbar({ color: 'error', text: this.$t('roleNameEmptyError') })
}
},
- async loadRole (roleId) {
- const response = await this.$http('/api/roles/' + this.roleId)
- this.roleName = response.data.name
- this.roleDescr = response.data.descr
- this.permissionsSelected = response.data.permissions
-
- var blacklistPush = []
- for (let i = 0; i < response.data.groups.length; i++) {
- if (response.data.groups[i].role_x_group.blacklist) {
- blacklistPush.push(response.data.groups[i])
- } else {
- this.whitelist.push(response.data.groups[i])
- }
- }
-
- this.loadChilds().then(() => {
- this.blacklist = this.blacklist.concat(blacklistPush)
- })
- },
completeStepOne () {
- if (this.roleName !== '') {
+ if (this.$refs.form.validate()) {
this.step = 2
this.stepCompleted = Math.max(1, this.stepCompleted)
- } else {
- this.$refs.form.validate()
}
},
completeStepTwo () {
@@ -313,89 +199,63 @@ export default {
this.stepCompleted = Math.max(2, this.stepCompleted)
},
completeStepThree () {
+ this.loadChilds()
this.step = 4
this.stepCompleted = Math.max(3, this.stepCompleted)
- this.loadChilds()
- },
- completeStepFour () {
- this.step = 5
- this.stepCompleted = Math.max(4, this.stepCompleted)
},
async loadChilds () {
- this.blacklistGroups = []
- var promises = []
- this.whitelist.forEach(group => {
- promises.push(
- this.$http('/api/groups/' + group.id + '?all').then(response => {
- this.blacklistGroups = this.blacklistGroups.concat(response.data.subgroups)
- }))
- })
- await Promise.all(promises)
+ if (this.groups.length > 0) {
+ var response = await this.$http.post('/api/events/blacklist', { groups: this.groups })
+ this.blacklistList = response.data.subgroups
+ this.blacklist = this.blacklist.filter(g => this.blacklistList.map(x => x.id).indexOf(g.id) !== -1)
+ } else {
+ this.blacklist = []
+ this.blacklistList = []
+ }
}
},
computed: {
- ...mapState('permissions', ['permissions', 'groups']),
- edit: function () {
- return this.$store.state.permissions.edit
- }
+ ...mapState('permissions', ['dialog', 'permissionsList']),
+ ...mapState('groups', ['groupList'])
},
watch: {
- edit: function (value) {
- if (value) {
- this.$refs.form.resetValidation()
- this.permissionsSelected = []
- this.whitelist = []
- this.blacklist = []
- this.step = 1
- if (this.roleId !== 0) {
- this.loadRole(this.roleId)
- this.stepCompleted = 5
- } else {
- this.roleName = ''
- this.roleDescr = ''
- this.stepCompleted = 0
+ step (val) {
+ if (val === '3') this.loadChilds()
+ },
+ dialog: {
+ immediate: true,
+ deep: true,
+ handler (value) {
+ if (value.type === 'edit' && value.show) {
+ if (this.$refs.form) this.$refs.form.resetValidation()
+ this.step = 1
+ this.stepCompleted = value.info.id ? 4 : 0
+ this.name = value.info.name || ''
+ this.description = value.info.descr || ''
+ this.permissions = value.info.permissions || []
+ this.groups = []
+ this.blacklist = []
+ this.blacklistList = []
+ if (value.info.groups) {
+ var groupsPush = []
+ for (let i = 0; i < value.info.groups.length; i++) {
+ if (value.info.groups[i].role_x_group.blacklist) groupsPush.push(value.info.groups[i])
+ else this.groups.push(value.info.groups[i])
+ }
+ this.loadChilds().then(() => {
+ this.blacklist = groupsPush
+ })
+ }
}
}
}
- },
- created () {
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
-.table-container {
- padding: 0;
- max-height: 700px;
-}
.stepper-padding-0 {
padding: 0;
}
-.info-input {
- margin: 20px;
-}
-.list-header-margin {
- margin-bottom: 10px;
-}
-.dialog-title {
- padding: 0px;
- z-index: 1;
-}
-.list-item {
- height: 48px;
- max-width: 500px;
- display: flex;
- flex-direction: column;
- justify-content: center;
-}
-.list-item-header {
- font-size: 16px;
-}
-.theme--light .list-item > .list-item-subheader {
- color: rgba(0,0,0,.54);
-}
-.theme--dark .list-item > .list-item-subheader {
- color: hsla(0,0%,100%,.7);
-}
</style>
diff --git a/webapp/src/components/PermissionModuleGrantRevoke.vue b/webapp/src/components/PermissionModuleGrantRevoke.vue
index a137ea1..10a5ad6 100644
--- a/webapp/src/components/PermissionModuleGrantRevoke.vue
+++ b/webapp/src/components/PermissionModuleGrantRevoke.vue
@@ -10,8 +10,8 @@
"id": "ID",
"name": "Name",
"description": "Description",
- "roleGrantedSuccess" : "Roles successfully granted.",
- "roleRevokedSuccess" : "Roles successfully revoked."
+ "roleGrantedSuccess" : "Role successfully granted. | Roles successfully granted.",
+ "roleRevokedSuccess" : "Role successfully revoked. | Roles successfully revoked."
},
"de": {
"select_roles": "Rollen auswählen",
@@ -23,98 +23,30 @@
"id": "ID",
"name": "Name",
"description": "Beschreibung",
- "roleGrantedSuccess" : "Rollen erfolgreich zugewiesen.",
- "roleRevokedSuccess" : "Rollen erfolgreich entzogen."
+ "roleGrantedSuccess" : "Rolle erfolgreich zugewiesen. | Rollen erfolgreich zugewiesen.",
+ "roleRevokedSuccess" : "Rolle erfolgreich entzogen. | Rollen erfolgreich entzogen."
}
}
</i18n>
<template>
- <v-dialog
- :value="$store.state.permissions.grantRevoke"
- @input="$store.commit('permissions/setGrantRevoke', $event)"
- max-width="800px"
- scrollable
- >
- <v-card>
- <v-card-title class="dialog-title">
- <v-stepper v-model="step" horizontal style="width: 100%; background: transparent;" class="elevation-3">
- <v-stepper-header>
- <v-stepper-step
- :complete="stepCompleted >= 1"
- step="1"
- :editable="stepCompleted >= 0"
- edit-icon="check"
- >
- {{ $t('select_roles') }}
- </v-stepper-step>
- <v-divider></v-divider>
- <v-stepper-step
- :complete="stepCompleted >= 2"
- step="2"
- :editable="stepCompleted >= 1"
- edit-icon="check"
- >
- {{ $t('check_selection') }}
- </v-stepper-step>
- </v-stepper-header>
- </v-stepper>
- </v-card-title>
- <v-card-text class="table-container">
- <v-form v-model="valid" ref="form" @submit.prevent="submit" lazy-validation>
- <v-stepper v-model="step" horizontal style="width: 100%; background: transparent" class="elevation-0">
- <v-stepper-items>
- <v-stepper-content step="1" class="stepper-padding-0">
- <data-table v-model="selectedRoles" :headers="roleHeaders" :items="roles"/>
- </v-stepper-content>
- <v-stepper-content step="2">
- <v-layout row wrap>
- <v-flex>
- <v-list subheader>
- <v-subheader inset>{{ $t('roles') }}</v-subheader>
- <v-divider class="list-header-margin"></v-divider>
- <v-list-tile
- v-for="role in selectedRoles"
- :key="role.id"
- >
- <v-list-tile-content>
- <v-list-tile-title>{{ role.name }}</v-list-tile-title>
- <v-list-tile-sub-title>{{ role.descr }}</v-list-tile-sub-title>
- </v-list-tile-content>
- </v-list-tile>
- </v-list>
- </v-flex>
- <v-flex>
- <v-list subheader>
- <v-subheader inset>{{ $t('users') }}</v-subheader>
- <v-divider class="list-header-margin"></v-divider>
- <v-list-tile
- v-for="user in selectedUsers"
- :key="user.username"
- >
- <v-list-tile-content>
- <v-list-tile-title>{{ user.username }}</v-list-tile-title>
- <v-list-tile-sub-title>{{ user.name }}</v-list-tile-sub-title>
- </v-list-tile-content>
- </v-list-tile>
- </v-list>
- </v-flex>
- </v-layout>
- </v-stepper-content>
- </v-stepper-items>
- </v-stepper>
- </v-form>
- </v-card-text>
- <v-divider></v-divider>
- <v-card-actions>
- <v-spacer></v-spacer>
- <v-btn flat @click.native="$store.commit('permissions/setGrantRevoke', false )">{{ $t('cancel') }}</v-btn>
- <v-btn color="primary" v-show="step == 1" @click.native="completeStepOne()">{{ $t('continue') }}</v-btn>
- <v-btn type="submit" @click="submit" v-show="step == 2" v-if="grant" class="success">{{ $t('grant') }}</v-btn>
- <v-btn type="submit" @click="submit" v-show="step == 2" v-else class="error">{{ $t('revoke') }}</v-btn>
- </v-card-actions>
- </v-card>
- </v-dialog>
+ <v-card>
+ <v-card-title class="dialog-title elevation-3">
+ <div class="headline">{{ $t('select_roles') }}</div>
+ </v-card-title>
+ <v-card-text class="pa-0">
+ <v-form v-model="valid" ref="form" @submit.prevent="submit" lazy-validation>
+ <data-table v-model="selectedRoles" :headers="roleHeaders" :items="roles"/>
+ </v-form>
+ </v-card-text>
+ <v-divider></v-divider>
+ <v-card-actions>
+ <v-spacer></v-spacer>
+ <v-btn flat @click.native="$store.commit('permissions/setDialog', { show : false } )">{{ $t('cancel') }}</v-btn>
+ <v-btn type="submit" @click="submit" v-if="grant" class="success">{{ $t('grant') }}</v-btn>
+ <v-btn type="submit" @click="submit" v-if="revoke" class="error">{{ $t('revoke') }}</v-btn>
+ </v-card-actions>
+ </v-card>
</template>
<script>
@@ -123,16 +55,15 @@ import DataTable from '@/components/DataTable'
export default {
name: 'PermissionModuleGrantRevoke',
- props: ['grant'],
components: {
DataTable
},
data () {
return {
valid: true,
- step: 1,
- stepCompleted: 0,
selectedRoles: [],
+ grant: false,
+ revoke: false,
roleHeaders: [
{ text: this.$t('id'), key: 'id' },
{ text: this.$t('name'), key: 'name' },
@@ -142,36 +73,35 @@ export default {
},
methods: {
async submit (event) {
- const roleIds = this.selectedRoles.map(x => x.id)
- for (let i = 0; i < this.selectedUsers.length; i++) {
- await this.$http.post('/api/users/' + this.selectedUsers[i].id + '/roles' + (this.grant ? '' : '/?delete'), { ids: roleIds })
- }
+ const roleIds = this.selectedRoles.map(r => r.id)
+ const userIds = this.selectedUsers.map(u => u.id)
+ await this.$http.post('/api/users/roles' + (this.grant ? '' : '?delete'), {
+ roles: roleIds,
+ users: userIds
+ })
if (this.grant) {
- this.$snackbar({ color: 'success', text: this.$t('roleGrantedSuccess') })
- } else {
- this.$snackbar({ color: 'success', text: this.$t('roleRevokedSuccess') })
+ this.$snackbar({ color: 'success', text: this.$tc('roleGrantedSuccess', [roleIds.length]) })
+ } else if (this.revoke) {
+ this.$snackbar({ color: 'success', text: this.$tc('roleRevokedSuccess', [roleIds.length]) })
}
- this.$store.dispatch('permissions/loadUserData')
- this.$store.commit('permissions/setGrantRevoke', false)
+ this.$store.dispatch('users/loadData')
+ this.$store.commit('permissions/setDialog', { show: false })
this.$store.commit('permissions/setSelectedUsers', [])
- },
- completeStepOne () {
- this.step = 2
- this.stepCompleted = Math.max(1, this.stepCompleted)
}
},
computed: {
- ...mapState('permissions', ['roles', 'selectedUsers']),
- grantRevoke: function () {
- return this.$store.state.permissions.grantRevoke
- }
+ ...mapState('permissions', ['dialog', 'roles', 'selectedUsers'])
},
watch: {
- grantRevoke: function (value) {
- if (value) {
- this.selectedRoles = []
- this.step = 1
- this.stepCompleted = 0
+ dialog: {
+ immediate: true,
+ deep: true,
+ handler (value) {
+ if (value.show) {
+ this.selectedRoles = []
+ this.grant = value.type === 'grant' || false
+ this.revoke = value.type === 'revoke' || false
+ }
}
}
}
@@ -180,18 +110,10 @@ export default {
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
-.table-container {
- padding: 0;
- height: 700px;
-}
.stepper-padding-0 {
padding: 0;
}
-.list-header-margin {
- margin-bottom: 10px;
-}
.dialog-title {
- padding: 0px;
z-index: 1;
}
</style>
diff --git a/webapp/src/components/PermissionModuleRoleList.vue b/webapp/src/components/PermissionModuleRoleList.vue
index 67fbb9f..9f9ac73 100644
--- a/webapp/src/components/PermissionModuleRoleList.vue
+++ b/webapp/src/components/PermissionModuleRoleList.vue
@@ -20,17 +20,17 @@
<template>
<div>
<v-card>
- <data-table :value="selectedRoles" @input="$store.commit('permissions/setSelectedRoles', $event)" :headers="headers" :items="roles">
- <div slot="action" slot-scope="row" style="text-align: right" v-if="canEdit">
- <v-btn flat icon color="primary" @click.stop="$store.commit('permissions/editRole', row.item.id)"><v-icon>edit</v-icon></v-btn>
+ <data-table v-model="selectedRoles" :headers="headers" :items="roles" @dblclick="editRole($event)">
+ <div slot="action" slot-scope="row" style="text-align: right">
+ <v-btn flat icon color="primary" @click.stop="editRole(row.item)"><v-icon>edit</v-icon></v-btn>
</div>
</data-table>
</v-card>
- <div class="text-xs-right" v-if="canEdit">
- <v-btn color="error" flat @click="$store.commit('permissions/setDialog', true )" :disabled="selectedRoles.length === 0">
+ <div class="text-xs-right">
+ <v-btn color="error" flat @click="deleteRole" :disabled="selectedRoles.length === 0">
<v-icon left>remove_circle_outline</v-icon>{{ $tc('delete-role', selectedRoles.length, [selectedRoles.length]) }}
</v-btn>
- <v-btn color="success" flat @click="$store.commit('permissions/editRole', 0)">
+ <v-btn color="success" flat @click="createRole">
<v-icon left>add_circle_outline</v-icon>{{ $t('create-role') }}
</v-btn>
</div>
@@ -38,7 +38,7 @@
</template>
<script>
-import { mapState } from 'vuex'
+import { mapState, mapMutations } from 'vuex'
import DataTable from '@/components/DataTable'
export default {
@@ -48,24 +48,31 @@ export default {
},
data () {
return {
- headers: [
+ selectedRoles: []
+ }
+ },
+ computed: {
+ headers () {
+ return [
{ text: this.$t('id'), key: 'id' },
{ text: this.$t('name'), key: 'name' },
{ text: this.$t('description'), key: 'descr' },
{ sortable: false, key: 'action', width: '60px' }
- ],
- canEdit: false
- }
- },
- computed: {
- ...mapState('permissions', ['selectedRoles', 'roles'])
+ ]
+ },
+ ...mapState('permissions', ['roles'])
},
methods: {
- },
- created () {
- this.$http.get('/api/permissions/permissions.editrole').then(response => {
- this.canEdit = response.data
- })
+ ...mapMutations('permissions', ['setDialog']),
+ createRole () {
+ this.setDialog({ show: true, type: 'edit', info: {} })
+ },
+ deleteRole () {
+ this.setDialog({ show: true, type: 'delete', info: this.selectedRoles })
+ },
+ editRole (role) {
+ this.setDialog({ show: true, type: 'edit', info: role })
+ }
}
}
</script>
diff --git a/webapp/src/components/PermissionModuleUserList.vue b/webapp/src/components/PermissionModuleUserList.vue
index 609ab37..d25d1e8 100644
--- a/webapp/src/components/PermissionModuleUserList.vue
+++ b/webapp/src/components/PermissionModuleUserList.vue
@@ -31,11 +31,11 @@
</div>
</data-table>
</v-card>
- <div class="text-xs-right" v-if="canGrant">
- <v-btn color="error" flat @click="$store.commit('permissions/grantRevoke', { show: true, grant: false } )" :disabled="selectedUsers.length === 0">
+ <div class="text-xs-right">
+ <v-btn color="error" flat @click="revokeRoles" :disabled="selectedUsers.length === 0">
<v-icon left>remove_circle_outline</v-icon>{{ $t('revoke-role') }}
</v-btn>
- <v-btn color="success" flat @click="$store.commit('permissions/grantRevoke', { show: true, grant: true } )" :disabled="selectedUsers.length === 0">
+ <v-btn color="success" flat @click="grantRoles" :disabled="selectedUsers.length === 0">
<v-icon left>add_circle_outline</v-icon>{{ $t('grant-role') }}
</v-btn>
</div>
@@ -43,7 +43,7 @@
</template>
<script>
-import { mapState } from 'vuex'
+import { mapState, mapMutations } from 'vuex'
import DataTable from '@/components/DataTable'
export default {
@@ -57,19 +57,21 @@ export default {
{ text: this.$t('username'), key: 'username' },
{ text: this.$t('name'), key: 'name' },
{ text: this.$t('roles'), key: 'roles' }
- ],
- canGrant: false
+ ]
}
},
computed: {
- ...mapState('permissions', ['selectedUsers', 'users'])
+ ...mapState('users', ['users']),
+ ...mapState('permissions', ['selectedUsers'])
},
methods: {
- },
- created () {
- this.$http.get('/api/permissions/permissions.grantrevoke').then(response => {
- this.canGrant = response.data
- })
+ ...mapMutations('permissions', ['setDialog']),
+ revokeRoles () {
+ this.setDialog({ show: true, type: 'revoke', info: this.selectedUsers })
+ },
+ grantRoles () {
+ this.setDialog({ show: true, type: 'grant', info: this.selectedUsers })
+ }
}
}
</script>
diff --git a/webapp/src/store/permissions.js b/webapp/src/store/permissions.js
index 7ec454c..5f16045 100644
--- a/webapp/src/store/permissions.js
+++ b/webapp/src/store/permissions.js
@@ -4,88 +4,34 @@ export default {
namespaced: true,
state: {
roles: [],
- users: [],
- groups: [],
- permissions: [],
- selectedRoles: [],
+ permissionsList: [],
selectedUsers: [],
- roleId: '',
- dialog: false,
- grantRevoke: false,
- grant: false,
- edit: false
+ dialog: { show: false, type: null, info: {} }
},
mutations: {
- setDialog (state, value) {
- state.dialog = value
- },
- setRoles (state, value) {
- state.roles = value
- },
- setUsers (state, value) {
- state.users = value
- },
- setGroups (state, value) {
- state.groups = value
- },
- setPermissions (state, value) {
- state.permissions = value
- },
- setSelectedRoles (state, value) {
- state.selectedRoles = value
- },
- setSelectedUsers (state, value) {
- state.selectedUsers = value
- },
- editRole (state, value) {
- state.roleId = value
- state.edit = true
- },
- setEdit (state, value) {
- state.edit = value
- },
- grantRevoke (state, value) {
- state.grantRevoke = value.show
- state.grant = value.grant
- },
- setGrantRevoke (state, value) {
- state.grantRevoke = value
+ setRoles (state, value) { state.roles = value },
+ setSelectedUsers (state, value) { state.selectedUsers = value },
+ setPermissions (state, value) { state.permissionsList = value },
+ setDialog (state, { show, type, info }) {
+ if (show !== undefined) state.dialog.show = show
+ if (type !== undefined) state.dialog.type = type
+ if (info !== undefined) state.dialog.info = info
}
},
actions: {
- deleteSelectedRoles (context) {
- // Filter selected array to get a list of ids.
- const filteredArray = context.state.selectedRoles.map(x => x.id)
- axios.post('/api/roles?delete', { ids: filteredArray }).then(response => {
- context.dispatch('loadData')
- context.commit('setSelectedRoles', [])
- })
- },
- loadRoleData (context) {
+ loadRoles (context) {
axios.get('/api/roles').then(response => {
context.commit('setRoles', response.data)
})
},
- loadUserData (context) {
- axios.get('/api/users').then(response => {
- context.commit('setUsers', response.data)
- })
- },
- loadGroupData (context) {
- axios.get('/api/groups').then(response => {
- context.commit('setGroups', response.data)
- })
- },
- loadPermissionData (context) {
+ loadPermissions (context) {
axios.get('/api/permissions').then(response => {
context.commit('setPermissions', response.data)
})
},
- loadData (context) {
- context.dispatch('loadRoleData')
- context.dispatch('loadUserData')
- context.dispatch('loadGroupData')
- context.dispatch('loadPermissionData')
+ loadLists (context) {
+ context.dispatch('loadRoles')
+ context.dispatch('loadPermissions')
}
}
}