streamby-core 0.21.6 β 0.21.8
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/README.md +206 -206
- package/dist/middleware/routes/auth.js +2 -2
- package/dist/middleware/routes/database.js +3 -3
- package/dist/middleware/routes/export.js +10 -10
- package/dist/middleware/routes/file.js +14 -14
- package/dist/middleware/routes/project.js +74 -96
- package/dist/services/auth.d.ts +5 -2
- package/dist/services/auth.js +16 -0
- package/dist/types/index.d.ts +2 -2
- package/package.json +60 -60
package/README.md
CHANGED
|
@@ -1,206 +1,206 @@
|
|
|
1
|
-
# @streamby/core
|
|
2
|
-
|
|
3
|
-
Middleware framework for building storage-agnostic media APIs.
|
|
4
|
-
Part of the [StreamBy](https://streamby.nhexa.cl) ecosystem by TerminalCore Labs.
|
|
5
|
-
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
## π What is it?
|
|
9
|
-
|
|
10
|
-
`@streamby/core` is a plug-and-play middleware for Express (or compatible frameworks) that enables file uploads, listings and **multi-project access** over services like:
|
|
11
|
-
|
|
12
|
-
- β
AWS S3
|
|
13
|
-
- β
Google Cloud Storage (soon)
|
|
14
|
-
- β
Cloudflare R2 (soon)
|
|
15
|
-
- β
Local/Personal servers (soon)
|
|
16
|
-
|
|
17
|
-
It's designed to be installed inside your existing API as a library β **no need to run a separate backend**.
|
|
18
|
-
|
|
19
|
-
---
|
|
20
|
-
|
|
21
|
-
## π¦ Installation
|
|
22
|
-
|
|
23
|
-
```bash
|
|
24
|
-
npm install @streamby/core
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
---
|
|
28
|
-
|
|
29
|
-
## π§± Basic usage
|
|
30
|
-
|
|
31
|
-
```ts
|
|
32
|
-
import express from 'express';
|
|
33
|
-
import { createStreamByRouter } from '@streamby/core';
|
|
34
|
-
|
|
35
|
-
const app = express();
|
|
36
|
-
|
|
37
|
-
app.use('/streamby', createStreamByRouter({
|
|
38
|
-
storageProvider: {
|
|
39
|
-
type: 's3',
|
|
40
|
-
config: {
|
|
41
|
-
bucket: 'your-bucket-name',
|
|
42
|
-
region: 'your-region',
|
|
43
|
-
accessKeyId: 'YOUR_AWS_KEY',
|
|
44
|
-
secretAccessKey: 'YOUR_AWS_SECRET'
|
|
45
|
-
}
|
|
46
|
-
},
|
|
47
|
-
authProvider: async (req) => {
|
|
48
|
-
// extract token/cookie and validate
|
|
49
|
-
return {
|
|
50
|
-
userId: 'demo',
|
|
51
|
-
projects: ['demo-project'],
|
|
52
|
-
role: 'admin',
|
|
53
|
-
};
|
|
54
|
-
},
|
|
55
|
-
projectProvider: async (projectId) => {
|
|
56
|
-
// fetch project from your DB
|
|
57
|
-
return {
|
|
58
|
-
id: projectId,
|
|
59
|
-
name: 'Demo Project',
|
|
60
|
-
description: 'Demo for StreamBy integration',
|
|
61
|
-
rootFolders: [],
|
|
62
|
-
settings: { allowUpload: true }
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
}));
|
|
66
|
-
|
|
67
|
-
app.listen(3000);
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
---
|
|
71
|
-
|
|
72
|
-
## π§ͺ Testing
|
|
73
|
-
|
|
74
|
-
```bash
|
|
75
|
-
npm run test
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
Unit tests use [Vitest](https://vitest.dev) and [Supertest](https://www.npmjs.com/package/supertest).
|
|
79
|
-
|
|
80
|
-
---
|
|
81
|
-
|
|
82
|
-
## π Features
|
|
83
|
-
|
|
84
|
-
- π Multi-project access control
|
|
85
|
-
- π Project-aware file uploads & listings
|
|
86
|
-
- π§Ή Modular adapters per storage provider
|
|
87
|
-
- π§° Built-in testability with mock auth & storage
|
|
88
|
-
- β¨ Simple to extend for custom business logic
|
|
89
|
-
|
|
90
|
-
---
|
|
91
|
-
|
|
92
|
-
## πΊοΈ API Endpoints
|
|
93
|
-
|
|
94
|
-
Here's a summary of the key API endpoints provided by `@streamby/core`:
|
|
95
|
-
|
|
96
|
-
### `GET /streamby/projects`
|
|
97
|
-
|
|
98
|
-
Lists all projects accessible by the authenticated user.
|
|
99
|
-
|
|
100
|
-
**Query Parameters:**
|
|
101
|
-
- `archived`: (Optional) Filter projects by their archived status.
|
|
102
|
-
- `true`: Returns only archived projects.
|
|
103
|
-
- `false`: Returns only unarchived projects.
|
|
104
|
-
- (Omitted): Returns all projects (both archived and unarchived).
|
|
105
|
-
|
|
106
|
-
**Example Response:**
|
|
107
|
-
```json
|
|
108
|
-
{
|
|
109
|
-
"projects": [
|
|
110
|
-
{
|
|
111
|
-
"id": "project1_id",
|
|
112
|
-
"dbType": "nosql",
|
|
113
|
-
"name": "My NoSQL Project",
|
|
114
|
-
"image": "url_to_image",
|
|
115
|
-
"archived": false
|
|
116
|
-
},
|
|
117
|
-
{
|
|
118
|
-
"id": "project2_id",
|
|
119
|
-
"dbType": "sql",
|
|
120
|
-
"name": "My SQL Project",
|
|
121
|
-
"image": "url_to_image",
|
|
122
|
-
"archived": true
|
|
123
|
-
}
|
|
124
|
-
]
|
|
125
|
-
}
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
### `PATCH /streamby/projects/:id/archive`
|
|
129
|
-
|
|
130
|
-
Archives a specific project. After archiving, it returns the complete list of projects for the user, including the updated project.
|
|
131
|
-
|
|
132
|
-
**Example Response:**
|
|
133
|
-
```json
|
|
134
|
-
{
|
|
135
|
-
"success": true,
|
|
136
|
-
"projects": [
|
|
137
|
-
{
|
|
138
|
-
"id": "project1_id",
|
|
139
|
-
"dbType": "nosql",
|
|
140
|
-
"name": "My NoSQL Project",
|
|
141
|
-
"image": "url_to_image",
|
|
142
|
-
"archived": true
|
|
143
|
-
},
|
|
144
|
-
{
|
|
145
|
-
"id": "project2_id",
|
|
146
|
-
"dbType": "sql",
|
|
147
|
-
"name": "My SQL Project",
|
|
148
|
-
"image": "url_to_image",
|
|
149
|
-
"archived": false
|
|
150
|
-
}
|
|
151
|
-
]
|
|
152
|
-
}
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
### `PATCH /streamby/projects/:id/unarchive`
|
|
156
|
-
|
|
157
|
-
Unarchives a specific project. After unarchiving, it returns the complete list of projects for the user, including the updated project.
|
|
158
|
-
|
|
159
|
-
**Example Response:**
|
|
160
|
-
```json
|
|
161
|
-
{
|
|
162
|
-
"success": true,
|
|
163
|
-
"projects": [
|
|
164
|
-
{
|
|
165
|
-
"id": "project1_id",
|
|
166
|
-
"dbType": "nosql",
|
|
167
|
-
"name": "My NoSQL Project",
|
|
168
|
-
"image": "url_to_image",
|
|
169
|
-
"archived": false
|
|
170
|
-
},
|
|
171
|
-
{
|
|
172
|
-
"id": "project2_id",
|
|
173
|
-
"dbType": "sql",
|
|
174
|
-
"name": "My SQL Project",
|
|
175
|
-
"image": "url_to_image",
|
|
176
|
-
"archived": false
|
|
177
|
-
}
|
|
178
|
-
]
|
|
179
|
-
}
|
|
180
|
-
```
|
|
181
|
-
|
|
182
|
-
---
|
|
183
|
-
|
|
184
|
-
## π£ Roadmap
|
|
185
|
-
|
|
186
|
-
- [ ] Support for Google Cloud Storage
|
|
187
|
-
- [ ] CLI tool for uploading files
|
|
188
|
-
- [ ] Role-based access control middleware
|
|
189
|
-
- [ ] Plugin system for extended routes
|
|
190
|
-
- [ ] Streaming support (HLS, audio, etc.)
|
|
191
|
-
|
|
192
|
-
---
|
|
193
|
-
|
|
194
|
-
## π§βπ» Maintained by
|
|
195
|
-
|
|
196
|
-
**TerminalCore Labs** β part of [Nhexa Entertainment](https://nhexa.cl)
|
|
197
|
-
Developed as open-source infrastructure for creative and media-oriented apps.
|
|
198
|
-
|
|
199
|
-
Visit us [here](https://terminalcore.cl)
|
|
200
|
-
|
|
201
|
-
---
|
|
202
|
-
|
|
203
|
-
## π License
|
|
204
|
-
|
|
205
|
-
[MIT](./LICENSE)
|
|
206
|
-
|
|
1
|
+
# @streamby/core
|
|
2
|
+
|
|
3
|
+
Middleware framework for building storage-agnostic media APIs.
|
|
4
|
+
Part of the [StreamBy](https://streamby.nhexa.cl) ecosystem by TerminalCore Labs.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## π What is it?
|
|
9
|
+
|
|
10
|
+
`@streamby/core` is a plug-and-play middleware for Express (or compatible frameworks) that enables file uploads, listings and **multi-project access** over services like:
|
|
11
|
+
|
|
12
|
+
- β
AWS S3
|
|
13
|
+
- β
Google Cloud Storage (soon)
|
|
14
|
+
- β
Cloudflare R2 (soon)
|
|
15
|
+
- β
Local/Personal servers (soon)
|
|
16
|
+
|
|
17
|
+
It's designed to be installed inside your existing API as a library β **no need to run a separate backend**.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## π¦ Installation
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm install @streamby/core
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## π§± Basic usage
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
import express from 'express';
|
|
33
|
+
import { createStreamByRouter } from '@streamby/core';
|
|
34
|
+
|
|
35
|
+
const app = express();
|
|
36
|
+
|
|
37
|
+
app.use('/streamby', createStreamByRouter({
|
|
38
|
+
storageProvider: {
|
|
39
|
+
type: 's3',
|
|
40
|
+
config: {
|
|
41
|
+
bucket: 'your-bucket-name',
|
|
42
|
+
region: 'your-region',
|
|
43
|
+
accessKeyId: 'YOUR_AWS_KEY',
|
|
44
|
+
secretAccessKey: 'YOUR_AWS_SECRET'
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
authProvider: async (req) => {
|
|
48
|
+
// extract token/cookie and validate
|
|
49
|
+
return {
|
|
50
|
+
userId: 'demo',
|
|
51
|
+
projects: ['demo-project'],
|
|
52
|
+
role: 'admin',
|
|
53
|
+
};
|
|
54
|
+
},
|
|
55
|
+
projectProvider: async (projectId) => {
|
|
56
|
+
// fetch project from your DB
|
|
57
|
+
return {
|
|
58
|
+
id: projectId,
|
|
59
|
+
name: 'Demo Project',
|
|
60
|
+
description: 'Demo for StreamBy integration',
|
|
61
|
+
rootFolders: [],
|
|
62
|
+
settings: { allowUpload: true }
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
}));
|
|
66
|
+
|
|
67
|
+
app.listen(3000);
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## π§ͺ Testing
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
npm run test
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Unit tests use [Vitest](https://vitest.dev) and [Supertest](https://www.npmjs.com/package/supertest).
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## π Features
|
|
83
|
+
|
|
84
|
+
- π Multi-project access control
|
|
85
|
+
- π Project-aware file uploads & listings
|
|
86
|
+
- π§Ή Modular adapters per storage provider
|
|
87
|
+
- π§° Built-in testability with mock auth & storage
|
|
88
|
+
- β¨ Simple to extend for custom business logic
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## πΊοΈ API Endpoints
|
|
93
|
+
|
|
94
|
+
Here's a summary of the key API endpoints provided by `@streamby/core`:
|
|
95
|
+
|
|
96
|
+
### `GET /streamby/projects`
|
|
97
|
+
|
|
98
|
+
Lists all projects accessible by the authenticated user.
|
|
99
|
+
|
|
100
|
+
**Query Parameters:**
|
|
101
|
+
- `archived`: (Optional) Filter projects by their archived status.
|
|
102
|
+
- `true`: Returns only archived projects.
|
|
103
|
+
- `false`: Returns only unarchived projects.
|
|
104
|
+
- (Omitted): Returns all projects (both archived and unarchived).
|
|
105
|
+
|
|
106
|
+
**Example Response:**
|
|
107
|
+
```json
|
|
108
|
+
{
|
|
109
|
+
"projects": [
|
|
110
|
+
{
|
|
111
|
+
"id": "project1_id",
|
|
112
|
+
"dbType": "nosql",
|
|
113
|
+
"name": "My NoSQL Project",
|
|
114
|
+
"image": "url_to_image",
|
|
115
|
+
"archived": false
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
"id": "project2_id",
|
|
119
|
+
"dbType": "sql",
|
|
120
|
+
"name": "My SQL Project",
|
|
121
|
+
"image": "url_to_image",
|
|
122
|
+
"archived": true
|
|
123
|
+
}
|
|
124
|
+
]
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### `PATCH /streamby/projects/:id/archive`
|
|
129
|
+
|
|
130
|
+
Archives a specific project. After archiving, it returns the complete list of projects for the user, including the updated project.
|
|
131
|
+
|
|
132
|
+
**Example Response:**
|
|
133
|
+
```json
|
|
134
|
+
{
|
|
135
|
+
"success": true,
|
|
136
|
+
"projects": [
|
|
137
|
+
{
|
|
138
|
+
"id": "project1_id",
|
|
139
|
+
"dbType": "nosql",
|
|
140
|
+
"name": "My NoSQL Project",
|
|
141
|
+
"image": "url_to_image",
|
|
142
|
+
"archived": true
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
"id": "project2_id",
|
|
146
|
+
"dbType": "sql",
|
|
147
|
+
"name": "My SQL Project",
|
|
148
|
+
"image": "url_to_image",
|
|
149
|
+
"archived": false
|
|
150
|
+
}
|
|
151
|
+
]
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### `PATCH /streamby/projects/:id/unarchive`
|
|
156
|
+
|
|
157
|
+
Unarchives a specific project. After unarchiving, it returns the complete list of projects for the user, including the updated project.
|
|
158
|
+
|
|
159
|
+
**Example Response:**
|
|
160
|
+
```json
|
|
161
|
+
{
|
|
162
|
+
"success": true,
|
|
163
|
+
"projects": [
|
|
164
|
+
{
|
|
165
|
+
"id": "project1_id",
|
|
166
|
+
"dbType": "nosql",
|
|
167
|
+
"name": "My NoSQL Project",
|
|
168
|
+
"image": "url_to_image",
|
|
169
|
+
"archived": false
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
"id": "project2_id",
|
|
173
|
+
"dbType": "sql",
|
|
174
|
+
"name": "My SQL Project",
|
|
175
|
+
"image": "url_to_image",
|
|
176
|
+
"archived": false
|
|
177
|
+
}
|
|
178
|
+
]
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
## π£ Roadmap
|
|
185
|
+
|
|
186
|
+
- [ ] Support for Google Cloud Storage
|
|
187
|
+
- [ ] CLI tool for uploading files
|
|
188
|
+
- [ ] Role-based access control middleware
|
|
189
|
+
- [ ] Plugin system for extended routes
|
|
190
|
+
- [ ] Streaming support (HLS, audio, etc.)
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## π§βπ» Maintained by
|
|
195
|
+
|
|
196
|
+
**TerminalCore Labs** β part of [Nhexa Entertainment](https://nhexa.cl)
|
|
197
|
+
Developed as open-source infrastructure for creative and media-oriented apps.
|
|
198
|
+
|
|
199
|
+
Visit us [here](https://terminalcore.cl)
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## π License
|
|
204
|
+
|
|
205
|
+
[MIT](./LICENSE)
|
|
206
|
+
|
|
@@ -12,10 +12,10 @@ function authRouter(config) {
|
|
|
12
12
|
!auth.role) {
|
|
13
13
|
throw new Error('Invalid or missing authentication context');
|
|
14
14
|
}
|
|
15
|
-
return res.status(200).json({ logged: true, ...auth });
|
|
15
|
+
return res.status(200).json({ logged: true, message: 'Authentication successful', ...auth });
|
|
16
16
|
}
|
|
17
17
|
catch (err) {
|
|
18
|
-
return res.status(401).json({ logged: false });
|
|
18
|
+
return res.status(401).json({ logged: false, message: err.message });
|
|
19
19
|
}
|
|
20
20
|
});
|
|
21
21
|
return router;
|
|
@@ -11,16 +11,16 @@ function databaseRouter(config) {
|
|
|
11
11
|
if (!auth ||
|
|
12
12
|
!auth.userId ||
|
|
13
13
|
!auth.role) {
|
|
14
|
-
return res.status(401).json({
|
|
14
|
+
return res.status(401).json({ message: 'Unauthorized' });
|
|
15
15
|
}
|
|
16
16
|
const connectedDbIds = (0, connectionManager_1.getConnectedIds)();
|
|
17
17
|
const databases = (config.databases || [])
|
|
18
18
|
.filter(db => connectedDbIds.includes(db.id))
|
|
19
19
|
.map(db => ({ name: db.id, value: db.type }));
|
|
20
|
-
res.status(200).json({ databases });
|
|
20
|
+
res.status(200).json({ databases, message: 'Databases retrieved successfully' });
|
|
21
21
|
}
|
|
22
22
|
catch (err) {
|
|
23
|
-
res.status(500).json({
|
|
23
|
+
res.status(500).json({ message: err.message });
|
|
24
24
|
}
|
|
25
25
|
});
|
|
26
26
|
return router;
|
|
@@ -14,22 +14,22 @@ function exportRouter(config) {
|
|
|
14
14
|
if (!auth ||
|
|
15
15
|
!auth.userId ||
|
|
16
16
|
!auth.role) {
|
|
17
|
-
return res.status(401).json({
|
|
17
|
+
return res.status(401).json({ message: 'Unauthorized' });
|
|
18
18
|
}
|
|
19
19
|
const projectId = req.params.id;
|
|
20
20
|
const exportId = req.params.export_id;
|
|
21
21
|
const project = await Project.findOne({ _id: projectId });
|
|
22
22
|
if (!project) {
|
|
23
|
-
return res.status(404).json({
|
|
23
|
+
return res.status(404).json({ message: 'Project not found' });
|
|
24
24
|
}
|
|
25
25
|
if (!(0, auth_1.isProjectMember)(project, auth.userId)) {
|
|
26
|
-
return res.status(403).json({
|
|
26
|
+
return res.status(403).json({ message: 'Unauthorized access' });
|
|
27
27
|
}
|
|
28
28
|
const data = await Export.findOne({ _id: exportId });
|
|
29
|
-
res.json({ data: { ...data, id: data._id || data.id, _id: undefined } });
|
|
29
|
+
res.json({ data: { ...data, id: data._id || data.id, _id: undefined }, message: 'Export data fetched successfully' });
|
|
30
30
|
}
|
|
31
31
|
catch (err) {
|
|
32
|
-
res.status(500).json({
|
|
32
|
+
res.status(500).json({ message: 'Failed to fetch export data', details: err.message });
|
|
33
33
|
}
|
|
34
34
|
});
|
|
35
35
|
router.post('/projects/:id/exports', async (req, res) => {
|
|
@@ -38,16 +38,16 @@ function exportRouter(config) {
|
|
|
38
38
|
if (!auth ||
|
|
39
39
|
!auth.userId ||
|
|
40
40
|
!auth.role) {
|
|
41
|
-
return res.status(401).json({
|
|
41
|
+
return res.status(401).json({ message: 'Unauthorized' });
|
|
42
42
|
}
|
|
43
43
|
const projectId = req.params.id;
|
|
44
44
|
const { name, description, collectionName } = req.body;
|
|
45
45
|
if (!name || !collectionName) {
|
|
46
|
-
return res.status(400).json({
|
|
46
|
+
return res.status(400).json({ message: 'Missing export name or collectionName' });
|
|
47
47
|
}
|
|
48
48
|
const project = await Project.findOne({ _id: projectId });
|
|
49
49
|
if (!project || !(0, auth_1.isProjectMember)(project, auth.userId)) {
|
|
50
|
-
return res.status(403).json({
|
|
50
|
+
return res.status(403).json({ message: 'Unauthorized project access' });
|
|
51
51
|
}
|
|
52
52
|
const newExport = await Export.create({
|
|
53
53
|
name,
|
|
@@ -55,10 +55,10 @@ function exportRouter(config) {
|
|
|
55
55
|
collectionName,
|
|
56
56
|
projectId
|
|
57
57
|
});
|
|
58
|
-
res.status(201).json({ data: { ...newExport, id: newExport._id || newExport.id, _id: undefined } });
|
|
58
|
+
res.status(201).json({ data: { ...newExport, id: newExport._id || newExport.id, _id: undefined }, message: 'Export created successfully' });
|
|
59
59
|
}
|
|
60
60
|
catch (err) {
|
|
61
|
-
res.status(500).json({
|
|
61
|
+
res.status(500).json({ message: 'Failed to create export', details: err.message });
|
|
62
62
|
}
|
|
63
63
|
});
|
|
64
64
|
return router;
|
|
@@ -16,20 +16,20 @@ function fileRouter(config) {
|
|
|
16
16
|
if (!auth ||
|
|
17
17
|
!auth.userId ||
|
|
18
18
|
!auth.role) {
|
|
19
|
-
return res.status(401).json({
|
|
19
|
+
return res.status(401).json({ message: 'Unauthorized' });
|
|
20
20
|
}
|
|
21
21
|
if (auth.role !== 'admin' && auth.role !== 'editor') {
|
|
22
|
-
return res.status(403).json({
|
|
22
|
+
return res.status(403).json({ message: 'Permission denied' });
|
|
23
23
|
}
|
|
24
24
|
const projectId = req.params.id;
|
|
25
25
|
if (!projectId) {
|
|
26
|
-
return res.status(400).json({
|
|
26
|
+
return res.status(400).json({ message: 'Missing projectId' });
|
|
27
27
|
}
|
|
28
28
|
const response = await (0, presign_1.getPresignedProjectImageUrl)(adapter, projectId);
|
|
29
|
-
res.status(200).json(response);
|
|
29
|
+
res.status(200).json({ ...response, message: 'Presigned URL generated successfully' });
|
|
30
30
|
}
|
|
31
31
|
catch (err) {
|
|
32
|
-
res.status(500).json({
|
|
32
|
+
res.status(500).json({ message: 'Failed to generate presigned URL', details: err.message });
|
|
33
33
|
}
|
|
34
34
|
});
|
|
35
35
|
router.delete('/delete-project-image-url/:id', async (req, res) => {
|
|
@@ -38,21 +38,21 @@ function fileRouter(config) {
|
|
|
38
38
|
if (!auth ||
|
|
39
39
|
!auth.userId ||
|
|
40
40
|
!auth.role) {
|
|
41
|
-
return res.status(401).json({
|
|
41
|
+
return res.status(401).json({ message: 'Unauthorized' });
|
|
42
42
|
}
|
|
43
43
|
if (auth.role !== 'admin' && auth.role !== 'editor') {
|
|
44
|
-
return res.status(403).json({
|
|
44
|
+
return res.status(403).json({ message: 'Permission denied' });
|
|
45
45
|
}
|
|
46
46
|
const projectId = req.params.id;
|
|
47
47
|
if (!projectId) {
|
|
48
|
-
return res.status(400).json({
|
|
48
|
+
return res.status(400).json({ message: 'Missing projectId' });
|
|
49
49
|
}
|
|
50
50
|
await (0, file_1.deleteProjectImage)(adapter, projectId);
|
|
51
51
|
const updated = await Project.update({ _id: projectId }, { image: '' });
|
|
52
|
-
res.status(201).json(updated);
|
|
52
|
+
res.status(201).json({ ...updated, message: 'Image deleted successfully' });
|
|
53
53
|
}
|
|
54
54
|
catch (err) {
|
|
55
|
-
res.status(500).json({
|
|
55
|
+
res.status(500).json({ message: 'Failed to delete image', details: err.message });
|
|
56
56
|
}
|
|
57
57
|
});
|
|
58
58
|
router.get('/files', async (req, res) => {
|
|
@@ -61,17 +61,17 @@ function fileRouter(config) {
|
|
|
61
61
|
if (!auth ||
|
|
62
62
|
!auth.userId ||
|
|
63
63
|
!auth.role) {
|
|
64
|
-
return res.status(401).json({
|
|
64
|
+
return res.status(401).json({ message: 'Unauthorized' });
|
|
65
65
|
}
|
|
66
66
|
const projectId = (req.query.projectId || req.headers['x-project-id']);
|
|
67
67
|
if (!projectId) {
|
|
68
|
-
return res.status(403).json({
|
|
68
|
+
return res.status(403).json({ message: 'Unauthorized or missing projectId' });
|
|
69
69
|
}
|
|
70
70
|
const files = await (0, file_1.listFilesService)(adapter, req, projectId);
|
|
71
|
-
res.json(files);
|
|
71
|
+
res.json({ files, message: 'Files listed successfully' });
|
|
72
72
|
}
|
|
73
73
|
catch (err) {
|
|
74
|
-
res.status(500).json({
|
|
74
|
+
res.status(500).json({ message: 'Failed to list files', details: err });
|
|
75
75
|
}
|
|
76
76
|
});
|
|
77
77
|
return router;
|
|
@@ -6,8 +6,10 @@ const manager_1 = require("../../models/manager");
|
|
|
6
6
|
const auth_1 = require("../../utils/auth");
|
|
7
7
|
const connectionManager_1 = require("../../adapters/database/connectionManager");
|
|
8
8
|
const sql_1 = require("../../adapters/database/sql");
|
|
9
|
+
const auth_2 = require("../../services/auth");
|
|
9
10
|
function projectRouter(config) {
|
|
10
11
|
const router = (0, express_1.Router)();
|
|
12
|
+
router.use((0, auth_2.authenticate)(config));
|
|
11
13
|
const Project = (0, manager_1.getModel)('projects');
|
|
12
14
|
const mapProjectToResponseFormat = (project, userId) => {
|
|
13
15
|
const currentUserMember = project.members?.find((member) => member.userId === userId);
|
|
@@ -21,12 +23,7 @@ function projectRouter(config) {
|
|
|
21
23
|
};
|
|
22
24
|
router.get('/projects', async (req, res) => {
|
|
23
25
|
try {
|
|
24
|
-
const auth =
|
|
25
|
-
if (!auth ||
|
|
26
|
-
!auth.userId ||
|
|
27
|
-
!auth.role) {
|
|
28
|
-
return res.status(401).json({ error: 'Unauthorized' });
|
|
29
|
-
}
|
|
26
|
+
const auth = req.auth;
|
|
30
27
|
const archivedQuery = req.query.archived;
|
|
31
28
|
const filterArchived = archivedQuery !== undefined ? String(archivedQuery).toLowerCase() === 'true' : undefined;
|
|
32
29
|
const allProjects = await Project.find({}); // Fetch all projects
|
|
@@ -42,34 +39,29 @@ function projectRouter(config) {
|
|
|
42
39
|
return true;
|
|
43
40
|
})
|
|
44
41
|
.map(project => mapProjectToResponseFormat(project, auth.userId));
|
|
45
|
-
res.json({ projects });
|
|
42
|
+
res.json({ projects, message: 'Projects listed successfully' });
|
|
46
43
|
}
|
|
47
44
|
catch (err) {
|
|
48
45
|
console.error('Error in /projects endpoint:', err);
|
|
49
|
-
res.status(500).json({
|
|
46
|
+
res.status(500).json({ message: 'Failed to list projects', details: err });
|
|
50
47
|
}
|
|
51
48
|
});
|
|
52
49
|
router.post('/projects/create', async (req, res) => {
|
|
53
50
|
try {
|
|
54
|
-
const auth =
|
|
55
|
-
if (!auth ||
|
|
56
|
-
!auth.userId ||
|
|
57
|
-
!auth.role) {
|
|
58
|
-
return res.status(401).json({ error: 'Unauthorized' });
|
|
59
|
-
}
|
|
51
|
+
const auth = req.auth;
|
|
60
52
|
if (auth.role !== 'admin' && auth.role !== 'editor') {
|
|
61
|
-
return res.status(403).json({
|
|
53
|
+
return res.status(403).json({ message: 'Permission denied' });
|
|
62
54
|
}
|
|
63
55
|
const { name, description, dbType, image } = req.body;
|
|
64
56
|
const mainDb = config.databases?.find(db => db.main);
|
|
65
57
|
if (!mainDb) {
|
|
66
|
-
return res.status(500).json({
|
|
58
|
+
return res.status(500).json({ message: 'Main database not configured' });
|
|
67
59
|
}
|
|
68
60
|
const userDbType = mainDb.type;
|
|
69
61
|
const User = (0, manager_1.getModel)('users', userDbType);
|
|
70
62
|
const user = await User.findOne({ _id: auth.userId });
|
|
71
63
|
if (!user) {
|
|
72
|
-
return res.status(404).json({
|
|
64
|
+
return res.status(404).json({ message: 'User not found' });
|
|
73
65
|
}
|
|
74
66
|
const newProject = await Project.create({
|
|
75
67
|
dbType: dbType || 'nosql',
|
|
@@ -78,102 +70,103 @@ function projectRouter(config) {
|
|
|
78
70
|
image: image || '',
|
|
79
71
|
members: [{ userId: auth.userId, username: user.username, role: "admin", archived: false }]
|
|
80
72
|
});
|
|
81
|
-
|
|
73
|
+
const allProjects = await Project.find({});
|
|
74
|
+
const projects = allProjects
|
|
75
|
+
.filter(project => {
|
|
76
|
+
const isMember = project.members?.some((m) => m.userId?.toString() === auth.userId?.toString());
|
|
77
|
+
return isMember; // Only include projects where the user is a member
|
|
78
|
+
})
|
|
79
|
+
.map(project => mapProjectToResponseFormat(project, auth.userId));
|
|
80
|
+
res.status(200).json({ success: true, projects: projects, projectId: newProject._id || newProject.id, message: 'Project created successfully' });
|
|
82
81
|
}
|
|
83
82
|
catch (err) {
|
|
84
|
-
res.status(500).json({
|
|
83
|
+
res.status(500).json({ message: 'Failed to create project', details: err.message });
|
|
85
84
|
}
|
|
86
85
|
});
|
|
87
86
|
router.get('/projects/:id', async (req, res) => {
|
|
88
87
|
try {
|
|
89
|
-
const auth =
|
|
90
|
-
if (!auth ||
|
|
91
|
-
!auth.userId ||
|
|
92
|
-
!auth.role) {
|
|
93
|
-
return res.status(401).json({ error: 'Unauthorized' });
|
|
94
|
-
}
|
|
88
|
+
const auth = req.auth;
|
|
95
89
|
const projectId = req.params.id;
|
|
96
90
|
const project = await Project.findOne({ _id: projectId });
|
|
97
91
|
if (!project) {
|
|
98
|
-
return res.status(404).json({
|
|
92
|
+
return res.status(404).json({ message: 'Project not found' });
|
|
99
93
|
}
|
|
100
94
|
if (!(0, auth_1.isProjectMember)(project, auth.userId)) {
|
|
101
|
-
return res.status(403).json({
|
|
95
|
+
return res.status(403).json({ message: 'Unauthorized project access' });
|
|
102
96
|
}
|
|
103
|
-
res.json({ project: { ...project, id: project._id || project.id, _id: undefined } });
|
|
97
|
+
res.json({ project: { ...project, id: project._id || project.id, _id: undefined }, message: 'Project fetched successfully' });
|
|
104
98
|
}
|
|
105
99
|
catch (err) {
|
|
106
|
-
res.status(500).json({
|
|
100
|
+
res.status(500).json({ message: 'Failed to fetch project', details: err.message });
|
|
107
101
|
}
|
|
108
102
|
});
|
|
109
103
|
router.patch('/projects/:id', async (req, res) => {
|
|
110
104
|
try {
|
|
111
|
-
const auth =
|
|
112
|
-
if (!auth ||
|
|
113
|
-
!auth.userId ||
|
|
114
|
-
!auth.role) {
|
|
115
|
-
return res.status(401).json({ error: 'Unauthorized' });
|
|
116
|
-
}
|
|
105
|
+
const auth = req.auth;
|
|
117
106
|
if (auth.role !== 'admin' && auth.role !== 'editor') {
|
|
118
|
-
return res.status(403).json({
|
|
107
|
+
return res.status(403).json({ message: 'Permission denied' });
|
|
119
108
|
}
|
|
120
109
|
const projectId = req.params.id;
|
|
121
110
|
const updates = req.body;
|
|
122
111
|
const project = await Project.findOne({ _id: projectId });
|
|
123
112
|
if (!project) {
|
|
124
|
-
return res.status(404).json({
|
|
113
|
+
return res.status(404).json({ message: 'Project not found' });
|
|
125
114
|
}
|
|
126
115
|
if (!updates || typeof updates !== 'object') {
|
|
127
|
-
return res.status(400).json({
|
|
116
|
+
return res.status(400).json({ message: 'Missing updates payload' });
|
|
128
117
|
}
|
|
129
118
|
if (!(0, auth_1.isProjectMember)(project, auth.userId)) {
|
|
130
|
-
return res.status(403).json({
|
|
119
|
+
return res.status(403).json({ message: 'Unauthorized project access' });
|
|
131
120
|
}
|
|
132
121
|
const updated = await Project.update({ _id: projectId }, updates);
|
|
133
122
|
if (!updated) {
|
|
134
|
-
return res.status(404).json({
|
|
123
|
+
return res.status(404).json({ message: 'Project not found or not updated' });
|
|
135
124
|
}
|
|
136
|
-
|
|
125
|
+
const allProjects = await Project.find({});
|
|
126
|
+
const projects = allProjects
|
|
127
|
+
.filter(project => {
|
|
128
|
+
const isMember = project.members?.some((m) => m.userId?.toString() === auth.userId?.toString());
|
|
129
|
+
return isMember; // Only include projects where the user is a member
|
|
130
|
+
})
|
|
131
|
+
.map(project => mapProjectToResponseFormat(project, auth.userId));
|
|
132
|
+
res.status(200).json({ success: true, projects: projects, projectId: updated._id || updated.id, message: 'Project updated successfully' });
|
|
137
133
|
}
|
|
138
134
|
catch (err) {
|
|
139
|
-
res.status(500).json({
|
|
135
|
+
res.status(500).json({ message: 'Failed to update project', details: err.message });
|
|
140
136
|
}
|
|
141
137
|
});
|
|
142
138
|
router.delete('/projects/:id', async (req, res) => {
|
|
143
139
|
try {
|
|
144
|
-
const auth =
|
|
145
|
-
if (!auth ||
|
|
146
|
-
!auth.userId ||
|
|
147
|
-
!auth.role) {
|
|
148
|
-
return res.status(401).json({ error: 'Unauthorized' });
|
|
149
|
-
}
|
|
140
|
+
const auth = req.auth;
|
|
150
141
|
const projectId = req.params.id;
|
|
151
142
|
const project = await Project.findOne({ _id: projectId });
|
|
152
143
|
if (!project) {
|
|
153
|
-
return res.status(404).json({
|
|
144
|
+
return res.status(404).json({ message: 'Project not found' });
|
|
154
145
|
}
|
|
155
146
|
if (!(0, auth_1.isProjectMember)(project, auth.userId)) {
|
|
156
|
-
return res.status(403).json({
|
|
147
|
+
return res.status(403).json({ message: 'Unauthorized project access' });
|
|
157
148
|
}
|
|
158
149
|
await Project.delete({ _id: projectId });
|
|
159
|
-
|
|
150
|
+
const allProjects = await Project.find({});
|
|
151
|
+
const projects = allProjects
|
|
152
|
+
.filter(project => {
|
|
153
|
+
const isMember = project.members?.some((m) => m.userId?.toString() === auth.userId?.toString());
|
|
154
|
+
return isMember; // Only include projects where the user is a member
|
|
155
|
+
})
|
|
156
|
+
.map(project => mapProjectToResponseFormat(project, auth.userId));
|
|
157
|
+
res.status(200).json({ success: true, projects: projects, message: 'Project deleted successfully' });
|
|
160
158
|
}
|
|
161
159
|
catch (err) {
|
|
162
|
-
res.status(500).json({
|
|
160
|
+
res.status(500).json({ message: 'Failed to delete project', details: err.message });
|
|
163
161
|
}
|
|
164
162
|
});
|
|
165
163
|
router.patch('/projects/:id/archive', async (req, res) => {
|
|
166
164
|
try {
|
|
167
|
-
const auth =
|
|
168
|
-
if (!auth ||
|
|
169
|
-
!auth.userId ||
|
|
170
|
-
!auth.role) {
|
|
171
|
-
return res.status(401).json({ error: 'Unauthorized' });
|
|
172
|
-
}
|
|
165
|
+
const auth = req.auth;
|
|
173
166
|
const projectId = req.params.id;
|
|
174
167
|
const project = await Project.findOne({ _id: projectId });
|
|
175
168
|
if (!project || !(0, auth_1.isProjectMember)(project, auth.userId)) {
|
|
176
|
-
return res.status(403).json({
|
|
169
|
+
return res.status(403).json({ message: 'Unauthorized project access' });
|
|
177
170
|
}
|
|
178
171
|
if (project.dbType === 'sql') {
|
|
179
172
|
const connection = (0, connectionManager_1.getConnection)(config.databases?.find(db => db.main)?.id || '').client;
|
|
@@ -182,7 +175,7 @@ function projectRouter(config) {
|
|
|
182
175
|
else {
|
|
183
176
|
const memberIndex = project.members.findIndex((member) => member.userId === auth.userId);
|
|
184
177
|
if (memberIndex === -1) {
|
|
185
|
-
return res.status(403).json({
|
|
178
|
+
return res.status(403).json({ message: 'Unauthorized project access' });
|
|
186
179
|
}
|
|
187
180
|
project.members[memberIndex].archived = true;
|
|
188
181
|
project.members[memberIndex].archivedBy = auth.userId;
|
|
@@ -197,24 +190,19 @@ function projectRouter(config) {
|
|
|
197
190
|
return isMember; // Only include projects where the user is a member
|
|
198
191
|
})
|
|
199
192
|
.map(project => mapProjectToResponseFormat(project, auth.userId));
|
|
200
|
-
res.status(200).json({ success: true, projects: projects });
|
|
193
|
+
res.status(200).json({ success: true, projects: projects, message: 'Project archived successfully' });
|
|
201
194
|
}
|
|
202
195
|
catch (err) {
|
|
203
|
-
res.status(500).json({
|
|
196
|
+
res.status(500).json({ message: 'Failed to archive project', details: err.message });
|
|
204
197
|
}
|
|
205
198
|
});
|
|
206
199
|
router.patch('/projects/:id/unarchive', async (req, res) => {
|
|
207
200
|
try {
|
|
208
|
-
const auth =
|
|
209
|
-
if (!auth ||
|
|
210
|
-
!auth.userId ||
|
|
211
|
-
!auth.role) {
|
|
212
|
-
return res.status(401).json({ error: 'Unauthorized' });
|
|
213
|
-
}
|
|
201
|
+
const auth = req.auth;
|
|
214
202
|
const projectId = req.params.id;
|
|
215
203
|
const project = await Project.findOne({ _id: projectId });
|
|
216
204
|
if (!project || !(0, auth_1.isProjectMember)(project, auth.userId)) {
|
|
217
|
-
return res.status(403).json({
|
|
205
|
+
return res.status(403).json({ message: 'Unauthorized project access' });
|
|
218
206
|
}
|
|
219
207
|
if (project.dbType === 'sql') {
|
|
220
208
|
const connection = (0, connectionManager_1.getConnection)(config.databases?.find(db => db.main)?.id || '').client;
|
|
@@ -223,7 +211,7 @@ function projectRouter(config) {
|
|
|
223
211
|
else {
|
|
224
212
|
const memberIndex = project.members.findIndex((member) => member.userId === auth.userId);
|
|
225
213
|
if (memberIndex === -1) {
|
|
226
|
-
return res.status(403).json({
|
|
214
|
+
return res.status(403).json({ message: 'Unauthorized project access' });
|
|
227
215
|
}
|
|
228
216
|
project.members[memberIndex].archived = false;
|
|
229
217
|
project.members[memberIndex].archivedBy = null;
|
|
@@ -238,31 +226,26 @@ function projectRouter(config) {
|
|
|
238
226
|
return isMember; // Only include projects where the user is a member
|
|
239
227
|
})
|
|
240
228
|
.map(project => mapProjectToResponseFormat(project, auth.userId));
|
|
241
|
-
res.status(200).json({ success: true, projects: projects });
|
|
229
|
+
res.status(200).json({ success: true, projects: projects, message: 'Project unarchived successfully' });
|
|
242
230
|
}
|
|
243
231
|
catch (err) {
|
|
244
|
-
res.status(500).json({
|
|
232
|
+
res.status(500).json({ message: 'Failed to unarchive project', details: err.message });
|
|
245
233
|
}
|
|
246
234
|
});
|
|
247
235
|
router.get('/projects/:id/members', async (req, res) => {
|
|
248
236
|
try {
|
|
249
|
-
const auth =
|
|
250
|
-
if (!auth ||
|
|
251
|
-
!auth.userId ||
|
|
252
|
-
!auth.role) {
|
|
253
|
-
return res.status(401).json({ error: 'Unauthorized' });
|
|
254
|
-
}
|
|
237
|
+
const auth = req.auth;
|
|
255
238
|
const projectId = req.params.id;
|
|
256
239
|
const project = await Project.findOne({ _id: projectId });
|
|
257
240
|
if (!project) {
|
|
258
|
-
return res.status(404).json({
|
|
241
|
+
return res.status(404).json({ message: 'Project not found' });
|
|
259
242
|
}
|
|
260
243
|
if (!(0, auth_1.isProjectMember)(project, auth.userId)) {
|
|
261
|
-
return res.status(403).json({
|
|
244
|
+
return res.status(403).json({ message: 'Unauthorized project access' });
|
|
262
245
|
}
|
|
263
246
|
const mainDb = config.databases?.find(db => db.main);
|
|
264
247
|
if (!mainDb) {
|
|
265
|
-
return res.status(500).json({
|
|
248
|
+
return res.status(500).json({ message: 'Main database not configured' });
|
|
266
249
|
}
|
|
267
250
|
const userDbType = mainDb.type;
|
|
268
251
|
const User = (0, manager_1.getModel)('users', userDbType);
|
|
@@ -275,43 +258,38 @@ function projectRouter(config) {
|
|
|
275
258
|
profilePic: user ? user.profilePic : ''
|
|
276
259
|
};
|
|
277
260
|
}));
|
|
278
|
-
res.json({ members: membersWithUsernames });
|
|
261
|
+
res.json({ members: membersWithUsernames, message: 'Project members fetched successfully' });
|
|
279
262
|
}
|
|
280
263
|
catch (err) {
|
|
281
|
-
res.status(500).json({
|
|
264
|
+
res.status(500).json({ message: 'Failed to fetch project members', details: err.message });
|
|
282
265
|
}
|
|
283
266
|
});
|
|
284
267
|
router.post('/projects/:id/image', async (req, res) => {
|
|
285
268
|
try {
|
|
286
|
-
const auth =
|
|
287
|
-
if (!auth ||
|
|
288
|
-
!auth.userId ||
|
|
289
|
-
!auth.role) {
|
|
290
|
-
return res.status(401).json({ error: 'Unauthorized' });
|
|
291
|
-
}
|
|
269
|
+
const auth = req.auth;
|
|
292
270
|
if (auth.role !== 'admin' && auth.role !== 'editor') {
|
|
293
|
-
return res.status(403).json({
|
|
271
|
+
return res.status(403).json({ message: 'Permission denied' });
|
|
294
272
|
}
|
|
295
273
|
const projectId = req.params.id;
|
|
296
274
|
const { imageUrl } = req.body;
|
|
297
275
|
if (!projectId || !imageUrl) {
|
|
298
|
-
return res.status(400).json({
|
|
276
|
+
return res.status(400).json({ message: 'Missing projectId or imageUrl' });
|
|
299
277
|
}
|
|
300
278
|
const project = await Project.findOne({ _id: projectId });
|
|
301
279
|
if (!project) {
|
|
302
|
-
return res.status(404).json({
|
|
280
|
+
return res.status(404).json({ message: 'Project not found' });
|
|
303
281
|
}
|
|
304
282
|
if (!(0, auth_1.isProjectMember)(project, auth.userId)) {
|
|
305
|
-
return res.status(403).json({
|
|
283
|
+
return res.status(403).json({ message: 'Unauthorized project access' });
|
|
306
284
|
}
|
|
307
285
|
const updatedProject = await Project.update({ _id: projectId }, { image: imageUrl });
|
|
308
286
|
if (!updatedProject) {
|
|
309
|
-
return res.status(404).json({
|
|
287
|
+
return res.status(404).json({ message: 'Project not found or not updated' });
|
|
310
288
|
}
|
|
311
|
-
res.status(200).json({ success: true, project: { ...updatedProject, id: updatedProject._id || updatedProject.id, _id: undefined } });
|
|
289
|
+
res.status(200).json({ success: true, project: { ...updatedProject, id: updatedProject._id || updatedProject.id, _id: undefined }, message: 'Project image updated successfully' });
|
|
312
290
|
}
|
|
313
291
|
catch (err) {
|
|
314
|
-
res.status(500).json({
|
|
292
|
+
res.status(500).json({ message: 'Failed to update project image', details: err.message });
|
|
315
293
|
}
|
|
316
294
|
});
|
|
317
295
|
return router;
|
package/dist/services/auth.d.ts
CHANGED
|
@@ -1,2 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { Auth } from '../types';
|
|
2
|
+
import { Request, Response, NextFunction } from 'express';
|
|
3
|
+
import { StreamByConfig } from '../types';
|
|
4
|
+
export declare const authenticate: (config: StreamByConfig) => (req: Request, res: Response, next: NextFunction) => Promise<Response<any, Record<string, any>> | undefined>;
|
|
5
|
+
export declare function checkRole(auth: Auth, required: 'viewer' | 'editor' | 'admin'): void;
|
package/dist/services/auth.js
CHANGED
|
@@ -1,6 +1,22 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.authenticate = void 0;
|
|
3
4
|
exports.checkRole = checkRole;
|
|
5
|
+
const authenticate = (config) => async (req, res, next) => {
|
|
6
|
+
try {
|
|
7
|
+
const auth = await config.authProvider(req);
|
|
8
|
+
if (!auth || !auth.userId || !auth.role) {
|
|
9
|
+
return res.status(401).json({ error: 'Unauthorized' });
|
|
10
|
+
}
|
|
11
|
+
req.auth = auth;
|
|
12
|
+
next();
|
|
13
|
+
}
|
|
14
|
+
catch (error) {
|
|
15
|
+
console.error('Authentication failed:', error);
|
|
16
|
+
return res.status(401).json({ error: 'Unauthorized' });
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
exports.authenticate = authenticate;
|
|
4
20
|
function checkRole(auth, required) {
|
|
5
21
|
const roles = ['viewer', 'editor', 'admin'];
|
|
6
22
|
const userIdx = roles.indexOf(auth.role);
|
package/dist/types/index.d.ts
CHANGED
|
@@ -61,12 +61,12 @@ export interface StreamByConfig {
|
|
|
61
61
|
databases?: DatabaseCredential[];
|
|
62
62
|
adapter?: StorageAdapter;
|
|
63
63
|
}
|
|
64
|
-
export interface
|
|
64
|
+
export interface Auth {
|
|
65
65
|
userId: string;
|
|
66
66
|
username: string;
|
|
67
67
|
role: 'viewer' | 'editor' | 'admin';
|
|
68
68
|
}
|
|
69
|
-
export type AuthProvider = (req: Request) => Promise<
|
|
69
|
+
export type AuthProvider = (req: Request) => Promise<Auth>;
|
|
70
70
|
export interface Export {
|
|
71
71
|
_id?: string;
|
|
72
72
|
id: string;
|
package/package.json
CHANGED
|
@@ -1,60 +1,60 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "streamby-core",
|
|
3
|
-
"version": "0.21.
|
|
4
|
-
"description": "StreamBy middleware framework for media storage management",
|
|
5
|
-
"main": "dist/index.js",
|
|
6
|
-
"types": "dist/index.d.ts",
|
|
7
|
-
"files": [
|
|
8
|
-
"dist"
|
|
9
|
-
],
|
|
10
|
-
"scripts": {
|
|
11
|
-
"build": "tsc",
|
|
12
|
-
"test": "vitest",
|
|
13
|
-
"dev": "ts-node-dev --respawn --clear dev.ts",
|
|
14
|
-
"prepublishOnly": "npm run build"
|
|
15
|
-
},
|
|
16
|
-
"repository": {
|
|
17
|
-
"type": "git",
|
|
18
|
-
"url": "https://github.com/GwerhDev/StreamBy-Package.git"
|
|
19
|
-
},
|
|
20
|
-
"keywords": [
|
|
21
|
-
"streamby",
|
|
22
|
-
"middleware",
|
|
23
|
-
"upload",
|
|
24
|
-
"storage",
|
|
25
|
-
"s3",
|
|
26
|
-
"express",
|
|
27
|
-
"typescript"
|
|
28
|
-
],
|
|
29
|
-
"author": "TerminalCore Labs",
|
|
30
|
-
"license": "MIT",
|
|
31
|
-
"dependencies": {
|
|
32
|
-
"@aws-sdk/client-s3": "^3.528.0",
|
|
33
|
-
"@aws-sdk/s3-request-presigner": "^3.787.0",
|
|
34
|
-
"@prisma/client": "^6.12.0",
|
|
35
|
-
"bcrypt": "^5.1.1",
|
|
36
|
-
"dotenv": "^16.5.0",
|
|
37
|
-
"express": "^4.0.0",
|
|
38
|
-
"mongodb": "^6.17.0",
|
|
39
|
-
"mongoose": "^8.13.2",
|
|
40
|
-
"pg": "^8.16.3",
|
|
41
|
-
"prisma": "^6.12.0"
|
|
42
|
-
},
|
|
43
|
-
"devDependencies": {
|
|
44
|
-
"@types/bcrypt": "^5.0.2",
|
|
45
|
-
"@types/cors": "^2.8.18",
|
|
46
|
-
"@types/express": "^4.17.17",
|
|
47
|
-
"@types/mongodb": "^4.0.7",
|
|
48
|
-
"@types/node": "^22.15.21",
|
|
49
|
-
"@types/pg": "^8.15.4",
|
|
50
|
-
"@types/supertest": "^6.0.3",
|
|
51
|
-
"cors": "^2.8.5",
|
|
52
|
-
"supertest": "^7.1.4",
|
|
53
|
-
"ts-node-dev": "^2.0.0",
|
|
54
|
-
"typescript": "^5.8.3",
|
|
55
|
-
"vitest": "^3.1.1"
|
|
56
|
-
},
|
|
57
|
-
"peerDependencies": {
|
|
58
|
-
"express": "^4.0.0"
|
|
59
|
-
}
|
|
60
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "streamby-core",
|
|
3
|
+
"version": "0.21.8",
|
|
4
|
+
"description": "StreamBy middleware framework for media storage management",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist"
|
|
9
|
+
],
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"test": "vitest",
|
|
13
|
+
"dev": "ts-node-dev --respawn --clear dev.ts",
|
|
14
|
+
"prepublishOnly": "npm run build"
|
|
15
|
+
},
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "https://github.com/GwerhDev/StreamBy-Package.git"
|
|
19
|
+
},
|
|
20
|
+
"keywords": [
|
|
21
|
+
"streamby",
|
|
22
|
+
"middleware",
|
|
23
|
+
"upload",
|
|
24
|
+
"storage",
|
|
25
|
+
"s3",
|
|
26
|
+
"express",
|
|
27
|
+
"typescript"
|
|
28
|
+
],
|
|
29
|
+
"author": "TerminalCore Labs",
|
|
30
|
+
"license": "MIT",
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"@aws-sdk/client-s3": "^3.528.0",
|
|
33
|
+
"@aws-sdk/s3-request-presigner": "^3.787.0",
|
|
34
|
+
"@prisma/client": "^6.12.0",
|
|
35
|
+
"bcrypt": "^5.1.1",
|
|
36
|
+
"dotenv": "^16.5.0",
|
|
37
|
+
"express": "^4.0.0",
|
|
38
|
+
"mongodb": "^6.17.0",
|
|
39
|
+
"mongoose": "^8.13.2",
|
|
40
|
+
"pg": "^8.16.3",
|
|
41
|
+
"prisma": "^6.12.0"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@types/bcrypt": "^5.0.2",
|
|
45
|
+
"@types/cors": "^2.8.18",
|
|
46
|
+
"@types/express": "^4.17.17",
|
|
47
|
+
"@types/mongodb": "^4.0.7",
|
|
48
|
+
"@types/node": "^22.15.21",
|
|
49
|
+
"@types/pg": "^8.15.4",
|
|
50
|
+
"@types/supertest": "^6.0.3",
|
|
51
|
+
"cors": "^2.8.5",
|
|
52
|
+
"supertest": "^7.1.4",
|
|
53
|
+
"ts-node-dev": "^2.0.0",
|
|
54
|
+
"typescript": "^5.8.3",
|
|
55
|
+
"vitest": "^3.1.1"
|
|
56
|
+
},
|
|
57
|
+
"peerDependencies": {
|
|
58
|
+
"express": "^4.0.0"
|
|
59
|
+
}
|
|
60
|
+
}
|