Browse Source

refactor: allow owner/creator to transfer ownership of a view

pull/9807/head
Pranav C 2 weeks ago
parent
commit
4465e7d7e5
  1. 16
      packages/nc-gui/components/dlg/ReAssign/index.vue
  2. 2
      packages/nc-gui/components/smartsheet/toolbar/ViewActionMenu.vue
  3. 1
      packages/nc-gui/lib/acl.ts
  4. 19
      packages/nocodb/src/services/views.service.ts

16
packages/nc-gui/components/dlg/ReAssign/index.vue

@ -74,6 +74,15 @@ const searchQuery = ref('')
const selectedUser = ref() const selectedUser = ref()
const userSelectMenu = ref(false) const userSelectMenu = ref(false)
const currentOwner = computed(() => {
return (
(props.view && basesUser.value.get(props.view.base_id)?.find((u) => u.id === props.view.owned_by)) || {
id: props.view.owned_by,
display_name: 'Unknown',
}
)
})
const filterdBaseUsers = computed(() => { const filterdBaseUsers = computed(() => {
let users = props.view.base_id ? basesUser.value.get(props.view.base_id) || [] : [] let users = props.view.base_id ? basesUser.value.get(props.view.base_id) || [] : []
if (searchQuery.value) { if (searchQuery.value) {
@ -83,7 +92,8 @@ const filterdBaseUsers = computed(() => {
}) })
} }
return users.filter((u) => u.id !== user.value?.id) // exclude current owner from the list
return users.filter((u) => u.id !== currentOwner.value?.id)
}) })
const { user } = useGlobal() const { user } = useGlobal()
@ -142,12 +152,12 @@ const inputEl = (el: HTMLInputElement) => {
<NcModal v-model:visible="vModel" wrap-class-name="nc-modal-re-assign" width="448px"> <NcModal v-model:visible="vModel" wrap-class-name="nc-modal-re-assign" width="448px">
<div class="mb-4"> <div class="mb-4">
<div class="flex text-base font-bold mb-2">Re-assign this view</div> <div class="flex text-base font-bold mb-2">Re-assign this view</div>
<div class="flex">Once reassigned, you will no longer be able to edit the view configuration.</div> <div class="flex">Once reassigned, current owner will no longer be able to edit the view configuration.</div>
</div> </div>
<div class="mb-4"> <div class="mb-4">
<div class="mb-1">Current owner</div> <div class="mb-1">Current owner</div>
<UserItem :user="user" class="bg-gray-100" /> <UserItem :user="currentOwner" class="bg-gray-100" />
</div> </div>
<div> <div>
<div class="mb-1">New owner</div> <div class="mb-1">New owner</div>

2
packages/nc-gui/components/smartsheet/toolbar/ViewActionMenu.vue

@ -337,7 +337,7 @@ const isViewOwner = computed(() => {
</a-menu-item> </a-menu-item>
</NcSubMenu> </NcSubMenu>
<NcMenuItem @click="openReAssignDlg" v-if="isViewOwner && isEeUI"> <NcMenuItem @click="openReAssignDlg" v-if="(isViewOwner || isUIAllowed('reAssignViewOwner')) && isEeUI">
<div <div
v-e="[ v-e="[
'c:navdraw:preview-as', 'c:navdraw:preview-as',

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

@ -88,6 +88,7 @@ const rolePermissions = {
baseDuplicate: true, baseDuplicate: true,
sourceCreate: true, sourceCreate: true,
baseAuditList: true, baseAuditList: true,
reAssignViewOwner: true,
}, },
}, },
[ProjectRoles.EDITOR]: { [ProjectRoles.EDITOR]: {

19
packages/nocodb/src/services/views.service.ts

@ -164,7 +164,7 @@ export class ViewsService {
) { ) {
// if owned_by is not empty then check if the user is the owner of the project // if owned_by is not empty then check if the user is the owner of the project
if (ownedBy && ownedBy !== param.user.id) { if (ownedBy && ownedBy !== param.user.id) {
NcError.unauthorized('Only owner can change to personal view'); NcError.unauthorized('Only owner/creator can change to personal view');
} }
// if empty then check if current user is the owner of the project then allow and update the owned_by // if empty then check if current user is the owner of the project then allow and update the owned_by
@ -180,7 +180,17 @@ export class ViewsService {
} }
} }
if (ownedBy && param.view.owned_by && param.user.id === ownedBy) { // handle view ownership transfer
if (ownedBy && param.view.owned_by && ownedBy !== param.view.owned_by) {
// extract user roles and allow creator and owner to change to personal view
if (
param.user.id !== ownedBy &&
!param.user.base_roles?.[ProjectRoles.OWNER] &&
!param.user.base_roles?.[ProjectRoles.CREATOR]
) {
NcError.unauthorized('Only owner/creator can transfer view ownership');
}
ownedBy = param.view.owned_by; ownedBy = param.view.owned_by;
// verify if the new owned_by is a valid user who have access to the base/workspace // verify if the new owned_by is a valid user who have access to the base/workspace
@ -196,11 +206,6 @@ export class ViewsService {
} }
includeCreatedByAndUpdateBy = true; includeCreatedByAndUpdateBy = true;
// // todo: ee only
// if(!baseUser) {
// const workspace = await WorkspaceUser
// }
} }
const result = await View.update( const result = await View.update(

Loading…
Cancel
Save