mirror of
https://github.com/Infisical/infisical.git
synced 2026-01-10 07:58:15 -05:00
feat(infisical-pg): first setup for postgres migration script
This commit is contained in:
6
backend-pg/src/@types/knex.d.ts
vendored
6
backend-pg/src/@types/knex.d.ts
vendored
@@ -12,6 +12,7 @@ import {
|
||||
TAuthTokenSessions,
|
||||
TAuthTokenSessionsInsert,
|
||||
TAuthTokenSessionsUpdate,
|
||||
TAuthTokensInsert,
|
||||
TAuthTokensUpdate,
|
||||
TBackupPrivateKey,
|
||||
TBackupPrivateKeyInsert,
|
||||
@@ -272,11 +273,6 @@ declare module "knex/types/tables" {
|
||||
TSecretImportsInsert,
|
||||
TSecretImportsUpdate
|
||||
>;
|
||||
[TableName.SecretSnapshot]: Knex.CompositeTableType<
|
||||
TSecretSnapshots,
|
||||
TSecretSnapshotsInsert,
|
||||
TSecretSnapshotsUpdate
|
||||
>;
|
||||
[TableName.Integration]: Knex.CompositeTableType<
|
||||
TIntegrations,
|
||||
TIntegrationsInsert,
|
||||
|
||||
@@ -2,11 +2,11 @@ import { TSuperAdmin, TSuperAdminUpdate } from "@app/db/schemas";
|
||||
import { BadRequestError } from "@app/lib/errors";
|
||||
|
||||
import { TAuthLoginFactory } from "../auth/auth-login-service";
|
||||
import { AuthMethod } from "../auth/auth-type";
|
||||
import { TOrgServiceFactory } from "../org/org-service";
|
||||
import { TUserDalFactory } from "../user/user-dal";
|
||||
import { TSuperAdminDalFactory } from "./super-admin-dal";
|
||||
import { TAdminSignUpDTO } from "./super-admin-types";
|
||||
import { TOrgServiceFactory } from "../org/org-service";
|
||||
import { AuthMethod } from "../auth/auth-type";
|
||||
|
||||
type TSuperAdminServiceFactoryDep = {
|
||||
serverCfgDal: TSuperAdminDalFactory;
|
||||
|
||||
1365
pg-migrator/package-lock.json
generated
Normal file
1365
pg-migrator/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
26
pg-migrator/package.json
Normal file
26
pg-migrator/package.json
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"name": "pg-migrator",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"migration": "tsx src/index.ts"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.11.0",
|
||||
"@types/prompt-sync": "^4.2.3",
|
||||
"tsx": "^4.7.0",
|
||||
"typescript": "^5.3.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"dotenv": "^16.3.1",
|
||||
"knex": "^3.1.0",
|
||||
"level": "^8.0.0",
|
||||
"mongoose": "^8.0.4",
|
||||
"pg": "^8.11.3",
|
||||
"prompt-sync": "^4.2.0",
|
||||
"zod": "^3.22.4"
|
||||
}
|
||||
}
|
||||
1
pg-migrator/src/.gitignore
vendored
Normal file
1
pg-migrator/src/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
db
|
||||
443
pg-migrator/src/@types/knex.d.ts
vendored
Normal file
443
pg-migrator/src/@types/knex.d.ts
vendored
Normal file
@@ -0,0 +1,443 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import {
|
||||
TableName,
|
||||
TApiKeys,
|
||||
TApiKeysInsert,
|
||||
TApiKeysUpdate,
|
||||
TAuditLogs,
|
||||
TAuditLogsInsert,
|
||||
TAuditLogsUpdate,
|
||||
TAuthTokens,
|
||||
TAuthTokenSessions,
|
||||
TAuthTokenSessionsInsert,
|
||||
TAuthTokenSessionsUpdate,
|
||||
TAuthTokensUpdate,
|
||||
TBackupPrivateKey,
|
||||
TBackupPrivateKeyInsert,
|
||||
TBackupPrivateKeyUpdate,
|
||||
TGitAppInstallSessions,
|
||||
TGitAppInstallSessionsInsert,
|
||||
TGitAppInstallSessionsUpdate,
|
||||
TGitAppOrg,
|
||||
TGitAppOrgInsert,
|
||||
TGitAppOrgUpdate,
|
||||
TIdentities,
|
||||
TIdentitiesInsert,
|
||||
TIdentitiesUpdate,
|
||||
TIdentityAccessTokens,
|
||||
TIdentityAccessTokensInsert,
|
||||
TIdentityAccessTokensUpdate,
|
||||
TIdentityOrgMemberships,
|
||||
TIdentityOrgMembershipsInsert,
|
||||
TIdentityOrgMembershipsUpdate,
|
||||
TIdentityProjectMemberships,
|
||||
TIdentityProjectMembershipsInsert,
|
||||
TIdentityProjectMembershipsUpdate,
|
||||
TIdentityUaClientSecrets,
|
||||
TIdentityUaClientSecretsInsert,
|
||||
TIdentityUaClientSecretsUpdate,
|
||||
TIdentityUniversalAuths,
|
||||
TIdentityUniversalAuthsInsert,
|
||||
TIdentityUniversalAuthsUpdate,
|
||||
TIncidentContacts,
|
||||
TIncidentContactsInsert,
|
||||
TIncidentContactsUpdate,
|
||||
TIntegrationAuths,
|
||||
TIntegrationAuthsInsert,
|
||||
TIntegrationAuthsUpdate,
|
||||
TIntegrations,
|
||||
TIntegrationsInsert,
|
||||
TIntegrationsUpdate,
|
||||
TOrganizations,
|
||||
TOrganizationsInsert,
|
||||
TOrganizationsUpdate,
|
||||
TOrgBots,
|
||||
TOrgBotsInsert,
|
||||
TOrgBotsUpdate,
|
||||
TOrgMemberships,
|
||||
TOrgMembershipsInsert,
|
||||
TOrgMembershipsUpdate,
|
||||
TOrgRoles,
|
||||
TOrgRolesInsert,
|
||||
TOrgRolesUpdate,
|
||||
TProjectBots,
|
||||
TProjectBotsInsert,
|
||||
TProjectBotsUpdate,
|
||||
TProjectEnvironments,
|
||||
TProjectEnvironmentsInsert,
|
||||
TProjectEnvironmentsUpdate,
|
||||
TProjectKeys,
|
||||
TProjectKeysInsert,
|
||||
TProjectKeysUpdate,
|
||||
TProjectMemberships,
|
||||
TProjectMembershipsInsert,
|
||||
TProjectMembershipsUpdate,
|
||||
TProjectRoles,
|
||||
TProjectRolesInsert,
|
||||
TProjectRolesUpdate,
|
||||
TProjects,
|
||||
TProjectsInsert,
|
||||
TProjectsUpdate,
|
||||
TSamlConfigs,
|
||||
TSamlConfigsInsert,
|
||||
TSamlConfigsUpdate,
|
||||
TSapApprovers,
|
||||
TSapApproversInsert,
|
||||
TSapApproversUpdate,
|
||||
TSaRequestSecrets,
|
||||
TSaRequestSecretsInsert,
|
||||
TSaRequestSecretsUpdate,
|
||||
TSaRequestSecretTags,
|
||||
TSaRequestSecretTagsInsert,
|
||||
TSaRequestSecretTagsUpdate,
|
||||
TSarReviewers,
|
||||
TSarReviewersInsert,
|
||||
TSarReviewersUpdate,
|
||||
TSecretApprovalPolicies,
|
||||
TSecretApprovalPoliciesInsert,
|
||||
TSecretApprovalPoliciesUpdate,
|
||||
TSecretApprovalRequests,
|
||||
TSecretApprovalRequestsInsert,
|
||||
TSecretApprovalRequestsUpdate,
|
||||
TSecretBlindIndexes,
|
||||
TSecretBlindIndexesInsert,
|
||||
TSecretBlindIndexesUpdate,
|
||||
TSecretFolders,
|
||||
TSecretFoldersInsert,
|
||||
TSecretFoldersUpdate,
|
||||
TSecretFolderVersions,
|
||||
TSecretFolderVersionsInsert,
|
||||
TSecretFolderVersionsUpdate,
|
||||
TSecretImports,
|
||||
TSecretImportsInsert,
|
||||
TSecretImportsUpdate,
|
||||
TSecretRotationOutputs,
|
||||
TSecretRotationOutputsInsert,
|
||||
TSecretRotationOutputsUpdate,
|
||||
TSecretRotations,
|
||||
TSecretRotationsInsert,
|
||||
TSecretRotationsUpdate,
|
||||
TSecrets,
|
||||
TSecretScanningGitRisks,
|
||||
TSecretScanningGitRisksInsert,
|
||||
TSecretScanningGitRisksUpdate,
|
||||
TSecretsInsert,
|
||||
TSecretSnapshotFolders,
|
||||
TSecretSnapshotFoldersInsert,
|
||||
TSecretSnapshotFoldersUpdate,
|
||||
TSecretSnapshots,
|
||||
TSecretSnapshotSecrets,
|
||||
TSecretSnapshotSecretsInsert,
|
||||
TSecretSnapshotSecretsUpdate,
|
||||
TSecretSnapshotsInsert,
|
||||
TSecretSnapshotsUpdate,
|
||||
TSecretsUpdate,
|
||||
TSecretTagJunction,
|
||||
TSecretTagJunctionInsert,
|
||||
TSecretTagJunctionUpdate,
|
||||
TSecretTags,
|
||||
TSecretTagsInsert,
|
||||
TSecretTagsUpdate,
|
||||
TSecretVersions,
|
||||
TSecretVersionsInsert,
|
||||
TSecretVersionsUpdate,
|
||||
TServiceTokens,
|
||||
TServiceTokensInsert,
|
||||
TServiceTokensUpdate,
|
||||
TSuperAdmin,
|
||||
TSuperAdminInsert,
|
||||
TSuperAdminUpdate,
|
||||
TTrustedIps,
|
||||
TTrustedIpsInsert,
|
||||
TTrustedIpsUpdate,
|
||||
TUserActions,
|
||||
TUserActionsInsert,
|
||||
TUserActionsUpdate,
|
||||
TUserEncryptionKeys,
|
||||
TUserEncryptionKeysInsert,
|
||||
TUserEncryptionKeysUpdate,
|
||||
TUsers,
|
||||
TUsersInsert,
|
||||
TUsersUpdate,
|
||||
TWebhooks,
|
||||
TWebhooksInsert,
|
||||
TWebhooksUpdate,
|
||||
TAuthTokensInsert,
|
||||
} from "../schemas";
|
||||
|
||||
declare module "knex/types/tables" {
|
||||
interface Tables {
|
||||
[TableName.Users]: Knex.CompositeTableType<
|
||||
TUsers,
|
||||
TUsersInsert,
|
||||
TUsersUpdate
|
||||
>;
|
||||
[TableName.UserEncryptionKey]: Knex.CompositeTableType<
|
||||
TUserEncryptionKeys,
|
||||
TUserEncryptionKeysInsert,
|
||||
TUserEncryptionKeysUpdate
|
||||
>;
|
||||
[TableName.AuthTokens]: Knex.CompositeTableType<
|
||||
TAuthTokens,
|
||||
TAuthTokensInsert,
|
||||
TAuthTokensUpdate
|
||||
>;
|
||||
[TableName.AuthTokenSession]: Knex.CompositeTableType<
|
||||
TAuthTokenSessions,
|
||||
TAuthTokenSessionsInsert,
|
||||
TAuthTokenSessionsUpdate
|
||||
>;
|
||||
[TableName.BackupPrivateKey]: Knex.CompositeTableType<
|
||||
TBackupPrivateKey,
|
||||
TBackupPrivateKeyInsert,
|
||||
TBackupPrivateKeyUpdate
|
||||
>;
|
||||
[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.ApiKey]: Knex.CompositeTableType<
|
||||
TApiKeys,
|
||||
TApiKeysInsert,
|
||||
TApiKeysUpdate
|
||||
>;
|
||||
[TableName.Project]: Knex.CompositeTableType<
|
||||
TProjects,
|
||||
TProjectsInsert,
|
||||
TProjectsUpdate
|
||||
>;
|
||||
[TableName.ProjectMembership]: Knex.CompositeTableType<
|
||||
TProjectMemberships,
|
||||
TProjectMembershipsInsert,
|
||||
TProjectMembershipsUpdate
|
||||
>;
|
||||
[TableName.Environment]: Knex.CompositeTableType<
|
||||
TProjectEnvironments,
|
||||
TProjectEnvironmentsInsert,
|
||||
TProjectEnvironmentsUpdate
|
||||
>;
|
||||
[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.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.Webhook]: Knex.CompositeTableType<
|
||||
TWebhooks,
|
||||
TWebhooksInsert,
|
||||
TWebhooksUpdate
|
||||
>;
|
||||
[TableName.ServiceToken]: Knex.CompositeTableType<
|
||||
TServiceTokens,
|
||||
TServiceTokensInsert,
|
||||
TServiceTokensUpdate
|
||||
>;
|
||||
[TableName.IntegrationAuth]: Knex.CompositeTableType<
|
||||
TIntegrationAuths,
|
||||
TIntegrationAuthsInsert,
|
||||
TIntegrationAuthsUpdate
|
||||
>;
|
||||
[TableName.Identity]: Knex.CompositeTableType<
|
||||
TIdentities,
|
||||
TIdentitiesInsert,
|
||||
TIdentitiesUpdate
|
||||
>;
|
||||
[TableName.IdentityUniversalAuth]: Knex.CompositeTableType<
|
||||
TIdentityUniversalAuths,
|
||||
TIdentityUniversalAuthsInsert,
|
||||
TIdentityUniversalAuthsUpdate
|
||||
>;
|
||||
[TableName.IdentityUaClientSecret]: Knex.CompositeTableType<
|
||||
TIdentityUaClientSecrets,
|
||||
TIdentityUaClientSecretsInsert,
|
||||
TIdentityUaClientSecretsUpdate
|
||||
>;
|
||||
[TableName.IdentityAccessToken]: Knex.CompositeTableType<
|
||||
TIdentityAccessTokens,
|
||||
TIdentityAccessTokensInsert,
|
||||
TIdentityAccessTokensUpdate
|
||||
>;
|
||||
[TableName.IdentityOrgMembership]: Knex.CompositeTableType<
|
||||
TIdentityOrgMemberships,
|
||||
TIdentityOrgMembershipsInsert,
|
||||
TIdentityOrgMembershipsUpdate
|
||||
>;
|
||||
[TableName.IdentityProjectMembership]: Knex.CompositeTableType<
|
||||
TIdentityProjectMemberships,
|
||||
TIdentityProjectMembershipsInsert,
|
||||
TIdentityProjectMembershipsUpdate
|
||||
>;
|
||||
[TableName.SecretApprovalPolicy]: Knex.CompositeTableType<
|
||||
TSecretApprovalPolicies,
|
||||
TSecretApprovalPoliciesInsert,
|
||||
TSecretApprovalPoliciesUpdate
|
||||
>;
|
||||
[TableName.SapApprover]: Knex.CompositeTableType<
|
||||
TSapApprovers,
|
||||
TSapApproversInsert,
|
||||
TSapApproversUpdate
|
||||
>;
|
||||
[TableName.SecretApprovalRequest]: Knex.CompositeTableType<
|
||||
TSecretApprovalRequests,
|
||||
TSecretApprovalRequestsInsert,
|
||||
TSecretApprovalRequestsUpdate
|
||||
>;
|
||||
[TableName.SarReviewer]: Knex.CompositeTableType<
|
||||
TSarReviewers,
|
||||
TSarReviewersInsert,
|
||||
TSarReviewersUpdate
|
||||
>;
|
||||
[TableName.SarSecret]: Knex.CompositeTableType<
|
||||
TSaRequestSecrets,
|
||||
TSaRequestSecretsInsert,
|
||||
TSaRequestSecretsUpdate
|
||||
>;
|
||||
[TableName.SarSecretTag]: Knex.CompositeTableType<
|
||||
TSaRequestSecretTags,
|
||||
TSaRequestSecretTagsInsert,
|
||||
TSaRequestSecretTagsUpdate
|
||||
>;
|
||||
[TableName.SecretRotation]: Knex.CompositeTableType<
|
||||
TSecretRotations,
|
||||
TSecretRotationsInsert,
|
||||
TSecretRotationsUpdate
|
||||
>;
|
||||
[TableName.SecretRotationOutput]: Knex.CompositeTableType<
|
||||
TSecretRotationOutputs,
|
||||
TSecretRotationOutputsInsert,
|
||||
TSecretRotationOutputsUpdate
|
||||
>;
|
||||
[TableName.Snapshot]: Knex.CompositeTableType<
|
||||
TSecretSnapshots,
|
||||
TSecretSnapshotsInsert,
|
||||
TSecretSnapshotsUpdate
|
||||
>;
|
||||
[TableName.SnapshotSecret]: Knex.CompositeTableType<
|
||||
TSecretSnapshotSecrets,
|
||||
TSecretSnapshotSecretsInsert,
|
||||
TSecretSnapshotSecretsUpdate
|
||||
>;
|
||||
[TableName.SnapshotFolder]: Knex.CompositeTableType<
|
||||
TSecretSnapshotFolders,
|
||||
TSecretSnapshotFoldersInsert,
|
||||
TSecretSnapshotFoldersUpdate
|
||||
>;
|
||||
[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<
|
||||
TGitAppInstallSessions,
|
||||
TGitAppInstallSessionsInsert,
|
||||
TGitAppInstallSessionsUpdate
|
||||
>;
|
||||
[TableName.GitAppOrg]: Knex.CompositeTableType<
|
||||
TGitAppOrg,
|
||||
TGitAppOrgInsert,
|
||||
TGitAppOrgUpdate
|
||||
>;
|
||||
[TableName.SecretScanningGitRisk]: Knex.CompositeTableType<
|
||||
TSecretScanningGitRisks,
|
||||
TSecretScanningGitRisksInsert,
|
||||
TSecretScanningGitRisksUpdate
|
||||
>;
|
||||
[TableName.TrustedIps]: Knex.CompositeTableType<
|
||||
TTrustedIps,
|
||||
TTrustedIpsInsert,
|
||||
TTrustedIpsUpdate
|
||||
>;
|
||||
// Junction tables
|
||||
[TableName.JnSecretTag]: Knex.CompositeTableType<
|
||||
TSecretTagJunction,
|
||||
TSecretTagJunctionInsert,
|
||||
TSecretTagJunctionUpdate
|
||||
>;
|
||||
}
|
||||
}
|
||||
80
pg-migrator/src/index.ts
Normal file
80
pg-migrator/src/index.ts
Normal file
@@ -0,0 +1,80 @@
|
||||
import promptSync from "prompt-sync";
|
||||
import mongoose from "mongoose";
|
||||
import dotenv from "dotenv";
|
||||
import knex from "knex";
|
||||
import path from "path";
|
||||
import { Level } from "level";
|
||||
import { IUser, User } from "./models";
|
||||
import { TUsers, TUsersInsert, TableName } from "./schemas";
|
||||
|
||||
const kdb = new Level<string, any>("./db", { valueEncoding: "json" });
|
||||
|
||||
const main = async () => {
|
||||
try {
|
||||
dotenv.config();
|
||||
const prompt = promptSync({ sigint: true });
|
||||
|
||||
let mongodb_url = process.env.MONGO_DB_URL;
|
||||
if (!mongodb_url) {
|
||||
mongodb_url = prompt("Type the mongodb url: ");
|
||||
}
|
||||
console.log("Checking mongoose connection...");
|
||||
await mongoose.connect(mongodb_url);
|
||||
console.log("Connected successfully to mongo");
|
||||
|
||||
let postgres_url = process.env.POSTGRES_DB_URL;
|
||||
if (!postgres_url) {
|
||||
postgres_url = prompt("Type the mongodb url: ");
|
||||
}
|
||||
|
||||
console.log("Checking postgres connection...");
|
||||
const db = knex({
|
||||
client: "pg",
|
||||
connection: postgres_url,
|
||||
migrations: {
|
||||
directory: path.join(__dirname, "./migrations"),
|
||||
extension: "ts",
|
||||
tableName: "infisical_migrations",
|
||||
},
|
||||
});
|
||||
console.log("Connected successfully to postgres");
|
||||
await db.raw("select 1+1 as result");
|
||||
|
||||
console.log("Executing migration");
|
||||
await db.migrate.latest();
|
||||
|
||||
console.log("Starting to insert users");
|
||||
const users: IUser[] = [];
|
||||
const newUsers: TUsersInsert[] = [];
|
||||
for await (const doc of User.find().cursor({ batchSize: 100 })) {
|
||||
users.push(doc);
|
||||
newUsers.push({
|
||||
firstName: doc.firstName,
|
||||
email: doc.email,
|
||||
devices: doc.devices,
|
||||
lastName: doc.lastName,
|
||||
isAccepted: Boolean(doc.publicKey),
|
||||
superAdmin: doc.superAdmin,
|
||||
authMethods: doc.authMethods,
|
||||
isMfaEnabled: doc.isMfaEnabled,
|
||||
});
|
||||
if (users.length >= 1000) {
|
||||
const newUserIds = await db.transaction(async (tx) => {
|
||||
return await tx
|
||||
.batchInsert<TUsers>(TableName.Users, newUsers)
|
||||
.returning("id");
|
||||
});
|
||||
console.log(newUserIds.length);
|
||||
users.slice(0, users.length);
|
||||
newUsers.slice(0, newUsers.length);
|
||||
}
|
||||
}
|
||||
|
||||
process.exit(1);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
main();
|
||||
37
pg-migrator/src/migrations/20231128072457_user.ts
Normal file
37
pg-migrator/src/migrations/20231128072457_user.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { TableName } from "../schemas";
|
||||
import {
|
||||
createOnUpdateTrigger,
|
||||
createUpdateAtTriggerFunction,
|
||||
dropOnUpdateTrigger,
|
||||
dropUpdatedAtTriggerFunction
|
||||
} from "../utils";
|
||||
|
||||
export async function up(knex: Knex): Promise<void> {
|
||||
const isTablePresent = await knex.schema.hasTable(TableName.Users);
|
||||
if (!isTablePresent) {
|
||||
await knex.schema.createTable(TableName.Users, (t) => {
|
||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
t.string("email").notNullable();
|
||||
t.specificType("authMethods", "text[]");
|
||||
t.boolean("superAdmin").defaultTo(false);
|
||||
t.string("firstName");
|
||||
t.string("lastName");
|
||||
t.boolean("isAccepted").defaultTo(false);
|
||||
t.boolean("isMfaEnabled").defaultTo(false);
|
||||
t.specificType("mfaMethods", "text[]");
|
||||
t.jsonb("devices");
|
||||
t.timestamps(true, true, true);
|
||||
});
|
||||
}
|
||||
// this is a one time function
|
||||
await createUpdateAtTriggerFunction(knex);
|
||||
await createOnUpdateTrigger(knex, TableName.Users);
|
||||
}
|
||||
|
||||
export async function down(knex: Knex): Promise<void> {
|
||||
await knex.schema.dropTableIfExists(TableName.Users);
|
||||
await dropOnUpdateTrigger(knex, TableName.Users);
|
||||
await dropUpdatedAtTriggerFunction(knex);
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { TableName } from "../schemas";
|
||||
|
||||
export async function up(knex: Knex): Promise<void> {
|
||||
const isTablePresent = await knex.schema.hasTable(TableName.UserEncryptionKey);
|
||||
if (!isTablePresent) {
|
||||
await knex.schema.createTable(TableName.UserEncryptionKey, (t) => {
|
||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
t.text("clientPublicKey");
|
||||
t.text("serverPrivateKey");
|
||||
t.integer("encryptionVersion").defaultTo(2);
|
||||
t.text("protectedKey").notNullable();
|
||||
t.text("protectedKeyIV").notNullable();
|
||||
t.text("protectedKeyTag").notNullable();
|
||||
t.text("publicKey").notNullable();
|
||||
t.text("encryptedPrivateKey").notNullable();
|
||||
t.text("iv").notNullable();
|
||||
t.text("tag").notNullable();
|
||||
t.text("salt").notNullable();
|
||||
t.text("verifier").notNullable();
|
||||
// one to one relationship
|
||||
t.uuid("userId").notNullable().unique();
|
||||
t.foreign("userId").references("id").inTable(TableName.Users).onDelete("CASCADE");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export async function down(knex: Knex): Promise<void> {
|
||||
await knex.schema.dropTableIfExists(TableName.UserEncryptionKey);
|
||||
}
|
||||
25
pg-migrator/src/migrations/20231129072939_auth-token.ts
Normal file
25
pg-migrator/src/migrations/20231129072939_auth-token.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { TableName } from "../schemas";
|
||||
|
||||
export async function up(knex: Knex): Promise<void> {
|
||||
const isTablePresent = await knex.schema.hasTable(TableName.AuthTokens);
|
||||
if (!isTablePresent) {
|
||||
await knex.schema.createTable(TableName.AuthTokens, (t) => {
|
||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
t.string("type").notNullable();
|
||||
t.string("phoneNumber");
|
||||
t.string("tokenHash").notNullable();
|
||||
t.integer("triesLeft");
|
||||
t.datetime("expiresAt").notNullable();
|
||||
// does not need update trigger we will do it manually
|
||||
t.timestamps(true, true, true);
|
||||
t.uuid("userId");
|
||||
t.foreign("userId").references("id").inTable(TableName.Users).onDelete("CASCADE");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export async function down(knex: Knex): Promise<void> {
|
||||
await knex.schema.dropTableIfExists(TableName.AuthTokens);
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { TableName } from "../schemas";
|
||||
import { createOnUpdateTrigger, dropOnUpdateTrigger } from "../utils";
|
||||
|
||||
export async function up(knex: Knex): Promise<void> {
|
||||
const isTablePresent = await knex.schema.hasTable(TableName.AuthTokenSession);
|
||||
if (!isTablePresent) {
|
||||
await knex.schema.createTable(TableName.AuthTokenSession, (t) => {
|
||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
t.string("ip").notNullable();
|
||||
t.string("userAgent");
|
||||
t.integer("refreshVersion").notNullable().defaultTo(1);
|
||||
t.integer("accessVersion").notNullable().defaultTo(1);
|
||||
t.datetime("lastUsed").notNullable();
|
||||
// does not need update trigger we will do it manually
|
||||
t.timestamps(true, true, true);
|
||||
t.uuid("userId").notNullable();
|
||||
t.foreign("userId").references("id").inTable(TableName.Users).onDelete("CASCADE");
|
||||
});
|
||||
}
|
||||
// this is a one time function
|
||||
await createOnUpdateTrigger(knex, TableName.AuthTokenSession);
|
||||
}
|
||||
|
||||
export async function down(knex: Knex): Promise<void> {
|
||||
await knex.schema.dropTableIfExists(TableName.AuthTokenSession);
|
||||
await dropOnUpdateTrigger(knex, TableName.AuthTokenSession);
|
||||
}
|
||||
26
pg-migrator/src/migrations/20231201151432_backup-key.ts
Normal file
26
pg-migrator/src/migrations/20231201151432_backup-key.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { TableName } from "../schemas";
|
||||
|
||||
export async function up(knex: Knex): Promise<void> {
|
||||
const doesTableExist = await knex.schema.hasTable(TableName.BackupPrivateKey);
|
||||
if (!doesTableExist) {
|
||||
await knex.schema.createTable(TableName.BackupPrivateKey, (t) => {
|
||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
t.text("encryptedPrivateKey").notNullable();
|
||||
t.text("iv").notNullable();
|
||||
t.text("tag").notNullable();
|
||||
t.string("algorithm").notNullable();
|
||||
t.string("keyEncoding").notNullable();
|
||||
t.text("salt").notNullable();
|
||||
t.text("verifier").notNullable();
|
||||
t.timestamps(true, true, true);
|
||||
t.uuid("userId").notNullable().unique();
|
||||
t.foreign("userId").references("id").inTable(TableName.Users).onDelete("CASCADE");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export async function down(knex: Knex): Promise<void> {
|
||||
await knex.schema.dropTableIfExists(TableName.BackupPrivateKey);
|
||||
}
|
||||
33
pg-migrator/src/migrations/20231204092737_organization.ts
Normal file
33
pg-migrator/src/migrations/20231204092737_organization.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { TableName } from "../schemas";
|
||||
import { createOnUpdateTrigger, dropOnUpdateTrigger } from "../utils";
|
||||
|
||||
export async function up(knex: Knex): Promise<void> {
|
||||
const isTablePresent = await knex.schema.hasTable(TableName.Organization);
|
||||
if (!isTablePresent) {
|
||||
await knex.schema.createTable(TableName.Organization, (t) => {
|
||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
t.string("name").notNullable();
|
||||
t.string("customerId");
|
||||
// does not need update trigger we will do it manually
|
||||
t.timestamps(true, true, true);
|
||||
});
|
||||
await knex.schema.alterTable(TableName.AuthTokens, (t) => {
|
||||
t.uuid("orgId");
|
||||
t.foreign("orgId").references("id").inTable(TableName.Organization).onDelete("CASCADE");
|
||||
});
|
||||
}
|
||||
// this is a one time function
|
||||
await createOnUpdateTrigger(knex, TableName.Organization);
|
||||
}
|
||||
|
||||
export async function down(knex: Knex): Promise<void> {
|
||||
if (await knex.schema.hasColumn(TableName.AuthTokens, "orgId")) {
|
||||
await knex.schema.alterTable(TableName.AuthTokens, (t) => {
|
||||
t.dropColumn("orgId");
|
||||
});
|
||||
}
|
||||
await knex.schema.dropTableIfExists(TableName.Organization);
|
||||
await dropOnUpdateTrigger(knex, TableName.Organization);
|
||||
}
|
||||
48
pg-migrator/src/migrations/20231204092747_org-membership.ts
Normal file
48
pg-migrator/src/migrations/20231204092747_org-membership.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { TableName } from "../schemas";
|
||||
import { OrgMembershipStatus } from "../schemas/models";
|
||||
import { createOnUpdateTrigger, dropOnUpdateTrigger } from "../utils";
|
||||
|
||||
export async function up(knex: Knex): Promise<void> {
|
||||
const isOrgRolePresent = await knex.schema.hasTable(TableName.OrgRoles);
|
||||
if (!isOrgRolePresent) {
|
||||
await knex.schema.createTable(TableName.OrgRoles, (t) => {
|
||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
t.string("name").notNullable();
|
||||
t.string("description");
|
||||
t.string("slug").notNullable();
|
||||
t.jsonb("permissions").notNullable();
|
||||
// does not need update trigger we will do it manually
|
||||
t.timestamps(true, true, true);
|
||||
t.uuid("orgId").notNullable();
|
||||
t.foreign("orgId").references("id").inTable(TableName.Organization).onDelete("CASCADE");
|
||||
});
|
||||
}
|
||||
|
||||
const isOrgTablePresent = await knex.schema.hasTable(TableName.OrgMembership);
|
||||
if (!isOrgTablePresent) {
|
||||
await knex.schema.createTable(TableName.OrgMembership, (t) => {
|
||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
t.string("role").notNullable();
|
||||
t.string("status").notNullable().defaultTo(OrgMembershipStatus.Invited);
|
||||
t.string("inviteEmail");
|
||||
// does not need update trigger we will do it manually
|
||||
t.timestamps(true, true, true);
|
||||
t.uuid("userId");
|
||||
t.foreign("userId").references("id").inTable(TableName.Users).onDelete("CASCADE");
|
||||
t.uuid("orgId").notNullable();
|
||||
t.foreign("orgId").references("id").inTable(TableName.Organization).onDelete("CASCADE");
|
||||
t.uuid("roleId");
|
||||
t.foreign("roleId").references("id").inTable(TableName.OrgRoles);
|
||||
});
|
||||
}
|
||||
// this is a one time function
|
||||
await createOnUpdateTrigger(knex, TableName.OrgMembership);
|
||||
}
|
||||
|
||||
export async function down(knex: Knex): Promise<void> {
|
||||
await knex.schema.dropTableIfExists(TableName.OrgMembership);
|
||||
await knex.schema.dropTableIfExists(TableName.OrgRoles);
|
||||
await dropOnUpdateTrigger(knex, TableName.OrgMembership);
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { TableName } from "../schemas";
|
||||
import { createOnUpdateTrigger, dropOnUpdateTrigger } from "../utils";
|
||||
|
||||
export async function up(knex: Knex): Promise<void> {
|
||||
const isTablePresent = await knex.schema.hasTable(TableName.IncidentContact);
|
||||
if (!isTablePresent) {
|
||||
await knex.schema.createTable(TableName.IncidentContact, (t) => {
|
||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
t.string("email").notNullable();
|
||||
// does not need update trigger we will do it manually
|
||||
t.timestamps(true, true, true);
|
||||
t.uuid("orgId").notNullable();
|
||||
t.foreign("orgId").references("id").inTable(TableName.Organization).onDelete("CASCADE");
|
||||
});
|
||||
}
|
||||
// this is a one time function
|
||||
await createOnUpdateTrigger(knex, TableName.IncidentContact);
|
||||
}
|
||||
|
||||
export async function down(knex: Knex): Promise<void> {
|
||||
await knex.schema.dropTableIfExists(TableName.IncidentContact);
|
||||
await dropOnUpdateTrigger(knex, TableName.IncidentContact);
|
||||
}
|
||||
20
pg-migrator/src/migrations/20231207055643_user-action.ts
Normal file
20
pg-migrator/src/migrations/20231207055643_user-action.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { TableName } from "../schemas";
|
||||
|
||||
export async function up(knex: Knex): Promise<void> {
|
||||
const isTablePresent = await knex.schema.hasTable(TableName.UserAction);
|
||||
if (!isTablePresent) {
|
||||
await knex.schema.createTable(TableName.UserAction, (t) => {
|
||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
t.string("action").notNullable();
|
||||
t.timestamps(true, true, true);
|
||||
t.uuid("userId").notNullable();
|
||||
t.foreign("userId").references("id").inTable(TableName.Users).onDelete("CASCADE");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export async function down(knex: Knex): Promise<void> {
|
||||
await knex.schema.dropTableIfExists(TableName.UserAction);
|
||||
}
|
||||
23
pg-migrator/src/migrations/20231207055701_super-admin.ts
Normal file
23
pg-migrator/src/migrations/20231207055701_super-admin.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { TableName } from "../schemas";
|
||||
import { createOnUpdateTrigger, dropOnUpdateTrigger } from "../utils";
|
||||
|
||||
export async function up(knex: Knex): Promise<void> {
|
||||
const isTablePresent = await knex.schema.hasTable(TableName.SuperAdmin);
|
||||
if (!isTablePresent) {
|
||||
await knex.schema.createTable(TableName.SuperAdmin, (t) => {
|
||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
t.boolean("initialized").defaultTo(false);
|
||||
t.boolean("allowSignUp").defaultTo(true);
|
||||
t.timestamps(true, true, true);
|
||||
});
|
||||
}
|
||||
// this is a one time function
|
||||
await createOnUpdateTrigger(knex, TableName.SuperAdmin);
|
||||
}
|
||||
|
||||
export async function down(knex: Knex): Promise<void> {
|
||||
await knex.schema.dropTableIfExists(TableName.SuperAdmin);
|
||||
await dropOnUpdateTrigger(knex, TableName.SuperAdmin);
|
||||
}
|
||||
26
pg-migrator/src/migrations/20231207105059_api-key.ts
Normal file
26
pg-migrator/src/migrations/20231207105059_api-key.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { TableName } from "../schemas";
|
||||
import { createOnUpdateTrigger, dropOnUpdateTrigger } from "../utils";
|
||||
|
||||
export async function up(knex: Knex): Promise<void> {
|
||||
const isTablePresent = await knex.schema.hasTable(TableName.ApiKey);
|
||||
if (!isTablePresent) {
|
||||
await knex.schema.createTable(TableName.ApiKey, (t) => {
|
||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
t.string("name").notNullable();
|
||||
t.datetime("lastUsed");
|
||||
t.datetime("expiresAt");
|
||||
t.string("secretHash").notNullable();
|
||||
t.timestamps(true, true, true);
|
||||
t.uuid("userId").notNullable();
|
||||
t.foreign("userId").references("id").inTable(TableName.Users).onDelete("CASCADE");
|
||||
});
|
||||
}
|
||||
await createOnUpdateTrigger(knex, TableName.ApiKey);
|
||||
}
|
||||
|
||||
export async function down(knex: Knex): Promise<void> {
|
||||
await knex.schema.dropTableIfExists(TableName.ApiKey);
|
||||
await dropOnUpdateTrigger(knex, TableName.ApiKey);
|
||||
}
|
||||
60
pg-migrator/src/migrations/20231212110939_project.ts
Normal file
60
pg-migrator/src/migrations/20231212110939_project.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { TableName } from "../schemas";
|
||||
import { createOnUpdateTrigger, dropOnUpdateTrigger } from "../utils";
|
||||
|
||||
export async function up(knex: Knex): Promise<void> {
|
||||
if (!(await knex.schema.hasTable(TableName.Project))) {
|
||||
await knex.schema.createTable(TableName.Project, (t) => {
|
||||
t.string("id", 36).primary().defaultTo(knex.fn.uuid());
|
||||
t.string("name").notNullable();
|
||||
t.boolean("autoCapitalization").defaultTo(true);
|
||||
t.uuid("orgId").notNullable();
|
||||
t.foreign("orgId").references("id").inTable(TableName.Organization).onDelete("CASCADE");
|
||||
t.timestamps(true, true, true);
|
||||
});
|
||||
}
|
||||
await createOnUpdateTrigger(knex, TableName.Project);
|
||||
// environments
|
||||
if (!(await knex.schema.hasTable(TableName.Environment))) {
|
||||
await knex.schema.createTable(TableName.Environment, (t) => {
|
||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
t.string("name").notNullable();
|
||||
t.string("slug").notNullable();
|
||||
t.integer("position").notNullable();
|
||||
t.string("projectId").notNullable();
|
||||
t.foreign("projectId").references("id").inTable(TableName.Project).onDelete("CASCADE");
|
||||
// this will ensure ever env has its position
|
||||
t.unique(["projectId", "position"], {
|
||||
indexName: "env_pos_composite_uniqe",
|
||||
deferrable: "deferred"
|
||||
});
|
||||
t.timestamps(true, true, true);
|
||||
});
|
||||
}
|
||||
// project key
|
||||
if (!(await knex.schema.hasTable(TableName.ProjectKeys))) {
|
||||
await knex.schema.createTable(TableName.ProjectKeys, (t) => {
|
||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
t.text("encryptedKey").notNullable();
|
||||
t.text("nonce").notNullable();
|
||||
t.uuid("receiverId").notNullable();
|
||||
t.foreign("receiverId").references("id").inTable(TableName.Users).onDelete("CASCADE");
|
||||
t.uuid("senderId");
|
||||
// if sender is deleted just don't do anything to this record
|
||||
t.foreign("senderId").references("id").inTable(TableName.Users).onDelete("SET NULL");
|
||||
t.string("projectId").notNullable();
|
||||
t.foreign("projectId").references("id").inTable(TableName.Project).onDelete("CASCADE");
|
||||
t.timestamps(true, true, true);
|
||||
});
|
||||
}
|
||||
await createOnUpdateTrigger(knex, TableName.ProjectKeys);
|
||||
}
|
||||
|
||||
export async function down(knex: Knex): Promise<void> {
|
||||
await knex.schema.dropTableIfExists(TableName.Environment);
|
||||
await knex.schema.dropTableIfExists(TableName.ProjectKeys);
|
||||
await knex.schema.dropTableIfExists(TableName.Project);
|
||||
await dropOnUpdateTrigger(knex, TableName.ProjectKeys);
|
||||
await dropOnUpdateTrigger(knex, TableName.Project);
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { TableName } from "../schemas";
|
||||
import { createOnUpdateTrigger, dropOnUpdateTrigger } from "../utils";
|
||||
|
||||
export async function up(knex: Knex): Promise<void> {
|
||||
if (!(await knex.schema.hasTable(TableName.ProjectRoles))) {
|
||||
await knex.schema.createTable(TableName.ProjectRoles, (t) => {
|
||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
t.string("name").notNullable();
|
||||
t.string("description");
|
||||
t.string("slug").notNullable();
|
||||
t.jsonb("permissions").notNullable();
|
||||
// does not need update trigger we will do it manually
|
||||
t.timestamps(true, true, true);
|
||||
t.string("projectId").notNullable();
|
||||
t.foreign("projectId").references("id").inTable(TableName.Project).onDelete("CASCADE");
|
||||
});
|
||||
}
|
||||
|
||||
if (!(await knex.schema.hasTable(TableName.ProjectMembership))) {
|
||||
await knex.schema.createTable(TableName.ProjectMembership, (t) => {
|
||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
t.string("role").notNullable();
|
||||
// does not need update trigger we will do it manually
|
||||
t.timestamps(true, true, true);
|
||||
t.uuid("userId").notNullable();
|
||||
t.foreign("userId").references("id").inTable(TableName.Users).onDelete("CASCADE");
|
||||
t.string("projectId").notNullable();
|
||||
t.foreign("projectId").references("id").inTable(TableName.Project).onDelete("CASCADE");
|
||||
// until role is changed/removed the role should not deleted
|
||||
t.uuid("roleId");
|
||||
t.foreign("roleId").references("id").inTable(TableName.ProjectRoles);
|
||||
});
|
||||
}
|
||||
await createOnUpdateTrigger(knex, TableName.ProjectMembership);
|
||||
}
|
||||
|
||||
export async function down(knex: Knex): Promise<void> {
|
||||
await knex.schema.dropTableIfExists(TableName.ProjectMembership);
|
||||
await knex.schema.dropTableIfExists(TableName.ProjectRoles);
|
||||
await dropOnUpdateTrigger(knex, TableName.ProjectMembership);
|
||||
}
|
||||
42
pg-migrator/src/migrations/20231218092441_secret-folder.ts
Normal file
42
pg-migrator/src/migrations/20231218092441_secret-folder.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { TableName } from "../schemas";
|
||||
import { createOnUpdateTrigger, dropOnUpdateTrigger } from "../utils";
|
||||
|
||||
export async function up(knex: Knex): Promise<void> {
|
||||
if (!(await knex.schema.hasTable(TableName.SecretFolder))) {
|
||||
await knex.schema.createTable(TableName.SecretFolder, (t) => {
|
||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
t.string("name").notNullable();
|
||||
t.integer("version").defaultTo(1);
|
||||
t.timestamps(true, true, true);
|
||||
t.uuid("envId").notNullable();
|
||||
t.foreign("envId").references("id").inTable(TableName.Environment).onDelete("CASCADE");
|
||||
t.uuid("parentId");
|
||||
t.foreign("parentId").references("id").inTable(TableName.SecretFolder).onDelete("CASCADE");
|
||||
});
|
||||
}
|
||||
await createOnUpdateTrigger(knex, TableName.SecretFolder);
|
||||
|
||||
if (!(await knex.schema.hasTable(TableName.SecretFolderVersion))) {
|
||||
await knex.schema.createTable(TableName.SecretFolderVersion, (t) => {
|
||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
t.string("name").notNullable();
|
||||
t.integer("version").defaultTo(1);
|
||||
t.timestamps(true, true, true);
|
||||
t.uuid("envId").notNullable();
|
||||
t.foreign("envId").references("id").inTable(TableName.Environment).onDelete("CASCADE");
|
||||
t.uuid("folderId").notNullable();
|
||||
// t.foreign("folderId").references("id").inTable(TableName.SecretFolder).onDelete("SET NULL");
|
||||
});
|
||||
}
|
||||
|
||||
await createOnUpdateTrigger(knex, TableName.SecretFolderVersion);
|
||||
}
|
||||
|
||||
export async function down(knex: Knex): Promise<void> {
|
||||
await knex.schema.dropTableIfExists(TableName.SecretFolderVersion);
|
||||
await knex.schema.dropTableIfExists(TableName.SecretFolder);
|
||||
await dropOnUpdateTrigger(knex, TableName.SecretFolder);
|
||||
await dropOnUpdateTrigger(knex, TableName.SecretFolderVersion);
|
||||
}
|
||||
30
pg-migrator/src/migrations/20231218092508_secret-import.ts
Normal file
30
pg-migrator/src/migrations/20231218092508_secret-import.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { TableName } from "../schemas";
|
||||
import { createOnUpdateTrigger, dropOnUpdateTrigger } from "../utils";
|
||||
|
||||
export async function up(knex: Knex): Promise<void> {
|
||||
if (!(await knex.schema.hasTable(TableName.SecretImport))) {
|
||||
await knex.schema.createTable(TableName.SecretImport, (t) => {
|
||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
t.integer("version").defaultTo(1);
|
||||
t.string("importPath").notNullable();
|
||||
t.uuid("importEnv").notNullable();
|
||||
t.foreign("importEnv").references("id").inTable(TableName.Environment).onDelete("CASCADE");
|
||||
t.integer("position").notNullable();
|
||||
t.timestamps(true, true, true);
|
||||
t.uuid("folderId").notNullable();
|
||||
t.foreign("folderId").references("id").inTable(TableName.SecretFolder).onDelete("CASCADE");
|
||||
t.unique(["folderId", "position"], {
|
||||
indexName: "import_pos_composite_uniqe",
|
||||
deferrable: "deferred"
|
||||
});
|
||||
});
|
||||
}
|
||||
await createOnUpdateTrigger(knex, TableName.SecretImport);
|
||||
}
|
||||
|
||||
export async function down(knex: Knex): Promise<void> {
|
||||
await knex.schema.dropTableIfExists(TableName.SecretImport);
|
||||
await dropOnUpdateTrigger(knex, TableName.SecretImport);
|
||||
}
|
||||
26
pg-migrator/src/migrations/20231218092517_secret-tag.ts
Normal file
26
pg-migrator/src/migrations/20231218092517_secret-tag.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { TableName } from "../schemas";
|
||||
import { createOnUpdateTrigger, dropOnUpdateTrigger } from "../utils";
|
||||
|
||||
export async function up(knex: Knex): Promise<void> {
|
||||
if (!(await knex.schema.hasTable(TableName.SecretTag))) {
|
||||
await knex.schema.createTable(TableName.SecretTag, (t) => {
|
||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
t.string("name").notNullable();
|
||||
t.string("slug").notNullable();
|
||||
t.string("color");
|
||||
t.timestamps(true, true, true);
|
||||
t.uuid("createdBy");
|
||||
t.foreign("createdBy").references("id").inTable(TableName.Users).onDelete("SET NULL");
|
||||
t.string("projectId").notNullable();
|
||||
t.foreign("projectId").references("id").inTable(TableName.Project).onDelete("CASCADE");
|
||||
});
|
||||
}
|
||||
await createOnUpdateTrigger(knex, TableName.SecretTag);
|
||||
}
|
||||
|
||||
export async function down(knex: Knex): Promise<void> {
|
||||
await knex.schema.dropTableIfExists(TableName.SecretTag);
|
||||
await dropOnUpdateTrigger(knex, TableName.SecretTag);
|
||||
}
|
||||
65
pg-migrator/src/migrations/20231218103423_secret.ts
Normal file
65
pg-migrator/src/migrations/20231218103423_secret.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { SecretEncryptionAlgo, SecretKeyEncoding, SecretType, TableName } from "../schemas";
|
||||
import { createJunctionTable, createOnUpdateTrigger, dropOnUpdateTrigger } from "../utils";
|
||||
|
||||
export async function up(knex: Knex): Promise<void> {
|
||||
if (!(await knex.schema.hasTable(TableName.SecretBlindIndex))) {
|
||||
await knex.schema.createTable(TableName.SecretBlindIndex, (t) => {
|
||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
t.text("encryptedSaltCipherText").notNullable();
|
||||
t.text("saltIV").notNullable();
|
||||
t.text("saltTag").notNullable();
|
||||
t.string("algorithm").notNullable().defaultTo(SecretEncryptionAlgo.AES_256_GCM);
|
||||
t.string("keyEncoding").notNullable().defaultTo(SecretKeyEncoding.UTF8);
|
||||
t.string("projectId").notNullable().unique();
|
||||
t.foreign("projectId").references("id").inTable(TableName.Project).onDelete("CASCADE");
|
||||
t.timestamps(true, true, true);
|
||||
});
|
||||
}
|
||||
await createOnUpdateTrigger(knex, TableName.SecretBlindIndex);
|
||||
|
||||
if (!(await knex.schema.hasTable(TableName.Secret))) {
|
||||
await knex.schema.createTable(TableName.Secret, (t) => {
|
||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
t.integer("version").defaultTo(1).notNullable();
|
||||
t.string("type").notNullable().defaultTo(SecretType.Shared);
|
||||
// t.text("secretKeyHash").notNullable();
|
||||
// t.text("secretValueHash");
|
||||
// t.text("secretCommentHash");
|
||||
t.text("secretBlindIndex").notNullable();
|
||||
t.text("secretKeyCiphertext").notNullable();
|
||||
t.text("secretKeyIV").notNullable();
|
||||
t.text("secretKeyTag").notNullable();
|
||||
t.text("secretValueCiphertext").notNullable();
|
||||
t.text("secretValueIV").notNullable(); // symmetric encryption
|
||||
t.text("secretValueTag").notNullable();
|
||||
t.text("secretCommentCiphertext");
|
||||
t.text("secretCommentIV");
|
||||
t.text("secretCommentTag");
|
||||
t.string("secretReminderNote");
|
||||
t.integer("secretReminderRepeatDays");
|
||||
t.boolean("skipMultilineEncoding").defaultTo(false);
|
||||
t.string("algorithm").notNullable().defaultTo(SecretEncryptionAlgo.AES_256_GCM);
|
||||
t.string("keyEncoding").notNullable().defaultTo(SecretKeyEncoding.UTF8);
|
||||
t.jsonb("metadata");
|
||||
t.uuid("userId");
|
||||
t.foreign("userId").references("id").inTable(TableName.Users).onDelete("CASCADE");
|
||||
t.uuid("folderId").notNullable();
|
||||
t.foreign("folderId").references("id").inTable(TableName.SecretFolder).onDelete("CASCADE");
|
||||
t.timestamps(true, true, true);
|
||||
});
|
||||
}
|
||||
await createOnUpdateTrigger(knex, TableName.Secret);
|
||||
// many to many relation between tags
|
||||
await createJunctionTable(knex, TableName.JnSecretTag, TableName.Secret, TableName.SecretTag);
|
||||
}
|
||||
|
||||
export async function down(knex: Knex): Promise<void> {
|
||||
await knex.schema.dropTableIfExists(TableName.SecretBlindIndex);
|
||||
await dropOnUpdateTrigger(knex, TableName.SecretBlindIndex);
|
||||
|
||||
await knex.schema.dropTableIfExists(TableName.JnSecretTag);
|
||||
await knex.schema.dropTableIfExists(TableName.Secret);
|
||||
await dropOnUpdateTrigger(knex, TableName.Secret);
|
||||
}
|
||||
53
pg-migrator/src/migrations/20231220052508_secret-version.ts
Normal file
53
pg-migrator/src/migrations/20231220052508_secret-version.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { SecretEncryptionAlgo, SecretKeyEncoding, SecretType, TableName } from "../schemas";
|
||||
import { createJunctionTable, createOnUpdateTrigger, dropOnUpdateTrigger } from "../utils";
|
||||
|
||||
export async function up(knex: Knex): Promise<void> {
|
||||
if (!(await knex.schema.hasTable(TableName.SecretVersion))) {
|
||||
await knex.schema.createTable(TableName.SecretVersion, (t) => {
|
||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
t.integer("version").defaultTo(1).notNullable();
|
||||
t.string("type").notNullable().defaultTo(SecretType.Shared);
|
||||
t.text("secretBlindIndex").notNullable();
|
||||
t.text("secretKeyCiphertext").notNullable();
|
||||
t.text("secretKeyIV").notNullable();
|
||||
t.text("secretKeyTag").notNullable();
|
||||
t.text("secretValueCiphertext").notNullable();
|
||||
t.text("secretValueIV").notNullable(); // symmetric encryption
|
||||
t.text("secretValueTag").notNullable();
|
||||
t.text("secretCommentCiphertext");
|
||||
t.text("secretCommentIV");
|
||||
t.text("secretCommentTag");
|
||||
t.string("secretReminderNote");
|
||||
t.integer("secretReminderRepeatDays");
|
||||
t.boolean("skipMultilineEncoding").defaultTo(false);
|
||||
t.string("algorithm").notNullable().defaultTo(SecretEncryptionAlgo.AES_256_GCM);
|
||||
t.string("keyEncoding").notNullable().defaultTo(SecretKeyEncoding.UTF8);
|
||||
t.jsonb("metadata");
|
||||
// to avoid orphan rows
|
||||
t.uuid("envId");
|
||||
t.foreign("envId").references("id").inTable(TableName.Environment).onDelete("CASCADE");
|
||||
t.uuid("secretId").notNullable();
|
||||
t.uuid("folderId").notNullable();
|
||||
// t.foreign("secretId").references("id").inTable(TableName.Secret).onDelete("SET NULL");
|
||||
t.uuid("userId");
|
||||
t.foreign("userId").references("id").inTable(TableName.Users).onDelete("CASCADE");
|
||||
t.timestamps(true, true, true);
|
||||
});
|
||||
}
|
||||
await createOnUpdateTrigger(knex, TableName.SecretVersion);
|
||||
// many to many relation between tags
|
||||
await createJunctionTable(
|
||||
knex,
|
||||
TableName.JnSecretVersionTag,
|
||||
TableName.SecretVersion,
|
||||
TableName.SecretTag
|
||||
);
|
||||
}
|
||||
|
||||
export async function down(knex: Knex): Promise<void> {
|
||||
await knex.schema.dropTableIfExists(TableName.JnSecretVersionTag);
|
||||
await knex.schema.dropTableIfExists(TableName.SecretVersion);
|
||||
await dropOnUpdateTrigger(knex, TableName.SecretVersion);
|
||||
}
|
||||
35
pg-migrator/src/migrations/20231222092113_project-bot.ts
Normal file
35
pg-migrator/src/migrations/20231222092113_project-bot.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { TableName } from "../schemas";
|
||||
import { createOnUpdateTrigger, dropOnUpdateTrigger } from "../utils";
|
||||
|
||||
export async function up(knex: Knex): Promise<void> {
|
||||
if (!(await knex.schema.hasTable(TableName.ProjectBot))) {
|
||||
await knex.schema.createTable(TableName.ProjectBot, (t) => {
|
||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
t.string("name").notNullable();
|
||||
t.boolean("isActive").defaultTo(false).notNullable();
|
||||
t.text("encryptedPrivateKey").notNullable();
|
||||
t.text("publicKey").notNullable();
|
||||
t.text("iv").notNullable();
|
||||
t.text("tag").notNullable();
|
||||
t.string("algorithm").notNullable();
|
||||
t.string("keyEncoding").notNullable();
|
||||
t.text("encryptedProjectKey");
|
||||
t.text("encryptedProjectKeyNonce");
|
||||
// one to one relationship
|
||||
t.string("projectId").notNullable().unique();
|
||||
t.foreign("projectId").references("id").inTable(TableName.Project).onDelete("CASCADE");
|
||||
t.uuid("senderId");
|
||||
t.foreign("senderId").references("id").inTable(TableName.Users).onDelete("SET NULL");
|
||||
t.timestamps(true, true, true);
|
||||
});
|
||||
}
|
||||
|
||||
await createOnUpdateTrigger(knex, TableName.ProjectBot);
|
||||
}
|
||||
|
||||
export async function down(knex: Knex): Promise<void> {
|
||||
await knex.schema.dropTableIfExists(TableName.ProjectBot);
|
||||
await dropOnUpdateTrigger(knex, TableName.ProjectBot);
|
||||
}
|
||||
71
pg-migrator/src/migrations/20231222172455_integration.ts
Normal file
71
pg-migrator/src/migrations/20231222172455_integration.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { TableName } from "../schemas";
|
||||
import { createOnUpdateTrigger, dropOnUpdateTrigger } from "../utils";
|
||||
|
||||
export async function up(knex: Knex): Promise<void> {
|
||||
if (!(await knex.schema.hasTable(TableName.IntegrationAuth))) {
|
||||
await knex.schema.createTable(TableName.IntegrationAuth, (t) => {
|
||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
t.string("integration").notNullable();
|
||||
t.string("teamId"); // vercel-specific
|
||||
t.string("url"); // for self hosted
|
||||
t.string("namespace"); // hashicorp specific
|
||||
t.string("accountId"); // netlify
|
||||
t.string("refreshCiphertext");
|
||||
t.string("refreshIV");
|
||||
t.string("refreshTag");
|
||||
t.string("accessIdCiphertext");
|
||||
t.string("accessIdIV");
|
||||
t.string("accessIdTag");
|
||||
t.string("accessCiphertext");
|
||||
t.string("accessIV");
|
||||
t.string("accessTag");
|
||||
t.datetime("accessExpiresAt");
|
||||
t.jsonb("metadata");
|
||||
t.string("algorithm").notNullable();
|
||||
t.string("keyEncoding").notNullable();
|
||||
t.string("projectId").notNullable();
|
||||
t.foreign("projectId").references("id").inTable(TableName.Project).onDelete("CASCADE");
|
||||
t.timestamps(true, true, true);
|
||||
});
|
||||
}
|
||||
await createOnUpdateTrigger(knex, TableName.IntegrationAuth);
|
||||
|
||||
if (!(await knex.schema.hasTable(TableName.Integration))) {
|
||||
await knex.schema.createTable(TableName.Integration, (t) => {
|
||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
t.boolean("isActive").notNullable();
|
||||
t.string("url"); // self hosted
|
||||
t.string("app"); // name of app in provider
|
||||
t.string("appId");
|
||||
t.string("targetEnvironment");
|
||||
t.string("targetEnvironmentId");
|
||||
t.string("targetService"); // railway - qovery specific
|
||||
t.string("targetServiceId");
|
||||
t.string("owner"); // github specific
|
||||
t.string("path"); // aws parameter store / vercel preview branch
|
||||
t.string("region"); // aws
|
||||
t.string("scope"); // qovery specific scope
|
||||
t.string("integration").notNullable();
|
||||
t.jsonb("metadata");
|
||||
t.uuid("integrationAuthId").notNullable();
|
||||
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");
|
||||
t.timestamps(true, true, true);
|
||||
});
|
||||
}
|
||||
await createOnUpdateTrigger(knex, TableName.Integration);
|
||||
}
|
||||
|
||||
export async function down(knex: Knex): Promise<void> {
|
||||
await knex.schema.dropTableIfExists(TableName.Integration);
|
||||
await knex.schema.dropTableIfExists(TableName.IntegrationAuth);
|
||||
await dropOnUpdateTrigger(knex, TableName.IntegrationAuth);
|
||||
await dropOnUpdateTrigger(knex, TableName.Integration);
|
||||
}
|
||||
32
pg-migrator/src/migrations/20231225072545_service-token.ts
Normal file
32
pg-migrator/src/migrations/20231225072545_service-token.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { TableName } from "../schemas";
|
||||
import { createOnUpdateTrigger, dropOnUpdateTrigger } from "../utils";
|
||||
|
||||
export async function up(knex: Knex): Promise<void> {
|
||||
if (!(await knex.schema.hasTable(TableName.ServiceToken))) {
|
||||
await knex.schema.createTable(TableName.ServiceToken, (t) => {
|
||||
t.string("id", 36).primary().defaultTo(knex.fn.uuid());
|
||||
t.string("name").notNullable();
|
||||
t.jsonb("scopes").notNullable();
|
||||
t.specificType("permissions", "text[]").notNullable();
|
||||
t.datetime("lastUsed");
|
||||
t.datetime("expiresAt");
|
||||
t.text("secretHash").notNullable();
|
||||
t.text("encryptedKey");
|
||||
t.text("iv");
|
||||
t.text("tag");
|
||||
t.timestamps(true, true, true);
|
||||
// user is old one
|
||||
t.string("createdBy").notNullable();
|
||||
t.string("projectId").notNullable();
|
||||
t.foreign("projectId").references("id").inTable(TableName.Project).onDelete("CASCADE");
|
||||
});
|
||||
}
|
||||
await createOnUpdateTrigger(knex, TableName.ServiceToken);
|
||||
}
|
||||
|
||||
export async function down(knex: Knex): Promise<void> {
|
||||
await knex.schema.dropTableIfExists(TableName.ServiceToken);
|
||||
await dropOnUpdateTrigger(knex, TableName.ServiceToken);
|
||||
}
|
||||
32
pg-migrator/src/migrations/20231225072552_webhook.ts
Normal file
32
pg-migrator/src/migrations/20231225072552_webhook.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { TableName } from "../schemas";
|
||||
import { createOnUpdateTrigger, dropOnUpdateTrigger } from "../utils";
|
||||
|
||||
export async function up(knex: Knex): Promise<void> {
|
||||
if (!(await knex.schema.hasTable(TableName.Webhook))) {
|
||||
await knex.schema.createTable(TableName.Webhook, (t) => {
|
||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
t.string("secretPath").notNullable().defaultTo("/");
|
||||
t.string("url").notNullable();
|
||||
t.string("lastStatus");
|
||||
t.text("lastRunErrorMessage");
|
||||
t.boolean("isDisabled").defaultTo(false).notNullable();
|
||||
// webhook signature
|
||||
t.text("encryptedSecretKey");
|
||||
t.text("iv");
|
||||
t.text("tag");
|
||||
t.string("algorithm");
|
||||
t.string("keyEncoding");
|
||||
t.timestamps(true, true, true);
|
||||
t.uuid("envId").notNullable();
|
||||
t.foreign("envId").references("id").inTable(TableName.Environment).onDelete("CASCADE");
|
||||
});
|
||||
}
|
||||
await createOnUpdateTrigger(knex, TableName.Webhook);
|
||||
}
|
||||
|
||||
export async function down(knex: Knex): Promise<void> {
|
||||
await knex.schema.dropTableIfExists(TableName.Webhook);
|
||||
await dropOnUpdateTrigger(knex, TableName.Webhook);
|
||||
}
|
||||
21
pg-migrator/src/migrations/20231228074856_identity.ts
Normal file
21
pg-migrator/src/migrations/20231228074856_identity.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { TableName } from "../schemas";
|
||||
import { createOnUpdateTrigger, dropOnUpdateTrigger } from "../utils";
|
||||
|
||||
export async function up(knex: Knex): Promise<void> {
|
||||
if (!(await knex.schema.hasTable(TableName.Identity))) {
|
||||
await knex.schema.createTable(TableName.Identity, (t) => {
|
||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
t.string("name").notNullable();
|
||||
t.string("authMethod");
|
||||
t.timestamps(true, true, true);
|
||||
});
|
||||
}
|
||||
await createOnUpdateTrigger(knex, TableName.Identity);
|
||||
}
|
||||
|
||||
export async function down(knex: Knex): Promise<void> {
|
||||
await knex.schema.dropTableIfExists(TableName.Identity);
|
||||
await dropOnUpdateTrigger(knex, TableName.Identity);
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { TableName } from "../schemas";
|
||||
import { createOnUpdateTrigger, dropOnUpdateTrigger } from "../utils";
|
||||
|
||||
export async function up(knex: Knex): Promise<void> {
|
||||
if (!(await knex.schema.hasTable(TableName.IdentityUniversalAuth))) {
|
||||
await knex.schema.createTable(TableName.IdentityUniversalAuth, (t) => {
|
||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
t.string("clientId").notNullable();
|
||||
t.integer("accessTokenTTL").defaultTo(7200).notNullable();
|
||||
t.integer("accessTokenMaxTTL").defaultTo(7200).notNullable();
|
||||
t.integer("accessTokenNumUsesLimit").defaultTo(0).notNullable();
|
||||
t.jsonb("clientSecretTrustedIps").notNullable();
|
||||
t.jsonb("accessTokenTrustedIps").notNullable();
|
||||
t.timestamps(true, true, true);
|
||||
t.uuid("identityId").notNullable().unique();
|
||||
t.foreign("identityId").references("id").inTable(TableName.Identity).onDelete("CASCADE");
|
||||
});
|
||||
}
|
||||
if (!(await knex.schema.hasTable(TableName.IdentityUaClientSecret))) {
|
||||
await knex.schema.createTable(TableName.IdentityUaClientSecret, (t) => {
|
||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
t.string("description").notNullable();
|
||||
t.string("clientSecretPrefix").notNullable();
|
||||
t.string("clientSecretHash").notNullable();
|
||||
t.datetime("clientSecretLastUsedAt");
|
||||
t.integer("clientSecretNumUses").defaultTo(0).notNullable();
|
||||
t.integer("clientSecretNumUsesLimit").defaultTo(0).notNullable();
|
||||
t.integer("clientSecretTTL").defaultTo(0).notNullable();
|
||||
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");
|
||||
});
|
||||
}
|
||||
await createOnUpdateTrigger(knex, TableName.IdentityUniversalAuth);
|
||||
await createOnUpdateTrigger(knex, TableName.IdentityUaClientSecret);
|
||||
}
|
||||
|
||||
export async function down(knex: Knex): Promise<void> {
|
||||
await knex.schema.dropTableIfExists(TableName.IdentityUaClientSecret);
|
||||
await knex.schema.dropTableIfExists(TableName.IdentityUniversalAuth);
|
||||
await dropOnUpdateTrigger(knex, TableName.IdentityUaClientSecret);
|
||||
await dropOnUpdateTrigger(knex, TableName.IdentityUniversalAuth);
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { TableName } from "../schemas";
|
||||
import { createOnUpdateTrigger, dropOnUpdateTrigger } from "../utils";
|
||||
|
||||
export async function up(knex: Knex): Promise<void> {
|
||||
if (!(await knex.schema.hasTable(TableName.IdentityAccessToken))) {
|
||||
await knex.schema.createTable(TableName.IdentityAccessToken, (t) => {
|
||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
t.string("authType").notNullable();
|
||||
t.integer("accessTokenTTL").defaultTo(2592000).notNullable(); // 30 days second
|
||||
t.integer("accessTokenMaxTTL").defaultTo(2592000).notNullable();
|
||||
t.integer("accessTokenNumUses").defaultTo(0).notNullable();
|
||||
t.integer("accessTokenNumUsesLimit").defaultTo(0).notNullable();
|
||||
t.datetime("accessTokenLastUsedAt");
|
||||
t.datetime("accessTokenLastRenewedAt");
|
||||
t.boolean("isAccessTokenRevoked").defaultTo(false).notNullable();
|
||||
t.uuid("identityUAClientSecretId");
|
||||
t.foreign("identityUAClientSecretId")
|
||||
.references("id")
|
||||
.inTable(TableName.IdentityUaClientSecret)
|
||||
.onDelete("CASCADE");
|
||||
t.uuid("identityId").notNullable();
|
||||
t.foreign("identityId").references("id").inTable(TableName.Identity).onDelete("CASCADE");
|
||||
t.timestamps(true, true, true);
|
||||
});
|
||||
}
|
||||
|
||||
await createOnUpdateTrigger(knex, TableName.IdentityAccessToken);
|
||||
}
|
||||
|
||||
export async function down(knex: Knex): Promise<void> {
|
||||
await knex.schema.dropTableIfExists(TableName.IdentityAccessToken);
|
||||
await dropOnUpdateTrigger(knex, TableName.IdentityAccessToken);
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { TableName } from "../schemas";
|
||||
import { createOnUpdateTrigger, dropOnUpdateTrigger } from "../utils";
|
||||
|
||||
export async function up(knex: Knex): Promise<void> {
|
||||
if (!(await knex.schema.hasTable(TableName.IdentityOrgMembership))) {
|
||||
await knex.schema.createTable(TableName.IdentityOrgMembership, (t) => {
|
||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
t.string("role").notNullable();
|
||||
t.uuid("roleId");
|
||||
t.foreign("roleId").references("id").inTable(TableName.OrgRoles);
|
||||
t.uuid("orgId").notNullable();
|
||||
t.foreign("orgId").references("id").inTable(TableName.Organization).onDelete("CASCADE");
|
||||
t.timestamps(true, true, true);
|
||||
t.uuid("identityId").notNullable();
|
||||
t.foreign("identityId").references("id").inTable(TableName.Identity).onDelete("CASCADE");
|
||||
});
|
||||
}
|
||||
await createOnUpdateTrigger(knex, TableName.IdentityOrgMembership);
|
||||
|
||||
if (!(await knex.schema.hasTable(TableName.IdentityProjectMembership))) {
|
||||
await knex.schema.createTable(TableName.IdentityProjectMembership, (t) => {
|
||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
t.string("role").notNullable();
|
||||
t.uuid("roleId");
|
||||
t.foreign("roleId").references("id").inTable(TableName.ProjectRoles);
|
||||
t.string("projectId").notNullable();
|
||||
t.foreign("projectId").references("id").inTable(TableName.Project).onDelete("CASCADE");
|
||||
t.uuid("identityId").notNullable();
|
||||
t.foreign("identityId").references("id").inTable(TableName.Identity).onDelete("CASCADE");
|
||||
t.timestamps(true, true, true);
|
||||
});
|
||||
}
|
||||
await createOnUpdateTrigger(knex, TableName.IdentityProjectMembership);
|
||||
}
|
||||
|
||||
export async function down(knex: Knex): Promise<void> {
|
||||
await knex.schema.dropTableIfExists(TableName.IdentityOrgMembership);
|
||||
await knex.schema.dropTableIfExists(TableName.IdentityProjectMembership);
|
||||
|
||||
await dropOnUpdateTrigger(knex, TableName.IdentityProjectMembership);
|
||||
await dropOnUpdateTrigger(knex, TableName.IdentityOrgMembership);
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { TableName } from "../schemas";
|
||||
import { createOnUpdateTrigger, dropOnUpdateTrigger } from "../utils";
|
||||
|
||||
export async function up(knex: Knex): Promise<void> {
|
||||
if (!(await knex.schema.hasTable(TableName.SecretApprovalPolicy))) {
|
||||
await knex.schema.createTable(TableName.SecretApprovalPolicy, (t) => {
|
||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
t.string("name").notNullable();
|
||||
t.string("secretPath");
|
||||
t.integer("approvals").defaultTo(1).notNullable();
|
||||
t.uuid("envId").notNullable();
|
||||
t.foreign("envId").references("id").inTable(TableName.Environment).onDelete("CASCADE");
|
||||
t.timestamps(true, true, true);
|
||||
});
|
||||
}
|
||||
await createOnUpdateTrigger(knex, TableName.SecretApprovalPolicy);
|
||||
|
||||
if (!(await knex.schema.hasTable(TableName.SapApprover))) {
|
||||
await knex.schema.createTable(TableName.SapApprover, (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.uuid("policyId").notNullable();
|
||||
t.foreign("policyId")
|
||||
.references("id")
|
||||
.inTable(TableName.SecretApprovalPolicy)
|
||||
.onDelete("CASCADE");
|
||||
t.timestamps(true, true, true);
|
||||
});
|
||||
}
|
||||
|
||||
await createOnUpdateTrigger(knex, TableName.SapApprover);
|
||||
}
|
||||
|
||||
export async function down(knex: Knex): Promise<void> {
|
||||
await knex.schema.dropTableIfExists(TableName.SapApprover);
|
||||
await knex.schema.dropTableIfExists(TableName.SecretApprovalPolicy);
|
||||
await dropOnUpdateTrigger(knex, TableName.SapApprover);
|
||||
await dropOnUpdateTrigger(knex, TableName.SecretApprovalPolicy);
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { SecretEncryptionAlgo, SecretKeyEncoding, TableName } from "../schemas";
|
||||
import { createOnUpdateTrigger, dropOnUpdateTrigger } from "../utils";
|
||||
|
||||
export async function up(knex: Knex): Promise<void> {
|
||||
if (!(await knex.schema.hasTable(TableName.SecretApprovalRequest))) {
|
||||
await knex.schema.createTable(TableName.SecretApprovalRequest, (t) => {
|
||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
t.uuid("policyId").notNullable();
|
||||
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.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("CASCADE");
|
||||
t.uuid("committerId").notNullable();
|
||||
t.foreign("committerId")
|
||||
.references("id")
|
||||
.inTable(TableName.ProjectMembership)
|
||||
.onDelete("CASCADE");
|
||||
t.timestamps(true, true, true);
|
||||
});
|
||||
}
|
||||
await createOnUpdateTrigger(knex, TableName.SecretApprovalRequest);
|
||||
|
||||
if (!(await knex.schema.hasTable(TableName.SarReviewer))) {
|
||||
await knex.schema.createTable(TableName.SarReviewer, (t) => {
|
||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
t.uuid("member").notNullable();
|
||||
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.timestamps(true, true, true);
|
||||
});
|
||||
}
|
||||
await createOnUpdateTrigger(knex, TableName.SarReviewer);
|
||||
|
||||
if (!(await knex.schema.hasTable(TableName.SarSecret))) {
|
||||
await knex.schema.createTable(TableName.SarSecret, (t) => {
|
||||
// everything related to secret
|
||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
t.integer("version").defaultTo(1);
|
||||
t.text("secretBlindIndex").notNullable();
|
||||
t.text("secretKeyCiphertext").notNullable();
|
||||
t.text("secretKeyIV").notNullable();
|
||||
t.text("secretKeyTag").notNullable();
|
||||
t.text("secretValueCiphertext").notNullable();
|
||||
t.text("secretValueIV").notNullable(); // symmetric encryption
|
||||
t.text("secretValueTag").notNullable();
|
||||
t.text("secretCommentCiphertext");
|
||||
t.text("secretCommentIV");
|
||||
t.text("secretCommentTag");
|
||||
t.string("secretReminderNote");
|
||||
t.integer("secretReminderRepeatDays");
|
||||
t.boolean("skipMultilineEncoding").defaultTo(false);
|
||||
t.string("algorithm").notNullable().defaultTo(SecretEncryptionAlgo.AES_256_GCM);
|
||||
t.string("keyEncoding").notNullable().defaultTo(SecretKeyEncoding.UTF8);
|
||||
t.jsonb("metadata");
|
||||
t.timestamps(true, true, true);
|
||||
// commit details
|
||||
t.uuid("requestId").notNullable();
|
||||
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");
|
||||
});
|
||||
}
|
||||
await createOnUpdateTrigger(knex, TableName.SarSecret);
|
||||
|
||||
if (!(await knex.schema.hasTable(TableName.SarSecretTag))) {
|
||||
await knex.schema.createTable(TableName.SarSecretTag, (t) => {
|
||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
t.uuid("secretId").notNullable();
|
||||
t.foreign("secretId").references("id").inTable(TableName.SarSecret).onDelete("CASCADE");
|
||||
t.uuid("tagId").notNullable();
|
||||
t.foreign("tagId").references("id").inTable(TableName.SecretTag).onDelete("CASCADE");
|
||||
t.timestamps(true, true, true);
|
||||
});
|
||||
}
|
||||
await createOnUpdateTrigger(knex, TableName.SarSecretTag);
|
||||
}
|
||||
|
||||
export async function down(knex: Knex): Promise<void> {
|
||||
await knex.schema.dropTableIfExists(TableName.SarSecretTag);
|
||||
await knex.schema.dropTableIfExists(TableName.SarSecret);
|
||||
await knex.schema.dropTableIfExists(TableName.SarReviewer);
|
||||
await knex.schema.dropTableIfExists(TableName.SecretApprovalRequest);
|
||||
|
||||
await dropOnUpdateTrigger(knex, TableName.SarSecretTag);
|
||||
await dropOnUpdateTrigger(knex, TableName.SarSecret);
|
||||
await dropOnUpdateTrigger(knex, TableName.SarReviewer);
|
||||
await dropOnUpdateTrigger(knex, TableName.SecretApprovalRequest);
|
||||
}
|
||||
47
pg-migrator/src/migrations/20240102152111_secret-rotation.ts
Normal file
47
pg-migrator/src/migrations/20240102152111_secret-rotation.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { TableName } from "../schemas";
|
||||
import { createOnUpdateTrigger, dropOnUpdateTrigger } from "../utils";
|
||||
|
||||
export async function up(knex: Knex): Promise<void> {
|
||||
if (!(await knex.schema.hasTable(TableName.SecretRotation))) {
|
||||
await knex.schema.createTable(TableName.SecretRotation, (t) => {
|
||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
t.string("provider").notNullable();
|
||||
t.string("secretPath").notNullable();
|
||||
t.integer("interval").notNullable();
|
||||
t.datetime("lastRotatedAt");
|
||||
t.string("status");
|
||||
t.text("statusMessage");
|
||||
t.text("encryptedData");
|
||||
t.text("encryptedDataIV");
|
||||
t.text("encryptedDataTag");
|
||||
t.string("algorithm");
|
||||
t.string("keyEncoding");
|
||||
t.uuid("envId").notNullable();
|
||||
t.foreign("envId").references("id").inTable(TableName.Environment).onDelete("CASCADE");
|
||||
t.timestamps(true, true, true);
|
||||
});
|
||||
}
|
||||
await createOnUpdateTrigger(knex, TableName.SecretRotation);
|
||||
|
||||
if (!(await knex.schema.hasTable(TableName.SecretRotationOutput))) {
|
||||
await knex.schema.createTable(TableName.SecretRotationOutput, (t) => {
|
||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
t.string("key").notNullable();
|
||||
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");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export async function down(knex: Knex): Promise<void> {
|
||||
await knex.schema.dropTableIfExists(TableName.SecretRotationOutput);
|
||||
await knex.schema.dropTableIfExists(TableName.SecretRotation);
|
||||
await dropOnUpdateTrigger(knex, TableName.SecretRotation);
|
||||
}
|
||||
61
pg-migrator/src/migrations/20240104140641_secret-snapshot.ts
Normal file
61
pg-migrator/src/migrations/20240104140641_secret-snapshot.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { TableName } from "../schemas";
|
||||
import { createOnUpdateTrigger, dropOnUpdateTrigger } from "../utils";
|
||||
|
||||
export async function up(knex: Knex): Promise<void> {
|
||||
if (!(await knex.schema.hasTable(TableName.Snapshot))) {
|
||||
await knex.schema.createTable(TableName.Snapshot, (t) => {
|
||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
t.uuid("envId").notNullable();
|
||||
t.foreign("envId").references("id").inTable(TableName.Environment).onDelete("CASCADE");
|
||||
// this is not a relation kept like that
|
||||
// this ensure snapshot are not lost when folder gets deleted and rolled back
|
||||
t.uuid("folderId").notNullable();
|
||||
t.uuid("parentFolderId");
|
||||
t.timestamps(true, true, true);
|
||||
});
|
||||
}
|
||||
await createOnUpdateTrigger(knex, TableName.Snapshot);
|
||||
|
||||
if (!(await knex.schema.hasTable(TableName.SnapshotSecret))) {
|
||||
await knex.schema.createTable(TableName.SnapshotSecret, (t) => {
|
||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
t.uuid("envId").notNullable();
|
||||
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.uuid("snapshotId").notNullable();
|
||||
t.foreign("snapshotId").references("id").inTable(TableName.Snapshot).onDelete("CASCADE");
|
||||
t.timestamps(true, true, true);
|
||||
});
|
||||
}
|
||||
|
||||
if (!(await knex.schema.hasTable(TableName.SnapshotFolder))) {
|
||||
await knex.schema.createTable(TableName.SnapshotFolder, (t) => {
|
||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
t.uuid("envId").notNullable();
|
||||
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.uuid("snapshotId").notNullable();
|
||||
t.foreign("snapshotId").references("id").inTable(TableName.Snapshot).onDelete("CASCADE");
|
||||
t.timestamps(true, true, true);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export async function down(knex: Knex): Promise<void> {
|
||||
await knex.schema.dropTableIfExists(TableName.SnapshotSecret);
|
||||
await knex.schema.dropTableIfExists(TableName.SnapshotFolder);
|
||||
await knex.schema.dropTableIfExists(TableName.Snapshot);
|
||||
await dropOnUpdateTrigger(knex, TableName.Snapshot);
|
||||
}
|
||||
33
pg-migrator/src/migrations/20240107153439_saml-config.ts
Normal file
33
pg-migrator/src/migrations/20240107153439_saml-config.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { TableName } from "../schemas";
|
||||
import { createOnUpdateTrigger, dropOnUpdateTrigger } from "../utils";
|
||||
|
||||
export async function up(knex: Knex): Promise<void> {
|
||||
if (!(await knex.schema.hasTable(TableName.SamlConfig))) {
|
||||
await knex.schema.createTable(TableName.SamlConfig, (t) => {
|
||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
t.string("authProvider").notNullable();
|
||||
t.boolean("isActive").notNullable();
|
||||
t.string("encryptedEntryPoint");
|
||||
t.string("entryPointIV");
|
||||
t.string("entryPointTag");
|
||||
t.string("encryptedIssuer");
|
||||
t.string("issuerTag");
|
||||
t.string("issuerIV");
|
||||
t.text("encryptedCert");
|
||||
t.string("certIV");
|
||||
t.string("certTag");
|
||||
t.timestamps(true, true, true);
|
||||
t.uuid("orgId").notNullable().unique();
|
||||
t.foreign("orgId").references("id").inTable(TableName.Organization);
|
||||
});
|
||||
}
|
||||
|
||||
await createOnUpdateTrigger(knex, TableName.SamlConfig);
|
||||
}
|
||||
|
||||
export async function down(knex: Knex): Promise<void> {
|
||||
await knex.schema.dropTableIfExists(TableName.SamlConfig);
|
||||
await dropOnUpdateTrigger(knex, TableName.SamlConfig);
|
||||
}
|
||||
35
pg-migrator/src/migrations/20240107163155_org-bot.ts
Normal file
35
pg-migrator/src/migrations/20240107163155_org-bot.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { TableName } from "../schemas";
|
||||
import { createOnUpdateTrigger, dropOnUpdateTrigger } from "../utils";
|
||||
|
||||
export async function up(knex: Knex): Promise<void> {
|
||||
if (!(await knex.schema.hasTable(TableName.OrgBot))) {
|
||||
await knex.schema.createTable(TableName.OrgBot, (t) => {
|
||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
t.string("name").notNullable();
|
||||
t.text("publicKey").notNullable();
|
||||
t.text("encryptedSymmetricKey").notNullable();
|
||||
t.text("symmetricKeyIV").notNullable();
|
||||
t.text("symmetricKeyTag").notNullable();
|
||||
t.string("symmetricKeyAlgorithm").notNullable();
|
||||
t.string("symmetricKeyKeyEncoding").notNullable();
|
||||
t.text("encryptedPrivateKey").notNullable();
|
||||
t.text("privateKeyIV").notNullable();
|
||||
t.text("privateKeyTag").notNullable();
|
||||
t.string("privateKeyAlgorithm").notNullable();
|
||||
t.string("privateKeyKeyEncoding").notNullable();
|
||||
// one to one relationship
|
||||
t.uuid("orgId").notNullable().unique();
|
||||
t.foreign("orgId").references("id").inTable(TableName.Organization).onDelete("CASCADE");
|
||||
t.timestamps(true, true, true);
|
||||
});
|
||||
}
|
||||
|
||||
await createOnUpdateTrigger(knex, TableName.OrgBot);
|
||||
}
|
||||
|
||||
export async function down(knex: Knex): Promise<void> {
|
||||
await knex.schema.dropTableIfExists(TableName.OrgBot);
|
||||
await dropOnUpdateTrigger(knex, TableName.OrgBot);
|
||||
}
|
||||
29
pg-migrator/src/migrations/20240108134148_audit-log.ts
Normal file
29
pg-migrator/src/migrations/20240108134148_audit-log.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { TableName } from "../schemas";
|
||||
|
||||
export async function up(knex: Knex): Promise<void> {
|
||||
if (!(await knex.schema.hasTable(TableName.AuditLog))) {
|
||||
await knex.schema.createTable(TableName.AuditLog, (t) => {
|
||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
t.string("actor").notNullable();
|
||||
t.jsonb("actorMetadata").notNullable();
|
||||
t.string("ipAddress");
|
||||
t.string("eventType").notNullable();
|
||||
t.jsonb("eventMetadata");
|
||||
t.string("userAgent");
|
||||
t.string("userAgentType");
|
||||
t.datetime("expiresAt");
|
||||
t.timestamps(true, true, true);
|
||||
// no trigger needed as this collection is append only
|
||||
t.uuid("orgId");
|
||||
t.foreign("orgId").references("id").inTable(TableName.Organization).onDelete("CASCADE");
|
||||
t.string("projectId");
|
||||
t.foreign("projectId").references("id").inTable(TableName.Project).onDelete("CASCADE");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export async function down(knex: Knex): Promise<void> {
|
||||
await knex.schema.dropTableIfExists(TableName.AuditLog);
|
||||
}
|
||||
79
pg-migrator/src/migrations/20240111051011_secret-scanning.ts
Normal file
79
pg-migrator/src/migrations/20240111051011_secret-scanning.ts
Normal file
@@ -0,0 +1,79 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { TableName } from "../schemas";
|
||||
import { createOnUpdateTrigger, dropOnUpdateTrigger } from "../utils";
|
||||
|
||||
export async function up(knex: Knex): Promise<void> {
|
||||
if (!(await knex.schema.hasTable(TableName.GitAppInstallSession))) {
|
||||
await knex.schema.createTable(TableName.GitAppInstallSession, (t) => {
|
||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
t.string("sessionId").notNullable().unique();
|
||||
t.uuid("userId");
|
||||
// one to one relationship
|
||||
t.uuid("orgId").notNullable().unique();
|
||||
t.foreign("orgId").references("id").inTable(TableName.Organization).onDelete("CASCADE");
|
||||
t.timestamps(true, true, true);
|
||||
});
|
||||
}
|
||||
createOnUpdateTrigger(knex, TableName.GitAppInstallSession);
|
||||
|
||||
if (!(await knex.schema.hasTable(TableName.GitAppOrg))) {
|
||||
await knex.schema.createTable(TableName.GitAppOrg, (t) => {
|
||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
t.string("installationId").notNullable().unique();
|
||||
t.uuid("userId").notNullable();
|
||||
// one to one relationship
|
||||
t.uuid("orgId").notNullable().unique();
|
||||
t.foreign("orgId").references("id").inTable(TableName.Organization).onDelete("CASCADE");
|
||||
t.timestamps(true, true, true);
|
||||
});
|
||||
}
|
||||
createOnUpdateTrigger(knex, TableName.GitAppOrg);
|
||||
|
||||
if (!(await knex.schema.hasTable(TableName.SecretScanningGitRisk))) {
|
||||
await knex.schema.createTable(TableName.SecretScanningGitRisk, (t) => {
|
||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
t.string("description");
|
||||
t.string("startLine");
|
||||
t.string("endLine");
|
||||
t.string("startColumn");
|
||||
t.string("endColumn");
|
||||
t.string("file");
|
||||
t.string("symlinkFile");
|
||||
t.string("commit");
|
||||
t.string("entropy");
|
||||
t.string("author");
|
||||
t.string("email");
|
||||
t.string("date");
|
||||
t.text("message");
|
||||
t.specificType("tags", "text[]");
|
||||
t.string("ruleID");
|
||||
t.string("fingerprint").unique();
|
||||
t.string("fingerPrintWithoutCommitId");
|
||||
t.boolean("isFalsePositive").defaultTo(false);
|
||||
t.boolean("isResolved").defaultTo(false);
|
||||
t.string("riskOwner");
|
||||
t.string("installationId").notNullable();
|
||||
t.string("repositoryId");
|
||||
t.string("repositoryLink");
|
||||
t.string("repositoryFullName");
|
||||
t.string("pusherName");
|
||||
t.string("pusherEmail");
|
||||
t.string("status");
|
||||
// one to one relationship
|
||||
t.uuid("orgId").notNullable();
|
||||
t.foreign("orgId").references("id").inTable(TableName.Organization).onDelete("CASCADE");
|
||||
t.timestamps(true, true, true);
|
||||
});
|
||||
}
|
||||
createOnUpdateTrigger(knex, TableName.SecretScanningGitRisk);
|
||||
}
|
||||
|
||||
export async function down(knex: Knex): Promise<void> {
|
||||
await knex.schema.dropTableIfExists(TableName.SecretScanningGitRisk);
|
||||
await knex.schema.dropTableIfExists(TableName.GitAppOrg);
|
||||
await knex.schema.dropTableIfExists(TableName.GitAppInstallSession);
|
||||
await dropOnUpdateTrigger(knex, TableName.SecretScanningGitRisk);
|
||||
await dropOnUpdateTrigger(knex, TableName.GitAppOrg);
|
||||
await dropOnUpdateTrigger(knex, TableName.GitAppInstallSession);
|
||||
}
|
||||
26
pg-migrator/src/migrations/20240113103743_trusted-ip.ts
Normal file
26
pg-migrator/src/migrations/20240113103743_trusted-ip.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { TableName } from "../schemas";
|
||||
import { createOnUpdateTrigger, dropOnUpdateTrigger } from "../utils";
|
||||
|
||||
export async function up(knex: Knex): Promise<void> {
|
||||
if (!(await knex.schema.hasTable(TableName.TrustedIps))) {
|
||||
await knex.schema.createTable(TableName.TrustedIps, (t) => {
|
||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
t.string("ipAddress").notNullable();
|
||||
t.string("type").notNullable();
|
||||
t.integer("prefix");
|
||||
t.boolean("isActive").defaultTo(true);
|
||||
t.string("comment");
|
||||
t.string("projectId").notNullable();
|
||||
t.foreign("projectId").references("id").inTable(TableName.Project);
|
||||
t.timestamps(true, true, true);
|
||||
});
|
||||
}
|
||||
await createOnUpdateTrigger(knex, TableName.TrustedIps);
|
||||
}
|
||||
|
||||
export async function down(knex: Knex): Promise<void> {
|
||||
await knex.schema.dropTableIfExists(TableName.TrustedIps);
|
||||
await dropOnUpdateTrigger(knex, TableName.TrustedIps);
|
||||
}
|
||||
39
pg-migrator/src/models/apiKeyData.ts
Normal file
39
pg-migrator/src/models/apiKeyData.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import { Schema, Types, model } from "mongoose";
|
||||
|
||||
export interface IAPIKeyData {
|
||||
name: string;
|
||||
user: Types.ObjectId;
|
||||
lastUsed: Date;
|
||||
expiresAt: Date;
|
||||
secretHash: string;
|
||||
}
|
||||
|
||||
const apiKeyDataSchema = new Schema<IAPIKeyData>(
|
||||
{
|
||||
name: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
user: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "User",
|
||||
required: true,
|
||||
},
|
||||
lastUsed: {
|
||||
type: Date,
|
||||
},
|
||||
expiresAt: {
|
||||
type: Date,
|
||||
},
|
||||
secretHash: {
|
||||
type: String,
|
||||
required: true,
|
||||
select: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamps: true,
|
||||
}
|
||||
);
|
||||
|
||||
export const APIKeyData = model<IAPIKeyData>("APIKeyData", apiKeyDataSchema);
|
||||
38
pg-migrator/src/models/apiKeyDataV2.ts
Normal file
38
pg-migrator/src/models/apiKeyDataV2.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import { Document, Schema, Types, model } from "mongoose";
|
||||
|
||||
export interface IAPIKeyDataV2 extends Document {
|
||||
_id: Types.ObjectId;
|
||||
name: string;
|
||||
user: Types.ObjectId;
|
||||
lastUsed?: Date
|
||||
usageCount: number;
|
||||
expiresAt?: Date;
|
||||
}
|
||||
|
||||
const apiKeyDataV2Schema = new Schema(
|
||||
{
|
||||
name: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
user: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "User",
|
||||
required: true
|
||||
},
|
||||
lastUsed: {
|
||||
type: Date,
|
||||
required: false
|
||||
},
|
||||
usageCount: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
{
|
||||
timestamps: true
|
||||
}
|
||||
);
|
||||
|
||||
export const APIKeyDataV2 = model<IAPIKeyDataV2>("APIKeyDataV2", apiKeyDataV2Schema);
|
||||
70
pg-migrator/src/models/auditLog/auditLog.ts
Normal file
70
pg-migrator/src/models/auditLog/auditLog.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
import { Schema, Types, model } from "mongoose";
|
||||
import { ActorType, EventType, UserAgentType } from "./enums";
|
||||
import { Actor, Event } from "./types";
|
||||
|
||||
export interface IAuditLog {
|
||||
actor: Actor;
|
||||
organization: Types.ObjectId;
|
||||
workspace: Types.ObjectId;
|
||||
ipAddress: string;
|
||||
event: Event;
|
||||
userAgent: string;
|
||||
userAgentType: UserAgentType;
|
||||
expiresAt?: Date;
|
||||
}
|
||||
|
||||
const auditLogSchema = new Schema<IAuditLog>(
|
||||
{
|
||||
actor: {
|
||||
type: {
|
||||
type: String,
|
||||
enum: ActorType,
|
||||
required: true
|
||||
},
|
||||
metadata: {
|
||||
type: Schema.Types.Mixed
|
||||
}
|
||||
},
|
||||
organization: {
|
||||
type: Schema.Types.ObjectId,
|
||||
required: false
|
||||
},
|
||||
workspace: {
|
||||
type: Schema.Types.ObjectId,
|
||||
required: false,
|
||||
index: true
|
||||
},
|
||||
ipAddress: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
event: {
|
||||
type: {
|
||||
type: String,
|
||||
enum: EventType,
|
||||
required: true
|
||||
},
|
||||
metadata: {
|
||||
type: Schema.Types.Mixed
|
||||
}
|
||||
},
|
||||
userAgent: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
userAgentType: {
|
||||
type: String,
|
||||
enum: UserAgentType,
|
||||
required: true
|
||||
},
|
||||
expiresAt: {
|
||||
type: Date,
|
||||
expires: 0
|
||||
}
|
||||
},
|
||||
{
|
||||
timestamps: true
|
||||
}
|
||||
);
|
||||
|
||||
export const AuditLog = model<IAuditLog>("AuditLog", auditLogSchema);
|
||||
69
pg-migrator/src/models/auditLog/enums.ts
Normal file
69
pg-migrator/src/models/auditLog/enums.ts
Normal file
@@ -0,0 +1,69 @@
|
||||
export enum ActorType { // would extend to AWS, Azure, ...
|
||||
USER = "user", // userIdentity
|
||||
SERVICE = "service",
|
||||
IDENTITY = "identity"
|
||||
}
|
||||
|
||||
export enum UserAgentType {
|
||||
WEB = "web",
|
||||
CLI = "cli",
|
||||
K8_OPERATOR = "k8-operator",
|
||||
TERRAFORM = "terraform",
|
||||
OTHER = "other",
|
||||
PYTHON_SDK = "InfisicalPythonSDK",
|
||||
NODE_SDK = "InfisicalNodeSDK"
|
||||
}
|
||||
|
||||
export enum EventType {
|
||||
GET_SECRETS = "get-secrets",
|
||||
GET_SECRET = "get-secret",
|
||||
REVEAL_SECRET = "reveal-secret",
|
||||
CREATE_SECRET = "create-secret",
|
||||
CREATE_SECRETS = "create-secrets",
|
||||
UPDATE_SECRET = "update-secret",
|
||||
UPDATE_SECRETS = "update-secrets",
|
||||
DELETE_SECRET = "delete-secret",
|
||||
DELETE_SECRETS = "delete-secrets",
|
||||
GET_WORKSPACE_KEY = "get-workspace-key",
|
||||
AUTHORIZE_INTEGRATION = "authorize-integration",
|
||||
UNAUTHORIZE_INTEGRATION = "unauthorize-integration",
|
||||
CREATE_INTEGRATION = "create-integration",
|
||||
DELETE_INTEGRATION = "delete-integration",
|
||||
ADD_TRUSTED_IP = "add-trusted-ip",
|
||||
UPDATE_TRUSTED_IP = "update-trusted-ip",
|
||||
DELETE_TRUSTED_IP = "delete-trusted-ip",
|
||||
CREATE_SERVICE_TOKEN = "create-service-token", // v2
|
||||
DELETE_SERVICE_TOKEN = "delete-service-token", // v2
|
||||
CREATE_IDENTITY = "create-identity",
|
||||
UPDATE_IDENTITY = "update-identity",
|
||||
DELETE_IDENTITY = "delete-identity",
|
||||
LOGIN_IDENTITY_UNIVERSAL_AUTH = "login-identity-universal-auth",
|
||||
ADD_IDENTITY_UNIVERSAL_AUTH = "add-identity-universal-auth",
|
||||
UPDATE_IDENTITY_UNIVERSAL_AUTH = "update-identity-universal-auth",
|
||||
GET_IDENTITY_UNIVERSAL_AUTH = "get-identity-universal-auth",
|
||||
CREATE_IDENTITY_UNIVERSAL_AUTH_CLIENT_SECRET = "create-identity-universal-auth-client-secret",
|
||||
REVOKE_IDENTITY_UNIVERSAL_AUTH_CLIENT_SECRET = "revoke-identity-universal-auth-client-secret",
|
||||
GET_IDENTITY_UNIVERSAL_AUTH_CLIENT_SECRETS = "get-identity-universal-auth-client-secret",
|
||||
CREATE_ENVIRONMENT = "create-environment",
|
||||
UPDATE_ENVIRONMENT = "update-environment",
|
||||
DELETE_ENVIRONMENT = "delete-environment",
|
||||
ADD_WORKSPACE_MEMBER = "add-workspace-member",
|
||||
ADD_BATCH_WORKSPACE_MEMBER = "add-workspace-members",
|
||||
REMOVE_WORKSPACE_MEMBER = "remove-workspace-member",
|
||||
CREATE_FOLDER = "create-folder",
|
||||
UPDATE_FOLDER = "update-folder",
|
||||
DELETE_FOLDER = "delete-folder",
|
||||
CREATE_WEBHOOK = "create-webhook",
|
||||
UPDATE_WEBHOOK_STATUS = "update-webhook-status",
|
||||
DELETE_WEBHOOK = "delete-webhook",
|
||||
GET_SECRET_IMPORTS = "get-secret-imports",
|
||||
CREATE_SECRET_IMPORT = "create-secret-import",
|
||||
UPDATE_SECRET_IMPORT = "update-secret-import",
|
||||
DELETE_SECRET_IMPORT = "delete-secret-import",
|
||||
UPDATE_USER_WORKSPACE_ROLE = "update-user-workspace-role",
|
||||
UPDATE_USER_WORKSPACE_DENIED_PERMISSIONS = "update-user-workspace-denied-permissions",
|
||||
SECRET_APPROVAL_MERGED = "secret-approval-merged",
|
||||
SECRET_APPROVAL_REQUEST = "secret-approval-request",
|
||||
SECRET_APPROVAL_CLOSED = "secret-approval-closed",
|
||||
SECRET_APPROVAL_REOPENED = "secret-approval-reopened"
|
||||
}
|
||||
3
pg-migrator/src/models/auditLog/index.ts
Normal file
3
pg-migrator/src/models/auditLog/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export * from "./auditLog";
|
||||
export * from "./enums";
|
||||
export * from "./types";
|
||||
585
pg-migrator/src/models/auditLog/types.ts
Normal file
585
pg-migrator/src/models/auditLog/types.ts
Normal file
@@ -0,0 +1,585 @@
|
||||
import { ActorType, EventType } from "./enums";
|
||||
import { IIdentityTrustedIp } from "../../../models";
|
||||
|
||||
interface UserActorMetadata {
|
||||
userId: string;
|
||||
email: string;
|
||||
}
|
||||
|
||||
interface ServiceActorMetadata {
|
||||
serviceId: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
interface IdentityActorMetadata {
|
||||
identityId: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface UserActor {
|
||||
type: ActorType.USER;
|
||||
metadata: UserActorMetadata;
|
||||
}
|
||||
|
||||
export interface ServiceActor {
|
||||
type: ActorType.SERVICE;
|
||||
metadata: ServiceActorMetadata;
|
||||
}
|
||||
|
||||
export interface IdentityActor {
|
||||
type: ActorType.IDENTITY;
|
||||
metadata: IdentityActorMetadata;
|
||||
}
|
||||
|
||||
export type Actor = UserActor | ServiceActor | IdentityActor;
|
||||
|
||||
interface GetSecretsEvent {
|
||||
type: EventType.GET_SECRETS;
|
||||
metadata: {
|
||||
environment: string;
|
||||
secretPath: string;
|
||||
numberOfSecrets: number;
|
||||
};
|
||||
}
|
||||
|
||||
interface GetSecretEvent {
|
||||
type: EventType.GET_SECRET;
|
||||
metadata: {
|
||||
environment: string;
|
||||
secretPath: string;
|
||||
secretId: string;
|
||||
secretKey: string;
|
||||
secretVersion: number;
|
||||
};
|
||||
}
|
||||
|
||||
interface CreateSecretEvent {
|
||||
type: EventType.CREATE_SECRET;
|
||||
metadata: {
|
||||
environment: string;
|
||||
secretPath: string;
|
||||
secretId: string;
|
||||
secretKey: string;
|
||||
secretVersion: number;
|
||||
};
|
||||
}
|
||||
|
||||
interface CreateSecretBatchEvent {
|
||||
type: EventType.CREATE_SECRETS;
|
||||
metadata: {
|
||||
environment: string;
|
||||
secretPath: string;
|
||||
secrets: Array<{ secretId: string; secretKey: string; secretVersion: number }>;
|
||||
};
|
||||
}
|
||||
|
||||
interface UpdateSecretEvent {
|
||||
type: EventType.UPDATE_SECRET;
|
||||
metadata: {
|
||||
environment: string;
|
||||
secretPath: string;
|
||||
secretId: string;
|
||||
secretKey: string;
|
||||
secretVersion: number;
|
||||
};
|
||||
}
|
||||
|
||||
interface UpdateSecretBatchEvent {
|
||||
type: EventType.UPDATE_SECRETS;
|
||||
metadata: {
|
||||
environment: string;
|
||||
secretPath: string;
|
||||
secrets: Array<{ secretId: string; secretKey: string; secretVersion: number }>;
|
||||
};
|
||||
}
|
||||
|
||||
interface DeleteSecretEvent {
|
||||
type: EventType.DELETE_SECRET;
|
||||
metadata: {
|
||||
environment: string;
|
||||
secretPath: string;
|
||||
secretId: string;
|
||||
secretKey: string;
|
||||
secretVersion: number;
|
||||
};
|
||||
}
|
||||
|
||||
interface DeleteSecretBatchEvent {
|
||||
type: EventType.DELETE_SECRETS;
|
||||
metadata: {
|
||||
environment: string;
|
||||
secretPath: string;
|
||||
secrets: Array<{ secretId: string; secretKey: string; secretVersion: number }>;
|
||||
};
|
||||
}
|
||||
|
||||
interface GetWorkspaceKeyEvent {
|
||||
type: EventType.GET_WORKSPACE_KEY;
|
||||
metadata: {
|
||||
keyId: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface AuthorizeIntegrationEvent {
|
||||
type: EventType.AUTHORIZE_INTEGRATION;
|
||||
metadata: {
|
||||
integration: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface UnauthorizeIntegrationEvent {
|
||||
type: EventType.UNAUTHORIZE_INTEGRATION;
|
||||
metadata: {
|
||||
integration: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface CreateIntegrationEvent {
|
||||
type: EventType.CREATE_INTEGRATION;
|
||||
metadata: {
|
||||
integrationId: string;
|
||||
integration: string; // TODO: fix type
|
||||
environment: string;
|
||||
secretPath: string;
|
||||
url?: string;
|
||||
app?: string;
|
||||
appId?: string;
|
||||
targetEnvironment?: string;
|
||||
targetEnvironmentId?: string;
|
||||
targetService?: string;
|
||||
targetServiceId?: string;
|
||||
path?: string;
|
||||
region?: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface DeleteIntegrationEvent {
|
||||
type: EventType.DELETE_INTEGRATION;
|
||||
metadata: {
|
||||
integrationId: string;
|
||||
integration: string; // TODO: fix type
|
||||
environment: string;
|
||||
secretPath: string;
|
||||
url?: string;
|
||||
app?: string;
|
||||
appId?: string;
|
||||
targetEnvironment?: string;
|
||||
targetEnvironmentId?: string;
|
||||
targetService?: string;
|
||||
targetServiceId?: string;
|
||||
path?: string;
|
||||
region?: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface AddTrustedIPEvent {
|
||||
type: EventType.ADD_TRUSTED_IP;
|
||||
metadata: {
|
||||
trustedIpId: string;
|
||||
ipAddress: string;
|
||||
prefix?: number;
|
||||
};
|
||||
}
|
||||
|
||||
interface UpdateTrustedIPEvent {
|
||||
type: EventType.UPDATE_TRUSTED_IP;
|
||||
metadata: {
|
||||
trustedIpId: string;
|
||||
ipAddress: string;
|
||||
prefix?: number;
|
||||
};
|
||||
}
|
||||
|
||||
interface DeleteTrustedIPEvent {
|
||||
type: EventType.DELETE_TRUSTED_IP;
|
||||
metadata: {
|
||||
trustedIpId: string;
|
||||
ipAddress: string;
|
||||
prefix?: number;
|
||||
};
|
||||
}
|
||||
|
||||
interface CreateServiceTokenEvent {
|
||||
type: EventType.CREATE_SERVICE_TOKEN;
|
||||
metadata: {
|
||||
name: string;
|
||||
scopes: Array<{
|
||||
environment: string;
|
||||
secretPath: string;
|
||||
}>;
|
||||
};
|
||||
}
|
||||
|
||||
interface DeleteServiceTokenEvent {
|
||||
type: EventType.DELETE_SERVICE_TOKEN;
|
||||
metadata: {
|
||||
name: string;
|
||||
scopes: Array<{
|
||||
environment: string;
|
||||
secretPath: string;
|
||||
}>;
|
||||
};
|
||||
}
|
||||
|
||||
interface CreateIdentityEvent { // note: currently not logging org-role
|
||||
type: EventType.CREATE_IDENTITY;
|
||||
metadata: {
|
||||
identityId: string;
|
||||
name: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface UpdateIdentityEvent {
|
||||
type: EventType.UPDATE_IDENTITY;
|
||||
metadata: {
|
||||
identityId: string;
|
||||
name?: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface DeleteIdentityEvent {
|
||||
type: EventType.DELETE_IDENTITY;
|
||||
metadata: {
|
||||
identityId: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface LoginIdentityUniversalAuthEvent {
|
||||
type: EventType.LOGIN_IDENTITY_UNIVERSAL_AUTH ;
|
||||
metadata: {
|
||||
identityId: string;
|
||||
identityUniversalAuthId: string;
|
||||
clientSecretId: string;
|
||||
identityAccessTokenId: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface AddIdentityUniversalAuthEvent {
|
||||
type: EventType.ADD_IDENTITY_UNIVERSAL_AUTH;
|
||||
metadata: {
|
||||
identityId: string;
|
||||
clientSecretTrustedIps: Array<IIdentityTrustedIp>;
|
||||
accessTokenTTL: number;
|
||||
accessTokenMaxTTL: number;
|
||||
accessTokenNumUsesLimit: number;
|
||||
accessTokenTrustedIps: Array<IIdentityTrustedIp>;
|
||||
};
|
||||
}
|
||||
|
||||
interface UpdateIdentityUniversalAuthEvent {
|
||||
type: EventType.UPDATE_IDENTITY_UNIVERSAL_AUTH;
|
||||
metadata: {
|
||||
identityId: string;
|
||||
clientSecretTrustedIps?: Array<IIdentityTrustedIp>;
|
||||
accessTokenTTL?: number;
|
||||
accessTokenMaxTTL?: number;
|
||||
accessTokenNumUsesLimit?: number;
|
||||
accessTokenTrustedIps?: Array<IIdentityTrustedIp>;
|
||||
};
|
||||
}
|
||||
|
||||
interface GetIdentityUniversalAuthEvent {
|
||||
type: EventType.GET_IDENTITY_UNIVERSAL_AUTH;
|
||||
metadata: {
|
||||
identityId: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface CreateIdentityUniversalAuthClientSecretEvent {
|
||||
type: EventType.CREATE_IDENTITY_UNIVERSAL_AUTH_CLIENT_SECRET ;
|
||||
metadata: {
|
||||
identityId: string;
|
||||
clientSecretId: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface GetIdentityUniversalAuthClientSecretsEvent {
|
||||
type: EventType.GET_IDENTITY_UNIVERSAL_AUTH_CLIENT_SECRETS;
|
||||
metadata: {
|
||||
identityId: string;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
interface RevokeIdentityUniversalAuthClientSecretEvent {
|
||||
type: EventType.REVOKE_IDENTITY_UNIVERSAL_AUTH_CLIENT_SECRET ;
|
||||
metadata: {
|
||||
identityId: string;
|
||||
clientSecretId: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface CreateEnvironmentEvent {
|
||||
type: EventType.CREATE_ENVIRONMENT;
|
||||
metadata: {
|
||||
name: string;
|
||||
slug: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface UpdateEnvironmentEvent {
|
||||
type: EventType.UPDATE_ENVIRONMENT;
|
||||
metadata: {
|
||||
oldName: string;
|
||||
newName: string;
|
||||
oldSlug: string;
|
||||
newSlug: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface DeleteEnvironmentEvent {
|
||||
type: EventType.DELETE_ENVIRONMENT;
|
||||
metadata: {
|
||||
name: string;
|
||||
slug: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface AddWorkspaceMemberEvent {
|
||||
type: EventType.ADD_WORKSPACE_MEMBER;
|
||||
metadata: {
|
||||
userId: string;
|
||||
email: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface AddBatchWorkspaceMemberEvent {
|
||||
type: EventType.ADD_BATCH_WORKSPACE_MEMBER;
|
||||
metadata: Array<{
|
||||
userId: string;
|
||||
email: string;
|
||||
}>;
|
||||
}
|
||||
|
||||
interface RemoveWorkspaceMemberEvent {
|
||||
type: EventType.REMOVE_WORKSPACE_MEMBER;
|
||||
metadata: {
|
||||
userId: string;
|
||||
email: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface CreateFolderEvent {
|
||||
type: EventType.CREATE_FOLDER;
|
||||
metadata: {
|
||||
environment: string;
|
||||
folderId: string;
|
||||
folderName: string;
|
||||
folderPath: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface UpdateFolderEvent {
|
||||
type: EventType.UPDATE_FOLDER;
|
||||
metadata: {
|
||||
environment: string;
|
||||
folderId: string;
|
||||
oldFolderName: string;
|
||||
newFolderName: string;
|
||||
folderPath: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface DeleteFolderEvent {
|
||||
type: EventType.DELETE_FOLDER;
|
||||
metadata: {
|
||||
environment: string;
|
||||
folderId: string;
|
||||
folderName: string;
|
||||
folderPath: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface CreateWebhookEvent {
|
||||
type: EventType.CREATE_WEBHOOK;
|
||||
metadata: {
|
||||
webhookId: string;
|
||||
environment: string;
|
||||
secretPath: string;
|
||||
webhookUrl: string;
|
||||
isDisabled: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
interface UpdateWebhookStatusEvent {
|
||||
type: EventType.UPDATE_WEBHOOK_STATUS;
|
||||
metadata: {
|
||||
webhookId: string;
|
||||
environment: string;
|
||||
secretPath: string;
|
||||
webhookUrl: string;
|
||||
isDisabled: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
interface DeleteWebhookEvent {
|
||||
type: EventType.DELETE_WEBHOOK;
|
||||
metadata: {
|
||||
webhookId: string;
|
||||
environment: string;
|
||||
secretPath: string;
|
||||
webhookUrl: string;
|
||||
isDisabled: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
interface GetSecretImportsEvent {
|
||||
type: EventType.GET_SECRET_IMPORTS;
|
||||
metadata: {
|
||||
environment: string;
|
||||
secretImportId: string;
|
||||
folderId: string;
|
||||
numberOfImports: number;
|
||||
};
|
||||
}
|
||||
|
||||
interface CreateSecretImportEvent {
|
||||
type: EventType.CREATE_SECRET_IMPORT;
|
||||
metadata: {
|
||||
secretImportId: string;
|
||||
folderId: string;
|
||||
importFromEnvironment: string;
|
||||
importFromSecretPath: string;
|
||||
importToEnvironment: string;
|
||||
importToSecretPath: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface UpdateSecretImportEvent {
|
||||
type: EventType.UPDATE_SECRET_IMPORT;
|
||||
metadata: {
|
||||
secretImportId: string;
|
||||
folderId: string;
|
||||
importToEnvironment: string;
|
||||
importToSecretPath: string;
|
||||
orderBefore: {
|
||||
environment: string;
|
||||
secretPath: string;
|
||||
}[];
|
||||
orderAfter: {
|
||||
environment: string;
|
||||
secretPath: string;
|
||||
}[];
|
||||
};
|
||||
}
|
||||
|
||||
interface DeleteSecretImportEvent {
|
||||
type: EventType.DELETE_SECRET_IMPORT;
|
||||
metadata: {
|
||||
secretImportId: string;
|
||||
folderId: string;
|
||||
importFromEnvironment: string;
|
||||
importFromSecretPath: string;
|
||||
importToEnvironment: string;
|
||||
importToSecretPath: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface UpdateUserRole {
|
||||
type: EventType.UPDATE_USER_WORKSPACE_ROLE;
|
||||
metadata: {
|
||||
userId: string;
|
||||
email: string;
|
||||
oldRole: string;
|
||||
newRole: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface UpdateUserDeniedPermissions {
|
||||
type: EventType.UPDATE_USER_WORKSPACE_DENIED_PERMISSIONS;
|
||||
metadata: {
|
||||
userId: string;
|
||||
email: string;
|
||||
deniedPermissions: {
|
||||
environmentSlug: string;
|
||||
ability: string;
|
||||
}[];
|
||||
};
|
||||
}
|
||||
interface SecretApprovalMerge {
|
||||
type: EventType.SECRET_APPROVAL_MERGED;
|
||||
metadata: {
|
||||
mergedBy: string;
|
||||
secretApprovalRequestSlug: string;
|
||||
secretApprovalRequestId: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface SecretApprovalClosed {
|
||||
type: EventType.SECRET_APPROVAL_CLOSED;
|
||||
metadata: {
|
||||
closedBy: string;
|
||||
secretApprovalRequestSlug: string;
|
||||
secretApprovalRequestId: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface SecretApprovalReopened {
|
||||
type: EventType.SECRET_APPROVAL_REOPENED;
|
||||
metadata: {
|
||||
reopenedBy: string;
|
||||
secretApprovalRequestSlug: string;
|
||||
secretApprovalRequestId: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface SecretApprovalRequest {
|
||||
type: EventType.SECRET_APPROVAL_REQUEST;
|
||||
metadata: {
|
||||
committedBy: string;
|
||||
secretApprovalRequestSlug: string;
|
||||
secretApprovalRequestId: string;
|
||||
};
|
||||
}
|
||||
|
||||
export type Event =
|
||||
| GetSecretsEvent
|
||||
| GetSecretEvent
|
||||
| CreateSecretEvent
|
||||
| CreateSecretBatchEvent
|
||||
| UpdateSecretEvent
|
||||
| UpdateSecretBatchEvent
|
||||
| DeleteSecretEvent
|
||||
| DeleteSecretBatchEvent
|
||||
| GetWorkspaceKeyEvent
|
||||
| AuthorizeIntegrationEvent
|
||||
| UnauthorizeIntegrationEvent
|
||||
| CreateIntegrationEvent
|
||||
| DeleteIntegrationEvent
|
||||
| AddTrustedIPEvent
|
||||
| UpdateTrustedIPEvent
|
||||
| DeleteTrustedIPEvent
|
||||
| CreateServiceTokenEvent
|
||||
| DeleteServiceTokenEvent
|
||||
| CreateIdentityEvent
|
||||
| UpdateIdentityEvent
|
||||
| DeleteIdentityEvent
|
||||
| LoginIdentityUniversalAuthEvent
|
||||
| AddIdentityUniversalAuthEvent
|
||||
| UpdateIdentityUniversalAuthEvent
|
||||
| GetIdentityUniversalAuthEvent
|
||||
| CreateIdentityUniversalAuthClientSecretEvent
|
||||
| GetIdentityUniversalAuthClientSecretsEvent
|
||||
| RevokeIdentityUniversalAuthClientSecretEvent
|
||||
| CreateEnvironmentEvent
|
||||
| UpdateEnvironmentEvent
|
||||
| DeleteEnvironmentEvent
|
||||
| AddWorkspaceMemberEvent
|
||||
| AddBatchWorkspaceMemberEvent
|
||||
| RemoveWorkspaceMemberEvent
|
||||
| CreateFolderEvent
|
||||
| UpdateFolderEvent
|
||||
| DeleteFolderEvent
|
||||
| CreateWebhookEvent
|
||||
| UpdateWebhookStatusEvent
|
||||
| DeleteWebhookEvent
|
||||
| GetSecretImportsEvent
|
||||
| CreateSecretImportEvent
|
||||
| UpdateSecretImportEvent
|
||||
| DeleteSecretImportEvent
|
||||
| UpdateUserRole
|
||||
| UpdateUserDeniedPermissions
|
||||
| SecretApprovalMerge
|
||||
| SecretApprovalClosed
|
||||
| SecretApprovalRequest
|
||||
| SecretApprovalReopened;
|
||||
74
pg-migrator/src/models/backupPrivateKey.ts
Normal file
74
pg-migrator/src/models/backupPrivateKey.ts
Normal file
@@ -0,0 +1,74 @@
|
||||
import { Schema, Types, model } from "mongoose";
|
||||
import {
|
||||
ALGORITHM_AES_256_GCM,
|
||||
ENCODING_SCHEME_BASE64,
|
||||
ENCODING_SCHEME_UTF8,
|
||||
} from "../variables";
|
||||
|
||||
export interface IBackupPrivateKey {
|
||||
_id: Types.ObjectId;
|
||||
user: Types.ObjectId;
|
||||
encryptedPrivateKey: string;
|
||||
iv: string;
|
||||
tag: string;
|
||||
salt: string;
|
||||
algorithm: string;
|
||||
keyEncoding: "base64" | "utf8";
|
||||
verifier: string;
|
||||
}
|
||||
|
||||
const backupPrivateKeySchema = new Schema<IBackupPrivateKey>(
|
||||
{
|
||||
user: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "User",
|
||||
required: true,
|
||||
},
|
||||
encryptedPrivateKey: {
|
||||
type: String,
|
||||
select: false,
|
||||
required: true,
|
||||
},
|
||||
iv: {
|
||||
type: String,
|
||||
select: false,
|
||||
required: true,
|
||||
},
|
||||
tag: {
|
||||
type: String,
|
||||
select: false,
|
||||
required: true,
|
||||
},
|
||||
algorithm: { // the encryption algorithm used
|
||||
type: String,
|
||||
enum: [ALGORITHM_AES_256_GCM],
|
||||
required: true,
|
||||
},
|
||||
keyEncoding: {
|
||||
type: String,
|
||||
enum: [
|
||||
ENCODING_SCHEME_UTF8,
|
||||
ENCODING_SCHEME_BASE64,
|
||||
],
|
||||
required: true,
|
||||
},
|
||||
salt: {
|
||||
type: String,
|
||||
select: false,
|
||||
required: true,
|
||||
},
|
||||
verifier: {
|
||||
type: String,
|
||||
select: false,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamps: true,
|
||||
}
|
||||
);
|
||||
|
||||
export const BackupPrivateKey = model<IBackupPrivateKey>(
|
||||
"BackupPrivateKey",
|
||||
backupPrivateKeySchema
|
||||
);
|
||||
77
pg-migrator/src/models/bot.ts
Normal file
77
pg-migrator/src/models/bot.ts
Normal file
@@ -0,0 +1,77 @@
|
||||
import { Schema, Types, model } from "mongoose";
|
||||
import {
|
||||
ALGORITHM_AES_256_GCM,
|
||||
ENCODING_SCHEME_BASE64,
|
||||
ENCODING_SCHEME_UTF8,
|
||||
} from "../variables";
|
||||
|
||||
export interface IBot {
|
||||
_id: Types.ObjectId;
|
||||
name: string;
|
||||
workspace: Types.ObjectId;
|
||||
isActive: boolean;
|
||||
publicKey: string;
|
||||
encryptedPrivateKey: string;
|
||||
iv: string;
|
||||
tag: string;
|
||||
algorithm: "aes-256-gcm";
|
||||
keyEncoding: "base64" | "utf8";
|
||||
}
|
||||
|
||||
const botSchema = new Schema<IBot>(
|
||||
{
|
||||
name: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
workspace: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Workspace",
|
||||
required: true,
|
||||
},
|
||||
isActive: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
default: false,
|
||||
},
|
||||
publicKey: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
encryptedPrivateKey: {
|
||||
type: String,
|
||||
required: true,
|
||||
select: false,
|
||||
},
|
||||
iv: {
|
||||
type: String,
|
||||
required: true,
|
||||
select: false,
|
||||
},
|
||||
tag: {
|
||||
type: String,
|
||||
required: true,
|
||||
select: false,
|
||||
},
|
||||
algorithm: { // the encryption algorithm used
|
||||
type: String,
|
||||
enum: [ALGORITHM_AES_256_GCM],
|
||||
required: true,
|
||||
select: false,
|
||||
},
|
||||
keyEncoding: {
|
||||
type: String,
|
||||
enum: [
|
||||
ENCODING_SCHEME_UTF8,
|
||||
ENCODING_SCHEME_BASE64,
|
||||
],
|
||||
required: true,
|
||||
select: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamps: true,
|
||||
}
|
||||
);
|
||||
|
||||
export const Bot = model<IBot>("Bot", botSchema);
|
||||
43
pg-migrator/src/models/botKey.ts
Normal file
43
pg-migrator/src/models/botKey.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import { Schema, Types, model } from "mongoose";
|
||||
|
||||
export interface IBotKey {
|
||||
_id: Types.ObjectId;
|
||||
encryptedKey: string;
|
||||
nonce: string;
|
||||
sender: Types.ObjectId;
|
||||
bot: Types.ObjectId;
|
||||
workspace: Types.ObjectId;
|
||||
}
|
||||
|
||||
const botKeySchema = new Schema<IBotKey>(
|
||||
{
|
||||
encryptedKey: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
nonce: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
sender: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "User",
|
||||
required: true,
|
||||
},
|
||||
bot: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Bot",
|
||||
required: true,
|
||||
},
|
||||
workspace: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Workspace",
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamps: true,
|
||||
}
|
||||
);
|
||||
|
||||
export const BotKey = model<IBotKey>("BotKey", botKeySchema);
|
||||
96
pg-migrator/src/models/botOrg.ts
Normal file
96
pg-migrator/src/models/botOrg.ts
Normal file
@@ -0,0 +1,96 @@
|
||||
import { Schema, Types, model } from "mongoose";
|
||||
import {
|
||||
ALGORITHM_AES_256_GCM,
|
||||
ENCODING_SCHEME_BASE64,
|
||||
ENCODING_SCHEME_UTF8,
|
||||
} from "../variables";
|
||||
|
||||
export interface IBotOrg {
|
||||
_id: Types.ObjectId;
|
||||
name: string;
|
||||
organization: Types.ObjectId;
|
||||
publicKey: string;
|
||||
encryptedSymmetricKey: string;
|
||||
symmetricKeyIV: string;
|
||||
symmetricKeyTag: string;
|
||||
symmetricKeyAlgorithm: "aes-256-gcm";
|
||||
symmetricKeyKeyEncoding: "base64" | "utf8";
|
||||
encryptedPrivateKey: string;
|
||||
privateKeyIV: string;
|
||||
privateKeyTag: string;
|
||||
privateKeyAlgorithm: "aes-256-gcm";
|
||||
privateKeyKeyEncoding: "base64" | "utf8";
|
||||
}
|
||||
|
||||
const botOrgSchema = new Schema<IBotOrg>(
|
||||
{
|
||||
name: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
organization: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Organization",
|
||||
required: true,
|
||||
},
|
||||
publicKey: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
encryptedSymmetricKey: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
symmetricKeyIV: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
symmetricKeyTag: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
symmetricKeyAlgorithm: {
|
||||
type: String,
|
||||
enum: [ALGORITHM_AES_256_GCM],
|
||||
required: true
|
||||
},
|
||||
symmetricKeyKeyEncoding: {
|
||||
type: String,
|
||||
enum: [
|
||||
ENCODING_SCHEME_UTF8,
|
||||
ENCODING_SCHEME_BASE64,
|
||||
],
|
||||
required: true
|
||||
},
|
||||
encryptedPrivateKey: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
privateKeyIV: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
privateKeyTag: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
privateKeyAlgorithm: {
|
||||
type: String,
|
||||
enum: [ALGORITHM_AES_256_GCM],
|
||||
required: true
|
||||
},
|
||||
privateKeyKeyEncoding: {
|
||||
type: String,
|
||||
enum: [
|
||||
ENCODING_SCHEME_UTF8,
|
||||
ENCODING_SCHEME_BASE64,
|
||||
],
|
||||
required: true
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamps: true,
|
||||
}
|
||||
);
|
||||
|
||||
export const BotOrg = model<IBotOrg>("BotOrg", botOrgSchema);
|
||||
54
pg-migrator/src/models/folder.ts
Normal file
54
pg-migrator/src/models/folder.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
import { Schema, Types, model } from "mongoose";
|
||||
|
||||
export type TFolderRootSchema = {
|
||||
_id: Types.ObjectId;
|
||||
workspace: Types.ObjectId;
|
||||
environment: string;
|
||||
nodes: TFolderSchema;
|
||||
};
|
||||
|
||||
export type TFolderSchema = {
|
||||
id: string;
|
||||
name: string;
|
||||
version: number;
|
||||
children: TFolderSchema[];
|
||||
};
|
||||
|
||||
const folderSchema = new Schema<TFolderSchema>({
|
||||
id: {
|
||||
required: true,
|
||||
type: String,
|
||||
},
|
||||
version: {
|
||||
required: true,
|
||||
type: Number,
|
||||
default: 1,
|
||||
},
|
||||
name: {
|
||||
required: true,
|
||||
type: String,
|
||||
default: "root",
|
||||
},
|
||||
});
|
||||
|
||||
folderSchema.add({ children: [folderSchema] });
|
||||
|
||||
const folderRootSchema = new Schema<TFolderRootSchema>(
|
||||
{
|
||||
workspace: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Workspace",
|
||||
required: true,
|
||||
},
|
||||
environment: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
nodes: folderSchema,
|
||||
},
|
||||
{
|
||||
timestamps: true,
|
||||
}
|
||||
);
|
||||
|
||||
export const Folder = model<TFolderRootSchema>("Folder", folderRootSchema);
|
||||
58
pg-migrator/src/models/folderVersion.ts
Normal file
58
pg-migrator/src/models/folderVersion.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import { Schema, Types, model } from "mongoose";
|
||||
|
||||
export type TFolderRootVersionSchema = {
|
||||
_id: Types.ObjectId;
|
||||
workspace: Types.ObjectId;
|
||||
environment: string;
|
||||
nodes: TFolderVersionSchema;
|
||||
};
|
||||
|
||||
export type TFolderVersionSchema = {
|
||||
id: string;
|
||||
name: string;
|
||||
version: number;
|
||||
children: TFolderVersionSchema[];
|
||||
};
|
||||
|
||||
const folderVersionSchema = new Schema<TFolderVersionSchema>({
|
||||
id: {
|
||||
required: true,
|
||||
type: String,
|
||||
default: "root",
|
||||
},
|
||||
name: {
|
||||
required: true,
|
||||
type: String,
|
||||
default: "root",
|
||||
},
|
||||
version: {
|
||||
required: true,
|
||||
type: Number,
|
||||
default: 1,
|
||||
},
|
||||
});
|
||||
|
||||
folderVersionSchema.add({ children: [folderVersionSchema] });
|
||||
|
||||
const folderRootVersionSchema = new Schema<TFolderRootVersionSchema>(
|
||||
{
|
||||
workspace: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Workspace",
|
||||
required: true,
|
||||
},
|
||||
environment: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
nodes: folderVersionSchema,
|
||||
},
|
||||
{
|
||||
timestamps: true,
|
||||
}
|
||||
);
|
||||
|
||||
export const FolderVersion = model<TFolderRootVersionSchema>(
|
||||
"FolderVersion",
|
||||
folderRootVersionSchema
|
||||
);
|
||||
32
pg-migrator/src/models/gitAppInstallationSession.ts
Normal file
32
pg-migrator/src/models/gitAppInstallationSession.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import { Schema, Types, model } from "mongoose";
|
||||
|
||||
type GitAppInstallationSession = {
|
||||
id: string;
|
||||
sessionId: string;
|
||||
organization: Types.ObjectId;
|
||||
user: Types.ObjectId;
|
||||
}
|
||||
|
||||
const gitAppInstallationSession = new Schema<GitAppInstallationSession>({
|
||||
id: {
|
||||
required: true,
|
||||
type: String,
|
||||
},
|
||||
sessionId: {
|
||||
type: String,
|
||||
required: true,
|
||||
unique: true
|
||||
},
|
||||
organization: {
|
||||
type: Schema.Types.ObjectId,
|
||||
required: true,
|
||||
unique: true
|
||||
},
|
||||
user: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "User"
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
export const GitAppInstallationSession = model<GitAppInstallationSession>("git_app_installation_session", gitAppInstallationSession);
|
||||
29
pg-migrator/src/models/gitAppOrganizationInstallation.ts
Normal file
29
pg-migrator/src/models/gitAppOrganizationInstallation.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { Schema, model } from "mongoose";
|
||||
|
||||
type Installation = {
|
||||
installationId: string
|
||||
organizationId: string
|
||||
user: Schema.Types.ObjectId
|
||||
};
|
||||
|
||||
|
||||
const gitAppOrganizationInstallation = new Schema<Installation>({
|
||||
installationId: {
|
||||
type: String,
|
||||
required: true,
|
||||
unique: true
|
||||
},
|
||||
organizationId: {
|
||||
type: String,
|
||||
required: true,
|
||||
unique: true
|
||||
},
|
||||
user: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "User",
|
||||
required: true,
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
export const GitAppOrganizationInstallation = model<Installation>("git_app_organization_installation", gitAppOrganizationInstallation);
|
||||
150
pg-migrator/src/models/gitRisks.ts
Normal file
150
pg-migrator/src/models/gitRisks.ts
Normal file
@@ -0,0 +1,150 @@
|
||||
import { Schema, model } from "mongoose";
|
||||
|
||||
export const STATUS_RESOLVED_FALSE_POSITIVE = "RESOLVED_FALSE_POSITIVE";
|
||||
export const STATUS_RESOLVED_REVOKED = "RESOLVED_REVOKED";
|
||||
export const STATUS_RESOLVED_NOT_REVOKED = "RESOLVED_NOT_REVOKED";
|
||||
export const STATUS_UNRESOLVED = "UNRESOLVED";
|
||||
|
||||
export type IGitRisks = {
|
||||
id: string;
|
||||
description: string;
|
||||
startLine: string;
|
||||
endLine: string;
|
||||
startColumn: string;
|
||||
endColumn: string;
|
||||
match: string;
|
||||
secret: string;
|
||||
file: string;
|
||||
symlinkFile: string;
|
||||
commit: string;
|
||||
entropy: string;
|
||||
author: string;
|
||||
email: string;
|
||||
date: string;
|
||||
message: string;
|
||||
tags: string[];
|
||||
ruleID: string;
|
||||
fingerprint: string;
|
||||
fingerPrintWithoutCommitId: string
|
||||
|
||||
isFalsePositive: boolean; // New field for marking risks as false positives
|
||||
isResolved: boolean; // New field for marking risks as resolved
|
||||
riskOwner: string | null; // New field for setting a risk owner (nullable string)
|
||||
installationId: string,
|
||||
repositoryId: string,
|
||||
repositoryLink: string
|
||||
repositoryFullName: string
|
||||
status: string
|
||||
pusher: {
|
||||
name: string,
|
||||
email: string
|
||||
},
|
||||
organization: Schema.Types.ObjectId,
|
||||
}
|
||||
|
||||
const gitRisks = new Schema<IGitRisks>({
|
||||
id: {
|
||||
type: String,
|
||||
},
|
||||
description: {
|
||||
type: String,
|
||||
},
|
||||
startLine: {
|
||||
type: String,
|
||||
},
|
||||
endLine: {
|
||||
type: String,
|
||||
},
|
||||
startColumn: {
|
||||
type: String,
|
||||
},
|
||||
endColumn: {
|
||||
type: String,
|
||||
},
|
||||
file: {
|
||||
type: String,
|
||||
},
|
||||
symlinkFile: {
|
||||
type: String,
|
||||
},
|
||||
commit: {
|
||||
type: String,
|
||||
},
|
||||
entropy: {
|
||||
type: String,
|
||||
},
|
||||
author: {
|
||||
type: String,
|
||||
},
|
||||
email: {
|
||||
type: String,
|
||||
},
|
||||
date: {
|
||||
type: String,
|
||||
},
|
||||
message: {
|
||||
type: String,
|
||||
},
|
||||
tags: {
|
||||
type: [String],
|
||||
},
|
||||
ruleID: {
|
||||
type: String,
|
||||
},
|
||||
fingerprint: {
|
||||
type: String,
|
||||
unique: true
|
||||
},
|
||||
fingerPrintWithoutCommitId: {
|
||||
type: String,
|
||||
},
|
||||
isFalsePositive: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
isResolved: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
riskOwner: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
installationId: {
|
||||
type: String,
|
||||
require: true
|
||||
},
|
||||
repositoryId: {
|
||||
type: String
|
||||
},
|
||||
repositoryLink: {
|
||||
type: String
|
||||
},
|
||||
repositoryFullName: {
|
||||
type: String
|
||||
},
|
||||
pusher: {
|
||||
name: {
|
||||
type: String
|
||||
},
|
||||
email: {
|
||||
type: String
|
||||
},
|
||||
},
|
||||
organization: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Organization",
|
||||
},
|
||||
status: {
|
||||
type: String,
|
||||
enum: [
|
||||
STATUS_RESOLVED_FALSE_POSITIVE,
|
||||
STATUS_RESOLVED_REVOKED,
|
||||
STATUS_RESOLVED_NOT_REVOKED,
|
||||
STATUS_UNRESOLVED
|
||||
],
|
||||
default: STATUS_UNRESOLVED
|
||||
}
|
||||
}, { timestamps: true });
|
||||
|
||||
export const GitRisks = model<IGitRisks>("GitRisks", gitRisks);
|
||||
38
pg-migrator/src/models/identity.ts
Normal file
38
pg-migrator/src/models/identity.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import { Document, Schema, Types, model } from "mongoose";
|
||||
import { IPType } from "../ee/models";
|
||||
|
||||
export interface IIdentityTrustedIp {
|
||||
ipAddress: string;
|
||||
type: IPType;
|
||||
prefix: number;
|
||||
}
|
||||
|
||||
export enum IdentityAuthMethod {
|
||||
UNIVERSAL_AUTH = "universal-auth"
|
||||
}
|
||||
|
||||
export interface IIdentity extends Document {
|
||||
_id: Types.ObjectId;
|
||||
name: string;
|
||||
authMethod?: IdentityAuthMethod;
|
||||
}
|
||||
|
||||
const identitySchema = new Schema(
|
||||
{
|
||||
name: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
authMethod: {
|
||||
type: String,
|
||||
enum: IdentityAuthMethod,
|
||||
required: false,
|
||||
},
|
||||
|
||||
},
|
||||
{
|
||||
timestamps: true
|
||||
}
|
||||
);
|
||||
|
||||
export const Identity = model<IIdentity>("Identity", identitySchema);
|
||||
104
pg-migrator/src/models/identityAccessToken.ts
Normal file
104
pg-migrator/src/models/identityAccessToken.ts
Normal file
@@ -0,0 +1,104 @@
|
||||
import { Document, Schema, Types, model } from "mongoose";
|
||||
import { IIdentityTrustedIp } from "./identity";
|
||||
import { IPType } from "../ee/models/trustedIp";
|
||||
|
||||
export interface IIdentityAccessToken extends Document {
|
||||
_id: Types.ObjectId;
|
||||
identity: Types.ObjectId;
|
||||
identityUniversalAuthClientSecret?: Types.ObjectId;
|
||||
accessTokenLastUsedAt?: Date;
|
||||
accessTokenLastRenewedAt?: Date;
|
||||
accessTokenNumUses: number;
|
||||
accessTokenNumUsesLimit: number;
|
||||
accessTokenTTL: number;
|
||||
accessTokenMaxTTL: number;
|
||||
accessTokenTrustedIps: Array<IIdentityTrustedIp>;
|
||||
isAccessTokenRevoked: boolean;
|
||||
updatedAt: Date;
|
||||
createdAt: Date;
|
||||
}
|
||||
|
||||
const identityAccessTokenSchema = new Schema(
|
||||
{
|
||||
identity: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Identity",
|
||||
required: false
|
||||
},
|
||||
identityUniversalAuthClientSecret: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "IdentityUniversalAuthClientSecret",
|
||||
required: false
|
||||
},
|
||||
accessTokenLastUsedAt: {
|
||||
type: Date,
|
||||
required: false
|
||||
},
|
||||
accessTokenLastRenewedAt: {
|
||||
type: Date,
|
||||
required: false
|
||||
},
|
||||
accessTokenNumUses: {
|
||||
// number of times access token has been used
|
||||
type: Number,
|
||||
default: 0,
|
||||
required: true
|
||||
},
|
||||
accessTokenNumUsesLimit: {
|
||||
// number of times access token can be used for
|
||||
type: Number,
|
||||
default: 0, // default: used as many times as needed
|
||||
required: true
|
||||
},
|
||||
accessTokenTTL: { // seconds
|
||||
// incremental lifetime
|
||||
type: Number,
|
||||
default: 2592000, // 30 days
|
||||
required: true
|
||||
},
|
||||
accessTokenMaxTTL: { // seconds
|
||||
// max lifetime
|
||||
type: Number,
|
||||
default: 2592000, // 30 days
|
||||
required: true
|
||||
},
|
||||
accessTokenTrustedIps: {
|
||||
type: [
|
||||
{
|
||||
ipAddress: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
enum: [
|
||||
IPType.IPV4,
|
||||
IPType.IPV6
|
||||
],
|
||||
required: true
|
||||
},
|
||||
prefix: {
|
||||
type: Number,
|
||||
required: false
|
||||
}
|
||||
}
|
||||
],
|
||||
default: [{
|
||||
ipAddress: "0.0.0.0",
|
||||
type: IPType.IPV4.toString(),
|
||||
prefix: 0
|
||||
}],
|
||||
required: true
|
||||
},
|
||||
isAccessTokenRevoked: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
required: true
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamps: true
|
||||
}
|
||||
);
|
||||
|
||||
export const IdentityAccessToken = model<IIdentityAccessToken>("IdentityAccessToken", identityAccessTokenSchema);
|
||||
39
pg-migrator/src/models/identityMembership.ts
Normal file
39
pg-migrator/src/models/identityMembership.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import { Schema, Types, model } from "mongoose";
|
||||
import { ADMIN, CUSTOM, MEMBER, NO_ACCESS, VIEWER } from "../variables";
|
||||
|
||||
export interface IIdentityMembership {
|
||||
_id: Types.ObjectId;
|
||||
identity: Types.ObjectId;
|
||||
workspace: Types.ObjectId;
|
||||
role: "admin" | "member" | "viewer" | "no-access" | "custom";
|
||||
customRole: Types.ObjectId;
|
||||
}
|
||||
|
||||
const identityMembershipSchema = new Schema<IIdentityMembership>(
|
||||
{
|
||||
identity: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Identity"
|
||||
},
|
||||
workspace: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Workspace",
|
||||
required: true,
|
||||
index: true,
|
||||
},
|
||||
role: {
|
||||
type: String,
|
||||
enum: [ADMIN, MEMBER, VIEWER, CUSTOM, NO_ACCESS],
|
||||
required: true
|
||||
},
|
||||
customRole: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Role"
|
||||
}
|
||||
},
|
||||
{
|
||||
timestamps: true
|
||||
}
|
||||
);
|
||||
|
||||
export const IdentityMembership = model<IIdentityMembership>("IdentityMembership", identityMembershipSchema);
|
||||
37
pg-migrator/src/models/identityMembershipOrg.ts
Normal file
37
pg-migrator/src/models/identityMembershipOrg.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import { Schema, Types, model } from "mongoose";
|
||||
import { ADMIN, CUSTOM, MEMBER, NO_ACCESS} from "../variables";
|
||||
|
||||
export interface IIdentityMembershipOrg {
|
||||
_id: Types.ObjectId;
|
||||
identity: Types.ObjectId;
|
||||
organization: Types.ObjectId;
|
||||
role: "admin" | "member" | "no-access" | "custom";
|
||||
customRole: Types.ObjectId;
|
||||
}
|
||||
|
||||
const identityMembershipOrgSchema = new Schema<IIdentityMembershipOrg>(
|
||||
{
|
||||
identity: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Identity"
|
||||
},
|
||||
organization: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Organization"
|
||||
},
|
||||
role: {
|
||||
type: String,
|
||||
enum: [ADMIN, MEMBER, NO_ACCESS, CUSTOM],
|
||||
required: true
|
||||
},
|
||||
customRole: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Role"
|
||||
}
|
||||
},
|
||||
{
|
||||
timestamps: true
|
||||
}
|
||||
);
|
||||
|
||||
export const IdentityMembershipOrg = model<IIdentityMembershipOrg>("IdentityMembershipOrg", identityMembershipOrgSchema);
|
||||
107
pg-migrator/src/models/identityUniversalAuth.ts
Normal file
107
pg-migrator/src/models/identityUniversalAuth.ts
Normal file
@@ -0,0 +1,107 @@
|
||||
import { Document, Schema, Types, model } from "mongoose";
|
||||
import { IPType } from "../ee/models";
|
||||
import { IIdentityTrustedIp } from "./identity";
|
||||
|
||||
export interface IIdentityUniversalAuth extends Document {
|
||||
_id: Types.ObjectId;
|
||||
identity: Types.ObjectId;
|
||||
clientId: string;
|
||||
clientSecretTrustedIps: Array<IIdentityTrustedIp>;
|
||||
accessTokenTTL: number;
|
||||
accessTokenMaxTTL: number;
|
||||
accessTokenNumUsesLimit: number;
|
||||
accessTokenTrustedIps: Array<IIdentityTrustedIp>;
|
||||
}
|
||||
|
||||
const identityUniversalAuthSchema = new Schema(
|
||||
{
|
||||
identity: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Identity",
|
||||
required: true
|
||||
},
|
||||
clientId: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
clientSecretTrustedIps: {
|
||||
type: [
|
||||
{
|
||||
ipAddress: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
enum: [
|
||||
IPType.IPV4,
|
||||
IPType.IPV6
|
||||
],
|
||||
required: true
|
||||
},
|
||||
prefix: {
|
||||
type: Number,
|
||||
required: false
|
||||
}
|
||||
}
|
||||
],
|
||||
default: [{
|
||||
ipAddress: "0.0.0.0",
|
||||
type: IPType.IPV4.toString(),
|
||||
prefix: 0
|
||||
}],
|
||||
required: true
|
||||
},
|
||||
accessTokenTTL: { // seconds
|
||||
// incremental lifetime
|
||||
type: Number,
|
||||
default: 7200,
|
||||
required: true
|
||||
},
|
||||
accessTokenMaxTTL: { // seconds
|
||||
// max lifetime
|
||||
type: Number,
|
||||
default: 7200,
|
||||
required: true
|
||||
},
|
||||
accessTokenNumUsesLimit: {
|
||||
// number of times access token can be used for
|
||||
type: Number,
|
||||
default: 0, // default: used as many times as needed
|
||||
required: true
|
||||
},
|
||||
accessTokenTrustedIps: {
|
||||
type: [
|
||||
{
|
||||
ipAddress: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
enum: [
|
||||
IPType.IPV4,
|
||||
IPType.IPV6
|
||||
],
|
||||
required: true
|
||||
},
|
||||
prefix: {
|
||||
type: Number,
|
||||
required: false
|
||||
}
|
||||
}
|
||||
],
|
||||
default: [{
|
||||
ipAddress: "0.0.0.0",
|
||||
type: IPType.IPV4.toString(),
|
||||
prefix: 0
|
||||
}],
|
||||
required: true
|
||||
}
|
||||
},
|
||||
{
|
||||
timestamps: true
|
||||
}
|
||||
);
|
||||
|
||||
export const IdentityUniversalAuth = model<IIdentityUniversalAuth>("IdentityUniversalAuth", identityUniversalAuthSchema);
|
||||
81
pg-migrator/src/models/identityUniversalAuthClientSecret.ts
Normal file
81
pg-migrator/src/models/identityUniversalAuthClientSecret.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
import { Document, Schema, Types, model } from "mongoose";
|
||||
|
||||
export interface IIdentityUniversalAuthClientSecret extends Document {
|
||||
_id: Types.ObjectId;
|
||||
identity: Types.ObjectId;
|
||||
identityUniversalAuth : Types.ObjectId;
|
||||
description: string;
|
||||
clientSecretPrefix: string;
|
||||
clientSecretHash: string;
|
||||
clientSecretLastUsedAt?: Date;
|
||||
clientSecretNumUses: number;
|
||||
clientSecretNumUsesLimit: number;
|
||||
clientSecretTTL: number;
|
||||
updatedAt: Date;
|
||||
createdAt: Date;
|
||||
isClientSecretRevoked: boolean;
|
||||
}
|
||||
|
||||
const identityUniversalAuthClientSecretSchema = new Schema(
|
||||
{
|
||||
identity: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Identity",
|
||||
required: true
|
||||
},
|
||||
identityUniversalAuth: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "IdentityUniversalAuth",
|
||||
required: true
|
||||
},
|
||||
description: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
clientSecretPrefix: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
clientSecretHash: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
clientSecretLastUsedAt: {
|
||||
type: Date,
|
||||
required: false
|
||||
},
|
||||
clientSecretNumUses: {
|
||||
// number of times client secret has been used
|
||||
// in login operation
|
||||
type: Number,
|
||||
default: 0,
|
||||
required: true
|
||||
},
|
||||
clientSecretNumUsesLimit: {
|
||||
// number of times client secret can be used for
|
||||
// a login operation
|
||||
type: Number,
|
||||
default: 0, // default: used as many times as needed
|
||||
required: true
|
||||
},
|
||||
clientSecretTTL: {
|
||||
type: Number,
|
||||
default: 0, // default: does not expire
|
||||
required: true
|
||||
},
|
||||
isClientSecretRevoked: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
{
|
||||
timestamps: true
|
||||
}
|
||||
);
|
||||
|
||||
identityUniversalAuthClientSecretSchema.index(
|
||||
{ identityUniversalAuth: 1, isClientSecretRevoked: 1 }
|
||||
);
|
||||
|
||||
export const IdentityUniversalAuthClientSecret = model<IIdentityUniversalAuthClientSecret>("IdentityUniversalAuthClientSecret", identityUniversalAuthClientSecretSchema);
|
||||
29
pg-migrator/src/models/incidentContactOrg.ts
Normal file
29
pg-migrator/src/models/incidentContactOrg.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { Schema, Types, model } from "mongoose";
|
||||
|
||||
export interface IIncidentContactOrg {
|
||||
_id: Types.ObjectId;
|
||||
email: string;
|
||||
organization: Types.ObjectId;
|
||||
}
|
||||
|
||||
const incidentContactOrgSchema = new Schema<IIncidentContactOrg>(
|
||||
{
|
||||
email: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
organization: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Organization",
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamps: true,
|
||||
}
|
||||
);
|
||||
|
||||
export const IncidentContactOrg = model<IIncidentContactOrg>(
|
||||
"IncidentContactOrg",
|
||||
incidentContactOrgSchema
|
||||
);
|
||||
49
pg-migrator/src/models/index.ts
Normal file
49
pg-migrator/src/models/index.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
export * from "./backupPrivateKey";
|
||||
export * from "./bot";
|
||||
export * from "./botOrg";
|
||||
export * from "./botKey";
|
||||
export * from "./incidentContactOrg";
|
||||
export * from "./integration/integration";
|
||||
export * from "./integrationAuth";
|
||||
export * from "./key";
|
||||
export * from "./membership";
|
||||
export * from "./membershipOrg";
|
||||
export * from "./organization";
|
||||
export * from "./secret";
|
||||
export * from "./tag";
|
||||
export * from "./folder";
|
||||
export * from "./secretImports";
|
||||
export * from "./secretBlindIndexData";
|
||||
export * from "./serviceToken"; // TODO: deprecate
|
||||
export * from "./tokenData";
|
||||
export * from "./user";
|
||||
export * from "./userAction";
|
||||
export * from "./workspace";
|
||||
export * from "./serviceTokenData"; // TODO: deprecate
|
||||
|
||||
// new
|
||||
export * from "./identity";
|
||||
export * from "./identityMembership";
|
||||
export * from "./identityMembershipOrg";
|
||||
export * from "./identityUniversalAuth";
|
||||
export * from "./identityUniversalAuthClientSecret";
|
||||
export * from "./identityAccessToken";
|
||||
|
||||
export * from "./apiKeyData"; // TODO: deprecate
|
||||
export * from "./apiKeyDataV2";
|
||||
export * from "./loginSRPDetail";
|
||||
export * from "./tokenVersion";
|
||||
export * from "./webhooks";
|
||||
|
||||
export * from "./secretSnapshot";
|
||||
export * from "./secretVersion";
|
||||
export * from "./folderVersion";
|
||||
export * from "./role";
|
||||
export * from "./ssoConfig";
|
||||
export * from "./trustedIp";
|
||||
export * from "./auditLog";
|
||||
export * from "./gitRisks";
|
||||
export * from "./gitAppOrganizationInstallation";
|
||||
export * from "./gitAppInstallationSession";
|
||||
export * from "./secretApprovalPolicy";
|
||||
export * from "./secretApprovalRequest";
|
||||
1
pg-migrator/src/models/integration/index.ts
Normal file
1
pg-migrator/src/models/integration/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from "./integration";
|
||||
216
pg-migrator/src/models/integration/integration.ts
Normal file
216
pg-migrator/src/models/integration/integration.ts
Normal file
@@ -0,0 +1,216 @@
|
||||
import {
|
||||
INTEGRATION_AWS_PARAMETER_STORE,
|
||||
INTEGRATION_AWS_SECRET_MANAGER,
|
||||
INTEGRATION_AZURE_KEY_VAULT,
|
||||
INTEGRATION_BITBUCKET,
|
||||
INTEGRATION_CHECKLY,
|
||||
INTEGRATION_CIRCLECI,
|
||||
INTEGRATION_CLOUDFLARE_PAGES,
|
||||
INTEGRATION_CLOUDFLARE_WORKERS,
|
||||
INTEGRATION_CLOUD_66,
|
||||
INTEGRATION_CODEFRESH,
|
||||
INTEGRATION_DIGITAL_OCEAN_APP_PLATFORM,
|
||||
INTEGRATION_FLYIO,
|
||||
INTEGRATION_GCP_SECRET_MANAGER,
|
||||
INTEGRATION_GITHUB,
|
||||
INTEGRATION_GITLAB,
|
||||
INTEGRATION_HASHICORP_VAULT,
|
||||
INTEGRATION_HASURA_CLOUD,
|
||||
INTEGRATION_HEROKU,
|
||||
INTEGRATION_LARAVELFORGE,
|
||||
INTEGRATION_NETLIFY,
|
||||
INTEGRATION_NORTHFLANK,
|
||||
INTEGRATION_QOVERY,
|
||||
INTEGRATION_RAILWAY,
|
||||
INTEGRATION_RENDER,
|
||||
INTEGRATION_SUPABASE,
|
||||
INTEGRATION_TEAMCITY,
|
||||
INTEGRATION_TERRAFORM_CLOUD,
|
||||
INTEGRATION_TRAVISCI,
|
||||
INTEGRATION_VERCEL,
|
||||
INTEGRATION_WINDMILL
|
||||
} from "../../variables";
|
||||
import { Schema, Types, model } from "mongoose";
|
||||
import { Metadata } from "./types";
|
||||
|
||||
export interface IIntegration {
|
||||
_id: Types.ObjectId;
|
||||
workspace: Types.ObjectId;
|
||||
environment: string;
|
||||
isActive: boolean;
|
||||
url: string;
|
||||
app: string;
|
||||
appId: string;
|
||||
owner: string;
|
||||
targetEnvironment: string;
|
||||
targetEnvironmentId: string;
|
||||
targetService: string;
|
||||
targetServiceId: string;
|
||||
path: string;
|
||||
region: string;
|
||||
scope: string;
|
||||
secretPath: string;
|
||||
integration:
|
||||
| "azure-key-vault"
|
||||
| "aws-parameter-store"
|
||||
| "aws-secret-manager"
|
||||
| "heroku"
|
||||
| "vercel"
|
||||
| "netlify"
|
||||
| "github"
|
||||
| "gitlab"
|
||||
| "render"
|
||||
| "railway"
|
||||
| "flyio"
|
||||
| "circleci"
|
||||
| "laravel-forge"
|
||||
| "travisci"
|
||||
| "supabase"
|
||||
| "checkly"
|
||||
| "qovery"
|
||||
| "terraform-cloud"
|
||||
| "teamcity"
|
||||
| "hashicorp-vault"
|
||||
| "cloudflare-pages"
|
||||
| "cloudflare-workers"
|
||||
| "bitbucket"
|
||||
| "codefresh"
|
||||
| "digital-ocean-app-platform"
|
||||
| "cloud-66"
|
||||
| "northflank"
|
||||
| "windmill"
|
||||
| "gcp-secret-manager"
|
||||
| "hasura-cloud";
|
||||
integrationAuth: Types.ObjectId;
|
||||
metadata: Metadata;
|
||||
}
|
||||
|
||||
const integrationSchema = new Schema<IIntegration>(
|
||||
{
|
||||
workspace: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Workspace",
|
||||
required: true
|
||||
},
|
||||
environment: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
isActive: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
},
|
||||
url: {
|
||||
// for custom self-hosted integrations (e.g. self-hosted GitHub enterprise)
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
app: {
|
||||
// name of app in provider
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
appId: {
|
||||
// id of app in provider
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
targetEnvironment: {
|
||||
// target environment
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
targetEnvironmentId: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
targetService: {
|
||||
// railway-specific service
|
||||
// qovery-specific project
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
targetServiceId: {
|
||||
// railway-specific service
|
||||
// qovery specific project
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
owner: {
|
||||
// github-specific repo owner-login
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
path: {
|
||||
// aws-parameter-store-specific path
|
||||
// (also) vercel preview-branch
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
region: {
|
||||
// aws-parameter-store-specific path
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
scope: {
|
||||
// qovery-specific scope
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
integration: {
|
||||
type: String,
|
||||
enum: [
|
||||
INTEGRATION_AZURE_KEY_VAULT,
|
||||
INTEGRATION_AWS_PARAMETER_STORE,
|
||||
INTEGRATION_AWS_SECRET_MANAGER,
|
||||
INTEGRATION_HEROKU,
|
||||
INTEGRATION_VERCEL,
|
||||
INTEGRATION_NETLIFY,
|
||||
INTEGRATION_GITHUB,
|
||||
INTEGRATION_GITLAB,
|
||||
INTEGRATION_RENDER,
|
||||
INTEGRATION_RAILWAY,
|
||||
INTEGRATION_FLYIO,
|
||||
INTEGRATION_CIRCLECI,
|
||||
INTEGRATION_LARAVELFORGE,
|
||||
INTEGRATION_TRAVISCI,
|
||||
INTEGRATION_SUPABASE,
|
||||
INTEGRATION_CHECKLY,
|
||||
INTEGRATION_QOVERY,
|
||||
INTEGRATION_TERRAFORM_CLOUD,
|
||||
INTEGRATION_TEAMCITY,
|
||||
INTEGRATION_HASHICORP_VAULT,
|
||||
INTEGRATION_CLOUDFLARE_PAGES,
|
||||
INTEGRATION_CLOUDFLARE_WORKERS,
|
||||
INTEGRATION_CODEFRESH,
|
||||
INTEGRATION_WINDMILL,
|
||||
INTEGRATION_BITBUCKET,
|
||||
INTEGRATION_DIGITAL_OCEAN_APP_PLATFORM,
|
||||
INTEGRATION_CLOUD_66,
|
||||
INTEGRATION_NORTHFLANK,
|
||||
INTEGRATION_GCP_SECRET_MANAGER,
|
||||
INTEGRATION_HASURA_CLOUD
|
||||
],
|
||||
required: true
|
||||
},
|
||||
integrationAuth: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "IntegrationAuth",
|
||||
required: true
|
||||
},
|
||||
secretPath: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: "/"
|
||||
},
|
||||
metadata: {
|
||||
type: Schema.Types.Mixed,
|
||||
default: {}
|
||||
}
|
||||
},
|
||||
{
|
||||
timestamps: true
|
||||
}
|
||||
);
|
||||
|
||||
export const Integration = model<IIntegration>("Integration", integrationSchema);
|
||||
8
pg-migrator/src/models/integration/types.ts
Normal file
8
pg-migrator/src/models/integration/types.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
export type Metadata = {
|
||||
secretPrefix?: string;
|
||||
secretSuffix?: string;
|
||||
secretGCPLabel?: {
|
||||
labelName: string;
|
||||
labelValue: string;
|
||||
}
|
||||
}
|
||||
1
pg-migrator/src/models/integrationAuth/index.ts
Normal file
1
pg-migrator/src/models/integrationAuth/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from "./integrationAuth";
|
||||
206
pg-migrator/src/models/integrationAuth/integrationAuth.ts
Normal file
206
pg-migrator/src/models/integrationAuth/integrationAuth.ts
Normal file
@@ -0,0 +1,206 @@
|
||||
import {
|
||||
ALGORITHM_AES_256_GCM,
|
||||
ENCODING_SCHEME_BASE64,
|
||||
ENCODING_SCHEME_UTF8,
|
||||
INTEGRATION_AWS_PARAMETER_STORE,
|
||||
INTEGRATION_AWS_SECRET_MANAGER,
|
||||
INTEGRATION_AZURE_KEY_VAULT,
|
||||
INTEGRATION_BITBUCKET,
|
||||
INTEGRATION_CIRCLECI,
|
||||
INTEGRATION_CLOUDFLARE_PAGES,
|
||||
INTEGRATION_CLOUDFLARE_WORKERS,
|
||||
INTEGRATION_CLOUD_66,
|
||||
INTEGRATION_CODEFRESH,
|
||||
INTEGRATION_DIGITAL_OCEAN_APP_PLATFORM,
|
||||
INTEGRATION_FLYIO,
|
||||
INTEGRATION_GCP_SECRET_MANAGER,
|
||||
INTEGRATION_GITHUB,
|
||||
INTEGRATION_GITLAB,
|
||||
INTEGRATION_HASHICORP_VAULT,
|
||||
INTEGRATION_HASURA_CLOUD,
|
||||
INTEGRATION_HEROKU,
|
||||
INTEGRATION_LARAVELFORGE,
|
||||
INTEGRATION_NETLIFY,
|
||||
INTEGRATION_NORTHFLANK,
|
||||
INTEGRATION_RAILWAY,
|
||||
INTEGRATION_RENDER,
|
||||
INTEGRATION_SUPABASE,
|
||||
INTEGRATION_TEAMCITY,
|
||||
INTEGRATION_TERRAFORM_CLOUD,
|
||||
INTEGRATION_TRAVISCI,
|
||||
INTEGRATION_VERCEL,
|
||||
INTEGRATION_WINDMILL
|
||||
} from "../../variables";
|
||||
import { Document, Schema, Types, model } from "mongoose";
|
||||
import { IntegrationAuthMetadata } from "./types";
|
||||
|
||||
export interface IIntegrationAuth extends Document {
|
||||
_id: Types.ObjectId;
|
||||
workspace: Types.ObjectId;
|
||||
integration:
|
||||
| "heroku"
|
||||
| "vercel"
|
||||
| "netlify"
|
||||
| "github"
|
||||
| "gitlab"
|
||||
| "render"
|
||||
| "railway"
|
||||
| "flyio"
|
||||
| "azure-key-vault"
|
||||
| "laravel-forge"
|
||||
| "circleci"
|
||||
| "travisci"
|
||||
| "supabase"
|
||||
| "aws-parameter-store"
|
||||
| "aws-secret-manager"
|
||||
| "checkly"
|
||||
| "qovery"
|
||||
| "cloudflare-pages"
|
||||
| "cloudflare-workers"
|
||||
| "codefresh"
|
||||
| "digital-ocean-app-platform"
|
||||
| "bitbucket"
|
||||
| "cloud-66"
|
||||
| "terraform-cloud"
|
||||
| "teamcity"
|
||||
| "northflank"
|
||||
| "windmill"
|
||||
| "gcp-secret-manager"
|
||||
| "hasura-cloud";
|
||||
teamId: string;
|
||||
accountId: string;
|
||||
url: string;
|
||||
namespace: string;
|
||||
refreshCiphertext?: string;
|
||||
refreshIV?: string;
|
||||
refreshTag?: string;
|
||||
accessIdCiphertext?: string;
|
||||
accessIdIV?: string;
|
||||
accessIdTag?: string;
|
||||
accessCiphertext?: string;
|
||||
accessIV?: string;
|
||||
accessTag?: string;
|
||||
algorithm?: "aes-256-gcm";
|
||||
keyEncoding?: "utf8" | "base64";
|
||||
accessExpiresAt?: Date;
|
||||
metadata?: IntegrationAuthMetadata;
|
||||
}
|
||||
|
||||
const integrationAuthSchema = new Schema<IIntegrationAuth>(
|
||||
{
|
||||
workspace: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Workspace",
|
||||
required: true
|
||||
},
|
||||
integration: {
|
||||
type: String,
|
||||
enum: [
|
||||
INTEGRATION_AZURE_KEY_VAULT,
|
||||
INTEGRATION_AWS_PARAMETER_STORE,
|
||||
INTEGRATION_AWS_SECRET_MANAGER,
|
||||
INTEGRATION_HEROKU,
|
||||
INTEGRATION_VERCEL,
|
||||
INTEGRATION_NETLIFY,
|
||||
INTEGRATION_GITHUB,
|
||||
INTEGRATION_GITLAB,
|
||||
INTEGRATION_RENDER,
|
||||
INTEGRATION_RAILWAY,
|
||||
INTEGRATION_FLYIO,
|
||||
INTEGRATION_CIRCLECI,
|
||||
INTEGRATION_LARAVELFORGE,
|
||||
INTEGRATION_TRAVISCI,
|
||||
INTEGRATION_TEAMCITY,
|
||||
INTEGRATION_SUPABASE,
|
||||
INTEGRATION_TERRAFORM_CLOUD,
|
||||
INTEGRATION_HASHICORP_VAULT,
|
||||
INTEGRATION_CLOUDFLARE_PAGES,
|
||||
INTEGRATION_CLOUDFLARE_WORKERS,
|
||||
INTEGRATION_CODEFRESH,
|
||||
INTEGRATION_WINDMILL,
|
||||
INTEGRATION_BITBUCKET,
|
||||
INTEGRATION_DIGITAL_OCEAN_APP_PLATFORM,
|
||||
INTEGRATION_CLOUD_66,
|
||||
INTEGRATION_NORTHFLANK,
|
||||
INTEGRATION_GCP_SECRET_MANAGER,
|
||||
INTEGRATION_HASURA_CLOUD
|
||||
],
|
||||
required: true
|
||||
},
|
||||
teamId: {
|
||||
// vercel-specific integration param
|
||||
type: String
|
||||
},
|
||||
url: {
|
||||
// for any self-hosted integrations (e.g. self-hosted hashicorp-vault)
|
||||
type: String
|
||||
},
|
||||
namespace: {
|
||||
// hashicorp-vault-specific integration param
|
||||
type: String
|
||||
},
|
||||
accountId: {
|
||||
// netlify-specific integration param
|
||||
type: String
|
||||
},
|
||||
refreshCiphertext: {
|
||||
type: String,
|
||||
select: false
|
||||
},
|
||||
refreshIV: {
|
||||
type: String,
|
||||
select: false
|
||||
},
|
||||
refreshTag: {
|
||||
type: String,
|
||||
select: false
|
||||
},
|
||||
accessIdCiphertext: {
|
||||
type: String,
|
||||
select: false
|
||||
},
|
||||
accessIdIV: {
|
||||
type: String,
|
||||
select: false
|
||||
},
|
||||
accessIdTag: {
|
||||
type: String,
|
||||
select: false
|
||||
},
|
||||
accessCiphertext: {
|
||||
type: String,
|
||||
select: false
|
||||
},
|
||||
accessIV: {
|
||||
type: String,
|
||||
select: false
|
||||
},
|
||||
accessTag: {
|
||||
type: String,
|
||||
select: false
|
||||
},
|
||||
accessExpiresAt: {
|
||||
type: Date,
|
||||
select: false
|
||||
},
|
||||
algorithm: {
|
||||
// the encryption algorithm used
|
||||
type: String,
|
||||
enum: [ALGORITHM_AES_256_GCM],
|
||||
required: true
|
||||
},
|
||||
keyEncoding: {
|
||||
type: String,
|
||||
enum: [ENCODING_SCHEME_UTF8, ENCODING_SCHEME_BASE64],
|
||||
required: true
|
||||
},
|
||||
metadata: {
|
||||
type: Schema.Types.Mixed
|
||||
}
|
||||
},
|
||||
{
|
||||
timestamps: true
|
||||
}
|
||||
);
|
||||
|
||||
export const IntegrationAuth = model<IIntegrationAuth>("IntegrationAuth", integrationAuthSchema);
|
||||
5
pg-migrator/src/models/integrationAuth/types.ts
Normal file
5
pg-migrator/src/models/integrationAuth/types.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
interface GCPIntegrationAuthMetadata {
|
||||
authMethod: "oauth2" | "serviceAccount"
|
||||
}
|
||||
|
||||
export type IntegrationAuthMetadata = GCPIntegrationAuthMetadata;
|
||||
43
pg-migrator/src/models/key.ts
Normal file
43
pg-migrator/src/models/key.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import { Schema, Types, model } from "mongoose";
|
||||
|
||||
export interface IKey {
|
||||
_id: Types.ObjectId;
|
||||
encryptedKey: string;
|
||||
nonce: string;
|
||||
sender: Types.ObjectId;
|
||||
receiver: Types.ObjectId;
|
||||
workspace: Types.ObjectId;
|
||||
}
|
||||
|
||||
const keySchema = new Schema<IKey>(
|
||||
{
|
||||
encryptedKey: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
nonce: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
sender: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "User",
|
||||
required: true,
|
||||
},
|
||||
receiver: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "User",
|
||||
required: true,
|
||||
},
|
||||
workspace: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Workspace",
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamps: true,
|
||||
},
|
||||
);
|
||||
|
||||
export const Key = model<IKey>("Key", keySchema);
|
||||
27
pg-migrator/src/models/loginSRPDetail.ts
Normal file
27
pg-migrator/src/models/loginSRPDetail.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import mongoose, { Schema, Types, model } from "mongoose";
|
||||
|
||||
export interface ILoginSRPDetail {
|
||||
_id: Types.ObjectId;
|
||||
clientPublicKey: string;
|
||||
email: string;
|
||||
serverBInt: mongoose.Schema.Types.Buffer;
|
||||
userId: string;
|
||||
expireAt: Date;
|
||||
}
|
||||
|
||||
const loginSRPDetailSchema = new Schema<ILoginSRPDetail>(
|
||||
{
|
||||
clientPublicKey: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
email: {
|
||||
type: String,
|
||||
unique: true,
|
||||
},
|
||||
serverBInt: { type: mongoose.Schema.Types.Buffer },
|
||||
expireAt: { type: Date },
|
||||
}
|
||||
);
|
||||
|
||||
export const LoginSRPDetail = model("LoginSRPDetail", loginSRPDetailSchema);
|
||||
60
pg-migrator/src/models/membership.ts
Normal file
60
pg-migrator/src/models/membership.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import { Schema, Types, model } from "mongoose";
|
||||
import { ADMIN, CUSTOM, MEMBER, NO_ACCESS, VIEWER } from "../variables";
|
||||
|
||||
export interface IMembershipPermission {
|
||||
environmentSlug: string;
|
||||
ability: string;
|
||||
}
|
||||
|
||||
export interface IMembership {
|
||||
_id: Types.ObjectId;
|
||||
user: Types.ObjectId;
|
||||
inviteEmail?: string;
|
||||
workspace: Types.ObjectId;
|
||||
role: "admin" | "member" | "viewer" | "no-access" | "custom";
|
||||
customRole: Types.ObjectId;
|
||||
deniedPermissions: IMembershipPermission[];
|
||||
}
|
||||
|
||||
const membershipSchema = new Schema<IMembership>(
|
||||
{
|
||||
user: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "User"
|
||||
},
|
||||
inviteEmail: {
|
||||
type: String
|
||||
},
|
||||
workspace: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Workspace",
|
||||
required: true
|
||||
},
|
||||
deniedPermissions: {
|
||||
type: [
|
||||
{
|
||||
environmentSlug: String,
|
||||
ability: {
|
||||
type: String,
|
||||
enum: ["read", "write"]
|
||||
}
|
||||
}
|
||||
],
|
||||
default: []
|
||||
},
|
||||
role: {
|
||||
type: String,
|
||||
enum: [ADMIN, MEMBER, VIEWER, NO_ACCESS, CUSTOM],
|
||||
required: true
|
||||
},
|
||||
customRole: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Role"
|
||||
}
|
||||
},
|
||||
{
|
||||
timestamps: true
|
||||
}
|
||||
);
|
||||
|
||||
export const Membership = model<IMembership>("Membership", membershipSchema);
|
||||
47
pg-migrator/src/models/membershipOrg.ts
Normal file
47
pg-migrator/src/models/membershipOrg.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import { Document, Schema, Types, model } from "mongoose";
|
||||
import { ACCEPTED, ADMIN, CUSTOM, INVITED, MEMBER, NO_ACCESS } from "../variables";
|
||||
|
||||
export interface IMembershipOrg extends Document {
|
||||
_id: Types.ObjectId;
|
||||
user: Types.ObjectId;
|
||||
inviteEmail: string;
|
||||
organization: Types.ObjectId;
|
||||
role: "admin" | "member" | "no-access" | "custom";
|
||||
customRole: Types.ObjectId;
|
||||
status: "invited" | "accepted";
|
||||
}
|
||||
|
||||
const membershipOrgSchema = new Schema(
|
||||
{
|
||||
user: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "User"
|
||||
},
|
||||
inviteEmail: {
|
||||
type: String
|
||||
},
|
||||
organization: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Organization"
|
||||
},
|
||||
role: {
|
||||
type: String,
|
||||
enum: [ADMIN, MEMBER, NO_ACCESS, CUSTOM],
|
||||
required: true
|
||||
},
|
||||
status: {
|
||||
type: String,
|
||||
enum: [INVITED, ACCEPTED],
|
||||
required: true
|
||||
},
|
||||
customRole: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Role"
|
||||
}
|
||||
},
|
||||
{
|
||||
timestamps: true
|
||||
}
|
||||
);
|
||||
|
||||
export const MembershipOrg = model<IMembershipOrg>("MembershipOrg", membershipOrgSchema);
|
||||
24
pg-migrator/src/models/organization.ts
Normal file
24
pg-migrator/src/models/organization.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { Schema, Types, model } from "mongoose";
|
||||
|
||||
export interface IOrganization {
|
||||
_id: Types.ObjectId;
|
||||
name: string;
|
||||
customerId?: string;
|
||||
}
|
||||
|
||||
const organizationSchema = new Schema<IOrganization>(
|
||||
{
|
||||
name: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
customerId: {
|
||||
type: String,
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamps: true,
|
||||
}
|
||||
);
|
||||
|
||||
export const Organization = model<IOrganization>("Organization", organizationSchema);
|
||||
53
pg-migrator/src/models/role.ts
Normal file
53
pg-migrator/src/models/role.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import { Schema, Types, model } from "mongoose";
|
||||
|
||||
export interface IRole {
|
||||
_id: Types.ObjectId;
|
||||
name: string;
|
||||
description: string;
|
||||
slug: string;
|
||||
permissions: Array<unknown>;
|
||||
workspace: Types.ObjectId;
|
||||
organization: Types.ObjectId;
|
||||
isOrgRole: boolean;
|
||||
}
|
||||
|
||||
const roleSchema = new Schema<IRole>(
|
||||
{
|
||||
name: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
organization: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Organization",
|
||||
required: true
|
||||
},
|
||||
workspace: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Workspace"
|
||||
},
|
||||
isOrgRole: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
select: false
|
||||
},
|
||||
description: {
|
||||
type: String
|
||||
},
|
||||
slug: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
permissions: {
|
||||
type: Array,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
{
|
||||
timestamps: true
|
||||
}
|
||||
);
|
||||
|
||||
roleSchema.index({ organization: 1, workspace: 1 });
|
||||
|
||||
export const Role = model<IRole>("Role", roleSchema);
|
||||
172
pg-migrator/src/models/secret.ts
Normal file
172
pg-migrator/src/models/secret.ts
Normal file
@@ -0,0 +1,172 @@
|
||||
import { Schema, Types, model } from "mongoose";
|
||||
import {
|
||||
ALGORITHM_AES_256_GCM,
|
||||
ENCODING_SCHEME_BASE64,
|
||||
ENCODING_SCHEME_UTF8,
|
||||
SECRET_PERSONAL,
|
||||
SECRET_SHARED
|
||||
} from "../variables";
|
||||
|
||||
export interface ISecret {
|
||||
_id: Types.ObjectId;
|
||||
version: number;
|
||||
workspace: Types.ObjectId;
|
||||
type: string;
|
||||
user?: Types.ObjectId;
|
||||
environment: string;
|
||||
secretBlindIndex?: string;
|
||||
secretKeyCiphertext: string;
|
||||
secretKeyIV: string;
|
||||
secretKeyTag: string;
|
||||
secretKeyHash: string;
|
||||
secretValueCiphertext: string;
|
||||
secretValueIV: string;
|
||||
secretValueTag: string;
|
||||
secretValueHash: string;
|
||||
secretCommentCiphertext?: string;
|
||||
secretCommentIV?: string;
|
||||
secretCommentTag?: string;
|
||||
secretCommentHash?: string;
|
||||
|
||||
// ? NOTE: This works great for workspace-level reminders.
|
||||
// ? If we want to do it on a user-basis, we should ideally have a seperate model for reminders.
|
||||
secretReminderRepeatDays?: number | null;
|
||||
secretReminderNote?: string | null;
|
||||
|
||||
skipMultilineEncoding?: boolean;
|
||||
algorithm: "aes-256-gcm";
|
||||
keyEncoding: "utf8" | "base64";
|
||||
tags?: string[];
|
||||
folder?: string;
|
||||
metadata?: {
|
||||
[key: string]: string;
|
||||
};
|
||||
}
|
||||
|
||||
const secretSchema = new Schema<ISecret>(
|
||||
{
|
||||
version: {
|
||||
type: Number,
|
||||
required: true,
|
||||
default: 1
|
||||
},
|
||||
workspace: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Workspace",
|
||||
required: true
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
enum: [SECRET_SHARED, SECRET_PERSONAL],
|
||||
required: true
|
||||
},
|
||||
user: {
|
||||
// user associated with the personal secret
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "User"
|
||||
},
|
||||
tags: {
|
||||
ref: "Tag",
|
||||
type: [Schema.Types.ObjectId],
|
||||
default: []
|
||||
},
|
||||
environment: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
secretBlindIndex: {
|
||||
type: String,
|
||||
select: false
|
||||
},
|
||||
secretKeyCiphertext: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
secretKeyIV: {
|
||||
type: String, // symmetric
|
||||
required: true
|
||||
},
|
||||
secretKeyTag: {
|
||||
type: String, // symmetric
|
||||
required: true
|
||||
},
|
||||
secretKeyHash: {
|
||||
type: String
|
||||
},
|
||||
secretValueCiphertext: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
secretValueIV: {
|
||||
type: String, // symmetric
|
||||
required: true
|
||||
},
|
||||
secretValueTag: {
|
||||
type: String, // symmetric
|
||||
required: true
|
||||
},
|
||||
secretValueHash: {
|
||||
type: String
|
||||
},
|
||||
secretCommentCiphertext: {
|
||||
type: String,
|
||||
required: false
|
||||
},
|
||||
secretCommentIV: {
|
||||
type: String, // symmetric
|
||||
required: false
|
||||
},
|
||||
secretCommentTag: {
|
||||
type: String, // symmetric
|
||||
required: false
|
||||
},
|
||||
secretCommentHash: {
|
||||
type: String,
|
||||
required: false
|
||||
},
|
||||
|
||||
secretReminderRepeatDays: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: null
|
||||
},
|
||||
secretReminderNote: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: null
|
||||
},
|
||||
|
||||
skipMultilineEncoding: {
|
||||
type: Boolean,
|
||||
required: false
|
||||
},
|
||||
|
||||
algorithm: {
|
||||
// the encryption algorithm used
|
||||
type: String,
|
||||
enum: [ALGORITHM_AES_256_GCM],
|
||||
required: true,
|
||||
default: ALGORITHM_AES_256_GCM
|
||||
},
|
||||
keyEncoding: {
|
||||
type: String,
|
||||
enum: [ENCODING_SCHEME_UTF8, ENCODING_SCHEME_BASE64],
|
||||
required: true,
|
||||
default: ENCODING_SCHEME_UTF8
|
||||
},
|
||||
folder: {
|
||||
type: String,
|
||||
default: "root"
|
||||
},
|
||||
metadata: {
|
||||
type: Schema.Types.Mixed
|
||||
}
|
||||
},
|
||||
{
|
||||
timestamps: true
|
||||
}
|
||||
);
|
||||
|
||||
secretSchema.index({ tags: 1 }, { background: true });
|
||||
|
||||
export const Secret = model<ISecret>("Secret", secretSchema);
|
||||
51
pg-migrator/src/models/secretApprovalPolicy.ts
Normal file
51
pg-migrator/src/models/secretApprovalPolicy.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
import { Schema, Types, model } from "mongoose";
|
||||
|
||||
export interface ISecretApprovalPolicy {
|
||||
_id: Types.ObjectId;
|
||||
workspace: Types.ObjectId;
|
||||
name: string;
|
||||
environment: string;
|
||||
secretPath?: string;
|
||||
approvers: Types.ObjectId[];
|
||||
approvals: number;
|
||||
}
|
||||
|
||||
const secretApprovalPolicySchema = new Schema<ISecretApprovalPolicy>(
|
||||
{
|
||||
workspace: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Workspace",
|
||||
required: true
|
||||
},
|
||||
approvers: [
|
||||
{
|
||||
// user associated with the personal secret
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Membership"
|
||||
}
|
||||
],
|
||||
name: {
|
||||
type: String
|
||||
},
|
||||
environment: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
secretPath: {
|
||||
type: String,
|
||||
required: false
|
||||
},
|
||||
approvals: {
|
||||
type: Number,
|
||||
default: 1
|
||||
}
|
||||
},
|
||||
{
|
||||
timestamps: true
|
||||
}
|
||||
);
|
||||
|
||||
export const SecretApprovalPolicy = model<ISecretApprovalPolicy>(
|
||||
"SecretApprovalPolicy",
|
||||
secretApprovalPolicySchema
|
||||
);
|
||||
203
pg-migrator/src/models/secretApprovalRequest.ts
Normal file
203
pg-migrator/src/models/secretApprovalRequest.ts
Normal file
@@ -0,0 +1,203 @@
|
||||
import { Schema, Types, model } from "mongoose";
|
||||
import { customAlphabet } from "nanoid";
|
||||
import {
|
||||
ALGORITHM_AES_256_GCM,
|
||||
ENCODING_SCHEME_BASE64,
|
||||
ENCODING_SCHEME_UTF8
|
||||
} from "../../variables";
|
||||
|
||||
export enum ApprovalStatus {
|
||||
PENDING = "pending",
|
||||
APPROVED = "approved",
|
||||
REJECTED = "rejected"
|
||||
}
|
||||
|
||||
export enum CommitType {
|
||||
DELETE = "delete",
|
||||
UPDATE = "update",
|
||||
CREATE = "create"
|
||||
}
|
||||
|
||||
const SLUG_ALPHABETS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
const nanoId = customAlphabet(SLUG_ALPHABETS, 10);
|
||||
|
||||
export interface ISecretApprovalSecChange {
|
||||
_id: Types.ObjectId;
|
||||
version: number;
|
||||
secretBlindIndex?: string;
|
||||
secretKeyCiphertext: string;
|
||||
secretKeyIV: string;
|
||||
secretKeyTag: string;
|
||||
secretValueCiphertext: string;
|
||||
secretValueIV: string;
|
||||
secretValueTag: string;
|
||||
secretCommentIV?: string;
|
||||
secretCommentTag?: string;
|
||||
secretCommentCiphertext?: string;
|
||||
skipMultilineEncoding?: boolean;
|
||||
algorithm?: "aes-256-gcm";
|
||||
keyEncoding?: "utf8" | "base64";
|
||||
tags?: string[];
|
||||
}
|
||||
|
||||
export type ISecretCommits<T = Types.ObjectId, J = Types.ObjectId> = Array<
|
||||
| {
|
||||
newVersion: ISecretApprovalSecChange;
|
||||
op: CommitType.CREATE;
|
||||
}
|
||||
| {
|
||||
// secret is recorded to get the latest version, we can keep ref to secret for pulling change as it will also get changed
|
||||
// on merge
|
||||
secretVersion: J;
|
||||
secret: T;
|
||||
newVersion: Partial<Omit<ISecretApprovalSecChange, "_id">> & { _id: Types.ObjectId };
|
||||
op: CommitType.UPDATE;
|
||||
}
|
||||
| {
|
||||
secret: T;
|
||||
secretVersion: J;
|
||||
op: CommitType.DELETE;
|
||||
}
|
||||
>;
|
||||
export interface ISecretApprovalRequest {
|
||||
_id: Types.ObjectId;
|
||||
committer: Types.ObjectId;
|
||||
slug: string;
|
||||
statusChangeBy: Types.ObjectId;
|
||||
reviewers: {
|
||||
member: Types.ObjectId;
|
||||
status: ApprovalStatus;
|
||||
}[];
|
||||
workspace: Types.ObjectId;
|
||||
environment: string;
|
||||
folderId: string;
|
||||
hasMerged: boolean;
|
||||
status: "open" | "close";
|
||||
policy: Types.ObjectId;
|
||||
commits: ISecretCommits;
|
||||
conflicts: Array<{ secretId: string; op: CommitType }>;
|
||||
}
|
||||
|
||||
const secretApprovalSecretChangeSchema = new Schema<ISecretApprovalSecChange>({
|
||||
version: {
|
||||
type: Number,
|
||||
default: 1,
|
||||
required: true
|
||||
},
|
||||
secretBlindIndex: {
|
||||
type: String,
|
||||
select: false
|
||||
},
|
||||
secretKeyCiphertext: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
secretKeyIV: {
|
||||
type: String, // symmetric
|
||||
required: true
|
||||
},
|
||||
secretKeyTag: {
|
||||
type: String, // symmetric
|
||||
required: true
|
||||
},
|
||||
secretValueCiphertext: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
secretValueIV: {
|
||||
type: String, // symmetric
|
||||
required: true
|
||||
},
|
||||
secretValueTag: {
|
||||
type: String, // symmetric
|
||||
required: true
|
||||
},
|
||||
skipMultilineEncoding: {
|
||||
type: Boolean,
|
||||
required: false
|
||||
},
|
||||
algorithm: {
|
||||
// the encryption algorithm used
|
||||
type: String,
|
||||
enum: [ALGORITHM_AES_256_GCM],
|
||||
required: true,
|
||||
default: ALGORITHM_AES_256_GCM
|
||||
},
|
||||
keyEncoding: {
|
||||
type: String,
|
||||
enum: [ENCODING_SCHEME_UTF8, ENCODING_SCHEME_BASE64],
|
||||
required: true,
|
||||
default: ENCODING_SCHEME_UTF8
|
||||
},
|
||||
tags: {
|
||||
ref: "Tag",
|
||||
type: [Schema.Types.ObjectId],
|
||||
default: []
|
||||
}
|
||||
});
|
||||
|
||||
const secretApprovalRequestSchema = new Schema<ISecretApprovalRequest>(
|
||||
{
|
||||
workspace: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Workspace",
|
||||
required: true
|
||||
},
|
||||
environment: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
folderId: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: "root"
|
||||
},
|
||||
slug: {
|
||||
type: String,
|
||||
default: () => nanoId()
|
||||
},
|
||||
reviewers: {
|
||||
type: [
|
||||
{
|
||||
member: {
|
||||
// user associated with the personal secret
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Membership"
|
||||
},
|
||||
status: { type: String, enum: ApprovalStatus, default: ApprovalStatus.PENDING }
|
||||
}
|
||||
],
|
||||
default: []
|
||||
},
|
||||
policy: { type: Schema.Types.ObjectId, ref: "SecretApprovalPolicy" },
|
||||
hasMerged: { type: Boolean, default: false },
|
||||
status: { type: String, enum: ["close", "open"], default: "open" },
|
||||
committer: { type: Schema.Types.ObjectId, ref: "Membership" },
|
||||
statusChangeBy: { type: Schema.Types.ObjectId, ref: "Membership" },
|
||||
commits: [
|
||||
{
|
||||
secret: { type: Types.ObjectId, ref: "Secret" },
|
||||
newVersion: secretApprovalSecretChangeSchema,
|
||||
secretVersion: { type: Types.ObjectId, ref: "SecretVersion" },
|
||||
op: { type: String, enum: [CommitType], required: true }
|
||||
}
|
||||
],
|
||||
conflicts: {
|
||||
type: [
|
||||
{
|
||||
secretId: { type: String, required: true },
|
||||
op: { type: String, enum: [CommitType], required: true }
|
||||
}
|
||||
],
|
||||
default: []
|
||||
}
|
||||
},
|
||||
{
|
||||
timestamps: true
|
||||
}
|
||||
);
|
||||
|
||||
export const SecretApprovalRequest = model<ISecretApprovalRequest>(
|
||||
"SecretApprovalRequest",
|
||||
secretApprovalRequestSchema
|
||||
);
|
||||
58
pg-migrator/src/models/secretBlindIndexData.ts
Normal file
58
pg-migrator/src/models/secretBlindIndexData.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import { Document, Schema, Types, model } from "mongoose";
|
||||
import {
|
||||
ALGORITHM_AES_256_GCM,
|
||||
ENCODING_SCHEME_BASE64,
|
||||
ENCODING_SCHEME_UTF8,
|
||||
} from "../variables";
|
||||
|
||||
export interface ISecretBlindIndexData extends Document {
|
||||
_id: Types.ObjectId;
|
||||
workspace: Types.ObjectId;
|
||||
encryptedSaltCiphertext: string;
|
||||
saltIV: string;
|
||||
saltTag: string;
|
||||
algorithm: "aes-256-gcm";
|
||||
keyEncoding: "base64" | "utf8"
|
||||
}
|
||||
|
||||
const secretBlindIndexDataSchema = new Schema<ISecretBlindIndexData>(
|
||||
{
|
||||
workspace: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Workspace",
|
||||
required: true,
|
||||
},
|
||||
encryptedSaltCiphertext: { // TODO: make these select: false
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
saltIV: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
saltTag: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
algorithm: {
|
||||
type: String,
|
||||
enum: [ALGORITHM_AES_256_GCM],
|
||||
required: true,
|
||||
select: false,
|
||||
},
|
||||
keyEncoding: {
|
||||
type: String,
|
||||
enum: [
|
||||
ENCODING_SCHEME_UTF8,
|
||||
ENCODING_SCHEME_BASE64,
|
||||
],
|
||||
required: true,
|
||||
select: false,
|
||||
},
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
secretBlindIndexDataSchema.index({ workspace: 1 });
|
||||
|
||||
export const SecretBlindIndexData = model<ISecretBlindIndexData>("SecretBlindIndexData", secretBlindIndexDataSchema);
|
||||
51
pg-migrator/src/models/secretImports.ts
Normal file
51
pg-migrator/src/models/secretImports.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
import { Schema, Types, model } from "mongoose";
|
||||
|
||||
export interface ISecretImports {
|
||||
_id: Types.ObjectId;
|
||||
workspace: Types.ObjectId;
|
||||
environment: string;
|
||||
folderId: string;
|
||||
imports: Array<{
|
||||
environment: string;
|
||||
secretPath: string;
|
||||
}>;
|
||||
}
|
||||
|
||||
const secretImportSchema = new Schema<ISecretImports>(
|
||||
{
|
||||
workspace: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Workspace",
|
||||
required: true
|
||||
},
|
||||
environment: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
folderId: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: "root"
|
||||
},
|
||||
imports: {
|
||||
type: [
|
||||
{
|
||||
environment: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
secretPath: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
}
|
||||
],
|
||||
default: []
|
||||
}
|
||||
},
|
||||
{
|
||||
timestamps: true
|
||||
}
|
||||
);
|
||||
|
||||
export const SecretImport = model<ISecretImports>("SecretImports", secretImportSchema);
|
||||
52
pg-migrator/src/models/secretSnapshot.ts
Normal file
52
pg-migrator/src/models/secretSnapshot.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import { Schema, Types, model } from "mongoose";
|
||||
|
||||
export interface ISecretSnapshot {
|
||||
workspace: Types.ObjectId;
|
||||
environment: string;
|
||||
folderId: string | "root";
|
||||
version: number;
|
||||
secretVersions: Types.ObjectId[];
|
||||
folderVersion: Types.ObjectId;
|
||||
}
|
||||
|
||||
const secretSnapshotSchema = new Schema<ISecretSnapshot>(
|
||||
{
|
||||
workspace: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Workspace",
|
||||
required: true,
|
||||
},
|
||||
environment: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
folderId: {
|
||||
type: String,
|
||||
default: "root",
|
||||
},
|
||||
version: {
|
||||
type: Number,
|
||||
default: 1,
|
||||
required: true,
|
||||
},
|
||||
secretVersions: [
|
||||
{
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "SecretVersion",
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
folderVersion: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "FolderVersion",
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamps: true,
|
||||
}
|
||||
);
|
||||
|
||||
export const SecretSnapshot = model<ISecretSnapshot>(
|
||||
"SecretSnapshot",
|
||||
secretSnapshotSchema
|
||||
);
|
||||
132
pg-migrator/src/models/secretVersion.ts
Normal file
132
pg-migrator/src/models/secretVersion.ts
Normal file
@@ -0,0 +1,132 @@
|
||||
import { Schema, Types, model } from "mongoose";
|
||||
import {
|
||||
ALGORITHM_AES_256_GCM,
|
||||
ENCODING_SCHEME_BASE64,
|
||||
ENCODING_SCHEME_UTF8,
|
||||
SECRET_PERSONAL,
|
||||
SECRET_SHARED
|
||||
} from "../../variables";
|
||||
|
||||
export interface ISecretVersion {
|
||||
_id: Types.ObjectId;
|
||||
secret: Types.ObjectId;
|
||||
version: number;
|
||||
workspace: Types.ObjectId; // new
|
||||
type: string; // new
|
||||
user?: Types.ObjectId; // new
|
||||
environment: string; // new
|
||||
isDeleted: boolean;
|
||||
secretBlindIndex?: string;
|
||||
secretKeyCiphertext: string;
|
||||
secretKeyIV: string;
|
||||
secretKeyTag: string;
|
||||
secretValueCiphertext: string;
|
||||
secretValueIV: string;
|
||||
secretValueTag: string;
|
||||
skipMultilineEncoding?: boolean;
|
||||
algorithm: "aes-256-gcm";
|
||||
keyEncoding: "utf8" | "base64";
|
||||
createdAt: string;
|
||||
folder?: string;
|
||||
tags?: string[];
|
||||
}
|
||||
|
||||
const secretVersionSchema = new Schema<ISecretVersion>(
|
||||
{
|
||||
secret: {
|
||||
// could be deleted
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Secret",
|
||||
required: true
|
||||
},
|
||||
version: {
|
||||
type: Number,
|
||||
default: 1,
|
||||
required: true
|
||||
},
|
||||
workspace: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Workspace",
|
||||
required: true
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
enum: [SECRET_SHARED, SECRET_PERSONAL],
|
||||
required: true
|
||||
},
|
||||
user: {
|
||||
// user associated with the personal secret
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "User"
|
||||
},
|
||||
environment: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
isDeleted: {
|
||||
// consider removing field
|
||||
type: Boolean,
|
||||
default: false,
|
||||
required: true
|
||||
},
|
||||
secretBlindIndex: {
|
||||
type: String,
|
||||
select: false
|
||||
},
|
||||
secretKeyCiphertext: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
secretKeyIV: {
|
||||
type: String, // symmetric
|
||||
required: true
|
||||
},
|
||||
secretKeyTag: {
|
||||
type: String, // symmetric
|
||||
required: true
|
||||
},
|
||||
secretValueCiphertext: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
secretValueIV: {
|
||||
type: String, // symmetric
|
||||
required: true
|
||||
},
|
||||
secretValueTag: {
|
||||
type: String, // symmetric
|
||||
required: true
|
||||
},
|
||||
skipMultilineEncoding: {
|
||||
type: Boolean,
|
||||
required: false
|
||||
},
|
||||
algorithm: {
|
||||
// the encryption algorithm used
|
||||
type: String,
|
||||
enum: [ALGORITHM_AES_256_GCM],
|
||||
required: true,
|
||||
default: ALGORITHM_AES_256_GCM
|
||||
},
|
||||
keyEncoding: {
|
||||
type: String,
|
||||
enum: [ENCODING_SCHEME_UTF8, ENCODING_SCHEME_BASE64],
|
||||
required: true,
|
||||
default: ENCODING_SCHEME_UTF8
|
||||
},
|
||||
folder: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
tags: {
|
||||
ref: "Tag",
|
||||
type: [Schema.Types.ObjectId],
|
||||
default: []
|
||||
}
|
||||
},
|
||||
{
|
||||
timestamps: true
|
||||
}
|
||||
);
|
||||
|
||||
export const SecretVersion = model<ISecretVersion>("SecretVersion", secretVersionSchema);
|
||||
25
pg-migrator/src/models/serverConfig.ts
Normal file
25
pg-migrator/src/models/serverConfig.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { Schema, Types, model } from "mongoose";
|
||||
|
||||
export interface IServerConfig {
|
||||
_id: Types.ObjectId;
|
||||
initialized: boolean;
|
||||
allowSignUp: boolean;
|
||||
}
|
||||
|
||||
const serverConfigSchema = new Schema<IServerConfig>(
|
||||
{
|
||||
initialized: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
allowSignUp: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
{
|
||||
timestamps: true
|
||||
}
|
||||
);
|
||||
|
||||
export const ServerConfig = model<IServerConfig>("ServerConfig", serverConfigSchema);
|
||||
60
pg-migrator/src/models/serviceToken.ts
Normal file
60
pg-migrator/src/models/serviceToken.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
// TODO: deprecate
|
||||
import { Schema, Types, model } from "mongoose";
|
||||
export interface IServiceToken {
|
||||
_id: Types.ObjectId;
|
||||
name: string;
|
||||
user: Types.ObjectId;
|
||||
workspace: Types.ObjectId;
|
||||
environment: string;
|
||||
expiresAt: Date;
|
||||
publicKey: string;
|
||||
encryptedKey: string;
|
||||
nonce: string;
|
||||
}
|
||||
|
||||
const serviceTokenSchema = new Schema<IServiceToken>(
|
||||
{
|
||||
name: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
user: {
|
||||
// token issuer
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "User",
|
||||
required: true,
|
||||
},
|
||||
workspace: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Workspace",
|
||||
required: true,
|
||||
},
|
||||
environment: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
expiresAt: {
|
||||
type: Date,
|
||||
},
|
||||
publicKey: {
|
||||
type: String,
|
||||
required: true,
|
||||
select: true,
|
||||
},
|
||||
encryptedKey: {
|
||||
type: String,
|
||||
required: true,
|
||||
select: true,
|
||||
},
|
||||
nonce: {
|
||||
type: String,
|
||||
required: true,
|
||||
select: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamps: true,
|
||||
}
|
||||
);
|
||||
|
||||
export const ServiceToken = model<IServiceToken>("ServiceToken", serviceTokenSchema);
|
||||
93
pg-migrator/src/models/serviceTokenData.ts
Normal file
93
pg-migrator/src/models/serviceTokenData.ts
Normal file
@@ -0,0 +1,93 @@
|
||||
// TODO: deprecate
|
||||
import { Document, Schema, Types, model } from "mongoose";
|
||||
|
||||
export interface IServiceTokenData extends Document {
|
||||
_id: Types.ObjectId;
|
||||
name: string;
|
||||
workspace: Types.ObjectId;
|
||||
scopes: Array<{
|
||||
environment: string;
|
||||
secretPath: string;
|
||||
}>;
|
||||
user: Types.ObjectId;
|
||||
serviceAccount: Types.ObjectId;
|
||||
lastUsed: Date;
|
||||
expiresAt: Date;
|
||||
secretHash: string;
|
||||
encryptedKey: string;
|
||||
iv: string;
|
||||
tag: string;
|
||||
permissions: string[];
|
||||
}
|
||||
|
||||
const serviceTokenDataSchema = new Schema<IServiceTokenData>(
|
||||
{
|
||||
name: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
workspace: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Workspace",
|
||||
required: true
|
||||
},
|
||||
scopes: {
|
||||
type: [
|
||||
{
|
||||
environment: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
secretPath: {
|
||||
type: String,
|
||||
default: "/",
|
||||
required: true
|
||||
}
|
||||
}
|
||||
],
|
||||
required: true
|
||||
},
|
||||
user: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "User",
|
||||
required: true
|
||||
},
|
||||
serviceAccount: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "ServiceAccount"
|
||||
},
|
||||
lastUsed: {
|
||||
type: Date
|
||||
},
|
||||
expiresAt: {
|
||||
type: Date
|
||||
},
|
||||
secretHash: {
|
||||
type: String,
|
||||
required: true,
|
||||
select: false
|
||||
},
|
||||
encryptedKey: {
|
||||
type: String,
|
||||
select: false
|
||||
},
|
||||
iv: {
|
||||
type: String,
|
||||
select: false
|
||||
},
|
||||
tag: {
|
||||
type: String,
|
||||
select: false
|
||||
},
|
||||
permissions: {
|
||||
type: [String],
|
||||
enum: ["read", "write"],
|
||||
default: ["read"]
|
||||
}
|
||||
},
|
||||
{
|
||||
timestamps: true
|
||||
}
|
||||
);
|
||||
|
||||
export const ServiceTokenData = model<IServiceTokenData>("ServiceTokenData", serviceTokenDataSchema);
|
||||
72
pg-migrator/src/models/ssoConfig.ts
Normal file
72
pg-migrator/src/models/ssoConfig.ts
Normal file
@@ -0,0 +1,72 @@
|
||||
import { Schema, Types, model } from "mongoose";
|
||||
|
||||
export enum AuthProvider {
|
||||
OKTA_SAML = "okta-saml",
|
||||
AZURE_SAML = "azure-saml",
|
||||
JUMPCLOUD_SAML = "jumpcloud-saml"
|
||||
}
|
||||
|
||||
export interface ISSOConfig {
|
||||
organization: Types.ObjectId;
|
||||
authProvider: AuthProvider;
|
||||
isActive: boolean;
|
||||
encryptedEntryPoint: string;
|
||||
entryPointIV: string;
|
||||
entryPointTag: string;
|
||||
encryptedIssuer: string;
|
||||
issuerIV: string;
|
||||
issuerTag: string;
|
||||
encryptedCert: string;
|
||||
certIV: string;
|
||||
certTag: string;
|
||||
}
|
||||
|
||||
const ssoConfigSchema = new Schema<ISSOConfig>(
|
||||
{
|
||||
organization: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Organization"
|
||||
},
|
||||
authProvider: {
|
||||
type: String,
|
||||
enum: AuthProvider,
|
||||
required: true
|
||||
},
|
||||
isActive: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
},
|
||||
encryptedEntryPoint: {
|
||||
type: String
|
||||
},
|
||||
entryPointIV: {
|
||||
type: String
|
||||
},
|
||||
entryPointTag: {
|
||||
type: String
|
||||
},
|
||||
encryptedIssuer: {
|
||||
type: String
|
||||
},
|
||||
issuerIV: {
|
||||
type: String
|
||||
},
|
||||
issuerTag: {
|
||||
type: String
|
||||
},
|
||||
encryptedCert: {
|
||||
type: String
|
||||
},
|
||||
certIV: {
|
||||
type: String
|
||||
},
|
||||
certTag: {
|
||||
type: String
|
||||
}
|
||||
},
|
||||
{
|
||||
timestamps: true
|
||||
}
|
||||
);
|
||||
|
||||
export const SSOConfig = model<ISSOConfig>("SSOConfig", ssoConfigSchema);
|
||||
53
pg-migrator/src/models/tag.ts
Normal file
53
pg-migrator/src/models/tag.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import { Schema, Types, model } from "mongoose";
|
||||
|
||||
export interface ITag {
|
||||
_id: Types.ObjectId;
|
||||
name: string;
|
||||
tagColor: string;
|
||||
slug: string;
|
||||
user: Types.ObjectId;
|
||||
workspace: Types.ObjectId;
|
||||
}
|
||||
|
||||
const tagSchema = new Schema<ITag>(
|
||||
{
|
||||
name: {
|
||||
type: String,
|
||||
required: true,
|
||||
trim: true,
|
||||
},
|
||||
tagColor: {
|
||||
type: String,
|
||||
required: false,
|
||||
trim: true,
|
||||
},
|
||||
slug: {
|
||||
type: String,
|
||||
required: true,
|
||||
trim: true,
|
||||
lowercase: true,
|
||||
validate: [
|
||||
function (value: any) {
|
||||
return value.indexOf(" ") === -1;
|
||||
},
|
||||
"slug cannot contain spaces",
|
||||
],
|
||||
},
|
||||
user: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "User",
|
||||
},
|
||||
workspace: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Workspace",
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamps: true,
|
||||
}
|
||||
);
|
||||
|
||||
tagSchema.index({ slug: 1, workspace: 1 }, { unique: true })
|
||||
tagSchema.index({ workspace: 1 })
|
||||
|
||||
export const Tag = model<ITag>("Tag", tagSchema);
|
||||
30
pg-migrator/src/models/token.ts
Normal file
30
pg-migrator/src/models/token.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { Schema, model } from "mongoose";
|
||||
|
||||
export interface IToken {
|
||||
email: string;
|
||||
token: string;
|
||||
createdAt: Date;
|
||||
ttl: number;
|
||||
}
|
||||
|
||||
const tokenSchema = new Schema<IToken>({
|
||||
email: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
token: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
createdAt: {
|
||||
type: Date,
|
||||
default: Date.now,
|
||||
},
|
||||
ttl: {
|
||||
type: Number,
|
||||
},
|
||||
});
|
||||
|
||||
tokenSchema.index({ email: 1 });
|
||||
|
||||
export const Token = model<IToken>("Token", tokenSchema);
|
||||
53
pg-migrator/src/models/tokenData.ts
Normal file
53
pg-migrator/src/models/tokenData.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import { Schema, Types, model } from "mongoose";
|
||||
|
||||
export interface ITokenData {
|
||||
type: string;
|
||||
email?: string;
|
||||
phoneNumber?: string;
|
||||
organization?: Types.ObjectId;
|
||||
tokenHash: string;
|
||||
triesLeft?: number;
|
||||
expiresAt: Date;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
}
|
||||
|
||||
const tokenDataSchema = new Schema<ITokenData>({
|
||||
type: {
|
||||
type: String,
|
||||
enum: [
|
||||
"emailConfirmation",
|
||||
"emailMfa",
|
||||
"organizationInvitation",
|
||||
"passwordReset",
|
||||
],
|
||||
required: true,
|
||||
},
|
||||
email: {
|
||||
type: String,
|
||||
},
|
||||
phoneNumber: {
|
||||
type: String,
|
||||
},
|
||||
organization: { // organizationInvitation-specific field
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Organization",
|
||||
},
|
||||
tokenHash: {
|
||||
type: String,
|
||||
select: false,
|
||||
required: true,
|
||||
},
|
||||
triesLeft: {
|
||||
type: Number,
|
||||
},
|
||||
expiresAt: {
|
||||
type: Date,
|
||||
expires: 0,
|
||||
required: true,
|
||||
},
|
||||
}, {
|
||||
timestamps: true,
|
||||
});
|
||||
|
||||
export const TokenData = model<ITokenData>("TokenData", tokenDataSchema);
|
||||
45
pg-migrator/src/models/tokenVersion.ts
Normal file
45
pg-migrator/src/models/tokenVersion.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import { Document, Schema, Types, model } from "mongoose";
|
||||
|
||||
export interface ITokenVersion extends Document {
|
||||
user: Types.ObjectId;
|
||||
ip: string;
|
||||
userAgent: string;
|
||||
refreshVersion: number;
|
||||
accessVersion: number;
|
||||
lastUsed: Date;
|
||||
}
|
||||
|
||||
const tokenVersionSchema = new Schema<ITokenVersion>(
|
||||
{
|
||||
user: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "User",
|
||||
required: true,
|
||||
},
|
||||
ip: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
userAgent: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
refreshVersion: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
accessVersion: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
lastUsed: {
|
||||
type: Date,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamps: true,
|
||||
}
|
||||
);
|
||||
|
||||
export const TokenVersion = model<ITokenVersion>("TokenVersion", tokenVersionSchema);
|
||||
54
pg-migrator/src/models/trustedIp.ts
Normal file
54
pg-migrator/src/models/trustedIp.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
import { Schema, Types, model } from "mongoose";
|
||||
|
||||
export enum IPType {
|
||||
IPV4 = "ipv4",
|
||||
IPV6 = "ipv6"
|
||||
}
|
||||
|
||||
export interface ITrustedIP {
|
||||
_id: Types.ObjectId;
|
||||
workspace: Types.ObjectId;
|
||||
ipAddress: string;
|
||||
type: "ipv4" | "ipv6", // either IPv4/IPv6 address or network IPv4/IPv6 address
|
||||
isActive: boolean;
|
||||
comment: string;
|
||||
prefix?: number; // CIDR
|
||||
}
|
||||
|
||||
const trustedIpSchema = new Schema<ITrustedIP>(
|
||||
{
|
||||
workspace: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Workspace",
|
||||
required: true
|
||||
},
|
||||
ipAddress: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
enum: [
|
||||
IPType.IPV4,
|
||||
IPType.IPV6
|
||||
],
|
||||
required: true
|
||||
},
|
||||
prefix: {
|
||||
type: Number,
|
||||
required: false
|
||||
},
|
||||
isActive: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
},
|
||||
comment: {
|
||||
type: String
|
||||
}
|
||||
},
|
||||
{
|
||||
timestamps: true
|
||||
}
|
||||
);
|
||||
|
||||
export const TrustedIP = model<ITrustedIP>("TrustedIP", trustedIpSchema);
|
||||
141
pg-migrator/src/models/user.ts
Normal file
141
pg-migrator/src/models/user.ts
Normal file
@@ -0,0 +1,141 @@
|
||||
import { Document, Schema, Types, model } from "mongoose";
|
||||
|
||||
export enum AuthMethod {
|
||||
EMAIL = "email",
|
||||
GOOGLE = "google",
|
||||
GITHUB = "github",
|
||||
GITLAB = "gitlab",
|
||||
OKTA_SAML = "okta-saml",
|
||||
AZURE_SAML = "azure-saml",
|
||||
JUMPCLOUD_SAML = "jumpcloud-saml"
|
||||
}
|
||||
|
||||
export interface IUser extends Document {
|
||||
_id: Types.ObjectId;
|
||||
authProvider?: AuthMethod;
|
||||
authMethods: AuthMethod[];
|
||||
email: string;
|
||||
superAdmin?: boolean;
|
||||
firstName?: string;
|
||||
lastName?: string;
|
||||
encryptionVersion: number;
|
||||
protectedKey: string;
|
||||
protectedKeyIV: string;
|
||||
protectedKeyTag: string;
|
||||
publicKey?: string;
|
||||
encryptedPrivateKey?: string;
|
||||
iv?: string;
|
||||
tag?: string;
|
||||
salt?: string;
|
||||
verifier?: string;
|
||||
isMfaEnabled: boolean;
|
||||
mfaMethods: boolean;
|
||||
devices: {
|
||||
ip: string;
|
||||
userAgent: string;
|
||||
}[];
|
||||
}
|
||||
|
||||
const userSchema = new Schema<IUser>(
|
||||
{
|
||||
authProvider: {
|
||||
// TODO field: deprecate
|
||||
type: String,
|
||||
enum: AuthMethod
|
||||
},
|
||||
authMethods: {
|
||||
type: [
|
||||
{
|
||||
type: String,
|
||||
enum: AuthMethod
|
||||
}
|
||||
],
|
||||
default: [AuthMethod.EMAIL],
|
||||
required: true
|
||||
},
|
||||
email: {
|
||||
type: String,
|
||||
required: true,
|
||||
unique: true
|
||||
},
|
||||
firstName: {
|
||||
type: String
|
||||
},
|
||||
lastName: {
|
||||
type: String
|
||||
},
|
||||
encryptionVersion: {
|
||||
type: Number,
|
||||
select: false,
|
||||
default: 1 // to resolve backward-compatibility issues
|
||||
},
|
||||
protectedKey: {
|
||||
// introduced as part of encryption version 2
|
||||
type: String,
|
||||
select: false
|
||||
},
|
||||
protectedKeyIV: {
|
||||
// introduced as part of encryption version 2
|
||||
type: String,
|
||||
select: false
|
||||
},
|
||||
protectedKeyTag: {
|
||||
// introduced as part of encryption version 2
|
||||
type: String,
|
||||
select: false
|
||||
},
|
||||
publicKey: {
|
||||
type: String,
|
||||
select: false
|
||||
},
|
||||
encryptedPrivateKey: {
|
||||
type: String,
|
||||
select: false
|
||||
},
|
||||
superAdmin: {
|
||||
type: Boolean
|
||||
},
|
||||
iv: {
|
||||
// iv of [encryptedPrivateKey]
|
||||
type: String,
|
||||
select: false
|
||||
},
|
||||
tag: {
|
||||
// tag of [encryptedPrivateKey]
|
||||
type: String,
|
||||
select: false
|
||||
},
|
||||
salt: {
|
||||
type: String,
|
||||
select: false
|
||||
},
|
||||
verifier: {
|
||||
type: String,
|
||||
select: false
|
||||
},
|
||||
isMfaEnabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
mfaMethods: [
|
||||
{
|
||||
type: String
|
||||
}
|
||||
],
|
||||
devices: {
|
||||
type: [
|
||||
{
|
||||
ip: String,
|
||||
userAgent: String
|
||||
}
|
||||
],
|
||||
default: [],
|
||||
select: false
|
||||
}
|
||||
},
|
||||
{
|
||||
timestamps: true
|
||||
}
|
||||
);
|
||||
|
||||
export const User = model<IUser>("User", userSchema);
|
||||
26
pg-migrator/src/models/userAction.ts
Normal file
26
pg-migrator/src/models/userAction.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { Schema, Types, model } from "mongoose";
|
||||
|
||||
export interface IUserAction {
|
||||
_id: Types.ObjectId;
|
||||
user: Types.ObjectId;
|
||||
action: string;
|
||||
}
|
||||
|
||||
const userActionSchema = new Schema<IUserAction>(
|
||||
{
|
||||
user: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "User",
|
||||
required: true,
|
||||
},
|
||||
action: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamps: true,
|
||||
}
|
||||
);
|
||||
|
||||
export const UserAction = model<IUserAction>("UserAction", userActionSchema);
|
||||
81
pg-migrator/src/models/webhooks.ts
Normal file
81
pg-migrator/src/models/webhooks.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
import { Document, Schema, Types, model } from "mongoose";
|
||||
import { ALGORITHM_AES_256_GCM, ENCODING_SCHEME_BASE64, ENCODING_SCHEME_UTF8 } from "../variables";
|
||||
|
||||
export interface IWebhook extends Document {
|
||||
_id: Types.ObjectId;
|
||||
workspace: Types.ObjectId;
|
||||
environment: string;
|
||||
secretPath: string;
|
||||
url: string;
|
||||
lastStatus: "success" | "failed";
|
||||
lastRunErrorMessage?: string;
|
||||
isDisabled: boolean;
|
||||
encryptedSecretKey: string;
|
||||
iv: string;
|
||||
tag: string;
|
||||
algorithm: "aes-256-gcm";
|
||||
keyEncoding: "base64" | "utf8";
|
||||
}
|
||||
|
||||
const WebhookSchema = new Schema<IWebhook>(
|
||||
{
|
||||
workspace: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Workspace",
|
||||
required: true
|
||||
},
|
||||
environment: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
secretPath: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: "/"
|
||||
},
|
||||
url: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
lastStatus: {
|
||||
type: String,
|
||||
enum: ["success", "failed"]
|
||||
},
|
||||
lastRunErrorMessage: {
|
||||
type: String
|
||||
},
|
||||
isDisabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// used for webhook signature
|
||||
encryptedSecretKey: {
|
||||
type: String,
|
||||
select: false
|
||||
},
|
||||
iv: {
|
||||
type: String,
|
||||
select: false
|
||||
},
|
||||
tag: {
|
||||
type: String,
|
||||
select: false
|
||||
},
|
||||
algorithm: {
|
||||
// the encryption algorithm used
|
||||
type: String,
|
||||
enum: [ALGORITHM_AES_256_GCM],
|
||||
select: false
|
||||
},
|
||||
keyEncoding: {
|
||||
type: String,
|
||||
enum: [ENCODING_SCHEME_UTF8, ENCODING_SCHEME_BASE64],
|
||||
select: false
|
||||
}
|
||||
},
|
||||
{
|
||||
timestamps: true
|
||||
}
|
||||
);
|
||||
|
||||
export const Webhook = model<IWebhook>("Webhook", WebhookSchema);
|
||||
52
pg-migrator/src/models/workspace.ts
Normal file
52
pg-migrator/src/models/workspace.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import { Schema, Types, model } from "mongoose";
|
||||
|
||||
export interface IWorkspace {
|
||||
_id: Types.ObjectId;
|
||||
name: string;
|
||||
organization: Types.ObjectId;
|
||||
environments: Array<{
|
||||
name: string;
|
||||
slug: string;
|
||||
}>;
|
||||
autoCapitalization: boolean;
|
||||
}
|
||||
|
||||
const workspaceSchema = new Schema<IWorkspace>({
|
||||
name: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
autoCapitalization: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
organization: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Organization",
|
||||
required: true,
|
||||
},
|
||||
environments: {
|
||||
type: [
|
||||
{
|
||||
name: String,
|
||||
slug: String,
|
||||
},
|
||||
],
|
||||
default: [
|
||||
{
|
||||
name: "Development",
|
||||
slug: "dev",
|
||||
},
|
||||
{
|
||||
name: "Staging",
|
||||
slug: "staging",
|
||||
},
|
||||
{
|
||||
name: "Production",
|
||||
slug: "prod",
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
export const Workspace = model<IWorkspace>("Workspace", workspaceSchema);
|
||||
23
pg-migrator/src/schemas/api-keys.ts
Normal file
23
pg-migrator/src/schemas/api-keys.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
// Code generated by automation script, DO NOT EDIT.
|
||||
// Automated by pulling database and generating zod schema
|
||||
// To update. Just run npm run generate:schema
|
||||
// Written by akhilmhdh.
|
||||
|
||||
import { z } from "zod";
|
||||
|
||||
import { TImmutableDBKeys } from "./models";
|
||||
|
||||
export const ApiKeysSchema = z.object({
|
||||
id: z.string().uuid(),
|
||||
name: z.string(),
|
||||
lastUsed: z.date().nullable().optional(),
|
||||
expiresAt: z.date().nullable().optional(),
|
||||
secretHash: z.string(),
|
||||
createdAt: z.date(),
|
||||
updatedAt: z.date(),
|
||||
userId: z.string().uuid(),
|
||||
});
|
||||
|
||||
export type TApiKeys = z.infer<typeof ApiKeysSchema>;
|
||||
export type TApiKeysInsert = Omit<TApiKeys, TImmutableDBKeys>;
|
||||
export type TApiKeysUpdate = Partial<Omit<TApiKeys, TImmutableDBKeys>>;
|
||||
28
pg-migrator/src/schemas/audit-logs.ts
Normal file
28
pg-migrator/src/schemas/audit-logs.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
// Code generated by automation script, DO NOT EDIT.
|
||||
// Automated by pulling database and generating zod schema
|
||||
// To update. Just run npm run generate:schema
|
||||
// Written by akhilmhdh.
|
||||
|
||||
import { z } from "zod";
|
||||
|
||||
import { TImmutableDBKeys } from "./models";
|
||||
|
||||
export const AuditLogsSchema = z.object({
|
||||
id: z.string().uuid(),
|
||||
actor: z.string(),
|
||||
actorMetadata: z.unknown(),
|
||||
ipAddress: z.string().nullable().optional(),
|
||||
eventType: z.string(),
|
||||
eventMetadata: z.unknown().nullable().optional(),
|
||||
userAgent: z.string().nullable().optional(),
|
||||
userAgentType: z.string().nullable().optional(),
|
||||
expiresAt: z.date().nullable().optional(),
|
||||
createdAt: z.date(),
|
||||
updatedAt: z.date(),
|
||||
orgId: z.string().uuid().nullable().optional(),
|
||||
projectId: z.string().nullable().optional(),
|
||||
});
|
||||
|
||||
export type TAuditLogs = z.infer<typeof AuditLogsSchema>;
|
||||
export type TAuditLogsInsert = Omit<TAuditLogs, TImmutableDBKeys>;
|
||||
export type TAuditLogsUpdate = Partial<Omit<TAuditLogs, TImmutableDBKeys>>;
|
||||
24
pg-migrator/src/schemas/auth-token-sessions.ts
Normal file
24
pg-migrator/src/schemas/auth-token-sessions.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
// Code generated by automation script, DO NOT EDIT.
|
||||
// Automated by pulling database and generating zod schema
|
||||
// To update. Just run npm run generate:schema
|
||||
// Written by akhilmhdh.
|
||||
|
||||
import { z } from "zod";
|
||||
|
||||
import { TImmutableDBKeys } from "./models";
|
||||
|
||||
export const AuthTokenSessionsSchema = z.object({
|
||||
id: z.string().uuid(),
|
||||
ip: z.string(),
|
||||
userAgent: z.string().nullable().optional(),
|
||||
refreshVersion: z.number().default(1),
|
||||
accessVersion: z.number().default(1),
|
||||
lastUsed: z.date(),
|
||||
createdAt: z.date(),
|
||||
updatedAt: z.date(),
|
||||
userId: z.string().uuid(),
|
||||
});
|
||||
|
||||
export type TAuthTokenSessions = z.infer<typeof AuthTokenSessionsSchema>;
|
||||
export type TAuthTokenSessionsInsert = Omit<TAuthTokenSessions, TImmutableDBKeys>;
|
||||
export type TAuthTokenSessionsUpdate = Partial<Omit<TAuthTokenSessions, TImmutableDBKeys>>;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user