mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
Service account checkpoint
This commit is contained in:
@@ -6,8 +6,17 @@ import {
|
||||
ServiceAccountPermission
|
||||
} from '../../models';
|
||||
import {
|
||||
CreateServiceAccountDto
|
||||
validateCreateServiceAccountPermission
|
||||
} from '../../helpers/serviceAccount';
|
||||
import {
|
||||
CreateServiceAccountDto,
|
||||
AddServiceAccountPermissionDto
|
||||
} from '../../interfaces/serviceAccounts/dto';
|
||||
import {
|
||||
PERMISSION_SA_WORKSPACE_SET,
|
||||
PERMISSION_SA_SET
|
||||
} from '../../variables';
|
||||
import { ServiceAccountKeyNotFoundError, ValidationError } from '../../utils/errors';
|
||||
|
||||
/**
|
||||
* Create a new service account under organization with id [organizationId]
|
||||
@@ -70,22 +79,39 @@ export const addServiceAccountKey = async (req: Request, res: Response) => {
|
||||
|
||||
/**
|
||||
* Add a permission to service account with id [serviceAccountId]
|
||||
* @param req
|
||||
* @param res
|
||||
* @param req
|
||||
* @param res
|
||||
*/
|
||||
export const addServiceAccountPermission = async (req: Request, res: Response) => {
|
||||
const {
|
||||
name,
|
||||
workspaceId,
|
||||
environment
|
||||
} = req.body; // TODO: add DTO
|
||||
}: AddServiceAccountPermissionDto = req.body;
|
||||
|
||||
// TODO: validation?
|
||||
if (PERMISSION_SA_WORKSPACE_SET.has(name)) {
|
||||
// case: permission named [name] is workspace-related
|
||||
|
||||
// some such permissions require workspaceId and environment to be present.
|
||||
|
||||
if (!workspaceId || !environment) {
|
||||
throw ValidationError({
|
||||
message: 'Failed validation that is workspace-related permission must specify a workspace and environment'
|
||||
});
|
||||
} else {
|
||||
const serviceAccountKey = await ServiceAccountKey.findOne({
|
||||
serviceAccount: req.serviceAccount._id,
|
||||
workspace: new Types.ObjectId(workspaceId)
|
||||
});
|
||||
|
||||
if (!serviceAccountKey) throw ServiceAccountKeyNotFoundError({ message: 'Failed to find service account key' });
|
||||
}
|
||||
}
|
||||
|
||||
const serviceAccountPermission = await new ServiceAccountPermission({
|
||||
serviceAccount: req.serviceAccount._id,
|
||||
name,
|
||||
workspace: new Types.ObjectId(workspaceId),
|
||||
workspace: workspaceId ? new Types.ObjectId(workspaceId) : undefined,
|
||||
environment
|
||||
});
|
||||
|
||||
@@ -100,19 +126,15 @@ export const addServiceAccountPermission = async (req: Request, res: Response) =
|
||||
* @param res
|
||||
*/
|
||||
export const deleteServiceAccountPermission = async (req: Request, res: Response) => {
|
||||
const {
|
||||
name,
|
||||
workspaceId,
|
||||
environment
|
||||
} = req.body; // TODO: DTO
|
||||
const { serviceAccountPermissionId } = req.params;
|
||||
|
||||
// user must either be an admin/owner of the organization or they must
|
||||
// have created the service account in the first place to be able to delete it
|
||||
|
||||
// TODO: how to delete just 1 permission?
|
||||
const serviceAccountPermission = await ServiceAccountPermission.findOneAndDelete({
|
||||
serviceAccount: req.serviceAccount._id,
|
||||
name,
|
||||
workspace: new Types.ObjectId(workspaceId),
|
||||
environment
|
||||
});
|
||||
|
||||
|
||||
const serviceAccountPermission = await ServiceAccountPermission.findByIdAndDelete(serviceAccountPermissionId);
|
||||
|
||||
return res.status(200).send({
|
||||
serviceAccountPermission
|
||||
@@ -130,40 +152,19 @@ export const deleteServiceAccount = async (req: Request, res: Response) => {
|
||||
|
||||
const serviceAccount = await ServiceAccount.findByIdAndDelete(serviceAccountId);
|
||||
|
||||
await ServiceAccountKey.deleteMany({
|
||||
serviceAccount: new Types.ObjectId(serviceAccountId)
|
||||
});
|
||||
if (serviceAccount) {
|
||||
// case: service account with id [serviceAccountId] was deleted
|
||||
|
||||
await ServiceAccountKey.deleteMany({
|
||||
serviceAccount: serviceAccount?._id
|
||||
});
|
||||
|
||||
await ServiceAccountPermission.deleteMany({
|
||||
serviceAccount: new Types.ObjectId(serviceAccountId)
|
||||
});
|
||||
}
|
||||
|
||||
await ServiceAccountPermission.deleteMany({
|
||||
serviceAccount: new Types.ObjectId(serviceAccountId)
|
||||
});
|
||||
|
||||
return res.status(200).send({
|
||||
serviceAccount
|
||||
});
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Add a service account key to service account with id [serviceAccountId]
|
||||
// * for workspace with id [workspaceId]
|
||||
// * @param req
|
||||
// * @param res
|
||||
// * @returns
|
||||
// */
|
||||
// export const addServiceAccountKey = async (req: Request, res: Response) => {
|
||||
// const {
|
||||
// workspaceId,
|
||||
// encryptedKey,
|
||||
// nonce
|
||||
// } = req.body;
|
||||
|
||||
// const serviceAccountKey = await new ServiceAccountKey({
|
||||
// encryptedKey,
|
||||
// nonce,
|
||||
// sender: req.user._id,
|
||||
// serviceAccount: req.serviceAccount._d,
|
||||
// workspace: new Types.ObjectId(workspaceId)
|
||||
// }).save();
|
||||
|
||||
// return serviceAccountKey;
|
||||
// }
|
||||
}
|
||||
@@ -1,5 +1,9 @@
|
||||
import * as Sentry from '@sentry/node';
|
||||
import { Membership, Key } from '../models';
|
||||
import {
|
||||
MembershipNotFoundError,
|
||||
BadRequestError
|
||||
} from '../utils/errors';
|
||||
|
||||
/**
|
||||
* Validate that user with id [userId] is a member of workspace with id [workspaceId]
|
||||
@@ -19,23 +23,17 @@ const validateMembership = async ({
|
||||
acceptedRoles: string[];
|
||||
}) => {
|
||||
|
||||
let membership;
|
||||
//TODO: Refactor code to take advantage of using RequestError. It's possible to create new types of errors for more detailed errors
|
||||
try {
|
||||
membership = await Membership.findOne({
|
||||
user: userId,
|
||||
workspace: workspaceId
|
||||
}).populate("workspace");
|
||||
|
||||
if (!membership) throw new Error('Failed to find membership');
|
||||
|
||||
if (!acceptedRoles.includes(membership.role)) {
|
||||
throw new Error('Failed to validate membership role');
|
||||
}
|
||||
} catch (err) {
|
||||
Sentry.setUser(null);
|
||||
Sentry.captureException(err);
|
||||
throw new Error('Failed to validate membership');
|
||||
const membership = await Membership.findOne({
|
||||
user: userId,
|
||||
workspace: workspaceId
|
||||
}).populate("workspace");
|
||||
|
||||
if (!membership) {
|
||||
throw MembershipNotFoundError({ message: 'Failed to find workspace membership' });
|
||||
}
|
||||
|
||||
if (!acceptedRoles.includes(membership.role)) {
|
||||
throw BadRequestError({ message: 'Failed to validate workspace membership role' });
|
||||
}
|
||||
|
||||
return membership;
|
||||
|
||||
@@ -1,40 +1,48 @@
|
||||
import * as Sentry from '@sentry/node';
|
||||
import { Types } from 'mongoose';
|
||||
import { MembershipOrg, Workspace, Membership, Key } from '../models';
|
||||
import {
|
||||
MembershipOrgNotFoundError,
|
||||
BadRequestError
|
||||
} from '../utils/errors';
|
||||
|
||||
/**
|
||||
* Validate that user with id [userId] is a member of organization with id [organizationId]
|
||||
* and has at least one of the roles in [acceptedRoles]
|
||||
*
|
||||
* @param {Object} obj
|
||||
* @param {Types.ObjectId} obj.userId
|
||||
* @param {Types.ObjectId} obj.organizationId
|
||||
* @param {String[]} obj.acceptedRoles
|
||||
*/
|
||||
const validateMembership = async ({
|
||||
const validateMembershipOrg = async ({
|
||||
userId,
|
||||
organizationId,
|
||||
acceptedRoles
|
||||
acceptedRoles,
|
||||
acceptedStatuses
|
||||
}: {
|
||||
userId: string;
|
||||
organizationId: string;
|
||||
userId: Types.ObjectId;
|
||||
organizationId: Types.ObjectId;
|
||||
acceptedRoles: string[];
|
||||
acceptedStatuses: string[];
|
||||
}) => {
|
||||
let membership;
|
||||
try {
|
||||
membership = await MembershipOrg.findOne({
|
||||
user: new Types.ObjectId(userId),
|
||||
organization: new Types.ObjectId(organizationId)
|
||||
});
|
||||
|
||||
if (!membership) throw new Error('Failed to find organization membership');
|
||||
|
||||
if (!acceptedRoles.includes(membership.role)) {
|
||||
throw new Error('Failed to validate organization membership role');
|
||||
}
|
||||
} catch (err) {
|
||||
Sentry.setUser(null);
|
||||
Sentry.captureException(err);
|
||||
throw new Error('Failed to validate organization membership');
|
||||
const membershipOrg = await MembershipOrg.findOne({
|
||||
user: userId,
|
||||
organization: organizationId
|
||||
});
|
||||
|
||||
if (!membershipOrg) {
|
||||
throw MembershipOrgNotFoundError({ message: 'Failed to find organization membership' });
|
||||
}
|
||||
|
||||
return membership;
|
||||
if (!acceptedRoles.includes(membershipOrg.role)) {
|
||||
throw BadRequestError({ message: 'Failed to validate organization membership role' });
|
||||
}
|
||||
|
||||
if (!acceptedStatuses.includes(membershipOrg.status)) {
|
||||
throw BadRequestError({ message: 'Failed to validate organization membership status' });
|
||||
}
|
||||
|
||||
return membershipOrg;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -156,7 +164,7 @@ const deleteMembershipOrg = async ({
|
||||
};
|
||||
|
||||
export {
|
||||
validateMembership,
|
||||
validateMembershipOrg,
|
||||
findMembershipOrg,
|
||||
addMembershipsOrg,
|
||||
deleteMembershipOrg
|
||||
|
||||
110
backend/src/helpers/serviceAccount.ts
Normal file
110
backend/src/helpers/serviceAccount.ts
Normal file
@@ -0,0 +1,110 @@
|
||||
import { Types } from 'mongoose';
|
||||
import {
|
||||
Workspace,
|
||||
ServiceAccount,
|
||||
ServiceAccountKey
|
||||
} from '../models';
|
||||
import {
|
||||
WorkspaceNotFoundError,
|
||||
ServiceAccountNotFoundError,
|
||||
ServiceAccountKeyNotFoundError
|
||||
} from '../utils/errors';
|
||||
import {
|
||||
PERMISSION_SA_WORKSPACE_READ,
|
||||
PERMISSION_SA_WORKSPACE_WRITE,
|
||||
PERMISSION_SA_SET
|
||||
} from '../variables';
|
||||
|
||||
/**
|
||||
* Validate that user with id [userId] can provision the permission
|
||||
* named [name] for a service account with id [serviceAccountId] and
|
||||
* optionally workspace with id [workspaceId] and environment [environment]
|
||||
* @param {Object} obj
|
||||
* @param {String} obj.name - name of permission to create
|
||||
* @param {Types.ObjectId} userId - id of user creating the permission
|
||||
* @param {Types.ObjectId} serviceAccountId - id of service account that permission will be bound to
|
||||
* @param {Types.ObjectId} workspaceId - id of workspace that permission concerns
|
||||
* @param {Types.ObjectId} workspaceId - id of service account that permission will be bound to
|
||||
*/
|
||||
const validateCreateServiceAccountPermission = async ({
|
||||
name,
|
||||
userId,
|
||||
serviceAccountId,
|
||||
workspaceId,
|
||||
environment
|
||||
}: {
|
||||
name: string;
|
||||
userId: Types.ObjectId;
|
||||
serviceAccountId: Types.ObjectId,
|
||||
workspaceId?: Types.ObjectId;
|
||||
environment?: string;
|
||||
}) => {
|
||||
|
||||
// TODO: as we upgrade user permissions to be more global, then we should take into account
|
||||
// the user's permissions as it concerns to being able to interact with service accounts
|
||||
|
||||
if (!PERMISSION_SA_SET.has(name)) throw new Error(`${name} is not a valid permission name`);
|
||||
|
||||
if ([
|
||||
PERMISSION_SA_WORKSPACE_READ,
|
||||
PERMISSION_SA_WORKSPACE_WRITE
|
||||
].includes(name)) {
|
||||
if (workspaceId && environment) {
|
||||
// case: either workspace id [workspaceId] or environment name [environment] is being passed in
|
||||
// (i.e. validating a service account permission concerning a workspace and/or environment)
|
||||
const workspace = await Workspace.findById(workspaceId);
|
||||
|
||||
if (!workspace) {
|
||||
// case: workspace does not exist
|
||||
throw WorkspaceNotFoundError({ message: 'Failed to locate workspace' });
|
||||
}
|
||||
|
||||
if (!workspace.environments.some((env) => env.slug === environment)) {
|
||||
// case: environment name [environment] is not a valid environment slug in workspace
|
||||
throw Error('Failed to locate environment in workspace');
|
||||
}
|
||||
|
||||
const serviceAccount = await ServiceAccount.findById(serviceAccountId);
|
||||
if (!serviceAccount) {
|
||||
// case: service account does not exist
|
||||
throw ServiceAccountNotFoundError({ message: 'Failed to locate service account' });
|
||||
}
|
||||
|
||||
const serviceAccountKey = await ServiceAccountKey.findOne({
|
||||
serviceAccount: serviceAccount._id,
|
||||
workspace: workspaceId
|
||||
});
|
||||
|
||||
if (!serviceAccountKey) {
|
||||
// case: service account key does not exist
|
||||
throw ServiceAccountKeyNotFoundError({ message: 'Failed to locate service account key' });
|
||||
}
|
||||
} else {
|
||||
throw new Error('Failed to validate workspace and environment for workspace-related permission');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const validateDeleteServiceAccountPermission = async ({
|
||||
userId,
|
||||
serviceAccountId,
|
||||
name,
|
||||
workspaceId,
|
||||
environment
|
||||
}: {
|
||||
userId: Types.ObjectId;
|
||||
serviceAccountId: Types.ObjectId;
|
||||
name: string;
|
||||
workspaceId: Types.ObjectId;
|
||||
environment: string;
|
||||
}) => {
|
||||
// does the user have the authority to delete the permission?
|
||||
// does the service account permission exist?
|
||||
|
||||
|
||||
}
|
||||
|
||||
export {
|
||||
validateCreateServiceAccountPermission
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
interface AddServiceAccountPermissionDto {
|
||||
name: string;
|
||||
workspaceId?: string;
|
||||
environment?: string;
|
||||
}
|
||||
|
||||
export default AddServiceAccountPermissionDto;
|
||||
@@ -1,5 +1,7 @@
|
||||
import CreateServiceAccountDto from './CreateServiceAccountDto';
|
||||
import AddServiceAccountPermissionDto from './AddServiceAccountPermissionDto';
|
||||
|
||||
export {
|
||||
CreateServiceAccountDto
|
||||
CreateServiceAccountDto,
|
||||
AddServiceAccountPermissionDto
|
||||
}
|
||||
@@ -3,7 +3,7 @@ import { UnauthorizedRequestError } from '../utils/errors';
|
||||
import {
|
||||
MembershipOrg
|
||||
} from '../models';
|
||||
import { validateMembership } from '../helpers/membershipOrg';
|
||||
import { validateMembershipOrg } from '../helpers/membershipOrg';
|
||||
|
||||
|
||||
type req = 'params' | 'body' | 'query';
|
||||
@@ -17,9 +17,11 @@ type req = 'params' | 'body' | 'query';
|
||||
*/
|
||||
const requireMembershipOrgAuth = ({
|
||||
acceptedRoles,
|
||||
acceptedStatuses,
|
||||
location = 'params'
|
||||
}: {
|
||||
acceptedRoles: string[];
|
||||
acceptedStatuses: string[];
|
||||
location?: req;
|
||||
}) => {
|
||||
return async (req: Request, res: Response, next: NextFunction) => {
|
||||
@@ -29,14 +31,13 @@ const requireMembershipOrgAuth = ({
|
||||
|
||||
if (!membershipOrg) throw new Error('Failed to find target organization membership');
|
||||
|
||||
const targetMembership = await validateMembership({
|
||||
userId: req.user._id.toString(),
|
||||
organizationId: membershipOrg.organization.toString(),
|
||||
acceptedRoles
|
||||
req.targetMembership = await validateMembershipOrg({
|
||||
userId: req.user._id,
|
||||
organizationId: membershipOrg.organization,
|
||||
acceptedRoles,
|
||||
acceptedStatuses
|
||||
});
|
||||
|
||||
req.targetMembership = targetMembership;
|
||||
|
||||
return next();
|
||||
} catch (err) {
|
||||
return next(UnauthorizedRequestError({
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { Request, Response, NextFunction } from 'express';
|
||||
import { Types } from 'mongoose';
|
||||
import { IOrganization, MembershipOrg } from '../models';
|
||||
import { UnauthorizedRequestError, ValidationError } from '../utils/errors';
|
||||
import { validateMembershipOrg } from '../helpers/membershipOrg';
|
||||
|
||||
type req = 'params' | 'body' | 'query';
|
||||
|
||||
@@ -9,7 +11,7 @@ type req = 'params' | 'body' | 'query';
|
||||
* on request params.
|
||||
* @param {Object} obj
|
||||
* @param {String[]} obj.acceptedRoles - accepted organization roles
|
||||
* @param {String[]} obj.acceptedStatuses - accepted organization statuses
|
||||
* @param {String[]} obj.accepteStatuses - accepted organization statuses
|
||||
*/
|
||||
const requireOrganizationAuth = ({
|
||||
acceptedRoles,
|
||||
@@ -21,30 +23,13 @@ const requireOrganizationAuth = ({
|
||||
location?: req;
|
||||
}) => {
|
||||
return async (req: Request, res: Response, next: NextFunction) => {
|
||||
// organization authorization middleware
|
||||
|
||||
const { organizationId } = req[location];
|
||||
|
||||
// validate organization membership
|
||||
const membershipOrg = await MembershipOrg.findOne({
|
||||
user: req.user._id,
|
||||
organization: organizationId
|
||||
}).populate<{ organization: IOrganization }>('organization');
|
||||
|
||||
|
||||
if (!membershipOrg) {
|
||||
return next(UnauthorizedRequestError({message: "You're not a member of this Organization."}))
|
||||
}
|
||||
//TODO is this important to validate? I mean is it possible to save wrong role to database or get wrong role from databse? - Zamion101
|
||||
if (!acceptedRoles.includes(membershipOrg.role)) {
|
||||
return next(ValidationError({message: 'Failed to validate Organization Membership Role'}))
|
||||
}
|
||||
|
||||
if (!acceptedStatuses.includes(membershipOrg.status)) {
|
||||
return next(ValidationError({message: 'Failed to validate Organization Membership Status'}))
|
||||
}
|
||||
|
||||
req.membershipOrg = membershipOrg;
|
||||
req.membershipOrg = await validateMembershipOrg({
|
||||
userId: req.user._id,
|
||||
organizationId: new Types.ObjectId(organizationId),
|
||||
acceptedRoles,
|
||||
acceptedStatuses
|
||||
});
|
||||
|
||||
return next();
|
||||
};
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import { Request, Response, NextFunction } from 'express';
|
||||
import { ServiceAccount } from '../models';
|
||||
import {
|
||||
AccountNotFoundError,
|
||||
UnauthorizedRequestError
|
||||
ServiceAccountNotFoundError
|
||||
} from '../utils/errors';
|
||||
import {
|
||||
validateMembershipOrg
|
||||
} from '../helpers/membershipOrg';
|
||||
|
||||
type req = 'params' | 'body' | 'query';
|
||||
|
||||
@@ -20,14 +22,19 @@ const requireServiceAccountAuth = ({
|
||||
const serviceAccountId = req[location].serviceAccountId;
|
||||
const serviceAccount = await ServiceAccount.findById(serviceAccountId);
|
||||
|
||||
// TODO: acceptedRoles and acceptedStatuses
|
||||
|
||||
if (!serviceAccount) {
|
||||
return next(AccountNotFoundError({ message: 'Failed to locate Service Account' }));
|
||||
return next(ServiceAccountNotFoundError({ message: 'Failed to locate Service Account' }));
|
||||
}
|
||||
|
||||
if (serviceAccount.user.toString() !== req.user.id.toString()) {
|
||||
return next(UnauthorizedRequestError({ message: 'Failed to authenticate the Service Account' }));
|
||||
// case: creator of the service account is different from
|
||||
// the user on the request -> apply middleware role/status validation
|
||||
await validateMembershipOrg({
|
||||
userId: req.user._id,
|
||||
organizationId: serviceAccount.organization,
|
||||
acceptedRoles,
|
||||
acceptedStatuses
|
||||
});
|
||||
}
|
||||
|
||||
req.serviceAccount = serviceAccount;
|
||||
|
||||
@@ -22,9 +22,11 @@ const serviceAccountPermissionSchema = new Schema<IServiceAccountPermission>(
|
||||
workspace: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: 'Workspace',
|
||||
default: null
|
||||
},
|
||||
environment: {
|
||||
type: 'String'
|
||||
type: 'String',
|
||||
default: null
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -40,7 +40,8 @@ router.patch(
|
||||
acceptedStatuses: [ACCEPTED]
|
||||
}),
|
||||
requireMembershipOrgAuth({
|
||||
acceptedRoles: [OWNER, ADMIN]
|
||||
acceptedRoles: [OWNER, ADMIN],
|
||||
acceptedStatuses: [ACCEPTED]
|
||||
}),
|
||||
organizationsController.updateOrganizationMembership
|
||||
);
|
||||
@@ -58,7 +59,8 @@ router.delete(
|
||||
acceptedStatuses: [ACCEPTED]
|
||||
}),
|
||||
requireMembershipOrgAuth({
|
||||
acceptedRoles: [OWNER, ADMIN]
|
||||
acceptedRoles: [OWNER, ADMIN],
|
||||
acceptedStatuses: [ACCEPTED]
|
||||
}),
|
||||
organizationsController.deleteOrganizationMembership
|
||||
);
|
||||
|
||||
@@ -2,14 +2,17 @@ import express from 'express';
|
||||
const router = express.Router();
|
||||
import {
|
||||
requireOrganizationAuth,
|
||||
requireServiceAccountAuth
|
||||
requireWorkspaceAuth,
|
||||
requireServiceAccountAuth,
|
||||
validateRequest
|
||||
} from '../../middleware';
|
||||
import { body } from 'express-validator';
|
||||
import {
|
||||
OWNER,
|
||||
ADMIN,
|
||||
MEMBER,
|
||||
ACCEPTED
|
||||
ACCEPTED,
|
||||
PERMISSION_SA_SET
|
||||
} from '../../variables';
|
||||
import { serviceAccountsController } from '../../controllers/v2';
|
||||
|
||||
@@ -27,6 +30,19 @@ router.post(
|
||||
serviceAccountsController.createServiceAccount
|
||||
);
|
||||
|
||||
router.post(
|
||||
'/serviceAccountId/:serviceAccountId/permissions',
|
||||
body('name').exists().isString().trim().custom((value) => PERMISSION_SA_SET.has(value)),
|
||||
body('workspaceId').optional().isMongoId(),
|
||||
body('environment').optional(),
|
||||
validateRequest,
|
||||
requireServiceAccountAuth({
|
||||
acceptedRoles: [OWNER, ADMIN],
|
||||
acceptedStatuses: [ACCEPTED]
|
||||
}),
|
||||
serviceAccountsController.addServiceAccountPermission
|
||||
);
|
||||
|
||||
// router.post(
|
||||
// '/:serviceAccountId/key',
|
||||
// body('workspaceId').exists().isString().trim(),
|
||||
@@ -42,7 +58,7 @@ router.post(
|
||||
router.delete(
|
||||
'/:serviceAccountId/key/:serviceAccountKeyId',
|
||||
requireServiceAccountAuth({
|
||||
acceptedRoles: [OWNER, ADMIN, MEMBER],
|
||||
acceptedRoles: [OWNER, ADMIN],
|
||||
acceptedStatuses: [ACCEPTED]
|
||||
}),
|
||||
async (req, res) => {
|
||||
@@ -50,4 +66,17 @@ router.delete(
|
||||
}
|
||||
);
|
||||
|
||||
// TODO: create service account permission
|
||||
// router.post(
|
||||
|
||||
// );
|
||||
|
||||
// TODO: delete service account permission
|
||||
|
||||
router.delete(
|
||||
'/:serviceAccountId/service-account-permission/:serviceAccountPermissionId',
|
||||
|
||||
)
|
||||
|
||||
|
||||
export default router;
|
||||
@@ -93,6 +93,16 @@ export const WorkspaceNotFoundError = (error?: Partial<RequestErrorContext>) =>
|
||||
stack: error?.stack
|
||||
});
|
||||
|
||||
//* ----->[WORKSPACE MEMBERSHIP ERRORS]<-----
|
||||
export const MembershipNotFoundError = (error?: Partial<RequestErrorContext>) => new RequestError({
|
||||
logLevel: error?.logLevel ?? LogLevel.ERROR,
|
||||
statusCode: error?.statusCode ?? 404,
|
||||
type: error?.type ?? 'workspace_membership_not_found_error',
|
||||
message: error?.message ?? 'The requested membership was not found',
|
||||
context: error?.context,
|
||||
stack: error?.stack
|
||||
});
|
||||
|
||||
//* ----->[ORGANIZATION ERRORS]<-----
|
||||
export const OrganizationNotFoundError = (error?: Partial<RequestErrorContext>) => new RequestError({
|
||||
logLevel: error?.logLevel ?? LogLevel.ERROR,
|
||||
@@ -103,6 +113,16 @@ export const OrganizationNotFoundError = (error?: Partial<RequestErrorContext>)
|
||||
stack: error?.stack
|
||||
});
|
||||
|
||||
//* ----->[MEMBERSHIP ORGANIZATION ERRORS]<-----
|
||||
export const MembershipOrgNotFoundError = (error?: Partial<RequestErrorContext>) => new RequestError({
|
||||
logLevel: error?.logLevel ?? LogLevel.ERROR,
|
||||
statusCode: error?.statusCode ?? 404,
|
||||
type: error?.type ?? 'organization_membership_not_found_error',
|
||||
message: error?.message ?? 'The requested organization membership was not found',
|
||||
context: error?.context,
|
||||
stack: error?.stack
|
||||
});
|
||||
|
||||
//* ----->[ACCOUNT ERRORS]<-----
|
||||
export const AccountNotFoundError = (error?: Partial<RequestErrorContext>) => new RequestError({
|
||||
logLevel: error?.logLevel ?? LogLevel.ERROR,
|
||||
@@ -157,10 +177,29 @@ export const ServiceTokenDataNotFoundError = (error?: Partial<RequestErrorContex
|
||||
export const APIKeyDataNotFoundError = (error?: Partial<RequestErrorContext>) => new RequestError({
|
||||
logLevel: error?.logLevel ?? LogLevel.ERROR,
|
||||
statusCode: error?.statusCode ?? 404,
|
||||
type: error?.type ?? 'service_token_data_not_found_error',
|
||||
type: error?.type ?? 'api_key_data_not_found_error',
|
||||
message: error?.message ?? 'The requested service token data was not found',
|
||||
context: error?.context,
|
||||
stack: error?.stack
|
||||
});
|
||||
|
||||
//* ----->[SERVICE_ACCOUNT ERRORS]<-----
|
||||
export const ServiceAccountNotFoundError = (error?: Partial<RequestErrorContext>) => new RequestError({
|
||||
logLevel: error?.logLevel ?? LogLevel.ERROR,
|
||||
statusCode: error?.statusCode ?? 404,
|
||||
type: error?.type ?? 'service_account_not_found_error',
|
||||
message: error?.message ?? 'The requested service account was not found',
|
||||
context: error?.context,
|
||||
stack: error?.stack
|
||||
});
|
||||
|
||||
export const ServiceAccountKeyNotFoundError = (error?: Partial<RequestErrorContext>) => new RequestError({
|
||||
logLevel: error?.logLevel ?? LogLevel.ERROR,
|
||||
statusCode: error?.statusCode ?? 404,
|
||||
type: error?.type ?? 'service_account_key_not_found_error',
|
||||
message: error?.message ?? 'The requested service account key was not found',
|
||||
context: error?.context,
|
||||
stack: error?.stack
|
||||
})
|
||||
|
||||
//* ----->[MISC ERRORS]<-----
|
||||
|
||||
@@ -63,6 +63,12 @@ import {
|
||||
TOKEN_EMAIL_ORG_INVITATION,
|
||||
TOKEN_EMAIL_PASSWORD_RESET
|
||||
} from './token';
|
||||
import {
|
||||
PERMISSION_SA_WORKSPACE_READ,
|
||||
PERMISSION_SA_WORKSPACE_WRITE,
|
||||
PERMISSION_SA_WORKSPACE_SET,
|
||||
PERMISSION_SA_SET
|
||||
} from './permissions';
|
||||
|
||||
export {
|
||||
OWNER,
|
||||
@@ -124,5 +130,9 @@ export {
|
||||
TOKEN_EMAIL_CONFIRMATION,
|
||||
TOKEN_EMAIL_MFA,
|
||||
TOKEN_EMAIL_ORG_INVITATION,
|
||||
TOKEN_EMAIL_PASSWORD_RESET
|
||||
TOKEN_EMAIL_PASSWORD_RESET,
|
||||
PERMISSION_SA_WORKSPACE_READ,
|
||||
PERMISSION_SA_WORKSPACE_WRITE,
|
||||
PERMISSION_SA_WORKSPACE_SET,
|
||||
PERMISSION_SA_SET
|
||||
};
|
||||
|
||||
19
backend/src/variables/permissions.ts
Normal file
19
backend/src/variables/permissions.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
const PERMISSION_SA_WORKSPACE_READ = 'read';
|
||||
const PERMISSION_SA_WORKSPACE_WRITE = 'write';
|
||||
|
||||
const PERMISSION_SA_WORKSPACE_SET = new Set([
|
||||
PERMISSION_SA_WORKSPACE_READ,
|
||||
PERMISSION_SA_WORKSPACE_WRITE
|
||||
]);
|
||||
|
||||
const PERMISSION_SA_SET = new Set([
|
||||
PERMISSION_SA_WORKSPACE_READ,
|
||||
PERMISSION_SA_WORKSPACE_WRITE
|
||||
]);
|
||||
|
||||
export {
|
||||
PERMISSION_SA_WORKSPACE_READ,
|
||||
PERMISSION_SA_WORKSPACE_WRITE,
|
||||
PERMISSION_SA_WORKSPACE_SET,
|
||||
PERMISSION_SA_SET
|
||||
}
|
||||
Reference in New Issue
Block a user