accounts/server/api/auth.go

127 lines
2.9 KiB
Go

package api
import (
"bytes"
"encoding/json"
"log/slog"
"net/http"
"net/url"
"os"
"strings"
"time"
"github.com/gin-gonic/gin"
)
const defaultAccountServiceURL = "http://localhost:8080"
var accountServiceHTTPClient = &http.Client{Timeout: 10 * time.Second}
func registerAuthRoutes(r *gin.RouterGroup) {
r.POST("/auth/register", handleAuthRegister)
}
func handleAuthRegister(c *gin.Context) {
name := strings.TrimSpace(c.PostForm("name"))
email := strings.ToLower(strings.TrimSpace(c.PostForm("email")))
password := c.PostForm("password")
confirm := c.PostForm("confirmPassword")
if email == "" || password == "" {
redirectWithError(c, "missing_fields")
return
}
if password != confirm {
redirectWithError(c, "password_mismatch")
return
}
payload := map[string]string{
"name": name,
"email": email,
"password": password,
}
body, err := json.Marshal(payload)
if err != nil {
slog.Error("marshal register payload", "err", err)
redirectWithError(c, "registration_failed")
return
}
req, err := http.NewRequestWithContext(
c.Request.Context(),
http.MethodPost,
accountServiceRegisterURL(),
bytes.NewReader(body),
)
if err != nil {
slog.Error("create account service request", "err", err)
redirectWithError(c, "registration_failed")
return
}
req.Header.Set("Content-Type", "application/json")
resp, err := accountServiceHTTPClient.Do(req)
if err != nil {
slog.Error("call account service", "err", err)
redirectWithError(c, "registration_failed")
return
}
defer resp.Body.Close()
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
var result struct {
Error string `json:"error"`
}
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
slog.Error("decode account service error", "err", err)
}
message := strings.TrimSpace(result.Error)
if message == "" {
message = "registration_failed"
}
redirectWithError(c, message)
return
}
redirectToLogin(c)
}
func redirectWithError(c *gin.Context, message string) {
target := &url.URL{Path: "/register"}
values := url.Values{}
values.Set("error", message)
target.RawQuery = values.Encode()
c.Redirect(http.StatusSeeOther, target.String())
}
func redirectToLogin(c *gin.Context) {
target := &url.URL{Path: "/login"}
values := url.Values{}
values.Set("registered", "1")
target.RawQuery = values.Encode()
c.Redirect(http.StatusSeeOther, target.String())
}
func accountServiceRegisterURL() string {
base := strings.TrimSuffix(resolveAccountServiceBaseURL(), "/")
return base + "/v1/register"
}
func resolveAccountServiceBaseURL() string {
candidates := []string{
os.Getenv("ACCOUNT_SERVICE_URL"),
os.Getenv("ACCOUNT_SERVICE_BASE_URL"),
os.Getenv("NEXT_PUBLIC_ACCOUNT_SERVICE_URL"),
}
for _, candidate := range candidates {
candidate = strings.TrimSpace(candidate)
if candidate != "" {
return candidate
}
}
return defaultAccountServiceURL
}