feat: implement SSO service for secure module authentication and provide scripts for tenant and module seeding
This commit is contained in:
@@ -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}"
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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()
|
||||
@@ -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()
|
||||
Reference in New Issue
Block a user