fix: assign-user de reseller usava resellerId do body, não o :id da URL
Bug de design encontrado em revisão: PATCH /v1/resellers/:id/assign-user aceitava um resellerId diferente no corpo, e a implementação usava esse valor do corpo como alvo real da atribuição — o :id da URL virava só uma checagem de existência, não o alvo de fato. Corrigido: o :id da URL é agora a única fonte de verdade; desatribuição (reseller_id = null) virou um endpoint próprio (POST /v1/resellers/unassign-user), já que 'nenhuma revenda' não pertence à URL de nenhuma revenda específica. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -63,17 +63,15 @@ export class ResellersService {
|
||||
return reseller;
|
||||
}
|
||||
|
||||
/** Always assigns to the reseller identified by the URL `:id` — see the DTO's comment for why that's now the only source of truth. */
|
||||
async assignUser(
|
||||
id: string,
|
||||
dto: AssignUserToResellerDto,
|
||||
actorId: string,
|
||||
): Promise<{ userId: string; resellerId: string | null }> {
|
||||
await this.get(id); // 404 if the reseller in the URL doesn't exist
|
||||
if (dto.resellerId !== null && dto.resellerId !== id) {
|
||||
await this.get(dto.resellerId); // 404 if a different target reseller doesn't exist
|
||||
}
|
||||
): Promise<{ userId: string; resellerId: string }> {
|
||||
await this.get(id); // 404 if the reseller doesn't exist
|
||||
|
||||
const found = await usersRepo.assignUserToReseller(dto.userId, dto.resellerId);
|
||||
const found = await usersRepo.assignUserToReseller(dto.userId, id);
|
||||
if (!found) throw new NotFoundException("Usuário não encontrado");
|
||||
|
||||
await auditRepo.appendAuditEvent({
|
||||
@@ -82,10 +80,26 @@ export class ResellersService {
|
||||
action: "reseller.user_assigned",
|
||||
resourceType: "user",
|
||||
resourceId: dto.userId,
|
||||
metadata: { resellerId: dto.resellerId },
|
||||
metadata: { resellerId: id },
|
||||
});
|
||||
|
||||
return { userId: dto.userId, resellerId: dto.resellerId };
|
||||
return { userId: dto.userId, resellerId: id };
|
||||
}
|
||||
|
||||
/** Clears a user's reseller assignment (sets `reseller_id = null`) — not scoped to any particular reseller's URL, since "no reseller" isn't a reseller. */
|
||||
async unassignUser(userId: string, actorId: string): Promise<{ userId: string; resellerId: null }> {
|
||||
const found = await usersRepo.assignUserToReseller(userId, null);
|
||||
if (!found) throw new NotFoundException("Usuário não encontrado");
|
||||
|
||||
await auditRepo.appendAuditEvent({
|
||||
actorType: "user",
|
||||
actorId,
|
||||
action: "reseller.user_unassigned",
|
||||
resourceType: "user",
|
||||
resourceId: userId,
|
||||
});
|
||||
|
||||
return { userId, resellerId: null };
|
||||
}
|
||||
|
||||
/** Mirrors Companies' assertValidCnpjIfPresent — document is CPF or CNPJ here. */
|
||||
|
||||
Reference in New Issue
Block a user