Browse Source

wip(api): set cache for project list

Signed-off-by: Pranav C <pranavxc@gmail.com>
pull/4426/head
Pranav C 2 years ago
parent
commit
6553defb34
  1. 4
      packages/nc-gui/components.d.ts
  2. 14
      packages/nc-gui/components/tabs/auth/UserManagement.vue
  3. 11
      packages/nocodb/src/lib/meta/api/projectApis.ts
  4. 4
      packages/nocodb/src/lib/models/Project.ts
  5. 111
      packages/nocodb/src/lib/models/ProjectUser.ts
  6. 1
      packages/nocodb/src/lib/utils/globals.ts

4
packages/nc-gui/components.d.ts vendored

@ -131,7 +131,6 @@ declare module '@vue/runtime-core' {
MdiChevronDown: typeof import('~icons/mdi/chevron-down')['default']
MdiChevronLeft: typeof import('~icons/mdi/chevron-left')['default']
MdiChevronRight: typeof import('~icons/mdi/chevron-right')['default']
MdiClipboard: typeof import('~icons/mdi/clipboard')['default']
MdiClose: typeof import('~icons/mdi/close')['default']
MdiCloseBox: typeof import('~icons/mdi/close-box')['default']
MdiCloseCircle: typeof import('~icons/mdi/close-circle')['default']
@ -142,7 +141,6 @@ declare module '@vue/runtime-core' {
MdiCommentTextOutline: typeof import('~icons/mdi/comment-text-outline')['default']
MdiContentCopy: typeof import('~icons/mdi/content-copy')['default']
MdiContentSave: typeof import('~icons/mdi/content-save')['default']
MdiCopy: typeof import('~icons/mdi/copy')['default']
MdiCurrencyUsd: typeof import('~icons/mdi/currency-usd')['default']
MdiDatabaseOutline: typeof import('~icons/mdi/database-outline')['default']
MdiDatabaseSync: typeof import('~icons/mdi/database-sync')['default']
@ -180,7 +178,6 @@ declare module '@vue/runtime-core' {
MdiInformation: typeof import('~icons/mdi/information')['default']
MdiJson: typeof import('~icons/mdi/json')['default']
MdiKeyboardReturn: typeof import('~icons/mdi/keyboard-return')['default']
MdiKeyChainVariant: typeof import('~icons/mdi/key-chain-variant')['default']
MdiKeyChange: typeof import('~icons/mdi/key-change')['default']
MdiKeyStar: typeof import('~icons/mdi/key-star')['default']
MdiLink: typeof import('~icons/mdi/link')['default']
@ -207,7 +204,6 @@ declare module '@vue/runtime-core' {
MdiRocketLaunchOutline: typeof import('~icons/mdi/rocket-launch-outline')['default']
MdiScriptTextKeyOutline: typeof import('~icons/mdi/script-text-key-outline')['default']
MdiScriptTextOutline: typeof import('~icons/mdi/script-text-outline')['default']
MdiShieldAccountOutline: typeof import('~icons/mdi/shield-account-outline')['default']
MdiShieldKeyOutline: typeof import('~icons/mdi/shield-key-outline')['default']
MdiSlack: typeof import('~icons/mdi/slack')['default']
MdiSort: typeof import('~icons/mdi/sort')['default']

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

@ -251,20 +251,21 @@ const isSuperAdmin = (user: { main_roles?: string }) => {
</div>
</div>
<div v-for="(user, index) of users" :key="index"
class="flex flex-row items-center border-b-1 py-2 px-2 nc-user-row">
<div v-for="(user, index) of users" :key="index" class="flex flex-row items-center border-b-1 py-2 px-2 nc-user-row">
<div class="flex w-4/6 flex-wrap nc-user-email">
{{ user.email }}
</div>
<div class="flex w-1/6 justify-center flex-wrap ml-4">
<div v-if="isSuperAdmin(user)" class="rounded-full px-2 py-1 nc-user-role"
:style="{ backgroundColor: projectRoleTagColors[OrgUserRoles.SUPER_ADMIN] }"
<div
v-if="isSuperAdmin(user)"
class="rounded-full px-2 py-1 nc-user-role"
:style="{ backgroundColor: projectRoleTagColors[OrgUserRoles.SUPER_ADMIN] }"
>
Super Admin
</div>
<div
v-else-if="user.roles"
v-if="user.roles"
class="rounded-full px-2 py-1 nc-user-role"
:style="{ backgroundColor: projectRoleTagColors[user.roles] }"
>
@ -311,8 +312,7 @@ const isSuperAdmin = (user: { main_roles?: string }) => {
</a-button>
</a-tooltip>
<a-dropdown :trigger="['click']" class="flex" placement="bottomRight"
overlay-class-name="nc-dropdown-user-mgmt">
<a-dropdown :trigger="['click']" class="flex" placement="bottomRight" overlay-class-name="nc-dropdown-user-mgmt">
<div class="flex flex-row items-center">
<a-button type="text" class="!px-0">
<div class="flex flex-row items-center h-[1.2rem]">

11
packages/nocodb/src/lib/meta/api/projectApis.ts

@ -1,5 +1,5 @@
import { Request, Response } from 'express';
import { OrgUserRoles } from 'nocodb-sdk';
import { OrgUserRoles, ProjectType } from 'nocodb-sdk';
import Project from '../../models/Project';
import { ModelTypes, ProjectListType, UITypes } from 'nocodb-sdk';
import DOMPurify from 'isomorphic-dompurify';
@ -77,14 +77,13 @@ export async function projectList(
next
) {
try {
const projects = await ProjectUser.getProjectsList(
req.user.id,
req.user?.roles?.includes(OrgUserRoles.SUPER_ADMIN)
);
const projects = req.user?.roles?.includes(OrgUserRoles.SUPER_ADMIN)
? await Project.list(req.query)
: await ProjectUser.getProjectsList(req.user.id, req.query);
res // todo: pagination
.json(
new PagedResponseImpl(projects, {
new PagedResponseImpl(projects as ProjectType[], {
count: projects.length,
limit: projects.length,
})

4
packages/nocodb/src/lib/models/Project.ts

@ -194,6 +194,8 @@ export default class Project implements ProjectType {
await NocoCache.del(`${CacheScope.PROJECT}:ref:${o.id}`);
}
await NocoCache.delAll(CacheScope.USER_PROJECT, '*');
await NocoCache.del(CacheScope.INSTANCE_META);
// remove item in cache list
@ -292,6 +294,8 @@ export default class Project implements ProjectType {
await NocoCache.del(`${CacheScope.PROJECT}:ref:${project.id}`);
}
await NocoCache.delAll(CacheScope.USER_PROJECT, '*');
await NocoCache.deepDel(
CacheScope.PROJECT,
`${CacheScope.PROJECT}:${projectId}`,

111
packages/nocodb/src/lib/models/ProjectUser.ts

@ -36,6 +36,12 @@ export default class ProjectUser {
true
);
await NocoCache.appendToList(
CacheScope.USER_PROJECT,
[projectUser.fk_user_id],
`${CacheScope.USER_PROJECT}:${projectUser.project_id}`
);
return this.get(project_id, fk_user_id, ncMeta);
}
@ -166,7 +172,7 @@ export default class ProjectUser {
);
}
static async delete(projectId: string, userId, ncMeta = Noco.ncMeta) {
static async delete(projectId: string, userId: string, ncMeta = Noco.ncMeta) {
// await NocoCache.deepDel(
// CacheScope.PROJECT_USER,
// `${CacheScope.PROJECT_USER}:${projectId}:${userId}`,
@ -178,6 +184,20 @@ export default class ProjectUser {
if (email) {
await NocoCache.delAll(CacheScope.USER, `${email}*`);
}
// remove project from user project list cache
let cachedProjectList = await NocoCache.getList(CacheScope.USER_PROJECT, [
userId,
]);
if (cachedProjectList?.length) {
cachedProjectList = cachedProjectList.filter((p) => p.id !== projectId);
await NocoCache.setList(
CacheScope.USER_PROJECT,
[userId],
cachedProjectList
);
}
await NocoCache.del(`${CacheScope.PROJECT_USER}:${projectId}:${userId}`);
return await ncMeta.metaDelete(null, null, MetaTable.PROJECT_USERS, {
fk_user_id: userId,
@ -196,83 +216,44 @@ export default class ProjectUser {
static async getProjectsList(
userId: string,
isSuperAdmin: boolean,
_params: any,
ncMeta = Noco.ncMeta
): Promise<ProjectType[]> {
// todo: pagination
// todo: caching
// let projectList = await NocoCache.getList(CacheScope.PROJECT, []);
let projectList = await NocoCache.getList(CacheScope.USER_PROJECT, [
userId,
]);
const qb = ncMeta
if (projectList.length) {
return projectList;
}
projectList = await ncMeta
.knex(MetaTable.PROJECT)
.select(`${MetaTable.PROJECT}.*`)
[isSuperAdmin ? 'leftJoin' : 'innerJoin'](
MetaTable.PROJECT_USERS,
function () {
this.on(
`${MetaTable.PROJECT_USERS}.project_id`,
`${MetaTable.PROJECT}.id`
);
.innerJoin(MetaTable.PROJECT_USERS, function () {
this.on(
`${MetaTable.PROJECT_USERS}.project_id`,
`${MetaTable.PROJECT}.id`
);
if (!isSuperAdmin) {
this.andOn(
`${MetaTable.PROJECT_USERS}.fk_user_id`,
ncMeta.knex.raw('?', [userId])
);
}
}
)
// .innerJoin(MetaTable.USERS, function () {
// this.on(
// `${MetaTable.PROJECT_USERS}.fk_user_id`,
// `${MetaTable.USERS}.id`
// );
// })
// .where(function () {
// this.where(`${MetaTable.PROJECT_USERS}.fk_user_id`, userId)
// .orWhere(
// `${MetaTable.USERS}.roles`,
// 'like',
// `%${OrgUserRoles.SUPER_ADMIN}%`
// );
// })
// if (!isSuperAdmin) {
this.andOn(
`${MetaTable.PROJECT_USERS}.fk_user_id`,
ncMeta.knex.raw('?', [userId])
);
// }
})
.where(function () {
this.where(`${MetaTable.PROJECT}.deleted`, false).orWhereNull(
`${MetaTable.PROJECT}.deleted`
);
});
// if (!projectList.length) {
// projectList = await ncMeta.metaList2(null, null, MetaTable.PROJECT, {
// xcCondition: {
// _or: [
// {
// deleted: {
// eq: false,
// },
// },
// {
// deleted: {
// eq: null,
// },
// },
// ],
// },
// })
// await NocoCache.setList(CacheScope.PROJECT, [], projectList)
// }
// projectList = projectList.filter(
// (p) => p.deleted === 0 || p.deleted === false || p.deleted === null,
// )
// return projectList.map((m) => new Project(m))
//
//
// return await ncMeta.metaList2(null, null, MetaTable.PROJECT_USERS, {
// condition: { fk_user_id: userId },
// })
// }
console.log(qb.toQuery());
if (projectList?.length) {
await NocoCache.setList(CacheScope.USER_PROJECT, [userId], projectList);
}
return qb;
return projectList;
}
}

1
packages/nocodb/src/lib/utils/globals.ts

@ -136,6 +136,7 @@ export enum CacheScope {
MODEL_ROLE_VISIBILITY = 'modelRoleVisibility',
API_TOKEN = 'apiToken',
INSTANCE_META = 'instanceMeta',
USER_PROJECT = 'userProject',
}
export enum CacheGetType {
TYPE_ARRAY = 'TYPE_ARRAY',

Loading…
Cancel
Save