Files
makemd/server/src/api/routes/saas-tenant.ts

335 lines
11 KiB
TypeScript
Raw Normal View History

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;