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 | var getPad;
|
33 | var getPadID;
|
34 | var getPadHTML;
|
35 | var isWaitingforDeletion;
|
36 | try {
|
37 |
|
38 | var epVersion = parseFloat(require('ep_etherpad-lite/package.json').version);
|
39 | if (epVersion >= 1.8) {
|
40 | var utils = require('./utils');
|
41 | getPad = utils.callbackify1(require('ep_etherpad-lite/node/db/PadManager').getPad);
|
42 | getPadID = utils.callbackify1(require('ep_etherpad-lite/node/db/API').getPadID);
|
43 | getPadHTML = utils.callbackify2(require('ep_etherpad-lite/node/utils/ExportHtml').getPadHTML);
|
44 | } else {
|
45 | getPad = require('ep_etherpad-lite/node/db/PadManager').getPad;
|
46 | getPadID = require('ep_etherpad-lite/node/db/API').getPadID;
|
47 | getPadHTML = require('ep_etherpad-lite/node/utils/ExportHtml').getPadHTML;
|
48 | }
|
49 | }
|
50 | catch (e) {
|
51 |
|
52 | getPad = function (padId, callback) { callback(null); };
|
53 | getPadID = function (padId, callback) { callback(null); };
|
54 | getPadHTML = function (pad, rev, callback) {
|
55 | callback(null, '<p>Testing only</p>');
|
56 | };
|
57 | isWaitingforDeletion = function(padId, callback) { callback(null, null); };
|
58 |
|
59 | }
|
60 | var ld = require('lodash');
|
61 | var decode = require('js-base64').Base64.decode;
|
62 | var conf = require('./configuration.js');
|
63 | var auth = require('./auth.js');
|
64 | var pad = require('./model/pad.js');
|
65 | var group = require('./model/group.js');
|
66 | var storage = require('./storage.js');
|
67 |
|
68 | var JOBQ_PREFIX = storage.DBPREFIX.JOBQ;
|
69 |
|
70 | if (typeof(isWaitingforDeletion) === 'undefined') {
|
71 | isWaitingforDeletion = function(padId, callback) {
|
72 | storage.db.get(JOBQ_PREFIX+'deletePad:'+padId, callback);
|
73 | };
|
74 | }
|
75 |
|
76 | module.exports = (function () {
|
77 | 'use strict';
|
78 |
|
79 | var perm = {};
|
80 |
|
81 | |
82 |
|
83 |
|
84 |
|
85 | perm.fn = {};
|
86 |
|
87 | |
88 |
|
89 |
|
90 |
|
91 |
|
92 |
|
93 |
|
94 |
|
95 | perm.fn.getVarFromReferer = function (varName, req) {
|
96 | var ref = req.headers.referer;
|
97 | if (!ref) { return false; }
|
98 | var rg = new RegExp(varName + '=([^&]+)');
|
99 | var rgxres = rg.exec(ref);
|
100 | return (rgxres ? rgxres[1] : false);
|
101 | };
|
102 |
|
103 | |
104 |
|
105 |
|
106 |
|
107 |
|
108 |
|
109 |
|
110 |
|
111 |
|
112 | perm.fn.getPadAndGroup = function (pid, callback) {
|
113 | pad.get(pid, function (err, p) {
|
114 | if (err) { console.error(err); }
|
115 | if (err || !p) { return callback(null, null); }
|
116 | group.get(p.group, function (err, g) {
|
117 | if (err) { return callback(err); }
|
118 | return callback(null, { pad : p, group: g });
|
119 | });
|
120 | });
|
121 | };
|
122 |
|
123 | |
124 |
|
125 |
|
126 |
|
127 |
|
128 |
|
129 |
|
130 | perm.fn.check = function (params) {
|
131 | var callback = ld.partial(params.callback, params);
|
132 | var checkPass = function (el) {
|
133 | var rq = params.req.query;
|
134 | var password = (rq ? rq.mypadspassword : false );
|
135 | if (!password) {
|
136 | password = perm.fn.getVarFromReferer('mypadspassword', params.req);
|
137 | }
|
138 | if (!password) { return params.refuse(); }
|
139 | auth.fn.isPasswordValid(el, decode(password), function (err, valid) {
|
140 | if (err) { return params.unexpected(err); }
|
141 | return (valid ? callback() : params.refuse());
|
142 | });
|
143 | };
|
144 | var token = (params.req.query ? params.req.query.auth_token : false);
|
145 | if (!token) {
|
146 | var ref = params.req.headers.referer;
|
147 | if (ref) {
|
148 | var rgxres = /&auth_token=(.+)&?/.exec(ref);
|
149 | if (rgxres) { token = rgxres[1]; }
|
150 | }
|
151 | }
|
152 | var u = auth.fn.getUser(token);
|
153 | var uid = u && u._id || false;
|
154 |
|
155 | if (!params.pg) {
|
156 | return isWaitingforDeletion(params.pid, function(err, val) {
|
157 | if (err) { return params.unexpected(err); }
|
158 |
|
159 | if (val === null) {
|
160 | return params[(conf.get('allowEtherPads') ? 'next' : 'unexpected')]();
|
161 | } else {
|
162 | return params.unexpected();
|
163 | }
|
164 | });
|
165 | }
|
166 | var g = params.pg.group;
|
167 | var p = params.pg.pad;
|
168 |
|
169 |
|
170 | if (ld.includes(g.admins, uid)) { return callback(); }
|
171 |
|
172 |
|
173 | if (conf.get('allPadsPublicsAuthentifiedOnly')) {
|
174 | if (u) {
|
175 | return callback();
|
176 | } else {
|
177 | return params.refuse();
|
178 | }
|
179 | }
|
180 |
|
181 | switch (p.visibility) {
|
182 | case 'public':
|
183 | return callback();
|
184 | case 'private':
|
185 | return checkPass(p);
|
186 | default:
|
187 | switch (g.visibility) {
|
188 | case 'public':
|
189 | return callback();
|
190 | case 'private':
|
191 | return (ld.includes(g.users, uid) ? checkPass(p) : checkPass(g));
|
192 |
|
193 | default:
|
194 | return (ld.includes(g.users, uid) ? callback() : params.refuse());
|
195 | }
|
196 | }
|
197 | };
|
198 |
|
199 | |
200 |
|
201 |
|
202 |
|
203 |
|
204 |
|
205 |
|
206 | perm.fn.readonly = function (params) {
|
207 | var g = params.pg.group;
|
208 | var p = params.pg.pad;
|
209 | if (p.readonly || (g.readonly && p.readonly === null)) {
|
210 | return getPad(params.pg.pad._id, function (err, p) {
|
211 | if (err) { return params.unexpected(err); }
|
212 | getPadHTML(p, undefined, function (err, html) {
|
213 | if (err) { return params.unexpected(err); }
|
214 | html = '<!DOCTYPE HTML><html><body>' + html + '</body></html>';
|
215 | return params.res.status(200).send(html);
|
216 | });
|
217 | });
|
218 | } else {
|
219 | return params.next();
|
220 | }
|
221 | };
|
222 |
|
223 | |
224 |
|
225 |
|
226 |
|
227 |
|
228 |
|
229 |
|
230 |
|
231 |
|
232 | var trimRgx = new RegExp('/.*');
|
233 | perm.check = function (req, res, next) {
|
234 | var params;
|
235 | var pid = req.params.pid || req.params[0];
|
236 | pid = pid.replace(trimRgx, '');
|
237 | var unexpected = function (err) {
|
238 | return res.status(401).send({
|
239 | error: 'BACKEND.ERROR.PERMISSION.UNEXPECTED',
|
240 | extra: err
|
241 | });
|
242 | };
|
243 | var refuse = function () {
|
244 | var mypadsRoute = conf.get('rootUrl') + '/mypads/index.html?/mypads/group/' +
|
245 | params.pg.group._id + '/pad/view/' + params.pg.pad._id;
|
246 | return res.redirect(mypadsRoute);
|
247 | };
|
248 | params = {
|
249 | req: req,
|
250 | res: res,
|
251 | next: next,
|
252 | callback: perm.fn.readonly,
|
253 | unexpected: unexpected,
|
254 | refuse: refuse,
|
255 | pid: pid
|
256 | };
|
257 |
|
258 | if (pid.match(/^r\.[A-Za-z0-9_-]{32}$/)) {
|
259 |
|
260 | getPadID(pid, function(err, result) {
|
261 | if (err) { return unexpected(err); }
|
262 | pid = result.padID;
|
263 |
|
264 | perm.fn.getPadAndGroup(pid, function (err, pg) {
|
265 | if (err) { return unexpected(err); }
|
266 | params.pg = pg;
|
267 | perm.fn.check(params);
|
268 | });
|
269 | });
|
270 | } else {
|
271 |
|
272 | perm.fn.getPadAndGroup(pid, function (err, pg) {
|
273 | if (err) { return unexpected(err); }
|
274 | params.pg = pg;
|
275 | perm.fn.check(params);
|
276 | });
|
277 | }
|
278 | };
|
279 |
|
280 | |
281 |
|
282 |
|
283 |
|
284 |
|
285 |
|
286 |
|
287 |
|
288 |
|
289 |
|
290 | perm.padAndAuthor = {};
|
291 |
|
292 | perm.setNameAndColor = function (req, res, next) {
|
293 | var token = (req.query ? req.query.auth_token : false);
|
294 | if (!token) { token = perm.fn.getVarFromReferer('auth_token', req); }
|
295 | var u = auth.fn.getUser(token);
|
296 | if (u && u.useLoginAndColorInPads) {
|
297 | var opts = { userName: u.login };
|
298 | if (u.padNickname) {
|
299 | opts.userName = u.padNickname;
|
300 | }
|
301 | if (conf.get('useFirstLastNameInPads')) {
|
302 | var firstname = (u.firstname) ? u.firstname : '';
|
303 | var lastname = (u.lastname) ? u.lastname : '';
|
304 | opts.userName = firstname+' '+lastname;
|
305 | }
|
306 | if (u.color) {
|
307 | opts.userColor = u.color;
|
308 | req.query.userColor = opts.userColor;
|
309 | }
|
310 | perm.padAndAuthor[req.params.pid] = opts;
|
311 | req.query.userName = opts.userName;
|
312 | } else {
|
313 | delete perm.padAndAuthor[req.params.pid];
|
314 | }
|
315 | return next();
|
316 | };
|
317 |
|
318 |
|
319 | |
320 |
|
321 |
|
322 |
|
323 |
|
324 |
|
325 |
|
326 |
|
327 |
|
328 |
|
329 |
|
330 |
|
331 | perm.init = function (app) {
|
332 |
|
333 | var rgx = new RegExp('/p/(r\.[A-Za-z0-9_-]{32}$|[.A-Za-z0-9_-]+[A-Za-z0-9_/-]*)');
|
334 | app.all(rgx, perm.check);
|
335 | app.all('/p/:pid', perm.setNameAndColor);
|
336 | app.get('/', function (req, res, next) {
|
337 | if (conf.get('allowEtherPads')) {
|
338 | return next();
|
339 | } else {
|
340 | return res.redirect(conf.get('rootUrl') + '/mypads/');
|
341 | }
|
342 | });
|
343 | };
|
344 |
|
345 | return perm;
|
346 |
|
347 | }).call(this);
|