seed superuser on migrate
This commit is contained in:
+1
-1
@@ -32,7 +32,7 @@ func main() {
|
|||||||
log.Panic(err.Error())
|
log.Panic(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := database.Migrate(db); err != nil {
|
if err := database.Migrate(db, cfg.SuperUser); err != nil {
|
||||||
log.Panic(err.Error())
|
log.Panic(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ require (
|
|||||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||||
github.com/valyala/fasthttp v1.71.0 // indirect
|
github.com/valyala/fasthttp v1.71.0 // indirect
|
||||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||||
|
golang.org/x/crypto v0.52.0 // indirect
|
||||||
golang.org/x/sync v0.20.0 // indirect
|
golang.org/x/sync v0.20.0 // indirect
|
||||||
golang.org/x/sys v0.45.0 // indirect
|
golang.org/x/sys v0.45.0 // indirect
|
||||||
golang.org/x/text v0.37.0 // indirect
|
golang.org/x/text v0.37.0 // indirect
|
||||||
|
|||||||
@@ -76,6 +76,8 @@ github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZ
|
|||||||
github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
|
github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
|
||||||
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
||||||
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||||
|
golang.org/x/crypto v0.52.0 h1:RMs7fP2rXdep0CftQlK8Uf+kibLm7qkCcradZWYz988=
|
||||||
|
golang.org/x/crypto v0.52.0/go.mod h1:1QgfPxDqh0T2M/elOJtp9RvuR95kVjir0e6/BvEmGbc=
|
||||||
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
|
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
|
||||||
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
||||||
golang.org/x/sys v0.45.0 h1:dO4czNzziLiiXplLQgBCEpCvXQ3dnkn0SdaZSYdQ+FY=
|
golang.org/x/sys v0.45.0 h1:dO4czNzziLiiXplLQgBCEpCvXQ3dnkn0SdaZSYdQ+FY=
|
||||||
|
|||||||
@@ -6,12 +6,19 @@ import (
|
|||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type User struct {
|
||||||
|
Name string `mapstructure:"name"`
|
||||||
|
Email string `mapstructure:"email"`
|
||||||
|
Password string `mapstructure:"password"`
|
||||||
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
DBDriver string `mapstructure:"db_driver"`
|
DBDriver string `mapstructure:"db_driver"`
|
||||||
DBConnString string `mapstructure:"db_conn_string"`
|
DBConnString string `mapstructure:"db_conn_string"`
|
||||||
JWTSecret string `mapstructure:"jwt_secret"`
|
JWTSecret string `mapstructure:"jwt_secret"`
|
||||||
SessionSecret string `mapstructure:"session_secret"`
|
SessionSecret string `mapstructure:"session_secret"`
|
||||||
ServerPort int `mapstructure:"server_port"`
|
ServerPort int `mapstructure:"server_port"`
|
||||||
|
SuperUser User `mapstructure:"superuser"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func Load(path string) (*Config, error) {
|
func Load(path string) (*Config, error) {
|
||||||
|
|||||||
+47
-1
@@ -3,12 +3,14 @@ package database
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/Henelik/cms/pkg/config"
|
||||||
|
"golang.org/x/crypto/bcrypt"
|
||||||
"gorm.io/driver/postgres"
|
"gorm.io/driver/postgres"
|
||||||
"gorm.io/driver/sqlite"
|
"gorm.io/driver/sqlite"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Migrate(db *gorm.DB) error {
|
func Migrate(db *gorm.DB, su config.User) error {
|
||||||
if err := db.AutoMigrate(&User{}, &Role{}); err != nil {
|
if err := db.AutoMigrate(&User{}, &Role{}); err != nil {
|
||||||
return fmt.Errorf("auto-migrate: %w", err)
|
return fmt.Errorf("auto-migrate: %w", err)
|
||||||
}
|
}
|
||||||
@@ -27,6 +29,50 @@ func Migrate(db *gorm.DB) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if su.Name != "" && su.Email != "" && su.Password != "" {
|
||||||
|
if err := seedSuperUser(db, su); err != nil {
|
||||||
|
return fmt.Errorf("seed superuser: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func seedSuperUser(db *gorm.DB, su config.User) error {
|
||||||
|
hash, err := bcrypt.GenerateFromPassword([]byte(su.Password), bcrypt.DefaultCost)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("hash password: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
user := User{
|
||||||
|
Name: su.Name,
|
||||||
|
Email: su.Email,
|
||||||
|
PasswordHash: string(hash),
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := db.FirstOrCreate(&user, User{Email: su.Email}).Error; err != nil {
|
||||||
|
return fmt.Errorf("create user: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var superadmin Role
|
||||||
|
if err := db.First(&superadmin, "name = ?", "superadmin").Error; err != nil {
|
||||||
|
return fmt.Errorf("find superadmin role: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if user already has the superadmin role
|
||||||
|
var count int64
|
||||||
|
if err := db.Table("user_roles").
|
||||||
|
Where("user_id = ? AND role_id = ?", user.ID, superadmin.ID).
|
||||||
|
Count(&count).Error; err != nil {
|
||||||
|
return fmt.Errorf("check role association: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if count == 0 {
|
||||||
|
if err := db.Model(&user).Association("Roles").Append(&superadmin); err != nil {
|
||||||
|
return fmt.Errorf("assign superadmin role: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user