Rename register resend endpoint to send (#622)
This commit is contained in:
parent
a898b95248
commit
32784d74b6
@ -187,7 +187,7 @@ func RegisterRoutes(r *gin.Engine, opts ...Option) {
|
||||
|
||||
auth.POST("/register", h.register)
|
||||
auth.POST("/register/verify", h.verifyEmail)
|
||||
auth.POST("/register/resend", h.resendEmailVerification)
|
||||
auth.POST("/register/send", h.sendEmailVerification)
|
||||
|
||||
auth.POST("/login", h.login)
|
||||
|
||||
@ -229,7 +229,7 @@ type verificationCodeRequest struct {
|
||||
Code string `json:"code"`
|
||||
}
|
||||
|
||||
type verificationResendRequest struct {
|
||||
type verificationSendRequest struct {
|
||||
Email string `json:"email"`
|
||||
}
|
||||
|
||||
@ -429,13 +429,13 @@ func (h *handler) verifyEmail(c *gin.Context) {
|
||||
})
|
||||
}
|
||||
|
||||
func (h *handler) resendEmailVerification(c *gin.Context) {
|
||||
func (h *handler) sendEmailVerification(c *gin.Context) {
|
||||
if hasQueryParameter(c, "email") {
|
||||
respondError(c, http.StatusBadRequest, "email_in_query", "email must be sent in the request body")
|
||||
return
|
||||
}
|
||||
|
||||
var req verificationResendRequest
|
||||
var req verificationSendRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
respondError(c, http.StatusBadRequest, "invalid_request", "invalid request payload")
|
||||
return
|
||||
@ -468,12 +468,12 @@ func (h *handler) resendEmailVerification(c *gin.Context) {
|
||||
}
|
||||
|
||||
if err := h.enqueueEmailVerification(c.Request.Context(), user); err != nil {
|
||||
slog.Error("failed to resend verification email", "err", err, "email", user.Email)
|
||||
slog.Error("failed to send verification email", "err", err, "email", user.Email)
|
||||
respondError(c, http.StatusInternalServerError, "verification_failed", "verification email could not be sent")
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"message": "verification email resent"})
|
||||
c.JSON(http.StatusOK, gin.H{"message": "verification email sent"})
|
||||
}
|
||||
|
||||
func (h *handler) requestPasswordReset(c *gin.Context) {
|
||||
|
||||
@ -290,7 +290,7 @@ func TestResendVerificationEndpoint(t *testing.T) {
|
||||
t.Fatalf("failed to marshal resend payload: %v", err)
|
||||
}
|
||||
|
||||
req = httptest.NewRequest(http.MethodPost, "/api/auth/register/resend", bytes.NewReader(resendBody))
|
||||
req = httptest.NewRequest(http.MethodPost, "/api/auth/register/send", bytes.NewReader(resendBody))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
rr = httptest.NewRecorder()
|
||||
router.ServeHTTP(rr, req)
|
||||
@ -382,7 +382,7 @@ func TestResendVerificationEndpointErrors(t *testing.T) {
|
||||
t.Fatalf("failed to marshal resend payload: %v", err)
|
||||
}
|
||||
|
||||
req = httptest.NewRequest(http.MethodPost, "/api/auth/register/resend", bytes.NewReader(resendBody))
|
||||
req = httptest.NewRequest(http.MethodPost, "/api/auth/register/send", bytes.NewReader(resendBody))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
rr = httptest.NewRecorder()
|
||||
router.ServeHTTP(rr, req)
|
||||
@ -396,7 +396,7 @@ func TestResendVerificationEndpointErrors(t *testing.T) {
|
||||
t.Fatalf("failed to marshal unknown payload: %v", err)
|
||||
}
|
||||
|
||||
req = httptest.NewRequest(http.MethodPost, "/api/auth/register/resend", bytes.NewReader(unknownBody))
|
||||
req = httptest.NewRequest(http.MethodPost, "/api/auth/register/send", bytes.NewReader(unknownBody))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
rr = httptest.NewRecorder()
|
||||
router.ServeHTTP(rr, req)
|
||||
|
||||
@ -483,7 +483,7 @@ export default function RegisterContent() {
|
||||
}
|
||||
|
||||
try {
|
||||
const resendResponse = await fetch('/api/auth/register/resend', {
|
||||
const resendResponse = await fetch('/api/auth/register/send', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
@ -705,7 +705,7 @@ export default function RegisterContent() {
|
||||
setIsResending(true)
|
||||
|
||||
try {
|
||||
const response = await fetch('/api/auth/register/resend', {
|
||||
const response = await fetch('/api/auth/register/send', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
|
||||
@ -1 +0,0 @@
|
||||
export { POST, GET } from '../../verify-email/resend/route'
|
||||
1
dashboard/app/api/auth/register/send/route.ts
Normal file
1
dashboard/app/api/auth/register/send/route.ts
Normal file
@ -0,0 +1 @@
|
||||
export { POST, GET } from '../../verify-email/send/route'
|
||||
@ -5,7 +5,7 @@ import { getAccountServiceBaseUrl } from '@lib/serviceConfig'
|
||||
const ACCOUNT_SERVICE_URL = getAccountServiceBaseUrl()
|
||||
const ACCOUNT_API_BASE = `${ACCOUNT_SERVICE_URL}/api/auth`
|
||||
|
||||
type ResendPayload = {
|
||||
type SendPayload = {
|
||||
email?: string
|
||||
}
|
||||
|
||||
@ -14,11 +14,11 @@ function normalizeEmail(value: unknown) {
|
||||
}
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
let payload: ResendPayload
|
||||
let payload: SendPayload
|
||||
try {
|
||||
payload = (await request.json()) as ResendPayload
|
||||
payload = (await request.json()) as SendPayload
|
||||
} catch (error) {
|
||||
console.error('Failed to decode verification resend payload', error)
|
||||
console.error('Failed to decode verification send payload', error)
|
||||
return NextResponse.json({ success: false, error: 'invalid_request', needMfa: false }, { status: 400 })
|
||||
}
|
||||
|
||||
@ -28,7 +28,7 @@ export async function POST(request: NextRequest) {
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(`${ACCOUNT_API_BASE}/register/resend`, {
|
||||
const response = await fetch(`${ACCOUNT_API_BASE}/register/send`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
@ -45,7 +45,7 @@ export async function POST(request: NextRequest) {
|
||||
|
||||
return NextResponse.json({ success: true, error: null, needMfa: false })
|
||||
} catch (error) {
|
||||
console.error('Account service verification resend proxy failed', error)
|
||||
console.error('Account service verification send proxy failed', error)
|
||||
return NextResponse.json(
|
||||
{ success: false, error: 'account_service_unreachable', needMfa: false },
|
||||
{ status: 502 },
|
||||
@ -4,7 +4,7 @@ This document describes the HTTP endpoints provided by the XControl platform. Ea
|
||||
|
||||
## Authentication Gateway (Next.js)
|
||||
|
||||
The XControl web frontend exposes authentication APIs under `dashboard/app/api/auth`. These endpoints act as a secure gateway that proxies requests to the shared Account Service (`/api/auth/register`, `/api/auth/register/verify`, `/api/auth/login`, `/api/auth/mfa/setup`, `/api/auth/mfa/verify`). Responses always include `{ "success": boolean, "error": string | null, "needMfa": boolean }` so that multiple frontends can share the same Account Service behaviour.
|
||||
The XControl web frontend exposes authentication APIs under `dashboard/app/api/auth`. These endpoints act as a secure gateway that proxies requests to the shared Account Service (`/api/auth/register`, `/api/auth/register/send`, `/api/auth/register/verify`, `/api/auth/login`, `/api/auth/mfa/setup`, `/api/auth/mfa/verify`). Responses always include `{ "success": boolean, "error": string | null, "needMfa": boolean }` so that multiple frontends can share the same Account Service behaviour.
|
||||
|
||||
Gateway-managed session cookies (`xc_session`) and MFA challenge cookies (`xc_mfa_challenge`) are issued with `HttpOnly`, `Secure`, and `SameSite=Strict` attributes. Cookies are HTTPS-only and never expose raw secrets to JavaScript.
|
||||
|
||||
@ -22,6 +22,18 @@ Gateway-managed session cookies (`xc_session`) and MFA challenge cookies (`xc_mf
|
||||
-d '{"name":"demo","email":"demo@example.com","password":"Secret123","confirmPassword":"Secret123"}'
|
||||
```
|
||||
|
||||
### POST /api/auth/register/send
|
||||
- **Description:** Trigger a verification email for an existing pending registration. This endpoint may be used to send the initial code when the frontend wants to separate registration from verification, or to resend a code if the user did not receive the previous email.
|
||||
- **Body Parameters (JSON):**
|
||||
- `email` – The pending account email address.
|
||||
- **Response:** `{ "success": true, "error": null, "needMfa": false }` on success. On failure `error` contains the Account Service error code.
|
||||
- **Test:**
|
||||
```bash
|
||||
curl -X POST http://localhost:3000/api/auth/register/send \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"email":"demo@example.com"}'
|
||||
```
|
||||
|
||||
### POST /api/auth/verify-email
|
||||
- **Description:** Confirm the 6-digit email verification code issued during registration. Activates the account when the code matches and has not expired.
|
||||
- **Body Parameters (JSON):**
|
||||
|
||||
Loading…
Reference in New Issue
Block a user