Browse Source

feat(api): limit api access with api token

Signed-off-by: Pranav C <pranavxc@gmail.com>
pull/4134/head
Pranav C 2 years ago
parent
commit
33efebf146
  1. 2
      packages/nc-gui/components/admin/License.vue
  2. 2
      packages/nc-gui/components/admin/Token.vue
  3. 19
      packages/nocodb/src/lib/meta/api/orgTokenApis.ts
  4. 35
      packages/nocodb/src/lib/meta/api/orgUserApis.ts
  5. 1
      packages/nocodb/src/lib/meta/api/userApi/initStrategies.ts
  6. 11
      packages/nocodb/src/lib/meta/helpers/ncMetaAclMw.ts

2
packages/nc-gui/components/admin/License.vue

@ -47,7 +47,7 @@ loadTokens()
</script>
<template>
<div class="h-full overflow-y-scroll scrollbar-thin-dull pt-4">
<div class="h-full overflow-y-scroll scrollbar-thin-dull pt-2">
<div class="text-xl mt-4">License</div>
<a-divider class="!my-3" />
<a-textarea placeholder="License key" class="!mt-4 max-w-[300px]"></a-textarea>

2
packages/nc-gui/components/admin/Token.vue

@ -93,7 +93,7 @@ const copyToken = (token: string | undefined) => {
</script>
<template>
<div class="h-full overflow-y-scroll scrollbar-thin-dull pt-4">
<div class="h-full overflow-y-scroll scrollbar-thin-dull pt-2">
<div class="text-xl mt-4">Token Management</div>
<a-divider class="!my-3" />
<div class="max-w-[900px] mx-auto p-4">

19
packages/nocodb/src/lib/meta/api/orgTokenApis.ts

@ -1,7 +1,7 @@
import { Request, Response, Router } from 'express'
import { Request, Response, Router } from 'express';
import { OrgUserRoles } from '../../../enums/OrgUserRoles';
import ApiToken from '../../models/ApiToken';
import { Tele } from '../../utils/Tele'
import { Tele } from '../../utils/Tele';
import { metaApiMetrics } from '../helpers/apiMetrics';
import ncMetaAclMw from '../helpers/ncMetaAclMw';
import { PagedResponseImpl } from '../helpers/PagedResponse';
@ -30,16 +30,25 @@ const router = Router({ mergeParams: true });
router.get(
'/api/v1/tokens',
metaApiMetrics,
ncMetaAclMw(apiTokenList, 'apiTokenList', [OrgUserRoles.SUPER])
ncMetaAclMw(apiTokenList, 'apiTokenList', {
allowedRoles: [OrgUserRoles.SUPER],
blockApiTokenAccess: true,
})
);
router.post(
'/api/v1/tokens',
metaApiMetrics,
ncMetaAclMw(apiTokenCreate, 'apiTokenCreate', [OrgUserRoles.SUPER])
ncMetaAclMw(apiTokenCreate, 'apiTokenCreate', {
allowedRoles: [OrgUserRoles.SUPER],
blockApiTokenAccess: true,
})
);
router.delete(
'/api/v1/tokens/:token',
metaApiMetrics,
ncMetaAclMw(apiTokenDelete, 'apiTokenDelete', [OrgUserRoles.SUPER])
ncMetaAclMw(apiTokenDelete, 'apiTokenDelete', {
allowedRoles: [OrgUserRoles.SUPER],
blockApiTokenAccess: true,
})
);
export default router;

35
packages/nocodb/src/lib/meta/api/orgUserApis.ts

@ -231,36 +231,57 @@ const router = Router({ mergeParams: true });
router.get(
'/api/v1/users',
metaApiMetrics,
ncMetaAclMw(userList, 'userList', [OrgUserRoles.SUPER])
ncMetaAclMw(userList, 'userList', {
allowedRoles: [OrgUserRoles.SUPER],
blockApiTokenAccess: true,
})
);
router.patch(
'/api/v1/users/:userId',
metaApiMetrics,
ncMetaAclMw(userUpdate, 'userUpdate', [OrgUserRoles.SUPER])
ncMetaAclMw(userUpdate, 'userUpdate', {
allowedRoles: [OrgUserRoles.SUPER],
blockApiTokenAccess: true,
})
);
router.delete(
'/api/v1/users/:userId',
metaApiMetrics,
ncMetaAclMw(userDelete, 'userDelete', [OrgUserRoles.SUPER])
ncMetaAclMw(userDelete, 'userDelete', {
allowedRoles: [OrgUserRoles.SUPER],
blockApiTokenAccess: true,
})
);
router.post(
'/api/v1/users',
metaApiMetrics,
ncMetaAclMw(userAdd, 'userAdd', [OrgUserRoles.SUPER])
ncMetaAclMw(userAdd, 'userAdd', {
allowedRoles: [OrgUserRoles.SUPER],
blockApiTokenAccess: true,
})
);
router.post(
'/api/v1/users/settings',
metaApiMetrics,
ncMetaAclMw(userSettings, 'userSettings', [OrgUserRoles.SUPER])
ncMetaAclMw(userSettings, 'userSettings', {
allowedRoles: [OrgUserRoles.SUPER],
blockApiTokenAccess: true,
})
);
router.post(
'/api/v1/users/:userId/resend-invite',
metaApiMetrics,
ncMetaAclMw(userInviteResend, 'userInviteResend', [OrgUserRoles.SUPER])
ncMetaAclMw(userInviteResend, 'userInviteResend', {
allowedRoles: [OrgUserRoles.SUPER],
blockApiTokenAccess: true,
})
);
router.post(
'/api/v1/users/:userId/generate-reset-url',
metaApiMetrics,
ncMetaAclMw(generateResetUrl, 'generateResetUrl', [OrgUserRoles.SUPER])
ncMetaAclMw(generateResetUrl, 'generateResetUrl', {
allowedRoles: [OrgUserRoles.SUPER],
blockApiTokenAccess: true,
})
);
export default router;

1
packages/nocodb/src/lib/meta/api/userApi/initStrategies.ts

@ -40,6 +40,7 @@ export function initStrategies(router): void {
if (!apiToken.fk_user_id) return done(null, { roles: 'editor' });
User.get(apiToken.fk_user_id)
.then((user) => {
user['is_api_token'] = true;
if (req.ncProjectId) {
ProjectUser.get(req.ncProjectId, user.id)
.then(async (projectUser) => {

11
packages/nocodb/src/lib/meta/helpers/ncMetaAclMw.ts

@ -7,12 +7,21 @@ import extractProjectIdAndAuthenticate from './extractProjectIdAndAuthenticate';
export default function (
handlerFn,
permissionName,
allowedRoles?: (OrgUserRoles | string)[]
{
allowedRoles,
blockApiTokenAccess,
}: {
allowedRoles?: (OrgUserRoles | string)[];
blockApiTokenAccess?: boolean;
} = {}
) {
return [
extractProjectIdAndAuthenticate,
catchError(async function authMiddleware(req, _res, next) {
const roles = req?.session?.passport?.user?.roles;
if (req?.session?.passport?.user?.is_api_token && blockApiTokenAccess) {
NcError.forbidden('Not allowed with API token');
}
if (
(!allowedRoles || allowedRoles.some((role) => roles?.[role])) &&
!(

Loading…
Cancel
Save