Fix some translations and error messages
authorBenjamin Auder <benjamin.auder@somewhere>
Sun, 1 Mar 2020 17:57:45 +0000 (18:57 +0100)
committerBenjamin Auder <benjamin.auder@somewhere>
Sun, 1 Mar 2020 17:57:45 +0000 (18:57 +0100)
13 files changed:
client/src/components/UpsertUser.vue
client/src/data/userCheck.js
client/src/parameters.js.dist
client/src/store.js
client/src/translations/en.js
client/src/translations/es.js
client/src/translations/fr.js
client/src/utils/ajax.js
client/src/views/Auth.vue
client/src/views/Logout.vue
server/routes/users.js
server/routes/variants.js
server/utils/access.js

index ac15324..2be637c 100644 (file)
@@ -142,7 +142,7 @@ export default {
         case "Login":
           return "Connection token sent. Check your emails!";
         case "Register":
-          return "Registration complete! Please check your emails";
+          return "Registration complete! Please check your emails now";
         case "Update":
           return "Modifications applied!";
       }
index 0dccf1f..0d3a801 100644 (file)
@@ -1,11 +1,11 @@
 export function checkNameEmail(o) {
   if (typeof o.name === "string") {
-    if (o.name.length == 0) return "Empty name";
-    if (!o.name.match(/^[\w]+$/)) return "Name: alphanumerics and underscore";
+    if (o.name.length == 0) return "Missing name";
+    if (!o.name.match(/^[\w-]+$/)) return "Name: alphanumerics, hyphen and underscore";
   }
 
   if (typeof o.email === "string") {
-    if (o.email.length == 0) return "Empty email";
+    if (o.email.length == 0) return "Missing email";
     if (!o.email.match(/^[\w.+-]+@[\w.+-]+$/)) return "Invalid email";
   }
 
index edad3bb..e96535b 100644 (file)
@@ -8,6 +8,9 @@ const Parameters =
 
   // true if the server is at a different address
   cors: true,
+
+  // "include" if the server is at a different address
+  credentials: "same-origin"
 };
 
 export default Parameters;
index b81ec55..10ad10e 100644 (file)
@@ -1,4 +1,5 @@
-import { ajax } from "./utils/ajax";
+// NOTE: do not use ajax() here because ajax.js require the store for translations
+import params from "./parameters"; //for server URL
 import { getRandString } from "./utils/alea";
 
 // Global store: see https://medium.com/fullstackio/managing-state-in-vue-js-23a0352b1c87
@@ -12,8 +13,13 @@ export const store = {
   },
   socketCloseListener: null,
   initialize() {
-    ajax("/variants", "GET", res => {
-      this.state.variants = res.variantArray.sort(
+    fetch(
+      params.serverUrl + "/variants",
+      {method: "GET"},
+    )
+    .then(res => res.json())
+    .then(json => {
+      this.state.variants = json.variantArray.sort(
         (v1,v2) => v1.name.localeCompare(v2.name));
     });
     let mysid = localStorage.getItem("mysid");
@@ -32,25 +38,33 @@ export const store = {
     };
     // Slow verification through the server:
     // NOTE: still superficial identity usurpation possible, but difficult.
-    ajax("/whoami", "GET", res => {
-      this.state.user.id = res.id;
+    fetch(
+      params.serverUrl + "/whoami",
+      {
+        method: "GET",
+        credentials: params.credentials
+      }
+    )
+    .then(res => res.json())
+    .then(json => {
+      this.state.user.id = json.id;
       const storedId = localStorage.getItem("myid");
-      if (res.id > 0 && !storedId)
+      if (json.id > 0 && !storedId)
         // User cleared localStorage
-        localStorage.setItem("myid", res.id);
-      else if (res.id == 0 && !!storedId)
+        localStorage.setItem("myid", json.id);
+      else if (json.id == 0 && !!storedId)
         // User cleared cookie
         localStorage.removeItem("myid");
-      this.state.user.name = res.name;
+      this.state.user.name = json.name;
       const storedName = localStorage.getItem("myname");
-      if (!!res.name && !storedName)
+      if (!!json.name && !storedName)
         // User cleared localStorage
-        localStorage.setItem("myname", res.name);
-      else if (!res.name && !!storedName)
+        localStorage.setItem("myname", json.name);
+      else if (!json.name && !!storedName)
         // User cleared cookie
         localStorage.removeItem("myname");
-      this.state.user.email = res.email;
-      this.state.user.notify = res.notify;
+      this.state.user.email = json.email;
+      this.state.user.notify = json.notify;
     });
     // Settings initialized with values from localStorage
     const getItemDefaultTrue = (item) => {
index c807457..190b412 100644 (file)
@@ -10,6 +10,7 @@ export const translations = {
   Apply: "Apply",
   "Are you sure?": "Are you sure?",
   "Authentication successful!": "Authentication successful!",
+  "Back to Hall in 3 seconds...": "Back to Hall in 3 seconds...",
   "Back to list": "Back to list",
   "Black to move": "Black to move",
   "Black surrender": "Black surrender",
@@ -36,6 +37,7 @@ export const translations = {
   Email: "Email",
   "Email sent!": "Email sent!",
   "Empty message": "Empty message",
+  "Error: try to delete cookies": "Error: try to delete cookies",
   "Errors in FEN": "Errors in FEN",
   "Example game": "Example game",
   Go: "Go",
@@ -64,7 +66,7 @@ export const translations = {
   "Mutual agreement": "Mutual agreement",
   "My games": "My games",
   "My problems": "My problems",
-  "Name: alphanumerics and underscore": "Name: alphanumerics and underscore",
+  "Name: alphanumerics, hyphen and underscore": "Name: alphanumerics, hyphen and underscore",
   "Name or Email": "Name or Email",
   Next: "Next",
   "New connexion detected: tab now offline": "New connexion detected: tab now offline",
@@ -115,7 +117,9 @@ export const translations = {
   Time: "Time",
   "Undetermined result": "Undetermined result",
   Update: "Update",
+  "User creation failed. Try again": "User creation failed. Try again",
   "User name": "User name",
+  "User name or email already in use": "User name or email already in use",
   Variant: "Variant",
   Variants: "Variants",
   Versus: "Versus",
index 3c63ffb..94b8390 100644 (file)
@@ -10,6 +10,7 @@ export const translations = {
   Apply: "Aplicar",
   "Are you sure?": "¿Está usted seguro?",
   "Authentication successful!": "¡Autenticación exitosa!",
+  "Back to Hall in 3 seconds...": "Regreso al salón en 3 segundos...",
   "Back to list": "Volver a la lista",
   "Black to move": "Juegan las negras",
   "Black surrender": "Las negras abandonan",
@@ -36,6 +37,7 @@ export const translations = {
   Email: "Email",
   "Email sent!": "¡Email enviado!",
   "Empty message": "Mensaje vacio",
+  "Error: try to delete cookies": "Error: intente eliminar las cookies",
   "Errors in FEN": "FEN errónea",
   "Example game": "Ejemplo de partida",
   Go: "Go",
@@ -64,7 +66,7 @@ export const translations = {
   "Mutual agreement": "Acuerdo mutuo",
   "My games": "Mis partidas",
   "My problems": "Mis problemas",
-  "Name: alphanumerics and underscore": "Nombre: alfanuméricos y underscore",
+  "Name: alphanumerics, hyphen and underscore": "Nombre: alfanuméricos, guión y underscore",
   "Name or Email": "Nombre o Email",
   Next: "Próximo",
   "New connexion detected: tab now offline": "Nueva conexión detectada: pestaña ahora desconectada",
@@ -115,7 +117,9 @@ export const translations = {
   Time: "Tiempo",
   "Undetermined result": "Resultado indeterminado",
   Update: "Actualización",
+  "User creation failed. Try again": "Error al crear cuenta. inténtelo de nuevo",
   "User name": "Nombre de usuario",
+  "User name or email already in use": "Nombre de usuario o correo electrónico ya en uso",
   Variant: "Variante",
   Variants: "Variantes",
   Versus: "Contra",
index c724681..c5d82e9 100644 (file)
@@ -10,6 +10,7 @@ export const translations = {
   Apply: "Appliquer",
   "Authentication successful!": "Authentification réussie !",
   "Are you sure?": "Étes vous sûr?",
+  "Back to Hall in 3 seconds...": "Retour au Hall dans 3 secondes...",
   "Back to list": "Retour à la liste",
   "Black to move": "Trait aux noirs",
   "Black surrender": "Les noirs abandonnent",
@@ -36,6 +37,7 @@ export const translations = {
   Email: "Email",
   "Email sent!": "Email envoyé !",
   "Empty message": "Message vide",
+  "Error: try to delete cookies": "Erreur : essayez de supprimer les cookies",
   "Errors in FEN": "FEN erronée",
   "Example game": "Partie exemple",
   Go: "Go",
@@ -64,7 +66,7 @@ export const translations = {
   "Mutual agreement": "Accord mutuel",
   "My games": "Mes parties",
   "My problems": "Mes problèmes",
-  "Name: alphanumerics and underscore": "Nom: alphanumériques et underscore",
+  "Name: alphanumerics, hyphen and underscore": "Nom: alphanumériques, tiret et underscore",
   "Name or Email": "Nom ou Email",
   Next: "Suivant",
   "New connexion detected: tab now offline": "Nouvelle connexion détectée : onglet désormais hors ligne",
@@ -115,7 +117,9 @@ export const translations = {
   Time: "Temps",
   "Undetermined result": "Résultat indéterminé",
   Update: "Mise à jour",
+  "User creation failed. Try again": "Échec de la création du compte. Réessayez",
   "User name": "Nom d'utilisateur",
+  "User name or email already in use": "Nom d'utilisateur ou email déjà utilisés",
   Variant: "Variante",
   Variants: "Variantes",
   Versus: "Contre",
index e539f46..4573dd8 100644 (file)
@@ -1,8 +1,8 @@
 import params from "../parameters"; //for server URL
+import { store } from "../store"; //for translations
 
 // TODO: replace by fetch API ?
 // https://www.sitepoint.com/xmlhttprequest-vs-the-fetch-api-whats-best-for-ajax-in-2019/
-// Problem: fetch() does not set req.xhr... see access/ajax() security especially for /whoami
 
 // From JSON (encoded string values!) to "arg1=...&arg2=..."
 function toQueryString(data) {
@@ -25,7 +25,7 @@ export function ajax(url, method, data, success, error) {
   if (!success) success = () => {}; //by default, do nothing
   if (!error)
     error = errmsg => {
-      alert(errmsg);
+      alert(store.state.tr[errmsg] || errmsg);
     };
   xhr.onreadystatechange = function() {
     if (this.readyState == 4 && this.status == 200) {
index 36e79c8..7d682a0 100644 (file)
@@ -2,7 +2,9 @@
 main
   .row
     .col-sm-12.col-md-10.col-md-offset-1.col-lg-8.col-lg-offset-2
-      p {{ st.tr["Authentication successful!"] }}
+      div(v-if="authOk")
+        p {{ st.tr["Authentication successful!"] }}
+        p {{ st.tr["Back to Hall in 3 seconds..."] }}
 </template>
 
 <script>
@@ -12,7 +14,8 @@ export default {
   name: "my-auth",
   data: function() {
     return {
-      st: store.state
+      st: store.state,
+      authOk: false
     };
   },
   created: function() {
@@ -21,12 +24,16 @@ export default {
       "GET",
       { token: this.$route.params["token"] },
       res => {
+        this.authOk = true;
         this.st.user.id = res.id;
         this.st.user.name = res.name;
         this.st.user.email = res.email;
         this.st.user.notify = res.notify;
         localStorage["myname"] = res.name;
         localStorage["myid"] = res.id;
+        setTimeout(() => {
+          this.$router.replace("/");
+        }, 3000);
       }
     );
   }
index 62f057c..1740c7d 100644 (file)
@@ -2,7 +2,9 @@
 main
   .row
     .col-sm-12.col-md-10.col-md-offset-1.col-lg-8.col-lg-offset-2
-      p {{ st.tr["Logout successful!"] }}
+      div(v-if="logoutOk")
+        p {{ st.tr["Logout successful!"] }}
+        p {{ st.tr["Back to Hall in 3 seconds..."] }}
 </template>
 
 <script>
@@ -12,7 +14,8 @@ export default {
   name: "my-logout",
   data: function() {
     return {
-      st: store.state
+      st: store.state,
+      logoutOk: false
     };
   },
   created: function() {
@@ -20,12 +23,16 @@ export default {
       "/logout",
       "GET",
       () => {
+        this.logoutOk = true;
         this.st.user.id = 0;
         this.st.user.name = "";
         this.st.user.email = "";
         this.st.user.notify = false;
         localStorage.removeItem("myid");
         localStorage.removeItem("myname");
+        setTimeout(() => {
+          this.$router.replace("/");
+        }, 3000);
       }
     );
   }
index f9f1d86..1196675 100644 (file)
@@ -13,7 +13,12 @@ router.post('/register', access.unlogged, access.ajax, (req,res) => {
   {
     UserModel.create(name, email, notify, (err,ret) => {
       if (err)
-        res.json({errmsg: "User creation failed. Try again"});
+      {
+        const msg = err.code == "SQLITE_CONSTRAINT"
+          ? "User name or email already in use"
+          : "User creation failed. Try again";
+        res.json({errmsg: msg});
+      }
       else
       {
         const user = {
@@ -29,7 +34,7 @@ router.post('/register', access.unlogged, access.ajax, (req,res) => {
 });
 
 // NOTE: this method is safe because the sessionToken must be guessed
-router.get("/whoami", access.ajax, (req,res) => {
+router.get("/whoami", (req,res) => {
   const callback = (user) => {
     res.json({
       name: user.name,
index 3f7417e..57d4a30 100644 (file)
@@ -4,7 +4,7 @@ let router = require("express").Router();
 const VariantModel = require("../models/Variant");
 const access = require("../utils/access");
 
-router.get('/variants', access.ajax, function(req, res) {
+router.get('/variants', function(req, res) {
   VariantModel.getAll((err,variants) => {
     res.json(err || {variantArray:variants});
   });
index df86b75..36511db 100644 (file)
@@ -6,7 +6,7 @@ module.exports =
   logged: function(req, res, next) {
     const callback = () => {
       if (!loggedIn)
-        res.json({errmsg: "Error: please delete cookies and cross fingers"});
+        res.json({errmsg: "Error: try to delete cookies"});
       else next();
     };
     let loggedIn = undefined;
@@ -40,7 +40,7 @@ module.exports =
     // Just a quick heuristic, which should be enough
     const loggedIn = !!req.cookies.token;
     if (loggedIn)
-      res.json({errmsg: "Error: please delete cookies and cross fingers"});
+      res.json({errmsg: "Error: try to delete cookies"});
     else next();
   },