1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
import ApiManager, { Registration } from "./ApiManager";
import { Method } from "../RouteManager";
import { Database } from "../database";
import { msToTime } from "../ActionUtilities";
import * as bcrypt from "bcrypt-nodejs";
import { Opt } from "../../new_fields/Doc";
export const timeMap: { [id: string]: number } = {};
interface ActivityUnit {
user: string;
duration: number;
}
export default class UserManager extends ApiManager {
protected initialize(register: Registration): void {
register({
method: Method.GET,
subscription: "/getUsers",
secureHandler: async ({ res }) => {
const cursor = await Database.Instance.query({}, { email: 1, userDocumentId: 1 }, "users");
const results = await cursor.toArray();
res.send(results.map(user => ({ email: user.email, userDocumentId: user.userDocumentId })));
}
});
register({
method: Method.GET,
subscription: "/getUserDocumentId",
secureHandler: ({ res, user }) => res.send(user.userDocumentId)
});
register({
method: Method.GET,
subscription: "/getCurrentUser",
secureHandler: ({ res, user: { _id, email } }) => res.send(JSON.stringify({ id: _id, email })),
publicHandler: ({ res }) => res.send(JSON.stringify({ id: "__guest__", email: "" }))
});
register({
method: Method.POST,
subscription: '/internalResetPassword',
secureHandler: async ({ user, req, res }) => {
const result: any = {};
const { curr_pass, new_pass, new_confirm } = req.body;
// perhaps should assert whether curr password is entered correctly
const validated = await new Promise<Opt<boolean>>(resolve => {
bcrypt.compare(curr_pass, user.password, (err, passwords_match) => {
if (err || !passwords_match) {
result.error = [{ msg: "Incorrect current password" }];
res.send(result);
resolve(undefined);
} else {
resolve(passwords_match);
}
});
});
if (validated === undefined) {
return;
}
req.assert("new_pass", "Password must be at least 4 characters long").len({ min: 4 });
req.assert("new_confirm", "Passwords do not match").equals(new_pass);
if (curr_pass === new_pass) {
result.error = [{ msg: "Current and new password are the same" }];
}
// was there error in validating new passwords?
if (req.validationErrors()) {
// was there error?
result.error = req.validationErrors();
}
// will only change password if there are no errors.
if (!result.error) {
user.password = new_pass;
user.passwordResetToken = undefined;
user.passwordResetExpires = undefined;
}
user.save(err => {
if (err) {
result.error = [{ msg: "Error while saving new password" }];
}
});
res.send(result);
}
});
register({
method: Method.GET,
subscription: "/activity",
secureHandler: ({ res }) => {
const now = Date.now();
const activeTimes: ActivityUnit[] = [];
const inactiveTimes: ActivityUnit[] = [];
for (const user in timeMap) {
const time = timeMap[user];
const duration = now - time;
const target = (duration / 1000) < (60 * 5) ? activeTimes : inactiveTimes;
target.push({ user, duration });
}
const process = (target: { user: string, duration: number }[]) => {
const comparator = (first: ActivityUnit, second: ActivityUnit) => first.duration - second.duration;
const sorted = target.sort(comparator);
return sorted.map(({ user, duration }) => `${user} (${msToTime(duration)})`);
};
res.render("user_activity.pug", {
title: "User Activity",
active: process(activeTimes),
inactive: process(inactiveTimes)
});
}
});
}
}
|