diff --git a/packages/nc-gui/components/roles/Selector.vue b/packages/nc-gui/components/roles/Selector.vue
index c6079daf01..79308fb1ef 100644
--- a/packages/nc-gui/components/roles/Selector.vue
+++ b/packages/nc-gui/components/roles/Selector.vue
@@ -11,7 +11,7 @@ const props = withDefaults(
description?: boolean
inherit?: string
onRoleChange: (role: keyof typeof RoleLabels) => void
- size: 'sm' | 'md'
+ size: 'sm' | 'md' | 'lg'
}>(),
{
description: true,
diff --git a/packages/nc-gui/components/workspace/InviteSection.vue b/packages/nc-gui/components/workspace/InviteSection.vue
index 00694079ed..0f88e387ed 100644
--- a/packages/nc-gui/components/workspace/InviteSection.vue
+++ b/packages/nc-gui/components/workspace/InviteSection.vue
@@ -6,7 +6,7 @@ import { validateEmail } from '~/utils/validation'
const inviteData = reactive({
email: '',
- roles: WorkspaceUserRoles.VIEWER,
+ roles: WorkspaceUserRoles.NO_ACCESS,
})
const focusRef = ref()
diff --git a/packages/nc-gui/composables/useRoles/index.ts b/packages/nc-gui/composables/useRoles/index.ts
index 7f410f1ffb..89707ed247 100644
--- a/packages/nc-gui/composables/useRoles/index.ts
+++ b/packages/nc-gui/composables/useRoles/index.ts
@@ -1,8 +1,8 @@
import { isString } from '@vue/shared'
import type { Roles, RolesObj, WorkspaceUserRoles } from 'nocodb-sdk'
import { extractRolesObj } from 'nocodb-sdk'
-import { computed, createSharedComposable, rolePermissions, useApi, useGlobal } from '#imports'
import type { Permission } from '#imports'
+import { computed, createSharedComposable, rolePermissions, useApi, useGlobal } from '#imports'
const hasPermission = (role: Exclude, hasRole: boolean, permission: Permission | string) => {
const rolePermission = rolePermissions[role]
diff --git a/packages/nc-gui/lang/en.json b/packages/nc-gui/lang/en.json
index c4c4e88232..4ec8a9a43b 100644
--- a/packages/nc-gui/lang/en.json
+++ b/packages/nc-gui/lang/en.json
@@ -702,6 +702,10 @@
"clearSelection": "Clear selection"
},
"activity": {
+ "addMembers": "Add Members",
+ "enterEmail": "Enter email addresses",
+ "inviteToBase": "Invite to Base",
+ "addMember": "Add Member to Base",
"noRange": "Calendar view requires a date range",
"goToToday": "Go to Today",
"toggleSidebar": "Toggle Sidebar",
diff --git a/packages/nc-gui/lib/acl.ts b/packages/nc-gui/lib/acl.ts
index 1497026071..b13b2b9524 100644
--- a/packages/nc-gui/lib/acl.ts
+++ b/packages/nc-gui/lib/acl.ts
@@ -2,7 +2,14 @@ import { OrgUserRoles, ProjectRoles } from 'nocodb-sdk'
const roleScopes = {
org: [OrgUserRoles.VIEWER, OrgUserRoles.CREATOR],
- base: [ProjectRoles.VIEWER, ProjectRoles.COMMENTER, ProjectRoles.EDITOR, ProjectRoles.CREATOR, ProjectRoles.OWNER],
+ base: [
+ ProjectRoles.NO_ACCESS,
+ ProjectRoles.VIEWER,
+ ProjectRoles.COMMENTER,
+ ProjectRoles.EDITOR,
+ ProjectRoles.CREATOR,
+ ProjectRoles.OWNER,
+ ],
}
interface Perm {
diff --git a/packages/nocodb-sdk/src/lib/enums.ts b/packages/nocodb-sdk/src/lib/enums.ts
index 4136a17d82..dd77534f27 100644
--- a/packages/nocodb-sdk/src/lib/enums.ts
+++ b/packages/nocodb-sdk/src/lib/enums.ts
@@ -19,6 +19,7 @@ export enum WorkspaceUserRoles {
VIEWER = 'workspace-level-viewer',
EDITOR = 'workspace-level-editor',
COMMENTER = 'workspace-level-commenter',
+ NO_ACCESS = 'workspace-level-no-access',
}
export enum AppEvents {
@@ -167,6 +168,7 @@ export const RoleLabels = {
[WorkspaceUserRoles.EDITOR]: 'editor',
[WorkspaceUserRoles.COMMENTER]: 'commenter',
[WorkspaceUserRoles.VIEWER]: 'viewer',
+ [WorkspaceUserRoles.NO_ACCESS]: 'noaccess',
[ProjectRoles.OWNER]: 'owner',
[ProjectRoles.CREATOR]: 'creator',
[ProjectRoles.EDITOR]: 'editor',
@@ -184,6 +186,7 @@ export const RoleColors = {
[WorkspaceUserRoles.EDITOR]: 'green',
[WorkspaceUserRoles.COMMENTER]: 'orange',
[WorkspaceUserRoles.VIEWER]: 'yellow',
+ [WorkspaceUserRoles.NO_ACCESS]: 'red',
[ProjectRoles.OWNER]: 'purple',
[ProjectRoles.CREATOR]: 'blue',
[ProjectRoles.EDITOR]: 'green',
@@ -203,6 +206,7 @@ export const RoleDescriptions = {
[WorkspaceUserRoles.COMMENTER]:
'Can view and comment data in workspace bases',
[WorkspaceUserRoles.VIEWER]: 'Can view data in workspace bases',
+ [WorkspaceUserRoles.NO_ACCESS]: 'Cannot access this workspace',
[ProjectRoles.OWNER]: 'Full access to base',
[ProjectRoles.CREATOR]:
'Can create tables, views, setup webhook, invite collaborators and more',
@@ -222,6 +226,7 @@ export const RoleIcons = {
[WorkspaceUserRoles.EDITOR]: 'role_editor',
[WorkspaceUserRoles.COMMENTER]: 'role_commenter',
[WorkspaceUserRoles.VIEWER]: 'role_viewer',
+ [WorkspaceUserRoles.NO_ACCESS]: 'role_no_access',
[ProjectRoles.OWNER]: 'role_owner',
[ProjectRoles.CREATOR]: 'role_creator',
[ProjectRoles.EDITOR]: 'role_editor',
@@ -239,6 +244,7 @@ export const WorkspaceRolesToProjectRoles = {
[WorkspaceUserRoles.EDITOR]: ProjectRoles.EDITOR,
[WorkspaceUserRoles.COMMENTER]: ProjectRoles.COMMENTER,
[WorkspaceUserRoles.VIEWER]: ProjectRoles.VIEWER,
+ [WorkspaceUserRoles.NO_ACCESS]: ProjectRoles.NO_ACCESS,
};
export const OrderedWorkspaceRoles = [
@@ -247,6 +253,7 @@ export const OrderedWorkspaceRoles = [
WorkspaceUserRoles.EDITOR,
WorkspaceUserRoles.COMMENTER,
WorkspaceUserRoles.VIEWER,
+ WorkspaceUserRoles.NO_ACCESS,
];
export const OrderedOrgRoles = [
diff --git a/packages/nocodb/src/middlewares/extract-ids/extract-ids.middleware.ts b/packages/nocodb/src/middlewares/extract-ids/extract-ids.middleware.ts
index 12cdef3be0..22bbf1bb45 100644
--- a/packages/nocodb/src/middlewares/extract-ids/extract-ids.middleware.ts
+++ b/packages/nocodb/src/middlewares/extract-ids/extract-ids.middleware.ts
@@ -35,6 +35,7 @@ export const rolesLabel = {
[ProjectRoles.VIEWER]: 'Base Viewer',
[ProjectRoles.EDITOR]: 'Base Editor',
[ProjectRoles.COMMENTER]: 'Base Commenter',
+ [ProjectRoles.NO_ACCESS]: 'No Access',
};
export function getRolesLabels(
diff --git a/packages/nocodb/src/models/BaseUser.ts b/packages/nocodb/src/models/BaseUser.ts
index 2f7be5a8c4..12c6dceb50 100644
--- a/packages/nocodb/src/models/BaseUser.ts
+++ b/packages/nocodb/src/models/BaseUser.ts
@@ -26,6 +26,47 @@ export default class BaseUser {
return baseUser && new BaseUser(baseUser);
}
+ public static async bulkInsert(
+ baseUsers: Partial[],
+ ncMeta = Noco.ncMeta,
+ ) {
+ const insertObj = baseUsers.map((baseUser) =>
+ extractProps(baseUser, ['fk_user_id', 'base_id', 'roles']),
+ );
+
+ const bulkData = await ncMeta.bulkMetaInsert(
+ null,
+ null,
+ MetaTable.PROJECT_USERS,
+ insertObj,
+ true,
+ );
+
+ const uniqueFks: string[] = [
+ ...new Set(bulkData.map((d) => d.base_id)),
+ ] as string[];
+
+ for (const fk of uniqueFks) {
+ await NocoCache.deepDel(
+ `${CacheScope.BASE_USER}:${fk}:list`,
+ CacheDelDirection.PARENT_TO_CHILD,
+ );
+ }
+
+ for (const d of bulkData) {
+ await NocoCache.set(
+ `${CacheScope.BASE_USER}:${d.base_id}:${d.fk_user_id}`,
+ d,
+ );
+
+ await NocoCache.appendToList(
+ CacheScope.BASE_USER,
+ [d.base_id],
+ `${CacheScope.BASE_USER}:${d.base_id}:${d.fk_user_id}`,
+ );
+ }
+ }
+
public static async insert(
baseUser: Partial,
ncMeta = Noco.ncMeta,
diff --git a/packages/nocodb/src/schema/swagger.json b/packages/nocodb/src/schema/swagger.json
index 0dfe0409da..40abea1495 100644
--- a/packages/nocodb/src/schema/swagger.json
+++ b/packages/nocodb/src/schema/swagger.json
@@ -22605,7 +22605,6 @@
"type": "object",
"properties": {
"email": {
- "format": "email",
"type": "string",
"description": "Base User Email"
},