monorepo/cloud/maplepress-backend/internal/service/tenant/create.go

92 lines
3 KiB
Go

package tenant
import (
"context"
"go.uber.org/zap"
tenantusecase "codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/internal/usecase/tenant"
"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/pkg/logger"
)
// CreateTenantService handles tenant creation operations
type CreateTenantService interface {
CreateTenant(ctx context.Context, input *tenantusecase.CreateTenantInput) (*tenantusecase.CreateTenantOutput, error)
}
type createTenantService struct {
// Focused usecases
validateSlugUC *tenantusecase.ValidateTenantSlugUniqueUseCase
createEntityUC *tenantusecase.CreateTenantEntityUseCase
saveTenantToRepoUC *tenantusecase.SaveTenantToRepoUseCase
logger *zap.Logger
}
// NewCreateTenantService creates a new CreateTenantService
func NewCreateTenantService(
validateSlugUC *tenantusecase.ValidateTenantSlugUniqueUseCase,
createEntityUC *tenantusecase.CreateTenantEntityUseCase,
saveTenantToRepoUC *tenantusecase.SaveTenantToRepoUseCase,
logger *zap.Logger,
) CreateTenantService {
return &createTenantService{
validateSlugUC: validateSlugUC,
createEntityUC: createEntityUC,
saveTenantToRepoUC: saveTenantToRepoUC,
logger: logger.Named("create-tenant-service"),
}
}
// CreateTenant orchestrates the tenant creation workflow
func (s *createTenantService) CreateTenant(ctx context.Context, input *tenantusecase.CreateTenantInput) (*tenantusecase.CreateTenantOutput, error) {
// CWE-532: Use redacted tenant slug for logging
s.logger.Info("creating tenant",
logger.TenantSlugHash(input.Slug),
logger.SafeTenantSlug("tenant_slug_redacted", input.Slug),
zap.String("name", input.Name))
// Step 1: Validate slug uniqueness (fail fast)
if err := s.validateSlugUC.Execute(ctx, input.Slug); err != nil {
// CWE-532: Use redacted tenant slug for logging
s.logger.Error("slug validation failed",
logger.TenantSlugHash(input.Slug),
logger.SafeTenantSlug("tenant_slug_redacted", input.Slug),
zap.Error(err))
return nil, err
}
// Step 2: Create and validate tenant entity
tenant, err := s.createEntityUC.Execute(input)
if err != nil {
// CWE-532: Use redacted tenant slug for logging
s.logger.Error("entity creation failed",
logger.TenantSlugHash(input.Slug),
logger.SafeTenantSlug("tenant_slug_redacted", input.Slug),
zap.Error(err))
return nil, err
}
// Step 3: Save tenant to repository
if err := s.saveTenantToRepoUC.Execute(ctx, tenant); err != nil {
s.logger.Error("failed to save tenant",
zap.String("tenant_id", tenant.ID),
zap.Error(err))
return nil, err
}
// CWE-532: Use redacted tenant slug for logging
s.logger.Info("tenant created successfully",
zap.String("tenant_id", tenant.ID),
logger.TenantSlugHash(tenant.Slug),
logger.SafeTenantSlug("tenant_slug_redacted", tenant.Slug))
// Step 4: Build output
return &tenantusecase.CreateTenantOutput{
ID: tenant.ID,
Name: tenant.Name,
Slug: tenant.Slug,
Status: string(tenant.Status),
CreatedAt: tenant.CreatedAt,
}, nil
}