package main import ( "fmt" "os" "strconv" "github.com/gochat/gochat/internal/app" "github.com/gochat/gochat/internal/config" "github.com/gochat/gochat/internal/model" channelmodel "github.com/gochat/gochat/internal/model/channel" "github.com/gochat/gochat/internal/security" "gorm.io/gorm" ) func main() { env := os.Getenv("GOCHAT_ENV") if env == "" { env = "prod" } cfg, err := config.LoadWithEnv(env) if err != nil { panic(err) } db, err := app.NewDatabase(&cfg.Database, "silent") if err != nil { panic(err) } previous := make(map[int]string, len(cfg.Encryption.PreviousKeys)) for version, key := range cfg.Encryption.PreviousKeys { parsed, err := strconv.Atoi(version) if err != nil { panic(err) } previous[parsed] = key } encryptor, err := security.NewEncryptorWithPreviousKeys(security.EncryptionConfig{ Enabled: cfg.Encryption.Enabled, AESKey: cfg.Encryption.AESKey, KeyVersion: cfg.Encryption.CurrentKeyVersion, }, previous) if err != nil { panic(err) } if err := security.RegisterGORMEncryption(db, encryptor); err != nil { panic(err) } for _, rotate := range []func(*gorm.DB) error{ rotateRows[model.AgentBot], rotateRows[model.Inbox], rotateRows[model.IntegrationHook], rotateRows[model.WebhookSubscription], rotateRows[model.User], rotateRows[channelmodel.ChannelAPI], rotateRows[channelmodel.ChannelFacebook], rotateRows[channelmodel.ChannelInstagram], rotateRows[channelmodel.ChannelTikTok], rotateRows[channelmodel.ChannelWhatsApp], rotateRows[channelmodel.ChannelEmail], rotateRows[channelmodel.ChannelWebWidget], } { if err := rotate(db); err != nil { panic(err) } } fmt.Printf("sensitive fields rotated to encryption key v%d\n", cfg.Encryption.CurrentKeyVersion) } func rotateRows[T any](db *gorm.DB) error { var rows []T if err := db.Find(&rows).Error; err != nil { return err } return db.Transaction(func(tx *gorm.DB) error { for i := range rows { if err := tx.Save(&rows[i]).Error; err != nil { return err } } return nil }) }