diff --git a/packages/nocodb/src/lib/meta/api/index.ts b/packages/nocodb/src/lib/meta/api/index.ts index 579dd53088..62798bf79a 100644 --- a/packages/nocodb/src/lib/meta/api/index.ts +++ b/packages/nocodb/src/lib/meta/api/index.ts @@ -1,3 +1,4 @@ +import orgUserApis from './orgUserApis' import projectApis from './projectApis'; import tableApis from './tableApis'; import columnApis from './columnApis'; @@ -87,6 +88,7 @@ export default function (router: Router, server) { router.use(hookApis); router.use(pluginApis); router.use(projectUserApis); + router.use(orgUserApis); router.use(sharedBaseApis); router.use(modelVisibilityApis); router.use(metaDiffApis); diff --git a/packages/nocodb/src/lib/meta/api/orgUserApis.ts b/packages/nocodb/src/lib/meta/api/orgUserApis.ts new file mode 100644 index 0000000000..8647f06b24 --- /dev/null +++ b/packages/nocodb/src/lib/meta/api/orgUserApis.ts @@ -0,0 +1,65 @@ +import { Router } from 'express'; +import { OrgUserRoles } from '../../../enums/OrgUserRoles'; +import User from '../../models/User'; +import { metaApiMetrics } from '../helpers/apiMetrics'; +import { extractProps } from '../helpers/extractProps'; +import ncMetaAclMw from '../helpers/ncMetaAclMw'; +import { PagedResponseImpl } from '../helpers/PagedResponse'; + +async function userList(req, res) { + res.json( + new PagedResponseImpl(await User.list(req.query), { + ...req.query, + count: await User.count(req.query), + }) + ); +} + +async function userUpdate(req, res) { + const updteBody = extractProps(req.body, ['role']); + + const user = await User.get(req.params.userId); + + if (user.roles.includes(OrgUserRoles.SUPER)) { + throw new Error('Cannot update super admin roles'); + } + + res.json(await User.update(req.params.userId, updteBody)); +} + +async function userDelete(req, res) { + const user = await User.get(req.params.userId); + + if (user.roles.includes(OrgUserRoles.SUPER)) { + throw new Error('Cannot delete super admin'); + } + + res.json(await User.delete(req.params.userId)); +} + +async function userAdd(req, res) { + +} + +const router = Router({ mergeParams: true }); +router.get( + '/api/v1/users', + metaApiMetrics, + ncMetaAclMw(userList, 'userList', [OrgUserRoles.SUPER]) +); +router.patch( + '/api/v1/db/meta/users/:userId', + metaApiMetrics, + ncMetaAclMw(userUpdate, 'userUpdate', [OrgUserRoles.SUPER]) +); +router.delete( + '/api/v1/db/meta/users/:userId', + metaApiMetrics, + ncMetaAclMw(userAdd, 'userAdd', [OrgUserRoles.SUPER]) +); +router.post( + '/api/v1/db/meta/users/:userId', + metaApiMetrics, + ncMetaAclMw(userDelete, 'userDelete', [OrgUserRoles.SUPER]) +); +export default router; diff --git a/packages/nocodb/src/lib/meta/api/userApi/initStrategies.ts b/packages/nocodb/src/lib/meta/api/userApi/initStrategies.ts index 4f71798dda..8966c18789 100644 --- a/packages/nocodb/src/lib/meta/api/userApi/initStrategies.ts +++ b/packages/nocodb/src/lib/meta/api/userApi/initStrategies.ts @@ -1,4 +1,3 @@ -import { OrgUserRoles } from '../../../../enums/OrgUserRoles'; import User from '../../../models/User'; import ProjectUser from '../../../models/ProjectUser'; import { promisify } from 'util'; @@ -93,11 +92,11 @@ export function initStrategies(router): void { }, async (req, jwtPayload, done) => { // todo: improve this - if (req.roles.split(',').includes(OrgUserRoles.SUPER)) { - return User.getByEmail(jwtPayload?.email).then(async (user) => { - return done(null, { ...user, roles: 'owner,creator' }); - }); - } + // if (req.roles.split(',').includes(OrgUserRoles.SUPER)) { + // return User.getByEmail(jwtPayload?.email).then(async (user) => { + // return done(null, { ...user, roles: 'owner,creator' }); + // }); + // } const keyVals = [jwtPayload?.email]; if (req.ncProjectId) { diff --git a/packages/nocodb/src/lib/meta/helpers/ncMetaAclMw.ts b/packages/nocodb/src/lib/meta/helpers/ncMetaAclMw.ts index b024ef7ab4..f8fef0e617 100644 --- a/packages/nocodb/src/lib/meta/helpers/ncMetaAclMw.ts +++ b/packages/nocodb/src/lib/meta/helpers/ncMetaAclMw.ts @@ -1,22 +1,29 @@ +import { OrgUserRoles } from '../../../enums/OrgUserRoles'; import projectAcl from '../../utils/projectAcl'; import { NextFunction, Request, Response } from 'express'; import catchError, { NcError } from './catchError'; import extractProjectIdAndAuthenticate from './extractProjectIdAndAuthenticate'; -export default function (handlerFn, permissionName) { +export default function ( + handlerFn, + permissionName, + allowedRoles?: (OrgUserRoles | string)[] +) { return [ extractProjectIdAndAuthenticate, catchError(async function authMiddleware(req, _res, next) { const roles = req?.session?.passport?.user?.roles; if ( + (!allowedRoles || allowedRoles.some((role) => roles?.[role])) && !( roles?.creator || roles?.owner || roles?.editor || roles?.viewer || roles?.commenter || - roles?.user || - roles?.user_new + roles?.[OrgUserRoles.SUPER] ||a + roles?.[OrgUserRoles.CREATOR] || + roles?.[OrgUserRoles.VIEWER] ) ) { NcError.unauthorized('Unauthorized access'); diff --git a/packages/nocodb/src/lib/models/User.ts b/packages/nocodb/src/lib/models/User.ts index 57213d177a..e3b819005c 100644 --- a/packages/nocodb/src/lib/models/User.ts +++ b/packages/nocodb/src/lib/models/User.ts @@ -1,4 +1,5 @@ import { UserType } from 'nocodb-sdk'; +import { NcError } from '../meta/helpers/catchError' import { CacheGetType, CacheScope, MetaTable } from '../utils/globals'; import Noco from '../Noco'; import { extractProps } from '../meta/helpers/extractProps'; @@ -151,7 +152,7 @@ export default class User implements UserType { return (await qb.count('id', { as: 'count' }).first()).count; } - static async get(userId, ncMeta = Noco.ncMeta) { + static async get(userId, ncMeta = Noco.ncMeta): Promise { let user = userId && (await NocoCache.get( @@ -225,4 +226,8 @@ export default class User implements UserType { await NocoCache.del(`${CacheScope.USER}:${userId}`); await ncMeta.metaDelete(null, null, MetaTable.USERS, userId); } + + static async delete(_userId:string) { + NcError.notImplemented() + } }