site

package
v0.0.0-...-991afdd Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 2, 2025 License: AGPL-3.0 Imports: 4 Imported by: 0

Documentation

Overview

File Path: monorepo/cloud/maplepress-backend/internal/domain/site/site.go

Index

Constants

View Source
const (
	StatusPending   = "pending"   // Site created, awaiting verification
	StatusActive    = "active"    // Site verified and operational
	StatusInactive  = "inactive"  // User temporarily disabled
	StatusSuspended = "suspended" // Suspended due to violation or non-payment
	StatusArchived  = "archived"  // Soft deleted
)

Status constants

Variables

View Source
var (
	// ErrNotFound is returned when a site is not found
	ErrNotFound = errors.New("site not found")

	// ErrSiteNotFound is an alias for ErrNotFound
	ErrSiteNotFound = ErrNotFound

	// ErrDomainAlreadyExists is returned when trying to create a site with a domain that already exists
	ErrDomainAlreadyExists = errors.New("domain already exists")

	// ErrInvalidAPIKey is returned when API key authentication fails
	ErrInvalidAPIKey = errors.New("invalid API key")

	// ErrSiteNotActive is returned when trying to perform operations on an inactive site
	ErrSiteNotActive = errors.New("site is not active")

	// ErrSiteNotVerified is returned when trying to perform operations on an unverified site
	ErrSiteNotVerified = errors.New("site is not verified")

	// ErrQuotaExceeded is returned when a quota limit is reached
	ErrQuotaExceeded = errors.New("quota exceeded")

	// ErrStorageQuotaExceeded is returned when storage quota is exceeded
	ErrStorageQuotaExceeded = errors.New("storage quota exceeded")

	// ErrSearchQuotaExceeded is returned when search quota is exceeded
	ErrSearchQuotaExceeded = errors.New("search quota exceeded")

	// ErrIndexingQuotaExceeded is returned when indexing quota is exceeded
	ErrIndexingQuotaExceeded = errors.New("indexing quota exceeded")
)

Functions

This section is empty.

Types

type Repository

type Repository interface {
	// Create inserts a new site into all Cassandra tables
	Create(ctx context.Context, site *Site) error

	// GetByID retrieves a site by tenant_id and site_id
	GetByID(ctx context.Context, tenantID, siteID gocql.UUID) (*Site, error)

	// GetByDomain retrieves a site by domain name
	GetByDomain(ctx context.Context, domain string) (*Site, error)

	// GetByAPIKeyHash retrieves a site by API key hash (for authentication)
	GetByAPIKeyHash(ctx context.Context, apiKeyHash string) (*Site, error)

	// ListByTenant retrieves all sites for a tenant (paginated)
	ListByTenant(ctx context.Context, tenantID gocql.UUID, pageSize int, pageState []byte) ([]*Site, []byte, error)

	// Update updates a site in all Cassandra tables
	Update(ctx context.Context, site *Site) error

	// UpdateAPIKey updates the API key for a site (handles sites_by_apikey table correctly)
	// Must provide both old and new API key hashes to properly delete old entry and insert new one
	UpdateAPIKey(ctx context.Context, site *Site, oldAPIKeyHash string) error

	// Delete removes a site from all Cassandra tables
	Delete(ctx context.Context, tenantID, siteID gocql.UUID) error

	// DomainExists checks if a domain is already registered
	DomainExists(ctx context.Context, domain string) (bool, error)

	// UpdateUsage updates only usage tracking fields (optimized for frequent updates)
	UpdateUsage(ctx context.Context, site *Site) error

	// GetAllSitesForUsageReset retrieves all sites for monthly usage counter reset
	// This uses ALLOW FILTERING and should only be used for administrative tasks
	GetAllSitesForUsageReset(ctx context.Context, pageSize int, pageState []byte) ([]*Site, []byte, error)
}

Repository defines the interface for site data access

type Site

type Site struct {
	// Core Identity
	ID       gocql.UUID `json:"id"`
	TenantID gocql.UUID `json:"tenant_id"`

	// Site Information
	SiteURL string `json:"site_url"` // Full URL: https://example.com
	Domain  string `json:"domain"`   // Extracted: example.com

	// Authentication
	APIKeyHash     string `json:"-"`                 // SHA-256 hash, never exposed in JSON
	APIKeyPrefix   string `json:"api_key_prefix"`    // "live_sk_a1b2" for display
	APIKeyLastFour string `json:"api_key_last_four"` // Last 4 chars for display

	// Status & Verification
	Status            string `json:"status"` // active, inactive, pending, suspended, archived
	IsVerified        bool   `json:"is_verified"`
	VerificationToken string `json:"-"` // Never exposed

	// Search & Indexing
	SearchIndexName   string    `json:"search_index_name"`
	TotalPagesIndexed int64     `json:"total_pages_indexed"` // All-time total for stats
	LastIndexedAt     time.Time `json:"last_indexed_at,omitempty"`

	// Plugin Info
	PluginVersion string `json:"plugin_version,omitempty"`

	// Usage Tracking (for billing) - no quotas/limits
	StorageUsedBytes    int64     `json:"storage_used_bytes"`    // Current storage usage
	SearchRequestsCount int64     `json:"search_requests_count"` // Monthly search count
	MonthlyPagesIndexed int64     `json:"monthly_pages_indexed"` // Monthly indexing count
	LastResetAt         time.Time `json:"last_reset_at"`         // Last monthly reset

	// Metadata (optional fields)
	Language string `json:"language,omitempty"` // ISO 639-1
	Timezone string `json:"timezone,omitempty"` // IANA timezone
	Notes    string `json:"notes,omitempty"`

	// Audit
	CreatedAt time.Time `json:"created_at"`
	UpdatedAt time.Time `json:"updated_at"`

	// CWE-359: IP address tracking for GDPR compliance (90-day expiration)
	CreatedFromIPAddress    string    `json:"-"` // Encrypted IP address, never exposed in JSON
	CreatedFromIPTimestamp  time.Time `json:"-"` // For 90-day expiration tracking
	ModifiedFromIPAddress   string    `json:"-"` // Encrypted IP address, never exposed in JSON
	ModifiedFromIPTimestamp time.Time `json:"-"` // For 90-day expiration tracking
}

Site represents a WordPress site registered in the system

func NewSite

func NewSite(tenantID gocql.UUID, domain, siteURL string, apiKeyHash, apiKeyPrefix, apiKeyLastFour string, encryptedIP string) *Site

NewSite creates a new Site entity with defaults

func (*Site) CanAccessAPI

func (s *Site) CanAccessAPI() bool

CanAccessAPI checks if the site can access the API More lenient than IsActive - allows pending sites for initial setup

func (*Site) IncrementMonthlyPageCount

func (s *Site) IncrementMonthlyPageCount(count int64)

IncrementMonthlyPageCount increments both lifetime and monthly page counters

func (*Site) IncrementPageCount

func (s *Site) IncrementPageCount()

IncrementPageCount increments the indexed page counter (lifetime total)

func (*Site) IncrementSearchCount

func (s *Site) IncrementSearchCount()

IncrementSearchCount increments the search request counter

func (*Site) IsActive

func (s *Site) IsActive() bool

IsActive checks if the site is active and verified

func (*Site) IsTestMode

func (s *Site) IsTestMode() bool

IsTestMode checks if the site is using a test API key

func (*Site) RequiresVerification

func (s *Site) RequiresVerification() bool

RequiresVerification checks if the site requires verification Test mode sites skip verification for development

func (*Site) ResetMonthlyUsage

func (s *Site) ResetMonthlyUsage()

ResetMonthlyUsage resets monthly usage counters for billing cycles

func (*Site) UpdateStorageUsed

func (s *Site) UpdateStorageUsed(bytes int64)

UpdateStorageUsed updates the storage usage

func (*Site) Verify

func (s *Site) Verify()

Verify marks the site as verified

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL