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:
YourDreamNameHere
2025-11-20 16:36:28 -05:00
parent aa93326897
commit 89443f213b
57 changed files with 14404 additions and 0 deletions

View File

@@ -0,0 +1,133 @@
package database
import (
"fmt"
"log"
"github.com/ydn/yourdreamnamehere/internal/models"
"gorm.io/driver/postgres"
"gorm.io/gorm"
"gorm.io/gorm/logger"
)
type Database struct {
DB *gorm.DB
}
func NewDatabase(dsn string, logLevel logger.LogLevel) (*Database, error) {
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{
Logger: logger.Default.LogMode(logLevel),
})
if err != nil {
return nil, fmt.Errorf("failed to connect to database: %w", err)
}
return &Database{DB: db}, nil
}
func (d *Database) Migrate() error {
log.Println("Running database migrations...")
err := d.DB.AutoMigrate(
&models.User{},
&models.Customer{},
&models.Subscription{},
&models.Domain{},
&models.VPS{},
&models.DeploymentLog{},
&models.Invitation{},
)
if err != nil {
return fmt.Errorf("failed to run migrations: %w", err)
}
// Add additional constraints that GORM doesn't handle
if err := d.addConstraints(); err != nil {
return fmt.Errorf("failed to add constraints: %w", err)
}
// Create indexes for performance
if err := d.createIndexes(); err != nil {
return fmt.Errorf("failed to create indexes: %w", err)
}
log.Println("Database migrations completed successfully")
return nil
}
func (d *Database) addConstraints() error {
// Add check constraints
constraints := []string{
"ALTER TABLE users ADD CONSTRAINT check_users_role CHECK (role IN ('user', 'admin'))",
"ALTER TABLE customers ADD CONSTRAINT check_customers_status CHECK (status IN ('pending', 'active', 'canceled', 'past_due'))",
"ALTER TABLE subscriptions ADD CONSTRAINT check_subscriptions_status CHECK (status IN ('active', 'trialing', 'past_due', 'canceled', 'unpaid'))",
"ALTER TABLE subscriptions ADD CONSTRAINT check_subscriptions_interval CHECK (interval IN ('month', 'year'))",
"ALTER TABLE domains ADD CONSTRAINT check_domains_status CHECK (status IN ('pending', 'registered', 'active', 'error', 'expired'))",
"ALTER TABLE vps ADD CONSTRAINT check_vps_status CHECK (status IN ('pending', 'provisioning', 'active', 'error', 'terminated'))",
"ALTER TABLE deployment_logs ADD CONSTRAINT check_deployment_logs_status CHECK (status IN ('started', 'completed', 'failed', 'in_progress'))",
"ALTER TABLE invitations ADD CONSTRAINT check_invitations_status CHECK (status IN ('pending', 'accepted', 'expired'))",
}
for _, constraint := range constraints {
if err := d.DB.Exec(constraint).Error; err != nil {
// Log but don't fail if constraint already exists
log.Printf("Warning: Failed to add constraint (may already exist): %v", err)
}
}
return nil
}
func (d *Database) createIndexes() error {
indexes := []string{
"CREATE INDEX IF NOT EXISTS idx_users_email ON users(email)",
"CREATE INDEX IF NOT EXISTS idx_customers_user_id ON customers(user_id)",
"CREATE INDEX IF NOT EXISTS idx_customers_stripe_id ON customers(stripe_id)",
"CREATE INDEX IF NOT EXISTS idx_customers_status ON customers(status)",
"CREATE INDEX IF NOT EXISTS idx_subscriptions_customer_id ON subscriptions(customer_id)",
"CREATE INDEX IF NOT EXISTS idx_subscriptions_stripe_id ON subscriptions(stripe_id)",
"CREATE INDEX IF NOT EXISTS idx_subscriptions_status ON subscriptions(status)",
"CREATE INDEX IF NOT EXISTS idx_domains_customer_id ON domains(customer_id)",
"CREATE INDEX IF NOT EXISTS idx_domains_name ON domains(name)",
"CREATE INDEX IF NOT EXISTS idx_domains_status ON domains(status)",
"CREATE INDEX IF NOT EXISTS idx_vps_domain_id ON vps(domain_id)",
"CREATE INDEX IF NOT EXISTS idx_vps_ovh_instance_id ON vps(ovh_instance_id)",
"CREATE INDEX IF NOT EXISTS idx_vps_status ON vps(status)",
"CREATE INDEX IF NOT EXISTS idx_deployment_logs_vps_id ON deployment_logs(vps_id)",
"CREATE INDEX IF NOT EXISTS idx_deployment_logs_created_at ON deployment_logs(created_at)",
"CREATE INDEX IF NOT EXISTS idx_invitations_token ON invitations(token)",
"CREATE INDEX IF NOT EXISTS idx_invitations_vps_id ON invitations(vps_id)",
"CREATE INDEX IF NOT EXISTS idx_invitations_expires_at ON invitations(expires_at)",
}
for _, index := range indexes {
if err := d.DB.Exec(index).Error; err != nil {
log.Printf("Warning: Failed to create index (may already exist): %v", err)
}
}
return nil
}
func (d *Database) Close() error {
sqlDB, err := d.DB.DB()
if err != nil {
return fmt.Errorf("failed to get underlying sql.DB: %w", err)
}
return sqlDB.Close()
}
func (d *Database) Health() error {
sqlDB, err := d.DB.DB()
if err != nil {
return fmt.Errorf("failed to get underlying sql.DB: %w", err)
}
if err := sqlDB.Ping(); err != nil {
return fmt.Errorf("failed to ping database: %w", err)
}
return nil
}