first commit

This commit is contained in:
orohi
2026-06-17 04:28:17 +03:00
commit 8c21b62a4f
15 changed files with 965 additions and 0 deletions
+18
View File
@@ -0,0 +1,18 @@
package config
import (
"fmt"
"os"
)
type Config struct {
DatabaseURL string
}
func Load() (*Config, error) {
url := os.Getenv("DATABASE_URL")
if url == "" {
return nil, fmt.Errorf("DATABASE_URL is required")
}
return &Config{DatabaseURL: url}, nil
}
+44
View File
@@ -0,0 +1,44 @@
package database
import (
"errors"
"fmt"
"github.com/golang-migrate/migrate/v4"
_ "github.com/golang-migrate/migrate/v4/database/postgres"
_ "github.com/golang-migrate/migrate/v4/source/file"
)
func RunMigrations(databaseURL, migrationsPath string) error {
m, err := migrate.New(
fmt.Sprintf("file://%s", migrationsPath),
databaseURL,
)
if err != nil {
return fmt.Errorf("create migrator: %w", err)
}
defer m.Close()
if err := m.Up(); err != nil && !errors.Is(err, migrate.ErrNoChange) {
return fmt.Errorf("migrate up: %w", err)
}
return nil
}
func RollbackMigrations(databaseURL, migrationsPath string) error {
m, err := migrate.New(
fmt.Sprintf("file://%s", migrationsPath),
databaseURL,
)
if err != nil {
return fmt.Errorf("create migrator: %w", err)
}
defer m.Close()
if err := m.Down(); err != nil && !errors.Is(err, migrate.ErrNoChange) {
return fmt.Errorf("migrate down: %w", err)
}
return nil
}
+34
View File
@@ -0,0 +1,34 @@
package database
import (
"context"
"fmt"
"time"
"github.com/jackc/pgx/v5/pgxpool"
)
func NewPool(ctx context.Context, databaseURL string) (*pgxpool.Pool, error) {
cfg, err := pgxpool.ParseConfig(databaseURL)
if err != nil {
return nil, fmt.Errorf("parse database url: %w", err)
}
cfg.MaxConns = 20
cfg.MinConns = 2
cfg.MaxConnLifetime = time.Hour
cfg.MaxConnIdleTime = 30 * time.Minute
cfg.HealthCheckPeriod = time.Minute
pool, err := pgxpool.NewWithConfig(ctx, cfg)
if err != nil {
return nil, fmt.Errorf("create pool: %w", err)
}
if err := pool.Ping(ctx); err != nil {
pool.Close()
return nil, fmt.Errorf("ping database: %w", err)
}
return pool, nil
}
+146
View File
@@ -0,0 +1,146 @@
package models
import (
"time"
"github.com/google/uuid"
)
type UserStatus string
const (
UserStatusActive UserStatus = "active"
UserStatusSuspended UserStatus = "suspended"
UserStatusPending UserStatus = "pending"
)
type UserRole string
const (
RoleSuperAdmin UserRole = "superadmin"
RoleAdmin UserRole = "admin"
RoleReseller UserRole = "reseller"
RoleUser UserRole = "user"
)
type User struct {
ID int64 `json:"id"`
UUID uuid.UUID `json:"uuid"`
Email string `json:"email"`
Username string `json:"username"`
PasswordHash string `json:"-"`
Role UserRole `json:"role"`
Status UserStatus `json:"status"`
Locale string `json:"locale"`
Timezone string `json:"timezone"`
LastLoginAt *time.Time `json:"last_login_at,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
type ServerStatus string
const (
ServerOnline ServerStatus = "online"
ServerOffline ServerStatus = "offline"
ServerMaintenance ServerStatus = "maintenance"
ServerProvisioning ServerStatus = "provisioning"
)
type Server struct {
ID int64 `json:"id"`
UUID uuid.UUID `json:"uuid"`
Name string `json:"name"`
Hostname string `json:"hostname"`
IPAddress string `json:"ip_address"`
SSHPort int `json:"ssh_port"`
Status ServerStatus `json:"status"`
AgentVersion *string `json:"agent_version,omitempty"`
OSInfo map[string]any `json:"os_info"`
Resources map[string]any `json:"resources"`
Settings map[string]any `json:"settings"`
LastSeenAt *time.Time `json:"last_seen_at,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
type SiteStatus string
const (
SiteActive SiteStatus = "active"
SiteSuspended SiteStatus = "suspended"
SiteCreating SiteStatus = "creating"
SiteDeleting SiteStatus = "deleting"
SiteError SiteStatus = "error"
)
type Site struct {
ID int64 `json:"id"`
UUID uuid.UUID `json:"uuid"`
ServerID int64 `json:"server_id"`
OwnerID int64 `json:"owner_id"`
Name string `json:"name"`
DocumentRoot string `json:"document_root"`
PHPVersion *string `json:"php_version,omitempty"`
Status SiteStatus `json:"status"`
Settings map[string]any `json:"settings"`
DiskQuotaMB *int `json:"disk_quota_mb,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
type Domain struct {
ID int64 `json:"id"`
SiteID int64 `json:"site_id"`
Domain string `json:"domain"`
IsPrimary bool `json:"is_primary"`
SSLEnabled bool `json:"ssl_enabled"`
CreatedAt time.Time `json:"created_at"`
}
type DBEngine string
const (
EngineMySQL DBEngine = "mysql"
EnginePostgreSQL DBEngine = "postgresql"
)
type Database struct {
ID int64 `json:"id"`
UUID uuid.UUID `json:"uuid"`
SiteID int64 `json:"site_id"`
ServerID int64 `json:"server_id"`
Name string `json:"name"`
Engine DBEngine `json:"engine"`
Charset string `json:"charset"`
CreatedAt time.Time `json:"created_at"`
}
type JobStatus string
const (
JobPending JobStatus = "pending"
JobRunning JobStatus = "running"
JobCompleted JobStatus = "completed"
JobFailed JobStatus = "failed"
JobCancelled JobStatus = "cancelled"
)
type Job struct {
ID int64 `json:"id"`
UUID uuid.UUID `json:"uuid"`
ServerID *int64 `json:"server_id,omitempty"`
SiteID *int64 `json:"site_id,omitempty"`
UserID *int64 `json:"user_id,omitempty"`
Type string `json:"type"`
Payload map[string]any `json:"payload"`
Status JobStatus `json:"status"`
Result map[string]any `json:"result,omitempty"`
ErrorMessage *string `json:"error_message,omitempty"`
Attempts int `json:"attempts"`
MaxAttempts int `json:"max_attempts"`
ScheduledAt time.Time `json:"scheduled_at"`
StartedAt *time.Time `json:"started_at,omitempty"`
CompletedAt *time.Time `json:"completed_at,omitempty"`
CreatedAt time.Time `json:"created_at"`
}