package server import ( "context" "encoding/json" "fmt" "time" "github.com/deluan/navidrome/conf" "github.com/deluan/navidrome/consts" "github.com/deluan/navidrome/log" "github.com/deluan/navidrome/model" "github.com/google/uuid" ) func initialSetup(ds model.DataStore) { _ = ds.WithTx(func(tx model.DataStore) error { if err := createDefaultTranscodings(ds); err != nil { return err } properties := ds.Property(context.TODO()) _, err := properties.Get(consts.InitialSetupFlagKey) if err == nil { return nil } log.Warn("Running initial setup") if err = createJWTSecret(ds); err != nil { return err } if conf.Server.DevAutoCreateAdminPassword != "" { if err = createInitialAdminUser(ds); err != nil { return err } } err = properties.Put(consts.InitialSetupFlagKey, time.Now().String()) return err }) } func createInitialAdminUser(ds model.DataStore) error { users := ds.User(context.TODO()) c, err := users.CountAll() if err != nil { panic(fmt.Sprintf("Could not access User table: %s", err)) } if c == 0 { id, _ := uuid.NewRandom() random, _ := uuid.NewRandom() initialPassword := random.String() if conf.Server.DevAutoCreateAdminPassword != "" { initialPassword = conf.Server.DevAutoCreateAdminPassword } log.Warn("Creating initial admin user. This should only be used for development purposes!!", "user", consts.DevInitialUserName, "password", initialPassword) initialUser := model.User{ ID: id.String(), UserName: consts.DevInitialUserName, Name: consts.DevInitialName, Email: "", Password: initialPassword, IsAdmin: true, } err := users.Put(&initialUser) if err != nil { log.Error("Could not create initial admin user", "user", initialUser, err) } } return err } func createJWTSecret(ds model.DataStore) error { properties := ds.Property(context.TODO()) _, err := properties.Get(consts.JWTSecretKey) if err == nil { return nil } jwtSecret, _ := uuid.NewRandom() log.Warn("Creating JWT secret, used for encrypting UI sessions") err = properties.Put(consts.JWTSecretKey, jwtSecret.String()) if err != nil { log.Error("Could not save JWT secret in DB", err) } return err } func createDefaultTranscodings(ds model.DataStore) error { transcodings := ds.Transcoding(context.TODO()) c, _ := transcodings.CountAll() if c != 0 { return nil } for _, d := range consts.DefaultTranscodings { var j []byte var err error if j, err = json.Marshal(d); err != nil { return err } var t model.Transcoding if err = json.Unmarshal(j, &t); err != nil { return err } log.Info("Creating default transcoding config", "name", t.Name) if err = transcodings.Put(&t); err != nil { return err } } return nil }