mirror of
https://gitlab.com/bramw/baserow.git
synced 2025-01-12 20:08:16 +00:00
RBAC Help Icons
This commit is contained in:
parent
2b9de4afdf
commit
aa70d78614
23 changed files with 199 additions and 64 deletions
changelog.md
enterprise/web-frontend/modules/baserow_enterprise
assets/scss/components
components
locales
membersPagePluginTypes.jsweb-frontend/modules/core
assets/scss/components
components
crudTable
locales
plugins
|
@ -10,6 +10,7 @@ For example:
|
|||
## Unreleased
|
||||
|
||||
### New Features
|
||||
* Add various help icons to explain RBAC in the UI [#1318](https://gitlab.com/bramw/baserow/-/issues/1318)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
|
@ -21,7 +22,6 @@ For example:
|
|||
* (Optional) - Regenerate the `card_cover` thumbnails to have better quality images in gallery views with: `./baserow regenerate_user_file_thumbnails card_cover`
|
||||
|
||||
### New Features
|
||||
|
||||
* (Enterprise Preview Feature) Database and Table level RBAC with Teams are now available as a preview feature for enterprise users, Add 'RBAC' to the FEATURE_FLAG env and restart var to enable.
|
||||
* Possibility to disable password authentication if another authentication provider is enabled. [#1317](https://gitlab.com/bramw/baserow/-/issues/1317)
|
||||
* Users with roles higher than viewer on tables and databases now counted as paid users
|
||||
|
|
|
@ -7,3 +7,4 @@
|
|||
@import 'subject_sample_field';
|
||||
@import 'member_roles';
|
||||
@import 'select_list_footer';
|
||||
@import 'manage_team_form';
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
.manage-team-form__role-title {
|
||||
display: flex;
|
||||
margin-bottom: 10px;
|
||||
}
|
|
@ -69,6 +69,10 @@
|
|||
overflow: hidden;
|
||||
}
|
||||
|
||||
.member-roles-members-list__role-selector {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.select-members-list__user-name {
|
||||
max-width: 400px;
|
||||
text-overflow: ellipsis;
|
||||
|
|
|
@ -27,6 +27,17 @@
|
|||
role-value-column="role_uid"
|
||||
@update-role="roleUpdate($event)"
|
||||
></EditRoleContext>
|
||||
<HelpIcon
|
||||
v-if="roleUidSelected === 'NO_ACCESS'"
|
||||
:tooltip="$t('membersRoleField.noAccessHelpText')"
|
||||
class="margin-left-1"
|
||||
/>
|
||||
<HelpIcon
|
||||
v-if="roleUidSelected === 'ADMIN'"
|
||||
:tooltip="$t('membersRoleField.adminHelpText')"
|
||||
class="margin-left-1"
|
||||
is-warning
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -65,6 +76,9 @@ export default {
|
|||
})
|
||||
: []
|
||||
},
|
||||
roleUidSelected() {
|
||||
return this.row[this.column.key]
|
||||
},
|
||||
...mapGetters({ userId: 'auth/getUserId' }),
|
||||
},
|
||||
methods: {
|
||||
|
|
|
@ -40,17 +40,24 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<RoleSelector
|
||||
:disabled="
|
||||
roleAssignment.subject.id === userId &&
|
||||
roleAssignment.subject_type === 'auth.User'
|
||||
"
|
||||
:roles="getAvailableRoles(roles)"
|
||||
:value="getRole(roleAssignment)"
|
||||
:allow-removing-role="true"
|
||||
@delete="$emit('role-updated', roleAssignment, null)"
|
||||
@input="({ uid }) => $emit('role-updated', roleAssignment, uid)"
|
||||
/>
|
||||
<div class="member-roles-members-list__role-selector">
|
||||
<HelpIcon
|
||||
v-if="getRole(roleAssignment).uid === 'ADMIN'"
|
||||
class="margin-right-1"
|
||||
:tooltip="$t('memberRolesMembersList.adminHelpText')"
|
||||
/>
|
||||
<RoleSelector
|
||||
:disabled="
|
||||
roleAssignment.subject.id === userId &&
|
||||
roleAssignment.subject_type === 'auth.User'
|
||||
"
|
||||
:roles="getAvailableRoles(roles)"
|
||||
:value="getRole(roleAssignment)"
|
||||
:allow-removing-role="true"
|
||||
@delete="$emit('role-updated', roleAssignment, null)"
|
||||
@input="({ uid }) => $emit('role-updated', roleAssignment, uid)"
|
||||
/>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
||||
|
|
|
@ -6,12 +6,18 @@
|
|||
$t(`memberRolesTab.${translationPrefix}.title`, { name: scope.name })
|
||||
}}
|
||||
</h2>
|
||||
<a
|
||||
:class="{ 'button--loading': loading }"
|
||||
class="button button--ghost"
|
||||
@click="loading ? null : $refs.roleAssignmentModal.show()"
|
||||
>{{ $t(`memberRolesTab.${translationPrefix}.selectMembers`) }}</a
|
||||
>
|
||||
<div>
|
||||
<HelpIcon
|
||||
:tooltip="$t(`memberRolesTab.${translationPrefix}.headerTooltip`)"
|
||||
class="margin-right-1"
|
||||
></HelpIcon>
|
||||
<a
|
||||
:class="{ 'button--loading': loading }"
|
||||
class="button button--ghost"
|
||||
@click="loading ? null : $refs.roleAssignmentModal.show()"
|
||||
>{{ $t(`memberRolesTab.${translationPrefix}.selectMembers`) }}</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="loading" class="loading"></div>
|
||||
<div v-else>
|
||||
|
|
|
@ -6,17 +6,23 @@
|
|||
<div v-if="showRoleSelector">
|
||||
<RoleSelector v-model="roleSelected" :roles="roles" />
|
||||
</div>
|
||||
<a
|
||||
class="button"
|
||||
:class="{ disabled: !inviteEnabled }"
|
||||
@click="inviteEnabled ? $emit('invite', roleSelected) : null"
|
||||
>{{
|
||||
$t('selectSubjectsListFooter.invite', {
|
||||
count,
|
||||
type: subjectTypeLabel,
|
||||
})
|
||||
}}
|
||||
</a>
|
||||
<div>
|
||||
<HelpIcon
|
||||
:tooltip="$t('selectSubjectsListFooter.helpTooltip')"
|
||||
class="margin-right-1"
|
||||
></HelpIcon>
|
||||
<a
|
||||
class="button"
|
||||
:class="{ disabled: !inviteEnabled }"
|
||||
@click="inviteEnabled ? $emit('invite', roleSelected) : null"
|
||||
>{{
|
||||
$t('selectSubjectsListFooter.invite', {
|
||||
count,
|
||||
type: subjectTypeLabel,
|
||||
})
|
||||
}}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -31,7 +31,15 @@
|
|||
</FormElement>
|
||||
</div>
|
||||
<div class="col col-5">
|
||||
<h3>{{ $t('manageTeamForm.roleTitle') }}</h3>
|
||||
<div class="manage-team-form__role-title">
|
||||
<h3>
|
||||
{{ $t('manageTeamForm.roleTitle') }}
|
||||
<HelpIcon
|
||||
class="margin-left-1"
|
||||
:tooltip="$t('manageTeamForm.roleHelpText')"
|
||||
/>
|
||||
</h3>
|
||||
</div>
|
||||
<FormElement class="control">
|
||||
<div class="control__elements">
|
||||
<Dropdown v-model="values.default_role" :show-search="false">
|
||||
|
|
|
@ -134,7 +134,8 @@ export default {
|
|||
{
|
||||
roles: this.roles,
|
||||
groupId: this.group.id,
|
||||
}
|
||||
},
|
||||
this.$t('teamsTable.roleHelpText')
|
||||
),
|
||||
new CrudTableColumn(
|
||||
'subject_sample',
|
||||
|
|
|
@ -34,7 +34,8 @@
|
|||
"roleTitle": "Default role",
|
||||
"inviteMembers": "Add members",
|
||||
"membersTitle": "Members",
|
||||
"noSubjectsSelected": "Click '{buttonLabel}' to optionally add team users."
|
||||
"noSubjectsSelected": "Click '{buttonLabel}' to optionally add team users.",
|
||||
"roleHelpText": "User specific roles will always override Team roles."
|
||||
},
|
||||
"editTeamContext": {
|
||||
"edit": "Edit team",
|
||||
|
@ -46,7 +47,8 @@
|
|||
"nameColumn": "Name",
|
||||
"createdColumn": "Created on",
|
||||
"subjectsColumn": "Members",
|
||||
"roleColumn": "Default role"
|
||||
"roleColumn": "Default role",
|
||||
"roleHelpText": "Can be overriden with roles on databases and tables."
|
||||
},
|
||||
"subjectSampleField": {
|
||||
"titleAttr": "{subjectCount} members in this team."
|
||||
|
@ -158,7 +160,8 @@
|
|||
"everyoneHasAccess": "Everyone at {name} workspace can access this database.",
|
||||
"onlyYouHaveAccess": "Only you can access this database.",
|
||||
"warningTitle": "Other users might inherit access!",
|
||||
"warningMessage": "Other users might inherit access via their respective roles on the parent group."
|
||||
"warningMessage": "Other users might inherit access via their respective roles on the parent group.",
|
||||
"headerTooltip": "Database roles will override group roles."
|
||||
},
|
||||
"table": {
|
||||
"title": "{name} table",
|
||||
|
@ -166,7 +169,8 @@
|
|||
"everyoneHasAccess": "Everyone at {name} workspace can access this table.",
|
||||
"onlyYouHaveAccess": "Only you can access this table.",
|
||||
"warningTitle": "Other users might inherit access!",
|
||||
"warningMessage": "Other users might inherit access via their respective roles on the parent database or group."
|
||||
"warningMessage": "Other users might inherit access via their respective roles on the parent database or group.",
|
||||
"headerTooltip": "Table roles will override group and database roles."
|
||||
}
|
||||
},
|
||||
"memberRolesShareToggle": {
|
||||
|
@ -181,7 +185,8 @@
|
|||
},
|
||||
"memberRolesMembersList": {
|
||||
"remove": "Remove",
|
||||
"teamMembersCount": "{count} team members"
|
||||
"teamMembersCount": "{count} team members",
|
||||
"adminHelpText": "Admins can restrict other admins roles."
|
||||
},
|
||||
"roleAssignmentModal": {
|
||||
"membersTab": "Members",
|
||||
|
@ -202,7 +207,15 @@
|
|||
"types": {
|
||||
"members": "members",
|
||||
"teams": "teams"
|
||||
}
|
||||
},
|
||||
"helpTooltip": "Member role assignments override team role assignments."
|
||||
},
|
||||
"membersRoleField": {
|
||||
"noAccessHelpText": "This user requires explicit access to resources.",
|
||||
"adminHelpText": "Admins can restrict other admins roles."
|
||||
},
|
||||
"membersPagePlugin": {
|
||||
"roleHelpText": "Can be overriden with roles on databases and tables."
|
||||
},
|
||||
"oauthSettingsForm": {
|
||||
"providerName": "Name",
|
||||
|
@ -229,4 +242,4 @@
|
|||
"userTeamsField": {
|
||||
"no_records": "No teams"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,7 +68,8 @@ export class EnterpriseMembersPagePluginType extends MembersPagePluginType {
|
|||
false,
|
||||
{
|
||||
groupId: group.id,
|
||||
}
|
||||
},
|
||||
this.app.i18n.t('membersPagePlugin.roleHelpText')
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
|
@ -107,3 +107,5 @@
|
|||
@import 'auth';
|
||||
@import "expand_on_overflow_list";
|
||||
@import 'list';
|
||||
@import 'help_icon';
|
||||
@import 'group_invite_form';
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
.group-invite-form__role-selector {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.group-invite-form__role-selector-dropdown {
|
||||
width: 100%;
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
.help-icon {
|
||||
color: $color-neutral-600;
|
||||
}
|
|
@ -42,6 +42,7 @@
|
|||
color: $white;
|
||||
padding: 0 8px;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
|
||||
@include fixed-height(26px, 12px);
|
||||
}
|
||||
|
|
26
web-frontend/modules/core/components/HelpIcon.vue
Normal file
26
web-frontend/modules/core/components/HelpIcon.vue
Normal file
|
@ -0,0 +1,26 @@
|
|||
<template>
|
||||
<i v-tooltip="tooltip" class="help-icon fas" :class="iconClass"> </i>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'HelpIcon',
|
||||
props: {
|
||||
tooltip: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: null,
|
||||
},
|
||||
isWarning: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
iconClass() {
|
||||
return this.isWarning ? 'fa-exclamation-circle' : 'fa-question-circle'
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
|
@ -25,11 +25,14 @@
|
|||
>
|
||||
<div class="data-table__table-cell-head">
|
||||
<template v-if="col.sortable">
|
||||
<a
|
||||
class="data-table__table-cell-head-link"
|
||||
@click="toggleSort(col)"
|
||||
>{{ col.header }}</a
|
||||
>
|
||||
<div>
|
||||
<a
|
||||
class="data-table__table-cell-head-link"
|
||||
@click="toggleSort(col)"
|
||||
>{{ col.header }}</a
|
||||
>
|
||||
<HelpIcon v-if="col.helpText" :tooltip="col.helpText" />
|
||||
</div>
|
||||
<div>
|
||||
<template v-if="sorted(col)">
|
||||
<i class="fas" :class="sortIcon(col)"></i>
|
||||
|
@ -37,7 +40,14 @@
|
|||
</template>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>{{ col.header }}</template>
|
||||
<template v-else>
|
||||
<div>
|
||||
{{ col.header }}
|
||||
<HelpIcon
|
||||
v-if="col.helpText"
|
||||
:tooltip="col.helpText"
|
||||
/></div
|
||||
></template>
|
||||
</div>
|
||||
</th>
|
||||
</tr>
|
||||
|
|
|
@ -22,15 +22,22 @@
|
|||
<div class="col col-5">
|
||||
<FormElement class="control">
|
||||
<div class="control__elements">
|
||||
<Dropdown v-model="values.permissions" :show-search="false">
|
||||
<DropdownItem
|
||||
v-for="role in roles"
|
||||
:key="role.uid"
|
||||
:name="role.name"
|
||||
:value="role.uid"
|
||||
:description="role.description"
|
||||
></DropdownItem>
|
||||
</Dropdown>
|
||||
<div class="group-invite-form__role-selector">
|
||||
<slot name="roleSelectorLabel"></slot>
|
||||
<Dropdown
|
||||
v-model="values.permissions"
|
||||
class="group-invite-form__role-selector-dropdown"
|
||||
:show-search="false"
|
||||
>
|
||||
<DropdownItem
|
||||
v-for="role in roles"
|
||||
:key="role.uid"
|
||||
:name="role.name"
|
||||
:value="role.uid"
|
||||
:description="role.description"
|
||||
></DropdownItem>
|
||||
</Dropdown>
|
||||
</div>
|
||||
</div>
|
||||
</FormElement>
|
||||
</div>
|
||||
|
|
|
@ -9,15 +9,23 @@
|
|||
:group="group"
|
||||
@submitted="inviteSubmitted"
|
||||
>
|
||||
<div class="col col-12 align-right">
|
||||
<button
|
||||
:class="{ 'button--loading': inviteLoading }"
|
||||
class="button"
|
||||
:disabled="inviteLoading"
|
||||
>
|
||||
{{ $t('membersSettings.membersInviteModal.submit') }}
|
||||
</button>
|
||||
</div>
|
||||
<template #default>
|
||||
<div class="col col-12 align-right">
|
||||
<button
|
||||
:class="{ 'button--loading': inviteLoading }"
|
||||
class="button"
|
||||
:disabled="inviteLoading"
|
||||
>
|
||||
{{ $t('membersSettings.membersInviteModal.submit') }}
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
<template #roleSelectorLabel>
|
||||
<HelpIcon
|
||||
class="margin-right-1"
|
||||
:tooltip="$t('membersSettings.membersInviteModal.helpIconText')"
|
||||
/>
|
||||
</template>
|
||||
</GroupInviteForm>
|
||||
</Modal>
|
||||
</template>
|
||||
|
|
|
@ -25,7 +25,8 @@ export default class CrudTableColumn {
|
|||
stickyLeft = false,
|
||||
stickyRight = false,
|
||||
additionalProps = {},
|
||||
widthPerc = ''
|
||||
widthPerc = '',
|
||||
helpText = null
|
||||
) {
|
||||
this.key = key
|
||||
this._header = header
|
||||
|
@ -35,6 +36,7 @@ export default class CrudTableColumn {
|
|||
this.stickyRight = stickyRight
|
||||
this.additionalProps = additionalProps
|
||||
this.widthPerc = widthPerc
|
||||
this.helpText = helpText
|
||||
}
|
||||
|
||||
get header() {
|
||||
|
|
|
@ -465,6 +465,7 @@
|
|||
"membersInviteModal": {
|
||||
"title": "Invite group members",
|
||||
"submit": "Send invite",
|
||||
"helpIconText": "The selected role will be the users default role in this group.",
|
||||
"errors": {
|
||||
"userAlreadyInGroup": {
|
||||
"title": "User is already in the group.",
|
||||
|
|
|
@ -20,6 +20,7 @@ import Alert from '@baserow/modules/core/components/Alert'
|
|||
import Tabs from '@baserow/modules/core/components/Tabs'
|
||||
import Tab from '@baserow/modules/core/components/Tab'
|
||||
import List from '@baserow/modules/core/components/List'
|
||||
import HelpIcon from '@baserow/modules/core/components/HelpIcon'
|
||||
|
||||
import lowercase from '@baserow/modules/core/filters/lowercase'
|
||||
import uppercase from '@baserow/modules/core/filters/uppercase'
|
||||
|
@ -54,6 +55,7 @@ Vue.component('ProgressBar', ProgressBar)
|
|||
Vue.component('Tab', Tab)
|
||||
Vue.component('Tabs', Tabs)
|
||||
Vue.component('List', List)
|
||||
Vue.component('HelpIcon', HelpIcon)
|
||||
|
||||
Vue.filter('lowercase', lowercase)
|
||||
Vue.filter('uppercase', uppercase)
|
||||
|
|
Loading…
Reference in a new issue