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 | var rFS = require('fs').readFileSync;
|
32 |
|
33 | var ld = require('lodash');
|
34 | var passport = require('passport');
|
35 | var jwt = require('jsonwebtoken');
|
36 | var testMode = false;
|
37 | var express;
|
38 | try {
|
39 |
|
40 | express = require('ep_etherpad-lite/node_modules/express');
|
41 | }
|
42 | catch (e) {
|
43 |
|
44 | testMode = true;
|
45 | express = require('express');
|
46 | }
|
47 | var settings;
|
48 | try {
|
49 |
|
50 | settings = require('ep_etherpad-lite/node/utils/Settings');
|
51 | }
|
52 | catch (e) {
|
53 |
|
54 | if (process.env.TEST_LDAP) {
|
55 | settings = {
|
56 | 'ep_mypads': {
|
57 | 'ldap': {
|
58 | 'url': 'ldap://rroemhild-test-openldap',
|
59 | 'bindDN': 'cn=admin,dc=planetexpress,dc=com',
|
60 | 'bindCredentials': 'GoodNewsEveryone',
|
61 | 'searchBase': 'ou=people,dc=planetexpress,dc=com',
|
62 | 'searchFilter': '(uid={{username}})',
|
63 | 'properties': {
|
64 | 'login': 'uid',
|
65 | 'email': 'mail',
|
66 | 'firstname': 'givenName',
|
67 | 'lastname': 'sn'
|
68 | },
|
69 | 'defaultLang': 'fr'
|
70 | }
|
71 | }
|
72 | };
|
73 | } else {
|
74 | settings = {};
|
75 | }
|
76 | }
|
77 | var bodyParser = require('body-parser');
|
78 | var cookieParser = require('cookie-parser');
|
79 | var decode = require('js-base64').Base64.decode;
|
80 |
|
81 | var conf = require('./configuration.js');
|
82 | var mail = require('./mail.js');
|
83 | var user = require('./model/user.js');
|
84 | var userCache = require('./model/user-cache.js');
|
85 | var group = require('./model/group.js');
|
86 | var pad = require('./model/pad.js');
|
87 | var auth = require('./auth.js');
|
88 | var perm = require('./perm.js');
|
89 | var common = require('./model/common.js');
|
90 |
|
91 | module.exports = (function () {
|
92 | 'use strict';
|
93 |
|
94 | var api = {};
|
95 | api.initialRoute = '/mypads/api/';
|
96 | var authAPI;
|
97 | var configurationAPI;
|
98 | var userAPI;
|
99 | var groupAPI;
|
100 | var padAPI;
|
101 | var cacheAPI;
|
102 | var statsAPI;
|
103 |
|
104 | |
105 |
|
106 |
|
107 |
|
108 |
|
109 |
|
110 |
|
111 |
|
112 |
|
113 |
|
114 |
|
115 | api.init = function (app, callback) {
|
116 |
|
117 | app.use(bodyParser.json());
|
118 | app.use(cookieParser());
|
119 | app.use('/mypads', express.static(__dirname + '/static'));
|
120 | if (testMode) {
|
121 |
|
122 | app.use('/mypads/functest', express.static(__dirname + '/spec/frontend'));
|
123 | }
|
124 | var rFSOpts = { encoding: 'utf8' };
|
125 | api.l10n = {
|
126 | mail: {
|
127 | de: JSON.parse(rFS(__dirname + '/templates/mail_de.json', rFSOpts)),
|
128 | en: JSON.parse(rFS(__dirname + '/templates/mail_en.json', rFSOpts)),
|
129 | es: JSON.parse(rFS(__dirname + '/templates/mail_es.json', rFSOpts)),
|
130 | fr: JSON.parse(rFS(__dirname + '/templates/mail_fr.json', rFSOpts)),
|
131 | it: JSON.parse(rFS(__dirname + '/templates/mail_it.json', rFSOpts)),
|
132 | }
|
133 | };
|
134 | auth.init(app);
|
135 | authAPI(app);
|
136 | configurationAPI(app);
|
137 | userAPI(app);
|
138 | groupAPI(app);
|
139 | padAPI(app);
|
140 | cacheAPI(app);
|
141 | statsAPI(app);
|
142 | perm.init(app);
|
143 |
|
144 | |
145 |
|
146 |
|
147 | var idxTpl = ld.template(rFS(__dirname + '/templates/index.html', rFSOpts));
|
148 | var idxHandle = function (req, res) {
|
149 | var mypadsURL = req.protocol + '://' + req.header('host') + req.path;
|
150 | return res.send(idxTpl({
|
151 | HTMLExtraHead: conf.get('HTMLExtraHead'),
|
152 | hideHelpBlocks: conf.get('hideHelpBlocks'),
|
153 | mypadsURL: mypadsURL
|
154 | }));
|
155 | };
|
156 | app.get('/mypads/index.html', idxHandle);
|
157 | app.get('/mypads/', idxHandle);
|
158 |
|
159 | callback(null);
|
160 | };
|
161 |
|
162 | |
163 |
|
164 |
|
165 |
|
166 |
|
167 |
|
168 |
|
169 | var fn = {};
|
170 |
|
171 | |
172 |
|
173 |
|
174 |
|
175 |
|
176 |
|
177 |
|
178 |
|
179 | fn.get = function (module, req, res, next, cond) {
|
180 | try {
|
181 | module.get(req.params.key, function (err, val) {
|
182 | if (err) {
|
183 | return res.status(404).send({
|
184 | error: err.message,
|
185 | key: req.params.key
|
186 | });
|
187 | }
|
188 | if (cond && !cond(val)) {
|
189 | if (conf.get('allPadsPublicsAuthentifiedOnly')) {
|
190 | return fn.denied(res, 'BACKEND.ERROR.AUTHENTICATION.MUST_BE');
|
191 | } else {
|
192 | return fn.denied(res, 'BACKEND.ERROR.AUTHENTICATION.DENIED_RECORD');
|
193 | }
|
194 | } else {
|
195 | return res.send({ key: req.params.key, value: val });
|
196 | }
|
197 | });
|
198 | }
|
199 | catch (e) {
|
200 | res.status(400).send({ error: e.message });
|
201 | }
|
202 | };
|
203 |
|
204 | |
205 |
|
206 |
|
207 |
|
208 |
|
209 |
|
210 |
|
211 |
|
212 |
|
213 | fn.set = function (setFn, key, value, req, res) {
|
214 | try {
|
215 | setFn(function (err, data) {
|
216 | if (err) { return res.status(400).send({ error: err.message }); }
|
217 | res.send({ success: true, key: key || data._id, value: data || value });
|
218 | });
|
219 | }
|
220 | catch (e) {
|
221 | res.status(400).send({ error: e.message });
|
222 | }
|
223 | };
|
224 |
|
225 | |
226 |
|
227 |
|
228 |
|
229 |
|
230 |
|
231 |
|
232 |
|
233 |
|
234 | fn.del = function (delFn, req, res) {
|
235 | var key = req.params.key;
|
236 | delFn(key, function (err) {
|
237 | if (err) { return res.status(404).send({ error: err.message }); }
|
238 | res.send({ success: true, key: key });
|
239 | });
|
240 | };
|
241 |
|
242 | |
243 |
|
244 |
|
245 |
|
246 |
|
247 | fn.denied = function (res, errCode) {
|
248 | return res
|
249 | .status(401)
|
250 | .send({ error: errCode });
|
251 | };
|
252 |
|
253 | |
254 |
|
255 |
|
256 |
|
257 |
|
258 |
|
259 |
|
260 | fn.mailMessage = function (tpl, data, lang) {
|
261 | lang = lang || conf.get('defaultLanguage');
|
262 | tpl = ld.template(api.l10n.mail[lang][tpl]);
|
263 | return tpl(data);
|
264 | };
|
265 |
|
266 |
|
267 | |
268 |
|
269 |
|
270 |
|
271 |
|
272 |
|
273 | fn.ensureAuthenticated = passport.authenticate('jwt', { session: false });
|
274 |
|
275 | |
276 |
|
277 |
|
278 |
|
279 |
|
280 | fn.isAdmin = function (req) {
|
281 | var token = req.query.auth_token || req.body.auth_token;
|
282 | if (!token) { return false; }
|
283 | try {
|
284 | var jwt_payload = jwt.verify(token, auth.secret);
|
285 | var admin = auth.adminTokens[jwt_payload.login];
|
286 | return (admin && (admin.key === jwt_payload.key));
|
287 | }
|
288 | catch (e) { return false; }
|
289 | };
|
290 |
|
291 | |
292 |
|
293 |
|
294 |
|
295 |
|
296 |
|
297 | fn.ensureAdmin = function (req, res, next) {
|
298 | if (!fn.isAdmin(req)) {
|
299 | return fn.denied(res, 'BACKEND.ERROR.AUTHENTICATION.ADMIN');
|
300 | } else {
|
301 | return next();
|
302 | }
|
303 | };
|
304 |
|
305 | |
306 |
|
307 |
|
308 |
|
309 |
|
310 |
|
311 | fn.ensureAdminOrSelf = function (req, res, next) {
|
312 | var isAdmin = fn.isAdmin(req);
|
313 |
|
314 | var token = (req.body.auth_token || req.query.auth_token);
|
315 | var login = req.params.key;
|
316 | var u = auth.fn.getUser(token);
|
317 | var isSelf = (u && login === u.login);
|
318 | if (isSelf) { req.mypadsLogin = u.login; }
|
319 |
|
320 | if (!isAdmin && !isSelf) {
|
321 | return fn.denied(res, 'BACKEND.ERROR.AUTHENTICATION.DENIED');
|
322 | } else {
|
323 | return next();
|
324 | }
|
325 | };
|
326 |
|
327 | |
328 |
|
329 |
|
330 |
|
331 | authAPI = function (app) {
|
332 | var authRoute = api.initialRoute + 'auth';
|
333 |
|
334 | |
335 |
|
336 |
|
337 |
|
338 |
|
339 |
|
340 |
|
341 |
|
342 | app.post(authRoute + '/check', fn.ensureAuthenticated,
|
343 | function (req, res) {
|
344 | auth.fn.localFn(req.body.login, req.body.password, function (err, u) {
|
345 | if (err) { return res.status(400).send({ error: err.message }); }
|
346 | if (!u) {
|
347 | var emsg = 'BACKEND.ERROR.AUTHENTICATION.PASSWORD_INCORRECT';
|
348 | return res.status(400).send({ error: emsg });
|
349 | }
|
350 | res.status(200).send({ success: true });
|
351 | });
|
352 | }
|
353 | );
|
354 |
|
355 | |
356 |
|
357 |
|
358 |
|
359 |
|
360 |
|
361 |
|
362 |
|
363 |
|
364 | app.post(authRoute + '/login/cas', function (req, res) {
|
365 | auth.fn.casAuth(req, res, function(err, infos) {
|
366 | if (err) { return res.status(400).send({ error: err.message }); }
|
367 |
|
368 | auth.fn.JWTFn(req, infos, false, function (err, u, info) {
|
369 | if (err) { return res.status(400).send({ error: err.message }); }
|
370 | if (!u) { return res.status(400).send({ error: info.message }); }
|
371 | if (u.active) {
|
372 | var token = {
|
373 | login: u.login,
|
374 | key: auth.tokens[u.login].key
|
375 | };
|
376 | return res.status(200).send({
|
377 | success: true,
|
378 | user: ld.omit(u, 'password'),
|
379 | token: jwt.sign(token, auth.secret)
|
380 | });
|
381 | } else {
|
382 | var msg = 'BACKEND.ERROR.AUTHENTICATION.ACTIVATION_NEEDED';
|
383 | return fn.denied(res, msg);
|
384 | }
|
385 | });
|
386 | });
|
387 | });
|
388 |
|
389 | |
390 |
|
391 |
|
392 |
|
393 |
|
394 |
|
395 |
|
396 |
|
397 | app.post(authRoute + '/login', function (req, res) {
|
398 | var eplAuthorToken;
|
399 | if (typeof(req.body.login) !== 'undefined' && typeof(req.cookies['token-'+req.body.login]) !== 'undefined') {
|
400 | eplAuthorToken = req.cookies['token-'+req.body.login];
|
401 | } else if (typeof(req.cookies.token) !== 'undefined') {
|
402 | eplAuthorToken = req.cookies.token;
|
403 | }
|
404 | auth.fn.JWTFn(req, req.body, false, function (err, u, info) {
|
405 | if (err) { return res.status(400).send({ error: err.message }); }
|
406 | if (!u) { return res.status(400).send({ error: info.message }); }
|
407 | if (u.active) {
|
408 | var token = {
|
409 | login: u.login,
|
410 | key: auth.tokens[u.login].key
|
411 | };
|
412 | if (!u.eplAuthorToken && typeof(eplAuthorToken) !== 'undefined') {
|
413 | u.eplAuthorToken = eplAuthorToken;
|
414 | var uToUpdate = ld.cloneDeep(u);
|
415 | uToUpdate.password = req.body.password;
|
416 | user.set(uToUpdate, function (err) {
|
417 | if (err) { return res.status(400).send({ error: err.message }); }
|
418 | return res.status(200).send({
|
419 | success: true,
|
420 | user: ld.omit(u, 'password'),
|
421 | token: jwt.sign(token, auth.secret)
|
422 | });
|
423 | });
|
424 | } else {
|
425 | return res.status(200).send({
|
426 | success: true,
|
427 | user: ld.omit(u, 'password'),
|
428 | token: jwt.sign(token, auth.secret)
|
429 | });
|
430 | }
|
431 | } else {
|
432 | var msg = 'BACKEND.ERROR.AUTHENTICATION.ACTIVATION_NEEDED';
|
433 | return fn.denied(res, msg);
|
434 | }
|
435 | });
|
436 | });
|
437 |
|
438 | |
439 |
|
440 |
|
441 |
|
442 |
|
443 |
|
444 |
|
445 | app.get(authRoute + '/logout', fn.ensureAuthenticated, function (req, res) {
|
446 | delete auth.tokens[req.mypadsLogin];
|
447 | res.status(200).send({ success: true });
|
448 | });
|
449 |
|
450 | |
451 |
|
452 |
|
453 |
|
454 |
|
455 |
|
456 |
|
457 |
|
458 | app.post(authRoute + '/admin/login', function (req, res) {
|
459 | auth.fn.JWTFn(req, req.body, true, function (err, u, info) {
|
460 | if (err) { return res.status(400).send({ error: err.message }); }
|
461 | if (!u) { return res.status(400).send({ error: info.message }); }
|
462 | var token = {
|
463 | login: u.login,
|
464 | key: auth.adminTokens[u.login].key
|
465 | };
|
466 | return res.status(200).send({
|
467 | success: true,
|
468 | token: jwt.sign(token, auth.secret)
|
469 | });
|
470 | });
|
471 | });
|
472 |
|
473 | |
474 |
|
475 |
|
476 |
|
477 |
|
478 |
|
479 |
|
480 | app.get(authRoute + '/admin/logout', fn.ensureAdmin, function (req, res) {
|
481 | delete auth.adminTokens[req.mypadsLogin];
|
482 | return res.status(200).send({ success: true });
|
483 | });
|
484 |
|
485 | };
|
486 |
|
487 | |
488 |
|
489 |
|
490 |
|
491 | configurationAPI = function (app) {
|
492 | var confRoute = api.initialRoute + 'configuration';
|
493 |
|
494 | |
495 |
|
496 |
|
497 |
|
498 |
|
499 |
|
500 |
|
501 |
|
502 | app.get(confRoute, function (req, res) {
|
503 | var u = auth.fn.getUser(req.query.auth_token);
|
504 | var isAdmin = fn.isAdmin(req);
|
505 | var action = (isAdmin === true) ? 'all' : 'public';
|
506 | var value = conf[action]();
|
507 | var resp = { value: value };
|
508 | resp.auth = isAdmin || !!u;
|
509 | if (u) { resp.user = u; }
|
510 | |
511 |
|
512 |
|
513 |
|
514 | res.set('Expires', '-1');
|
515 | res.send(resp);
|
516 | });
|
517 |
|
518 | |
519 |
|
520 |
|
521 |
|
522 |
|
523 |
|
524 |
|
525 |
|
526 | app.get(confRoute + '/:key', fn.ensureAdmin, function (req, res) {
|
527 | var value = conf.get(req.params.key);
|
528 | if (ld.isUndefined(value)) {
|
529 | return res.status(404).send({
|
530 | error: 'BACKEND.ERROR.CONFIGURATION.KEY_NOT_FOUND',
|
531 | key: req.params.key
|
532 | });
|
533 | }
|
534 | |
535 |
|
536 |
|
537 |
|
538 | res.set('Expires', '-1');
|
539 | res.send({ key: req.params.key, value: value });
|
540 | });
|
541 |
|
542 | |
543 |
|
544 |
|
545 |
|
546 |
|
547 |
|
548 |
|
549 |
|
550 |
|
551 |
|
552 | var _set = function (req, res) {
|
553 | var key = (req.method === 'POST') ? req.body.key : req.params.key;
|
554 | var value = req.body.value;
|
555 | var setFn = ld.partial(conf.set, key, value);
|
556 | fn.set(setFn, key, value, req, res);
|
557 | };
|
558 |
|
559 | app.post(confRoute, fn.ensureAdmin, _set);
|
560 | app.put(confRoute + '/:key', fn.ensureAdmin, _set);
|
561 |
|
562 | |
563 |
|
564 |
|
565 |
|
566 |
|
567 |
|
568 |
|
569 |
|
570 | app.delete(confRoute + '/:key', fn.ensureAdmin,
|
571 | ld.partial(fn.del, conf.del));
|
572 |
|
573 | |
574 |
|
575 |
|
576 |
|
577 |
|
578 |
|
579 |
|
580 |
|
581 |
|
582 | app.get(confRoute + '/public/usefirstlastname', function (req, res) {
|
583 | return res.send({ success: true, usefirstlastname: conf.get('useFirstLastNameInPads') });
|
584 | });
|
585 |
|
586 | |
587 |
|
588 |
|
589 |
|
590 |
|
591 |
|
592 |
|
593 |
|
594 |
|
595 |
|
596 | app.get(confRoute + '/public/allpadspublicsauthentifiedonly', function (req, res) {
|
597 | var confValue = conf.get('allPadsPublicsAuthentifiedOnly');
|
598 | var data = {
|
599 | success: true,
|
600 | allpadspublicsauthentifiedonly: confValue
|
601 | };
|
602 | |
603 |
|
604 |
|
605 |
|
606 | res.set('Expires', '-1');
|
607 | if (confValue) {
|
608 | pad.get(req.query.pid, function (err, p) {
|
609 | if (err) {
|
610 | return res.send({ success: false, error: err });
|
611 | }
|
612 | data.group = p.group;
|
613 | return res.send(data);
|
614 | });
|
615 | } else {
|
616 | return res.send(data);
|
617 | }
|
618 | });
|
619 |
|
620 | };
|
621 |
|
622 | |
623 |
|
624 |
|
625 |
|
626 |
|
627 |
|
628 | userAPI = function (app) {
|
629 | var userRoute = api.initialRoute + 'user';
|
630 | var allUsersRoute = api.initialRoute + 'all-users';
|
631 | var searchUsersRoute = api.initialRoute + 'search-users';
|
632 | var userlistRoute = api.initialRoute + 'userlist';
|
633 |
|
634 | |
635 |
|
636 |
|
637 |
|
638 |
|
639 |
|
640 |
|
641 |
|
642 |
|
643 | app.get(userlistRoute, fn.ensureAuthenticated,
|
644 | function (req, res) {
|
645 | var opts = { crud: 'get', login: req.mypadsLogin };
|
646 | user.userlist(opts, function (err, u) {
|
647 | if (err) { return res.status(400).send({ error: err.message }); }
|
648 | |
649 |
|
650 |
|
651 |
|
652 | res.set('Expires', '-1');
|
653 | res.send({ value: u.userlists });
|
654 | });
|
655 | }
|
656 | );
|
657 |
|
658 | |
659 |
|
660 |
|
661 |
|
662 |
|
663 |
|
664 |
|
665 |
|
666 |
|
667 | app.post(userlistRoute, fn.ensureAuthenticated,
|
668 | function (req, res) {
|
669 | try {
|
670 | var users = { absent: [], present: [] };
|
671 | var lm = req.body.loginsOrEmails;
|
672 | if (lm) { users = userCache.fn.getIdsFromLoginsOrEmails(lm); }
|
673 | var opts = {
|
674 | crud: 'add',
|
675 | login: req.mypadsLogin,
|
676 | name: req.body.name
|
677 | };
|
678 | if (users.uids) { opts.uids = users.uids; }
|
679 | user.userlist(opts, function (err, u) {
|
680 | if (err) { return res.status(400).send({ error: err.message }); }
|
681 | return res.send({
|
682 | success: true,
|
683 | value: u.userlists,
|
684 | present: users.present,
|
685 | absent: users.absent
|
686 | });
|
687 | });
|
688 | }
|
689 | catch (e) { return res.status(400).send({ error: e.message }); }
|
690 | }
|
691 | );
|
692 |
|
693 | |
694 |
|
695 |
|
696 |
|
697 |
|
698 |
|
699 |
|
700 |
|
701 |
|
702 |
|
703 | app.put(userlistRoute + '/:key', fn.ensureAuthenticated,
|
704 | function (req, res) {
|
705 | try {
|
706 | var users = { absent: [], present: [] };
|
707 | var lm = req.body.loginsOrEmails;
|
708 | if (lm) { users = userCache.fn.getIdsFromLoginsOrEmails(lm); }
|
709 | var opts = {
|
710 | crud: 'set',
|
711 | login: req.mypadsLogin,
|
712 | ulistid: req.params.key,
|
713 | name: req.body.name
|
714 | };
|
715 | if (users.uids) { opts.uids = users.uids; }
|
716 | user.userlist(opts, function (err, u) {
|
717 | if (err) { return res.status(400).send({ error: err.message }); }
|
718 | return res.send({
|
719 | success: true,
|
720 | value: u.userlists,
|
721 | present: users.present,
|
722 | absent: users.absent
|
723 | });
|
724 | });
|
725 | }
|
726 | catch (e) { return res.status(400).send({ error: e.message }); }
|
727 | }
|
728 | );
|
729 |
|
730 | |
731 |
|
732 |
|
733 |
|
734 |
|
735 |
|
736 |
|
737 |
|
738 |
|
739 | app.delete(userlistRoute + '/:key', fn.ensureAuthenticated,
|
740 | function (req, res) {
|
741 | try {
|
742 | var opts = {
|
743 | crud: 'del',
|
744 | login: req.mypadsLogin,
|
745 | ulistid: req.params.key
|
746 | };
|
747 | user.userlist(opts, function (err, u) {
|
748 | if (err) { return res.status(400).send({ error: err.message }); }
|
749 | res.send({ success: true, value: u.userlists });
|
750 | });
|
751 | }
|
752 | catch (e) { return res.status(400).send({ error: e.message }); }
|
753 | }
|
754 | );
|
755 |
|
756 |
|
757 | |
758 |
|
759 |
|
760 |
|
761 |
|
762 |
|
763 |
|
764 | app.get(userRoute + '/:key', fn.ensureAdminOrSelf,
|
765 | ld.partial(fn.get, user));
|
766 |
|
767 | |
768 |
|
769 |
|
770 |
|
771 |
|
772 |
|
773 |
|
774 |
|
775 |
|
776 |
|
777 |
|
778 |
|
779 |
|
780 |
|
781 |
|
782 |
|
783 |
|
784 |
|
785 | app.get(allUsersRoute, fn.ensureAdmin,
|
786 | function (req, res) {
|
787 | var emails = ld.reduce(userCache.emails, function (result, n, key) {
|
788 | result[n] = key;
|
789 | return result;
|
790 | }, {});
|
791 | var users = ld.reduce(userCache.logins, function (result, n, key) {
|
792 | result[key] = {
|
793 | email: emails[n],
|
794 | firstname: userCache.firstname[n],
|
795 | lastname: userCache.lastname[n]
|
796 | };
|
797 | return result;
|
798 | }, {});
|
799 | res.send({ users: users, usersCount: ld.size(users) });
|
800 | }
|
801 | );
|
802 |
|
803 | |
804 |
|
805 |
|
806 |
|
807 |
|
808 |
|
809 |
|
810 |
|
811 |
|
812 |
|
813 |
|
814 |
|
815 |
|
816 |
|
817 |
|
818 |
|
819 |
|
820 |
|
821 | app.get(searchUsersRoute + '/:key', fn.ensureAdmin,
|
822 | function (req, res) {
|
823 | var users = userCache.fn.searchUserInfos(req.params.key);
|
824 | res.send({ users: users, usersCount: ld.size(users) });
|
825 | }
|
826 | );
|
827 |
|
828 |
|
829 | var _set = function (req, res) {
|
830 | var key;
|
831 | var value = req.body;
|
832 | var stop;
|
833 | if (req.method === 'POST' && !fn.isAdmin(req)) {
|
834 | if (conf.isNotInternalAuth() || !conf.get('openRegistration')) {
|
835 | stop = true;
|
836 | res.status(400).send({ error: 'BACKEND.ERROR.AUTHENTICATION.NO_REGISTRATION' });
|
837 | } else {
|
838 | key = req.body.login;
|
839 | if (conf.get('checkMails')) {
|
840 | var token = mail.genToken({ login: key, action: 'accountconfirm' });
|
841 | var url = conf.get('rootUrl') +
|
842 | '/mypads/index.html?/accountconfirm/' + token;
|
843 | console.log(url);
|
844 | var lang = (function () {
|
845 | if (ld.includes(ld.keys(conf.cache.languages), req.body.lang)) {
|
846 | return req.body.lang;
|
847 | } else {
|
848 | return conf.get('defaultLanguage');
|
849 | }
|
850 | })();
|
851 | var subject = fn.mailMessage('ACCOUNT_CONFIRMATION_SUBJECT', {
|
852 | title: conf.get('title') });
|
853 | var message = fn.mailMessage('ACCOUNT_CONFIRMATION', {
|
854 | login: key,
|
855 | title: conf.get('title'),
|
856 | url: url,
|
857 | duration: conf.get('tokenDuration')
|
858 | }, lang);
|
859 | mail.send(req.body.email, subject, message, function (err) {
|
860 | if (err) {
|
861 | stop = true;
|
862 | return res.status(501).send({ error: err });
|
863 | }
|
864 | }, lang);
|
865 | }
|
866 | }
|
867 | } else {
|
868 | key = req.params.key;
|
869 | value.login = req.body.login || key;
|
870 | value._id = userCache.logins[key];
|
871 | }
|
872 |
|
873 | if (!stop) {
|
874 | var u = auth.fn.getUser(req.body.auth_token);
|
875 | if (u && !fn.isAdmin(req)) {
|
876 | auth.tokens[u.login].color = req.body.color || u.color;
|
877 | if (!ld.isUndefined(req.body.useLoginAndColorInPads)) {
|
878 | auth.tokens[u.login].useLoginAndColorInPads = req.body.useLoginAndColorInPads;
|
879 | }
|
880 | }
|
881 | if (fn.isAdmin(req) && req.method !== 'POST') {
|
882 | delete value.auth_token;
|
883 | delete value.passwordConfirm;
|
884 | user.get(value.login, function (err, u) {
|
885 | if (err) { return res.status(400).send({ error: err.message }); }
|
886 | if (value.password) {
|
887 | common.hashPassword(null, value.password, function (err, pass) {
|
888 | if (err) { return res.status(400).send({ error: err }); }
|
889 |
|
890 | value.password = pass;
|
891 | ld.assign(u, value);
|
892 | var setFn = ld.partial(user.fn.set, u);
|
893 | fn.set(setFn, key, u, req, res);
|
894 | });
|
895 | } else {
|
896 | ld.assign(u, value);
|
897 | var setFn = ld.partial(user.fn.set, u);
|
898 | fn.set(setFn, key, u, req, res);
|
899 | }
|
900 | });
|
901 | } else {
|
902 | var setFn = ld.partial(user.set, value);
|
903 | fn.set(setFn, key, value, req, res);
|
904 | }
|
905 | }
|
906 | };
|
907 |
|
908 | |
909 |
|
910 |
|
911 |
|
912 |
|
913 |
|
914 |
|
915 |
|
916 | app.post(userRoute, _set);
|
917 |
|
918 | |
919 |
|
920 |
|
921 |
|
922 |
|
923 |
|
924 |
|
925 | app.put(userRoute + '/:key', fn.ensureAdminOrSelf, _set);
|
926 |
|
927 | |
928 |
|
929 |
|
930 |
|
931 |
|
932 |
|
933 |
|
934 |
|
935 | app.delete(userRoute + '/:key', fn.ensureAdminOrSelf, function (req, res) {
|
936 | var isSelf = (req.params.key === req.mypadsLogin);
|
937 | if (isSelf) { delete auth.tokens[req.mypadsLogin]; }
|
938 | fn.del(user.del, req, res);
|
939 | });
|
940 |
|
941 | |
942 |
|
943 |
|
944 |
|
945 |
|
946 |
|
947 |
|
948 |
|
949 | app.post(userRoute + 'mark', fn.ensureAuthenticated,
|
950 | function (req, res) {
|
951 | try {
|
952 | user.mark(req.mypadsLogin, req.body.type, req.body.key,
|
953 | function (err) {
|
954 | if (err) { return res.status(404).send({ error: err.message }); }
|
955 | res.send({ success: true });
|
956 | }
|
957 | );
|
958 | }
|
959 | catch (e) { res.status(400).send({ error: e.message }); }
|
960 | }
|
961 | );
|
962 |
|
963 | |
964 |
|
965 |
|
966 |
|
967 |
|
968 |
|
969 |
|
970 |
|
971 | app.post(api.initialRoute + 'passrecover', function (req, res) {
|
972 | var email = req.body.email;
|
973 | var err;
|
974 | if (conf.isNotInternalAuth()) {
|
975 | err = 'BACKEND.ERROR.AUTHENTICATION.NO_RECOVER';
|
976 | return res.status(400).send({ error: err });
|
977 | }
|
978 | if (!ld.isEmail(email)) {
|
979 | err = 'BACKEND.ERROR.TYPE.MAIL';
|
980 | return res.status(400).send({ error: err });
|
981 | }
|
982 | if (!userCache.emails[email]) {
|
983 | err = 'BACKEND.ERROR.USER.NOT_FOUND';
|
984 | return res.status(404).send({ error: err });
|
985 | }
|
986 | if (conf.get('rootUrl').length === 0) {
|
987 | err = 'BACKEND.ERROR.CONFIGURATION.ROOTURL_NOT_CONFIGURED';
|
988 | return res.status(501).send({ error: err });
|
989 | }
|
990 | user.get(email, function (err, u) {
|
991 | if (err) { return res.status(400).send({ error: err }); }
|
992 | var token = mail.genToken({ login: u.login, action: 'passrecover' });
|
993 | console.log(conf.get('rootUrl') + '/mypads/index.html?/passrecover/' +
|
994 | token);
|
995 | var subject = fn.mailMessage('PASSRECOVER_SUBJECT', {
|
996 | title: conf.get('title') }, u.lang);
|
997 | var message = fn.mailMessage('PASSRECOVER', {
|
998 | login: u.login,
|
999 | title: conf.get('title'),
|
1000 | url: conf.get('rootUrl') + '/mypads/index.html?/passrecover/' + token,
|
1001 | duration: conf.get('tokenDuration')
|
1002 | }, u.lang);
|
1003 | mail.send(u.email, subject, message, function (err) {
|
1004 | if (err) { return res.status(501).send({ error: err }); }
|
1005 | return res.send({ success: true });
|
1006 | });
|
1007 | });
|
1008 | });
|
1009 |
|
1010 | |
1011 |
|
1012 |
|
1013 |
|
1014 |
|
1015 |
|
1016 |
|
1017 |
|
1018 | app.put(api.initialRoute + 'passrecover/:token', function (req, res) {
|
1019 | var err;
|
1020 | var val = mail.tokens[req.params.token];
|
1021 | var badLogin = (!val || !val.login || !userCache.logins[val.login]);
|
1022 | var badAction = (!val || !val.action || (val.action !== 'passrecover'));
|
1023 | if (conf.isNotInternalAuth()) {
|
1024 | err = 'BACKEND.ERROR.AUTHENTICATION.NO_RECOVER';
|
1025 | return res.status(400).send({ error: err });
|
1026 | }
|
1027 | if (badLogin || badAction) {
|
1028 | err = 'BACKEND.ERROR.TOKEN.INCORRECT';
|
1029 | return res.status(400).send({ error: err });
|
1030 | }
|
1031 | if (!mail.isValidToken(req.params.token)) {
|
1032 | err = 'BACKEND.ERROR.TOKEN.EXPIRED';
|
1033 | return res.status(400).send({ error: err });
|
1034 | }
|
1035 | var pass = req.body.password;
|
1036 | var passC = req.body.passwordConfirm;
|
1037 | if (!pass || (pass !== passC)) {
|
1038 | err = 'USER.ERR.PASSWORD_MISMATCH';
|
1039 | return res.status(400).send({ error: err });
|
1040 | }
|
1041 | user.get(val.login, function (err, u) {
|
1042 | if (err) { return res.status(400).send({ error: err.message }); }
|
1043 | u.password = pass;
|
1044 | if (!u.active) { u.active = true; }
|
1045 | user.set(u, function (err) {
|
1046 | if (err) { return res.status(400).send({ error: err.message }); }
|
1047 | res.send({ success: true, login: val.login });
|
1048 | });
|
1049 | });
|
1050 | });
|
1051 |
|
1052 | |
1053 |
|
1054 |
|
1055 |
|
1056 |
|
1057 |
|
1058 |
|
1059 | app.post(api.initialRoute + 'accountconfirm', function (req, res) {
|
1060 | var val = mail.tokens[req.body.token];
|
1061 | var err;
|
1062 | if (conf.isNotInternalAuth()) {
|
1063 | err = 'BACKEND.ERROR.AUTHENTICATION.NO_RECOVER';
|
1064 | return res.status(400).send({ error: err });
|
1065 | }
|
1066 | if (!val || !val.action || (val.action !== 'accountconfirm')) {
|
1067 | err = 'BACKEND.ERROR.TOKEN.INCORRECT';
|
1068 | return res.status(400).send({ error: err });
|
1069 | }
|
1070 | if (!mail.isValidToken(req.body.token)) {
|
1071 | err = 'BACKEND.ERROR.TOKEN.EXPIRED';
|
1072 | return res.status(400).send({ error: err });
|
1073 | }
|
1074 | user.get(val.login, function (err, u) {
|
1075 | if (err) { return res.status(400).send({ error: err.message }); }
|
1076 | u.active = true;
|
1077 | user.fn.set(u, function (err) {
|
1078 | if (err) { return res.status(400).send({ error: err.message }); }
|
1079 | res.send({ success: true, login: val.login });
|
1080 | });
|
1081 | });
|
1082 | });
|
1083 |
|
1084 | };
|
1085 |
|
1086 | |
1087 |
|
1088 |
|
1089 |
|
1090 |
|
1091 |
|
1092 | groupAPI = function (app) {
|
1093 | var groupRoute = api.initialRoute + 'group';
|
1094 |
|
1095 | |
1096 |
|
1097 |
|
1098 |
|
1099 |
|
1100 |
|
1101 |
|
1102 |
|
1103 |
|
1104 |
|
1105 | app.get(groupRoute, fn.ensureAuthenticated,
|
1106 | function (req, res) {
|
1107 | user.get(req.mypadsLogin, function (err, u) {
|
1108 | if (err) { return res.status(400).send({ error: err }); }
|
1109 | try {
|
1110 | group.getByUser(u, true, function (err, data) {
|
1111 | if (err) {
|
1112 | return res.status(404).send({
|
1113 | error: err.message
|
1114 | });
|
1115 | }
|
1116 | data.groups = ld.transform(data.groups,
|
1117 | function (memo, val, key) {
|
1118 | memo[key] = ld.omit(val, 'password');
|
1119 | }
|
1120 | );
|
1121 | data.pads = ld.transform(data.pads,
|
1122 | function (memo, val, key) {
|
1123 | memo[key] = ld.omit(val, 'password');
|
1124 | }
|
1125 | );
|
1126 | data.users = ld.transform(data.users, function (memo, val, key) {
|
1127 | memo[key] = ld.pick(val, '_id', 'login', 'firstname',
|
1128 | 'lastname', 'email');
|
1129 | });
|
1130 | data.admins = ld.transform(data.admins,
|
1131 | function (memo, val, key) {
|
1132 | memo[key] = ld.pick(val, '_id', 'login', 'firstname',
|
1133 | 'lastname', 'email');
|
1134 | }
|
1135 | );
|
1136 | data.bookmarks = { groups: {}, pads: {} };
|
1137 | group.getBookmarkedGroupsByUser(u, function (err, bookmarks) {
|
1138 | if (err) {
|
1139 | return res.status(404).send({
|
1140 | error: err.message
|
1141 | });
|
1142 | }
|
1143 | data.bookmarks.groups = ld.transform(bookmarks,
|
1144 | function (memo, val, key) {
|
1145 | memo[key] = ld.omit(val, 'password');
|
1146 | }
|
1147 | );
|
1148 | pad.getBookmarkedPadsByUser(u, function (err, bookmarks) {
|
1149 | if (err) {
|
1150 | return res.status(404).send({
|
1151 | error: err.message
|
1152 | });
|
1153 | }
|
1154 | data.bookmarks.pads = ld.transform(bookmarks,
|
1155 | function (memo, val, key) {
|
1156 | memo[key] = ld.omit(val, 'password');
|
1157 | }
|
1158 | );
|
1159 | |
1160 |
|
1161 |
|
1162 |
|
1163 | res.set('Expires', '-1');
|
1164 | res.send({ value: data });
|
1165 | });
|
1166 | });
|
1167 | });
|
1168 | }
|
1169 | catch (e) {
|
1170 | res.status(400).send({ error: e.message });
|
1171 | }
|
1172 | });
|
1173 | }
|
1174 | );
|
1175 |
|
1176 | |
1177 |
|
1178 |
|
1179 |
|
1180 |
|
1181 |
|
1182 |
|
1183 |
|
1184 | app.get(groupRoute + '/:key', function (req, res) {
|
1185 | try {
|
1186 | var key = req.params.key;
|
1187 | group.getWithPads(key, function (err, g, pads) {
|
1188 | if (err) {
|
1189 | return res.status(404).send({ key: key, error: err.message });
|
1190 | }
|
1191 | var u = auth.fn.getUser(req.query.auth_token);
|
1192 | var isAdmin = fn.isAdmin(req);
|
1193 | var isUser = (u && ld.includes(ld.union(g.admins, g.users), u._id));
|
1194 | var isAllowedForPublic = (g.visibility === 'public');
|
1195 |
|
1196 |
|
1197 | if (conf.get('allPadsPublicsAuthentifiedOnly')) {
|
1198 | isAllowedForPublic = false;
|
1199 | if (u && !isAdmin) {
|
1200 | isUser = true;
|
1201 | }
|
1202 | }
|
1203 |
|
1204 | if (isAllowedForPublic && !isAdmin && !isUser) {
|
1205 | pads = ld.transform(pads, function (memo, p, key) {
|
1206 | if (!p.visibility || p.visibility === g.visibility) {
|
1207 | memo[key] = p;
|
1208 | }
|
1209 | });
|
1210 | }
|
1211 | if (isAdmin || isUser || isAllowedForPublic) {
|
1212 | return res.send({ key: key, value: g, pads: pads });
|
1213 | }
|
1214 | var isPrivate = (g.visibility === 'private' && !conf.get('allPadsPublicsAuthentifiedOnly'));
|
1215 | if (isPrivate) {
|
1216 | if (req.query.password) {
|
1217 | var pwd = (ld.isUndefined(req.query.password)) ? undefined : decode(req.query.password);
|
1218 | auth.fn.isPasswordValid(g, pwd,
|
1219 | function (err, valid) {
|
1220 | if (!err && !valid) {
|
1221 | err = { message: 'BACKEND.ERROR.PERMISSION.UNAUTHORIZED' };
|
1222 | }
|
1223 | if (err) {
|
1224 | return res.status(401)
|
1225 | .send({ key: key, error: err.message });
|
1226 | }
|
1227 | if (isPrivate && !isAdmin && !isUser) {
|
1228 | pads = ld.transform(pads, function (memo, p, key) {
|
1229 | if (!p.visibility || p.visibility === g.visibility) {
|
1230 | memo[key] = p;
|
1231 | }
|
1232 | });
|
1233 | }
|
1234 | return res.send({ key: key, value: g, pads: pads });
|
1235 | }
|
1236 | );
|
1237 | } else {
|
1238 | var value = ld.pick(g, 'name', 'visibility');
|
1239 | return res.send({ key: req.params.key, value: value });
|
1240 | }
|
1241 | } else {
|
1242 | if (conf.get('allPadsPublicsAuthentifiedOnly')) {
|
1243 | return fn.denied(res, 'BACKEND.ERROR.AUTHENTICATION.MUST_BE');
|
1244 | } else {
|
1245 | return fn.denied(res, 'BACKEND.ERROR.AUTHENTICATION.DENIED_RECORD');
|
1246 | }
|
1247 | }
|
1248 | });
|
1249 | }
|
1250 | catch (e) { res.status(400).send({ error: e.message }); }
|
1251 | });
|
1252 |
|
1253 | |
1254 |
|
1255 |
|
1256 |
|
1257 |
|
1258 |
|
1259 |
|
1260 |
|
1261 |
|
1262 |
|
1263 | var canEdit = function (req, res, successFn) {
|
1264 | var isAdmin = fn.isAdmin(req);
|
1265 | if (isAdmin) { return successFn(); }
|
1266 | var u = auth.fn.getUser(req.body.auth_token);
|
1267 | if (!u) {
|
1268 | return fn.denied(res, 'BACKEND.ERROR.AUTHENTICATION.NOT_AUTH');
|
1269 | }
|
1270 | group.get(req.params.key, function (err, g) {
|
1271 | if (err) { return res.status(400).send({ error: err.message }); }
|
1272 | var isAllowed = ld.includes(g.admins, auth.tokens[u.login]._id);
|
1273 | if (isAllowed) {
|
1274 | return successFn();
|
1275 | } else {
|
1276 | return fn.denied(res,
|
1277 | 'BACKEND.ERROR.AUTHENTICATION.DENIED_RECORD_EDIT');
|
1278 | }
|
1279 | });
|
1280 | };
|
1281 |
|
1282 |
|
1283 | var _set = function (req, res) {
|
1284 | var setFn = ld.partial(group.set, req.body);
|
1285 | fn.set(setFn, req.body._id, req.body, req, res);
|
1286 | };
|
1287 |
|
1288 | |
1289 |
|
1290 |
|
1291 |
|
1292 |
|
1293 |
|
1294 |
|
1295 | app.post(groupRoute, function (req, res) {
|
1296 | var isAdmin = fn.isAdmin(req);
|
1297 | var u = auth.fn.getUser(req.body.auth_token);
|
1298 | if (!u && !isAdmin) {
|
1299 | return fn.denied(res, 'BACKEND.ERROR.AUTHENTICATION.NOT_AUTH');
|
1300 | }
|
1301 | if (!isAdmin) { req.body.admin = u._id; }
|
1302 | _set(req, res);
|
1303 | });
|
1304 |
|
1305 | |
1306 |
|
1307 |
|
1308 |
|
1309 |
|
1310 |
|
1311 |
|
1312 | app.put(groupRoute + '/:key', function (req, res) {
|
1313 | canEdit(req, res, ld.partial(_set, req, res));
|
1314 | });
|
1315 |
|
1316 | |
1317 |
|
1318 |
|
1319 |
|
1320 |
|
1321 |
|
1322 |
|
1323 | app.delete(groupRoute + '/:key', function (req, res) {
|
1324 | canEdit(req, res, ld.partial(fn.del, group.del, req, res));
|
1325 | }
|
1326 | );
|
1327 |
|
1328 | |
1329 |
|
1330 |
|
1331 |
|
1332 |
|
1333 |
|
1334 |
|
1335 |
|
1336 |
|
1337 | app.post(groupRoute + '/invite', function (req, res) {
|
1338 | if (!req.body.gid) {
|
1339 | return res.status(400)
|
1340 | .send({ error: 'BACKEND.ERROR.TYPE.PARAMS_REQUIRED' });
|
1341 | }
|
1342 | req.params.key = req.body.gid;
|
1343 | var successFn = ld.partial(function (req, res) {
|
1344 | try {
|
1345 | group.inviteOrShare(req.body.invite, req.body.gid,
|
1346 | req.body.loginsOrEmails, function (err, g, uids) {
|
1347 | if (err) {
|
1348 | return res.status(401).send({ error: err.message });
|
1349 | }
|
1350 | return res.send(ld.assign({ success: true, value: g }, uids));
|
1351 | });
|
1352 | }
|
1353 | catch (e) { res.status(400).send({ error: e.message }); }
|
1354 | }, req, res);
|
1355 | canEdit(req, res, successFn);
|
1356 | });
|
1357 |
|
1358 | |
1359 |
|
1360 |
|
1361 |
|
1362 |
|
1363 |
|
1364 |
|
1365 | app.post(groupRoute + '/resign', fn.ensureAuthenticated,
|
1366 | function (req, res) {
|
1367 | try {
|
1368 | group.resign(req.body.gid, auth.tokens[req.mypadsLogin]._id,
|
1369 | function (err, g) {
|
1370 | if (err) { return res.status(400).send({ error: err.message }); }
|
1371 | return res.send({ success: true, value: g });
|
1372 | }
|
1373 | );
|
1374 | }
|
1375 | catch (e) { return res.status(400).send({ error: e.message }); }
|
1376 | }
|
1377 | );
|
1378 |
|
1379 | };
|
1380 |
|
1381 | |
1382 |
|
1383 |
|
1384 |
|
1385 |
|
1386 |
|
1387 | padAPI = function (app) {
|
1388 | var padRoute = api.initialRoute + 'pad';
|
1389 |
|
1390 | |
1391 |
|
1392 |
|
1393 |
|
1394 |
|
1395 |
|
1396 |
|
1397 |
|
1398 |
|
1399 |
|
1400 |
|
1401 |
|
1402 | var canAct = function (edit, successFn, req, res) {
|
1403 | pad.get(req.params.key, function (err, p) {
|
1404 | var key = req.params.key;
|
1405 | if (err) { return res.status(404).send({ error: err.message }); }
|
1406 | var isAdmin = fn.isAdmin(req);
|
1407 | if (isAdmin) { return successFn(req, res, p); }
|
1408 |
|
1409 |
|
1410 | if (conf.get('allPadsPublicsAuthentifiedOnly') && req.route.method === 'get') {
|
1411 | var token = req.body.auth_token || req.query.auth_token;
|
1412 | var u = auth.fn.getUser(token);
|
1413 | return (!u) ? fn.denied(res, 'BACKEND.ERROR.AUTHENTICATION.MUST_BE') : successFn(req, res, p);
|
1414 | }
|
1415 |
|
1416 | if (!edit && (p.visibility === 'public')) {
|
1417 | return successFn(req, res, p);
|
1418 | }
|
1419 | if (!edit && (p.visibility === 'private')) {
|
1420 | var pwd = (ld.isUndefined(req.query.password)) ? undefined : decode(req.query.password);
|
1421 | auth.fn.isPasswordValid(p, pwd, function (err, valid) {
|
1422 | if (!err && !valid) {
|
1423 | err = { message: 'BACKEND.ERROR.PERMISSION.UNAUTHORIZED' };
|
1424 | }
|
1425 | if (err) {
|
1426 | return res.status(401).send({ key: key, error: err.message });
|
1427 | }
|
1428 | return successFn(req, res, p);
|
1429 | });
|
1430 | } else {
|
1431 | group.get(p.group, function (err, g) {
|
1432 | if (err) { return res.status(400).send({ error: err.message }); }
|
1433 | if (!edit && (g.visibility === 'public')) {
|
1434 | return successFn(req, res, p);
|
1435 | } else if (!edit && (g.visibility === 'private')) {
|
1436 | var pwd = (ld.isUndefined(req.query.password)) ? undefined : decode(req.query.password);
|
1437 | auth.fn.isPasswordValid(g, pwd,
|
1438 | function (err, valid) {
|
1439 | if (!err && !valid) {
|
1440 | err = { message: 'BACKEND.ERROR.PERMISSION.UNAUTHORIZED' };
|
1441 | }
|
1442 | if (err) {
|
1443 | return res.status(401)
|
1444 | .send({ key: key, error: err.message });
|
1445 | }
|
1446 | return successFn(req, res, p);
|
1447 | }
|
1448 | );
|
1449 | } else {
|
1450 | var token = req.body.auth_token || req.query.auth_token;
|
1451 | var u = auth.fn.getUser(token);
|
1452 | if (!u) {
|
1453 | return fn.denied(res, 'BACKEND.ERROR.AUTHENTICATION.MUST_BE');
|
1454 | }
|
1455 | var users = edit ? g.admins : ld.union(g.admins, g.users);
|
1456 | var uid = auth.tokens[u.login]._id;
|
1457 | var isAllowed = ld.includes(users, uid);
|
1458 | if (isAllowed) {
|
1459 | return successFn(req, res, p);
|
1460 | } else {
|
1461 | var msg = edit ? 'DENIED_RECORD_EDIT' : 'DENIED_RECORD';
|
1462 | return fn.denied(res, 'BACKEND.ERROR.AUTHENTICATION.' + msg);
|
1463 | }
|
1464 | }
|
1465 | });
|
1466 | }
|
1467 | });
|
1468 | };
|
1469 |
|
1470 | |
1471 |
|
1472 |
|
1473 |
|
1474 |
|
1475 |
|
1476 |
|
1477 |
|
1478 |
|
1479 | app.get(padRoute + '/:key',
|
1480 | ld.partial(canAct, false, function (req, res, val) {
|
1481 | return res.send({ key: req.params.key, value: val });
|
1482 | }));
|
1483 |
|
1484 |
|
1485 | var _set = function (req, res) {
|
1486 | var setFn = ld.partial(pad.set, req.body);
|
1487 | fn.set(setFn, req.body._id, req.body, req, res);
|
1488 | };
|
1489 |
|
1490 | |
1491 |
|
1492 |
|
1493 |
|
1494 |
|
1495 |
|
1496 |
|
1497 | app.post(padRoute, function (req, res) {
|
1498 | var isAdmin = fn.isAdmin(req);
|
1499 | var u;
|
1500 | if (!isAdmin) { u = auth.fn.getUser(req.body.auth_token); }
|
1501 | if (!isAdmin && !u) {
|
1502 | return fn.denied(res, 'BACKEND.ERROR.AUTHENTICATION.NOT_AUTH');
|
1503 | }
|
1504 | if (isAdmin) {
|
1505 | _set(req, res);
|
1506 | } else {
|
1507 | if (req.body.group) {
|
1508 | group.get(req.body.group, function (err, g) {
|
1509 | if (err) {
|
1510 | if (ld.isEqual(err, new Error('BACKEND.ERROR.CONFIGURATION.KEY_NOT_FOUND'))) {
|
1511 | err = 'BACKEND.ERROR.PAD.ITEMS_NOT_FOUND';
|
1512 | }
|
1513 | return res.status(400).send({ success: false, error: err });
|
1514 | }
|
1515 | if (ld.isUndefined(g)) {
|
1516 | return res.status(400).send({ success: false, error: 'BACKEND.ERROR.PAD.ITEMS_NOT_FOUND'});
|
1517 | } else {
|
1518 | if (ld.indexOf(g.admins, u._id) !== -1 ||
|
1519 | (g.allowUsersToCreatePads && ld.indexOf(g.users, u._id) !== -1)) {
|
1520 | _set(req, res);
|
1521 | } else {
|
1522 | return fn.denied(res, 'BACKEND.ERROR.AUTHENTICATION.DENIED');
|
1523 | }
|
1524 | }
|
1525 | });
|
1526 | } else {
|
1527 | return res.status(400).send({ success: false, error: 'BACKEND.ERROR.TYPE.PARAM_STR'});
|
1528 | }
|
1529 | }
|
1530 | });
|
1531 |
|
1532 | |
1533 |
|
1534 |
|
1535 |
|
1536 |
|
1537 |
|
1538 |
|
1539 | app.put(padRoute + '/:key', ld.partial(canAct, true, _set));
|
1540 |
|
1541 | |
1542 |
|
1543 |
|
1544 |
|
1545 |
|
1546 |
|
1547 |
|
1548 | app.delete(padRoute + '/:key', function (req, res) {
|
1549 | var isAdmin = fn.isAdmin(req);
|
1550 | var u;
|
1551 | if (!isAdmin) { u = auth.fn.getUser(req.body.auth_token); }
|
1552 | if (!isAdmin && !u) {
|
1553 | return fn.denied(res, 'BACKEND.ERROR.AUTHENTICATION.NOT_AUTH');
|
1554 | }
|
1555 | canAct(true, ld.partial(fn.del, pad.del), req, res);
|
1556 | });
|
1557 |
|
1558 | |
1559 |
|
1560 |
|
1561 |
|
1562 |
|
1563 |
|
1564 |
|
1565 | app.delete(padRoute + '/chathistory/:key', function (req, res) {
|
1566 | var isAdmin = fn.isAdmin(req);
|
1567 | var u;
|
1568 | if (!isAdmin) { u = auth.fn.getUser(req.body.auth_token); }
|
1569 | if (!isAdmin && !u) {
|
1570 | return fn.denied(res, 'BACKEND.ERROR.AUTHENTICATION.NOT_AUTH');
|
1571 | }
|
1572 | canAct(true, ld.partial(fn.del, pad.delChatHistory), req, res);
|
1573 | });
|
1574 |
|
1575 | |
1576 |
|
1577 |
|
1578 |
|
1579 |
|
1580 |
|
1581 |
|
1582 |
|
1583 |
|
1584 | app.get(padRoute + '/ispublic/:key', function (req, res) {
|
1585 | pad.get(req.params.key, function(err, p) {
|
1586 | if (err) {
|
1587 | return res.send({ success: false, error: err });
|
1588 | } else if (p.visibility !== null) {
|
1589 | return res.send({ success: true, key: req.params.key, ispublic: (p.visibility === 'public') });
|
1590 | } else {
|
1591 | group.get(p.group, function(err, g) {
|
1592 | if (err) { return res.send({ success: false, error: err }); }
|
1593 | return res.send({ success: true, key: req.params.key, ispublic: (g.visibility === 'public') });
|
1594 | });
|
1595 | }
|
1596 | });
|
1597 | });
|
1598 | };
|
1599 |
|
1600 | cacheAPI = function (app) {
|
1601 | var cacheRoute = api.initialRoute + 'cache';
|
1602 |
|
1603 | |
1604 |
|
1605 |
|
1606 |
|
1607 |
|
1608 |
|
1609 |
|
1610 |
|
1611 |
|
1612 |
|
1613 | app.get(cacheRoute + '/check', function (req, res) {
|
1614 | return res.send({ userCacheReady: userCache.userCacheReady });
|
1615 | });
|
1616 |
|
1617 | };
|
1618 |
|
1619 | statsAPI = function (app) {
|
1620 | var statsRoute = api.initialRoute + 'stats';
|
1621 |
|
1622 | |
1623 |
|
1624 |
|
1625 |
|
1626 |
|
1627 |
|
1628 |
|
1629 |
|
1630 |
|
1631 |
|
1632 | app.get(statsRoute + '/stats.json', function (req, res) {
|
1633 | var time = Math.floor(Date.now() / 1000);
|
1634 |
|
1635 | pad.count(function(err, pcount) {
|
1636 | if (err) { return res.send({ timestamp: time, err: err }); }
|
1637 | group.count(function(err, gcount) {
|
1638 | if (err) { return res.send({ timestamp: time, err: err }); }
|
1639 | return res.send({
|
1640 | timestamp: time,
|
1641 | users: ld.size(userCache.logins),
|
1642 | pad: pcount,
|
1643 | groups: gcount
|
1644 | });
|
1645 | });
|
1646 | });
|
1647 | });
|
1648 | };
|
1649 |
|
1650 | return api;
|
1651 |
|
1652 | }).call(this);
|