feat(rbac): added new validation to all routes and permission check to most

This commit is contained in:
Akhil Mohan
2023-09-08 21:22:36 +05:30
parent 520a553ea1
commit 549121f44e
78 changed files with 4518 additions and 3499 deletions
+19
View File
@@ -0,0 +1,19 @@
import { z } from "zod";
export const GetActionV1 = z.object({
params: z.object({
actionId: z.string().trim()
})
});
export const AddUserActionV1 = z.object({
body: z.object({
action: z.string().trim()
})
});
export const GetUserActionV1 = z.object({
query: z.object({
action: z.string().trim()
})
});
+134
View File
@@ -0,0 +1,134 @@
import { z } from "zod";
export const BeginEmailSignUpV1 = z.object({
body: z.object({
email: z.string().email().trim()
})
});
export const VerifyEmailSignUpV1 = z.object({
body: z.object({
email: z.string().email().trim(),
code: z.string().email().trim()
})
});
export const Login1V1 = z.object({
body: z.object({
email: z.string().email().trim(),
clientPublicKey: z.string().trim()
})
});
export const Login2V1 = z.object({
body: z.object({
email: z.string().email().trim(),
clientProof: z.string().trim()
})
});
export const Srp1V1 = z.object({
body: z.object({
clientPublicKey: z.string().trim()
})
});
export const ChangePasswordV1 = z.object({
body: z.object({
clientProof: z.string().trim(),
protectedKey: z.string().trim(),
protectedKeyIV: z.string().trim(),
protectedKeyTag: z.string().trim(),
encryptedPrivateKey: z.string().trim(),
encryptedPrivateKeyIV: z.string().trim(),
encryptedPrivateKeyTag: z.string().trim(),
salt: z.string().trim(),
verifier: z.string().trim()
})
});
export const EmailPasswordResetV1 = z.object({
body: z.object({
email: z.string().email().trim()
})
});
export const EmailPasswordResetVerifyV1 = z.object({
body: z.object({
email: z.string().email().trim(),
code: z.string().trim()
})
});
export const CreateBackupPrivateKeyV1 = z.object({
body: z.object({
clientProof: z.string().trim(),
encryptedPrivateKey: z.string().trim(),
iv: z.string().trim(),
tag: z.string().trim(),
salt: z.string().trim(),
verifier: z.string().trim()
})
});
export const ResetPasswordV1 = z.object({
body: z.object({
protectedKey: z.string().trim(),
protectedKeyIV: z.string().trim(),
protectedKeyTag: z.string().trim(),
encryptedPrivateKey: z.string().trim(),
encryptedPrivateKeyIV: z.string().trim(),
encryptedPrivateKeyTag: z.string().trim(),
salt: z.string().trim(),
verifier: z.string().trim()
})
});
export const SendMfaTokenV2 = z.object({
body: z.object({
email: z.string().email().trim()
})
});
export const VerifyMfaTokenV2 = z.object({
body: z.object({
email: z.string().email().trim(),
mfaToken: z.string().trim()
})
});
export const Login1V3 = z.object({
body: z.object({
email: z.string().email().trim(),
providerAuthToken: z.string().trim().optional(),
clientPublicKey: z.string().trim()
})
});
export const Login2V3 = z.object({
body: z.object({
email: z.string().email().trim(),
providerAuthToken: z.string().trim().optional(),
clientProof: z.string().trim()
})
});
export const CompletedAccountSignupV3 = z.object({
body: z.object({
email: z.string().email().trim(),
firstName: z.string().trim(),
lastName: z.string().trim().optional().nullish(),
protectedKey: z.string().trim(),
protectedKeyIV: z.string().trim(),
protectedKeyTag: z.string().trim(),
publicKey: z.string().trim(),
encryptedPrivateKey: z.string().trim(),
encryptedPrivateKeyIV: z.string().trim(),
encryptedPrivateKeyTag: z.string().trim(),
salt: z.string().trim(),
verifier: z.string().trim(),
organizationName: z.string().trim(),
providerAuthToken: z.string().trim().optional().nullish(),
attributionSource: z.string().trim().optional()
})
});
+29 -13
View File
@@ -1,15 +1,10 @@
import { Types } from "mongoose";
import {
Bot,
IUser,
} from "../models";
import { Bot, IUser } from "../models";
import { validateUserClientForWorkspace } from "./user";
import {
BotNotFoundError,
UnauthorizedRequestError,
} from "../utils/errors";
import { BotNotFoundError, UnauthorizedRequestError } from "../utils/errors";
import { AuthData } from "../interfaces/middleware";
import { ActorType } from "../ee/models";
import { z } from "zod";
/**
* Validate authenticated clients for bot with id [botId] based
@@ -22,7 +17,7 @@ import { ActorType } from "../ee/models";
export const validateClientForBot = async ({
authData,
botId,
acceptedRoles,
acceptedRoles
}: {
authData: AuthData;
botId: Types.ObjectId;
@@ -30,18 +25,39 @@ export const validateClientForBot = async ({
}) => {
const bot = await Bot.findById(botId);
if (!bot) throw BotNotFoundError();
switch (authData.actor.type) {
case ActorType.USER:
await validateUserClientForWorkspace({
user: authData.authPayload as IUser,
workspaceId: bot.workspace,
acceptedRoles,
acceptedRoles
});
return bot;
case ActorType.SERVICE:
throw UnauthorizedRequestError({
message: "Failed service token authorization for bot",
message: "Failed service token authorization for bot"
});
}
};
};
export const GetBotByWorkspaceIdV1 = z.object({
params: z.object({
workspaceId: z.string().trim()
})
});
export const SetBotActiveStateV1 = z.object({
body: z.object({
isActive: z.boolean(),
botKey: z
.object({
nonce: z.string().trim().optional(),
encryptedKey: z.string().trim().optional()
})
.optional()
}),
params: z.object({
botId: z.string().trim()
})
});
+7
View File
@@ -0,0 +1,7 @@
import { z } from "zod";
export const GetCloudProductsV1 = z.object({
query: z.object({
"billing-cycle": z.enum(["monthly", "yearly"])
})
});
+37
View File
@@ -0,0 +1,37 @@
import { z } from "zod";
export const CreateWorkspaceEnvironmentV2 = z.object({
params: z.object({
workspaceId: z.string().trim()
}),
body: z.object({
environmentSlug: z.string().trim(),
environmentName: z.string().trim()
})
});
export const UpdateWorkspaceEnvironmentV2 = z.object({
params: z.object({
workspaceId: z.string().trim()
}),
body: z.object({
environmentSlug: z.string().trim(),
environmentName: z.string().trim(),
oldEnvironmentSlug: z.string().trim()
})
});
export const DeleteWorkspaceEnvironmentV2 = z.object({
params: z.object({
workspaceId: z.string().trim()
}),
body: z.object({
environmentSlug: z.string().trim()
})
});
export const GetAllAccessibileEnvironmentsOfWorkspaceV2 = z.object({
params: z.object({
workspaceId: z.string().trim()
})
});
+40
View File
@@ -0,0 +1,40 @@
import { z } from "zod";
export const CreateFolderV1 = z.object({
body: z.object({
workspaceId: z.string().trim(),
environment: z.string().trim(),
folderName: z.string().trim(),
parentFolderId: z.string().trim().optional()
})
});
export const UpdateFolderV1 = z.object({
params: z.object({
folderId: z.string().trim()
}),
body: z.object({
workspaceId: z.string().trim(),
environment: z.string().trim(),
name: z.string().trim()
})
});
export const DeleteFolderV1 = z.object({
params: z.object({
folderId: z.string().trim()
}),
body: z.object({
workspaceId: z.string().trim(),
environment: z.string().trim()
})
});
export const GetFoldersV1 = z.object({
query: z.object({
workspaceId: z.string().trim(),
environment: z.string().trim(),
parentFolderId: z.string().trim().optional(),
parentFolderPath: z.string().trim().optional()
})
});
+78 -43
View File
@@ -1,18 +1,15 @@
import { Types } from "mongoose";
import {
IUser,
Integration,
IntegrationAuth,
} from "../models";
import { IUser, Integration, IntegrationAuth } from "../models";
import { validateUserClientForWorkspace } from "./user";
import { IntegrationService } from "../services";
import {
IntegrationAuthNotFoundError,
IntegrationNotFoundError,
UnauthorizedRequestError,
IntegrationAuthNotFoundError,
IntegrationNotFoundError,
UnauthorizedRequestError
} from "../utils/errors";
import { AuthData } from "../interfaces/middleware";
import { ActorType } from "../ee/models";
import { z } from "zod";
/**
* Validate authenticated clients for integration with id [integrationId] based
@@ -25,42 +22,80 @@ import { ActorType } from "../ee/models";
* @param {String[]} obj.requiredPermissions - required permissions as part of the endpoint
*/
export const validateClientForIntegration = async ({
authData,
integrationId,
acceptedRoles,
authData,
integrationId,
acceptedRoles
}: {
authData: AuthData;
integrationId: Types.ObjectId;
acceptedRoles: Array<"admin" | "member">;
authData: AuthData;
integrationId: Types.ObjectId;
acceptedRoles: Array<"admin" | "member">;
}) => {
const integration = await Integration.findById(integrationId);
if (!integration) throw IntegrationNotFoundError();
const integration = await Integration.findById(integrationId);
if (!integration) throw IntegrationNotFoundError();
const integrationAuth = await IntegrationAuth
.findById(integration.integrationAuth)
.select(
"+refreshCiphertext +refreshIV +refreshTag +accessCiphertext +accessIV +accessTag +accessExpiresAt"
);
if (!integrationAuth) throw IntegrationAuthNotFoundError();
const integrationAuth = await IntegrationAuth.findById(integration.integrationAuth).select(
"+refreshCiphertext +refreshIV +refreshTag +accessCiphertext +accessIV +accessTag +accessExpiresAt"
);
const accessToken = (await IntegrationService.getIntegrationAuthAccess({
integrationAuthId: integrationAuth._id,
})).accessToken;
switch (authData.actor.type) {
case ActorType.USER:
await validateUserClientForWorkspace({
user: authData.authPayload as IUser,
workspaceId: integration.workspace,
acceptedRoles,
});
return ({ integration, accessToken });
case ActorType.SERVICE:
throw UnauthorizedRequestError({
message: "Failed service token authorization for integration",
});
}
}
if (!integrationAuth) throw IntegrationAuthNotFoundError();
const accessToken = (
await IntegrationService.getIntegrationAuthAccess({
integrationAuthId: integrationAuth._id
})
).accessToken;
switch (authData.actor.type) {
case ActorType.USER:
await validateUserClientForWorkspace({
user: authData.authPayload as IUser,
workspaceId: integration.workspace,
acceptedRoles
});
return { integration, accessToken };
case ActorType.SERVICE:
throw UnauthorizedRequestError({
message: "Failed service token authorization for integration"
});
}
};
export const CreateIntegrationV1 = z.object({
body: z.object({
integrationAuthId: z.string().trim(),
app: z.string().trim(),
isActive: z.boolean(),
appId: z.string().trim(),
secretPath: z.string().trim().default("/"),
sourceEnvironment: z.string().trim(),
targetEnvironment: z.string().trim(),
targetEnvironmentId: z.string().trim(),
targetService: z.string().trim(),
targetServiceId: z.string().trim(),
owner: z.string().trim(),
path: z.string().trim(),
region: z.string().trim()
})
});
export const UpdateIntegrationV1 = z.object({
params: z.object({
integrationId: z.string().trim()
}),
body: z.object({
app: z.string().trim(),
appId: z.string().trim(),
isActive: z.boolean(),
secretPath: z.string().trim().default("/"),
targetEnvironment: z.string().trim(),
owner: z.string().trim(),
environment: z.string().trim()
})
});
export const DeleteIntegrationV1 = z.object({
params: z.object({
integrationId: z.string().trim()
})
});
+142 -54
View File
@@ -1,17 +1,11 @@
import { Types } from "mongoose";
import {
IUser,
IWorkspace,
IntegrationAuth,
} from "../models";
import {
IntegrationAuthNotFoundError,
UnauthorizedRequestError,
} from "../utils/errors";
import { IUser, IWorkspace, IntegrationAuth } from "../models";
import { IntegrationAuthNotFoundError, UnauthorizedRequestError } from "../utils/errors";
import { IntegrationService } from "../services";
import { validateUserClientForWorkspace } from "./user";
import { AuthData } from "../interfaces/middleware";
import { ActorType } from "../ee/models";
import { z } from "zod";
/**
* Validate authenticated clients for integration authorization with id [integrationAuthId] based
@@ -22,53 +16,147 @@ import { ActorType } from "../ee/models";
* @param {Array<'admin' | 'member'>} obj.acceptedRoles - accepted workspace roles
* @param {String[]} obj.requiredPermissions - required permissions as part of the endpoint
*/
const validateClientForIntegrationAuth = async ({
authData,
integrationAuthId,
acceptedRoles,
attachAccessToken,
const validateClientForIntegrationAuth = async ({
authData,
integrationAuthId,
acceptedRoles,
attachAccessToken
}: {
authData: AuthData;
integrationAuthId: Types.ObjectId;
acceptedRoles: Array<"admin" | "member">;
attachAccessToken?: boolean;
authData: AuthData;
integrationAuthId: Types.ObjectId;
acceptedRoles: Array<"admin" | "member">;
attachAccessToken?: boolean;
}) => {
const integrationAuth = await IntegrationAuth.findById(integrationAuthId)
.populate<{ workspace: IWorkspace }>("workspace")
.select(
"+refreshCiphertext +refreshIV +refreshTag +accessCiphertext +accessIV +accessTag +accessExpiresAt"
);
const integrationAuth = await IntegrationAuth
.findById(integrationAuthId)
.populate<{ workspace: IWorkspace }>("workspace")
.select(
"+refreshCiphertext +refreshIV +refreshTag +accessCiphertext +accessIV +accessTag +accessExpiresAt"
);
if (!integrationAuth) throw IntegrationAuthNotFoundError();
let accessToken, accessId;
if (attachAccessToken) {
const access = (await IntegrationService.getIntegrationAuthAccess({
integrationAuthId: integrationAuth._id,
}));
accessToken = access.accessToken;
accessId = access.accessId;
}
switch (authData.actor.type) {
case ActorType.USER:
await validateUserClientForWorkspace({
user: authData.authPayload as IUser,
workspaceId: integrationAuth.workspace._id,
acceptedRoles,
});
if (!integrationAuth) throw IntegrationAuthNotFoundError();
return ({ integrationAuth, accessToken, accessId });
case ActorType.SERVICE:
throw UnauthorizedRequestError({
message: "Failed service token authorization for integration authorization",
});
}
}
let accessToken, accessId;
if (attachAccessToken) {
const access = await IntegrationService.getIntegrationAuthAccess({
integrationAuthId: integrationAuth._id
});
export {
validateClientForIntegrationAuth,
};
accessToken = access.accessToken;
accessId = access.accessId;
}
switch (authData.actor.type) {
case ActorType.USER:
await validateUserClientForWorkspace({
user: authData.authPayload as IUser,
workspaceId: integrationAuth.workspace._id,
acceptedRoles
});
return { integrationAuth, accessToken, accessId };
case ActorType.SERVICE:
throw UnauthorizedRequestError({
message: "Failed service token authorization for integration authorization"
});
}
};
export const GetIntegrationAuthV1 = z.object({
params: z.object({
integrationAuthId: z.string().trim()
})
});
export const OauthExchangeV1 = z.object({
body: z.object({
workspaceId: z.string().trim(),
code: z.string().trim(),
integration: z.string().trim(),
url: z.string().trim().url().optional(),
})
});
export const SaveIntegrationAccessTokenV1 = z.object({
body: z.object({
workspaceId: z.string().trim(),
accessId: z.string().trim().optional(),
accessToken: z.string().trim().optional(),
url: z.string().url().trim(),
namespace: z.string().trim(),
integration: z.string().trim(),
refreshToken:z.string().trim().optional()
})
});
export const GetIntegrationAuthAppsV1 = z.object({
params: z.object({
integrationAuthId: z.string().trim()
}),
query: z.object({
teamId: z.string().trim(),
workspaceSlug: z.string().trim()
})
});
export const GetIntegrationAuthTeamsV1 = z.object({
params: z.object({
integrationAuthId: z.string().trim()
})
});
export const GetIntegrationAuthVercelBranchesV1 = z.object({
params: z.object({
integrationAuthId: z.string().trim()
}),
query: z.object({
appId: z.string().trim()
})
});
export const GetIntegrationAuthRailwayEnvironmentsV1 = z.object({
params: z.object({
integrationAuthId: z.string().trim()
}),
query: z.object({
appId: z.string().trim()
})
});
export const GetIntegrationAuthRailwayServicesV1 = z.object({
params: z.object({
integrationAuthId: z.string().trim()
}),
query: z.object({
appId: z.string().trim()
})
});
export const GetIntegrationAuthBitbucketWorkspacesV1 = z.object({
params: z.object({
integrationAuthId: z.string().trim()
})
});
export const GetIntegrationAuthNorthflankSecretGroupsV1 = z.object({
params: z.object({
integrationAuthId: z.string().trim()
}),
query: z.object({
appId: z.string().trim()
})
});
export const DeleteIntegrationAuthV1 = z.object({
params: z.object({
integrationAuthId: z.string().trim()
})
});
export const GetIntegrationAuthTeamCityBuildConfigsV1 = z.object({
params:z.object({
appId:z.string().trim(),
integrationAuthId:z.string().trim()
})
})
export { validateClientForIntegrationAuth };
+20
View File
@@ -0,0 +1,20 @@
import { z } from "zod";
export const UploadKeyV1 = z.object({
params: z.object({
workspaceId: z.string().trim()
}),
body: z.object({
key: z.object({
encryptedKey: z.string().trim(),
nonce: z.string().trim(),
userId: z.string().trim()
})
})
});
export const GetLatestKeyV1 = z.object({
params: z.object({
workspaceId: z.string().trim()
})
});
+63 -39
View File
@@ -1,16 +1,12 @@
import { Types } from "mongoose";
import {
IServiceTokenData,
IUser,
Membership,
} from "../models";
import { IServiceTokenData, IUser, Membership } from "../models";
import { validateUserClientForWorkspace } from "./user";
import { validateServiceTokenDataClientForWorkspace } from "./serviceTokenData";
import {
MembershipNotFoundError,
} from "../utils/errors";
import { MembershipNotFoundError } from "../utils/errors";
import { AuthData } from "../interfaces/middleware";
import { ActorType } from "../ee/models";
import { z } from "zod";
import { ADMIN, CUSTOM, MEMBER, VIEWER } from "../variables";
/**
* Validate authenticated clients for membership with id [membershipId] based
@@ -22,36 +18,64 @@ import { ActorType } from "../ee/models";
* @returns {Membership} - validated membership
*/
export const validateClientForMembership = async ({
authData,
membershipId,
acceptedRoles,
authData,
membershipId,
acceptedRoles
}: {
authData: AuthData;
membershipId: Types.ObjectId;
acceptedRoles: Array<"admin" | "member">;
authData: AuthData;
membershipId: Types.ObjectId;
acceptedRoles: Array<"admin" | "member">;
}) => {
const membership = await Membership.findById(membershipId);
if (!membership) throw MembershipNotFoundError({
message: "Failed to find membership",
});
switch (authData.actor.type) {
case ActorType.USER:
await validateUserClientForWorkspace({
user: authData.authPayload as IUser,
workspaceId: membership.workspace,
acceptedRoles,
});
return membership;
case ActorType.SERVICE:
await validateServiceTokenDataClientForWorkspace({
serviceTokenData: authData.authPayload as IServiceTokenData,
workspaceId: new Types.ObjectId(membership.workspace),
});
return membership;
}
}
const membership = await Membership.findById(membershipId);
if (!membership)
throw MembershipNotFoundError({
message: "Failed to find membership"
});
switch (authData.actor.type) {
case ActorType.USER:
await validateUserClientForWorkspace({
user: authData.authPayload as IUser,
workspaceId: membership.workspace,
acceptedRoles
});
return membership;
case ActorType.SERVICE:
await validateServiceTokenDataClientForWorkspace({
serviceTokenData: authData.authPayload as IServiceTokenData,
workspaceId: new Types.ObjectId(membership.workspace)
});
return membership;
}
};
export const ValidateMembershipV1 = z.object({
params: z.object({
workspaceId: z.string().trim()
})
});
export const DeleteMembershipV1 = z.object({
params: z.object({
membershipId: z.string().trim()
})
});
export const ChangeMembershipRoleV1 = z.object({
body: z.object({
role: z.enum([ADMIN, VIEWER, MEMBER, CUSTOM])
}),
params: z.object({ membershipId: z.string().trim() })
});
export const DenyMembershipPermissionV1 = z.object({
params: z.object({
membershipId: z.string().trim()
}),
body: z.object({
permissions: z.object({}).array()
})
});
+8
View File
@@ -197,3 +197,11 @@ export const DeleteOrgMemberv2 = z.object({
export const GetOrgWorkspacesv2 = z.object({
params: z.object({ organizationId: z.string().trim() })
});
export const VerfiyUserToOrganizationV1 = z.object({
body: z.object({
email: z.string().trim().email(),
organizationId: z.string().trim(),
code: z.string().trim()
})
});
+53
View File
@@ -0,0 +1,53 @@
import { z } from "zod";
export const CreateSecretImportV1 = z.object({
body: z.object({
workspaceId: z.string().trim(),
environment: z.string().trim(),
folderId: z.string().trim().default("root"),
secretImport: z.object({
environment: z.string().trim(),
secretPath: z.string().trim()
})
})
});
export const UpdateSecretImportV1 = z.object({
params: z.object({
id: z.string().trim()
}),
body: z.object({
secretImports: z
.object({
environment: z.string().trim(),
secretPath: z.string().trim()
})
.array()
})
});
export const DeleteSecretImportV1 = z.object({
params: z.object({
id: z.string().trim()
}),
body: z.object({
secretImportPath: z.string().trim(),
secretImportEnv: z.string().trim()
})
});
export const GetSecretImportsV1 = z.object({
query: z.object({
workspaceId: z.string().trim(),
environment: z.string().trim(),
folderId: z.string().trim()
})
});
export const GetAllSecretsFromImportV1 = z.object({
query: z.object({
workspaceId: z.string().trim(),
environment: z.string().trim(),
folderId: z.string().trim().default("root")
})
});
+7
View File
@@ -0,0 +1,7 @@
import { z } from "zod";
export const GetSecretSnapshotV1 = z.object({
params: z.object({
secretSnapshotId: z.string().trim()
})
});
+324 -77
View File
@@ -1,18 +1,15 @@
import { Types } from "mongoose";
import {
ISecret,
IServiceTokenData,
IUser,
Secret,
} from "../models";
import { ISecret, IServiceTokenData, IUser, Secret } from "../models";
import { validateUserClientForSecret, validateUserClientForSecrets } from "./user";
import { validateServiceTokenDataClientForSecrets, validateServiceTokenDataClientForWorkspace } from "./serviceTokenData";
import {
BadRequestError,
SecretNotFoundError,
} from "../utils/errors";
validateServiceTokenDataClientForSecrets,
validateServiceTokenDataClientForWorkspace
} from "./serviceTokenData";
import { BadRequestError, SecretNotFoundError } from "../utils/errors";
import { AuthData } from "../interfaces/middleware";
import { ActorType } from "../ee/models";
import { z } from "zod";
import { SECRET_PERSONAL, SECRET_SHARED } from "../variables";
/**
* Validate authenticated clients for secrets with id [secretId] based
@@ -24,42 +21,43 @@ import { ActorType } from "../ee/models";
* @param {String[]} obj.requiredPermissions - required permissions as part of the endpoint
*/
export const validateClientForSecret = async ({
authData,
secretId,
acceptedRoles,
requiredPermissions,
authData,
secretId,
acceptedRoles,
requiredPermissions
}: {
authData: AuthData;
secretId: Types.ObjectId;
acceptedRoles: Array<"admin" | "member">;
requiredPermissions: string[];
authData: AuthData;
secretId: Types.ObjectId;
acceptedRoles: Array<"admin" | "member">;
requiredPermissions: string[];
}) => {
const secret = await Secret.findById(secretId);
const secret = await Secret.findById(secretId);
if (!secret) throw SecretNotFoundError({
message: "Failed to find secret",
if (!secret)
throw SecretNotFoundError({
message: "Failed to find secret"
});
switch (authData.actor.type) {
case ActorType.USER:
await validateUserClientForSecret({
user: authData.authPayload as IUser,
secret,
acceptedRoles,
requiredPermissions,
});
return secret;
case ActorType.SERVICE:
await validateServiceTokenDataClientForWorkspace({
serviceTokenData: authData.authPayload as IServiceTokenData,
workspaceId: secret.workspace,
environment: secret.environment,
});
return secret;
}
}
switch (authData.actor.type) {
case ActorType.USER:
await validateUserClientForSecret({
user: authData.authPayload as IUser,
secret,
acceptedRoles,
requiredPermissions
});
return secret;
case ActorType.SERVICE:
await validateServiceTokenDataClientForWorkspace({
serviceTokenData: authData.authPayload as IServiceTokenData,
workspaceId: secret.workspace,
environment: secret.environment
});
return secret;
}
};
/**
* Validate authenticated clients for secrets with ids [secretIds] based
@@ -72,43 +70,292 @@ export const validateClientForSecret = async ({
* @param {String[]} obj.requiredPermissions - required permissions as part of the endpoint
*/
export const validateClientForSecrets = async ({
authData,
secretIds,
requiredPermissions,
authData,
secretIds,
requiredPermissions
}: {
authData: AuthData;
secretIds: Types.ObjectId[];
requiredPermissions: string[];
authData: AuthData;
secretIds: Types.ObjectId[];
requiredPermissions: string[];
}) => {
let secrets: ISecret[] = [];
let secrets: ISecret[] = [];
secrets = await Secret.find({
_id: {
$in: secretIds,
},
});
secrets = await Secret.find({
_id: {
$in: secretIds
}
});
if (secrets.length != secretIds.length) {
throw BadRequestError({ message: "Failed to validate non-existent secrets" })
}
switch (authData.actor.type) {
case ActorType.USER:
await validateUserClientForSecrets({
user: authData.authPayload as IUser,
secrets,
requiredPermissions,
});
return secrets;
case ActorType.SERVICE:
await validateServiceTokenDataClientForSecrets({
serviceTokenData: authData.authPayload as IServiceTokenData,
secrets,
requiredPermissions,
});
return secrets;
}
}
if (secrets.length != secretIds.length) {
throw BadRequestError({ message: "Failed to validate non-existent secrets" });
}
switch (authData.actor.type) {
case ActorType.USER:
await validateUserClientForSecrets({
user: authData.authPayload as IUser,
secrets,
requiredPermissions
});
return secrets;
case ActorType.SERVICE:
await validateServiceTokenDataClientForSecrets({
serviceTokenData: authData.authPayload as IServiceTokenData,
secrets,
requiredPermissions
});
return secrets;
}
};
export const GetSecretVersionsV1 = z.object({
params: z.object({
secretId: z.string().trim()
}),
query: z.object({
offset: z.number(),
limit: z.number()
})
});
export const RollbackSecretVersionV1 = z.object({
params: z.object({
secretId: z.string().trim()
}),
body: z.object({
version: z.number()
})
});
export const PushSecretsV1 = z.object({
params: z.object({
workspaceId: z.string().trim()
}),
body: z.object({
secrets: z.object({}).array(),
keys: z.object({}).array(),
environment: z.string().trim(),
channel: z.string().trim()
})
});
export const PullSecretsV1 = z.object({
params: z.object({
workspaceId: z.string().trim()
}),
query: z.object({
channel: z.string().optional(),
environment: z.string().trim()
})
});
export const PullSecretsServiceTokenV1 = z.object({
params: z.object({
workspaceId: z.string().trim()
}),
query: z.object({
channel: z.string().optional(),
environment: z.string().trim()
})
});
const batchUpdateRequestV2 = z.object({
_id: z.string(),
folderId: z.string().trim().optional(),
type: z.enum(["shared", "personal"]),
secretName: z.string().trim(),
secretKeyCiphertext: z.string().trim(),
secretKeyIV: z.string().trim(),
secretKeyTag: z.string().trim(),
secretValueCiphertext: z.string().trim(),
secretValueIV: z.string().trim(),
secretValueTag: z.string().trim(),
secretCommentCiphertext: z.string().trim().optional(),
secretCommentIV: z.string().trim().optional(),
secretCommentTag: z.string().trim().optional(),
tags: z.object({
_id: z.string().trim(),
name: z.string().trim(),
slug: z.string().trim()
})
});
export const BatchSecretsV2 = z.object({
body: z.object({
workspaceId: z.string().trim(),
folderId: z.string().trim(),
environment: z.string().trim(),
secretPath: z.string().trim().optional(),
requests: z
.discriminatedUnion("method", [
z.object({
method: z.literal("POST"),
secret: batchUpdateRequestV2.omit({ _id: true })
}),
z.object({
method: z.literal("PATCH"),
secret: batchUpdateRequestV2
}),
z.object({
method: z.literal("DELETE"),
secret: z.object({ _id: z.string().trim(), secretName: z.string().trim() })
})
])
.array()
})
});
export const GetSecretsV2 = z.object({
query: z.object({
workspaceId: z.string().trim(),
environment: z.string().trim(),
tagSlugs: z.string().trim().optional(),
folderId: z.string().trim().default("root"),
secretPath: z.string().trim().optional(),
include_imports: z
.enum(["true", "false"])
.default("false")
.transform((value) => value === "true")
})
});
export const GetSecretsRawV3 = z.object({
query: z.object({
workspaceId: z.string().trim(),
environment: z.string().trim(),
secretPath: z.string().trim().default("/"),
folderId:z.string().trim().optional(),
include_imports: z
.enum(["true", "false"])
.default("false")
.transform((value) => value === "true")
})
});
export const GetSecretByNameRawV3 = z.object({
params: z.object({
secretName: z.string().trim()
}),
query: z.object({
workspaceId: z.string().trim(),
environment: z.string().trim(),
secretPath: z.string().trim().default("/"),
type: z.enum([SECRET_SHARED, SECRET_PERSONAL]).optional()
})
});
export const CreateSecretRawV3 = z.object({
body: z.object({
workspaceId: z.string().trim(),
environment: z.string().trim(),
secretPath: z.string().trim().default("/"),
secretValue: z.string().trim(),
secretComment: z.string().trim(),
type: z.enum([SECRET_SHARED, SECRET_PERSONAL])
}),
params: z.object({
secretName: z.string().trim()
})
});
export const UpdateSecretByNameRawV3 = z.object({
params: z.object({
secretName: z.string().trim()
}),
body: z.object({
workspaceId: z.string().trim(),
environment: z.string().trim(),
secretValue: z.string().trim(),
secretName: z.string().trim(),
secretPath: z.string().trim().default("/"),
type: z.enum([SECRET_SHARED, SECRET_PERSONAL]).default(SECRET_SHARED)
})
});
export const DeleteSecretByNameRawV3 = z.object({
params: z.object({
secretName: z.string().trim()
}),
body: z.object({
workspaceId: z.string().trim(),
environment: z.string().trim(),
secretPath: z.string().trim().default("/"),
type: z.enum([SECRET_SHARED, SECRET_PERSONAL]).default(SECRET_SHARED)
})
});
export const GetSecretsV3 = z.object({
query: z.object({
workspaceId: z.string().trim(),
environment: z.string().trim(),
secretPath: z.string().trim().default("/"),
folderId: z.string().trim().optional(),
include_imports: z
.enum(["true", "false"])
.default("false")
.transform((value) => value === "true")
})
});
export const GetSecretByNameV3 = z.object({
query: z.object({
workspaceId: z.string().trim(),
environment: z.string().trim(),
secretPath: z.string().trim().default("/"),
type: z.enum([SECRET_SHARED, SECRET_PERSONAL]).optional()
}),
params: z.object({
secretName: z.string().trim()
})
});
export const CreateSecretV3 = z.object({
body: z.object({
workspaceId: z.string().trim(),
environment: z.string().trim(),
type: z.enum([SECRET_SHARED, SECRET_PERSONAL]),
secretPath: z.string().trim().default("/"),
secretName: z.string().trim(),
secretKeyCiphertext: z.string().trim(),
secretKeyIV: z.string().trim(),
secretKeyTag: z.string().trim(),
secretValueCiphertext: z.string().trim(),
secretValueIV: z.string().trim(),
secretValueTag: z.string().trim(),
secretCommentCiphertext: z.string().trim().optional(),
secretCommentIV: z.string().trim().optional(),
secretCommentTag: z.string().trim().optional(),
metadata: z.object({
source: z.string()
})
})
});
export const UpdateSecretByNameV3 = z.object({
body: z.object({
workspaceId: z.string().trim(),
environment: z.string().trim(),
type: z.enum([SECRET_SHARED, SECRET_PERSONAL]),
secretPath: z.string().trim().default("/"),
secretValueCiphertext: z.string().trim(),
secretValueIV: z.string().trim(),
secretValueTag: z.string().trim()
}),
params: z.object({
secretName: z.string()
})
});
export const DeleteSecretByNameV3 = z.object({
body: z.object({
workspaceId: z.string().trim(),
environment: z.string().trim(),
type: z.enum([SECRET_SHARED, SECRET_PERSONAL]),
secretPath: z.string().trim().default("/")
}),
params: z.object({
secretName: z.string()
})
});
+32 -10
View File
@@ -1,14 +1,10 @@
import { Types } from "mongoose";
import {
ISecret,
IServiceTokenData,
IUser,
ServiceTokenData,
} from "../models";
import { ISecret, IServiceTokenData, IUser, ServiceTokenData } from "../models";
import { ServiceTokenDataNotFoundError, UnauthorizedRequestError } from "../utils/errors";
import { validateUserClientForWorkspace } from "./user";
import { ActorType } from "../ee/models";
import { AuthData } from "../interfaces/middleware";
import { z } from "zod";
/**
* Validate authenticated clients for service token with id [serviceTokenId] based
@@ -31,10 +27,11 @@ export const validateClientForServiceTokenData = async ({
.select("+encryptedKey +iv +tag")
.populate<{ user: IUser }>("user");
if (!serviceTokenData) throw ServiceTokenDataNotFoundError({
message: "Failed to find service token data"
});
if (!serviceTokenData)
throw ServiceTokenDataNotFoundError({
message: "Failed to find service token data"
});
switch (authData.actor.type) {
case ActorType.USER:
await validateUserClientForWorkspace({
@@ -140,3 +137,28 @@ export const validateServiceTokenDataClientForSecrets = async ({
});
});
};
export const CreateServiceTokenV2 = z.object({
body: z.object({
name: z.string().trim(),
workspaceId: z.string().trim(),
scopes: z
.object({
environment: z.string().trim(),
secretPath: z.string().trim()
})
.array()
.min(1),
encryptedKey: z.string().trim(),
iv: z.string().trim(),
tag: z.string().trim(),
expiresIn: z.number(),
permissions: z.enum(["read", "write"]).array()
})
});
export const DeleteServiceTokenV2 = z.object({
params: z.object({
serviceTokenDataId: z.string().trim()
})
});
+23
View File
@@ -0,0 +1,23 @@
import { z } from "zod";
export const GetWorkspaceTagsV2 = z.object({
params: z.object({
workspaceId: z.string().trim()
})
});
export const DeleteWorkspaceTagsV2 = z.object({
params: z.object({
tagId: z.string().trim()
})
});
export const CreateWorkspaceTagsV2 = z.object({
params: z.object({
workspaceId: z.string().trim()
}),
body: z.object({
name: z.string().trim(),
slug: z.string().trim()
})
});
+184 -150
View File
@@ -1,39 +1,30 @@
import fs from "fs";
import path from "path";
import { Types } from "mongoose";
import {
IOrganization,
ISecret,
IServiceAccount,
IUser,
Membership,
} from "../models";
import { IOrganization, ISecret, IServiceAccount, IUser, Membership } from "../models";
import { validateMembership } from "../helpers/membership";
import _ from "lodash";
import { BadRequestError, UnauthorizedRequestError, ValidationError } from "../utils/errors";
import {
validateMembershipOrg,
} from "../helpers/membershipOrg";
import {
PERMISSION_READ_SECRETS,
PERMISSION_WRITE_SECRETS,
} from "../variables";
import { validateMembershipOrg } from "../helpers/membershipOrg";
import { PERMISSION_READ_SECRETS, PERMISSION_WRITE_SECRETS } from "../variables";
import { AuthMethod } from "../models";
import { z } from "zod";
/**
* Validate that email [email] is not disposable
* @param email - email to validate
*/
export const validateUserEmail = (email: string) => {
const emailDomain = email.split("@")[1];
const disposableEmails = fs.readFileSync(
path.resolve(__dirname, "../data/" + "disposable_emails.txt"),
"utf8"
).split("\n");
if (disposableEmails.includes(emailDomain)) throw ValidationError({
message: "Failed to validate email as non-disposable",
});
}
const emailDomain = email.split("@")[1];
const disposableEmails = fs
.readFileSync(path.resolve(__dirname, "../data/" + "disposable_emails.txt"), "utf8")
.split("\n");
if (disposableEmails.includes(emailDomain))
throw ValidationError({
message: "Failed to validate email as non-disposable"
});
};
/**
* Validate that user (client) can access workspace
@@ -46,48 +37,53 @@ export const validateUserEmail = (email: string) => {
* @param {String[]} requiredPermissions - required permissions as part of the endpoint
*/
export const validateUserClientForWorkspace = async ({
user,
workspaceId,
environment,
acceptedRoles,
requiredPermissions,
user,
workspaceId,
environment,
acceptedRoles,
requiredPermissions
}: {
user: IUser;
workspaceId: Types.ObjectId;
environment?: string;
acceptedRoles: Array<"admin" | "member">;
requiredPermissions?: string[];
user: IUser;
workspaceId: Types.ObjectId;
environment?: string;
acceptedRoles: Array<"admin" | "member">;
requiredPermissions?: string[];
}) => {
// validate user membership in workspace
const membership = await validateMembership({
userId: user._id,
workspaceId,
acceptedRoles,
});
let runningIsDisallowed = false;
requiredPermissions?.forEach((requiredPermission: string) => {
switch (requiredPermission) {
case PERMISSION_READ_SECRETS:
runningIsDisallowed = _.some(membership.deniedPermissions, { environmentSlug: environment, ability: PERMISSION_READ_SECRETS });
break;
case PERMISSION_WRITE_SECRETS:
runningIsDisallowed = _.some(membership.deniedPermissions, { environmentSlug: environment, ability: PERMISSION_WRITE_SECRETS });
break;
default:
break;
}
if (runningIsDisallowed) {
throw UnauthorizedRequestError({
message: `Failed permissions authorization for workspace environment action : ${requiredPermission}`,
});
}
});
return membership;
}
// validate user membership in workspace
const membership = await validateMembership({
userId: user._id,
workspaceId,
acceptedRoles
});
let runningIsDisallowed = false;
requiredPermissions?.forEach((requiredPermission: string) => {
switch (requiredPermission) {
case PERMISSION_READ_SECRETS:
runningIsDisallowed = _.some(membership.deniedPermissions, {
environmentSlug: environment,
ability: PERMISSION_READ_SECRETS
});
break;
case PERMISSION_WRITE_SECRETS:
runningIsDisallowed = _.some(membership.deniedPermissions, {
environmentSlug: environment,
ability: PERMISSION_WRITE_SECRETS
});
break;
default:
break;
}
if (runningIsDisallowed) {
throw UnauthorizedRequestError({
message: `Failed permissions authorization for workspace environment action : ${requiredPermission}`
});
}
});
return membership;
};
/**
* Validate that user (client) can access secret [secret]
@@ -98,32 +94,35 @@ export const validateUserClientForWorkspace = async ({
* @param {String[]} requiredPermissions - required permissions as part of the endpoint
*/
export const validateUserClientForSecret = async ({
user,
secret,
acceptedRoles,
requiredPermissions,
user,
secret,
acceptedRoles,
requiredPermissions
}: {
user: IUser;
secret: ISecret;
acceptedRoles?: Array<"admin" | "member">;
requiredPermissions?: string[];
user: IUser;
secret: ISecret;
acceptedRoles?: Array<"admin" | "member">;
requiredPermissions?: string[];
}) => {
const membership = await validateMembership({
userId: user._id,
workspaceId: secret.workspace,
acceptedRoles,
});
if (requiredPermissions?.includes(PERMISSION_WRITE_SECRETS)) {
const isDisallowed = _.some(membership.deniedPermissions, { environmentSlug: secret.environment, ability: PERMISSION_WRITE_SECRETS });
const membership = await validateMembership({
userId: user._id,
workspaceId: secret.workspace,
acceptedRoles
});
if (isDisallowed) {
throw UnauthorizedRequestError({
message: "You do not have the required permissions to perform this action",
});
}
}
}
if (requiredPermissions?.includes(PERMISSION_WRITE_SECRETS)) {
const isDisallowed = _.some(membership.deniedPermissions, {
environmentSlug: secret.environment,
ability: PERMISSION_WRITE_SECRETS
});
if (isDisallowed) {
throw UnauthorizedRequestError({
message: "You do not have the required permissions to perform this action"
});
}
}
};
/**
* Validate that user (client) can access secrets [secrets]
@@ -134,41 +133,44 @@ export const validateUserClientForSecret = async ({
* @param {String[]} requiredPermissions - required permissions as part of the endpoint
*/
export const validateUserClientForSecrets = async ({
user,
secrets,
requiredPermissions,
user,
secrets,
requiredPermissions
}: {
user: IUser;
secrets: ISecret[];
requiredPermissions?: string[];
user: IUser;
secrets: ISecret[];
requiredPermissions?: string[];
}) => {
// TODO: add acceptedRoles?
// TODO: add acceptedRoles?
const userMemberships = await Membership.find({ user: user._id })
const userMembershipById = _.keyBy(userMemberships, "workspace");
const workspaceIdsSet = new Set(userMemberships.map((m) => m.workspace.toString()));
const userMemberships = await Membership.find({ user: user._id });
const userMembershipById = _.keyBy(userMemberships, "workspace");
const workspaceIdsSet = new Set(userMemberships.map((m) => m.workspace.toString()));
// for each secret check if the secret belongs to a workspace the user is a member of
secrets.forEach((secret: ISecret) => {
if (!workspaceIdsSet.has(secret.workspace.toString())) {
throw BadRequestError({
message: "Failed authorization for the secret",
});
}
// for each secret check if the secret belongs to a workspace the user is a member of
secrets.forEach((secret: ISecret) => {
if (!workspaceIdsSet.has(secret.workspace.toString())) {
throw BadRequestError({
message: "Failed authorization for the secret"
});
}
if (requiredPermissions?.includes(PERMISSION_WRITE_SECRETS)) {
const deniedMembershipPermissions = userMembershipById[secret.workspace.toString()].deniedPermissions;
const isDisallowed = _.some(deniedMembershipPermissions, { environmentSlug: secret.environment, ability: PERMISSION_WRITE_SECRETS });
if (requiredPermissions?.includes(PERMISSION_WRITE_SECRETS)) {
const deniedMembershipPermissions =
userMembershipById[secret.workspace.toString()].deniedPermissions;
const isDisallowed = _.some(deniedMembershipPermissions, {
environmentSlug: secret.environment,
ability: PERMISSION_WRITE_SECRETS
});
if (isDisallowed) {
throw UnauthorizedRequestError({
message: "You do not have the required permissions to perform this action",
});
}
}
});
}
if (isDisallowed) {
throw UnauthorizedRequestError({
message: "You do not have the required permissions to perform this action"
});
}
}
});
};
/**
* Validate that user (client) can access service account [serviceAccount]
@@ -179,25 +181,25 @@ export const validateUserClientForSecrets = async ({
* @param {String[]} requiredPermissions - required permissions as part of the endpoint
*/
export const validateUserClientForServiceAccount = async ({
user,
serviceAccount,
requiredPermissions,
user,
serviceAccount,
requiredPermissions
}: {
user: IUser;
serviceAccount: IServiceAccount;
requiredPermissions?: string[];
user: IUser;
serviceAccount: IServiceAccount;
requiredPermissions?: string[];
}) => {
if (!serviceAccount.user.equals(user._id)) {
// case: user who created service account is not the
// same user that is on the request
await validateMembershipOrg({
userId: user._id,
organizationId: serviceAccount.organization,
acceptedRoles: [],
acceptedStatuses: [],
});
}
}
if (!serviceAccount.user.equals(user._id)) {
// case: user who created service account is not the
// same user that is on the request
await validateMembershipOrg({
userId: user._id,
organizationId: serviceAccount.organization,
acceptedRoles: [],
acceptedStatuses: []
});
}
};
/**
* Validate that user (client) can access organization [organization]
@@ -206,22 +208,54 @@ export const validateUserClientForServiceAccount = async ({
* @param {Organization} obj.organization - organization to validate against
*/
export const validateUserClientForOrganization = async ({
user,
organization,
acceptedRoles,
acceptedStatuses,
user,
organization,
acceptedRoles,
acceptedStatuses
}: {
user: IUser;
organization: IOrganization;
acceptedRoles: Array<"owner" | "admin" | "member">;
acceptedStatuses: Array<"invited" | "accepted">;
user: IUser;
organization: IOrganization;
acceptedRoles: Array<"owner" | "admin" | "member">;
acceptedStatuses: Array<"invited" | "accepted">;
}) => {
const membershipOrg = await validateMembershipOrg({
userId: user._id,
organizationId: organization._id,
acceptedRoles,
acceptedStatuses,
});
return membershipOrg;
}
const membershipOrg = await validateMembershipOrg({
userId: user._id,
organizationId: organization._id,
acceptedRoles,
acceptedStatuses
});
return membershipOrg;
};
export const UpdateMyMfaEnabledV2 = z.object({
body: z.object({
isMfaEnabled: z.boolean()
})
});
export const UpdateNameV2 = z.object({
body: z.object({
firstName: z.string().trim(),
lastName: z.string().trim()
})
});
export const UpdateAuthMethodsV2 = z.object({
body: z.object({
authMethods: z.nativeEnum(AuthMethod).array().min(1)
})
});
export const CreateApiKeyV2 = z.object({
body: z.object({
name: z.string().trim(),
expiresIn: z.number()
})
});
export const DeleteApiKeyV2 = z.object({
params: z.object({
apiKeyDataId: z.string().trim()
})
});
+40
View File
@@ -0,0 +1,40 @@
import { z } from "zod";
export const CreateWebhookV1 = z.object({
body: z.object({
workspaceId: z.string().trim(),
environment: z.string().trim(),
webhookUrl: z.string().url().trim(),
webhookSecretKey: z.string().trim().optional(),
secretPath: z.string().trim().default("/")
})
});
export const UpdateWebhookV1 = z.object({
params: z.object({
webhookId: z.string().trim()
}),
body: z.object({
isDisabled: z.boolean().default(false)
})
});
export const TestWebhookV1 = z.object({
params: z.object({
webhookId: z.string().trim()
})
});
export const DeleteWebhookV1 = z.object({
params: z.object({
webhookId: z.string().trim()
})
});
export const ListWebhooksV1 = z.object({
query: z.object({
workspaceId: z.string().trim(),
environment: z.string().trim().optional(),
secretPath: z.string().trim().optional()
})
});
+234 -1
View File
@@ -9,6 +9,7 @@ import { BotService } from "../services";
import { AuthData } from "../interfaces/middleware";
import { extractIPDetails } from "../utils/ip";
import { z } from "zod";
import { EventType, UserAgentType } from "../ee/models";
/**
* Validate authenticated clients for workspace with id [workspaceId] based
@@ -122,9 +123,241 @@ export const validateClientForWorkspace = async ({
}
};
export const CreateWorkspacev1 = z.object({
export const GetWorkspaceSecretSnapshotsV1 = z.object({
params: z.object({
workspaceId: z.string().trim()
}),
query: z.object({
environment: z.string().trim(),
folderId: z.string().trim().default("root"),
offset: z.number(),
limit: z.number()
})
});
export const GetWorkspaceSecretSnapshotsCountV1 = z.object({
params: z.object({
workspaceId: z.string().trim()
}),
query: z.object({
environment: z.string().trim(),
folderId: z.string().trim().default("root")
})
});
export const RollbackWorkspaceSecretSnapshotV1 = z.object({
params: z.object({
workspaceId: z.string().trim()
}),
body: z.object({
environment: z.string().trim(),
folderId: z.string().trim().default("root"),
version: z.number()
})
});
export const GetWorkspaceLogsV1 = z.object({
params: z.object({
workspaceId: z.string().trim()
}),
query: z.object({
offset: z.number(),
limit: z.number(),
sortBy: z.string().trim().optional(),
userId: z.string().trim().optional(),
actionNames: z.string().trim().optional()
})
});
export const GetWorkspaceAuditLogsV1 = z.object({
params: z.object({
workspaceId: z.string().trim()
}),
query: z.object({
eventType: z.nativeEnum(EventType).nullable().optional(),
userAgentType: z.nativeEnum(UserAgentType).nullable().optional(),
startDate: z.string().datetime().nullable().optional(),
endDate: z.string().datetime().nullable().optional(),
offset: z.number(),
limit: z.number(),
actor: z.string().nullish().optional()
})
});
export const GetWorkspaceAuditLogActorFilterOptsV1 = z.object({
params: z.object({
workspaceId: z.string().trim()
})
});
export const GetWorkspaceTrustedIpsV1 = z.object({
params: z.object({
workspaceId: z.string().trim()
})
});
export const AddWorkspaceTrustedIpV1 = z.object({
params: z.object({
workspaceId: z.string().trim()
}),
body: z.object({
ipAddress: z.string().trim(),
comment: z.string().trim().default(""),
isActive: z.boolean()
})
});
export const UpdateWorkspaceTrustedIpV1 = z.object({
params: z.object({
workspaceId: z.string().trim(),
trustedIpId: z.string().trim()
}),
body: z.object({
ipAddress: z.string().trim(),
comment: z.string().trim().default("")
})
});
export const DeleteWorkspaceTrustedIpV1 = z.object({
params: z.object({
workspaceId: z.string().trim(),
trustedIpId: z.string().trim()
})
});
export const GetWorkspacePublicKeysV1 = z.object({
params: z.object({
workspaceId: z.string().trim()
})
});
export const GetWorkspaceMembershipsV1 = z.object({
params: z.object({
workspaceId: z.string().trim()
})
});
export const GetWorkspaceV1 = z.object({
params: z.object({
workspaceId: z.string().trim()
})
});
export const CreateWorkspaceV1 = z.object({
body: z.object({
workspaceName: z.string().trim(),
organizationId: z.string().trim()
})
});
export const DeleteWorkspaceV1 = z.object({
params: z.object({
workspaceId: z.string().trim()
})
});
export const ChangeWorkspaceNameV1 = z.object({
params: z.object({
workspaceId: z.string().trim()
}),
body: z.object({
name: z.string().trim()
})
});
export const InviteUserToWorkspaceV1 = z.object({
params: z.object({
workspaceId: z.string().trim()
}),
body: z.object({
email: z.string().trim()
})
});
export const GetWorkspaceIntegrationsV1 = z.object({
params: z.object({
workspaceId: z.string().trim()
})
});
export const GetWorkspaceIntegrationAuthorizationsV1 = z.object({
params: z.object({
workspaceId: z.string().trim()
})
});
export const GetWorkspaceServiceTokensV1 = z.object({
params: z.object({
workspaceId: z.string().trim()
})
});
export const GetWorkspaceServiceTokenDataV2 = z.object({
params: z.object({
workspaceId: z.string().trim()
})
});
export const GetWorkspaceKeyV2 = z.object({
params: z.object({
workspaceId: z.string().trim()
})
});
export const GetWorkspaceMembershipsV2 = z.object({
params: z.object({
workspaceId: z.string().trim()
})
});
export const UpdateWorkspaceMembershipsV2 = z.object({
params: z.object({
workspaceId: z.string().trim(),
membershipId: z.string().trim()
}),
body: z.object({
role: z.string().trim()
})
});
export const DeleteWorkspaceMembershipsV2 = z.object({
params: z.object({
workspaceId: z.string().trim(),
membershipId: z.string().trim()
})
});
export const ToggleAutoCapitalizationV2 = z.object({
params: z.object({
workspaceId: z.string().trim()
}),
body: z.object({
autoCapitalization: z.string().trim()
})
});
export const GetWorkspaceBlinkIndexStatusV3 = z.object({
params: z.object({
workspaceId: z.string().trim()
})
});
export const GetWorkspaceSecretsV3 = z.object({
params: z.object({
workspaceId: z.string().trim()
})
});
export const NameWorkspaceSecretsV3 = z.object({
params: z.object({
workspaceId: z.string().trim()
}),
body: z.object({
secretsToUpdate: z
.object({
secretName: z.string().trim(),
_id: z.string().trim()
})
.array()
})
});