rez_core 3.1.198 → 3.1.200

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rez_core",
3
- "version": "3.1.198",
3
+ "version": "3.1.200",
4
4
  "description": "",
5
5
  "author": "",
6
6
  "private": false,
@@ -79,4 +79,14 @@ export class MediaController {
79
79
  });
80
80
  }
81
81
  }
82
+
83
+ @Post('generateUploadPath')
84
+ async generateUploadPath(@Req() req: Request & { user: any }, @Query('mapped_entity_type') mapped_entity_type: string,
85
+ @Query('mapped_entity_id') mapped_entity_id?: number,
86
+ @Query('parent_id') parent_id?: number,
87
+ @Query('parent_type') parent_type?: string,
88
+ ) {
89
+ const loggedInUser = req.user.userData;
90
+ return this.mediaDataService.buildUploadPathGeneric(mapped_entity_type, loggedInUser, mapped_entity_id,parent_id, parent_type)
91
+ }
82
92
  }
@@ -75,4 +75,10 @@ export class EntityMaster extends BaseEntity {
75
75
 
76
76
  @Column({ name: 'is_workflow', nullable: true })
77
77
  is_workflow: boolean;
78
+
79
+ @Column({ name: 'doc_upload_path', nullable: true, length:50 })
80
+ doc_upload_path: string;
81
+
82
+ @Column({name: 'overwrite_path', type: 'tinyint', nullable: true})
83
+ overwrite_path: number;
78
84
  }
@@ -9,12 +9,16 @@ import {
9
9
  STATUS_PENDING,
10
10
  } from '../../../constant/global.constant';
11
11
  import { v4 as uuidv4 } from 'uuid';
12
+ import { OrganizationService } from '../../enterprise/service/organization.service';
13
+ import { EntityMasterService } from './entity-master.service';
14
+ import { DataSource } from 'typeorm';
12
15
 
13
16
  @Injectable()
14
17
  export class MediaDataService extends EntityServiceImpl {
15
18
  constructor(
16
19
  private readonly configService: ConfigService,
17
20
  private readonly mediaRepository: MediaDataRepository,
21
+ private dataSource: DataSource,
18
22
  ) {
19
23
  super();
20
24
  }
@@ -44,6 +48,8 @@ export class MediaDataService extends EntityServiceImpl {
44
48
  const ext = fileName.split('.').pop()?.toLowerCase() ?? '';
45
49
 
46
50
  const id = uuidv4();
51
+
52
+ //TODO:
47
53
  const s3Key = `uploads/${id}.${ext}`;
48
54
 
49
55
  const uploadUrl = await this.s3.getSignedUrlPromise('putObject', {
@@ -140,10 +146,95 @@ export class MediaDataService extends EntityServiceImpl {
140
146
  Key: mediaData.media_url,
141
147
  Expires: Number(expiresIn) || 60 * 5,
142
148
  });
143
- return { signedUrl, fileName: mediaData.file_name, id: mediaData.id, size: fileSize};
149
+ return { signedUrl, fileName: mediaData.file_name, id: mediaData.id, size: fileSize };
144
150
  } catch (error) {
145
151
  console.error('Error generating signed URL for media:', error);
146
152
  throw new Error('Failed to generate signed URL');
147
153
  }
148
154
  }
155
+
156
+ public async buildUploadPathGeneric(
157
+ mappedEntityType: string,
158
+ loggedInUser,
159
+ mappedEntityId?: number,
160
+ parentId?: number,
161
+ parentType?: string,
162
+ ) {
163
+ // 1️⃣ Fetch entity metadata
164
+ const entityMaster = await this.entityMasterService.getEntityData(mappedEntityType, loggedInUser);
165
+ if (!entityMaster) {
166
+ throw new Error(`Entity master not found for ${mappedEntityType}`);
167
+ }
168
+
169
+ let pathTemplate = entityMaster.doc_upload_path ?? '';
170
+ const entityOverwrite = entityMaster.overwrite_path ?? 0;
171
+
172
+ if (!pathTemplate) {
173
+ throw new Error(`doc_upload_path not defined for ${mappedEntityType}`);
174
+ }
175
+
176
+ // 2️⃣ Prepare replacement map
177
+ const replacements: Record<string, string | null> = {};
178
+
179
+ // --- ORG ---
180
+ let organizationData = await this.dataSource.query('SELECT * FROM sso_organization WHERE id = ?', [loggedInUser.organization_id]);
181
+ replacements['org_code'] = organizationData[0].code;
182
+
183
+ // --- LEVEL CODE ---
184
+ // Determine which entity to use for level_code
185
+ const levelEntityId = entityOverwrite ? mappedEntityId : loggedInUser.level_id;
186
+ const levelEntityData = await super.getEntityData(loggedInUser.level_type, levelEntityId, loggedInUser);
187
+ if (levelEntityData?.code) {
188
+ replacements['level_code'] = levelEntityData.code; // universal alias
189
+ }
190
+
191
+ // --- Dynamic variables inside path ---
192
+ const matches = pathTemplate.match(/\$\{(\w+)\}/g) || [];
193
+
194
+ for (const variable of matches) {
195
+ const key = variable.replace(/\$\{|\}/g, '');
196
+ if (replacements[key]) continue; // already resolved
197
+
198
+ if (key === 'org_code') continue; // already set
199
+ if (key.endsWith('_code')) {
200
+ // derive entity type dynamically
201
+ const entityType = key.replace('_code', '').toUpperCase();
202
+
203
+ let entityId: number | undefined;
204
+ if (parentType?.toUpperCase() === entityType && parentId) {
205
+ entityId = parentId;
206
+ } else {
207
+ entityId = mappedEntityId;
208
+ }
209
+
210
+ // Generic lookup
211
+ if (entityId) {
212
+ const entityData = await super.getEntityData(entityType, entityId, loggedInUser);
213
+ replacements[key] = entityData?.code ?? null;
214
+ }
215
+ }
216
+ }
217
+
218
+ // --- ORG special case ---
219
+ // If ORG level & overwrite = 0 → remove level_code variable
220
+ if (loggedInUser.level_type === 'ORG' && entityOverwrite === 0) {
221
+ replacements['level_code'] = null;
222
+ }
223
+
224
+ // 3️⃣ Final substitution and cleanup
225
+ if (pathTemplate) {
226
+ const finalPath = this.resolveUploadPath(pathTemplate, replacements);
227
+ return finalPath;
228
+ }
229
+ return null;
230
+ }
231
+
232
+ /**
233
+ * Replace placeholders with actual values, remove missing variables
234
+ */
235
+ private resolveUploadPath(template: string, replacements: Record<string, string | null>) {
236
+ let path = template;
237
+ path = path.replace(/\$\{(\w+)\}/g, (_, key) => replacements[key] || '');
238
+ return path.replace(/\/+/g, '/').replace(/\/$/, '');
239
+ }
149
240
  }
@@ -70,12 +70,19 @@ export class OtpService {
70
70
  // Find OTP entity by ID
71
71
  const otpEntity = await this.findByOtpId(otp_id);
72
72
  if (!otpEntity) {
73
- throw new BadRequestException('OTP not found!');
73
+ // throw new BadRequestException('OTP not found!');
74
+ return {
75
+ sucess: false,
76
+ message: 'OTP not found!',
77
+ };
74
78
  }
75
79
 
76
80
  // Validate the identifier against the OTP entity
77
81
  if (otpEntity.identifier !== identifier) {
78
- throw new BadRequestException('Invalid OTP identifier!');
82
+ return {
83
+ sucess: false,
84
+ message: 'Invalid OTP identifier!',
85
+ };
79
86
  }
80
87
 
81
88
  // OTP validation logic