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.
- package/CHANGELOG.md +100 -0
- package/LICENSE +661 -0
- package/README.md +111 -11
- package/dist/adapters/database/connectionManager.js +18 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +4 -1
- package/dist/middleware/createRouter.js +19 -2
- package/dist/middleware/routes/ai.js +3 -3
- package/dist/middleware/routes/{credential.d.ts → apiToken.d.ts} +1 -1
- package/dist/middleware/routes/apiToken.js +58 -0
- package/dist/middleware/routes/connection.js +3 -12
- package/dist/middleware/routes/dbConnection.js +7 -26
- package/dist/middleware/routes/distribution.js +12 -5
- package/dist/middleware/routes/export.js +5 -4
- package/dist/middleware/routes/media.js +27 -10
- package/dist/middleware/routes/member.js +3 -12
- package/dist/middleware/routes/pipeline.js +3 -3
- package/dist/middleware/routes/production.js +9 -9
- package/dist/middleware/routes/project.js +12 -25
- package/dist/middleware/routes/renderFarm.js +13 -6
- package/dist/middleware/routes/review.js +4 -4
- package/dist/middleware/routes/rights.js +1 -1
- package/dist/middleware/routes/storage.js +21 -15
- package/dist/middleware/routes/storageConnection.js +2 -8
- package/dist/middleware/routes/workflow.js +1 -1
- package/dist/services/apiTokens.d.ts +47 -0
- package/dist/services/apiTokens.js +110 -0
- package/dist/services/auth.d.ts +5 -3
- package/dist/services/auth.js +49 -11
- package/dist/services/connectionResolver.js +2 -2
- package/dist/services/executor.d.ts +4 -1
- package/dist/services/executor.js +29 -11
- package/dist/services/reencryptCredentials.d.ts +5 -0
- package/dist/services/reencryptCredentials.js +74 -0
- package/dist/services/userIntegration.d.ts +2 -2
- package/dist/services/userIntegration.js +7 -1
- package/dist/services/wsHub.js +6 -0
- package/dist/types/index.d.ts +9 -0
- package/dist/utils/auth.d.ts +15 -1
- package/dist/utils/auth.js +21 -6
- package/dist/utils/encryption.d.ts +6 -1
- package/dist/utils/encryption.js +80 -27
- package/dist/utils/serviceEndpoints.d.ts +2 -0
- package/dist/utils/serviceEndpoints.js +26 -0
- package/package.json +4 -3
- package/dist/middleware/routes/apiConnection.d.ts +0 -3
- package/dist/middleware/routes/apiConnection.js +0 -100
- package/dist/middleware/routes/credential.js +0 -80
- package/dist/services/apiConnection.d.ts +0 -18
- package/dist/services/apiConnection.js +0 -65
- package/dist/services/credential.d.ts +0 -8
- package/dist/services/credential.js +0 -70
- package/dist/services/pipeline.d.ts +0 -2
- package/dist/services/pipeline.js +0 -292
|
@@ -8,6 +8,7 @@ const jobQueue_1 = require("../../services/jobQueue");
|
|
|
8
8
|
const mediaProcessor_1 = require("../../services/mediaProcessor");
|
|
9
9
|
const storage_1 = require("../../providers/storage");
|
|
10
10
|
const connectionManager_1 = require("../../adapters/database/connectionManager");
|
|
11
|
+
const auth_2 = require("../../services/auth");
|
|
11
12
|
function getMetadataCollection() {
|
|
12
13
|
const ids = (0, connectionManager_1.getConnectedIds)().filter(id => (0, connectionManager_1.getConnection)(id).type === 'nosql');
|
|
13
14
|
if (!ids.length)
|
|
@@ -25,11 +26,27 @@ function mediaRouter(config) {
|
|
|
25
26
|
const adapter = config.adapter || (0, storage_1.createStorageProvider)(config.storageProviders);
|
|
26
27
|
const Project = (0, manager_1.getModel)('projects');
|
|
27
28
|
// GET /jobs/:jobId — poll job status
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
// Only for whoever started it, or a member of its project: someone else's job is as if it
|
|
30
|
+
// didn't exist.
|
|
31
|
+
router.get('/jobs/:jobId', async (req, res) => {
|
|
32
|
+
try {
|
|
33
|
+
const auth = req.auth;
|
|
34
|
+
const job = (0, jobQueue_1.getJob)(req.params.jobId);
|
|
35
|
+
if (!job)
|
|
36
|
+
return res.status(404).json({ message: 'Job not found' });
|
|
37
|
+
// With an API token, only a job of a project it reaches.
|
|
38
|
+
if (!(0, auth_2.scopeReachesProject)(auth.apiToken, job.projectId))
|
|
39
|
+
return res.status(404).json({ message: 'Job not found' });
|
|
40
|
+
if (job.userId !== auth.userId) {
|
|
41
|
+
const project = await Project.findOne({ _id: job.projectId });
|
|
42
|
+
if (!(0, auth_1.isProjectMember)(project, auth.userId))
|
|
43
|
+
return res.status(404).json({ message: 'Job not found' });
|
|
44
|
+
}
|
|
45
|
+
res.json({ job });
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
res.status(500).json({ message: 'Failed to fetch job', details: err.message });
|
|
49
|
+
}
|
|
33
50
|
});
|
|
34
51
|
// POST /projects/:projectId/jobs/ingest — queue an ingest job for an already-uploaded file
|
|
35
52
|
router.post('/projects/:projectId/jobs/ingest', async (req, res) => {
|
|
@@ -42,7 +59,7 @@ function mediaRouter(config) {
|
|
|
42
59
|
const project = await Project.findOne({ _id: projectId });
|
|
43
60
|
if (!project)
|
|
44
61
|
return res.status(404).json({ message: 'Project not found' });
|
|
45
|
-
if (!(0, auth_1.
|
|
62
|
+
if (!(0, auth_1.canEditProject)(project, auth.userId))
|
|
46
63
|
return res.status(403).json({ message: 'Unauthorized' });
|
|
47
64
|
const job = (0, jobQueue_1.createJob)('ingest', auth.userId, projectId, { fileId });
|
|
48
65
|
// Run async — response returns immediately with jobId
|
|
@@ -64,7 +81,7 @@ function mediaRouter(config) {
|
|
|
64
81
|
const project = await Project.findOne({ _id: projectId });
|
|
65
82
|
if (!project)
|
|
66
83
|
return res.status(404).json({ message: 'Project not found' });
|
|
67
|
-
if (!(0, auth_1.
|
|
84
|
+
if (!(0, auth_1.canEditProject)(project, auth.userId))
|
|
68
85
|
return res.status(403).json({ message: 'Unauthorized' });
|
|
69
86
|
const job = (0, jobQueue_1.createJob)('transcode', auth.userId, projectId, {
|
|
70
87
|
fileId, codec, resolution, outputFormat, bitrate, audioCodec,
|
|
@@ -87,7 +104,7 @@ function mediaRouter(config) {
|
|
|
87
104
|
const project = await Project.findOne({ _id: projectId });
|
|
88
105
|
if (!project)
|
|
89
106
|
return res.status(404).json({ message: 'Project not found' });
|
|
90
|
-
if (!(0, auth_1.
|
|
107
|
+
if (!(0, auth_1.canEditProject)(project, auth.userId))
|
|
91
108
|
return res.status(403).json({ message: 'Unauthorized' });
|
|
92
109
|
const job = (0, jobQueue_1.createJob)('thumbnail', auth.userId, projectId, { fileId, timecode, resolution, strategy });
|
|
93
110
|
setImmediate(() => (0, mediaProcessor_1.runThumbnailJob)(job.jobId, fileId, projectId, { timecode, resolution, strategy }));
|
|
@@ -108,7 +125,7 @@ function mediaRouter(config) {
|
|
|
108
125
|
const project = await Project.findOne({ _id: projectId });
|
|
109
126
|
if (!project)
|
|
110
127
|
return res.status(404).json({ message: 'Project not found' });
|
|
111
|
-
if (!(0, auth_1.
|
|
128
|
+
if (!(0, auth_1.canEditProject)(project, auth.userId))
|
|
112
129
|
return res.status(403).json({ message: 'Unauthorized' });
|
|
113
130
|
const job = (0, jobQueue_1.createJob)('caption', auth.userId, projectId, { fileId, sourceLanguage, outputFormat, provider });
|
|
114
131
|
setImmediate(() => (0, mediaProcessor_1.runCaptionJob)(job.jobId, fileId, projectId, { sourceLanguage, outputFormat, provider }));
|
|
@@ -150,7 +167,7 @@ function mediaRouter(config) {
|
|
|
150
167
|
const project = await Project.findOne({ _id: projectId });
|
|
151
168
|
if (!project)
|
|
152
169
|
return res.status(404).json({ message: 'Project not found' });
|
|
153
|
-
if (!(0, auth_1.
|
|
170
|
+
if (!(0, auth_1.canEditProject)(project, auth.userId))
|
|
154
171
|
return res.status(403).json({ message: 'Unauthorized' });
|
|
155
172
|
const col = getMetadataCollection();
|
|
156
173
|
if (!col)
|
|
@@ -52,9 +52,6 @@ function memberRouter(config) {
|
|
|
52
52
|
router.post('/projects/:id/members', async (req, res) => {
|
|
53
53
|
try {
|
|
54
54
|
const auth = req.auth;
|
|
55
|
-
if (auth.role !== 'admin') {
|
|
56
|
-
return res.status(403).json({ message: 'Only admins can invite members' });
|
|
57
|
-
}
|
|
58
55
|
const projectId = req.params.id;
|
|
59
56
|
const { userId, role } = req.body;
|
|
60
57
|
if (!userId || !role) {
|
|
@@ -67,7 +64,7 @@ function memberRouter(config) {
|
|
|
67
64
|
if (!project) {
|
|
68
65
|
return res.status(404).json({ message: 'Project not found' });
|
|
69
66
|
}
|
|
70
|
-
if (!(0, auth_1.
|
|
67
|
+
if (!(0, auth_1.isProjectAdmin)(project, auth.userId)) {
|
|
71
68
|
return res.status(403).json({ message: 'Unauthorized project access' });
|
|
72
69
|
}
|
|
73
70
|
const alreadyMember = project.members?.some((m) => m.userId?.toString() === userId?.toString());
|
|
@@ -107,9 +104,6 @@ function memberRouter(config) {
|
|
|
107
104
|
router.patch('/projects/:id/members/:userId', async (req, res) => {
|
|
108
105
|
try {
|
|
109
106
|
const auth = req.auth;
|
|
110
|
-
if (auth.role !== 'admin') {
|
|
111
|
-
return res.status(403).json({ message: 'Only admins can update member roles' });
|
|
112
|
-
}
|
|
113
107
|
const projectId = req.params.id;
|
|
114
108
|
const targetUserId = req.params.userId;
|
|
115
109
|
const { role } = req.body;
|
|
@@ -120,7 +114,7 @@ function memberRouter(config) {
|
|
|
120
114
|
if (!project) {
|
|
121
115
|
return res.status(404).json({ message: 'Project not found' });
|
|
122
116
|
}
|
|
123
|
-
if (!(0, auth_1.
|
|
117
|
+
if (!(0, auth_1.isProjectAdmin)(project, auth.userId)) {
|
|
124
118
|
return res.status(403).json({ message: 'Unauthorized project access' });
|
|
125
119
|
}
|
|
126
120
|
const memberExists = project.members?.some((m) => m.userId?.toString() === targetUserId?.toString());
|
|
@@ -282,9 +276,6 @@ function memberRouter(config) {
|
|
|
282
276
|
router.delete('/projects/:id/members/:userId', async (req, res) => {
|
|
283
277
|
try {
|
|
284
278
|
const auth = req.auth;
|
|
285
|
-
if (auth.role !== 'admin') {
|
|
286
|
-
return res.status(403).json({ message: 'Only admins can remove members' });
|
|
287
|
-
}
|
|
288
279
|
const projectId = req.params.id;
|
|
289
280
|
const targetUserId = req.params.userId;
|
|
290
281
|
if (targetUserId === auth.userId) {
|
|
@@ -294,7 +285,7 @@ function memberRouter(config) {
|
|
|
294
285
|
if (!project) {
|
|
295
286
|
return res.status(404).json({ message: 'Project not found' });
|
|
296
287
|
}
|
|
297
|
-
if (!(0, auth_1.
|
|
288
|
+
if (!(0, auth_1.isProjectAdmin)(project, auth.userId)) {
|
|
298
289
|
return res.status(403).json({ message: 'Unauthorized project access' });
|
|
299
290
|
}
|
|
300
291
|
const memberExists = project.members?.some((m) => m.userId?.toString() === targetUserId?.toString());
|
|
@@ -67,7 +67,7 @@ function pipelineRouter(_config) {
|
|
|
67
67
|
const project = await Project.findOne({ _id: projectId });
|
|
68
68
|
if (!project)
|
|
69
69
|
return res.status(404).json({ message: 'Project not found' });
|
|
70
|
-
if (!(0, auth_1.
|
|
70
|
+
if (!(0, auth_1.canEditProject)(project, auth.userId))
|
|
71
71
|
return res.status(403).json({ message: 'Unauthorized' });
|
|
72
72
|
const db = getDb();
|
|
73
73
|
if (!db)
|
|
@@ -120,7 +120,7 @@ function pipelineRouter(_config) {
|
|
|
120
120
|
const project = await Project.findOne({ _id: projectId });
|
|
121
121
|
if (!project)
|
|
122
122
|
return res.status(404).json({ message: 'Project not found' });
|
|
123
|
-
if (!(0, auth_1.
|
|
123
|
+
if (!(0, auth_1.canEditProject)(project, auth.userId))
|
|
124
124
|
return res.status(403).json({ message: 'Unauthorized' });
|
|
125
125
|
const db = getDb();
|
|
126
126
|
if (!db)
|
|
@@ -154,7 +154,7 @@ function pipelineRouter(_config) {
|
|
|
154
154
|
const project = await Project.findOne({ _id: projectId });
|
|
155
155
|
if (!project)
|
|
156
156
|
return res.status(404).json({ message: 'Project not found' });
|
|
157
|
-
if (!(0, auth_1.
|
|
157
|
+
if (!(0, auth_1.canEditProject)(project, auth.userId))
|
|
158
158
|
return res.status(403).json({ message: 'Unauthorized' });
|
|
159
159
|
const db = getDb();
|
|
160
160
|
if (!db)
|
|
@@ -51,7 +51,7 @@ function productionRouter(_config) {
|
|
|
51
51
|
const project = await Project.findOne({ _id: projectId });
|
|
52
52
|
if (!project)
|
|
53
53
|
return res.status(404).json({ message: 'Project not found' });
|
|
54
|
-
if (!(0, auth_1.
|
|
54
|
+
if (!(0, auth_1.canEditProject)(project, auth.userId))
|
|
55
55
|
return res.status(403).json({ message: 'Unauthorized' });
|
|
56
56
|
const db = getDb();
|
|
57
57
|
if (!db)
|
|
@@ -81,7 +81,7 @@ function productionRouter(_config) {
|
|
|
81
81
|
const project = await Project.findOne({ _id: projectId });
|
|
82
82
|
if (!project)
|
|
83
83
|
return res.status(404).json({ message: 'Project not found' });
|
|
84
|
-
if (!(0, auth_1.
|
|
84
|
+
if (!(0, auth_1.canEditProject)(project, auth.userId))
|
|
85
85
|
return res.status(403).json({ message: 'Unauthorized' });
|
|
86
86
|
const db = getDb();
|
|
87
87
|
if (!db)
|
|
@@ -110,7 +110,7 @@ function productionRouter(_config) {
|
|
|
110
110
|
const project = await Project.findOne({ _id: projectId });
|
|
111
111
|
if (!project)
|
|
112
112
|
return res.status(404).json({ message: 'Project not found' });
|
|
113
|
-
if (!(0, auth_1.
|
|
113
|
+
if (!(0, auth_1.canEditProject)(project, auth.userId))
|
|
114
114
|
return res.status(403).json({ message: 'Unauthorized' });
|
|
115
115
|
const db = getDb();
|
|
116
116
|
if (!db)
|
|
@@ -156,7 +156,7 @@ function productionRouter(_config) {
|
|
|
156
156
|
const project = await Project.findOne({ _id: projectId });
|
|
157
157
|
if (!project)
|
|
158
158
|
return res.status(404).json({ message: 'Project not found' });
|
|
159
|
-
if (!(0, auth_1.
|
|
159
|
+
if (!(0, auth_1.canEditProject)(project, auth.userId))
|
|
160
160
|
return res.status(403).json({ message: 'Unauthorized' });
|
|
161
161
|
const db = getDb();
|
|
162
162
|
if (!db)
|
|
@@ -192,7 +192,7 @@ function productionRouter(_config) {
|
|
|
192
192
|
const project = await Project.findOne({ _id: projectId });
|
|
193
193
|
if (!project)
|
|
194
194
|
return res.status(404).json({ message: 'Project not found' });
|
|
195
|
-
if (!(0, auth_1.
|
|
195
|
+
if (!(0, auth_1.canEditProject)(project, auth.userId))
|
|
196
196
|
return res.status(403).json({ message: 'Unauthorized' });
|
|
197
197
|
const db = getDb();
|
|
198
198
|
if (!db)
|
|
@@ -231,7 +231,7 @@ function productionRouter(_config) {
|
|
|
231
231
|
const project = await Project.findOne({ _id: projectId });
|
|
232
232
|
if (!project)
|
|
233
233
|
return res.status(404).json({ message: 'Project not found' });
|
|
234
|
-
if (!(0, auth_1.
|
|
234
|
+
if (!(0, auth_1.canEditProject)(project, auth.userId))
|
|
235
235
|
return res.status(403).json({ message: 'Unauthorized' });
|
|
236
236
|
const db = getDb();
|
|
237
237
|
if (!db)
|
|
@@ -277,7 +277,7 @@ function productionRouter(_config) {
|
|
|
277
277
|
const project = await Project.findOne({ _id: projectId });
|
|
278
278
|
if (!project)
|
|
279
279
|
return res.status(404).json({ message: 'Project not found' });
|
|
280
|
-
if (!(0, auth_1.
|
|
280
|
+
if (!(0, auth_1.canEditProject)(project, auth.userId))
|
|
281
281
|
return res.status(403).json({ message: 'Unauthorized' });
|
|
282
282
|
const db = getDb();
|
|
283
283
|
if (!db)
|
|
@@ -311,7 +311,7 @@ function productionRouter(_config) {
|
|
|
311
311
|
const project = await Project.findOne({ _id: projectId });
|
|
312
312
|
if (!project)
|
|
313
313
|
return res.status(404).json({ message: 'Project not found' });
|
|
314
|
-
if (!(0, auth_1.
|
|
314
|
+
if (!(0, auth_1.canEditProject)(project, auth.userId))
|
|
315
315
|
return res.status(403).json({ message: 'Unauthorized' });
|
|
316
316
|
const db = getDb();
|
|
317
317
|
if (!db)
|
|
@@ -346,7 +346,7 @@ function productionRouter(_config) {
|
|
|
346
346
|
const project = await Project.findOne({ _id: projectId });
|
|
347
347
|
if (!project)
|
|
348
348
|
return res.status(404).json({ message: 'Project not found' });
|
|
349
|
-
if (!(0, auth_1.
|
|
349
|
+
if (!(0, auth_1.canEditProject)(project, auth.userId))
|
|
350
350
|
return res.status(403).json({ message: 'Unauthorized' });
|
|
351
351
|
const db = getDb();
|
|
352
352
|
if (!db)
|
|
@@ -8,6 +8,7 @@ const connectionManager_1 = require("../../adapters/database/connectionManager")
|
|
|
8
8
|
const sql_1 = require("../../adapters/database/sql");
|
|
9
9
|
const sanitize_1 = require("../../utils/sanitize");
|
|
10
10
|
const projectIntegration_1 = require("../../services/projectIntegration");
|
|
11
|
+
const auth_2 = require("../../services/auth");
|
|
11
12
|
function projectRouter(config) {
|
|
12
13
|
const router = (0, express_1.Router)();
|
|
13
14
|
const Project = (0, manager_1.getModel)('projects');
|
|
@@ -32,6 +33,9 @@ function projectRouter(config) {
|
|
|
32
33
|
const currentUserMember = project.members?.find((m) => m.userId?.toString() === auth.userId?.toString());
|
|
33
34
|
if (!currentUserMember || currentUserMember.status !== 'active')
|
|
34
35
|
return false;
|
|
36
|
+
// With an API token, only the projects it reaches.
|
|
37
|
+
if (!(0, auth_2.scopeReachesProject)(auth.apiToken, (project._id ?? project.id)?.toString()))
|
|
38
|
+
return false;
|
|
35
39
|
if (filterArchived !== undefined) {
|
|
36
40
|
return (currentUserMember.archived || false) === filterArchived;
|
|
37
41
|
}
|
|
@@ -72,9 +76,6 @@ function projectRouter(config) {
|
|
|
72
76
|
if (req.subscription === 'freemium') {
|
|
73
77
|
return res.status(403).json({ error: 'Freemium users cannot create projects' });
|
|
74
78
|
}
|
|
75
|
-
if (auth.role !== 'admin' && auth.role !== 'editor') {
|
|
76
|
-
return res.status(403).json({ message: 'Permission denied' });
|
|
77
|
-
}
|
|
78
79
|
const { name, description, image, allowedOrigin, public: isPublic = true, category, integrationIds } = req.body;
|
|
79
80
|
if (isPublic === false && req.subscription === 'freemium') {
|
|
80
81
|
return res.status(403).json({ error: 'Private projects require a subscriber plan' });
|
|
@@ -208,9 +209,6 @@ function projectRouter(config) {
|
|
|
208
209
|
router.patch('/projects/:id', async (req, res) => {
|
|
209
210
|
try {
|
|
210
211
|
const auth = req.auth;
|
|
211
|
-
if (auth.role !== 'admin' && auth.role !== 'editor') {
|
|
212
|
-
return res.status(403).json({ message: 'Permission denied' });
|
|
213
|
-
}
|
|
214
212
|
const projectId = req.params.id;
|
|
215
213
|
const updates = req.body;
|
|
216
214
|
const project = await Project.findOne({ _id: projectId });
|
|
@@ -220,7 +218,7 @@ function projectRouter(config) {
|
|
|
220
218
|
if (!updates || typeof updates !== 'object') {
|
|
221
219
|
return res.status(400).json({ message: 'Missing updates payload' });
|
|
222
220
|
}
|
|
223
|
-
if (!(0, auth_1.
|
|
221
|
+
if (!(0, auth_1.canEditProject)(project, auth.userId)) {
|
|
224
222
|
return res.status(403).json({ message: 'Unauthorized project access' });
|
|
225
223
|
}
|
|
226
224
|
const updated = await Project.update({ _id: projectId }, updates);
|
|
@@ -250,8 +248,9 @@ function projectRouter(config) {
|
|
|
250
248
|
if (!project) {
|
|
251
249
|
return res.status(404).json({ message: 'Project not found' });
|
|
252
250
|
}
|
|
253
|
-
|
|
254
|
-
|
|
251
|
+
// Only an admin of the project deletes it.
|
|
252
|
+
if (!(0, auth_1.isProjectAdmin)(project, auth.userId)) {
|
|
253
|
+
return res.status(403).json({ message: 'Only a project admin can delete it' });
|
|
255
254
|
}
|
|
256
255
|
await Project.useDbType(project.dbType).delete({ _id: projectId });
|
|
257
256
|
const allProjects = await Project.find({});
|
|
@@ -348,9 +347,6 @@ function projectRouter(config) {
|
|
|
348
347
|
router.post('/projects/:id/image', async (req, res) => {
|
|
349
348
|
try {
|
|
350
349
|
const auth = req.auth;
|
|
351
|
-
if (auth.role !== 'admin' && auth.role !== 'editor') {
|
|
352
|
-
return res.status(403).json({ message: 'Permission denied' });
|
|
353
|
-
}
|
|
354
350
|
const projectId = req.params.id;
|
|
355
351
|
const { imageUrl } = req.body;
|
|
356
352
|
if (!projectId || !imageUrl) {
|
|
@@ -360,7 +356,7 @@ function projectRouter(config) {
|
|
|
360
356
|
if (!project) {
|
|
361
357
|
return res.status(404).json({ message: 'Project not found' });
|
|
362
358
|
}
|
|
363
|
-
if (!(0, auth_1.
|
|
359
|
+
if (!(0, auth_1.canEditProject)(project, auth.userId)) {
|
|
364
360
|
return res.status(403).json({ message: 'Unauthorized project access' });
|
|
365
361
|
}
|
|
366
362
|
const updatedProject = await Project.update({ _id: projectId }, { image: imageUrl });
|
|
@@ -376,16 +372,13 @@ function projectRouter(config) {
|
|
|
376
372
|
router.patch('/projects/:id/origins', async (req, res) => {
|
|
377
373
|
try {
|
|
378
374
|
const auth = req.auth;
|
|
379
|
-
if (auth.role !== 'admin' && auth.role !== 'editor') {
|
|
380
|
-
return res.status(403).json({ message: 'Permission denied' });
|
|
381
|
-
}
|
|
382
375
|
const projectId = req.params.id;
|
|
383
376
|
const { origins } = req.body;
|
|
384
377
|
const project = await Project.findOne({ _id: projectId });
|
|
385
378
|
if (!project) {
|
|
386
379
|
return res.status(404).json({ message: 'Project not found' });
|
|
387
380
|
}
|
|
388
|
-
if (!(0, auth_1.
|
|
381
|
+
if (!(0, auth_1.canEditProject)(project, auth.userId)) {
|
|
389
382
|
return res.status(403).json({ message: 'Unauthorized project access' });
|
|
390
383
|
}
|
|
391
384
|
const updated = await Project.update({ _id: projectId }, { allowedOrigin: origins });
|
|
@@ -402,9 +395,6 @@ function projectRouter(config) {
|
|
|
402
395
|
router.post('/projects/:id/integrations', async (req, res) => {
|
|
403
396
|
try {
|
|
404
397
|
const auth = req.auth;
|
|
405
|
-
if (auth.role !== 'admin' && auth.role !== 'editor') {
|
|
406
|
-
return res.status(403).json({ message: 'Permission denied' });
|
|
407
|
-
}
|
|
408
398
|
const projectId = req.params.id;
|
|
409
399
|
const { integrationId } = req.body;
|
|
410
400
|
if (!integrationId)
|
|
@@ -412,7 +402,7 @@ function projectRouter(config) {
|
|
|
412
402
|
const project = await Project.findOne({ _id: projectId });
|
|
413
403
|
if (!project)
|
|
414
404
|
return res.status(404).json({ message: 'Project not found' });
|
|
415
|
-
if (!(0, auth_1.
|
|
405
|
+
if (!(0, auth_1.canEditProject)(project, auth.userId))
|
|
416
406
|
return res.status(403).json({ message: 'Unauthorized project access' });
|
|
417
407
|
const alreadyConnected = [...(project.dbConnections ?? []), ...(project.storageConnections ?? []), ...(project.integrationConnections ?? [])]
|
|
418
408
|
.some((c) => c.integrationId === integrationId);
|
|
@@ -438,15 +428,12 @@ function projectRouter(config) {
|
|
|
438
428
|
router.delete('/projects/:id/integrations/:integrationId', async (req, res) => {
|
|
439
429
|
try {
|
|
440
430
|
const auth = req.auth;
|
|
441
|
-
if (auth.role !== 'admin' && auth.role !== 'editor') {
|
|
442
|
-
return res.status(403).json({ message: 'Permission denied' });
|
|
443
|
-
}
|
|
444
431
|
const projectId = req.params.id;
|
|
445
432
|
const { integrationId } = req.params;
|
|
446
433
|
const project = await Project.findOne({ _id: projectId });
|
|
447
434
|
if (!project)
|
|
448
435
|
return res.status(404).json({ message: 'Project not found' });
|
|
449
|
-
if (!(0, auth_1.
|
|
436
|
+
if (!(0, auth_1.canEditProject)(project, auth.userId))
|
|
450
437
|
return res.status(403).json({ message: 'Unauthorized project access' });
|
|
451
438
|
const dbConn = (project.dbConnections ?? []).find((c) => c.integrationId === integrationId);
|
|
452
439
|
const storageConn = (project.storageConnections ?? []).find((c) => c.integrationId === integrationId);
|
|
@@ -11,6 +11,7 @@ const jobQueue_1 = require("../../services/jobQueue");
|
|
|
11
11
|
const vfxProcessor_1 = require("../../services/vfxProcessor");
|
|
12
12
|
const sanitize_1 = require("../../utils/sanitize");
|
|
13
13
|
const crypto_1 = __importDefault(require("crypto"));
|
|
14
|
+
const encryption_1 = require("../../utils/encryption");
|
|
14
15
|
function renderFarmRouter(_config) {
|
|
15
16
|
const router = (0, express_1.Router)();
|
|
16
17
|
const Project = (0, manager_1.getModel)('projects');
|
|
@@ -34,14 +35,20 @@ function renderFarmRouter(_config) {
|
|
|
34
35
|
try {
|
|
35
36
|
const auth = req.auth;
|
|
36
37
|
const { projectId } = req.params;
|
|
37
|
-
const { name, provider, apiUrl, encryptedCredential, description } = req.body;
|
|
38
|
+
const { name, provider, apiUrl, credential: credentialValue, encryptedCredential: legacyCredential, description } = req.body;
|
|
39
|
+
// The credential, as given (`encryptedCredential` was its old name: it was always the
|
|
40
|
+
// value itself), stored encrypted.
|
|
41
|
+
const credential = credentialValue ?? legacyCredential;
|
|
42
|
+
if (credential && !(0, encryption_1.isEncryptionKeySet)())
|
|
43
|
+
return res.status(500).json({ message: 'Encryption key is not set' });
|
|
44
|
+
const encryptedCredential = credential ? (0, encryption_1.encrypt)(String(credential)) : undefined;
|
|
38
45
|
if (!name || !provider || !apiUrl) {
|
|
39
46
|
return res.status(400).json({ message: 'name, provider and apiUrl are required' });
|
|
40
47
|
}
|
|
41
48
|
const project = await Project.findOne({ _id: projectId });
|
|
42
49
|
if (!project)
|
|
43
50
|
return res.status(404).json({ message: 'Project not found' });
|
|
44
|
-
if (!(0, auth_1.
|
|
51
|
+
if (!(0, auth_1.canEditProject)(project, auth.userId))
|
|
45
52
|
return res.status(403).json({ message: 'Unauthorized' });
|
|
46
53
|
const connection = {
|
|
47
54
|
id: crypto_1.default.randomUUID(),
|
|
@@ -67,7 +74,7 @@ function renderFarmRouter(_config) {
|
|
|
67
74
|
const project = await Project.findOne({ _id: projectId });
|
|
68
75
|
if (!project)
|
|
69
76
|
return res.status(404).json({ message: 'Project not found' });
|
|
70
|
-
if (!(0, auth_1.
|
|
77
|
+
if (!(0, auth_1.canEditProject)(project, auth.userId))
|
|
71
78
|
return res.status(403).json({ message: 'Unauthorized' });
|
|
72
79
|
await Project.update({ _id: projectId }, { $pull: { renderFarmConnections: { id: connectionId } } });
|
|
73
80
|
res.json({ message: 'Connection deleted' });
|
|
@@ -87,7 +94,7 @@ function renderFarmRouter(_config) {
|
|
|
87
94
|
const project = await Project.findOne({ _id: projectId });
|
|
88
95
|
if (!project)
|
|
89
96
|
return res.status(404).json({ message: 'Project not found' });
|
|
90
|
-
if (!(0, auth_1.
|
|
97
|
+
if (!(0, auth_1.canEditProject)(project, auth.userId))
|
|
91
98
|
return res.status(403).json({ message: 'Unauthorized' });
|
|
92
99
|
const job = (0, jobQueue_1.createJob)('render', auth.userId, projectId, { fileId, renderer, renderFarmConnectionId, frameRange, resolution, samples, outputFormat });
|
|
93
100
|
setImmediate(() => (0, vfxProcessor_1.runRenderJob)(job.jobId, fileId, projectId, { renderer, renderFarmConnectionId, frameRange, resolution, samples, outputFormat }));
|
|
@@ -107,7 +114,7 @@ function renderFarmRouter(_config) {
|
|
|
107
114
|
const project = await Project.findOne({ _id: projectId });
|
|
108
115
|
if (!project)
|
|
109
116
|
return res.status(404).json({ message: 'Project not found' });
|
|
110
|
-
if (!(0, auth_1.
|
|
117
|
+
if (!(0, auth_1.canEditProject)(project, auth.userId))
|
|
111
118
|
return res.status(403).json({ message: 'Unauthorized' });
|
|
112
119
|
const job = (0, jobQueue_1.createJob)('format-convert', auth.userId, projectId, { fileId, inputFormat, outputFormat, applyTransforms, embedTextures });
|
|
113
120
|
setImmediate(() => (0, vfxProcessor_1.runFormatConvertJob)(job.jobId, fileId, projectId, { inputFormat, outputFormat, applyTransforms, embedTextures }));
|
|
@@ -127,7 +134,7 @@ function renderFarmRouter(_config) {
|
|
|
127
134
|
const project = await Project.findOne({ _id: projectId });
|
|
128
135
|
if (!project)
|
|
129
136
|
return res.status(404).json({ message: 'Project not found' });
|
|
130
|
-
if (!(0, auth_1.
|
|
137
|
+
if (!(0, auth_1.canEditProject)(project, auth.userId))
|
|
131
138
|
return res.status(403).json({ message: 'Unauthorized' });
|
|
132
139
|
const job = (0, jobQueue_1.createJob)('lod', auth.userId, projectId, { fileId, levels, reductionRatios, algorithm, outputFormat });
|
|
133
140
|
setImmediate(() => (0, vfxProcessor_1.runLodJob)(job.jobId, fileId, projectId, { levels, reductionRatios, algorithm, outputFormat }));
|
|
@@ -60,7 +60,7 @@ function reviewRouter(_config) {
|
|
|
60
60
|
const project = await Project.findOne({ _id: projectId });
|
|
61
61
|
if (!project)
|
|
62
62
|
return res.status(404).json({ message: 'Project not found' });
|
|
63
|
-
if (!(0, auth_1.
|
|
63
|
+
if (!(0, auth_1.canEditProject)(project, auth.userId))
|
|
64
64
|
return res.status(403).json({ message: 'Unauthorized' });
|
|
65
65
|
const db = getDb();
|
|
66
66
|
if (!db)
|
|
@@ -120,7 +120,7 @@ function reviewRouter(_config) {
|
|
|
120
120
|
const project = await Project.findOne({ _id: projectId });
|
|
121
121
|
if (!project)
|
|
122
122
|
return res.status(404).json({ message: 'Project not found' });
|
|
123
|
-
if (!(0, auth_1.
|
|
123
|
+
if (!(0, auth_1.canEditProject)(project, auth.userId))
|
|
124
124
|
return res.status(403).json({ message: 'Unauthorized' });
|
|
125
125
|
const db = getDb();
|
|
126
126
|
if (!db)
|
|
@@ -190,7 +190,7 @@ function reviewRouter(_config) {
|
|
|
190
190
|
const project = await Project.findOne({ _id: projectId });
|
|
191
191
|
if (!project)
|
|
192
192
|
return res.status(404).json({ message: 'Project not found' });
|
|
193
|
-
if (!(0, auth_1.
|
|
193
|
+
if (!(0, auth_1.canEditProject)(project, auth.userId))
|
|
194
194
|
return res.status(403).json({ message: 'Unauthorized' });
|
|
195
195
|
const db = getDb();
|
|
196
196
|
if (!db)
|
|
@@ -224,7 +224,7 @@ function reviewRouter(_config) {
|
|
|
224
224
|
const project = await Project.findOne({ _id: projectId });
|
|
225
225
|
if (!project)
|
|
226
226
|
return res.status(404).json({ message: 'Project not found' });
|
|
227
|
-
if (!(0, auth_1.
|
|
227
|
+
if (!(0, auth_1.canEditProject)(project, auth.userId))
|
|
228
228
|
return res.status(403).json({ message: 'Unauthorized' });
|
|
229
229
|
const db = getDb();
|
|
230
230
|
if (!db)
|
|
@@ -42,7 +42,7 @@ function rightsRouter(_config) {
|
|
|
42
42
|
const project = await Project.findOne({ _id: projectId });
|
|
43
43
|
if (!project)
|
|
44
44
|
return res.status(404).json({ message: 'Project not found' });
|
|
45
|
-
if (!(0, auth_1.
|
|
45
|
+
if (!(0, auth_1.canEditProject)(project, auth.userId))
|
|
46
46
|
return res.status(403).json({ message: 'Unauthorized' });
|
|
47
47
|
const db = getDb();
|
|
48
48
|
if (!db)
|
|
@@ -71,11 +71,14 @@ function storageRouter(config) {
|
|
|
71
71
|
router.get('/upload-project-image-url/:id', async (req, res) => {
|
|
72
72
|
try {
|
|
73
73
|
const auth = req.auth;
|
|
74
|
-
if (auth.role !== 'admin' && auth.role !== 'editor')
|
|
75
|
-
return res.status(403).json({ message: 'Permission denied' });
|
|
76
74
|
const projectId = req.params.id;
|
|
77
75
|
if (!projectId)
|
|
78
76
|
return res.status(400).json({ message: 'Missing projectId' });
|
|
77
|
+
const project = await Project.findOne({ _id: projectId });
|
|
78
|
+
if (!project)
|
|
79
|
+
return res.status(404).json({ message: 'Project not found' });
|
|
80
|
+
if (!(0, auth_1.canEditProject)(project, auth.userId))
|
|
81
|
+
return res.status(403).json({ message: 'Permission denied' });
|
|
79
82
|
const response = await (0, presign_1.getPresignedProjectImageUrl)(adapter, projectId);
|
|
80
83
|
res.status(200).json({ ...response, message: 'Presigned URL generated successfully' });
|
|
81
84
|
}
|
|
@@ -86,11 +89,14 @@ function storageRouter(config) {
|
|
|
86
89
|
router.delete('/delete-project-image-url/:id', async (req, res) => {
|
|
87
90
|
try {
|
|
88
91
|
const auth = req.auth;
|
|
89
|
-
if (auth.role !== 'admin' && auth.role !== 'editor')
|
|
90
|
-
return res.status(403).json({ message: 'Permission denied' });
|
|
91
92
|
const projectId = req.params.id;
|
|
92
93
|
if (!projectId)
|
|
93
94
|
return res.status(400).json({ message: 'Missing projectId' });
|
|
95
|
+
const project = await Project.findOne({ _id: projectId });
|
|
96
|
+
if (!project)
|
|
97
|
+
return res.status(404).json({ message: 'Project not found' });
|
|
98
|
+
if (!(0, auth_1.canEditProject)(project, auth.userId))
|
|
99
|
+
return res.status(403).json({ message: 'Permission denied' });
|
|
94
100
|
await (0, file_1.deleteProjectImage)(adapter, projectId);
|
|
95
101
|
const updated = await Project.update({ _id: projectId }, { image: '' });
|
|
96
102
|
res.status(201).json({ ...updated, message: 'Image deleted successfully' });
|
|
@@ -119,7 +125,7 @@ function storageRouter(config) {
|
|
|
119
125
|
const project = await Project.findOne({ _id: projectId });
|
|
120
126
|
if (!project)
|
|
121
127
|
return res.status(404).json({ message: 'Project not found' });
|
|
122
|
-
if (!(0, auth_1.
|
|
128
|
+
if (!(0, auth_1.canEditProject)(project, auth.userId))
|
|
123
129
|
return res.status(403).json({ message: 'Unauthorized access' });
|
|
124
130
|
if (!adapter.getPresignedUploadUrl) {
|
|
125
131
|
return res.status(501).json({ message: 'Storage adapter does not support presigned uploads' });
|
|
@@ -192,7 +198,7 @@ function storageRouter(config) {
|
|
|
192
198
|
const project = await Project.findOne({ _id: projectId });
|
|
193
199
|
if (!project)
|
|
194
200
|
return res.status(404).json({ message: 'Project not found' });
|
|
195
|
-
if (!(0, auth_1.
|
|
201
|
+
if (!(0, auth_1.canEditProject)(project, auth.userId))
|
|
196
202
|
return res.status(403).json({ message: 'Unauthorized access' });
|
|
197
203
|
const collection = getRawFilesCollection();
|
|
198
204
|
if (!collection)
|
|
@@ -213,7 +219,7 @@ function storageRouter(config) {
|
|
|
213
219
|
const project = await Project.findOne({ _id: projectId });
|
|
214
220
|
if (!project)
|
|
215
221
|
return res.status(404).json({ message: 'Project not found' });
|
|
216
|
-
if (!(0, auth_1.
|
|
222
|
+
if (!(0, auth_1.canEditProject)(project, auth.userId))
|
|
217
223
|
return res.status(403).json({ message: 'Unauthorized access' });
|
|
218
224
|
const collection = getRawFilesCollection();
|
|
219
225
|
if (!collection)
|
|
@@ -291,7 +297,7 @@ function storageRouter(config) {
|
|
|
291
297
|
const project = await Project.findOne({ _id: projectId });
|
|
292
298
|
if (!project)
|
|
293
299
|
return res.status(404).json({ message: 'Project not found' });
|
|
294
|
-
if (!(0, auth_1.
|
|
300
|
+
if (!(0, auth_1.canEditProject)(project, auth.userId))
|
|
295
301
|
return res.status(403).json({ message: 'Unauthorized access' });
|
|
296
302
|
const connAdapter = await resolveConnAdapter(connId, project, auth);
|
|
297
303
|
if ('error' in connAdapter)
|
|
@@ -419,7 +425,7 @@ function storageRouter(config) {
|
|
|
419
425
|
const project = await Project.findOne({ _id: projectId });
|
|
420
426
|
if (!project)
|
|
421
427
|
return res.status(404).json({ message: 'Project not found' });
|
|
422
|
-
if (!(0, auth_1.
|
|
428
|
+
if (!(0, auth_1.canEditProject)(project, auth.userId))
|
|
423
429
|
return res.status(403).json({ message: 'Unauthorized access' });
|
|
424
430
|
const collection = getRawFilesCollection();
|
|
425
431
|
if (!collection)
|
|
@@ -440,7 +446,7 @@ function storageRouter(config) {
|
|
|
440
446
|
const project = await Project.findOne({ _id: projectId });
|
|
441
447
|
if (!project)
|
|
442
448
|
return res.status(404).json({ message: 'Project not found' });
|
|
443
|
-
if (!(0, auth_1.
|
|
449
|
+
if (!(0, auth_1.canEditProject)(project, auth.userId))
|
|
444
450
|
return res.status(403).json({ message: 'Unauthorized access' });
|
|
445
451
|
const connAdapter = await resolveConnAdapter(connId, project, auth);
|
|
446
452
|
if ('error' in connAdapter)
|
|
@@ -539,7 +545,7 @@ function storageRouter(config) {
|
|
|
539
545
|
const project = await Project.findOne({ _id: projectId });
|
|
540
546
|
if (!project)
|
|
541
547
|
return res.status(404).json({ message: 'Project not found' });
|
|
542
|
-
if (!(0, auth_1.
|
|
548
|
+
if (!(0, auth_1.canEditProject)(project, auth.userId))
|
|
543
549
|
return res.status(403).json({ message: 'Unauthorized access' });
|
|
544
550
|
const conn = findStorageConn(project, connId);
|
|
545
551
|
const isBuiltin = conn?.source === 'builtin';
|
|
@@ -590,7 +596,7 @@ function storageRouter(config) {
|
|
|
590
596
|
const project = await Project.findOne({ _id: projectId });
|
|
591
597
|
if (!project)
|
|
592
598
|
return res.status(404).json({ message: 'Project not found' });
|
|
593
|
-
if (!(0, auth_1.
|
|
599
|
+
if (!(0, auth_1.canEditProject)(project, auth.userId))
|
|
594
600
|
return res.status(403).json({ message: 'Unauthorized access' });
|
|
595
601
|
const collection = getRawFoldersCollection();
|
|
596
602
|
if (!collection)
|
|
@@ -624,7 +630,7 @@ function storageRouter(config) {
|
|
|
624
630
|
const project = await Project.findOne({ _id: projectId });
|
|
625
631
|
if (!project)
|
|
626
632
|
return res.status(404).json({ message: 'Project not found' });
|
|
627
|
-
if (!(0, auth_1.
|
|
633
|
+
if (!(0, auth_1.canEditProject)(project, auth.userId))
|
|
628
634
|
return res.status(403).json({ message: 'Unauthorized access' });
|
|
629
635
|
const collection = getRawFoldersCollection();
|
|
630
636
|
if (!collection)
|
|
@@ -654,7 +660,7 @@ function storageRouter(config) {
|
|
|
654
660
|
const project = await Project.findOne({ _id: projectId });
|
|
655
661
|
if (!project)
|
|
656
662
|
return res.status(404).json({ message: 'Project not found' });
|
|
657
|
-
if (!(0, auth_1.
|
|
663
|
+
if (!(0, auth_1.canEditProject)(project, auth.userId))
|
|
658
664
|
return res.status(403).json({ message: 'Unauthorized access' });
|
|
659
665
|
const foldersCollection = getRawFoldersCollection();
|
|
660
666
|
if (!foldersCollection)
|
|
@@ -682,7 +688,7 @@ function storageRouter(config) {
|
|
|
682
688
|
const project = await Project.findOne({ _id: projectId });
|
|
683
689
|
if (!project)
|
|
684
690
|
return res.status(404).json({ message: 'Project not found' });
|
|
685
|
-
if (!(0, auth_1.
|
|
691
|
+
if (!(0, auth_1.canEditProject)(project, auth.userId))
|
|
686
692
|
return res.status(403).json({ message: 'Unauthorized access' });
|
|
687
693
|
if (folderId != null) {
|
|
688
694
|
const foldersCollection = getRawFoldersCollection();
|