'update'
[qomet.git] / models / user.js
1 const params = require("../config/parameters");
2 const db = require("../utils/database");
3
4 const UserModel =
5 {
6 /*
7 * Structure:
8 * _id: BSON id
9 * ** Strings, identification informations:
10 * email
11 * name
12 * initials : computed, Benjamin Auder --> ba ...etc
13 * loginToken: {
14 * value: string
15 * timestamp: datetime (validity)
16 * ip: address of requesting machine
17 * }
18 * sessionTokens (array): cookie identification
19 */
20
21 // BASIC FUNCTIONS
22 //////////////////
23
24 getInitialsByPrefix: function(prefix, cb)
25 {
26 db.users.find(
27 { initials: new RegExp("^" + prefix) },
28 { initials: 1, _id: 0 },
29 cb
30 );
31 },
32
33 insert: function(newUser, cb)
34 {
35 db.users.insert(Object.assign({},
36 newUser,
37 {
38 loginToken: { },
39 sessionTokens: [ ],
40 }),
41 cb
42 );
43 },
44
45 getByLoginToken: function(token, cb)
46 {
47 db.users.findOne(
48 { "loginToken.value": token },
49 cb
50 );
51 },
52
53 getBySessionToken: function(token, cb)
54 {
55 db.users.findOne(
56 { sessionTokens: token},
57 cb
58 );
59 },
60
61 getById: function(uid, cb)
62 {
63 db.users.findOne(
64 { _id: uid },
65 cb
66 );
67 },
68
69 getByEmail: function(email, cb)
70 {
71 db.users.findOne(
72 { email: email },
73 cb
74 );
75 },
76
77 getByInitials: function(initials, cb)
78 {
79 db.users.findOne(
80 { initials: initials },
81 cb
82 );
83 },
84
85 getUnlogged: function(cb)
86 {
87 var tsNow = new Date().getTime();
88 // 86400000 = 24 hours in milliseconds
89 var day = 86400000;
90 db.users.find({}, (err,userArray) => {
91 let unlogged = userArray.filter( u => {
92 return u.sessionTokens.length==0 && u._id.getTimestamp().getTime() + day < tsNow;
93 });
94 cb(err, unlogged);
95 });
96 },
97
98 getAll: function(cb)
99 {
100 db.users.find({}, cb);
101 },
102
103 setLoginToken: function(token, uid, ip, cb)
104 {
105 db.users.update(
106 { _id: uid },
107 { $set: { loginToken: {
108 value: token,
109 timestamp: new Date().getTime(),
110 ip: ip,
111 } } },
112 cb
113 );
114 },
115
116 setSessionToken: function(token, uid, cb)
117 {
118 // Also empty the login token to invalidate future attempts
119 db.users.update(
120 { _id: uid },
121 {
122 $set: { loginToken: {} },
123 $push: { sessionTokens: {
124 $each: [token],
125 $slice: -7 //only allow 7 simultaneous connections per user (TODO?)
126 }}
127 },
128 cb
129 );
130 },
131
132 removeToken: function(uid, token, cb)
133 {
134 db.users.update(
135 { _id: uid },
136 { $pull: {sessionTokens: token} },
137 cb
138 );
139 },
140
141 // TODO: later, allow account removal
142 remove: function(uids)
143 {
144 db.users.remove({_id: uids});
145 },
146
147 /////////////////////
148 // ADVANCED FUNCTIONS
149
150 create: function(newUser, callback)
151 {
152 // Determine initials from name parts
153 let nameParts = newUser.name.split(/[ -]+/);
154 let initials = nameParts.map( n => { return n.charAt(0).toLowerCase(); }).join("");
155 // First retrieve all users with similar prefix initials
156 UserModel.getInitialsByPrefix(initials, (err,userArray) => {
157 if (!!userArray && userArray.length == 1)
158 initials = initials + "2"; //thus number == users count for this hash
159 else if (!!userArray && userArray.length > 1)
160 {
161 // Pick the highest number after initials (if any), and increment
162 let numbers = userArray.map( u => {
163 let digitMatch = u.initials.match(/[0-9]/);
164 if (!digitMatch)
165 return 1; //irrelevant
166 let firstDigit = digitMatch.index;
167 return parseInt(u.initials.slice(digitMatch.index));
168 });
169 initials = initials + (Math.max(...numbers)+1);
170 }
171 Object.assign(newUser, {initials: initials});
172 UserModel.insert(newUser, callback);
173 });
174 },
175
176 whitelistCheck: function(email)
177 {
178 if (params.whitelist.length == 0)
179 return true; //no whitelist, everyone allowed
180 for (let w of params.whitelist)
181 {
182 if ((w.indexOf('@') >= 0 && w==email) || !!email.match(new RegExp(w+"$")))
183 return true;
184 }
185 return false;
186 },
187
188 cleanUsersDb: function()
189 {
190 UserModel.getUnlogged( (err,unlogged) => {
191 UserModel.remove(unlogged);
192 });
193 },
194 }
195
196 module.exports = UserModel;