diff --git a/Readme.md b/Readme.md index f97184f..e6833e5 100644 --- a/Readme.md +++ b/Readme.md @@ -18,10 +18,10 @@ Run your own AIM chat server, managing users and groups. Hook up a vintage clien ## Getting Started -Clone this repository, make sure you have [Go](https://go.dev/) installed in your terminal's path, then run: +Clone this repository and make sure you have [Go](https://go.dev/) installed in your terminal's path. Copy `env/example.dev.env` to `env/dev.env` and configure your database settings. `OSCAR_BOS_HOST` should be configured to your host's IP or address. In the example dev env it asks macOS what the host's address is but this should be changed if you're on Linux. Then you can run the `run.sh` script to get started. ``` -$ go build && ./aim-oscar +$ ./run.sh ``` ### Configuration diff --git a/cmd/.DS_Store b/cmd/.DS_Store deleted file mode 100644 index 3d01f9e..0000000 Binary files a/cmd/.DS_Store and /dev/null differ diff --git a/cmd/bun/main.go b/cmd/bun/main.go deleted file mode 100644 index c377dd9..0000000 --- a/cmd/bun/main.go +++ /dev/null @@ -1,235 +0,0 @@ -package main - -import ( - "fmt" - "log" - "os" - "strings" - - "github.com/go-bun/bun-starter-kit/bunapp" - "github.com/go-bun/bun-starter-kit/cmd/bun/migrations" - "github.com/go-bun/bun/migrate" - - cli "github.com/urfave/cli/v2" -) - -func main() { - app := &cli.App{ - Name: "bun", - Flags: []cli.Flag{ - &cli.StringFlag{ - Name: "env", - Value: "dev", - Usage: "environment", - }, - }, - Commands: []*cli.Command{ - newDBCommand(migrations.Migrations), - }, - } - if err := app.Run(os.Args); err != nil { - log.Fatal(err) - } -} -func newDBCommand(migrations *migrate.Migrations) *cli.Command { - return &cli.Command{ - Name: "db", - Usage: "manage database migrations", - Subcommands: []*cli.Command{ - { - Name: "init", - Usage: "create migration tables", - Action: func(c *cli.Context) error { - ctx, app, err := bunapp.StartCLI(c) - if err != nil { - return err - } - defer app.Stop() - - migrator := migrate.NewMigrator(app.DB(), migrations) - return migrator.Init(ctx) - }, - }, - { - Name: "migrate", - Usage: "migrate database", - Action: func(c *cli.Context) error { - ctx, app, err := bunapp.StartCLI(c) - if err != nil { - return err - } - defer app.Stop() - - migrator := migrate.NewMigrator(app.DB(), migrations) - - group, err := migrator.Migrate(ctx) - if err != nil { - return err - } - - if group.ID == 0 { - fmt.Printf("there are no new migrations to run\n") - return nil - } - - fmt.Printf("migrated to %s\n", group) - return nil - }, - }, - { - Name: "rollback", - Usage: "rollback the last migration group", - Action: func(c *cli.Context) error { - ctx, app, err := bunapp.StartCLI(c) - if err != nil { - return err - } - defer app.Stop() - - migrator := migrate.NewMigrator(app.DB(), migrations) - - group, err := migrator.Rollback(ctx) - if err != nil { - return err - } - - if group.ID == 0 { - fmt.Printf("there are no groups to roll back\n") - return nil - } - - fmt.Printf("rolled back %s\n", group) - return nil - }, - }, - { - Name: "lock", - Usage: "lock migrations", - Action: func(c *cli.Context) error { - ctx, app, err := bunapp.StartCLI(c) - if err != nil { - return err - } - defer app.Stop() - - migrator := migrate.NewMigrator(app.DB(), migrations) - return migrator.Lock(ctx) - }, - }, - { - Name: "unlock", - Usage: "unlock migrations", - Action: func(c *cli.Context) error { - ctx, app, err := bunapp.StartCLI(c) - if err != nil { - return err - } - defer app.Stop() - - migrator := migrate.NewMigrator(app.DB(), migrations) - return migrator.Unlock(ctx) - }, - }, - { - Name: "create_go", - Usage: "create Go migration", - Action: func(c *cli.Context) error { - ctx, app, err := bunapp.StartCLI(c) - if err != nil { - return err - } - defer app.Stop() - - migrator := migrate.NewMigrator(app.DB(), migrations) - - name := strings.Join(c.Args().Slice(), "_") - mf, err := migrator.CreateGoMigration(ctx, name) - if err != nil { - return err - } - fmt.Printf("created migration %s (%s)\n", mf.Name, mf.Path) - - return nil - }, - }, - { - Name: "create_sql", - Usage: "create up and down SQL migrations", - Action: func(c *cli.Context) error { - ctx, app, err := bunapp.StartCLI(c) - if err != nil { - return err - } - defer app.Stop() - - migrator := migrate.NewMigrator(app.DB(), migrations) - - name := strings.Join(c.Args().Slice(), "_") - files, err := migrator.CreateSQLMigrations(ctx, name) - if err != nil { - return err - } - - for _, mf := range files { - fmt.Printf("created migration %s (%s)\n", mf.Name, mf.Path) - } - - return nil - }, - }, - { - Name: "status", - Usage: "print migrations status", - Action: func(c *cli.Context) error { - ctx, app, err := bunapp.StartCLI(c) - if err != nil { - return err - } - defer app.Stop() - - migrator := migrate.NewMigrator(app.DB(), migrations) - - ms, err := migrator.MigrationsWithStatus(ctx) - if err != nil { - return err - } - fmt.Printf("migrations: %s\n", ms) - fmt.Printf("unapplied migrations: %s\n", ms.Unapplied()) - fmt.Printf("last migration group: %s\n", ms.LastGroup()) - - return nil - }, - }, - { - Name: "mark_applied", - Usage: "mark migrations as applied without actually running them", - Action: func(c *cli.Context) error { - ctx, app, err := bunapp.StartCLI(c) - if err != nil { - return err - } - defer app.Stop() - - migrator := migrate.NewMigrator(app.DB(), migrations) - - group, err := migrator.Migrate(ctx, migrate.WithNopMigration()) - if err != nil { - return err - } - - if group.ID == 0 { - fmt.Printf("there are no new migrations to mark as applied\n") - return nil - } - - fmt.Printf("marked as applied %s\n", group) - return nil - }, - }, - }, - } -} - -func isServerClosed(err error) bool { - return err.Error() == "http: Server closed" -} diff --git a/cmd/bun/migrations/20210505110026_init.go b/cmd/bun/migrations/20210505110026_init.go deleted file mode 100644 index 26b0d18..0000000 --- a/cmd/bun/migrations/20210505110026_init.go +++ /dev/null @@ -1,19 +0,0 @@ -package migrations - -import ( - "aim-oscar/models" - "context" - "os" - - "github.com/uptrace/bun" - "github.com/uptrace/bun/dbfixture" -) - -func init() { - Migrations.MustRegister(func(ctx context.Context, db *bun.DB) error { - db.RegisterModel((*models.User)(nil), (*models.Message)(nil), (*models.Buddy)(nil), (*models.EmailVerification)(nil)) - - fixture := dbfixture.New(db, dbfixture.WithRecreateTables()) - return fixture.Load(context.Background(), os.DirFS("./"), "init_fixtures.yml") - }, nil) -} diff --git a/cmd/migrate/main.go b/cmd/migrate/main.go new file mode 100644 index 0000000..71aae6e --- /dev/null +++ b/cmd/migrate/main.go @@ -0,0 +1,118 @@ +package main + +import ( + "aim-oscar/cmd/migrate/migrations" + "context" + "crypto/tls" + "database/sql" + "fmt" + "log" + "os" + "strings" + "time" + + "github.com/uptrace/bun" + "github.com/uptrace/bun/dialect/pgdialect" + "github.com/uptrace/bun/driver/pgdriver" + "github.com/uptrace/bun/migrate" +) + +var ( + DB_URL = "" + DB_USER = "" + DB_PASSWORD = "" +) + +func init() { + if dbUrl, ok := os.LookupEnv("DB_URL"); ok { + DB_URL = strings.TrimSpace(dbUrl) + } + + if dbUser, ok := os.LookupEnv("DB_USER"); ok { + DB_USER = strings.TrimSpace(dbUser) + } + + if dbPassword, ok := os.LookupEnv("DB_PASSWORD"); ok { + DB_PASSWORD = strings.TrimSpace(dbPassword) + } + + if len(os.Args) != 2 { + log.Fatalf("Usage: %s ", os.Args[0]) + } +} + +func main() { + pgconn := pgdriver.NewConnector( + pgdriver.WithNetwork("tcp"), + pgdriver.WithAddr(DB_URL), + pgdriver.WithTLSConfig(&tls.Config{InsecureSkipVerify: true}), + pgdriver.WithUser(DB_USER), + pgdriver.WithPassword(DB_PASSWORD), + pgdriver.WithDatabase("postgres"), + pgdriver.WithInsecure(true), + pgdriver.WithTimeout(5*time.Second), + pgdriver.WithDialTimeout(5*time.Second), + pgdriver.WithReadTimeout(5*time.Second), + pgdriver.WithWriteTimeout(5*time.Second), + ) + + // Set up the DB + sqldb := sql.OpenDB(pgconn) + db := bun.NewDB(sqldb, pgdialect.New()) + db.SetConnMaxIdleTime(15 * time.Second) + db.SetConnMaxLifetime(1 * time.Minute) + + ctx := context.Background() + cmd := os.Args[1] + migrator := migrate.NewMigrator(db, migrations.Migrations) + + if cmd == "init" { + if err := migrator.Init(ctx); err != nil { + panic(err) + } + } else if cmd == "up" { + group, err := migrator.Migrate(context.Background()) + if err != nil { + panic(err) + } + + if group.ID == 0 { + fmt.Printf("there are no new migrations to run\n") + return + } + + fmt.Printf("migrated to %s\n", group) + } else if cmd == "down" { + group, err := migrator.Rollback(ctx) + if err != nil { + panic(err) + } + + if group.ID == 0 { + fmt.Printf("there are no groups to roll back\n") + return + } + + fmt.Printf("rolled back %s\n", group) + } else if cmd == "status" { + ms, err := migrator.MigrationsWithStatus(ctx) + if err != nil { + panic(err) + } + fmt.Printf("migrations: %s\n", ms) + fmt.Printf("unapplied migrations: %s\n", ms.Unapplied()) + fmt.Printf("last migration group: %s\n", ms.LastGroup()) + } else if cmd == "mark_applied" { + group, err := migrator.Migrate(ctx, migrate.WithNopMigration()) + if err != nil { + panic(err) + } + + if group.ID == 0 { + fmt.Printf("there are no new migrations to mark as applied\n") + return + } + + fmt.Printf("marked as applied %s\n", group) + } +} diff --git a/cmd/bun/migrations/init_fixtures.yml b/cmd/migrate/migrations/20210505110026_fixtures.yml similarity index 90% rename from cmd/bun/migrations/init_fixtures.yml rename to cmd/migrate/migrations/20210505110026_fixtures.yml index f4f5192..b5747d5 100644 --- a/cmd/bun/migrations/init_fixtures.yml +++ b/cmd/migrate/migrations/20210505110026_fixtures.yml @@ -1,11 +1,11 @@ - model: User rows: - - uin: 10000 + - uin: 1 screen_name: toof password: bar email: toof@example.com verified: true - - uin: 10001 + - uin: 2 screen_name: artem password: bar email: artem@example.com diff --git a/cmd/migrate/migrations/20210505110026_init.go b/cmd/migrate/migrations/20210505110026_init.go new file mode 100644 index 0000000..324cd13 --- /dev/null +++ b/cmd/migrate/migrations/20210505110026_init.go @@ -0,0 +1,28 @@ +package migrations + +import ( + "aim-oscar/models" + "context" + + "github.com/uptrace/bun" + "github.com/uptrace/bun/dbfixture" +) + +func init() { + Migrations.MustRegister(func(ctx context.Context, db *bun.DB) error { + db.RegisterModel((*models.User)(nil), (*models.Message)(nil), (*models.Buddy)(nil), (*models.EmailVerification)(nil)) + + fixture := dbfixture.New(db, dbfixture.WithRecreateTables()) + return fixture.Load(context.Background(), sqlMigrations, "20210505110026_fixtures.yml") + }, func(ctx context.Context, db *bun.DB) error { + models := []interface{}{(*models.User)(nil), (*models.Message)(nil), (*models.Buddy)(nil), (*models.EmailVerification)(nil)} + + for _, model := range models { + if _, err := db.NewDropTable().Model(model).Exec(ctx, nil); err != nil { + return err + } + } + + return nil + }) +} diff --git a/cmd/bun/migrations/20210505110847_sql.up.sql b/cmd/migrate/migrations/20210505110847_sql.up.sql similarity index 100% rename from cmd/bun/migrations/20210505110847_sql.up.sql rename to cmd/migrate/migrations/20210505110847_sql.up.sql diff --git a/cmd/bun/migrations/main.go b/cmd/migrate/migrations/main.go similarity index 91% rename from cmd/bun/migrations/main.go rename to cmd/migrate/migrations/main.go index 7dfd5e0..d956d92 100644 --- a/cmd/bun/migrations/main.go +++ b/cmd/migrate/migrations/main.go @@ -8,7 +8,7 @@ import ( var Migrations = migrate.NewMigrations() -//go:embed *.sql +//go:embed *.sql *.yml var sqlMigrations embed.FS func init() { diff --git a/env/example.dev.env b/env/example.dev.env new file mode 100644 index 0000000..79fd1be --- /dev/null +++ b/env/example.dev.env @@ -0,0 +1,6 @@ +export POSTGRES_USER=postgres +export POSTGRES_PASSWORD=password +export DB_URL="$(hostname):5432" +export DB_USER=${POSTGRES_USER} +export DB_PASSWORD=${POSTGRES_PASSWORD} +export OSCAR_BOS_HOST=$(osascript -e "IPv4 address of (system info)") diff --git a/main.go b/main.go index fed2247..b324261 100644 --- a/main.go +++ b/main.go @@ -147,7 +147,7 @@ func main() { serviceManager := NewServiceManager() serviceManager.RegisterService(0x01, &services.GenericServiceControls{OnlineCh: onlineCh, ServerHostname: OSCAR_ADDRESS}) serviceManager.RegisterService(0x02, &services.LocationServices{OnlineCh: onlineCh}) - serviceManager.RegisterService(0x03, &services.BuddyListManagement{}) + serviceManager.RegisterService(0x03, &services.BuddyListManagement{OnlineCh: onlineCh}) serviceManager.RegisterService(0x04, &services.ICBM{CommCh: commCh}) serviceManager.RegisterService(0x17, &services.AuthorizationRegistrationService{BOSAddress: OSCAR_BOS_ADDRESS}) diff --git a/run.sh b/run.sh new file mode 100755 index 0000000..a400cf5 --- /dev/null +++ b/run.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +source env/dev.env +npm install +npm run dev