import { Router, Request, Response } from 'express'; import { SaasTenantService } from '../../services/tenant/SaasTenantService'; import { TenantDomainMiddleware } from '../../middleware/TenantDomainMiddleware'; import { logger } from '../../utils/logger'; const router = Router(); router.use(TenantDomainMiddleware.resolveTenant); router.get('/tenants', async (req: Request, res: Response) => { try { const filters: any = {}; if (req.query.status) { filters.status = req.query.status as string; } if (req.query.plan) { filters.plan = req.query.plan as string; } if (req.query.type) { filters.type = req.query.type as string; } const tenants = await SaasTenantService.listTenants(filters); res.json({ success: true, data: tenants }); } catch (error: any) { logger.error('[SaasTenantAPI] Error listing tenants:', error); res.status(500).json({ error: error.message }); } }); router.get('/tenants/:tenantId', async (req: Request, res: Response) => { try { const tenant = await SaasTenantService.getTenant(req.params.tenantId as string); if (!tenant) { return res.status(404).json({ error: 'Tenant not found' }); } res.json({ success: true, data: tenant }); } catch (error: any) { logger.error('[SaasTenantAPI] Error getting tenant:', error); res.status(500).json({ error: error.message }); } }); router.post('/tenants', async (req: Request, res: Response) => { try { const tenant = await SaasTenantService.createTenant(req.body); res.status(201).json({ success: true, data: tenant }); } catch (error: any) { logger.error('[SaasTenantAPI] Error creating tenant:', error); res.status(500).json({ error: error.message }); } }); router.get('/tenants/:tenantId/domains', async (req: Request, res: Response) => { try { const domains = await SaasTenantService.getTenantDomains(req.params.tenantId as string); res.json({ success: true, data: domains }); } catch (error: any) { logger.error('[SaasTenantAPI] Error getting tenant domains:', error); res.status(500).json({ error: error.message }); } }); router.post('/tenants/:tenantId/domains', async (req: Request, res: Response) => { try { const { domain, type } = req.body; if (!domain) { return res.status(400).json({ error: 'Domain is required' }); } const tenantDomain = await SaasTenantService.addDomain( req.params.tenantId as string, domain, type || 'SUBDOMAIN' ); res.status(201).json({ success: true, data: tenantDomain }); } catch (error: any) { logger.error('[SaasTenantAPI] Error adding domain:', error); res.status(500).json({ error: error.message }); } }); router.post('/domains/:domainId/verify', async (req: Request, res: Response) => { try { const domain = await SaasTenantService.verifyDomain(req.params.domainId as string); res.json({ success: true, data: domain }); } catch (error: any) { logger.error('[SaasTenantAPI] Error verifying domain:', error); res.status(500).json({ error: error.message }); } }); router.post('/domains/:domainId/primary', async (req: Request, res: Response) => { try { await SaasTenantService.setPrimaryDomain(req.params.domainId as string); res.json({ success: true, message: 'Primary domain set successfully' }); } catch (error: any) { logger.error('[SaasTenantAPI] Error setting primary domain:', error); res.status(500).json({ error: error.message }); } }); router.get('/tenants/:tenantId/users', async (req: Request, res: Response) => { try { const users = await SaasTenantService.getTenantUsers(req.params.tenantId as string); res.json({ success: true, data: users }); } catch (error: any) { logger.error('[SaasTenantAPI] Error getting tenant users:', error); res.status(500).json({ error: error.message }); } }); router.post('/tenants/:tenantId/users', async (req: Request, res: Response) => { try { const { userId, role, permissions } = req.body; if (!userId) { return res.status(400).json({ error: 'User ID is required' }); } const tenantUser = await SaasTenantService.addUser( req.params.tenantId as string, userId, role || 'OPERATOR', permissions || [] ); res.status(201).json({ success: true, data: tenantUser }); } catch (error: any) { logger.error('[SaasTenantAPI] Error adding user:', error); res.status(500).json({ error: error.message }); } }); router.put('/tenants/:tenantId/users/:userId', async (req: Request, res: Response) => { try { const { role, permissions } = req.body; if (!role) { return res.status(400).json({ error: 'Role is required' }); } const tenantUser = await SaasTenantService.updateUserRole( req.params.tenantId as string, req.params.userId as string, role, permissions || [] ); res.json({ success: true, data: tenantUser }); } catch (error: any) { logger.error('[SaasTenantAPI] Error updating user role:', error); res.status(500).json({ error: error.message }); } }); router.get('/users/:userId/tenants', async (req: Request, res: Response) => { try { const tenants = await SaasTenantService.getUserTenants(req.params.userId as string); res.json({ success: true, data: tenants }); } catch (error: any) { logger.error('[SaasTenantAPI] Error getting user tenants:', error); res.status(500).json({ error: error.message }); } }); router.get('/tenants/:tenantId/settings', async (req: Request, res: Response) => { try { const category = req.query.category as string; const settings = await SaasTenantService.getSettings(req.params.tenantId as string, category); res.json({ success: true, data: settings }); } catch (error: any) { logger.error('[SaasTenantAPI] Error getting tenant settings:', error); res.status(500).json({ error: error.message }); } }); router.get('/tenants/:tenantId/settings/:key', async (req: Request, res: Response) => { try { const tenantId = Array.isArray(req.params.tenantId) ? req.params.tenantId[0] : req.params.tenantId; const key = Array.isArray(req.params.key) ? req.params.key[0] : req.params.key; const value = await SaasTenantService.getSetting(tenantId, key); if (value === null) { return res.status(404).json({ error: 'Setting not found' }); } res.json({ success: true, data: { key, value } }); } catch (error: any) { logger.error('[SaasTenantAPI] Error getting tenant setting:', error); res.status(500).json({ error: error.message }); } }); router.put('/tenants/:tenantId/settings/:key', async (req: Request, res: Response) => { try { const { value, category } = req.body; if (value === undefined) { return res.status(400).json({ error: 'Value is required' }); } const tenantId = Array.isArray(req.params.tenantId) ? req.params.tenantId[0] : req.params.tenantId; const key = Array.isArray(req.params.key) ? req.params.key[0] : req.params.key; await SaasTenantService.setSetting( tenantId, key, value, category || 'general' ); res.json({ success: true, message: 'Setting updated successfully' }); } catch (error: any) { logger.error('[SaasTenantAPI] Error setting tenant setting:', error); res.status(500).json({ error: error.message }); } }); router.get('/current-tenant', (req: Request, res: Response) => { if (!req.tenant) { return res.status(404).json({ error: 'No tenant found for current request' }); } res.json({ success: true, data: req.tenant }); }); router.put('/tenants/:tenantId', async (req: Request, res: Response) => { try { const tenant = await SaasTenantService.updateTenant(req.params.tenantId as string, req.body); res.json({ success: true, data: tenant }); } catch (error: any) { logger.error('[SaasTenantAPI] Error updating tenant:', error); res.status(500).json({ error: error.message }); } }); router.delete('/tenants/:tenantId', async (req: Request, res: Response) => { try { await SaasTenantService.deleteTenant(req.params.tenantId as string); res.json({ success: true, message: 'Tenant deleted successfully' }); } catch (error: any) { logger.error('[SaasTenantAPI] Error deleting tenant:', error); res.status(500).json({ error: error.message }); } }); router.put('/tenants/:tenantId/status', async (req: Request, res: Response) => { try { const { status } = req.body; if (!status) { return res.status(400).json({ error: 'Status is required' }); } const tenant = await SaasTenantService.updateTenantStatus(req.params.tenantId as string, status); res.json({ success: true, data: tenant }); } catch (error: any) { logger.error('[SaasTenantAPI] Error updating tenant status:', error); res.status(500).json({ error: error.message }); } }); router.delete('/domains/:domainId', async (req: Request, res: Response) => { try { await SaasTenantService.deleteDomain(req.params.domainId as string); res.json({ success: true, message: 'Domain deleted successfully' }); } catch (error: any) { logger.error('[SaasTenantAPI] Error deleting domain:', error); res.status(500).json({ error: error.message }); } }); router.delete('/tenants/:tenantId/users/:userId', async (req: Request, res: Response) => { try { await SaasTenantService.removeUser(req.params.tenantId as string, req.params.userId as string); res.json({ success: true, message: 'User removed successfully' }); } catch (error: any) { logger.error('[SaasTenantAPI] Error removing user:', error); res.status(500).json({ error: error.message }); } }); router.get('/stats', async (req: Request, res: Response) => { try { const stats = await SaasTenantService.getStats(); res.json({ success: true, data: stats }); } catch (error: any) { logger.error('[SaasTenantAPI] Error getting stats:', error); res.status(500).json({ error: error.message }); } }); router.get('/tenants/:tenantId/usage', async (req: Request, res: Response) => { try { const usage = await SaasTenantService.getUsage(req.params.tenantId as string); res.json({ success: true, data: usage }); } catch (error: any) { logger.error('[SaasTenantAPI] Error getting tenant usage:', error); res.status(500).json({ error: error.message }); } }); router.get('/tenants/:tenantId/logs', async (req: Request, res: Response) => { try { const logs = await SaasTenantService.getOperationLogs(req.params.tenantId as string); res.json({ success: true, data: logs }); } catch (error: any) { logger.error('[SaasTenantAPI] Error getting operation logs:', error); res.status(500).json({ error: error.message }); } }); export default router;