feat: changed line length to 120

This commit is contained in:
Akhil Mohan
2024-01-30 22:40:10 +05:30
parent 5855cc660a
commit bcbb49ed1b
142 changed files with 1183 additions and 3706 deletions

View File

@@ -1,7 +1,7 @@
{
"singleQuote": false,
"printWidth": 100,
"printWidth": 120,
"trailingComma": "none",
"tabWidth": 2,
"semi": true
}
}

View File

@@ -1,9 +1,4 @@
import {
FastifyInstance,
RawReplyDefaultExpression,
RawRequestDefaultExpression,
RawServerDefault
} from "fastify";
import { FastifyInstance, RawReplyDefaultExpression, RawRequestDefaultExpression, RawServerDefault } from "fastify";
import { Logger } from "pino";
import { ZodTypeProvider } from "@app/server/plugins/fastify-zod";

View File

@@ -177,11 +177,7 @@ declare module "knex/types/tables" {
TUserEncryptionKeysInsert,
TUserEncryptionKeysUpdate
>;
[TableName.AuthTokens]: Knex.CompositeTableType<
TAuthTokens,
TAuthTokensInsert,
TAuthTokensUpdate
>;
[TableName.AuthTokens]: Knex.CompositeTableType<TAuthTokens, TAuthTokensInsert, TAuthTokensUpdate>;
[TableName.AuthTokenSession]: Knex.CompositeTableType<
TAuthTokenSessions,
TAuthTokenSessionsInsert,
@@ -192,32 +188,16 @@ declare module "knex/types/tables" {
TBackupPrivateKeyInsert,
TBackupPrivateKeyUpdate
>;
[TableName.Organization]: Knex.CompositeTableType<
TOrganizations,
TOrganizationsInsert,
TOrganizationsUpdate
>;
[TableName.OrgMembership]: Knex.CompositeTableType<
TOrgMemberships,
TOrgMembershipsInsert,
TOrgMembershipsUpdate
>;
[TableName.Organization]: Knex.CompositeTableType<TOrganizations, TOrganizationsInsert, TOrganizationsUpdate>;
[TableName.OrgMembership]: Knex.CompositeTableType<TOrgMemberships, TOrgMembershipsInsert, TOrgMembershipsUpdate>;
[TableName.OrgRoles]: Knex.CompositeTableType<TOrgRoles, TOrgRolesInsert, TOrgRolesUpdate>;
[TableName.IncidentContact]: Knex.CompositeTableType<
TIncidentContacts,
TIncidentContactsInsert,
TIncidentContactsUpdate
>;
[TableName.UserAction]: Knex.CompositeTableType<
TUserActions,
TUserActionsInsert,
TUserActionsUpdate
>;
[TableName.SuperAdmin]: Knex.CompositeTableType<
TSuperAdmin,
TSuperAdminInsert,
TSuperAdminUpdate
>;
[TableName.UserAction]: Knex.CompositeTableType<TUserActions, TUserActionsInsert, TUserActionsUpdate>;
[TableName.SuperAdmin]: Knex.CompositeTableType<TSuperAdmin, TSuperAdminInsert, TSuperAdminUpdate>;
[TableName.ApiKey]: Knex.CompositeTableType<TApiKeys, TApiKeysInsert, TApiKeysUpdate>;
[TableName.Project]: Knex.CompositeTableType<TProjects, TProjectsInsert, TProjectsUpdate>;
[TableName.ProjectMembership]: Knex.CompositeTableType<
@@ -230,73 +210,33 @@ declare module "knex/types/tables" {
TProjectEnvironmentsInsert,
TProjectEnvironmentsUpdate
>;
[TableName.ProjectBot]: Knex.CompositeTableType<
TProjectBots,
TProjectBotsInsert,
TProjectBotsUpdate
>;
[TableName.ProjectRoles]: Knex.CompositeTableType<
TProjectRoles,
TProjectRolesInsert,
TProjectRolesUpdate
>;
[TableName.ProjectKeys]: Knex.CompositeTableType<
TProjectKeys,
TProjectKeysInsert,
TProjectKeysUpdate
>;
[TableName.ProjectBot]: Knex.CompositeTableType<TProjectBots, TProjectBotsInsert, TProjectBotsUpdate>;
[TableName.ProjectRoles]: Knex.CompositeTableType<TProjectRoles, TProjectRolesInsert, TProjectRolesUpdate>;
[TableName.ProjectKeys]: Knex.CompositeTableType<TProjectKeys, TProjectKeysInsert, TProjectKeysUpdate>;
[TableName.Secret]: Knex.CompositeTableType<TSecrets, TSecretsInsert, TSecretsUpdate>;
[TableName.SecretBlindIndex]: Knex.CompositeTableType<
TSecretBlindIndexes,
TSecretBlindIndexesInsert,
TSecretBlindIndexesUpdate
>;
[TableName.SecretVersion]: Knex.CompositeTableType<
TSecretVersions,
TSecretVersionsInsert,
TSecretVersionsUpdate
>;
[TableName.SecretFolder]: Knex.CompositeTableType<
TSecretFolders,
TSecretFoldersInsert,
TSecretFoldersUpdate
>;
[TableName.SecretVersion]: Knex.CompositeTableType<TSecretVersions, TSecretVersionsInsert, TSecretVersionsUpdate>;
[TableName.SecretFolder]: Knex.CompositeTableType<TSecretFolders, TSecretFoldersInsert, TSecretFoldersUpdate>;
[TableName.SecretFolderVersion]: Knex.CompositeTableType<
TSecretFolderVersions,
TSecretFolderVersionsInsert,
TSecretFolderVersionsUpdate
>;
[TableName.SecretTag]: Knex.CompositeTableType<
TSecretTags,
TSecretTagsInsert,
TSecretTagsUpdate
>;
[TableName.SecretImport]: Knex.CompositeTableType<
TSecretImports,
TSecretImportsInsert,
TSecretImportsUpdate
>;
[TableName.Integration]: Knex.CompositeTableType<
TIntegrations,
TIntegrationsInsert,
TIntegrationsUpdate
>;
[TableName.SecretTag]: Knex.CompositeTableType<TSecretTags, TSecretTagsInsert, TSecretTagsUpdate>;
[TableName.SecretImport]: Knex.CompositeTableType<TSecretImports, TSecretImportsInsert, TSecretImportsUpdate>;
[TableName.Integration]: Knex.CompositeTableType<TIntegrations, TIntegrationsInsert, TIntegrationsUpdate>;
[TableName.Webhook]: Knex.CompositeTableType<TWebhooks, TWebhooksInsert, TWebhooksUpdate>;
[TableName.ServiceToken]: Knex.CompositeTableType<
TServiceTokens,
TServiceTokensInsert,
TServiceTokensUpdate
>;
[TableName.ServiceToken]: Knex.CompositeTableType<TServiceTokens, TServiceTokensInsert, TServiceTokensUpdate>;
[TableName.IntegrationAuth]: Knex.CompositeTableType<
TIntegrationAuths,
TIntegrationAuthsInsert,
TIntegrationAuthsUpdate
>;
[TableName.Identity]: Knex.CompositeTableType<
TIdentities,
TIdentitiesInsert,
TIdentitiesUpdate
>;
[TableName.Identity]: Knex.CompositeTableType<TIdentities, TIdentitiesInsert, TIdentitiesUpdate>;
[TableName.IdentityUniversalAuth]: Knex.CompositeTableType<
TIdentityUniversalAuths,
TIdentityUniversalAuthsInsert,
@@ -362,11 +302,7 @@ declare module "knex/types/tables" {
TSecretRotationOutputsInsert,
TSecretRotationOutputsUpdate
>;
[TableName.Snapshot]: Knex.CompositeTableType<
TSecretSnapshots,
TSecretSnapshotsInsert,
TSecretSnapshotsUpdate
>;
[TableName.Snapshot]: Knex.CompositeTableType<TSecretSnapshots, TSecretSnapshotsInsert, TSecretSnapshotsUpdate>;
[TableName.SnapshotSecret]: Knex.CompositeTableType<
TSecretSnapshotSecrets,
TSecretSnapshotSecretsInsert,
@@ -377,11 +313,7 @@ declare module "knex/types/tables" {
TSecretSnapshotFoldersInsert,
TSecretSnapshotFoldersUpdate
>;
[TableName.SamlConfig]: Knex.CompositeTableType<
TSamlConfigs,
TSamlConfigsInsert,
TSamlConfigsUpdate
>;
[TableName.SamlConfig]: Knex.CompositeTableType<TSamlConfigs, TSamlConfigsInsert, TSamlConfigsUpdate>;
[TableName.OrgBot]: Knex.CompositeTableType<TOrgBots, TOrgBotsInsert, TOrgBotsUpdate>;
[TableName.AuditLog]: Knex.CompositeTableType<TAuditLogs, TAuditLogsInsert, TAuditLogsUpdate>;
[TableName.GitAppInstallSession]: Knex.CompositeTableType<
@@ -395,11 +327,7 @@ declare module "knex/types/tables" {
TSecretScanningGitRisksInsert,
TSecretScanningGitRisksUpdate
>;
[TableName.TrustedIps]: Knex.CompositeTableType<
TTrustedIps,
TTrustedIpsInsert,
TTrustedIpsUpdate
>;
[TableName.TrustedIps]: Knex.CompositeTableType<TTrustedIps, TTrustedIpsInsert, TTrustedIpsUpdate>;
// Junction tables
[TableName.JnSecretTag]: Knex.CompositeTableType<
TSecretTagJunction,

View File

@@ -38,12 +38,7 @@ export async function up(knex: Knex): Promise<void> {
}
await createOnUpdateTrigger(knex, TableName.SecretVersion);
// many to many relation between tags
await createJunctionTable(
knex,
TableName.SecretVersionTag,
TableName.SecretVersion,
TableName.SecretTag
);
await createJunctionTable(knex, TableName.SecretVersionTag, TableName.SecretVersion, TableName.SecretTag);
}
export async function down(knex: Knex): Promise<void> {

View File

@@ -50,10 +50,7 @@ export async function up(knex: Knex): Promise<void> {
t.string("integration").notNullable();
t.jsonb("metadata");
t.uuid("integrationAuthId").notNullable();
t.foreign("integrationAuthId")
.references("id")
.inTable(TableName.IntegrationAuth)
.onDelete("CASCADE");
t.foreign("integrationAuthId").references("id").inTable(TableName.IntegrationAuth).onDelete("CASCADE");
t.uuid("envId").notNullable();
t.string("secretPath").defaultTo("/").notNullable();
t.foreign("envId").references("id").inTable(TableName.Environment).onDelete("CASCADE");

View File

@@ -31,10 +31,7 @@ export async function up(knex: Knex): Promise<void> {
t.boolean("isClientSecretRevoked").defaultTo(false).notNullable();
t.timestamps(true, true, true);
t.uuid("identityUAId").notNullable();
t.foreign("identityUAId")
.references("id")
.inTable(TableName.IdentityUniversalAuth)
.onDelete("CASCADE");
t.foreign("identityUAId").references("id").inTable(TableName.IdentityUniversalAuth).onDelete("CASCADE");
});
}
await createOnUpdateTrigger(knex, TableName.IdentityUniversalAuth);

View File

@@ -21,15 +21,9 @@ export async function up(knex: Knex): Promise<void> {
await knex.schema.createTable(TableName.SecretApprovalPolicyApprover, (t) => {
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
t.uuid("approverId").notNullable();
t.foreign("approverId")
.references("id")
.inTable(TableName.ProjectMembership)
.onDelete("CASCADE");
t.foreign("approverId").references("id").inTable(TableName.ProjectMembership).onDelete("CASCADE");
t.uuid("policyId").notNullable();
t.foreign("policyId")
.references("id")
.inTable(TableName.SecretApprovalPolicy)
.onDelete("CASCADE");
t.foreign("policyId").references("id").inTable(TableName.SecretApprovalPolicy).onDelete("CASCADE");
t.timestamps(true, true, true);
});
}

View File

@@ -11,23 +11,14 @@ export async function up(knex: Knex): Promise<void> {
t.boolean("hasMerged").defaultTo(false).notNullable();
t.string("status").defaultTo("open").notNullable();
t.jsonb("conflicts");
t.foreign("policyId")
.references("id")
.inTable(TableName.SecretApprovalPolicy)
.onDelete("CASCADE");
t.foreign("policyId").references("id").inTable(TableName.SecretApprovalPolicy).onDelete("CASCADE");
t.string("slug").notNullable();
t.uuid("folderId").notNullable();
t.foreign("folderId").references("id").inTable(TableName.SecretFolder).onDelete("CASCADE");
t.uuid("statusChangeBy");
t.foreign("statusChangeBy")
.references("id")
.inTable(TableName.ProjectMembership)
.onDelete("SET NULL");
t.foreign("statusChangeBy").references("id").inTable(TableName.ProjectMembership).onDelete("SET NULL");
t.uuid("committerId").notNullable();
t.foreign("committerId")
.references("id")
.inTable(TableName.ProjectMembership)
.onDelete("CASCADE");
t.foreign("committerId").references("id").inTable(TableName.ProjectMembership).onDelete("CASCADE");
t.timestamps(true, true, true);
});
}
@@ -40,10 +31,7 @@ export async function up(knex: Knex): Promise<void> {
t.foreign("member").references("id").inTable(TableName.ProjectMembership).onDelete("CASCADE");
t.string("status").notNullable();
t.uuid("requestId").notNullable();
t.foreign("requestId")
.references("id")
.inTable(TableName.SecretApprovalRequest)
.onDelete("CASCADE");
t.foreign("requestId").references("id").inTable(TableName.SecretApprovalRequest).onDelete("CASCADE");
t.timestamps(true, true, true);
});
}
@@ -73,18 +61,12 @@ export async function up(knex: Knex): Promise<void> {
t.timestamps(true, true, true);
// commit details
t.uuid("requestId").notNullable();
t.foreign("requestId")
.references("id")
.inTable(TableName.SecretApprovalRequest)
.onDelete("CASCADE");
t.foreign("requestId").references("id").inTable(TableName.SecretApprovalRequest).onDelete("CASCADE");
t.string("op").notNullable();
t.uuid("secretId");
t.foreign("secretId").references("id").inTable(TableName.Secret).onDelete("SET NULL");
t.uuid("secretVersion");
t.foreign("secretVersion")
.references("id")
.inTable(TableName.SecretVersion)
.onDelete("SET NULL");
t.foreign("secretVersion").references("id").inTable(TableName.SecretVersion).onDelete("SET NULL");
});
}
await createOnUpdateTrigger(knex, TableName.SecretApprovalRequestSecret);
@@ -93,10 +75,7 @@ export async function up(knex: Knex): Promise<void> {
await knex.schema.createTable(TableName.SecretApprovalRequestSecretTag, (t) => {
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
t.uuid("secretId").notNullable();
t.foreign("secretId")
.references("id")
.inTable(TableName.SecretApprovalRequestSecret)
.onDelete("CASCADE");
t.foreign("secretId").references("id").inTable(TableName.SecretApprovalRequestSecret).onDelete("CASCADE");
t.uuid("tagId").notNullable();
t.foreign("tagId").references("id").inTable(TableName.SecretTag).onDelete("CASCADE");
t.timestamps(true, true, true);

View File

@@ -32,10 +32,7 @@ export async function up(knex: Knex): Promise<void> {
t.uuid("secretId").notNullable();
t.foreign("secretId").references("id").inTable(TableName.Secret).onDelete("CASCADE");
t.uuid("rotationId").notNullable();
t.foreign("rotationId")
.references("id")
.inTable(TableName.SecretRotation)
.onDelete("CASCADE");
t.foreign("rotationId").references("id").inTable(TableName.SecretRotation).onDelete("CASCADE");
});
}
}

View File

@@ -25,10 +25,7 @@ export async function up(knex: Knex): Promise<void> {
t.foreign("envId").references("id").inTable(TableName.Environment).onDelete("CASCADE");
// not a relation kept like that to keep it when rolled back
t.uuid("secretVersionId").notNullable();
t.foreign("secretVersionId")
.references("id")
.inTable(TableName.SecretVersion)
.onDelete("CASCADE");
t.foreign("secretVersionId").references("id").inTable(TableName.SecretVersion).onDelete("CASCADE");
t.uuid("snapshotId").notNullable();
t.foreign("snapshotId").references("id").inTable(TableName.Snapshot).onDelete("CASCADE");
t.timestamps(true, true, true);
@@ -42,10 +39,7 @@ export async function up(knex: Knex): Promise<void> {
t.foreign("envId").references("id").inTable(TableName.Environment).onDelete("CASCADE");
// not a relation kept like that to keep it when rolled back
t.uuid("folderVersionId").notNullable();
t.foreign("folderVersionId")
.references("id")
.inTable(TableName.SecretFolderVersion)
.onDelete("CASCADE");
t.foreign("folderVersionId").references("id").inTable(TableName.SecretFolderVersion).onDelete("CASCADE");
t.uuid("snapshotId").notNullable();
t.foreign("snapshotId").references("id").inTable(TableName.Snapshot).onDelete("CASCADE");
t.timestamps(true, true, true);

View File

@@ -19,6 +19,4 @@ export const IdentityOrgMembershipsSchema = z.object({
export type TIdentityOrgMemberships = z.infer<typeof IdentityOrgMembershipsSchema>;
export type TIdentityOrgMembershipsInsert = Omit<TIdentityOrgMemberships, TImmutableDBKeys>;
export type TIdentityOrgMembershipsUpdate = Partial<
Omit<TIdentityOrgMemberships, TImmutableDBKeys>
>;
export type TIdentityOrgMembershipsUpdate = Partial<Omit<TIdentityOrgMemberships, TImmutableDBKeys>>;

View File

@@ -19,6 +19,4 @@ export const IdentityProjectMembershipsSchema = z.object({
export type TIdentityProjectMemberships = z.infer<typeof IdentityProjectMembershipsSchema>;
export type TIdentityProjectMembershipsInsert = Omit<TIdentityProjectMemberships, TImmutableDBKeys>;
export type TIdentityProjectMembershipsUpdate = Partial<
Omit<TIdentityProjectMemberships, TImmutableDBKeys>
>;
export type TIdentityProjectMembershipsUpdate = Partial<Omit<TIdentityProjectMemberships, TImmutableDBKeys>>;

View File

@@ -24,6 +24,4 @@ export const IdentityUaClientSecretsSchema = z.object({
export type TIdentityUaClientSecrets = z.infer<typeof IdentityUaClientSecretsSchema>;
export type TIdentityUaClientSecretsInsert = Omit<TIdentityUaClientSecrets, TImmutableDBKeys>;
export type TIdentityUaClientSecretsUpdate = Partial<
Omit<TIdentityUaClientSecrets, TImmutableDBKeys>
>;
export type TIdentityUaClientSecretsUpdate = Partial<Omit<TIdentityUaClientSecrets, TImmutableDBKeys>>;

View File

@@ -22,6 +22,4 @@ export const IdentityUniversalAuthsSchema = z.object({
export type TIdentityUniversalAuths = z.infer<typeof IdentityUniversalAuthsSchema>;
export type TIdentityUniversalAuthsInsert = Omit<TIdentityUniversalAuths, TImmutableDBKeys>;
export type TIdentityUniversalAuthsUpdate = Partial<
Omit<TIdentityUniversalAuths, TImmutableDBKeys>
>;
export type TIdentityUniversalAuthsUpdate = Partial<Omit<TIdentityUniversalAuths, TImmutableDBKeys>>;

View File

@@ -15,13 +15,6 @@ export const SecretApprovalPoliciesApproversSchema = z.object({
updatedAt: z.date()
});
export type TSecretApprovalPoliciesApprovers = z.infer<
typeof SecretApprovalPoliciesApproversSchema
>;
export type TSecretApprovalPoliciesApproversInsert = Omit<
TSecretApprovalPoliciesApprovers,
TImmutableDBKeys
>;
export type TSecretApprovalPoliciesApproversUpdate = Partial<
Omit<TSecretApprovalPoliciesApprovers, TImmutableDBKeys>
>;
export type TSecretApprovalPoliciesApprovers = z.infer<typeof SecretApprovalPoliciesApproversSchema>;
export type TSecretApprovalPoliciesApproversInsert = Omit<TSecretApprovalPoliciesApprovers, TImmutableDBKeys>;
export type TSecretApprovalPoliciesApproversUpdate = Partial<Omit<TSecretApprovalPoliciesApprovers, TImmutableDBKeys>>;

View File

@@ -19,6 +19,4 @@ export const SecretApprovalPoliciesSchema = z.object({
export type TSecretApprovalPolicies = z.infer<typeof SecretApprovalPoliciesSchema>;
export type TSecretApprovalPoliciesInsert = Omit<TSecretApprovalPolicies, TImmutableDBKeys>;
export type TSecretApprovalPoliciesUpdate = Partial<
Omit<TSecretApprovalPolicies, TImmutableDBKeys>
>;
export type TSecretApprovalPoliciesUpdate = Partial<Omit<TSecretApprovalPolicies, TImmutableDBKeys>>;

View File

@@ -15,13 +15,6 @@ export const SecretApprovalRequestSecretTagsSchema = z.object({
updatedAt: z.date()
});
export type TSecretApprovalRequestSecretTags = z.infer<
typeof SecretApprovalRequestSecretTagsSchema
>;
export type TSecretApprovalRequestSecretTagsInsert = Omit<
TSecretApprovalRequestSecretTags,
TImmutableDBKeys
>;
export type TSecretApprovalRequestSecretTagsUpdate = Partial<
Omit<TSecretApprovalRequestSecretTags, TImmutableDBKeys>
>;
export type TSecretApprovalRequestSecretTags = z.infer<typeof SecretApprovalRequestSecretTagsSchema>;
export type TSecretApprovalRequestSecretTagsInsert = Omit<TSecretApprovalRequestSecretTags, TImmutableDBKeys>;
export type TSecretApprovalRequestSecretTagsUpdate = Partial<Omit<TSecretApprovalRequestSecretTags, TImmutableDBKeys>>;

View File

@@ -16,13 +16,6 @@ export const SecretApprovalRequestsReviewersSchema = z.object({
updatedAt: z.date()
});
export type TSecretApprovalRequestsReviewers = z.infer<
typeof SecretApprovalRequestsReviewersSchema
>;
export type TSecretApprovalRequestsReviewersInsert = Omit<
TSecretApprovalRequestsReviewers,
TImmutableDBKeys
>;
export type TSecretApprovalRequestsReviewersUpdate = Partial<
Omit<TSecretApprovalRequestsReviewers, TImmutableDBKeys>
>;
export type TSecretApprovalRequestsReviewers = z.infer<typeof SecretApprovalRequestsReviewersSchema>;
export type TSecretApprovalRequestsReviewersInsert = Omit<TSecretApprovalRequestsReviewers, TImmutableDBKeys>;
export type TSecretApprovalRequestsReviewersUpdate = Partial<Omit<TSecretApprovalRequestsReviewers, TImmutableDBKeys>>;

View File

@@ -35,10 +35,5 @@ export const SecretApprovalRequestsSecretsSchema = z.object({
});
export type TSecretApprovalRequestsSecrets = z.infer<typeof SecretApprovalRequestsSecretsSchema>;
export type TSecretApprovalRequestsSecretsInsert = Omit<
TSecretApprovalRequestsSecrets,
TImmutableDBKeys
>;
export type TSecretApprovalRequestsSecretsUpdate = Partial<
Omit<TSecretApprovalRequestsSecrets, TImmutableDBKeys>
>;
export type TSecretApprovalRequestsSecretsInsert = Omit<TSecretApprovalRequestsSecrets, TImmutableDBKeys>;
export type TSecretApprovalRequestsSecretsUpdate = Partial<Omit<TSecretApprovalRequestsSecrets, TImmutableDBKeys>>;

View File

@@ -23,6 +23,4 @@ export const SecretApprovalRequestsSchema = z.object({
export type TSecretApprovalRequests = z.infer<typeof SecretApprovalRequestsSchema>;
export type TSecretApprovalRequestsInsert = Omit<TSecretApprovalRequests, TImmutableDBKeys>;
export type TSecretApprovalRequestsUpdate = Partial<
Omit<TSecretApprovalRequests, TImmutableDBKeys>
>;
export type TSecretApprovalRequestsUpdate = Partial<Omit<TSecretApprovalRequests, TImmutableDBKeys>>;

View File

@@ -43,6 +43,4 @@ export const SecretScanningGitRisksSchema = z.object({
export type TSecretScanningGitRisks = z.infer<typeof SecretScanningGitRisksSchema>;
export type TSecretScanningGitRisksInsert = Omit<TSecretScanningGitRisks, TImmutableDBKeys>;
export type TSecretScanningGitRisksUpdate = Partial<
Omit<TSecretScanningGitRisks, TImmutableDBKeys>
>;
export type TSecretScanningGitRisksUpdate = Partial<Omit<TSecretScanningGitRisks, TImmutableDBKeys>>;

View File

@@ -15,6 +15,4 @@ export const SecretVersionTagJunctionSchema = z.object({
export type TSecretVersionTagJunction = z.infer<typeof SecretVersionTagJunctionSchema>;
export type TSecretVersionTagJunctionInsert = Omit<TSecretVersionTagJunction, TImmutableDBKeys>;
export type TSecretVersionTagJunctionUpdate = Partial<
Omit<TSecretVersionTagJunction, TImmutableDBKeys>
>;
export type TSecretVersionTagJunctionUpdate = Partial<Omit<TSecretVersionTagJunction, TImmutableDBKeys>>;

View File

@@ -48,14 +48,12 @@ export const generateUserSrpKeys = async (password: string) => {
await new Promise((resolve) => {
client.init({ username: seedData1.email, password: seedData1.password }, () => resolve(null));
});
const { salt, verifier } = await new Promise<{ salt: string; verifier: string }>(
(resolve, reject) => {
client.createVerifier((err, res) => {
if (err) return reject(err);
return resolve(res);
});
}
);
const { salt, verifier } = await new Promise<{ salt: string; verifier: string }>((resolve, reject) => {
client.createVerifier((err, res) => {
if (err) return reject(err);
return resolve(res);
});
});
const derivedKey = await argon2.hash(password, {
salt: Buffer.from(salt),
memoryCost: 65536,

View File

@@ -45,7 +45,5 @@ export async function seed(knex: Knex): Promise<void> {
}))
)
.returning("*");
await knex(TableName.SecretFolder).insert(
envs.map(({ id }) => ({ name: "root", envId: id, parentId: null }))
);
await knex(TableName.SecretFolder).insert(envs.map(({ id }) => ({ name: "root", envId: id, parentId: null })));
}

View File

@@ -2,12 +2,7 @@ import { Knex } from "knex";
import { TableName } from "./schemas";
export const createJunctionTable = (
knex: Knex,
tableName: TableName,
table1Name: TableName,
table2Name: TableName
) =>
export const createJunctionTable = (knex: Knex, tableName: TableName, table1Name: TableName, table2Name: TableName) =>
knex.schema.createTable(tableName, (table) => {
table.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
table.uuid(`${table1Name}Id`).unsigned().notNullable(); // Foreign key for table1

View File

@@ -26,11 +26,7 @@ export const registerOrgRoleRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => {
const role = await server.services.orgRole.createRole(
req.permission.id,
req.params.organizationId,
req.body
);
const role = await server.services.orgRole.createRole(req.permission.id, req.params.organizationId, req.body);
return { role };
}
});
@@ -111,10 +107,7 @@ export const registerOrgRoleRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => {
const roles = await server.services.orgRole.listRoles(
req.permission.id,
req.params.organizationId
);
const roles = await server.services.orgRole.listRoles(req.permission.id, req.params.organizationId);
return { data: { roles } };
}
});

View File

@@ -82,9 +82,9 @@ export const registerSamlRouter = async (server: FastifyZodProvider) => {
const serverCfg = getServerCfg();
if (!profile) throw new BadRequestError({ message: "Missing profile" });
const { firstName } = profile;
const email = profile?.email ?? profile?.emailAddress as string // emailRippling is added because in Rippling the field `email` reserved
if (!email || !firstName){
const email = profile?.email ?? (profile?.emailAddress as string); // emailRippling is added because in Rippling the field `email` reserved
if (!email || !firstName) {
throw new BadRequestError({ message: "Invalid request. Missing email or first name" });
}
@@ -150,15 +150,11 @@ export const registerSamlRouter = async (server: FastifyZodProvider) => {
handler: (req, res) => {
if (req.passportUser.isUserCompleted) {
return res.redirect(
`${appCfg.SITE_URL}/login/sso?token=${encodeURIComponent(
req.passportUser.providerAuthToken
)}`
`${appCfg.SITE_URL}/login/sso?token=${encodeURIComponent(req.passportUser.providerAuthToken)}`
);
}
return res.redirect(
`${appCfg.SITE_URL}/signup/sso?token=${encodeURIComponent(
req.passportUser.providerAuthToken
)}`
`${appCfg.SITE_URL}/signup/sso?token=${encodeURIComponent(req.passportUser.providerAuthToken)}`
);
}
});

View File

@@ -117,12 +117,11 @@ export const registerSecretApprovalPolicyRouter = async (server: FastifyZodProvi
},
onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => {
const approvals =
await server.services.secretApprovalPolicy.getSecretApprovalPolicyByProjectId({
actor: req.permission.type,
actorId: req.permission.id,
projectId: req.query.workspaceId
});
const approvals = await server.services.secretApprovalPolicy.getSecretApprovalPolicyByProjectId({
actor: req.permission.type,
actorId: req.permission.id,
projectId: req.query.workspaceId
});
return { approvals };
}
});

View File

@@ -9,10 +9,7 @@ import {
SecretVersionsSchema
} from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import {
ApprovalStatus,
RequestState
} from "@app/ee/services/secret-approval-request/secret-approval-request-types";
import { ApprovalStatus, RequestState } from "@app/ee/services/secret-approval-request/secret-approval-request-types";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
@@ -41,9 +38,7 @@ export const registerSecretApprovalRequestRouter = async (server: FastifyZodProv
approvers: z.string().array(),
secretPath: z.string().optional().nullable()
}),
commits: z
.object({ op: z.string(), secretId: z.string().nullable().optional() })
.array(),
commits: z.object({ op: z.string(), secretId: z.string().nullable().optional() }).array(),
environment: z.string(),
reviewers: z.object({ member: z.string(), status: z.string() }).array(),
approvers: z.string().array()
@@ -176,8 +171,7 @@ export const registerSecretApprovalRequestRouter = async (server: FastifyZodProv
type: isClosing ? EventType.SECRET_APPROVAL_CLOSED : EventType.SECRET_APPROVAL_REOPENED,
// eslint-disable-next-line
metadata: {
[isClosing ? ("closedBy" as const) : ("reopenedBy" as const)]:
approval.statusChangeBy as string,
[isClosing ? ("closedBy" as const) : ("reopenedBy" as const)]: approval.statusChangeBy as string,
secretApprovalRequestId: approval.id,
secretApprovalRequestSlug: approval.slug
// eslint-disable-next-line

View File

@@ -62,12 +62,11 @@ export const registerSecretScanningRouter = async (server: FastifyZodProvider) =
},
onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => {
const appInstallationCompleted =
await server.services.secretScanning.getOrgInstallationStatus({
actor: req.permission.type,
actorId: req.permission.id,
orgId: req.params.organizationId
});
const appInstallationCompleted = await server.services.secretScanning.getOrgInstallationStatus({
actor: req.permission.type,
actorId: req.permission.id,
orgId: req.params.organizationId
});
return { appInstallationCompleted };
}
});

View File

@@ -22,17 +22,7 @@ export const auditLogDALFactory = (db: TDbClient) => {
const auditLogOrm = ormify(db, TableName.AuditLog);
const find = async (
{
orgId,
projectId,
userAgentType,
startDate,
endDate,
limit = 20,
offset = 0,
actor,
eventType
}: TFindQuery,
{ orgId, projectId, userAgentType, startDate, endDate, limit = 20, offset = 0, actor, eventType }: TFindQuery,
tx?: Knex
) => {
const sqlQuery = (tx || db)(TableName.AuditLog)

View File

@@ -34,10 +34,7 @@ export const auditLogServiceFactory = ({
auditLogActor
}: TListProjectAuditLogDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId);
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Read,
ProjectPermissionSub.AuditLogs
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.AuditLogs);
const auditLogs = await auditLogDAL.find({
startDate,
endDate,
@@ -48,20 +45,17 @@ export const auditLogServiceFactory = ({
actor: auditLogActor,
projectId
});
return auditLogs.map(
({ eventType: logEventType, actor: eActor, actorMetadata, eventMetadata, ...el }) => ({
...el,
event: { type: logEventType, metadata: eventMetadata },
actor: { type: eActor, metadata: actorMetadata }
})
);
return auditLogs.map(({ eventType: logEventType, actor: eActor, actorMetadata, eventMetadata, ...el }) => ({
...el,
event: { type: logEventType, metadata: eventMetadata },
actor: { type: eActor, metadata: actorMetadata }
}));
};
const createAuditLog = async (data: TCreateAuditLogDTO) => {
// add all cases in which project id or org id cannot be added
if (data.event.type !== EventType.LOGIN_IDENTITY_UNIVERSAL_AUTH) {
if (!data.projectId && !data.orgId)
throw new BadRequestError({ message: "Must either project id or org id" });
if (!data.projectId && !data.orgId) throw new BadRequestError({ message: "Must either project id or org id" });
}
return auditLogQueue.pushToLog(data);
};

View File

@@ -31,11 +31,7 @@ export const getDefaultOnPremFeatures = (): TFeatureSet => ({
secretRotation: true
});
export const setupLicenceRequestWithStore = (
baseURL: string,
refreshUrl: string,
licenseKey: string
) => {
export const setupLicenceRequestWithStore = (baseURL: string, refreshUrl: string, licenseKey: string) => {
let token: string;
const licenceReq = axios.create({
baseURL,

View File

@@ -20,6 +20,7 @@ import {
InstanceType,
TAddOrgPmtMethodDTO,
TAddOrgTaxIdDTO,
TCreateOrgPortalSession,
TDelOrgPmtMethodDTO,
TDelOrgTaxIdDTO,
TFeatureSet,
@@ -31,7 +32,6 @@ import {
TOrgPlansTableDTO,
TOrgPmtMethodsDTO,
TStartOrgTrialDTO,
TCreateOrgPortalSession,
TUpdateOrgBillingDetailsDTO
} from "./license-types";
@@ -47,11 +47,7 @@ const LICENSE_SERVER_CLOUD_LOGIN = "/api/auth/v1/license-server-login";
const LICENSE_SERVER_ON_PREM_LOGIN = "/api/auth/v1/licence-login";
const FEATURE_CACHE_KEY = (orgId: string, projectId?: string) => `${orgId}-${projectId || ""}`;
export const licenseServiceFactory = ({
orgDAL,
permissionService,
licenseDAL
}: TLicenseServiceFactoryDep) => {
export const licenseServiceFactory = ({ orgDAL, permissionService, licenseDAL }: TLicenseServiceFactoryDep) => {
let isValidLicense = false;
let instanceType = InstanceType.OnPrem;
let onPremFeatures: TFeatureSet = getDefaultOnPremFeatures();
@@ -84,9 +80,7 @@ export const licenseServiceFactory = ({
if (token) {
const {
data: { currentPlan }
} = await licenseServerOnPremApi.request.get<{ currentPlan: TFeatureSet }>(
"/api/license/v1/plan"
);
} = await licenseServerOnPremApi.request.get<{ currentPlan: TFeatureSet }>("/api/license/v1/plan");
onPremFeatures = currentPlan;
instanceType = InstanceType.EnterpriseOnPrem;
logger.info(`Instance type: ${InstanceType.EnterpriseOnPrem}`);
@@ -168,12 +162,9 @@ export const licenseServiceFactory = ({
const count = await licenseDAL.countOfOrgMembers(orgId);
if (org?.customerId) {
await licenseServerCloudApi.request.patch(
`/api/license-server/v1/customers/${org.customerId}/cloud-plan`,
{
quantity: count
}
);
await licenseServerCloudApi.request.patch(`/api/license-server/v1/customers/${org.customerId}/cloud-plan`, {
quantity: count
});
}
featureStore.del(orgId);
} else if (instanceType === InstanceType.EnterpriseOnPrem) {
@@ -184,17 +175,9 @@ export const licenseServiceFactory = ({
};
// below all are api calls
const getOrgPlansTableByBillCycle = async ({
orgId,
actor,
actorId,
billingCycle
}: TOrgPlansTableDTO) => {
const getOrgPlansTableByBillCycle = async ({ orgId, actor, actorId, billingCycle }: TOrgPlansTableDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId);
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.Billing
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing);
const { data } = await licenseServerCloudApi.request.get(
`/api/license-server/v1/cloud-products?billing-cycle=${billingCycle}`
);
@@ -203,24 +186,15 @@ export const licenseServiceFactory = ({
const getOrgPlan = async ({ orgId, actor, actorId, projectId }: TOrgPlanDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId);
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.Billing
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing);
const plan = await getPlan(orgId, projectId);
return plan;
};
const startOrgTrial = async ({ orgId, actorId, actor, success_url }: TStartOrgTrialDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId);
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Create,
OrgPermissionSubjects.Billing
);
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Edit,
OrgPermissionSubjects.Billing
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.Billing);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Billing);
const organization = await orgDAL.findOrgById(orgId);
if (!organization) {
@@ -241,14 +215,8 @@ export const licenseServiceFactory = ({
const createOrganizationPortalSession = async ({ orgId, actorId, actor }: TCreateOrgPortalSession) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId);
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Create,
OrgPermissionSubjects.Billing
);
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Edit,
OrgPermissionSubjects.Billing
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.Billing);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Billing);
const organization = await orgDAL.findOrgById(orgId);
if (!organization) {
@@ -259,7 +227,7 @@ export const licenseServiceFactory = ({
const {
data: { pmtMethods }
} = await licenseServerCloudApi.request.get(
} = await licenseServerCloudApi.request.get<{ pmtMethods: string[] }>(
`/api/license-server/v1/customers/${organization.customerId}/billing-details/payment-methods`
);
@@ -271,34 +239,30 @@ export const licenseServiceFactory = ({
} = await licenseServerCloudApi.request.post(
`/api/license-server/v1/customers/${organization.customerId}/billing-details/payment-methods`,
{
success_url: appCfg.SITE_URL + "/dashboard",
cancel_url: appCfg.SITE_URL + "/dashboard"
}
);
return { url };
} else {
// case: organization has payment method on file
// -> redirect to billing portal
const {
data: { url }
} = await licenseServerCloudApi.request.post(
`/api/license-server/v1/customers/${organization.customerId}/billing-details/billing-portal`,
{
return_url: appCfg.SITE_URL + "/dashboard"
success_url: `${appCfg.SITE_URL}/dashboard`,
cancel_url: `${appCfg.SITE_URL}/dashboard`
}
);
return { url };
}
}
// case: organization has payment method on file
// -> redirect to billing portal
const {
data: { url }
} = await licenseServerCloudApi.request.post(
`/api/license-server/v1/customers/${organization.customerId}/billing-details/billing-portal`,
{
return_url: `${appCfg.SITE_URL}/dashboard`
}
);
return { url };
};
const getOrgBillingInfo = async ({ orgId, actor, actorId }: TGetOrgBillInfoDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId);
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.Billing
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing);
const organization = await orgDAL.findOrgById(orgId);
if (!organization) {
@@ -315,10 +279,7 @@ export const licenseServiceFactory = ({
// returns org current plan feature table
const getOrgPlanTable = async ({ orgId, actor, actorId }: TGetOrgBillInfoDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId);
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.Billing
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing);
const organization = await orgDAL.findOrgById(orgId);
if (!organization) {
@@ -334,10 +295,7 @@ export const licenseServiceFactory = ({
const getOrgBillingDetails = async ({ orgId, actor, actorId }: TGetOrgBillInfoDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId);
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.Billing
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing);
const organization = await orgDAL.findOrgById(orgId);
if (!organization) {
@@ -352,18 +310,9 @@ export const licenseServiceFactory = ({
return data;
};
const updateOrgBillingDetails = async ({
actorId,
actor,
orgId,
name,
email
}: TUpdateOrgBillingDetailsDTO) => {
const updateOrgBillingDetails = async ({ actorId, actor, orgId, name, email }: TUpdateOrgBillingDetailsDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId);
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.Billing
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing);
const organization = await orgDAL.findOrgById(orgId);
if (!organization) {
@@ -383,10 +332,7 @@ export const licenseServiceFactory = ({
const getOrgPmtMethods = async ({ orgId, actor, actorId }: TOrgPmtMethodsDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId);
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.Billing
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing);
const organization = await orgDAL.findOrgById(orgId);
if (!organization) {
@@ -403,18 +349,9 @@ export const licenseServiceFactory = ({
return pmtMethods;
};
const addOrgPmtMethods = async ({
orgId,
actor,
actorId,
success_url,
cancel_url
}: TAddOrgPmtMethodDTO) => {
const addOrgPmtMethods = async ({ orgId, actor, actorId, success_url, cancel_url }: TAddOrgPmtMethodDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId);
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.Billing
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing);
const organization = await orgDAL.findOrgById(orgId);
if (!organization) {
@@ -436,10 +373,7 @@ export const licenseServiceFactory = ({
const delOrgPmtMethods = async ({ actorId, actor, orgId, pmtMethodId }: TDelOrgPmtMethodDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId);
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.Billing
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing);
const organization = await orgDAL.findOrgById(orgId);
if (!organization) {
@@ -456,10 +390,7 @@ export const licenseServiceFactory = ({
const getOrgTaxIds = async ({ orgId, actor, actorId }: TGetOrgTaxIdDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId);
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.Billing
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing);
const organization = await orgDAL.findOrgById(orgId);
if (!organization) {
@@ -477,10 +408,7 @@ export const licenseServiceFactory = ({
const addOrgTaxId = async ({ actorId, actor, orgId, type, value }: TAddOrgTaxIdDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId);
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.Billing
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing);
const organization = await orgDAL.findOrgById(orgId);
if (!organization) {
@@ -501,10 +429,7 @@ export const licenseServiceFactory = ({
const delOrgTaxId = async ({ orgId, actor, actorId, taxId }: TDelOrgTaxIdDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId);
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.Billing
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing);
const organization = await orgDAL.findOrgById(orgId);
if (!organization) {
@@ -521,10 +446,7 @@ export const licenseServiceFactory = ({
const getOrgTaxInvoices = async ({ actorId, actor, orgId }: TOrgInvoiceDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId);
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.Billing
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing);
const organization = await orgDAL.findOrgById(orgId);
if (!organization) {
@@ -535,18 +457,13 @@ export const licenseServiceFactory = ({
const {
data: { invoices }
} = await licenseServerCloudApi.request.get(
`/api/license-server/v1/customers/${organization.customerId}/invoices`
);
} = await licenseServerCloudApi.request.get(`/api/license-server/v1/customers/${organization.customerId}/invoices`);
return invoices;
};
const getOrgLicenses = async ({ orgId, actor, actorId }: TOrgLicensesDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId);
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.Billing
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Billing);
const organization = await orgDAL.findOrgById(orgId);
if (!organization) {
@@ -557,9 +474,7 @@ export const licenseServiceFactory = ({
const {
data: { licenses }
} = await licenseServerCloudApi.request.get(
`/api/license-server/v1/customers/${organization.customerId}/licenses`
);
} = await licenseServerCloudApi.request.get(`/api/license-server/v1/customers/${organization.customerId}/licenses`);
return licenses;
};

View File

@@ -9,11 +9,7 @@ export const permissionDALFactory = (db: TDbClient) => {
const getOrgPermission = async (userId: string, orgId: string) => {
try {
const membership = await db(TableName.OrgMembership)
.leftJoin(
TableName.OrgRoles,
`${TableName.OrgMembership}.roleId`,
`${TableName.OrgRoles}.id`
)
.leftJoin(TableName.OrgRoles, `${TableName.OrgMembership}.roleId`, `${TableName.OrgRoles}.id`)
.where("userId", userId)
.where(`${TableName.OrgMembership}.orgId`, orgId)
.select("permissions")
@@ -29,11 +25,7 @@ export const permissionDALFactory = (db: TDbClient) => {
const getOrgIdentityPermission = async (identityId: string, orgId: string) => {
try {
const membership = await db(TableName.IdentityOrgMembership)
.leftJoin(
TableName.OrgRoles,
`${TableName.IdentityOrgMembership}.roleId`,
`${TableName.OrgRoles}.id`
)
.leftJoin(TableName.OrgRoles, `${TableName.IdentityOrgMembership}.roleId`, `${TableName.OrgRoles}.id`)
.where("identityId", identityId)
.where(`${TableName.IdentityOrgMembership}.orgId`, orgId)
.select(selectAllTableCols(TableName.IdentityOrgMembership))
@@ -48,11 +40,7 @@ export const permissionDALFactory = (db: TDbClient) => {
const getProjectPermission = async (userId: string, projectId: string) => {
try {
const membership = await db(TableName.ProjectMembership)
.leftJoin(
TableName.ProjectRoles,
`${TableName.ProjectMembership}.roleId`,
`${TableName.ProjectRoles}.id`
)
.leftJoin(TableName.ProjectRoles, `${TableName.ProjectMembership}.roleId`, `${TableName.ProjectRoles}.id`)
.where("userId", userId)
.where(`${TableName.ProjectMembership}.projectId`, projectId)
.select(selectAllTableCols(TableName.ProjectMembership))

View File

@@ -16,12 +16,7 @@ import { TOrgRoleDALFactory } from "@app/services/org/org-role-dal";
import { TProjectRoleDALFactory } from "@app/services/project-role/project-role-dal";
import { TServiceTokenDALFactory } from "@app/services/service-token/service-token-dal";
import {
orgAdminPermissions,
orgMemberPermissions,
orgNoAccessPermissions,
OrgPermissionSet
} from "./org-permission";
import { orgAdminPermissions, orgMemberPermissions, orgNoAccessPermissions, OrgPermissionSet } from "./org-permission";
import { TPermissionDALFactory } from "./permission-dal";
import {
buildServiceTokenProjectPermission,
@@ -188,9 +183,9 @@ export const permissionServiceFactory = ({
? { permission: MongoAbility<ProjectPermissionSet, MongoQuery>; membership: undefined }
: {
permission: MongoAbility<ProjectPermissionSet, MongoQuery>;
membership: (T extends ActorType.USER
? TProjectMemberships
: TIdentityProjectMemberships) & { permissions?: unknown };
membership: (T extends ActorType.USER ? TProjectMemberships : TIdentityProjectMemberships) & {
permissions?: unknown;
};
};
const getProjectPermission = async <T extends ActorType>(
@@ -214,9 +209,7 @@ export const permissionServiceFactory = ({
};
const getProjectPermissionByRole = async (role: string, projectId: string) => {
const isCustomRole = !Object.values(ProjectMembershipRole).includes(
role as ProjectMembershipRole
);
const isCustomRole = !Object.values(ProjectMembershipRole).includes(role as ProjectMembershipRole);
if (isCustomRole) {
const projectRole = await projectRoleDAL.findOne({ slug: role, projectId });
if (!projectRole) throw new BadRequestError({ message: "Role not found" });

View File

@@ -38,10 +38,7 @@ import {
type TSamlConfigServiceFactoryDep = {
samlConfigDAL: TSamlConfigDALFactory;
userDAL: Pick<TUserDALFactory, "create" | "findUserByEmail" | "transaction" | "updateById">;
orgDAL: Pick<
TOrgDALFactory,
"createMembership" | "updateMembershipById" | "findMembership" | "findOrgById"
>;
orgDAL: Pick<TOrgDALFactory, "createMembership" | "updateMembershipById" | "findMembership" | "findOrgById">;
orgBotDAL: Pick<TOrgBotDALFactory, "findOne" | "create" | "transaction">;
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">;
licenseService: Pick<TLicenseServiceFactory, "getPlan">;
@@ -68,10 +65,7 @@ export const samlConfigServiceFactory = ({
authProvider
}: TCreateSamlCfgDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId);
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Create,
OrgPermissionSubjects.Sso
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.Sso);
const plan = await licenseService.getPlan(orgId);
if (!plan.samlSSO)
@@ -128,16 +122,8 @@ export const samlConfigServiceFactory = ({
keyEncoding: orgBot.symmetricKeyKeyEncoding as SecretKeyEncoding
});
const {
ciphertext: encryptedEntryPoint,
iv: entryPointIV,
tag: entryPointTag
} = encryptSymmetric(entryPoint, key);
const {
ciphertext: encryptedIssuer,
iv: issuerIV,
tag: issuerTag
} = encryptSymmetric(issuer, key);
const { ciphertext: encryptedEntryPoint, iv: entryPointIV, tag: entryPointTag } = encryptSymmetric(entryPoint, key);
const { ciphertext: encryptedIssuer, iv: issuerIV, tag: issuerTag } = encryptSymmetric(issuer, key);
const { ciphertext: encryptedCert, iv: certIV, tag: certTag } = encryptSymmetric(cert, key);
const samlConfig = await samlConfigDAL.create({
@@ -168,10 +154,7 @@ export const samlConfigServiceFactory = ({
authProvider
}: TUpdateSamlCfgDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId);
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Edit,
OrgPermissionSubjects.Sso
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Sso);
const plan = await licenseService.getPlan(orgId);
if (!plan.samlSSO)
throw new BadRequestError({
@@ -181,8 +164,7 @@ export const samlConfigServiceFactory = ({
const updateQuery: TSamlConfigsUpdate = { authProvider, isActive };
const orgBot = await orgBotDAL.findOne({ orgId });
if (!orgBot)
throw new BadRequestError({ message: "Org bot not found", name: "OrgBotNotFound" });
if (!orgBot) throw new BadRequestError({ message: "Org bot not found", name: "OrgBotNotFound" });
const key = infisicalSymmetricDecrypt({
ciphertext: orgBot.encryptedSymmetricKey,
iv: orgBot.symmetricKeyIV,
@@ -201,11 +183,7 @@ export const samlConfigServiceFactory = ({
updateQuery.entryPointTag = entryPointTag;
}
if (issuer) {
const {
ciphertext: encryptedIssuer,
iv: issuerIV,
tag: issuerTag
} = encryptSymmetric(issuer, key);
const { ciphertext: encryptedIssuer, iv: issuerIV, tag: issuerTag } = encryptSymmetric(issuer, key);
updateQuery.encryptedIssuer = encryptedIssuer;
updateQuery.issuerIV = issuerIV;
updateQuery.issuerTag = issuerTag;
@@ -249,15 +227,8 @@ export const samlConfigServiceFactory = ({
// when dto is type id means it's internally used
if (dto.type === "org") {
const { permission } = await permissionService.getOrgPermission(
dto.actor,
dto.actorId,
ssoConfig.orgId
);
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.Sso
);
const { permission } = await permissionService.getOrgPermission(dto.actor, dto.actorId, ssoConfig.orgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Sso);
}
const {
entryPointTag,
@@ -272,8 +243,7 @@ export const samlConfigServiceFactory = ({
} = ssoConfig;
const orgBot = await orgBotDAL.findOne({ orgId: ssoConfig.orgId });
if (!orgBot)
throw new BadRequestError({ message: "Org bot not found", name: "OrgBotNotFound" });
if (!orgBot) throw new BadRequestError({ message: "Org bot not found", name: "OrgBotNotFound" });
const key = infisicalSymmetricDecrypt({
ciphertext: orgBot.encryptedSymmetricKey,
iv: orgBot.symmetricKeyIV,
@@ -330,8 +300,7 @@ export const samlConfigServiceFactory = ({
const appCfg = getConfig();
let user = await userDAL.findUserByEmail(email);
const isSamlSignUpDisabled = !isSignupAllowed && !user;
if (isSamlSignUpDisabled)
throw new BadRequestError({ message: "User signup disabled", name: "Saml SSO login" });
if (isSamlSignUpDisabled) throw new BadRequestError({ message: "User signup disabled", name: "Saml SSO login" });
const organization = await orgDAL.findOrgById(orgId);
if (!organization) throw new BadRequestError({ message: "Org not found" });

View File

@@ -2,9 +2,7 @@ import { TDbClient } from "@app/db";
import { TableName } from "@app/db/schemas";
import { ormify } from "@app/lib/knex";
export type TSecretApprovalPolicyApproverDALFactory = ReturnType<
typeof secretApprovalPolicyApproverDALFactory
>;
export type TSecretApprovalPolicyApproverDALFactory = ReturnType<typeof secretApprovalPolicyApproverDALFactory>;
export const secretApprovalPolicyApproverDALFactory = (db: TDbClient) => {
const sapApproverOrm = ormify(db, TableName.SecretApprovalPolicyApprover);

View File

@@ -3,13 +3,7 @@ import { Knex } from "knex";
import { TDbClient } from "@app/db";
import { TableName, TSecretApprovalPolicies } from "@app/db/schemas";
import { DatabaseError } from "@app/lib/errors";
import {
buildFindFilter,
mergeOneToManyRelation,
ormify,
selectAllTableCols,
TFindFilter
} from "@app/lib/knex";
import { buildFindFilter, mergeOneToManyRelation, ormify, selectAllTableCols, TFindFilter } from "@app/lib/knex";
export type TSecretApprovalPolicyDALFactory = ReturnType<typeof secretApprovalPolicyDALFactory>;
@@ -20,11 +14,7 @@ export const secretApprovalPolicyDALFactory = (db: TDbClient) => {
tx(TableName.SecretApprovalPolicy)
// eslint-disable-next-line
.where(buildFindFilter(filter))
.join(
TableName.Environment,
`${TableName.SecretApprovalPolicy}.envId`,
`${TableName.Environment}.id`
)
.join(TableName.Environment, `${TableName.SecretApprovalPolicy}.envId`, `${TableName.Environment}.id`)
.join(
TableName.SecretApprovalPolicyApprover,
`${TableName.SecretApprovalPolicy}.id`,
@@ -60,10 +50,7 @@ export const secretApprovalPolicyDALFactory = (db: TDbClient) => {
}
};
const find = async (
filter: TFindFilter<TSecretApprovalPolicies & { projectId: string }>,
tx?: Knex
) => {
const find = async (filter: TFindFilter<TSecretApprovalPolicies & { projectId: string }>, tx?: Knex) => {
try {
const docs = await sapFindQuery(tx || db, filter);
const formatedDoc = mergeOneToManyRelation(

View File

@@ -2,10 +2,7 @@ import { ForbiddenError, subject } from "@casl/ability";
import picomatch from "picomatch";
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
import {
ProjectPermissionActions,
ProjectPermissionSub
} from "@app/ee/services/permission/project-permission";
import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
import { BadRequestError } from "@app/lib/errors";
import { containsGlobPatterns } from "@app/lib/picomatch";
import { TProjectEnvDALFactory } from "@app/services/project-env/project-env-dal";
@@ -34,9 +31,7 @@ type TSecretApprovalPolicyServiceFactoryDep = {
projectMembershipDAL: Pick<TProjectMembershipDALFactory, "find">;
};
export type TSecretApprovalPolicyServiceFactory = ReturnType<
typeof secretApprovalPolicyServiceFactory
>;
export type TSecretApprovalPolicyServiceFactory = ReturnType<typeof secretApprovalPolicyServiceFactory>;
export const secretApprovalPolicyServiceFactory = ({
secretApprovalPolicyDAL,
@@ -105,18 +100,10 @@ export const secretApprovalPolicyServiceFactory = ({
secretPolicyId
}: TUpdateSapDTO) => {
const secretApprovalPolicy = await secretApprovalPolicyDAL.findById(secretPolicyId);
if (!secretApprovalPolicy)
throw new BadRequestError({ message: "Secret approval policy not found" });
if (!secretApprovalPolicy) throw new BadRequestError({ message: "Secret approval policy not found" });
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
secretApprovalPolicy.projectId
);
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Edit,
ProjectPermissionSub.SecretApproval
);
const { permission } = await permissionService.getProjectPermission(actor, actorId, secretApprovalPolicy.projectId);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.SecretApproval);
const updatedSap = await secretApprovalPolicyDAL.transaction(async (tx) => {
const doc = await secretApprovalPolicyDAL.updateById(
@@ -162,11 +149,7 @@ export const secretApprovalPolicyServiceFactory = ({
const sapPolicy = await secretApprovalPolicyDAL.findById(secretPolicyId);
if (!sapPolicy) throw new BadRequestError({ message: "Secret approval policy not found" });
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
sapPolicy.projectId
);
const { permission } = await permissionService.getProjectPermission(actor, actorId, sapPolicy.projectId);
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Delete,
ProjectPermissionSub.SecretApproval
@@ -178,20 +161,13 @@ export const secretApprovalPolicyServiceFactory = ({
const getSecretApprovalPolicyByProjectId = async ({ actorId, actor, projectId }: TListSapDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId);
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Read,
ProjectPermissionSub.SecretApproval
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretApproval);
const sapPolicies = await secretApprovalPolicyDAL.find({ projectId });
return sapPolicies;
};
const getSecretApprovalPolicy = async (
projectId: string,
environment: string,
secretPath: string
) => {
const getSecretApprovalPolicy = async (projectId: string, environment: string, secretPath: string) => {
const env = await projectEnvDAL.findOne({ slug: environment, projectId });
if (!env) throw new BadRequestError({ message: "Environment not found" });
@@ -199,14 +175,11 @@ export const secretApprovalPolicyServiceFactory = ({
if (!policies.length) return;
// this will filter policies either without scoped to secret path or the one that matches with secret path
const policiesFilteredByPath = policies.filter(
({ secretPath: policyPath }) =>
!policyPath || picomatch.isMatch(secretPath, policyPath, { strictSlashes: false })
({ secretPath: policyPath }) => !policyPath || picomatch.isMatch(secretPath, policyPath, { strictSlashes: false })
);
// now sort by priority. exact secret path gets first match followed by glob followed by just env scoped
// if that is tie get by first createdAt
const policiesByPriority = policiesFilteredByPath.sort(
(a, b) => getPolicyScore(b) - getPolicyScore(a)
);
const policiesByPriority = policiesFilteredByPath.sort((a, b) => getPolicyScore(b) - getPolicyScore(a));
const finalPolicy = policiesByPriority.shift();
return finalPolicy;
};

View File

@@ -8,13 +8,7 @@ import {
TSecretApprovalRequestsSecrets
} from "@app/db/schemas";
import { DatabaseError } from "@app/lib/errors";
import {
ormify,
selectAllTableCols,
sqlNestRelationships,
stripUndefinedInWhere,
TFindFilter
} from "@app/lib/knex";
import { ormify, selectAllTableCols, sqlNestRelationships, stripUndefinedInWhere, TFindFilter } from "@app/lib/knex";
import { RequestState } from "./secret-approval-request-types";
@@ -36,11 +30,7 @@ export const secretApprovalRequestDALFactory = (db: TDbClient) => {
const findQuery = (filter: TFindFilter<TSecretApprovalRequests>, tx: Knex) =>
tx(TableName.SecretApprovalRequest)
.where(filter)
.join(
TableName.SecretFolder,
`${TableName.SecretApprovalRequest}.folderId`,
`${TableName.SecretFolder}.id`
)
.join(TableName.SecretFolder, `${TableName.SecretApprovalRequest}.folderId`, `${TableName.SecretFolder}.id`)
.join(TableName.Environment, `${TableName.SecretFolder}.envId`, `${TableName.Environment}.id`)
.join(
TableName.SecretApprovalPolicy,
@@ -92,8 +82,7 @@ export const secretApprovalRequestDALFactory = (db: TDbClient) => {
{
key: "reviewerMemberId",
label: "reviewers" as const,
mapper: ({ reviewerMemberId: member, reviewerStatus: status }) =>
member ? { member, status } : undefined
mapper: ({ reviewerMemberId: member, reviewerStatus: status }) => (member ? { member, status } : undefined)
},
{ key: "approverId", label: "approvers" as const, mapper: ({ approverId }) => approverId }
]
@@ -114,16 +103,8 @@ export const secretApprovalRequestDALFactory = (db: TDbClient) => {
.with(
"temp",
(tx || db)(TableName.SecretApprovalRequest)
.join(
TableName.SecretFolder,
`${TableName.SecretApprovalRequest}.folderId`,
`${TableName.SecretFolder}.id`
)
.join(
TableName.Environment,
`${TableName.SecretFolder}.envId`,
`${TableName.Environment}.id`
)
.join(TableName.SecretFolder, `${TableName.SecretApprovalRequest}.folderId`, `${TableName.SecretFolder}.id`)
.join(TableName.Environment, `${TableName.SecretFolder}.envId`, `${TableName.Environment}.id`)
.join(
TableName.SecretApprovalPolicyApprover,
`${TableName.SecretApprovalRequest}.policyId`,
@@ -147,13 +128,11 @@ export const secretApprovalRequestDALFactory = (db: TDbClient) => {
return {
open: parseInt(
(docs.find(({ status }) => status === RequestState.Open) as { count: string })?.count ||
"0",
(docs.find(({ status }) => status === RequestState.Open) as { count: string })?.count || "0",
10
),
closed: parseInt(
(docs.find(({ status }) => status === RequestState.Closed) as { count: string })?.count ||
"0",
(docs.find(({ status }) => status === RequestState.Closed) as { count: string })?.count || "0",
10
)
};
@@ -163,31 +142,15 @@ export const secretApprovalRequestDALFactory = (db: TDbClient) => {
};
const findByProjectId = async (
{
status,
limit = 20,
offset = 0,
projectId,
committer,
environment,
membershipId
}: TFindQueryFilter,
{ status, limit = 20, offset = 0, projectId, committer, environment, membershipId }: TFindQueryFilter,
tx?: Knex
) => {
try {
// akhilmhdh: If ever u wanted a 1 to so many relationship connected with pagination
// this is the place u wanna look at.
const query = (tx || db)(TableName.SecretApprovalRequest)
.join(
TableName.SecretFolder,
`${TableName.SecretApprovalRequest}.folderId`,
`${TableName.SecretFolder}.id`
)
.join(
TableName.Environment,
`${TableName.SecretFolder}.envId`,
`${TableName.Environment}.id`
)
.join(TableName.SecretFolder, `${TableName.SecretApprovalRequest}.folderId`, `${TableName.SecretFolder}.id`)
.join(TableName.Environment, `${TableName.SecretFolder}.envId`, `${TableName.Environment}.id`)
.join(
TableName.SecretApprovalPolicy,
`${TableName.SecretApprovalRequest}.policyId`,
@@ -266,8 +229,7 @@ export const secretApprovalRequestDALFactory = (db: TDbClient) => {
{
key: "reviewerMemberId",
label: "reviewers" as const,
mapper: ({ reviewerMemberId: member, reviewerStatus: s }) =>
member ? { member, status: s } : undefined
mapper: ({ reviewerMemberId: member, reviewerStatus: s }) => (member ? { member, status: s } : undefined)
},
{
key: "approverId",

View File

@@ -2,9 +2,7 @@ import { TDbClient } from "@app/db";
import { TableName } from "@app/db/schemas";
import { ormify } from "@app/lib/knex";
export type TSecretApprovalRequestReviewerDALFactory = ReturnType<
typeof secretApprovalRequestReviewerDALFactory
>;
export type TSecretApprovalRequestReviewerDALFactory = ReturnType<typeof secretApprovalRequestReviewerDALFactory>;
export const secretApprovalRequestReviewerDALFactory = (db: TDbClient) => {
const secretApprovalRequestReviewerOrm = ormify(db, TableName.SecretApprovalRequestReviewer);

View File

@@ -5,9 +5,7 @@ import { SecretApprovalRequestsSecretsSchema, TableName, TSecretTags } from "@ap
import { DatabaseError } from "@app/lib/errors";
import { ormify, selectAllTableCols, sqlNestRelationships } from "@app/lib/knex";
export type TSecretApprovalRequestSecretDALFactory = ReturnType<
typeof secretApprovalRequestSecretDALFactory
>;
export type TSecretApprovalRequestSecretDALFactory = ReturnType<typeof secretApprovalRequestSecretDALFactory>;
export const secretApprovalRequestSecretDALFactory = (db: TDbClient) => {
const secretApprovalRequestSecretOrm = ormify(db, TableName.SecretApprovalRequestSecret);
@@ -25,16 +23,8 @@ export const secretApprovalRequestSecretDALFactory = (db: TDbClient) => {
`${TableName.SecretApprovalRequestSecret}.id`,
`${TableName.SecretApprovalRequestSecretTag}.secretId`
)
.leftJoin(
TableName.SecretTag,
`${TableName.SecretApprovalRequestSecretTag}.tagId`,
`${TableName.SecretTag}.id`
)
.leftJoin(
TableName.Secret,
`${TableName.SecretApprovalRequestSecret}.secretId`,
`${TableName.Secret}.id`
)
.leftJoin(TableName.SecretTag, `${TableName.SecretApprovalRequestSecretTag}.tagId`, `${TableName.SecretTag}.id`)
.leftJoin(TableName.Secret, `${TableName.SecretApprovalRequestSecret}.secretId`, `${TableName.Secret}.id`)
.leftJoin(
TableName.SecretVersion,
`${TableName.SecretVersion}.id`,
@@ -75,37 +65,24 @@ export const secretApprovalRequestSecretDALFactory = (db: TDbClient) => {
db.ref("secretValueCiphertext").withSchema(TableName.Secret).as("orgSecValueCiphertext"),
db.ref("secretCommentIV").withSchema(TableName.Secret).as("orgSecCommentIV"),
db.ref("secretCommentTag").withSchema(TableName.Secret).as("orgSecCommentTag"),
db
.ref("secretCommentCiphertext")
.withSchema(TableName.Secret)
.as("orgSecCommentCiphertext")
db.ref("secretCommentCiphertext").withSchema(TableName.Secret).as("orgSecCommentCiphertext")
)
.select(
db.ref("version").withSchema(TableName.SecretVersion).as("secVerVersion"),
db.ref("secretKeyIV").withSchema(TableName.SecretVersion).as("secVerKeyIV"),
db.ref("secretKeyTag").withSchema(TableName.SecretVersion).as("secVerKeyTag"),
db
.ref("secretKeyCiphertext")
.withSchema(TableName.SecretVersion)
.as("secVerKeyCiphertext"),
db.ref("secretKeyCiphertext").withSchema(TableName.SecretVersion).as("secVerKeyCiphertext"),
db.ref("secretValueIV").withSchema(TableName.SecretVersion).as("secVerValueIV"),
db.ref("secretValueTag").withSchema(TableName.SecretVersion).as("secVerValueTag"),
db
.ref("secretValueCiphertext")
.withSchema(TableName.SecretVersion)
.as("secVerValueCiphertext"),
db.ref("secretValueCiphertext").withSchema(TableName.SecretVersion).as("secVerValueCiphertext"),
db.ref("secretCommentIV").withSchema(TableName.SecretVersion).as("secVerCommentIV"),
db.ref("secretCommentTag").withSchema(TableName.SecretVersion).as("secVerCommentTag"),
db
.ref("secretCommentCiphertext")
.withSchema(TableName.SecretVersion)
.as("secVerCommentCiphertext")
db.ref("secretCommentCiphertext").withSchema(TableName.SecretVersion).as("secVerCommentCiphertext")
);
const formatedDoc = sqlNestRelationships({
data: doc,
key: "id",
parentMapper: (data) =>
SecretApprovalRequestsSecretsSchema.omit({ secretVersion: true }).parse(data),
parentMapper: (data) => SecretApprovalRequestsSecretsSchema.omit({ secretVersion: true }).parse(data),
childrenMapper: [
{
key: "tagJnId",
@@ -186,12 +163,7 @@ export const secretApprovalRequestSecretDALFactory = (db: TDbClient) => {
{
key: "secVerTagId",
label: "tags" as const,
mapper: ({
secVerTagId: id,
secVerTagName: name,
secVerTagSlug: slug,
secVerTagColor: color
}) => ({
mapper: ({ secVerTagId: id, secVerTagName: name, secVerTagSlug: slug, secVerTagColor: color }) => ({
// eslint-disable-next-line
id,
// eslint-disable-next-line

View File

@@ -42,10 +42,7 @@ type TSecretApprovalRequestServiceFactoryDep = {
secretApprovalRequestDAL: TSecretApprovalRequestDALFactory;
secretApprovalRequestSecretDAL: TSecretApprovalRequestSecretDALFactory;
secretApprovalRequestReviewerDAL: TSecretApprovalRequestReviewerDALFactory;
folderDAL: Pick<
TSecretFolderDALFactory,
"findBySecretPath" | "findById" | "findSecretPathByFolderIds"
>;
folderDAL: Pick<TSecretFolderDALFactory, "findBySecretPath" | "findById" | "findSecretPathByFolderIds">;
secretTagDAL: Pick<TSecretTagDALFactory, "findManyTagsById">;
secretBlindIndexDAL: Pick<TSecretBlindIndexDALFactory, "findOne">;
snapshotService: Pick<TSecretSnapshotServiceFactory, "performSnapshot">;
@@ -61,9 +58,7 @@ type TSecretApprovalRequestServiceFactoryDep = {
secretQueueService: Pick<TSecretQueueFactory, "syncSecrets">;
};
export type TSecretApprovalRequestServiceFactory = ReturnType<
typeof secretApprovalRequestServiceFactory
>;
export type TSecretApprovalRequestServiceFactory = ReturnType<typeof secretApprovalRequestServiceFactory>;
export const secretApprovalRequestServiceFactory = ({
secretApprovalRequestDAL,
@@ -79,14 +74,9 @@ export const secretApprovalRequestServiceFactory = ({
secretQueueService
}: TSecretApprovalRequestServiceFactoryDep) => {
const requestCount = async ({ projectId, actor, actorId }: TApprovalRequestCountDTO) => {
if (actor === ActorType.SERVICE)
throw new BadRequestError({ message: "Cannot use service token" });
if (actor === ActorType.SERVICE) throw new BadRequestError({ message: "Cannot use service token" });
const { membership } = await permissionService.getProjectPermission(
actor as ActorType.USER,
actorId,
projectId
);
const { membership } = await permissionService.getProjectPermission(actor as ActorType.USER, actorId, projectId);
const count = await secretApprovalRequestDAL.findProjectRequestCount(projectId, membership.id);
return count;
@@ -102,8 +92,7 @@ export const secretApprovalRequestServiceFactory = ({
limit,
offset
}: TListApprovalsDTO) => {
if (actor === ActorType.SERVICE)
throw new BadRequestError({ message: "Cannot use service token" });
if (actor === ActorType.SERVICE) throw new BadRequestError({ message: "Cannot use service token" });
const { membership } = await permissionService.getProjectPermission(actor, actorId, projectId);
const approvals = await secretApprovalRequestDAL.findByProjectId({
@@ -119,12 +108,10 @@ export const secretApprovalRequestServiceFactory = ({
};
const getSecretApprovalDetails = async ({ actor, actorId, id }: TSecretApprovalDetailsDTO) => {
if (actor === ActorType.SERVICE)
throw new BadRequestError({ message: "Cannot use service token" });
if (actor === ActorType.SERVICE) throw new BadRequestError({ message: "Cannot use service token" });
const secretApprovalRequest = await secretApprovalRequestDAL.findById(id);
if (!secretApprovalRequest)
throw new BadRequestError({ message: "Secret approval request not found" });
if (!secretApprovalRequest) throw new BadRequestError({ message: "Secret approval request not found" });
const { policy } = secretApprovalRequest;
const { membership } = await permissionService.getProjectPermission(
@@ -149,8 +136,7 @@ export const secretApprovalRequestServiceFactory = ({
const reviewApproval = async ({ approvalId, actor, status, actorId }: TReviewRequestDTO) => {
const secretApprovalRequest = await secretApprovalRequestDAL.findById(approvalId);
if (!secretApprovalRequest)
throw new BadRequestError({ message: "Secret approval request not found" });
if (!secretApprovalRequest) throw new BadRequestError({ message: "Secret approval request not found" });
if (actor !== ActorType.USER) throw new BadRequestError({ message: "Must be a user" });
const { policy } = secretApprovalRequest;
@@ -191,8 +177,7 @@ export const secretApprovalRequestServiceFactory = ({
const updateApprovalStatus = async ({ actorId, status, approvalId, actor }: TStatusChangeDTO) => {
const secretApprovalRequest = await secretApprovalRequestDAL.findById(approvalId);
if (!secretApprovalRequest)
throw new BadRequestError({ message: "Secret approval request not found" });
if (!secretApprovalRequest) throw new BadRequestError({ message: "Secret approval request not found" });
if (actor !== ActorType.USER) throw new BadRequestError({ message: "Must be a user" });
const { policy } = secretApprovalRequest;
@@ -209,8 +194,7 @@ export const secretApprovalRequestServiceFactory = ({
throw new UnauthorizedError({ message: "User has no access" });
}
if (secretApprovalRequest.hasMerged)
throw new BadRequestError({ message: "Approval request has been merged" });
if (secretApprovalRequest.hasMerged) throw new BadRequestError({ message: "Approval request has been merged" });
if (secretApprovalRequest.status === RequestState.Closed && status === RequestState.Closed)
throw new BadRequestError({ message: "Approval request is already closed" });
if (secretApprovalRequest.status === RequestState.Open && status === RequestState.Open)
@@ -223,22 +207,13 @@ export const secretApprovalRequestServiceFactory = ({
return { ...secretApprovalRequest, ...updatedRequest };
};
const mergeSecretApprovalRequest = async ({
approvalId,
actor,
actorId
}: TMergeSecretApprovalRequestDTO) => {
const mergeSecretApprovalRequest = async ({ approvalId, actor, actorId }: TMergeSecretApprovalRequestDTO) => {
const secretApprovalRequest = await secretApprovalRequestDAL.findById(approvalId);
if (!secretApprovalRequest)
throw new BadRequestError({ message: "Secret approval request not found" });
if (!secretApprovalRequest) throw new BadRequestError({ message: "Secret approval request not found" });
if (actor !== ActorType.USER) throw new BadRequestError({ message: "Must be a user" });
const { policy, folderId, projectId } = secretApprovalRequest;
const { membership } = await permissionService.getProjectPermission(
ActorType.USER,
actorId,
projectId
);
const { membership } = await permissionService.getProjectPermission(ActorType.USER, actorId, projectId);
if (
membership.role !== ProjectMembershipRole.Admin &&
secretApprovalRequest.committerId !== membership.id &&
@@ -256,28 +231,24 @@ export const secretApprovalRequestServiceFactory = ({
(approverId) => reviewers[approverId.toString()] === ApprovalStatus.APPROVED
).length;
if (!hasMinApproval)
throw new BadRequestError({ message: "Doesn't have minimum approvals needed" });
const secretApprovalSecrets = await secretApprovalRequestSecretDAL.findByRequestId(
secretApprovalRequest.id
);
if (!hasMinApproval) throw new BadRequestError({ message: "Doesn't have minimum approvals needed" });
const secretApprovalSecrets = await secretApprovalRequestSecretDAL.findByRequestId(secretApprovalRequest.id);
if (!secretApprovalSecrets) throw new BadRequestError({ message: "No secrets found" });
const conflicts: Array<{ secretId: string; op: CommitType }> = [];
let secretCreationCommits = secretApprovalSecrets.filter(({ op }) => op === CommitType.Create);
if (secretCreationCommits.length) {
const { secsGroupedByBlindIndex: conflictGroupByBlindIndex } =
await secretService.fnSecretBlindIndexCheckV2({
folderId,
inputSecrets: secretCreationCommits.map(({ secretBlindIndex }) => {
if (!secretBlindIndex) {
throw new BadRequestError({
message: "Missing secret blind index"
});
}
return { secretBlindIndex };
})
});
const { secsGroupedByBlindIndex: conflictGroupByBlindIndex } = await secretService.fnSecretBlindIndexCheckV2({
folderId,
inputSecrets: secretCreationCommits.map(({ secretBlindIndex }) => {
if (!secretBlindIndex) {
throw new BadRequestError({
message: "Missing secret blind index"
});
}
return { secretBlindIndex };
})
});
secretCreationCommits
.filter(({ secretBlindIndex }) => conflictGroupByBlindIndex[secretBlindIndex || ""])
.forEach((el) => {
@@ -290,23 +261,19 @@ export const secretApprovalRequestServiceFactory = ({
let secretUpdationCommits = secretApprovalSecrets.filter(({ op }) => op === CommitType.Update);
if (secretUpdationCommits.length) {
const { secsGroupedByBlindIndex: conflictGroupByBlindIndex } =
await secretService.fnSecretBlindIndexCheckV2({
folderId,
inputSecrets: secretUpdationCommits
.filter(
({ secretBlindIndex, secret }) =>
secret && secret.secretBlindIndex !== secretBlindIndex
)
.map(({ secretBlindIndex }) => {
if (!secretBlindIndex) {
throw new BadRequestError({
message: "Missing secret blind index"
});
}
return { secretBlindIndex };
})
});
const { secsGroupedByBlindIndex: conflictGroupByBlindIndex } = await secretService.fnSecretBlindIndexCheckV2({
folderId,
inputSecrets: secretUpdationCommits
.filter(({ secretBlindIndex, secret }) => secret && secret.secretBlindIndex !== secretBlindIndex)
.map(({ secretBlindIndex }) => {
if (!secretBlindIndex) {
throw new BadRequestError({
message: "Missing secret blind index"
});
}
return { secretBlindIndex };
})
});
secretUpdationCommits
.filter(
({ secretBlindIndex, secretId }) =>
@@ -318,14 +285,11 @@ export const secretApprovalRequestServiceFactory = ({
secretUpdationCommits = secretUpdationCommits.filter(
({ secretBlindIndex, secretId }) =>
Boolean(secretId) &&
(secretBlindIndex ? !conflictGroupByBlindIndex[secretBlindIndex] : true)
Boolean(secretId) && (secretBlindIndex ? !conflictGroupByBlindIndex[secretBlindIndex] : true)
);
}
const secretDeletionCommits = secretApprovalSecrets.filter(
({ op }) => op === CommitType.Delete
);
const secretDeletionCommits = secretApprovalSecrets.filter(({ op }) => op === CommitType.Delete);
const mergeStatus = await secretApprovalRequestDAL.transaction(async (tx) => {
const newSecrets = secretCreationCommits.length
@@ -442,27 +406,20 @@ export const secretApprovalRequestServiceFactory = ({
secretPath,
environment
}: TGenerateSecretApprovalRequestDTO) => {
if (actor === ActorType.SERVICE)
throw new BadRequestError({ message: "Cannot use service token" });
if (actor === ActorType.SERVICE) throw new BadRequestError({ message: "Cannot use service token" });
const { permission, membership } = await permissionService.getProjectPermission(
actor,
actorId,
projectId
);
const { permission, membership } = await permissionService.getProjectPermission(actor, actorId, projectId);
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Read,
subject(ProjectPermissionSub.Secrets, { environment, secretPath })
);
const folder = await folderDAL.findBySecretPath(projectId, environment, secretPath);
if (!folder)
throw new BadRequestError({ message: "Folder not found", name: "GenSecretApproval" });
if (!folder) throw new BadRequestError({ message: "Folder not found", name: "GenSecretApproval" });
const folderId = folder.id;
const blindIndexCfg = await secretBlindIndexDAL.findOne({ projectId });
if (!blindIndexCfg)
throw new BadRequestError({ message: "Blind index not found", name: "Update secret" });
if (!blindIndexCfg) throw new BadRequestError({ message: "Blind index not found", name: "Update secret" });
const commits: Omit<TSecretApprovalRequestsSecretsInsert, "requestId">[] = [];
const commitTagIds: Record<string, string[]> = {};
@@ -496,38 +453,28 @@ export const secretApprovalRequestServiceFactory = ({
// get all blind index
// Find all those secrets
// if not throw not found
const { keyName2BlindIndex, secrets: secretsToBeUpdated } =
await secretService.fnSecretBlindIndexCheck({
inputSecrets: updatedSecrets,
folderId,
isNew: false,
blindIndexCfg
});
const { keyName2BlindIndex, secrets: secretsToBeUpdated } = await secretService.fnSecretBlindIndexCheck({
inputSecrets: updatedSecrets,
folderId,
isNew: false,
blindIndexCfg
});
// now find any secret that needs to update its name
// same process as above
const nameUpdatedSecrets = updatedSecrets.filter(({ newSecretName }) =>
Boolean(newSecretName)
);
const { keyName2BlindIndex: newKeyName2BlindIndex } =
await secretService.fnSecretBlindIndexCheck({
inputSecrets: nameUpdatedSecrets,
folderId,
isNew: true,
blindIndexCfg
});
const nameUpdatedSecrets = updatedSecrets.filter(({ newSecretName }) => Boolean(newSecretName));
const { keyName2BlindIndex: newKeyName2BlindIndex } = await secretService.fnSecretBlindIndexCheck({
inputSecrets: nameUpdatedSecrets,
folderId,
isNew: true,
blindIndexCfg
});
const secsGroupedByBlindIndex = groupBy(
secretsToBeUpdated,
(el) => el.secretBlindIndex as string
);
const secsGroupedByBlindIndex = groupBy(secretsToBeUpdated, (el) => el.secretBlindIndex as string);
const updatedSecretIds = updatedSecrets.map(
(el) => secsGroupedByBlindIndex[keyName2BlindIndex[el.secretName]][0].id
);
const latestSecretVersions = await secretVersionDAL.findLatestVersionMany(
folderId,
updatedSecretIds
);
const latestSecretVersions = await secretVersionDAL.findLatestVersionMany(folderId, updatedSecretIds);
commits.push(
...updatedSecrets.map(({ newSecretName, secretName, tagIds, ...el }) => {
const secretId = secsGroupedByBlindIndex[keyName2BlindIndex[secretName]][0].id;
@@ -562,17 +509,13 @@ export const secretApprovalRequestServiceFactory = ({
blindIndexCfg
});
const secretsGroupedByBlindIndex = groupBy(secrets, (i) => {
if (!i.secretBlindIndex)
throw new BadRequestError({ message: "Missing secret blind index" });
if (!i.secretBlindIndex) throw new BadRequestError({ message: "Missing secret blind index" });
return i.secretBlindIndex;
});
const deletedSecretIds = deletedSecrets.map(
(el) => secretsGroupedByBlindIndex[keyName2BlindIndex[el.secretName]][0].id
);
const latestSecretVersions = await secretVersionDAL.findLatestVersionMany(
folderId,
deletedSecretIds
);
const latestSecretVersions = await secretVersionDAL.findLatestVersionMany(folderId, deletedSecretIds);
commits.push(
...deletedSecrets.map((el) => {
const secretId = secretsGroupedByBlindIndex[keyName2BlindIndex[el.secretName]][0].id;

View File

@@ -1,8 +1,4 @@
import {
TImmutableDBKeys,
TSecretApprovalPolicies,
TSecretApprovalRequestsSecrets
} from "@app/db/schemas";
import { TImmutableDBKeys, TSecretApprovalPolicies, TSecretApprovalRequestsSecrets } from "@app/db/schemas";
import { TProjectPermission } from "@app/lib/types";
export enum CommitType {
@@ -24,14 +20,7 @@ export enum ApprovalStatus {
type TApprovalCreateSecret = Omit<
TSecretApprovalRequestsSecrets,
| TImmutableDBKeys
| "version"
| "algorithm"
| "keyEncoding"
| "requestId"
| "op"
| "secretVersion"
| "secretBlindIndex"
TImmutableDBKeys | "version" | "algorithm" | "keyEncoding" | "requestId" | "op" | "secretVersion" | "secretBlindIndex"
> & {
secretName: string;
tagIds?: string[];

View File

@@ -14,21 +14,13 @@ export const secretRotationDALFactory = (db: TDbClient) => {
const findQuery = (filter: TFindFilter<TSecretRotations & { projectId: string }>, tx: Knex) =>
tx(TableName.SecretRotation)
.where(filter)
.join(
TableName.Environment,
`${TableName.SecretRotation}.envId`,
`${TableName.Environment}.id`
)
.join(TableName.Environment, `${TableName.SecretRotation}.envId`, `${TableName.Environment}.id`)
.leftJoin(
TableName.SecretRotationOutput,
`${TableName.SecretRotation}.id`,
`${TableName.SecretRotationOutput}.rotationId`
)
.join(
TableName.Secret,
`${TableName.SecretRotationOutput}.secretId`,
`${TableName.Secret}.id`
)
.join(TableName.Secret, `${TableName.SecretRotationOutput}.secretId`, `${TableName.Secret}.id`)
.select(selectAllTableCols(TableName.SecretRotation))
.select(tx.ref("name").withSchema(TableName.Environment).as("envName"))
.select(tx.ref("slug").withSchema(TableName.Environment).as("envSlug"))
@@ -102,11 +94,7 @@ export const secretRotationDALFactory = (db: TDbClient) => {
const findById = async (id: string, tx?: Knex) => {
try {
const doc = await (tx || db)(TableName.SecretRotation)
.join(
TableName.Environment,
`${TableName.SecretRotation}.envId`,
`${TableName.Environment}.id`
)
.join(TableName.Environment, `${TableName.SecretRotation}.envId`, `${TableName.Environment}.id`)
.where({ [`${TableName.SecretRotation}.id` as "id"]: id })
.select(selectAllTableCols(TableName.SecretRotation))
.select(
@@ -125,8 +113,7 @@ export const secretRotationDALFactory = (db: TDbClient) => {
}
};
const findRotationOutputsByRotationId = async (rotationId: string) =>
secretRotationOutputOrm.find({ rotationId });
const findRotationOutputsByRotationId = async (rotationId: string) => secretRotationOutputOrm.find({ rotationId });
return {
...secretRotationOrm,

View File

@@ -11,12 +11,7 @@ import knex from "knex";
import { getConfig } from "@app/lib/config/env";
import { alphaNumericNanoId } from "@app/lib/nanoid";
import {
TAssignOp,
TDbProviderClients,
TDirectAssignOp,
THttpProviderFunction
} from "../templates/types";
import { TAssignOp, TDbProviderClients, TDirectAssignOp, THttpProviderFunction } from "../templates/types";
import { TSecretRotationData, TSecretRotationDbFn } from "./secret-rotation-queue-types";
const REGEX = /\${([^}]+)}/g;
@@ -64,10 +59,7 @@ const getInterpolationValue = (variables: TSecretRotationData) => (key: string)
return variables[type as keyof TSecretRotationData][keyName];
};
export const secretRotationHttpFn = async (
func: THttpProviderFunction,
variables: TSecretRotationData
) => {
export const secretRotationHttpFn = async (func: THttpProviderFunction, variables: TSecretRotationData) => {
// string interpolation
const headers = interpolate(func.header, getInterpolationValue(variables));
const url = interpolate(func.url, getInterpolationValue(variables));
@@ -117,10 +109,7 @@ export const secretRotationDbFn = async ({
return data;
};
export const secretRotationPreSetFn = (
op: Record<string, TDirectAssignOp>,
variables: TSecretRotationData
) => {
export const secretRotationPreSetFn = (op: Record<string, TDirectAssignOp>, variables: TSecretRotationData) => {
const getValFn = getInterpolationValue(variables);
Object.entries(op || {}).forEach(([key, assignFn]) => {
const [type, keyName] = key.split(".") as [keyof TSecretRotationData, string];
@@ -128,10 +117,7 @@ export const secretRotationPreSetFn = (
});
};
export const secretRotationHttpSetFn = async (
func: THttpProviderFunction,
variables: TSecretRotationData
) => {
export const secretRotationHttpSetFn = async (func: THttpProviderFunction, variables: TSecretRotationData) => {
const getValFn = getInterpolationValue(variables);
// http setter
const res = await secretRotationHttpFn(func, variables);
@@ -145,10 +131,7 @@ export const secretRotationHttpSetFn = async (
});
};
export const getDbSetQuery = (
db: TDbProviderClients,
variables: { username: string; password: string }
) => {
export const getDbSetQuery = (db: TDbProviderClients, variables: { username: string; password: string }) => {
if (db === TDbProviderClients.Pg) {
return {
query: `ALTER USER ?? WITH PASSWORD '${variables.password}'`,

View File

@@ -18,11 +18,7 @@ import { PostHogEventTypes } from "@app/services/telemetry/telemetry-types";
import { TSecretRotationDALFactory } from "../secret-rotation-dal";
import { rotationTemplates } from "../templates";
import {
TDbProviderClients,
TProviderFunctionTypes,
TSecretRotationProviderTemplate
} from "../templates/types";
import { TDbProviderClients, TProviderFunctionTypes, TSecretRotationProviderTemplate } from "../templates/types";
import {
getDbSetQuery,
secretRotationDbFn,
@@ -30,11 +26,7 @@ import {
secretRotationHttpSetFn,
secretRotationPreSetFn
} from "./secret-rotation-queue-fn";
import {
TSecretRotationData,
TSecretRotationDbFn,
TSecretRotationEncData
} from "./secret-rotation-queue-types";
import { TSecretRotationData, TSecretRotationDbFn, TSecretRotationEncData } from "./secret-rotation-queue-types";
export type TSecretRotationQueueFactory = ReturnType<typeof secretRotationQueueFactory>;
@@ -78,10 +70,7 @@ export const secretRotationQueueFactory = ({
jobId: rotationId,
repeat: {
// on prod it this will be in days, in development this will be second
every:
appCfg.NODE_ENV === "development"
? secondsToMillis(interval)
: daysToMillisecond(interval),
every: appCfg.NODE_ENV === "development" ? secondsToMillis(interval) : daysToMillisecond(interval),
immediately: true
}
}
@@ -95,10 +84,7 @@ export const secretRotationQueueFactory = ({
QueueJobs.SecretRotation,
{
// on prod it this will be in days, in development this will be second
every:
appCfg.NODE_ENV === "development"
? secondsToMillis(interval)
: daysToMillisecond(interval)
every: appCfg.NODE_ENV === "development" ? secondsToMillis(interval) : daysToMillisecond(interval)
},
rotationId
);
@@ -108,22 +94,16 @@ export const secretRotationQueueFactory = ({
const { rotationId } = job.data;
logger.info(`secretRotationQueue.process: [rotationDocument=${rotationId}]`);
const secretRotation = await secretRotationDAL.findById(rotationId);
const rotationProvider = rotationTemplates.find(
({ name }) => name === secretRotation?.provider
);
const rotationProvider = rotationTemplates.find(({ name }) => name === secretRotation?.provider);
try {
if (!rotationProvider || !secretRotation)
throw new DisableRotationErrors({ message: "Provider not found" });
if (!rotationProvider || !secretRotation) throw new DisableRotationErrors({ message: "Provider not found" });
const rotationOutputs = await secretRotationDAL.findRotationOutputsByRotationId(rotationId);
if (!rotationOutputs.length)
throw new DisableRotationErrors({ message: "Secrets not found" });
if (!rotationOutputs.length) throw new DisableRotationErrors({ message: "Secrets not found" });
// deep copy
const provider = JSON.parse(
JSON.stringify(rotationProvider)
) as TSecretRotationProviderTemplate;
const provider = JSON.parse(JSON.stringify(rotationProvider)) as TSecretRotationProviderTemplate;
// now get the encrypted variable values
// in includes the inputs, the previous outputs
@@ -156,20 +136,11 @@ export const secretRotationQueueFactory = ({
? variables.inputs.username2
: variables.inputs.username1;
} else {
newCredential.internal.username = lastCred
? lastCred.internal.username
: variables.inputs.username1;
newCredential.internal.username = lastCred ? lastCred.internal.username : variables.inputs.username1;
}
// set a random value for new password
newCredential.internal.rotated_password = alphaNumericNanoId(32);
const {
admin_username: username,
admin_password: password,
host,
database,
port,
ca
} = newCredential.inputs;
const { admin_username: username, admin_password: password, host, database, port, ca } = newCredential.inputs;
const dbFunctionArg = {
username,
password,
@@ -177,10 +148,7 @@ export const secretRotationQueueFactory = ({
database,
port,
ca: ca as string,
client:
provider.template.client === TDbProviderClients.MySql
? "mysql2"
: provider.template.client
client: provider.template.client === TDbProviderClients.MySql ? "mysql2" : provider.template.client
} as TSecretRotationDbFn;
// set function
await secretRotationDbFn({

View File

@@ -47,10 +47,7 @@ export const secretRotationServiceFactory = ({
}: TSecretRotationServiceFactoryDep) => {
const getProviderTemplates = async ({ actor, actorId, projectId }: TProjectPermission) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId);
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Read,
ProjectPermissionSub.SecretRotation
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRotation);
return {
custom: [],
@@ -93,8 +90,7 @@ export const secretRotationServiceFactory = ({
const plan = await licenseService.getPlan(project.orgId);
if (!plan.secretRotation)
throw new BadRequestError({
message:
"Failed to add secret rotation due to plan restriction. Upgrade plan to add secret rotation."
message: "Failed to add secret rotation due to plan restriction. Upgrade plan to add secret rotation."
});
const selectedTemplate = rotationTemplates.find(({ name }) => name === provider);
@@ -152,24 +148,14 @@ export const secretRotationServiceFactory = ({
const [doc] = await secretRotationDAL.find({ id: rotationId });
if (!doc) throw new BadRequestError({ message: "Rotation not found" });
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
doc.projectId
);
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Read,
ProjectPermissionSub.SecretRotation
);
const { permission } = await permissionService.getProjectPermission(actor, actorId, doc.projectId);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRotation);
return doc;
};
const getByProjectId = async ({ actorId, projectId, actor }: TListByProjectIdDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId);
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Read,
ProjectPermissionSub.SecretRotation
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRotation);
const doc = await secretRotationDAL.find({ projectId });
return doc;
};
@@ -182,19 +168,11 @@ export const secretRotationServiceFactory = ({
const plan = await licenseService.getPlan(project.orgId);
if (!plan.secretRotation)
throw new BadRequestError({
message:
"Failed to add secret rotation due to plan restriction. Upgrade plan to add secret rotation."
message: "Failed to add secret rotation due to plan restriction. Upgrade plan to add secret rotation."
});
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
doc.projectId
);
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Edit,
ProjectPermissionSub.SecretRotation
);
const { permission } = await permissionService.getProjectPermission(actor, actorId, doc.projectId);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.SecretRotation);
await secretRotationQueue.removeFromQueue(doc.id, doc.interval);
await secretRotationQueue.addToQueue(doc.id, doc.interval);
return doc;
@@ -204,11 +182,7 @@ export const secretRotationServiceFactory = ({
const doc = await secretRotationDAL.findById(rotationId);
if (!doc) throw new BadRequestError({ message: "Rotation not found" });
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
doc.projectId
);
const { permission } = await permissionService.getProjectPermission(actor, actorId, doc.projectId);
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Delete,
ProjectPermissionSub.SecretRotation

View File

@@ -23,15 +23,7 @@ export const MYSQL_TEMPLATE = {
},
ca: { type: "string", desc: "SSL certificate for db auth(string)" }
},
required: [
"admin_username",
"admin_password",
"host",
"database",
"username1",
"username2",
"port"
],
required: ["admin_username", "admin_password", "host", "database", "username1", "username2", "port"],
additionalProperties: false
},
outputs: {

View File

@@ -23,15 +23,7 @@ export const POSTGRES_TEMPLATE = {
},
ca: { type: "string", desc: "SSL certificate for db auth(string)" }
},
required: [
"admin_username",
"admin_password",
"host",
"database",
"username1",
"username2",
"port"
],
required: ["admin_username", "admin_password", "host", "database", "username1", "username2", "port"],
additionalProperties: false
},
outputs: {

View File

@@ -12,11 +12,7 @@ export const gitAppDALFactory = (db: TDbClient) => {
const upsert = async (data: TGitAppOrgInsert, tx?: Knex) => {
try {
const [doc] = await (tx || db)(TableName.GitAppOrg)
.insert(data)
.onConflict("orgId")
.merge()
.returning("*");
const [doc] = await (tx || db)(TableName.GitAppOrg).insert(data).onConflict("orgId").merge().returning("*");
return doc;
} catch (error) {
throw new DatabaseError({ error, name: "UpsertGitAppOrm" });

View File

@@ -12,10 +12,7 @@ export const secretScanningDALFactory = (db: TDbClient) => {
const upsert = async (data: TSecretScanningGitRisksInsert[], tx?: Knex) => {
try {
const docs = await (tx || db)(TableName.SecretScanningGitRisk)
.insert(data)
.onConflict("fingerprint")
.merge();
const docs = await (tx || db)(TableName.SecretScanningGitRisk).insert(data).onConflict("fingerprint").merge();
return docs;
} catch (error) {
throw new DatabaseError({ error, name: "GitRiskUpsert" });

View File

@@ -10,15 +10,8 @@ import { TTelemetryServiceFactory } from "@app/services/telemetry/telemetry-serv
import { PostHogEventTypes } from "@app/services/telemetry/telemetry-types";
import { TSecretScanningDALFactory } from "../secret-scanning-dal";
import {
scanContentAndGetFindings,
scanFullRepoContentAndGetFindings
} from "./secret-scanning-fns";
import {
SecretMatch,
TScanFullRepoEventPayload,
TScanPushEventPayload
} from "./secret-scanning-queue-types";
import { scanContentAndGetFindings, scanFullRepoContentAndGetFindings } from "./secret-scanning-fns";
import { SecretMatch, TScanFullRepoEventPayload, TScanPushEventPayload } from "./secret-scanning-queue-types";
type TSecretScanningQueueFactoryDep = {
queueService: TQueueServiceFactory;

View File

@@ -4,10 +4,7 @@ import { ForbiddenError } from "@casl/ability";
import { WebhookEventMap } from "@octokit/webhooks-types";
import { ProbotOctokit } from "probot";
import {
OrgPermissionActions,
OrgPermissionSubjects
} from "@app/ee/services/permission/org-permission";
import { OrgPermissionActions, OrgPermissionSubjects } from "@app/ee/services/permission/org-permission";
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
import { getConfig } from "@app/lib/config/env";
import { UnauthorizedError } from "@app/lib/errors";
@@ -44,30 +41,19 @@ export const secretScanningServiceFactory = ({
}: TSecretScanningServiceFactoryDep) => {
const createInstallationSession = async ({ actor, orgId, actorId }: TInstallAppSessionDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId);
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Create,
OrgPermissionSubjects.SecretScanning
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.SecretScanning);
const sessionId = crypto.randomBytes(16).toString("hex");
await gitAppInstallSessionDAL.upsert({ orgId, sessionId, userId: actorId });
return { sessionId };
};
const linkInstallationToOrg = async ({
sessionId,
actorId,
installationId,
actor
}: TLinkInstallSessionDTO) => {
const linkInstallationToOrg = async ({ sessionId, actorId, installationId, actor }: TLinkInstallSessionDTO) => {
const session = await gitAppInstallSessionDAL.findOne({ sessionId });
if (!session) throw new UnauthorizedError({ message: "Session not found" });
const { permission } = await permissionService.getOrgPermission(actor, actorId, session.orgId);
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Create,
OrgPermissionSubjects.SecretScanning
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.SecretScanning);
const installatedApp = await gitAppOrgDAL.transaction(async (tx) => {
await gitAppInstallSessionDAL.deleteById(session.id, tx);
return gitAppOrgDAL.upsert({ orgId: session.orgId, installationId, userId: actorId }, tx);
@@ -99,10 +85,7 @@ export const secretScanningServiceFactory = ({
const getOrgInstallationStatus = async ({ actorId, orgId, actor }: TGetOrgInstallStatusDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId);
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.SecretScanning
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.SecretScanning);
const appInstallation = await gitAppOrgDAL.findOne({ orgId });
return Boolean(appInstallation);
@@ -110,26 +93,14 @@ export const secretScanningServiceFactory = ({
const getRisksByOrg = async ({ actor, orgId, actorId }: TGetOrgRisksDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId);
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.SecretScanning
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.SecretScanning);
const risks = await secretScanningDAL.find({ orgId }, { sort: [["createdAt", "desc"]] });
return { risks };
};
const updateRiskStatus = async ({
actorId,
orgId,
actor,
riskId,
status
}: TUpdateRiskStatusDTO) => {
const updateRiskStatus = async ({ actorId, orgId, actor, riskId, status }: TUpdateRiskStatusDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId);
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Edit,
OrgPermissionSubjects.SecretScanning
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.SecretScanning);
const isRiskResolved = Boolean(
[
@@ -169,9 +140,7 @@ export const secretScanningServiceFactory = ({
const handleRepoDeleteEvent = async (installationId: string, repositoryIds: string[]) => {
await secretScanningDAL.transaction(async (tx) => {
if (repositoryIds.length) {
await Promise.all(
repositoryIds.map((repoId) => secretScanningDAL.delete({ repositoryId: repoId }, tx))
);
await Promise.all(repositoryIds.map((repoId) => secretScanningDAL.delete({ repositoryId: repoId }, tx)));
}
await gitAppOrgDAL.delete({ installationId }, tx);
});

View File

@@ -29,17 +29,11 @@ type TSecretSnapshotServiceFactoryDep = {
snapshotSecretDAL: TSnapshotSecretDALFactory;
snapshotFolderDAL: TSnapshotFolderDALFactory;
secretVersionDAL: Pick<TSecretVersionDALFactory, "insertMany" | "findLatestVersionByFolderId">;
folderVersionDAL: Pick<
TSecretFolderVersionDALFactory,
"findLatestVersionByFolderId" | "insertMany"
>;
folderVersionDAL: Pick<TSecretFolderVersionDALFactory, "findLatestVersionByFolderId" | "insertMany">;
secretDAL: Pick<TSecretDALFactory, "delete" | "insertMany">;
secretTagDAL: Pick<TSecretTagDALFactory, "saveTagsToSecret">;
secretVersionTagDAL: Pick<TSecretVersionTagDALFactory, "insertMany">;
folderDAL: Pick<
TSecretFolderDALFactory,
"findById" | "findBySecretPath" | "delete" | "insertMany"
>;
folderDAL: Pick<TSecretFolderDALFactory, "findById" | "findBySecretPath" | "delete" | "insertMany">;
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission">;
licenseService: Pick<TLicenseServiceFactory, "isValidLicense">;
};
@@ -67,10 +61,7 @@ export const secretSnapshotServiceFactory = ({
path
}: TProjectSnapshotCountDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId);
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Read,
ProjectPermissionSub.SecretRollback
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRollback);
const folder = await folderDAL.findBySecretPath(projectId, environment, path);
if (!folder) throw new BadRequestError({ message: "Folder not found" });
@@ -89,40 +80,26 @@ export const secretSnapshotServiceFactory = ({
offset = 0
}: TProjectSnapshotListDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId);
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Read,
ProjectPermissionSub.SecretRollback
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRollback);
const folder = await folderDAL.findBySecretPath(projectId, environment, path);
if (!folder) throw new BadRequestError({ message: "Folder not found" });
const snapshots = await snapshotDAL.find(
{ folderId: folder.id },
{ limit, offset, sort: [["createdAt", "desc"]] }
);
const snapshots = await snapshotDAL.find({ folderId: folder.id }, { limit, offset, sort: [["createdAt", "desc"]] });
return snapshots;
};
const getSnapshotData = async ({ actorId, actor, id }: TGetSnapshotDataDTO) => {
const snapshot = await snapshotDAL.findSecretSnapshotDataById(id);
if (!snapshot) throw new BadRequestError({ message: "Snapshot not found" });
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
snapshot.projectId
);
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Read,
ProjectPermissionSub.SecretRollback
);
const { permission } = await permissionService.getProjectPermission(actor, actorId, snapshot.projectId);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRollback);
return snapshot;
};
const performSnapshot = async (folderId: string) => {
try {
if (!licenseService.isValidLicense)
throw new InternalServerError({ message: "Invalid license" });
if (!licenseService.isValidLicense) throw new InternalServerError({ message: "Invalid license" });
const snapshot = await snapshotDAL.transaction(async (tx) => {
const folder = await folderDAL.findById(folderId, tx);
@@ -170,11 +147,7 @@ export const secretSnapshotServiceFactory = ({
const snapshot = await snapshotDAL.findById(snapshotId);
if (!snapshot) throw new BadRequestError({ message: "Snapshot not found" });
const { permission } = await permissionService.getProjectPermission(
actor,
actorId,
snapshot.projectId
);
const { permission } = await permissionService.getProjectPermission(actor, actorId, snapshot.projectId);
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Create,
ProjectPermissionSub.SecretRollback
@@ -199,9 +172,7 @@ export const secretSnapshotServiceFactory = ({
id,
// this means don't bump up the version if not root folder
// because below ones can be same version as nothing changed
version: deletedTopLevelFolders[folderId]
? latestFolderVersion + 1
: latestFolderVersion,
version: deletedTopLevelFolders[folderId] ? latestFolderVersion + 1 : latestFolderVersion,
name,
parentId: folderId
}))
@@ -211,22 +182,10 @@ export const secretSnapshotServiceFactory = ({
const secrets = await secretDAL.insertMany(
rollbackSnaps.flatMap(({ secretVersions, folderId }) =>
secretVersions.map(
({
latestSecretVersion,
version,
updatedAt,
createdAt,
secretId,
envId,
id,
tags,
...el
}) => ({
({ latestSecretVersion, version, updatedAt, createdAt, secretId, envId, id, tags, ...el }) => ({
...el,
id: secretId,
version: deletedTopLevelSecsGroupById[secretId]
? latestSecretVersion + 1
: latestSecretVersion,
version: deletedTopLevelSecsGroupById[secretId] ? latestSecretVersion + 1 : latestSecretVersion,
folderId
})
)
@@ -239,8 +198,7 @@ export const secretSnapshotServiceFactory = ({
secretVersions.forEach((secVer) => {
secVer.tags.forEach((tag) => {
secretTagsToBeInsert.push({ secretsId: secVer.secretId, secret_tagsId: tag.id });
if (!secretVerTagToBeInsert?.[secVer.secretId])
secretVerTagToBeInsert[secVer.secretId] = [];
if (!secretVerTagToBeInsert?.[secVer.secretId]) secretVerTagToBeInsert[secVer.secretId] = [];
secretVerTagToBeInsert[secVer.secretId].push(tag.id);
});
});

View File

@@ -57,11 +57,7 @@ export const snapshotDALFactory = (db: TDbClient) => {
const data = await (tx || db)(TableName.Snapshot)
.where(`${TableName.Snapshot}.id`, snapshotId)
.join(TableName.Environment, `${TableName.Snapshot}.envId`, `${TableName.Environment}.id`)
.leftJoin(
TableName.SnapshotSecret,
`${TableName.Snapshot}.id`,
`${TableName.SnapshotSecret}.snapshotId`
)
.leftJoin(TableName.SnapshotSecret, `${TableName.Snapshot}.id`, `${TableName.SnapshotSecret}.snapshotId`)
.leftJoin(
TableName.SecretVersion,
`${TableName.SnapshotSecret}.secretVersionId`,
@@ -77,11 +73,7 @@ export const snapshotDALFactory = (db: TDbClient) => {
`${TableName.SecretVersionTag}.${TableName.SecretTag}Id`,
`${TableName.SecretTag}.id`
)
.leftJoin(
TableName.SnapshotFolder,
`${TableName.SnapshotFolder}.snapshotId`,
`${TableName.Snapshot}.id`
)
.leftJoin(TableName.SnapshotFolder, `${TableName.SnapshotFolder}.snapshotId`, `${TableName.Snapshot}.id`)
.leftJoin<TSecretFolderVersions>(
TableName.SecretFolderVersion,
`${TableName.SnapshotFolder}.folderVersionId`,
@@ -131,13 +123,13 @@ export const snapshotDALFactory = (db: TDbClient) => {
{
key: "tagVersionId",
label: "tags" as const,
mapper: ({
tagId: id,
tagName: name,
tagSlug: slug,
tagColor: color,
tagVersionId: vId
}) => ({ id, name, slug, color, vId })
mapper: ({ tagId: id, tagName: name, tagSlug: slug, tagColor: color, tagVersionId: vId }) => ({
id,
name,
slug,
color,
vId
})
}
]
},
@@ -192,11 +184,7 @@ export const snapshotDALFactory = (db: TDbClient) => {
)
.from(TableName.Snapshot)
.join<TSecretSnapshots, TSecretSnapshots & { secretId: string; max: number }>(
db(TableName.Snapshot)
.groupBy("folderId")
.max("createdAt")
.select("folderId")
.as("latestVersion"),
db(TableName.Snapshot).groupBy("folderId").max("createdAt").select("folderId").as("latestVersion"),
`${TableName.Snapshot}.createdAt`,
"latestVersion.max"
)
@@ -215,11 +203,7 @@ export const snapshotDALFactory = (db: TDbClient) => {
})
.orderBy("depth", "asc")
.from<TSecretSnapshots & { folderVerId: string; folderVerName: string }>("parent")
.leftJoin<TSecretSnapshots>(
TableName.SnapshotSecret,
`parent.id`,
`${TableName.SnapshotSecret}.snapshotId`
)
.leftJoin<TSecretSnapshots>(TableName.SnapshotSecret, `parent.id`, `${TableName.SnapshotSecret}.snapshotId`)
.leftJoin<TSecretVersions>(
TableName.SecretVersion,
`${TableName.SnapshotSecret}.secretVersionId`,
@@ -272,11 +256,7 @@ export const snapshotDALFactory = (db: TDbClient) => {
const formated = sqlNestRelationships({
data,
key: "snapshotId",
parentMapper: ({
snapshotId: id,
snapshotFolderId: folderId,
snapshotParentFolderId: parentFolderId
}) => ({
parentMapper: ({ snapshotId: id, snapshotFolderId: folderId, snapshotParentFolderId: parentFolderId }) => ({
id,
folderId,
parentFolderId
@@ -293,13 +273,13 @@ export const snapshotDALFactory = (db: TDbClient) => {
{
key: "tagVersionId",
label: "tags" as const,
mapper: ({
tagId: id,
tagName: name,
tagSlug: slug,
tagColor: color,
tagVersionId: vId
}) => ({ id, name, slug, color, vId })
mapper: ({ tagId: id, tagName: name, tagSlug: slug, tagColor: color, tagVersionId: vId }) => ({
id,
name,
slug,
color,
vId
})
}
]
},
@@ -328,11 +308,7 @@ export const snapshotDALFactory = (db: TDbClient) => {
const docs = await (tx || db)(TableName.Snapshot)
.where(`${TableName.Snapshot}.folderId`, folderId)
.join<TSecretSnapshots>(
(tx || db)(TableName.Snapshot)
.groupBy("folderId")
.max("createdAt")
.select("folderId")
.as("latestVersion"),
(tx || db)(TableName.Snapshot).groupBy("folderId").max("createdAt").select("folderId").as("latestVersion"),
(bd) => {
bd.on(`${TableName.Snapshot}.folderId`, "latestVersion.folderId").andOn(
`${TableName.Snapshot}.createdAt`,

View File

@@ -28,36 +28,22 @@ export const trustedIpServiceFactory = ({
}: TTrustedIpServiceFactoryDep) => {
const listIpsByProjectId = async ({ projectId, actor, actorId }: TProjectPermission) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId);
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Read,
ProjectPermissionSub.IpAllowList
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.IpAllowList);
const trustedIps = await trustedIpDAL.find({
projectId
});
return trustedIps;
};
const addProjectIp = async ({
projectId,
actorId,
actor,
ipAddress: ip,
comment,
isActive
}: TCreateIpDTO) => {
const addProjectIp = async ({ projectId, actorId, actor, ipAddress: ip, comment, isActive }: TCreateIpDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId);
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Create,
ProjectPermissionSub.IpAllowList
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.IpAllowList);
const project = await projectDAL.findById(projectId);
const plan = await licenseService.getPlan(project.orgId);
if (!plan.ipAllowlisting)
throw new BadRequestError({
message:
"Failed to add IP access range due to plan restriction. Upgrade plan to add IP access range."
message: "Failed to add IP access range due to plan restriction. Upgrade plan to add IP access range."
});
const isValidIp = isValidIpOrCidr(ip);
@@ -79,26 +65,15 @@ export const trustedIpServiceFactory = ({
return { trustedIp, project }; // for audit log
};
const updateProjectIp = async ({
projectId,
actorId,
actor,
ipAddress: ip,
comment,
trustedIpId
}: TUpdateIpDTO) => {
const updateProjectIp = async ({ projectId, actorId, actor, ipAddress: ip, comment, trustedIpId }: TUpdateIpDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId);
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Create,
ProjectPermissionSub.IpAllowList
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.IpAllowList);
const project = await projectDAL.findById(projectId);
const plan = await licenseService.getPlan(project.orgId);
if (!plan.ipAllowlisting)
throw new BadRequestError({
message:
"Failed to add IP access range due to plan restriction. Upgrade plan to add IP access range."
message: "Failed to add IP access range due to plan restriction. Upgrade plan to add IP access range."
});
const isValidIp = isValidIpOrCidr(ip);
@@ -124,17 +99,13 @@ export const trustedIpServiceFactory = ({
const deleteProjectIp = async ({ projectId, actorId, actor, trustedIpId }: TDeleteIpDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId);
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Create,
ProjectPermissionSub.IpAllowList
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.IpAllowList);
const project = await projectDAL.findById(projectId);
const plan = await licenseService.getPlan(project.orgId);
if (!plan.ipAllowlisting)
throw new BadRequestError({
message:
"Failed to add IP access range due to plan restriction. Upgrade plan to add IP access range."
message: "Failed to add IP access range due to plan restriction. Upgrade plan to add IP access range."
});
const [trustedIp] = await trustedIpDAL.delete({ projectId, id: trustedIpId });

View File

@@ -24,9 +24,7 @@ export const conditionsMatcher = buildMongoQueryMatcher({ $glob }, { glob });
* Extracts and formats permissions from a CASL Ability object or a raw permission set.
*/
const extractPermissions = (ability: MongoAbility) =>
ability.rules.map(
(permission) => `${permission.action as string}_${permission.subject as string}`
);
ability.rules.map((permission) => `${permission.action as string}_${permission.subject as string}`);
/**
* Compares two sets of permissions to determine if the first set is at least as privileged as the second set.

View File

@@ -38,9 +38,7 @@ const envSchema = z
// Telemetry
TELEMETRY_ENABLED: zodStrBool.default("true"),
POSTHOG_HOST: zpStr(z.string().optional().default("https://app.posthog.com")),
POSTHOG_PROJECT_API_KEY: zpStr(
z.string().optional().default("phc_nSin8j5q2zdhpFDI1ETmFNUIuTG4DwKVyIigrY10XiE")
),
POSTHOG_PROJECT_API_KEY: zpStr(z.string().optional().default("phc_nSin8j5q2zdhpFDI1ETmFNUIuTG4DwKVyIigrY10XiE")),
LOOPS_API_KEY: zpStr(z.string().optional()),
// jwt options
AUTH_SECRET: zpStr(z.string()).default(process.env.JWT_AUTH_SECRET), // for those still using old JWT_AUTH_SECRET

View File

@@ -20,11 +20,7 @@ export const BLOCK_SIZE_BYTES_16 = 16;
export const decryptSymmetric = ({ ciphertext, iv, tag, key }: TDecryptSymmetricInput): string => {
const secretKey = crypto.createSecretKey(key, "base64");
const decipher = crypto.createDecipheriv(
SecretEncryptionAlgo.AES_256_GCM,
secretKey,
Buffer.from(iv, "base64")
);
const decipher = crypto.createDecipheriv(SecretEncryptionAlgo.AES_256_GCM, secretKey, Buffer.from(iv, "base64"));
decipher.setAuthTag(Buffer.from(tag, "base64"));
let cleartext = decipher.update(ciphertext, "base64", "utf8");
cleartext += decipher.final("utf8");
@@ -62,17 +58,8 @@ export const encryptSymmetric128BitHexKeyUTF8 = (plaintext: string, key: string)
};
};
export const decryptSymmetric128BitHexKeyUTF8 = ({
ciphertext,
iv,
tag,
key
}: TDecryptSymmetricInput): string => {
const decipher = crypto.createDecipheriv(
SecretEncryptionAlgo.AES_256_GCM,
key,
Buffer.from(iv, "base64")
);
export const decryptSymmetric128BitHexKeyUTF8 = ({ ciphertext, iv, tag, key }: TDecryptSymmetricInput): string => {
const decipher = crypto.createDecipheriv(SecretEncryptionAlgo.AES_256_GCM, key, Buffer.from(iv, "base64"));
decipher.setAuthTag(Buffer.from(tag, "base64"));
@@ -104,12 +91,7 @@ export type TDecryptAsymmetricInput = {
privateKey: string;
};
export const decryptAsymmetric = ({
ciphertext,
nonce,
publicKey,
privateKey
}: TDecryptAsymmetricInput) => {
export const decryptAsymmetric = ({ ciphertext, nonce, publicKey, privateKey }: TDecryptAsymmetricInput) => {
const plaintext: Uint8Array | null = nacl.box.open(
naclUtils.decodeBase64(ciphertext),
naclUtils.decodeBase64(nonce),

View File

@@ -23,10 +23,7 @@ export const groupBy = <T, Key extends string | number | symbol>(
* to convert each item in the list to a comparable identity
* value
*/
export const unique = <T, K extends string | number | symbol>(
array: readonly T[],
toKey?: (item: T) => K
): T[] => {
export const unique = <T, K extends string | number | symbol>(array: readonly T[], toKey?: (item: T) => K): T[] => {
const valueMap = array.reduce(
(acc, item) => {
const key = toKey ? toKey(item) : (item as unknown as string | number | symbol);

View File

@@ -2,10 +2,7 @@
* Pick a list of properties from an object
* into a new object
*/
export const pick = <T extends object, TKeys extends keyof T>(
obj: T,
keys: TKeys[]
): Pick<T, TKeys> => {
export const pick = <T extends object, TKeys extends keyof T>(obj: T, keys: TKeys[]): Pick<T, TKeys> => {
if (!obj) return {} as Pick<T, TKeys>;
return keys.reduce(
(acc, key) => {

View File

@@ -111,13 +111,7 @@ export type TIp = {
/**
* Validates the IP address [ipAddress] against the trusted IPs [trustedIps].
*/
export const checkIPAgainstBlocklist = ({
ipAddress,
trustedIps
}: {
ipAddress: string;
trustedIps: TIp[];
}) => {
export const checkIPAgainstBlocklist = ({ ipAddress, trustedIps }: { ipAddress: string; trustedIps: TIp[] }) => {
const blockList = new net.BlockList();
for (const trustedIp of trustedIps) {

View File

@@ -41,11 +41,7 @@ export type TFindOpt<R extends object = object> = {
// What is ormify
// It is to inject typical operations like find, findOne, update, delete, create
// This will avoid writing most common ones each time
export const ormify = <DbOps extends object, Tname extends keyof Tables>(
db: Knex,
tableName: Tname,
dal?: DbOps
) => ({
export const ormify = <DbOps extends object, Tname extends keyof Tables>(db: Knex, tableName: Tname, dal?: DbOps) => ({
transaction: async <T>(cb: (tx: Knex) => Promise<T>) =>
db.transaction(async (trx) => {
const res = await cb(trx);
@@ -78,9 +74,7 @@ export const ormify = <DbOps extends object, Tname extends keyof Tables>(
if (limit) void query.limit(limit);
if (offset) void query.offset(offset);
if (sort) {
void query.orderBy(
sort.map(([column, order, nulls]) => ({ column: column as string, order, nulls }))
);
void query.orderBy(sort.map(([column, order, nulls]) => ({ column: column as string, order, nulls })));
}
const res = await query;
return res;
@@ -120,11 +114,7 @@ export const ormify = <DbOps extends object, Tname extends keyof Tables>(
throw new DatabaseError({ error, name: "Update by id" });
}
},
update: async (
filter: TFindFilter<Tables[Tname]["base"]>,
data: Tables[Tname]["update"],
tx?: Knex
) => {
update: async (filter: TFindFilter<Tables[Tname]["base"]>, data: Tables[Tname]["update"], tx?: Knex) => {
try {
const res = await (tx || db)(tableName)
.where(buildFindFilter(filter))
@@ -148,10 +138,7 @@ export const ormify = <DbOps extends object, Tname extends keyof Tables>(
},
delete: async (filter: TFindFilter<Tables[Tname]["base"]>, tx?: Knex) => {
try {
const res = await (tx || db)(tableName)
.where(buildFindFilter(filter))
.delete()
.returning("*");
const res = await (tx || db)(tableName).where(buildFindFilter(filter)).delete().returning("*");
return res;
} catch (error) {
throw new DatabaseError({ error, name: "Delete" });

View File

@@ -1,10 +1,7 @@
import { z, ZodTypeAny } from "zod";
// this is a patched zod string to remove empty string to undefined
export const zpStr = <T extends ZodTypeAny>(
schema: T,
opt: { stripNull: boolean } = { stripNull: true }
) =>
export const zpStr = <T extends ZodTypeAny>(schema: T, opt: { stripNull: boolean } = { stripNull: true }) =>
z.preprocess((val) => {
if (opt.stripNull && val === null) return undefined;
if (typeof val !== "string") return val;

View File

@@ -74,23 +74,18 @@ export const queueServiceFactory = (redisUrl: string) => {
const start = <T extends QueueName>(
name: T,
jobFn: (
job: Job<TQueueJobTypes[T]["payload"], void, TQueueJobTypes[T]["name"]>
) => Promise<void>
jobFn: (job: Job<TQueueJobTypes[T]["payload"], void, TQueueJobTypes[T]["name"]>) => Promise<void>
) => {
if (queueContainer[name]) {
throw new Error(`${name} queue is already initialized`);
}
queueContainer[name] = new Queue<TQueueJobTypes[T]["payload"], void, TQueueJobTypes[T]["name"]>(
name as string,
{ connection }
);
workerContainer[name] = new Worker<
TQueueJobTypes[T]["payload"],
void,
TQueueJobTypes[T]["name"]
>(name, jobFn, { connection });
queueContainer[name] = new Queue<TQueueJobTypes[T]["payload"], void, TQueueJobTypes[T]["name"]>(name as string, {
connection
});
workerContainer[name] = new Worker<TQueueJobTypes[T]["payload"], void, TQueueJobTypes[T]["name"]>(name, jobFn, {
connection
});
};
const listen = <

View File

@@ -5,12 +5,7 @@ import jwt, { JwtPayload } from "jsonwebtoken";
import { TServiceTokens, TUsers } from "@app/db/schemas";
import { getConfig } from "@app/lib/config/env";
import { UnauthorizedError } from "@app/lib/errors";
import {
ActorType,
AuthMode,
AuthModeJwtTokenPayload,
AuthTokenType
} from "@app/services/auth/auth-type";
import { ActorType, AuthMode, AuthModeJwtTokenPayload, AuthTokenType } from "@app/services/auth/auth-type";
import { TIdentityAccessTokenJwtPayload } from "@app/services/identity-access-token/identity-access-token-types";
export type TAuthMode =
@@ -87,16 +82,12 @@ export const injectIdentity = fp(async (server: FastifyZodProvider) => {
switch (authMode) {
case AuthMode.JWT: {
const { user, tokenVersionId } =
await server.services.authToken.fnValidateJwtIdentity(token);
const { user, tokenVersionId } = await server.services.authToken.fnValidateJwtIdentity(token);
req.auth = { authMode: AuthMode.JWT, user, userId: user.id, tokenVersionId, actor };
break;
}
case AuthMode.IDENTITY_ACCESS_TOKEN: {
const identity = await server.services.identityAccessToken.fnValidateIdentityAccessToken(
token,
req.realIp
);
const identity = await server.services.identityAccessToken.fnValidateIdentityAccessToken(token, req.realIp);
req.auth = {
authMode: AuthMode.IDENTITY_ACCESS_TOKEN,
actor,

View File

@@ -7,8 +7,7 @@ export const verifyAuth =
<T extends FastifyRequest>(authStrats: AuthMode[]) =>
(req: T, _res: FastifyReply, done: HookHandlerDoneFunction) => {
if (!Array.isArray(authStrats)) throw new Error("Auth strategy must be array");
if (!req.auth)
throw new UnauthorizedError({ name: "Unauthorized access", message: "Token missing" });
if (!req.auth) throw new UnauthorizedError({ name: "Unauthorized access", message: "Token missing" });
const isAccessAllowed = authStrats.some((strat) => strat === req.auth.authMode);
if (!isAccessAllowed) {

View File

@@ -2,12 +2,7 @@ import { ForbiddenError } from "@casl/ability";
import fastifyPlugin from "fastify-plugin";
import { ZodError } from "zod";
import {
BadRequestError,
DatabaseError,
InternalServerError,
UnauthorizedError
} from "@app/lib/errors";
import { BadRequestError, DatabaseError, InternalServerError, UnauthorizedError } from "@app/lib/errors";
export const fastifyErrHandler = fastifyPlugin(async (server: FastifyZodProvider) => {
server.setErrorHandler((error, req, res) => {
@@ -17,13 +12,9 @@ export const fastifyErrHandler = fastifyPlugin(async (server: FastifyZodProvider
} else if (error instanceof UnauthorizedError) {
void res.status(403).send({ statusCode: 403, message: error.message, error: error.name });
} else if (error instanceof DatabaseError || error instanceof InternalServerError) {
void res
.status(500)
.send({ statusCode: 500, message: "Something went wrong", error: error.name });
void res.status(500).send({ statusCode: 500, message: "Something went wrong", error: error.name });
} else if (error instanceof ZodError) {
void res
.status(403)
.send({ statusCode: 403, error: "ValidationFailure", message: error.issues });
void res.status(403).send({ statusCode: 403, error: "ValidationFailure", message: error.issues });
} else if (error instanceof ForbiddenError) {
void res.status(401).send({
statusCode: 401,

View File

@@ -92,10 +92,7 @@ import { serviceTokenDALFactory } from "@app/services/service-token/service-toke
import { serviceTokenServiceFactory } from "@app/services/service-token/service-token-service";
import { TSmtpService } from "@app/services/smtp/smtp-service";
import { superAdminDALFactory } from "@app/services/super-admin/super-admin-dal";
import {
getServerCfg,
superAdminServiceFactory
} from "@app/services/super-admin/super-admin-service";
import { getServerCfg, superAdminServiceFactory } from "@app/services/super-admin/super-admin-service";
import { telemetryServiceFactory } from "@app/services/telemetry/telemetry-service";
import { userDALFactory } from "@app/services/user/user-dal";
import { userServiceFactory } from "@app/services/user/user-service";
@@ -112,11 +109,7 @@ import { registerV3Routes } from "./v3";
export const registerRoutes = async (
server: FastifyZodProvider,
{
db,
smtp: smtpService,
queue: queueService
}: { db: Knex; smtp: TSmtpService; queue: TQueueServiceFactory }
{ db, smtp: smtpService, queue: queueService }: { db: Knex; smtp: TSmtpService; queue: TQueueServiceFactory }
) => {
await server.register(registerSecretScannerGhApp, { prefix: "/ss-webhook" });

View File

@@ -5,11 +5,7 @@ import { getConfig } from "@app/lib/config/env";
import { BadRequestError, UnauthorizedError } from "@app/lib/errors";
import { authRateLimit } from "@app/server/config/rateLimiter";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import {
AuthMode,
AuthModeRefreshJwtTokenPayload,
AuthTokenType
} from "@app/services/auth/auth-type";
import { AuthMode, AuthModeRefreshJwtTokenPayload, AuthTokenType } from "@app/services/auth/auth-type";
export const registerAuthRoutes = async (server: FastifyZodProvider) => {
server.route({
@@ -74,10 +70,7 @@ export const registerAuthRoutes = async (server: FastifyZodProvider) => {
message: "Failed to find refresh token"
});
const decodedToken = jwt.verify(
refreshToken,
appCfg.AUTH_SECRET
) as AuthModeRefreshJwtTokenPayload;
const decodedToken = jwt.verify(refreshToken, appCfg.AUTH_SECRET) as AuthModeRefreshJwtTokenPayload;
if (decodedToken.authTokenType !== AuthTokenType.REFRESH_TOKEN)
throw new UnauthorizedError({ message: "Invalid token", name: "Auth token route" });
@@ -85,8 +78,7 @@ export const registerAuthRoutes = async (server: FastifyZodProvider) => {
decodedToken.tokenVersionId,
decodedToken.userId
);
if (!tokenVersion)
throw new UnauthorizedError({ message: "Invalid token", name: "Auth token route" });
if (!tokenVersion) throw new UnauthorizedError({ message: "Invalid token", name: "Auth token route" });
if (decodedToken.refreshVersion !== tokenVersion.refreshVersion)
throw new UnauthorizedError({ message: "Invalid token", name: "Auth token route" });

View File

@@ -18,10 +18,9 @@ export const registerIdentityAccessTokenRouter = async (server: FastifyZodProvid
}
},
handler: async (req) => {
const { accessToken, identityAccessToken } =
await server.services.identityAccessToken.renewAccessToken({
accessToken: req.body.accessToken
});
const { accessToken, identityAccessToken } = await server.services.identityAccessToken.renewAccessToken({
accessToken: req.body.accessToken
});
return {
accessToken,
tokenType: "Bearer" as const,

View File

@@ -39,11 +39,7 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
},
handler: async (req) => {
const { identityUa, accessToken, identityAccessToken, validClientSecretInfo } =
await server.services.identityUa.login(
req.body.clientId,
req.body.clientSecret,
req.realIp
);
await server.services.identityUa.login(req.body.clientId, req.body.clientSecret, req.realIp);
await server.services.auditLog.createAuditLog({
...req.auditLogInfo,
@@ -128,10 +124,8 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
identityId: identityUniversalAuth.identityId,
accessTokenTTL: identityUniversalAuth.accessTokenTTL,
accessTokenMaxTTL: identityUniversalAuth.accessTokenMaxTTL,
accessTokenTrustedIps:
identityUniversalAuth.accessTokenTrustedIps as TIdentityTrustedIp[],
clientSecretTrustedIps:
identityUniversalAuth.clientSecretTrustedIps as TIdentityTrustedIp[],
accessTokenTrustedIps: identityUniversalAuth.accessTokenTrustedIps as TIdentityTrustedIp[],
clientSecretTrustedIps: identityUniversalAuth.clientSecretTrustedIps as TIdentityTrustedIp[],
accessTokenNumUsesLimit: identityUniversalAuth.accessTokenNumUsesLimit
}
}
@@ -197,10 +191,8 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
identityId: identityUniversalAuth.identityId,
accessTokenTTL: identityUniversalAuth.accessTokenTTL,
accessTokenMaxTTL: identityUniversalAuth.accessTokenMaxTTL,
accessTokenTrustedIps:
identityUniversalAuth.accessTokenTrustedIps as TIdentityTrustedIp[],
clientSecretTrustedIps:
identityUniversalAuth.clientSecretTrustedIps as TIdentityTrustedIp[],
accessTokenTrustedIps: identityUniversalAuth.accessTokenTrustedIps as TIdentityTrustedIp[],
clientSecretTrustedIps: identityUniversalAuth.clientSecretTrustedIps as TIdentityTrustedIp[],
accessTokenNumUsesLimit: identityUniversalAuth.accessTokenNumUsesLimit
}
}
@@ -267,13 +259,12 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
}
},
handler: async (req) => {
const { clientSecret, clientSecretData, orgId } =
await server.services.identityUa.createUaClientSecret({
actor: req.permission.type,
actorId: req.permission.id,
identityId: req.params.identityId,
...req.body
});
const { clientSecret, clientSecretData, orgId } = await server.services.identityUa.createUaClientSecret({
actor: req.permission.type,
actorId: req.permission.id,
identityId: req.params.identityId,
...req.body
});
await server.services.auditLog.createAuditLog({
...req.auditLogInfo,
@@ -306,12 +297,11 @@ export const registerIdentityUaRouter = async (server: FastifyZodProvider) => {
}
},
handler: async (req) => {
const { clientSecrets: clientSecretData, orgId } =
await server.services.identityUa.getUaClientSecrets({
actor: req.permission.type,
actorId: req.permission.id,
identityId: req.params.identityId
});
const { clientSecrets: clientSecretData, orgId } = await server.services.identityUa.getUaClientSecrets({
actor: req.permission.type,
actorId: req.permission.id,
identityId: req.params.identityId
});
await server.services.auditLog.createAuditLog({
...req.auditLogInfo,

View File

@@ -1,11 +1,6 @@
import { z } from "zod";
import {
IncidentContactsSchema,
OrganizationsSchema,
OrgMembershipsSchema,
UsersSchema
} from "@app/db/schemas";
import { IncidentContactsSchema, OrganizationsSchema, OrgMembershipsSchema, UsersSchema } from "@app/db/schemas";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
@@ -42,10 +37,7 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => {
const organization = await server.services.org.findOrganizationById(
req.permission.id,
req.params.organizationId
);
const organization = await server.services.org.findOrganizationById(req.permission.id, req.params.organizationId);
return { organization };
}
});
@@ -76,10 +68,7 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => {
const users = await server.services.org.findAllOrgMembers(
req.permission.id,
req.params.organizationId
);
const users = await server.services.org.findAllOrgMembers(req.permission.id, req.params.organizationId);
return { users };
}
});

View File

@@ -119,10 +119,7 @@ export const registerPasswordRouter = async (server: FastifyZodProvider) => {
}
},
handler: async (req) => {
const { token, user } = await server.services.password.verifyPasswordResetEmail(
req.body.email,
req.body.code
);
const { token, user } = await server.services.password.verifyPasswordResetEmail(req.body.email, req.body.code);
return {
message: "Successfully verified email",
@@ -183,9 +180,7 @@ export const registerPasswordRouter = async (server: FastifyZodProvider) => {
},
handler: async (req) => {
const token = validateSignUpAuthorization(req.headers.authorization as string, "", false)!;
const backupPrivateKey = await server.services.password.getBackupPrivateKeyOfUser(
token.userId
);
const backupPrivateKey = await server.services.password.getBackupPrivateKeyOfUser(token.userId);
if (!backupPrivateKey) throw new Error("Failed to find backup key");
return { message: "Successfully fetched backup private key", backupPrivateKey };

View File

@@ -1,11 +1,6 @@
import { z } from "zod";
import {
OrgMembershipsSchema,
ProjectMembershipsSchema,
UserEncryptionKeysSchema,
UsersSchema
} from "@app/db/schemas";
import { OrgMembershipsSchema, ProjectMembershipsSchema, UserEncryptionKeysSchema, UsersSchema } from "@app/db/schemas";
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";

View File

@@ -25,12 +25,7 @@ export const registerSecretFolderRouter = async (server: FastifyZodProvider) =>
})
}
},
onRequest: verifyAuth([
AuthMode.JWT,
AuthMode.API_KEY,
AuthMode.SERVICE_TOKEN,
AuthMode.IDENTITY_ACCESS_TOKEN
]),
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN]),
handler: async (req) => {
const path = req.body.path || req.body.directory;
const folder = await server.services.folder.createFolder({
@@ -79,12 +74,7 @@ export const registerSecretFolderRouter = async (server: FastifyZodProvider) =>
})
}
},
onRequest: verifyAuth([
AuthMode.JWT,
AuthMode.API_KEY,
AuthMode.SERVICE_TOKEN,
AuthMode.IDENTITY_ACCESS_TOKEN
]),
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN]),
handler: async (req) => {
const path = req.body.path || req.body.directory;
const { folder, old } = await server.services.folder.updateFolder({
@@ -133,12 +123,7 @@ export const registerSecretFolderRouter = async (server: FastifyZodProvider) =>
})
}
},
onRequest: verifyAuth([
AuthMode.JWT,
AuthMode.API_KEY,
AuthMode.SERVICE_TOKEN,
AuthMode.IDENTITY_ACCESS_TOKEN
]),
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN]),
handler: async (req) => {
const path = req.body.path || req.body.directory;
const folder = await server.services.folder.deleteFolder({
@@ -183,12 +168,7 @@ export const registerSecretFolderRouter = async (server: FastifyZodProvider) =>
})
}
},
onRequest: verifyAuth([
AuthMode.JWT,
AuthMode.API_KEY,
AuthMode.SERVICE_TOKEN,
AuthMode.IDENTITY_ACCESS_TOKEN
]),
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN]),
handler: async (req) => {
const path = req.query.path || req.query.directory;
const folders = await server.services.folder.getFolders({

View File

@@ -31,12 +31,7 @@ export const registerSecretImportRouter = async (server: FastifyZodProvider) =>
})
}
},
onRequest: verifyAuth([
AuthMode.JWT,
AuthMode.API_KEY,
AuthMode.SERVICE_TOKEN,
AuthMode.IDENTITY_ACCESS_TOKEN
]),
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN]),
handler: async (req) => {
const secretImport = await server.services.secretImport.createImport({
actorId: req.permission.id,
@@ -97,12 +92,7 @@ export const registerSecretImportRouter = async (server: FastifyZodProvider) =>
})
}
},
onRequest: verifyAuth([
AuthMode.JWT,
AuthMode.API_KEY,
AuthMode.SERVICE_TOKEN,
AuthMode.IDENTITY_ACCESS_TOKEN
]),
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN]),
handler: async (req) => {
const secretImport = await server.services.secretImport.updateImport({
actorId: req.permission.id,
@@ -155,12 +145,7 @@ export const registerSecretImportRouter = async (server: FastifyZodProvider) =>
})
}
},
onRequest: verifyAuth([
AuthMode.JWT,
AuthMode.API_KEY,
AuthMode.SERVICE_TOKEN,
AuthMode.IDENTITY_ACCESS_TOKEN
]),
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN]),
handler: async (req) => {
const secretImport = await server.services.secretImport.deleteImport({
actorId: req.permission.id,
@@ -211,12 +196,7 @@ export const registerSecretImportRouter = async (server: FastifyZodProvider) =>
})
}
},
onRequest: verifyAuth([
AuthMode.JWT,
AuthMode.API_KEY,
AuthMode.SERVICE_TOKEN,
AuthMode.IDENTITY_ACCESS_TOKEN
]),
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN]),
handler: async (req) => {
const secretImports = await server.services.secretImport.getImports({
actorId: req.permission.id,
@@ -268,12 +248,7 @@ export const registerSecretImportRouter = async (server: FastifyZodProvider) =>
})
}
},
onRequest: verifyAuth([
AuthMode.JWT,
AuthMode.API_KEY,
AuthMode.SERVICE_TOKEN,
AuthMode.IDENTITY_ACCESS_TOKEN
]),
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN]),
handler: async (req) => {
const importedSecrets = await server.services.secretImport.getSecretsFromImports({
actorId: req.permission.id,

View File

@@ -27,9 +27,7 @@ export const registerSsoRouter = async (server: FastifyZodProvider) => {
await server.register(passport.initialize());
await server.register(passport.secureSession());
// passport oauth strategy for Google
const isGoogleOauthActive = Boolean(
appCfg.CLIENT_ID_GOOGLE_LOGIN && appCfg.CLIENT_SECRET_GOOGLE_LOGIN
);
const isGoogleOauthActive = Boolean(appCfg.CLIENT_ID_GOOGLE_LOGIN && appCfg.CLIENT_SECRET_GOOGLE_LOGIN);
if (isGoogleOauthActive) {
passport.use(
new GoogleStrategy(
@@ -70,9 +68,7 @@ export const registerSsoRouter = async (server: FastifyZodProvider) => {
}
// Passport strategy for Github
const isGithubOauthActive = Boolean(
appCfg.CLIENT_SECRET_GITHUB_LOGIN && appCfg.CLIENT_ID_GITHUB_LOGIN
);
const isGithubOauthActive = Boolean(appCfg.CLIENT_SECRET_GITHUB_LOGIN && appCfg.CLIENT_ID_GITHUB_LOGIN);
if (isGithubOauthActive) {
passport.use(
new GitHubStrategy(
@@ -109,9 +105,7 @@ export const registerSsoRouter = async (server: FastifyZodProvider) => {
// passport strategy for gitlab
const isGitlabOauthActive = Boolean(
appCfg.CLIENT_ID_GITLAB_LOGIN &&
appCfg.CLIENT_SECRET_GITLAB_LOGIN &&
appCfg.CLIENT_GITLAB_LOGIN_URL
appCfg.CLIENT_ID_GITLAB_LOGIN && appCfg.CLIENT_SECRET_GITLAB_LOGIN && appCfg.CLIENT_GITLAB_LOGIN_URL
);
if (isGitlabOauthActive) {
passport.use(
@@ -180,15 +174,11 @@ export const registerSsoRouter = async (server: FastifyZodProvider) => {
handler: (req, res) => {
if (req.passportUser.isUserCompleted) {
return res.redirect(
`${appCfg.SITE_URL}/login/sso?token=${encodeURIComponent(
req.passportUser.providerAuthToken
)}`
`${appCfg.SITE_URL}/login/sso?token=${encodeURIComponent(req.passportUser.providerAuthToken)}`
);
}
return res.redirect(
`${appCfg.SITE_URL}/signup/sso?token=${encodeURIComponent(
req.passportUser.providerAuthToken
)}`
`${appCfg.SITE_URL}/signup/sso?token=${encodeURIComponent(req.passportUser.providerAuthToken)}`
);
}
});
@@ -225,15 +215,11 @@ export const registerSsoRouter = async (server: FastifyZodProvider) => {
handler: (req, res) => {
if (req.passportUser.isUserCompleted) {
return res.redirect(
`${appCfg.SITE_URL}/login/sso?token=${encodeURIComponent(
req.passportUser.providerAuthToken
)}`
`${appCfg.SITE_URL}/login/sso?token=${encodeURIComponent(req.passportUser.providerAuthToken)}`
);
}
return res.redirect(
`${appCfg.SITE_URL}/signup/sso?token=${encodeURIComponent(
req.passportUser.providerAuthToken
)}`
`${appCfg.SITE_URL}/signup/sso?token=${encodeURIComponent(req.passportUser.providerAuthToken)}`
);
}
});
@@ -272,15 +258,11 @@ export const registerSsoRouter = async (server: FastifyZodProvider) => {
handler: (req, res) => {
if (req.passportUser.isUserCompleted) {
return res.redirect(
`${appCfg.SITE_URL}/login/sso?token=${encodeURIComponent(
req.passportUser.providerAuthToken
)}`
`${appCfg.SITE_URL}/login/sso?token=${encodeURIComponent(req.passportUser.providerAuthToken)}`
);
}
return res.redirect(
`${appCfg.SITE_URL}/signup/sso?token=${encodeURIComponent(
req.passportUser.providerAuthToken
)}`
`${appCfg.SITE_URL}/signup/sso?token=${encodeURIComponent(req.passportUser.providerAuthToken)}`
);
}
});

View File

@@ -21,10 +21,7 @@ export const registerUserActionRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => {
const userAction = await server.services.user.createUserAction(
req.permission.id,
req.body.action
);
const userAction = await server.services.user.createUserAction(req.permission.id, req.body.action);
return { userAction, message: "Successfully recorded user action" };
}
});
@@ -44,10 +41,7 @@ export const registerUserActionRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => {
const userAction = await server.services.user.getUserAction(
req.permission.id,
req.query.action
);
const userAction = await server.services.user.getUserAction(req.permission.id, req.query.action);
return { userAction };
}
});

View File

@@ -22,8 +22,7 @@ export const registerMfaRouter = async (server: FastifyZodProvider) => {
}
const decodedToken = jwt.verify(token, cfg.AUTH_SECRET) as AuthModeMfaJwtTokenPayload;
if (decodedToken.authTokenType !== AuthTokenType.MFA_TOKEN)
throw new Error("Unauthorized access");
if (decodedToken.authTokenType !== AuthTokenType.MFA_TOKEN) throw new Error("Unauthorized access");
const user = await server.store.user.findById(decodedToken.userId);
if (!user) throw new Error("User not found");

View File

@@ -1,11 +1,6 @@
import { z } from "zod";
import {
OrganizationsSchema,
OrgMembershipsSchema,
UserEncryptionKeysSchema,
UsersSchema
} from "@app/db/schemas";
import { OrganizationsSchema, OrgMembershipsSchema, UserEncryptionKeysSchema, UsersSchema } from "@app/db/schemas";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { ActorType, AuthMode } from "@app/services/auth/auth-type";
@@ -38,10 +33,7 @@ export const registerOrgRouter = async (server: FastifyZodProvider) => {
handler: async (req) => {
if (req.auth.actor !== ActorType.USER) return;
const users = await server.services.org.findAllOrgMembers(
req.permission.id,
req.params.organizationId
);
const users = await server.services.org.findAllOrgMembers(req.permission.id, req.params.organizationId);
return { users };
}
});

View File

@@ -1,11 +1,6 @@
import { z } from "zod";
import {
AuthTokenSessionsSchema,
OrganizationsSchema,
UserEncryptionKeysSchema,
UsersSchema
} from "@app/db/schemas";
import { AuthTokenSessionsSchema, OrganizationsSchema, UserEncryptionKeysSchema, UsersSchema } from "@app/db/schemas";
import { ApiKeysSchema } from "@app/db/schemas/api-keys";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMethod, AuthMode } from "@app/services/auth/auth-type";
@@ -26,10 +21,7 @@ export const registerUserRouter = async (server: FastifyZodProvider) => {
},
preHandler: verifyAuth([AuthMode.JWT, AuthMode.API_KEY]),
handler: async (req) => {
const user = await server.services.user.toggleUserMfa(
req.permission.id,
req.body.isMfaEnabled
);
const user = await server.services.user.toggleUserMfa(req.permission.id, req.body.isMfaEnabled);
return { user };
}
});
@@ -50,11 +42,7 @@ export const registerUserRouter = async (server: FastifyZodProvider) => {
},
preHandler: verifyAuth([AuthMode.JWT, AuthMode.API_KEY]),
handler: async (req) => {
const user = await server.services.user.updateUserName(
req.permission.id,
req.body.firstName,
req.body.lastName
);
const user = await server.services.user.updateUserName(req.permission.id, req.body.firstName, req.body.lastName);
return { user };
}
});
@@ -74,10 +62,7 @@ export const registerUserRouter = async (server: FastifyZodProvider) => {
},
preHandler: verifyAuth([AuthMode.JWT, AuthMode.API_KEY]),
handler: async (req) => {
const user = await server.services.user.updateAuthMethods(
req.permission.id,
req.body.authMethods
);
const user = await server.services.user.updateAuthMethods(req.permission.id, req.body.authMethods);
return { user };
}
});
@@ -131,11 +116,7 @@ export const registerUserRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => {
const apiKeys = await server.services.apiKey.createApiKey(
req.permission.id,
req.body.name,
req.body.expiresIn
);
const apiKeys = await server.services.apiKey.createApiKey(req.permission.id, req.body.name, req.body.expiresIn);
return apiKeys;
}
});
@@ -155,10 +136,7 @@ export const registerUserRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => {
const apiKeyData = await server.services.apiKey.deleteApiKey(
req.permission.id,
req.params.apiKeyDataId
);
const apiKeyData = await server.services.apiKey.deleteApiKey(req.permission.id, req.params.apiKeyDataId);
return { apiKeyData };
}
});

View File

@@ -61,12 +61,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
})
}
},
onRequest: verifyAuth([
AuthMode.JWT,
AuthMode.API_KEY,
AuthMode.SERVICE_TOKEN,
AuthMode.IDENTITY_ACCESS_TOKEN
]),
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN]),
handler: async (req) => {
// just for delivery hero usecase
let { secretPath, environment, workspaceId } = req.query;
@@ -80,8 +75,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
}
}
if (!workspaceId || !environment)
throw new BadRequestError({ message: "Missing workspace id or environment" });
if (!workspaceId || !environment) throw new BadRequestError({ message: "Missing workspace id or environment" });
const { secrets, imports } = await server.services.secret.getSecretsRaw({
actorId: req.permission.id,
@@ -144,12 +138,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
})
}
},
onRequest: verifyAuth([
AuthMode.JWT,
AuthMode.API_KEY,
AuthMode.SERVICE_TOKEN,
AuthMode.IDENTITY_ACCESS_TOKEN
]),
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN]),
handler: async (req) => {
let { secretPath, environment, workspaceId } = req.query;
if (req.auth.actor === ActorType.SERVICE) {
@@ -162,8 +151,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
}
}
if (!workspaceId || !environment)
throw new BadRequestError({ message: "Missing workspace id or environment" });
if (!workspaceId || !environment) throw new BadRequestError({ message: "Missing workspace id or environment" });
const secret = await server.services.secret.getSecretByNameRaw({
actorId: req.permission.id,
@@ -218,9 +206,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
workspaceId: z.string().trim(),
environment: z.string().trim(),
secretPath: z.string().trim().default("/").transform(removeTrailingSlash),
secretValue: z
.string()
.transform((val) => (val.at(-1) === "\n" ? `${val.trim()}\n` : val.trim())),
secretValue: z.string().transform((val) => (val.at(-1) === "\n" ? `${val.trim()}\n` : val.trim())),
secretComment: z.string().trim().optional().default(""),
skipMultilineEncoding: z.boolean().optional(),
type: z.nativeEnum(SecretType).default(SecretType.Shared)
@@ -231,12 +217,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
})
}
},
onRequest: verifyAuth([
AuthMode.JWT,
AuthMode.API_KEY,
AuthMode.SERVICE_TOKEN,
AuthMode.IDENTITY_ACCESS_TOKEN
]),
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN]),
handler: async (req) => {
const secret = await server.services.secret.createSecretRaw({
actorId: req.permission.id,
@@ -293,9 +274,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
body: z.object({
workspaceId: z.string().trim(),
environment: z.string().trim(),
secretValue: z
.string()
.transform((val) => (val.at(-1) === "\n" ? `${val.trim()}\n` : val.trim())),
secretValue: z.string().transform((val) => (val.at(-1) === "\n" ? `${val.trim()}\n` : val.trim())),
secretPath: z.string().trim().default("/").transform(removeTrailingSlash),
skipMultilineEncoding: z.boolean().optional(),
type: z.nativeEnum(SecretType).default(SecretType.Shared)
@@ -306,12 +285,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
})
}
},
onRequest: verifyAuth([
AuthMode.JWT,
AuthMode.API_KEY,
AuthMode.SERVICE_TOKEN,
AuthMode.IDENTITY_ACCESS_TOKEN
]),
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN]),
handler: async (req) => {
const secret = await server.services.secret.updateSecretRaw({
actorId: req.permission.id,
@@ -375,12 +349,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
})
}
},
onRequest: verifyAuth([
AuthMode.JWT,
AuthMode.API_KEY,
AuthMode.SERVICE_TOKEN,
AuthMode.IDENTITY_ACCESS_TOKEN
]),
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN]),
handler: async (req) => {
const secret = await server.services.secret.deleteSecretRaw({
actorId: req.permission.id,
@@ -474,12 +443,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
})
}
},
onRequest: verifyAuth([
AuthMode.JWT,
AuthMode.API_KEY,
AuthMode.SERVICE_TOKEN,
AuthMode.IDENTITY_ACCESS_TOKEN
]),
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN]),
handler: async (req) => {
const { secrets, imports } = await server.services.secret.getSecrets({
actorId: req.permission.id,
@@ -549,12 +513,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
})
}
},
onRequest: verifyAuth([
AuthMode.JWT,
AuthMode.API_KEY,
AuthMode.SERVICE_TOKEN,
AuthMode.IDENTITY_ACCESS_TOKEN
]),
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN]),
handler: async (req) => {
const secret = await server.services.secret.getSecretByName({
actorId: req.permission.id,
@@ -634,18 +593,11 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
})
)
}),
z
.object({ approval: SecretApprovalRequestsSchema })
.describe("When secret protection policy is enabled")
z.object({ approval: SecretApprovalRequestsSchema }).describe("When secret protection policy is enabled")
])
}
},
onRequest: verifyAuth([
AuthMode.JWT,
AuthMode.API_KEY,
AuthMode.SERVICE_TOKEN,
AuthMode.IDENTITY_ACCESS_TOKEN
]),
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN]),
handler: async (req) => {
const {
workspaceId: projectId,
@@ -673,32 +625,31 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
projectId
});
if (policy) {
const approval =
await server.services.secretApprovalRequest.generateSecretApprovalRequest({
actorId: req.permission.id,
actor: req.permission.type,
secretPath,
environment,
projectId,
policy,
data: {
[CommitType.Create]: [
{
secretName: req.params.secretName,
secretValueCiphertext,
secretValueIV,
secretValueTag,
secretCommentIV,
secretCommentTag,
secretCommentCiphertext,
skipMultilineEncoding,
secretKeyTag,
secretKeyCiphertext,
secretKeyIV
}
]
}
});
const approval = await server.services.secretApprovalRequest.generateSecretApprovalRequest({
actorId: req.permission.id,
actor: req.permission.type,
secretPath,
environment,
projectId,
policy,
data: {
[CommitType.Create]: [
{
secretName: req.params.secretName,
secretValueCiphertext,
secretValueIV,
secretValueTag,
secretCommentIV,
secretCommentTag,
secretCommentCiphertext,
skipMultilineEncoding,
secretKeyTag,
secretKeyCiphertext,
secretKeyIV
}
]
}
});
await server.services.auditLog.createAuditLog({
projectId: req.body.workspaceId,
@@ -810,18 +761,11 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
})
)
}),
z
.object({ approval: SecretApprovalRequestsSchema })
.describe("When secret protection policy is enabled")
z.object({ approval: SecretApprovalRequestsSchema }).describe("When secret protection policy is enabled")
])
}
},
onRequest: verifyAuth([
AuthMode.JWT,
AuthMode.API_KEY,
AuthMode.SERVICE_TOKEN,
AuthMode.IDENTITY_ACCESS_TOKEN
]),
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN]),
handler: async (req) => {
const {
secretValueCiphertext,
@@ -854,34 +798,33 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
projectId
});
if (policy) {
const approval =
await server.services.secretApprovalRequest.generateSecretApprovalRequest({
actorId: req.permission.id,
actor: req.permission.type,
secretPath,
environment,
projectId,
policy,
data: {
[CommitType.Update]: [
{
secretName: req.params.secretName,
newSecretName,
secretValueCiphertext,
secretValueIV,
secretValueTag,
secretCommentIV,
secretCommentTag,
secretCommentCiphertext,
skipMultilineEncoding,
secretKeyTag,
secretKeyCiphertext,
secretKeyIV,
tagIds: tags
}
]
}
});
const approval = await server.services.secretApprovalRequest.generateSecretApprovalRequest({
actorId: req.permission.id,
actor: req.permission.type,
secretPath,
environment,
projectId,
policy,
data: {
[CommitType.Update]: [
{
secretName: req.params.secretName,
newSecretName,
secretValueCiphertext,
secretValueIV,
secretValueTag,
secretCommentIV,
secretCommentTag,
secretCommentCiphertext,
skipMultilineEncoding,
secretKeyTag,
secretKeyCiphertext,
secretKeyIV,
tagIds: tags
}
]
}
});
await server.services.auditLog.createAuditLog({
projectId: req.body.workspaceId,
@@ -980,18 +923,11 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
})
)
}),
z
.object({ approval: SecretApprovalRequestsSchema })
.describe("When secret protection policy is enabled")
z.object({ approval: SecretApprovalRequestsSchema }).describe("When secret protection policy is enabled")
])
}
},
onRequest: verifyAuth([
AuthMode.JWT,
AuthMode.API_KEY,
AuthMode.SERVICE_TOKEN,
AuthMode.IDENTITY_ACCESS_TOKEN
]),
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN]),
handler: async (req) => {
const { secretPath, type, workspaceId: projectId, secretId, environment } = req.body;
if (req.body.type !== SecretType.Personal && req.permission.type === ActorType.USER) {
@@ -1003,22 +939,21 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
projectId
});
if (policy) {
const approval =
await server.services.secretApprovalRequest.generateSecretApprovalRequest({
actorId: req.permission.id,
actor: req.permission.type,
secretPath,
environment,
projectId,
policy,
data: {
[CommitType.Delete]: [
{
secretName: req.params.secretName
}
]
}
});
const approval = await server.services.secretApprovalRequest.generateSecretApprovalRequest({
actorId: req.permission.id,
actor: req.permission.type,
secretPath,
environment,
projectId,
policy,
data: {
[CommitType.Delete]: [
{
secretName: req.params.secretName
}
]
}
});
await server.services.auditLog.createAuditLog({
projectId: req.body.workspaceId,
@@ -1110,18 +1045,11 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
z.object({
secrets: SecretsSchema.omit({ secretBlindIndex: true }).array()
}),
z
.object({ approval: SecretApprovalRequestsSchema })
.describe("When secret protection policy is enabled")
z.object({ approval: SecretApprovalRequestsSchema }).describe("When secret protection policy is enabled")
])
}
},
onRequest: verifyAuth([
AuthMode.JWT,
AuthMode.API_KEY,
AuthMode.SERVICE_TOKEN,
AuthMode.IDENTITY_ACCESS_TOKEN
]),
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN]),
handler: async (req) => {
const { environment, workspaceId: projectId, secretPath, secrets: inputSecrets } = req.body;
if (req.permission.type === ActorType.USER) {
@@ -1133,18 +1061,17 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
projectId
});
if (policy) {
const approval =
await server.services.secretApprovalRequest.generateSecretApprovalRequest({
actorId: req.permission.id,
actor: req.permission.type,
secretPath,
environment,
projectId,
policy,
data: {
[CommitType.Create]: inputSecrets.filter(({ type }) => type === "shared")
}
});
const approval = await server.services.secretApprovalRequest.generateSecretApprovalRequest({
actorId: req.permission.id,
actor: req.permission.type,
secretPath,
environment,
projectId,
policy,
data: {
[CommitType.Create]: inputSecrets.filter(({ type }) => type === "shared")
}
});
await server.services.auditLog.createAuditLog({
projectId: req.body.workspaceId,
@@ -1236,18 +1163,11 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
z.object({
secrets: SecretsSchema.omit({ secretBlindIndex: true }).array()
}),
z
.object({ approval: SecretApprovalRequestsSchema })
.describe("When secret protection policy is enabled")
z.object({ approval: SecretApprovalRequestsSchema }).describe("When secret protection policy is enabled")
])
}
},
onRequest: verifyAuth([
AuthMode.JWT,
AuthMode.API_KEY,
AuthMode.SERVICE_TOKEN,
AuthMode.IDENTITY_ACCESS_TOKEN
]),
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN]),
handler: async (req) => {
const { environment, workspaceId: projectId, secretPath, secrets: inputSecrets } = req.body;
if (req.permission.type === ActorType.USER) {
@@ -1259,18 +1179,17 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
projectId
});
if (policy) {
const approval =
await server.services.secretApprovalRequest.generateSecretApprovalRequest({
actorId: req.permission.id,
actor: req.permission.type,
secretPath,
environment,
projectId,
policy,
data: {
[CommitType.Update]: inputSecrets.filter(({ type }) => type === "shared")
}
});
const approval = await server.services.secretApprovalRequest.generateSecretApprovalRequest({
actorId: req.permission.id,
actor: req.permission.type,
secretPath,
environment,
projectId,
policy,
data: {
[CommitType.Update]: inputSecrets.filter(({ type }) => type === "shared")
}
});
await server.services.auditLog.createAuditLog({
projectId: req.body.workspaceId,
@@ -1350,18 +1269,11 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
z.object({
secrets: SecretsSchema.omit({ secretBlindIndex: true }).array()
}),
z
.object({ approval: SecretApprovalRequestsSchema })
.describe("When secret protection policy is enabled")
z.object({ approval: SecretApprovalRequestsSchema }).describe("When secret protection policy is enabled")
])
}
},
onRequest: verifyAuth([
AuthMode.JWT,
AuthMode.API_KEY,
AuthMode.SERVICE_TOKEN,
AuthMode.IDENTITY_ACCESS_TOKEN
]),
onRequest: verifyAuth([AuthMode.JWT, AuthMode.API_KEY, AuthMode.SERVICE_TOKEN, AuthMode.IDENTITY_ACCESS_TOKEN]),
handler: async (req) => {
const { environment, workspaceId: projectId, secretPath, secrets: inputSecrets } = req.body;
if (req.permission.type === ActorType.USER) {
@@ -1373,18 +1285,17 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
projectId
});
if (policy) {
const approval =
await server.services.secretApprovalRequest.generateSecretApprovalRequest({
actorId: req.permission.id,
actor: req.permission.type,
secretPath,
environment,
projectId,
policy,
data: {
[CommitType.Delete]: inputSecrets.filter(({ type }) => type === "shared")
}
});
const approval = await server.services.secretApprovalRequest.generateSecretApprovalRequest({
actorId: req.permission.id,
actor: req.permission.type,
secretPath,
environment,
projectId,
policy,
data: {
[CommitType.Delete]: inputSecrets.filter(({ type }) => type === "shared")
}
});
await server.services.auditLog.createAuditLog({
projectId: req.body.workspaceId,
...req.auditLogInfo,

View File

@@ -48,10 +48,7 @@ export const registerSignupRouter = async (server: FastifyZodProvider) => {
}
},
handler: async (req) => {
const { token, user } = await server.services.signup.verifyEmailSignup(
req.body.email,
req.body.code
);
const { token, user } = await server.services.signup.verifyEmailSignup(req.body.email, req.body.code);
return { message: "Successfuly verified email", token, user };
}
});
@@ -93,19 +90,14 @@ export const registerSignupRouter = async (server: FastifyZodProvider) => {
if (!userAgent) throw new Error("user agent header is required");
const appCfg = getConfig();
const { user, accessToken, refreshToken } =
await server.services.signup.completeEmailAccountSignup({
...req.body,
ip: req.realIp,
userAgent,
authorization: req.headers.authorization as string
});
const { user, accessToken, refreshToken } = await server.services.signup.completeEmailAccountSignup({
...req.body,
ip: req.realIp,
userAgent,
authorization: req.headers.authorization as string
});
void server.services.telemetry.sendLoopsEvent(
user.email,
user.firstName || "",
user.lastName || ""
);
void server.services.telemetry.sendLoopsEvent(user.email, user.firstName || "", user.lastName || "");
void server.services.telemetry.sendPostHogEvents({
event: PostHogEventTypes.UserSignedUp,
@@ -161,12 +153,11 @@ export const registerSignupRouter = async (server: FastifyZodProvider) => {
if (!userAgent) throw new Error("user agent header is required");
const appCfg = getConfig();
const { user, accessToken, refreshToken } =
await server.services.signup.completeAccountInvite({
...req.body,
ip: req.realIp,
userAgent
});
const { user, accessToken, refreshToken } = await server.services.signup.completeAccountInvite({
...req.body,
ip: req.realIp,
userAgent
});
await res.setCookie("jid", refreshToken, {
httpOnly: true,

View File

@@ -45,8 +45,7 @@ export const apiKeyServiceFactory = ({ apiKeyDAL, userDAL }: TApiKeyServiceFacto
const deleteApiKey = async (userId: string, apiKeyId: string) => {
const [apiKeyData] = await apiKeyDAL.delete({ id: apiKeyId, userId });
if (!apiKeyData)
throw new BadRequestError({ message: "Failed to find api key", name: "delete api key" });
if (!apiKeyData) throw new BadRequestError({ message: "Failed to find api key", name: "delete api key" });
return formatApiKey(apiKeyData);
};

View File

@@ -12,9 +12,7 @@ export type TTokenDALFactory = ReturnType<typeof tokenDALFactory>;
export const tokenDALFactory = (db: TDbClient) => {
const authOrm = ormify(db, TableName.AuthTokens);
const findOneTokenSession = async (
filter: Partial<TAuthTokenSessions>
): Promise<TAuthTokenSessions | undefined> => {
const findOneTokenSession = async (filter: Partial<TAuthTokenSessions>): Promise<TAuthTokenSessions | undefined> => {
try {
const doc = await db(TableName.AuthTokenSession).where(filter).first();
return doc;
@@ -29,20 +27,14 @@ export const tokenDALFactory = (db: TDbClient) => {
orgId
}: TDeleteTokenForUserDALDTO): Promise<TAuthTokens[] | undefined> => {
try {
const doc = await db(TableName.AuthTokens)
.where({ userId, type, orgId })
.delete()
.returning("*");
const doc = await db(TableName.AuthTokens).where({ userId, type, orgId }).delete().returning("*");
return doc;
} catch (error) {
throw new DatabaseError({ error, name: "DeleteTokenForUser" });
}
};
const decrementTriesField = async ({
userId,
type
}: TDeleteTokenForUserDALDTO): Promise<void> => {
const decrementTriesField = async ({ userId, type }: TDeleteTokenForUserDALDTO): Promise<void> => {
try {
await db(TableName.AuthTokens).where({ userId, type }).decrement("triesLeft", 1);
} catch (error) {
@@ -99,10 +91,7 @@ export const tokenDALFactory = (db: TDbClient) => {
const deleteTokenSession = async (filter: Partial<TAuthTokenSessions>, tx?: Knex) => {
try {
const sessions = await (tx || db)(TableName.AuthTokenSession)
.where(filter)
.del()
.returning("*");
const sessions = await (tx || db)(TableName.AuthTokenSession).where(filter).del().returning("*");
return sessions;
} catch (error) {
throw new DatabaseError({ name: "Delete token session", error });

View File

@@ -9,12 +9,7 @@ import { UnauthorizedError } from "@app/lib/errors";
import { AuthModeJwtTokenPayload } from "../auth/auth-type";
import { TUserDALFactory } from "../user/user-dal";
import { TTokenDALFactory } from "./auth-token-dal";
import {
TCreateTokenForUserDTO,
TIssueAuthTokenDTO,
TokenType,
TValidateTokenForUserDTO
} from "./auth-token-types";
import { TCreateTokenForUserDTO, TIssueAuthTokenDTO, TokenType, TValidateTokenForUserDTO } from "./auth-token-types";
type TAuthTokenServiceFactoryDep = {
tokenDAL: TTokenDALFactory;
@@ -125,14 +120,10 @@ export const tokenServiceFactory = ({ tokenDAL, userDAL }: TAuthTokenServiceFact
return session;
};
const clearTokenSessionById = async (
userId: string,
sessionId: string
): Promise<TAuthTokenSessions | undefined> =>
const clearTokenSessionById = async (userId: string, sessionId: string): Promise<TAuthTokenSessions | undefined> =>
tokenDAL.incrementTokenSessionVersion(userId, sessionId);
const getUserTokenSessionById = async (id: string, userId: string) =>
tokenDAL.findOneTokenSession({ id, userId });
const getUserTokenSessionById = async (id: string, userId: string) => tokenDAL.findOneTokenSession({ id, userId });
const getTokenSessionByUser = async (userId: string) => tokenDAL.findTokenSessions({ userId });
@@ -145,8 +136,7 @@ export const tokenServiceFactory = ({ tokenDAL, userDAL }: TAuthTokenServiceFact
userId: token.userId
});
if (!session) throw new UnauthorizedError({ name: "Session not found" });
if (token.accessVersion !== session.accessVersion)
throw new UnauthorizedError({ name: "Stale session" });
if (token.accessVersion !== session.accessVersion) throw new UnauthorizedError({ name: "Stale session" });
const user = await userDAL.findById(session.userId);
if (!user || !user.isAccepted) throw new UnauthorizedError({ name: "Token user not found" });

View File

@@ -3,19 +3,12 @@ import jwt from "jsonwebtoken";
import { getConfig } from "@app/lib/config/env";
import { BadRequestError, UnauthorizedError } from "@app/lib/errors";
import {
AuthModeProviderJwtTokenPayload,
AuthModeProviderSignUpTokenPayload,
AuthTokenType
} from "./auth-type";
import { AuthModeProviderJwtTokenPayload, AuthModeProviderSignUpTokenPayload, AuthTokenType } from "./auth-type";
export const validateProviderAuthToken = (providerToken: string, email: string) => {
if (!providerToken) throw new UnauthorizedError();
const appCfg = getConfig();
const decodedToken = jwt.verify(
providerToken,
appCfg.AUTH_SECRET
) as AuthModeProviderJwtTokenPayload;
const decodedToken = jwt.verify(providerToken, appCfg.AUTH_SECRET) as AuthModeProviderJwtTokenPayload;
if (decodedToken.authTokenType !== AuthTokenType.PROVIDER_TOKEN) throw new UnauthorizedError();
if (decodedToken.email !== email) throw new Error("Invalid auth credentials");
@@ -23,10 +16,7 @@ export const validateProviderAuthToken = (providerToken: string, email: string)
export const validateSignUpAuthorization = (token: string, userId: string, validate = true) => {
const appCfg = getConfig();
const [AUTH_TOKEN_TYPE, AUTH_TOKEN_VALUE] = <[string, string]>token?.split(" ", 2) ?? [
null,
null
];
const [AUTH_TOKEN_TYPE, AUTH_TOKEN_VALUE] = <[string, string]>token?.split(" ", 2) ?? [null, null];
if (AUTH_TOKEN_TYPE === null) {
throw new BadRequestError({ message: "Missing Authorization Header in the request header." });
}
@@ -41,10 +31,7 @@ export const validateSignUpAuthorization = (token: string, userId: string, valid
});
}
const decodedToken = jwt.verify(
AUTH_TOKEN_VALUE,
appCfg.AUTH_SECRET
) as AuthModeProviderSignUpTokenPayload;
const decodedToken = jwt.verify(AUTH_TOKEN_VALUE, appCfg.AUTH_SECRET) as AuthModeProviderSignUpTokenPayload;
if (!validate) return decodedToken;
if (decodedToken.authTokenType !== AuthTokenType.SIGNUP_TOKEN) throw new UnauthorizedError();

View File

@@ -25,11 +25,7 @@ type TAuthLoginServiceFactoryDep = {
};
export type TAuthLoginFactory = ReturnType<typeof authLoginServiceFactory>;
export const authLoginServiceFactory = ({
userDAL,
tokenService,
smtpService
}: TAuthLoginServiceFactoryDep) => {
export const authLoginServiceFactory = ({ userDAL, tokenService, smtpService }: TAuthLoginServiceFactoryDep) => {
/*
* Private
* Not exported. This is to update user device list
@@ -37,9 +33,7 @@ export const authLoginServiceFactory = ({
*/
const updateUserDeviceSession = async (user: TUsers, ip: string, userAgent: string) => {
const devices = await UserDeviceSchema.parseAsync(user.devices || []);
const isDeviceSeen = devices.some(
(device) => device.ip === ip && device.userAgent === userAgent
);
const isDeviceSeen = devices.some((device) => device.ip === ip && device.userAgent === userAgent);
if (!isDeviceSeen) {
const newDeviceList = devices.concat([{ ip, userAgent }]);
@@ -159,8 +153,7 @@ export const authLoginServiceFactory = ({
validateProviderAuthToken(providerAuthToken as string, email);
}
if (!userEnc.serverPrivateKey || !userEnc.clientPublicKey)
throw new Error("Failed to authenticate. Try again?");
if (!userEnc.serverPrivateKey || !userEnc.clientPublicKey) throw new Error("Failed to authenticate. Try again?");
const isValidClientProof = await srpCheckClientProof(
userEnc.salt,
userEnc.verifier,
@@ -176,11 +169,9 @@ export const authLoginServiceFactory = ({
});
// send multi factor auth token if they it enabled
if (userEnc.isMfaEnabled) {
const mfaToken = jwt.sign(
{ authTokenType: AuthTokenType.MFA_TOKEN, userId: userEnc.userId },
cfg.AUTH_SECRET,
{ expiresIn: cfg.JWT_MFA_LIFETIME }
);
const mfaToken = jwt.sign({ authTokenType: AuthTokenType.MFA_TOKEN, userId: userEnc.userId }, cfg.AUTH_SECRET, {
expiresIn: cfg.JWT_MFA_LIFETIME
});
await sendUserMfaCode(userEnc.userId, userEnc.email);
return { isMfaEnabled: true, token: mfaToken } as const;
@@ -230,8 +221,7 @@ export const authLoginServiceFactory = ({
let user = await userDAL.findUserByEmail(email);
const appCfg = getConfig();
const isOauthSignUpDisabled = !isSignupAllowed && !user;
if (isOauthSignUpDisabled)
throw new BadRequestError({ message: "User signup disabled", name: "Oauth 2 login" });
if (isOauthSignUpDisabled) throw new BadRequestError({ message: "User signup disabled", name: "Oauth 2 login" });
if (!user) {
user = await userDAL.create({ email, firstName, lastName, authMethods: [authMethod] });

View File

@@ -9,11 +9,7 @@ import { TokenType } from "../auth-token/auth-token-types";
import { SmtpTemplates, TSmtpService } from "../smtp/smtp-service";
import { TUserDALFactory } from "../user/user-dal";
import { TAuthDALFactory } from "./auth-dal";
import {
TChangePasswordDTO,
TCreateBackupPrivateKeyDTO,
TResetPasswordViaBackupKeyDTO
} from "./auth-password-type";
import { TChangePasswordDTO, TCreateBackupPrivateKeyDTO, TResetPasswordViaBackupKeyDTO } from "./auth-password-type";
import { AuthTokenType } from "./auth-type";
type TAuthPasswordServiceFactoryDep = {
@@ -70,8 +66,7 @@ export const authPaswordServiceFactory = ({
serverPrivateKey: null,
clientPublicKey: null
});
if (!userEnc.serverPrivateKey || !userEnc.clientPublicKey)
throw new Error("Failed to authenticate. Try again?");
if (!userEnc.serverPrivateKey || !userEnc.clientPublicKey) throw new Error("Failed to authenticate. Try again?");
const isValidClientProof = await srpCheckClientProof(
userEnc.salt,
userEnc.verifier,
@@ -200,8 +195,7 @@ export const authPaswordServiceFactory = ({
throw new Error("Failed to find user");
}
if (!userEnc.clientPublicKey || !userEnc.serverPrivateKey)
throw new Error("failed to create backup key");
if (!userEnc.clientPublicKey || !userEnc.serverPrivateKey) throw new Error("failed to create backup key");
const isValidClientProff = await srpCheckClientProof(
userEnc.salt,
userEnc.verifier,

View File

@@ -148,9 +148,7 @@ export const authSignupServiceFactory = ({
});
const hasSamlEnabled = user?.authMethods?.some((authMethod) =>
[AuthMethod.OKTA_SAML, AuthMethod.AZURE_SAML, AuthMethod.JUMPCLOUD_SAML].includes(
authMethod as AuthMethod
)
[AuthMethod.OKTA_SAML, AuthMethod.AZURE_SAML, AuthMethod.JUMPCLOUD_SAML].includes(authMethod as AuthMethod)
);
if (!hasSamlEnabled) {
@@ -162,9 +160,7 @@ export const authSignupServiceFactory = ({
{ userId: user.id, status: OrgMembershipStatus.Accepted }
);
const uniqueOrgId = [...new Set(updatedMembersips.map(({ orgId }) => orgId))];
await Promise.allSettled(
uniqueOrgId.map((orgId) => licenseService.updateSubscriptionOrgMemberCount(orgId))
);
await Promise.allSettled(uniqueOrgId.map((orgId) => licenseService.updateSubscriptionOrgMemberCount(orgId)));
const tokenSession = await tokenService.getUserTokenSession({
userAgent,
@@ -259,9 +255,7 @@ export const authSignupServiceFactory = ({
tx
);
const uniqueOrgId = [...new Set(updatedMembersips.map(({ orgId }) => orgId))];
await Promise.allSettled(
uniqueOrgId.map((orgId) => licenseService.updateSubscriptionOrgMemberCount(orgId))
);
await Promise.allSettled(uniqueOrgId.map((orgId) => licenseService.updateSubscriptionOrgMemberCount(orgId)));
return { info: us, key: userEncKey };
});

View File

@@ -14,11 +14,7 @@ export const identityAccessTokenDALFactory = (db: TDbClient) => {
try {
const doc = await (tx || db)(TableName.IdentityAccessToken)
.where(filter)
.join(
TableName.Identity,
`${TableName.Identity}.id`,
`${TableName.IdentityAccessToken}.identityId`
)
.join(TableName.Identity, `${TableName.Identity}.id`, `${TableName.IdentityAccessToken}.identityId`)
.leftJoin(
TableName.IdentityUaClientSecret,
`${TableName.IdentityAccessToken}.identityUAClientSecretId`,

View File

@@ -7,18 +7,13 @@ import { checkIPAgainstBlocklist, TIp } from "@app/lib/ip";
import { AuthTokenType } from "../auth/auth-type";
import { TIdentityAccessTokenDALFactory } from "./identity-access-token-dal";
import {
TIdentityAccessTokenJwtPayload,
TRenewAccessTokenDTO
} from "./identity-access-token-types";
import { TIdentityAccessTokenJwtPayload, TRenewAccessTokenDTO } from "./identity-access-token-types";
type TIdentityAccessTokenServiceFactoryDep = {
identityAccessTokenDAL: TIdentityAccessTokenDALFactory;
};
export type TIdentityAccessTokenServiceFactory = ReturnType<
typeof identityAccessTokenServiceFactory
>;
export type TIdentityAccessTokenServiceFactory = ReturnType<typeof identityAccessTokenServiceFactory>;
export const identityAccessTokenServiceFactory = ({
identityAccessTokenDAL
@@ -33,11 +28,7 @@ export const identityAccessTokenServiceFactory = ({
createdAt: accessTokenCreatedAt
} = identityAccessToken;
if (
accessTokenNumUsesLimit > 0 &&
accessTokenNumUses > 0 &&
accessTokenNumUses >= accessTokenNumUsesLimit
) {
if (accessTokenNumUsesLimit > 0 && accessTokenNumUses > 0 && accessTokenNumUses >= accessTokenNumUsesLimit) {
throw new BadRequestError({
message: "Unable to renew because access token number of uses limit reached"
});
@@ -95,8 +86,7 @@ export const identityAccessTokenServiceFactory = ({
const decodedToken = jwt.verify(accessToken, appCfg.AUTH_SECRET) as JwtPayload & {
identityAccessTokenId: string;
};
if (decodedToken.authTokenType !== AuthTokenType.IDENTITY_ACCESS_TOKEN)
throw new UnauthorizedError();
if (decodedToken.authTokenType !== AuthTokenType.IDENTITY_ACCESS_TOKEN) throw new UnauthorizedError();
const identityAccessToken = await identityAccessTokenDAL.findOne({
[`${TableName.IdentityAccessToken}.id` as "id"]: decodedToken.identityAccessTokenId,
@@ -106,20 +96,14 @@ export const identityAccessTokenServiceFactory = ({
validateAccessTokenExp(identityAccessToken);
const updatedIdentityAccessToken = await identityAccessTokenDAL.updateById(
identityAccessToken.id,
{
accessTokenLastRenewedAt: new Date()
}
);
const updatedIdentityAccessToken = await identityAccessTokenDAL.updateById(identityAccessToken.id, {
accessTokenLastRenewedAt: new Date()
});
return { accessToken, identityAccessToken: updatedIdentityAccessToken };
};
const fnValidateIdentityAccessToken = async (
token: TIdentityAccessTokenJwtPayload,
ipAddress?: string
) => {
const fnValidateIdentityAccessToken = async (token: TIdentityAccessTokenJwtPayload, ipAddress?: string) => {
const identityAccessToken = await identityAccessTokenDAL.findOne({
[`${TableName.IdentityAccessToken}.id` as "id"]: token.identityAccessTokenId,
isAccessTokenRevoked: false

View File

@@ -14,11 +14,7 @@ export const identityProjectDALFactory = (db: TDbClient) => {
try {
const docs = await (tx || db)(TableName.IdentityProjectMembership)
.where(`${TableName.IdentityProjectMembership}.projectId`, projectId)
.join(
TableName.Identity,
`${TableName.IdentityProjectMembership}.identityId`,
`${TableName.Identity}.id`
)
.join(TableName.Identity, `${TableName.IdentityProjectMembership}.identityId`, `${TableName.Identity}.id`)
.leftJoin(
TableName.ProjectRoles,
`${TableName.IdentityProjectMembership}.roleId`,

View File

@@ -2,10 +2,7 @@ import { ForbiddenError } from "@casl/ability";
import { ProjectMembershipRole, TProjectRoles } from "@app/db/schemas";
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
import {
ProjectPermissionActions,
ProjectPermissionSub
} from "@app/ee/services/permission/project-permission";
import { ProjectPermissionActions, ProjectPermissionSub } from "@app/ee/services/permission/project-permission";
import { isAtLeastAsPrivileged } from "@app/lib/casl";
import { BadRequestError, ForbiddenRequestError } from "@app/lib/errors";
@@ -24,10 +21,7 @@ type TIdentityProjectServiceFactoryDep = {
identityProjectDAL: TIdentityProjectDALFactory;
projectDAL: Pick<TProjectDALFactory, "findById">;
identityOrgMembershipDAL: Pick<TIdentityOrgDALFactory, "findOne">;
permissionService: Pick<
TPermissionServiceFactory,
"getProjectPermission" | "getProjectPermissionByRole"
>;
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission" | "getProjectPermissionByRole">;
};
export type TIdentityProjectServiceFactory = ReturnType<typeof identityProjectServiceFactory>;
@@ -38,18 +32,9 @@ export const identityProjectServiceFactory = ({
identityOrgMembershipDAL,
projectDAL
}: TIdentityProjectServiceFactoryDep) => {
const createProjectIdentity = async ({
identityId,
actor,
actorId,
projectId,
role
}: TCreateProjectIdentityDTO) => {
const createProjectIdentity = async ({ identityId, actor, actorId, projectId, role }: TCreateProjectIdentityDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId);
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Create,
ProjectPermissionSub.Identity
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Create, ProjectPermissionSub.Identity);
const existingIdentity = await identityProjectDAL.findOne({ identityId, projectId });
if (existingIdentity)
@@ -67,8 +52,10 @@ export const identityProjectServiceFactory = ({
message: `Failed to find identity with id ${identityId}`
});
const { permission: rolePermission, role: customRole } =
await permissionService.getProjectPermissionByRole(role, project.id);
const { permission: rolePermission, role: customRole } = await permissionService.getProjectPermissionByRole(
role,
project.id
);
const hasPriviledge = isAtLeastAsPrivileged(permission, rolePermission);
if (!hasPriviledge)
throw new ForbiddenRequestError({
@@ -85,18 +72,9 @@ export const identityProjectServiceFactory = ({
return projectIdentity;
};
const updateProjectIdentity = async ({
projectId,
identityId,
role,
actor,
actorId
}: TUpdateProjectIdentityDTO) => {
const updateProjectIdentity = async ({ projectId, identityId, role, actor, actorId }: TUpdateProjectIdentityDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId);
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Edit,
ProjectPermissionSub.Identity
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Identity);
const projectIdentity = await identityProjectDAL.findOne({ identityId, projectId });
if (!projectIdentity)
@@ -115,8 +93,10 @@ export const identityProjectServiceFactory = ({
let customRole: TProjectRoles | undefined;
if (role) {
const { permission: rolePermission, role: customOrgRole } =
await permissionService.getProjectPermissionByRole(role, projectIdentity.projectId);
const { permission: rolePermission, role: customOrgRole } = await permissionService.getProjectPermissionByRole(
role,
projectIdentity.projectId
);
const isCustomRole = Boolean(customOrgRole);
const hasRequiredNewRolePermission = isAtLeastAsPrivileged(permission, rolePermission);
@@ -135,12 +115,7 @@ export const identityProjectServiceFactory = ({
return updatedProjectIdentity;
};
const deleteProjectIdentity = async ({
identityId,
actorId,
actor,
projectId
}: TDeleteProjectIdentityDTO) => {
const deleteProjectIdentity = async ({ identityId, actorId, actor, projectId }: TDeleteProjectIdentityDTO) => {
const identityProjectMembership = await identityProjectDAL.findOne({ identityId, projectId });
if (!identityProjectMembership)
throw new BadRequestError({ message: `Failed to find identity with id ${identityId}` });
@@ -150,10 +125,7 @@ export const identityProjectServiceFactory = ({
actorId,
identityProjectMembership.projectId
);
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Delete,
ProjectPermissionSub.Identity
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Delete, ProjectPermissionSub.Identity);
const { permission: identityRolePermission } = await permissionService.getProjectPermission(
ActorType.IDENTITY,
identityId,
@@ -169,10 +141,7 @@ export const identityProjectServiceFactory = ({
const listProjectIdentities = async ({ projectId, actor, actorId }: TListProjectIdentityDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId);
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Read,
ProjectPermissionSub.Identity
);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.Identity);
const identityMemberhips = await identityProjectDAL.findByProjectId(projectId);
return identityMemberhips;

View File

@@ -6,10 +6,7 @@ import jwt from "jsonwebtoken";
import { IdentityAuthMethod } from "@app/db/schemas";
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
import {
OrgPermissionActions,
OrgPermissionSubjects
} from "@app/ee/services/permission/org-permission";
import { OrgPermissionActions, OrgPermissionSubjects } from "@app/ee/services/permission/org-permission";
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
import { isAtLeastAsPrivileged } from "@app/lib/casl";
import { getConfig } from "@app/lib/config/env";
@@ -71,8 +68,7 @@ export const identityUaServiceFactory = ({
);
if (!validClientSecretInfo) throw new UnauthorizedError();
const { clientSecretTTL, clientSecretNumUses, clientSecretNumUsesLimit } =
validClientSecretInfo;
const { clientSecretTTL, clientSecretNumUses, clientSecretNumUsesLimit } = validClientSecretInfo;
if (clientSecretTTL > 0) {
const clientSecretCreated = new Date(validClientSecretInfo.createdAt);
const ttlInMilliseconds = clientSecretTTL * 1000;
@@ -97,16 +93,12 @@ export const identityUaServiceFactory = ({
isClientSecretRevoked: true
});
throw new UnauthorizedError({
message:
"Failed to authenticate identity credentials due to client secret number of uses limit reached"
message: "Failed to authenticate identity credentials due to client secret number of uses limit reached"
});
}
const identityAccessToken = await identityUaDAL.transaction(async (tx) => {
const uaClientSecretDoc = await identityUaClientSecretDAL.incrementUsage(
validClientSecretInfo.id,
tx
);
const uaClientSecretDoc = await identityUaClientSecretDAL.incrementUsage(validClientSecretInfo.id, tx);
const newToken = await identityAccessTokenDAL.create(
{
identityId: identityUa.identityId,
@@ -132,10 +124,7 @@ export const identityUaServiceFactory = ({
} as TIdentityAccessTokenJwtPayload,
appCfg.AUTH_SECRET,
{
expiresIn:
identityAccessToken.accessTokenMaxTTL === 0
? undefined
: identityAccessToken.accessTokenMaxTTL
expiresIn: identityAccessToken.accessTokenMaxTTL === 0 ? undefined : identityAccessToken.accessTokenMaxTTL
}
);
return { accessToken, identityUa, validClientSecretInfo, identityAccessToken };
@@ -162,35 +151,26 @@ export const identityUaServiceFactory = ({
throw new BadRequestError({ message: "Access token TTL cannot be greater than max TTL" });
}
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId
);
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Create,
OrgPermissionSubjects.Identity
);
const { permission } = await permissionService.getOrgPermission(actor, actorId, identityMembershipOrg.orgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.Identity);
const plan = await licenseService.getPlan(identityMembershipOrg.orgId);
const reformattedClientSecretTrustedIps = clientSecretTrustedIps.map(
(clientSecretTrustedIp) => {
if (
!plan.ipAllowlisting &&
clientSecretTrustedIp.ipAddress !== "0.0.0.0/0" &&
clientSecretTrustedIp.ipAddress !== "::/0"
)
throw new BadRequestError({
message:
"Failed to add IP access range to service token due to plan restriction. Upgrade plan to add IP access range."
});
if (!isValidIpOrCidr(clientSecretTrustedIp.ipAddress))
throw new BadRequestError({
message: "The IP is not a valid IPv4, IPv6, or CIDR block"
});
return extractIPDetails(clientSecretTrustedIp.ipAddress);
}
);
const reformattedClientSecretTrustedIps = clientSecretTrustedIps.map((clientSecretTrustedIp) => {
if (
!plan.ipAllowlisting &&
clientSecretTrustedIp.ipAddress !== "0.0.0.0/0" &&
clientSecretTrustedIp.ipAddress !== "::/0"
)
throw new BadRequestError({
message:
"Failed to add IP access range to service token due to plan restriction. Upgrade plan to add IP access range."
});
if (!isValidIpOrCidr(clientSecretTrustedIp.ipAddress))
throw new BadRequestError({
message: "The IP is not a valid IPv4, IPv6, or CIDR block"
});
return extractIPDetails(clientSecretTrustedIp.ipAddress);
});
const reformattedAccessTokenTrustedIps = accessTokenTrustedIps.map((accessTokenTrustedIp) => {
if (
!plan.ipAllowlisting &&
@@ -254,41 +234,31 @@ export const identityUaServiceFactory = ({
if (
(accessTokenMaxTTL || uaIdentityAuth.accessTokenMaxTTL) > 0 &&
(accessTokenTTL || uaIdentityAuth.accessTokenMaxTTL) >
(accessTokenMaxTTL || uaIdentityAuth.accessTokenMaxTTL)
(accessTokenTTL || uaIdentityAuth.accessTokenMaxTTL) > (accessTokenMaxTTL || uaIdentityAuth.accessTokenMaxTTL)
) {
throw new BadRequestError({ message: "Access token TTL cannot be greater than max TTL" });
}
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId
);
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Edit,
OrgPermissionSubjects.Identity
);
const { permission } = await permissionService.getOrgPermission(actor, actorId, identityMembershipOrg.orgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Identity);
const plan = await licenseService.getPlan(identityMembershipOrg.orgId);
const reformattedClientSecretTrustedIps = clientSecretTrustedIps?.map(
(clientSecretTrustedIp) => {
if (
!plan.ipAllowlisting &&
clientSecretTrustedIp.ipAddress !== "0.0.0.0/0" &&
clientSecretTrustedIp.ipAddress !== "::/0"
)
throw new BadRequestError({
message:
"Failed to add IP access range to service token due to plan restriction. Upgrade plan to add IP access range."
});
if (!isValidIpOrCidr(clientSecretTrustedIp.ipAddress))
throw new BadRequestError({
message: "The IP is not a valid IPv4, IPv6, or CIDR block"
});
return extractIPDetails(clientSecretTrustedIp.ipAddress);
}
);
const reformattedClientSecretTrustedIps = clientSecretTrustedIps?.map((clientSecretTrustedIp) => {
if (
!plan.ipAllowlisting &&
clientSecretTrustedIp.ipAddress !== "0.0.0.0/0" &&
clientSecretTrustedIp.ipAddress !== "::/0"
)
throw new BadRequestError({
message:
"Failed to add IP access range to service token due to plan restriction. Upgrade plan to add IP access range."
});
if (!isValidIpOrCidr(clientSecretTrustedIp.ipAddress))
throw new BadRequestError({
message: "The IP is not a valid IPv4, IPv6, or CIDR block"
});
return extractIPDetails(clientSecretTrustedIp.ipAddress);
});
const reformattedAccessTokenTrustedIps = accessTokenTrustedIps?.map((accessTokenTrustedIp) => {
if (
!plan.ipAllowlisting &&
@@ -330,15 +300,8 @@ export const identityUaServiceFactory = ({
const uaIdentityAuth = await identityUaDAL.findOne({ identityId });
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId
);
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.Identity
);
const { permission } = await permissionService.getOrgPermission(actor, actorId, identityMembershipOrg.orgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Identity);
return { ...uaIdentityAuth, orgId: identityMembershipOrg.orgId };
};
@@ -356,15 +319,8 @@ export const identityUaServiceFactory = ({
throw new BadRequestError({
message: "The identity does not have universal auth"
});
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId
);
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Create,
OrgPermissionSubjects.Identity
);
const { permission } = await permissionService.getOrgPermission(actor, actorId, identityMembershipOrg.orgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.Identity);
const { permission: rolePermission } = await permissionService.getOrgPermission(
ActorType.IDENTITY,
@@ -409,15 +365,8 @@ export const identityUaServiceFactory = ({
throw new BadRequestError({
message: "The identity does not have universal auth"
});
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId
);
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.Identity
);
const { permission } = await permissionService.getOrgPermission(actor, actorId, identityMembershipOrg.orgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Identity);
const { permission: rolePermission } = await permissionService.getOrgPermission(
ActorType.IDENTITY,
@@ -441,27 +390,15 @@ export const identityUaServiceFactory = ({
return { clientSecrets, orgId: identityMembershipOrg.orgId };
};
const revokeUaClientSecret = async ({
identityId,
actorId,
actor,
clientSecretId
}: TRevokeUaClientSecretDTO) => {
const revokeUaClientSecret = async ({ identityId, actorId, actor, clientSecretId }: TRevokeUaClientSecretDTO) => {
const identityMembershipOrg = await identityOrgMembershipDAL.findOne({ identityId });
if (!identityMembershipOrg) throw new BadRequestError({ message: "Failed to find identity" });
if (identityMembershipOrg.identity?.authMethod !== IdentityAuthMethod.Univeral)
throw new BadRequestError({
message: "The identity does not have universal auth"
});
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityMembershipOrg.orgId
);
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Delete,
OrgPermissionSubjects.Identity
);
const { permission } = await permissionService.getOrgPermission(actor, actorId, identityMembershipOrg.orgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Delete, OrgPermissionSubjects.Identity);
const { permission: rolePermission } = await permissionService.getOrgPermission(
ActorType.IDENTITY,

View File

@@ -14,11 +14,7 @@ export const identityOrgDALFactory = (db: TDbClient) => {
try {
const [data] = await (tx || db)(TableName.IdentityOrgMembership)
.where(filter)
.join(
TableName.Identity,
`${TableName.IdentityOrgMembership}.identityId`,
`${TableName.Identity}.id`
)
.join(TableName.Identity, `${TableName.IdentityOrgMembership}.identityId`, `${TableName.Identity}.id`)
.select(selectAllTableCols(TableName.IdentityOrgMembership))
.select(db.ref("name").withSchema(TableName.Identity))
.select(db.ref("authMethod").withSchema(TableName.Identity));
@@ -35,16 +31,8 @@ export const identityOrgDALFactory = (db: TDbClient) => {
try {
const docs = await (tx || db)(TableName.IdentityOrgMembership)
.where(`${TableName.IdentityOrgMembership}.orgId`, orgId)
.join(
TableName.Identity,
`${TableName.IdentityOrgMembership}.identityId`,
`${TableName.Identity}.id`
)
.leftJoin(
TableName.OrgRoles,
`${TableName.IdentityOrgMembership}.roleId`,
`${TableName.OrgRoles}.id`
)
.join(TableName.Identity, `${TableName.IdentityOrgMembership}.identityId`, `${TableName.Identity}.id`)
.leftJoin(TableName.OrgRoles, `${TableName.IdentityOrgMembership}.roleId`, `${TableName.OrgRoles}.id`)
.select(selectAllTableCols(TableName.IdentityOrgMembership))
// cr stands for custom role
.select(db.ref("id").as("crId").withSchema(TableName.OrgRoles))

View File

@@ -1,10 +1,7 @@
import { ForbiddenError } from "@casl/ability";
import { OrgMembershipRole, TOrgRoles } from "@app/db/schemas";
import {
OrgPermissionActions,
OrgPermissionSubjects
} from "@app/ee/services/permission/org-permission";
import { OrgPermissionActions, OrgPermissionSubjects } from "@app/ee/services/permission/org-permission";
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
import { isAtLeastAsPrivileged } from "@app/lib/casl";
import { BadRequestError, ForbiddenRequestError } from "@app/lib/errors";
@@ -30,17 +27,15 @@ export const identityServiceFactory = ({
}: TIdentityServiceFactoryDep) => {
const createIdentity = async ({ name, role, actor, orgId, actorId }: TCreateIdentityDTO) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId);
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Create,
OrgPermissionSubjects.Identity
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.Identity);
const { permission: rolePermission, role: customRole } =
await permissionService.getOrgPermissionByRole(role, orgId);
const { permission: rolePermission, role: customRole } = await permissionService.getOrgPermissionByRole(
role,
orgId
);
const isCustomRole = Boolean(customRole);
const hasRequiredPriviledges = isAtLeastAsPrivileged(permission, rolePermission);
if (!hasRequiredPriviledges)
throw new BadRequestError({ message: "Failed to create a more privileged identity" });
if (!hasRequiredPriviledges) throw new BadRequestError({ message: "Failed to create a more privileged identity" });
const identity = await identityDAL.transaction(async (tx) => {
const newIdentity = await identityDAL.create({ name }, tx);
@@ -61,18 +56,10 @@ export const identityServiceFactory = ({
const updateIdentity = async ({ id, role, name, actor, actorId }: TUpdateIdentityDTO) => {
const identityOrgMembership = await identityOrgMembershipDAL.findOne({ identityId: id });
if (!identityOrgMembership)
throw new BadRequestError({ message: `Failed to find identity with id ${id}` });
if (!identityOrgMembership) throw new BadRequestError({ message: `Failed to find identity with id ${id}` });
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityOrgMembership.orgId
);
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Edit,
OrgPermissionSubjects.Identity
);
const { permission } = await permissionService.getOrgPermission(actor, actorId, identityOrgMembership.orgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.Identity);
const { permission: identityRolePermission } = await permissionService.getOrgPermission(
ActorType.IDENTITY,
@@ -85,8 +72,10 @@ export const identityServiceFactory = ({
let customRole: TOrgRoles | undefined;
if (role) {
const { permission: rolePermission, role: customOrgRole } =
await permissionService.getOrgPermissionByRole(role, identityOrgMembership.orgId);
const { permission: rolePermission, role: customOrgRole } = await permissionService.getOrgPermissionByRole(
role,
identityOrgMembership.orgId
);
const isCustomRole = Boolean(customOrgRole);
const hasRequiredNewRolePermission = isAtLeastAsPrivileged(permission, rolePermission);
@@ -96,9 +85,7 @@ export const identityServiceFactory = ({
}
const identity = await identityDAL.transaction(async (tx) => {
const newIdentity = name
? await identityDAL.updateById(id, { name }, tx)
: await identityDAL.findById(id, tx);
const newIdentity = name ? await identityDAL.updateById(id, { name }, tx) : await identityDAL.findById(id, tx);
if (role) {
await identityOrgMembershipDAL.update(
{ identityId: id },
@@ -117,18 +104,10 @@ export const identityServiceFactory = ({
const deleteIdentity = async ({ actorId, actor, id }: TDeleteIdentityDTO) => {
const identityOrgMembership = await identityOrgMembershipDAL.findOne({ identityId: id });
if (!identityOrgMembership)
throw new BadRequestError({ message: `Failed to find identity with id ${id}` });
if (!identityOrgMembership) throw new BadRequestError({ message: `Failed to find identity with id ${id}` });
const { permission } = await permissionService.getOrgPermission(
actor,
actorId,
identityOrgMembership.orgId
);
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Delete,
OrgPermissionSubjects.Identity
);
const { permission } = await permissionService.getOrgPermission(actor, actorId, identityOrgMembership.orgId);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Delete, OrgPermissionSubjects.Identity);
const { permission: identityRolePermission } = await permissionService.getOrgPermission(
ActorType.IDENTITY,
id,
@@ -144,10 +123,7 @@ export const identityServiceFactory = ({
const listOrgIdentities = async ({ orgId, actor, actorId }: TOrgPermission) => {
const { permission } = await permissionService.getOrgPermission(actor, actorId, orgId);
ForbiddenError.from(permission).throwUnlessCan(
OrgPermissionActions.Read,
OrgPermissionSubjects.Identity
);
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.Identity);
const identityMemberhips = await identityOrgMembershipDAL.findByOrgId(orgId);
return identityMemberhips;

Some files were not shown because too many files have changed in this diff Show More