mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-08 13:28:27 +00:00
feat(infisical-pg): completed first version of pg migrator
This commit is contained in:
Generated
+63
@@ -9,21 +9,35 @@
|
|||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@casl/ability": "^6.5.0",
|
||||||
"dotenv": "^16.3.1",
|
"dotenv": "^16.3.1",
|
||||||
"knex": "^3.1.0",
|
"knex": "^3.1.0",
|
||||||
"level": "^8.0.0",
|
"level": "^8.0.0",
|
||||||
"mongoose": "^8.0.4",
|
"mongoose": "^8.0.4",
|
||||||
"pg": "^8.11.3",
|
"pg": "^8.11.3",
|
||||||
"prompt-sync": "^4.2.0",
|
"prompt-sync": "^4.2.0",
|
||||||
|
"uuid": "^9.0.1",
|
||||||
"zod": "^3.22.4"
|
"zod": "^3.22.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^20.11.0",
|
"@types/node": "^20.11.0",
|
||||||
"@types/prompt-sync": "^4.2.3",
|
"@types/prompt-sync": "^4.2.3",
|
||||||
|
"@types/uuid": "^9.0.7",
|
||||||
"tsx": "^4.7.0",
|
"tsx": "^4.7.0",
|
||||||
"typescript": "^5.3.3"
|
"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": {
|
"node_modules/@esbuild/aix-ppc64": {
|
||||||
"version": "0.19.11",
|
"version": "0.19.11",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.11.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.11.tgz",
|
||||||
@@ -414,6 +428,12 @@
|
|||||||
"integrity": "sha512-Ox77gCSx0YyeakGt/qfOZUSFNSSi+sh3ABoGOiCwiO2KODx492BJnUm9oIXS+AHJtqp12iM4RduY6viTJ9bYwA==",
|
"integrity": "sha512-Ox77gCSx0YyeakGt/qfOZUSFNSSi+sh3ABoGOiCwiO2KODx492BJnUm9oIXS+AHJtqp12iM4RduY6viTJ9bYwA==",
|
||||||
"dev": true
|
"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": {
|
"node_modules/@types/webidl-conversions": {
|
||||||
"version": "7.0.3",
|
"version": "7.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz",
|
||||||
@@ -428,6 +448,37 @@
|
|||||||
"@types/webidl-conversions": "*"
|
"@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": {
|
"node_modules/abstract-level": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/abstract-level/-/abstract-level-1.0.3.tgz",
|
"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",
|
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
|
||||||
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="
|
"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": {
|
"node_modules/webidl-conversions": {
|
||||||
"version": "7.0.0",
|
"version": "7.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
|
||||||
|
|||||||
@@ -4,23 +4,27 @@
|
|||||||
"description": "",
|
"description": "",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"migration": "tsx src/index.ts"
|
"migration": "tsx src/index.ts",
|
||||||
|
"rollback": "tsx src/rollback.ts"
|
||||||
},
|
},
|
||||||
"author": "",
|
"author": "",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^20.11.0",
|
"@types/node": "^20.11.0",
|
||||||
"@types/prompt-sync": "^4.2.3",
|
"@types/prompt-sync": "^4.2.3",
|
||||||
|
"@types/uuid": "^9.0.7",
|
||||||
"tsx": "^4.7.0",
|
"tsx": "^4.7.0",
|
||||||
"typescript": "^5.3.3"
|
"typescript": "^5.3.3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@casl/ability": "^6.5.0",
|
||||||
"dotenv": "^16.3.1",
|
"dotenv": "^16.3.1",
|
||||||
"knex": "^3.1.0",
|
"knex": "^3.1.0",
|
||||||
"level": "^8.0.0",
|
"level": "^8.0.0",
|
||||||
"mongoose": "^8.0.4",
|
"mongoose": "^8.0.4",
|
||||||
"pg": "^8.11.3",
|
"pg": "^8.11.3",
|
||||||
"prompt-sync": "^4.2.0",
|
"prompt-sync": "^4.2.0",
|
||||||
|
"uuid": "^9.0.1",
|
||||||
"zod": "^3.22.4"
|
"zod": "^3.22.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
};
|
||||||
+1606
-29
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,16 @@
|
|||||||
import { Knex } from "knex";
|
import { Knex } from "knex";
|
||||||
|
|
||||||
import { SecretEncryptionAlgo, SecretKeyEncoding, SecretType, TableName } from "../schemas";
|
import {
|
||||||
import { createJunctionTable, createOnUpdateTrigger, dropOnUpdateTrigger } from "../utils";
|
SecretEncryptionAlgo,
|
||||||
|
SecretKeyEncoding,
|
||||||
|
SecretType,
|
||||||
|
TableName,
|
||||||
|
} from "../schemas";
|
||||||
|
import {
|
||||||
|
createJunctionTable,
|
||||||
|
createOnUpdateTrigger,
|
||||||
|
dropOnUpdateTrigger,
|
||||||
|
} from "../utils";
|
||||||
|
|
||||||
export async function up(knex: Knex): Promise<void> {
|
export async function up(knex: Knex): Promise<void> {
|
||||||
if (!(await knex.schema.hasTable(TableName.SecretBlindIndex))) {
|
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("encryptedSaltCipherText").notNullable();
|
||||||
t.text("saltIV").notNullable();
|
t.text("saltIV").notNullable();
|
||||||
t.text("saltTag").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("keyEncoding").notNullable().defaultTo(SecretKeyEncoding.UTF8);
|
||||||
t.string("projectId").notNullable().unique();
|
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);
|
t.timestamps(true, true, true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -27,7 +41,8 @@ export async function up(knex: Knex): Promise<void> {
|
|||||||
// t.text("secretKeyHash").notNullable();
|
// t.text("secretKeyHash").notNullable();
|
||||||
// t.text("secretValueHash");
|
// t.text("secretValueHash");
|
||||||
// t.text("secretCommentHash");
|
// 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("secretKeyCiphertext").notNullable();
|
||||||
t.text("secretKeyIV").notNullable();
|
t.text("secretKeyIV").notNullable();
|
||||||
t.text("secretKeyTag").notNullable();
|
t.text("secretKeyTag").notNullable();
|
||||||
@@ -40,19 +55,32 @@ export async function up(knex: Knex): Promise<void> {
|
|||||||
t.string("secretReminderNote");
|
t.string("secretReminderNote");
|
||||||
t.integer("secretReminderRepeatDays");
|
t.integer("secretReminderRepeatDays");
|
||||||
t.boolean("skipMultilineEncoding").defaultTo(false);
|
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.string("keyEncoding").notNullable().defaultTo(SecretKeyEncoding.UTF8);
|
||||||
t.jsonb("metadata");
|
t.jsonb("metadata");
|
||||||
t.uuid("userId");
|
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.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);
|
t.timestamps(true, true, true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
await createOnUpdateTrigger(knex, TableName.Secret);
|
await createOnUpdateTrigger(knex, TableName.Secret);
|
||||||
// many to many relation between tags
|
// 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> {
|
export async function down(knex: Knex): Promise<void> {
|
||||||
|
|||||||
@@ -1,7 +1,16 @@
|
|||||||
import { Knex } from "knex";
|
import { Knex } from "knex";
|
||||||
|
|
||||||
import { SecretEncryptionAlgo, SecretKeyEncoding, SecretType, TableName } from "../schemas";
|
import {
|
||||||
import { createJunctionTable, createOnUpdateTrigger, dropOnUpdateTrigger } from "../utils";
|
SecretEncryptionAlgo,
|
||||||
|
SecretKeyEncoding,
|
||||||
|
SecretType,
|
||||||
|
TableName,
|
||||||
|
} from "../schemas";
|
||||||
|
import {
|
||||||
|
createJunctionTable,
|
||||||
|
createOnUpdateTrigger,
|
||||||
|
dropOnUpdateTrigger,
|
||||||
|
} from "../utils";
|
||||||
|
|
||||||
export async function up(knex: Knex): Promise<void> {
|
export async function up(knex: Knex): Promise<void> {
|
||||||
if (!(await knex.schema.hasTable(TableName.SecretVersion))) {
|
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.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||||
t.integer("version").defaultTo(1).notNullable();
|
t.integer("version").defaultTo(1).notNullable();
|
||||||
t.string("type").notNullable().defaultTo(SecretType.Shared);
|
t.string("type").notNullable().defaultTo(SecretType.Shared);
|
||||||
t.text("secretBlindIndex").notNullable();
|
t.text("secretBlindIndex");
|
||||||
t.text("secretKeyCiphertext").notNullable();
|
t.text("secretKeyCiphertext").notNullable();
|
||||||
t.text("secretKeyIV").notNullable();
|
t.text("secretKeyIV").notNullable();
|
||||||
t.text("secretKeyTag").notNullable();
|
t.text("secretKeyTag").notNullable();
|
||||||
@@ -22,17 +31,25 @@ export async function up(knex: Knex): Promise<void> {
|
|||||||
t.string("secretReminderNote");
|
t.string("secretReminderNote");
|
||||||
t.integer("secretReminderRepeatDays");
|
t.integer("secretReminderRepeatDays");
|
||||||
t.boolean("skipMultilineEncoding").defaultTo(false);
|
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.string("keyEncoding").notNullable().defaultTo(SecretKeyEncoding.UTF8);
|
||||||
t.jsonb("metadata");
|
t.jsonb("metadata");
|
||||||
// to avoid orphan rows
|
// to avoid orphan rows
|
||||||
t.uuid("envId");
|
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("secretId").notNullable();
|
||||||
t.uuid("folderId").notNullable();
|
t.uuid("folderId").notNullable();
|
||||||
// t.foreign("secretId").references("id").inTable(TableName.Secret).onDelete("SET NULL");
|
// t.foreign("secretId").references("id").inTable(TableName.Secret).onDelete("SET NULL");
|
||||||
t.uuid("userId");
|
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);
|
t.timestamps(true, true, true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -42,7 +59,7 @@ export async function up(knex: Knex): Promise<void> {
|
|||||||
knex,
|
knex,
|
||||||
TableName.JnSecretVersionTag,
|
TableName.JnSecretVersionTag,
|
||||||
TableName.SecretVersion,
|
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))) {
|
if (!(await knex.schema.hasTable(TableName.IdentityAccessToken))) {
|
||||||
await knex.schema.createTable(TableName.IdentityAccessToken, (t) => {
|
await knex.schema.createTable(TableName.IdentityAccessToken, (t) => {
|
||||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||||
t.string("authType").notNullable();
|
|
||||||
t.integer("accessTokenTTL").defaultTo(2592000).notNullable(); // 30 days second
|
t.integer("accessTokenTTL").defaultTo(2592000).notNullable(); // 30 days second
|
||||||
t.integer("accessTokenMaxTTL").defaultTo(2592000).notNullable();
|
t.integer("accessTokenMaxTTL").defaultTo(2592000).notNullable();
|
||||||
t.integer("accessTokenNumUses").defaultTo(0).notNullable();
|
t.integer("accessTokenNumUses").defaultTo(0).notNullable();
|
||||||
@@ -21,7 +20,10 @@ export async function up(knex: Knex): Promise<void> {
|
|||||||
.inTable(TableName.IdentityUaClientSecret)
|
.inTable(TableName.IdentityUaClientSecret)
|
||||||
.onDelete("CASCADE");
|
.onDelete("CASCADE");
|
||||||
t.uuid("identityId").notNullable();
|
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);
|
t.timestamps(true, true, true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ const apiKeyDataSchema = new Schema<IAPIKeyData>(
|
|||||||
secretHash: {
|
secretHash: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
required: true,
|
||||||
select: false,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,74 +1,67 @@
|
|||||||
import { Schema, Types, model } from "mongoose";
|
import { Schema, Types, model } from "mongoose";
|
||||||
import {
|
|
||||||
ALGORITHM_AES_256_GCM,
|
|
||||||
ENCODING_SCHEME_BASE64,
|
|
||||||
ENCODING_SCHEME_UTF8,
|
|
||||||
} from "../variables";
|
|
||||||
|
|
||||||
export interface IBackupPrivateKey {
|
export interface IBackupPrivateKey {
|
||||||
_id: Types.ObjectId;
|
_id: Types.ObjectId;
|
||||||
user: Types.ObjectId;
|
user: Types.ObjectId;
|
||||||
encryptedPrivateKey: string;
|
encryptedPrivateKey: string;
|
||||||
iv: string;
|
iv: string;
|
||||||
tag: string;
|
tag: string;
|
||||||
salt: string;
|
salt: string;
|
||||||
algorithm: string;
|
algorithm: string;
|
||||||
keyEncoding: "base64" | "utf8";
|
keyEncoding: "base64" | "utf8";
|
||||||
verifier: string;
|
verifier: string;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const backupPrivateKeySchema = new Schema<IBackupPrivateKey>(
|
const backupPrivateKeySchema = new Schema<IBackupPrivateKey>(
|
||||||
{
|
{
|
||||||
user: {
|
user: {
|
||||||
type: Schema.Types.ObjectId,
|
type: Schema.Types.ObjectId,
|
||||||
ref: "User",
|
ref: "User",
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
encryptedPrivateKey: {
|
encryptedPrivateKey: {
|
||||||
type: String,
|
type: String,
|
||||||
select: false,
|
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
iv: {
|
iv: {
|
||||||
type: String,
|
type: String,
|
||||||
select: false,
|
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
tag: {
|
tag: {
|
||||||
type: String,
|
type: String,
|
||||||
select: false,
|
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
algorithm: { // the encryption algorithm used
|
algorithm: {
|
||||||
type: String,
|
// the encryption algorithm used
|
||||||
enum: [ALGORITHM_AES_256_GCM],
|
type: String,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
keyEncoding: {
|
keyEncoding: {
|
||||||
type: String,
|
type: String,
|
||||||
enum: [
|
required: true,
|
||||||
ENCODING_SCHEME_UTF8,
|
},
|
||||||
ENCODING_SCHEME_BASE64,
|
salt: {
|
||||||
],
|
type: String,
|
||||||
required: true,
|
|
||||||
},
|
required: true,
|
||||||
salt: {
|
},
|
||||||
type: String,
|
verifier: {
|
||||||
select: false,
|
type: String,
|
||||||
required: true,
|
|
||||||
},
|
required: true,
|
||||||
verifier: {
|
},
|
||||||
type: String,
|
},
|
||||||
select: false,
|
{
|
||||||
required: true,
|
timestamps: true,
|
||||||
},
|
},
|
||||||
},
|
|
||||||
{
|
|
||||||
timestamps: true,
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
|
|
||||||
export const BackupPrivateKey = model<IBackupPrivateKey>(
|
export const BackupPrivateKey = model<IBackupPrivateKey>(
|
||||||
"BackupPrivateKey",
|
"BackupPrivateKey",
|
||||||
backupPrivateKeySchema
|
backupPrivateKeySchema,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,77 +1,68 @@
|
|||||||
import { Schema, Types, model } from "mongoose";
|
import { Schema, Types, model } from "mongoose";
|
||||||
import {
|
|
||||||
ALGORITHM_AES_256_GCM,
|
|
||||||
ENCODING_SCHEME_BASE64,
|
|
||||||
ENCODING_SCHEME_UTF8,
|
|
||||||
} from "../variables";
|
|
||||||
|
|
||||||
export interface IBot {
|
export interface IBot {
|
||||||
_id: Types.ObjectId;
|
_id: Types.ObjectId;
|
||||||
name: string;
|
name: string;
|
||||||
workspace: Types.ObjectId;
|
workspace: Types.ObjectId;
|
||||||
isActive: boolean;
|
isActive: boolean;
|
||||||
publicKey: string;
|
publicKey: string;
|
||||||
encryptedPrivateKey: string;
|
encryptedPrivateKey: string;
|
||||||
iv: string;
|
iv: string;
|
||||||
tag: string;
|
tag: string;
|
||||||
algorithm: "aes-256-gcm";
|
algorithm: "aes-256-gcm";
|
||||||
keyEncoding: "base64" | "utf8";
|
keyEncoding: "base64" | "utf8";
|
||||||
}
|
}
|
||||||
|
|
||||||
const botSchema = new Schema<IBot>(
|
const botSchema = new Schema<IBot>(
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
workspace: {
|
workspace: {
|
||||||
type: Schema.Types.ObjectId,
|
type: Schema.Types.ObjectId,
|
||||||
ref: "Workspace",
|
ref: "Workspace",
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
isActive: {
|
isActive: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
required: true,
|
required: true,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
publicKey: {
|
publicKey: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
encryptedPrivateKey: {
|
encryptedPrivateKey: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
required: true,
|
||||||
select: false,
|
|
||||||
},
|
},
|
||||||
iv: {
|
iv: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
required: true,
|
||||||
select: false,
|
|
||||||
},
|
},
|
||||||
tag: {
|
tag: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
required: true,
|
||||||
select: false,
|
|
||||||
},
|
},
|
||||||
algorithm: { // the encryption algorithm used
|
algorithm: {
|
||||||
type: String,
|
// the encryption algorithm used
|
||||||
enum: [ALGORITHM_AES_256_GCM],
|
type: String,
|
||||||
required: true,
|
required: true,
|
||||||
select: false,
|
|
||||||
},
|
},
|
||||||
keyEncoding: {
|
keyEncoding: {
|
||||||
type: String,
|
type: String,
|
||||||
enum: [
|
required: true,
|
||||||
ENCODING_SCHEME_UTF8,
|
|
||||||
ENCODING_SCHEME_BASE64,
|
},
|
||||||
],
|
},
|
||||||
required: true,
|
{
|
||||||
select: false,
|
timestamps: 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 { Schema, Types, model } from "mongoose";
|
||||||
import {
|
|
||||||
ALGORITHM_AES_256_GCM,
|
|
||||||
ENCODING_SCHEME_BASE64,
|
|
||||||
ENCODING_SCHEME_UTF8,
|
|
||||||
} from "../variables";
|
|
||||||
|
|
||||||
export interface IBotOrg {
|
export interface IBotOrg {
|
||||||
_id: Types.ObjectId;
|
_id: Types.ObjectId;
|
||||||
name: string;
|
name: string;
|
||||||
organization: Types.ObjectId;
|
organization: Types.ObjectId;
|
||||||
publicKey: string;
|
publicKey: string;
|
||||||
encryptedSymmetricKey: string;
|
encryptedSymmetricKey: string;
|
||||||
symmetricKeyIV: string;
|
symmetricKeyIV: string;
|
||||||
symmetricKeyTag: string;
|
symmetricKeyTag: string;
|
||||||
symmetricKeyAlgorithm: "aes-256-gcm";
|
symmetricKeyAlgorithm: "aes-256-gcm";
|
||||||
symmetricKeyKeyEncoding: "base64" | "utf8";
|
symmetricKeyKeyEncoding: "base64" | "utf8";
|
||||||
encryptedPrivateKey: string;
|
encryptedPrivateKey: string;
|
||||||
privateKeyIV: string;
|
privateKeyIV: string;
|
||||||
privateKeyTag: string;
|
privateKeyTag: string;
|
||||||
privateKeyAlgorithm: "aes-256-gcm";
|
privateKeyAlgorithm: "aes-256-gcm";
|
||||||
privateKeyKeyEncoding: "base64" | "utf8";
|
privateKeyKeyEncoding: "base64" | "utf8";
|
||||||
}
|
}
|
||||||
|
|
||||||
const botOrgSchema = new Schema<IBotOrg>(
|
const botOrgSchema = new Schema<IBotOrg>(
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
organization: {
|
organization: {
|
||||||
type: Schema.Types.ObjectId,
|
type: Schema.Types.ObjectId,
|
||||||
ref: "Organization",
|
ref: "Organization",
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
publicKey: {
|
publicKey: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
encryptedSymmetricKey: {
|
encryptedSymmetricKey: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
symmetricKeyIV: {
|
symmetricKeyIV: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
symmetricKeyTag: {
|
symmetricKeyTag: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
symmetricKeyAlgorithm: {
|
symmetricKeyAlgorithm: {
|
||||||
type: String,
|
type: String,
|
||||||
enum: [ALGORITHM_AES_256_GCM],
|
required: true,
|
||||||
required: true
|
},
|
||||||
},
|
symmetricKeyKeyEncoding: {
|
||||||
symmetricKeyKeyEncoding: {
|
type: String,
|
||||||
type: String,
|
required: true,
|
||||||
enum: [
|
},
|
||||||
ENCODING_SCHEME_UTF8,
|
encryptedPrivateKey: {
|
||||||
ENCODING_SCHEME_BASE64,
|
type: String,
|
||||||
],
|
required: true,
|
||||||
required: true
|
},
|
||||||
},
|
privateKeyIV: {
|
||||||
encryptedPrivateKey: {
|
type: String,
|
||||||
type: String,
|
required: true,
|
||||||
required: true
|
},
|
||||||
},
|
privateKeyTag: {
|
||||||
privateKeyIV: {
|
type: String,
|
||||||
type: String,
|
required: true,
|
||||||
required: true
|
},
|
||||||
},
|
privateKeyAlgorithm: {
|
||||||
privateKeyTag: {
|
type: String,
|
||||||
type: String,
|
required: true,
|
||||||
required: true
|
},
|
||||||
},
|
privateKeyKeyEncoding: {
|
||||||
privateKeyAlgorithm: {
|
type: String,
|
||||||
type: String,
|
required: true,
|
||||||
enum: [ALGORITHM_AES_256_GCM],
|
},
|
||||||
required: true
|
},
|
||||||
},
|
{
|
||||||
privateKeyKeyEncoding: {
|
timestamps: true,
|
||||||
type: String,
|
},
|
||||||
enum: [
|
|
||||||
ENCODING_SCHEME_UTF8,
|
|
||||||
ENCODING_SCHEME_BASE64,
|
|
||||||
],
|
|
||||||
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 { Document, Schema, Types, model } from "mongoose";
|
||||||
import { IIdentityTrustedIp } from "./identity";
|
import { IIdentityTrustedIp } from "./identity";
|
||||||
import { IPType } from "../ee/models/trustedIp";
|
|
||||||
|
|
||||||
export interface IIdentityAccessToken extends Document {
|
export interface IIdentityAccessToken extends Document {
|
||||||
_id: Types.ObjectId;
|
_id: Types.ObjectId;
|
||||||
identity: Types.ObjectId;
|
identity: Types.ObjectId;
|
||||||
identityUniversalAuthClientSecret?: Types.ObjectId;
|
identityUniversalAuthClientSecret?: Types.ObjectId;
|
||||||
accessTokenLastUsedAt?: Date;
|
accessTokenLastUsedAt?: Date;
|
||||||
accessTokenLastRenewedAt?: Date;
|
accessTokenLastRenewedAt?: Date;
|
||||||
accessTokenNumUses: number;
|
accessTokenNumUses: number;
|
||||||
accessTokenNumUsesLimit: number;
|
accessTokenNumUsesLimit: number;
|
||||||
accessTokenTTL: number;
|
accessTokenTTL: number;
|
||||||
accessTokenMaxTTL: number;
|
accessTokenMaxTTL: number;
|
||||||
accessTokenTrustedIps: Array<IIdentityTrustedIp>;
|
accessTokenTrustedIps: Array<IIdentityTrustedIp>;
|
||||||
isAccessTokenRevoked: boolean;
|
isAccessTokenRevoked: boolean;
|
||||||
updatedAt: Date;
|
updatedAt: Date;
|
||||||
createdAt: Date;
|
createdAt: Date;
|
||||||
}
|
}
|
||||||
|
|
||||||
const identityAccessTokenSchema = new Schema(
|
const identityAccessTokenSchema = new Schema(
|
||||||
{
|
{
|
||||||
identity: {
|
identity: {
|
||||||
type: Schema.Types.ObjectId,
|
type: Schema.Types.ObjectId,
|
||||||
ref: "Identity",
|
ref: "Identity",
|
||||||
required: false
|
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
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
identityUniversalAuthClientSecret: {
|
||||||
timestamps: true
|
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 { Schema, Types, model } from "mongoose";
|
||||||
import { ADMIN, CUSTOM, MEMBER, NO_ACCESS, VIEWER } from "../variables";
|
|
||||||
|
|
||||||
export interface IIdentityMembership {
|
export interface IIdentityMembership {
|
||||||
_id: Types.ObjectId;
|
_id: Types.ObjectId;
|
||||||
@@ -13,7 +12,7 @@ const identityMembershipSchema = new Schema<IIdentityMembership>(
|
|||||||
{
|
{
|
||||||
identity: {
|
identity: {
|
||||||
type: Schema.Types.ObjectId,
|
type: Schema.Types.ObjectId,
|
||||||
ref: "Identity"
|
ref: "Identity",
|
||||||
},
|
},
|
||||||
workspace: {
|
workspace: {
|
||||||
type: Schema.Types.ObjectId,
|
type: Schema.Types.ObjectId,
|
||||||
@@ -23,17 +22,19 @@ const identityMembershipSchema = new Schema<IIdentityMembership>(
|
|||||||
},
|
},
|
||||||
role: {
|
role: {
|
||||||
type: String,
|
type: String,
|
||||||
enum: [ADMIN, MEMBER, VIEWER, CUSTOM, NO_ACCESS],
|
required: true,
|
||||||
required: true
|
|
||||||
},
|
},
|
||||||
customRole: {
|
customRole: {
|
||||||
type: Schema.Types.ObjectId,
|
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 { Schema, Types, model } from "mongoose";
|
||||||
import { ADMIN, CUSTOM, MEMBER, NO_ACCESS} from "../variables";
|
|
||||||
|
|
||||||
export interface IIdentityMembershipOrg {
|
export interface IIdentityMembershipOrg {
|
||||||
_id: Types.ObjectId;
|
_id: Types.ObjectId;
|
||||||
@@ -13,25 +12,27 @@ const identityMembershipOrgSchema = new Schema<IIdentityMembershipOrg>(
|
|||||||
{
|
{
|
||||||
identity: {
|
identity: {
|
||||||
type: Schema.Types.ObjectId,
|
type: Schema.Types.ObjectId,
|
||||||
ref: "Identity"
|
ref: "Identity",
|
||||||
},
|
},
|
||||||
organization: {
|
organization: {
|
||||||
type: Schema.Types.ObjectId,
|
type: Schema.Types.ObjectId,
|
||||||
ref: "Organization"
|
ref: "Organization",
|
||||||
},
|
},
|
||||||
role: {
|
role: {
|
||||||
type: String,
|
type: String,
|
||||||
enum: [ADMIN, MEMBER, NO_ACCESS, CUSTOM],
|
required: true,
|
||||||
required: true
|
|
||||||
},
|
},
|
||||||
customRole: {
|
customRole: {
|
||||||
type: Schema.Types.ObjectId,
|
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 { Document, Schema, Types, model } from "mongoose";
|
||||||
import { IPType } from "../ee/models";
|
|
||||||
import { IIdentityTrustedIp } from "./identity";
|
|
||||||
|
|
||||||
export interface IIdentityUniversalAuth extends Document {
|
export interface IIdentityUniversalAuth extends Document {
|
||||||
_id: Types.ObjectId;
|
_id: Types.ObjectId;
|
||||||
identity: Types.ObjectId;
|
identity: Types.ObjectId;
|
||||||
clientId: string;
|
clientId: string;
|
||||||
clientSecretTrustedIps: Array<IIdentityTrustedIp>;
|
clientSecretTrustedIps: Array<{}>;
|
||||||
accessTokenTTL: number;
|
accessTokenTTL: number;
|
||||||
accessTokenMaxTTL: number;
|
accessTokenMaxTTL: number;
|
||||||
accessTokenNumUsesLimit: number;
|
accessTokenNumUsesLimit: number;
|
||||||
accessTokenTrustedIps: Array<IIdentityTrustedIp>;
|
accessTokenTrustedIps: Array<{}>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const identityUniversalAuthSchema = new Schema(
|
const identityUniversalAuthSchema = new Schema(
|
||||||
{
|
{
|
||||||
identity: {
|
identity: {
|
||||||
type: Schema.Types.ObjectId,
|
type: Schema.Types.ObjectId,
|
||||||
ref: "Identity",
|
ref: "Identity",
|
||||||
required: true
|
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
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
clientId: {
|
||||||
timestamps: true
|
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 { Schema, Types, model } from "mongoose";
|
||||||
import { Metadata } from "./types";
|
import { Metadata } from "./types";
|
||||||
|
|
||||||
@@ -90,127 +58,98 @@ const integrationSchema = new Schema<IIntegration>(
|
|||||||
workspace: {
|
workspace: {
|
||||||
type: Schema.Types.ObjectId,
|
type: Schema.Types.ObjectId,
|
||||||
ref: "Workspace",
|
ref: "Workspace",
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
environment: {
|
environment: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
isActive: {
|
isActive: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
url: {
|
url: {
|
||||||
// for custom self-hosted integrations (e.g. self-hosted GitHub enterprise)
|
// for custom self-hosted integrations (e.g. self-hosted GitHub enterprise)
|
||||||
type: String,
|
type: String,
|
||||||
default: null
|
default: null,
|
||||||
},
|
},
|
||||||
app: {
|
app: {
|
||||||
// name of app in provider
|
// name of app in provider
|
||||||
type: String,
|
type: String,
|
||||||
default: null
|
default: null,
|
||||||
},
|
},
|
||||||
appId: {
|
appId: {
|
||||||
// id of app in provider
|
// id of app in provider
|
||||||
type: String,
|
type: String,
|
||||||
default: null
|
default: null,
|
||||||
},
|
},
|
||||||
targetEnvironment: {
|
targetEnvironment: {
|
||||||
// target environment
|
// target environment
|
||||||
type: String,
|
type: String,
|
||||||
default: null
|
default: null,
|
||||||
},
|
},
|
||||||
targetEnvironmentId: {
|
targetEnvironmentId: {
|
||||||
type: String,
|
type: String,
|
||||||
default: null
|
default: null,
|
||||||
},
|
},
|
||||||
targetService: {
|
targetService: {
|
||||||
// railway-specific service
|
// railway-specific service
|
||||||
// qovery-specific project
|
// qovery-specific project
|
||||||
type: String,
|
type: String,
|
||||||
default: null
|
default: null,
|
||||||
},
|
},
|
||||||
targetServiceId: {
|
targetServiceId: {
|
||||||
// railway-specific service
|
// railway-specific service
|
||||||
// qovery specific project
|
// qovery specific project
|
||||||
type: String,
|
type: String,
|
||||||
default: null
|
default: null,
|
||||||
},
|
},
|
||||||
owner: {
|
owner: {
|
||||||
// github-specific repo owner-login
|
// github-specific repo owner-login
|
||||||
type: String,
|
type: String,
|
||||||
default: null
|
default: null,
|
||||||
},
|
},
|
||||||
path: {
|
path: {
|
||||||
// aws-parameter-store-specific path
|
// aws-parameter-store-specific path
|
||||||
// (also) vercel preview-branch
|
// (also) vercel preview-branch
|
||||||
type: String,
|
type: String,
|
||||||
default: null
|
default: null,
|
||||||
},
|
},
|
||||||
region: {
|
region: {
|
||||||
// aws-parameter-store-specific path
|
// aws-parameter-store-specific path
|
||||||
type: String,
|
type: String,
|
||||||
default: null
|
default: null,
|
||||||
},
|
},
|
||||||
scope: {
|
scope: {
|
||||||
// qovery-specific scope
|
// qovery-specific scope
|
||||||
type: String,
|
type: String,
|
||||||
default: null
|
default: null,
|
||||||
},
|
},
|
||||||
integration: {
|
integration: {
|
||||||
type: String,
|
type: String,
|
||||||
enum: [
|
required: true,
|
||||||
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: {
|
integrationAuth: {
|
||||||
type: Schema.Types.ObjectId,
|
type: Schema.Types.ObjectId,
|
||||||
ref: "IntegrationAuth",
|
ref: "IntegrationAuth",
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
secretPath: {
|
secretPath: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
required: true,
|
||||||
default: "/"
|
default: "/",
|
||||||
},
|
},
|
||||||
metadata: {
|
metadata: {
|
||||||
type: Schema.Types.Mixed,
|
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 { Document, Schema, Types, model } from "mongoose";
|
||||||
import { IntegrationAuthMetadata } from "./types";
|
import { IntegrationAuthMetadata } from "./types";
|
||||||
|
|
||||||
@@ -91,116 +58,87 @@ const integrationAuthSchema = new Schema<IIntegrationAuth>(
|
|||||||
workspace: {
|
workspace: {
|
||||||
type: Schema.Types.ObjectId,
|
type: Schema.Types.ObjectId,
|
||||||
ref: "Workspace",
|
ref: "Workspace",
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
integration: {
|
integration: {
|
||||||
type: String,
|
type: String,
|
||||||
enum: [
|
required: true,
|
||||||
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: {
|
teamId: {
|
||||||
// vercel-specific integration param
|
// vercel-specific integration param
|
||||||
type: String
|
type: String,
|
||||||
},
|
},
|
||||||
url: {
|
url: {
|
||||||
// for any self-hosted integrations (e.g. self-hosted hashicorp-vault)
|
// for any self-hosted integrations (e.g. self-hosted hashicorp-vault)
|
||||||
type: String
|
type: String,
|
||||||
},
|
},
|
||||||
namespace: {
|
namespace: {
|
||||||
// hashicorp-vault-specific integration param
|
// hashicorp-vault-specific integration param
|
||||||
type: String
|
type: String,
|
||||||
},
|
},
|
||||||
accountId: {
|
accountId: {
|
||||||
// netlify-specific integration param
|
// netlify-specific integration param
|
||||||
type: String
|
type: String,
|
||||||
},
|
},
|
||||||
refreshCiphertext: {
|
refreshCiphertext: {
|
||||||
type: String,
|
type: String,
|
||||||
select: false
|
|
||||||
},
|
},
|
||||||
refreshIV: {
|
refreshIV: {
|
||||||
type: String,
|
type: String,
|
||||||
select: false
|
|
||||||
},
|
},
|
||||||
refreshTag: {
|
refreshTag: {
|
||||||
type: String,
|
type: String,
|
||||||
select: false
|
|
||||||
},
|
},
|
||||||
accessIdCiphertext: {
|
accessIdCiphertext: {
|
||||||
type: String,
|
type: String,
|
||||||
select: false
|
|
||||||
},
|
},
|
||||||
accessIdIV: {
|
accessIdIV: {
|
||||||
type: String,
|
type: String,
|
||||||
select: false
|
|
||||||
},
|
},
|
||||||
accessIdTag: {
|
accessIdTag: {
|
||||||
type: String,
|
type: String,
|
||||||
select: false
|
|
||||||
},
|
},
|
||||||
accessCiphertext: {
|
accessCiphertext: {
|
||||||
type: String,
|
type: String,
|
||||||
select: false
|
|
||||||
},
|
},
|
||||||
accessIV: {
|
accessIV: {
|
||||||
type: String,
|
type: String,
|
||||||
select: false
|
|
||||||
},
|
},
|
||||||
accessTag: {
|
accessTag: {
|
||||||
type: String,
|
type: String,
|
||||||
select: false
|
|
||||||
},
|
},
|
||||||
accessExpiresAt: {
|
accessExpiresAt: {
|
||||||
type: Date,
|
type: Date,
|
||||||
select: false
|
|
||||||
},
|
},
|
||||||
algorithm: {
|
algorithm: {
|
||||||
// the encryption algorithm used
|
// the encryption algorithm used
|
||||||
type: String,
|
type: String,
|
||||||
enum: [ALGORITHM_AES_256_GCM],
|
required: true,
|
||||||
required: true
|
|
||||||
},
|
},
|
||||||
keyEncoding: {
|
keyEncoding: {
|
||||||
type: String,
|
type: String,
|
||||||
enum: [ENCODING_SCHEME_UTF8, ENCODING_SCHEME_BASE64],
|
required: true,
|
||||||
required: true
|
|
||||||
},
|
},
|
||||||
metadata: {
|
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 { Schema, Types, model } from "mongoose";
|
||||||
import { ADMIN, CUSTOM, MEMBER, NO_ACCESS, VIEWER } from "../variables";
|
|
||||||
|
|
||||||
export interface IMembershipPermission {
|
export interface IMembershipPermission {
|
||||||
environmentSlug: string;
|
environmentSlug: string;
|
||||||
@@ -20,15 +19,15 @@ const membershipSchema = new Schema<IMembership>(
|
|||||||
{
|
{
|
||||||
user: {
|
user: {
|
||||||
type: Schema.Types.ObjectId,
|
type: Schema.Types.ObjectId,
|
||||||
ref: "User"
|
ref: "User",
|
||||||
},
|
},
|
||||||
inviteEmail: {
|
inviteEmail: {
|
||||||
type: String
|
type: String,
|
||||||
},
|
},
|
||||||
workspace: {
|
workspace: {
|
||||||
type: Schema.Types.ObjectId,
|
type: Schema.Types.ObjectId,
|
||||||
ref: "Workspace",
|
ref: "Workspace",
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
deniedPermissions: {
|
deniedPermissions: {
|
||||||
type: [
|
type: [
|
||||||
@@ -36,25 +35,24 @@ const membershipSchema = new Schema<IMembership>(
|
|||||||
environmentSlug: String,
|
environmentSlug: String,
|
||||||
ability: {
|
ability: {
|
||||||
type: String,
|
type: String,
|
||||||
enum: ["read", "write"]
|
enum: ["read", "write"],
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
default: []
|
default: [],
|
||||||
},
|
},
|
||||||
role: {
|
role: {
|
||||||
type: String,
|
type: String,
|
||||||
enum: [ADMIN, MEMBER, VIEWER, NO_ACCESS, CUSTOM],
|
required: true,
|
||||||
required: true
|
|
||||||
},
|
},
|
||||||
customRole: {
|
customRole: {
|
||||||
type: Schema.Types.ObjectId,
|
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 { Document, Schema, Types, model } from "mongoose";
|
||||||
import { ACCEPTED, ADMIN, CUSTOM, INVITED, MEMBER, NO_ACCESS } from "../variables";
|
|
||||||
|
|
||||||
export interface IMembershipOrg extends Document {
|
export interface IMembershipOrg extends Document {
|
||||||
_id: Types.ObjectId;
|
_id: Types.ObjectId;
|
||||||
@@ -9,39 +8,42 @@ export interface IMembershipOrg extends Document {
|
|||||||
role: "admin" | "member" | "no-access" | "custom";
|
role: "admin" | "member" | "no-access" | "custom";
|
||||||
customRole: Types.ObjectId;
|
customRole: Types.ObjectId;
|
||||||
status: "invited" | "accepted";
|
status: "invited" | "accepted";
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const membershipOrgSchema = new Schema(
|
const membershipOrgSchema = new Schema(
|
||||||
{
|
{
|
||||||
user: {
|
user: {
|
||||||
type: Schema.Types.ObjectId,
|
type: Schema.Types.ObjectId,
|
||||||
ref: "User"
|
ref: "User",
|
||||||
},
|
},
|
||||||
inviteEmail: {
|
inviteEmail: {
|
||||||
type: String
|
type: String,
|
||||||
},
|
},
|
||||||
organization: {
|
organization: {
|
||||||
type: Schema.Types.ObjectId,
|
type: Schema.Types.ObjectId,
|
||||||
ref: "Organization"
|
ref: "Organization",
|
||||||
},
|
},
|
||||||
role: {
|
role: {
|
||||||
type: String,
|
type: String,
|
||||||
enum: [ADMIN, MEMBER, NO_ACCESS, CUSTOM],
|
required: true,
|
||||||
required: true
|
|
||||||
},
|
},
|
||||||
status: {
|
status: {
|
||||||
type: String,
|
type: String,
|
||||||
enum: [INVITED, ACCEPTED],
|
required: true,
|
||||||
required: true
|
|
||||||
},
|
},
|
||||||
customRole: {
|
customRole: {
|
||||||
type: Schema.Types.ObjectId,
|
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";
|
import { Schema, Types, model } from "mongoose";
|
||||||
|
|
||||||
export interface IOrganization {
|
export interface IOrganization {
|
||||||
_id: Types.ObjectId;
|
_id: Types.ObjectId;
|
||||||
name: string;
|
name: string;
|
||||||
customerId?: string;
|
customerId?: string;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const organizationSchema = new Schema<IOrganization>(
|
const organizationSchema = new Schema<IOrganization>(
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
customerId: {
|
customerId: {
|
||||||
type: String,
|
type: String,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
timestamps: true,
|
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;
|
workspace: Types.ObjectId;
|
||||||
organization: Types.ObjectId;
|
organization: Types.ObjectId;
|
||||||
isOrgRole: boolean;
|
isOrgRole: boolean;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const roleSchema = new Schema<IRole>(
|
const roleSchema = new Schema<IRole>(
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
organization: {
|
organization: {
|
||||||
type: Schema.Types.ObjectId,
|
type: Schema.Types.ObjectId,
|
||||||
ref: "Organization",
|
ref: "Organization",
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
workspace: {
|
workspace: {
|
||||||
type: Schema.Types.ObjectId,
|
type: Schema.Types.ObjectId,
|
||||||
ref: "Workspace"
|
ref: "Workspace",
|
||||||
},
|
},
|
||||||
isOrgRole: {
|
isOrgRole: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
required: true,
|
required: true,
|
||||||
select: false
|
|
||||||
},
|
},
|
||||||
description: {
|
description: {
|
||||||
type: String
|
type: String,
|
||||||
},
|
},
|
||||||
slug: {
|
slug: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
permissions: {
|
permissions: {
|
||||||
type: Array,
|
type: Array,
|
||||||
required: true
|
required: true,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
timestamps: true
|
timestamps: true,
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
roleSchema.index({ organization: 1, workspace: 1 });
|
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 { 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 {
|
export interface ISecret {
|
||||||
_id: Types.ObjectId;
|
_id: Types.ObjectId;
|
||||||
@@ -48,123 +41,118 @@ const secretSchema = new Schema<ISecret>(
|
|||||||
version: {
|
version: {
|
||||||
type: Number,
|
type: Number,
|
||||||
required: true,
|
required: true,
|
||||||
default: 1
|
default: 1,
|
||||||
},
|
},
|
||||||
workspace: {
|
workspace: {
|
||||||
type: Schema.Types.ObjectId,
|
type: Schema.Types.ObjectId,
|
||||||
ref: "Workspace",
|
ref: "Workspace",
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
type: {
|
type: {
|
||||||
type: String,
|
type: String,
|
||||||
enum: [SECRET_SHARED, SECRET_PERSONAL],
|
required: true,
|
||||||
required: true
|
|
||||||
},
|
},
|
||||||
user: {
|
user: {
|
||||||
// user associated with the personal secret
|
// user associated with the personal secret
|
||||||
type: Schema.Types.ObjectId,
|
type: Schema.Types.ObjectId,
|
||||||
ref: "User"
|
ref: "User",
|
||||||
},
|
},
|
||||||
tags: {
|
tags: {
|
||||||
ref: "Tag",
|
ref: "Tag",
|
||||||
type: [Schema.Types.ObjectId],
|
type: [Schema.Types.ObjectId],
|
||||||
default: []
|
default: [],
|
||||||
},
|
},
|
||||||
environment: {
|
environment: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
secretBlindIndex: {
|
secretBlindIndex: {
|
||||||
type: String,
|
type: String,
|
||||||
select: false
|
|
||||||
},
|
},
|
||||||
secretKeyCiphertext: {
|
secretKeyCiphertext: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
secretKeyIV: {
|
secretKeyIV: {
|
||||||
type: String, // symmetric
|
type: String, // symmetric
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
secretKeyTag: {
|
secretKeyTag: {
|
||||||
type: String, // symmetric
|
type: String, // symmetric
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
secretKeyHash: {
|
secretKeyHash: {
|
||||||
type: String
|
type: String,
|
||||||
},
|
},
|
||||||
secretValueCiphertext: {
|
secretValueCiphertext: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
secretValueIV: {
|
secretValueIV: {
|
||||||
type: String, // symmetric
|
type: String, // symmetric
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
secretValueTag: {
|
secretValueTag: {
|
||||||
type: String, // symmetric
|
type: String, // symmetric
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
secretValueHash: {
|
secretValueHash: {
|
||||||
type: String
|
type: String,
|
||||||
},
|
},
|
||||||
secretCommentCiphertext: {
|
secretCommentCiphertext: {
|
||||||
type: String,
|
type: String,
|
||||||
required: false
|
required: false,
|
||||||
},
|
},
|
||||||
secretCommentIV: {
|
secretCommentIV: {
|
||||||
type: String, // symmetric
|
type: String, // symmetric
|
||||||
required: false
|
required: false,
|
||||||
},
|
},
|
||||||
secretCommentTag: {
|
secretCommentTag: {
|
||||||
type: String, // symmetric
|
type: String, // symmetric
|
||||||
required: false
|
required: false,
|
||||||
},
|
},
|
||||||
secretCommentHash: {
|
secretCommentHash: {
|
||||||
type: String,
|
type: String,
|
||||||
required: false
|
required: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
secretReminderRepeatDays: {
|
secretReminderRepeatDays: {
|
||||||
type: Number,
|
type: Number,
|
||||||
required: false,
|
required: false,
|
||||||
default: null
|
default: null,
|
||||||
},
|
},
|
||||||
secretReminderNote: {
|
secretReminderNote: {
|
||||||
type: String,
|
type: String,
|
||||||
required: false,
|
required: false,
|
||||||
default: null
|
default: null,
|
||||||
},
|
},
|
||||||
|
|
||||||
skipMultilineEncoding: {
|
skipMultilineEncoding: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
required: false
|
required: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
algorithm: {
|
algorithm: {
|
||||||
// the encryption algorithm used
|
// the encryption algorithm used
|
||||||
type: String,
|
type: String,
|
||||||
enum: [ALGORITHM_AES_256_GCM],
|
|
||||||
required: true,
|
required: true,
|
||||||
default: ALGORITHM_AES_256_GCM
|
|
||||||
},
|
},
|
||||||
keyEncoding: {
|
keyEncoding: {
|
||||||
type: String,
|
type: String,
|
||||||
enum: [ENCODING_SCHEME_UTF8, ENCODING_SCHEME_BASE64],
|
|
||||||
required: true,
|
required: true,
|
||||||
default: ENCODING_SCHEME_UTF8
|
|
||||||
},
|
},
|
||||||
folder: {
|
folder: {
|
||||||
type: String,
|
type: String,
|
||||||
default: "root"
|
default: "root",
|
||||||
},
|
},
|
||||||
metadata: {
|
metadata: {
|
||||||
type: Schema.Types.Mixed
|
type: Schema.Types.Mixed,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
timestamps: true
|
timestamps: true,
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
secretSchema.index({ tags: 1 }, { background: true });
|
secretSchema.index({ tags: 1 }, { background: true });
|
||||||
|
|||||||
@@ -1,26 +1,17 @@
|
|||||||
import { Schema, Types, model } from "mongoose";
|
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 {
|
export enum ApprovalStatus {
|
||||||
PENDING = "pending",
|
PENDING = "pending",
|
||||||
APPROVED = "approved",
|
APPROVED = "approved",
|
||||||
REJECTED = "rejected"
|
REJECTED = "rejected",
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum CommitType {
|
export enum CommitType {
|
||||||
DELETE = "delete",
|
DELETE = "delete",
|
||||||
UPDATE = "update",
|
UPDATE = "update",
|
||||||
CREATE = "create"
|
CREATE = "create",
|
||||||
}
|
}
|
||||||
|
|
||||||
const SLUG_ALPHABETS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
|
||||||
const nanoId = customAlphabet(SLUG_ALPHABETS, 10);
|
|
||||||
|
|
||||||
export interface ISecretApprovalSecChange {
|
export interface ISecretApprovalSecChange {
|
||||||
_id: Types.ObjectId;
|
_id: Types.ObjectId;
|
||||||
version: number;
|
version: number;
|
||||||
@@ -50,7 +41,9 @@ export type ISecretCommits<T = Types.ObjectId, J = Types.ObjectId> = Array<
|
|||||||
// on merge
|
// on merge
|
||||||
secretVersion: J;
|
secretVersion: J;
|
||||||
secret: T;
|
secret: T;
|
||||||
newVersion: Partial<Omit<ISecretApprovalSecChange, "_id">> & { _id: Types.ObjectId };
|
newVersion: Partial<Omit<ISecretApprovalSecChange, "_id">> & {
|
||||||
|
_id: Types.ObjectId;
|
||||||
|
};
|
||||||
op: CommitType.UPDATE;
|
op: CommitType.UPDATE;
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
@@ -82,58 +75,54 @@ const secretApprovalSecretChangeSchema = new Schema<ISecretApprovalSecChange>({
|
|||||||
version: {
|
version: {
|
||||||
type: Number,
|
type: Number,
|
||||||
default: 1,
|
default: 1,
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
secretBlindIndex: {
|
secretBlindIndex: {
|
||||||
type: String,
|
type: String,
|
||||||
select: false
|
|
||||||
},
|
},
|
||||||
secretKeyCiphertext: {
|
secretKeyCiphertext: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
secretKeyIV: {
|
secretKeyIV: {
|
||||||
type: String, // symmetric
|
type: String, // symmetric
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
secretKeyTag: {
|
secretKeyTag: {
|
||||||
type: String, // symmetric
|
type: String, // symmetric
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
secretValueCiphertext: {
|
secretValueCiphertext: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
secretValueIV: {
|
secretValueIV: {
|
||||||
type: String, // symmetric
|
type: String, // symmetric
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
secretValueTag: {
|
secretValueTag: {
|
||||||
type: String, // symmetric
|
type: String, // symmetric
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
skipMultilineEncoding: {
|
skipMultilineEncoding: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
required: false
|
required: false,
|
||||||
},
|
},
|
||||||
algorithm: {
|
algorithm: {
|
||||||
// the encryption algorithm used
|
// the encryption algorithm used
|
||||||
type: String,
|
type: String,
|
||||||
enum: [ALGORITHM_AES_256_GCM],
|
|
||||||
required: true,
|
required: true,
|
||||||
default: ALGORITHM_AES_256_GCM
|
|
||||||
},
|
},
|
||||||
keyEncoding: {
|
keyEncoding: {
|
||||||
type: String,
|
type: String,
|
||||||
enum: [ENCODING_SCHEME_UTF8, ENCODING_SCHEME_BASE64],
|
|
||||||
required: true,
|
required: true,
|
||||||
default: ENCODING_SCHEME_UTF8
|
|
||||||
},
|
},
|
||||||
tags: {
|
tags: {
|
||||||
ref: "Tag",
|
ref: "Tag",
|
||||||
type: [Schema.Types.ObjectId],
|
type: [Schema.Types.ObjectId],
|
||||||
default: []
|
default: [],
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const secretApprovalRequestSchema = new Schema<ISecretApprovalRequest>(
|
const secretApprovalRequestSchema = new Schema<ISecretApprovalRequest>(
|
||||||
@@ -141,20 +130,19 @@ const secretApprovalRequestSchema = new Schema<ISecretApprovalRequest>(
|
|||||||
workspace: {
|
workspace: {
|
||||||
type: Schema.Types.ObjectId,
|
type: Schema.Types.ObjectId,
|
||||||
ref: "Workspace",
|
ref: "Workspace",
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
environment: {
|
environment: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
folderId: {
|
folderId: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
required: true,
|
||||||
default: "root"
|
default: "root",
|
||||||
},
|
},
|
||||||
slug: {
|
slug: {
|
||||||
type: String,
|
type: String,
|
||||||
default: () => nanoId()
|
|
||||||
},
|
},
|
||||||
reviewers: {
|
reviewers: {
|
||||||
type: [
|
type: [
|
||||||
@@ -162,12 +150,16 @@ const secretApprovalRequestSchema = new Schema<ISecretApprovalRequest>(
|
|||||||
member: {
|
member: {
|
||||||
// user associated with the personal secret
|
// user associated with the personal secret
|
||||||
type: Schema.Types.ObjectId,
|
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" },
|
policy: { type: Schema.Types.ObjectId, ref: "SecretApprovalPolicy" },
|
||||||
hasMerged: { type: Boolean, default: false },
|
hasMerged: { type: Boolean, default: false },
|
||||||
@@ -179,25 +171,25 @@ const secretApprovalRequestSchema = new Schema<ISecretApprovalRequest>(
|
|||||||
secret: { type: Types.ObjectId, ref: "Secret" },
|
secret: { type: Types.ObjectId, ref: "Secret" },
|
||||||
newVersion: secretApprovalSecretChangeSchema,
|
newVersion: secretApprovalSecretChangeSchema,
|
||||||
secretVersion: { type: Types.ObjectId, ref: "SecretVersion" },
|
secretVersion: { type: Types.ObjectId, ref: "SecretVersion" },
|
||||||
op: { type: String, enum: [CommitType], required: true }
|
op: { type: String, enum: [CommitType], required: true },
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
conflicts: {
|
conflicts: {
|
||||||
type: [
|
type: [
|
||||||
{
|
{
|
||||||
secretId: { type: String, required: true },
|
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>(
|
export const SecretApprovalRequest = model<ISecretApprovalRequest>(
|
||||||
"SecretApprovalRequest",
|
"SecretApprovalRequest",
|
||||||
secretApprovalRequestSchema
|
secretApprovalRequestSchema,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,58 +1,49 @@
|
|||||||
import { Document, Schema, Types, model } from "mongoose";
|
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 {
|
export interface ISecretBlindIndexData extends Document {
|
||||||
_id: Types.ObjectId;
|
_id: Types.ObjectId;
|
||||||
workspace: Types.ObjectId;
|
workspace: Types.ObjectId;
|
||||||
encryptedSaltCiphertext: string;
|
encryptedSaltCiphertext: string;
|
||||||
saltIV: string;
|
saltIV: string;
|
||||||
saltTag: string;
|
saltTag: string;
|
||||||
algorithm: "aes-256-gcm";
|
algorithm: "aes-256-gcm";
|
||||||
keyEncoding: "base64" | "utf8"
|
keyEncoding: "base64" | "utf8";
|
||||||
}
|
}
|
||||||
|
|
||||||
const secretBlindIndexDataSchema = new Schema<ISecretBlindIndexData>(
|
const secretBlindIndexDataSchema = new Schema<ISecretBlindIndexData>({
|
||||||
{
|
workspace: {
|
||||||
workspace: {
|
type: Schema.Types.ObjectId,
|
||||||
type: Schema.Types.ObjectId,
|
ref: "Workspace",
|
||||||
ref: "Workspace",
|
required: true,
|
||||||
required: true,
|
},
|
||||||
},
|
encryptedSaltCiphertext: {
|
||||||
encryptedSaltCiphertext: { // TODO: make these select: false
|
// TODO: make these
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
saltIV: {
|
saltIV: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
saltTag: {
|
saltTag: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
algorithm: {
|
algorithm: {
|
||||||
type: String,
|
type: String,
|
||||||
enum: [ALGORITHM_AES_256_GCM],
|
required: true,
|
||||||
required: true,
|
|
||||||
select: false,
|
},
|
||||||
},
|
keyEncoding: {
|
||||||
keyEncoding: {
|
type: String,
|
||||||
type: String,
|
required: true,
|
||||||
enum: [
|
|
||||||
ENCODING_SCHEME_UTF8,
|
},
|
||||||
ENCODING_SCHEME_BASE64,
|
});
|
||||||
],
|
|
||||||
required: true,
|
|
||||||
select: false,
|
|
||||||
},
|
|
||||||
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
secretBlindIndexDataSchema.index({ workspace: 1 });
|
secretBlindIndexDataSchema.index({ workspace: 1 });
|
||||||
|
|
||||||
export const SecretBlindIndexData = model<ISecretBlindIndexData>("SecretBlindIndexData", secretBlindIndexDataSchema);
|
export const SecretBlindIndexData = model<ISecretBlindIndexData>(
|
||||||
|
"SecretBlindIndexData",
|
||||||
|
secretBlindIndexDataSchema,
|
||||||
|
);
|
||||||
|
|||||||
@@ -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";
|
import { Schema, Types, model } from "mongoose";
|
||||||
|
|
||||||
export interface ISecretSnapshot {
|
export interface ISecretSnapshot {
|
||||||
|
id: string;
|
||||||
|
_id: string;
|
||||||
workspace: Types.ObjectId;
|
workspace: Types.ObjectId;
|
||||||
environment: string;
|
environment: string;
|
||||||
folderId: string | "root";
|
folderId: string | "root";
|
||||||
@@ -43,10 +45,10 @@ const secretSnapshotSchema = new Schema<ISecretSnapshot>(
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
timestamps: true,
|
timestamps: true,
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
export const SecretSnapshot = model<ISecretSnapshot>(
|
export const SecretSnapshot = model<ISecretSnapshot>(
|
||||||
"SecretSnapshot",
|
"SecretSnapshot",
|
||||||
secretSnapshotSchema
|
secretSnapshotSchema,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,11 +1,4 @@
|
|||||||
import { Schema, Types, model } from "mongoose";
|
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 {
|
export interface ISecretVersion {
|
||||||
_id: Types.ObjectId;
|
_id: Types.ObjectId;
|
||||||
@@ -37,96 +30,94 @@ const secretVersionSchema = new Schema<ISecretVersion>(
|
|||||||
// could be deleted
|
// could be deleted
|
||||||
type: Schema.Types.ObjectId,
|
type: Schema.Types.ObjectId,
|
||||||
ref: "Secret",
|
ref: "Secret",
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
version: {
|
version: {
|
||||||
type: Number,
|
type: Number,
|
||||||
default: 1,
|
default: 1,
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
workspace: {
|
workspace: {
|
||||||
type: Schema.Types.ObjectId,
|
type: Schema.Types.ObjectId,
|
||||||
ref: "Workspace",
|
ref: "Workspace",
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
type: {
|
type: {
|
||||||
type: String,
|
type: String,
|
||||||
enum: [SECRET_SHARED, SECRET_PERSONAL],
|
required: true,
|
||||||
required: true
|
|
||||||
},
|
},
|
||||||
user: {
|
user: {
|
||||||
// user associated with the personal secret
|
// user associated with the personal secret
|
||||||
type: Schema.Types.ObjectId,
|
type: Schema.Types.ObjectId,
|
||||||
ref: "User"
|
ref: "User",
|
||||||
},
|
},
|
||||||
environment: {
|
environment: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
isDeleted: {
|
isDeleted: {
|
||||||
// consider removing field
|
// consider removing field
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
secretBlindIndex: {
|
secretBlindIndex: {
|
||||||
type: String,
|
type: String,
|
||||||
select: false
|
|
||||||
},
|
},
|
||||||
secretKeyCiphertext: {
|
secretKeyCiphertext: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
secretKeyIV: {
|
secretKeyIV: {
|
||||||
type: String, // symmetric
|
type: String, // symmetric
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
secretKeyTag: {
|
secretKeyTag: {
|
||||||
type: String, // symmetric
|
type: String, // symmetric
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
secretValueCiphertext: {
|
secretValueCiphertext: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
secretValueIV: {
|
secretValueIV: {
|
||||||
type: String, // symmetric
|
type: String, // symmetric
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
secretValueTag: {
|
secretValueTag: {
|
||||||
type: String, // symmetric
|
type: String, // symmetric
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
skipMultilineEncoding: {
|
skipMultilineEncoding: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
required: false
|
required: false,
|
||||||
},
|
},
|
||||||
algorithm: {
|
algorithm: {
|
||||||
// the encryption algorithm used
|
// the encryption algorithm used
|
||||||
type: String,
|
type: String,
|
||||||
enum: [ALGORITHM_AES_256_GCM],
|
|
||||||
required: true,
|
required: true,
|
||||||
default: ALGORITHM_AES_256_GCM
|
|
||||||
},
|
},
|
||||||
keyEncoding: {
|
keyEncoding: {
|
||||||
type: String,
|
type: String,
|
||||||
enum: [ENCODING_SCHEME_UTF8, ENCODING_SCHEME_BASE64],
|
|
||||||
required: true,
|
required: true,
|
||||||
default: ENCODING_SCHEME_UTF8
|
|
||||||
},
|
},
|
||||||
folder: {
|
folder: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
tags: {
|
tags: {
|
||||||
ref: "Tag",
|
ref: "Tag",
|
||||||
type: [Schema.Types.ObjectId],
|
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: {
|
secretHash: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
required: true,
|
||||||
select: false
|
|
||||||
},
|
},
|
||||||
encryptedKey: {
|
encryptedKey: {
|
||||||
type: String,
|
type: String,
|
||||||
select: false
|
|
||||||
},
|
},
|
||||||
iv: {
|
iv: {
|
||||||
type: String,
|
type: String,
|
||||||
select: false
|
|
||||||
},
|
},
|
||||||
tag: {
|
tag: {
|
||||||
type: String,
|
type: String,
|
||||||
select: false
|
|
||||||
},
|
},
|
||||||
permissions: {
|
permissions: {
|
||||||
type: [String],
|
type: [String],
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ const tokenDataSchema = new Schema<ITokenData>({
|
|||||||
},
|
},
|
||||||
tokenHash: {
|
tokenHash: {
|
||||||
type: String,
|
type: String,
|
||||||
select: false,
|
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
triesLeft: {
|
triesLeft: {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ export enum AuthMethod {
|
|||||||
GITLAB = "gitlab",
|
GITLAB = "gitlab",
|
||||||
OKTA_SAML = "okta-saml",
|
OKTA_SAML = "okta-saml",
|
||||||
AZURE_SAML = "azure-saml",
|
AZURE_SAML = "azure-saml",
|
||||||
JUMPCLOUD_SAML = "jumpcloud-saml"
|
JUMPCLOUD_SAML = "jumpcloud-saml",
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IUser extends Document {
|
export interface IUser extends Document {
|
||||||
@@ -34,6 +34,8 @@ export interface IUser extends Document {
|
|||||||
ip: string;
|
ip: string;
|
||||||
userAgent: string;
|
userAgent: string;
|
||||||
}[];
|
}[];
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const userSchema = new Schema<IUser>(
|
const userSchema = new Schema<IUser>(
|
||||||
@@ -41,101 +43,101 @@ const userSchema = new Schema<IUser>(
|
|||||||
authProvider: {
|
authProvider: {
|
||||||
// TODO field: deprecate
|
// TODO field: deprecate
|
||||||
type: String,
|
type: String,
|
||||||
enum: AuthMethod
|
enum: AuthMethod,
|
||||||
},
|
},
|
||||||
authMethods: {
|
authMethods: {
|
||||||
type: [
|
type: [
|
||||||
{
|
{
|
||||||
type: String,
|
type: String,
|
||||||
enum: AuthMethod
|
enum: AuthMethod,
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
default: [AuthMethod.EMAIL],
|
default: [AuthMethod.EMAIL],
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
email: {
|
email: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
required: true,
|
||||||
unique: true
|
unique: true,
|
||||||
},
|
},
|
||||||
firstName: {
|
firstName: {
|
||||||
type: String
|
type: String,
|
||||||
},
|
},
|
||||||
lastName: {
|
lastName: {
|
||||||
type: String
|
type: String,
|
||||||
},
|
},
|
||||||
encryptionVersion: {
|
encryptionVersion: {
|
||||||
type: Number,
|
type: Number,
|
||||||
select: false,
|
|
||||||
default: 1 // to resolve backward-compatibility issues
|
default: 1, // to resolve backward-compatibility issues
|
||||||
},
|
},
|
||||||
protectedKey: {
|
protectedKey: {
|
||||||
// introduced as part of encryption version 2
|
// introduced as part of encryption version 2
|
||||||
type: String,
|
type: String,
|
||||||
select: false
|
|
||||||
},
|
},
|
||||||
protectedKeyIV: {
|
protectedKeyIV: {
|
||||||
// introduced as part of encryption version 2
|
// introduced as part of encryption version 2
|
||||||
type: String,
|
type: String,
|
||||||
select: false
|
|
||||||
},
|
},
|
||||||
protectedKeyTag: {
|
protectedKeyTag: {
|
||||||
// introduced as part of encryption version 2
|
// introduced as part of encryption version 2
|
||||||
type: String,
|
type: String,
|
||||||
select: false
|
|
||||||
},
|
},
|
||||||
publicKey: {
|
publicKey: {
|
||||||
type: String,
|
type: String,
|
||||||
select: false
|
|
||||||
},
|
},
|
||||||
encryptedPrivateKey: {
|
encryptedPrivateKey: {
|
||||||
type: String,
|
type: String,
|
||||||
select: false
|
|
||||||
},
|
},
|
||||||
superAdmin: {
|
superAdmin: {
|
||||||
type: Boolean
|
type: Boolean,
|
||||||
},
|
},
|
||||||
iv: {
|
iv: {
|
||||||
// iv of [encryptedPrivateKey]
|
// iv of [encryptedPrivateKey]
|
||||||
type: String,
|
type: String,
|
||||||
select: false
|
|
||||||
},
|
},
|
||||||
tag: {
|
tag: {
|
||||||
// tag of [encryptedPrivateKey]
|
// tag of [encryptedPrivateKey]
|
||||||
type: String,
|
type: String,
|
||||||
select: false
|
|
||||||
},
|
},
|
||||||
salt: {
|
salt: {
|
||||||
type: String,
|
type: String,
|
||||||
select: false
|
|
||||||
},
|
},
|
||||||
verifier: {
|
verifier: {
|
||||||
type: String,
|
type: String,
|
||||||
select: false
|
|
||||||
},
|
},
|
||||||
isMfaEnabled: {
|
isMfaEnabled: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false,
|
||||||
},
|
},
|
||||||
mfaMethods: [
|
mfaMethods: [
|
||||||
{
|
{
|
||||||
type: String
|
type: String,
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
devices: {
|
devices: {
|
||||||
type: [
|
type: [
|
||||||
{
|
{
|
||||||
ip: String,
|
ip: String,
|
||||||
userAgent: String
|
userAgent: String,
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
default: [],
|
default: [],
|
||||||
select: false
|
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
timestamps: true
|
timestamps: true,
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
export const User = model<IUser>("User", userSchema);
|
export const User = model<IUser>("User", userSchema);
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { Document, Schema, Types, model } from "mongoose";
|
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 {
|
export interface IWebhook extends Document {
|
||||||
_id: Types.ObjectId;
|
_id: Types.ObjectId;
|
||||||
@@ -22,60 +21,58 @@ const WebhookSchema = new Schema<IWebhook>(
|
|||||||
workspace: {
|
workspace: {
|
||||||
type: Schema.Types.ObjectId,
|
type: Schema.Types.ObjectId,
|
||||||
ref: "Workspace",
|
ref: "Workspace",
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
environment: {
|
environment: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
secretPath: {
|
secretPath: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
required: true,
|
||||||
default: "/"
|
default: "/",
|
||||||
},
|
},
|
||||||
url: {
|
url: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
lastStatus: {
|
lastStatus: {
|
||||||
type: String,
|
type: String,
|
||||||
enum: ["success", "failed"]
|
enum: ["success", "failed"],
|
||||||
},
|
},
|
||||||
lastRunErrorMessage: {
|
lastRunErrorMessage: {
|
||||||
type: String
|
type: String,
|
||||||
},
|
},
|
||||||
isDisabled: {
|
isDisabled: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false,
|
||||||
},
|
},
|
||||||
// used for webhook signature
|
// used for webhook signature
|
||||||
encryptedSecretKey: {
|
encryptedSecretKey: {
|
||||||
type: String,
|
type: String,
|
||||||
select: false
|
|
||||||
},
|
},
|
||||||
iv: {
|
iv: {
|
||||||
type: String,
|
type: String,
|
||||||
select: false
|
|
||||||
},
|
},
|
||||||
tag: {
|
tag: {
|
||||||
type: String,
|
type: String,
|
||||||
select: false
|
|
||||||
},
|
},
|
||||||
algorithm: {
|
algorithm: {
|
||||||
// the encryption algorithm used
|
// the encryption algorithm used
|
||||||
type: String,
|
type: String,
|
||||||
enum: [ALGORITHM_AES_256_GCM],
|
|
||||||
select: false
|
|
||||||
},
|
},
|
||||||
keyEncoding: {
|
keyEncoding: {
|
||||||
type: String,
|
type: String,
|
||||||
enum: [ENCODING_SCHEME_UTF8, ENCODING_SCHEME_BASE64],
|
|
||||||
select: false
|
},
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
timestamps: true
|
timestamps: true,
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
export const Webhook = model<IWebhook>("Webhook", WebhookSchema);
|
export const Webhook = model<IWebhook>("Webhook", WebhookSchema);
|
||||||
|
|||||||
@@ -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({
|
export const IdentityAccessTokensSchema = z.object({
|
||||||
id: z.string().uuid(),
|
id: z.string().uuid(),
|
||||||
authType: z.string(),
|
|
||||||
accessTokenTTL: z.number().default(2592000),
|
accessTokenTTL: z.number().default(2592000),
|
||||||
accessTokenMaxTTL: z.number().default(2592000),
|
accessTokenMaxTTL: z.number().default(2592000),
|
||||||
accessTokenNumUses: z.number().default(0),
|
accessTokenNumUses: z.number().default(0),
|
||||||
@@ -24,5 +23,10 @@ export const IdentityAccessTokensSchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export type TIdentityAccessTokens = z.infer<typeof IdentityAccessTokensSchema>;
|
export type TIdentityAccessTokens = z.infer<typeof IdentityAccessTokensSchema>;
|
||||||
export type TIdentityAccessTokensInsert = Omit<TIdentityAccessTokens, TImmutableDBKeys>;
|
export type TIdentityAccessTokensInsert = Omit<
|
||||||
export type TIdentityAccessTokensUpdate = Partial<Omit<TIdentityAccessTokens, TImmutableDBKeys>>;
|
TIdentityAccessTokens,
|
||||||
|
TImmutableDBKeys
|
||||||
|
>;
|
||||||
|
export type TIdentityAccessTokensUpdate = Partial<
|
||||||
|
Omit<TIdentityAccessTokens, TImmutableDBKeys>
|
||||||
|
>;
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ import { TImmutableDBKeys } from "./models";
|
|||||||
export const SecretVersionsSchema = z.object({
|
export const SecretVersionsSchema = z.object({
|
||||||
id: z.string().uuid(),
|
id: z.string().uuid(),
|
||||||
version: z.number().default(1),
|
version: z.number().default(1),
|
||||||
type: z.string().default('shared'),
|
type: z.string().default("shared"),
|
||||||
secretBlindIndex: z.string(),
|
secretBlindIndex: z.string().nullable().optional(),
|
||||||
secretKeyCiphertext: z.string(),
|
secretKeyCiphertext: z.string(),
|
||||||
secretKeyIV: z.string(),
|
secretKeyIV: z.string(),
|
||||||
secretKeyTag: z.string(),
|
secretKeyTag: z.string(),
|
||||||
@@ -24,8 +24,8 @@ export const SecretVersionsSchema = z.object({
|
|||||||
secretReminderNote: z.string().nullable().optional(),
|
secretReminderNote: z.string().nullable().optional(),
|
||||||
secretReminderRepeatDays: z.number().nullable().optional(),
|
secretReminderRepeatDays: z.number().nullable().optional(),
|
||||||
skipMultilineEncoding: z.boolean().default(false).nullable().optional(),
|
skipMultilineEncoding: z.boolean().default(false).nullable().optional(),
|
||||||
algorithm: z.string().default('aes-256-gcm'),
|
algorithm: z.string().default("aes-256-gcm"),
|
||||||
keyEncoding: z.string().default('utf8'),
|
keyEncoding: z.string().default("utf8"),
|
||||||
metadata: z.unknown().nullable().optional(),
|
metadata: z.unknown().nullable().optional(),
|
||||||
envId: z.string().uuid().nullable().optional(),
|
envId: z.string().uuid().nullable().optional(),
|
||||||
secretId: z.string().uuid(),
|
secretId: z.string().uuid(),
|
||||||
@@ -37,4 +37,6 @@ export const SecretVersionsSchema = z.object({
|
|||||||
|
|
||||||
export type TSecretVersions = z.infer<typeof SecretVersionsSchema>;
|
export type TSecretVersions = z.infer<typeof SecretVersionsSchema>;
|
||||||
export type TSecretVersionsInsert = Omit<TSecretVersions, TImmutableDBKeys>;
|
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({
|
export const SecretsSchema = z.object({
|
||||||
id: z.string().uuid(),
|
id: z.string().uuid(),
|
||||||
version: z.number().default(1),
|
version: z.number().default(1),
|
||||||
type: z.string().default('shared'),
|
type: z.string().default("shared"),
|
||||||
secretBlindIndex: z.string(),
|
secretBlindIndex: z.string().nullable().optional(),
|
||||||
secretKeyCiphertext: z.string(),
|
secretKeyCiphertext: z.string(),
|
||||||
secretKeyIV: z.string(),
|
secretKeyIV: z.string(),
|
||||||
secretKeyTag: z.string(),
|
secretKeyTag: z.string(),
|
||||||
@@ -24,8 +24,8 @@ export const SecretsSchema = z.object({
|
|||||||
secretReminderNote: z.string().nullable().optional(),
|
secretReminderNote: z.string().nullable().optional(),
|
||||||
secretReminderRepeatDays: z.number().nullable().optional(),
|
secretReminderRepeatDays: z.number().nullable().optional(),
|
||||||
skipMultilineEncoding: z.boolean().default(false).nullable().optional(),
|
skipMultilineEncoding: z.boolean().default(false).nullable().optional(),
|
||||||
algorithm: z.string().default('aes-256-gcm'),
|
algorithm: z.string().default("aes-256-gcm"),
|
||||||
keyEncoding: z.string().default('utf8'),
|
keyEncoding: z.string().default("utf8"),
|
||||||
metadata: z.unknown().nullable().optional(),
|
metadata: z.unknown().nullable().optional(),
|
||||||
userId: z.string().uuid().nullable().optional(),
|
userId: z.string().uuid().nullable().optional(),
|
||||||
folderId: z.string().uuid(),
|
folderId: z.string().uuid(),
|
||||||
|
|||||||
@@ -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