Browse Source

fix: refactor isUIAllowed and move to useRoles composable

pull/6399/head
mertmit 1 year ago
parent
commit
b2eadae74f
  1. 4
      packages/nc-gui/components/cell/MultiSelect.vue
  2. 4
      packages/nc-gui/components/cell/SingleSelect.vue
  3. 4
      packages/nc-gui/components/cell/TextArea.vue
  4. 9
      packages/nc-gui/components/cell/attachment/Modal.vue
  5. 16
      packages/nc-gui/components/dashboard/TreeView/AddNewTableNode.vue
  6. 14
      packages/nc-gui/components/dashboard/TreeView/BaseOptions.vue
  7. 20
      packages/nc-gui/components/dashboard/TreeView/ProjectNode.vue
  8. 16
      packages/nc-gui/components/dashboard/TreeView/TableNode.vue
  9. 4
      packages/nc-gui/components/dashboard/TreeView/index.vue
  10. 2
      packages/nc-gui/components/general/AddBaseButton.vue
  11. 4
      packages/nc-gui/components/general/ShareBaseButton.vue
  12. 4
      packages/nc-gui/components/general/ShareProject.vue
  13. 7
      packages/nc-gui/components/project/AllTables.vue
  14. 2
      packages/nc-gui/components/project/View.vue
  15. 6
      packages/nc-gui/components/smartsheet/Cell.vue
  16. 2
      packages/nc-gui/components/smartsheet/Details.vue
  17. 4
      packages/nc-gui/components/smartsheet/Form.vue
  18. 2
      packages/nc-gui/components/smartsheet/Gallery.vue
  19. 2
      packages/nc-gui/components/smartsheet/Kanban.vue
  20. 4
      packages/nc-gui/components/smartsheet/Toolbar.vue
  21. 15
      packages/nc-gui/components/smartsheet/expanded-form/Comments.vue
  22. 4
      packages/nc-gui/components/smartsheet/expanded-form/Header.vue
  23. 3
      packages/nc-gui/components/smartsheet/expanded-form/index.vue
  24. 4
      packages/nc-gui/components/smartsheet/grid/Table.vue
  25. 4
      packages/nc-gui/components/smartsheet/header/Cell.vue
  26. 4
      packages/nc-gui/components/smartsheet/header/VirtualCell.vue
  27. 4
      packages/nc-gui/components/smartsheet/sidebar/RenameableMenuItem.vue
  28. 4
      packages/nc-gui/components/smartsheet/sidebar/index.vue
  29. 2
      packages/nc-gui/components/smartsheet/sidebar/toolbar/Developer.vue
  30. 4
      packages/nc-gui/components/smartsheet/toolbar/KanbanStackEditOrAdd.vue
  31. 4
      packages/nc-gui/components/smartsheet/toolbar/MoreActions.vue
  32. 4
      packages/nc-gui/components/smartsheet/toolbar/ShareView.vue
  33. 4
      packages/nc-gui/components/smartsheet/toolbar/ViewActions.vue
  34. 4
      packages/nc-gui/components/tabs/Auth.vue
  35. 4
      packages/nc-gui/components/tabs/Smartsheet.vue
  36. 4
      packages/nc-gui/components/tabs/auth/UserManagement.vue
  37. 4
      packages/nc-gui/components/virtual-cell/BelongsTo.vue
  38. 4
      packages/nc-gui/components/virtual-cell/HasMany.vue
  39. 2
      packages/nc-gui/components/virtual-cell/Links.vue
  40. 4
      packages/nc-gui/components/virtual-cell/ManyToMany.vue
  41. 2
      packages/nc-gui/components/virtual-cell/components/ItemChip.vue
  42. 4
      packages/nc-gui/components/workspace/CreateProjectBtn.vue
  43. 10
      packages/nc-gui/components/workspace/ProjectList.vue
  44. 2
      packages/nc-gui/composables/useExpandedFormStore.ts
  45. 15
      packages/nc-gui/composables/useGridViewColumn.ts
  46. 4
      packages/nc-gui/composables/useKanbanViewStore.ts
  47. 2
      packages/nc-gui/composables/useMapViewDataStore.ts
  48. 47
      packages/nc-gui/composables/useRoles/index.ts
  49. 51
      packages/nc-gui/composables/useUIPermission/index.ts
  50. 0
      packages/nc-gui/composables/useUIPermission/rolePermissions.ts
  51. 15
      packages/nc-gui/composables/useViewColumns.ts
  52. 4
      packages/nc-gui/composables/useViewData.ts
  53. 4
      packages/nc-gui/composables/useViewFilters.ts
  54. 2
      packages/nc-gui/composables/useViewGroupBy.ts
  55. 4
      packages/nc-gui/composables/useViewSorts.ts
  56. 148
      packages/nc-gui/lib/acl.ts
  57. 149
      packages/nc-gui/lib/constants.ts
  58. 1
      packages/nc-gui/lib/index.ts
  59. 4
      packages/nc-gui/pages/account/index.vue
  60. 4
      packages/nc-gui/pages/account/index/users/[[nestedPage]].vue
  61. 2
      packages/nc-gui/store/projectsShortcuts.ts
  62. 4
      packages/nocodb-sdk/src/lib/helperFunctions.ts

4
packages/nc-gui/components/cell/MultiSelect.vue

@ -26,8 +26,8 @@ import {
useEventListener, useEventListener,
useMetas, useMetas,
useProject, useProject,
useRoles,
useSelectedCellKeyupListener, useSelectedCellKeyupListener,
useUIPermission,
watch, watch,
} from '#imports' } from '#imports'
import MdiCloseCircle from '~icons/mdi/close-circle' import MdiCloseCircle from '~icons/mdi/close-circle'
@ -79,7 +79,7 @@ const { $api } = useNuxtApp()
const { getMeta } = useMetas() const { getMeta } = useMetas()
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useRoles()
const { isPg, isMysql } = useProject() const { isPg, isMysql } = useProject()

4
packages/nc-gui/components/cell/SingleSelect.vue

@ -22,8 +22,8 @@ import {
ref, ref,
useEventListener, useEventListener,
useProject, useProject,
useRoles,
useSelectedCellKeyupListener, useSelectedCellKeyupListener,
useUIPermission,
watch, watch,
} from '#imports' } from '#imports'
@ -69,7 +69,7 @@ const searchVal = ref()
const { getMeta } = useMetas() const { getMeta } = useMetas()
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useRoles()
const { isPg, isMysql } = useProject() const { isPg, isMysql } = useProject()

4
packages/nc-gui/components/cell/TextArea.vue

@ -6,11 +6,11 @@ import {
EditColumnInj, EditColumnInj,
EditModeInj, EditModeInj,
IsExpandedFormOpenInj, IsExpandedFormOpenInj,
ReadonlyInj,
RowHeightInj, RowHeightInj,
iconMap, iconMap,
inject, inject,
useVModel, useVModel,
ReadonlyInj,
} from '#imports' } from '#imports'
const props = defineProps<{ const props = defineProps<{
@ -139,9 +139,9 @@ onClickOutside(inputWrapperRef, (e) => {
class="p-1 !pt-1 !pr-3 !border-0 !border-r-0 !focus:outline-transparent nc-scrollbar-md !text-black" class="p-1 !pt-1 !pr-3 !border-0 !border-r-0 !focus:outline-transparent nc-scrollbar-md !text-black"
:bordered="false" :bordered="false"
:auto-size="{ minRows: 20, maxRows: 20 }" :auto-size="{ minRows: 20, maxRows: 20 }"
:disabled="readOnly"
@keydown.stop @keydown.stop
@keydown.escape="isVisible = false" @keydown.escape="isVisible = false"
:disabled="readOnly"
/> />
</div> </div>
</template> </template>

9
packages/nc-gui/components/cell/attachment/Modal.vue

@ -2,9 +2,9 @@
import { onKeyDown, useEventListener } from '@vueuse/core' import { onKeyDown, useEventListener } from '@vueuse/core'
import { useAttachmentCell } from './utils' import { useAttachmentCell } from './utils'
import { useSortable } from './sort' import { useSortable } from './sort'
import { iconMap, isImage, ref, useAttachment, useDropZone, useUIPermission, watch } from '#imports' import { iconMap, isImage, ref, useAttachment, useDropZone, useRoles, watch } from '#imports'
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useRoles()
const { const {
open, open,
@ -155,10 +155,7 @@ const handleFileDelete = (i: number) => {
</div> </div>
</a-tooltip> </a-tooltip>
<a-tooltip <a-tooltip v-if="isSharedForm || (!readOnly && isUIAllowed('dataEdit') && !isPublic && !isLocked)" placement="bottom">
v-if="isSharedForm || (!readOnly && isUIAllowed('dataEdit') && !isPublic && !isLocked)"
placement="bottom"
>
<template #title> Rename File </template> <template #title> Rename File </template>
<div class="nc-attachment-download group-hover:(opacity-100) mr-[35px]"> <div class="nc-attachment-download group-hover:(opacity-100) mr-[35px]">

16
packages/nc-gui/components/dashboard/TreeView/AddNewTableNode.vue

@ -4,7 +4,7 @@ import { storeToRefs } from 'pinia'
import { toRef } from '@vue/reactivity' import { toRef } from '@vue/reactivity'
import { resolveComponent } from '@vue/runtime-core' import { resolveComponent } from '@vue/runtime-core'
import { ref } from 'vue' import { ref } from 'vue'
import { ProjectRoleInj, useDialog, useUIPermission } from '#imports' import { ProjectRoleInj, useDialog, useRoles } from '#imports'
const props = withDefaults( const props = withDefaults(
defineProps<{ defineProps<{
@ -20,7 +20,7 @@ const emit = defineEmits<{
openTableCreateDialog: () => void openTableCreateDialog: () => void
}>() }>()
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useRoles()
const project = toRef(props, 'project') const project = toRef(props, 'project')
@ -116,7 +116,7 @@ function openTableCreateMagicDialog(baseId?: string) {
<template> <template>
<div <div
v-if="isUIAllowed('tableCreate', false, projectRole)" v-if="isUIAllowed('tableCreate', { roles: projectRole })"
class="group flex items-center gap-2 pl-2 pr-4.75 py-1 text-primary/70 hover:(text-primary/100) cursor-pointer select-none" class="group flex items-center gap-2 pl-2 pr-4.75 py-1 text-primary/70 hover:(text-primary/100) cursor-pointer select-none"
@click="emit('openTableCreateDialog')" @click="emit('openTableCreateDialog')"
> >
@ -158,7 +158,7 @@ function openTableCreateMagicDialog(baseId?: string) {
<!-- Quick Import From --> <!-- Quick Import From -->
<a-menu-item-group :title="$t('title.quickImportFrom')" class="!px-0 !mx-0"> <a-menu-item-group :title="$t('title.quickImportFrom')" class="!px-0 !mx-0">
<a-menu-item <a-menu-item
v-if="isUIAllowed('airtableImport', false, projectRole)" v-if="isUIAllowed('airtableImport', { roles: projectRole })"
key="quick-import-airtable" key="quick-import-airtable"
@click="openAirtableImportDialog(project.bases[baseIndex].id)" @click="openAirtableImportDialog(project.bases[baseIndex].id)"
> >
@ -169,7 +169,7 @@ function openTableCreateMagicDialog(baseId?: string) {
</a-menu-item> </a-menu-item>
<a-menu-item <a-menu-item
v-if="isUIAllowed('csvImport', false, projectRole)" v-if="isUIAllowed('csvImport', { roles: projectRole })"
key="quick-import-csv" key="quick-import-csv"
@click="openQuickImportDialog('csv', project.bases[baseIndex].id)" @click="openQuickImportDialog('csv', project.bases[baseIndex].id)"
> >
@ -180,7 +180,7 @@ function openTableCreateMagicDialog(baseId?: string) {
</a-menu-item> </a-menu-item>
<a-menu-item <a-menu-item
v-if="isUIAllowed('jsonImport', false, projectRole)" v-if="isUIAllowed('jsonImport', { roles: projectRole })"
key="quick-import-json" key="quick-import-json"
@click="openQuickImportDialog('json', project.bases[baseIndex].id)" @click="openQuickImportDialog('json', project.bases[baseIndex].id)"
> >
@ -191,7 +191,7 @@ function openTableCreateMagicDialog(baseId?: string) {
</a-menu-item> </a-menu-item>
<a-menu-item <a-menu-item
v-if="isUIAllowed('excelImport', false, projectRole)" v-if="isUIAllowed('excelImport', { roles: projectRole })"
key="quick-import-excel" key="quick-import-excel"
@click="openQuickImportDialog('excel', project.bases[baseIndex].id)" @click="openQuickImportDialog('excel', project.bases[baseIndex].id)"
> >
@ -243,7 +243,7 @@ function openTableCreateMagicDialog(baseId?: string) {
<a-menu-divider class="my-0" /> --> <a-menu-divider class="my-0" /> -->
<a-menu-item v-if="isUIAllowed('importRequest', false, projectRole)" key="add-new-table" class="py-1 rounded-b"> <a-menu-item v-if="isUIAllowed('importRequest', { roles: projectRole })" key="add-new-table" class="py-1 rounded-b">
<a <a
v-e="['e:datasource:import-request']" v-e="['e:datasource:import-request']"
href="https://github.com/nocodb/nocodb/issues/2052" href="https://github.com/nocodb/nocodb/issues/2052"

14
packages/nc-gui/components/dashboard/TreeView/BaseOptions.vue

@ -8,7 +8,7 @@ const props = defineProps<{
const base = toRef(props, 'base') const base = toRef(props, 'base')
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useRoles()
const projectRole = inject(ProjectRoleInj) const projectRole = inject(ProjectRoleInj)
@ -68,7 +68,7 @@ function openQuickImportDialog(type: string) {
<template #expandIcon></template> <template #expandIcon></template>
<NcMenuItem <NcMenuItem
v-if="isUIAllowed('airtableImport', false, projectRole)" v-if="isUIAllowed('airtableImport', { roles: projectRole })"
key="quick-import-airtable" key="quick-import-airtable"
@click="openAirtableImportDialog(base.id)" @click="openAirtableImportDialog(base.id)"
> >
@ -76,13 +76,17 @@ function openQuickImportDialog(type: string) {
<div class="ml-0.5">Airtable</div> <div class="ml-0.5">Airtable</div>
</NcMenuItem> </NcMenuItem>
<NcMenuItem v-if="isUIAllowed('csvImport', false, projectRole)" key="quick-import-csv" @click="openQuickImportDialog('csv')"> <NcMenuItem
v-if="isUIAllowed('csvImport', { roles: projectRole })"
key="quick-import-csv"
@click="openQuickImportDialog('csv')"
>
<GeneralIcon icon="csv" class="w-4 group-hover:text-black" /> <GeneralIcon icon="csv" class="w-4 group-hover:text-black" />
CSV file CSV file
</NcMenuItem> </NcMenuItem>
<NcMenuItem <NcMenuItem
v-if="isUIAllowed('jsonImport', false, projectRole)" v-if="isUIAllowed('jsonImport', { roles: projectRole })"
key="quick-import-json" key="quick-import-json"
@click="openQuickImportDialog('json')" @click="openQuickImportDialog('json')"
> >
@ -91,7 +95,7 @@ function openQuickImportDialog(type: string) {
</NcMenuItem> </NcMenuItem>
<NcMenuItem <NcMenuItem
v-if="isUIAllowed('excelImport', false, projectRole)" v-if="isUIAllowed('excelImport', { roles: projectRole })"
key="quick-import-excel" key="quick-import-excel"
@click="openQuickImportDialog('excel')" @click="openQuickImportDialog('excel')"
> >

20
packages/nc-gui/components/dashboard/TreeView/ProjectNode.vue

@ -44,7 +44,7 @@ const { activeTable } = storeToRefs(useTablesStore())
const { appInfo, navigateToProject } = useGlobal() const { appInfo, navigateToProject } = useGlobal()
const { orgRoles } = useRoles() const { orgRoles, isUIAllowed } = useRoles()
useTabs() useTabs()
@ -56,8 +56,6 @@ const { t } = useI18n()
const input = ref<HTMLInputElement>() const input = ref<HTMLInputElement>()
const { isUIAllowed } = useUIPermission()
const projectRole = inject(ProjectRoleInj) const projectRole = inject(ProjectRoleInj)
const { activeProjectId } = storeToRefs(useProjects()) const { activeProjectId } = storeToRefs(useProjects())
@ -441,7 +439,11 @@ const DlgProjectDuplicateOnOk = async (jobData: { id: string; project_id: string
</span> </span>
<div :class="{ 'flex flex-grow h-full': !editMode }" @click="onProjectClick(project)"></div> <div :class="{ 'flex flex-grow h-full': !editMode }" @click="onProjectClick(project)"></div>
<NcDropdown v-if="isUIAllowed('tableCreate', false, projectRole)" v-model:visible="isOptionsOpen" :trigger="['click']"> <NcDropdown
v-if="isUIAllowed('tableCreate', { roles: projectRole })"
v-model:visible="isOptionsOpen"
:trigger="['click']"
>
<NcButton <NcButton
class="nc-sidebar-node-btn" class="nc-sidebar-node-btn"
:class="{ '!text-black !opacity-100': isOptionsOpen }" :class="{ '!text-black !opacity-100': isOptionsOpen }"
@ -473,7 +475,7 @@ const DlgProjectDuplicateOnOk = async (jobData: { id: string; project_id: string
{{ $t('activity.account.projInfo') }} {{ $t('activity.account.projInfo') }}
</NcMenuItem> </NcMenuItem>
<NcMenuItem <NcMenuItem
v-if="isUIAllowed('projectDuplicate', true, [stringifyRolesObj(orgRoles), projectRole].join())" v-if="isUIAllowed('projectDuplicate', { roles: [stringifyRolesObj(orgRoles), projectRole].join() })"
@click="duplicateProject(project)" @click="duplicateProject(project)"
> >
<GeneralIcon icon="duplicate" class="text-gray-700" /> <GeneralIcon icon="duplicate" class="text-gray-700" />
@ -516,7 +518,7 @@ const DlgProjectDuplicateOnOk = async (jobData: { id: string; project_id: string
</template> </template>
<NcMenuItem <NcMenuItem
v-if="isUIAllowed('projectDelete', false, projectRole)" v-if="isUIAllowed('projectDelete', { roles: [stringifyRolesObj(orgRoles), projectRole].join() })"
class="!text-red-500 !hover:bg-red-50" class="!text-red-500 !hover:bg-red-50"
@click="isProjectDeleteDialogVisible = true" @click="isProjectDeleteDialogVisible = true"
> >
@ -528,7 +530,7 @@ const DlgProjectDuplicateOnOk = async (jobData: { id: string; project_id: string
</NcDropdown> </NcDropdown>
<NcButton <NcButton
v-if="isUIAllowed('tableCreate', false, projectRole)" v-if="isUIAllowed('tableCreate', { roles: projectRole })"
class="nc-sidebar-node-btn" class="nc-sidebar-node-btn"
size="xxsmall" size="xxsmall"
type="text" type="text"
@ -610,7 +612,7 @@ const DlgProjectDuplicateOnOk = async (jobData: { id: string; project_id: string
</a-tooltip> </a-tooltip>
</div> </div>
<div <div
v-if="isUIAllowed('tableCreate', false, projectRole)" v-if="isUIAllowed('tableCreate', { roles: projectRole })"
class="flex flex-row items-center gap-x-0.25 w-12.25" class="flex flex-row items-center gap-x-0.25 w-12.25"
> >
<NcDropdown <NcDropdown
@ -648,7 +650,7 @@ const DlgProjectDuplicateOnOk = async (jobData: { id: string; project_id: string
</NcDropdown> </NcDropdown>
<NcButton <NcButton
v-if="isUIAllowed('tableCreate', false, projectRole)" v-if="isUIAllowed('tableCreate', { roles: projectRole })"
type="text" type="text"
size="xxsmall" size="xxsmall"
class="nc-sidebar-node-btn" class="nc-sidebar-node-btn"

16
packages/nc-gui/components/dashboard/TreeView/TableNode.vue

@ -5,7 +5,7 @@ import { message } from 'ant-design-vue'
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import { useNuxtApp } from '#app' import { useNuxtApp } from '#app'
import { ProjectRoleInj, TreeViewInj, useTabs, useUIPermission } from '#imports' import { ProjectRoleInj, TreeViewInj, useRoles, useTabs } from '#imports'
const props = withDefaults( const props = withDefaults(
defineProps<{ defineProps<{
@ -22,7 +22,7 @@ const baseIndex = toRef(props, 'baseIndex')
const route = useRoute() const route = useRoute()
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useRoles()
const tabStore = useTabs() const tabStore = useTabs()
const { updateTab } = tabStore const { updateTab } = tabStore
@ -71,7 +71,7 @@ const { isSharedBase } = useProject()
// const isMultiBase = computed(() => project.bases && project.bases.length > 1) // const isMultiBase = computed(() => project.bases && project.bases.length > 1)
const canUserEditEmote = computed(() => { const canUserEditEmote = computed(() => {
return isUIAllowed('tableIconEdit', false, projectRole?.value) return isUIAllowed('tableIconEdit', { roles: projectRole?.value })
}) })
</script> </script>
@ -125,7 +125,7 @@ const canUserEditEmote = computed(() => {
v-if="table.type === 'table'" v-if="table.type === 'table'"
class="flex w-5 !text-gray-500 text-sm" class="flex w-5 !text-gray-500 text-sm"
:class="{ :class="{
'group-hover:text-gray-500': isUIAllowed('tableSort', false, projectRole), 'group-hover:text-gray-500': isUIAllowed('tableSort', { roles: projectRole }),
'!text-black': openedTableId === table.id, '!text-black': openedTableId === table.id,
}" }"
/> />
@ -133,7 +133,7 @@ const canUserEditEmote = computed(() => {
v-else v-else
class="flex w-5 !text-gray-500 text-sm" class="flex w-5 !text-gray-500 text-sm"
:class="{ :class="{
'group-hover:text-gray-500': isUIAllowed('tableSort', false, projectRole), 'group-hover:text-gray-500': isUIAllowed('tableSort', { roles: projectRole }),
'!text-black': openedTableId === table.id, '!text-black': openedTableId === table.id,
}" }"
/> />
@ -157,7 +157,7 @@ const canUserEditEmote = computed(() => {
<NcDropdown <NcDropdown
v-if=" v-if="
!isSharedBase && (isUIAllowed('tableRename', false, projectRole) || isUIAllowed('tableDelete', false, projectRole)) !isSharedBase && (isUIAllowed('tableRename', { roles: projectRole }) || isUIAllowed('tableDelete', { roles: projectRole }))
" "
:trigger="['click']" :trigger="['click']"
@click.stop @click.stop
@ -173,7 +173,7 @@ const canUserEditEmote = computed(() => {
<template #overlay> <template #overlay>
<NcMenu> <NcMenu>
<NcMenuItem <NcMenuItem
v-if="isUIAllowed('tableRename', false, projectRole)" v-if="isUIAllowed('tableRename', { roles: projectRole })"
:data-testid="`sidebar-table-rename-${table.title}`" :data-testid="`sidebar-table-rename-${table.title}`"
@click="openRenameTableDialog(table, project.bases[baseIndex].id)" @click="openRenameTableDialog(table, project.bases[baseIndex].id)"
> >
@ -195,7 +195,7 @@ const canUserEditEmote = computed(() => {
</NcMenuItem> </NcMenuItem>
<NcMenuItem <NcMenuItem
v-if="isUIAllowed('tableDelete', false, projectRole)" v-if="isUIAllowed('tableDelete', { roles: projectRole })"
:data-testid="`sidebar-table-delete-${table.title}`" :data-testid="`sidebar-table-delete-${table.title}`"
class="!text-red-500 !hover:bg-red-50" class="!text-red-500 !hover:bg-red-50"
@click="isTableDeleteDialogVisible = true" @click="isTableDeleteDialogVisible = true"

4
packages/nc-gui/components/dashboard/TreeView/index.vue

@ -20,14 +20,14 @@ import {
useNuxtApp, useNuxtApp,
useProject, useProject,
useProjects, useProjects,
useRoles,
useTablesStore, useTablesStore,
useTabs, useTabs,
useUIPermission,
} from '#imports' } from '#imports'
import { useRouter } from '#app' import { useRouter } from '#app'
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useRoles()
const { addTab } = useTabs() const { addTab } = useTabs()

2
packages/nc-gui/components/general/AddBaseButton.vue

@ -1,7 +1,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { iconMap } from '#imports' import { iconMap } from '#imports'
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useRoles()
const { t } = useI18n() const { t } = useI18n()

4
packages/nc-gui/components/general/ShareBaseButton.vue

@ -1,11 +1,11 @@
<script setup lang="ts"> <script setup lang="ts">
import { isDrawerOrModalExist, isMac, useNuxtApp, useRoute, useUIPermission } from '#imports' import { isDrawerOrModalExist, isMac, useNuxtApp, useRoles, useRoute } from '#imports'
const route = useRoute() const route = useRoute()
const showUserModal = ref(false) const showUserModal = ref(false)
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useRoles()
const { $e } = useNuxtApp() const { $e } = useNuxtApp()

4
packages/nc-gui/components/general/ShareProject.vue

@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { isDrawerOrModalExist, isMac, useNuxtApp } from '#imports' import { isDrawerOrModalExist, isMac, useNuxtApp, useRoles } from '#imports'
interface Props { interface Props {
disabled?: boolean disabled?: boolean
@ -15,7 +15,7 @@ const { project } = storeToRefs(useProject())
const { $e } = useNuxtApp() const { $e } = useNuxtApp()
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useRoles()
useEventListener(document, 'keydown', async (e: KeyboardEvent) => { useEventListener(document, 'keydown', async (e: KeyboardEvent) => {
const cmdOrCtrl = isMac() ? e.metaKey : e.ctrlKey const cmdOrCtrl = isMac() ? e.metaKey : e.ctrlKey

7
packages/nc-gui/components/project/AllTables.vue

@ -1,5 +1,4 @@
<script lang="ts" setup> <script lang="ts" setup>
import { stringifyRolesObj } from 'nocodb-sdk'
import type { BaseType, TableType } from 'nocodb-sdk' import type { BaseType, TableType } from 'nocodb-sdk'
import dayjs from 'dayjs' import dayjs from 'dayjs'
@ -7,9 +6,7 @@ const { activeTables } = storeToRefs(useTablesStore())
const { openTable } = useTablesStore() const { openTable } = useTablesStore()
const { openedProject } = storeToRefs(useProjects()) const { openedProject } = storeToRefs(useProjects())
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useRoles()
const { allRoles } = useRoles()
const { $e } = useNuxtApp() const { $e } = useNuxtApp()
@ -74,7 +71,7 @@ function openTableCreateDialog(baseIndex?: number | undefined) {
<template> <template>
<div class="nc-all-tables-view"> <div class="nc-all-tables-view">
<div v-if="isUIAllowed('tableCreate', false, stringifyRolesObj(allRoles))" class="flex flex-row gap-x-6 pb-3 pt-6"> <div v-if="isUIAllowed('tableCreate')" class="flex flex-row gap-x-6 pb-3 pt-6">
<div class="nc-project-view-all-table-btn" data-testid="proj-view-btn__add-new-table" @click="openTableCreateDialog()"> <div class="nc-project-view-all-table-btn" data-testid="proj-view-btn__add-new-table" @click="openTableCreateDialog()">
<GeneralIcon icon="addOutlineBox" /> <GeneralIcon icon="addOutlineBox" />
<div class="label">{{ $t('general.new') }} {{ $t('objects.table') }}</div> <div class="label">{{ $t('general.new') }} {{ $t('objects.table') }}</div>

2
packages/nc-gui/components/project/View.vue

@ -14,7 +14,7 @@ const route = router.currentRoute
return openedProject.value?.bases?.[0] return openedProject.value?.bases?.[0]
}) */ }) */
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useRoles()
const { isMobileMode } = useGlobal() const { isMobileMode } = useGlobal()

6
packages/nc-gui/components/smartsheet/Cell.vue

@ -252,7 +252,11 @@ onUnmounted(() => {
<LazyCellJson v-else-if="isJSON(column)" v-model="vModel" /> <LazyCellJson v-else-if="isJSON(column)" v-model="vModel" />
<LazyCellText v-else v-model="vModel" /> <LazyCellText v-else v-model="vModel" />
<div <div
v-if="(isLocked || (isPublic && readOnly && !isForm) || isSystemColumn(column)) && !isAttachment(column) && !isTextArea(column)" v-if="
(isLocked || (isPublic && readOnly && !isForm) || isSystemColumn(column)) &&
!isAttachment(column) &&
!isTextArea(column)
"
class="nc-locked-overlay" class="nc-locked-overlay"
/> />
</template> </template>

2
packages/nc-gui/components/smartsheet/Details.vue

@ -2,7 +2,7 @@
const { openedViewsTab } = storeToRefs(useViewsStore()) const { openedViewsTab } = storeToRefs(useViewsStore())
const { onViewsTabChange } = useViewsStore() const { onViewsTabChange } = useViewsStore()
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useRoles()
const openedSubTab = computed({ const openedSubTab = computed({
get() { get() {

4
packages/nc-gui/components/smartsheet/Form.vue

@ -22,7 +22,7 @@ import {
useGlobal, useGlobal,
useI18n, useI18n,
useNuxtApp, useNuxtApp,
useUIPermission, useRoles,
useViewColumns, useViewColumns,
useViewData, useViewData,
watch, watch,
@ -42,7 +42,7 @@ const formRef = ref()
const { $api, $e } = useNuxtApp() const { $api, $e } = useNuxtApp()
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useRoles()
const formState = reactive({}) const formState = reactive({})

2
packages/nc-gui/components/smartsheet/Gallery.vue

@ -84,7 +84,7 @@ const isRowEmpty = (record: any, col: any) => {
return Array.isArray(val) && val.length === 0 return Array.isArray(val) && val.length === 0
} }
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useRoles()
const hasEditPermission = computed(() => isUIAllowed('dataEdit')) const hasEditPermission = computed(() => isUIAllowed('dataEdit'))
// TODO: extract this code (which is duplicated in grid and gallery) into a separate component // TODO: extract this code (which is duplicated in grid and gallery) into a separate component
const _contextMenu = ref(false) const _contextMenu = ref(false)

2
packages/nc-gui/components/smartsheet/Kanban.vue

@ -89,7 +89,7 @@ const {
const { isViewDataLoading } = storeToRefs(useViewsStore()) const { isViewDataLoading } = storeToRefs(useViewsStore())
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useRoles()
const { appInfo } = useGlobal() const { appInfo } = useGlobal()

4
packages/nc-gui/components/smartsheet/Toolbar.vue

@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { IsPublicInj, inject, ref, useSharedView, useSmartsheetStoreOrThrow, useUIPermission, useViewsStore } from '#imports' import { IsPublicInj, inject, ref, useRoles, useSharedView, useSmartsheetStoreOrThrow, useViewsStore } from '#imports'
const { isGrid, isGallery, isKanban, isMap } = useSmartsheetStoreOrThrow() const { isGrid, isGallery, isKanban, isMap } = useSmartsheetStoreOrThrow()
@ -9,7 +9,7 @@ const { isViewsLoading } = storeToRefs(useViewsStore())
const { isMobileMode } = useGlobal() const { isMobileMode } = useGlobal()
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useRoles()
const { allowCSVDownload } = useSharedView() const { allowCSVDownload } = useSharedView()

15
packages/nc-gui/components/smartsheet/expanded-form/Comments.vue

@ -1,7 +1,18 @@
<script setup lang="ts"> <script setup lang="ts">
import type { VNodeRef } from '@vue/runtime-core' import type { VNodeRef } from '@vue/runtime-core'
import type { AuditType } from 'nocodb-sdk' import type { AuditType } from 'nocodb-sdk'
import { enumColor, iconMap, ref, timeAgo, useCopy, useExpandedFormStoreOrThrow, useGlobal, useI18n, watch } from '#imports' import {
enumColor,
iconMap,
ref,
timeAgo,
useCopy,
useExpandedFormStoreOrThrow,
useGlobal,
useI18n,
useRoles,
watch,
} from '#imports'
const { loadCommentsAndLogs, commentsAndLogs, isCommentsLoading, commentsOnly, saveComment, isYou, comment, updateComment } = const { loadCommentsAndLogs, commentsAndLogs, isCommentsLoading, commentsOnly, saveComment, isYou, comment, updateComment } =
useExpandedFormStoreOrThrow() useExpandedFormStoreOrThrow()
@ -18,7 +29,7 @@ const { t } = useI18n()
const { user } = useGlobal() const { user } = useGlobal()
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useRoles()
const hasEditPermission = computed(() => isUIAllowed('commentEdit')) const hasEditPermission = computed(() => isUIAllowed('commentEdit'))

4
packages/nc-gui/components/smartsheet/expanded-form/Header.vue

@ -7,9 +7,9 @@ import {
isMac, isMac,
useCopy, useCopy,
useExpandedFormStoreOrThrow, useExpandedFormStoreOrThrow,
useRoles,
useSmartsheetRowStoreOrThrow, useSmartsheetRowStoreOrThrow,
useSmartsheetStoreOrThrow, useSmartsheetStoreOrThrow,
useUIPermission,
} from '#imports' } from '#imports'
const props = defineProps<{ view?: ViewType }>() const props = defineProps<{ view?: ViewType }>()
@ -24,7 +24,7 @@ const { commentsDrawer, displayValue, primaryKey, save: _save, loadRow, deleteRo
const { isNew, syncLTARRefs, state } = useSmartsheetRowStoreOrThrow() const { isNew, syncLTARRefs, state } = useSmartsheetRowStoreOrThrow()
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useRoles()
const reloadTrigger = inject(ReloadRowDataHookInj, createEventHook()) const reloadTrigger = inject(ReloadRowDataHookInj, createEventHook())

3
packages/nc-gui/components/smartsheet/expanded-form/index.vue

@ -21,6 +21,7 @@ import {
useActiveKeyupListener, useActiveKeyupListener,
useProvideExpandedFormStore, useProvideExpandedFormStore,
useProvideSmartsheetStore, useProvideSmartsheetStore,
useRoles,
useRouter, useRouter,
useVModel, useVModel,
watch, watch,
@ -57,7 +58,7 @@ const meta = toRef(props, 'meta')
const router = useRouter() const router = useRouter()
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useRoles()
// override cell click hook to avoid unexpected behavior at form fields // override cell click hook to avoid unexpected behavior at form fields
provide(CellClickHookInj, undefined) provide(CellClickHookInj, undefined)

4
packages/nc-gui/components/smartsheet/grid/Table.vue

@ -30,9 +30,9 @@ import {
useI18n, useI18n,
useMultiSelect, useMultiSelect,
useNuxtApp, useNuxtApp,
useRoles,
useRoute, useRoute,
useSmartsheetStoreOrThrow, useSmartsheetStoreOrThrow,
useUIPermission,
useUndoRedo, useUndoRedo,
useViewsStore, useViewsStore,
watch, watch,
@ -171,7 +171,7 @@ const cellRefs = ref<{ el: HTMLElement }[]>([])
const gridRect = useElementBounding(gridWrapper) const gridRect = useElementBounding(gridWrapper)
// #Permissions // #Permissions
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useRoles()
const hasEditPermission = computed(() => isUIAllowed('dataEdit')) const hasEditPermission = computed(() => isUIAllowed('dataEdit'))
const isAddingColumnAllowed = computed(() => !readOnly.value && !isLocked.value && isUIAllowed('fieldAdd') && !isSqlView.value) const isAddingColumnAllowed = computed(() => !readOnly.value && !isLocked.value && isUIAllowed('fieldAdd') && !isSqlView.value)

4
packages/nc-gui/components/smartsheet/header/Cell.vue

@ -1,6 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import type { ColumnReqType, ColumnType } from 'nocodb-sdk' import type { ColumnReqType, ColumnType } from 'nocodb-sdk'
import { ColumnInj, IsExpandedFormOpenInj, IsFormInj, IsKanbanInj, inject, provide, ref, toRef, useUIPermission } from '#imports' import { ColumnInj, IsExpandedFormOpenInj, IsFormInj, IsKanbanInj, inject, provide, ref, toRef, useRoles } from '#imports'
interface Props { interface Props {
column: ColumnType column: ColumnType
@ -23,7 +23,7 @@ const isKanban = inject(IsKanbanInj, ref(false))
const column = toRef(props, 'column') const column = toRef(props, 'column')
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useRoles()
provide(ColumnInj, column) provide(ColumnInj, column)

4
packages/nc-gui/components/smartsheet/header/VirtualCell.vue

@ -19,7 +19,7 @@ import {
toRef, toRef,
useI18n, useI18n,
useMetas, useMetas,
useUIPermission, useRoles,
} from '#imports' } from '#imports'
const props = defineProps<{ column: ColumnType; hideMenu?: boolean; required?: boolean | number; hideIcon?: boolean }>() const props = defineProps<{ column: ColumnType; hideMenu?: boolean; required?: boolean | number; hideIcon?: boolean }>()
@ -38,7 +38,7 @@ provide(ColumnInj, column)
const { metas } = useMetas() const { metas } = useMetas()
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useRoles()
const meta = inject(MetaInj, ref()) const meta = inject(MetaInj, ref())

4
packages/nc-gui/components/smartsheet/sidebar/RenameableMenuItem.vue

@ -2,7 +2,7 @@
import type { VNodeRef } from '@vue/runtime-core' import type { VNodeRef } from '@vue/runtime-core'
import type { KanbanType, ViewType, ViewTypes } from 'nocodb-sdk' import type { KanbanType, ViewType, ViewTypes } from 'nocodb-sdk'
import type { WritableComputedRef } from '@vue/reactivity' import type { WritableComputedRef } from '@vue/reactivity'
import { IsLockedInj, inject, message, onKeyStroke, useDebounceFn, useNuxtApp, useUIPermission, useVModel } from '#imports' import { IsLockedInj, inject, message, onKeyStroke, useDebounceFn, useNuxtApp, useRoles, useVModel } from '#imports'
interface Props { interface Props {
view: ViewType view: ViewType
@ -31,7 +31,7 @@ const vModel = useVModel(props, 'view', emits) as WritableComputedRef<ViewType &
const { $e } = useNuxtApp() const { $e } = useNuxtApp()
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useRoles()
const activeView = inject(ActiveViewInj, ref()) const activeView = inject(ActiveViewInj, ref())

4
packages/nc-gui/components/smartsheet/sidebar/index.vue

@ -10,9 +10,9 @@ import {
useCommandPalette, useCommandPalette,
useDialog, useDialog,
useNuxtApp, useNuxtApp,
useRoles,
useRoute, useRoute,
useRouter, useRouter,
useUIPermission,
useViewsStore, useViewsStore,
watch, watch,
} from '#imports' } from '#imports'
@ -39,7 +39,7 @@ const setLastOpenedViewId = (viewId?: string) => {
} }
} }
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useRoles()
const router = useRouter() const router = useRouter()

2
packages/nc-gui/components/smartsheet/sidebar/toolbar/Developer.vue

@ -1,7 +1,7 @@
<script setup lang="ts"> <script setup lang="ts">
const { isMobileMode } = useGlobal() const { isMobileMode } = useGlobal()
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useRoles()
const isPublicView = inject(IsPublicInj, ref(false)) const isPublicView = inject(IsPublicInj, ref(false))

4
packages/nc-gui/components/smartsheet/toolbar/KanbanStackEditOrAdd.vue

@ -9,10 +9,10 @@ import {
ref, ref,
useKanbanViewStoreOrThrow, useKanbanViewStoreOrThrow,
useMenuCloseOnEsc, useMenuCloseOnEsc,
useUIPermission, useRoles,
} from '#imports' } from '#imports'
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useRoles()
const { groupingFieldColumn } = useKanbanViewStoreOrThrow() const { groupingFieldColumn } = useKanbanViewStoreOrThrow()

4
packages/nc-gui/components/smartsheet/toolbar/MoreActions.vue

@ -15,9 +15,9 @@ import {
useI18n, useI18n,
useNuxtApp, useNuxtApp,
useProject, useProject,
useRoles,
useSharedView, useSharedView,
useSmartsheetStoreOrThrow, useSmartsheetStoreOrThrow,
useUIPermission,
} from '#imports' } from '#imports'
const { t } = useI18n() const { t } = useI18n()
@ -48,7 +48,7 @@ const showWebhookDrawer = ref(false)
const quickImportDialog = ref(false) const quickImportDialog = ref(false)
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useRoles()
const exportFile = async (exportType: ExportTypes) => { const exportFile = async (exportType: ExportTypes) => {
let offset = 0 let offset = 0

4
packages/nc-gui/components/smartsheet/toolbar/ShareView.vue

@ -16,8 +16,8 @@ import {
useI18n, useI18n,
useNuxtApp, useNuxtApp,
useProject, useProject,
useRoles,
useSmartsheetStoreOrThrow, useSmartsheetStoreOrThrow,
useUIPermission,
watch, watch,
} from '#imports' } from '#imports'
import type { SharedView } from '#imports' import type { SharedView } from '#imports'
@ -32,7 +32,7 @@ const { $e } = useNuxtApp()
const { dashboardUrl } = useDashboard() const { dashboardUrl } = useDashboard()
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useRoles()
const { isSharedBase } = storeToRefs(useProject()) const { isSharedBase } = storeToRefs(useProject())

4
packages/nc-gui/components/smartsheet/toolbar/ViewActions.vue

@ -17,8 +17,8 @@ import {
useMenuCloseOnEsc, useMenuCloseOnEsc,
useNuxtApp, useNuxtApp,
useProject, useProject,
useRoles,
useSmartsheetStoreOrThrow, useSmartsheetStoreOrThrow,
useUIPermission,
} from '#imports' } from '#imports'
const { t } = useI18n() const { t } = useI18n()
@ -56,7 +56,7 @@ const quickImportDialogs: Record<(typeof quickImportDialogTypes)[number], Ref<bo
{}, {},
) as Record<QuickImportDialogType, Ref<boolean>> ) as Record<QuickImportDialogType, Ref<boolean>>
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useRoles()
useProject() useProject()

4
packages/nc-gui/components/tabs/Auth.vue

@ -1,6 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import type { ComputedRef } from 'vue' import type { ComputedRef } from 'vue'
import { computed, useI18n, useUIPermission } from '#imports' import { computed, useI18n, useRoles } from '#imports'
interface Tab { interface Tab {
title: string title: string
@ -10,7 +10,7 @@ interface Tab {
const { t } = useI18n() const { t } = useI18n()
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useRoles()
const tabsInfo: Tab[] = [ const tabsInfo: Tab[] = [
{ {

4
packages/nc-gui/components/tabs/Smartsheet.vue

@ -21,8 +21,8 @@ import {
useMetas, useMetas,
useProvideKanbanViewStore, useProvideKanbanViewStore,
useProvideSmartsheetStore, useProvideSmartsheetStore,
useRoles,
useSqlEditor, useSqlEditor,
useUIPermission,
} from '#imports' } from '#imports'
import type { TabItem } from '#imports' import type { TabItem } from '#imports'
@ -30,7 +30,7 @@ const props = defineProps<{
activeTab: TabItem activeTab: TabItem
}>() }>()
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useRoles()
const { metas, getMeta } = useMetas() const { metas, getMeta } = useMetas()

4
packages/nc-gui/components/tabs/auth/UserManagement.vue

@ -14,7 +14,7 @@ import {
useI18n, useI18n,
useNuxtApp, useNuxtApp,
useProject, useProject,
useUIPermission, useRoles,
watchDebounced, watchDebounced,
} from '#imports' } from '#imports'
import type { User } from '#imports' import type { User } from '#imports'
@ -29,7 +29,7 @@ const { project } = storeToRefs(useProject())
const { copy } = useCopy() const { copy } = useCopy()
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useRoles()
const { dashboardUrl } = useDashboard() const { dashboardUrl } = useDashboard()

4
packages/nc-gui/components/virtual-cell/BelongsTo.vue

@ -16,9 +16,9 @@ import {
inject, inject,
ref, ref,
useProvideLTARStore, useProvideLTARStore,
useRoles,
useSelectedCellKeyupListener, useSelectedCellKeyupListener,
useSmartsheetRowStoreOrThrow, useSmartsheetRowStoreOrThrow,
useUIPermission,
} from '#imports' } from '#imports'
const column = inject(ColumnInj)! const column = inject(ColumnInj)!
@ -39,7 +39,7 @@ const isLocked = inject(IsLockedInj, ref(false))
const isUnderLookup = inject(IsUnderLookupInj, ref(false)) const isUnderLookup = inject(IsUnderLookupInj, ref(false))
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useRoles()
const listItemsDlg = ref(false) const listItemsDlg = ref(false)

4
packages/nc-gui/components/virtual-cell/HasMany.vue

@ -14,9 +14,9 @@ import {
inject, inject,
ref, ref,
useProvideLTARStore, useProvideLTARStore,
useRoles,
useSelectedCellKeyupListener, useSelectedCellKeyupListener,
useSmartsheetRowStoreOrThrow, useSmartsheetRowStoreOrThrow,
useUIPermission,
} from '#imports' } from '#imports'
const column = inject(ColumnInj)! const column = inject(ColumnInj)!
@ -39,7 +39,7 @@ const listItemsDlg = ref(false)
const childListDlg = ref(false) const childListDlg = ref(false)
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useRoles()
const { state, isNew, removeLTARRef } = useSmartsheetRowStoreOrThrow() const { state, isNew, removeLTARRef } = useSmartsheetRowStoreOrThrow()

2
packages/nc-gui/components/virtual-cell/Links.vue

@ -27,7 +27,7 @@ const listItemsDlg = ref(false)
const childListDlg = ref(false) const childListDlg = ref(false)
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useRoles()
const { state, isNew } = useSmartsheetRowStoreOrThrow() const { state, isNew } = useSmartsheetRowStoreOrThrow()

4
packages/nc-gui/components/virtual-cell/ManyToMany.vue

@ -16,9 +16,9 @@ import {
inject, inject,
ref, ref,
useProvideLTARStore, useProvideLTARStore,
useRoles,
useSelectedCellKeyupListener, useSelectedCellKeyupListener,
useSmartsheetRowStoreOrThrow, useSmartsheetRowStoreOrThrow,
useUIPermission,
} from '#imports' } from '#imports'
const column = inject(ColumnInj)! const column = inject(ColumnInj)!
@ -41,7 +41,7 @@ const listItemsDlg = ref(false)
const childListDlg = ref(false) const childListDlg = ref(false)
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useRoles()
const { state, isNew, removeLTARRef } = useSmartsheetRowStoreOrThrow() const { state, isNew, removeLTARRef } = useSmartsheetRowStoreOrThrow()

2
packages/nc-gui/components/virtual-cell/components/ItemChip.vue

@ -28,7 +28,7 @@ const emit = defineEmits(['unlink'])
const { relatedTableMeta } = useLTARStoreOrThrow()! const { relatedTableMeta } = useLTARStoreOrThrow()!
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useRoles()
const readOnly = inject(ReadonlyInj, ref(false)) const readOnly = inject(ReadonlyInj, ref(false))

4
packages/nc-gui/components/workspace/CreateProjectBtn.vue

@ -10,7 +10,7 @@ const props = defineProps<{
centered?: boolean centered?: boolean
}>() }>()
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useRoles()
const { orgRoles, workspaceRoles } = useRoles() const { orgRoles, workspaceRoles } = useRoles()
@ -28,7 +28,7 @@ const centered = computed(() => props.centered ?? true)
<template> <template>
<NcButton <NcButton
v-if="isUIAllowed('projectCreate', false, workspaceRoles ?? orgRoles) && !isSharedBase" v-if="isUIAllowed('projectCreate', { roles: workspaceRoles ?? orgRoles }) && !isSharedBase"
type="text" type="text"
:size="size" :size="size"
:centered="centered" :centered="centered"

10
packages/nc-gui/components/workspace/ProjectList.vue

@ -20,7 +20,7 @@ const { navigateToProject } = useGlobal()
const { $e, $jobs } = useNuxtApp() const { $e, $jobs } = useNuxtApp()
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useRoles()
const { refreshCommandPalette } = useCommandPalette() const { refreshCommandPalette } = useCommandPalette()
@ -326,7 +326,7 @@ const setIcon = async (icon: string, project: ProjectType) => {
<template v-if="column.dataIndex === 'id'"> <template v-if="column.dataIndex === 'id'">
<a-dropdown <a-dropdown
v-if="isUIAllowed('projectActionMenu', true, [record.workspace_role, record.project_role].join())" v-if="isUIAllowed('projectActionMenu', { roles: [record.workspace_role, record.project_role].join() })"
:trigger="['click']" :trigger="['click']"
> >
<div @click.stop> <div @click.stop>
@ -346,7 +346,7 @@ const setIcon = async (icon: string, project: ProjectType) => {
<a-menu-item <a-menu-item
v-if=" v-if="
record.type === NcProjectType.DB && record.type === NcProjectType.DB &&
isUIAllowed('projectDuplicate', true, [record.workspace_role, record.project_role].join()) isUIAllowed('projectDuplicate', { roles: [record.workspace_role, record.project_role].join() })
" "
@click="duplicateProject(record)" @click="duplicateProject(record)"
> >
@ -357,7 +357,7 @@ const setIcon = async (icon: string, project: ProjectType) => {
</a-menu-item> </a-menu-item>
<!-- <!--
<a-menu-item <a-menu-item
v-if="false && isUIAllowed('projectMove', true, [record.workspace_role, record.project_role].join())" v-if="false && isUIAllowed('projectMove', { roles: [record.workspace_role, record.project_role].join() })"
@click="moveProject(record)" @click="moveProject(record)"
> >
<div class="nc-menu-item-wrapper"> <div class="nc-menu-item-wrapper">
@ -367,7 +367,7 @@ const setIcon = async (icon: string, project: ProjectType) => {
</a-menu-item> </a-menu-item>
--> -->
<a-menu-item <a-menu-item
v-if="isUIAllowed('projectDelete', true, [record.workspace_role, record.project_role].join())" v-if="isUIAllowed('projectDelete', { roles: [record.workspace_role, record.project_role].join() })"
@click="deleteProject(record)" @click="deleteProject(record)"
> >
<div class="nc-menu-item-wrapper text-red-500"> <div class="nc-menu-item-wrapper text-red-500">

2
packages/nc-gui/composables/useExpandedFormStore.ts

@ -57,7 +57,7 @@ const [useProvideExpandedFormStore, useExpandedFormStore] = useInjectionState((m
const reloadTrigger = inject(ReloadRowDataHookInj, createEventHook()) const reloadTrigger = inject(ReloadRowDataHookInj, createEventHook())
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useRoles()
// getters // getters
const displayValue = computed(() => { const displayValue = computed(() => {

15
packages/nc-gui/composables/useGridViewColumn.ts

@ -1,23 +1,12 @@
import type { ColumnType, GridColumnReqType, GridColumnType, ViewType } from 'nocodb-sdk' import type { ColumnType, GridColumnReqType, GridColumnType, ViewType } from 'nocodb-sdk'
import type { Ref } from 'vue' import type { Ref } from 'vue'
import { import { IsPublicInj, computed, inject, ref, useMetas, useNuxtApp, useRoles, useStyleTag, useUndoRedo, watch } from '#imports'
IsPublicInj,
computed,
inject,
ref,
useMetas,
useNuxtApp,
useStyleTag,
useUIPermission,
useUndoRedo,
watch,
} from '#imports'
const [useProvideGridViewColumn, useGridViewColumn] = useInjectionState( const [useProvideGridViewColumn, useGridViewColumn] = useInjectionState(
(view: Ref<(ViewType & { columns?: GridColumnType[] }) | undefined>, statePublic = false) => { (view: Ref<(ViewType & { columns?: GridColumnType[] }) | undefined>, statePublic = false) => {
const { css, load: loadCss, unload: unloadCss } = useStyleTag('') const { css, load: loadCss, unload: unloadCss } = useStyleTag('')
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useRoles()
const { $api } = useNuxtApp() const { $api } = useNuxtApp()

4
packages/nc-gui/composables/useKanbanViewStore.ts

@ -21,9 +21,9 @@ import {
useInjectionState, useInjectionState,
useNuxtApp, useNuxtApp,
useProject, useProject,
useRoles,
useSharedView, useSharedView,
useSmartsheetStoreOrThrow, useSmartsheetStoreOrThrow,
useUIPermission,
useUndoRedo, useUndoRedo,
} from '#imports' } from '#imports'
@ -51,7 +51,7 @@ const [useProvideKanbanViewStore, useKanbanViewStore] = useInjectionState(
const { sharedView, fetchSharedViewData, fetchSharedViewGroupedData } = useSharedView() const { sharedView, fetchSharedViewData, fetchSharedViewGroupedData } = useSharedView()
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useRoles()
const isPublic = ref(shared) || inject(IsPublicInj, ref(false)) const isPublic = ref(shared) || inject(IsPublicInj, ref(false))

2
packages/nc-gui/composables/useMapViewDataStore.ts

@ -34,7 +34,7 @@ const [useProvideMapViewStore, useMapViewStore] = useInjectionState(
const { $api } = useNuxtApp() const { $api } = useNuxtApp()
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useRoles()
const isPublic = ref(shared) || inject(IsPublicInj, ref(false)) const isPublic = ref(shared) || inject(IsPublicInj, ref(false))

47
packages/nc-gui/composables/useRoles/index.ts

@ -1,6 +1,22 @@
import type { RolesObj } from 'nocodb-sdk' import { isString } from '@vue/shared'
import type { Roles, RolesObj, WorkspaceUserRoles } from 'nocodb-sdk'
import { extractRolesObj } from 'nocodb-sdk' import { extractRolesObj } from 'nocodb-sdk'
import { computed, createSharedComposable, useApi, useGlobal } from '#imports' import { computed, createSharedComposable, rolePermissions, useApi, useGlobal } from '#imports'
import type { Permission } from '#imports'
const hasPermission = (role: Exclude<Roles, WorkspaceUserRoles>, hasRole: boolean, permission: Permission | string) => {
const rolePermission = rolePermissions[role]
if (!hasRole || !rolePermission) return false
if (isString(rolePermission) && rolePermission === '*') return true
if ('include' in rolePermission && rolePermission.include) {
return !!rolePermission.include[permission as keyof typeof rolePermission.include]
}
return rolePermission[permission as keyof typeof rolePermission]
}
/** /**
* Provides the roles a user currently has * Provides the roles a user currently has
@ -74,7 +90,7 @@ export const useRoles = createSharedComposable(() => {
...user.value, ...user.value,
roles: res.roles, roles: res.roles,
project_roles: res.project_roles, project_roles: res.project_roles,
} } as typeof User
} else if (options?.isSharedErd) { } else if (options?.isSharedErd) {
const res = await api.auth.me( const res = await api.auth.me(
{ {
@ -91,7 +107,7 @@ export const useRoles = createSharedComposable(() => {
...user.value, ...user.value,
roles: res.roles, roles: res.roles,
project_roles: res.project_roles, project_roles: res.project_roles,
} } as typeof User
} else if (projectId) { } else if (projectId) {
const res = await api.auth.me({ project_id: projectId }) const res = await api.auth.me({ project_id: projectId })
@ -99,9 +115,28 @@ export const useRoles = createSharedComposable(() => {
...user.value, ...user.value,
roles: res.roles, roles: res.roles,
project_roles: res.project_roles, project_roles: res.project_roles,
} } as typeof User
} }
} }
return { allRoles, orgRoles, workspaceRoles, projectRoles, loadRoles } const isUIAllowed = (
permission: Permission | string,
args: { roles?: string | Record<string, boolean> | string[] | null } = {},
) => {
const { roles } = args
let checkRoles: Record<string, boolean> = {}
if (!roles) {
if (allRoles.value) checkRoles = allRoles.value
} else {
checkRoles = extractRolesObj(roles)
}
return Object.entries(checkRoles).some(([role, hasRole]) =>
hasPermission(role as Exclude<Roles, WorkspaceUserRoles>, hasRole, permission),
)
}
return { allRoles, orgRoles, workspaceRoles, projectRoles, loadRoles, isUIAllowed }
}) })

51
packages/nc-gui/composables/useUIPermission/index.ts

@ -1,51 +0,0 @@
import { isString } from '@vue/shared'
import type { Roles } from 'nocodb-sdk'
import { extractRolesObj } from 'nocodb-sdk'
import { createSharedComposable, rolePermissions, useGlobal, useRoles } from '#imports'
import type { Permission } from '#imports'
const hasPermission = (role: Roles, hasRole: boolean, permission: Permission | string) => {
const rolePermission = rolePermissions[role]
if (!hasRole || !rolePermission) return false
if (isString(rolePermission) && rolePermission === '*') return true
if ('include' in rolePermission && rolePermission.include) {
return !!rolePermission.include[permission as keyof typeof rolePermission.include]
}
return rolePermission[permission as keyof typeof rolePermission]
}
export const useUIPermission = createSharedComposable(() => {
const { previewAs } = useGlobal()
const { allRoles } = useRoles()
const isUIAllowed = (
permission: Permission | string,
skipPreviewAs = false,
userRoles: string | Record<string, boolean> | string[] | null = null,
combineWithStateRoles = false,
) => {
if (previewAs.value && !skipPreviewAs) {
return hasPermission(previewAs.value, true, permission)
}
let roles: Record<string, boolean> = {}
if (!userRoles) {
if (allRoles.value) roles = allRoles.value
} else {
roles = extractRolesObj(userRoles)
}
if (userRoles && combineWithStateRoles) {
roles = { ...roles, ...allRoles.value }
}
return Object.entries(roles).some(([role, hasRole]) => hasPermission(role as Roles, hasRole, permission))
}
return { isUIAllowed }
})

0
packages/nc-gui/composables/useUIPermission/rolePermissions.ts

15
packages/nc-gui/composables/useViewColumns.ts

@ -1,18 +1,7 @@
import { ViewTypes, isSystemColumn } from 'nocodb-sdk' import { ViewTypes, isSystemColumn } from 'nocodb-sdk'
import type { ColumnType, MapType, TableType, ViewType } from 'nocodb-sdk' import type { ColumnType, MapType, TableType, ViewType } from 'nocodb-sdk'
import type { ComputedRef, Ref } from 'vue' import type { ComputedRef, Ref } from 'vue'
import { import { IsPublicInj, computed, inject, ref, storeToRefs, useNuxtApp, useProject, useRoles, useUndoRedo, watch } from '#imports'
IsPublicInj,
computed,
inject,
ref,
storeToRefs,
useNuxtApp,
useProject,
useUIPermission,
useUndoRedo,
watch,
} from '#imports'
import type { Field } from '#imports' import type { Field } from '#imports'
export function useViewColumns( export function useViewColumns(
@ -28,7 +17,7 @@ export function useViewColumns(
const { $api, $e } = useNuxtApp() const { $api, $e } = useNuxtApp()
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useRoles()
const { isSharedBase } = storeToRefs(useProject()) const { isSharedBase } = storeToRefs(useProject())

4
packages/nc-gui/composables/useViewData.ts

@ -16,11 +16,11 @@ import {
useI18n, useI18n,
useNuxtApp, useNuxtApp,
useProject, useProject,
useRoles,
useRouter, useRouter,
useSharedView, useSharedView,
useSmartsheetStoreOrThrow, useSmartsheetStoreOrThrow,
useState, useState,
useUIPermission,
} from '#imports' } from '#imports'
import type { Row } from '#imports' import type { Row } from '#imports'
@ -76,7 +76,7 @@ export function useViewData(
const { sorts, nestedFilters } = useSmartsheetStoreOrThrow() const { sorts, nestedFilters } = useSmartsheetStoreOrThrow()
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useRoles()
const routeQuery = computed(() => route.value.query as Record<string, string>) const routeQuery = computed(() => route.value.query as Record<string, string>)

4
packages/nc-gui/composables/useViewFilters.ts

@ -16,7 +16,7 @@ import {
useMetas, useMetas,
useNuxtApp, useNuxtApp,
useProject, useProject,
useUIPermission, useRoles,
watch, watch,
} from '#imports' } from '#imports'
import type { Filter, UndoRedoAction } from '#imports' import type { Filter, UndoRedoAction } from '#imports'
@ -42,7 +42,7 @@ export function useViewFilters(
const { $api, $e } = useNuxtApp() const { $api, $e } = useNuxtApp()
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useRoles()
const { metas } = useMetas() const { metas } = useMetas()

2
packages/nc-gui/composables/useViewGroupBy.ts

@ -34,7 +34,7 @@ export const useViewGroupBy = (view: Ref<ViewType | undefined>, where?: Computed
const isGroupBy = computed(() => !!groupBy.value.length) const isGroupBy = computed(() => !!groupBy.value.length)
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useRoles()
const { sorts, nestedFilters } = useSmartsheetStoreOrThrow() const { sorts, nestedFilters } = useSmartsheetStoreOrThrow()

4
packages/nc-gui/composables/useViewSorts.ts

@ -12,9 +12,9 @@ import {
storeToRefs, storeToRefs,
useNuxtApp, useNuxtApp,
useProject, useProject,
useRoles,
useSharedView, useSharedView,
useSmartsheetStoreOrThrow, useSmartsheetStoreOrThrow,
useUIPermission,
} from '#imports' } from '#imports'
export function useViewSorts(view: Ref<ViewType | undefined>, reloadData?: () => void) { export function useViewSorts(view: Ref<ViewType | undefined>, reloadData?: () => void) {
@ -24,7 +24,7 @@ export function useViewSorts(view: Ref<ViewType | undefined>, reloadData?: () =>
const { $api, $e } = useNuxtApp() const { $api, $e } = useNuxtApp()
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useRoles()
const { isSharedBase } = storeToRefs(useProject()) const { isSharedBase } = storeToRefs(useProject())

148
packages/nc-gui/lib/acl.ts

@ -0,0 +1,148 @@
import { OrgUserRoles, ProjectRoles } from 'nocodb-sdk'
const roleScopes = {
org: [OrgUserRoles.VIEWER, OrgUserRoles.CREATOR],
project: [ProjectRoles.VIEWER, ProjectRoles.COMMENTER, ProjectRoles.EDITOR, ProjectRoles.CREATOR, ProjectRoles.OWNER],
}
interface Perm {
include?: Record<string, boolean>
}
/**
* Each permission value means the following
* `*` - which is wildcard, means all permissions are allowed
* `include` - which is an object, means only the permissions listed in the object are allowed
* `undefined` or `{}` - which is the default value, means no permissions are allowed
* */
const rolePermissions = {
// org level role permissions
[OrgUserRoles.SUPER_ADMIN]: '*',
[OrgUserRoles.CREATOR]: {
include: {
projectCreate: true,
projectMove: true,
projectDelete: true,
projectDuplicate: true,
newUser: true,
},
},
[OrgUserRoles.VIEWER]: {
include: {
importRequest: true,
},
},
// Project role permissions
[ProjectRoles.OWNER]: {
include: {
projectDelete: true,
},
},
[ProjectRoles.CREATOR]: {
include: {
baseCreate: true,
fieldUpdate: true,
hookList: true,
tableCreate: true,
tableRename: true,
tableDelete: true,
tableDuplicate: true,
tableSort: true,
layoutRename: true,
layoutDelete: true,
airtableImport: true,
jsonImport: true,
excelImport: true,
settingsPage: true,
newUser: true,
webhook: true,
fieldEdit: true,
fieldAdd: true,
tableIconEdit: true,
viewCreateOrEdit: true,
viewShare: true,
projectShare: true,
},
},
[ProjectRoles.EDITOR]: {
include: {
dataInsert: true,
dataEdit: true,
sortSync: true,
filterSync: true,
filterChildrenRead: true,
viewFieldEdit: true,
csvImport: true,
apiDocs: true,
},
},
[ProjectRoles.COMMENTER]: {
include: {
commentEdit: true,
commentList: true,
commentCount: true,
},
},
[ProjectRoles.VIEWER]: {
include: {
projectSettings: true,
expandedForm: true,
},
},
[ProjectRoles.NO_ACCESS]: {
include: {},
},
} as Record<OrgUserRoles | ProjectRoles, Perm | '*'>
/*
We inherit include permissions from previous roles in the same scope (role order)
To determine role order, we use `roleScopes` object
So for example ProjectRoles.COMMENTER has `commentEdit` permission,
which means ProjectRoles.EDITOR, ProjectRoles.CREATOR, ProjectRoles.OWNER will also have `commentEdit` permission
where as ProjectRoles.VIEWER, ProjectRoles.NO_ACCESS will not have `commentEdit` permission.
This is why we are validating that there are no duplicate permissions within the same scope
even though it is not required for the code to work. It is to keep the code clean and easy to understand.
*/
// validate no duplicate permissions within same scope
Object.values(roleScopes).forEach((roles) => {
const scopePermissions: Record<string, boolean> = {}
const duplicates: string[] = []
roles.forEach((role) => {
const perms = (rolePermissions[role] as Perm).include || {}
Object.keys(perms).forEach((perm) => {
if (scopePermissions[perm]) {
duplicates.push(perm)
}
scopePermissions[perm] = true
})
})
if (duplicates.length) {
throw new Error(
`Duplicate permissions found in roles ${roles.join(', ')}. Please remove duplicate permissions: ${duplicates.join(', ')}`,
)
}
})
// inherit include permissions within scope (role order)
Object.values(roleScopes).forEach((roles) => {
let roleIndex = 0
for (const role of roles) {
if (roleIndex === 0) {
roleIndex++
continue
}
if (rolePermissions[role] === '*') continue
if ((rolePermissions[role] as Perm).include && (rolePermissions[roles[roleIndex - 1]] as Perm).include) {
Object.assign((rolePermissions[role] as Perm).include!, (rolePermissions[roles[roleIndex - 1]] as Perm).include)
}
roleIndex++
}
})
export { rolePermissions }

149
packages/nc-gui/lib/constants.ts

@ -1,5 +1,3 @@
import { OrgUserRoles, ProjectRoles } from 'nocodb-sdk'
export const NOCO = 'noco' export const NOCO = 'noco'
export const SYSTEM_COLUMNS = ['id', 'title', 'created_at', 'updated_at'] export const SYSTEM_COLUMNS = ['id', 'title', 'created_at', 'updated_at']
@ -18,150 +16,3 @@ export const GROUP_BY_VARS = {
__nc_false__: 'Unchecked', __nc_false__: 'Unchecked',
} as Record<string, string>, } as Record<string, string>,
} }
const roleScopes = {
org: [OrgUserRoles.VIEWER, OrgUserRoles.CREATOR],
project: [ProjectRoles.VIEWER, ProjectRoles.COMMENTER, ProjectRoles.EDITOR, ProjectRoles.CREATOR, ProjectRoles.OWNER],
}
interface Perm {
include?: Record<string, boolean>
}
/**
* Each permission value means the following
* `*` - which is wildcard, means all permissions are allowed
* `include` - which is an object, means only the permissions listed in the object are allowed
* `undefined` or `{}` - which is the default value, means no permissions are allowed
* */
const rolePermissions = {
// org level role permissions
[OrgUserRoles.SUPER_ADMIN]: '*',
[OrgUserRoles.CREATOR]: {
include: {
projectCreate: true,
projectMove: true,
projectDelete: true,
projectDuplicate: true,
newUser: true,
},
},
[OrgUserRoles.VIEWER]: {
include: {
importRequest: true,
},
},
// Project role permissions
[ProjectRoles.OWNER]: {
include: {
projectDelete: true,
},
},
[ProjectRoles.CREATOR]: {
include: {
baseCreate: true,
fieldUpdate: true,
hookList: true,
tableCreate: true,
tableRename: true,
tableDelete: true,
tableDuplicate: true,
tableSort: true,
layoutRename: true,
layoutDelete: true,
airtableImport: true,
jsonImport: true,
excelImport: true,
settingsPage: true,
newUser: true,
webhook: true,
fieldEdit: true,
fieldAdd: true,
tableIconEdit: true,
viewCreateOrEdit: true,
viewShare: true,
projectShare: true,
},
},
[ProjectRoles.EDITOR]: {
include: {
dataInsert: true,
dataEdit: true,
sortSync: true,
filterSync: true,
filterChildrenRead: true,
viewFieldEdit: true,
csvImport: true,
apiDocs: true,
},
},
[ProjectRoles.COMMENTER]: {
include: {
commentEdit: true,
commentList: true,
commentCount: true,
},
},
[ProjectRoles.VIEWER]: {
include: {
projectSettings: true,
expandedForm: true,
},
},
[ProjectRoles.NO_ACCESS]: {
include: {},
},
} as Record<OrgUserRoles | ProjectRoles, Perm | '*'>
/*
We inherit include permissions from previous roles in the same scope (role order)
To determine role order, we use `roleScopes` object
So for example ProjectRoles.COMMENTER has `commentEdit` permission,
which means ProjectRoles.EDITOR, ProjectRoles.CREATOR, ProjectRoles.OWNER will also have `commentEdit` permission
where as ProjectRoles.VIEWER, ProjectRoles.NO_ACCESS will not have `commentEdit` permission.
This is why we are validating that there are no duplicate permissions within the same scope
even though it is not required for the code to work. It is to keep the code clean and easy to understand.
*/
// validate no duplicate permissions within same scope
Object.values(roleScopes).forEach((roles) => {
const scopePermissions: Record<string, boolean> = {}
const duplicates: string[] = []
roles.forEach((role) => {
const perms = (rolePermissions[role] as Perm).include || {}
Object.keys(perms).forEach((perm) => {
if (scopePermissions[perm]) {
duplicates.push(perm)
}
scopePermissions[perm] = true
})
})
if (duplicates.length) {
throw new Error(
`Duplicate permissions found in roles ${roles.join(', ')}. Please remove duplicate permissions: ${duplicates.join(', ')}`,
)
}
})
// inherit include permissions within scope (role order)
Object.values(roleScopes).forEach((roles) => {
let roleIndex = 0
for (const role of roles) {
if (roleIndex === 0) {
roleIndex++
continue
}
if (rolePermissions[role] === '*') continue
if ((rolePermissions[role] as Perm).include && (rolePermissions[roles[roleIndex - 1]] as Perm).include) {
Object.assign((rolePermissions[role] as Perm).include!, (rolePermissions[roles[roleIndex - 1]] as Perm).include)
}
roleIndex++
}
})
export { rolePermissions }

1
packages/nc-gui/lib/index.ts

@ -1,3 +1,4 @@
export * from './constants' export * from './constants'
export * from './enums' export * from './enums'
export * from './types' export * from './types'
export * from './acl'

4
packages/nc-gui/pages/account/index.vue

@ -1,11 +1,11 @@
<script lang="ts" setup> <script lang="ts" setup>
import { iconMap, navigateTo, useUIPermission } from '#imports' import { iconMap, navigateTo, useRoles } from '#imports'
definePageMeta({ definePageMeta({
hideHeader: true, hideHeader: true,
}) })
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useRoles()
const $route = useRoute() const $route = useRoute()

4
packages/nc-gui/pages/account/index/users/[[nestedPage]].vue

@ -1,7 +1,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { useUIPermission } from '#imports' import { useRoles } from '#imports'
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useRoles()
</script> </script>
<template> <template>

2
packages/nc-gui/store/projectsShortcuts.ts

@ -3,7 +3,7 @@ import { isDrawerOrModalExist, useEventListener } from '#imports'
export const useProjectsShortcuts = defineStore('projectsShortcutsStore', () => { export const useProjectsShortcuts = defineStore('projectsShortcutsStore', () => {
const { $e } = useNuxtApp() const { $e } = useNuxtApp()
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useRoles()
const isMounted = ref(false) const isMounted = ref(false)

4
packages/nocodb-sdk/src/lib/helperFunctions.ts

@ -1,5 +1,5 @@
import UITypes from './UITypes'; import UITypes from './UITypes';
import { Roles, RolesObj, RolesType } from './globals'; import { RolesObj, RolesType } from './globals';
// import {RelationTypes} from "./globals"; // import {RelationTypes} from "./globals";
@ -39,7 +39,7 @@ const extractRolesObj = (roles: RolesType): RolesObj => {
}, {}); }, {});
}; };
const stringifyRolesObj = (roles?: Roles | null): string => { const stringifyRolesObj = (roles?: RolesObj | null): string => {
if (!roles) return ''; if (!roles) return '';
const rolesArr = Object.keys(roles).filter((r) => roles[r]); const rolesArr = Object.keys(roles).filter((r) => roles[r]);
return rolesArr.join(','); return rolesArr.join(',');

Loading…
Cancel
Save