From b166ceaea72dc6db77467621ffc270fbdccb6566 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Guillot?= Date: Sun, 29 Apr 2018 17:04:23 -0700 Subject: [PATCH] Avoid people to unlink their OAuth2 account without having a local password --- locale/translations.go | 7 ++++--- locale/translations/fr_FR.json | 3 ++- storage/user.go | 18 ++++++++++++++++++ ui/oauth2_unlink.go | 16 ++++++++++++++-- ui/settings_update.go | 1 + 5 files changed, 39 insertions(+), 6 deletions(-) diff --git a/locale/translations.go b/locale/translations.go index 33bb4f64..e828234a 100755 --- a/locale/translations.go +++ b/locale/translations.go @@ -1,5 +1,5 @@ // Code generated by go generate; DO NOT EDIT. -// 2018-04-29 16:22:00.540830112 -0700 PDT m=+0.025120206 +// 2018-04-29 16:59:49.591693595 -0700 PDT m=+0.022587229 package locale @@ -461,7 +461,8 @@ var translations = map[string]string{ "Comments": "Commentaires", "View Comments": "Voir les commentaires", "This file is empty": "Ce fichier est vide", - "Your external account is now dissociated!": "Votre compte externe est maintenant dissocié !" + "Your external account is now dissociated!": "Votre compte externe est maintenant dissocié !", + "You must define a password otherwise you won't be able to login again.": "Vous devez définir un mot de passe sinon vous ne pourrez plus vous connecter par la suite." } `, "nl_NL": `{ @@ -1136,7 +1137,7 @@ var translations = map[string]string{ var translationsChecksums = map[string]string{ "de_DE": "791d72c96137ab03b729017bdfa27c8eed2f65912e372fcb5b2796d5099d5498", "en_US": "6fe95384260941e8a5a3c695a655a932e0a8a6a572c1e45cb2b1ae8baa01b897", - "fr_FR": "b4e407e3665b30b29da3bce197a035b842a9bdd7781c28cc056d978b46646f3c", + "fr_FR": "5a954b28ac31af6fc525cb000d86c884950dac7414b695bd38a4c0aebdfe35b5", "nl_NL": "1a73f1dd1c4c0d2c2adc8695cdd050c2dad81c14876caed3892b44adc2491265", "pl_PL": "da709c14ff71f3b516eec66cb2758d89c5feab1472c94b2b518f425162a9f806", "zh_CN": "d80594c1b67d15e9f4673d3d62fe4949e8606a5fdfb741d8a8921f21dceb8cf2", diff --git a/locale/translations/fr_FR.json b/locale/translations/fr_FR.json index 60ad9d89..ac3c5713 100644 --- a/locale/translations/fr_FR.json +++ b/locale/translations/fr_FR.json @@ -221,5 +221,6 @@ "Comments": "Commentaires", "View Comments": "Voir les commentaires", "This file is empty": "Ce fichier est vide", - "Your external account is now dissociated!": "Votre compte externe est maintenant dissocié !" + "Your external account is now dissociated!": "Votre compte externe est maintenant dissocié !", + "You must define a password otherwise you won't be able to login again.": "Vous devez définir un mot de passe sinon vous ne pourrez plus vous connecter par la suite." } diff --git a/storage/user.go b/storage/user.go index fea59d4f..de58c098 100644 --- a/storage/user.go +++ b/storage/user.go @@ -339,6 +339,24 @@ func (s *Storage) CheckPassword(username, password string) error { return nil } +// HasPassword returns true if the given user has a password defined. +func (s *Storage) HasPassword(userID int64) (bool, error) { + var result bool + query := `SELECT true FROM users WHERE id=$1 AND password <> ''` + + err := s.db.QueryRow(query, userID).Scan(&result) + if err == sql.ErrNoRows { + return false, nil + } else if err != nil { + return false, fmt.Errorf("unable to execute query: %v", err) + } + + if result { + return true, nil + } + return false, nil +} + func hashPassword(password string) (string, error) { bytes, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) return string(bytes), err diff --git a/ui/oauth2_unlink.go b/ui/oauth2_unlink.go index e67c6fef..4421092c 100644 --- a/ui/oauth2_unlink.go +++ b/ui/oauth2_unlink.go @@ -33,13 +33,25 @@ func (c *Controller) OAuth2Unlink(w http.ResponseWriter, r *http.Request) { } ctx := context.New(r) + sess := session.New(c.store, ctx) + + hasPassword, err := c.store.HasPassword(ctx.UserID()) + if err != nil { + html.ServerError(w, err) + return + } + + if !hasPassword { + sess.NewFlashErrorMessage(c.translator.GetLanguage(ctx.UserLanguage()).Get("You must define a password otherwise you won't be able to login again.")) + response.Redirect(w, r, route.Path(c.router, "settings")) + return + } + if err := c.store.RemoveExtraField(ctx.UserID(), authProvider.GetUserExtraKey()); err != nil { html.ServerError(w, err) return } - sess := session.New(c.store, ctx) sess.NewFlashMessage(c.translator.GetLanguage(ctx.UserLanguage()).Get("Your external account is now dissociated!")) response.Redirect(w, r, route.Path(c.router, "settings")) - return } diff --git a/ui/settings_update.go b/ui/settings_update.go index a8b49ff7..5e889e28 100644 --- a/ui/settings_update.go +++ b/ui/settings_update.go @@ -67,6 +67,7 @@ func (c *Controller) UpdateSettings(w http.ResponseWriter, r *http.Request) { return } + sess.SetLanguage(user.Language) sess.NewFlashMessage(c.translator.GetLanguage(ctx.UserLanguage()).Get("Preferences saved!")) response.Redirect(w, r, route.Path(c.router, "settings")) }