2025-08-21 23:47:15 -04:00

116 lines
3.1 KiB
Go

package core
import (
"context"
"encoding/json"
"errors"
"ips-lacpass-backend/internal/users/client"
customErrors "ips-lacpass-backend/pkg/errors"
authMiddleware "ips-lacpass-backend/pkg/middleware"
)
type ServiceInterface interface {
CreateUser(ctx context.Context, ur UserRequest) (*User, error)
UpdateUser(ctx context.Context, ur UserUpdateRequest) (*User, error)
}
type UserService struct {
Client client.ClientInterface
}
func NewService(r client.ClientInterface) UserService {
return UserService{
Client: r,
}
}
func structToMap(obj interface{}) (map[string]interface{}, error) {
data, err := json.Marshal(obj)
if err != nil {
return nil, err
}
var result map[string]interface{}
if err := json.Unmarshal(data, &result); err != nil {
return nil, err
}
return result, nil
}
func (us *UserService) CreateUser(ctx context.Context, ur UserRequest) (*User, error) {
user := &User{
Username: ur.Identifier,
Email: ur.Email,
FirstName: ur.FirstName,
LastName: ur.LastName,
Locale: ur.Locale,
DocumentType: ur.DocumentType,
Identifier: ur.Identifier,
}
// TODO fix this workaround for cyclic dependency issue
userMap, err := structToMap(user)
if err != nil {
return nil, &customErrors.HttpError{
StatusCode: 500,
Body: []map[string]interface{}{{"error": "internal_error", "message": "Failed to convert user to map"}},
Err: err,
}
}
resp, err := us.Client.CreateUser(ctx, userMap, ur.Password)
if err != nil {
var uErr *customErrors.HttpError
if errors.As(err, &uErr) {
return nil, uErr
}
return nil, &customErrors.HttpError{
StatusCode: 502,
Body: []map[string]interface{}{{"error": "auth_service_error", "message": "Failed to connect to authentication service"}}, Err: err,
}
}
user.ID = resp.ID
return user, nil
}
func (us *UserService) UpdateUser(ctx context.Context, ur UserUpdateRequest) (*User, error) {
userUUID, err := authMiddleware.GetUserUUIDFromContext(ctx)
if err != nil {
return nil, &customErrors.HttpError{
StatusCode: 401,
Body: []map[string]interface{}{{"error": "user_uuid_not_found", "message": "User UUID not found in request context"}},
Err: err,
}
}
updateMap, err := structToMap(ur)
if err != nil {
return nil, &customErrors.HttpError{
StatusCode: 500,
Body: []map[string]interface{}{{"error": "internal_error", "message": "Failed to convert update request to map"}},
Err: err,
}
}
resp, err := us.Client.UpdateUser(ctx, userUUID, updateMap)
if err != nil {
var uErr *customErrors.HttpError
if errors.As(err, &uErr) {
return nil, uErr
}
return nil, &customErrors.HttpError{
StatusCode: 502,
Body: []map[string]interface{}{{"error": "auth_service_error", "message": "Failed to connect to authentication service"}}, Err: err,
}
}
return &User{
Username: resp.ID,
Email: resp.Email,
FirstName: resp.FirstName,
LastName: resp.LastName,
Locale: resp.Attributes["locale"][0],
DocumentType: AllowedDocumenTypes[resp.Attributes["document_type"][0]],
Identifier: resp.ID,
}, nil
}