Implement cleaning methods (CRON tasks)
[vchess.git] / server / models / User.js
CommitLineData
8d7e2786 1var db = require("../utils/database");
badeb466 2var genToken = require("../utils/tokenGenerator");
c018b304 3var params = require("../config/parameters");
2be5d614 4var 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{
98db2082
BA
20 checkNameEmail: function(o)
21 {
22 if (typeof o.name === "string")
23 {
24 if (o.name.length == 0)
25 return "Empty name";
26 if (!o.name.match(/^[\w]+$/))
27 return "Bad characters in name";
28 }
29 if (typeof o.email === "string")
30 {
31 if (o.email.length == 0)
32 return "Empty email";
33 if (!o.email.match(/^[\w.+-]+@[\w.+-]+$/))
34 return "Bad characters in email";
35 }
36 },
37
ab4f4bf2
BA
38 // NOTE: parameters are already cleaned (in controller), thus no sanitization here
39 create: function(name, email, notify, callback)
40 {
41 db.serialize(function() {
42 const insertQuery =
43 "INSERT INTO Users " +
83494c7f
BA
44 "(name, email, notify, created) VALUES " +
45 "('" + name + "', '" + email + "', " + notify + "," + Date.now() + ")";
ab4f4bf2
BA
46 db.run(insertQuery, err => {
47 if (!!err)
48 return callback(err);
49 db.get("SELECT last_insert_rowid() AS rowid", callback);
50 });
c018b304 51 });
ab4f4bf2 52 },
8d7e2786 53
ab4f4bf2
BA
54 // Find one user (by id, name, email, or token)
55 getOne: function(by, value, cb)
56 {
57 const delimiter = (typeof value === "string" ? "'" : "");
58 db.serialize(function() {
59 const query =
60 "SELECT * " +
61 "FROM Users " +
62 "WHERE " + by + " = " + delimiter + value + delimiter;
63 db.get(query, cb);
64 });
65 },
8d7e2786 66
ed9c9c37
BA
67 getByIds: function(ids, cb) {
68 db.serialize(function() {
69 const query =
70 "SELECT id, name " +
1f49533d 71 "FROM Users " +
ed9c9c37
BA
72 "WHERE id IN (" + ids + ")";
73 db.all(query, cb);
74 });
1f49533d
BA
75 },
76
ab4f4bf2
BA
77 /////////
78 // MODIFY
8d7e2786 79
ab4f4bf2
BA
80 setLoginToken: function(token, uid, cb)
81 {
82 db.serialize(function() {
83 const query =
8a477a7e 84 "UPDATE Users " +
ab4f4bf2 85 "SET loginToken = '" + token + "', loginTime = " + Date.now() + " " +
8a477a7e 86 "WHERE id = " + uid;
ab4f4bf2 87 db.run(query, cb);
0bd5933d 88 });
ab4f4bf2 89 },
8d7e2786 90
ab4f4bf2
BA
91 // Set session token only if empty (first login)
92 // TODO: weaker security (but avoid to re-login everywhere after each logout)
93 trySetSessionToken: function(uid, cb)
94 {
95 // Also empty the login token to invalidate future attempts
96 db.serialize(function() {
97 const querySessionToken =
98 "SELECT sessionToken " +
99 "FROM Users " +
100 "WHERE id = " + uid;
101 db.get(querySessionToken, (err,ret) => {
102 if (!!err)
103 return cb(err);
104 const token = ret.sessionToken || genToken(params.token.length);
105 const queryUpdate =
106 "UPDATE Users " +
107 "SET loginToken = NULL" +
108 (!ret.sessionToken ? (", sessionToken = '" + token + "'") : "") + " " +
109 "WHERE id = " + uid;
110 db.run(queryUpdate);
111 cb(null, token);
112 });
113 });
114 },
115
116 updateSettings: function(user, cb)
117 {
118 db.serialize(function() {
119 const query =
120 "UPDATE Users " +
121 "SET name = '" + user.name + "'" +
122 ", email = '" + user.email + "'" +
123 ", notify = " + user.notify + " " +
124 "WHERE id = " + user.id;
125 db.run(query, cb);
126 });
127 },
5d04793e
BA
128
129 /////////////////
130 // NOTIFICATIONS
131
2be5d614 132 tryNotify: function(oppId, message)
5d04793e 133 {
2be5d614
BA
134 UserModel.getOne("id", oppId, (err,opp) => {
135 if (!err || !opp.notify)
136 return; //error is ignored here (TODO: should be logged)
137 const subject = "vchess.club - notification";
138 const body = "Hello " + opp.name + "!\n" + message;
139 sendEmail(params.mail.noreply, opp.email, subject, body, err => {
140 res.json(err || {});
141 });
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 =
155 "SELECT id, sessionToken, created " +
156 "FROM Users";
157 db.all(query, (err, users) => {
158 users.forEach(u => {
159 // Remove unlogged users for >1 day
160 if (!u.sessionToken && tsNow - u.created > day)
161 db.run("DELETE FROM Users WHERE id = " + u.id);
162 });
163 });
164 });
165 },
166}
d431028c 167
ab4f4bf2 168module.exports = UserModel;