diff --git a/client/components/admin.vue b/client/components/admin.vue
index 6e369b6c..e8d7f30c 100644
--- a/client/components/admin.vue
+++ b/client/components/admin.vue
@@ -7,40 +7,42 @@
v-list-tile.pt-2(to='/dashboard')
v-list-tile-avatar: v-icon dashboard
v-list-tile-title {{ $t('admin:dashboard.title') }}
- v-divider.my-2
- v-subheader.pl-4 {{ $t('admin:nav.site') }}
- v-list-tile(to='/general', v-if='hasPermission(`manage:system`)')
- v-list-tile-avatar: v-icon widgets
- v-list-tile-title {{ $t('admin:general.title') }}
- v-list-tile(to='/locale', v-if='hasPermission(`manage:system`)')
- v-list-tile-avatar: v-icon language
- v-list-tile-title {{ $t('admin:locale.title') }}
- v-list-tile(to='/navigation', v-if='hasPermission([`manage:system`, `manage:navigation`])')
- v-list-tile-avatar: v-icon near_me
- v-list-tile-title {{ $t('admin:navigation.title') }}
- v-list-tile(to='/pages')
- v-list-tile-avatar: v-icon insert_drive_file
- v-list-tile-title {{ $t('admin:pages.title') }}
- v-list-tile-action
- v-chip(small, disabled, :color='darkMode ? `grey darken-3-d4` : `grey lighten-4`')
- .caption.grey--text {{ info.pagesTotal }}
- v-list-tile(to='/theme', v-if='hasPermission([`manage:system`, `manage:theme`])')
- v-list-tile-avatar: v-icon palette
- v-list-tile-title {{ $t('admin:theme.title') }}
- v-divider.my-2
- v-subheader.pl-4 {{ $t('admin:nav.users') }}
- v-list-tile(to='/groups')
- v-list-tile-avatar: v-icon people
- v-list-tile-title {{ $t('admin:groups.title') }}
- v-list-tile-action
- v-chip(small, disabled, :color='darkMode ? `grey darken-3-d4` : `grey lighten-4`')
- .caption.grey--text {{ info.groupsTotal }}
- v-list-tile(to='/users')
- v-list-tile-avatar: v-icon perm_identity
- v-list-tile-title {{ $t('admin:users.title') }}
- v-list-tile-action
- v-chip(small, disabled, :color='darkMode ? `grey darken-3-d4` : `grey lighten-4`')
- .caption.grey--text {{ info.usersTotal }}
+ template(v-if='hasPermission([`manage:system`, `manage:navigation`, `write:pages`, `manage:pages`, `delete:pages`])')
+ v-divider.my-2
+ v-subheader.pl-4 {{ $t('admin:nav.site') }}
+ v-list-tile(to='/general', v-if='hasPermission(`manage:system`)')
+ v-list-tile-avatar: v-icon widgets
+ v-list-tile-title {{ $t('admin:general.title') }}
+ v-list-tile(to='/locale', v-if='hasPermission(`manage:system`)')
+ v-list-tile-avatar: v-icon language
+ v-list-tile-title {{ $t('admin:locale.title') }}
+ v-list-tile(to='/navigation', v-if='hasPermission([`manage:system`, `manage:navigation`])')
+ v-list-tile-avatar: v-icon near_me
+ v-list-tile-title {{ $t('admin:navigation.title') }}
+ v-list-tile(to='/pages', v-if='hasPermission([`manage:system`, `write:pages`, `manage:pages`, `delete:pages`])')
+ v-list-tile-avatar: v-icon insert_drive_file
+ v-list-tile-title {{ $t('admin:pages.title') }}
+ v-list-tile-action
+ v-chip(small, disabled, :color='darkMode ? `grey darken-3-d4` : `grey lighten-4`')
+ .caption.grey--text {{ info.pagesTotal }}
+ v-list-tile(to='/theme', v-if='hasPermission([`manage:system`, `manage:theme`])')
+ v-list-tile-avatar: v-icon palette
+ v-list-tile-title {{ $t('admin:theme.title') }}
+ template(v-if='hasPermission([`manage:system`, `manage:groups`, `write:groups`, `manage:users`, `write:users`])')
+ v-divider.my-2
+ v-subheader.pl-4 {{ $t('admin:nav.users') }}
+ v-list-tile(to='/groups', v-if='hasPermission([`manage:system`, `manage:groups`, `write:groups`])')
+ v-list-tile-avatar: v-icon people
+ v-list-tile-title {{ $t('admin:groups.title') }}
+ v-list-tile-action
+ v-chip(small, disabled, :color='darkMode ? `grey darken-3-d4` : `grey lighten-4`')
+ .caption.grey--text {{ info.groupsTotal }}
+ v-list-tile(to='/users', v-if='hasPermission([`manage:system`, `manage:groups`, `write:groups`, `manage:users`, `write:users`])')
+ v-list-tile-avatar: v-icon perm_identity
+ v-list-tile-title {{ $t('admin:users.title') }}
+ v-list-tile-action
+ v-chip(small, disabled, :color='darkMode ? `grey darken-3-d4` : `grey lighten-4`')
+ .caption.grey--text {{ info.usersTotal }}
template(v-if='hasPermission(`manage:system`)')
v-divider.my-2
v-subheader.pl-4 {{ $t('admin:nav.modules') }}
@@ -62,8 +64,8 @@
v-list-tile(to='/storage')
v-list-tile-avatar: v-icon storage
v-list-tile-title {{ $t('admin:storage.title') }}
- v-divider.my-2
template(v-if='hasPermission([`manage:system`, `manage:api`])')
+ v-divider.my-2
v-subheader.pl-4 {{ $t('admin:nav.system') }}
v-list-tile(to='/api', v-if='hasPermission([`manage:system`, `manage:api`])')
v-list-tile-avatar: v-icon call_split
@@ -74,8 +76,8 @@
v-list-tile(to='/system', v-if='hasPermission(`manage:system`)')
v-list-tile-avatar: v-icon tune
v-list-tile-title {{ $t('admin:system.title') }}
- v-list-tile(to='/utilities', v-if='hasPermission(`manage:system`)')
- v-list-tile-avatar: v-icon build
+ v-list-tile(to='/utilities', v-if='hasPermission(`manage:system`)', disabled)
+ v-list-tile-avatar: v-icon(color='grey lighten-2') build
v-list-tile-title {{ $t('admin:utilities.title') }}
v-list-tile(to='/dev', v-if='hasPermission([`manage:system`, `manage:api`])')
v-list-tile-avatar: v-icon weekend
diff --git a/client/components/admin/admin-dashboard.vue b/client/components/admin/admin-dashboard.vue
index b7832e46..34e0659a 100644
--- a/client/components/admin/admin-dashboard.vue
+++ b/client/components/admin/admin-dashboard.vue
@@ -45,7 +45,7 @@
:class='isLatestVersion ? "teal lighten-2" : "red lighten-2"'
dark
)
- v-btn(fab, absolute, right, top, small, light, to='system')
+ v-btn(fab, absolute, right, top, small, light, to='system', v-if='hasPermission(`manage:system`)')
v-icon(v-if='isLatestVersion', color='teal') build
v-icon(v-else, color='red darken-4') get_app
v-card-text
@@ -101,6 +101,7 @@
diff --git a/client/components/admin/admin-groups-edit-rules.vue b/client/components/admin/admin-groups-edit-rules.vue
index dc5c48ab..6bb3baad 100644
--- a/client/components/admin/admin-groups-edit-rules.vue
+++ b/client/components/admin/admin-groups-edit-rules.vue
@@ -78,8 +78,8 @@
dense
)
template(slot='selection', slot-scope='{ item, index }')
- v-chip.white--text.ml-0(v-if='index <= 2', small, label, :color='rule.deny ? `red` : `green`').caption {{ item.value }}
- v-chip.white--text.ml-0(v-if='index === 3', small, label, :color='rule.deny ? `red lighten-2` : `green lighten-2`').caption + {{ rule.roles.length - 3 }} more
+ v-chip.white--text.ml-0(v-if='index <= 1', small, label, :color='rule.deny ? `red` : `green`').caption {{ item.value }}
+ v-chip.white--text.ml-0(v-if='index === 2', small, label, :color='rule.deny ? `red lighten-2` : `green lighten-2`').caption + {{ rule.roles.length - 2 }} more
template(slot='item', slot-scope='props')
v-list-tile-action(style='min-width: 30px;')
v-checkbox(
@@ -163,6 +163,26 @@
v-btn(icon, @click='removeRule(rule.id)')
v-icon(:color='$vuetify.dark ? `grey` : `blue-grey`') clear
+
+ v-divider.mt-3
+ v-subheader.pl-0 Rules Order
+ .body-1.pl-3 Rules are applied in order of path specificity. A more precise path will always override a less defined path.
+ .body-1.pl-4 For example, #[span.teal--text /geography/countries] will override #[span.teal--text /geography].
+ .body-1.pl-3.pt-2 When 2 rules have the same specificity, the priority is given from lowest to highest as follows:
+ .body-1.pl-3.pt-1
+ ul
+ li
+ strong Path Starts With...
+ em.caption.pl-1 (lowest)
+ li
+ strong Path Ends With...
+ li
+ strong Path Matches Regex...
+ li
+ strong Path Is Exactly...
+ em.caption.pl-1 (highest)
+ .body-1.pl-3.pt-2 When 2 rules have the same path specificity AND the same match type, #[strong.red--text DENY] will always override an #[strong.green--text ALLOW] rule.
+