fix: format tenant API response to match frontend DTO
Map flat quota fields to nested quota object and add userCount field to match the frontend's expected Tenant interface. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
3816d6841d
commit
8f89b8121c
|
|
@ -28,13 +28,34 @@ export class TenantController {
|
||||||
private readonly tenantProvisioningService: TenantProvisioningService,
|
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
|
* GET /api/v1/admin/tenants
|
||||||
* Returns all tenants from the public schema's tenants table.
|
* Returns all tenants from the public schema's tenants table.
|
||||||
*/
|
*/
|
||||||
@Get()
|
@Get()
|
||||||
async listTenants() {
|
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) {
|
if (!tenant) {
|
||||||
throw new NotFoundException(`Tenant with id "${id}" not found`);
|
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
|
// 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.
|
* Updates tenant metadata.
|
||||||
*/
|
*/
|
||||||
@Patch(':id')
|
@Patch(':id')
|
||||||
async updateTenant(@Param('id') id: string, @Body() body: Partial<Tenant>) {
|
async updateTenant(@Param('id') id: string, @Body() body: any) {
|
||||||
const tenant = await this.tenantRepository.findOne({ where: { id } });
|
const tenant = await this.tenantRepository.findOne({ where: { id } });
|
||||||
if (!tenant) {
|
if (!tenant) {
|
||||||
throw new NotFoundException(`Tenant with id "${id}" not found`);
|
throw new NotFoundException(`Tenant with id "${id}" not found`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only allow updating specific fields
|
if (body.name !== undefined) tenant.name = body.name;
|
||||||
const allowedFields: (keyof Tenant)[] = [
|
if (body.plan !== undefined) tenant.plan = body.plan;
|
||||||
'name',
|
if (body.status !== undefined) tenant.status = body.status;
|
||||||
'plan',
|
if (body.adminEmail !== undefined) tenant.adminEmail = body.adminEmail;
|
||||||
'status',
|
|
||||||
'adminEmail',
|
|
||||||
'maxServers',
|
|
||||||
'maxUsers',
|
|
||||||
'maxStandingOrders',
|
|
||||||
'maxAgentTokensPerMonth',
|
|
||||||
];
|
|
||||||
|
|
||||||
for (const field of allowedFields) {
|
// Support nested quota object from frontend
|
||||||
if (body[field] !== undefined) {
|
if (body.quota) {
|
||||||
(tenant as any)[field] = body[field];
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue