75 lines
2 KiB
Go
75 lines
2 KiB
Go
package tenant
|
|
|
|
import (
|
|
"errors"
|
|
"regexp"
|
|
"time"
|
|
)
|
|
|
|
var (
|
|
ErrNameRequired = errors.New("tenant name is required")
|
|
ErrNameTooShort = errors.New("tenant name must be at least 2 characters")
|
|
ErrNameTooLong = errors.New("tenant name must not exceed 100 characters")
|
|
ErrSlugRequired = errors.New("tenant slug is required")
|
|
ErrSlugInvalid = errors.New("tenant slug must contain only lowercase letters, numbers, and hyphens")
|
|
ErrTenantNotFound = errors.New("tenant not found")
|
|
ErrTenantExists = errors.New("tenant already exists")
|
|
ErrTenantInactive = errors.New("tenant is inactive")
|
|
)
|
|
|
|
// Status represents the tenant's current status
|
|
type Status string
|
|
|
|
const (
|
|
StatusActive Status = "active"
|
|
StatusInactive Status = "inactive"
|
|
StatusSuspended Status = "suspended"
|
|
)
|
|
|
|
// Tenant represents a tenant in the system
|
|
// Each tenant is a separate customer/organization
|
|
type Tenant struct {
|
|
ID string
|
|
Name string // Display name (e.g., "Acme Corporation")
|
|
Slug string // URL-friendly identifier (e.g., "acme-corp")
|
|
Status Status
|
|
CreatedAt time.Time
|
|
UpdatedAt time.Time
|
|
|
|
// CWE-359: IP address tracking for GDPR compliance (90-day expiration)
|
|
CreatedFromIPAddress string // Encrypted IP address
|
|
CreatedFromIPTimestamp time.Time // For 90-day expiration tracking
|
|
ModifiedFromIPAddress string // Encrypted IP address
|
|
ModifiedFromIPTimestamp time.Time // For 90-day expiration tracking
|
|
}
|
|
|
|
var slugRegex = regexp.MustCompile(`^[a-z0-9]+(?:-[a-z0-9]+)*$`)
|
|
|
|
// Validate validates the tenant entity
|
|
func (t *Tenant) Validate() error {
|
|
// Name validation
|
|
if t.Name == "" {
|
|
return ErrNameRequired
|
|
}
|
|
if len(t.Name) < 2 {
|
|
return ErrNameTooShort
|
|
}
|
|
if len(t.Name) > 100 {
|
|
return ErrNameTooLong
|
|
}
|
|
|
|
// Slug validation
|
|
if t.Slug == "" {
|
|
return ErrSlugRequired
|
|
}
|
|
if !slugRegex.MatchString(t.Slug) {
|
|
return ErrSlugInvalid
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// IsActive returns true if the tenant is active
|
|
func (t *Tenant) IsActive() bool {
|
|
return t.Status == StatusActive
|
|
}
|