package site import ( "context" "fmt" "github.com/gocql/gocql" "go.uber.org/zap" domainsite "codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/internal/domain/site" "codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/pkg/dns" ) // VerifySiteUseCase handles site verification business logic type VerifySiteUseCase struct { repo domainsite.Repository dnsVerifier *dns.Verifier logger *zap.Logger } // ProvideVerifySiteUseCase creates a new VerifySiteUseCase func ProvideVerifySiteUseCase( repo domainsite.Repository, dnsVerifier *dns.Verifier, logger *zap.Logger, ) *VerifySiteUseCase { return &VerifySiteUseCase{ repo: repo, dnsVerifier: dnsVerifier, logger: logger, } } // VerifySiteInput is the input for verifying a site // No input fields needed - verification is done via DNS TXT record lookup type VerifySiteInput struct { // Empty struct - DNS verification uses the token stored in the site entity } // VerifySiteOutput is the output after verifying a site type VerifySiteOutput struct { Success bool `json:"success"` Status string `json:"status"` Message string `json:"message"` } // Execute verifies a site using the verification token func (uc *VerifySiteUseCase) Execute( ctx context.Context, tenantID gocql.UUID, siteID gocql.UUID, input *VerifySiteInput, ) (*VerifySiteOutput, error) { uc.logger.Info("executing verify site use case via DNS", zap.String("tenant_id", tenantID.String()), zap.String("site_id", siteID.String())) // Get site from repository site, err := uc.repo.GetByID(ctx, tenantID, siteID) if err != nil { uc.logger.Error("failed to get site", zap.Error(err)) return nil, domainsite.ErrSiteNotFound } // Check if site is already verified if site.IsVerified { uc.logger.Info("site already verified", zap.String("site_id", siteID.String())) return &VerifySiteOutput{ Success: true, Status: site.Status, Message: "Site is already verified", }, nil } // Test mode sites don't need verification if site.IsTestMode() { uc.logger.Info("test mode site, skipping DNS verification", zap.String("site_id", siteID.String())) site.Verify() if err := uc.repo.Update(ctx, site); err != nil { uc.logger.Error("failed to update site", zap.Error(err)) return nil, fmt.Errorf("failed to update site: %w", err) } return &VerifySiteOutput{ Success: true, Status: site.Status, Message: "Test mode site verified successfully", }, nil } // Perform DNS TXT record verification uc.logger.Info("performing DNS verification", zap.String("site_id", siteID.String()), zap.String("domain", site.Domain), zap.String("expected_token", site.VerificationToken)) verified, err := uc.dnsVerifier.VerifyDomainOwnership(ctx, site.Domain, site.VerificationToken) if err != nil { uc.logger.Error("DNS verification failed", zap.String("site_id", siteID.String()), zap.String("domain", site.Domain), zap.Error(err)) return nil, fmt.Errorf("DNS verification failed: %w", err) } if !verified { uc.logger.Warn("DNS verification record not found", zap.String("site_id", siteID.String()), zap.String("domain", site.Domain)) return nil, fmt.Errorf("DNS TXT record not found. Please add the verification record to your domain's DNS settings") } // DNS verification successful - mark site as verified site.Verify() // Update in repository if err := uc.repo.Update(ctx, site); err != nil { uc.logger.Error("failed to update site", zap.Error(err)) return nil, fmt.Errorf("failed to update site: %w", err) } uc.logger.Info("site verified successfully via DNS", zap.String("site_id", siteID.String()), zap.String("domain", site.Domain)) return &VerifySiteOutput{ Success: true, Status: site.Status, Message: "Domain ownership verified successfully via DNS TXT record", }, nil }