mirror of
https://github.com/SecurityBrewery/catalyst.git
synced 2025-12-06 15:22:47 +01:00
195 lines
4.5 KiB
Go
195 lines
4.5 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"log/slog"
|
|
"net/http"
|
|
"os"
|
|
"slices"
|
|
"time"
|
|
|
|
"github.com/urfave/cli/v3"
|
|
|
|
"github.com/SecurityBrewery/catalyst/app"
|
|
"github.com/SecurityBrewery/catalyst/app/data"
|
|
"github.com/SecurityBrewery/catalyst/app/database/sqlc"
|
|
"github.com/SecurityBrewery/catalyst/app/settings"
|
|
)
|
|
|
|
func main() {
|
|
cmd := &cli.Command{
|
|
Name: "catalyst",
|
|
Usage: "Catalyst CLI",
|
|
Flags: []cli.Flag{
|
|
&cli.StringFlag{Name: "app-url"},
|
|
&cli.StringSliceFlag{Name: "flags"},
|
|
},
|
|
Commands: []*cli.Command{
|
|
{
|
|
Name: "migrate",
|
|
Action: func(ctx context.Context, command *cli.Command) error {
|
|
_, cleanup, err := setup(ctx, command)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to setup catalyst: %w", err)
|
|
}
|
|
|
|
defer cleanup()
|
|
|
|
return nil
|
|
},
|
|
},
|
|
{
|
|
Name: "serve",
|
|
Usage: "Start the Catalyst server",
|
|
Flags: []cli.Flag{
|
|
&cli.StringFlag{Name: "http", Usage: "HTTP listen address", Value: ":8090"},
|
|
},
|
|
Action: serve,
|
|
},
|
|
{
|
|
Name: "demo-data",
|
|
Aliases: []string{"fake-data"},
|
|
Flags: []cli.Flag{
|
|
&cli.IntFlag{Name: "users", Usage: "Number of fake users to generate", Value: 10},
|
|
&cli.IntFlag{Name: "tickets", Usage: "Number of fake tickets to generate", Value: 100},
|
|
},
|
|
Action: fakeData,
|
|
},
|
|
{
|
|
Name: "upgrade-test-data",
|
|
Aliases: []string{"default-data"},
|
|
Usage: "Generate default data for Catalyst",
|
|
Action: defaultData,
|
|
},
|
|
{
|
|
Name: "admin",
|
|
Commands: []*cli.Command{
|
|
{Name: "create", Action: adminCreate},
|
|
{Name: "delete", Action: adminDelete},
|
|
{Name: "set-password", Action: adminSetPassword},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
ctx := context.Background()
|
|
if err := cmd.Run(ctx, os.Args); err != nil {
|
|
slog.ErrorContext(ctx, "Error running catalyst", "error", err)
|
|
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
|
|
func setup(ctx context.Context, command *cli.Command) (*app.App, func(), error) {
|
|
catalyst, cleanup, err := app.New(ctx, "./catalyst_data")
|
|
if err != nil {
|
|
return nil, nil, fmt.Errorf("failed to initialize catalyst: %w", err)
|
|
}
|
|
|
|
if appURL := command.String("app-url"); appURL != "" {
|
|
_, err := settings.Update(ctx, catalyst.Queries, func(settings *settings.Settings) {
|
|
settings.Meta.AppURL = appURL
|
|
})
|
|
if err != nil {
|
|
return nil, nil, fmt.Errorf("failed to update app URL: %w", err)
|
|
}
|
|
}
|
|
|
|
if err := setFlags(ctx, command.StringSlice("flags"), catalyst.Queries); err != nil {
|
|
return nil, nil, fmt.Errorf("failed to set flags: %w", err)
|
|
}
|
|
|
|
return catalyst, cleanup, nil
|
|
}
|
|
|
|
func serve(ctx context.Context, command *cli.Command) error {
|
|
catalyst, cleanup, err := setup(ctx, command)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to setup catalyst: %w", err)
|
|
}
|
|
|
|
defer cleanup()
|
|
|
|
addr := command.String("http")
|
|
|
|
server := &http.Server{
|
|
Addr: addr,
|
|
Handler: catalyst,
|
|
ReadTimeout: 10 * time.Minute,
|
|
}
|
|
|
|
slog.InfoContext(ctx, "Starting Catalyst server", "address", server.Addr)
|
|
|
|
return server.ListenAndServe()
|
|
}
|
|
|
|
func fakeData(ctx context.Context, command *cli.Command) error {
|
|
catalyst, cleanup, err := setup(ctx, command)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to setup catalyst: %w", err)
|
|
}
|
|
|
|
defer cleanup()
|
|
|
|
if err := data.GenerateDemoData(ctx, catalyst.Queries, command.Int("users"), command.Int("tickets")); err != nil {
|
|
return err
|
|
}
|
|
|
|
slog.InfoContext(ctx, "Fake data generated", "users", command.Int("users"), "tickets", command.Int("tickets"))
|
|
|
|
return nil
|
|
}
|
|
|
|
func defaultData(ctx context.Context, command *cli.Command) error {
|
|
catalyst, cleanup, err := setup(ctx, command)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to setup catalyst: %w", err)
|
|
}
|
|
|
|
defer cleanup()
|
|
|
|
if err := data.GenerateUpgradeTestData(ctx, catalyst.Queries); err != nil {
|
|
return fmt.Errorf("failed to generate default data: %w", err)
|
|
}
|
|
|
|
slog.InfoContext(ctx, "default data generated successfully")
|
|
|
|
return nil
|
|
}
|
|
|
|
func setFlags(ctx context.Context, newFlags []string, queries *sqlc.Queries) error {
|
|
features, err := queries.ListFeatures(ctx, sqlc.ListFeaturesParams{})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var existingFlags []string
|
|
|
|
for _, feature := range features {
|
|
if !slices.Contains(newFlags, feature.Key) {
|
|
if err := queries.DeleteFeature(ctx, feature.Key); err != nil {
|
|
return err
|
|
}
|
|
|
|
slog.InfoContext(ctx, "deleted feature", "name", feature.Key)
|
|
|
|
continue
|
|
}
|
|
|
|
existingFlags = append(existingFlags, feature.Key)
|
|
}
|
|
|
|
for _, flag := range newFlags {
|
|
if slices.Contains(existingFlags, flag) {
|
|
continue
|
|
}
|
|
|
|
if _, err := queries.CreateFeature(ctx, flag); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|