1 let router
= require("express").Router();
2 const UserModel
= require('../models/User');
3 const sendEmail
= require('../utils/mailer');
4 const genToken
= require("../utils/tokenGenerator");
5 const access
= require("../utils/access");
6 const params
= require("../config/parameters");
7 const sanitizeHtml_pkg
= require('sanitize-html');
8 const { exec
} = require("child_process");
11 'h3', 'h4', 'h5', 'h6', 'blockquote', 'p', 'a', 'ul', 'ol', 'li', 'b',
12 'i', 'strong', 'em', 'strike', 'code', 'hr', 'br', 'div', 'table',
13 'thead', 'caption', 'tbody', 'tr', 'th', 'td', 'pre'
15 function sanitizeHtml(text
) {
16 return sanitizeHtml_pkg(text
, { allowedTags: allowedTags
});
19 router
.get("/userbio", access
.ajax
, (req
,res
) => {
20 const uid
= req
.query
["id"];
21 if (!!(uid
.toString().match(/^[0-9]+$/))) {
22 UserModel
.getBio(uid
, (err
, bio
) => {
28 router
.put('/userbio', access
.logged
, access
.ajax
, (req
,res
) => {
29 const bio
= sanitizeHtml(req
.body
.bio
);
30 UserModel
.setBio(req
.userId
, bio
);
34 router
.post('/register', access
.unlogged
, access
.ajax
, (req
,res
) => {
35 const name
= req
.body
.name
;
36 const email
= req
.body
.email
;
37 const notify
= !!req
.body
.notify
;
38 if (UserModel
.checkNameEmail({ name: name
, email: email
})) {
39 UserModel
.create(name
, email
, notify
, (err
, ret
) => {
41 const msg
= err
.code
== "SQLITE_CONSTRAINT"
42 ? "User name or email already in use"
43 : "User creation failed. Try again";
44 res
.json({ errmsg: msg
});
52 setAndSendLoginToken("Welcome to " + params
.siteURL
, user
);
53 // Update tournament DB (TODO: if error, log it)
54 exec(params
.tourneyPath
+ "/dbsync/insert_user.py " + ret
.id
);
61 // NOTE: this method is safe because the sessionToken must be guessed
62 router
.get("/whoami", access
.ajax
, (req
,res
) => {
63 const callback
= (user
) => {
77 if (!req
.cookies
.token
) callback(anonymous
);
78 else if (req
.cookies
.token
.match(/^[a-z0-9]+$/)) {
80 "sessionToken", req
.cookies
.token
, "name, email, id, notify",
81 (err
, user
) => callback(user
|| anonymous
)
86 // NOTE: this method is safe because only IDs and names are returned
87 router
.get("/users", access
.ajax
, (req
,res
) => {
88 const ids
= req
.query
["ids"];
89 // NOTE: slightly too permissive RegExp
90 if (!!ids
&& !!ids
.match(/^([0-9]+,?)+$/)) {
91 UserModel
.getByIds(ids
, (err
, users
) => {
92 res
.json({ users: users
});
97 router
.put('/update', access
.logged
, access
.ajax
, (req
,res
) => {
98 const name
= req
.body
.name
;
99 const email
= req
.body
.email
;
100 if (UserModel
.checkNameEmail({ name: name
, email: email
})) {
105 notify: !!req
.body
.notify
,
107 UserModel
.updateSettings(user
);
108 exec(params
.tourneyPath
+ "/dbsync/update_user.py " + ret
.id
);
113 // Authentication-related methods:
115 // to: object user (to who we send an email)
116 function setAndSendLoginToken(subject
, to
) {
117 // Set login token and send welcome(back) email with auth link
118 const token
= genToken(params
.token
.length
);
119 UserModel
.setLoginToken(token
, to
.id
);
121 "Hello " + to
.name
+ " !" + `
123 "Access your account here: " +
124 params
.siteURL
+ "/#/authenticate/" + token
+ `
126 "Token will expire in " + params
.token
.expire
/(1000*60) + " minutes."
127 sendEmail(params
.mail
.noreply
, to
.email
, subject
, body
);
130 router
.get('/sendtoken', access
.unlogged
, access
.ajax
, (req
,res
) => {
131 const nameOrEmail
= decodeURIComponent(req
.query
.nameOrEmail
);
132 const type
= (nameOrEmail
.indexOf('@') >= 0 ? "email" : "name");
133 if (UserModel
.checkNameEmail({ [type
]: nameOrEmail
})) {
134 UserModel
.getOne(type
, nameOrEmail
, "id, name, email", (err
, user
) => {
135 access
.checkRequest(res
, err
, user
, "Unknown user", () => {
136 setAndSendLoginToken("Token for " + params
.siteURL
, user
);
143 router
.get('/authenticate', access
.unlogged
, access
.ajax
, (req
,res
) => {
144 if (!req
.query
.token
.match(/^[a-z0-9]+$/))
145 return res
.json({ errmsg: "Bad token" });
147 "loginToken", req
.query
.token
, "id, name, email, notify",
149 access
.checkRequest(res
, err
, user
, "Invalid token", () => {
150 // If token older than params.tokenExpire, do nothing
151 if (Date
.now() > user
.loginTime
+ params
.token
.expire
)
152 res
.json({ errmsg: "Token expired" });
154 // Generate session token (if not exists) + destroy login token
155 UserModel
.trySetSessionToken(user
.id
, (token
) => {
156 res
.cookie("token", token
, {
158 secure: !!params
.siteURL
.match(/^https/),
159 maxAge: params
.cookieExpire
,
169 router
.get('/logout', access
.logged
, access
.ajax
, (req
,res
) => {
170 res
.clearCookie("token");
174 module
.exports
= router
;