mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
feat(infisical-pg): completed first version of pg migrator
This commit is contained in:
63
pg-migrator/package-lock.json
generated
63
pg-migrator/package-lock.json
generated
@@ -9,21 +9,35 @@
|
||||
"version": "1.0.0",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@casl/ability": "^6.5.0",
|
||||
"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",
|
||||
"uuid": "^9.0.1",
|
||||
"zod": "^3.22.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.11.0",
|
||||
"@types/prompt-sync": "^4.2.3",
|
||||
"@types/uuid": "^9.0.7",
|
||||
"tsx": "^4.7.0",
|
||||
"typescript": "^5.3.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@casl/ability": {
|
||||
"version": "6.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@casl/ability/-/ability-6.5.0.tgz",
|
||||
"integrity": "sha512-3guc94ugr5ylZQIpJTLz0CDfwNi0mxKVECj1vJUPAvs+Lwunh/dcuUjwzc4MHM9D8JOYX0XUZMEPedpB3vIbOw==",
|
||||
"dependencies": {
|
||||
"@ucast/mongo2js": "^1.3.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/stalniy/casl/blob/master/BACKERS.md"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/aix-ppc64": {
|
||||
"version": "0.19.11",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.11.tgz",
|
||||
@@ -414,6 +428,12 @@
|
||||
"integrity": "sha512-Ox77gCSx0YyeakGt/qfOZUSFNSSi+sh3ABoGOiCwiO2KODx492BJnUm9oIXS+AHJtqp12iM4RduY6viTJ9bYwA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/uuid": {
|
||||
"version": "9.0.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.7.tgz",
|
||||
"integrity": "sha512-WUtIVRUZ9i5dYXefDEAI7sh9/O7jGvHg7Df/5O/gtH3Yabe5odI3UWopVR1qbPXQtvOxWu3mM4XxlYeZtMWF4g==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/webidl-conversions": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz",
|
||||
@@ -428,6 +448,37 @@
|
||||
"@types/webidl-conversions": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@ucast/core": {
|
||||
"version": "1.10.2",
|
||||
"resolved": "https://registry.npmjs.org/@ucast/core/-/core-1.10.2.tgz",
|
||||
"integrity": "sha512-ons5CwXZ/51wrUPfoduC+cO7AS1/wRb0ybpQJ9RrssossDxVy4t49QxWoWgfBDvVKsz9VXzBk9z0wqTdZ+Cq8g=="
|
||||
},
|
||||
"node_modules/@ucast/js": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@ucast/js/-/js-3.0.3.tgz",
|
||||
"integrity": "sha512-jBBqt57T5WagkAjqfCIIE5UYVdaXYgGkOFYv2+kjq2AVpZ2RIbwCo/TujJpDlwTVluUI+WpnRpoGU2tSGlEvFQ==",
|
||||
"dependencies": {
|
||||
"@ucast/core": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@ucast/mongo": {
|
||||
"version": "2.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@ucast/mongo/-/mongo-2.4.3.tgz",
|
||||
"integrity": "sha512-XcI8LclrHWP83H+7H2anGCEeDq0n+12FU2mXCTz6/Tva9/9ddK/iacvvhCyW6cijAAOILmt0tWplRyRhVyZLsA==",
|
||||
"dependencies": {
|
||||
"@ucast/core": "^1.4.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@ucast/mongo2js": {
|
||||
"version": "1.3.4",
|
||||
"resolved": "https://registry.npmjs.org/@ucast/mongo2js/-/mongo2js-1.3.4.tgz",
|
||||
"integrity": "sha512-ahazOr1HtelA5AC1KZ9x0UwPMqqimvfmtSm/PRRSeKKeE5G2SCqTgwiNzO7i9jS8zA3dzXpKVPpXMkcYLnyItA==",
|
||||
"dependencies": {
|
||||
"@ucast/core": "^1.6.1",
|
||||
"@ucast/js": "^3.0.0",
|
||||
"@ucast/mongo": "^2.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/abstract-level": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/abstract-level/-/abstract-level-1.0.3.tgz",
|
||||
@@ -1325,6 +1376,18 @@
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
|
||||
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="
|
||||
},
|
||||
"node_modules/uuid": {
|
||||
"version": "9.0.1",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
|
||||
"integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
|
||||
"funding": [
|
||||
"https://github.com/sponsors/broofa",
|
||||
"https://github.com/sponsors/ctavan"
|
||||
],
|
||||
"bin": {
|
||||
"uuid": "dist/bin/uuid"
|
||||
}
|
||||
},
|
||||
"node_modules/webidl-conversions": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
|
||||
|
||||
@@ -4,23 +4,27 @@
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"migration": "tsx src/index.ts"
|
||||
"migration": "tsx src/index.ts",
|
||||
"rollback": "tsx src/rollback.ts"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.11.0",
|
||||
"@types/prompt-sync": "^4.2.3",
|
||||
"@types/uuid": "^9.0.7",
|
||||
"tsx": "^4.7.0",
|
||||
"typescript": "^5.3.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@casl/ability": "^6.5.0",
|
||||
"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",
|
||||
"uuid": "^9.0.1",
|
||||
"zod": "^3.22.4"
|
||||
}
|
||||
}
|
||||
|
||||
33
pg-migrator/src/folder.ts
Normal file
33
pg-migrator/src/folder.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import { TFolderSchema } from "./models";
|
||||
|
||||
export const folderBfsTraversal = async (
|
||||
root: TFolderSchema,
|
||||
callback: (
|
||||
data: TFolderSchema & { parentId: string | null },
|
||||
) => void | Promise<void>,
|
||||
) => {
|
||||
const queue = [root];
|
||||
while (queue.length) {
|
||||
const folder = queue.pop() as TFolderSchema & { parentId: null };
|
||||
callback(folder);
|
||||
queue.push(
|
||||
...folder.children.map((el) => ({
|
||||
...el,
|
||||
parentId: folder.id,
|
||||
})),
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export const flattenFolders = (folders: TFolderSchema) => {
|
||||
const flattened: {
|
||||
id: string;
|
||||
parentId: string | null;
|
||||
name: string;
|
||||
version: number;
|
||||
}[] = [];
|
||||
folderBfsTraversal(folders, ({ name, version, parentId, id }) => {
|
||||
flattened.push({ name, version, parentId, id });
|
||||
});
|
||||
return flattened;
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,16 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { SecretEncryptionAlgo, SecretKeyEncoding, SecretType, TableName } from "../schemas";
|
||||
import { createJunctionTable, createOnUpdateTrigger, dropOnUpdateTrigger } from "../utils";
|
||||
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))) {
|
||||
@@ -10,10 +19,15 @@ export async function up(knex: Knex): Promise<void> {
|
||||
t.text("encryptedSaltCipherText").notNullable();
|
||||
t.text("saltIV").notNullable();
|
||||
t.text("saltTag").notNullable();
|
||||
t.string("algorithm").notNullable().defaultTo(SecretEncryptionAlgo.AES_256_GCM);
|
||||
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.foreign("projectId")
|
||||
.references("id")
|
||||
.inTable(TableName.Project)
|
||||
.onDelete("CASCADE");
|
||||
t.timestamps(true, true, true);
|
||||
});
|
||||
}
|
||||
@@ -27,7 +41,8 @@ export async function up(knex: Knex): Promise<void> {
|
||||
// t.text("secretKeyHash").notNullable();
|
||||
// t.text("secretValueHash");
|
||||
// t.text("secretCommentHash");
|
||||
t.text("secretBlindIndex").notNullable();
|
||||
// this is required but for backward compatiability we are making it nullable
|
||||
t.text("secretBlindIndex");
|
||||
t.text("secretKeyCiphertext").notNullable();
|
||||
t.text("secretKeyIV").notNullable();
|
||||
t.text("secretKeyTag").notNullable();
|
||||
@@ -40,19 +55,32 @@ export async function up(knex: Knex): Promise<void> {
|
||||
t.string("secretReminderNote");
|
||||
t.integer("secretReminderRepeatDays");
|
||||
t.boolean("skipMultilineEncoding").defaultTo(false);
|
||||
t.string("algorithm").notNullable().defaultTo(SecretEncryptionAlgo.AES_256_GCM);
|
||||
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.foreign("userId")
|
||||
.references("id")
|
||||
.inTable(TableName.Users)
|
||||
.onDelete("CASCADE");
|
||||
t.uuid("folderId").notNullable();
|
||||
t.foreign("folderId").references("id").inTable(TableName.SecretFolder).onDelete("CASCADE");
|
||||
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);
|
||||
await createJunctionTable(
|
||||
knex,
|
||||
TableName.JnSecretTag,
|
||||
TableName.Secret,
|
||||
TableName.SecretTag,
|
||||
);
|
||||
}
|
||||
|
||||
export async function down(knex: Knex): Promise<void> {
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { SecretEncryptionAlgo, SecretKeyEncoding, SecretType, TableName } from "../schemas";
|
||||
import { createJunctionTable, createOnUpdateTrigger, dropOnUpdateTrigger } from "../utils";
|
||||
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))) {
|
||||
@@ -9,7 +18,7 @@ export async function up(knex: Knex): Promise<void> {
|
||||
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("secretBlindIndex");
|
||||
t.text("secretKeyCiphertext").notNullable();
|
||||
t.text("secretKeyIV").notNullable();
|
||||
t.text("secretKeyTag").notNullable();
|
||||
@@ -22,17 +31,25 @@ export async function up(knex: Knex): Promise<void> {
|
||||
t.string("secretReminderNote");
|
||||
t.integer("secretReminderRepeatDays");
|
||||
t.boolean("skipMultilineEncoding").defaultTo(false);
|
||||
t.string("algorithm").notNullable().defaultTo(SecretEncryptionAlgo.AES_256_GCM);
|
||||
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.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.foreign("userId")
|
||||
.references("id")
|
||||
.inTable(TableName.Users)
|
||||
.onDelete("CASCADE");
|
||||
t.timestamps(true, true, true);
|
||||
});
|
||||
}
|
||||
@@ -42,7 +59,7 @@ export async function up(knex: Knex): Promise<void> {
|
||||
knex,
|
||||
TableName.JnSecretVersionTag,
|
||||
TableName.SecretVersion,
|
||||
TableName.SecretTag
|
||||
TableName.SecretTag,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@ 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();
|
||||
@@ -21,7 +20,10 @@ export async function up(knex: Knex): Promise<void> {
|
||||
.inTable(TableName.IdentityUaClientSecret)
|
||||
.onDelete("CASCADE");
|
||||
t.uuid("identityId").notNullable();
|
||||
t.foreign("identityId").references("id").inTable(TableName.Identity).onDelete("CASCADE");
|
||||
t.foreign("identityId")
|
||||
.references("id")
|
||||
.inTable(TableName.Identity)
|
||||
.onDelete("CASCADE");
|
||||
t.timestamps(true, true, true);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ const apiKeyDataSchema = new Schema<IAPIKeyData>(
|
||||
secretHash: {
|
||||
type: String,
|
||||
required: true,
|
||||
select: false,
|
||||
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1,74 +1,67 @@
|
||||
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;
|
||||
_id: Types.ObjectId;
|
||||
user: Types.ObjectId;
|
||||
encryptedPrivateKey: string;
|
||||
iv: string;
|
||||
tag: string;
|
||||
salt: string;
|
||||
algorithm: string;
|
||||
keyEncoding: "base64" | "utf8";
|
||||
verifier: string;
|
||||
createdAt: string;
|
||||
updatedAt: 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,
|
||||
}
|
||||
{
|
||||
user: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "User",
|
||||
required: true,
|
||||
},
|
||||
encryptedPrivateKey: {
|
||||
type: String,
|
||||
|
||||
required: true,
|
||||
},
|
||||
iv: {
|
||||
type: String,
|
||||
|
||||
required: true,
|
||||
},
|
||||
tag: {
|
||||
type: String,
|
||||
|
||||
required: true,
|
||||
},
|
||||
algorithm: {
|
||||
// the encryption algorithm used
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
keyEncoding: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
salt: {
|
||||
type: String,
|
||||
|
||||
required: true,
|
||||
},
|
||||
verifier: {
|
||||
type: String,
|
||||
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamps: true,
|
||||
},
|
||||
);
|
||||
|
||||
export const BackupPrivateKey = model<IBackupPrivateKey>(
|
||||
"BackupPrivateKey",
|
||||
backupPrivateKeySchema
|
||||
"BackupPrivateKey",
|
||||
backupPrivateKeySchema,
|
||||
);
|
||||
|
||||
@@ -1,77 +1,68 @@
|
||||
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";
|
||||
_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,
|
||||
}
|
||||
{
|
||||
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,
|
||||
|
||||
},
|
||||
iv: {
|
||||
type: String,
|
||||
required: true,
|
||||
|
||||
},
|
||||
tag: {
|
||||
type: String,
|
||||
required: true,
|
||||
|
||||
},
|
||||
algorithm: {
|
||||
// the encryption algorithm used
|
||||
type: String,
|
||||
required: true,
|
||||
|
||||
},
|
||||
keyEncoding: {
|
||||
type: String,
|
||||
required: true,
|
||||
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamps: true,
|
||||
},
|
||||
);
|
||||
|
||||
export const Bot = model<IBot>("Bot", botSchema);
|
||||
export const Bot = model<IBot>("Bot", botSchema);
|
||||
|
||||
@@ -1,96 +1,81 @@
|
||||
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";
|
||||
_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,
|
||||
}
|
||||
{
|
||||
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,
|
||||
required: true,
|
||||
},
|
||||
symmetricKeyKeyEncoding: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
encryptedPrivateKey: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
privateKeyIV: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
privateKeyTag: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
privateKeyAlgorithm: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
privateKeyKeyEncoding: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamps: true,
|
||||
},
|
||||
);
|
||||
|
||||
export const BotOrg = model<IBotOrg>("BotOrg", botOrgSchema);
|
||||
export const BotOrg = model<IBotOrg>("BotOrg", botOrgSchema);
|
||||
|
||||
@@ -1,104 +1,100 @@
|
||||
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;
|
||||
_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
|
||||
},
|
||||
{
|
||||
identity: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Identity",
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
timestamps: true
|
||||
}
|
||||
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,
|
||||
required: true,
|
||||
},
|
||||
prefix: {
|
||||
type: Number,
|
||||
required: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
default: [],
|
||||
required: true,
|
||||
},
|
||||
isAccessTokenRevoked: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamps: true,
|
||||
},
|
||||
);
|
||||
|
||||
export const IdentityAccessToken = model<IIdentityAccessToken>("IdentityAccessToken", identityAccessTokenSchema);
|
||||
export const IdentityAccessToken = model<IIdentityAccessToken>(
|
||||
"IdentityAccessToken",
|
||||
identityAccessTokenSchema,
|
||||
);
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { Schema, Types, model } from "mongoose";
|
||||
import { ADMIN, CUSTOM, MEMBER, NO_ACCESS, VIEWER } from "../variables";
|
||||
|
||||
export interface IIdentityMembership {
|
||||
_id: Types.ObjectId;
|
||||
@@ -13,7 +12,7 @@ const identityMembershipSchema = new Schema<IIdentityMembership>(
|
||||
{
|
||||
identity: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Identity"
|
||||
ref: "Identity",
|
||||
},
|
||||
workspace: {
|
||||
type: Schema.Types.ObjectId,
|
||||
@@ -23,17 +22,19 @@ const identityMembershipSchema = new Schema<IIdentityMembership>(
|
||||
},
|
||||
role: {
|
||||
type: String,
|
||||
enum: [ADMIN, MEMBER, VIEWER, CUSTOM, NO_ACCESS],
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
customRole: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Role"
|
||||
}
|
||||
ref: "Role",
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamps: true
|
||||
}
|
||||
timestamps: true,
|
||||
},
|
||||
);
|
||||
|
||||
export const IdentityMembership = model<IIdentityMembership>("IdentityMembership", identityMembershipSchema);
|
||||
export const IdentityMembership = model<IIdentityMembership>(
|
||||
"IdentityMembership",
|
||||
identityMembershipSchema,
|
||||
);
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { Schema, Types, model } from "mongoose";
|
||||
import { ADMIN, CUSTOM, MEMBER, NO_ACCESS} from "../variables";
|
||||
|
||||
export interface IIdentityMembershipOrg {
|
||||
_id: Types.ObjectId;
|
||||
@@ -13,25 +12,27 @@ const identityMembershipOrgSchema = new Schema<IIdentityMembershipOrg>(
|
||||
{
|
||||
identity: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Identity"
|
||||
ref: "Identity",
|
||||
},
|
||||
organization: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Organization"
|
||||
ref: "Organization",
|
||||
},
|
||||
role: {
|
||||
type: String,
|
||||
enum: [ADMIN, MEMBER, NO_ACCESS, CUSTOM],
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
customRole: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Role"
|
||||
}
|
||||
ref: "Role",
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamps: true
|
||||
}
|
||||
timestamps: true,
|
||||
},
|
||||
);
|
||||
|
||||
export const IdentityMembershipOrg = model<IIdentityMembershipOrg>("IdentityMembershipOrg", identityMembershipOrgSchema);
|
||||
export const IdentityMembershipOrg = model<IIdentityMembershipOrg>(
|
||||
"IdentityMembershipOrg",
|
||||
identityMembershipOrgSchema,
|
||||
);
|
||||
|
||||
@@ -1,107 +1,99 @@
|
||||
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>;
|
||||
_id: Types.ObjectId;
|
||||
identity: Types.ObjectId;
|
||||
clientId: string;
|
||||
clientSecretTrustedIps: Array<{}>;
|
||||
accessTokenTTL: number;
|
||||
accessTokenMaxTTL: number;
|
||||
accessTokenNumUsesLimit: number;
|
||||
accessTokenTrustedIps: Array<{}>;
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
{
|
||||
identity: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Identity",
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
timestamps: true
|
||||
}
|
||||
clientId: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
clientSecretTrustedIps: {
|
||||
type: [
|
||||
{
|
||||
ipAddress: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
prefix: {
|
||||
type: Number,
|
||||
required: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
default: [
|
||||
{
|
||||
ipAddress: "0.0.0.0",
|
||||
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,
|
||||
required: true,
|
||||
},
|
||||
prefix: {
|
||||
type: Number,
|
||||
required: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
default: [],
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamps: true,
|
||||
},
|
||||
);
|
||||
|
||||
export const IdentityUniversalAuth = model<IIdentityUniversalAuth>("IdentityUniversalAuth", identityUniversalAuthSchema);
|
||||
export const IdentityUniversalAuth = model<IIdentityUniversalAuth>(
|
||||
"IdentityUniversalAuth",
|
||||
identityUniversalAuthSchema,
|
||||
);
|
||||
|
||||
@@ -1,35 +1,3 @@
|
||||
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";
|
||||
|
||||
@@ -90,127 +58,98 @@ const integrationSchema = new Schema<IIntegration>(
|
||||
workspace: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Workspace",
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
environment: {
|
||||
type: String,
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
isActive: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
url: {
|
||||
// for custom self-hosted integrations (e.g. self-hosted GitHub enterprise)
|
||||
type: String,
|
||||
default: null
|
||||
default: null,
|
||||
},
|
||||
app: {
|
||||
// name of app in provider
|
||||
type: String,
|
||||
default: null
|
||||
default: null,
|
||||
},
|
||||
appId: {
|
||||
// id of app in provider
|
||||
type: String,
|
||||
default: null
|
||||
default: null,
|
||||
},
|
||||
targetEnvironment: {
|
||||
// target environment
|
||||
type: String,
|
||||
default: null
|
||||
default: null,
|
||||
},
|
||||
targetEnvironmentId: {
|
||||
type: String,
|
||||
default: null
|
||||
default: null,
|
||||
},
|
||||
targetService: {
|
||||
// railway-specific service
|
||||
// qovery-specific project
|
||||
type: String,
|
||||
default: null
|
||||
default: null,
|
||||
},
|
||||
targetServiceId: {
|
||||
// railway-specific service
|
||||
// qovery specific project
|
||||
type: String,
|
||||
default: null
|
||||
default: null,
|
||||
},
|
||||
owner: {
|
||||
// github-specific repo owner-login
|
||||
type: String,
|
||||
default: null
|
||||
default: null,
|
||||
},
|
||||
path: {
|
||||
// aws-parameter-store-specific path
|
||||
// (also) vercel preview-branch
|
||||
type: String,
|
||||
default: null
|
||||
default: null,
|
||||
},
|
||||
region: {
|
||||
// aws-parameter-store-specific path
|
||||
type: String,
|
||||
default: null
|
||||
default: null,
|
||||
},
|
||||
scope: {
|
||||
// qovery-specific scope
|
||||
type: String,
|
||||
default: null
|
||||
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
|
||||
required: true,
|
||||
},
|
||||
integrationAuth: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "IntegrationAuth",
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
secretPath: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: "/"
|
||||
default: "/",
|
||||
},
|
||||
metadata: {
|
||||
type: Schema.Types.Mixed,
|
||||
default: {}
|
||||
}
|
||||
default: {},
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamps: true
|
||||
}
|
||||
timestamps: true,
|
||||
},
|
||||
);
|
||||
|
||||
export const Integration = model<IIntegration>("Integration", integrationSchema);
|
||||
export const Integration = model<IIntegration>(
|
||||
"Integration",
|
||||
integrationSchema,
|
||||
);
|
||||
|
||||
@@ -1,36 +1,3 @@
|
||||
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";
|
||||
|
||||
@@ -91,116 +58,87 @@ const integrationAuthSchema = new Schema<IIntegrationAuth>(
|
||||
workspace: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Workspace",
|
||||
required: true
|
||||
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
|
||||
required: true,
|
||||
},
|
||||
teamId: {
|
||||
// vercel-specific integration param
|
||||
type: String
|
||||
type: String,
|
||||
},
|
||||
url: {
|
||||
// for any self-hosted integrations (e.g. self-hosted hashicorp-vault)
|
||||
type: String
|
||||
type: String,
|
||||
},
|
||||
namespace: {
|
||||
// hashicorp-vault-specific integration param
|
||||
type: String
|
||||
type: String,
|
||||
},
|
||||
accountId: {
|
||||
// netlify-specific integration param
|
||||
type: String
|
||||
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
|
||||
required: true,
|
||||
},
|
||||
keyEncoding: {
|
||||
type: String,
|
||||
enum: [ENCODING_SCHEME_UTF8, ENCODING_SCHEME_BASE64],
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
metadata: {
|
||||
type: Schema.Types.Mixed
|
||||
}
|
||||
type: Schema.Types.Mixed,
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamps: true
|
||||
}
|
||||
timestamps: true,
|
||||
},
|
||||
);
|
||||
|
||||
export const IntegrationAuth = model<IIntegrationAuth>("IntegrationAuth", integrationAuthSchema);
|
||||
export const IntegrationAuth = model<IIntegrationAuth>(
|
||||
"IntegrationAuth",
|
||||
integrationAuthSchema,
|
||||
);
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { Schema, Types, model } from "mongoose";
|
||||
import { ADMIN, CUSTOM, MEMBER, NO_ACCESS, VIEWER } from "../variables";
|
||||
|
||||
export interface IMembershipPermission {
|
||||
environmentSlug: string;
|
||||
@@ -20,15 +19,15 @@ const membershipSchema = new Schema<IMembership>(
|
||||
{
|
||||
user: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "User"
|
||||
ref: "User",
|
||||
},
|
||||
inviteEmail: {
|
||||
type: String
|
||||
type: String,
|
||||
},
|
||||
workspace: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Workspace",
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
deniedPermissions: {
|
||||
type: [
|
||||
@@ -36,25 +35,24 @@ const membershipSchema = new Schema<IMembership>(
|
||||
environmentSlug: String,
|
||||
ability: {
|
||||
type: String,
|
||||
enum: ["read", "write"]
|
||||
}
|
||||
}
|
||||
enum: ["read", "write"],
|
||||
},
|
||||
},
|
||||
],
|
||||
default: []
|
||||
default: [],
|
||||
},
|
||||
role: {
|
||||
type: String,
|
||||
enum: [ADMIN, MEMBER, VIEWER, NO_ACCESS, CUSTOM],
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
customRole: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Role"
|
||||
}
|
||||
ref: "Role",
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamps: true
|
||||
}
|
||||
timestamps: true,
|
||||
},
|
||||
);
|
||||
|
||||
export const Membership = model<IMembership>("Membership", membershipSchema);
|
||||
export const Membership = model<IMembership>("Membership", membershipSchema);
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
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;
|
||||
@@ -9,39 +8,42 @@ export interface IMembershipOrg extends Document {
|
||||
role: "admin" | "member" | "no-access" | "custom";
|
||||
customRole: Types.ObjectId;
|
||||
status: "invited" | "accepted";
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
const membershipOrgSchema = new Schema(
|
||||
{
|
||||
user: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "User"
|
||||
ref: "User",
|
||||
},
|
||||
inviteEmail: {
|
||||
type: String
|
||||
type: String,
|
||||
},
|
||||
organization: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Organization"
|
||||
ref: "Organization",
|
||||
},
|
||||
role: {
|
||||
type: String,
|
||||
enum: [ADMIN, MEMBER, NO_ACCESS, CUSTOM],
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
status: {
|
||||
type: String,
|
||||
enum: [INVITED, ACCEPTED],
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
customRole: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Role"
|
||||
}
|
||||
ref: "Role",
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamps: true
|
||||
}
|
||||
timestamps: true,
|
||||
},
|
||||
);
|
||||
|
||||
export const MembershipOrg = model<IMembershipOrg>("MembershipOrg", membershipOrgSchema);
|
||||
export const MembershipOrg = model<IMembershipOrg>(
|
||||
"MembershipOrg",
|
||||
membershipOrgSchema,
|
||||
);
|
||||
|
||||
@@ -1,24 +1,29 @@
|
||||
import { Schema, Types, model } from "mongoose";
|
||||
|
||||
export interface IOrganization {
|
||||
_id: Types.ObjectId;
|
||||
name: string;
|
||||
customerId?: string;
|
||||
_id: Types.ObjectId;
|
||||
name: string;
|
||||
customerId?: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
const organizationSchema = new Schema<IOrganization>(
|
||||
{
|
||||
name: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
customerId: {
|
||||
type: String,
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamps: true,
|
||||
}
|
||||
{
|
||||
name: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
customerId: {
|
||||
type: String,
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamps: true,
|
||||
},
|
||||
);
|
||||
|
||||
export const Organization = model<IOrganization>("Organization", organizationSchema);
|
||||
export const Organization = model<IOrganization>(
|
||||
"Organization",
|
||||
organizationSchema,
|
||||
);
|
||||
|
||||
@@ -9,45 +9,47 @@ export interface IRole {
|
||||
workspace: Types.ObjectId;
|
||||
organization: Types.ObjectId;
|
||||
isOrgRole: boolean;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
const roleSchema = new Schema<IRole>(
|
||||
{
|
||||
name: {
|
||||
type: String,
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
organization: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Organization",
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
workspace: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Workspace"
|
||||
ref: "Workspace",
|
||||
},
|
||||
isOrgRole: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
select: false
|
||||
|
||||
},
|
||||
description: {
|
||||
type: String
|
||||
type: String,
|
||||
},
|
||||
slug: {
|
||||
type: String,
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
permissions: {
|
||||
type: Array,
|
||||
required: true
|
||||
}
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamps: true
|
||||
}
|
||||
timestamps: true,
|
||||
},
|
||||
);
|
||||
|
||||
roleSchema.index({ organization: 1, workspace: 1 });
|
||||
|
||||
export const Role = model<IRole>("Role", roleSchema);
|
||||
export const Role = model<IRole>("Role", roleSchema);
|
||||
|
||||
@@ -1,11 +1,4 @@
|
||||
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;
|
||||
@@ -48,123 +41,118 @@ const secretSchema = new Schema<ISecret>(
|
||||
version: {
|
||||
type: Number,
|
||||
required: true,
|
||||
default: 1
|
||||
default: 1,
|
||||
},
|
||||
workspace: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Workspace",
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
enum: [SECRET_SHARED, SECRET_PERSONAL],
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
user: {
|
||||
// user associated with the personal secret
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "User"
|
||||
ref: "User",
|
||||
},
|
||||
tags: {
|
||||
ref: "Tag",
|
||||
type: [Schema.Types.ObjectId],
|
||||
default: []
|
||||
default: [],
|
||||
},
|
||||
environment: {
|
||||
type: String,
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
secretBlindIndex: {
|
||||
type: String,
|
||||
select: false
|
||||
|
||||
},
|
||||
secretKeyCiphertext: {
|
||||
type: String,
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
secretKeyIV: {
|
||||
type: String, // symmetric
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
secretKeyTag: {
|
||||
type: String, // symmetric
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
secretKeyHash: {
|
||||
type: String
|
||||
type: String,
|
||||
},
|
||||
secretValueCiphertext: {
|
||||
type: String,
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
secretValueIV: {
|
||||
type: String, // symmetric
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
secretValueTag: {
|
||||
type: String, // symmetric
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
secretValueHash: {
|
||||
type: String
|
||||
type: String,
|
||||
},
|
||||
secretCommentCiphertext: {
|
||||
type: String,
|
||||
required: false
|
||||
required: false,
|
||||
},
|
||||
secretCommentIV: {
|
||||
type: String, // symmetric
|
||||
required: false
|
||||
required: false,
|
||||
},
|
||||
secretCommentTag: {
|
||||
type: String, // symmetric
|
||||
required: false
|
||||
required: false,
|
||||
},
|
||||
secretCommentHash: {
|
||||
type: String,
|
||||
required: false
|
||||
required: false,
|
||||
},
|
||||
|
||||
secretReminderRepeatDays: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: null
|
||||
default: null,
|
||||
},
|
||||
secretReminderNote: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: null
|
||||
default: null,
|
||||
},
|
||||
|
||||
skipMultilineEncoding: {
|
||||
type: Boolean,
|
||||
required: false
|
||||
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"
|
||||
default: "root",
|
||||
},
|
||||
metadata: {
|
||||
type: Schema.Types.Mixed
|
||||
}
|
||||
type: Schema.Types.Mixed,
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamps: true
|
||||
}
|
||||
timestamps: true,
|
||||
},
|
||||
);
|
||||
|
||||
secretSchema.index({ tags: 1 }, { background: true });
|
||||
|
||||
@@ -1,26 +1,17 @@
|
||||
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"
|
||||
REJECTED = "rejected",
|
||||
}
|
||||
|
||||
export enum CommitType {
|
||||
DELETE = "delete",
|
||||
UPDATE = "update",
|
||||
CREATE = "create"
|
||||
CREATE = "create",
|
||||
}
|
||||
|
||||
const SLUG_ALPHABETS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
const nanoId = customAlphabet(SLUG_ALPHABETS, 10);
|
||||
|
||||
export interface ISecretApprovalSecChange {
|
||||
_id: Types.ObjectId;
|
||||
version: number;
|
||||
@@ -50,7 +41,9 @@ export type ISecretCommits<T = Types.ObjectId, J = Types.ObjectId> = Array<
|
||||
// on merge
|
||||
secretVersion: J;
|
||||
secret: T;
|
||||
newVersion: Partial<Omit<ISecretApprovalSecChange, "_id">> & { _id: Types.ObjectId };
|
||||
newVersion: Partial<Omit<ISecretApprovalSecChange, "_id">> & {
|
||||
_id: Types.ObjectId;
|
||||
};
|
||||
op: CommitType.UPDATE;
|
||||
}
|
||||
| {
|
||||
@@ -82,58 +75,54 @@ const secretApprovalSecretChangeSchema = new Schema<ISecretApprovalSecChange>({
|
||||
version: {
|
||||
type: Number,
|
||||
default: 1,
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
secretBlindIndex: {
|
||||
type: String,
|
||||
select: false
|
||||
|
||||
},
|
||||
secretKeyCiphertext: {
|
||||
type: String,
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
secretKeyIV: {
|
||||
type: String, // symmetric
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
secretKeyTag: {
|
||||
type: String, // symmetric
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
secretValueCiphertext: {
|
||||
type: String,
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
secretValueIV: {
|
||||
type: String, // symmetric
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
secretValueTag: {
|
||||
type: String, // symmetric
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
skipMultilineEncoding: {
|
||||
type: Boolean,
|
||||
required: false
|
||||
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: []
|
||||
}
|
||||
default: [],
|
||||
},
|
||||
});
|
||||
|
||||
const secretApprovalRequestSchema = new Schema<ISecretApprovalRequest>(
|
||||
@@ -141,20 +130,19 @@ const secretApprovalRequestSchema = new Schema<ISecretApprovalRequest>(
|
||||
workspace: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Workspace",
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
environment: {
|
||||
type: String,
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
folderId: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: "root"
|
||||
default: "root",
|
||||
},
|
||||
slug: {
|
||||
type: String,
|
||||
default: () => nanoId()
|
||||
},
|
||||
reviewers: {
|
||||
type: [
|
||||
@@ -162,12 +150,16 @@ const secretApprovalRequestSchema = new Schema<ISecretApprovalRequest>(
|
||||
member: {
|
||||
// user associated with the personal secret
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Membership"
|
||||
ref: "Membership",
|
||||
},
|
||||
status: { type: String, enum: ApprovalStatus, default: ApprovalStatus.PENDING }
|
||||
}
|
||||
status: {
|
||||
type: String,
|
||||
enum: ApprovalStatus,
|
||||
default: ApprovalStatus.PENDING,
|
||||
},
|
||||
},
|
||||
],
|
||||
default: []
|
||||
default: [],
|
||||
},
|
||||
policy: { type: Schema.Types.ObjectId, ref: "SecretApprovalPolicy" },
|
||||
hasMerged: { type: Boolean, default: false },
|
||||
@@ -179,25 +171,25 @@ const secretApprovalRequestSchema = new Schema<ISecretApprovalRequest>(
|
||||
secret: { type: Types.ObjectId, ref: "Secret" },
|
||||
newVersion: secretApprovalSecretChangeSchema,
|
||||
secretVersion: { type: Types.ObjectId, ref: "SecretVersion" },
|
||||
op: { type: String, enum: [CommitType], required: true }
|
||||
}
|
||||
op: { type: String, enum: [CommitType], required: true },
|
||||
},
|
||||
],
|
||||
conflicts: {
|
||||
type: [
|
||||
{
|
||||
secretId: { type: String, required: true },
|
||||
op: { type: String, enum: [CommitType], required: true }
|
||||
}
|
||||
op: { type: String, enum: [CommitType], required: true },
|
||||
},
|
||||
],
|
||||
default: []
|
||||
}
|
||||
default: [],
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamps: true
|
||||
}
|
||||
timestamps: true,
|
||||
},
|
||||
);
|
||||
|
||||
export const SecretApprovalRequest = model<ISecretApprovalRequest>(
|
||||
"SecretApprovalRequest",
|
||||
secretApprovalRequestSchema
|
||||
secretApprovalRequestSchema,
|
||||
);
|
||||
|
||||
@@ -1,58 +1,49 @@
|
||||
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"
|
||||
_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,
|
||||
},
|
||||
|
||||
}
|
||||
);
|
||||
const secretBlindIndexDataSchema = new Schema<ISecretBlindIndexData>({
|
||||
workspace: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Workspace",
|
||||
required: true,
|
||||
},
|
||||
encryptedSaltCiphertext: {
|
||||
// TODO: make these
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
saltIV: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
saltTag: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
algorithm: {
|
||||
type: String,
|
||||
required: true,
|
||||
|
||||
},
|
||||
keyEncoding: {
|
||||
type: String,
|
||||
required: true,
|
||||
|
||||
},
|
||||
});
|
||||
|
||||
secretBlindIndexDataSchema.index({ workspace: 1 });
|
||||
|
||||
export const SecretBlindIndexData = model<ISecretBlindIndexData>("SecretBlindIndexData", secretBlindIndexDataSchema);
|
||||
export const SecretBlindIndexData = model<ISecretBlindIndexData>(
|
||||
"SecretBlindIndexData",
|
||||
secretBlindIndexDataSchema,
|
||||
);
|
||||
|
||||
106
pg-migrator/src/models/secretRotation.ts
Normal file
106
pg-migrator/src/models/secretRotation.ts
Normal file
@@ -0,0 +1,106 @@
|
||||
import { Document, Schema, model, Types } from "mongoose";
|
||||
|
||||
export interface ISecretRotation extends Document {
|
||||
_id: Types.ObjectId;
|
||||
name: string;
|
||||
interval: number;
|
||||
provider: string;
|
||||
customProvider: Types.ObjectId;
|
||||
workspace: Types.ObjectId;
|
||||
environment: string;
|
||||
secretPath: string;
|
||||
outputs: Array<{
|
||||
key: string;
|
||||
secret: Types.ObjectId;
|
||||
}>;
|
||||
status?: "success" | "failed";
|
||||
lastRotatedAt?: string;
|
||||
statusMessage?: string;
|
||||
encryptedData: string;
|
||||
encryptedDataIV: string;
|
||||
encryptedDataTag: string;
|
||||
algorithm: string;
|
||||
keyEncoding: string;
|
||||
}
|
||||
const secretRotationSchema = new Schema(
|
||||
{
|
||||
workspace: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Workspace",
|
||||
},
|
||||
provider: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
customProvider: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "SecretRotationProvider",
|
||||
},
|
||||
environment: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
secretPath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
interval: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
lastRotatedAt: {
|
||||
type: String,
|
||||
},
|
||||
status: {
|
||||
type: String,
|
||||
enum: ["success", "failed"],
|
||||
},
|
||||
statusMessage: {
|
||||
type: String,
|
||||
},
|
||||
// encrypted data on input keys and secrets got
|
||||
encryptedData: {
|
||||
type: String,
|
||||
select: false,
|
||||
},
|
||||
encryptedDataIV: {
|
||||
type: String,
|
||||
select: false,
|
||||
},
|
||||
encryptedDataTag: {
|
||||
type: String,
|
||||
select: false,
|
||||
},
|
||||
algorithm: {
|
||||
// the encryption algorithm used
|
||||
type: String,
|
||||
required: true,
|
||||
select: false,
|
||||
},
|
||||
keyEncoding: {
|
||||
type: String,
|
||||
required: true,
|
||||
select: false,
|
||||
},
|
||||
outputs: [
|
||||
{
|
||||
key: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
secret: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Secret",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
timestamps: true,
|
||||
},
|
||||
);
|
||||
|
||||
export const SecretRotation = model<ISecretRotation>(
|
||||
"SecretRotation",
|
||||
secretRotationSchema,
|
||||
);
|
||||
@@ -1,6 +1,8 @@
|
||||
import { Schema, Types, model } from "mongoose";
|
||||
|
||||
export interface ISecretSnapshot {
|
||||
id: string;
|
||||
_id: string;
|
||||
workspace: Types.ObjectId;
|
||||
environment: string;
|
||||
folderId: string | "root";
|
||||
@@ -43,10 +45,10 @@ const secretSnapshotSchema = new Schema<ISecretSnapshot>(
|
||||
},
|
||||
{
|
||||
timestamps: true,
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
export const SecretSnapshot = model<ISecretSnapshot>(
|
||||
"SecretSnapshot",
|
||||
secretSnapshotSchema
|
||||
);
|
||||
secretSnapshotSchema,
|
||||
);
|
||||
|
||||
@@ -1,11 +1,4 @@
|
||||
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;
|
||||
@@ -37,96 +30,94 @@ const secretVersionSchema = new Schema<ISecretVersion>(
|
||||
// could be deleted
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Secret",
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
version: {
|
||||
type: Number,
|
||||
default: 1,
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
workspace: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Workspace",
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
enum: [SECRET_SHARED, SECRET_PERSONAL],
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
user: {
|
||||
// user associated with the personal secret
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "User"
|
||||
ref: "User",
|
||||
},
|
||||
environment: {
|
||||
type: String,
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
isDeleted: {
|
||||
// consider removing field
|
||||
type: Boolean,
|
||||
default: false,
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
secretBlindIndex: {
|
||||
type: String,
|
||||
select: false
|
||||
|
||||
},
|
||||
secretKeyCiphertext: {
|
||||
type: String,
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
secretKeyIV: {
|
||||
type: String, // symmetric
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
secretKeyTag: {
|
||||
type: String, // symmetric
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
secretValueCiphertext: {
|
||||
type: String,
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
secretValueIV: {
|
||||
type: String, // symmetric
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
secretValueTag: {
|
||||
type: String, // symmetric
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
skipMultilineEncoding: {
|
||||
type: Boolean,
|
||||
required: false
|
||||
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
|
||||
required: true,
|
||||
},
|
||||
tags: {
|
||||
ref: "Tag",
|
||||
type: [Schema.Types.ObjectId],
|
||||
default: []
|
||||
}
|
||||
default: [],
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamps: true
|
||||
}
|
||||
timestamps: true,
|
||||
},
|
||||
);
|
||||
|
||||
export const SecretVersion = model<ISecretVersion>("SecretVersion", secretVersionSchema);
|
||||
export const SecretVersion = model<ISecretVersion>(
|
||||
"SecretVersion",
|
||||
secretVersionSchema,
|
||||
);
|
||||
|
||||
@@ -65,19 +65,19 @@ const serviceTokenDataSchema = new Schema<IServiceTokenData>(
|
||||
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],
|
||||
|
||||
@@ -35,7 +35,7 @@ const tokenDataSchema = new Schema<ITokenData>({
|
||||
},
|
||||
tokenHash: {
|
||||
type: String,
|
||||
select: false,
|
||||
|
||||
required: true,
|
||||
},
|
||||
triesLeft: {
|
||||
|
||||
@@ -7,7 +7,7 @@ export enum AuthMethod {
|
||||
GITLAB = "gitlab",
|
||||
OKTA_SAML = "okta-saml",
|
||||
AZURE_SAML = "azure-saml",
|
||||
JUMPCLOUD_SAML = "jumpcloud-saml"
|
||||
JUMPCLOUD_SAML = "jumpcloud-saml",
|
||||
}
|
||||
|
||||
export interface IUser extends Document {
|
||||
@@ -34,6 +34,8 @@ export interface IUser extends Document {
|
||||
ip: string;
|
||||
userAgent: string;
|
||||
}[];
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
const userSchema = new Schema<IUser>(
|
||||
@@ -41,101 +43,101 @@ const userSchema = new Schema<IUser>(
|
||||
authProvider: {
|
||||
// TODO field: deprecate
|
||||
type: String,
|
||||
enum: AuthMethod
|
||||
enum: AuthMethod,
|
||||
},
|
||||
authMethods: {
|
||||
type: [
|
||||
{
|
||||
type: String,
|
||||
enum: AuthMethod
|
||||
}
|
||||
enum: AuthMethod,
|
||||
},
|
||||
],
|
||||
default: [AuthMethod.EMAIL],
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
email: {
|
||||
type: String,
|
||||
required: true,
|
||||
unique: true
|
||||
unique: true,
|
||||
},
|
||||
firstName: {
|
||||
type: String
|
||||
type: String,
|
||||
},
|
||||
lastName: {
|
||||
type: String
|
||||
type: String,
|
||||
},
|
||||
encryptionVersion: {
|
||||
type: Number,
|
||||
select: false,
|
||||
default: 1 // to resolve backward-compatibility issues
|
||||
|
||||
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
|
||||
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
|
||||
default: false,
|
||||
},
|
||||
mfaMethods: [
|
||||
{
|
||||
type: String
|
||||
}
|
||||
type: String,
|
||||
},
|
||||
],
|
||||
devices: {
|
||||
type: [
|
||||
{
|
||||
ip: String,
|
||||
userAgent: String
|
||||
}
|
||||
userAgent: String,
|
||||
},
|
||||
],
|
||||
default: [],
|
||||
select: false
|
||||
}
|
||||
|
||||
},
|
||||
},
|
||||
{
|
||||
timestamps: true
|
||||
}
|
||||
timestamps: true,
|
||||
},
|
||||
);
|
||||
|
||||
export const User = model<IUser>("User", userSchema);
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
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;
|
||||
@@ -22,60 +21,58 @@ const WebhookSchema = new Schema<IWebhook>(
|
||||
workspace: {
|
||||
type: Schema.Types.ObjectId,
|
||||
ref: "Workspace",
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
environment: {
|
||||
type: String,
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
secretPath: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: "/"
|
||||
default: "/",
|
||||
},
|
||||
url: {
|
||||
type: String,
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
lastStatus: {
|
||||
type: String,
|
||||
enum: ["success", "failed"]
|
||||
enum: ["success", "failed"],
|
||||
},
|
||||
lastRunErrorMessage: {
|
||||
type: String
|
||||
type: String,
|
||||
},
|
||||
isDisabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
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
|
||||
}
|
||||
timestamps: true,
|
||||
},
|
||||
);
|
||||
|
||||
export const Webhook = model<IWebhook>("Webhook", WebhookSchema);
|
||||
|
||||
29
pg-migrator/src/rollback.ts
Normal file
29
pg-migrator/src/rollback.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import dotenv from "dotenv";
|
||||
import knex from "knex";
|
||||
import { Level } from "level";
|
||||
import path from "path";
|
||||
|
||||
const main = async () => {
|
||||
dotenv.config();
|
||||
let postgres_url = process.env.POSTGRES_DB_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("Good to go with postgres");
|
||||
const kdb = new Level<string, any>("./db", { valueEncoding: "json" });
|
||||
console.log("Starting rolling back to latest");
|
||||
await db.migrate.rollback({}, true);
|
||||
console.log("Rolling back completed");
|
||||
kdb.clear();
|
||||
process.exit(0);
|
||||
};
|
||||
|
||||
main();
|
||||
@@ -9,7 +9,6 @@ import { TImmutableDBKeys } from "./models";
|
||||
|
||||
export const IdentityAccessTokensSchema = z.object({
|
||||
id: z.string().uuid(),
|
||||
authType: z.string(),
|
||||
accessTokenTTL: z.number().default(2592000),
|
||||
accessTokenMaxTTL: z.number().default(2592000),
|
||||
accessTokenNumUses: z.number().default(0),
|
||||
@@ -24,5 +23,10 @@ export const IdentityAccessTokensSchema = z.object({
|
||||
});
|
||||
|
||||
export type TIdentityAccessTokens = z.infer<typeof IdentityAccessTokensSchema>;
|
||||
export type TIdentityAccessTokensInsert = Omit<TIdentityAccessTokens, TImmutableDBKeys>;
|
||||
export type TIdentityAccessTokensUpdate = Partial<Omit<TIdentityAccessTokens, TImmutableDBKeys>>;
|
||||
export type TIdentityAccessTokensInsert = Omit<
|
||||
TIdentityAccessTokens,
|
||||
TImmutableDBKeys
|
||||
>;
|
||||
export type TIdentityAccessTokensUpdate = Partial<
|
||||
Omit<TIdentityAccessTokens, TImmutableDBKeys>
|
||||
>;
|
||||
|
||||
@@ -10,8 +10,8 @@ import { TImmutableDBKeys } from "./models";
|
||||
export const SecretVersionsSchema = z.object({
|
||||
id: z.string().uuid(),
|
||||
version: z.number().default(1),
|
||||
type: z.string().default('shared'),
|
||||
secretBlindIndex: z.string(),
|
||||
type: z.string().default("shared"),
|
||||
secretBlindIndex: z.string().nullable().optional(),
|
||||
secretKeyCiphertext: z.string(),
|
||||
secretKeyIV: z.string(),
|
||||
secretKeyTag: z.string(),
|
||||
@@ -24,8 +24,8 @@ export const SecretVersionsSchema = z.object({
|
||||
secretReminderNote: z.string().nullable().optional(),
|
||||
secretReminderRepeatDays: z.number().nullable().optional(),
|
||||
skipMultilineEncoding: z.boolean().default(false).nullable().optional(),
|
||||
algorithm: z.string().default('aes-256-gcm'),
|
||||
keyEncoding: z.string().default('utf8'),
|
||||
algorithm: z.string().default("aes-256-gcm"),
|
||||
keyEncoding: z.string().default("utf8"),
|
||||
metadata: z.unknown().nullable().optional(),
|
||||
envId: z.string().uuid().nullable().optional(),
|
||||
secretId: z.string().uuid(),
|
||||
@@ -37,4 +37,6 @@ export const SecretVersionsSchema = z.object({
|
||||
|
||||
export type TSecretVersions = z.infer<typeof SecretVersionsSchema>;
|
||||
export type TSecretVersionsInsert = Omit<TSecretVersions, TImmutableDBKeys>;
|
||||
export type TSecretVersionsUpdate = Partial<Omit<TSecretVersions, TImmutableDBKeys>>;
|
||||
export type TSecretVersionsUpdate = Partial<
|
||||
Omit<TSecretVersions, TImmutableDBKeys>
|
||||
>;
|
||||
|
||||
@@ -10,8 +10,8 @@ import { TImmutableDBKeys } from "./models";
|
||||
export const SecretsSchema = z.object({
|
||||
id: z.string().uuid(),
|
||||
version: z.number().default(1),
|
||||
type: z.string().default('shared'),
|
||||
secretBlindIndex: z.string(),
|
||||
type: z.string().default("shared"),
|
||||
secretBlindIndex: z.string().nullable().optional(),
|
||||
secretKeyCiphertext: z.string(),
|
||||
secretKeyIV: z.string(),
|
||||
secretKeyTag: z.string(),
|
||||
@@ -24,8 +24,8 @@ export const SecretsSchema = z.object({
|
||||
secretReminderNote: z.string().nullable().optional(),
|
||||
secretReminderRepeatDays: z.number().nullable().optional(),
|
||||
skipMultilineEncoding: z.boolean().default(false).nullable().optional(),
|
||||
algorithm: z.string().default('aes-256-gcm'),
|
||||
keyEncoding: z.string().default('utf8'),
|
||||
algorithm: z.string().default("aes-256-gcm"),
|
||||
keyEncoding: z.string().default("utf8"),
|
||||
metadata: z.unknown().nullable().optional(),
|
||||
userId: z.string().uuid().nullable().optional(),
|
||||
folderId: z.string().uuid(),
|
||||
|
||||
45
pg-migrator/src/utils.ts
Normal file
45
pg-migrator/src/utils.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { TableName } from "./schemas";
|
||||
|
||||
export const createJunctionTable = (
|
||||
knex: Knex,
|
||||
tableName: TableName,
|
||||
table1Name: TableName,
|
||||
table2Name: TableName
|
||||
) =>
|
||||
knex.schema.createTable(tableName, (table) => {
|
||||
table.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||
table.uuid(`${table1Name}Id`).unsigned().notNullable(); // Foreign key for table1
|
||||
table.uuid(`${table2Name}Id`).unsigned().notNullable(); // Foreign key for table2
|
||||
table.foreign(`${table1Name}Id`).references("id").inTable(table1Name);
|
||||
table.foreign(`${table2Name}Id`).references("id").inTable(table2Name);
|
||||
});
|
||||
|
||||
// one time logic
|
||||
// this is a postgres function log to set updateAt to present time whenever row gets updated
|
||||
export const createUpdateAtTriggerFunction = (knex: Knex) =>
|
||||
knex.raw(`
|
||||
CREATE OR REPLACE FUNCTION on_update_timestamp() RETURNS TRIGGER AS $$ BEGIN NEW."updatedAt" = NOW();
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
`);
|
||||
|
||||
export const dropUpdatedAtTriggerFunction = (knex: Knex) =>
|
||||
knex.raw(`
|
||||
DROP FUNCTION IF EXISTS on_update_timestamp() CASCADE;
|
||||
`);
|
||||
|
||||
// we would be using this to apply updatedAt where ever we wanta
|
||||
// remember to set `timestamps(true,true,true)` before this on schema
|
||||
export const createOnUpdateTrigger = (knex: Knex, tableName: string) =>
|
||||
knex.raw(`
|
||||
CREATE TRIGGER "${tableName}_updatedAt"
|
||||
BEFORE UPDATE ON ${tableName}
|
||||
FOR EACH ROW
|
||||
EXECUTE PROCEDURE on_update_timestamp();
|
||||
`);
|
||||
|
||||
export const dropOnUpdateTrigger = (knex: Knex, tableName: string) =>
|
||||
knex.raw(`DROP TRIGGER IF EXISTS "${tableName}_updatedAt" ON ${tableName}`);
|
||||
Reference in New Issue
Block a user