trovesuite 1.0.26__py3-none-any.whl → 1.0.27__py3-none-any.whl

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.
@@ -79,6 +79,7 @@ class Settings:
79
79
  CORE_PLATFORM_UNIT_OF_MEASURE_TABLE = os.getenv("CORE_PLATFORM_UNIT_OF_MEASURE_TABLE", "core_platform.cp_unit_of_measures")
80
80
  CORE_PLATFORM_CURRENCY = os.getenv("CORE_PLATFORM_CURRENCY", "core_platform.cp_currencies")
81
81
  CORE_PLATFORM_THEMES_TABLE = os.getenv("CORE_PLATFORM_THEMES_TABLE", "core_platform.cp_themes")
82
+ CORE_PLATFORM_NOTIFICATION_EMAIL_CREDENTIALS_TABLE = os.getenv("CORE_PLATFORM_NOTIFICATION_EMAIL_CREDENTIALS_TABLE", "core_platform.cp_notification_email_credentials")
82
83
 
83
84
  # Mail Configurations
84
85
  MAIL_SENDER_EMAIL=os.getenv("MAIL_SENDER_EMAIL")
@@ -314,6 +314,75 @@ class Helper:
314
314
  # Log the error but don't fail the main operation
315
315
  logger.error(f"Failed to log activity: {str(e)}", exc_info=True)
316
316
 
317
+ @staticmethod
318
+ def get_email_credentials(tenant_id: Optional[str] = None) -> tuple[Optional[str], Optional[str]]:
319
+ """
320
+ Get email credentials for sending notifications.
321
+ If tenant_id is provided and tenant has custom email credentials, use those.
322
+ Otherwise, fall back to system default credentials.
323
+
324
+ Args:
325
+ tenant_id: Optional tenant ID to check for tenant-specific credentials
326
+
327
+ Returns:
328
+ Tuple of (email, password) or (None, None) if not configured
329
+ """
330
+ # If tenant_id is provided, check for tenant-specific credentials
331
+ if tenant_id:
332
+ try:
333
+ credentials_table = getattr(db_settings, 'CORE_PLATFORM_NOTIFICATION_EMAIL_CREDENTIALS_TABLE', 'core_platform.cp_notification_email_credentials')
334
+ tenant_credentials = DatabaseManager.execute_query(
335
+ f"""SELECT notification_email, notification_password
336
+ FROM {credentials_table}
337
+ WHERE tenant_id = %s
338
+ AND delete_status = 'NOT_DELETED'
339
+ AND is_active = true""",
340
+ (tenant_id,),
341
+ )
342
+
343
+ if tenant_credentials and len(tenant_credentials) > 0:
344
+ tenant_email = tenant_credentials[0].get('notification_email')
345
+ tenant_password = tenant_credentials[0].get('notification_password')
346
+
347
+ # If tenant has both email and password configured, use them
348
+ if tenant_email and tenant_password:
349
+ logger.info(
350
+ f"Using tenant-specific email credentials for tenant {tenant_id}",
351
+ extra={
352
+ "extra_fields": {
353
+ "tenant_id": tenant_id,
354
+ "email": tenant_email
355
+ }
356
+ }
357
+ )
358
+ return (tenant_email, tenant_password)
359
+ except Exception as e:
360
+ logger.warning(
361
+ f"Error fetching tenant email credentials for tenant {tenant_id}: {str(e)}",
362
+ extra={
363
+ "extra_fields": {
364
+ "tenant_id": tenant_id,
365
+ "error": str(e)
366
+ }
367
+ }
368
+ )
369
+
370
+ # Fall back to system default credentials
371
+ mail_sender_email = getattr(db_settings, 'MAIL_SENDER_EMAIL', None)
372
+ mail_sender_pwd = getattr(db_settings, 'MAIL_SENDER_PWD', None)
373
+
374
+ if tenant_id:
375
+ logger.info(
376
+ f"Using system default email credentials for tenant {tenant_id}",
377
+ extra={
378
+ "extra_fields": {
379
+ "tenant_id": tenant_id
380
+ }
381
+ }
382
+ )
383
+
384
+ return (mail_sender_email, mail_sender_pwd)
385
+
317
386
  @staticmethod
318
387
  def send_notification(
319
388
  email: str,
@@ -321,8 +390,19 @@ class Helper:
321
390
  text_template: str,
322
391
  html_template: str,
323
392
  variables: Optional[Dict[str, str]] = None,
393
+ tenant_id: Optional[str] = None,
324
394
  ):
325
- """Send a dynamic notification email."""
395
+ """
396
+ Send a dynamic notification email.
397
+
398
+ Args:
399
+ email: Recipient email address
400
+ subject: Email subject
401
+ text_template: Plain text email template
402
+ html_template: HTML email template
403
+ variables: Optional dictionary of variables to format templates
404
+ tenant_id: Optional tenant ID to use tenant-specific email credentials
405
+ """
326
406
  current_time = Helper.current_date_time()
327
407
  cdate = current_time["cdate"]
328
408
  ctime = current_time["ctime"]
@@ -345,12 +425,19 @@ class Helper:
345
425
  text_message = text_template.format(**safe_variables)
346
426
  html_message = html_template.format(**safe_variables)
347
427
 
348
- # Build email data
349
- mail_sender_email = getattr(db_settings, 'MAIL_SENDER_EMAIL', None)
350
- mail_sender_pwd = getattr(db_settings, 'MAIL_SENDER_PWD', None)
428
+ # Get email credentials (tenant-specific or system default)
429
+ mail_sender_email, mail_sender_pwd = Helper.get_email_credentials(tenant_id)
351
430
 
352
431
  if not mail_sender_email or not mail_sender_pwd:
353
- logger.error("MAIL_SENDER_EMAIL or MAIL_SENDER_PWD not configured in settings")
432
+ logger.error(
433
+ "Email credentials not configured. MAIL_SENDER_EMAIL or MAIL_SENDER_PWD not set in settings",
434
+ extra={
435
+ "extra_fields": {
436
+ "tenant_id": tenant_id,
437
+ "receiver_email": email
438
+ }
439
+ }
440
+ )
354
441
  return
355
442
 
356
443
  notification_data = NotificationEmailServiceWriteDto(
@@ -620,6 +707,8 @@ class Helper:
620
707
  "status_color": config["color"],
621
708
  "status_icon": config["icon"],
622
709
  "actor_name": actor_name,
710
+ },
711
+ tenant_id=tenant_id,
623
712
  "actor_email": actor_email,
624
713
  "message": message_value,
625
714
  "message_text": message_text,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: trovesuite
3
- Version: 1.0.26
3
+ Version: 1.0.27
4
4
  Summary: TroveSuite services package providing authentication, authorization, notifications, Azure Storage, and other enterprise services for TroveSuite applications
5
5
  Home-page: https://dev.azure.com/brightgclt/trovesuite/_git/packages
6
6
  Author: Bright Debrah Owusu
@@ -8,7 +8,7 @@ trovesuite/auth/auth_write_dto.py,sha256=rdwI7w6-9QZGv1H0PAGrjkLBCzaMHjgPIXeLb9R
8
8
  trovesuite/configs/__init__.py,sha256=h1mSZOaZ3kUy1ZMO_m9O9KklsxywM0RfMVZLh9h9WvQ,328
9
9
  trovesuite/configs/database.py,sha256=CdPurBNe2_Ymmn0fEkYHFPVaeCunGS1k0x1f3SfNlr4,11400
10
10
  trovesuite/configs/logging.py,sha256=mGjR2d4urVNry9l5_aXycMMtcY2RAFIpEL35hw33KZg,9308
11
- trovesuite/configs/settings.py,sha256=r3wyLdlLtnPzrTPV5Z4BytItLtfvQoP860waAfdecLA,6941
11
+ trovesuite/configs/settings.py,sha256=LvUNqs1Qsuu97b_RGaaphT2FQ4uqiXq_4WJw9OV6TUE,7113
12
12
  trovesuite/entities/__init__.py,sha256=Dbl_03Bueyh2vOP2hykd40MmNMrl5nNHSRGP-kqwwNo,160
13
13
  trovesuite/entities/health.py,sha256=KaW7yxTQdymIPlnkJJkDqEebBXkD0a7A66i5GgNZLoE,2700
14
14
  trovesuite/entities/sh_response.py,sha256=1_sw3PpVaDxWsNiBU0W9YLHZgTFxEj4JJBLBfSY63Ho,1579
@@ -25,10 +25,10 @@ trovesuite/storage/storage_read_dto.py,sha256=o7EVJdwrwVZAaeyGU9O01WMECGVaytkvLR
25
25
  trovesuite/storage/storage_service.py,sha256=V7LIePIV6b_iuhm-9x8r4zwpZHgeRPL1YIe5IBnxhco,19768
26
26
  trovesuite/storage/storage_write_dto.py,sha256=vl1iCZ93bpFmpvkCrn587QtMtOA_TPDseXSoTuj9RTQ,1355
27
27
  trovesuite/utils/__init__.py,sha256=mDZuY77BphvQFYLmcWxjP5Tcq9ZZ3WXJWBKB1v6wzHU,185
28
- trovesuite/utils/helper.py,sha256=28KjFtiDS4IxuO13QBQUmU4dq9xUJDll9ewWetCrOcc,27061
28
+ trovesuite/utils/helper.py,sha256=2Yc3mAM3zGS04pjtnQ8HeDn2JTE3n3srqZi-yObMxsM,30881
29
29
  trovesuite/utils/templates.py,sha256=_92k4-EkqWs-h0LNJxPgorbspmp24kDngS7O3qWIFyQ,20388
30
- trovesuite-1.0.26.dist-info/licenses/LICENSE,sha256=EJT35ct-Q794JYPdAQy3XNczQGKkU1HzToLeK1YVw2s,1070
31
- trovesuite-1.0.26.dist-info/METADATA,sha256=NaoWkeiWQCnQ7lxDz_2fbaTalS46OvTlxryyQljljYs,21737
32
- trovesuite-1.0.26.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
33
- trovesuite-1.0.26.dist-info/top_level.txt,sha256=GzKhG_-MTaxeHrIgkGkBH_nof2vroGFBrjeHKWUIwNc,11
34
- trovesuite-1.0.26.dist-info/RECORD,,
30
+ trovesuite-1.0.27.dist-info/licenses/LICENSE,sha256=EJT35ct-Q794JYPdAQy3XNczQGKkU1HzToLeK1YVw2s,1070
31
+ trovesuite-1.0.27.dist-info/METADATA,sha256=iIVdthL_ORuU8QBPTsrkEt2tKwuHAm88x2MCTVunM2U,21737
32
+ trovesuite-1.0.27.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
33
+ trovesuite-1.0.27.dist-info/top_level.txt,sha256=GzKhG_-MTaxeHrIgkGkBH_nof2vroGFBrjeHKWUIwNc,11
34
+ trovesuite-1.0.27.dist-info/RECORD,,