streamby-core 0.33.0 → 0.35.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/CHANGELOG.md +100 -0
  2. package/LICENSE +661 -0
  3. package/README.md +111 -11
  4. package/dist/adapters/database/connectionManager.js +18 -0
  5. package/dist/index.d.ts +3 -1
  6. package/dist/index.js +4 -1
  7. package/dist/middleware/createRouter.js +19 -2
  8. package/dist/middleware/routes/ai.js +3 -3
  9. package/dist/middleware/routes/{credential.d.ts → apiToken.d.ts} +1 -1
  10. package/dist/middleware/routes/apiToken.js +58 -0
  11. package/dist/middleware/routes/connection.js +3 -12
  12. package/dist/middleware/routes/dbConnection.js +7 -26
  13. package/dist/middleware/routes/distribution.js +12 -5
  14. package/dist/middleware/routes/export.js +5 -4
  15. package/dist/middleware/routes/media.js +27 -10
  16. package/dist/middleware/routes/member.js +3 -12
  17. package/dist/middleware/routes/pipeline.js +3 -3
  18. package/dist/middleware/routes/production.js +9 -9
  19. package/dist/middleware/routes/project.js +12 -25
  20. package/dist/middleware/routes/renderFarm.js +13 -6
  21. package/dist/middleware/routes/review.js +4 -4
  22. package/dist/middleware/routes/rights.js +1 -1
  23. package/dist/middleware/routes/storage.js +21 -15
  24. package/dist/middleware/routes/storageConnection.js +2 -8
  25. package/dist/middleware/routes/workflow.js +1 -1
  26. package/dist/services/apiTokens.d.ts +47 -0
  27. package/dist/services/apiTokens.js +110 -0
  28. package/dist/services/auth.d.ts +5 -3
  29. package/dist/services/auth.js +49 -11
  30. package/dist/services/connectionResolver.js +2 -2
  31. package/dist/services/executor.d.ts +4 -1
  32. package/dist/services/executor.js +29 -11
  33. package/dist/services/reencryptCredentials.d.ts +5 -0
  34. package/dist/services/reencryptCredentials.js +74 -0
  35. package/dist/services/userIntegration.d.ts +2 -2
  36. package/dist/services/userIntegration.js +7 -1
  37. package/dist/services/wsHub.js +6 -0
  38. package/dist/types/index.d.ts +9 -0
  39. package/dist/utils/auth.d.ts +15 -1
  40. package/dist/utils/auth.js +21 -6
  41. package/dist/utils/encryption.d.ts +6 -1
  42. package/dist/utils/encryption.js +80 -27
  43. package/dist/utils/serviceEndpoints.d.ts +2 -0
  44. package/dist/utils/serviceEndpoints.js +26 -0
  45. package/package.json +4 -3
  46. package/dist/middleware/routes/apiConnection.d.ts +0 -3
  47. package/dist/middleware/routes/apiConnection.js +0 -100
  48. package/dist/middleware/routes/credential.js +0 -80
  49. package/dist/services/apiConnection.d.ts +0 -18
  50. package/dist/services/apiConnection.js +0 -65
  51. package/dist/services/credential.d.ts +0 -8
  52. package/dist/services/credential.js +0 -70
  53. package/dist/services/pipeline.d.ts +0 -2
  54. package/dist/services/pipeline.js +0 -292
@@ -33,43 +33,96 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.isEncryptionKeySet = exports.decrypt = exports.encrypt = exports.setEncryptionKey = void 0;
36
+ exports.isEncryptionKeySet = exports.isVersionedEncryption = exports.isCurrentEncryption = exports.decrypt = exports.encrypt = exports.setEncryptionKey = void 0;
37
37
  const crypto = __importStar(require("crypto"));
38
- const ALGORITHM = 'aes-256-cbc';
39
- const IV_LENGTH = 16; // For AES, this is always 16
40
- let ENCRYPTION_KEY = undefined;
41
- const setEncryptionKey = (key) => {
42
- if (key.length !== 64) { // 32 bytes * 2 hex characters per byte
38
+ // Stored credentials, encrypted with AES-256-GCM (authenticated: an altered value fails to
39
+ // decrypt instead of decrypting to garbage), each value naming the key it was encrypted with:
40
+ //
41
+ // v2:<key id>:<iv>:<auth tag>:<ciphertext> (base64url parts; a 12-byte iv)
42
+ //
43
+ // A key's id is a fingerprint of it, so rotating is only configuring the new key as the
44
+ // current one and the old ones as previous keys: what's stored keeps decrypting, and is
45
+ // re-encrypted with the current key (see services/reencryptCredentials).
46
+ //
47
+ // Values stored before (AES-256-CBC, "<iv hex>:<ciphertext hex>", no key id) still decrypt,
48
+ // with the current key or a previous one.
49
+ const GCM = 'aes-256-gcm';
50
+ const GCM_IV_LENGTH = 12;
51
+ const LEGACY_CBC = 'aes-256-cbc';
52
+ const VERSION = 'v2';
53
+ let currentKey;
54
+ const keysById = new Map();
55
+ const keyBuffer = (hex) => {
56
+ if (typeof hex !== 'string' || !/^[0-9a-fA-F]{64}$/.test(hex)) {
43
57
  throw new Error('Invalid encryption key length. Key must be 32 bytes (64 hexadecimal characters).');
44
58
  }
45
- ENCRYPTION_KEY = key;
59
+ return Buffer.from(hex, 'hex');
60
+ };
61
+ // A key's id: a fingerprint of it (never the key, nor enough to find it).
62
+ const keyIdOf = (key) => crypto.createHash('sha256').update('streamby-encryption-key:').update(key).digest('hex').slice(0, 16);
63
+ /** The key credentials are encrypted with, and the previous ones they may still be in. */
64
+ const setEncryptionKey = (key, previousKeys = []) => {
65
+ const current = keyBuffer(key);
66
+ const previous = previousKeys.map(keyBuffer);
67
+ keysById.clear();
68
+ for (const k of [...previous, current])
69
+ keysById.set(keyIdOf(k), k);
70
+ currentKey = { id: keyIdOf(current), key: current };
46
71
  };
47
72
  exports.setEncryptionKey = setEncryptionKey;
73
+ const requireKey = () => {
74
+ if (!currentKey)
75
+ throw new Error('Encryption key is not set. Cannot encrypt or decrypt credentials.');
76
+ return currentKey;
77
+ };
48
78
  const encrypt = (text) => {
49
- if (!ENCRYPTION_KEY) {
50
- throw new Error('Encryption key is not set. Cannot encrypt credentials.');
51
- }
52
- const iv = crypto.randomBytes(IV_LENGTH);
53
- const cipher = crypto.createCipheriv(ALGORITHM, Buffer.from(ENCRYPTION_KEY, 'hex'), iv);
54
- let encrypted = cipher.update(text);
55
- encrypted = Buffer.concat([encrypted, cipher.final()]);
56
- return iv.toString('hex') + ':' + encrypted.toString('hex');
79
+ const { id, key } = requireKey();
80
+ const iv = crypto.randomBytes(GCM_IV_LENGTH);
81
+ const cipher = crypto.createCipheriv(GCM, key, iv);
82
+ const encrypted = Buffer.concat([cipher.update(text, 'utf8'), cipher.final()]);
83
+ const tag = cipher.getAuthTag();
84
+ return [VERSION, id, iv.toString('base64url'), tag.toString('base64url'), encrypted.toString('base64url')].join(':');
57
85
  };
58
86
  exports.encrypt = encrypt;
87
+ const decryptLegacy = (text, key) => {
88
+ const [ivHex, ...rest] = text.split(':');
89
+ const decipher = crypto.createDecipheriv(LEGACY_CBC, key, Buffer.from(ivHex, 'hex'));
90
+ return Buffer.concat([decipher.update(Buffer.from(rest.join(':'), 'hex')), decipher.final()]).toString();
91
+ };
59
92
  const decrypt = (text) => {
60
- if (!ENCRYPTION_KEY) {
61
- throw new Error('Encryption key is not set. Cannot decrypt credentials.');
93
+ requireKey();
94
+ if (text.startsWith(`${VERSION}:`)) {
95
+ const [, id, iv, tag, encrypted] = text.split(':');
96
+ const key = keysById.get(id);
97
+ if (!key)
98
+ throw new Error('This credential was encrypted with a key that is not configured.');
99
+ const decipher = crypto.createDecipheriv(GCM, key, Buffer.from(iv, 'base64url'));
100
+ decipher.setAuthTag(Buffer.from(tag, 'base64url'));
101
+ try {
102
+ return Buffer.concat([decipher.update(Buffer.from(encrypted, 'base64url')), decipher.final()]).toString('utf8');
103
+ }
104
+ catch {
105
+ throw new Error('This credential could not be decrypted: it was altered or damaged.');
106
+ }
107
+ }
108
+ // Stored before: CBC, with whichever configured key it was encrypted with.
109
+ let lastError;
110
+ for (const key of [currentKey.key, ...[...keysById.values()].filter(k => k !== currentKey.key)]) {
111
+ try {
112
+ return decryptLegacy(text, key);
113
+ }
114
+ catch (err) {
115
+ lastError = err;
116
+ }
62
117
  }
63
- const textParts = text.split(':');
64
- const iv = Buffer.from(textParts.shift(), 'hex');
65
- const encryptedText = Buffer.from(textParts.join(':'), 'hex');
66
- const decipher = crypto.createDecipheriv(ALGORITHM, Buffer.from(ENCRYPTION_KEY, 'hex'), iv);
67
- let decrypted = decipher.update(encryptedText);
68
- decrypted = Buffer.concat([decrypted, decipher.final()]);
69
- return decrypted.toString();
118
+ throw lastError instanceof Error ? lastError : new Error('This credential could not be decrypted.');
70
119
  };
71
120
  exports.decrypt = decrypt;
72
- const isEncryptionKeySet = () => {
73
- return !!ENCRYPTION_KEY;
74
- };
121
+ /** Whether a stored value is encrypted the current way (GCM, with the current key). */
122
+ const isCurrentEncryption = (text) => !!currentKey && text.startsWith(`${VERSION}:${currentKey.id}:`);
123
+ exports.isCurrentEncryption = isCurrentEncryption;
124
+ /** Whether a stored value is in this module's own format (GCM, any key). */
125
+ const isVersionedEncryption = (text) => text.startsWith(`${VERSION}:`);
126
+ exports.isVersionedEncryption = isVersionedEncryption;
127
+ const isEncryptionKeySet = () => !!currentKey;
75
128
  exports.isEncryptionKeySet = isEncryptionKeySet;
@@ -0,0 +1,2 @@
1
+ import { ServiceProviderType } from '../types';
2
+ export declare function isServiceEndpoint(provider: ServiceProviderType, endpoint: unknown): endpoint is string;
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isServiceEndpoint = isServiceEndpoint;
4
+ // Where a service integration's credential may be sent: its own provider's API, over https.
5
+ // A node chooses the endpoint it calls, and anyone who can edit the node could otherwise point
6
+ // it at a server of their own and receive the credential of whoever connected the integration.
7
+ const PROVIDER_HOSTS = {
8
+ claude: (host) => host === 'api.anthropic.com',
9
+ jira: (host) => host === 'api.atlassian.com' || host.endsWith('.atlassian.net'),
10
+ google: (host) => host === 'googleapis.com' || host.endsWith('.googleapis.com'),
11
+ };
12
+ function isServiceEndpoint(provider, endpoint) {
13
+ if (typeof endpoint !== 'string')
14
+ return false;
15
+ let url;
16
+ try {
17
+ url = new URL(endpoint);
18
+ }
19
+ catch {
20
+ return false;
21
+ }
22
+ if (url.protocol !== 'https:' || url.username || url.password || url.port)
23
+ return false;
24
+ const allowed = PROVIDER_HOSTS[provider];
25
+ return !!allowed && allowed(url.hostname.toLowerCase());
26
+ }
package/package.json CHANGED
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "name": "streamby-core",
3
- "version": "0.33.0",
3
+ "version": "0.35.0",
4
4
  "description": "StreamBy middleware framework for media storage management",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "files": [
8
- "dist"
8
+ "dist",
9
+ "CHANGELOG.md"
9
10
  ],
10
11
  "scripts": {
11
12
  "build": "tsc",
@@ -27,7 +28,7 @@
27
28
  "typescript"
28
29
  ],
29
30
  "author": "TerminalCore Labs",
30
- "license": "MIT",
31
+ "license": "AGPL-3.0-only",
31
32
  "dependencies": {
32
33
  "@aws-sdk/client-s3": "^3.528.0",
33
34
  "@aws-sdk/s3-request-presigner": "^3.787.0",
@@ -1,3 +0,0 @@
1
- import { Router } from 'express';
2
- import { StreamByConfig } from '../../types';
3
- export declare function apiConnectionRouter(config: StreamByConfig): Router;
@@ -1,100 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.apiConnectionRouter = apiConnectionRouter;
4
- const express_1 = require("express");
5
- const manager_1 = require("../../models/manager");
6
- const auth_1 = require("../../utils/auth");
7
- const apiConnection_1 = require("../../services/apiConnection");
8
- const VALID_METHODS = ['GET', 'POST', 'PATCH', 'PUT', 'DELETE'];
9
- function apiConnectionRouter(config) {
10
- const router = (0, express_1.Router)();
11
- const Project = (0, manager_1.getModel)('projects');
12
- // List API connections for a project
13
- router.get('/projects/:id/api/connections', async (req, res) => {
14
- try {
15
- const auth = req.auth;
16
- const projectId = req.params.id;
17
- const project = await Project.findOne({ _id: projectId });
18
- if (!project) {
19
- return res.status(404).json({ message: 'Project not found' });
20
- }
21
- if (!(0, auth_1.isProjectMember)(project, auth.userId)) {
22
- return res.status(403).json({ message: 'Unauthorized project access' });
23
- }
24
- return res.status(200).json({ data: project.apiConnections || [] });
25
- }
26
- catch (err) {
27
- res.status(500).json({ message: 'Failed to fetch API connections', details: err.message });
28
- }
29
- });
30
- // Add a new API connection to a project
31
- router.post('/projects/:id/api/connections', async (req, res) => {
32
- try {
33
- const auth = req.auth;
34
- if (auth.role !== 'admin' && auth.role !== 'editor') {
35
- return res.status(403).json({ message: 'Permission denied' });
36
- }
37
- const projectId = req.params.id;
38
- const { name, baseUrl, method, description, credentialId, prefix } = req.body;
39
- if (!name || !baseUrl) {
40
- return res.status(400).json({ message: 'name and baseUrl are required' });
41
- }
42
- if (!VALID_METHODS.includes(method)) {
43
- return res.status(400).json({ message: `method must be one of: ${VALID_METHODS.join(', ')}` });
44
- }
45
- const project = await Project.findOne({ _id: projectId });
46
- if (!project) {
47
- return res.status(404).json({ message: 'Project not found' });
48
- }
49
- if (!(0, auth_1.isProjectMember)(project, auth.userId)) {
50
- return res.status(403).json({ message: 'Unauthorized project access' });
51
- }
52
- if (credentialId) {
53
- const credExists = project.credentials?.some((c) => c.id === credentialId);
54
- if (!credExists) {
55
- return res.status(400).json({ message: 'Credential not found in project' });
56
- }
57
- }
58
- const connection = await (0, apiConnection_1.addApiConnection)(config, projectId, {
59
- name,
60
- baseUrl,
61
- method,
62
- prefix,
63
- ...(description !== undefined && { description }),
64
- ...(credentialId !== undefined && { credentialId }),
65
- });
66
- return res.status(201).json({ data: connection });
67
- }
68
- catch (err) {
69
- res.status(500).json({ message: 'Failed to add API connection', details: err.message });
70
- }
71
- });
72
- // Delete an API connection from a project
73
- router.delete('/projects/:id/api/connections/:connectionId', async (req, res) => {
74
- try {
75
- const auth = req.auth;
76
- if (auth.role !== 'admin' && auth.role !== 'editor') {
77
- return res.status(403).json({ message: 'Permission denied' });
78
- }
79
- const projectId = req.params.id;
80
- const { connectionId } = req.params;
81
- const project = await Project.findOne({ _id: projectId });
82
- if (!project) {
83
- return res.status(404).json({ message: 'Project not found' });
84
- }
85
- if (!(0, auth_1.isProjectMember)(project, auth.userId)) {
86
- return res.status(403).json({ message: 'Unauthorized project access' });
87
- }
88
- const exists = project.apiConnections?.some((c) => c.id === connectionId);
89
- if (!exists) {
90
- return res.status(404).json({ message: 'API connection not found' });
91
- }
92
- await (0, apiConnection_1.deleteApiConnection)(config, projectId, connectionId);
93
- return res.status(200).json({ message: 'API connection deleted successfully.' });
94
- }
95
- catch (err) {
96
- res.status(500).json({ message: 'Failed to delete API connection', details: err.message });
97
- }
98
- });
99
- return router;
100
- }
@@ -1,80 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.credentialRouter = credentialRouter;
4
- const express_1 = require("express");
5
- const manager_1 = require("../../models/manager");
6
- const auth_1 = require("../../utils/auth");
7
- const sanitize_1 = require("../../utils/sanitize");
8
- const credential_1 = require("../../services/credential");
9
- function credentialRouter(config) {
10
- const router = (0, express_1.Router)();
11
- const Project = (0, manager_1.getModel)('projects');
12
- // Add a new credential to a project
13
- router.post('/projects/:id/credentials', async (req, res) => {
14
- try {
15
- const auth = req.auth;
16
- if (auth.role !== 'admin' && auth.role !== 'editor') {
17
- return res.status(403).json({ message: 'Permission denied' });
18
- }
19
- const projectId = req.params.id;
20
- const { id, key, value } = req.body;
21
- if (!key || !value) {
22
- return res.status(400).json({ message: 'Missing credential key or value' });
23
- }
24
- const project = await Project.findOne({ _id: projectId });
25
- if (!project || !(0, auth_1.isProjectMember)(project, auth.userId)) {
26
- return res.status(403).json({ message: 'Unauthorized project access' });
27
- }
28
- const updatedProject = await (0, credential_1.addCredential)(config, projectId, { id, key, value });
29
- res.status(201).json({ message: 'Credential added successfully', project: (0, sanitize_1.sanitizeProject)(updatedProject) });
30
- }
31
- catch (err) {
32
- res.status(500).json({ message: 'Failed to add credential', details: err.message });
33
- }
34
- });
35
- // Update an existing credential in a project
36
- router.patch('/projects/:id/credentials/:credentialId', async (req, res) => {
37
- try {
38
- const auth = req.auth;
39
- if (auth.role !== 'admin' && auth.role !== 'editor') {
40
- return res.status(403).json({ message: 'Permission denied' });
41
- }
42
- const projectId = req.params.id;
43
- const credentialId = req.params.credentialId;
44
- const { key, value } = req.body;
45
- if (!key && !value) {
46
- return res.status(400).json({ message: 'No update fields provided' });
47
- }
48
- const project = await Project.findOne({ _id: projectId });
49
- if (!project || !(0, auth_1.isProjectMember)(project, auth.userId)) {
50
- return res.status(403).json({ message: 'Unauthorized project access' });
51
- }
52
- const updatedProject = await (0, credential_1.updateCredential)(config, projectId, credentialId, { key, value });
53
- res.status(200).json({ message: 'Credential updated successfully', project: (0, sanitize_1.sanitizeProject)(updatedProject) });
54
- }
55
- catch (err) {
56
- res.status(500).json({ message: 'Failed to update credential', details: err.message });
57
- }
58
- });
59
- // Delete a credential from a project
60
- router.delete('/projects/:id/credentials/:credentialId', async (req, res) => {
61
- try {
62
- const auth = req.auth;
63
- if (auth.role !== 'admin' && auth.role !== 'editor') {
64
- return res.status(403).json({ message: 'Permission denied' });
65
- }
66
- const projectId = req.params.id;
67
- const credentialId = req.params.credentialId;
68
- const project = await Project.findOne({ _id: projectId });
69
- if (!project || !(0, auth_1.isProjectMember)(project, auth.userId)) {
70
- return res.status(403).json({ message: 'Unauthorized project access' });
71
- }
72
- const updatedProject = await (0, credential_1.deleteCredential)(config, projectId, credentialId);
73
- res.status(200).json({ message: 'Credential deleted successfully', project: (0, sanitize_1.sanitizeProject)(updatedProject) });
74
- }
75
- catch (err) {
76
- res.status(500).json({ message: 'Failed to delete credential', details: err.message });
77
- }
78
- });
79
- return router;
80
- }
@@ -1,18 +0,0 @@
1
- import { StreamByConfig, ApiConnection, ApiConnectionMethod } from '../types';
2
- export declare function addApiConnection(config: StreamByConfig, projectId: string, data: {
3
- name: string;
4
- apiUrl: string;
5
- method: ApiConnectionMethod;
6
- prefix?: string;
7
- description?: string;
8
- credentialId?: string;
9
- }): Promise<ApiConnection>;
10
- export declare function updateApiConnection(config: StreamByConfig, projectId: string, connectionId: string, data: {
11
- name?: string;
12
- apiUrl?: string;
13
- method?: ApiConnectionMethod;
14
- prefix?: string;
15
- description?: string;
16
- credentialId?: string;
17
- }): Promise<ApiConnection>;
18
- export declare function deleteApiConnection(config: StreamByConfig, projectId: string, connectionId: string): Promise<void>;
@@ -1,65 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.addApiConnection = addApiConnection;
4
- exports.updateApiConnection = updateApiConnection;
5
- exports.deleteApiConnection = deleteApiConnection;
6
- const mongodb_1 = require("mongodb");
7
- const manager_1 = require("../models/manager");
8
- async function addApiConnection(config, projectId, data) {
9
- const ProjectModel = (0, manager_1.getModel)('projects');
10
- const project = await ProjectModel.findOne({ _id: projectId });
11
- if (!project) {
12
- throw new Error('Project not found.');
13
- }
14
- const connection = {
15
- id: new mongodb_1.ObjectId().toHexString(),
16
- name: data.name,
17
- prefix: data.prefix,
18
- apiUrl: data.apiUrl,
19
- method: data.method,
20
- projectId,
21
- createdAt: new Date(),
22
- ...(data.description !== undefined && { description: data.description }),
23
- ...(data.credentialId !== undefined && { credentialId: data.credentialId }),
24
- };
25
- const updatedProject = await ProjectModel.update({ _id: projectId }, { $push: { apiConnections: connection } });
26
- if (!updatedProject) {
27
- throw new Error('Failed to add API connection to project.');
28
- }
29
- return connection;
30
- }
31
- async function updateApiConnection(config, projectId, connectionId, data) {
32
- const ProjectModel = (0, manager_1.getModel)('projects');
33
- const project = await ProjectModel.findOne({ _id: projectId });
34
- if (!project)
35
- throw new Error('Project not found.');
36
- const connections = project.apiConnections ?? [];
37
- const index = connections.findIndex((c) => c.id === connectionId);
38
- if (index === -1)
39
- throw new Error('API connection not found.');
40
- const updated = {
41
- ...connections[index],
42
- ...(data.name !== undefined && { name: data.name }),
43
- ...(data.apiUrl !== undefined && { apiUrl: data.apiUrl }),
44
- ...(data.method !== undefined && { method: data.method }),
45
- ...(data.prefix !== undefined && { prefix: data.prefix }),
46
- ...(data.description !== undefined && { description: data.description }),
47
- ...(data.credentialId !== undefined && { credentialId: data.credentialId }),
48
- };
49
- connections[index] = updated;
50
- const result = await ProjectModel.update({ _id: projectId }, { $set: { apiConnections: connections } });
51
- if (!result)
52
- throw new Error('Failed to update API connection.');
53
- return updated;
54
- }
55
- async function deleteApiConnection(config, projectId, connectionId) {
56
- const ProjectModel = (0, manager_1.getModel)('projects');
57
- const project = await ProjectModel.findOne({ _id: projectId });
58
- if (!project) {
59
- throw new Error('Project not found.');
60
- }
61
- const updatedProject = await ProjectModel.update({ _id: projectId }, { $pull: { apiConnections: { id: connectionId } } });
62
- if (!updatedProject) {
63
- throw new Error('Failed to delete API connection from project.');
64
- }
65
- }
@@ -1,8 +0,0 @@
1
- import { StreamByConfig, Credential, ProjectInfo } from '../types';
2
- export declare function addCredential(config: StreamByConfig, projectId: string, newCredential: Omit<Credential, 'encryptedValue'> & {
3
- value: string;
4
- }): Promise<ProjectInfo>;
5
- export declare function updateCredential(config: StreamByConfig, projectId: string, credentialId: string, updates: Partial<Omit<Credential, 'encryptedValue'> & {
6
- value: string;
7
- }>): Promise<ProjectInfo>;
8
- export declare function deleteCredential(config: StreamByConfig, projectId: string, credentialId: string): Promise<ProjectInfo>;
@@ -1,70 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.addCredential = addCredential;
4
- exports.updateCredential = updateCredential;
5
- exports.deleteCredential = deleteCredential;
6
- const manager_1 = require("../models/manager");
7
- const encryption_1 = require("../utils/encryption");
8
- const mongodb_1 = require("mongodb");
9
- async function addCredential(config, projectId, newCredential) {
10
- if (!(0, encryption_1.isEncryptionKeySet)()) {
11
- throw new Error('Encryption key is not set. Cannot add credentials.');
12
- }
13
- const ProjectModel = (0, manager_1.getModel)('projects');
14
- const project = await ProjectModel.findOne({ _id: projectId });
15
- if (!project) {
16
- throw new Error('Project not found.');
17
- }
18
- const encryptedValue = (0, encryption_1.encrypt)(newCredential.value);
19
- const credentialToSave = {
20
- id: newCredential.id || new mongodb_1.ObjectId().toHexString(), // Generate ID if not provided
21
- key: newCredential.key,
22
- encryptedValue: encryptedValue,
23
- };
24
- const updatedProject = await ProjectModel.update({ _id: projectId }, { $push: { credentials: credentialToSave } });
25
- if (!updatedProject) {
26
- throw new Error('Failed to add credential to project.');
27
- }
28
- return updatedProject;
29
- }
30
- async function updateCredential(config, projectId, credentialId, updates) {
31
- if (!(0, encryption_1.isEncryptionKeySet)()) {
32
- throw new Error('Encryption key is not set. Cannot update credentials.');
33
- }
34
- const ProjectModel = (0, manager_1.getModel)('projects');
35
- const project = await ProjectModel.findOne({ _id: projectId });
36
- if (!project) {
37
- throw new Error('Project not found.');
38
- }
39
- const credentialIndex = project.credentials?.findIndex(cred => cred.id === credentialId);
40
- if (credentialIndex === undefined || credentialIndex === -1) {
41
- throw new Error(`Credential with ID ${credentialId} not found.`);
42
- }
43
- const currentCredential = project.credentials[credentialIndex];
44
- let encryptedValue = currentCredential.encryptedValue;
45
- if (updates.value !== undefined) {
46
- encryptedValue = (0, encryption_1.encrypt)(updates.value);
47
- }
48
- const updatedCredential = {
49
- ...currentCredential,
50
- key: updates.key || currentCredential.key,
51
- encryptedValue: encryptedValue,
52
- };
53
- const updatedProject = await ProjectModel.update({ _id: projectId, 'credentials.id': credentialId }, { $set: { 'credentials.$': updatedCredential } });
54
- if (!updatedProject) {
55
- throw new Error('Failed to update credential in project.');
56
- }
57
- return updatedProject;
58
- }
59
- async function deleteCredential(config, projectId, credentialId) {
60
- const ProjectModel = (0, manager_1.getModel)('projects');
61
- const project = await ProjectModel.findOne({ _id: projectId });
62
- if (!project) {
63
- throw new Error('Project not found.');
64
- }
65
- const updatedProject = await ProjectModel.update({ _id: projectId }, { $pull: { credentials: { id: credentialId } } });
66
- if (!updatedProject) {
67
- throw new Error('Failed to delete credential from project.');
68
- }
69
- return updatedProject;
70
- }
@@ -1,2 +0,0 @@
1
- import { NodeSchema, StreamByConfig } from '../types';
2
- export declare function executePipeline(nodeSchema: NodeSchema, project: any, config: StreamByConfig): Promise<any>;