diff --git a/packages/services/auth-service/src/interfaces/rest/controllers/tenant.controller.ts b/packages/services/auth-service/src/interfaces/rest/controllers/tenant.controller.ts index 9692078..08f6768 100644 --- a/packages/services/auth-service/src/interfaces/rest/controllers/tenant.controller.ts +++ b/packages/services/auth-service/src/interfaces/rest/controllers/tenant.controller.ts @@ -28,13 +28,34 @@ export class TenantController { private readonly tenantProvisioningService: TenantProvisioningService, ) {} + private toDto(t: Tenant) { + return { + id: t.id, + name: t.name, + slug: t.slug, + plan: t.plan, + status: t.status, + adminEmail: t.adminEmail, + userCount: 0, + quota: { + maxServers: t.maxServers, + maxUsers: t.maxUsers, + maxStandingOrders: t.maxStandingOrders, + maxAgentTokensPerMonth: t.maxAgentTokensPerMonth, + }, + createdAt: t.createdAt, + updatedAt: t.updatedAt, + }; + } + /** * GET /api/v1/admin/tenants * Returns all tenants from the public schema's tenants table. */ @Get() async listTenants() { - return this.tenantRepository.find({ order: { createdAt: 'DESC' } }); + const tenants = await this.tenantRepository.find({ order: { createdAt: 'DESC' } }); + return tenants.map((t) => this.toDto(t)); } /** @@ -47,7 +68,7 @@ export class TenantController { if (!tenant) { throw new NotFoundException(`Tenant with id "${id}" not found`); } - return tenant; + return this.toDto(tenant); } /** @@ -95,7 +116,7 @@ export class TenantController { // The tenant record is already saved; schema provisioning can be retried } - return savedTenant; + return this.toDto(savedTenant); } /** @@ -103,30 +124,32 @@ export class TenantController { * Updates tenant metadata. */ @Patch(':id') - async updateTenant(@Param('id') id: string, @Body() body: Partial) { + async updateTenant(@Param('id') id: string, @Body() body: any) { const tenant = await this.tenantRepository.findOne({ where: { id } }); if (!tenant) { throw new NotFoundException(`Tenant with id "${id}" not found`); } - // Only allow updating specific fields - const allowedFields: (keyof Tenant)[] = [ - 'name', - 'plan', - 'status', - 'adminEmail', - 'maxServers', - 'maxUsers', - 'maxStandingOrders', - 'maxAgentTokensPerMonth', - ]; + if (body.name !== undefined) tenant.name = body.name; + if (body.plan !== undefined) tenant.plan = body.plan; + if (body.status !== undefined) tenant.status = body.status; + if (body.adminEmail !== undefined) tenant.adminEmail = body.adminEmail; - for (const field of allowedFields) { - if (body[field] !== undefined) { - (tenant as any)[field] = body[field]; - } + // Support nested quota object from frontend + if (body.quota) { + if (body.quota.maxServers !== undefined) tenant.maxServers = body.quota.maxServers; + if (body.quota.maxUsers !== undefined) tenant.maxUsers = body.quota.maxUsers; + if (body.quota.maxStandingOrders !== undefined) tenant.maxStandingOrders = body.quota.maxStandingOrders; + if (body.quota.maxAgentTokensPerMonth !== undefined) tenant.maxAgentTokensPerMonth = body.quota.maxAgentTokensPerMonth; } - return this.tenantRepository.save(tenant); + // Also support flat fields + if (body.maxServers !== undefined) tenant.maxServers = body.maxServers; + if (body.maxUsers !== undefined) tenant.maxUsers = body.maxUsers; + if (body.maxStandingOrders !== undefined) tenant.maxStandingOrders = body.maxStandingOrders; + if (body.maxAgentTokensPerMonth !== undefined) tenant.maxAgentTokensPerMonth = body.maxAgentTokensPerMonth; + + const saved = await this.tenantRepository.save(tenant); + return this.toDto(saved); } }