trovesuite 1.0.16__tar.gz → 1.0.18__tar.gz
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.
- {trovesuite-1.0.16/src/trovesuite.egg-info → trovesuite-1.0.18}/PKG-INFO +1 -1
- {trovesuite-1.0.16 → trovesuite-1.0.18}/pyproject.toml +2 -2
- {trovesuite-1.0.16 → trovesuite-1.0.18}/setup.py +1 -1
- {trovesuite-1.0.16 → trovesuite-1.0.18}/src/trovesuite/auth/auth_service.py +15 -15
- trovesuite-1.0.18/src/trovesuite/configs/settings.py +101 -0
- {trovesuite-1.0.16 → trovesuite-1.0.18}/src/trovesuite/utils/helper.py +22 -19
- {trovesuite-1.0.16 → trovesuite-1.0.18/src/trovesuite.egg-info}/PKG-INFO +1 -1
- trovesuite-1.0.16/src/trovesuite/configs/settings.py +0 -62
- {trovesuite-1.0.16 → trovesuite-1.0.18}/LICENSE +0 -0
- {trovesuite-1.0.16 → trovesuite-1.0.18}/MANIFEST.in +0 -0
- {trovesuite-1.0.16 → trovesuite-1.0.18}/README.md +0 -0
- {trovesuite-1.0.16 → trovesuite-1.0.18}/requirements.txt +0 -0
- {trovesuite-1.0.16 → trovesuite-1.0.18}/setup.cfg +0 -0
- {trovesuite-1.0.16 → trovesuite-1.0.18}/src/trovesuite/__init__.py +0 -0
- {trovesuite-1.0.16 → trovesuite-1.0.18}/src/trovesuite/auth/__init__.py +0 -0
- {trovesuite-1.0.16 → trovesuite-1.0.18}/src/trovesuite/auth/auth_base.py +0 -0
- {trovesuite-1.0.16 → trovesuite-1.0.18}/src/trovesuite/auth/auth_controller.py +0 -0
- {trovesuite-1.0.16 → trovesuite-1.0.18}/src/trovesuite/auth/auth_read_dto.py +0 -0
- {trovesuite-1.0.16 → trovesuite-1.0.18}/src/trovesuite/auth/auth_write_dto.py +0 -0
- {trovesuite-1.0.16 → trovesuite-1.0.18}/src/trovesuite/configs/__init__.py +0 -0
- {trovesuite-1.0.16 → trovesuite-1.0.18}/src/trovesuite/configs/database.py +0 -0
- {trovesuite-1.0.16 → trovesuite-1.0.18}/src/trovesuite/configs/logging.py +0 -0
- {trovesuite-1.0.16 → trovesuite-1.0.18}/src/trovesuite/entities/__init__.py +0 -0
- {trovesuite-1.0.16 → trovesuite-1.0.18}/src/trovesuite/entities/health.py +0 -0
- {trovesuite-1.0.16 → trovesuite-1.0.18}/src/trovesuite/entities/sh_response.py +0 -0
- {trovesuite-1.0.16 → trovesuite-1.0.18}/src/trovesuite/notification/__init__.py +0 -0
- {trovesuite-1.0.16 → trovesuite-1.0.18}/src/trovesuite/notification/notification_base.py +0 -0
- {trovesuite-1.0.16 → trovesuite-1.0.18}/src/trovesuite/notification/notification_controller.py +0 -0
- {trovesuite-1.0.16 → trovesuite-1.0.18}/src/trovesuite/notification/notification_read_dto.py +0 -0
- {trovesuite-1.0.16 → trovesuite-1.0.18}/src/trovesuite/notification/notification_service.py +0 -0
- {trovesuite-1.0.16 → trovesuite-1.0.18}/src/trovesuite/notification/notification_write_dto.py +0 -0
- {trovesuite-1.0.16 → trovesuite-1.0.18}/src/trovesuite/storage/__init__.py +0 -0
- {trovesuite-1.0.16 → trovesuite-1.0.18}/src/trovesuite/storage/storage_base.py +0 -0
- {trovesuite-1.0.16 → trovesuite-1.0.18}/src/trovesuite/storage/storage_controller.py +0 -0
- {trovesuite-1.0.16 → trovesuite-1.0.18}/src/trovesuite/storage/storage_read_dto.py +0 -0
- {trovesuite-1.0.16 → trovesuite-1.0.18}/src/trovesuite/storage/storage_service.py +0 -0
- {trovesuite-1.0.16 → trovesuite-1.0.18}/src/trovesuite/storage/storage_write_dto.py +0 -0
- {trovesuite-1.0.16 → trovesuite-1.0.18}/src/trovesuite/utils/__init__.py +0 -0
- {trovesuite-1.0.16 → trovesuite-1.0.18}/src/trovesuite/utils/templates.py +0 -0
- {trovesuite-1.0.16 → trovesuite-1.0.18}/src/trovesuite.egg-info/SOURCES.txt +0 -0
- {trovesuite-1.0.16 → trovesuite-1.0.18}/src/trovesuite.egg-info/dependency_links.txt +0 -0
- {trovesuite-1.0.16 → trovesuite-1.0.18}/src/trovesuite.egg-info/not-zip-safe +0 -0
- {trovesuite-1.0.16 → trovesuite-1.0.18}/src/trovesuite.egg-info/requires.txt +0 -0
- {trovesuite-1.0.16 → trovesuite-1.0.18}/src/trovesuite.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: trovesuite
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.18
|
|
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
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[tool.poetry]
|
|
6
6
|
name = "trovesuite"
|
|
7
|
-
version = "1.0.
|
|
7
|
+
version = "1.0.18"
|
|
8
8
|
description = "TroveSuite services package providing authentication, authorization, notifications, Azure Storage, and other enterprise services for TroveSuite applications"
|
|
9
9
|
authors = ["brightgclt <brightgclt@gmail.com>"]
|
|
10
10
|
license = "MIT"
|
|
@@ -58,7 +58,7 @@ Documentation = "https://dev.azure.com/brightgclt/trovesuite/_git/packages"
|
|
|
58
58
|
|
|
59
59
|
[project]
|
|
60
60
|
name = "trovesuite"
|
|
61
|
-
version = "1.0.
|
|
61
|
+
version = "1.0.18"
|
|
62
62
|
description = "TroveSuite services package providing authentication, authorization, notifications, Azure Storage, and other enterprise services for TroveSuite applications"
|
|
63
63
|
readme = "README.md"
|
|
64
64
|
license = {text = "MIT"}
|
|
@@ -15,7 +15,7 @@ with open("pyproject.toml", "r", encoding="utf-8") as fh:
|
|
|
15
15
|
|
|
16
16
|
setup(
|
|
17
17
|
name="trovesuite",
|
|
18
|
-
version="1.0.
|
|
18
|
+
version="1.0.18",
|
|
19
19
|
author="Bright Debrah Owusu",
|
|
20
20
|
author_email="owusu.debrah@deladetech.com",
|
|
21
21
|
description="TroveSuite services package providing authentication, authorization, notifications, and other enterprise services for TroveSuite applications",
|
|
@@ -98,8 +98,9 @@ class AuthService:
|
|
|
98
98
|
|
|
99
99
|
# 1️⃣ Get all groups the user belongs to
|
|
100
100
|
user_groups = DatabaseManager.execute_query(
|
|
101
|
-
f"""SELECT group_id FROM
|
|
102
|
-
WHERE delete_status = 'NOT_DELETED' AND is_active = true AND user_id = %s""",
|
|
101
|
+
f"""SELECT group_id FROM {db_settings.TENANT_USER_GROUPS_TABLE}
|
|
102
|
+
WHERE tenant_id = %s AND delete_status = 'NOT_DELETED' AND is_active = true AND user_id = %s""",
|
|
103
|
+
(tenant_id, user_id,),
|
|
103
104
|
)
|
|
104
105
|
|
|
105
106
|
# 2️⃣ Prepare list of group_ids
|
|
@@ -110,20 +111,20 @@ class AuthService:
|
|
|
110
111
|
login_settings_details = DatabaseManager.execute_query(
|
|
111
112
|
f"""SELECT user_id, group_id, is_suspended, can_always_login,
|
|
112
113
|
is_multi_factor_enabled, is_login_before, working_days,
|
|
113
|
-
login_on, logout_on FROM
|
|
114
|
-
WHERE (delete_status = 'NOT_DELETED' AND is_active = true )
|
|
114
|
+
login_on, logout_on FROM {db_settings.TENANT_LOGIN_SETTINGS_TABLE}
|
|
115
|
+
WHERE tenant_id = %s AND (delete_status = 'NOT_DELETED' AND is_active = true )
|
|
115
116
|
AND (user_id = %s OR group_id = ANY(%s))
|
|
116
117
|
ORDER BY user_id NULLS LAST
|
|
117
118
|
LIMIT 1""",
|
|
118
|
-
(user_id, group_ids),
|
|
119
|
+
(tenant_id, user_id, group_ids),
|
|
119
120
|
)
|
|
120
121
|
else:
|
|
121
122
|
login_settings_details = DatabaseManager.execute_query(
|
|
122
123
|
f"""SELECT user_id, group_id, is_suspended, can_always_login,
|
|
123
124
|
is_multi_factor_enabled, is_login_before, working_days,
|
|
124
|
-
login_on, logout_on FROM
|
|
125
|
-
WHERE (delete_status = 'NOT_DELETED' AND is_active = true ) AND user_id = %s""",
|
|
126
|
-
(user_id,),
|
|
125
|
+
login_on, logout_on FROM {db_settings.TENANT_LOGIN_SETTINGS_TABLE}
|
|
126
|
+
WHERE tenant_id = %s AND (delete_status = 'NOT_DELETED' AND is_active = true ) AND user_id = %s""",
|
|
127
|
+
(tenant_id, user_id,),
|
|
127
128
|
)
|
|
128
129
|
|
|
129
130
|
if not login_settings_details or len(login_settings_details) == 0:
|
|
@@ -202,13 +203,13 @@ class AuthService:
|
|
|
202
203
|
f"""
|
|
203
204
|
SELECT DISTINCT ON (group_id, user_id, role_id)
|
|
204
205
|
group_id, user_id, role_id, resource_type
|
|
205
|
-
FROM
|
|
206
|
-
WHERE delete_status = 'NOT_DELETED'
|
|
206
|
+
FROM {db_settings.TENANT_ASSIGN_ROLES_TABLE}
|
|
207
|
+
WHERE tenant_id = %s AND delete_status = 'NOT_DELETED'
|
|
207
208
|
AND is_active = true
|
|
208
209
|
AND (user_id = %s OR group_id = ANY(%s))
|
|
209
210
|
ORDER BY group_id, user_id, role_id;
|
|
210
211
|
""",
|
|
211
|
-
(user_id, group_ids),
|
|
212
|
+
(tenant_id, user_id, group_ids),
|
|
212
213
|
)
|
|
213
214
|
else:
|
|
214
215
|
# No groups, just check roles for user
|
|
@@ -216,13 +217,13 @@ class AuthService:
|
|
|
216
217
|
f"""
|
|
217
218
|
SELECT DISTINCT ON (user_id, role_id)
|
|
218
219
|
user_id, role_id, resource_type
|
|
219
|
-
FROM
|
|
220
|
-
WHERE delete_status = 'NOT_DELETED'
|
|
220
|
+
FROM {db_settings.TENANT_ASSIGN_ROLES_TABLE}
|
|
221
|
+
WHERE tenant_id = %s AND delete_status = 'NOT_DELETED'
|
|
221
222
|
AND is_active = true
|
|
222
223
|
AND user_id = %s
|
|
223
224
|
ORDER BY user_id, role_id;
|
|
224
225
|
""",
|
|
225
|
-
(user_id,),
|
|
226
|
+
(tenant_id, user_id,),
|
|
226
227
|
)
|
|
227
228
|
|
|
228
229
|
# ✅ NEW: Get system-level roles from main.system_user_groups and main.system_assign_roles
|
|
@@ -301,7 +302,6 @@ class AuthService:
|
|
|
301
302
|
error="Authorization check failed due to an internal error"
|
|
302
303
|
)
|
|
303
304
|
|
|
304
|
-
|
|
305
305
|
@staticmethod
|
|
306
306
|
def check_permission(users_data: list, action=None, resource_type=None) -> bool:
|
|
307
307
|
"""
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import os
|
|
2
|
+
class Settings:
|
|
3
|
+
|
|
4
|
+
# Database URL
|
|
5
|
+
DATABASE_URL: str = os.getenv("DATABASE_URL")
|
|
6
|
+
|
|
7
|
+
DB_USER: str = os.getenv("DB_USER")
|
|
8
|
+
DB_HOST: str = os.getenv("DB_HOST")
|
|
9
|
+
DB_NAME: str = os.getenv("DB_NAME")
|
|
10
|
+
DB_PORT: str = os.getenv("DB_PORT")
|
|
11
|
+
DB_PASSWORD: str = os.getenv("DB_PASSWORD")
|
|
12
|
+
|
|
13
|
+
# Application settings
|
|
14
|
+
DEBUG: bool = os.getenv("DEBUG", "True").lower() in ("true",1)
|
|
15
|
+
APP_NAME: str = os.getenv("APP_NAME", "Python Template API")
|
|
16
|
+
APP_VERSION: str = os.getenv("APP_VERSION", "1.0.0")
|
|
17
|
+
|
|
18
|
+
# Logging settings
|
|
19
|
+
LOG_LEVEL: str = os.getenv("LOG_LEVEL", "INFO")
|
|
20
|
+
LOG_FORMAT: str = os.getenv("LOG_FORMAT", "detailed") # detailed, json, simple
|
|
21
|
+
LOG_TO_FILE: bool = os.getenv("LOG_TO_FILE", "False").lower() in ("true", 1)
|
|
22
|
+
LOG_MAX_SIZE: int = int(os.getenv("LOG_MAX_SIZE", "10485760")) # 10MB
|
|
23
|
+
LOG_BACKUP_COUNT: int = int(os.getenv("LOG_BACKUP_COUNT", "5"))
|
|
24
|
+
LOG_DIR: str = os.getenv("LOG_DIR", "logs")
|
|
25
|
+
|
|
26
|
+
# Security settings
|
|
27
|
+
ALGORITHM: str = os.getenv("ALGORITHM")
|
|
28
|
+
SECRET_KEY: str = os.getenv("SECRET_KEY")
|
|
29
|
+
ENVIRONMENT: str = os.getenv("ENVIRONMENT")
|
|
30
|
+
ACCESS_TOKEN_EXPIRE_MINUTES: int = int(os.getenv("ACCESS_TOKEN_EXPIRE_MINUTES", "120"))
|
|
31
|
+
|
|
32
|
+
# =============================================================================
|
|
33
|
+
# SHARED TABLES (main schema)
|
|
34
|
+
# =============================================================================
|
|
35
|
+
MAIN_TENANTS_TABLE = os.getenv("MAIN_TENANTS_TABLE", "main.tenants")
|
|
36
|
+
MAIN_TENANT_RESOURCE_ID_TABLE = os.getenv("MAIN_TENANT_RESOURCE_ID_TABLE", "main.tenant_resource_ids")
|
|
37
|
+
MAIN_SUBSCRIPTIONS_TABLE = os.getenv("MAIN_SUBSCRIPTIONS_TABLE", "main.subscriptions")
|
|
38
|
+
MAIN_APPS_TABLE = os.getenv("MAIN_APPS_TABLE", "main.apps")
|
|
39
|
+
MAIN_USERS_TABLE = os.getenv("MAIN_USERS_TABLE", "main.users")
|
|
40
|
+
MAIN_RESOURCE_TYPES_TABLE = os.getenv("MAIN_RESOURCE_TYPES_TABLE", "main.resource_types")
|
|
41
|
+
MAIN_RESOURCE_ID_TABLE = os.getenv("MAIN_RESOURCE_ID_TABLE", "main.resource_ids")
|
|
42
|
+
MAIN_RESOURCES_TABLE = os.getenv("MAIN_RESOURCES_TABLE", "main.resources")
|
|
43
|
+
MAIN_PERMISSIONS_TABLE = os.getenv("MAIN_PERMISSIONS_TABLE", "main.permissions")
|
|
44
|
+
MAIN_ROLES_TABLE = os.getenv("MAIN_ROLES_TABLE", "main.roles")
|
|
45
|
+
MAIN_ROLE_PERMISSIONS_TABLE = os.getenv("MAIN_ROLE_PERMISSIONS_TABLE", "main.role_permissions")
|
|
46
|
+
MAIN_USER_SUBSCRIPTIONS_TABLE = os.getenv("MAIN_USER_SUBSCRIPTIONS_TABLE", "main.user_subscriptions")
|
|
47
|
+
MAIN_USER_SUBSCRIPTION_HISTORY_TABLE = os.getenv("MAIN_USER_SUBSCRIPTION_HISTORY_TABLE", "main.user_subscription_history")
|
|
48
|
+
MAIN_OTP = os.getenv("MAIN_OTP", "main.otps")
|
|
49
|
+
MAIN_PASSWORD_POLICY = os.getenv("MAIN_PASSWORD_POLICY", "main.password_policies")
|
|
50
|
+
MAIN_MULTI_FACTOR_SETTINGS = os.getenv("MAIN_MULTI_FACTOR_SETTINGS", "main.multi_factor_settings")
|
|
51
|
+
MAIN_USER_LOGIN_TRACKING = os.getenv("MAIN_USER_LOGIN_TRACKING", "main.user_login_tracking")
|
|
52
|
+
MAIN_ENTERPRISE_SUBSCRIPTIONS_TABLE = os.getenv("MAIN_ENTERPRISE_SUBSCRIPTIONS_TABLE", "main.enterprise_subscriptions")
|
|
53
|
+
MAIN_CHANGE_PASSWORD_POLICY_TABLE = os.getenv("MAIN_CHANGE_PASSWORD_POLICY_TABLE", "main.change_password_policy")
|
|
54
|
+
|
|
55
|
+
# System-level tables
|
|
56
|
+
MAIN_SYSTEM_GROUPS_TABLE = os.getenv("MAIN_SYSTEM_GROUPS_TABLE", "main.system_groups")
|
|
57
|
+
MAIN_SYSTEM_USER_GROUPS_TABLE = os.getenv("MAIN_SYSTEM_USER_GROUPS_TABLE", "main.system_user_groups")
|
|
58
|
+
MAIN_SYSTEM_ASSIGN_ROLES_TABLE = os.getenv("MAIN_SYSTEM_ASSIGN_ROLES_TABLE", "main.system_assign_roles")
|
|
59
|
+
|
|
60
|
+
# =============================================================================
|
|
61
|
+
# TENANT-SPECIFIC TABLES (now in main schema with tenant_id)
|
|
62
|
+
# =============================================================================
|
|
63
|
+
# NOTE: These tables have been migrated from separate tenant schemas to main schema.
|
|
64
|
+
# All tables now include tenant_id column for multi-tenant isolation.
|
|
65
|
+
# =============================================================================
|
|
66
|
+
TENANT_SUBSCRIPTIONS_TABLE = os.getenv("TENANT_SUBSCRIPTIONS_TABLE", "main.tenant_subscriptions")
|
|
67
|
+
TENANT_GROUPS_TABLE = os.getenv("TENANT_GROUPS_TABLE", "main.tenant_groups")
|
|
68
|
+
TENANT_LOGIN_SETTINGS_TABLE = os.getenv("TENANT_LOGIN_SETTINGS_TABLE", "main.tenant_login_settings")
|
|
69
|
+
TENANT_RESOURCES_TABLE = os.getenv("TENANT_RESOURCES_TABLE", "main.tenant_resources")
|
|
70
|
+
TENANT_ASSIGN_ROLES_TABLE = os.getenv("TENANT_ASSIGN_ROLES_TABLE", "main.tenant_assign_roles")
|
|
71
|
+
TENANT_RESOURCE_ID_TABLE = os.getenv("TENANT_RESOURCE_ID_TABLE", "main.tenant_resource_ids")
|
|
72
|
+
TENANT_SUBSCRIPTION_HISTORY_TABLE = os.getenv("TENANT_SUBSCRIPTION_HISTORY_TABLE", "main.tenant_subscription_histories")
|
|
73
|
+
TENANT_RESOURCE_DELETION_CHAT_HISTORY_TABLE = os.getenv("TENANT_RESOURCE_DELETION_CHAT_HISTORY_TABLE", "main.tenant_resource_deletion_chat_histories")
|
|
74
|
+
TENANT_USER_GROUPS_TABLE = os.getenv("TENANT_USER_GROUPS_TABLE", "main.tenant_user_groups")
|
|
75
|
+
TENANT_ACTIVITY_LOGS_TABLE = os.getenv("TENANT_ACTIVITY_LOGS_TABLE", "main.tenant_activity_logs")
|
|
76
|
+
TENANT_ORGANIZATIONS_TABLE = os.getenv("TENANT_ORGANIZATIONS_TABLE", "main.tenant_organizations")
|
|
77
|
+
TENANT_BUSINESSES_TABLE = os.getenv("TENANT_BUSINESSES_TABLE", "main.tenant_businesses")
|
|
78
|
+
TENANT_BUSINESS_APPS_TABLE = os.getenv("TENANT_BUSINESS_APPS_TABLE", "main.tenant_business_apps")
|
|
79
|
+
TENANT_LOCATIONS_TABLE = os.getenv("TENANT_LOCATIONS_TABLE", "main.tenant_locations")
|
|
80
|
+
TENANT_ASSIGN_LOCATIONS_TABLE = os.getenv("TENANT_ASSIGN_LOCATIONS_TABLE", "main.tenant_assign_locations")
|
|
81
|
+
TENANT_UNIT_OF_MEASURE_TABLE = os.getenv("TENANT_UNIT_OF_MEASURE_TABLE", "main.tenant_unit_of_measure")
|
|
82
|
+
TENANT_CURRENCY = os.getenv("TENANT_CURRENCY", "main.tenant_currency")
|
|
83
|
+
|
|
84
|
+
# Mail Configurations
|
|
85
|
+
MAIL_SENDER_EMAIL=os.getenv("MAIL_SENDER_EMAIL")
|
|
86
|
+
MAIL_SENDER_PWD=os.getenv("MAIL_SENDER_PWD")
|
|
87
|
+
|
|
88
|
+
# Application Configurations
|
|
89
|
+
APP_URL=os.getenv("APP_URL", "https://trovesuite.com")
|
|
90
|
+
USER_ASSIGNED_MANAGED_IDENTITY=os.getenv("USER_ASSIGNED_MANAGED_IDENTITY")
|
|
91
|
+
|
|
92
|
+
@property
|
|
93
|
+
def database_url(self) -> str:
|
|
94
|
+
if self.DATABASE_URL:
|
|
95
|
+
return self.DATABASE_URL
|
|
96
|
+
|
|
97
|
+
port = int(self.DB_PORT) if self.DB_PORT else 5432
|
|
98
|
+
return f"postgresql://{self.DB_USER}:{self.DB_PASSWORD}@{self.DB_HOST}:{port}/{self.DB_NAME}"
|
|
99
|
+
|
|
100
|
+
# Global settings instance
|
|
101
|
+
db_settings = Settings()
|
|
@@ -96,14 +96,14 @@ class Helper:
|
|
|
96
96
|
|
|
97
97
|
try:
|
|
98
98
|
if tenant_id:
|
|
99
|
-
# For tenant-specific resource IDs, check
|
|
99
|
+
# For tenant-specific resource IDs, check shared schema with tenant_id filter
|
|
100
100
|
# Note: TENANT_RESOURCE_ID_TABLE needs to be defined in settings
|
|
101
101
|
tenant_resource_table = getattr(db_settings, 'TENANT_RESOURCE_ID_TABLE', None)
|
|
102
102
|
if tenant_resource_table:
|
|
103
103
|
resource_exists = DatabaseManager.execute_scalar(
|
|
104
|
-
f"""SELECT COUNT(1) FROM
|
|
105
|
-
WHERE id = %s""",
|
|
106
|
-
(candidate,),
|
|
104
|
+
f"""SELECT COUNT(1) FROM {tenant_resource_table}
|
|
105
|
+
WHERE tenant_id = %s AND id = %s""",
|
|
106
|
+
(tenant_id, candidate,),
|
|
107
107
|
)
|
|
108
108
|
else:
|
|
109
109
|
# Fallback: assume no conflict if table not configured
|
|
@@ -289,10 +289,10 @@ class Helper:
|
|
|
289
289
|
logger.debug(f"Activity log values - performed_by_email: {performed_by_email}, performed_by_contact: {performed_by_contact}, performed_by_fullname: {performed_by_fullname}")
|
|
290
290
|
|
|
291
291
|
result = DatabaseManager.execute_update(
|
|
292
|
-
f"""INSERT INTO
|
|
293
|
-
(id, action, resource_type, old_data, new_data, description, performed_by_email, performed_by_contact, performed_by_fullname, cdate, ctime, cdatetime)
|
|
294
|
-
VALUES (%s, %s, NULLIF(%s, '')::text, %s::jsonb, %s::jsonb, %s, %s, %s, %s, %s, %s, %s)""",
|
|
295
|
-
(log_id, action, resource_type, old_json, new_json, description, performed_by_email, performed_by_contact, performed_by_fullname, cdate, ctime, cdatetime),
|
|
292
|
+
f"""INSERT INTO {tenant_activity_logs_table}
|
|
293
|
+
(id, tenant_id, action, resource_type, old_data, new_data, description, performed_by_email, performed_by_contact, performed_by_fullname, cdate, ctime, cdatetime)
|
|
294
|
+
VALUES (%s, %s, %s, NULLIF(%s, '')::text, %s::jsonb, %s::jsonb, %s, %s, %s, %s, %s, %s, %s)""",
|
|
295
|
+
(log_id, tenant_id, action, resource_type, old_json, new_json, description, performed_by_email, performed_by_contact, performed_by_fullname, cdate, ctime, cdatetime),
|
|
296
296
|
)
|
|
297
297
|
|
|
298
298
|
logger.info(f"Activity logged successfully. Rows affected: {result}")
|
|
@@ -301,9 +301,9 @@ class Helper:
|
|
|
301
301
|
if result > 0:
|
|
302
302
|
verify_data = DatabaseManager.execute_query(
|
|
303
303
|
f"""SELECT performed_by_email, performed_by_contact, performed_by_fullname
|
|
304
|
-
FROM
|
|
305
|
-
WHERE id = %s""",
|
|
306
|
-
(log_id,)
|
|
304
|
+
FROM {tenant_activity_logs_table}
|
|
305
|
+
WHERE tenant_id = %s AND id = %s""",
|
|
306
|
+
(tenant_id, log_id,)
|
|
307
307
|
)
|
|
308
308
|
if verify_data:
|
|
309
309
|
logger.debug(f"Verification - Inserted activity log data: {verify_data[0]}")
|
|
@@ -416,8 +416,8 @@ class Helper:
|
|
|
416
416
|
# Get table names from settings with fallbacks
|
|
417
417
|
main_users_table = getattr(db_settings, 'MAIN_USERS_TABLE', 'main.users')
|
|
418
418
|
main_roles_table = getattr(db_settings, 'MAIN_ROLES_TABLE', 'main.roles')
|
|
419
|
-
tenant_assign_roles_table = getattr(db_settings, 'TENANT_ASSIGN_ROLES_TABLE', '
|
|
420
|
-
tenant_user_groups_table = getattr(db_settings, 'TENANT_USER_GROUPS_TABLE', '
|
|
419
|
+
tenant_assign_roles_table = getattr(db_settings, 'TENANT_ASSIGN_ROLES_TABLE', 'main.tenant_assign_roles')
|
|
420
|
+
tenant_user_groups_table = getattr(db_settings, 'TENANT_USER_GROUPS_TABLE', 'main.tenant_user_groups')
|
|
421
421
|
|
|
422
422
|
# Query to get users with admin roles - both direct and through groups
|
|
423
423
|
query = f"""
|
|
@@ -430,9 +430,10 @@ class Helper:
|
|
|
430
430
|
-- Direct role assignment
|
|
431
431
|
u.id IN (
|
|
432
432
|
SELECT ar.user_id
|
|
433
|
-
FROM
|
|
433
|
+
FROM {tenant_assign_roles_table} ar
|
|
434
434
|
INNER JOIN {main_roles_table} r ON ar.role_id = r.id
|
|
435
|
-
WHERE ar.
|
|
435
|
+
WHERE ar.tenant_id = %s
|
|
436
|
+
AND ar.delete_status = 'NOT_DELETED'
|
|
436
437
|
AND ar.is_active = true
|
|
437
438
|
AND r.delete_status = 'NOT_DELETED'
|
|
438
439
|
AND r.is_active = true
|
|
@@ -443,10 +444,12 @@ class Helper:
|
|
|
443
444
|
-- Group-based role assignment
|
|
444
445
|
u.id IN (
|
|
445
446
|
SELECT ug.user_id
|
|
446
|
-
FROM
|
|
447
|
-
INNER JOIN
|
|
447
|
+
FROM {tenant_user_groups_table} ug
|
|
448
|
+
INNER JOIN {tenant_assign_roles_table} ar ON ug.group_id = ar.group_id
|
|
448
449
|
INNER JOIN {main_roles_table} r ON ar.role_id = r.id
|
|
449
|
-
WHERE ug.
|
|
450
|
+
WHERE ug.tenant_id = %s
|
|
451
|
+
AND ar.tenant_id = %s
|
|
452
|
+
AND ug.delete_status = 'NOT_DELETED'
|
|
450
453
|
AND ug.is_active = true
|
|
451
454
|
AND ar.delete_status = 'NOT_DELETED'
|
|
452
455
|
AND ar.is_active = true
|
|
@@ -458,7 +461,7 @@ class Helper:
|
|
|
458
461
|
)
|
|
459
462
|
"""
|
|
460
463
|
|
|
461
|
-
results = DatabaseManager.execute_query(query)
|
|
464
|
+
results = DatabaseManager.execute_query(query, (tenant_id, tenant_id, tenant_id,))
|
|
462
465
|
|
|
463
466
|
admin_users = []
|
|
464
467
|
if results:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: trovesuite
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.18
|
|
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
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
class Settings:
|
|
3
|
-
|
|
4
|
-
# Database URL
|
|
5
|
-
DATABASE_URL: str = os.getenv("DATABASE_URL")
|
|
6
|
-
|
|
7
|
-
DB_USER: str = os.getenv("DB_USER")
|
|
8
|
-
DB_HOST: str = os.getenv("DB_HOST")
|
|
9
|
-
DB_NAME: str = os.getenv("DB_NAME")
|
|
10
|
-
DB_PORT: str = os.getenv("DB_PORT")
|
|
11
|
-
DB_PASSWORD: str = os.getenv("DB_PASSWORD")
|
|
12
|
-
|
|
13
|
-
# Application settings
|
|
14
|
-
APP_NAME: str = os.getenv("APP_NAME", "Python Template API")
|
|
15
|
-
DEBUG: bool = os.getenv("DEBUG", "True").lower() in ("true",1)
|
|
16
|
-
APP_VERSION: str = os.getenv("APP_VERSION", "1.0.0")
|
|
17
|
-
|
|
18
|
-
# Logging settings
|
|
19
|
-
LOG_LEVEL: str = os.getenv("LOG_LEVEL", "INFO")
|
|
20
|
-
LOG_FORMAT: str = os.getenv("LOG_FORMAT", "detailed") # detailed, json, simple
|
|
21
|
-
LOG_TO_FILE: bool = os.getenv("LOG_TO_FILE", "False").lower() in ("true", 1)
|
|
22
|
-
LOG_MAX_SIZE: int = int(os.getenv("LOG_MAX_SIZE", "10485760")) # 10MB
|
|
23
|
-
LOG_BACKUP_COUNT: int = int(os.getenv("LOG_BACKUP_COUNT", "5"))
|
|
24
|
-
LOG_DIR: str = os.getenv("LOG_DIR", "logs")
|
|
25
|
-
|
|
26
|
-
# Security settings
|
|
27
|
-
ENVIRONMENT: str = os.getenv("ENVIRONMENT")
|
|
28
|
-
ALGORITHM: str = os.getenv("ALGORITHM")
|
|
29
|
-
SECRET_KEY: str = os.getenv("SECRET_KEY")
|
|
30
|
-
ACCESS_TOKEN_EXPIRE_MINUTES: int = int(os.getenv("ACCESS_TOKEN_EXPIRE_MINUTES", "120"))
|
|
31
|
-
|
|
32
|
-
# =============================================================================
|
|
33
|
-
# SHARED TABLES (main schema)
|
|
34
|
-
# =============================================================================
|
|
35
|
-
MAIN_TENANTS_TABLE = os.getenv("MAIN_TENANTS_TABLE", "main.tenants")
|
|
36
|
-
MAIN_ROLE_PERMISSIONS_TABLE = os.getenv("MAIN_ROLE_PERMISSIONS_TABLE", "main.role_permissions")
|
|
37
|
-
MAIN_USER_SUBSCRIPTIONS_TABLE = os.getenv("MAIN_USER_SUBSCRIPTIONS_TABLE", "main.user_subscriptions")
|
|
38
|
-
MAIN_USER_SUBSCRIPTION_HISTORY_TABLE = os.getenv("MAIN_USER_SUBSCRIPTION_HISTORY_TABLE", "main.user_subscription_history")
|
|
39
|
-
MAIN_SUBSCRIPTIONS_TABLE = os.getenv("MAIN_SUBSCRIPTIONS_TABLE", "main.subscriptions")
|
|
40
|
-
|
|
41
|
-
# System-level tables
|
|
42
|
-
MAIN_SYSTEM_GROUPS_TABLE = os.getenv("MAIN_SYSTEM_GROUPS_TABLE", "main.system_groups")
|
|
43
|
-
MAIN_SYSTEM_USER_GROUPS_TABLE = os.getenv("MAIN_SYSTEM_USER_GROUPS_TABLE", "main.system_user_groups")
|
|
44
|
-
MAIN_SYSTEM_ASSIGN_ROLES_TABLE = os.getenv("MAIN_SYSTEM_ASSIGN_ROLES_TABLE", "main.system_assign_roles")
|
|
45
|
-
|
|
46
|
-
# =============================================================================
|
|
47
|
-
# TENANT-SPECIFIC TABLES (tenant schemas)
|
|
48
|
-
# =============================================================================
|
|
49
|
-
TENANT_LOGIN_SETTINGS_TABLE = os.getenv("TENANT_LOGIN_SETTINGS_TABLE")
|
|
50
|
-
TENANT_ASSIGN_ROLES_TABLE = os.getenv("TENANT_ASSIGN_ROLES_TABLE")
|
|
51
|
-
TENANT_USER_GROUPS_TABLE = os.getenv("TENANT_USER_GROUPS_TABLE")
|
|
52
|
-
|
|
53
|
-
@property
|
|
54
|
-
def database_url(self) -> str:
|
|
55
|
-
if self.DATABASE_URL:
|
|
56
|
-
return self.DATABASE_URL
|
|
57
|
-
|
|
58
|
-
port = int(self.DB_PORT) if self.DB_PORT else 5432
|
|
59
|
-
return f"postgresql://{self.DB_USER}:{self.DB_PASSWORD}@{self.DB_HOST}:{port}/{self.DB_NAME}"
|
|
60
|
-
|
|
61
|
-
# Global settings instance
|
|
62
|
-
db_settings = Settings()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{trovesuite-1.0.16 → trovesuite-1.0.18}/src/trovesuite/notification/notification_controller.py
RENAMED
|
File without changes
|
{trovesuite-1.0.16 → trovesuite-1.0.18}/src/trovesuite/notification/notification_read_dto.py
RENAMED
|
File without changes
|
|
File without changes
|
{trovesuite-1.0.16 → trovesuite-1.0.18}/src/trovesuite/notification/notification_write_dto.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|