package user import ( "context" "go.uber.org/zap" userusecase "codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/internal/usecase/user" "codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/pkg/logger" ) // CreateUserService handles user creation operations type CreateUserService interface { CreateUser(ctx context.Context, tenantID string, input *userusecase.CreateUserInput) (*userusecase.CreateUserOutput, error) } type createUserService struct { // Focused usecases validateEmailUC *userusecase.ValidateUserEmailUniqueUseCase createEntityUC *userusecase.CreateUserEntityUseCase saveUserToRepoUC *userusecase.SaveUserToRepoUseCase logger *zap.Logger } // NewCreateUserService creates a new CreateUserService func NewCreateUserService( validateEmailUC *userusecase.ValidateUserEmailUniqueUseCase, createEntityUC *userusecase.CreateUserEntityUseCase, saveUserToRepoUC *userusecase.SaveUserToRepoUseCase, logger *zap.Logger, ) CreateUserService { return &createUserService{ validateEmailUC: validateEmailUC, createEntityUC: createEntityUC, saveUserToRepoUC: saveUserToRepoUC, logger: logger.Named("create-user-service"), } } // CreateUser orchestrates the user creation workflow func (s *createUserService) CreateUser(ctx context.Context, tenantID string, input *userusecase.CreateUserInput) (*userusecase.CreateUserOutput, error) { // CWE-532: Use redacted email for logging s.logger.Info("creating user", zap.String("tenant_id", tenantID), logger.EmailHash(input.Email), logger.SafeEmail("email_redacted", input.Email)) // Step 1: Validate email uniqueness (fail fast) if err := s.validateEmailUC.Execute(ctx, tenantID, input.Email); err != nil { // CWE-532: Use redacted email for logging s.logger.Error("email validation failed", logger.EmailHash(input.Email), logger.SafeEmail("email_redacted", input.Email), zap.Error(err)) return nil, err } // Step 2: Create and validate user entity user, err := s.createEntityUC.Execute(tenantID, input) if err != nil { // CWE-532: Use redacted email for logging s.logger.Error("entity creation failed", logger.EmailHash(input.Email), logger.SafeEmail("email_redacted", input.Email), zap.Error(err)) return nil, err } // Step 3: Save user to repository if err := s.saveUserToRepoUC.Execute(ctx, tenantID, user); err != nil { s.logger.Error("failed to save user", zap.String("user_id", user.ID), zap.Error(err)) return nil, err } // CWE-532: Use redacted email for logging s.logger.Info("user created successfully", zap.String("user_id", user.ID), logger.EmailHash(user.Email), logger.SafeEmail("email_redacted", user.Email)) // Step 4: Build output return &userusecase.CreateUserOutput{ ID: user.ID, Email: user.Email, Name: user.Name, CreatedAt: user.CreatedAt, }, nil }