From a4c344aaa11f0e5139daf76e6d591dd70c4fa8e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ferdinand=20M=C3=BCtsch?= Date: Fri, 16 Oct 2020 16:11:14 +0200 Subject: [PATCH] chore: minor code restyling --- main.go | 29 +++++------------------------ middlewares/authenticate.go | 10 +++++----- migrations/common/fixtures.go | 15 +++++++++++++++ migrations/common/languages.go | 25 +++++++++++++++++++++++++ routes/settings.go | 6 ++++-- services/user.go | 8 ++++++-- utils/auth.go | 33 +++++++++++++++++---------------- 7 files changed, 77 insertions(+), 49 deletions(-) create mode 100644 migrations/common/fixtures.go create mode 100644 migrations/common/languages.go diff --git a/main.go b/main.go index 11d5cb3..1683071 100644 --- a/main.go +++ b/main.go @@ -3,6 +3,7 @@ package main import ( "github.com/gorilla/handlers" conf "github.com/muety/wakapi/config" + "github.com/muety/wakapi/migrations/common" "log" "net/http" "strconv" @@ -14,7 +15,6 @@ import ( _ "github.com/jinzhu/gorm/dialects/postgres" _ "github.com/jinzhu/gorm/dialects/sqlite" "github.com/muety/wakapi/middlewares" - "github.com/muety/wakapi/models" "github.com/muety/wakapi/routes" shieldsV1Routes "github.com/muety/wakapi/routes/compat/shields/v1" wtV1Routes "github.com/muety/wakapi/routes/compat/wakatime/v1" @@ -68,7 +68,7 @@ func main() { // Migrate database schema runDatabaseMigrations() - applyFixtures() + runCustomMigrations() // Services aliasService = services.NewAliasService(db) @@ -78,9 +78,6 @@ func main() { aggregationService = services.NewAggregationService(db, userService, summaryService, heartbeatService) keyValueService = services.NewKeyValueService(db) - // Custom migrations and initial data - migrateLanguages() - // Aggregate heartbeats to summaries and persist them go aggregationService.Schedule() @@ -175,25 +172,9 @@ func runDatabaseMigrations() { } } -func applyFixtures() { - if err := config.GetFixturesFunc(config.Db.Dialect)(db); err != nil { - log.Fatal(err) - } -} - -func migrateLanguages() { - for k, v := range config.App.CustomLanguages { - result := db.Model(models.Heartbeat{}). - Where("language = ?", ""). - Where("entity LIKE ?", "%."+k). - Updates(models.Heartbeat{Language: v}) - if result.Error != nil { - log.Fatal(result.Error) - } - if result.RowsAffected > 0 { - log.Printf("Migrated %+v rows for custom language %+s.\n", result.RowsAffected, k) - } - } +func runCustomMigrations() { + common.ApplyFixtures(db) + common.MigrateLanguages(db) } func promptAbort(message string, timeoutSec int) { diff --git a/middlewares/authenticate.go b/middlewares/authenticate.go index d0677c0..05d4ff7 100644 --- a/middlewares/authenticate.go +++ b/middlewares/authenticate.go @@ -4,7 +4,7 @@ import ( "context" "errors" "fmt" - config2 "github.com/muety/wakapi/config" + conf "github.com/muety/wakapi/config" "github.com/muety/wakapi/utils" "log" "net/http" @@ -18,7 +18,7 @@ import ( ) type AuthenticateMiddleware struct { - config *config2.Config + config *conf.Config userSrvc *services.UserService cache *cache.Cache whitelistPaths []string @@ -26,7 +26,7 @@ type AuthenticateMiddleware struct { func NewAuthenticateMiddleware(userService *services.UserService, whitelistPaths []string) *AuthenticateMiddleware { return &AuthenticateMiddleware{ - config: config2.Get(), + config: conf.Get(), userSrvc: userService, cache: cache.New(1*time.Hour, 2*time.Hour), whitelistPaths: whitelistPaths, @@ -117,12 +117,12 @@ func (m *AuthenticateMiddleware) tryGetUserByCookie(r *http.Request) (*models.Us // migrate old md5-hashed passwords to new salted bcrypt hashes for backwards compatibility func CheckAndMigratePassword(user *models.User, login *models.Login, salt string, userServiceRef *services.UserService) bool { if utils.IsMd5(user.Password) { - if utils.CheckPasswordMd5(user, login.Password) { + if utils.CompareMd5(user.Password, login.Password, "") { log.Printf("migrating old md5 password to new bcrypt format for user '%s'", user.ID) userServiceRef.MigrateMd5Password(user, login) return true } return false } - return utils.CheckPasswordBcrypt(user, login.Password, salt) + return utils.CompareBcrypt(user.Password, login.Password, salt) } diff --git a/migrations/common/fixtures.go b/migrations/common/fixtures.go new file mode 100644 index 0000000..7db2484 --- /dev/null +++ b/migrations/common/fixtures.go @@ -0,0 +1,15 @@ +package common + +import ( + "github.com/jinzhu/gorm" + "github.com/muety/wakapi/config" + "log" +) + +func ApplyFixtures(db *gorm.DB) { + cfg := config.Get() + + if err := cfg.GetFixturesFunc(cfg.Db.Dialect)(db); err != nil { + log.Fatal(err) + } +} diff --git a/migrations/common/languages.go b/migrations/common/languages.go new file mode 100644 index 0000000..ed63a7c --- /dev/null +++ b/migrations/common/languages.go @@ -0,0 +1,25 @@ +package common + +import ( + "github.com/jinzhu/gorm" + "github.com/muety/wakapi/config" + "github.com/muety/wakapi/models" + "log" +) + +func MigrateLanguages(db *gorm.DB) { + cfg := config.Get() + + for k, v := range cfg.App.CustomLanguages { + result := db.Model(models.Heartbeat{}). + Where("language = ?", ""). + Where("entity LIKE ?", "%."+k). + Updates(models.Heartbeat{Language: v}) + if result.Error != nil { + log.Fatal(result.Error) + } + if result.RowsAffected > 0 { + log.Printf("Migrated %+v rows for custom language %+s.\n", result.RowsAffected, k) + } + } +} diff --git a/routes/settings.go b/routes/settings.go index bc7bfb8..7993e35 100644 --- a/routes/settings.go +++ b/routes/settings.go @@ -59,7 +59,7 @@ func (h *SettingsHandler) PostCredentials(w http.ResponseWriter, r *http.Request return } - if !utils.CheckPasswordBcrypt(user, credentials.PasswordOld, h.config.Security.PasswordSalt) { + if !utils.CompareBcrypt(user.Password, credentials.PasswordOld, h.config.Security.PasswordSalt) { respondAlert(w, "invalid credentials", "", conf.SettingsTemplate, http.StatusUnauthorized) return } @@ -70,9 +70,11 @@ func (h *SettingsHandler) PostCredentials(w http.ResponseWriter, r *http.Request } user.Password = credentials.PasswordNew - if err := utils.HashPassword(user, h.config.Security.PasswordSalt); err != nil { + if hash, err := utils.HashBcrypt(user.Password, h.config.Security.PasswordSalt); err != nil { respondAlert(w, "internal server error", "", conf.SettingsTemplate, http.StatusInternalServerError) return + } else { + user.Password = hash } if _, err := h.userSrvc.Update(user); err != nil { diff --git a/services/user.go b/services/user.go index dbdc05c..6440b23 100644 --- a/services/user.go +++ b/services/user.go @@ -54,8 +54,10 @@ func (srv *UserService) CreateOrGet(signup *models.Signup) (*models.User, bool, Password: signup.Password, } - if err := utils.HashPassword(u, srv.Config.Security.PasswordSalt); err != nil { + if hash, err := utils.HashBcrypt(u.Password, srv.Config.Security.PasswordSalt); err != nil { return nil, false, err + } else { + u.Password = hash } result := srv.Db.FirstOrCreate(u, &models.User{ID: u.ID}) @@ -103,8 +105,10 @@ func (srv *UserService) ToggleBadges(user *models.User) (*models.User, error) { func (srv *UserService) MigrateMd5Password(user *models.User, login *models.Login) (*models.User, error) { user.Password = login.Password - if err := utils.HashPassword(user, srv.Config.Security.PasswordSalt); err != nil { + if hash, err := utils.HashBcrypt(user.Password, srv.Config.Security.PasswordSalt); err != nil { return nil, err + } else { + user.Password = hash } result := srv.Db.Model(user).Update("password", user.Password) diff --git a/utils/auth.go b/utils/auth.go index 9ca1389..e30c18e 100644 --- a/utils/auth.go +++ b/utils/auth.go @@ -63,28 +63,29 @@ func IsMd5(hash string) bool { return md5Regex.Match([]byte(hash)) } -func CheckPasswordBcrypt(user *models.User, password, salt string) bool { - plainPassword := []byte(strings.TrimSpace(password) + salt) - err := bcrypt.CompareHashAndPassword([]byte(user.Password), plainPassword) +func CompareBcrypt(wanted, actual, pepper string) bool { + plainPassword := []byte(strings.TrimSpace(actual) + pepper) + err := bcrypt.CompareHashAndPassword([]byte(wanted), plainPassword) return err == nil } // deprecated, only here for backwards compatibility -func CheckPasswordMd5(user *models.User, password string) bool { - hash := md5.Sum([]byte(password)) - hashStr := hex.EncodeToString(hash[:]) - if hashStr == user.Password { - return true - } - return false +func CompareMd5(wanted, actual, pepper string) bool { + return HashMd5(actual, pepper) == wanted } -// inplace -func HashPassword(u *models.User, salt string) error { - plainSaltedPassword := []byte(strings.TrimSpace(u.Password) + salt) - bytes, err := bcrypt.GenerateFromPassword(plainSaltedPassword, bcrypt.DefaultCost) +func HashBcrypt(plain, pepper string) (string, error) { + plainPepperedPassword := []byte(strings.TrimSpace(plain) + pepper) + bytes, err := bcrypt.GenerateFromPassword(plainPepperedPassword, bcrypt.DefaultCost) if err == nil { - u.Password = string(bytes) + return string(bytes), nil } - return err + return "", err +} + +func HashMd5(plain, pepper string) string { + plainPepperedPassword := []byte(strings.TrimSpace(plain) + pepper) + hash := md5.Sum(plainPepperedPassword) + hashStr := hex.EncodeToString(hash[:]) + return hashStr }