Browse Source

Avoid people to unlink their OAuth2 account without having a local password

Frédéric Guillot 8 years ago
parent
commit
b166ceaea7
5 changed files with 39 additions and 6 deletions
  1. 4 3
      locale/translations.go
  2. 2 1
      locale/translations/fr_FR.json
  3. 18 0
      storage/user.go
  4. 14 2
      ui/oauth2_unlink.go
  5. 1 0
      ui/settings_update.go

+ 4 - 3
locale/translations.go

@@ -1,5 +1,5 @@
 // Code generated by go generate; DO NOT EDIT.
 // 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
 package locale
 
 
@@ -461,7 +461,8 @@ var translations = map[string]string{
     "Comments": "Commentaires",
     "Comments": "Commentaires",
     "View Comments": "Voir les commentaires",
     "View Comments": "Voir les commentaires",
     "This file is empty": "Ce fichier est vide",
     "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": `{
 	"nl_NL": `{
@@ -1136,7 +1137,7 @@ var translations = map[string]string{
 var translationsChecksums = map[string]string{
 var translationsChecksums = map[string]string{
 	"de_DE": "791d72c96137ab03b729017bdfa27c8eed2f65912e372fcb5b2796d5099d5498",
 	"de_DE": "791d72c96137ab03b729017bdfa27c8eed2f65912e372fcb5b2796d5099d5498",
 	"en_US": "6fe95384260941e8a5a3c695a655a932e0a8a6a572c1e45cb2b1ae8baa01b897",
 	"en_US": "6fe95384260941e8a5a3c695a655a932e0a8a6a572c1e45cb2b1ae8baa01b897",
-	"fr_FR": "b4e407e3665b30b29da3bce197a035b842a9bdd7781c28cc056d978b46646f3c",
+	"fr_FR": "5a954b28ac31af6fc525cb000d86c884950dac7414b695bd38a4c0aebdfe35b5",
 	"nl_NL": "1a73f1dd1c4c0d2c2adc8695cdd050c2dad81c14876caed3892b44adc2491265",
 	"nl_NL": "1a73f1dd1c4c0d2c2adc8695cdd050c2dad81c14876caed3892b44adc2491265",
 	"pl_PL": "da709c14ff71f3b516eec66cb2758d89c5feab1472c94b2b518f425162a9f806",
 	"pl_PL": "da709c14ff71f3b516eec66cb2758d89c5feab1472c94b2b518f425162a9f806",
 	"zh_CN": "d80594c1b67d15e9f4673d3d62fe4949e8606a5fdfb741d8a8921f21dceb8cf2",
 	"zh_CN": "d80594c1b67d15e9f4673d3d62fe4949e8606a5fdfb741d8a8921f21dceb8cf2",

+ 2 - 1
locale/translations/fr_FR.json

@@ -221,5 +221,6 @@
     "Comments": "Commentaires",
     "Comments": "Commentaires",
     "View Comments": "Voir les commentaires",
     "View Comments": "Voir les commentaires",
     "This file is empty": "Ce fichier est vide",
     "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."
 }
 }

+ 18 - 0
storage/user.go

@@ -339,6 +339,24 @@ func (s *Storage) CheckPassword(username, password string) error {
 	return nil
 	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) {
 func hashPassword(password string) (string, error) {
 	bytes, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
 	bytes, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
 	return string(bytes), err
 	return string(bytes), err

+ 14 - 2
ui/oauth2_unlink.go

@@ -33,13 +33,25 @@ func (c *Controller) OAuth2Unlink(w http.ResponseWriter, r *http.Request) {
 	}
 	}
 
 
 	ctx := context.New(r)
 	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 {
 	if err := c.store.RemoveExtraField(ctx.UserID(), authProvider.GetUserExtraKey()); err != nil {
 		html.ServerError(w, err)
 		html.ServerError(w, err)
 		return
 		return
 	}
 	}
 
 
-	sess := session.New(c.store, ctx)
 	sess.NewFlashMessage(c.translator.GetLanguage(ctx.UserLanguage()).Get("Your external account is now dissociated!"))
 	sess.NewFlashMessage(c.translator.GetLanguage(ctx.UserLanguage()).Get("Your external account is now dissociated!"))
 	response.Redirect(w, r, route.Path(c.router, "settings"))
 	response.Redirect(w, r, route.Path(c.router, "settings"))
-	return
 }
 }

+ 1 - 0
ui/settings_update.go

@@ -67,6 +67,7 @@ func (c *Controller) UpdateSettings(w http.ResponseWriter, r *http.Request) {
 		return
 		return
 	}
 	}
 
 
+	sess.SetLanguage(user.Language)
 	sess.NewFlashMessage(c.translator.GetLanguage(ctx.UserLanguage()).Get("Preferences saved!"))
 	sess.NewFlashMessage(c.translator.GetLanguage(ctx.UserLanguage()).Get("Preferences saved!"))
 	response.Redirect(w, r, route.Path(c.router, "settings"))
 	response.Redirect(w, r, route.Path(c.router, "settings"))
 }
 }