streamby-core 0.21.0 → 0.21.2
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/dist/middleware/createRouter.js +10 -314
- package/dist/middleware/routes/auth.d.ts +3 -0
- package/dist/middleware/routes/auth.js +22 -0
- package/dist/middleware/routes/database.d.ts +3 -0
- package/dist/middleware/routes/database.js +27 -0
- package/dist/middleware/routes/export.d.ts +3 -0
- package/dist/middleware/routes/export.js +65 -0
- package/dist/middleware/routes/file.d.ts +5 -0
- package/dist/middleware/routes/file.js +78 -0
- package/dist/middleware/routes/project.d.ts +3 -0
- package/dist/middleware/routes/project.js +231 -0
- package/dist/services/auth.d.ts +1 -3
- package/dist/services/auth.js +0 -10
- package/dist/utils/auth.d.ts +1 -0
- package/dist/utils/auth.js +6 -0
- package/package.json +1 -1
|
@@ -5,15 +5,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.createStreamByRouter = createStreamByRouter;
|
|
7
7
|
const express_1 = __importDefault(require("express"));
|
|
8
|
-
const file_1 = require("../services/file");
|
|
9
|
-
const presign_1 = require("../services/presign");
|
|
10
8
|
const manager_1 = require("../models/manager");
|
|
11
9
|
const storage_1 = require("../providers/storage");
|
|
12
10
|
const connectionManager_1 = require("../adapters/database/connectionManager");
|
|
13
|
-
const auth_1 = require("
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
const auth_1 = require("./routes/auth");
|
|
12
|
+
const database_1 = require("./routes/database");
|
|
13
|
+
const file_1 = require("./routes/file");
|
|
14
|
+
const project_1 = require("./routes/project");
|
|
15
|
+
const export_1 = require("./routes/export");
|
|
17
16
|
function createStreamByRouter(config) {
|
|
18
17
|
const router = express_1.default.Router();
|
|
19
18
|
(0, connectionManager_1.initConnections)(config.databases || []);
|
|
@@ -23,313 +22,10 @@ function createStreamByRouter(config) {
|
|
|
23
22
|
(0, manager_1.registerModel)('projects', allDbIds, 'projects');
|
|
24
23
|
(0, manager_1.registerModel)('exports', allDbIds, 'exports');
|
|
25
24
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
router.
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
res.status(200).json({ logged: true, ...auth });
|
|
32
|
-
}
|
|
33
|
-
catch (err) {
|
|
34
|
-
res.status(401).json({ logged: false });
|
|
35
|
-
}
|
|
36
|
-
});
|
|
37
|
-
router.get('/databases', async (req, res) => {
|
|
38
|
-
try {
|
|
39
|
-
const auth = await config.authProvider(req);
|
|
40
|
-
if (!auth) {
|
|
41
|
-
return res.status(401).json({ error: 'Unauthorized' });
|
|
42
|
-
}
|
|
43
|
-
const connectedDbIds = (0, connectionManager_1.getConnectedIds)();
|
|
44
|
-
const databases = (config.databases || [])
|
|
45
|
-
.filter(db => connectedDbIds.includes(db.id))
|
|
46
|
-
.map(db => ({ name: db.id, value: db.type }));
|
|
47
|
-
res.status(200).json({ databases });
|
|
48
|
-
}
|
|
49
|
-
catch (err) {
|
|
50
|
-
res.status(500).json({ error: 'Failed to get databases' });
|
|
51
|
-
}
|
|
52
|
-
});
|
|
53
|
-
router.get('/upload-project-image-url/:id', async (req, res) => {
|
|
54
|
-
try {
|
|
55
|
-
const auth = await config.authProvider(req);
|
|
56
|
-
if (auth.role !== 'admin' && auth.role !== 'editor') {
|
|
57
|
-
return res.status(403).json({ error: 'Permission denied' });
|
|
58
|
-
}
|
|
59
|
-
const projectId = req.params.id;
|
|
60
|
-
if (!projectId) {
|
|
61
|
-
return res.status(400).json({ error: 'Missing projectId' });
|
|
62
|
-
}
|
|
63
|
-
const url = await (0, presign_1.getPresignedProjectImageUrl)(adapter, projectId);
|
|
64
|
-
res.json(url);
|
|
65
|
-
}
|
|
66
|
-
catch (err) {
|
|
67
|
-
res.status(500).json({ error: 'Failed to generate presigned URL', details: err.message });
|
|
68
|
-
}
|
|
69
|
-
});
|
|
70
|
-
router.delete('/delete-project-image-url/:id', async (req, res) => {
|
|
71
|
-
try {
|
|
72
|
-
const auth = await config.authProvider(req);
|
|
73
|
-
if (auth.role !== 'admin' && auth.role !== 'editor') {
|
|
74
|
-
return res.status(403).json({ error: 'Permission denied' });
|
|
75
|
-
}
|
|
76
|
-
const projectId = req.params.id;
|
|
77
|
-
if (!projectId) {
|
|
78
|
-
return res.status(400).json({ error: 'Missing projectId' });
|
|
79
|
-
}
|
|
80
|
-
await (0, file_1.deleteProjectImage)(adapter, projectId);
|
|
81
|
-
const updated = await Project.update({ _id: projectId }, { image: '' });
|
|
82
|
-
res.status(201).json(updated);
|
|
83
|
-
}
|
|
84
|
-
catch (err) {
|
|
85
|
-
res.status(500).json({ error: 'Failed to delete image', details: err.message });
|
|
86
|
-
}
|
|
87
|
-
});
|
|
88
|
-
router.get('/files', async (req, res) => {
|
|
89
|
-
try {
|
|
90
|
-
const auth = await config.authProvider(req);
|
|
91
|
-
const projectId = (req.query.projectId || req.headers['x-project-id']);
|
|
92
|
-
if (!projectId) {
|
|
93
|
-
return res.status(403).json({ error: 'Unauthorized or missing projectId' });
|
|
94
|
-
}
|
|
95
|
-
const files = await (0, file_1.listFilesService)(adapter, req, projectId);
|
|
96
|
-
res.json(files);
|
|
97
|
-
}
|
|
98
|
-
catch (err) {
|
|
99
|
-
res.status(500).json({ error: 'Failed to list files', details: err });
|
|
100
|
-
}
|
|
101
|
-
});
|
|
102
|
-
router.get('/projects', async (req, res) => {
|
|
103
|
-
try {
|
|
104
|
-
const auth = await config.authProvider(req);
|
|
105
|
-
const archivedQuery = req.query.archived;
|
|
106
|
-
const filterArchived = archivedQuery !== undefined ? String(archivedQuery).toLowerCase() === 'true' : undefined;
|
|
107
|
-
const allProjects = await Project.find({}); // Fetch all projects
|
|
108
|
-
const projects = allProjects
|
|
109
|
-
.filter(project => {
|
|
110
|
-
const isMember = project.members?.some((m) => m.userId?.toString() === auth.userId?.toString());
|
|
111
|
-
if (!isMember)
|
|
112
|
-
return false;
|
|
113
|
-
if (filterArchived !== undefined) {
|
|
114
|
-
const currentUserMember = project.members?.find((member) => member.userId === auth.userId);
|
|
115
|
-
return currentUserMember ? (currentUserMember.archived || false) === filterArchived : false;
|
|
116
|
-
}
|
|
117
|
-
return true;
|
|
118
|
-
})
|
|
119
|
-
.map(project => {
|
|
120
|
-
const currentUserMember = project.members?.find((member) => member.userId === auth.userId);
|
|
121
|
-
return {
|
|
122
|
-
id: project._id || project.id,
|
|
123
|
-
dbType: project.dbType,
|
|
124
|
-
name: project.name,
|
|
125
|
-
image: project.image || '',
|
|
126
|
-
archived: currentUserMember ? currentUserMember.archived || false : false,
|
|
127
|
-
};
|
|
128
|
-
});
|
|
129
|
-
res.json({ projects });
|
|
130
|
-
}
|
|
131
|
-
catch (err) {
|
|
132
|
-
console.error('Error in /projects endpoint:', err);
|
|
133
|
-
res.status(500).json({ error: 'Failed to list projects', details: err });
|
|
134
|
-
}
|
|
135
|
-
});
|
|
136
|
-
router.post('/projects/create', async (req, res) => {
|
|
137
|
-
try {
|
|
138
|
-
const auth = await config.authProvider(req);
|
|
139
|
-
if (auth.role !== 'admin' && auth.role !== 'editor') {
|
|
140
|
-
return res.status(403).json({ error: 'Permission denied' });
|
|
141
|
-
}
|
|
142
|
-
const { name, description, dbType } = req.body;
|
|
143
|
-
const newProject = await Project.create({
|
|
144
|
-
dbType: dbType || 'nosql',
|
|
145
|
-
name,
|
|
146
|
-
description: description || '',
|
|
147
|
-
members: [{ userId: auth.userId, role: "admin", archived: false }]
|
|
148
|
-
});
|
|
149
|
-
res.status(201).json({ project: { ...newProject, id: newProject._id || newProject.id, _id: undefined } });
|
|
150
|
-
}
|
|
151
|
-
catch (err) {
|
|
152
|
-
res.status(500).json({ error: 'Failed to create project', details: err.message });
|
|
153
|
-
}
|
|
154
|
-
});
|
|
155
|
-
router.get('/projects/:id', async (req, res) => {
|
|
156
|
-
try {
|
|
157
|
-
const auth = await config.authProvider(req);
|
|
158
|
-
const projectId = req.params.id;
|
|
159
|
-
const project = await Project.findOne({ _id: projectId });
|
|
160
|
-
if (!project) {
|
|
161
|
-
return res.status(404).json({ error: 'Project not found' });
|
|
162
|
-
}
|
|
163
|
-
if (!isProjectMember(project, auth.userId)) {
|
|
164
|
-
return res.status(403).json({ error: 'Unauthorized project access' });
|
|
165
|
-
}
|
|
166
|
-
res.json({ project: { ...project, id: project._id || project.id, _id: undefined } });
|
|
167
|
-
}
|
|
168
|
-
catch (err) {
|
|
169
|
-
res.status(500).json({ error: 'Failed to fetch project', details: err.message });
|
|
170
|
-
}
|
|
171
|
-
});
|
|
172
|
-
router.patch('/projects/:id', async (req, res) => {
|
|
173
|
-
try {
|
|
174
|
-
const auth = await config.authProvider(req);
|
|
175
|
-
if (auth.role !== 'admin' && auth.role !== 'editor') {
|
|
176
|
-
return res.status(403).json({ error: 'Permission denied' });
|
|
177
|
-
}
|
|
178
|
-
const projectId = req.params.id;
|
|
179
|
-
const updates = req.body;
|
|
180
|
-
const project = await Project.findOne({ _id: projectId });
|
|
181
|
-
if (!project) {
|
|
182
|
-
return res.status(404).json({ error: 'Project not found' });
|
|
183
|
-
}
|
|
184
|
-
if (!updates || typeof updates !== 'object') {
|
|
185
|
-
return res.status(400).json({ error: 'Missing updates payload' });
|
|
186
|
-
}
|
|
187
|
-
if (!isProjectMember(project, auth.userId)) {
|
|
188
|
-
return res.status(403).json({ error: 'Unauthorized project access' });
|
|
189
|
-
}
|
|
190
|
-
const updated = await Project.update({ _id: projectId }, updates);
|
|
191
|
-
if (!updated) {
|
|
192
|
-
return res.status(404).json({ error: 'Project not found or not updated' });
|
|
193
|
-
}
|
|
194
|
-
res.status(200).json({ success: true, project: { ...updated, id: updated._id || updated.id, _id: undefined } });
|
|
195
|
-
}
|
|
196
|
-
catch (err) {
|
|
197
|
-
res.status(500).json({ error: 'Failed to update project', details: err.message });
|
|
198
|
-
}
|
|
199
|
-
});
|
|
200
|
-
router.delete('/projects/:id', async (req, res) => {
|
|
201
|
-
try {
|
|
202
|
-
const auth = await config.authProvider(req);
|
|
203
|
-
const projectId = req.params.id;
|
|
204
|
-
const project = await Project.findOne({ _id: projectId });
|
|
205
|
-
if (!project) {
|
|
206
|
-
return res.status(404).json({ error: 'Project not found' });
|
|
207
|
-
}
|
|
208
|
-
if (!isProjectMember(project, auth.userId)) {
|
|
209
|
-
return res.status(403).json({ error: 'Unauthorized project access' });
|
|
210
|
-
}
|
|
211
|
-
await Project.delete({ _id: projectId });
|
|
212
|
-
res.status(200).json({ success: true });
|
|
213
|
-
}
|
|
214
|
-
catch (err) {
|
|
215
|
-
res.status(500).json({ error: 'Failed to delete project', details: err.message });
|
|
216
|
-
}
|
|
217
|
-
});
|
|
218
|
-
router.patch('/projects/:id/archive', async (req, res) => {
|
|
219
|
-
try {
|
|
220
|
-
const auth = await config.authProvider(req);
|
|
221
|
-
const projectId = req.params.id;
|
|
222
|
-
const project = await Project.findOne({ _id: projectId });
|
|
223
|
-
if (!project || !isProjectMember(project, auth.userId)) {
|
|
224
|
-
return res.status(403).json({ error: 'Unauthorized project access' });
|
|
225
|
-
}
|
|
226
|
-
await Project.update({ _id: projectId, "members.userId": auth.userId }, { "members.$.archived": true, "members.$.archivedBy": auth.userId, "members.$.archivedAt": new Date() });
|
|
227
|
-
const updatedProject = await Project.findOne({ _id: projectId }); // Fetch the updated project
|
|
228
|
-
const projects = (await Project.find({ members: { $elemMatch: { userId: auth.userId } } })).map(project => {
|
|
229
|
-
const currentUserMember = project.members?.find((member) => member.userId === auth.userId);
|
|
230
|
-
return {
|
|
231
|
-
id: project._id || project.id,
|
|
232
|
-
dbType: project.dbType,
|
|
233
|
-
name: project.name,
|
|
234
|
-
image: project.image || '',
|
|
235
|
-
archived: currentUserMember ? currentUserMember.archived || false : false,
|
|
236
|
-
};
|
|
237
|
-
});
|
|
238
|
-
// Replace the old project with the updated one in the list
|
|
239
|
-
const finalProjects = projects.map(p => p.id === (updatedProject?._id || updatedProject?.id) ? ({ ...updatedProject, id: updatedProject._id || updatedProject.id, _id: undefined }) : p);
|
|
240
|
-
res.status(200).json({ success: true, projects: finalProjects });
|
|
241
|
-
}
|
|
242
|
-
catch (err) {
|
|
243
|
-
res.status(500).json({ error: 'Failed to archive project', details: err.message });
|
|
244
|
-
}
|
|
245
|
-
});
|
|
246
|
-
router.patch('/projects/:id/unarchive', async (req, res) => {
|
|
247
|
-
try {
|
|
248
|
-
const auth = await config.authProvider(req);
|
|
249
|
-
const projectId = req.params.id;
|
|
250
|
-
const project = await Project.findOne({ _id: projectId });
|
|
251
|
-
if (!project || !isProjectMember(project, auth.userId)) {
|
|
252
|
-
return res.status(403).json({ error: 'Unauthorized project access' });
|
|
253
|
-
}
|
|
254
|
-
await Project.update({ _id: projectId, "members.userId": auth.userId }, { "members.$.archived": false, "members.$.archivedBy": null, "members.$.archivedAt": null });
|
|
255
|
-
const updatedProject = await Project.findOne({ _id: projectId }); // Fetch the updated project
|
|
256
|
-
const projects = (await Project.find({ members: { $elemMatch: { userId: auth.userId } } })).map(project => {
|
|
257
|
-
const currentUserMember = project.members?.find((member) => member.userId === auth.userId);
|
|
258
|
-
return {
|
|
259
|
-
id: project._id || project.id,
|
|
260
|
-
dbType: project.dbType,
|
|
261
|
-
name: project.name,
|
|
262
|
-
image: project.image || '',
|
|
263
|
-
archived: currentUserMember ? currentUserMember.archived || false : false,
|
|
264
|
-
};
|
|
265
|
-
});
|
|
266
|
-
// Replace the old project with the updated one in the list
|
|
267
|
-
const finalProjects = projects.map(p => p.id === (updatedProject?._id || updatedProject?.id) ? ({ ...updatedProject, id: updatedProject._id || updatedProject.id, _id: undefined }) : p);
|
|
268
|
-
res.status(200).json({ success: true, projects: finalProjects });
|
|
269
|
-
}
|
|
270
|
-
catch (err) {
|
|
271
|
-
res.status(500).json({ error: 'Failed to unarchive project', details: err.message });
|
|
272
|
-
}
|
|
273
|
-
});
|
|
274
|
-
router.get('/projects/:id/exports/:export_id', async (req, res) => {
|
|
275
|
-
try {
|
|
276
|
-
const auth = await config.authProvider(req);
|
|
277
|
-
const projectId = req.params.id;
|
|
278
|
-
const exportId = req.params.export_id;
|
|
279
|
-
const project = await Project.findOne({ _id: projectId });
|
|
280
|
-
if (!project) {
|
|
281
|
-
return res.status(404).json({ error: 'Project not found' });
|
|
282
|
-
}
|
|
283
|
-
if (!isProjectMember(project, auth.userId)) {
|
|
284
|
-
return res.status(403).json({ error: 'Unauthorized access' });
|
|
285
|
-
}
|
|
286
|
-
const data = await Export.findOne({ _id: exportId });
|
|
287
|
-
res.json({ data: { ...data, id: data._id || data.id, _id: undefined } });
|
|
288
|
-
}
|
|
289
|
-
catch (err) {
|
|
290
|
-
res.status(500).json({ error: 'Failed to fetch export data', details: err.message });
|
|
291
|
-
}
|
|
292
|
-
});
|
|
293
|
-
router.post('/projects/:id/exports', async (req, res) => {
|
|
294
|
-
try {
|
|
295
|
-
const auth = await config.authProvider(req);
|
|
296
|
-
const projectId = req.params.id;
|
|
297
|
-
const { name, description, collectionName } = req.body;
|
|
298
|
-
if (!name || !collectionName) {
|
|
299
|
-
return res.status(400).json({ error: 'Missing export name or collectionName' });
|
|
300
|
-
}
|
|
301
|
-
const project = await Project.findOne({ _id: projectId });
|
|
302
|
-
if (!project || !isProjectMember(project, auth.userId)) {
|
|
303
|
-
return res.status(403).json({ error: 'Unauthorized project access' });
|
|
304
|
-
}
|
|
305
|
-
const newExport = await Export.create({
|
|
306
|
-
name,
|
|
307
|
-
description,
|
|
308
|
-
collectionName,
|
|
309
|
-
projectId
|
|
310
|
-
});
|
|
311
|
-
res.status(201).json({ data: { ...newExport, id: newExport._id || newExport.id, _id: undefined } });
|
|
312
|
-
}
|
|
313
|
-
catch (err) {
|
|
314
|
-
res.status(500).json({ error: 'Failed to create export', details: err.message });
|
|
315
|
-
}
|
|
316
|
-
});
|
|
317
|
-
router.get('/projects/:id/members', async (req, res) => {
|
|
318
|
-
try {
|
|
319
|
-
const auth = await config.authProvider(req);
|
|
320
|
-
const projectId = req.params.id;
|
|
321
|
-
const project = await Project.findOne({ _id: projectId });
|
|
322
|
-
if (!project) {
|
|
323
|
-
return res.status(404).json({ error: 'Project not found' });
|
|
324
|
-
}
|
|
325
|
-
if (!isProjectMember(project, auth.userId)) {
|
|
326
|
-
return res.status(403).json({ error: 'Unauthorized project access' });
|
|
327
|
-
}
|
|
328
|
-
res.json({ members: project.members });
|
|
329
|
-
}
|
|
330
|
-
catch (err) {
|
|
331
|
-
res.status(500).json({ error: 'Failed to fetch project members', details: err.message });
|
|
332
|
-
}
|
|
333
|
-
});
|
|
25
|
+
router.use((0, auth_1.authRouter)(config));
|
|
26
|
+
router.use((0, database_1.databaseRouter)(config));
|
|
27
|
+
router.use((0, file_1.fileRouter)(config));
|
|
28
|
+
router.use((0, project_1.projectRouter)(config));
|
|
29
|
+
router.use((0, export_1.exportRouter)(config));
|
|
334
30
|
return router;
|
|
335
31
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.authRouter = authRouter;
|
|
4
|
+
const express_1 = require("express");
|
|
5
|
+
function authRouter(config) {
|
|
6
|
+
const router = (0, express_1.Router)();
|
|
7
|
+
router.get('/auth', async (req, res) => {
|
|
8
|
+
try {
|
|
9
|
+
const auth = await config.authProvider(req);
|
|
10
|
+
if (!auth ||
|
|
11
|
+
!auth.userId ||
|
|
12
|
+
!auth.role) {
|
|
13
|
+
throw new Error('Invalid or missing authentication context');
|
|
14
|
+
}
|
|
15
|
+
return res.status(200).json({ logged: true, ...auth });
|
|
16
|
+
}
|
|
17
|
+
catch (err) {
|
|
18
|
+
return res.status(401).json({ logged: false });
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
return router;
|
|
22
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.databaseRouter = databaseRouter;
|
|
4
|
+
const express_1 = require("express");
|
|
5
|
+
const connectionManager_1 = require("../../adapters/database/connectionManager");
|
|
6
|
+
function databaseRouter(config) {
|
|
7
|
+
const router = (0, express_1.Router)();
|
|
8
|
+
router.get('/databases', async (req, res) => {
|
|
9
|
+
try {
|
|
10
|
+
const auth = await config.authProvider(req);
|
|
11
|
+
if (!auth ||
|
|
12
|
+
!auth.userId ||
|
|
13
|
+
!auth.role) {
|
|
14
|
+
return res.status(401).json({ error: 'Unauthorized' });
|
|
15
|
+
}
|
|
16
|
+
const connectedDbIds = (0, connectionManager_1.getConnectedIds)();
|
|
17
|
+
const databases = (config.databases || [])
|
|
18
|
+
.filter(db => connectedDbIds.includes(db.id))
|
|
19
|
+
.map(db => ({ name: db.id, value: db.type }));
|
|
20
|
+
res.status(200).json({ databases });
|
|
21
|
+
}
|
|
22
|
+
catch (err) {
|
|
23
|
+
res.status(500).json({ error: 'Failed to get databases' });
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
return router;
|
|
27
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.exportRouter = exportRouter;
|
|
4
|
+
const express_1 = require("express");
|
|
5
|
+
const manager_1 = require("../../models/manager");
|
|
6
|
+
const auth_1 = require("../../utils/auth");
|
|
7
|
+
function exportRouter(config) {
|
|
8
|
+
const router = (0, express_1.Router)();
|
|
9
|
+
const Project = (0, manager_1.getModel)('projects');
|
|
10
|
+
const Export = (0, manager_1.getModel)('exports');
|
|
11
|
+
router.get('/projects/:id/exports/:export_id', async (req, res) => {
|
|
12
|
+
try {
|
|
13
|
+
const auth = await config.authProvider(req);
|
|
14
|
+
if (!auth ||
|
|
15
|
+
!auth.userId ||
|
|
16
|
+
!auth.role) {
|
|
17
|
+
return res.status(401).json({ error: 'Unauthorized' });
|
|
18
|
+
}
|
|
19
|
+
const projectId = req.params.id;
|
|
20
|
+
const exportId = req.params.export_id;
|
|
21
|
+
const project = await Project.findOne({ _id: projectId });
|
|
22
|
+
if (!project) {
|
|
23
|
+
return res.status(404).json({ error: 'Project not found' });
|
|
24
|
+
}
|
|
25
|
+
if (!(0, auth_1.isProjectMember)(project, auth.userId)) {
|
|
26
|
+
return res.status(403).json({ error: 'Unauthorized access' });
|
|
27
|
+
}
|
|
28
|
+
const data = await Export.findOne({ _id: exportId });
|
|
29
|
+
res.json({ data: { ...data, id: data._id || data.id, _id: undefined } });
|
|
30
|
+
}
|
|
31
|
+
catch (err) {
|
|
32
|
+
res.status(500).json({ error: 'Failed to fetch export data', details: err.message });
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
router.post('/projects/:id/exports', async (req, res) => {
|
|
36
|
+
try {
|
|
37
|
+
const auth = await config.authProvider(req);
|
|
38
|
+
if (!auth ||
|
|
39
|
+
!auth.userId ||
|
|
40
|
+
!auth.role) {
|
|
41
|
+
return res.status(401).json({ error: 'Unauthorized' });
|
|
42
|
+
}
|
|
43
|
+
const projectId = req.params.id;
|
|
44
|
+
const { name, description, collectionName } = req.body;
|
|
45
|
+
if (!name || !collectionName) {
|
|
46
|
+
return res.status(400).json({ error: 'Missing export name or collectionName' });
|
|
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({ error: 'Unauthorized project access' });
|
|
51
|
+
}
|
|
52
|
+
const newExport = await Export.create({
|
|
53
|
+
name,
|
|
54
|
+
description,
|
|
55
|
+
collectionName,
|
|
56
|
+
projectId
|
|
57
|
+
});
|
|
58
|
+
res.status(201).json({ data: { ...newExport, id: newExport._id || newExport.id, _id: undefined } });
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
res.status(500).json({ error: 'Failed to create export', details: err.message });
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
return router;
|
|
65
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.fileRouter = fileRouter;
|
|
4
|
+
const express_1 = require("express");
|
|
5
|
+
const file_1 = require("../../services/file");
|
|
6
|
+
const presign_1 = require("../../services/presign");
|
|
7
|
+
const storage_1 = require("../../providers/storage");
|
|
8
|
+
const manager_1 = require("../../models/manager");
|
|
9
|
+
function fileRouter(config) {
|
|
10
|
+
const router = (0, express_1.Router)();
|
|
11
|
+
const adapter = config.adapter || (0, storage_1.createStorageProvider)(config.storageProviders);
|
|
12
|
+
const Project = (0, manager_1.getModel)('projects');
|
|
13
|
+
router.get('/upload-project-image-url/:id', async (req, res) => {
|
|
14
|
+
try {
|
|
15
|
+
const auth = await config.authProvider(req);
|
|
16
|
+
if (!auth ||
|
|
17
|
+
!auth.userId ||
|
|
18
|
+
!auth.role) {
|
|
19
|
+
return res.status(401).json({ error: 'Unauthorized' });
|
|
20
|
+
}
|
|
21
|
+
if (auth.role !== 'admin' && auth.role !== 'editor') {
|
|
22
|
+
return res.status(403).json({ error: 'Permission denied' });
|
|
23
|
+
}
|
|
24
|
+
const projectId = req.params.id;
|
|
25
|
+
if (!projectId) {
|
|
26
|
+
return res.status(400).json({ error: 'Missing projectId' });
|
|
27
|
+
}
|
|
28
|
+
const url = await (0, presign_1.getPresignedProjectImageUrl)(adapter, projectId);
|
|
29
|
+
res.json(url);
|
|
30
|
+
}
|
|
31
|
+
catch (err) {
|
|
32
|
+
res.status(500).json({ error: 'Failed to generate presigned URL', details: err.message });
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
router.delete('/delete-project-image-url/:id', async (req, res) => {
|
|
36
|
+
try {
|
|
37
|
+
const auth = await config.authProvider(req);
|
|
38
|
+
if (!auth ||
|
|
39
|
+
!auth.userId ||
|
|
40
|
+
!auth.role) {
|
|
41
|
+
return res.status(401).json({ error: 'Unauthorized' });
|
|
42
|
+
}
|
|
43
|
+
if (auth.role !== 'admin' && auth.role !== 'editor') {
|
|
44
|
+
return res.status(403).json({ error: 'Permission denied' });
|
|
45
|
+
}
|
|
46
|
+
const projectId = req.params.id;
|
|
47
|
+
if (!projectId) {
|
|
48
|
+
return res.status(400).json({ error: 'Missing projectId' });
|
|
49
|
+
}
|
|
50
|
+
await (0, file_1.deleteProjectImage)(adapter, projectId);
|
|
51
|
+
const updated = await Project.update({ _id: projectId }, { image: '' });
|
|
52
|
+
res.status(201).json(updated);
|
|
53
|
+
}
|
|
54
|
+
catch (err) {
|
|
55
|
+
res.status(500).json({ error: 'Failed to delete image', details: err.message });
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
router.get('/files', async (req, res) => {
|
|
59
|
+
try {
|
|
60
|
+
const auth = await config.authProvider(req);
|
|
61
|
+
if (!auth ||
|
|
62
|
+
!auth.userId ||
|
|
63
|
+
!auth.role) {
|
|
64
|
+
return res.status(401).json({ error: 'Unauthorized' });
|
|
65
|
+
}
|
|
66
|
+
const projectId = (req.query.projectId || req.headers['x-project-id']);
|
|
67
|
+
if (!projectId) {
|
|
68
|
+
return res.status(403).json({ error: 'Unauthorized or missing projectId' });
|
|
69
|
+
}
|
|
70
|
+
const files = await (0, file_1.listFilesService)(adapter, req, projectId);
|
|
71
|
+
res.json(files);
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
res.status(500).json({ error: 'Failed to list files', details: err });
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
return router;
|
|
78
|
+
}
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.projectRouter = projectRouter;
|
|
4
|
+
const express_1 = require("express");
|
|
5
|
+
const manager_1 = require("../../models/manager");
|
|
6
|
+
const auth_1 = require("../../utils/auth");
|
|
7
|
+
function projectRouter(config) {
|
|
8
|
+
const router = (0, express_1.Router)();
|
|
9
|
+
const Project = (0, manager_1.getModel)('projects');
|
|
10
|
+
const mapProjectToResponseFormat = (project, userId) => {
|
|
11
|
+
const currentUserMember = project.members?.find((member) => member.userId === userId);
|
|
12
|
+
return {
|
|
13
|
+
id: project._id || project.id,
|
|
14
|
+
dbType: project.dbType,
|
|
15
|
+
name: project.name,
|
|
16
|
+
image: project.image || '',
|
|
17
|
+
archived: currentUserMember ? currentUserMember.archived || false : false,
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
router.get('/projects', async (req, res) => {
|
|
21
|
+
try {
|
|
22
|
+
const auth = await config.authProvider(req);
|
|
23
|
+
if (!auth ||
|
|
24
|
+
!auth.userId ||
|
|
25
|
+
!auth.role) {
|
|
26
|
+
return res.status(401).json({ error: 'Unauthorized' });
|
|
27
|
+
}
|
|
28
|
+
const archivedQuery = req.query.archived;
|
|
29
|
+
const filterArchived = archivedQuery !== undefined ? String(archivedQuery).toLowerCase() === 'true' : undefined;
|
|
30
|
+
const allProjects = await Project.find({}); // Fetch all projects
|
|
31
|
+
const projects = allProjects
|
|
32
|
+
.filter(project => {
|
|
33
|
+
const isMember = project.members?.some((m) => m.userId?.toString() === auth.userId?.toString());
|
|
34
|
+
if (!isMember)
|
|
35
|
+
return false;
|
|
36
|
+
if (filterArchived !== undefined) {
|
|
37
|
+
const currentUserMember = project.members?.find((member) => member.userId === auth.userId);
|
|
38
|
+
return currentUserMember ? (currentUserMember.archived || false) === filterArchived : false;
|
|
39
|
+
}
|
|
40
|
+
return true;
|
|
41
|
+
})
|
|
42
|
+
.map(project => mapProjectToResponseFormat(project, auth.userId));
|
|
43
|
+
res.json({ projects });
|
|
44
|
+
}
|
|
45
|
+
catch (err) {
|
|
46
|
+
console.error('Error in /projects endpoint:', err);
|
|
47
|
+
res.status(500).json({ error: 'Failed to list projects', details: err });
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
router.post('/projects/create', async (req, res) => {
|
|
51
|
+
try {
|
|
52
|
+
const auth = await config.authProvider(req);
|
|
53
|
+
if (!auth ||
|
|
54
|
+
!auth.userId ||
|
|
55
|
+
!auth.role) {
|
|
56
|
+
return res.status(401).json({ error: 'Unauthorized' });
|
|
57
|
+
}
|
|
58
|
+
if (auth.role !== 'admin' && auth.role !== 'editor') {
|
|
59
|
+
return res.status(403).json({ error: 'Permission denied' });
|
|
60
|
+
}
|
|
61
|
+
const { name, description, dbType } = req.body;
|
|
62
|
+
const newProject = await Project.create({
|
|
63
|
+
dbType: dbType || 'nosql',
|
|
64
|
+
name,
|
|
65
|
+
description: description || '',
|
|
66
|
+
members: [{ userId: auth.userId, role: "admin", archived: false }]
|
|
67
|
+
});
|
|
68
|
+
res.status(201).json({ project: { ...newProject, id: newProject._id || newProject.id, _id: undefined } });
|
|
69
|
+
}
|
|
70
|
+
catch (err) {
|
|
71
|
+
res.status(500).json({ error: 'Failed to create project', details: err.message });
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
router.get('/projects/:id', async (req, res) => {
|
|
75
|
+
try {
|
|
76
|
+
const auth = await config.authProvider(req);
|
|
77
|
+
if (!auth ||
|
|
78
|
+
!auth.userId ||
|
|
79
|
+
!auth.role) {
|
|
80
|
+
return res.status(401).json({ error: 'Unauthorized' });
|
|
81
|
+
}
|
|
82
|
+
const projectId = req.params.id;
|
|
83
|
+
const project = await Project.findOne({ _id: projectId });
|
|
84
|
+
if (!project) {
|
|
85
|
+
return res.status(404).json({ error: 'Project not found' });
|
|
86
|
+
}
|
|
87
|
+
if (!(0, auth_1.isProjectMember)(project, auth.userId)) {
|
|
88
|
+
return res.status(403).json({ error: 'Unauthorized project access' });
|
|
89
|
+
}
|
|
90
|
+
res.json({ project: { ...project, id: project._id || project.id, _id: undefined } });
|
|
91
|
+
}
|
|
92
|
+
catch (err) {
|
|
93
|
+
res.status(500).json({ error: 'Failed to fetch project', details: err.message });
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
router.patch('/projects/:id', async (req, res) => {
|
|
97
|
+
try {
|
|
98
|
+
const auth = await config.authProvider(req);
|
|
99
|
+
if (!auth ||
|
|
100
|
+
!auth.userId ||
|
|
101
|
+
!auth.role) {
|
|
102
|
+
return res.status(401).json({ error: 'Unauthorized' });
|
|
103
|
+
}
|
|
104
|
+
if (auth.role !== 'admin' && auth.role !== 'editor') {
|
|
105
|
+
return res.status(403).json({ error: 'Permission denied' });
|
|
106
|
+
}
|
|
107
|
+
const projectId = req.params.id;
|
|
108
|
+
const updates = req.body;
|
|
109
|
+
const project = await Project.findOne({ _id: projectId });
|
|
110
|
+
if (!project) {
|
|
111
|
+
return res.status(404).json({ error: 'Project not found' });
|
|
112
|
+
}
|
|
113
|
+
if (!updates || typeof updates !== 'object') {
|
|
114
|
+
return res.status(400).json({ error: 'Missing updates payload' });
|
|
115
|
+
}
|
|
116
|
+
if (!(0, auth_1.isProjectMember)(project, auth.userId)) {
|
|
117
|
+
return res.status(403).json({ error: 'Unauthorized project access' });
|
|
118
|
+
}
|
|
119
|
+
const updated = await Project.update({ _id: projectId }, updates);
|
|
120
|
+
if (!updated) {
|
|
121
|
+
return res.status(404).json({ error: 'Project not found or not updated' });
|
|
122
|
+
}
|
|
123
|
+
res.status(200).json({ success: true, project: { ...updated, id: updated._id || updated.id, _id: undefined } });
|
|
124
|
+
}
|
|
125
|
+
catch (err) {
|
|
126
|
+
res.status(500).json({ error: 'Failed to update project', details: err.message });
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
router.delete('/projects/:id', async (req, res) => {
|
|
130
|
+
try {
|
|
131
|
+
const auth = await config.authProvider(req);
|
|
132
|
+
if (!auth ||
|
|
133
|
+
!auth.userId ||
|
|
134
|
+
!auth.role) {
|
|
135
|
+
return res.status(401).json({ error: 'Unauthorized' });
|
|
136
|
+
}
|
|
137
|
+
const projectId = req.params.id;
|
|
138
|
+
const project = await Project.findOne({ _id: projectId });
|
|
139
|
+
if (!project) {
|
|
140
|
+
return res.status(404).json({ error: 'Project not found' });
|
|
141
|
+
}
|
|
142
|
+
if (!(0, auth_1.isProjectMember)(project, auth.userId)) {
|
|
143
|
+
return res.status(403).json({ error: 'Unauthorized project access' });
|
|
144
|
+
}
|
|
145
|
+
await Project.delete({ _id: projectId });
|
|
146
|
+
res.status(200).json({ success: true });
|
|
147
|
+
}
|
|
148
|
+
catch (err) {
|
|
149
|
+
res.status(500).json({ error: 'Failed to delete project', details: err.message });
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
router.patch('/projects/:id/archive', async (req, res) => {
|
|
153
|
+
try {
|
|
154
|
+
const auth = await config.authProvider(req);
|
|
155
|
+
if (!auth ||
|
|
156
|
+
!auth.userId ||
|
|
157
|
+
!auth.role) {
|
|
158
|
+
return res.status(401).json({ error: 'Unauthorized' });
|
|
159
|
+
}
|
|
160
|
+
const projectId = req.params.id;
|
|
161
|
+
const project = await Project.findOne({ _id: projectId });
|
|
162
|
+
if (!project || !(0, auth_1.isProjectMember)(project, auth.userId)) {
|
|
163
|
+
return res.status(403).json({ error: 'Unauthorized project access' });
|
|
164
|
+
}
|
|
165
|
+
await Project.update({ _id: projectId, "members.userId": auth.userId }, { "members.$.archived": true, "members.$.archivedBy": auth.userId, "members.$.archivedAt": new Date() });
|
|
166
|
+
// Re-fetch all projects for the user to ensure the list is up-to-date
|
|
167
|
+
const allProjects = await Project.find({});
|
|
168
|
+
const projects = allProjects
|
|
169
|
+
.filter(project => {
|
|
170
|
+
const isMember = project.members?.some((m) => m.userId?.toString() === auth.userId?.toString());
|
|
171
|
+
return isMember; // Only include projects where the user is a member
|
|
172
|
+
})
|
|
173
|
+
.map(project => mapProjectToResponseFormat(project, auth.userId));
|
|
174
|
+
res.status(200).json({ success: true, projects: projects });
|
|
175
|
+
}
|
|
176
|
+
catch (err) {
|
|
177
|
+
res.status(500).json({ error: 'Failed to archive project', details: err.message });
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
router.patch('/projects/:id/unarchive', async (req, res) => {
|
|
181
|
+
try {
|
|
182
|
+
const auth = await config.authProvider(req);
|
|
183
|
+
if (!auth ||
|
|
184
|
+
!auth.userId ||
|
|
185
|
+
!auth.role) {
|
|
186
|
+
return res.status(401).json({ error: 'Unauthorized' });
|
|
187
|
+
}
|
|
188
|
+
const projectId = req.params.id;
|
|
189
|
+
const project = await Project.findOne({ _id: projectId });
|
|
190
|
+
if (!project || !(0, auth_1.isProjectMember)(project, auth.userId)) {
|
|
191
|
+
return res.status(403).json({ error: 'Unauthorized project access' });
|
|
192
|
+
}
|
|
193
|
+
await Project.update({ _id: projectId, "members.userId": auth.userId }, { "members.$.archived": false, "members.$.archivedBy": null, "members.$.archivedAt": null });
|
|
194
|
+
// Re-fetch all projects for the user to ensure the list is up-to-date
|
|
195
|
+
const allProjects = await Project.find({});
|
|
196
|
+
const projects = allProjects
|
|
197
|
+
.filter(project => {
|
|
198
|
+
const isMember = project.members?.some((m) => m.userId?.toString() === auth.userId?.toString());
|
|
199
|
+
return isMember; // Only include projects where the user is a member
|
|
200
|
+
})
|
|
201
|
+
.map(project => mapProjectToResponseFormat(project, auth.userId));
|
|
202
|
+
res.status(200).json({ success: true, projects: projects });
|
|
203
|
+
}
|
|
204
|
+
catch (err) {
|
|
205
|
+
res.status(500).json({ error: 'Failed to unarchive project', details: err.message });
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
router.get('/projects/:id/members', async (req, res) => {
|
|
209
|
+
try {
|
|
210
|
+
const auth = await config.authProvider(req);
|
|
211
|
+
if (!auth ||
|
|
212
|
+
!auth.userId ||
|
|
213
|
+
!auth.role) {
|
|
214
|
+
return res.status(401).json({ error: 'Unauthorized' });
|
|
215
|
+
}
|
|
216
|
+
const projectId = req.params.id;
|
|
217
|
+
const project = await Project.findOne({ _id: projectId });
|
|
218
|
+
if (!project) {
|
|
219
|
+
return res.status(404).json({ error: 'Project not found' });
|
|
220
|
+
}
|
|
221
|
+
if (!(0, auth_1.isProjectMember)(project, auth.userId)) {
|
|
222
|
+
return res.status(403).json({ error: 'Unauthorized project access' });
|
|
223
|
+
}
|
|
224
|
+
res.json({ members: project.members });
|
|
225
|
+
}
|
|
226
|
+
catch (err) {
|
|
227
|
+
res.status(500).json({ error: 'Failed to fetch project members', details: err.message });
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
return router;
|
|
231
|
+
}
|
package/dist/services/auth.d.ts
CHANGED
|
@@ -1,4 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { StreamByConfig, AuthContext } from '../types';
|
|
3
|
-
export declare function resolveAuth(config: StreamByConfig, req: Request): Promise<AuthContext>;
|
|
1
|
+
import { AuthContext } from '../types';
|
|
4
2
|
export declare function checkRole(auth: AuthContext, required: 'viewer' | 'editor' | 'admin'): void;
|
package/dist/services/auth.js
CHANGED
|
@@ -1,16 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.resolveAuth = resolveAuth;
|
|
4
3
|
exports.checkRole = checkRole;
|
|
5
|
-
async function resolveAuth(config, req) {
|
|
6
|
-
const auth = await config.authProvider(req);
|
|
7
|
-
if (!auth ||
|
|
8
|
-
!auth.userId ||
|
|
9
|
-
!auth.role) {
|
|
10
|
-
throw new Error('Invalid or missing authentication context');
|
|
11
|
-
}
|
|
12
|
-
return auth;
|
|
13
|
-
}
|
|
14
4
|
function checkRole(auth, required) {
|
|
15
5
|
const roles = ['viewer', 'editor', 'admin'];
|
|
16
6
|
const userIdx = roles.indexOf(auth.role);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function isProjectMember(project: any, userId: string): any;
|