TroveSuite services package providing authentication, authorization, notifications, Azure Storage, and other enterprise services for TroveSuite applications
Project description
trovesuite
Shared service layer for TroveSuite applications. Bundles the internal building blocks — authentication, authorization, notifications, and Azure blob storage — behind a small, consistent API so downstream FastAPI services don't reimplement them.
This package is built for the TroveSuite platform and assumes TroveSuite's
core_platformPostgreSQL schema (tenants, users, groups, roles, permissions). It is published to PyPI as a convenience for TroveSuite services; it is not a general-purpose auth library.
What's inside
| Service | Purpose |
|---|---|
AuthService |
JWT decode, multi-tenant user authorization, role/permission resolution, permission checks. |
NotificationService |
Send email via Gmail SMTP (plain + HTML). SMS is stubbed. |
StorageService |
Azure Blob Storage: container creation, upload/update/delete, download, SAS URL generation. |
Helper |
OTP/ID generation, JWT encode, tenant-aware email dispatch, activity logging. |
Install
pip install trovesuite
Or with Poetry:
poetry add trovesuite
Requires Python 3.13.
Configure
The package reads configuration from environment variables (a .env file is loaded automatically via python-dotenv). See .env.example for the full list. The essentials:
# Postgres
DB_HOST=localhost
DB_PORT=5432
DB_NAME=trovesuite
DB_USER=postgres
DB_PASSWORD=...
# JWT
SECRET_KEY=change-me
ALGORITHM=HS256
ACCESS_TOKEN_EXPIRE_MINUTES=60
# Email (optional — used by Helper.send_notification)
MAIL_SENDER_EMAIL=alerts@yourdomain.com
MAIL_SENDER_PWD=gmail-app-password
# Azure Storage (optional — used by StorageService)
STORAGE_ACCOUNT_NAME=yourstorageaccount
USER_ASSIGNED_MANAGED_IDENTITY=<client-id> # omit for system-assigned
Usage
Authorize a user from a JWT
from trovesuite import AuthService
result = AuthService.authorize_user_from_token(token)
if result.success:
for role_entry in result.data:
print(role_entry.role_id, role_entry.permissions)
else:
print(result.error, result.detail)
Authorize by IDs
from trovesuite import AuthService
from trovesuite.auth import AuthServiceWriteDto
result = AuthService.authorize(
AuthServiceWriteDto(user_id="usr_...", tenant_id="tnt_...")
)
authorize verifies the tenant exists and is verified, checks login-window restrictions (working days or custom time period), merges tenant-level and system-level role assignments, and returns a Respons[AuthServiceReadDto] with each role's permissions attached.
Possible result.error codes: INVALID_USER_ID, INVALID_TENANT_ID, TENANT_NOT_FOUND, TENANT_NOT_VERIFIED, USER_NOT_FOUND, USER_SUSPENDED, LOGIN_TIME_RESTRICTED, LOGIN_DAY_RESTRICTED.
Check permissions
from trovesuite import AuthService
# Does the user have 'permission-user-create'?
can_create = AuthService.check_permission(
users_data=result.data,
action="permission-user-create",
)
# Same check, but only against roles scoped to a specific resource type
can_create_in_group = AuthService.check_permission(
users_data=result.data,
action="permission-user-create",
resource_type="rt-group",
)
# Aggregate helpers
all_perms = AuthService.get_user_permissions(result.data)
AuthService.has_any_permission(result.data, ["p-read", "p-write"])
AuthService.has_all_permissions(result.data, ["p-read", "p-write"])
Send an email
from trovesuite import NotificationService
from trovesuite.notification import NotificationEmailServiceWriteDto
result = NotificationService.send_email(NotificationEmailServiceWriteDto(
sender_email="alerts@yourdomain.com",
receiver_email=["user@example.com"], # str or list[str]
password="gmail-app-password",
subject="Welcome",
text_message="Plain text body",
html_message="<h1>HTML body</h1>", # optional
))
For tenant-aware sending that pulls credentials from the platform's cp_notification_email_credentials table (and falls back to MAIL_SENDER_*), use Helper.send_notification(...) with a template.
Azure Blob Storage
StorageService authenticates via Managed Identity (user-assigned if managed_identity_client_id is provided, otherwise falls back to DefaultAzureCredential for local dev). SAS URLs are generated via user-delegation keys — no storage account key required.
from trovesuite import StorageService
from trovesuite.storage import (
StorageFileUploadServiceWriteDto,
StorageFileUrlServiceWriteDto,
)
upload = StorageService.upload_file(StorageFileUploadServiceWriteDto(
storage_account_url="https://myaccount.blob.core.windows.net",
container_name="documents",
blob_name="invoice.pdf",
directory_path="tenants/tnt_abc", # optional prefix
file_content=pdf_bytes,
content_type="application/pdf",
))
url = StorageService.get_file_url(StorageFileUrlServiceWriteDto(
storage_account_url="https://myaccount.blob.core.windows.net",
container_name="documents",
blob_name="tenants/tnt_abc/invoice.pdf",
expiry_hours=2,
))
Also available: create_container, update_file, delete_file, delete_multiple_files, download_file.
Response shape
Every service method returns a generic Respons[T]:
class Respons[T](BaseModel):
detail: Optional[str] # human-readable message
error: Optional[str] # machine error code (None on success)
data: Optional[List[T]] # payload; always a list, possibly empty
status_code: int = 200
success: bool = True
pagination: Optional[PaginationMeta] = None
Always branch on result.success before reading result.data.
Database expectations
AuthService and Helper read from the TroveSuite core_platform schema. This package does NOT create or migrate the database — schema provisioning is owned by tvs-sqlscript (EF Core migrations). Run it once per environment before starting any consumer of this package:
cd ../tvs-sqlscript
dotnet run --project src/Trovesuite.Database.Runner -- deploy --module all
Table names are configurable via environment variables (CORE_PLATFORM_TENANTS_TABLE, CORE_PLATFORM_USER_GROUPS_TABLE, CORE_PLATFORM_LOGIN_SETTINGS_TABLE, CORE_PLATFORM_ASSIGN_ROLES_TABLE, CORE_PLATFORM_ROLE_PERMISSIONS_TABLE, CORE_PLATFORM_ROLES_TABLE, CORE_PLATFORM_USERS_TABLE, CORE_PLATFORM_ACTIVITY_LOGS_TABLE, CORE_PLATFORM_RESOURCE_ID_TABLE, CORE_PLATFORM_NOTIFICATION_EMAIL_CREDENTIALS_TABLE) — see .env.example.
Schemas must include the columns referenced in src/trovesuite/auth/auth_service.py (notably delete_status, is_active, is_system, is_suspended, working_days, login_on, logout_on, resource_type).
Development
git clone <repo>
cd tvs-package
poetry install --with dev
poetry run pytest
poetry run black src/
poetry run mypy src/
poetry run flake8 src/
Releasing
- Bump
versioninpyproject.toml(both[tool.poetry]and[project]blocks) andsetup.py. - Commit, then tag:
git tag v$(new_version) && git push --tags. - The
publishGitHub Actions workflow builds an sdist + wheel and uploads to PyPI using thePYPI_API_TOKENsecret from thepypienvironment.
License
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file trovesuite-1.0.37.tar.gz.
File metadata
- Download URL: trovesuite-1.0.37.tar.gz
- Upload date:
- Size: 41.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
789fc8c3adfe5ec212e012c126bff97a03efcae2e0cb3acba68bd365d66d2793
|
|
| MD5 |
7164f5a8438b7b636c48b79037ce606f
|
|
| BLAKE2b-256 |
2cea305acad95a13834769e490555f4d03e58bfa6384a6c34744b28012591c3e
|
File details
Details for the file trovesuite-1.0.37-py3-none-any.whl.
File metadata
- Download URL: trovesuite-1.0.37-py3-none-any.whl
- Upload date:
- Size: 44.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0c9d82d240b9d90738781ab497433712132376169388a74ae6e73337f1989e33
|
|
| MD5 |
7f3b7180f934032099e8dcc04a270235
|
|
| BLAKE2b-256 |
0dafbc2a7c8cdd5bf33a6f9bb2b4bc054a531ecf22e3d81ae35741ce1de011b2
|