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