feat: implement SSO service for secure module authentication and provide scripts for tenant and module seeding

This commit is contained in:
momorew
2026-08-28 23:17:44 +05:30
parent 7ab9cc3bee
commit a36d91fe90
4 changed files with 137 additions and 11 deletions
+10 -2
View File
@@ -60,6 +60,13 @@ class EventService:
ModuleEnvironment.module_id == module_id,
ModuleEnvironment.slug == env_slug
).first()
if not env:
env = db.query(ModuleEnvironment).filter(
ModuleEnvironment.module_id == module_id,
ModuleEnvironment.is_default == True
).first()
if env:
targets.append(env)
@@ -85,13 +92,14 @@ class EventService:
targets.append(env)
if not targets:
logger.warning(f"Event {event_type} emitted with no resolved targets. Payload scoping: {'Explicit' if 'targets' in payload.get('data', {}) else 'Implicit'}")
scoping_type = 'Explicit' if targets_list else 'Implicit'
logger.warning(f"Event {event_type} emitted with no resolved targets. Payload scoping: {scoping_type}")
return
for env in targets:
base = env.backend_base_url.rstrip('/')
if event_type in {"TENANT_PROVISION_REQUESTED", "TENANT_UPDATED", "TENANT_STATUS_CHANGED", "TENANT_DEPROVISION_REQUESTED"} and env.provisioning_endpoint:
if env.provisioning_endpoint:
endpoint = env.provisioning_endpoint.lstrip('/')
logger.info(f"Trace: base='{base}', endpoint='{endpoint}'")
target_url = f"{base}/{endpoint}"
+8 -5
View File
@@ -123,19 +123,22 @@ class SSOService:
if not user:
raise HTTPException(status_code=404, detail="User not found")
permissions = sorted(
plan_permissions = set(
SubscriptionEntitlementService.get_plan_module_access_codes(
db, tenant_id, module.id
)
)
if not permissions and user.role and user.role.role_module_accesses:
permissions = sorted(
{
permissions = []
if user.role and user.role.role_module_accesses:
role_permissions = {
rma.module_access.access_code
for rma in user.role.role_module_accesses
if rma.module_access and rma.module_access.module_id == module.id
}
)
permissions = sorted(plan_permissions.intersection(role_permissions))
# If user has no role, permissions remain empty so they don't get full access
timestamp = int(time.time() * 1000)
subscription_details = SubscriptionEntitlementService.get_subscription_summary(
+51
View File
@@ -0,0 +1,51 @@
import os
import sys
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from app.config.database import SessionLocal
from app.models.auth.module_model import Module
from app.models.auth.tenant_model import Tenant
from app.models.auth.tenant_module_model import TenantModule
from app.services.auth.module_permission_service import ModulePermissionService
def fix_docqube():
db = SessionLocal()
try:
# Get docqube module
docqube = db.query(Module).filter(Module.module_id == "docqube").first()
if not docqube:
print("Docqube module not found")
return
print("Syncing Docqube permissions...")
try:
res = ModulePermissionService.sync_permissions(db, str(docqube.id))
print(f"Sync result: {res}")
except Exception as e:
print(f"Failed to sync permissions: {e}")
# Assign to all active tenants
tenants = db.query(Tenant).filter(Tenant.status == "active").all()
for tenant in tenants:
mapping = db.query(TenantModule).filter(
TenantModule.tenant_id == tenant.id,
TenantModule.module_id == docqube.id
).first()
if not mapping:
print(f"Assigning Docqube to tenant {tenant.name}...")
mapping = TenantModule(
tenant_id=tenant.id,
module_id=docqube.id,
is_active=True,
assigned_environment_slug="localdev"
)
db.add(mapping)
db.commit()
print("Successfully assigned docqube to all active tenants.")
finally:
db.close()
if __name__ == "__main__":
fix_docqube()
+64
View File
@@ -0,0 +1,64 @@
import os
import sys
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from app.config.database import SessionLocal
from app.models.auth.module_model import Module
from app.models.auth.module_environment_model import ModuleEnvironment
def seed_docqube_module():
db = SessionLocal()
try:
docqube_module = db.query(Module).filter(Module.module_id == "docqube").first()
if not docqube_module:
print("Creating Docqube Module...")
docqube_module = Module(
module_id="docqube",
module_name="DocQube",
description="DocQube Document Management System",
status="active"
)
db.add(docqube_module)
db.commit()
db.refresh(docqube_module)
else:
print("Docqube Module already exists.")
docqube_env = db.query(ModuleEnvironment).filter(
ModuleEnvironment.module_id == docqube_module.id,
ModuleEnvironment.slug == "localdev"
).first()
if not docqube_env:
print("Creating Docqube localdev environment...")
docqube_env = ModuleEnvironment(
module_id=docqube_module.id,
slug="localdev",
frontend_base_url="http://localhost:3000",
backend_base_url="http://localhost:8001",
sso_entry_path="/sso/login",
permission_sync_endpoint="/api/sso/sync-permissions",
provisioning_endpoint="/api/sso/provision",
trust_type="HMAC",
trust_credentials={"hmac_secret": "VBN20DIyTbuqRJKKpxB2C4aDVYRUENa1rdzFXPLXwxA"},
is_default=True,
is_active=True
)
db.add(docqube_env)
db.commit()
print("Successfully created Docqube localdev environment.")
else:
print("Docqube localdev environment already exists.")
docqube_env.provisioning_endpoint = "/api/sso/provision"
docqube_env.permission_sync_endpoint = "/api/sso/sync-permissions"
docqube_env.trust_credentials = {"hmac_secret": "VBN20DIyTbuqRJKKpxB2C4aDVYRUENa1rdzFXPLXwxA"}
db.commit()
print("Updated existing Docqube localdev environment.")
finally:
db.close()
if __name__ == "__main__":
seed_docqube_module()