UI: Add permission checks for people #98

This commit is contained in:
Timo Volkmann 2021-10-21 13:09:37 +02:00
parent 39063d892d
commit 2f11587174
9 changed files with 54 additions and 13 deletions

View file

@ -117,7 +117,7 @@ Vue.mixin({
hasPermission(resource, ...actions) {
if (this.$config.values.public) return true;
const role = this.$session.getUser().getRole();
return this.acl.accessAllowedAny(role, resource, actions);
return this.acl.accessAllowedAny(role, resource, ...actions);
},
},
});

View file

@ -95,6 +95,8 @@ export default class Acl {
return act;
}
accessAllowedAny(role, resource, ...actions) {
return actions.some((action) => this.accessAllowed(role, resource, action));
return actions.some((action) => {
return this.accessAllowed(role, resource, action);
});
}
}

View file

@ -181,7 +181,7 @@
</v-list-tile-content>
</v-list-tile>
<v-list-tile v-show="$config.feature('people')" :to="{ name: 'people' }" class="nav-people" @click.stop="">
<v-list-tile v-show="$config.feature('people') && hasPermission(aclResources.ResourceSubjects, aclActions.ActionSearch, aclActions.ActionRead)" :to="{ name: 'people' }" class="nav-people" @click.stop="">
<v-list-tile-action :title="$gettext('People')">
<v-icon>person</v-icon>
</v-list-tile-action>
@ -273,7 +273,7 @@
</v-list-tile>
</v-list-group>
<v-list-tile v-show="$config.feature('labels')" to="/labels" class="nav-labels" @click.stop="">
<v-list-tile v-show="$config.feature('labels') && hasPermission(aclResources.ResourceLabels, aclActions.ActionRead, aclActions.ActionSearch)" to="/labels" class="nav-labels" @click.stop="">
<v-list-tile-action :title="$gettext('Labels')">
<v-icon>label</v-icon>
</v-list-tile-action>

View file

@ -29,7 +29,7 @@
:transition="false"
aspect-ratio="1"
class="accent lighten-2">
<v-btn v-if="!marker.SubjUID && !marker.Invalid" :ripple="false" :depressed="false" class="input-reject"
<v-btn v-if="!marker.SubjUID && !marker.Invalid && hasPermission(aclResources.ResourceFiles, aclActions.ActionUpdate)" :ripple="false" :depressed="false" class="input-reject"
icon flat small absolute :title="$gettext('Remove')"
@click.stop.prevent="onReject(marker)">
<v-icon color="white" class="action-reject">clear</v-icon>
@ -52,7 +52,7 @@
<v-text-field
v-model="marker.Name"
:rules="[textRule]"
:disabled="busy"
:disabled="busy || !hasPermission(aclResources.ResourceFiles, aclActions.ActionUpdate)"
:readonly="true"
browser-autocomplete="off"
class="input-name pa-0 ma-0"
@ -75,7 +75,7 @@
:items="$config.values.people"
item-value="Name"
item-text="Name"
:disabled="busy"
:disabled="busy || !hasPermission(aclResources.ResourceFiles, aclActions.ActionUpdate)"
:return-object="false"
:menu-props="menuProps"
:allow-overflow="false"

View file

@ -8,7 +8,7 @@
slider-color="secondary-dark"
:height="$vuetify.breakpoint.smAndDown ? 48 : 64"
>
<v-tab v-for="(item, index) in tabs" :id="'tab-' + item.name" :key="index" :class="item.class"
<v-tab v-for="(item, index) in permittedTabs" :id="'tab-' + item.name" :key="index" :class="item.class"
ripple @click.stop.prevent="changePath(item.path)">
<v-icon v-if="$vuetify.breakpoint.smAndDown" :title="item.label">{{ item.icon }}</v-icon>
<template v-else>
@ -23,7 +23,7 @@
</v-tab>
<v-tabs-items touchless>
<v-tab-item v-for="(item, index) in tabs" :key="index" lazy>
<v-tab-item v-for="(item, index) in permittedTabs" :key="index" lazy>
<component :is="item.component" :static-filter="item.filter" :active="active === index"
@updateFaceCount="onUpdateFaceCount"></component>
</v-tab-item>
@ -53,6 +53,9 @@ export default {
'class': '',
'path': '/people',
'icon': 'people_alt',
'permission': () => {
return this.hasPermission(this.aclResources.ResourceSubjects, this.aclActions.ActionRead, this.aclActions.ActionSearch);
},
},
{
'name': 'people_faces',
@ -63,6 +66,9 @@ export default {
'path': '/people/new',
'icon': 'person_add',
'count': 0,
'permission': () => {
return this.hasPermission(this.aclResources.ResourceSubjects, this.aclActions.ActionUpdate);
},
},
];
@ -76,6 +82,14 @@ export default {
rtl: this.$rtl,
};
},
computed: {
permittedTabs() {
if (!this.tabs) return this.tabs;
return this.tabs.filter(tab => {
return tab.permission();
});
}
},
watch: {
'$route'() {
this.openTab();

View file

@ -66,6 +66,7 @@
<v-layout v-if="model.SubjUID" row wrap align-center>
<v-flex xs12 class="text-xs-left pa-0">
<v-text-field
v-if="hasPermission(aclResources.ResourceSubjects, aclActions.ActionUpdate)"
v-model="model.Name"
:rules="[textRule]"
:readonly="readonly"

View file

@ -129,7 +129,7 @@
<span v-else>
<v-icon>edit</v-icon>
</span>
<template #input>
<template v-if="hasPermission(aclResources.ResourceSubjects, aclActions.ActionUpdate)" #input>
<v-text-field
v-model="model.Name"
:rules="[titleRule]"

View file

@ -61,7 +61,7 @@ const hasPermission = (resource, ...actions) => {
// const acl = new Acl(window.__CONFIG__.acl);
const acl = new Acl(config.values.acl);
const role = session.getUser().getRole();
return acl.accessAllowedAny(role, resource, actions);
return acl.accessAllowedAny(role, resource, ...actions);
};
export default [
@ -328,15 +328,28 @@ export default [
component: People,
meta: { title: $gettext("People"), auth: true, background: "application-light" },
beforeEnter: (to, from, next) => {
const nextGuarded = () => {
if (
hasPermission(
aclResources.ResourceSubjects,
aclActions.ActionRead,
aclActions.ActionSearch
)
) {
next();
} else {
next({ name: "home" });
}
};
if (!config || !from || !from.name || from.name.startsWith("people")) {
next();
nextGuarded();
} else {
config.load().finally(() => {
// Open new faces tab when there are no people.
if (config.values.count.people === 0) {
next({ name: "people_faces" });
} else {
next();
nextGuarded();
}
});
}
@ -347,6 +360,13 @@ export default [
path: "/people/new",
component: People,
meta: { title: $gettext("People"), auth: true, background: "application-light" },
beforeEnter: (to, from, next) => {
if (hasPermission(aclResources.ResourceSubjects, aclActions.ActionUpdate)) {
next();
} else {
next({ name: "people" });
}
},
},
{
name: "library",

View file

@ -51,4 +51,8 @@ var Permissions = ACL{
RoleAdmin: Actions{ActionDefault: true},
RoleMember: Actions{ActionSearch: true, ActionRead: true},
},
ResourceFiles: Roles{
RoleAdmin: Actions{ActionDefault: true},
RoleMember: Actions{ActionSearch: true, ActionRead: true},
},
}