fix: google provider auth
This commit is contained in:
@@ -99,5 +99,5 @@ var columnMappingListUsers map[string]string = map[string]string{
|
|||||||
"user_id": "users.id",
|
"user_id": "users.id",
|
||||||
"email": "users.email",
|
"email": "users.email",
|
||||||
"first_name": "users.first_name",
|
"first_name": "users.first_name",
|
||||||
"second_name": "users.second_name",
|
"last_name": "users.last_name",
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,11 @@ import (
|
|||||||
|
|
||||||
type UICustomerRepo interface {
|
type UICustomerRepo interface {
|
||||||
Get(id uint) (*model.Customer, error)
|
Get(id uint) (*model.Customer, error)
|
||||||
|
GetByEmail(email string) (*model.Customer, error)
|
||||||
|
GetByExternalProviderId(provider model.AuthProvider, id string) (*model.Customer, error)
|
||||||
Find(langId uint, p find.Paging, filt *filters.FiltersList) (*find.Found[model.UserInList], error)
|
Find(langId uint, p find.Paging, filt *filters.FiltersList) (*find.Found[model.UserInList], error)
|
||||||
|
Save(customer *model.Customer) error
|
||||||
|
Create(customer *model.Customer) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type CustomerRepo struct{}
|
type CustomerRepo struct{}
|
||||||
@@ -29,6 +33,30 @@ func (repo *CustomerRepo) Get(id uint) (*model.Customer, error) {
|
|||||||
return &customer, err
|
return &customer, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (repo *CustomerRepo) GetByEmail(email string) (*model.Customer, error) {
|
||||||
|
var customer model.Customer
|
||||||
|
|
||||||
|
err := db.DB.
|
||||||
|
Preload("Role.Permissions").
|
||||||
|
Where("email = ?", email).
|
||||||
|
First(&customer).
|
||||||
|
Error
|
||||||
|
|
||||||
|
return &customer, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (repo *CustomerRepo) GetByExternalProviderId(provider model.AuthProvider, id string) (*model.Customer, error) {
|
||||||
|
var customer model.Customer
|
||||||
|
|
||||||
|
err := db.DB.
|
||||||
|
Preload("Role.Permissions").
|
||||||
|
Where("provider = ? AND provider_id = ?", provider, id).
|
||||||
|
First(&customer).
|
||||||
|
Error
|
||||||
|
|
||||||
|
return &customer, err
|
||||||
|
}
|
||||||
|
|
||||||
func (repo *CustomerRepo) Find(langId uint, p find.Paging, filt *filters.FiltersList) (*find.Found[model.UserInList], error) {
|
func (repo *CustomerRepo) Find(langId uint, p find.Paging, filt *filters.FiltersList) (*find.Found[model.UserInList], error) {
|
||||||
found, err := find.Paginate[model.UserInList](langId, p, db.DB.
|
found, err := find.Paginate[model.UserInList](langId, p, db.DB.
|
||||||
Table("b2b_customers AS users").
|
Table("b2b_customers AS users").
|
||||||
@@ -44,6 +72,59 @@ func (repo *CustomerRepo) Find(langId uint, p find.Paging, filt *filters.Filters
|
|||||||
return &found, err
|
return &found, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (repo *CustomerRepo) Save(customer *model.Customer) error {
|
||||||
|
return db.DB.Save(customer).Error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (repo *CustomerRepo) Create(customer *model.Customer) error {
|
||||||
|
return db.DB.Create(customer).Error
|
||||||
|
}
|
||||||
|
|
||||||
|
// func (repo *CustomerRepo) Search(
|
||||||
|
// customerId uint,
|
||||||
|
// partnerCode string,
|
||||||
|
// p find.Paging,
|
||||||
|
// filt *filters.FiltersList,
|
||||||
|
// search string,
|
||||||
|
// ) (found find.Found[model.UserInList], err error) {
|
||||||
|
// words := strings.Fields(search)
|
||||||
|
// if len(words) > 5 {
|
||||||
|
// words = words[:5]
|
||||||
|
// }
|
||||||
|
|
||||||
|
// query := ctx.DB().
|
||||||
|
// Model(&model.Customer{}).
|
||||||
|
// Select("customer.id AS id, customer.first_name as first_name, customer.last_name as last_name, customer.phone_number AS phone_number, customer.email AS email, count(distinct investment_plan_contract.id) as iiplan_purchases, count(distinct `order`.id) as single_purchases, entity.name as entity_name").
|
||||||
|
// Where("customer.id <> ?", customerId).
|
||||||
|
// Where("(customer.id IN (SELECT id FROM customer WHERE partner_code IN (WITH RECURSIVE partners AS (SELECT code AS dst FROM partner WHERE code = ? UNION SELECT code FROM partner JOIN partners ON partners.dst = partner.superior_code) SELECT dst FROM partners)) OR customer.recommender_code = ?)", partnerCode, partnerCode).
|
||||||
|
// Scopes(view.CustomerListQuery())
|
||||||
|
|
||||||
|
// var conditions []string
|
||||||
|
// var args []interface{}
|
||||||
|
// for _, word := range words {
|
||||||
|
|
||||||
|
// conditions = append(conditions, `
|
||||||
|
// (LOWER(first_name) LIKE ? OR
|
||||||
|
// LOWER(last_name) LIKE ? OR
|
||||||
|
// phone_number LIKE ? OR
|
||||||
|
// LOWER(email) LIKE ?)
|
||||||
|
// `)
|
||||||
|
|
||||||
|
// for i := 0; i < 4; i++ {
|
||||||
|
// args = append(args, "%"+strings.ToLower(word)+"%")
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// finalQuery := strings.Join(conditions, " AND ")
|
||||||
|
|
||||||
|
// query = query.Where(finalQuery, args...).
|
||||||
|
// Scopes(filt.All()...)
|
||||||
|
|
||||||
|
// found, err = find.Paginate[V](ctx, p, query)
|
||||||
|
|
||||||
|
// return found, errs.Recorded(span, err)
|
||||||
|
// }
|
||||||
|
|
||||||
// func (repo *ListRepo) ListUsers(id_lang uint, p find.Paging, filt *filters.FiltersList) (find.Found[model.UserInList], error) {
|
// func (repo *ListRepo) ListUsers(id_lang uint, p find.Paging, filt *filters.FiltersList) (find.Found[model.UserInList], error) {
|
||||||
// var list []model.UserInList
|
// var list []model.UserInList
|
||||||
// var total int64
|
// var total int64
|
||||||
|
|||||||
22
app/repos/rolesRepo/rolesRepo.go
Normal file
22
app/repos/rolesRepo/rolesRepo.go
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
package roleRepo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/db"
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
type UIRolesRepo interface {
|
||||||
|
Get(id uint) (*model.Role, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type RolesRepo struct{}
|
||||||
|
|
||||||
|
func New() UIRolesRepo {
|
||||||
|
return &RolesRepo{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RolesRepo) Get(id uint) (*model.Role, error) {
|
||||||
|
var role model.Role
|
||||||
|
err := db.DB.First(&role, id).Error
|
||||||
|
return &role, err
|
||||||
|
}
|
||||||
@@ -11,6 +11,8 @@ import (
|
|||||||
"git.ma-al.com/goc_daniel/b2b/app/config"
|
"git.ma-al.com/goc_daniel/b2b/app/config"
|
||||||
"git.ma-al.com/goc_daniel/b2b/app/db"
|
"git.ma-al.com/goc_daniel/b2b/app/db"
|
||||||
"git.ma-al.com/goc_daniel/b2b/app/model"
|
"git.ma-al.com/goc_daniel/b2b/app/model"
|
||||||
|
"git.ma-al.com/goc_daniel/b2b/app/repos/customerRepo"
|
||||||
|
roleRepo "git.ma-al.com/goc_daniel/b2b/app/repos/rolesRepo"
|
||||||
"git.ma-al.com/goc_daniel/b2b/app/service/emailService"
|
"git.ma-al.com/goc_daniel/b2b/app/service/emailService"
|
||||||
constdata "git.ma-al.com/goc_daniel/b2b/app/utils/const_data"
|
constdata "git.ma-al.com/goc_daniel/b2b/app/utils/const_data"
|
||||||
"git.ma-al.com/goc_daniel/b2b/app/utils/responseErrors"
|
"git.ma-al.com/goc_daniel/b2b/app/utils/responseErrors"
|
||||||
@@ -38,6 +40,8 @@ type AuthService struct {
|
|||||||
db *gorm.DB
|
db *gorm.DB
|
||||||
config *config.AuthConfig
|
config *config.AuthConfig
|
||||||
email *emailService.EmailService
|
email *emailService.EmailService
|
||||||
|
customerRepo customerRepo.UICustomerRepo
|
||||||
|
roleRepo roleRepo.UIRolesRepo
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewAuthService creates a new AuthService instance
|
// NewAuthService creates a new AuthService instance
|
||||||
@@ -46,6 +50,8 @@ func NewAuthService() *AuthService {
|
|||||||
db: db.Get(),
|
db: db.Get(),
|
||||||
config: &config.Get().Auth,
|
config: &config.Get().Auth,
|
||||||
email: emailService.NewEmailService(),
|
email: emailService.NewEmailService(),
|
||||||
|
customerRepo: customerRepo.New(),
|
||||||
|
roleRepo: roleRepo.New(),
|
||||||
}
|
}
|
||||||
// Auto-migrate the refresh_tokens table
|
// Auto-migrate the refresh_tokens table
|
||||||
if svc.db != nil {
|
if svc.db != nil {
|
||||||
|
|||||||
@@ -108,26 +108,32 @@ func (s *AuthService) HandleGoogleCallback(code string) (*model.AuthResponse, st
|
|||||||
// findOrCreateGoogleUser finds an existing user by Google provider ID or email,
|
// findOrCreateGoogleUser finds an existing user by Google provider ID or email,
|
||||||
// or creates a new one.
|
// or creates a new one.
|
||||||
func (s *AuthService) findOrCreateGoogleUser(info *view.GoogleUserInfo) (*model.Customer, error) {
|
func (s *AuthService) findOrCreateGoogleUser(info *view.GoogleUserInfo) (*model.Customer, error) {
|
||||||
var user model.Customer
|
var user *model.Customer
|
||||||
|
|
||||||
// Try to find by provider + provider_id
|
// Try to find by provider + provider_id
|
||||||
err := s.db.Where("provider = ? AND provider_id = ?", model.ProviderGoogle, info.ID).First(&user).Error
|
user, err := s.customerRepo.GetByExternalProviderId(model.ProviderGoogle, info.ID)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
// Update avatar in case it changed
|
// Update avatar in case it changed
|
||||||
user.AvatarURL = info.Picture
|
user.AvatarURL = info.Picture
|
||||||
s.db.Save(&user)
|
err = s.customerRepo.Save(user)
|
||||||
return &user, nil
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return user, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to find by email (user may have registered locally before)
|
// Try to find by email (user may have registered locally before)
|
||||||
err = s.db.Where("email = ?", info.Email).First(&user).Error
|
user, err = s.customerRepo.GetByEmail(info.Email)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
// Link Google provider to existing account
|
// Link Google provider to existing account
|
||||||
user.Provider = model.ProviderGoogle
|
user.Provider = model.ProviderGoogle
|
||||||
user.ProviderID = info.ID
|
user.ProviderID = info.ID
|
||||||
user.AvatarURL = info.Picture
|
user.AvatarURL = info.Picture
|
||||||
user.IsActive = true
|
user.IsActive = true
|
||||||
s.db.Save(&user)
|
err = s.customerRepo.Save(user)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
// If email has not been verified yet, send email to admin.
|
// If email has not been verified yet, send email to admin.
|
||||||
if !user.EmailVerified {
|
if !user.EmailVerified {
|
||||||
@@ -139,7 +145,7 @@ func (s *AuthService) findOrCreateGoogleUser(info *view.GoogleUserInfo) (*model.
|
|||||||
}
|
}
|
||||||
user.EmailVerified = true
|
user.EmailVerified = true
|
||||||
|
|
||||||
return &user, nil
|
return user, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create new user
|
// Create new user
|
||||||
@@ -148,6 +154,7 @@ func (s *AuthService) findOrCreateGoogleUser(info *view.GoogleUserInfo) (*model.
|
|||||||
FirstName: info.GivenName,
|
FirstName: info.GivenName,
|
||||||
LastName: info.FamilyName,
|
LastName: info.FamilyName,
|
||||||
Provider: model.ProviderGoogle,
|
Provider: model.ProviderGoogle,
|
||||||
|
RoleID: 1, // user
|
||||||
ProviderID: info.ID,
|
ProviderID: info.ID,
|
||||||
AvatarURL: info.Picture,
|
AvatarURL: info.Picture,
|
||||||
IsActive: true,
|
IsActive: true,
|
||||||
@@ -156,7 +163,7 @@ func (s *AuthService) findOrCreateGoogleUser(info *view.GoogleUserInfo) (*model.
|
|||||||
CountryID: 2, // default is England
|
CountryID: 2, // default is England
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.db.Create(&newUser).Error; err != nil {
|
if err := s.customerRepo.Create(&newUser); err != nil {
|
||||||
return nil, fmt.Errorf("failed to create user: %w", err)
|
return nil, fmt.Errorf("failed to create user: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,6 +176,13 @@ func (s *AuthService) findOrCreateGoogleUser(info *view.GoogleUserInfo) (*model.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var role *model.Role
|
||||||
|
role, err = s.roleRepo.Get(newUser.RoleID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
newUser.Role = role
|
||||||
|
|
||||||
return &newUser, nil
|
return &newUser, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user