feat: setup account page for customer and centeralize the otps and phone usages to use the iam user

This commit is contained in:
Nathnael
2026-07-16 12:08:45 +00:00
parent 318af79962
commit f71bbbf782
26 changed files with 1057 additions and 62 deletions

View File

@@ -0,0 +1,62 @@
import { Body, Controller, Patch, Post, UseGuards } from "@nestjs/common";
import { ApiBearerAuth, ApiOperation, ApiTags } from "@nestjs/swagger";
import { CurrentUser } from "@tria-plc/api-common/modules/auth/decorators/current-user.decorator";
import { JwtGuard } from "@tria-plc/api-common/modules/auth/services/jwt.guard";
import type { TCurrentUser } from "@tria-plc/api-common/modules/auth/types/current-user.type";
import { AccountService } from "./account.service";
import {
SendContactOtpDto,
UpdateAccountNameDto,
UpdateContactDto,
} from "./dto/account.dto";
/**
* The caller's own account record. Everything here is scoped to the JWT's user
* id — there is no `:id` parameter to tamper with, so these routes need no
* permission key beyond being authenticated.
*/
@ApiTags("auth")
@Controller("me")
@ApiBearerAuth()
@UseGuards(JwtGuard)
export class AccountController {
constructor(private readonly accountService: AccountService) {}
@Post("contact/otp")
@ApiOperation({
summary: "Send a verification code to a new email/phone before changing it",
description:
"The code goes to the NEW value supplied here, proving the caller controls " +
"it. Returns the target masked — an unverified caller never gets it back in full.",
})
sendContactOtp(
@CurrentUser() user: TCurrentUser,
@Body() dto: SendContactOtpDto,
): Promise<{ sentTo: string }> {
return this.accountService.sendContactOtp(user.id, dto);
}
@Patch("contact")
@ApiOperation({
summary: "Change the account's email or phone, gated by a verification code",
description:
"Verifies the code and writes the new value in one call, so the API never " +
"has to take a client's word that verification happened.",
})
updateContact(
@CurrentUser() user: TCurrentUser,
@Body() dto: UpdateContactDto,
): Promise<{ success: true; value: string }> {
return this.accountService.updateContact(user.id, dto);
}
@Patch("name")
@ApiOperation({ summary: "Change the account's display name" })
updateName(
@CurrentUser() user: TCurrentUser,
@Body() dto: UpdateAccountNameDto,
): Promise<{ success: true }> {
return this.accountService.updateName(user.id, dto);
}
}