Skip to main content

TroveSuite services package providing authentication, authorization, notifications, Azure Storage, and other enterprise services for TroveSuite applications

Project description

trovesuite

PyPI version Python versions License: MIT

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_platform PostgreSQL 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. 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

  1. Bump version in pyproject.toml (both [tool.poetry] and [project] blocks) and setup.py.
  2. Commit, then tag: git tag v$(new_version) && git push --tags.
  3. The publish GitHub Actions workflow builds an sdist + wheel and uploads to PyPI using the PYPI_API_TOKEN secret from the pypi environment.

License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

trovesuite-1.0.36.tar.gz (41.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

trovesuite-1.0.36-py3-none-any.whl (43.9 kB view details)

Uploaded Python 3

File details

Details for the file trovesuite-1.0.36.tar.gz.

File metadata

  • Download URL: trovesuite-1.0.36.tar.gz
  • Upload date:
  • Size: 41.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for trovesuite-1.0.36.tar.gz
Algorithm Hash digest
SHA256 6daa3e509c4d04b0e87007981b20bd0ed227fb3635afff5b6a00e294a38facd8
MD5 98b85f8f203d587c04b67b05a5b18fd6
BLAKE2b-256 2056430ce6562086a23b562e23810d4c903e0b5c3c317c7fb700c3676b73365d

See more details on using hashes here.

File details

Details for the file trovesuite-1.0.36-py3-none-any.whl.

File metadata

  • Download URL: trovesuite-1.0.36-py3-none-any.whl
  • Upload date:
  • Size: 43.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for trovesuite-1.0.36-py3-none-any.whl
Algorithm Hash digest
SHA256 ae5f7c676d921112a405c65cc92d1891b606e337f430e597946bc7e672165721
MD5 854a2fa39ec8d1bf46a7d6f3a372bf34
BLAKE2b-256 c6929ac76af99eda1a9e665b34009e221334eb0070cca10bfa81b12fdc66b214

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page