Merge branch 'main' into snyk-fix-71fbba54e9eda81c90db390106760c64

This commit is contained in:
Maidul Islam
2024-02-16 12:12:48 -05:00
committed by GitHub
763 changed files with 6890 additions and 107517 deletions
+21 -16
View File
@@ -1,27 +1,39 @@
/* eslint-env node */
module.exports = {
root: true,
env: {
browser: true,
es2021: true
es6: true,
node: true
},
extends: ["airbnb-base", "airbnb-typescript/base", "prettier"],
plugins: ["prettier", "simple-import-sort", "import"],
extends: [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:@typescript-eslint/recommended-type-checked",
"airbnb-base",
"airbnb-typescript/base",
"plugin:prettier/recommended",
"prettier"
],
plugins: ["@typescript-eslint", "simple-import-sort", "import"],
parser: "@typescript-eslint/parser",
parserOptions: {
ecmaVersion: "latest",
project: true,
sourceType: "module",
project: "./tsconfig.json",
tsconfigRootDir: __dirname
},
root: true,
rules: {
// "@typescript-eslint/no-empty-function": "off",
"@typescript-eslint/no-empty-function": "off",
"@typescript-eslint/no-unsafe-enum-comparison": "off",
"no-void": "off",
"consistent-return": "off", // my style
"import/order": "off", // for simple-import-order
"import/prefer-default-export": "off", // why
"no-restricted-syntax": "off",
// importing rules
"simple-import-sort/exports": "error",
"import/first": "error",
"import/newline-after-import": "error",
"import/no-duplicates": "error",
"simple-import-sort/exports": "error",
"simple-import-sort/imports": [
"warn",
{
@@ -45,12 +57,5 @@ module.exports = {
]
}
]
},
settings: {
"import/resolver": {
typescript: {
project: ["./tsconfig.json"]
}
}
}
};
+2 -2
View File
@@ -1,7 +1,7 @@
{
"singleQuote": false,
"printWidth": 100,
"printWidth": 120,
"trailingComma": "none",
"tabWidth": 2,
"semi": true
}
}
+2
View File
@@ -28,6 +28,8 @@ RUN apk add --no-cache bash curl && curl -1sLf \
HEALTHCHECK --interval=10s --timeout=3s --start-period=10s \
CMD node healthcheck.js
ENV HOST=0.0.0.0
EXPOSE 4000
CMD ["npm", "start"]
+3 -1
View File
@@ -16,9 +16,11 @@ export const mockQueue = (): TQueueServiceFactory => {
queues[name] = jobFn;
workers[name] = jobFn;
},
listen: async (name, event) => {
listen: (name, event) => {
events[name] = event;
},
clearQueue: async () => {},
stopJobById: async () => {},
stopRepeatableJobByJobId: async () => true
};
};
+1220 -509
View File
File diff suppressed because it is too large Load Diff
+11 -7
View File
@@ -2,12 +2,12 @@
"name": "backend",
"version": "1.0.0",
"description": "",
"main": "index.js",
"main": "./dist/main.mjs",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "tsx watch --clear-screen=false ./src/main.ts | pino-pretty --colorize --colorizeObjects --singleLine",
"dev:docker": "nodemon",
"build": "rimraf dist && tsup",
"build": "tsup",
"start": "node dist/main.mjs",
"type:check": "tsc --noEmit",
"lint:fix": "eslint --fix --ext js,ts ./src",
@@ -44,11 +44,13 @@
"@types/pg": "^8.10.9",
"@types/picomatch": "^2.3.3",
"@types/prompt-sync": "^4.2.3",
"@types/resolve": "^1.20.6",
"@types/uuid": "^9.0.7",
"@typescript-eslint/eslint-plugin": "^6.13.2",
"@typescript-eslint/parser": "^6.13.2",
"@typescript-eslint/eslint-plugin": "^6.20.0",
"@typescript-eslint/parser": "^6.20.0",
"eslint": "^8.56.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-config-airbnb-typescript": "^17.1.0",
"eslint-config-prettier": "^9.1.0",
"eslint-import-resolver-typescript": "^3.6.1",
"eslint-plugin-import": "^2.29.1",
@@ -59,6 +61,7 @@
"prompt-sync": "^4.2.0",
"rimraf": "^5.0.5",
"ts-node": "^10.9.1",
"tsc-alias": "^1.8.8",
"tsconfig-paths": "^4.2.0",
"tsup": "^8.0.1",
"tsx": "^4.4.0",
@@ -71,6 +74,7 @@
"@casl/ability": "^6.5.0",
"@fastify/cookie": "^9.2.0",
"@fastify/cors": "^8.4.1",
"@fastify/etag": "^5.1.0",
"@fastify/formbody": "^7.4.0",
"@fastify/helmet": "^11.1.1",
"@fastify/passport": "^2.4.0",
@@ -81,6 +85,7 @@
"@node-saml/passport-saml": "^4.0.4",
"@octokit/rest": "^20.0.2",
"@octokit/webhooks-types": "^7.3.1",
"@serdnam/pino-cloudwatch-transport": "^1.0.4",
"@sindresorhus/slugify": "^2.2.1",
"@ucast/mongo2js": "^1.3.4",
"ajv": "^8.12.0",
@@ -91,7 +96,6 @@
"bcrypt": "^5.1.1",
"bullmq": "^5.1.1",
"dotenv": "^16.3.1",
"eslint-config-airbnb-typescript": "^17.1.0",
"fastify": "^4.24.3",
"fastify-plugin": "^4.5.1",
"handlebars": "^4.7.8",
@@ -105,7 +109,7 @@
"mysql2": "^3.6.5",
"nanoid": "^5.0.4",
"node-cache": "^5.1.2",
"nodemailer": "^6.9.7",
"nodemailer": "^6.9.9",
"ora": "^7.0.1",
"passport-github": "^1.1.0",
"passport-gitlab2": "^5.0.0",
@@ -122,4 +126,4 @@
"zod": "^3.22.4",
"zod-to-json-schema": "^3.22.0"
}
}
}
+6 -29
View File
@@ -3,13 +3,9 @@ import dotenv from "dotenv";
import path from "path";
import knex from "knex";
import { writeFileSync } from "fs";
import promptSync from "prompt-sync";
const prompt = promptSync({ sigint: true });
dotenv.config({
path: path.join(__dirname, "../.env"),
debug: true
path: path.join(__dirname, "../../.env.migration")
});
const db = knex({
@@ -94,17 +90,7 @@ const main = async () => {
.orderBy("table_name")
).filter((el) => !el.tableName.includes("_migrations"));
console.log("Select a table to generate schema");
console.table(tables);
console.log("all: all tables");
const selectedTables = prompt("Type table numbers comma seperated: ");
const tableNumbers =
selectedTables !== "all" ? selectedTables.split(",").map((el) => Number(el)) : [];
for (let i = 0; i < tables.length; i += 1) {
// skip if not desired table
if (selectedTables !== "all" && !tableNumbers.includes(i)) continue;
const { tableName } = tables[i];
const columns = await db(tableName).columnInfo();
const columnNames = Object.keys(columns);
@@ -124,16 +110,16 @@ const main = async () => {
if (colInfo.nullable) {
ztype = ztype.concat(".nullable().optional()");
}
schema = schema.concat(`${!schema ? "\n" : ""} ${columnName}: ${ztype},\n`);
schema = schema.concat(
`${!schema ? "\n" : ""} ${columnName}: ${ztype}${colNum === columnNames.length - 1 ? "" : ","}\n`
);
}
const dashcase = tableName.split("_").join("-");
const pascalCase = tableName
.split("_")
.reduce(
(prev, curr) => prev + `${curr.at(0)?.toUpperCase()}${curr.slice(1).toLowerCase()}`,
""
);
.reduce((prev, curr) => prev + `${curr.at(0)?.toUpperCase()}${curr.slice(1).toLowerCase()}`, "");
writeFileSync(
path.join(__dirname, "../src/db/schemas", `${dashcase}.ts`),
`// Code generated by automation script, DO NOT EDIT.
@@ -152,15 +138,6 @@ export type T${pascalCase}Insert = Omit<T${pascalCase}, TImmutableDBKeys>;
export type T${pascalCase}Update = Partial<Omit<T${pascalCase}, TImmutableDBKeys>>;
`
);
// const file = readFileSync(path.join(__dirname, "../src/db/schemas/index.ts"), "utf8");
// if (!file.includes(`export * from "./${dashcase};"`)) {
// appendFileSync(
// path.join(__dirname, "../src/db/schemas/index.ts"),
// `\nexport * from "./${dashcase}";`,
// "utf8"
// );
// }
}
process.exit(0);
+1 -6
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";
+2
View File
@@ -51,6 +51,7 @@ declare module "fastify" {
// used for mfa session authentication
mfa: {
userId: string;
orgId?: string;
user: TUsers;
};
// identity injection. depending on which kinda of token the information is filled in auth
@@ -58,6 +59,7 @@ declare module "fastify" {
permission: {
type: ActorType;
id: string;
orgId?: string;
};
// passport data
passportUser: {
+18 -90
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,
+10 -2
View File
@@ -1,10 +1,18 @@
import knex from "knex";
export type TDbClient = ReturnType<typeof initDbConnection>;
export const initDbConnection = (dbConnectionUri: string) => {
export const initDbConnection = ({ dbConnectionUri, dbRootCert }: { dbConnectionUri: string; dbRootCert?: string }) => {
const db = knex({
client: "pg",
connection: dbConnectionUri
connection: {
connectionString: dbConnectionUri,
ssl: dbRootCert
? {
rejectUnauthorized: true,
ca: Buffer.from(dbRootCert, "base64").toString("ascii")
}
: false
}
});
return db;
+2 -2
View File
@@ -5,9 +5,9 @@ import dotenv from "dotenv";
import type { Knex } from "knex";
import path from "path";
// Update with your config settings.
// Update with your config settings. .
dotenv.config({
path: path.join(__dirname, "../../.env"),
path: path.join(__dirname, "../../../.env.migration"),
debug: true
});
export default {
@@ -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> {
@@ -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");
@@ -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);
@@ -19,7 +19,7 @@ export async function up(knex: Knex): Promise<void> {
.references("id")
.inTable(TableName.IdentityUaClientSecret)
.onDelete("CASCADE");
t.uuid("identityId").notNullable();
t.uuid("identityId").notNullable();
t.foreign("identityId").references("id").inTable(TableName.Identity).onDelete("CASCADE");
t.timestamps(true, true, true);
});
@@ -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);
});
}
@@ -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);
@@ -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");
});
}
}
@@ -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);
@@ -15,7 +15,7 @@ export async function up(knex: Knex): Promise<void> {
t.timestamps(true, true, true);
});
}
createOnUpdateTrigger(knex, TableName.GitAppInstallSession);
await createOnUpdateTrigger(knex, TableName.GitAppInstallSession);
if (!(await knex.schema.hasTable(TableName.GitAppOrg))) {
await knex.schema.createTable(TableName.GitAppOrg, (t) => {
@@ -28,7 +28,7 @@ export async function up(knex: Knex): Promise<void> {
t.timestamps(true, true, true);
});
}
createOnUpdateTrigger(knex, TableName.GitAppOrg);
await createOnUpdateTrigger(knex, TableName.GitAppOrg);
if (!(await knex.schema.hasTable(TableName.SecretScanningGitRisk))) {
await knex.schema.createTable(TableName.SecretScanningGitRisk, (t) => {
@@ -66,7 +66,7 @@ export async function up(knex: Knex): Promise<void> {
t.timestamps(true, true, true);
});
}
createOnUpdateTrigger(knex, TableName.SecretScanningGitRisk);
await createOnUpdateTrigger(knex, TableName.SecretScanningGitRisk);
}
export async function down(knex: Knex): Promise<void> {
@@ -0,0 +1,25 @@
import { Knex } from "knex";
import { TableName } from "../schemas";
export async function up(knex: Knex): Promise<void> {
await knex.schema.alterTable(TableName.Organization, (t) => {
t.boolean("authEnforced").defaultTo(false);
t.index("slug");
});
await knex.schema.alterTable(TableName.SamlConfig, (t) => {
t.datetime("lastUsed");
});
}
export async function down(knex: Knex): Promise<void> {
await knex.schema.alterTable(TableName.Organization, (t) => {
t.dropColumn("authEnforced");
t.dropIndex("slug");
});
await knex.schema.alterTable(TableName.SamlConfig, (t) => {
t.dropColumn("lastUsed");
});
}
+1 -1
View File
@@ -15,7 +15,7 @@ export const ApiKeysSchema = z.object({
secretHash: z.string(),
createdAt: z.date(),
updatedAt: z.date(),
userId: z.string().uuid(),
userId: z.string().uuid()
});
export type TApiKeys = z.infer<typeof ApiKeysSchema>;
+1 -1
View File
@@ -20,7 +20,7 @@ export const AuditLogsSchema = z.object({
createdAt: z.date(),
updatedAt: z.date(),
orgId: z.string().uuid().nullable().optional(),
projectId: z.string().nullable().optional(),
projectId: z.string().nullable().optional()
});
export type TAuditLogs = z.infer<typeof AuditLogsSchema>;
@@ -16,7 +16,7 @@ export const AuthTokenSessionsSchema = z.object({
lastUsed: z.date(),
createdAt: z.date(),
updatedAt: z.date(),
userId: z.string().uuid(),
userId: z.string().uuid()
});
export type TAuthTokenSessions = z.infer<typeof AuthTokenSessionsSchema>;
+1 -1
View File
@@ -17,7 +17,7 @@ export const AuthTokensSchema = z.object({
createdAt: z.date(),
updatedAt: z.date(),
userId: z.string().uuid().nullable().optional(),
orgId: z.string().uuid().nullable().optional(),
orgId: z.string().uuid().nullable().optional()
});
export type TAuthTokens = z.infer<typeof AuthTokensSchema>;
+1 -1
View File
@@ -18,7 +18,7 @@ export const BackupPrivateKeySchema = z.object({
verifier: z.string(),
createdAt: z.date(),
updatedAt: z.date(),
userId: z.string().uuid(),
userId: z.string().uuid()
});
export type TBackupPrivateKey = z.infer<typeof BackupPrivateKeySchema>;
@@ -13,7 +13,7 @@ export const GitAppInstallSessionsSchema = z.object({
userId: z.string().uuid().nullable().optional(),
orgId: z.string().uuid(),
createdAt: z.date(),
updatedAt: z.date(),
updatedAt: z.date()
});
export type TGitAppInstallSessions = z.infer<typeof GitAppInstallSessionsSchema>;
+1 -1
View File
@@ -13,7 +13,7 @@ export const GitAppOrgSchema = z.object({
userId: z.string().uuid(),
orgId: z.string().uuid(),
createdAt: z.date(),
updatedAt: z.date(),
updatedAt: z.date()
});
export type TGitAppOrg = z.infer<typeof GitAppOrgSchema>;
+1 -1
View File
@@ -12,7 +12,7 @@ export const IdentitiesSchema = z.object({
name: z.string(),
authMethod: z.string().nullable().optional(),
createdAt: z.date(),
updatedAt: z.date(),
updatedAt: z.date()
});
export type TIdentities = z.infer<typeof IdentitiesSchema>;
@@ -8,7 +8,7 @@ import { z } from "zod";
import { TImmutableDBKeys } from "./models";
export const IdentityAccessTokensSchema = z.object({
id: z.string().uuid(),
id: z.string(),
accessTokenTTL: z.coerce.number().default(2592000),
accessTokenMaxTTL: z.coerce.number().default(2592000),
accessTokenNumUses: z.coerce.number().default(0),
@@ -19,7 +19,7 @@ export const IdentityAccessTokensSchema = z.object({
identityUAClientSecretId: z.string().nullable().optional(),
identityId: z.string().uuid(),
createdAt: z.date(),
updatedAt: z.date(),
updatedAt: z.date()
});
export type TIdentityAccessTokens = z.infer<typeof IdentityAccessTokensSchema>;
@@ -14,7 +14,7 @@ export const IdentityOrgMembershipsSchema = z.object({
orgId: z.string().uuid(),
createdAt: z.date(),
updatedAt: z.date(),
identityId: z.string().uuid(),
identityId: z.string().uuid()
});
export type TIdentityOrgMemberships = z.infer<typeof IdentityOrgMembershipsSchema>;
@@ -14,7 +14,7 @@ export const IdentityProjectMembershipsSchema = z.object({
projectId: z.string(),
identityId: z.string().uuid(),
createdAt: z.date(),
updatedAt: z.date(),
updatedAt: z.date()
});
export type TIdentityProjectMemberships = z.infer<typeof IdentityProjectMembershipsSchema>;
@@ -19,7 +19,7 @@ export const IdentityUaClientSecretsSchema = z.object({
isClientSecretRevoked: z.boolean().default(false),
createdAt: z.date(),
updatedAt: z.date(),
identityUAId: z.string().uuid(),
identityUAId: z.string().uuid()
});
export type TIdentityUaClientSecrets = z.infer<typeof IdentityUaClientSecretsSchema>;
@@ -17,7 +17,7 @@ export const IdentityUniversalAuthsSchema = z.object({
accessTokenTrustedIps: z.unknown(),
createdAt: z.date(),
updatedAt: z.date(),
identityId: z.string().uuid(),
identityId: z.string().uuid()
});
export type TIdentityUniversalAuths = z.infer<typeof IdentityUniversalAuthsSchema>;
+1 -1
View File
@@ -12,7 +12,7 @@ export const IncidentContactsSchema = z.object({
email: z.string(),
createdAt: z.date(),
updatedAt: z.date(),
orgId: z.string().uuid(),
orgId: z.string().uuid()
});
export type TIncidentContacts = z.infer<typeof IncidentContactsSchema>;
+1 -1
View File
@@ -29,7 +29,7 @@ export const IntegrationAuthsSchema = z.object({
keyEncoding: z.string(),
projectId: z.string(),
createdAt: z.date(),
updatedAt: z.date(),
updatedAt: z.date()
});
export type TIntegrationAuths = z.infer<typeof IntegrationAuthsSchema>;
+2 -2
View File
@@ -25,9 +25,9 @@ export const IntegrationsSchema = z.object({
metadata: z.unknown().nullable().optional(),
integrationAuthId: z.string().uuid(),
envId: z.string().uuid(),
secretPath: z.string().default('/'),
secretPath: z.string().default("/"),
createdAt: z.date(),
updatedAt: z.date(),
updatedAt: z.date()
});
export type TIntegrations = z.infer<typeof IntegrationsSchema>;
+1 -1
View File
@@ -23,7 +23,7 @@ export const OrgBotsSchema = z.object({
privateKeyKeyEncoding: z.string(),
orgId: z.string().uuid(),
createdAt: z.date(),
updatedAt: z.date(),
updatedAt: z.date()
});
export type TOrgBots = z.infer<typeof OrgBotsSchema>;
+2 -2
View File
@@ -10,13 +10,13 @@ import { TImmutableDBKeys } from "./models";
export const OrgMembershipsSchema = z.object({
id: z.string().uuid(),
role: z.string(),
status: z.string().default('invited'),
status: z.string().default("invited"),
inviteEmail: z.string().nullable().optional(),
createdAt: z.date(),
updatedAt: z.date(),
userId: z.string().uuid().nullable().optional(),
orgId: z.string().uuid(),
roleId: z.string().uuid().nullable().optional(),
roleId: z.string().uuid().nullable().optional()
});
export type TOrgMemberships = z.infer<typeof OrgMembershipsSchema>;
+1 -1
View File
@@ -15,7 +15,7 @@ export const OrgRolesSchema = z.object({
permissions: z.unknown(),
createdAt: z.date(),
updatedAt: z.date(),
orgId: z.string().uuid(),
orgId: z.string().uuid()
});
export type TOrgRoles = z.infer<typeof OrgRolesSchema>;
+2 -1
View File
@@ -13,7 +13,8 @@ export const OrganizationsSchema = z.object({
customerId: z.string().nullable().optional(),
slug: z.string(),
createdAt: z.date(),
updatedAt: z.date()
updatedAt: z.date(),
authEnforced: z.boolean().default(false).nullable().optional()
});
export type TOrganizations = z.infer<typeof OrganizationsSchema>;
+1 -1
View File
@@ -22,7 +22,7 @@ export const ProjectBotsSchema = z.object({
projectId: z.string(),
senderId: z.string().uuid().nullable().optional(),
createdAt: z.date(),
updatedAt: z.date(),
updatedAt: z.date()
});
export type TProjectBots = z.infer<typeof ProjectBotsSchema>;
@@ -14,7 +14,7 @@ export const ProjectEnvironmentsSchema = z.object({
position: z.number(),
projectId: z.string(),
createdAt: z.date(),
updatedAt: z.date(),
updatedAt: z.date()
});
export type TProjectEnvironments = z.infer<typeof ProjectEnvironmentsSchema>;
+1 -1
View File
@@ -15,7 +15,7 @@ export const ProjectKeysSchema = z.object({
senderId: z.string().uuid().nullable().optional(),
projectId: z.string(),
createdAt: z.date(),
updatedAt: z.date(),
updatedAt: z.date()
});
export type TProjectKeys = z.infer<typeof ProjectKeysSchema>;
@@ -14,7 +14,7 @@ export const ProjectMembershipsSchema = z.object({
updatedAt: z.date(),
userId: z.string().uuid(),
projectId: z.string(),
roleId: z.string().uuid().nullable().optional(),
roleId: z.string().uuid().nullable().optional()
});
export type TProjectMemberships = z.infer<typeof ProjectMembershipsSchema>;
+1 -1
View File
@@ -15,7 +15,7 @@ export const ProjectRolesSchema = z.object({
permissions: z.unknown(),
createdAt: z.date(),
updatedAt: z.date(),
projectId: z.string(),
projectId: z.string()
});
export type TProjectRoles = z.infer<typeof ProjectRolesSchema>;
+1 -1
View File
@@ -14,7 +14,7 @@ export const ProjectsSchema = z.object({
autoCapitalization: z.boolean().default(true).nullable().optional(),
orgId: z.string().uuid(),
createdAt: z.date(),
updatedAt: z.date(),
updatedAt: z.date()
});
export type TProjects = z.infer<typeof ProjectsSchema>;
+1
View File
@@ -23,6 +23,7 @@ export const SamlConfigsSchema = z.object({
createdAt: z.date(),
updatedAt: z.date(),
orgId: z.string().uuid(),
lastUsed: z.date().nullable().optional()
});
export type TSamlConfigs = z.infer<typeof SamlConfigsSchema>;
@@ -12,7 +12,7 @@ export const SecretApprovalPoliciesApproversSchema = z.object({
approverId: z.string().uuid(),
policyId: z.string().uuid(),
createdAt: z.date(),
updatedAt: z.date(),
updatedAt: z.date()
});
export type TSecretApprovalPoliciesApprovers = z.infer<typeof SecretApprovalPoliciesApproversSchema>;
@@ -14,7 +14,7 @@ export const SecretApprovalPoliciesSchema = z.object({
approvals: z.number().default(1),
envId: z.string().uuid(),
createdAt: z.date(),
updatedAt: z.date(),
updatedAt: z.date()
});
export type TSecretApprovalPolicies = z.infer<typeof SecretApprovalPoliciesSchema>;
@@ -12,7 +12,7 @@ export const SecretApprovalRequestSecretTagsSchema = z.object({
secretId: z.string().uuid(),
tagId: z.string().uuid(),
createdAt: z.date(),
updatedAt: z.date(),
updatedAt: z.date()
});
export type TSecretApprovalRequestSecretTags = z.infer<typeof SecretApprovalRequestSecretTagsSchema>;
@@ -13,7 +13,7 @@ export const SecretApprovalRequestsReviewersSchema = z.object({
status: z.string(),
requestId: z.string().uuid(),
createdAt: z.date(),
updatedAt: z.date(),
updatedAt: z.date()
});
export type TSecretApprovalRequestsReviewers = z.infer<typeof SecretApprovalRequestsReviewersSchema>;
@@ -10,7 +10,7 @@ import { TImmutableDBKeys } from "./models";
export const SecretApprovalRequestsSecretsSchema = z.object({
id: z.string().uuid(),
version: z.number().default(1).nullable().optional(),
secretBlindIndex: z.string(),
secretBlindIndex: z.string().nullable().optional(),
secretKeyCiphertext: z.string(),
secretKeyIV: z.string(),
secretKeyTag: z.string(),
@@ -23,15 +23,15 @@ export const SecretApprovalRequestsSecretsSchema = z.object({
secretReminderNote: z.string().nullable().optional(),
secretReminderRepeatDays: z.number().nullable().optional(),
skipMultilineEncoding: z.boolean().default(false).nullable().optional(),
algorithm: z.string().default('aes-256-gcm'),
keyEncoding: z.string().default('utf8'),
algorithm: z.string().default("aes-256-gcm"),
keyEncoding: z.string().default("utf8"),
metadata: z.unknown().nullable().optional(),
createdAt: z.date(),
updatedAt: z.date(),
requestId: z.string().uuid(),
op: z.string(),
secretId: z.string().uuid().nullable().optional(),
secretVersion: z.string().uuid().nullable().optional(),
secretVersion: z.string().uuid().nullable().optional()
});
export type TSecretApprovalRequestsSecrets = z.infer<typeof SecretApprovalRequestsSecretsSchema>;
@@ -11,14 +11,14 @@ export const SecretApprovalRequestsSchema = z.object({
id: z.string().uuid(),
policyId: z.string().uuid(),
hasMerged: z.boolean().default(false),
status: z.string().default('open'),
status: z.string().default("open"),
conflicts: z.unknown().nullable().optional(),
slug: z.string(),
folderId: z.string().uuid(),
statusChangeBy: z.string().uuid().nullable().optional(),
committerId: z.string().uuid(),
createdAt: z.date(),
updatedAt: z.date(),
updatedAt: z.date()
});
export type TSecretApprovalRequests = z.infer<typeof SecretApprovalRequestsSchema>;
@@ -12,11 +12,11 @@ export const SecretBlindIndexesSchema = z.object({
encryptedSaltCipherText: z.string(),
saltIV: z.string(),
saltTag: z.string(),
algorithm: z.string().default('aes-256-gcm'),
keyEncoding: z.string().default('utf8'),
algorithm: z.string().default("aes-256-gcm"),
keyEncoding: z.string().default("utf8"),
projectId: z.string(),
createdAt: z.date(),
updatedAt: z.date(),
updatedAt: z.date()
});
export type TSecretBlindIndexes = z.infer<typeof SecretBlindIndexesSchema>;
@@ -14,7 +14,7 @@ export const SecretFolderVersionsSchema = z.object({
createdAt: z.date(),
updatedAt: z.date(),
envId: z.string().uuid(),
folderId: z.string().uuid(),
folderId: z.string().uuid()
});
export type TSecretFolderVersions = z.infer<typeof SecretFolderVersionsSchema>;
+1 -1
View File
@@ -14,7 +14,7 @@ export const SecretFoldersSchema = z.object({
createdAt: z.date(),
updatedAt: z.date(),
envId: z.string().uuid(),
parentId: z.string().uuid().nullable().optional(),
parentId: z.string().uuid().nullable().optional()
});
export type TSecretFolders = z.infer<typeof SecretFoldersSchema>;
+1 -1
View File
@@ -15,7 +15,7 @@ export const SecretImportsSchema = z.object({
position: z.number(),
createdAt: z.date(),
updatedAt: z.date(),
folderId: z.string().uuid(),
folderId: z.string().uuid()
});
export type TSecretImports = z.infer<typeof SecretImportsSchema>;
@@ -11,7 +11,7 @@ export const SecretRotationOutputsSchema = z.object({
id: z.string().uuid(),
key: z.string(),
secretId: z.string().uuid(),
rotationId: z.string().uuid(),
rotationId: z.string().uuid()
});
export type TSecretRotationOutputs = z.infer<typeof SecretRotationOutputsSchema>;
+1 -1
View File
@@ -22,7 +22,7 @@ export const SecretRotationsSchema = z.object({
keyEncoding: z.string().nullable().optional(),
envId: z.string().uuid(),
createdAt: z.date(),
updatedAt: z.date(),
updatedAt: z.date()
});
export type TSecretRotations = z.infer<typeof SecretRotationsSchema>;
@@ -38,7 +38,7 @@ export const SecretScanningGitRisksSchema = z.object({
status: z.string().nullable().optional(),
orgId: z.string().uuid(),
createdAt: z.date(),
updatedAt: z.date(),
updatedAt: z.date()
});
export type TSecretScanningGitRisks = z.infer<typeof SecretScanningGitRisksSchema>;
@@ -13,7 +13,7 @@ export const SecretSnapshotFoldersSchema = z.object({
folderVersionId: z.string().uuid(),
snapshotId: z.string().uuid(),
createdAt: z.date(),
updatedAt: z.date(),
updatedAt: z.date()
});
export type TSecretSnapshotFolders = z.infer<typeof SecretSnapshotFoldersSchema>;
@@ -13,7 +13,7 @@ export const SecretSnapshotSecretsSchema = z.object({
secretVersionId: z.string().uuid(),
snapshotId: z.string().uuid(),
createdAt: z.date(),
updatedAt: z.date(),
updatedAt: z.date()
});
export type TSecretSnapshotSecrets = z.infer<typeof SecretSnapshotSecretsSchema>;
+1 -1
View File
@@ -13,7 +13,7 @@ export const SecretSnapshotsSchema = z.object({
folderId: z.string().uuid(),
parentFolderId: z.string().uuid().nullable().optional(),
createdAt: z.date(),
updatedAt: z.date(),
updatedAt: z.date()
});
export type TSecretSnapshots = z.infer<typeof SecretSnapshotsSchema>;
@@ -10,7 +10,7 @@ import { TImmutableDBKeys } from "./models";
export const SecretTagJunctionSchema = z.object({
id: z.string().uuid(),
secretsId: z.string().uuid(),
secret_tagsId: z.string().uuid(),
secret_tagsId: z.string().uuid()
});
export type TSecretTagJunction = z.infer<typeof SecretTagJunctionSchema>;
+1 -1
View File
@@ -15,7 +15,7 @@ export const SecretTagsSchema = z.object({
createdAt: z.date(),
updatedAt: z.date(),
createdBy: z.string().uuid().nullable().optional(),
projectId: z.string(),
projectId: z.string()
});
export type TSecretTags = z.infer<typeof SecretTagsSchema>;
@@ -10,7 +10,7 @@ import { TImmutableDBKeys } from "./models";
export const SecretVersionTagJunctionSchema = z.object({
id: z.string().uuid(),
secret_versionsId: z.string().uuid(),
secret_tagsId: z.string().uuid(),
secret_tagsId: z.string().uuid()
});
export type TSecretVersionTagJunction = z.infer<typeof SecretVersionTagJunctionSchema>;
+5 -5
View File
@@ -10,8 +10,8 @@ import { TImmutableDBKeys } from "./models";
export const SecretVersionsSchema = z.object({
id: z.string().uuid(),
version: z.number().default(1),
type: z.string().default('shared'),
secretBlindIndex: z.string(),
type: z.string().default("shared"),
secretBlindIndex: z.string().nullable().optional(),
secretKeyCiphertext: z.string(),
secretKeyIV: z.string(),
secretKeyTag: z.string(),
@@ -24,15 +24,15 @@ export const SecretVersionsSchema = z.object({
secretReminderNote: z.string().nullable().optional(),
secretReminderRepeatDays: z.number().nullable().optional(),
skipMultilineEncoding: z.boolean().default(false).nullable().optional(),
algorithm: z.string().default('aes-256-gcm'),
keyEncoding: z.string().default('utf8'),
algorithm: z.string().default("aes-256-gcm"),
keyEncoding: z.string().default("utf8"),
metadata: z.unknown().nullable().optional(),
envId: z.string().uuid().nullable().optional(),
secretId: z.string().uuid(),
folderId: z.string().uuid(),
userId: z.string().uuid().nullable().optional(),
createdAt: z.date(),
updatedAt: z.date(),
updatedAt: z.date()
});
export type TSecretVersions = z.infer<typeof SecretVersionsSchema>;
+5 -5
View File
@@ -10,8 +10,8 @@ import { TImmutableDBKeys } from "./models";
export const SecretsSchema = z.object({
id: z.string().uuid(),
version: z.number().default(1),
type: z.string().default('shared'),
secretBlindIndex: z.string(),
type: z.string().default("shared"),
secretBlindIndex: z.string().nullable().optional(),
secretKeyCiphertext: z.string(),
secretKeyIV: z.string(),
secretKeyTag: z.string(),
@@ -24,13 +24,13 @@ export const SecretsSchema = z.object({
secretReminderNote: z.string().nullable().optional(),
secretReminderRepeatDays: z.number().nullable().optional(),
skipMultilineEncoding: z.boolean().default(false).nullable().optional(),
algorithm: z.string().default('aes-256-gcm'),
keyEncoding: z.string().default('utf8'),
algorithm: z.string().default("aes-256-gcm"),
keyEncoding: z.string().default("utf8"),
metadata: z.unknown().nullable().optional(),
userId: z.string().uuid().nullable().optional(),
folderId: z.string().uuid(),
createdAt: z.date(),
updatedAt: z.date(),
updatedAt: z.date()
});
export type TSecrets = z.infer<typeof SecretsSchema>;
+1 -1
View File
@@ -21,7 +21,7 @@ export const ServiceTokensSchema = z.object({
createdAt: z.date(),
updatedAt: z.date(),
createdBy: z.string(),
projectId: z.string(),
projectId: z.string()
});
export type TServiceTokens = z.infer<typeof ServiceTokensSchema>;
+1 -1
View File
@@ -12,7 +12,7 @@ export const SuperAdminSchema = z.object({
initialized: z.boolean().default(false).nullable().optional(),
allowSignUp: z.boolean().default(true).nullable().optional(),
createdAt: z.date(),
updatedAt: z.date(),
updatedAt: z.date()
});
export type TSuperAdmin = z.infer<typeof SuperAdminSchema>;
+1 -1
View File
@@ -16,7 +16,7 @@ export const TrustedIpsSchema = z.object({
comment: z.string().nullable().optional(),
projectId: z.string(),
createdAt: z.date(),
updatedAt: z.date(),
updatedAt: z.date()
});
export type TTrustedIps = z.infer<typeof TrustedIpsSchema>;
+1 -1
View File
@@ -12,7 +12,7 @@ export const UserActionsSchema = z.object({
action: z.string(),
createdAt: z.date(),
updatedAt: z.date(),
userId: z.string().uuid(),
userId: z.string().uuid()
});
export type TUserActions = z.infer<typeof UserActionsSchema>;
@@ -12,16 +12,16 @@ export const UserEncryptionKeysSchema = z.object({
clientPublicKey: z.string().nullable().optional(),
serverPrivateKey: z.string().nullable().optional(),
encryptionVersion: z.number().default(2).nullable().optional(),
protectedKey: z.string().nullable(),
protectedKeyIV: z.string().nullable(),
protectedKeyTag: z.string().nullable(),
protectedKey: z.string().nullable().optional(),
protectedKeyIV: z.string().nullable().optional(),
protectedKeyTag: z.string().nullable().optional(),
publicKey: z.string(),
encryptedPrivateKey: z.string(),
iv: z.string(),
tag: z.string(),
salt: z.string(),
verifier: z.string(),
userId: z.string().uuid(),
userId: z.string().uuid()
});
export type TUserEncryptionKeys = z.infer<typeof UserEncryptionKeysSchema>;
+1 -1
View File
@@ -19,7 +19,7 @@ export const UsersSchema = z.object({
mfaMethods: z.string().array().nullable().optional(),
devices: z.unknown().nullable().optional(),
createdAt: z.date(),
updatedAt: z.date(),
updatedAt: z.date()
});
export type TUsers = z.infer<typeof UsersSchema>;
+2 -2
View File
@@ -9,7 +9,7 @@ import { TImmutableDBKeys } from "./models";
export const WebhooksSchema = z.object({
id: z.string().uuid(),
secretPath: z.string().default('/'),
secretPath: z.string().default("/"),
url: z.string(),
lastStatus: z.string().nullable().optional(),
lastRunErrorMessage: z.string().nullable().optional(),
@@ -21,7 +21,7 @@ export const WebhooksSchema = z.object({
keyEncoding: z.string().nullable().optional(),
createdAt: z.date(),
updatedAt: z.date(),
envId: z.string().uuid(),
envId: z.string().uuid()
});
export type TWebhooks = z.infer<typeof WebhooksSchema>;
+6 -8
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,
+2 -2
View File
@@ -14,7 +14,7 @@ export async function seed(knex: Knex): Promise<void> {
const [user] = await knex(TableName.Users)
.insert([
{
// @ts-ignore to calculate predefined
// @ts-expect-error exluded type id needs to be inserted here to keep it testable
id: seedData1.id,
email: seedData1.email,
superAdmin: true,
@@ -48,7 +48,7 @@ export async function seed(knex: Knex): Promise<void> {
]);
await knex(TableName.AuthTokenSession).insert({
// @ts-ignore
// @ts-expect-error exluded type id needs to be inserted here to keep it testable
id: seedData1.token.id,
userId: seedData1.id,
ip: "151.196.220.213",
+1 -1
View File
@@ -14,7 +14,7 @@ export async function seed(knex: Knex): Promise<void> {
const [org] = await knex(TableName.Organization)
.insert([
{
// @ts-ignore because we need that id for api calls
// @ts-expect-error exluded type id needs to be inserted here to keep it testable
id: seedData1.organization.id,
name: "infisical",
slug: "infisical",
+2 -4
View File
@@ -20,7 +20,7 @@ export async function seed(knex: Knex): Promise<void> {
name: seedData1.project.name,
orgId: seedData1.organization.id,
slug: "first-project",
// @ts-ignore pre calc id
// @ts-expect-error exluded type id needs to be inserted here to keep it testable
id: seedData1.project.id
})
.returning("*");
@@ -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 })));
}
+1 -6
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
+40 -1
View File
@@ -1,3 +1,6 @@
/* eslint-disable @typescript-eslint/no-unsafe-return */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
// TODO(akhilmhdh): Fix this when licence service gets it type
import { z } from "zod";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
@@ -19,6 +22,7 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
const data = await server.services.license.getOrgPlansTableByBillCycle({
actorId: req.permission.id,
actor: req.permission.type,
actorOrgId: req.permission.orgId,
orgId: req.params.organizationId,
billingCycle: req.query.billingCycle
});
@@ -40,6 +44,7 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
const plan = await server.services.license.getOrgPlan({
actorId: req.permission.id,
actor: req.permission.type,
actorOrgId: req.permission.orgId,
orgId: req.params.organizationId
});
return { plan };
@@ -79,9 +84,10 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => {
const data = await server.services.license.startOrgTrail({
const data = await server.services.license.startOrgTrial({
actorId: req.permission.id,
actor: req.permission.type,
actorOrgId: req.permission.orgId,
orgId: req.params.organizationId,
success_url: req.body.success_url
});
@@ -89,6 +95,27 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
}
});
server.route({
url: "/:organizationId/customer-portal-session",
method: "POST",
schema: {
params: z.object({ organizationId: z.string().trim() }),
response: {
200: z.any()
}
},
onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => {
const data = await server.services.license.createOrganizationPortalSession({
actorId: req.permission.id,
actor: req.permission.type,
actorOrgId: req.permission.orgId,
orgId: req.params.organizationId
});
return data;
}
});
server.route({
url: "/:organizationId/plan/billing",
method: "GET",
@@ -103,6 +130,7 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
const data = await server.services.license.getOrgBillingInfo({
actorId: req.permission.id,
actor: req.permission.type,
actorOrgId: req.permission.orgId,
orgId: req.params.organizationId
});
return data;
@@ -123,6 +151,7 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
const data = await server.services.license.getOrgPlanTable({
actorId: req.permission.id,
actor: req.permission.type,
actorOrgId: req.permission.orgId,
orgId: req.params.organizationId
});
return data;
@@ -143,6 +172,7 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
const data = await server.services.license.getOrgBillingDetails({
actorId: req.permission.id,
actor: req.permission.type,
actorOrgId: req.permission.orgId,
orgId: req.params.organizationId
});
return data;
@@ -167,6 +197,7 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
const data = await server.services.license.updateOrgBillingDetails({
actorId: req.permission.id,
actor: req.permission.type,
actorOrgId: req.permission.orgId,
orgId: req.params.organizationId,
name: req.body.name,
email: req.body.email
@@ -189,6 +220,7 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
const data = await server.services.license.getOrgPmtMethods({
actorId: req.permission.id,
actor: req.permission.type,
actorOrgId: req.permission.orgId,
orgId: req.params.organizationId
});
return data;
@@ -213,6 +245,7 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
const data = await server.services.license.addOrgPmtMethods({
actorId: req.permission.id,
actor: req.permission.type,
actorOrgId: req.permission.orgId,
orgId: req.params.organizationId,
success_url: req.body.success_url,
cancel_url: req.body.cancel_url
@@ -238,6 +271,7 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
const data = await server.services.license.delOrgPmtMethods({
actorId: req.permission.id,
actor: req.permission.type,
actorOrgId: req.permission.orgId,
orgId: req.params.organizationId,
pmtMethodId: req.params.pmtMethodId
});
@@ -261,6 +295,7 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
const data = await server.services.license.getOrgTaxIds({
actorId: req.permission.id,
actor: req.permission.type,
actorOrgId: req.permission.orgId,
orgId: req.params.organizationId
});
return data;
@@ -287,6 +322,7 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
const data = await server.services.license.addOrgTaxId({
actorId: req.permission.id,
actor: req.permission.type,
actorOrgId: req.permission.orgId,
orgId: req.params.organizationId,
type: req.body.type,
value: req.body.value
@@ -312,6 +348,7 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
const data = await server.services.license.delOrgTaxId({
actorId: req.permission.id,
actor: req.permission.type,
actorOrgId: req.permission.orgId,
orgId: req.params.organizationId,
taxId: req.params.taxId
});
@@ -335,6 +372,7 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
const data = await server.services.license.getOrgTaxInvoices({
actorId: req.permission.id,
actor: req.permission.type,
actorOrgId: req.permission.orgId,
orgId: req.params.organizationId
});
return data;
@@ -357,6 +395,7 @@ export const registerLicenseRouter = async (server: FastifyZodProvider) => {
const data = await server.services.license.getOrgLicenses({
actorId: req.permission.id,
actor: req.permission.type,
actorOrgId: req.permission.orgId,
orgId: req.params.organizationId
});
return data;
+10 -10
View File
@@ -26,11 +26,11 @@ 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
req.body,
req.permission.orgId
);
return { role };
}
@@ -58,12 +58,12 @@ export const registerOrgRoleRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => {
const role = await server.services.orgRole.updateRole(
req.permission.id,
req.params.organizationId,
req.params.roleId,
req.body
req.body,
req.permission.orgId
);
return { role };
}
@@ -85,11 +85,11 @@ export const registerOrgRoleRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => {
const role = await server.services.orgRole.deleteRole(
req.permission.id,
req.params.organizationId,
req.params.roleId
req.params.roleId,
req.permission.orgId
);
return { role };
}
@@ -114,10 +114,10 @@ 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
req.params.organizationId,
req.permission.orgId
);
return { data: { roles } };
}
@@ -139,10 +139,10 @@ export const registerOrgRoleRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => {
const { permissions, membership } = await server.services.orgRole.getUserPermission(
req.permission.id,
req.params.organizationId
req.params.organizationId,
req.permission.orgId
);
return { permissions, membership };
}
@@ -30,7 +30,8 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
req.permission.type,
req.permission.id,
req.params.projectId,
req.body
req.body,
req.permission.orgId
);
return { role };
}
@@ -63,7 +64,8 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
req.permission.id,
req.params.projectId,
req.params.roleId,
req.body
req.body,
req.permission.orgId
);
return { role };
}
@@ -89,7 +91,8 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
req.permission.type,
req.permission.id,
req.params.projectId,
req.params.roleId
req.params.roleId,
req.permission.orgId
);
return { role };
}
@@ -117,7 +120,8 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
const roles = await server.services.projectRole.listRoles(
req.permission.type,
req.permission.id,
req.params.projectId
req.params.projectId,
req.permission.orgId
);
return { data: { roles } };
}
@@ -141,10 +145,10 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
},
onRequest: verifyAuth([AuthMode.JWT]),
handler: async (req) => {
const { permissions, membership } = await server.services.projectRole.getUserPermission(
req.permission.id,
req.params.projectId
req.params.projectId,
req.permission.orgId
);
return { data: { permissions, membership } };
}
+20 -2
View File
@@ -2,6 +2,7 @@ import { z } from "zod";
import { AuditLogsSchema, SecretSnapshotsSchema } from "@app/db/schemas";
import { EventType, UserAgentType } from "@app/ee/services/audit-log/audit-log-types";
import { removeTrailingSlash } from "@app/lib/fn";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
@@ -10,12 +11,19 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
method: "GET",
url: "/:workspaceId/secret-snapshots",
schema: {
description: "Return project secret snapshots ids",
security: [
{
apiKeyAuth: [],
bearerAuth: []
}
],
params: z.object({
workspaceId: z.string().trim()
}),
querystring: z.object({
environment: z.string().trim(),
path: z.string().trim().default("/"),
path: z.string().trim().default("/").transform(removeTrailingSlash),
offset: z.coerce.number().default(0),
limit: z.coerce.number().default(20)
}),
@@ -30,6 +38,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
const secretSnapshots = await server.services.snapshot.listSnapshots({
actor: req.permission.type,
actorId: req.permission.id,
actorOrgId: req.permission.orgId,
projectId: req.params.workspaceId,
...req.query
});
@@ -46,7 +55,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
}),
querystring: z.object({
environment: z.string().trim(),
path: z.string().trim().default("/")
path: z.string().trim().default("/").transform(removeTrailingSlash)
}),
response: {
200: z.object({
@@ -59,6 +68,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
const count = await server.services.snapshot.projectSecretSnapshotCount({
actor: req.permission.type,
actorId: req.permission.id,
actorOrgId: req.permission.orgId,
projectId: req.params.workspaceId,
environment: req.query.environment,
path: req.query.path
@@ -71,6 +81,13 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
method: "GET",
url: "/:workspaceId/audit-logs",
schema: {
description: "Return audit logs",
security: [
{
bearerAuth: [],
apiKeyAuth: []
}
],
params: z.object({
workspaceId: z.string().trim()
}),
@@ -111,6 +128,7 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
handler: async (req) => {
const auditLogs = await server.services.auditLog.listProjectAuditLogs({
actorId: req.permission.id,
actorOrgId: req.permission.orgId,
projectId: req.params.workspaceId,
...req.query,
auditLogActor: req.query.actor,
+77 -26
View File
@@ -1,3 +1,11 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/no-unsafe-return */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-argument */
// All the any rules are disabled because passport typesense with fastify is really poor
import { Authenticator } from "@fastify/passport";
import fastifySession from "@fastify/session";
import { MultiSamlStrategy } from "@node-saml/passport-saml";
@@ -5,13 +13,12 @@ import { FastifyRequest } from "fastify";
import { z } from "zod";
import { SamlConfigsSchema } from "@app/db/schemas";
import { SamlProviders } from "@app/ee/services/saml-config/saml-config-types";
import { SamlProviders, TGetSamlCfgDTO } from "@app/ee/services/saml-config/saml-config-types";
import { getConfig } from "@app/lib/config/env";
import { BadRequestError } from "@app/lib/errors";
import { logger } from "@app/lib/logger";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
import { getServerCfg } from "@app/services/super-admin/super-admin-service";
type TSAMLConfig = {
callbackUrl: string;
@@ -20,6 +27,7 @@ type TSAMLConfig = {
cert: string;
audience: string;
wantAuthnResponseSigned?: boolean;
disableRequestedAuthnContext?: boolean;
};
export const registerSamlRouter = async (server: FastifyZodProvider) => {
@@ -33,19 +41,33 @@ export const registerSamlRouter = async (server: FastifyZodProvider) => {
new MultiSamlStrategy(
{
passReqToCallback: true,
// eslint-disable-next-line
getSamlOptions: async (req, done) => {
try {
const { ssoIdentifier } = req.params;
if (!ssoIdentifier) throw new BadRequestError({ message: "Missing sso identitier" });
const { samlConfigId, orgSlug } = req.params;
const ssoConfig = await server.services.saml.getSaml({
type: "ssoId",
id: ssoIdentifier
});
if (!ssoConfig) throw new BadRequestError({ message: "SSO config not found" });
let ssoLookupDetails: TGetSamlCfgDTO;
if (orgSlug) {
ssoLookupDetails = {
type: "orgSlug",
orgSlug
};
} else if (samlConfigId) {
ssoLookupDetails = {
type: "ssoId",
id: samlConfigId
};
} else {
throw new BadRequestError({ message: "Missing sso identitier or org slug" });
}
const ssoConfig = await server.services.saml.getSaml(ssoLookupDetails);
if (!ssoConfig || !ssoConfig.isActive)
throw new BadRequestError({ message: "Failed to authenticate with SAML SSO" });
const samlConfig: TSAMLConfig = {
callbackUrl: `${appCfg.SITE_URL}/api/v1/sso/saml2/${ssoIdentifier}`,
callbackUrl: `${appCfg.SITE_URL}/api/v1/sso/saml2/${ssoConfig.id}`,
entryPoint: ssoConfig.entryPoint,
issuer: ssoConfig.issuer,
cert: ssoConfig.cert,
@@ -55,7 +77,8 @@ export const registerSamlRouter = async (server: FastifyZodProvider) => {
samlConfig.wantAuthnResponseSigned = false;
}
if (ssoConfig.authProvider === SamlProviders.AZURE_SAML) {
if (req.body.RelayState && JSON.parse(req.body.RelayState).spIntiaited) {
samlConfig.disableRequestedAuthnContext = true;
if (req.body?.RelayState && JSON.parse(req.body.RelayState).spInitiated) {
samlConfig.audience = `spn:${ssoConfig.issuer}`;
}
}
@@ -67,19 +90,21 @@ export const registerSamlRouter = async (server: FastifyZodProvider) => {
}
}
},
// eslint-disable-next-line
async (req, profile, cb) => {
try {
const serverCfg = getServerCfg();
if (!profile) throw new BadRequestError({ message: "Missing profile" });
const { email, firstName } = profile;
if (!email || !firstName)
const { firstName } = profile;
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" });
}
const { isUserCompleted, providerAuthToken } = await server.services.saml.samlLogin({
email,
firstName: profile.firstName as string,
lastName: profile.lastName as string,
isSignupAllowed: Boolean(serverCfg.allowSignUp),
relayState: (req.body as { RelayState?: string }).RelayState,
authProvider: (req as unknown as FastifyRequest).ssoConfig?.authProvider as string,
orgId: (req as unknown as FastifyRequest).ssoConfig?.orgId as string
@@ -95,11 +120,11 @@ export const registerSamlRouter = async (server: FastifyZodProvider) => {
);
server.route({
url: "/redirect/saml2/:ssoIdentifier",
url: "/redirect/saml2/organizations/:orgSlug",
method: "GET",
schema: {
params: z.object({
ssoIdentifier: z.string().trim()
orgSlug: z.string().trim()
}),
querystring: z.object({
callback_port: z.string().optional()
@@ -121,11 +146,37 @@ export const registerSamlRouter = async (server: FastifyZodProvider) => {
});
server.route({
url: "/saml2/:ssoIdentifier",
url: "/redirect/saml2/:samlConfigId",
method: "GET",
schema: {
params: z.object({
samlConfigId: z.string().trim()
}),
querystring: z.object({
callback_port: z.string().optional()
})
},
preValidation: (req, res) =>
(
passport.authenticate("saml", {
failureRedirect: "/",
additionalParams: {
RelayState: JSON.stringify({
spInitiated: true,
callbackPort: req.query.callback_port ?? ""
})
}
} as any) as any
)(req, res),
handler: () => {}
});
server.route({
url: "/saml2/:samlConfigId",
method: "POST",
schema: {
params: z.object({
ssoIdentifier: z.string().trim()
samlConfigId: z.string().trim()
})
},
preValidation: passport.authenticate("saml", {
@@ -137,15 +188,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)}`
);
}
});
@@ -168,7 +215,8 @@ export const registerSamlRouter = async (server: FastifyZodProvider) => {
isActive: z.boolean(),
entryPoint: z.string(),
issuer: z.string(),
cert: z.string()
cert: z.string(),
lastUsed: z.date().nullable().optional()
})
.optional()
}
@@ -177,6 +225,7 @@ export const registerSamlRouter = async (server: FastifyZodProvider) => {
const saml = await server.services.saml.getSaml({
actor: req.permission.type,
actorId: req.permission.id,
actorOrgId: req.permission.orgId,
orgId: req.query.organizationId,
type: "org"
});
@@ -205,6 +254,7 @@ export const registerSamlRouter = async (server: FastifyZodProvider) => {
const saml = await server.services.saml.createSamlCfg({
actor: req.permission.type,
actorId: req.permission.id,
actorOrgId: req.permission.orgId,
orgId: req.body.organizationId,
...req.body
});
@@ -235,6 +285,7 @@ export const registerSamlRouter = async (server: FastifyZodProvider) => {
const saml = await server.services.saml.updateSamlCfg({
actor: req.permission.type,
actorId: req.permission.id,
actorOrgId: req.permission.orgId,
orgId: req.body.organizationId,
...req.body
});
@@ -34,6 +34,7 @@ export const registerSecretApprovalPolicyRouter = async (server: FastifyZodProvi
const approval = await server.services.secretApprovalPolicy.createSecretApprovalPolicy({
actor: req.permission.type,
actorId: req.permission.id,
actorOrgId: req.permission.orgId,
projectId: req.body.workspaceId,
...req.body,
name: req.body.name ?? `${req.body.environment}-${nanoid(3)}`
@@ -71,6 +72,7 @@ export const registerSecretApprovalPolicyRouter = async (server: FastifyZodProvi
const approval = await server.services.secretApprovalPolicy.updateSecretApprovalPolicy({
actor: req.permission.type,
actorId: req.permission.id,
actorOrgId: req.permission.orgId,
...req.body,
secretPolicyId: req.params.sapId
});
@@ -96,6 +98,7 @@ export const registerSecretApprovalPolicyRouter = async (server: FastifyZodProvi
const approval = await server.services.secretApprovalPolicy.deleteSecretApprovalPolicy({
actor: req.permission.type,
actorId: req.permission.id,
actorOrgId: req.permission.orgId,
secretPolicyId: req.params.sapId
});
return { approval };
@@ -111,7 +114,7 @@ export const registerSecretApprovalPolicyRouter = async (server: FastifyZodProvi
}),
response: {
200: z.object({
approvals: sapPubSchema.merge(z.object({approvers:z.string().array()})).array()
approvals: sapPubSchema.merge(z.object({ approvers: z.string().array() })).array()
})
}
},
@@ -120,6 +123,7 @@ export const registerSecretApprovalPolicyRouter = async (server: FastifyZodProvi
const approvals = await server.services.secretApprovalPolicy.getSecretApprovalPolicyByProjectId({
actor: req.permission.type,
actorId: req.permission.id,
actorOrgId: req.permission.orgId,
projectId: req.query.workspaceId
});
return { approvals };
@@ -137,7 +141,7 @@ export const registerSecretApprovalPolicyRouter = async (server: FastifyZodProvi
}),
response: {
200: z.object({
policy: sapPubSchema.merge(z.object({approvers:z.string().array()})).optional()
policy: sapPubSchema.merge(z.object({ approvers: z.string().array() })).optional()
})
}
},
@@ -146,6 +150,7 @@ export const registerSecretApprovalPolicyRouter = async (server: FastifyZodProvi
const policy = await server.services.secretApprovalPolicy.getSecretApprovalPolicyOfFolder({
actor: req.permission.type,
actorId: req.permission.id,
actorOrgId: req.permission.orgId,
projectId: req.query.workspaceId,
...req.query
});
@@ -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()
@@ -57,6 +52,7 @@ export const registerSecretApprovalRequestRouter = async (server: FastifyZodProv
const approvals = await server.services.secretApprovalRequest.getSecretApprovals({
actor: req.permission.type,
actorId: req.permission.id,
actorOrgId: req.permission.orgId,
...req.query,
projectId: req.query.workspaceId
});
@@ -85,6 +81,7 @@ export const registerSecretApprovalRequestRouter = async (server: FastifyZodProv
const approvals = await server.services.secretApprovalRequest.requestCount({
actor: req.permission.type,
actorId: req.permission.id,
actorOrgId: req.permission.orgId,
projectId: req.query.workspaceId
});
return { approvals };
@@ -109,6 +106,7 @@ export const registerSecretApprovalRequestRouter = async (server: FastifyZodProv
const { approval } = await server.services.secretApprovalRequest.mergeSecretApprovalRequest({
actorId: req.permission.id,
actor: req.permission.type,
actorOrgId: req.permission.orgId,
approvalId: req.params.id
});
return { approval };
@@ -136,6 +134,7 @@ export const registerSecretApprovalRequestRouter = async (server: FastifyZodProv
const review = await server.services.secretApprovalRequest.reviewApproval({
actorId: req.permission.id,
actor: req.permission.type,
actorOrgId: req.permission.orgId,
approvalId: req.params.id,
status: req.body.status
});
@@ -164,6 +163,7 @@ export const registerSecretApprovalRequestRouter = async (server: FastifyZodProv
const approval = await server.services.secretApprovalRequest.updateApprovalStatus({
actorId: req.permission.id,
actor: req.permission.type,
actorOrgId: req.permission.orgId,
approvalId: req.params.id,
status: req.body.status
});
@@ -174,11 +174,12 @@ export const registerSecretApprovalRequestRouter = async (server: FastifyZodProv
...req.auditLogInfo,
event: {
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
} as any
// akhilmhdh: had to apply any to avoid ts issue with this
}
@@ -270,6 +271,7 @@ export const registerSecretApprovalRequestRouter = async (server: FastifyZodProv
const approval = await server.services.secretApprovalRequest.getSecretApprovalDetails({
actor: req.permission.type,
actorId: req.permission.id,
actorOrgId: req.permission.orgId,
id: req.params.id
});
return { approval };
@@ -30,6 +30,7 @@ export const registerSecretRotationProviderRouter = async (server: FastifyZodPro
const providers = await server.services.secretRotation.getProviderTemplates({
actor: req.permission.type,
actorId: req.permission.id,
actorOrgId: req.permission.orgId,
projectId: req.params.workspaceId
});
return providers;
@@ -1,6 +1,7 @@
import { z } from "zod";
import { SecretRotationOutputsSchema, SecretRotationsSchema, SecretsSchema } from "@app/db/schemas";
import { removeTrailingSlash } from "@app/lib/fn";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { AuthMode } from "@app/services/auth/auth-type";
@@ -11,7 +12,7 @@ export const registerSecretRotationRouter = async (server: FastifyZodProvider) =
schema: {
body: z.object({
workspaceId: z.string().trim(),
secretPath: z.string().trim(),
secretPath: z.string().trim().transform(removeTrailingSlash),
environment: z.string().trim(),
interval: z.number().min(1),
provider: z.string().trim(),
@@ -39,6 +40,7 @@ export const registerSecretRotationRouter = async (server: FastifyZodProvider) =
const secretRotation = await server.services.secretRotation.createRotation({
actor: req.permission.type,
actorId: req.permission.id,
actorOrgId: req.permission.orgId,
...req.body,
projectId: req.body.workspaceId
});
@@ -72,6 +74,7 @@ export const registerSecretRotationRouter = async (server: FastifyZodProvider) =
const secretRotation = await server.services.secretRotation.restartById({
actor: req.permission.type,
actorId: req.permission.id,
actorOrgId: req.permission.orgId,
rotationId: req.body.id
});
return { secretRotation };
@@ -122,6 +125,7 @@ export const registerSecretRotationRouter = async (server: FastifyZodProvider) =
const secretRotations = await server.services.secretRotation.getByProjectId({
actor: req.permission.type,
actorId: req.permission.id,
actorOrgId: req.permission.orgId,
projectId: req.query.workspaceId
});
return { secretRotations };
@@ -154,6 +158,7 @@ export const registerSecretRotationRouter = async (server: FastifyZodProvider) =
const secretRotation = await server.services.secretRotation.deleteById({
actor: req.permission.type,
actorId: req.permission.id,
actorOrgId: req.permission.orgId,
rotationId: req.params.id
});
return { secretRotation };
@@ -22,6 +22,7 @@ export const registerSecretScanningRouter = async (server: FastifyZodProvider) =
const session = await server.services.secretScanning.createInstallationSession({
actor: req.permission.type,
actorId: req.permission.id,
actorOrgId: req.permission.orgId,
orgId: req.body.organizationId
});
return session;
@@ -45,6 +46,7 @@ export const registerSecretScanningRouter = async (server: FastifyZodProvider) =
const { installatedApp } = await server.services.secretScanning.linkInstallationToOrg({
actor: req.permission.type,
actorId: req.permission.id,
actorOrgId: req.permission.orgId,
...req.body
});
return installatedApp;
@@ -62,12 +64,12 @@ 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,
actorOrgId: req.permission.orgId,
orgId: req.params.organizationId
});
return { appInstallationCompleted };
}
});
@@ -86,6 +88,7 @@ export const registerSecretScanningRouter = async (server: FastifyZodProvider) =
const { risks } = await server.services.secretScanning.getRisksByOrg({
actor: req.permission.type,
actorId: req.permission.id,
actorOrgId: req.permission.orgId,
orgId: req.params.organizationId
});
return { risks };
@@ -107,6 +110,7 @@ export const registerSecretScanningRouter = async (server: FastifyZodProvider) =
const { risk } = await server.services.secretScanning.updateRiskStatus({
actor: req.permission.type,
actorId: req.permission.id,
actorOrgId: req.permission.orgId,
orgId: req.params.organizationId,
riskId: req.params.riskId,
...req.body
@@ -27,6 +27,7 @@ export const registerSecretVersionRouter = async (server: FastifyZodProvider) =>
const secretVersions = await server.services.secret.getSecretVersions({
actor: req.permission.type,
actorId: req.permission.id,
actorOrgId: req.permission.orgId,
limit: req.query.limit,
offset: req.query.offset,
secretId: req.params.secretId
@@ -46,6 +46,7 @@ export const registerSnapshotRouter = async (server: FastifyZodProvider) => {
const secretSnapshot = await server.services.snapshot.getSnapshotData({
actor: req.permission.type,
actorId: req.permission.id,
actorOrgId: req.permission.orgId,
id: req.params.secretSnapshotId
});
return { secretSnapshot };
@@ -56,6 +57,13 @@ export const registerSnapshotRouter = async (server: FastifyZodProvider) => {
method: "POST",
url: "/:secretSnapshotId/rollback",
schema: {
description: "Roll back project secrets to those captured in a secret snapshot version.",
security: [
{
apiKeyAuth: [],
bearerAuth: []
}
],
params: z.object({
secretSnapshotId: z.string().trim()
}),
@@ -70,6 +78,7 @@ export const registerSnapshotRouter = async (server: FastifyZodProvider) => {
const secretSnapshot = await server.services.snapshot.rollbackSnapshot({
actor: req.permission.type,
actorId: req.permission.id,
actorOrgId: req.permission.orgId,
id: req.params.secretSnapshotId
});
return { secretSnapshot };
@@ -24,7 +24,8 @@ export const registerTrustedIpRouter = async (server: FastifyZodProvider) => {
const trustedIps = await server.services.trustedIp.listIpsByProjectId({
projectId: req.params.workspaceId,
actor: req.permission.type,
actorId: req.permission.id
actorId: req.permission.id,
actorOrgId: req.permission.orgId
});
return { trustedIps };
}
@@ -54,6 +55,7 @@ export const registerTrustedIpRouter = async (server: FastifyZodProvider) => {
projectId: req.params.workspaceId,
actor: req.permission.type,
actorId: req.permission.id,
actorOrgId: req.permission.orgId,
...req.body
});
await server.services.auditLog.createAuditLog({
@@ -97,6 +99,7 @@ export const registerTrustedIpRouter = async (server: FastifyZodProvider) => {
projectId: req.params.workspaceId,
actor: req.permission.type,
actorId: req.permission.id,
actorOrgId: req.permission.orgId,
trustedIpId: req.params.trustedIpId,
...req.body
});
@@ -137,6 +140,7 @@ export const registerTrustedIpRouter = async (server: FastifyZodProvider) => {
projectId: req.params.workspaceId,
actor: req.permission.type,
actorId: req.permission.id,
actorOrgId: req.permission.orgId,
trustedIpId: req.params.trustedIpId
});
await server.services.auditLog.createAuditLog({
@@ -2,6 +2,7 @@ import { Knex } from "knex";
import { TDbClient } from "@app/db";
import { TableName } from "@app/db/schemas";
import { DatabaseError } from "@app/lib/errors";
import { ormify, stripUndefinedInWhere } from "@app/lib/knex";
export type TAuditLogDALFactory = ReturnType<typeof auditLogDALFactory>;
@@ -22,40 +23,46 @@ 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)
.where(
stripUndefinedInWhere({
projectId,
orgId,
eventType,
actor,
userAgentType
})
)
.limit(limit)
.offset(offset);
if (startDate) {
sqlQuery.where("createdAt", ">=", startDate);
try {
const sqlQuery = (tx || db)(TableName.AuditLog)
.where(
stripUndefinedInWhere({
projectId,
orgId,
eventType,
actor,
userAgentType
})
)
.limit(limit)
.offset(offset)
.orderBy("createdAt", "desc");
if (startDate) {
void sqlQuery.where("createdAt", ">=", startDate);
}
if (endDate) {
void sqlQuery.where("createdAt", "<=", endDate);
}
const docs = await sqlQuery;
return docs;
} catch (error) {
throw new DatabaseError({ error });
}
if (endDate) {
sqlQuery.where("createdAt", "<=", endDate);
}
const docs = await sqlQuery;
return docs;
};
return { ...auditLogOrm, find };
// delete all audit log that have expired
const pruneAuditLog = async (tx?: Knex) => {
try {
const today = new Date();
const docs = await (tx || db)(TableName.AuditLog).where("expiresAt", "<", today).del();
return docs;
} catch (error) {
throw new DatabaseError({ error, name: "PruneAuditLog" });
}
};
return { ...auditLogOrm, pruneAuditLog, find };
};
@@ -1,3 +1,4 @@
import { logger } from "@app/lib/logger";
import { QueueJobs, QueueName, TQueueServiceFactory } from "@app/queue";
import { TProjectDALFactory } from "@app/services/project/project-dal";
@@ -43,6 +44,8 @@ export const auditLogQueueServiceFactory = ({
const plan = await licenseService.getPlan(orgId);
const ttl = plan.auditLogsRetentionDays * MS_IN_DAY;
// skip inserting if audit log retention is 0 meaning its not supported
if (ttl === 0) return;
await auditLogDAL.create({
actor: actor.type,
actorMetadata: actor.metadata,
@@ -57,7 +60,35 @@ export const auditLogQueueServiceFactory = ({
});
});
queueService.start(QueueName.AuditLogPrune, async () => {
logger.info(`${QueueName.AuditLogPrune}: queue task started`);
await auditLogDAL.pruneAuditLog();
logger.info(`${QueueName.AuditLogPrune}: queue task completed`);
});
// we do a repeat cron job in utc timezone at 12 Midnight each day
const startAuditLogPruneJob = async () => {
// clear previous job
await queueService.stopRepeatableJob(
QueueName.AuditLogPrune,
QueueJobs.AuditLogPrune,
{ pattern: "0 0 * * *", utc: true },
QueueName.AuditLogPrune // just a job id
);
await queueService.queue(QueueName.AuditLogPrune, QueueJobs.AuditLogPrune, undefined, {
delay: 5000,
jobId: QueueName.AuditLogPrune,
repeat: { pattern: "0 0 * * *", utc: true }
});
};
queueService.listen(QueueName.AuditLogPrune, "failed", (err) => {
logger.error(err?.failedReason, `${QueueName.AuditLogPrune}: log pruning failed`);
});
return {
pushToLog
pushToLog,
startAuditLogPruneJob
};
};
@@ -30,14 +30,12 @@ export const auditLogServiceFactory = ({
startDate,
actor,
actorId,
actorOrgId,
projectId,
auditLogActor
}: TListProjectAuditLogDTO) => {
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId);
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionActions.Read,
ProjectPermissionSub.AuditLogs
);
const { permission } = await permissionService.getProjectPermission(actor, actorId, projectId, actorOrgId);
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.AuditLogs);
const auditLogs = await auditLogDAL.find({
startDate,
endDate,
@@ -48,20 +46,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);
};
+7 -11
View File
@@ -31,15 +31,11 @@ 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,
// timeout: 60 * 1000,
timeout: 35 * 1000
// signal: AbortSignal.timeout(60 * 1000)
});
@@ -47,7 +43,7 @@ export const setupLicenceRequestWithStore = (
const appCfg = getConfig();
const {
data: { token: authToken }
} = await request.post(
} = await request.post<{ token: string }>(
refreshUrl,
{},
{
@@ -75,18 +71,18 @@ export const setupLicenceRequestWithStore = (
licenceReq.interceptors.response.use(
(response) => response,
async (err) => {
const originalRequest = err.config;
const originalRequest = (err as AxiosError).config;
// eslint-disable-next-line
if ((err as AxiosError)?.response?.status === 401 && !originalRequest._retry) {
if ((err as AxiosError)?.response?.status === 401 && !(originalRequest as any)._retry) {
// eslint-disable-next-line
originalRequest._retry = true;
(originalRequest as any)._retry = true; // injected
// refresh
await refreshLicence();
licenceReq.defaults.headers.common.Authorization = `Bearer ${token}`;
return licenceReq(originalRequest);
return licenceReq(originalRequest!);
}
return Promise.reject(err);
@@ -13,7 +13,7 @@ export const licenseDALFactory = (db: TDbClient) => {
.where({ status: OrgMembershipStatus.Accepted })
.andWhere((bd) => {
if (orgId) {
bd.where({ orgId });
void bd.where({ orgId });
}
})
.count();

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