Fix HTMX expired-session handling, CSP-blocked form behaviors, reorder recovery, billing currency display, plan/checkout guards, FedWiki quota edge cases, and operator/member empty/error states. Add entitlement uniqueness migrations, canonical migration source wiring, and regression coverage for the remediated flows. Update status docs with the audit triage and model inventory.
117 lines
3.1 KiB
Go
117 lines
3.1 KiB
Go
package cmd
|
|
|
|
import (
|
|
"context"
|
|
"log/slog"
|
|
|
|
"git.coopcloud.tech/wiki-cafe/member-console/internal/db"
|
|
"git.coopcloud.tech/wiki-cafe/member-console/internal/logging"
|
|
"git.coopcloud.tech/wiki-cafe/member-console/internal/migrate"
|
|
"github.com/spf13/cobra"
|
|
"github.com/spf13/viper"
|
|
)
|
|
|
|
var migrateCmd = &cobra.Command{
|
|
Use: "migrate",
|
|
Short: "Database migration commands",
|
|
Long: "Run database migrations up, down, or check status",
|
|
}
|
|
|
|
var migrateUpCmd = &cobra.Command{
|
|
Use: "up",
|
|
Short: "Run all pending migrations",
|
|
Long: "Apply all pending database migrations",
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
logger := slog.Default()
|
|
if logging.AppLogger != nil {
|
|
logger = logging.AppLogger
|
|
}
|
|
|
|
dbDSN := viper.GetString("db-dsn")
|
|
config := db.DefaultDBConfig(dbDSN)
|
|
database, err := db.ConnectPlain(context.Background(), logger, config)
|
|
if err != nil {
|
|
logger.Error("failed to connect to database", slog.Any("error", err))
|
|
return err
|
|
}
|
|
defer database.Close()
|
|
|
|
if err := db.RunMigrations(database, migrationSources()); err != nil {
|
|
logger.Error("failed to run migrations", slog.Any("error", err))
|
|
return err
|
|
}
|
|
|
|
logger.Info("migrations completed successfully")
|
|
return nil
|
|
},
|
|
}
|
|
|
|
var migrateDownCmd = &cobra.Command{
|
|
Use: "down",
|
|
Short: "Rollback the last migration",
|
|
Long: "Rollback the most recently applied migration",
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
logger := slog.Default()
|
|
if logging.AppLogger != nil {
|
|
logger = logging.AppLogger
|
|
}
|
|
|
|
dbDSN := viper.GetString("db-dsn")
|
|
config := db.DefaultDBConfig(dbDSN)
|
|
database, err := db.ConnectPlain(context.Background(), logger, config)
|
|
if err != nil {
|
|
logger.Error("failed to connect to database", slog.Any("error", err))
|
|
return err
|
|
}
|
|
defer database.Close()
|
|
|
|
if err := db.RollbackMigration(database, migrationSources()); err != nil {
|
|
logger.Error("failed to rollback migration", slog.Any("error", err))
|
|
return err
|
|
}
|
|
|
|
logger.Info("migration rollback completed successfully")
|
|
return nil
|
|
},
|
|
}
|
|
|
|
var migrateStatusCmd = &cobra.Command{
|
|
Use: "status",
|
|
Short: "Show migration status",
|
|
Long: "Display the status of all migrations",
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
logger := slog.Default()
|
|
if logging.AppLogger != nil {
|
|
logger = logging.AppLogger
|
|
}
|
|
|
|
dbDSN := viper.GetString("db-dsn")
|
|
config := db.DefaultDBConfig(dbDSN)
|
|
database, err := db.ConnectPlain(context.Background(), logger, config)
|
|
if err != nil {
|
|
logger.Error("failed to connect to database", slog.Any("error", err))
|
|
return err
|
|
}
|
|
defer database.Close()
|
|
|
|
if err := db.MigrationStatus(database, migrationSources()); err != nil {
|
|
logger.Error("failed to get migration status", slog.Any("error", err))
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
},
|
|
}
|
|
|
|
// migrationSources returns the ordered migration sources for all modules.
|
|
func migrationSources() []db.MigrationSource {
|
|
return migrate.Sources()
|
|
}
|
|
|
|
func init() {
|
|
migrateCmd.AddCommand(migrateUpCmd)
|
|
migrateCmd.AddCommand(migrateDownCmd)
|
|
migrateCmd.AddCommand(migrateStatusCmd)
|
|
rootCmd.AddCommand(migrateCmd)
|
|
}
|