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!";
}
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";
}
// 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;
-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
},
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");
};
// 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) => {
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",
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",
"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",
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",
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",
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",
"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",
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",
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",
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",
"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",
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",
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) {
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) {
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>
name: "my-auth",
data: function() {
return {
- st: store.state
+ st: store.state,
+ authOk: false
};
},
created: function() {
"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);
}
);
}
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>
name: "my-logout",
data: function() {
return {
- st: store.state
+ st: store.state,
+ logoutOk: false
};
},
created: function() {
"/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);
}
);
}
{
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 = {
});
// 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,
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});
});
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;
// 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();
},