Improve games/challenges display and fix MyGames page reactivity (using () for now...)
[vchess.git] / server / models / User.js
CommitLineData
c5c47010
BA
1const db = require("../utils/database");
2const genToken = require("../utils/tokenGenerator");
3const params = require("../config/parameters");
4const sendEmail = require('../utils/mailer');
8d7e2786
BA
5
6/*
7 * Structure:
8 * _id: integer
9 * name: varchar
10 * email: varchar
11 * loginToken: token on server only
12 * loginTime: datetime (validity)
13 * sessionToken: token in cookies for authentication
14 * notify: boolean (send email notifications for corr games)
83494c7f 15 * created: datetime
8d7e2786
BA
16 */
17
ab4f4bf2 18const UserModel =
8d7e2786 19{
dac39588
BA
20 checkNameEmail: function(o)
21 {
866842c3 22 return (
188b4a8f
BA
23 (!o.name || !!(o.name.match(/^[\w-]+$/))) &&
24 (!o.email || !!(o.email.match(/^[\w.+-]+@[\w.+-]+$/)))
866842c3 25 );
dac39588 26 },
98db2082 27
866842c3 28 create: function(name, email, notify, cb)
dac39588
BA
29 {
30 db.serialize(function() {
866842c3 31 const query =
dac39588
BA
32 "INSERT INTO Users " +
33 "(name, email, notify, created) VALUES " +
866842c3
BA
34 "('" + name + "','" + email + "'," + notify + "," + Date.now() + ")";
35 db.run(query, function(err) {
36 cb(err, {uid: this.lastID});
dac39588
BA
37 });
38 });
39 },
8d7e2786 40
866842c3 41 // Find one user by id, name, email, or token
dac39588
BA
42 getOne: function(by, value, cb)
43 {
44 const delimiter = (typeof value === "string" ? "'" : "");
45 db.serialize(function() {
46 const query =
47 "SELECT * " +
48 "FROM Users " +
49 "WHERE " + by + " = " + delimiter + value + delimiter;
50 db.get(query, cb);
51 });
52 },
8d7e2786 53
ed9c9c37
BA
54 getByIds: function(ids, cb) {
55 db.serialize(function() {
56 const query =
57 "SELECT id, name " +
1f49533d 58 "FROM Users " +
ed9c9c37
BA
59 "WHERE id IN (" + ids + ")";
60 db.all(query, cb);
61 });
1f49533d
BA
62 },
63
dac39588
BA
64 /////////
65 // MODIFY
8d7e2786 66
866842c3 67 setLoginToken: function(token, uid)
dac39588
BA
68 {
69 db.serialize(function() {
70 const query =
71 "UPDATE Users " +
866842c3 72 "SET loginToken = '" + token + "',loginTime = " + Date.now() + " " +
dac39588 73 "WHERE id = " + uid;
866842c3 74 db.run(query);
dac39588
BA
75 });
76 },
8d7e2786 77
d9a7a1e4
BA
78 setNewsRead: function(uid)
79 {
80 db.serialize(function() {
81 const query =
82 "UPDATE Users " +
83 "SET newsRead = " + Date.now() + " " +
84 "WHERE id = " + uid;
85 db.run(query);
86 });
87 },
88
dac39588
BA
89 // Set session token only if empty (first login)
90 // NOTE: weaker security (but avoid to re-login everywhere after each logout)
91 // TODO: option would be to reset all tokens periodically, e.g. every 3 months
58e7b94e 92 trySetSessionToken: function(uid, cb)
dac39588 93 {
dac39588 94 db.serialize(function() {
866842c3 95 let query =
dac39588
BA
96 "SELECT sessionToken " +
97 "FROM Users " +
98 "WHERE id = " + uid;
866842c3 99 db.get(query, (err,ret) => {
dac39588 100 const token = ret.sessionToken || genToken(params.token.length);
866842c3 101 query =
dac39588 102 "UPDATE Users " +
866842c3 103 // Also empty the login token to invalidate future attempts
dac39588
BA
104 "SET loginToken = NULL" +
105 (!ret.sessionToken ? (", sessionToken = '" + token + "'") : "") + " " +
106 "WHERE id = " + uid;
866842c3
BA
107 db.run(query);
108 cb(token);
dac39588
BA
109 });
110 });
111 },
ab4f4bf2 112
866842c3 113 updateSettings: function(user)
dac39588
BA
114 {
115 db.serialize(function() {
116 const query =
117 "UPDATE Users " +
118 "SET name = '" + user.name + "'" +
119 ", email = '" + user.email + "'" +
120 ", notify = " + user.notify + " " +
121 "WHERE id = " + user.id;
866842c3 122 db.run(query);
dac39588
BA
123 });
124 },
5d04793e
BA
125
126 /////////////////
127 // NOTIFICATIONS
128
fe4c7e67 129 notify: function(user, message)
5d04793e 130 {
fe4c7e67 131 const subject = "vchess.club - notification";
f53871db 132 const body = "Hello " + user.name + " !" + `
a749972c 133` + message;
fe4c7e67
BA
134 sendEmail(params.mail.noreply, user.email, subject, body);
135 },
136
137 tryNotify: function(id, message)
138 {
139 UserModel.getOne("id", id, (err,user) => {
866842c3
BA
140 if (!err && user.notify)
141 UserModel.notify(user, message);
2be5d614 142 });
83494c7f
BA
143 },
144
145 ////////////
146 // CLEANING
ab4f4bf2 147
83494c7f
BA
148 cleanUsersDb: function()
149 {
150 const tsNow = Date.now();
151 // 86400000 = 24 hours in milliseconds
152 const day = 86400000;
153 db.serialize(function() {
154 const query =
a97bdbda 155 "SELECT id, sessionToken, created, name, email " +
83494c7f
BA
156 "FROM Users";
157 db.all(query, (err, users) => {
158 users.forEach(u => {
a97bdbda 159 // Remove unlogged users for > 24h
83494c7f 160 if (!u.sessionToken && tsNow - u.created > day)
a97bdbda
BA
161 {
162 notify(
163 u,
164 "Your account has been deleted because " +
165 "you didn't log in for 24h after registration"
166 );
83494c7f 167 db.run("DELETE FROM Users WHERE id = " + u.id);
a97bdbda 168 }
83494c7f
BA
169 });
170 });
171 });
172 },
173}
d431028c 174
ab4f4bf2 175module.exports = UserModel;