@programisto/edrm-storage 1.0.5 → 1.0.7

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.
@@ -40,6 +40,7 @@ export interface IFile {
40
40
  tenantId?: string;
41
41
  entityName?: string;
42
42
  entityId?: string;
43
+ portalEntityId?: string;
43
44
  uploadedBy?: string;
44
45
  expiresAt?: Date;
45
46
  lastAccessedAt?: Date;
@@ -65,6 +66,8 @@ declare class File extends EnduranceSchema implements IFile {
65
66
  tenantId: string;
66
67
  entityName: string;
67
68
  entityId: string;
69
+ /** Identifiant de l'entité du portail (multi-entités). Optionnel pour rétrocompatibilité. */
70
+ portalEntityId: string;
68
71
  uploadedBy: string;
69
72
  expiresAt: Date;
70
73
  lastAccessedAt: Date;
@@ -56,6 +56,8 @@ let File = class File extends EnduranceSchema {
56
56
  tenantId;
57
57
  entityName;
58
58
  entityId;
59
+ /** Identifiant de l'entité du portail (multi-entités). Optionnel pour rétrocompatibilité. */
60
+ portalEntityId;
59
61
  uploadedBy;
60
62
  expiresAt;
61
63
  lastAccessedAt;
@@ -140,6 +142,10 @@ __decorate([
140
142
  EnduranceModelType.prop({ required: false }),
141
143
  __metadata("design:type", String)
142
144
  ], File.prototype, "entityId", void 0);
145
+ __decorate([
146
+ EnduranceModelType.prop({ required: false }),
147
+ __metadata("design:type", String)
148
+ ], File.prototype, "portalEntityId", void 0);
143
149
  __decorate([
144
150
  EnduranceModelType.prop({ required: false }),
145
151
  __metadata("design:type", String)
@@ -47,6 +47,9 @@ class EdrmStorageRouter extends EnduranceRouter {
47
47
  * entityId:
48
48
  * type: string
49
49
  * description: Identifiant de l’entité métier associée
50
+ * public:
51
+ * type: boolean
52
+ * description: Si true, image publique accessible depuis n'importe quelle entité (portalEntityId non défini)
50
53
  * provider:
51
54
  * type: string
52
55
  * enum: [S3]
@@ -70,14 +73,23 @@ class EdrmStorageRouter extends EnduranceRouter {
70
73
  */
71
74
  this.post('/files/init', userOptions, async (req, res) => {
72
75
  try {
73
- const { originalName, mimeType, size, tenantId, entityName, entityId, provider = 'S3', metadata, tags } = req.body;
74
- if (!originalName || !mimeType || !size || !tenantId || !entityName || !entityId) {
76
+ const { originalName, mimeType, size, tenantId, entityName, entityId, public: isPublic = false, provider = 'S3', metadata, tags } = req.body;
77
+ const isPublicFile = isPublic === true;
78
+ const effectiveEntityName = isPublicFile ? 'portal' : entityName;
79
+ const effectiveEntityId = isPublicFile ? 'all' : entityId;
80
+ if (!originalName || !mimeType || !size || !tenantId) {
75
81
  return res.status(400).json({
76
82
  success: false,
77
- message: 'Paramètres manquants: originalName, mimeType, size, tenantId, entityName, entityId'
83
+ message: 'Paramètres manquants: originalName, mimeType, size, tenantId'
78
84
  });
79
85
  }
80
- const result = await this.storageService.initUpload(originalName, mimeType, size, tenantId, entityName, entityId, provider, metadata, tags);
86
+ if (!isPublicFile && (!entityName || !entityId)) {
87
+ return res.status(400).json({
88
+ success: false,
89
+ message: 'Paramètres manquants: entityName et entityId (ou public: true)'
90
+ });
91
+ }
92
+ const result = await this.storageService.initUpload(originalName, mimeType, size, tenantId, effectiveEntityName, effectiveEntityId, provider, metadata, tags, isPublicFile ? undefined : req.entity?._id?.toString());
81
93
  return res.json({
82
94
  success: true,
83
95
  data: result
@@ -114,7 +126,7 @@ class EdrmStorageRouter extends EnduranceRouter {
114
126
  this.post('/files/:fileId/complete', userOptions, async (req, res) => {
115
127
  try {
116
128
  const { fileId } = req.params;
117
- const result = await this.storageService.completeUpload(fileId);
129
+ const result = await this.storageService.completeUpload(fileId, req.entity?._id?.toString());
118
130
  return res.json({
119
131
  success: true,
120
132
  data: result
@@ -163,7 +175,7 @@ class EdrmStorageRouter extends EnduranceRouter {
163
175
  try {
164
176
  const { fileId } = req.params;
165
177
  const { filename, expiresIn = 3600 } = req.query;
166
- const result = await this.storageService.getDownloadUrl(fileId, filename, parseInt(expiresIn));
178
+ const result = await this.storageService.getDownloadUrl(fileId, filename, parseInt(expiresIn), req.entity?._id?.toString());
167
179
  return res.json({
168
180
  success: true,
169
181
  data: result
@@ -200,7 +212,7 @@ class EdrmStorageRouter extends EnduranceRouter {
200
212
  this.delete('/files/:fileId', adminOptions, async (req, res) => {
201
213
  try {
202
214
  const { fileId } = req.params;
203
- await this.storageService.deleteFile(fileId);
215
+ await this.storageService.deleteFile(fileId, req.entity?._id?.toString());
204
216
  return res.json({
205
217
  success: true,
206
218
  message: 'Fichier supprimé avec succès'
@@ -264,7 +276,7 @@ class EdrmStorageRouter extends EnduranceRouter {
264
276
  this.get('/files', adminOptions, async (req, res) => {
265
277
  try {
266
278
  const { tenantId, entityName, entityId, status, page = 1, limit = 20 } = req.query;
267
- const result = await this.storageService.listFiles(tenantId, entityName, entityId, status, parseInt(page), parseInt(limit));
279
+ const result = await this.storageService.listFiles(tenantId, entityName, entityId, status, parseInt(page), parseInt(limit), req.entity?._id?.toString());
268
280
  return res.json({
269
281
  success: true,
270
282
  data: result
@@ -301,7 +313,7 @@ class EdrmStorageRouter extends EnduranceRouter {
301
313
  this.get('/files/:fileId', userOptions, async (req, res) => {
302
314
  try {
303
315
  const { fileId } = req.params;
304
- const result = await this.storageService.getFileById(fileId);
316
+ const result = await this.storageService.getFileById(fileId, req.entity?._id?.toString());
305
317
  return res.json({
306
318
  success: true,
307
319
  data: result
@@ -7,7 +7,7 @@ export declare class EdrmStorageService {
7
7
  private getProvider;
8
8
  private generateKey;
9
9
  private detectFileType;
10
- initUpload(originalName: string, mimeType: string, size: number, tenantId: string, entityName: string, entityId: string, provider?: FileProvider, metadata?: Record<string, any>, tags?: string[]): Promise<{
10
+ initUpload(originalName: string, mimeType: string, size: number, tenantId: string, entityName: string, entityId: string, provider?: FileProvider, metadata?: Record<string, any>, tags?: string[], portalEntityId?: string): Promise<{
11
11
  fileId: import("mongoose").Types.ObjectId;
12
12
  uploadId: string;
13
13
  presignedUrl: string;
@@ -15,14 +15,14 @@ export declare class EdrmStorageService {
15
15
  bucket: string;
16
16
  key: string;
17
17
  }>;
18
- completeUpload(fileId: string): Promise<any>;
19
- getDownloadUrl(fileId: string, filename?: string, expiresIn?: number): Promise<any>;
20
- deleteFile(fileId: string): Promise<void>;
21
- listFiles(tenantId?: string, entityName?: string, entityId?: string, status?: FileStatus, page?: number, limit?: number): Promise<{
18
+ completeUpload(fileId: string, portalEntityId?: string): Promise<any>;
19
+ getDownloadUrl(fileId: string, filename?: string, expiresIn?: number, portalEntityId?: string): Promise<any>;
20
+ deleteFile(fileId: string, portalEntityId?: string): Promise<void>;
21
+ listFiles(tenantId?: string, entityName?: string, entityId?: string, status?: FileStatus, page?: number, limit?: number, portalEntityId?: string): Promise<{
22
22
  files: any[];
23
23
  total: number;
24
24
  page: number;
25
25
  totalPages: number;
26
26
  }>;
27
- getFileById(fileId: string): Promise<any>;
27
+ getFileById(fileId: string, portalEntityId?: string): Promise<any>;
28
28
  }
@@ -41,7 +41,7 @@ export class EdrmStorageService {
41
41
  return FileType.ARCHIVE;
42
42
  return FileType.OTHER;
43
43
  }
44
- async initUpload(originalName, mimeType, size, tenantId, entityName, entityId, provider = this.defaultProvider, metadata, tags) {
44
+ async initUpload(originalName, mimeType, size, tenantId, entityName, entityId, provider = this.defaultProvider, metadata, tags, portalEntityId) {
45
45
  const bucket = process.env.S3_BUCKET || 'edrm-storage';
46
46
  const key = this.generateKey(tenantId, entityName, entityId, originalName);
47
47
  const storageProvider = this.getProvider(provider);
@@ -64,6 +64,7 @@ export class EdrmStorageService {
64
64
  tenantId,
65
65
  entityName,
66
66
  entityId,
67
+ ...(portalEntityId && { portalEntityId }),
67
68
  uploadedBy: 'system', // À remplacer par l'utilisateur connecté
68
69
  accessCount: 0
69
70
  });
@@ -77,11 +78,14 @@ export class EdrmStorageService {
77
78
  key
78
79
  };
79
80
  }
80
- async completeUpload(fileId) {
81
+ async completeUpload(fileId, portalEntityId) {
81
82
  const fileRecord = await FileModel.findById(fileId);
82
83
  if (!fileRecord) {
83
84
  throw new Error('Fichier non trouvé');
84
85
  }
86
+ if (portalEntityId && fileRecord.portalEntityId && fileRecord.portalEntityId !== portalEntityId) {
87
+ throw new Error('Fichier non trouvé');
88
+ }
85
89
  const storageProvider = this.getProvider(fileRecord.provider);
86
90
  try {
87
91
  // Vérifier que le fichier existe dans le stockage
@@ -102,11 +106,14 @@ export class EdrmStorageService {
102
106
  throw new Error(`Erreur lors de la finalisation de l'upload: ${error}`);
103
107
  }
104
108
  }
105
- async getDownloadUrl(fileId, filename, expiresIn = 3600) {
109
+ async getDownloadUrl(fileId, filename, expiresIn = 3600, portalEntityId) {
106
110
  const fileRecord = await FileModel.findById(fileId);
107
111
  if (!fileRecord) {
108
112
  throw new Error('Fichier non trouvé');
109
113
  }
114
+ if (portalEntityId && fileRecord.portalEntityId && fileRecord.portalEntityId !== portalEntityId) {
115
+ throw new Error('Fichier non trouvé');
116
+ }
110
117
  if (fileRecord.status !== FileStatus.COMPLETED) {
111
118
  throw new Error('Fichier non encore finalisé');
112
119
  }
@@ -123,11 +130,14 @@ export class EdrmStorageService {
123
130
  contentType: downloadResponse.contentType
124
131
  };
125
132
  }
126
- async deleteFile(fileId) {
133
+ async deleteFile(fileId, portalEntityId) {
127
134
  const fileRecord = await FileModel.findById(fileId);
128
135
  if (!fileRecord) {
129
136
  throw new Error('Fichier non trouvé');
130
137
  }
138
+ if (portalEntityId && fileRecord.portalEntityId && fileRecord.portalEntityId !== portalEntityId) {
139
+ throw new Error('Fichier non trouvé');
140
+ }
131
141
  const storageProvider = this.getProvider(fileRecord.provider);
132
142
  try {
133
143
  // Supprimer du stockage
@@ -141,7 +151,7 @@ export class EdrmStorageService {
141
151
  throw new Error(`Erreur lors de la suppression: ${error}`);
142
152
  }
143
153
  }
144
- async listFiles(tenantId, entityName, entityId, status, page = 1, limit = 20) {
154
+ async listFiles(tenantId, entityName, entityId, status, page = 1, limit = 20, portalEntityId) {
145
155
  const query = {};
146
156
  if (tenantId)
147
157
  query.tenantId = tenantId;
@@ -149,6 +159,8 @@ export class EdrmStorageService {
149
159
  query.entityName = entityName;
150
160
  if (entityId)
151
161
  query.entityId = entityId;
162
+ if (portalEntityId)
163
+ query.portalEntityId = portalEntityId;
152
164
  if (status)
153
165
  query.status = status;
154
166
  const skip = (page - 1) * limit;
@@ -167,11 +179,14 @@ export class EdrmStorageService {
167
179
  totalPages: Math.ceil(total / limit)
168
180
  };
169
181
  }
170
- async getFileById(fileId) {
182
+ async getFileById(fileId, portalEntityId) {
171
183
  const fileRecord = await FileModel.findById(fileId);
172
184
  if (!fileRecord) {
173
185
  throw new Error('Fichier non trouvé');
174
186
  }
187
+ if (portalEntityId && fileRecord.portalEntityId && fileRecord.portalEntityId !== portalEntityId) {
188
+ throw new Error('Fichier non trouvé');
189
+ }
175
190
  return fileRecord;
176
191
  }
177
192
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@programisto/edrm-storage",
4
- "version": "1.0.5",
4
+ "version": "1.0.7",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },