This commit is contained in:
Daniel Goc
2026-03-18 16:09:03 +01:00
parent e094865fc7
commit 52c17d7017
8 changed files with 170 additions and 173 deletions

View File

@@ -6,6 +6,7 @@ import (
"encoding/hex"
"errors"
"fmt"
"strconv"
"time"
"git.ma-al.com/goc_daniel/b2b/app/config"
@@ -13,9 +14,13 @@ import (
"git.ma-al.com/goc_daniel/b2b/app/model"
"git.ma-al.com/goc_daniel/b2b/app/service/emailService"
constdata "git.ma-al.com/goc_daniel/b2b/app/utils/const_data"
"git.ma-al.com/goc_daniel/b2b/app/utils/i18n"
"git.ma-al.com/goc_daniel/b2b/app/utils/nullable"
"git.ma-al.com/goc_daniel/b2b/app/utils/response"
"git.ma-al.com/goc_daniel/b2b/app/utils/responseErrors"
"github.com/dlclark/regexp2"
"github.com/gofiber/fiber/v3"
"github.com/golang-jwt/jwt/v5"
"golang.org/x/crypto/bcrypt"
"gorm.io/gorm"
@@ -475,6 +480,16 @@ func hashToken(raw string) string {
// generateAccessToken generates a short-lived JWT access token
func (s *AuthService) generateAccessToken(user *model.Customer) (string, error) {
_, err := s.GetLangISOCode(user.LangID)
if err != nil {
return "", responseErrors.ErrBadLangID
}
err = s.CheckIfCountryExists(user.CountryID)
if err != nil {
return "", responseErrors.ErrBadCountryID
}
claims := JWTClaims{
UserID: user.ID,
Email: user.Email,
@@ -493,43 +508,82 @@ func (s *AuthService) generateAccessToken(user *model.Customer) (string, error)
return token.SignedString([]byte(s.config.JWTSecret))
}
// UpdateChoice updates the user's language and/or country choice and returns a new JWT token
func (s *AuthService) UpdateChoice(userID uint, langID uint, countryID uint) (string, error) {
func (s *AuthService) UpdateJWTToken(c fiber.Ctx) error {
// Get user ID from JWT claims in context (set by auth middleware)
claims, ok := c.Locals("jwt_claims").(*JWTClaims)
if !ok || claims == nil {
return c.Status(fiber.StatusUnauthorized).
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrNotAuthenticated)))
}
var user model.Customer
// Find user by ID
if err := s.db.First(&user, userID).Error; err != nil {
return "", err
if err := s.db.First(&user, claims.UserID).Error; err != nil {
return err
}
// Update user langID if provided
if langID == 0 {
langID = user.LangID
}
_, err := s.GetLangISOCode(langID)
if err != nil {
return "", responseErrors.ErrBadLangID
} else {
user.LangID = langID
// Parse language and country_id from query params
langIDStr := c.Query("lang_id")
var langID uint
if langIDStr != "" {
parsedID, err := strconv.ParseUint(langIDStr, 10, 32)
if err != nil {
return c.Status(fiber.StatusBadRequest).
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrBadLangID)))
}
langID = uint(parsedID)
_, err = s.GetLangISOCode(langID)
if err != nil {
return responseErrors.ErrBadLangID
} else {
user.LangID = langID
}
}
if countryID == 0 {
countryID = user.CountryID
countryIDStr := c.Query("country_id")
var countryID uint
if countryIDStr != "" {
parsedID, err := strconv.ParseUint(countryIDStr, 10, 32)
if err != nil {
return c.Status(fiber.StatusBadRequest).
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, responseErrors.ErrBadCountryID)))
}
countryID = uint(parsedID)
err = s.CheckIfCountryExists(countryID)
if err != nil {
return responseErrors.ErrBadCountryID
} else {
user.CountryID = countryID
}
}
err = s.CheckIfCountryExists(countryID)
// Update choice and get new token using AuthService
newToken, err := s.generateAccessToken(&user)
if err != nil {
return "", responseErrors.ErrBadCountryID
} else {
user.CountryID = countryID
return c.Status(responseErrors.GetErrorStatus(err)).
JSON(response.Make(nullable.GetNil(""), 0, responseErrors.GetErrorCode(c, err)))
}
// Save the updated user
if err := s.db.Save(&user).Error; err != nil {
return "", err
return fmt.Errorf("database error: %w", err)
}
// Generate new JWT token with updated claims
return s.generateAccessToken(&user)
// Set the new JWT cookie
cookie := new(fiber.Cookie)
cookie.Name = "jwt_token"
cookie.Value = newToken
cookie.HTTPOnly = true
cookie.Secure = true
cookie.SameSite = fiber.CookieSameSiteLaxMode
c.Cookie(cookie)
return c.JSON(response.Make(&fiber.Map{"token": newToken}, 0, i18n.T_(c, response.Message_OK)))
}
// generateVerificationToken generates a random verification token

View File

@@ -1,26 +0,0 @@
package jwtService
import (
"git.ma-al.com/goc_daniel/b2b/app/model"
"git.ma-al.com/goc_daniel/b2b/repository/jwtFieldsRepo"
)
// JWTService handles retrieving JWT fields (languages and countries)
type JWTService struct {
repo jwtFieldsRepo.UIJWTFieldsRepo
}
// NewJWTService creates a new JWT service
func New() *JWTService {
return &JWTService{
repo: jwtFieldsRepo.New(),
}
}
func (s *JWTService) GetLanguages() ([]model.Language, error) {
return s.repo.GetLanguages()
}
func (s *JWTService) GetCountriesAndCurrencies() ([]model.Country, error) {
return s.repo.GetCountriesAndCurrencies()
}

View File

@@ -0,0 +1,26 @@
package langsAndCountriesService
import (
"git.ma-al.com/goc_daniel/b2b/app/model"
"git.ma-al.com/goc_daniel/b2b/repository/langsAndCountriesRepo"
)
// LangsAndCountriesService literally sends back language and countries information.
type LangsAndCountriesService struct {
repo langsAndCountriesRepo.UILangsAndCountriesRepo
}
// NewLangsAndCountriesService creates a new LangsAndCountries service
func New() *LangsAndCountriesService {
return &LangsAndCountriesService{
repo: langsAndCountriesRepo.New(),
}
}
func (s *LangsAndCountriesService) GetLanguages() ([]model.Language, error) {
return s.repo.GetLanguages()
}
func (s *LangsAndCountriesService) GetCountriesAndCurrencies() ([]model.Country, error) {
return s.repo.GetCountriesAndCurrencies()
}