mirror of
https://github.com/amigan/aim-oscar-server.git
synced 2025-01-31 04:52:37 -05:00
db migrations
This commit is contained in:
parent
add16b5143
commit
0f8e600469
12 changed files with 163 additions and 260 deletions
|
@ -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
|
||||
|
|
BIN
cmd/.DS_Store
vendored
BIN
cmd/.DS_Store
vendored
Binary file not shown.
235
cmd/bun/main.go
235
cmd/bun/main.go
|
@ -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"
|
||||
}
|
|
@ -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)
|
||||
}
|
118
cmd/migrate/main.go
Normal file
118
cmd/migrate/main.go
Normal file
|
@ -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 <init|up|down|status|mark_applied>", 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)
|
||||
}
|
||||
}
|
|
@ -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
|
28
cmd/migrate/migrations/20210505110026_init.go
Normal file
28
cmd/migrate/migrations/20210505110026_init.go
Normal file
|
@ -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
|
||||
})
|
||||
}
|
|
@ -8,7 +8,7 @@ import (
|
|||
|
||||
var Migrations = migrate.NewMigrations()
|
||||
|
||||
//go:embed *.sql
|
||||
//go:embed *.sql *.yml
|
||||
var sqlMigrations embed.FS
|
||||
|
||||
func init() {
|
6
env/example.dev.env
vendored
Normal file
6
env/example.dev.env
vendored
Normal file
|
@ -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)")
|
2
main.go
2
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})
|
||||
|
||||
|
|
5
run.sh
Executable file
5
run.sh
Executable file
|
@ -0,0 +1,5 @@
|
|||
#!/bin/bash
|
||||
|
||||
source env/dev.env
|
||||
npm install
|
||||
npm run dev
|
Loading…
Reference in a new issue