diff --git a/go.mod b/go.mod index 8b98608..c7fa21a 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( github.com/caddyserver/certmagic v0.17.1 github.com/coreos/go-oidc/v3 v3.3.0 github.com/glebarez/sqlite v1.4.6 + github.com/go-gormigrate/gormigrate/v2 v2.0.2 github.com/google/uuid v1.3.0 github.com/hashicorp/go-bexpr v0.1.11 github.com/hashicorp/go-hclog v1.3.0 diff --git a/go.sum b/go.sum index e2bd41c..1547c63 100644 --- a/go.sum +++ b/go.sum @@ -115,6 +115,7 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/denisenkom/go-mssqldb v0.12.0 h1:VtrkII767ttSPNRfFekePK3sctr+joXgO58stqQbtUA= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dvyukov/go-fuzz v0.0.0-20210103155950-6a8e9d1f2415/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -144,6 +145,8 @@ github.com/glebarez/sqlite v1.4.6/go.mod h1:WYEtEFjhADPaPJqL/PGlbQQGINBA3eUAfDNb github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gormigrate/gormigrate/v2 v2.0.2 h1:YV4Lc5yMQX8ahVW0ENPq6sPhrhdkGukc6fPRYmZ1R6Y= +github.com/go-gormigrate/gormigrate/v2 v2.0.2/go.mod h1:vld36QpBTfTzLealsHsmQQJK5lSwJt6wiORv+oFX8/I= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= @@ -159,6 +162,7 @@ github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD87 github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY= github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= +github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= @@ -171,6 +175,8 @@ github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRx github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= +github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY= +github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188 h1:+eHOFJl1BaXrQxKX+T06f78590z4qA2ZzBTqahsKSE4= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -330,6 +336,7 @@ github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkr github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg= github.com/josharian/native v1.0.0 h1:Ts/E8zCSEsG17dUqv7joXJFybuMLjQfWE04tsBODTxk= github.com/josharian/native v1.0.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= @@ -399,6 +406,7 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/ github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= github.com/mattn/go-sqlite3 v1.14.12/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= +github.com/mattn/go-sqlite3 v1.14.14 h1:qZgc/Rwetq+MtyE18WhzjokPD93dNqLGNT3QJuLvBGw= github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= @@ -1079,8 +1087,11 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gorm.io/driver/mysql v1.3.3 h1:jXG9ANrwBc4+bMvBcSl8zCfPBaVoPyBEBshA8dA93X8= gorm.io/driver/postgres v1.3.9 h1:lWGiVt5CijhQAg0PWB7Od1RNcBw/jS4d2cAScBcSDXg= gorm.io/driver/postgres v1.3.9/go.mod h1:qw/FeqjxmYqW5dBcYNBsnhQULIApQdk7YuuDPktVi1U= +gorm.io/driver/sqlite v1.3.2 h1:nWTy4cE52K6nnMhv23wLmur9Y3qWbZvOBz+V4PrGAxg= +gorm.io/driver/sqlserver v1.3.2 h1:yYt8f/xdAKLY7lCCyXxIUEgZ/WsURos3dHrx8MKFGAk= gorm.io/gorm v1.23.7/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= gorm.io/gorm v1.23.8 h1:h8sGJ+biDgBA1AD1Ha9gFCx7h8npU7AsLdlkX0n2TpE= gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= diff --git a/internal/database/database.go b/internal/database/database.go index 4539f29..2cd604d 100644 --- a/internal/database/database.go +++ b/internal/database/database.go @@ -5,8 +5,10 @@ import ( "encoding/json" "errors" "fmt" + "github.com/go-gormigrate/gormigrate/v2" "github.com/hashicorp/go-hclog" "github.com/jsiebens/ionscale/internal/broker" + "github.com/jsiebens/ionscale/internal/database/migration" "net/http" "tailscale.com/tailcfg" "time" @@ -72,20 +74,9 @@ func createDB(config *config.Database, logger hclog.Logger) (db, broker.Pubsub, } func migrate(db *gorm.DB, repository domain.Repository) error { - err := db.AutoMigrate( - &domain.ServerConfig{}, - &domain.Tailnet{}, - &domain.Account{}, - &domain.User{}, - &domain.SystemApiKey{}, - &domain.ApiKey{}, - &domain.AuthKey{}, - &domain.Machine{}, - &domain.RegistrationRequest{}, - &domain.AuthenticationRequest{}, - ) + m := gormigrate.New(db, gormigrate.DefaultOptions, migration.Migrations()) - if err != nil { + if err := m.Migrate(); err != nil { return err } diff --git a/internal/database/migration/m202209070900_initial_schema.go b/internal/database/migration/m202209070900_initial_schema.go new file mode 100644 index 0000000..c7682ff --- /dev/null +++ b/internal/database/migration/m202209070900_initial_schema.go @@ -0,0 +1,151 @@ +package migration + +import ( + "github.com/go-gormigrate/gormigrate/v2" + "github.com/jsiebens/ionscale/internal/domain" + "gorm.io/gorm" + "time" +) + +func m202209070900_initial_schema() *gormigrate.Migration { + return &gormigrate.Migration{ + ID: "202209070900", + Migrate: func(db *gorm.DB) error { + // it's a good practice to copy the struct inside the function, + // so side effects are prevented if the original struct changes during the time + type ServerConfig struct { + Key string `gorm:"primary_key"` + Value []byte + } + + type Tailnet struct { + ID uint64 `gorm:"primary_key;autoIncrement:false"` + Name string `gorm:"type:varchar(64);unique_index"` + DNSConfig domain.DNSConfig + IAMPolicy domain.IAMPolicy + ACLPolicy domain.ACLPolicy + } + + type Account struct { + ID uint64 `gorm:"primary_key;autoIncrement:false"` + ExternalID string + LoginName string + } + + type User struct { + ID uint64 `gorm:"primary_key;autoIncrement:false"` + Name string + UserType domain.UserType + TailnetID uint64 + Tailnet Tailnet + AccountID *uint64 + Account *Account + } + + type SystemApiKey struct { + ID uint64 `gorm:"primary_key;autoIncrement:false"` + Key string `gorm:"type:varchar(64);unique_index"` + Hash string + + CreatedAt time.Time + ExpiresAt *time.Time + + AccountID uint64 + Account Account + } + + type ApiKey struct { + ID uint64 `gorm:"primary_key;autoIncrement:false"` + Key string `gorm:"type:varchar(64);unique_index"` + Hash string + + CreatedAt time.Time + ExpiresAt *time.Time + + TailnetID uint64 + Tailnet Tailnet + + UserID uint64 + User User + } + + type AuthKey struct { + ID uint64 `gorm:"primary_key;autoIncrement:false"` + Key string `gorm:"type:varchar(64);unique_index"` + Hash string + Ephemeral bool + Tags domain.Tags + + CreatedAt time.Time + ExpiresAt *time.Time + + TailnetID uint64 + Tailnet Tailnet + + UserID uint64 + User User + } + + type Machine struct { + ID uint64 `gorm:"primary_key;autoIncrement:false"` + Name string + NameIdx uint64 + MachineKey string + NodeKey string + DiscoKey string + Ephemeral bool + RegisteredTags domain.Tags + Tags domain.Tags + KeyExpiryDisabled bool + + HostInfo domain.HostInfo + Endpoints domain.Endpoints + AllowIPs domain.AllowIPs + + IPv4 domain.IP + IPv6 domain.IP + + CreatedAt time.Time + ExpiresAt time.Time + LastSeen *time.Time + + UserID uint64 + User User + + TailnetID uint64 + Tailnet Tailnet + } + + type RegistrationRequest struct { + MachineKey string `gorm:"primary_key;autoIncrement:false"` + Key string `gorm:"type:varchar(64);unique_index"` + Data domain.RegistrationRequestData + CreatedAt time.Time + Authenticated bool + Error string + } + + type AuthenticationRequest struct { + Key string `gorm:"primary_key;autoIncrement:false"` + Token string + TailnetID *uint64 + Error string + CreatedAt time.Time + } + + return db.AutoMigrate( + &ServerConfig{}, + &Tailnet{}, + &Account{}, + &User{}, + &SystemApiKey{}, + &ApiKey{}, + &AuthKey{}, + &Machine{}, + &RegistrationRequest{}, + &AuthenticationRequest{}, + ) + }, + Rollback: nil, + } +} diff --git a/internal/database/migration/migrations.go b/internal/database/migration/migrations.go new file mode 100644 index 0000000..5a90c1a --- /dev/null +++ b/internal/database/migration/migrations.go @@ -0,0 +1,12 @@ +package migration + +import ( + "github.com/go-gormigrate/gormigrate/v2" +) + +func Migrations() []*gormigrate.Migration { + var migrations = []*gormigrate.Migration{ + m202209070900_initial_schema(), + } + return migrations +} diff --git a/internal/domain/account.go b/internal/domain/account.go index 2d2844b..81d801d 100644 --- a/internal/domain/account.go +++ b/internal/domain/account.go @@ -8,7 +8,7 @@ import ( ) type Account struct { - ID uint64 `gorm:"primary_key;autoIncrement:false"` + ID uint64 `gorm:"primary_key"` ExternalID string LoginName string } diff --git a/internal/domain/api_key.go b/internal/domain/api_key.go index b8a992d..b8ef1f5 100644 --- a/internal/domain/api_key.go +++ b/internal/domain/api_key.go @@ -34,8 +34,8 @@ func CreateApiKey(tailnet *Tailnet, user *User, expiresAt *time.Time) (string, * } type ApiKey struct { - ID uint64 `gorm:"primary_key;autoIncrement:false"` - Key string `gorm:"type:varchar(64);unique_index"` + ID uint64 `gorm:"primary_key"` + Key string Hash string CreatedAt time.Time diff --git a/internal/domain/auth_key.go b/internal/domain/auth_key.go index 5368038..5210d6e 100644 --- a/internal/domain/auth_key.go +++ b/internal/domain/auth_key.go @@ -36,8 +36,8 @@ func CreateAuthKey(tailnet *Tailnet, user *User, ephemeral bool, tags Tags, expi } type AuthKey struct { - ID uint64 `gorm:"primary_key;autoIncrement:false"` - Key string `gorm:"type:varchar(64);unique_index"` + ID uint64 `gorm:"primary_key"` + Key string Hash string Ephemeral bool Tags Tags diff --git a/internal/domain/authentication_request.go b/internal/domain/authentication_request.go index 848b5fd..41b3946 100644 --- a/internal/domain/authentication_request.go +++ b/internal/domain/authentication_request.go @@ -8,7 +8,7 @@ import ( ) type AuthenticationRequest struct { - Key string `gorm:"primary_key;autoIncrement:false"` + Key string `gorm:"primary_key"` Token string TailnetID *uint64 Error string diff --git a/internal/domain/machine.go b/internal/domain/machine.go index 7940bdc..8627fe6 100644 --- a/internal/domain/machine.go +++ b/internal/domain/machine.go @@ -14,7 +14,7 @@ import ( ) type Machine struct { - ID uint64 `gorm:"primary_key;autoIncrement:false"` + ID uint64 `gorm:"primary_key"` Name string NameIdx uint64 MachineKey string diff --git a/internal/domain/registration_request.go b/internal/domain/registration_request.go index 31f35be..963edb3 100644 --- a/internal/domain/registration_request.go +++ b/internal/domain/registration_request.go @@ -13,8 +13,8 @@ import ( ) type RegistrationRequest struct { - MachineKey string `gorm:"primary_key;autoIncrement:false"` - Key string `gorm:"type:varchar(64);unique_index"` + MachineKey string `gorm:"primary_key"` + Key string Data RegistrationRequestData CreatedAt time.Time Authenticated bool diff --git a/internal/domain/system_api_key.go b/internal/domain/system_api_key.go index 2d7d53e..bd10caf 100644 --- a/internal/domain/system_api_key.go +++ b/internal/domain/system_api_key.go @@ -33,8 +33,8 @@ func CreateSystemApiKey(account *Account, expiresAt *time.Time) (string, *System } type SystemApiKey struct { - ID uint64 `gorm:"primary_key;autoIncrement:false"` - Key string `gorm:"type:varchar(64);unique_index"` + ID uint64 `gorm:"primary_key"` + Key string Hash string CreatedAt time.Time diff --git a/internal/domain/tailnet.go b/internal/domain/tailnet.go index 9ce7267..48a0139 100644 --- a/internal/domain/tailnet.go +++ b/internal/domain/tailnet.go @@ -8,8 +8,8 @@ import ( ) type Tailnet struct { - ID uint64 `gorm:"primary_key;autoIncrement:false"` - Name string `gorm:"type:varchar(64);unique_index"` + ID uint64 `gorm:"primary_key"` + Name string DNSConfig DNSConfig IAMPolicy IAMPolicy ACLPolicy ACLPolicy diff --git a/internal/domain/user.go b/internal/domain/user.go index ec51851..d14bd72 100644 --- a/internal/domain/user.go +++ b/internal/domain/user.go @@ -38,7 +38,7 @@ func (s UserRole) IsAdmin() bool { } type User struct { - ID uint64 `gorm:"primary_key;autoIncrement:false"` + ID uint64 `gorm:"primary_key"` Name string UserType UserType TailnetID uint64