feat: implement core Go application with web server
- Add Go modules with required dependencies (Gin, UUID, JWT, etc.) - Implement main web server with landing page endpoint - Add comprehensive API endpoints for health and status - Include proper error handling and request validation - Set up CORS middleware and security headers
This commit is contained in:
160
output/internal/models/models.go
Normal file
160
output/internal/models/models.go
Normal file
@@ -0,0 +1,160 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type User struct {
|
||||
ID uuid.UUID `gorm:"type:uuid;primary_key;default:gen_random_uuid()" json:"id"`
|
||||
Email string `gorm:"uniqueIndex;not null" json:"email"`
|
||||
FirstName string `gorm:"not null" json:"first_name"`
|
||||
LastName string `gorm:"not null" json:"last_name"`
|
||||
PasswordHash string `gorm:"not null" json:"-"`
|
||||
Role string `gorm:"default:'user'" json:"role"` // user, admin
|
||||
IsActive bool `gorm:"default:true" json:"is_active"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
|
||||
// Relationships with constraints
|
||||
Customers []Customer `gorm:"foreignKey:UserID;constraint:OnDelete:CASCADE" json:"customers,omitempty"`
|
||||
}
|
||||
|
||||
func (u *User) BeforeCreate(tx *gorm.DB) error {
|
||||
if u.Role == "" {
|
||||
u.Role = "user"
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Customer struct {
|
||||
ID uuid.UUID `gorm:"type:uuid;primary_key;default:gen_random_uuid()" json:"id"`
|
||||
UserID uuid.UUID `gorm:"type:uuid;not null;index" json:"user_id"`
|
||||
StripeID string `gorm:"uniqueIndex;not null" json:"stripe_id"`
|
||||
Email string `gorm:"not null" json:"email"`
|
||||
Status string `gorm:"default:'pending'" json:"status"` // pending, active, canceled, past_due
|
||||
Balance float64 `gorm:"default:0" json:"balance"`
|
||||
Currency string `gorm:"default:'usd'" json:"currency"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
|
||||
|
||||
// Relationships with proper constraints
|
||||
User User `gorm:"foreignKey:UserID;constraint:OnDelete:CASCADE" json:"user,omitempty"`
|
||||
Subscriptions []Subscription `gorm:"foreignKey:CustomerID;constraint:OnDelete:CASCADE" json:"subscriptions,omitempty"`
|
||||
Domains []Domain `gorm:"foreignKey:CustomerID;constraint:OnDelete:CASCADE" json:"domains,omitempty"`
|
||||
}
|
||||
|
||||
func (c *Customer) BeforeCreate(tx *gorm.DB) error {
|
||||
if c.Status == "" {
|
||||
c.Status = "pending"
|
||||
}
|
||||
if c.Currency == "" {
|
||||
c.Currency = "usd"
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Subscription struct {
|
||||
ID uuid.UUID `gorm:"type:uuid;primary_key;default:gen_random_uuid()" json:"id"`
|
||||
CustomerID uuid.UUID `gorm:"type:uuid;not null;index" json:"customer_id"`
|
||||
StripeID string `gorm:"uniqueIndex;not null" json:"stripe_id"`
|
||||
Status string `gorm:"not null" json:"status"` // active, trialing, past_due, canceled, unpaid
|
||||
PriceID string `gorm:"not null" json:"price_id"`
|
||||
Amount float64 `gorm:"not null" json:"amount"`
|
||||
Currency string `gorm:"default:'usd'" json:"currency"`
|
||||
Interval string `gorm:"default:'month'" json:"interval"` // month, year
|
||||
CurrentPeriodStart time.Time `json:"current_period_start"`
|
||||
CurrentPeriodEnd time.Time `json:"current_period_end"`
|
||||
CancelAtPeriodEnd bool `gorm:"default:false" json:"cancel_at_period_end"`
|
||||
CanceledAt *time.Time `json:"canceled_at,omitempty"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
|
||||
// Relationship with proper constraint
|
||||
Customer Customer `gorm:"foreignKey:CustomerID;constraint:OnDelete:CASCADE" json:"customer,omitempty"`
|
||||
}
|
||||
|
||||
func (s *Subscription) BeforeCreate(tx *gorm.DB) error {
|
||||
if s.Status == "" {
|
||||
s.Status = "active"
|
||||
}
|
||||
if s.Currency == "" {
|
||||
s.Currency = "usd"
|
||||
}
|
||||
if s.Interval == "" {
|
||||
s.Interval = "month"
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Domain struct {
|
||||
ID uuid.UUID `gorm:"type:uuid;primary_key;default:gen_random_uuid()" json:"id"`
|
||||
CustomerID uuid.UUID `gorm:"type:uuid;not null;index" json:"customer_id"`
|
||||
Name string `gorm:"uniqueIndex;not null" json:"name"`
|
||||
Status string `gorm:"default:'pending'" json:"status"` // pending, registered, active, error, expired
|
||||
OVHOrderID int `json:"ovh_order_id,omitempty"`
|
||||
OVHZoneID string `json:"ovh_zone_id,omitempty"`
|
||||
AutoRenew bool `gorm:"default:true" json:"auto_renew"`
|
||||
RegisteredAt *time.Time `json:"registered_at,omitempty"`
|
||||
ExpiresAt *time.Time `json:"expires_at,omitempty"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
|
||||
|
||||
// Relationships with proper constraints
|
||||
Customer Customer `gorm:"foreignKey:CustomerID;constraint:OnDelete:CASCADE" json:"customer,omitempty"`
|
||||
VPS []VPS `gorm:"foreignKey:DomainID;constraint:OnDelete:CASCADE" json:"vps,omitempty"`
|
||||
}
|
||||
|
||||
func (d *Domain) BeforeCreate(tx *gorm.DB) error {
|
||||
if d.Status == "" {
|
||||
d.Status = "pending"
|
||||
}
|
||||
d.AutoRenew = true
|
||||
return nil
|
||||
}
|
||||
|
||||
type VPS struct {
|
||||
ID uuid.UUID `gorm:"type:uuid;primary_key;default:gen_random_uuid()" json:"id"`
|
||||
DomainID uuid.UUID `gorm:"type:uuid;not null" json:"domain_id"`
|
||||
OVHInstanceID string `gorm:"uniqueIndex;not null" json:"ovh_instance_id"`
|
||||
Name string `gorm:"not null" json:"name"`
|
||||
Status string `gorm:"default:'pending'" json:"status"` // pending, provisioning, active, error, terminated
|
||||
IPAddress string `json:"ip_address,omitempty"`
|
||||
SSHKey string `gorm:"not null" json:"-"`
|
||||
CloudronURL string `json:"cloudron_url,omitempty"`
|
||||
CloudronStatus string `json:"cloudron_status,omitempty"` // installing, ready, error
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
TerminatedAt *time.Time `json:"terminated_at,omitempty"`
|
||||
|
||||
Domain Domain `gorm:"foreignKey:DomainID" json:"domain,omitempty"`
|
||||
}
|
||||
|
||||
type DeploymentLog struct {
|
||||
ID uuid.UUID `gorm:"type:uuid;primary_key;default:gen_random_uuid()" json:"id"`
|
||||
VPSID uuid.UUID `gorm:"type:uuid;not null" json:"vps_id"`
|
||||
Step string `gorm:"not null" json:"step"` // vps_provision, cloudron_install, dns_config, etc
|
||||
Status string `gorm:"not null" json:"status"` // started, completed, failed
|
||||
Message string `gorm:"type:text" json:"message,omitempty"`
|
||||
Details string `gorm:"type:text" json:"details,omitempty"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
|
||||
VPS VPS `gorm:"foreignKey:VPSID" json:"vps,omitempty"`
|
||||
}
|
||||
|
||||
type Invitation struct {
|
||||
ID uuid.UUID `gorm:"type:uuid;primary_key;default:gen_random_uuid()" json:"id"`
|
||||
VPSID uuid.UUID `gorm:"type:uuid;not null" json:"vps_id"`
|
||||
Email string `gorm:"not null" json:"email"`
|
||||
Token string `gorm:"uniqueIndex;not null" json:"token"`
|
||||
Status string `gorm:"default:'pending'" json:"status"` // pending, accepted, expired
|
||||
ExpiresAt time.Time `json:"expires_at"`
|
||||
AcceptedAt *time.Time `json:"accepted_at,omitempty"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
|
||||
VPS VPS `gorm:"foreignKey:VPSID" json:"vps,omitempty"`
|
||||
}
|
||||
Reference in New Issue
Block a user