diff --git a/backend/src/controllers/v2/serviceAccountsController.ts b/backend/src/controllers/v2/serviceAccountsController.ts index 07820f7fb..d950fdddb 100644 --- a/backend/src/controllers/v2/serviceAccountsController.ts +++ b/backend/src/controllers/v2/serviceAccountsController.ts @@ -79,7 +79,7 @@ export const createServiceAccount = async (req: Request, res: Response) => { const secretId = Buffer.from(serviceAccount._id.toString(), 'hex').toString('base64'); return res.status(200).send({ - serviceAccountAccessKey: `SA.${secretId}.${secret}`, + serviceAccountAccessKey: `sa.${secretId}.${secret}`, serviceAccount: serviceAccountObj }); } @@ -211,7 +211,7 @@ export const addServiceAccountWorkspacePermission = async (req: Request, res: Re const existingPermission = await ServiceAccountWorkspacePermission.findOne({ serviceAccount: new Types.ObjectId(serviceAccountId), - workspaceId: new Types.ObjectId(workspaceId), + workspace: new Types.ObjectId(workspaceId), environment }); diff --git a/backend/src/controllers/v2/workspaceController.ts b/backend/src/controllers/v2/workspaceController.ts index 650c70610..367b66993 100644 --- a/backend/src/controllers/v2/workspaceController.ts +++ b/backend/src/controllers/v2/workspaceController.ts @@ -508,3 +508,8 @@ export const toggleAutoCapitalization = async (req: Request, res: Response) => { }); }; +export const getAak = (req: Request, res: Response) => { + return res.status(200).send({ + message: 'getAak' + }); +} \ No newline at end of file diff --git a/backend/src/ee/middleware/requireSecretSnapshotAuth.ts b/backend/src/ee/middleware/requireSecretSnapshotAuth.ts index 5eae3721c..f43e9c315 100644 --- a/backend/src/ee/middleware/requireSecretSnapshotAuth.ts +++ b/backend/src/ee/middleware/requireSecretSnapshotAuth.ts @@ -30,8 +30,8 @@ const requireSecretSnapshotAuth = ({ } await validateMembership({ - userId: req.user._id.toString(), - workspaceId: secretSnapshot.workspace.toString(), + userId: req.user._id, + workspaceId: secretSnapshot.workspace, acceptedRoles }); diff --git a/backend/src/ee/routes/v1/workspace.ts b/backend/src/ee/routes/v1/workspace.ts index a799d073b..722bfb4a7 100644 --- a/backend/src/ee/routes/v1/workspace.ts +++ b/backend/src/ee/routes/v1/workspace.ts @@ -15,7 +15,8 @@ router.get( acceptedAuthModes: ['jwt', 'apiKey'] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER] + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), param('workspaceId').exists().trim(), query('offset').exists().isInt(), @@ -30,7 +31,8 @@ router.get( acceptedAuthModes: ['jwt'] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER] + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), param('workspaceId').exists().trim(), validateRequest, @@ -43,7 +45,8 @@ router.post( acceptedAuthModes: ['jwt', 'apiKey'] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER] + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), param('workspaceId').exists().trim(), body('version').exists().isInt(), @@ -57,7 +60,8 @@ router.get( acceptedAuthModes: ['jwt', 'apiKey'] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER] + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), param('workspaceId').exists().trim(), query('offset').exists().isInt(), diff --git a/backend/src/helpers/auth.ts b/backend/src/helpers/auth.ts index a08dcf2cc..33d079fd4 100644 --- a/backend/src/helpers/auth.ts +++ b/backend/src/helpers/auth.ts @@ -5,11 +5,13 @@ import { IUser, User, ServiceTokenData, + ServiceAccount, APIKeyData } from '../models'; import { AccountNotFoundError, ServiceTokenDataNotFoundError, + ServiceAccountNotFoundError, APIKeyDataNotFoundError, UnauthorizedRequestError, BadRequestError @@ -63,9 +65,13 @@ const validateAuthMode = ({ case 'st': authTokenType = 'serviceToken'; break; + case 'sa': + authTokenType = 'serviceAccount'; + break; default: authTokenType = 'jwt'; } + authTokenValue = tokenValue; } @@ -164,6 +170,36 @@ const getAuthSTDPayload = async ({ } /** + * Return service account access key payload + * @param {Object} obj + * @param {String} obj.authTokenValue - service account access token value + * @returns {ServiceAccount} serviceAccount + */ +const getAuthSAAKPayload = async ({ + authTokenValue +}: { + authTokenValue: string; +}) => { + const [_, TOKEN_IDENTIFIER, TOKEN_SECRET] = <[string, string, string]>authTokenValue.split('.', 3); + + const serviceAccount = await ServiceAccount.findById( + Buffer.from(TOKEN_IDENTIFIER, 'base64').toString('hex') + ).select('+secretHash'); + + if (!serviceAccount) { + throw ServiceAccountNotFoundError({ message: 'Failed to find service account' }); + } + + const result = await bcrypt.compare(TOKEN_SECRET, serviceAccount.secretHash); + if (!result) throw UnauthorizedRequestError({ + message: 'Failed to authenticate service account access key' + }); + + return serviceAccount; +} + +/** + * TODO: deprecate API keys * Return API key data payload corresponding to API key [authTokenValue] * @param {Object} obj * @param {String} obj.authTokenValue - API key value @@ -300,6 +336,7 @@ export { validateAuthMode, getAuthUserPayload, getAuthSTDPayload, + getAuthSAAKPayload, getAuthAPIKeyPayload, createToken, issueAuthTokens, diff --git a/backend/src/helpers/membership.ts b/backend/src/helpers/membership.ts index fc4a31074..93c1ac7e9 100644 --- a/backend/src/helpers/membership.ts +++ b/backend/src/helpers/membership.ts @@ -1,4 +1,5 @@ import * as Sentry from '@sentry/node'; +import { Types } from 'mongoose'; import { Membership, Key } from '../models'; import { MembershipNotFoundError, @@ -18,9 +19,9 @@ const validateMembership = async ({ workspaceId, acceptedRoles, }: { - userId: string; - workspaceId: string; - acceptedRoles: string[]; + userId: Types.ObjectId; + workspaceId: Types.ObjectId; + acceptedRoles?: string[]; }) => { const membership = await Membership.findOne({ @@ -32,8 +33,10 @@ const validateMembership = async ({ throw MembershipNotFoundError({ message: 'Failed to find workspace membership' }); } - if (!acceptedRoles.includes(membership.role)) { - throw BadRequestError({ message: 'Failed to validate workspace membership role' }); + if (acceptedRoles) { + if (!acceptedRoles.includes(membership.role)) { + throw BadRequestError({ message: 'Failed to validate workspace membership role' }); + } } return membership; diff --git a/backend/src/helpers/workspace.ts b/backend/src/helpers/workspace.ts index b43252bf3..f7cdd4138 100644 --- a/backend/src/helpers/workspace.ts +++ b/backend/src/helpers/workspace.ts @@ -1,4 +1,5 @@ import * as Sentry from '@sentry/node'; +import { Types } from 'mongoose'; import { Workspace, Bot, @@ -7,6 +8,50 @@ import { Secret } from '../models'; import { createBot } from '../helpers/bot'; +import { validateMembership } from '../helpers/membership'; + +/** + * Validate accepted clients by id including [userId], [serviceAccountId], + * and [serviceTokenDataId] for workspace with id [workspaceId] based + * on any known permissions. + * @param {Object} obj + * @param {Types.ObjectId} obj.userId - id of user + */ +const validateClientForWorkspace = async ({ + userId, + serviceAccountId, + serviceTokenDataId, + workspaceId, + environment +}: { + userId?: Types.ObjectId; + serviceAccountId?: Types.ObjectId; + serviceTokenDataId?: Types.ObjectId; + workspaceId: Types.ObjectId; + environment?: string; +}) => { + + let membership; + if (userId) { + membership = await validateMembership({ + userId, + workspaceId + }); + + } + + if (serviceAccountId) { + // TODO + } + + if (serviceTokenDataId) { + // TODO + } + + return ({ + membership + }); +} /** * Create a workspace with name [name] in organization with id [organizationId] @@ -71,4 +116,8 @@ const deleteWorkspace = async ({ id }: { id: string }) => { } }; -export { createWorkspace, deleteWorkspace }; +export { + validateClientForWorkspace, + createWorkspace, + deleteWorkspace +}; diff --git a/backend/src/middleware/requireAuth.ts b/backend/src/middleware/requireAuth.ts index f4921398a..e9f777e0b 100644 --- a/backend/src/middleware/requireAuth.ts +++ b/backend/src/middleware/requireAuth.ts @@ -4,7 +4,8 @@ import { validateAuthMode, getAuthUserPayload, getAuthSTDPayload, - getAuthAPIKeyPayload + getAuthAPIKeyPayload, + getAuthSAAKPayload } from '../helpers/auth'; import { UnauthorizedRequestError @@ -41,14 +42,22 @@ const requireAuth = ({ acceptedAuthModes }); + req.authTokenType = authTokenType; + // attach auth payloads let serviceTokenData: any; switch (authTokenType) { + case 'serviceAccount': + req.serviceAccount = await getAuthSAAKPayload({ + authTokenValue + }); + break; case 'serviceToken': serviceTokenData = await getAuthSTDPayload({ authTokenValue }); + // TODO: bring this into a separate collection requiredServiceTokenPermissions.forEach((requiredServiceTokenPermission) => { if (!serviceTokenData.permissions.includes(requiredServiceTokenPermission)) { return next(UnauthorizedRequestError({ message: 'Failed to authorize service token for endpoint' })); @@ -60,6 +69,7 @@ const requireAuth = ({ break; case 'apiKey': + // TODO: deprecate API key req.user = await getAuthAPIKeyPayload({ authTokenValue }); @@ -70,7 +80,7 @@ const requireAuth = ({ }); break; } - + return next(); } } diff --git a/backend/src/middleware/requireBotAuth.ts b/backend/src/middleware/requireBotAuth.ts index 435b06a59..c06f1c861 100644 --- a/backend/src/middleware/requireBotAuth.ts +++ b/backend/src/middleware/requireBotAuth.ts @@ -20,8 +20,8 @@ const requireBotAuth = ({ } await validateMembership({ - userId: req.user._id.toString(), - workspaceId: bot.workspace.toString(), + userId: req.user._id, + workspaceId: bot.workspace, acceptedRoles }); diff --git a/backend/src/middleware/requireIntegrationAuth.ts b/backend/src/middleware/requireIntegrationAuth.ts index b185b922b..51051584c 100644 --- a/backend/src/middleware/requireIntegrationAuth.ts +++ b/backend/src/middleware/requireIntegrationAuth.ts @@ -30,8 +30,8 @@ const requireIntegrationAuth = ({ } await validateMembership({ - userId: req.user._id.toString(), - workspaceId: integration.workspace.toString(), + userId: req.user._id, + workspaceId: integration.workspace, acceptedRoles }); diff --git a/backend/src/middleware/requireIntegrationAuthorizationAuth.ts b/backend/src/middleware/requireIntegrationAuthorizationAuth.ts index c712f4cca..07f347ecc 100644 --- a/backend/src/middleware/requireIntegrationAuthorizationAuth.ts +++ b/backend/src/middleware/requireIntegrationAuthorizationAuth.ts @@ -38,8 +38,8 @@ const requireIntegrationAuthorizationAuth = ({ } await validateMembership({ - userId: req.user._id.toString(), - workspaceId: integrationAuth.workspace._id.toString(), + userId: req.user._id, + workspaceId: integrationAuth.workspace._id, acceptedRoles }); diff --git a/backend/src/middleware/requireMembershipAuth.ts b/backend/src/middleware/requireMembershipAuth.ts index f5e4fe8b1..136fabadb 100644 --- a/backend/src/middleware/requireMembershipAuth.ts +++ b/backend/src/middleware/requireMembershipAuth.ts @@ -40,8 +40,8 @@ const requireMembershipAuth = ({ if (!userMembership) throw new Error('Failed to validate own membership') const targetMembership = await validateMembership({ - userId: req.user._id.toString(), - workspaceId: membership.workspace.toString(), + userId: req.user._id, + workspaceId: membership.workspace, acceptedRoles }); diff --git a/backend/src/middleware/requireSecretAuth.ts b/backend/src/middleware/requireSecretAuth.ts index 36e47247e..c86b7b680 100644 --- a/backend/src/middleware/requireSecretAuth.ts +++ b/backend/src/middleware/requireSecretAuth.ts @@ -32,8 +32,8 @@ const requireSecretAuth = ({ } await validateMembership({ - userId: req.user._id.toString(), - workspaceId: secret.workspace.toString(), + userId: req.user._id, + workspaceId: secret.workspace, acceptedRoles }); diff --git a/backend/src/middleware/requireServiceTokenDataAuth.ts b/backend/src/middleware/requireServiceTokenDataAuth.ts index 7c5ab4669..513cbe604 100644 --- a/backend/src/middleware/requireServiceTokenDataAuth.ts +++ b/backend/src/middleware/requireServiceTokenDataAuth.ts @@ -26,8 +26,8 @@ const requireServiceTokenDataAuth = ({ if (req.user) { // case: jwt auth await validateMembership({ - userId: req.user._id.toString(), - workspaceId: serviceTokenData.workspace.toString(), + userId: req.user._id, + workspaceId: serviceTokenData.workspace, acceptedRoles }); } diff --git a/backend/src/middleware/requireWorkspaceAuth.ts b/backend/src/middleware/requireWorkspaceAuth.ts index 56c24528c..a96625182 100644 --- a/backend/src/middleware/requireWorkspaceAuth.ts +++ b/backend/src/middleware/requireWorkspaceAuth.ts @@ -1,5 +1,7 @@ import { Request, Response, NextFunction } from 'express'; +import { Types } from 'mongoose'; import { validateMembership } from '../helpers/membership'; +import { validateClientForWorkspace } from '../helpers/workspace'; import { UnauthorizedRequestError } from '../utils/errors'; type req = 'params' | 'body' | 'query'; @@ -13,26 +15,33 @@ type req = 'params' | 'body' | 'query'; */ const requireWorkspaceAuth = ({ acceptedRoles, - location = 'params' + locationWorkspaceId, + locationEnvironment = undefined }: { acceptedRoles: string[]; - location?: req; + locationWorkspaceId: req; + locationEnvironment?: req | undefined; }) => { return async (req: Request, res: Response, next: NextFunction) => { try { - const { workspaceId } = req[location]; - - if (req.user) { - // case: jwt auth - const membership = await validateMembership({ - userId: req.user._id.toString(), - workspaceId, - acceptedRoles - }); + // TODO: throw errors if workspaceId or environemnt are not present + const workspaceId = req[locationWorkspaceId]?.workspaceId; + const environment = locationEnvironment ? req[locationEnvironment]?.environment : undefined; + + // validate clients + const { membership } = await validateClientForWorkspace({ + userId: req.user?._id, + serviceAccountId: req.serviceAccount?._id, + serviceTokenDataId: req.serviceTokenData?._id, + workspaceId: new Types.ObjectId(workspaceId), + environment + }); + + if (membership) { req.membership = membership; } - + if ( req.serviceTokenData && req.serviceTokenData.workspace.toString() !== workspaceId diff --git a/backend/src/routes/v1/bot.ts b/backend/src/routes/v1/bot.ts index 4d3865562..815a3030e 100644 --- a/backend/src/routes/v1/bot.ts +++ b/backend/src/routes/v1/bot.ts @@ -16,7 +16,8 @@ router.get( acceptedAuthModes: ['jwt'] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER] + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), param('workspaceId').exists().trim().notEmpty(), validateRequest, diff --git a/backend/src/routes/v1/integrationAuth.ts b/backend/src/routes/v1/integrationAuth.ts index 2c1f5f045..a81b28d8c 100644 --- a/backend/src/routes/v1/integrationAuth.ts +++ b/backend/src/routes/v1/integrationAuth.ts @@ -38,7 +38,7 @@ router.post( }), requireWorkspaceAuth({ acceptedRoles: [ADMIN, MEMBER], - location: 'body' + locationWorkspaceId: 'body' }), body('workspaceId').exists().trim().notEmpty(), body('code').exists().trim().notEmpty(), @@ -49,18 +49,18 @@ router.post( router.post( '/access-token', - requireAuth({ - acceptedAuthModes: ['jwt', 'apiKey'] - }), - requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER], - location: 'body' - }), body('workspaceId').exists().trim().notEmpty(), body('accessId').trim(), body('accessToken').exists().trim().notEmpty(), body('integration').exists().trim().notEmpty(), validateRequest, + requireAuth({ + acceptedAuthModes: ['jwt', 'apiKey'] + }), + requireWorkspaceAuth({ + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'body' + }), integrationAuthController.saveIntegrationAccessToken ); diff --git a/backend/src/routes/v1/key.ts b/backend/src/routes/v1/key.ts index b66bd1276..39693d805 100644 --- a/backend/src/routes/v1/key.ts +++ b/backend/src/routes/v1/key.ts @@ -15,7 +15,8 @@ router.post( acceptedAuthModes: ['jwt'] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER] + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), param('workspaceId').exists().trim(), body('key').exists(), @@ -29,7 +30,8 @@ router.get( acceptedAuthModes: ['jwt'] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER] + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), param('workspaceId'), validateRequest, diff --git a/backend/src/routes/v1/secret.ts b/backend/src/routes/v1/secret.ts index cce105500..433c7ac94 100644 --- a/backend/src/routes/v1/secret.ts +++ b/backend/src/routes/v1/secret.ts @@ -10,13 +10,16 @@ import { body, query, param } from 'express-validator'; import { secretController } from '../../controllers/v1'; import { ADMIN, MEMBER } from '../../variables'; +// note to devs: these endpoints will be deprecated in favor of v2 + router.post( '/:workspaceId', requireAuth({ acceptedAuthModes: ['jwt'] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER] + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), body('secrets').exists(), body('keys').exists(), @@ -33,7 +36,8 @@ router.get( acceptedAuthModes: ['jwt'] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER] + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), query('environment').exists().trim(), query('channel'), diff --git a/backend/src/routes/v1/serviceToken.ts b/backend/src/routes/v1/serviceToken.ts index 18487ac3e..f6c2fd360 100644 --- a/backend/src/routes/v1/serviceToken.ts +++ b/backend/src/routes/v1/serviceToken.ts @@ -25,7 +25,7 @@ router.post( }), requireWorkspaceAuth({ acceptedRoles: [ADMIN, MEMBER], - location: 'body' + locationWorkspaceId: 'body' }), body('name').exists().trim().notEmpty(), body('workspaceId').exists().trim().notEmpty(), diff --git a/backend/src/routes/v1/workspace.ts b/backend/src/routes/v1/workspace.ts index 801462662..6eb5d05ea 100644 --- a/backend/src/routes/v1/workspace.ts +++ b/backend/src/routes/v1/workspace.ts @@ -15,7 +15,8 @@ router.get( acceptedAuthModes: ['jwt'] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER] + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), param('workspaceId').exists().trim(), validateRequest, @@ -29,6 +30,7 @@ router.get( }), requireWorkspaceAuth({ acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), param('workspaceId').exists().trim(), validateRequest, @@ -49,7 +51,8 @@ router.get( acceptedAuthModes: ['jwt'] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER] + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), param('workspaceId').exists().trim(), validateRequest, @@ -73,7 +76,8 @@ router.delete( acceptedAuthModes: ['jwt'] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN] + acceptedRoles: [ADMIN], + locationWorkspaceId: 'params' }), param('workspaceId').exists().trim(), validateRequest, @@ -86,7 +90,8 @@ router.post( acceptedAuthModes: ['jwt'] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER] + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), param('workspaceId').exists().trim(), body('name').exists().trim().notEmpty(), @@ -100,7 +105,8 @@ router.post( acceptedAuthModes: ['jwt'] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER] + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), param('workspaceId').exists().trim(), body('email').exists().trim().notEmpty(), @@ -114,7 +120,8 @@ router.get( acceptedAuthModes: ['jwt'] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER] + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), param('workspaceId').exists().trim(), validateRequest, @@ -127,7 +134,8 @@ router.get( acceptedAuthModes: ['jwt'] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER] + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), param('workspaceId').exists().trim(), validateRequest, @@ -140,7 +148,8 @@ router.get( acceptedAuthModes: ['jwt'] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER] + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), param('workspaceId').exists().trim(), validateRequest, diff --git a/backend/src/routes/v2/secret.ts b/backend/src/routes/v2/secret.ts index f1b61b47c..0ed79f672 100644 --- a/backend/src/routes/v2/secret.ts +++ b/backend/src/routes/v2/secret.ts @@ -20,7 +20,8 @@ router.post( acceptedAuthModes: ['jwt'] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER] + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), param('workspaceId').exists().isMongoId().trim(), param('environment').exists().trim(), @@ -36,7 +37,8 @@ router.post( acceptedAuthModes: ['jwt'] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER] + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), param('workspaceId').exists().isMongoId().trim(), param('environment').exists().trim(), @@ -54,7 +56,8 @@ router.get( acceptedAuthModes: ['jwt', 'serviceToken'] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER] + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), query('channel'), validateRequest, @@ -82,7 +85,8 @@ router.delete( param('environmentName').exists().trim(), body('secretIds').exists().isArray().custom(array => array.length > 0), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER] + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), validateRequest, secretController.deleteSecrets @@ -110,13 +114,13 @@ router.patch( param('workspaceId').exists().isMongoId().trim(), param('environmentName').exists().trim(), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER] + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), validateRequest, secretController.updateSecrets ); - router.patch( '/workspace/:workspaceId/environment/:environmentName', requireAuth({ @@ -126,7 +130,8 @@ router.patch( param('workspaceId').exists().isMongoId().trim(), param('environmentName').exists().trim(), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER] + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), validateRequest, secretController.updateSecret diff --git a/backend/src/routes/v2/secrets.ts b/backend/src/routes/v2/secrets.ts index 983a8e54f..16ff9f480 100644 --- a/backend/src/routes/v2/secrets.ts +++ b/backend/src/routes/v2/secrets.ts @@ -27,7 +27,7 @@ router.post( }), requireWorkspaceAuth({ acceptedRoles: [ADMIN, MEMBER], - location: 'body' + locationWorkspaceId: 'body' }), body('workspaceId').exists().isString().trim(), body('environment').exists().isString().trim(), @@ -105,7 +105,7 @@ router.post( }), requireWorkspaceAuth({ acceptedRoles: [ADMIN, MEMBER], - location: 'body' + locationWorkspaceId: 'body' }), secretsController.createSecrets ); @@ -122,7 +122,7 @@ router.get( }), requireWorkspaceAuth({ acceptedRoles: [ADMIN, MEMBER], - location: 'query' + locationWorkspaceId: 'query' }), secretsController.getSecrets ); diff --git a/backend/src/routes/v2/serviceAccounts.ts b/backend/src/routes/v2/serviceAccounts.ts index 5d177c7b1..1b93a65c6 100644 --- a/backend/src/routes/v2/serviceAccounts.ts +++ b/backend/src/routes/v2/serviceAccounts.ts @@ -141,7 +141,7 @@ router.post( }), requireWorkspaceAuth({ acceptedRoles: [ADMIN, MEMBER], - location: 'body' + locationWorkspaceId: 'body' }), serviceAccountsController.addServiceAccountWorkspacePermission ); diff --git a/backend/src/routes/v2/serviceTokenData.ts b/backend/src/routes/v2/serviceTokenData.ts index 11e8b1c71..54db35724 100644 --- a/backend/src/routes/v2/serviceTokenData.ts +++ b/backend/src/routes/v2/serviceTokenData.ts @@ -28,7 +28,7 @@ router.post( }), requireWorkspaceAuth({ acceptedRoles: [ADMIN, MEMBER], - location: 'body' + locationWorkspaceId: 'body' }), body('name').exists().isString().trim(), body('workspaceId').exists().isString().trim(), diff --git a/backend/src/routes/v2/workspace.ts b/backend/src/routes/v2/workspace.ts index 6183c9e66..cf58bb7db 100644 --- a/backend/src/routes/v2/workspace.ts +++ b/backend/src/routes/v2/workspace.ts @@ -16,7 +16,8 @@ router.post( acceptedAuthModes: ['jwt'] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER] + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), body('secrets').exists(), body('keys').exists(), @@ -33,7 +34,8 @@ router.get( acceptedAuthModes: ['jwt', 'serviceToken'] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER] + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), query('environment').exists().trim(), query('channel'), @@ -48,7 +50,8 @@ router.get( acceptedAuthModes: ['jwt', 'apiKey'] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER] + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), param('workspaceId').exists().trim(), validateRequest, @@ -61,7 +64,8 @@ router.get( acceptedAuthModes: ['jwt'] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER] + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), param('workspaceId').exists().trim(), validateRequest, @@ -79,6 +83,7 @@ router.get( // new - TODO: rewire dashboard to this route }), requireWorkspaceAuth({ acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), workspaceController.getWorkspaceMemberships ); @@ -94,6 +99,7 @@ router.patch( // TODO - rewire dashboard to this route }), requireWorkspaceAuth({ acceptedRoles: [ADMIN], + locationWorkspaceId: 'params' }), requireMembershipAuth({ acceptedRoles: [ADMIN] @@ -111,6 +117,7 @@ router.delete( // TODO - rewire dashboard to this route }), requireWorkspaceAuth({ acceptedRoles: [ADMIN], + locationWorkspaceId: 'params' }), requireMembershipAuth({ acceptedRoles: [ADMIN] @@ -124,7 +131,8 @@ router.patch( acceptedAuthModes: ['jwt'] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER] + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), param('workspaceId').exists().trim(), body('autoCapitalization').exists().trim().notEmpty(), @@ -132,4 +140,18 @@ router.patch( workspaceController.toggleAutoCapitalization ); +router.get( + '/:workspaceId/aak', + requireAuth({ + acceptedAuthModes: ['serviceAccount'] + }), + requireWorkspaceAuth({ + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' + }), + param('workspaceId').exists().trim(), + validateRequest, + workspaceController.getAak +); + export default router; diff --git a/backend/src/types/express/index.d.ts b/backend/src/types/express/index.d.ts index 74833daf0..a64a16f3d 100644 --- a/backend/src/types/express/index.d.ts +++ b/backend/src/types/express/index.d.ts @@ -24,6 +24,7 @@ declare global { serviceTokenData: any; apiKeyData: any; query?: any; + authTokenType: string; } } } diff --git a/frontend/src/hooks/api/serviceAccounts/types.ts b/frontend/src/hooks/api/serviceAccounts/types.ts index a4da950be..5d4981db2 100644 --- a/frontend/src/hooks/api/serviceAccounts/types.ts +++ b/frontend/src/hooks/api/serviceAccounts/types.ts @@ -1,3 +1,5 @@ +import { Workspace } from '../workspace/types'; + export type ServiceAccount = { _id: string; name: string; @@ -27,7 +29,7 @@ export type RenameServiceAccountDTO = { export type ServiceAccountWorkspacePermission = { _id: string; serviceAccount: string; - workspace: string; + workspace: Workspace; environment: string; canRead: boolean; canWrite: boolean; diff --git a/frontend/src/pages/settings/service-account/[id].tsx b/frontend/src/pages/settings/service-account/[id].tsx deleted file mode 100644 index 1f23f980d..000000000 --- a/frontend/src/pages/settings/service-account/[id].tsx +++ /dev/null @@ -1,20 +0,0 @@ -/* eslint-disable @typescript-eslint/no-unused-vars */ -import Head from 'next/head'; - -export default function NewServiceAccountPage() { - console.log('NewServiceAccountPage'); - return ( -
Project-Level Permissions
@@ -217,28 +202,28 @@ export const SAProjectLevelPermissionsTable = ({ id="isReadPermissionEnabled" isChecked={canRead} isDisabled - /> + >{/**/}