lfapi

annotate lfapi/main.js @ 10:ad7255ce00c8

Fixed wrong argument name in nodemailer.send_mail call.
author bsw
date Mon Oct 24 21:27:46 2011 +0200 (2011-10-24)
parents 0f66da081ad3
children 5c6dec2a70a3
rev   line source
bsw@0 1 var api_version = '0.2.0';
bsw@0 2
bsw@0 3 // creates a random string with the given length
bsw@0 4 function randomString(number_of_chars) {
bsw@0 5 var charset, rand, i, ret;
bsw@0 6 charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
bsw@0 7 random_string = '';
bsw@0 8
bsw@0 9 for (var i = 0; i < number_of_chars; i++) {
bsw@0 10 random_string += charset[parseInt(Math.random() * charset.length)]
bsw@0 11 }
bsw@0 12 return random_string;
bsw@0 13 }
bsw@0 14
bsw@0 15 var fields = require('./fields.js');
bsw@0 16
bsw@0 17 var general_params = require('./general_params.js');
bsw@0 18
bsw@0 19 var config = general_params.config;
bsw@0 20 exports.config = config;
bsw@0 21
bsw@0 22 var db = require('./db.js');
bsw@0 23 exports.db = db;
bsw@0 24
bsw@0 25 var selector = db.selector;
bsw@0 26
bsw@5 27 var nodemailer = require('nodemailer');
bsw@0 28
bsw@0 29
bsw@0 30 // check if current session has at least given access level, returns error to client if not.
bsw@0 31 // used by request handlers below
bsw@0 32 function requireAccessLevel(conn, req, res, access_level, callback) {
bsw@0 33 switch (access_level) {
bsw@0 34 case 'anonymous':
bsw@0 35 if (req.current_access_level == 'anonymous') { callback(); return; };
bsw@0 36 case 'pseudonym':
bsw@0 37 if (req.current_access_level == 'pseudonym') { callback(); return; };
bsw@0 38 case 'full':
bsw@0 39 if (req.current_access_level == 'full') { callback(); return; };
bsw@0 40 case 'member':
bsw@0 41 if (req.current_member_id) { callback(); return; };
bsw@0 42 default:
bsw@0 43 respond('json', conn, req, res, 'forbidden', { error: 'Access denied' });
bsw@0 44 }
bsw@0 45 };
bsw@0 46
bsw@0 47 // callback function, encoding result and sending it to the client
bsw@0 48 function respond(mode, conn, req, res, status, object, err) {
bsw@3 49 var http_status = 200;
bsw@0 50 var command;
bsw@0 51
bsw@0 52 if (status == 'ok') {
bsw@0 53 command = 'COMMIT';
bsw@0 54 } else {
bsw@0 55 command = 'ROLLBACK';
bsw@0 56 };
bsw@0 57
bsw@0 58 switch (status) {
bsw@0 59 case 'ok':
bsw@0 60 http_status = 200;
bsw@0 61 break;
bsw@0 62 case 'forbidden':
bsw@0 63 //http_status = 403;
bsw@0 64 break;
bsw@0 65 case 'notfound':
bsw@0 66 http_status = 404;
bsw@0 67 break;
bsw@0 68 case 'unprocessable':
bsw@0 69 //http_status = 422;
bsw@0 70 break;
bsw@0 71 case 'conflict':
bsw@0 72 //http_status = 409;
bsw@0 73 break;
bsw@0 74 };
bsw@0 75
bsw@0 76 var query;
bsw@0 77 if (mode == 'json' && ! err) query = 'SELECT null';
bsw@0 78 db.query(conn, req, res, query, function(result, conn) {
bsw@0 79 db.query(conn, req, res, command, function (result, conn) {
bsw@0 80
bsw@0 81 if (mode == 'json') {
bsw@0 82 if (! object) object = {};
bsw@0 83 } else if (mode == 'html') {
bsw@0 84 if (! object) object = 'no content';
bsw@0 85 if (err) object = "Error: " + err;
bsw@0 86 }
bsw@0 87
bsw@0 88 object.status = status;
bsw@0 89 object.error = err;
bsw@0 90
bsw@0 91 if (mode == 'json') {
bsw@0 92 var body = JSON.stringify(object);
bsw@0 93 var content_type = 'application/json';
bsw@0 94 if (req.params && req.params.callback) {
bsw@0 95 body = req.params.callback + '(' + body + ')';
bsw@0 96 content_type = 'text/javascript';
bsw@0 97 }
bsw@0 98 res.writeHead(
bsw@0 99 http_status,
bsw@0 100 {
bsw@0 101 'Content-Type': content_type,
bsw@6 102 //'Content-Length': body.length // TODO doesn't work in chrome with JSONP
bsw@0 103 }
bsw@0 104 );
bsw@0 105 res.end(body);
bsw@0 106 } else if (mode == 'html') {
bsw@7 107 var body = ['<html><head><title>lfapi</title><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><style>body { font-family: sans-serif; }</style></head><body>']
bsw@0 108 body.push(object)
bsw@0 109 body.push('</body></html>')
bsw@0 110 body = body.join('');
bsw@0 111 res.writeHead(
bsw@0 112 http_status,
bsw@0 113 {
bsw@0 114 'Content-Type': 'text/html',
bsw@0 115 'Content-Length': body.length
bsw@0 116 }
bsw@0 117 );
bsw@0 118 res.end(body);
bsw@0 119 }
bsw@0 120 })
bsw@0 121 });
bsw@0 122 };
bsw@0 123
bsw@0 124 exports.respond = respond;
bsw@0 125 db.error_handler = respond;
bsw@0 126
bsw@0 127 // add requested related data for requests with include_* parameters
bsw@0 128 function addRelatedData(conn, req, res, result, includes) {
bsw@0 129 if (includes.length > 0) {
bsw@0 130 var include = includes.shift();
bsw@0 131 var class = include.class;
bsw@0 132 var objects = result[include.objects];
bsw@0 133
bsw@0 134 var query;
bsw@0 135
bsw@0 136 if (objects) {
bsw@0 137 var objects_exists = false;
bsw@0 138 var ids_hash = {};
bsw@0 139 if (typeof(objects) == 'array') {
bsw@0 140 if (objects.length > 0) {
bsw@0 141 objects_exists = true;
bsw@0 142 objects.forEach( function(object) {
bsw@0 143 if (object[class + "_id"]) {
bsw@0 144 ids_hash[object[class + "_id"]] = true;
bsw@0 145 };
bsw@0 146 });
bsw@0 147 }
bsw@0 148 } else {
bsw@0 149 for (var key in objects) {
bsw@0 150 objects_exists = true;
bsw@0 151 var object = objects[key];
bsw@0 152 if (object[class + "_id"]) {
bsw@0 153 ids_hash[object[class + "_id"]] = true;
bsw@0 154 };
bsw@0 155 };
bsw@0 156 };
bsw@0 157
bsw@0 158 if (objects_exists) {
bsw@0 159 var ids = [];
bsw@0 160 for (key in ids_hash) {
bsw@0 161 ids.push(key)
bsw@0 162 }
bsw@3 163 if (ids.length > 0) {
bsw@3 164 query = new selector.Selector();
bsw@3 165 query.from(class);
bsw@3 166 query.addWhere([class + '.id IN (??)', ids]);
bsw@3 167 fields.addObjectFields(query, class);
bsw@3 168 }
bsw@0 169 };
bsw@0 170 };
bsw@0 171
bsw@0 172 db.query(conn, req, res, query, function (result2, conn) {
bsw@0 173 // add result to main result, regarding correct pluralization
bsw@0 174 var tmp = {};
bsw@0 175 if (result2) {
bsw@0 176 result2.rows.forEach( function(row) {
bsw@0 177 tmp[row.id] = row;
bsw@0 178 });
bsw@0 179 };
bsw@0 180
bsw@0 181 if (class == 'policy') {
bsw@0 182 result['policies'] = tmp;
bsw@0 183 } else {
bsw@0 184 result[class + 's'] = tmp;
bsw@0 185 }
bsw@0 186 addRelatedData(conn, req, res, result, includes);
bsw@0 187 });
bsw@0 188 } else {
bsw@0 189 respond('json', conn, req, res, 'ok', result);
bsw@0 190 };
bsw@0 191
bsw@0 192 };
bsw@0 193
bsw@0 194 function lockMemberById(conn, req, res, member_id, callback) {
bsw@0 195 var query = new selector.Selector('member');
bsw@0 196 query.addField('NULL');
bsw@0 197 query.addWhere(['member.id = ?', member_id]);
bsw@0 198 query.forUpdate();
bsw@0 199 db.query(conn, req, res, query, callback);
bsw@0 200 };
bsw@0 201
bsw@0 202 function requireUnitPrivilege(conn, req, res, unit_id, callback) {
bsw@0 203 var query = new selector.Selector('privilege');
bsw@0 204 query.addField('NULL');
bsw@0 205 query.addWhere(['privilege.member_id = ?', req.current_member_id]);
bsw@0 206 query.addWhere(['privilege.unit_id = ?', unit_id ]);
bsw@0 207 query.addWhere('privilege.voting_right');
bsw@0 208 query.forShareOf('privilege');
bsw@0 209 db.query(conn, req, res, query, function(result, conn) {
bsw@0 210 if (result.rows.length != 1) {
bsw@0 211 respond('json', conn, req, res, 'forbidden', null, 'You have no voting right for this unit.');
bsw@0 212 return;
bsw@0 213 }
bsw@0 214 callback();
bsw@0 215 });
bsw@0 216 };
bsw@0 217
bsw@0 218 function requireAreaPrivilege(conn, req, res, area_id, callback) {
bsw@0 219 var query = new selector.Selector('privilege');
bsw@0 220 query.join('area', null, 'area.unit_id = privilege.unit_id');
bsw@0 221 query.addField('NULL');
bsw@0 222 query.addWhere(['privilege.member_id = ?', req.current_member_id]);
bsw@0 223 query.addWhere(['area.id = ?', area_id ]);
bsw@0 224 query.addWhere('privilege.voting_right');
bsw@0 225 query.forShareOf('privilege');
bsw@0 226 db.query(conn, req, res, query, function(result, conn) {
bsw@0 227 if (result.rows.length != 1) {
bsw@0 228 respond('json', conn, req, res, 'forbidden', null, 'You have no voting right for areas in this unit.');
bsw@0 229 return;
bsw@0 230 }
bsw@0 231 callback();
bsw@0 232 });
bsw@0 233 };
bsw@0 234
bsw@0 235 function requireIssuePrivilege(conn, req, res, issue_id, callback) {
bsw@0 236 var query = new selector.Selector('privilege');
bsw@0 237 query.join('area', null, 'area.unit_id = privilege.unit_id');
bsw@0 238 query.join('issue', null, 'issue.area_id = area.id');
bsw@0 239 query.addField('NULL');
bsw@0 240 query.addWhere(['privilege.member_id = ?', req.current_member_id]);
bsw@0 241 query.addWhere(['issue.id = ?', issue_id ]);
bsw@0 242 query.addWhere('privilege.voting_right');
bsw@0 243 query.forShareOf('privilege');
bsw@0 244 db.query(conn, req, res, query, function(result, conn) {
bsw@0 245 if (result.rows.length != 1) {
bsw@0 246 respond('json', conn, req, res, 'forbidden', null, 'You have no voting right for issues in this unit.');
bsw@0 247 return;
bsw@0 248 }
bsw@0 249 callback();
bsw@0 250 });
bsw@0 251 };
bsw@0 252
bsw@0 253 function requireInitiativePrivilege(conn, req, res, initiative_id, callback) {
bsw@0 254 var query = new selector.Selector('privilege');
bsw@0 255 query.join('area', null, 'area.unit_id = privilege.unit_id');
bsw@0 256 query.join('issue', null, 'issue.area_id = area.id');
bsw@0 257 query.join('initiative', null, 'initiative.issue_id = issue.id');
bsw@0 258 query.addField('NULL');
bsw@0 259 query.addWhere(['privilege.member_id = ?', req.current_member_id]);
bsw@0 260 query.addWhere(['initiative.id = ?', initiative_id ]);
bsw@0 261 query.addWhere('privilege.voting_right');
bsw@0 262 query.forShareOf('privilege');
bsw@0 263 db.query(conn, req, res, query, function(result, conn) {
bsw@0 264 if (result.rows.length != 1) {
bsw@0 265 respond('json', conn, req, res, 'forbidden', null, 'You have no voting right for initiatives in this unit.');
bsw@0 266 return;
bsw@0 267 }
bsw@0 268 callback();
bsw@0 269 });
bsw@0 270 };
bsw@0 271
bsw@0 272 function requireIssueState(conn, req, res, issue_id, required_states, callback) {
bsw@0 273 var query = new selector.Selector('issue');
bsw@0 274 query.addField('NULL');
bsw@0 275 query.addWhere(['issue.id = ?', issue_id]);
bsw@0 276 query.addWhere(['issue.state IN (??)', required_states]);
bsw@0 277 query.forUpdateOf('issue');
bsw@0 278 db.query(conn, req, res, query, function(result, conn) {
bsw@0 279 if (result.rows.length != 1) {
bsw@0 280 respond('json', conn, req, res, 'forbidden', null, 'Issue is in wrong state.');
bsw@0 281 return;
bsw@0 282 }
bsw@0 283 callback();
bsw@0 284 });
bsw@0 285 };
bsw@0 286
bsw@0 287 function requireIssueStateForInitiative(conn, req, res, initiative_id, required_states, callback) {
bsw@0 288 var query = new selector.Selector('issue');
bsw@0 289 query.join('initiative', null, 'initiative.issue_id = issue.id');
bsw@0 290 query.addField('NULL');
bsw@0 291 query.addWhere(['initiative.id = ?', initiative_id]);
bsw@0 292 query.addWhere(['issue.state IN (??)', required_states]);
bsw@0 293 query.forUpdateOf('issue');
bsw@0 294 db.query(conn, req, res, query, function(result, conn) {
bsw@0 295 if (result.rows.length != 1) {
bsw@0 296 respond('json', conn, req, res, 'forbidden', null, 'Issue is in wrong state.');
bsw@0 297 return;
bsw@0 298 }
bsw@0 299 callback();
bsw@0 300 });
bsw@0 301 }
bsw@0 302
bsw@0 303 function requireContingentLeft(conn, req, res, is_initiative, callback) {
bsw@0 304 var query = new selector.Selector('member_contingent_left');
bsw@0 305 query.addField('NULL');
bsw@0 306 query.addWhere(['member_contingent_left.member_id = ?', req.current_member_id]);
bsw@0 307 query.addWhere('member_contingent_left.text_entries_left >= 1');
bsw@0 308 if (is_initiative) {
bsw@0 309 query.addWhere('member_contingent_left.initiatives_left >= 1');
bsw@0 310 }
bsw@0 311 db.query(conn, req, res, query, function(result, conn) {
bsw@0 312 if (result.rows.length != 1) {
bsw@0 313 respond('json', conn, req, res, 'forbidden', null, 'Contingent empty.');
bsw@0 314 return;
bsw@0 315 }
bsw@0 316 callback();
bsw@0 317 });
bsw@0 318 }
bsw@0 319
bsw@0 320 // ==========================================================================
bsw@0 321 // GETT methods
bsw@0 322 // ==========================================================================
bsw@0 323
bsw@0 324
bsw@0 325 exports.get = {
bsw@0 326
bsw@0 327 // startpage (html) for users
bsw@0 328 // currently used for implementing public alpha test
bsw@0 329 '/': function (conn, req, res, params) {
bsw@0 330
bsw@0 331 var html = [];
bsw@0 332 html.push('<h2>welcome to lfapi public developer alpha test</h2>');
bsw@0 333 html.push('<p>This service is provided for testing purposes and is <i><b>dedicated to developers interested in creating applications</b></i> based on LiquidFeedback.</p>');
bsw@0 334 html.push('<h2>how to use</h2>');
bsw@0 335 html.push('<p>The programming interface is described in the <a href="http://dev.liquidfeedback.org/trac/lf/wiki/API">LiquidFeedback API specification</a>.</p>')
bsw@0 336 html.push('<p>The current implementation status of lfapi is published at the <a href="http://dev.liquidfeedback.org/trac/lf/wiki/lfapi">LiquidFeedback API server</a> page in our Wiki.</p>');
bsw@0 337 html.push('<p><b><i>Neither the API specification nor the implementation of lfapi is finished yet.</i></b> This public test should enable developers to join the specification process of the programming interface and makes it possible to start creating applications.</p>');
bsw@0 338 html.push('<h2>questions and suggestions</h2>');
bsw@0 339 html.push('<p>Please use our <a href="http://dev.liquidfeedback.org/cgi-bin/mailman/listinfo/main">public mailing list</a> if you have any questions or suggestions.</p>');
bsw@0 340 html.push('<h2>developer registration</h2>');
bsw@0 341 html.push('<p>To register as developer and receive an account, please submit the following form. You\'ll receive an email with instructions to complete the registration process by verifying your email address.<br />');
bsw@0 342 html.push('<form action="register_test" method="POST">');
bsw@0 343 html.push('<label for="name">Your name:</label> <input type="text" id="name" name="name" /> &nbsp; &nbsp; ');
bsw@0 344 html.push('<label for="email">Email address:</label> <input type="text" id="email" name="email" /> &nbsp; &nbsp; ');
bsw@0 345 html.push('<label for="location">Location:</label> <select name="location" id="location"><option value="earth">Earth</option><option value="moon">Moon</option><option value="mars">Mars</option></select>');
bsw@0 346 html.push('<br />');
bsw@0 347 html.push('<br />');
bsw@0 348 html.push('<div style="border: 2px solid #c00000; background-color: #ffa0a0; padding: 1ex;">');
bsw@0 349 html.push('<b>WARNING:</b> All data you entered above and all data you enter later while using the system and all data you are submitting via the programming interface will be stored in the LiquidFeedback database and published. Every access to the system is subject of tracing and logging for development purposes.<br />Please notice, this is a <b>public alpha test dedicated to developers</b>: serious errors can happen, private data unintentionally published or even <a href="http://en.wikipedia.org/wiki/Grey_goo"> grey goo</a> can appear without further warning. Everything is <b>ON YOUR OWN RISK</b>!');
bsw@0 350 html.push('<br />');
bsw@0 351 html.push('<br />');
bsw@0 352 html.push('<input type="checkbox" name="understood" value="understood" /> I understand the previous warning and I understand that everything is on my own risk.<br />');
bsw@0 353 html.push('</div>');
bsw@0 354 html.push('<br />');
bsw@0 355 html.push('<input type="submit" value="Register account" />');
bsw@0 356 respond('html', null, req, res, 'ok', html.join(''));
bsw@0 357 },
bsw@0 358
bsw@0 359 // temporary method to implement public alpha test
bsw@0 360 '/register_test_confirm': function (conn, req, res, params) {
bsw@0 361 var secret = params.secret;
bsw@0 362
bsw@0 363 var query = new selector.Selector('member');
bsw@0 364 query.addField('member.id, member.notify_email_unconfirmed');
bsw@0 365 query.addWhere(['member.notify_email_secret = ?', secret]);
bsw@0 366 db.query(conn, req, res, query, function (result, conn) {
bsw@0 367 var member = result.rows[0];
bsw@0 368 if (member) {
bsw@0 369 var query = new selector.SQLUpdate('member');
bsw@0 370 query.addValues({
bsw@0 371 notify_email: member.notify_email_unconfirmed,
bsw@0 372 notify_email_secret: null,
bsw@0 373 notify_email_unconfirmed: null,
bsw@0 374 active: true,
bsw@0 375 activated: 'now',
bsw@0 376 active: true,
bsw@0 377 last_activity: 'now',
bsw@0 378 locked: false
bsw@0 379 });
bsw@0 380 query.addWhere(['id = ?', member.id]);
bsw@0 381 db.query(conn, req, res, query, function (err, result) {
bsw@0 382 respond('html', conn, req, res, 'ok', 'Account activated: ');
bsw@0 383 });
bsw@0 384 } else {
bsw@0 385 respond('html', conn, req, res, 'forbidden', 'Secret not valid or already used.');
bsw@0 386 }
bsw@0 387 })
bsw@0 388 },
bsw@0 389
bsw@0 390 '/info': function (conn, req, res, params) {
bsw@0 391 requireAccessLevel(conn, req, res, 'anonymous', function() {
bsw@0 392 var query = new selector.Selector();
bsw@0 393 query.from('"liquid_feedback_version"');
bsw@0 394 query.addField('"liquid_feedback_version".*');
bsw@0 395 db.query(conn, req, res, query, function (result, conn) {
bsw@0 396 var liquid_feedback_version = result.rows[0];
bsw@3 397 var query = new selector.Selector();
bsw@3 398 query.from('"system_setting"');
bsw@3 399 query.addField('"member_ttl"');
bsw@3 400 db.query(conn, req, res, query, function (result, conn) {
bsw@3 401 var member_ttl = null;
bsw@3 402 if (result.rows[0]) {
bsw@3 403 member_ttl = result.rows[0].member_ttl;
bsw@3 404 };
bsw@3 405 respond('json', conn, req, res, 'ok', {
bsw@3 406 core_version: liquid_feedback_version.string,
bsw@3 407 api_version: api_version,
bsw@3 408 current_access_level: req.current_member_id ? 'member' : req.current_access_level,
bsw@3 409 current_member_id: req.current_member_id,
bsw@3 410 member_ttl: member_ttl,
bsw@3 411 settings: config.settings
bsw@3 412 });
bsw@0 413 });
bsw@0 414 });
bsw@0 415 });
bsw@0 416 },
bsw@0 417
bsw@0 418 '/member_count': function (conn, req, res, params) {
bsw@0 419 requireAccessLevel(conn, req, res, 'anonymous', function() {
bsw@0 420 var query = new selector.Selector();
bsw@0 421 query.from('"member_count"');
bsw@0 422 query.addField('"member_count".*');
bsw@0 423 db.query(conn, req, res, query, function (result, conn) {
bsw@0 424 var member_count = result.rows[0];
bsw@0 425 respond('json', conn, req, res, 'ok', {
bsw@3 426 total_count: member_count.total_count,
bsw@3 427 calculated: member_count.calculated
bsw@0 428 });
bsw@0 429 });
bsw@0 430 });
bsw@0 431 },
bsw@0 432
bsw@0 433 '/contingent': function (conn, req, res, params) {
bsw@0 434 requireAccessLevel(conn, req, res, 'anonymous', function() {
bsw@0 435 var query = new selector.Selector();
bsw@0 436 query.from('"contingent"');
bsw@0 437 query.addField('"contingent".*');
bsw@0 438 db.query(conn, req, res, query, function (result, conn) {
bsw@0 439 respond('json', conn, req, res, 'ok', { result: result.rows });
bsw@0 440 });
bsw@0 441 });
bsw@0 442 },
bsw@0 443
bsw@0 444 '/contingent_left': function (conn, req, res, params) {
bsw@0 445 requireAccessLevel(conn, req, res, 'member', function() {
bsw@0 446 var query = new selector.Selector();
bsw@0 447 query.from('"member_contingent_left"');
bsw@0 448 query.addField('"member_contingent_left".text_entries_left');
bsw@0 449 query.addField('"member_contingent_left".initiatives_left');
bsw@0 450 query.addWhere(['member_id = ?', req.current_member_id]);
bsw@0 451 db.query(conn, req, res, query, function (result, conn) {
bsw@0 452 respond('json', conn, req, res, 'ok', { result: result.rows[0] });
bsw@0 453 });
bsw@0 454 });
bsw@0 455 },
bsw@0 456
bsw@0 457 '/member': function (conn, req, res, params) {
bsw@0 458 requireAccessLevel(conn, req, res, 'pseudonym', function() {
bsw@0 459 var query = new selector.Selector();
bsw@0 460 query.from('"member"');
bsw@0 461 if (req.current_access_level == 'pseudonym' && !req.current_member_id ) {
bsw@0 462 fields.addObjectFields(query, 'member', 'member_pseudonym');
bsw@0 463 } else {
bsw@0 464 fields.addObjectFields(query, 'member');
bsw@0 465 }
bsw@0 466 general_params.addMemberOptions(req, query, params);
bsw@0 467 query.addOrderBy('"member"."id"');
bsw@0 468 general_params.addLimitAndOffset(query, params);
bsw@0 469 db.query(conn, req, res, query, function (result, conn) {
bsw@0 470 respond('json', conn, req, res, 'ok', { result: result.rows });
bsw@0 471 });
bsw@0 472 });
bsw@0 473 },
bsw@0 474
bsw@0 475 '/member_history': function (conn, req, res, params) {
bsw@0 476 requireAccessLevel(conn, req, res, 'full', function() {
bsw@0 477 var query = new selector.Selector();
bsw@0 478 query.from('"member_history" JOIN "member" ON "member"."id" = "member_history"."member_id"');
bsw@0 479 query.addField('"member_history".*');
bsw@0 480 general_params.addMemberOptions(req, query, params);
bsw@0 481 query.addOrderBy('member_history.id');
bsw@0 482 general_params.addLimitAndOffset(query, params);
bsw@0 483 db.query(conn, req, res, query, function (member_history_result, conn) {
bsw@0 484 var result = { result: member_history_result.rows }
bsw@0 485 includes = [];
bsw@0 486 if (params.include_members) includes.push({ class: 'member', objects: 'result'});
bsw@0 487 addRelatedData(conn, req, res, result, includes);
bsw@0 488 });
bsw@0 489 });
bsw@0 490 },
bsw@0 491
bsw@0 492 '/member_image': function (conn, req, res, params) {
bsw@0 493 requireAccessLevel(conn, req, res, 'full', function() {
bsw@0 494 var query = new selector.Selector();
bsw@0 495 query.from('"member_image" JOIN "member" ON "member"."id" = "member_image"."member_id"');
bsw@0 496 query.addField('"member_image".*');
bsw@0 497 query.addWhere('member_image.scaled');
bsw@0 498 general_params.addMemberOptions(req, query, params);
bsw@0 499 query.addOrderBy = ['member_image.member_id, member_image.image_type'];
bsw@0 500 db.query(conn, req, res, query, function (result, conn) {
bsw@0 501 respond('json', conn, req, res, 'ok', { result: result.rows });
bsw@0 502 });
bsw@0 503 });
bsw@0 504 },
bsw@0 505
bsw@0 506 '/contact': function (conn, req, res, params) {
bsw@0 507 requireAccessLevel(conn, req, res, 'pseudonym', function() {
bsw@0 508 var query = new selector.Selector();
bsw@0 509 query.from('contact JOIN member ON member.id = contact.member_id');
bsw@0 510 query.addField('"contact".*');
bsw@0 511 if (req.current_member_id) {
bsw@0 512 // public or own for members
bsw@0 513 query.addWhere(['"contact"."public" OR "contact"."member_id" = ?', req.current_member_id]);
bsw@0 514 } else {
bsw@0 515 // public for everybody
bsw@0 516 query.addWhere('"contact"."public"');
bsw@0 517 }
bsw@0 518 general_params.addMemberOptions(req, query, params);
bsw@0 519 query.addOrderBy('"contact"."id"');
bsw@0 520 general_params.addLimitAndOffset(query, params);
bsw@0 521 db.query(conn, req, res, query, function (result, conn) {
bsw@0 522 respond('json', conn, req, res, 'ok', { result: result.rows });
bsw@0 523 });
bsw@0 524 });
bsw@0 525 },
bsw@0 526
bsw@0 527 '/privilege': function (conn, req, res, params) {
bsw@0 528 requireAccessLevel(conn, req, res, 'pseudonym', function() {
bsw@0 529 var query = new selector.Selector();
bsw@0 530 query.from('privilege JOIN member ON member.id = privilege.member_id JOIN unit ON unit.id = privilege.unit_id');
bsw@0 531 query.addField('privilege.*');
bsw@0 532 general_params.addUnitOptions(req, query, params);
bsw@0 533 general_params.addMemberOptions(req, query, params);
bsw@0 534 query.addOrderBy('privilege.unit_id, privilege.member_id');
bsw@0 535 general_params.addLimitAndOffset(query, params);
bsw@0 536 db.query(conn, req, res, query, function (privilege_result, conn) {
bsw@0 537 var result = { result: privilege_result.rows }
bsw@0 538 includes = [];
bsw@0 539 if (params.include_units) includes.push({ class: 'unit', objects: 'result'});
bsw@0 540 if (params.include_members) includes.push({ class: 'member', objects: 'result'});
bsw@0 541 addRelatedData(conn, req, res, result, includes);
bsw@0 542 });
bsw@0 543 });
bsw@0 544 },
bsw@0 545
bsw@0 546 '/policy': function (conn, req, res, params) {
bsw@0 547 requireAccessLevel(conn, req, res, 'anonymous', function() {
bsw@0 548 var query = new selector.Selector();
bsw@0 549 query.from('"policy"');
bsw@0 550 query.addField('"policy".*');
bsw@0 551 general_params.addPolicyOptions(req, query, params);
bsw@0 552 query.addOrderBy('"policy"."index"');
bsw@0 553 general_params.addLimitAndOffset(query, params);
bsw@0 554 db.query(conn, req, res, query, function (result, conn) {
bsw@0 555 respond('json', conn, req, res, 'ok', { result: result.rows });
bsw@0 556 });
bsw@0 557 });
bsw@0 558 },
bsw@0 559
bsw@0 560 '/unit': function (conn, req, res, params) {
bsw@0 561 requireAccessLevel(conn, req, res, 'anonymous', function() {
bsw@0 562 var query = new selector.Selector();
bsw@0 563 query.from('"unit"');
bsw@0 564 fields.addObjectFields(query, 'unit');
bsw@0 565 general_params.addUnitOptions(req, query, params);
bsw@0 566 query.addOrderBy('unit.id');
bsw@0 567 general_params.addLimitAndOffset(query, params);
bsw@0 568 db.query(conn, req, res, query, function (result, conn) {
bsw@0 569 respond('json', conn, req, res, 'ok', { result: result.rows });
bsw@0 570 });
bsw@0 571 });
bsw@0 572 },
bsw@0 573
bsw@0 574 '/area': function (conn, req, res, params) {
bsw@0 575 requireAccessLevel(conn, req, res, 'anonymous', function() {
bsw@0 576 var query = new selector.Selector();
bsw@0 577 query.from('area JOIN unit ON area.unit_id = unit.id');
bsw@0 578 fields.addObjectFields(query, 'area');
bsw@0 579 general_params.addAreaOptions(req, query, params);
bsw@0 580 query.addOrderBy('area.id');
bsw@0 581 general_params.addLimitAndOffset(query, params);
bsw@0 582 db.query(conn, req, res, query, function (area_result, conn) {
bsw@0 583 var result = { result: area_result.rows }
bsw@0 584 includes = [];
bsw@0 585 if (params.include_units) includes.push({ class: 'unit', objects: 'result'});
bsw@0 586 addRelatedData(conn, req, res, result, includes);
bsw@0 587 });
bsw@0 588 });
bsw@0 589 },
bsw@0 590
bsw@0 591 '/allowed_policy': function (conn, req, res, params) {
bsw@0 592 requireAccessLevel(conn, req, res, 'anonymous', function() {
bsw@0 593 var query = new selector.Selector();
bsw@0 594 query.from('allowed_policy');
bsw@0 595 query.join('area', null, 'area.id = allowed_policy.area_id');
bsw@0 596 query.join('unit', null, 'unit.id = area.unit_id');
bsw@0 597 query.addField('allowed_policy.*');
bsw@0 598 general_params.addAreaOptions(req, query, params);
bsw@0 599 query.addOrderBy('allowed_policy.area_id, allowed_policy.policy_id');
bsw@0 600 general_params.addLimitAndOffset(query, params);
bsw@0 601 db.query(conn, req, res, query, function (allowed_policy_result, conn) {
bsw@0 602 var result = { result: allowed_policy_result.rows }
bsw@0 603 includes = [];
bsw@0 604 if (params.include_policies) includes.push({ class: 'policy', objects: 'result'});
bsw@0 605 if (params.include_areas) includes.push({ class: 'area', objects: 'result'});
bsw@0 606 if (params.include_units) includes.push({ class: 'unit', objects: 'areas'});
bsw@0 607 addRelatedData(conn, req, res, result, includes);
bsw@0 608 });
bsw@0 609 }); },
bsw@0 610
bsw@0 611 '/membership': function (conn, req, res, params) {
bsw@0 612 requireAccessLevel(conn, req, res, 'pseudonym', function() {
bsw@0 613 var query = new selector.Selector();
bsw@0 614 query.from('membership JOIN member ON membership.member_id = member.id JOIN area ON area.id = membership.area_id JOIN unit ON unit.id = area.unit_id');
bsw@0 615 query.addField('membership.*');
bsw@0 616 general_params.addAreaOptions(req, query, params);
bsw@0 617 general_params.addMemberOptions(req, query, params);
bsw@0 618 query.addOrderBy('membership.area_id, membership.member_id');
bsw@0 619 general_params.addLimitAndOffset(query, params);
bsw@0 620 db.query(conn, req, res, query, function (membership_result, conn) {
bsw@0 621 var result = { result: membership_result.rows }
bsw@0 622 includes = [];
bsw@0 623 if (params.include_members) includes.push({ class: 'member', objects: 'result'});
bsw@0 624 if (params.include_areas) includes.push({ class: 'area', objects: 'result'});
bsw@0 625 if (params.include_units) includes.push({ class: 'unit', objects: 'areas'});
bsw@0 626 addRelatedData(conn, req, res, result, includes);
bsw@0 627 });
bsw@0 628 });
bsw@0 629 },
bsw@0 630
bsw@0 631 '/issue': function (conn, req, res, params) {
bsw@0 632 requireAccessLevel(conn, req, res, 'anonymous', function() {
bsw@0 633 var query = new selector.Selector()
bsw@0 634 query.from('issue JOIN policy ON policy.id = issue.policy_id JOIN area ON area.id = issue.area_id JOIN unit ON area.unit_id = unit.id');
bsw@0 635 fields.addObjectFields(query, 'issue');
bsw@0 636 general_params.addIssueOptions(req, query, params);
bsw@0 637 query.addOrderBy('issue.id');
bsw@0 638 general_params.addLimitAndOffset(query, params);
bsw@0 639 db.query(conn, req, res, query, function (issue_result, conn) {
bsw@0 640 var result = { result: issue_result.rows }
bsw@0 641 includes = [];
bsw@0 642 if (params.include_areas) includes.push({ class: 'area', objects: 'result'});
bsw@0 643 if (params.include_units) includes.push({ class: 'unit', objects: 'areas'});
bsw@0 644 if (params.include_policies) includes.push({ class: 'policy', objects: 'result' });
bsw@0 645 addRelatedData(conn, req, res, result, includes);
bsw@0 646 });
bsw@0 647 });
bsw@0 648 },
bsw@0 649
bsw@0 650 '/interest': function (conn, req, res, params) {
bsw@0 651 requireAccessLevel(conn, req, res, 'pseudonym', function() {
bsw@0 652 var query = new selector.Selector();
bsw@3 653 if (!params.snapshot) {
bsw@3 654 query.from('interest');
bsw@3 655 } else if (params.snapshot == 'latest') {
bsw@3 656 query.from('direct_interest_snapshot', 'interest');
bsw@3 657 query.addWhere('interest.event = issue.latest_snapshot_event');
bsw@3 658 };
bsw@0 659 query.addField('interest.*');
bsw@3 660 query.join('member', null, 'member.id = interest.member_id');
bsw@3 661 query.join('issue', null, 'interest.issue_id = issue.id');
bsw@3 662 query.join('policy', null, 'policy.id = issue.policy_id');
bsw@3 663 query.join('area', null, 'area.id = issue.area_id');
bsw@3 664 query.join('unit', null, 'area.unit_id = unit.id');
bsw@0 665 general_params.addMemberOptions(req, query, params);
bsw@0 666 general_params.addIssueOptions(req, query, params);
bsw@0 667 query.addOrderBy('interest.issue_id, interest.member_id');
bsw@0 668 general_params.addLimitAndOffset(query, params);
bsw@0 669 db.query(conn, req, res, query, function (interest_result, conn) {
bsw@0 670 var result = { result: interest_result.rows }
bsw@0 671 includes = [];
bsw@0 672 if (params.include_members) includes.push({ class: 'member', objects: 'result'});
bsw@0 673 if (params.include_issues) includes.push({ class: 'issue', objects: 'result'});
bsw@0 674 if (params.include_areas) includes.push({ class: 'area', objects: 'issues'});
bsw@0 675 if (params.include_units) includes.push({ class: 'unit', objects: 'areas'});
bsw@0 676 if (params.include_policies) includes.push({ class: 'policy', objects: 'issues' });
bsw@0 677 addRelatedData(conn, req, res, result, includes);
bsw@0 678 });
bsw@0 679 });
bsw@0 680 },
bsw@0 681
bsw@0 682 '/issue_comment': function (conn, req, res, params) {
bsw@0 683 requireAccessLevel(conn, req, res, 'pseudonym', function() {
bsw@0 684 var query = new selector.Selector();
bsw@0 685 query.from('issue_comment JOIN member ON member.id = issue_comment.member_id JOIN issue on issue_comment.issue_id = issue.id JOIN policy ON policy.id = issue.policy_id JOIN area ON area.id = issue.area_id JOIN unit ON area.unit_id = unit.id');
bsw@0 686 query.addField('issue_comment.*');
bsw@0 687 general_params.addMemberOptions(req, query, params);
bsw@0 688 general_params.addIssueOptions(req, query, params);
bsw@0 689 query.addOrderBy('issue_comment.issue_id, issue_comment.member_id');
bsw@0 690 general_params.addLimitAndOffset(query, params);
bsw@0 691 db.query(conn, req, res, query, function (issue_comment_result, conn) {
bsw@0 692 var result = { result: issue_comment_result.rows }
bsw@0 693 includes = [];
bsw@0 694 if (params.include_members) includes.push({ class: 'member', objects: 'result'});
bsw@0 695 if (params.include_issues) includes.push({ class: 'issue', objects: 'result'});
bsw@0 696 if (params.include_areas) includes.push({ class: 'area', objects: 'issues'});
bsw@0 697 if (params.include_units) includes.push({ class: 'unit', objects: 'areas'});
bsw@0 698 if (params.include_policies) includes.push({ class: 'policy', objects: 'issues' });
bsw@0 699 addRelatedData(conn, req, res, result, includes);
bsw@0 700 });
bsw@0 701 });
bsw@0 702 },
bsw@0 703
bsw@0 704 '/initiative': function (conn, req, res, params) {
bsw@0 705 requireAccessLevel(conn, req, res, 'anonymous', function() {
bsw@0 706 var query = new selector.Selector();
bsw@0 707 query.from('initiative JOIN issue ON issue.id = initiative.issue_id JOIN policy ON policy.id = issue.policy_id JOIN area ON area.id = issue.area_id JOIN unit ON area.unit_id = unit.id');
bsw@0 708 fields.addObjectFields(query, 'initiative');
bsw@3 709 query.addOrderBy('initiative.id');
bsw@0 710 general_params.addInitiativeOptions(req, query, params);
bsw@0 711 general_params.addLimitAndOffset(query, params);
bsw@0 712 db.query(conn, req, res, query, function (initiative_result, conn) {
bsw@0 713 var result = { result: initiative_result.rows }
bsw@0 714 includes = [];
bsw@0 715 if (params.include_issues) includes.push({ class: 'issue', objects: 'result'});
bsw@0 716 if (params.include_areas) includes.push({ class: 'area', objects: 'issues'});
bsw@0 717 if (params.include_units) includes.push({ class: 'unit', objects: 'areas'});
bsw@0 718 if (params.include_policies) includes.push({ class: 'policy', objects: 'issues' });
bsw@0 719 addRelatedData(conn, req, res, result, includes);
bsw@0 720 });
bsw@0 721 });
bsw@0 722 },
bsw@0 723
bsw@0 724 '/initiator': function (conn, req, res, params) {
bsw@0 725 requireAccessLevel(conn, req, res, 'pseudonym', function() {
bsw@0 726 var fields = ['initiator.initiative_id', 'initiator.member_id'];
bsw@0 727 var query = new selector.Selector();
bsw@0 728 query.from('initiator JOIN member ON member.id = initiator.member_id JOIN initiative ON initiative.id = initiator.initiative_id JOIN issue ON issue.id = initiative.issue_id JOIN policy ON policy.id = issue.policy_id JOIN area ON area.id = issue.area_id JOIN unit ON area.unit_id = unit.id');
bsw@0 729 query.addWhere('initiator.accepted');
bsw@0 730 fields.forEach( function(field) {
bsw@0 731 query.addField(field, null, ['grouped']);
bsw@0 732 });
bsw@0 733 general_params.addMemberOptions(req, query, params);
bsw@0 734 general_params.addInitiativeOptions(req, query, params);
bsw@0 735 query.addOrderBy('initiator.initiative_id, initiator.member_id');
bsw@0 736 general_params.addLimitAndOffset(query, params);
bsw@0 737 db.query(conn, req, res, query, function (initiator, conn) {
bsw@0 738 var result = { result: initiator.rows }
bsw@0 739 includes = [];
bsw@0 740 if (params.include_initiatives) includes.push({ class: 'initiative', objects: 'result'});
bsw@0 741 if (params.include_issues) includes.push({ class: 'issue', objects: 'initiatives'});
bsw@0 742 if (params.include_areas) includes.push({ class: 'area', objects: 'issues'});
bsw@0 743 if (params.include_units) includes.push({ class: 'unit', objects: 'areas'});
bsw@0 744 if (params.include_policies) includes.push({ class: 'policy', objects: 'issues' });
bsw@0 745 addRelatedData(conn, req, res, result, includes);
bsw@0 746 });
bsw@0 747 });
bsw@0 748 },
bsw@0 749
bsw@0 750
bsw@0 751 '/supporter': function (conn, req, res, params) {
bsw@0 752 requireAccessLevel(conn, req, res, 'pseudonym', function() {
bsw@0 753 var fields = ['supporter.issue_id', 'supporter.initiative_id', 'supporter.member_id', 'supporter.draft_id'];
bsw@0 754 var query = new selector.Selector();
bsw@0 755 query.from('supporter')
bsw@0 756 query.join('member', null, 'member.id = supporter.member_id JOIN initiative ON initiative.id = supporter.initiative_id JOIN issue ON issue.id = initiative.issue_id JOIN policy ON policy.id = issue.policy_id JOIN area ON area.id = issue.area_id JOIN unit ON area.unit_id = unit.id');
bsw@0 757 fields.forEach( function(field) {
bsw@0 758 query.addField(field, null, ['grouped']);
bsw@0 759 });
bsw@0 760 general_params.addMemberOptions(req, query, params);
bsw@0 761 general_params.addInitiativeOptions(req, query, params);
bsw@0 762 query.addOrderBy('supporter.issue_id, supporter.initiative_id, supporter.member_id');
bsw@0 763 general_params.addLimitAndOffset(query, params);
bsw@0 764 db.query(conn, req, res, query, function (supporter, conn) {
bsw@0 765 var result = { result: supporter.rows }
bsw@0 766 includes = [];
bsw@0 767 if (params.include_initiatives) includes.push({ class: 'initiative', objects: 'result'});
bsw@0 768 if (params.include_issues) includes.push({ class: 'issue', objects: 'initiatives'});
bsw@0 769 if (params.include_areas) includes.push({ class: 'area', objects: 'issues'});
bsw@0 770 if (params.include_units) includes.push({ class: 'unit', objects: 'areas'});
bsw@0 771 if (params.include_policies) includes.push({ class: 'policy', objects: 'issues' });
bsw@0 772 addRelatedData(conn, req, res, result, includes);
bsw@0 773 });
bsw@0 774 });
bsw@0 775 },
bsw@0 776
bsw@0 777 '/battle': function (conn, req, res, params) {
bsw@0 778 requireAccessLevel(conn, req, res, 'anonymous', function() {
bsw@0 779 var query = new selector.Selector();
bsw@0 780 query.from('battle JOIN initiative ON initiative.id = battle.winning_initiative_id OR initiative.id = battle.losing_initiative_id JOIN issue ON issue.id = battle.issue_id JOIN policy ON policy.id = issue.policy_id JOIN area ON area.id = issue.area_id JOIN unit ON area.unit_id = unit.id');
bsw@0 781 query.addField('battle.*');
bsw@0 782 general_params.addInitiativeOptions(req, query, params);
bsw@0 783 query.addOrderBy('battle.issue_id, battle.winning_initiative_id, battle.losing_initiative_id');
bsw@0 784 general_params.addLimitAndOffset(query, params);
bsw@0 785 db.query(conn, req, res, query, function (result, conn) {
bsw@0 786 var result = { result: result.rows }
bsw@0 787 includes = [];
bsw@0 788 if (params.include_initiatives) includes.push({ class: 'initiative', objects: 'result'});
bsw@0 789 if (params.include_issues) includes.push({ class: 'issue', objects: 'initiatives'});
bsw@0 790 if (params.include_areas) includes.push({ class: 'area', objects: 'issues'});
bsw@0 791 if (params.include_units) includes.push({ class: 'unit', objects: 'areas'});
bsw@0 792 if (params.include_policies) includes.push({ class: 'policy', objects: 'issues' });
bsw@0 793 addRelatedData(conn, req, res, result, includes);
bsw@0 794 });
bsw@0 795 });
bsw@0 796 },
bsw@0 797
bsw@0 798 '/draft': function (conn, req, res, params) {
bsw@0 799 requireAccessLevel(conn, req, res, 'anonymous', function() {
bsw@0 800 var fields = ['draft.initiative_id', 'draft.id', 'draft.formatting_engine', 'draft.content', 'draft.author_id'];
bsw@0 801 var query = new selector.Selector();
bsw@0 802 query.from('draft JOIN initiative ON initiative.id = draft.initiative_id JOIN issue ON issue.id = initiative.issue_id JOIN policy ON policy.id = issue.policy_id JOIN area ON area.id = issue.area_id JOIN unit ON area.unit_id = unit.id');
bsw@0 803 fields.forEach( function(field) {
bsw@0 804 query.addField(field, null, ['grouped']);
bsw@0 805 });
bsw@0 806 if (req.current_access_level != 'anonymous' || req.current_member_id) {
bsw@0 807 query.addField('draft.author_id');
bsw@0 808 }
bsw@0 809 if (params.draft_id) {
bsw@0 810 query.addWhere('draft.id = ?', params.draft_id);
bsw@0 811 }
bsw@0 812 if (params.current_draft) {
bsw@0 813 query.join('current_draft', null, 'current_draft.initiative_id = initiative.id AND current_draft.id = draft.id')
bsw@0 814 }
bsw@0 815 general_params.addInitiativeOptions(req, query, params);
bsw@0 816 query.addOrderBy('draft.initiative_id, draft.id');
bsw@0 817 general_params.addLimitAndOffset(query, params);
bsw@0 818 db.query(conn, req, res, query, function (result, conn) {
bsw@0 819 var result = { result: result.rows }
bsw@0 820 includes = [];
bsw@0 821 if (params.include_initiatives) includes.push({ class: 'initiative', objects: 'result'});
bsw@0 822 if (params.include_issues) includes.push({ class: 'issue', objects: 'initiatives'});
bsw@0 823 if (params.include_areas) includes.push({ class: 'area', objects: 'issues'});
bsw@0 824 if (params.include_units) includes.push({ class: 'unit', objects: 'areas'});
bsw@0 825 if (params.include_policies) includes.push({ class: 'policy', objects: 'issues' });
bsw@0 826 addRelatedData(conn, req, res, result, includes);
bsw@0 827 });
bsw@0 828 });
bsw@0 829 },
bsw@0 830
bsw@0 831 '/suggestion': function (conn, req, res, params) {
bsw@0 832 requireAccessLevel(conn, req, res, 'anonymous', function() {
bsw@0 833 var query = new selector.Selector();
bsw@0 834 query.from('suggestion JOIN initiative ON initiative.id = suggestion.initiative_id JOIN issue ON issue.id = initiative.issue_id JOIN policy ON policy.id = issue.policy_id JOIN area ON area.id = issue.area_id JOIN unit ON area.unit_id = unit.id');
bsw@0 835 if (req.current_access_level == 'anonymous' && !req.current_member_id ) {
bsw@0 836 fields.addObjectFields(query, 'suggestion', 'suggestion_pseudonym');
bsw@0 837 } else {
bsw@0 838 fields.addObjectFields(query, 'suggestion');
bsw@0 839 }
bsw@0 840 general_params.addSuggestionOptions(req, query, params);
bsw@0 841 query.addOrderBy('suggestion.initiative_id, suggestion.id');
bsw@0 842 general_params.addLimitAndOffset(query, params);
bsw@0 843 db.query(conn, req, res, query, function (result, conn) {
bsw@0 844 var result = { result: result.rows }
bsw@0 845 includes = [];
bsw@0 846 if (params.include_initiatives) includes.push({ class: 'initiative', objects: 'result'});
bsw@0 847 if (params.include_issues) includes.push({ class: 'issue', objects: 'initiatives'});
bsw@0 848 if (params.include_areas) includes.push({ class: 'area', objects: 'issues'});
bsw@0 849 if (params.include_units) includes.push({ class: 'unit', objects: 'areas'});
bsw@0 850 if (params.include_policies) includes.push({ class: 'policy', objects: 'issues' });
bsw@0 851 addRelatedData(conn, req, res, result, includes);
bsw@0 852 });
bsw@0 853 });
bsw@0 854 },
bsw@0 855
bsw@0 856 '/opinion': function (conn, req, res, params) {
bsw@0 857 requireAccessLevel(conn, req, res, 'pseudonym', function() {
bsw@0 858 var fields = ['opinion.initiative_id', 'opinion.suggestion_id', 'opinion.member_id', 'opinion.degree', 'opinion.fulfilled']
bsw@0 859 var query = new selector.Selector();
bsw@0 860 query.from('opinion JOIN member ON member.id = opinion.member_id JOIN suggestion ON suggestion.id = opinion.suggestion_id JOIN initiative ON initiative.id = suggestion.initiative_id JOIN issue ON issue.id = initiative.issue_id JOIN policy ON policy.id = issue.policy_id JOIN area ON area.id = issue.area_id JOIN unit ON area.unit_id = unit.id');
bsw@0 861 fields.forEach( function(field) {
bsw@0 862 query.addField(field, null, ['grouped']);
bsw@0 863 });
bsw@0 864 general_params.addMemberOptions(req, query, params);
bsw@0 865 general_params.addSuggestionOptions(req, query, params);
bsw@0 866 query.addOrderBy = ['opinion.initiative_id, opinion.suggestion_id, opinion.member_id'];
bsw@0 867 general_params.addLimitAndOffset(query, params);
bsw@0 868 db.query(conn, req, res, query, function (result, conn) {
bsw@0 869 var result = { result: result.rows }
bsw@0 870 includes = [];
bsw@0 871 if (params.include_suggestions) includes.push({ class: 'suggestion', objects: 'result'});
bsw@0 872 if (params.include_initiatives) includes.push({ class: 'initiative', objects: 'suggestions'});
bsw@0 873 if (params.include_issues) includes.push({ class: 'issue', objects: 'initiatives'});
bsw@0 874 if (params.include_areas) includes.push({ class: 'area', objects: 'issues'});
bsw@0 875 if (params.include_units) includes.push({ class: 'unit', objects: 'areas'});
bsw@0 876 if (params.include_policies) includes.push({ class: 'policy', objects: 'issues' });
bsw@0 877 addRelatedData(conn, req, res, result, includes);
bsw@0 878 });
bsw@0 879 });
bsw@0 880 },
bsw@0 881
bsw@0 882 '/delegation': function (conn, req, res, params) {
bsw@0 883 requireAccessLevel(conn, req, res, 'pseudonym', function() {
bsw@0 884 var fields = ['delegation.id', 'delegation.truster_id', 'delegation.trustee_id', 'delegation.scope', 'delegation.area_id', 'delegation.issue_id', 'delegation.unit_id'];
bsw@0 885 var query = new selector.Selector();
bsw@0 886 query.from('delegation LEFT JOIN issue on delegation.issue_id = issue.id LEFT JOIN policy ON policy.id = issue.policy_id LEFT JOIN area ON area.id = issue.area_id OR area.id = delegation.area_id LEFT JOIN unit ON area.unit_id = unit.id OR unit.id = delegation.unit_id');
bsw@0 887 fields.forEach( function(field) {
bsw@0 888 query.addField(field, null, ['grouped']);
bsw@0 889 });
bsw@0 890 if (params.direction) {
bsw@0 891 switch (params.direction) {
bsw@0 892 case 'in':
bsw@0 893 query.join('member', null, 'member.id = delegation.trustee_id');
bsw@0 894 break;
bsw@0 895 case 'out':
bsw@0 896 query.join('member', null, 'member.id = delegation.truster_id');
bsw@0 897 break;
bsw@0 898 default:
bsw@0 899 respond('json', conn, req, res, 'unprocessable', 'Direction must be "in" or "out" if set.');
bsw@0 900 }
bsw@0 901 } else {
bsw@0 902 query.join('member', null, 'member.id = delegation.truster_id OR member.id = delegation.trustee_id');
bsw@0 903 }
bsw@0 904 general_params.addMemberOptions(req, query, params);
bsw@0 905 general_params.addIssueOptions(req, query, params);
bsw@0 906 if (params.scope) {
bsw@0 907 query.addWhere(['delegation.scope IN (??)', params.scope.split(',')]);
bsw@0 908 };
bsw@0 909 query.addOrderBy = ['delegation.id'];
bsw@0 910 general_params.addLimitAndOffset(query, params);
bsw@0 911 db.query(conn, req, res, query, function (result, conn) {
bsw@0 912 respond('json', conn, req, res, 'ok', { result: result.rows });
bsw@0 913 });
bsw@0 914 });
bsw@0 915 },
bsw@0 916
bsw@0 917 '/vote': function (conn, req, res, params) {
bsw@0 918 requireAccessLevel(conn, req, res, 'pseudonym', function() {
bsw@0 919 var query = new selector.Selector();
bsw@0 920 query.from('vote JOIN member ON member.id = vote.member_id JOIN initiative ON initiative.id = vote.initiative_id JOIN issue ON issue.id = initiative.issue_id JOIN policy ON policy.id = issue.policy_id JOIN area ON area.id = issue.area_id JOIN unit ON area.unit_id = unit.id');
bsw@0 921 query.addField('vote.*');
bsw@0 922 query.addWhere('issue.closed_at NOTNULL');
bsw@0 923 general_params.addMemberOptions(req, query, params);
bsw@0 924 general_params.addInitiativeOptions(req, query, params);
bsw@0 925 general_params.addLimitAndOffset(query, params);
bsw@0 926 db.query(conn, req, res, query, function (result, conn) {
bsw@0 927 respond('json', conn, req, res, 'ok', { result: result.rows });
bsw@0 928 });
bsw@0 929 });
bsw@0 930 },
bsw@0 931
bsw@0 932 '/event': function (conn, req, res, params) { requireAccessLevel(conn, req, res, 'anonymous', function() {
bsw@0 933 var fields = ['event.id', 'event.occurrence', 'event.event', 'event.member_id', 'event.issue_id', 'event.state', 'event.initiative_id', 'event.draft_id', 'event.suggestion_id'];
bsw@0 934 var query = new selector.Selector();
bsw@0 935 query.from('event LEFT JOIN member ON member.id = event.member_id LEFT JOIN initiative ON initiative.id = event.initiative_id LEFT JOIN issue ON issue.id = event.issue_id LEFT JOIN policy ON policy.id = issue.policy_id LEFT JOIN area ON area.id = issue.area_id LEFT JOIN unit ON area.unit_id = unit.id');
bsw@0 936 fields.forEach( function(field) {
bsw@0 937 query.addField(field, null, ['grouped']);
bsw@0 938 });
bsw@0 939 general_params.addMemberOptions(req, query, params);
bsw@0 940 general_params.addInitiativeOptions(req, query, params);
bsw@0 941 query.addOrderBy('event.id');
bsw@0 942 general_params.addLimitAndOffset(query, params);
bsw@0 943 db.query(conn, req, res, query, function (events, conn) {
bsw@0 944 var result = { result: events.rows }
bsw@0 945 includes = [];
bsw@0 946 if (params.include_initiatives) includes.push({ class: 'initiative', objects: 'result'});
bsw@0 947 if (params.include_issues) includes.push({ class: 'issue', objects: 'result'});
bsw@0 948 if (params.include_areas) includes.push({ class: 'area', objects: 'issues'});
bsw@0 949 if (params.include_units) includes.push({ class: 'unit', objects: 'areas'});
bsw@0 950 if (params.include_policies) includes.push({ class: 'policy', objects: 'issues' });
bsw@0 951 addRelatedData(conn, req, res, result, includes);
bsw@0 952 });
bsw@0 953 }); },
bsw@0 954
bsw@0 955 // TODO add interfaces for data structure:
bsw@0 956 // event requireAccessLevel(conn, req, res, 'member');
bsw@0 957 // ignored_member requireAccessLevel(conn, req, res, 'member');
bsw@0 958 // ignored_initiative requireAccessLevel(conn, req, res, 'member');
bsw@0 959 // setting requireAccessLevel(conn, req, res, 'member');
bsw@0 960
bsw@0 961 };
bsw@0 962
bsw@0 963 // ==========================================================================
bsw@0 964 // POST methods
bsw@0 965 // ==========================================================================
bsw@0 966
bsw@0 967
bsw@0 968
bsw@0 969 exports.post = {
bsw@0 970
bsw@0 971 '/echo_test': function (conn, req, res, params) { requireAccessLevel(conn, req, res, 'anonymous', function() {
bsw@0 972 respond('json', conn, req, res, 'ok', { result: params });
bsw@0 973 }); },
bsw@0 974
bsw@0 975 '/register_test': function (conn, req, res, params) {
bsw@0 976 var understood = params.understood;
bsw@0 977 var member_login = randomString(16);
bsw@0 978 var member_name = params.name;
bsw@0 979 var member_password = randomString(16);
bsw@0 980 var member_notify_email = params.email;
bsw@0 981 var member_notify_email_secret = randomString(24);
bsw@0 982 var api_key_member = randomString(24);
bsw@0 983 var api_key_full = randomString(24);
bsw@0 984 var api_key_pseudonym = randomString(24);
bsw@0 985 var api_key_anonymous = randomString(24);
bsw@0 986
bsw@0 987 if (understood != 'understood') {
bsw@0 988 respond('html', conn, req, res, 'unprocessable', null, 'You didn\'t checked the checkbox! Please hit back in your browser and try again.');
bsw@0 989 return;
bsw@0 990 }
bsw@0 991
bsw@0 992 // add member
bsw@0 993 var query = new selector.SQLInsert('member');
bsw@0 994 query.addValues({
bsw@0 995 login: member_login,
bsw@0 996 password: member_password, // TODO hashing of password
bsw@0 997 notify_email_unconfirmed: member_notify_email,
bsw@0 998 notify_email_secret: member_notify_email_secret,
bsw@0 999 name: member_name
bsw@0 1000 });
bsw@0 1001 query.addReturning('id');
bsw@0 1002 db.query(conn, req, res, query, function (result, conn) {
bsw@0 1003 var member_id = result.rows[0].id;
bsw@0 1004
bsw@0 1005 // add privilege for root unit
bsw@0 1006 var query = new selector.SQLInsert('privilege');
bsw@0 1007 query.addValues({ unit_id: 1, member_id: member_id, voting_right: true });
bsw@0 1008 db.query(conn, req, res, query, function (result, conn) {
bsw@0 1009
bsw@0 1010 var location = params.location;
bsw@0 1011 var unit_id;
bsw@0 1012 switch(location) {
bsw@0 1013 case 'earth':
bsw@0 1014 unit_id = 3;
bsw@0 1015 break;
bsw@0 1016 case 'moon':
bsw@0 1017 unit_id = 4;
bsw@0 1018 break;
bsw@0 1019 case 'mars':
bsw@0 1020 unit_id = 5;
bsw@0 1021 break;
bsw@0 1022 }
bsw@0 1023
bsw@0 1024 // add privilege for selected planet
bsw@0 1025 var query = new selector.SQLInsert('privilege');
bsw@0 1026 query.addValues({ unit_id: unit_id, member_id: member_id, voting_right: true });
bsw@0 1027 db.query(conn, req, res, query, function (result, conn) {
bsw@0 1028
bsw@0 1029 // add application key
bsw@0 1030 var query = new selector.SQLInsert('member_application');
bsw@0 1031 query.addValues({
bsw@0 1032 member_id: member_id,
bsw@0 1033 name: 'member',
bsw@0 1034 comment: 'access_level member',
bsw@0 1035 access_level: 'member',
bsw@0 1036 key: api_key_member
bsw@0 1037 });
bsw@0 1038 query.addReturning('id');
bsw@0 1039
bsw@0 1040 db.query(conn, req, res, query, function (result, conn) {
bsw@0 1041
bsw@9 1042 nodemailer.sendmail = '/usr/sbin/sendmail';
bsw@5 1043
bsw@0 1044 // send email to user
bsw@5 1045 nodemailer.send_mail({
bsw@10 1046 sender: config.mail.from,
bsw@0 1047 subject: config.mail.subject_prefix + "Your LiquidFeedback API alpha test account needs confirmation",
bsw@0 1048 to: member_notify_email,
bsw@0 1049 body: "\
bsw@0 1050 Hello " + member_name + ",\n\
bsw@0 1051 \n\
bsw@0 1052 thank you for registering at the public alpha test of the LiquidFeedback\n\
bsw@0 1053 application programming interface. To complete the registration process,\n\
bsw@0 1054 you need to confirm your email address by opening the following URL:\n\
bsw@0 1055 \n\
bsw@0 1056 " + config.public_url_path + "register_test_confirm?secret=" + member_notify_email_secret + "\n\
bsw@0 1057 \n\
bsw@0 1058 \n\
bsw@0 1059 After you've confirmed your email address, your account will be automatically\n\
bsw@0 1060 activated.\n\
bsw@0 1061 \n\
bsw@0 1062 Your account name is: " + member_name + "\n\
bsw@0 1063 \n\
bsw@0 1064 \n\
bsw@0 1065 You will need the following login and password to register and unregister\n\
bsw@0 1066 applications for your account later. This function is currently not\n\
bsw@0 1067 implemented, but please keep the credentials for future use.\n\
bsw@0 1068 \n\
bsw@0 1069 Account ID: " + member_id + "\n\
bsw@0 1070 Login: " + member_login + "\n\
bsw@0 1071 Password: " + member_password + "\n\
bsw@0 1072 \n\
bsw@0 1073 \n\
bsw@0 1074 To make you able to actually access the API interface, we added the following\n\
bsw@0 1075 application key with full member access privileges to your account:\n\
bsw@0 1076 \n\
bsw@0 1077 API Key: " + api_key_member + "\n\
bsw@0 1078 \n\
bsw@0 1079 \n\
bsw@0 1080 The base address of the public test is: " + config.public_url_path + "\n\
bsw@0 1081 \n\
bsw@0 1082 The programming interface is described in the LiquidFeedback API\n\
bsw@0 1083 specification: http://dev.liquidfeedback.org/trac/lf/wiki/API\n\
bsw@0 1084 \n\
bsw@0 1085 The current implementation status of lfapi is published at the LiquidFeedback\n\
bsw@0 1086 API server page: http://dev.liquidfeedback.org/trac/lf/wiki/lfapi\n\
bsw@0 1087 \n\
bsw@0 1088 If you have any questions or suggestions, please use our public mailing list\n\
bsw@0 1089 at http://dev.liquidfeedback.org/cgi-bin/mailman/listinfo/main\n\
bsw@0 1090 \n\
bsw@0 1091 For issues regarding your test account, contact us via email at\n\
bsw@0 1092 lqfb-maintainers@public-software-group.org\n\
bsw@0 1093 \n\
bsw@0 1094 \n\
bsw@0 1095 Sincerely,\n\
bsw@0 1096 \n\
bsw@0 1097 Your LiquidFeedback maintainers",
bsw@0 1098 },
bsw@0 1099 function(err, result){
bsw@0 1100 if(err){ console.log(err); }
bsw@0 1101 });
bsw@0 1102
bsw@0 1103 respond('html', conn, req, res, 'ok', 'Account created. Please check your mailbox!<br /><br /><br /><a href="/">Back to start page</a>');
bsw@0 1104 });
bsw@0 1105 });
bsw@0 1106 });
bsw@0 1107 });
bsw@0 1108 },
bsw@0 1109
bsw@0 1110 /*
bsw@0 1111 '/register': function (conn, req, res, params) {
bsw@0 1112 var invite_key = params.invite_key;
bsw@0 1113 var login = params.login;
bsw@0 1114 var password = params.password;
bsw@0 1115 var name = params.name;
bsw@0 1116 var notify_email = params.notify_email;
bsw@0 1117 if (!invite_key) {
bsw@0 1118 respond('json', conn, req, res, 'unprocessable', null, 'No invite_key supplied.');
bsw@0 1119 return;
bsw@0 1120 };
bsw@0 1121 if (!login) {
bsw@0 1122 respond('json', conn, req, res, 'unprocessable', null, 'No login supplied.');
bsw@0 1123 return;
bsw@0 1124 };
bsw@0 1125 if (!password) {
bsw@0 1126 respond('json', conn, req, res, 'unprocessable', null, 'No password supplied.');
bsw@0 1127 return;
bsw@0 1128 };
bsw@0 1129 if (!name) {
bsw@0 1130 respond('json', conn, req, res, 'unprocessable', null, 'No name supplied.');
bsw@0 1131 return;
bsw@0 1132 };
bsw@0 1133 if (!notify_email) {
bsw@0 1134 respond('json', conn, req, res, 'unprocessable', null, 'No notify_email supplied.');
bsw@0 1135 return;
bsw@0 1136 };
bsw@0 1137 // check if akey is valid and get member_id for akey
bsw@0 1138 db.query(conn, req, res, { select: ['member.id'], from: ['member'], where: ['NOT member.activation AND member.invite_key = ' + db.pgEncode(invite_key)] }, function (result, conn) {
bsw@0 1139 if (result.rows.length != 1) {
bsw@0 1140 respond('json', conn, req, res, 'forbidden', null, 'Supplied invite_key is not valid.');
bsw@0 1141 return;
bsw@0 1142 };
bsw@0 1143 var member_id = result.rows[0].id;
bsw@0 1144 // check if name is available
bsw@0 1145 db.query(conn, req, res, { select: ['NULL'], from: ['member'], where: ['member.name = ' + db.pgEncode(name)] }, function (result, conn) {
bsw@0 1146 if (result.rows.length > 0) {
bsw@0 1147 respond('json', conn, req, res, 'forbidden', null, 'Login name is not available, choose another one.');
bsw@0 1148 return;
bsw@0 1149 };
bsw@0 1150 // check if login is available
bsw@0 1151 db.query(conn, req, res, { select: ['NULL'], from: ['member'], where: ['member.login = ' + db.pgEncode(login)] }, function (result, conn) {
bsw@0 1152 if (result.rows.length > 0) {
bsw@0 1153 respond('json', conn, req, res, 'forbidden', null, 'Name is not available, choose another one.');
bsw@0 1154 return;
bsw@0 1155 };
bsw@0 1156 var query = { update: 'member', set: { activation: 'now', active: true, } };
bsw@0 1157
bsw@0 1158 });
bsw@0 1159 });
bsw@0 1160 });
bsw@0 1161 },
bsw@0 1162 */
bsw@0 1163
bsw@0 1164 '/session': function (conn, req, res, params) {
bsw@0 1165 var key = params.key;
bsw@0 1166 if (!key) {
bsw@0 1167 respond('json', conn, req, res, 'unprocessable', null, 'No application key supplied.');
bsw@0 1168 return;
bsw@0 1169 };
bsw@0 1170 var query = new selector.Selector();
bsw@0 1171 query.from('member');
bsw@0 1172 query.join('member_application', null, 'member_application.member_id = member.id');
bsw@0 1173 query.addField('member.id');
bsw@0 1174 query.addWhere(['member.active AND member_application.key = ?', key]);
bsw@0 1175 if (params.interactive) {
bsw@0 1176 query.forUpdateOf('member');
bsw@0 1177 }
bsw@0 1178 db.query(conn, req, res, query, function (result, conn) {
bsw@0 1179 if (result.rows.length != 1) {
bsw@0 1180 respond('json', conn, req, res, 'forbidden', null, 'Supplied application key is not valid.');
bsw@0 1181 return;
bsw@0 1182 };
bsw@0 1183 var member_id = result.rows[0].id;
bsw@0 1184 var session_key = randomString(16);
bsw@0 1185 req.sessions[session_key] = member_id;
bsw@0 1186 var query;
bsw@0 1187 if (params.interactive) {
bsw@0 1188 query = new selector.SQLUpdate('member');
bsw@0 1189 query.addWhere(['member.id = ?', member_id]);
bsw@0 1190 query.addValues({ last_activity: 'now' });
bsw@0 1191 }
bsw@0 1192 db.query(conn, req, res, query, function (result, conn) {
bsw@0 1193 respond('json', conn, req, res, 'ok', { session_key: session_key });
bsw@0 1194 });
bsw@0 1195 });
bsw@0 1196 },
bsw@0 1197
bsw@0 1198 '/member': function (conn, req, res, params) {
bsw@0 1199 var fields = ['organizational_unit', 'internal_posts', 'realname', 'birthday', 'address', 'email', 'xmpp_address', 'website', 'phone', 'mobile_phone', 'profession', 'external_memberships', 'external_posts', 'statement']
bsw@0 1200 requireAccessLevel(conn, req, res, 'member', function() {
bsw@0 1201 var query = new selector.SQLUpdate('member');
bsw@0 1202 query.addWhere(['member.id = ?', req.current_member_id]);
bsw@0 1203 fields.forEach( function(field) {
bsw@0 1204 if (typeof(params[field]) != 'undefined') {
bsw@3 1205 query.addValues({ field: params[field] });
bsw@0 1206 } else {
bsw@3 1207 query.addValues({ field: null });
bsw@0 1208 }
bsw@0 1209 });
bsw@0 1210 db.query(conn, req, res, query, function(result) { respond('json', conn, req, res, 'ok'); });
bsw@0 1211 });
bsw@0 1212 },
bsw@0 1213
bsw@0 1214 '/membership': function (conn, req, res, params) {
bsw@0 1215 requireAccessLevel(conn, req, res, 'member', function() {
bsw@0 1216
bsw@0 1217 // check if area_id is set
bsw@0 1218 var area_id = parseInt(params.area_id);
bsw@0 1219 if (!area_id) {
bsw@0 1220 respond('json', conn, req, res, 'unprocessable', null, 'You need to supply an area_id.');
bsw@0 1221 return;
bsw@0 1222 }
bsw@0 1223
bsw@0 1224 // delete membership
bsw@0 1225 if (params.delete) {
bsw@0 1226 var query;
bsw@0 1227 query = new selector.SQLDelete('membership');
bsw@0 1228 query.addWhere(['area_id = ?', area_id]);
bsw@0 1229 query.addWhere(['member_id = ?', req.current_member_id]);
bsw@0 1230 db.query(conn, req, res, query, function(result) { respond('json', conn, req, res, 'ok'); });
bsw@0 1231
bsw@0 1232 // add membership
bsw@0 1233 } else {
bsw@0 1234
bsw@0 1235 // lock member for upsert
bsw@0 1236 lockMemberById(conn, req, res, req.current_member_id, function() {
bsw@0 1237
bsw@0 1238 // check and lock privilege
bsw@0 1239 requireAreaPrivilege(conn, req, res, area_id, function() {
bsw@0 1240
bsw@0 1241 // upsert membership
bsw@0 1242 var query = new selector.Upserter('membership', ['area_id', 'member_id']);
bsw@0 1243 query.addValues({ area_id: area_id, member_id: req.current_member_id });
bsw@0 1244 db.query(conn, req, res, query, function(result) {
bsw@0 1245 respond('json', conn, req, res, 'ok');
bsw@0 1246 });
bsw@0 1247 });
bsw@0 1248 });
bsw@0 1249 }
bsw@0 1250 });
bsw@0 1251 },
bsw@0 1252
bsw@0 1253 '/interest': function (conn, req, res, params) {
bsw@0 1254 requireAccessLevel(conn, req, res, 'member', function() {
bsw@0 1255 var query;
bsw@0 1256
bsw@0 1257 // check if issue_id is set
bsw@0 1258 var issue_id = parseInt(params.issue_id);
bsw@0 1259 if (!issue_id) {
bsw@0 1260 respond('json', conn, req, res, 'unprocessable', null, 'You need to supply an issue_id.');
bsw@0 1261 return;
bsw@0 1262 }
bsw@0 1263
bsw@0 1264 // lock member for upsert
bsw@0 1265 lockMemberById(conn, req, res, req.current_member_id, function() {
bsw@0 1266
bsw@0 1267 // delete interest
bsw@0 1268 if (params.delete) {
bsw@0 1269
bsw@0 1270 // check issue state
bsw@0 1271 requireIssueState(conn, req, res, issue_id, ['admission', 'discussion', 'verification'], function() {
bsw@0 1272
bsw@0 1273 // delete interest
bsw@0 1274 query = new selector.SQLDelete('interest');
bsw@0 1275 query.addWhere(['issue_id = ?', issue_id]);
bsw@0 1276 query.addWhere(['member_id = ?', req.current_member_id]);
bsw@0 1277 db.query(conn, req, res, query, function(result) { respond('json', conn, req, res, 'ok'); });
bsw@0 1278 });
bsw@0 1279
bsw@0 1280 // add interest
bsw@0 1281 } else {
bsw@0 1282
bsw@0 1283 // check and lock privilege
bsw@0 1284 requireIssuePrivilege(conn, req, res, issue_id, function() {
bsw@0 1285
bsw@0 1286 // check issue state
bsw@0 1287 requireIssueState(conn, req, res, issue_id, ['admission', 'discussion', 'verification'], function() {
bsw@0 1288
bsw@0 1289 // upsert interest
bsw@0 1290 var query = new selector.Upserter('interest', ['issue_id', 'member_id']);
bsw@0 1291 query.addValues({ issue_id: issue_id, member_id: req.current_member_id });
bsw@0 1292 db.query(conn, req, res, query, function(result) {
bsw@0 1293 respond('json', conn, req, res, 'ok');
bsw@0 1294 });
bsw@0 1295 });
bsw@0 1296 });
bsw@0 1297 };
bsw@0 1298 });
bsw@0 1299 });
bsw@0 1300 },
bsw@0 1301
bsw@0 1302 '/issue_comment': function (conn, req, res, params) {
bsw@0 1303 requireAccessLevel(conn, req, res, 'member', function() {
bsw@0 1304
bsw@0 1305 var issue_id = parseInt(params.issue_id);
bsw@0 1306 var formatting_engine = params.formatting_engine
bsw@0 1307 var content = params.content;
bsw@0 1308
bsw@0 1309 if (!issue_id) {
bsw@0 1310 respond('json', conn, req, res, 'unprocessable', null, 'You need to supply an issue_id.');
bsw@0 1311 return;
bsw@0 1312 }
bsw@0 1313
bsw@0 1314 // delete issue comment
bsw@0 1315 if (params.delete) {
bsw@0 1316 var query;
bsw@0 1317 query = new selector.SQLDelete('issue_comment');
bsw@0 1318 query.addWhere(['issue_id = ?', params.issue_id]);
bsw@0 1319 query.addWhere(['member_id = ?', req.current_member_id]);
bsw@0 1320 db.query(conn, req, res, query, function(result) { respond('json', conn, req, res, 'ok'); });
bsw@0 1321
bsw@0 1322 // upsert issue comment
bsw@0 1323 } else {
bsw@0 1324
bsw@0 1325 // check if formatting engine is supplied and valid
bsw@0 1326 if (!formatting_engine) {
bsw@0 1327 respond('json', conn, req, res, 'unprocessable', null, 'No formatting engine supplied.');
bsw@0 1328 return;
bsw@0 1329 } else if (formatting_engine != 'rocketwiki' && formatting_engine != 'compat') {
bsw@0 1330 respond('json', conn, req, res, 'unprocessable', null, 'Invalid formatting engine supplied.');
bsw@0 1331 return;
bsw@0 1332 };
bsw@0 1333
bsw@0 1334 // check if content is supplied
bsw@0 1335 if (!content) {
bsw@0 1336 respond('json', conn, req, res, 'unprocessable', null, 'No content supplied.');
bsw@0 1337 return;
bsw@0 1338 }
bsw@0 1339
bsw@0 1340 // lock member for upsert
bsw@0 1341 lockMemberById(conn, req, res, req.current_member_id, function() {
bsw@0 1342
bsw@0 1343 // check and lock privilege
bsw@0 1344 requireIssuePrivilege(conn, req, res, issue_id, function() {
bsw@0 1345
bsw@0 1346 // upsert issue comment
bsw@0 1347 var query = new selector.Upserter('issue_comment', ['issue_id', 'member_id']);
bsw@0 1348 query.addValues({
bsw@0 1349 issue_id: issue_id,
bsw@0 1350 member_id: req.current_member_id,
bsw@0 1351 changed: 'now',
bsw@0 1352 formatting_engine: formatting_engine,
bsw@0 1353 content: content
bsw@0 1354 });
bsw@0 1355
bsw@0 1356 db.query(conn, req, res, query, function(result) {
bsw@0 1357 respond('json', conn, req, res, 'ok');
bsw@0 1358 });
bsw@0 1359
bsw@0 1360 });
bsw@0 1361 });
bsw@0 1362
bsw@0 1363 }
bsw@0 1364
bsw@0 1365 });
bsw@0 1366 },
bsw@0 1367
bsw@0 1368 '/voting_comment': function (conn, req, res, params) {
bsw@0 1369 requireAccessLevel(conn, req, res, 'member', function() {
bsw@0 1370
bsw@0 1371 var issue_id = parseInt(params.issue_id);
bsw@0 1372 var formatting_engine = params.formatting_engine
bsw@0 1373 var content = params.content;
bsw@0 1374
bsw@0 1375 if (!issue_id) {
bsw@0 1376 respond('json', conn, req, res, 'unprocessable', null, 'You need to supply an issue_id.');
bsw@0 1377 return;
bsw@0 1378 }
bsw@0 1379
bsw@0 1380
bsw@0 1381 // delete voting comment
bsw@0 1382 if (params.delete) {
bsw@0 1383 var query;
bsw@0 1384 query = new selector.SQLDelete('voting_comment');
bsw@0 1385 query.addWhere(['issue_id = ?', params.issue_id]);
bsw@0 1386 query.addWhere(['member_id = ?', req.current_member_id]);
bsw@0 1387 db.query(conn, req, res, query, function(result) { respond('json', conn, req, res, 'ok'); });
bsw@0 1388
bsw@0 1389 // upsert voting comment
bsw@0 1390 } else {
bsw@0 1391
bsw@0 1392 // check if formatting engine is supplied and valid
bsw@0 1393 if (!formatting_engine) {
bsw@0 1394 respond('json', conn, req, res, 'unprocessable', null, 'No formatting engine supplied.');
bsw@0 1395 return;
bsw@0 1396 } else if (formatting_engine != 'rocketwiki' && formatting_engine != 'compat') {
bsw@0 1397 respond('json', conn, req, res, 'unprocessable', null, 'Invalid formatting engine supplied.');
bsw@0 1398 return;
bsw@0 1399 };
bsw@0 1400
bsw@0 1401 // check if content is supplied
bsw@0 1402 if (!content) {
bsw@0 1403 respond('json', conn, req, res, 'unprocessable', null, 'No content supplied.');
bsw@0 1404 return;
bsw@0 1405 }
bsw@0 1406
bsw@0 1407 // lock member for upsert
bsw@0 1408 lockMemberById(conn, req, res, req.current_member_id, function() {
bsw@0 1409
bsw@0 1410 // check and lock privilege
bsw@0 1411 requireIssuePrivilege(conn, req, res, issue_id, function() {
bsw@0 1412
bsw@0 1413 // check issue state
bsw@0 1414 requireIssueState(conn, req, res, issue_id, ['voting', 'finished_with_winner', 'finished_without_winner'], function() {
bsw@0 1415
bsw@0 1416 // upsert voting comment
bsw@0 1417 var query = new selector.Upserter('voting_comment', ['issue_id', 'member_id']);
bsw@0 1418 query.addValues({
bsw@0 1419 issue_id: issue_id,
bsw@0 1420 member_id: req.current_member_id,
bsw@0 1421 changed: 'now',
bsw@0 1422 formatting_engine: formatting_engine,
bsw@0 1423 content: content
bsw@0 1424 });
bsw@0 1425
bsw@0 1426 db.query(conn, req, res, query, function(result) {
bsw@0 1427 respond('json', conn, req, res, 'ok');
bsw@0 1428 });
bsw@0 1429
bsw@0 1430 });
bsw@0 1431 });
bsw@0 1432 })
bsw@0 1433 };
bsw@0 1434 });
bsw@0 1435 },
bsw@0 1436
bsw@0 1437 '/supporter': function (conn, req, res, params) {
bsw@0 1438 requireAccessLevel(conn, req, res, 'member', function() {
bsw@0 1439 var initiative_id = parseInt(params.initiative_id);
bsw@0 1440 var draft_id = parseInt(params.draft_id);
bsw@0 1441
bsw@0 1442 // check if needed arguments are supplied
bsw@0 1443 if (!initiative_id) {
bsw@0 1444 respond('json', conn, req, res, 'unprocessable', null, 'You need to supply an initiative_id.');
bsw@0 1445 return;
bsw@0 1446 }
bsw@0 1447
bsw@0 1448 if (!draft_id) {
bsw@0 1449 respond('json', conn, req, res, 'unprocessable', null, 'You need to supply an draft_id.');
bsw@0 1450 return;
bsw@0 1451 }
bsw@0 1452
bsw@0 1453 // lock member for upsert
bsw@0 1454 lockMemberById(conn, req, res, req.current_member_id, function() {
bsw@0 1455
bsw@0 1456 // delete supporter
bsw@0 1457 if (params.delete) {
bsw@0 1458
bsw@0 1459 // check issue state
bsw@0 1460 requireIssueStateForInitiative(conn, req, res, initiative_id, ['admission', 'discussion', 'verification'], function() {
bsw@0 1461
bsw@0 1462 // delete supporter
bsw@0 1463 var query = new selector.SQLDelete('supporter');
bsw@0 1464 query.addWhere(['initiative_id = ?', initiative_id]);
bsw@0 1465 query.addWhere(['member_id = ?', req.current_member_id]);
bsw@0 1466 db.query(conn, req, res, query, function(result) { respond('json', conn, req, res, 'ok'); });
bsw@0 1467
bsw@0 1468 });
bsw@0 1469
bsw@0 1470 // upsert supporter
bsw@0 1471 } else {
bsw@0 1472
bsw@0 1473 // check and lock privilege
bsw@0 1474 requireInitiativePrivilege(conn, req, res, initiative_id, function() {
bsw@0 1475
bsw@0 1476 // check issue state
bsw@0 1477 requireIssueStateForInitiative(conn, req, res, initiative_id, ['admission', 'discussion', 'verification'], function() {
bsw@0 1478
bsw@0 1479 // check if given draft is the current one
bsw@0 1480 var query = new selector.Selector('current_draft');
bsw@0 1481 query.addField('NULL');
bsw@0 1482 query.addWhere(['current_draft.initiative_id = ?', initiative_id]);
bsw@0 1483 query.addWhere(['current_draft.id = ?', draft_id]);
bsw@0 1484
bsw@0 1485 db.query(conn, req, res, query, function(result) {
bsw@0 1486 if (result.rows.length != 1) {
bsw@0 1487 respond('json', conn, req, res, 'conflict', null, 'The draft with the supplied draft_id is not the current one anymore!');
bsw@0 1488 return;
bsw@0 1489 }
bsw@0 1490
bsw@0 1491 // upsert supporter
bsw@0 1492 var query = new selector.Upserter('supporter', ['initiative_id', 'member_id']);
bsw@0 1493 query.addValues({
bsw@0 1494 initiative_id: initiative_id,
bsw@0 1495 member_id: req.current_member_id,
bsw@0 1496 draft_id: draft_id
bsw@0 1497 });
bsw@0 1498
bsw@0 1499 db.query(conn, req, res, query, function(result) {
bsw@0 1500 respond('json', conn, req, res, 'ok');
bsw@0 1501 });
bsw@0 1502
bsw@0 1503 });
bsw@0 1504 });
bsw@0 1505 });
bsw@0 1506 };
bsw@0 1507 });
bsw@0 1508 });
bsw@0 1509 },
bsw@0 1510
bsw@0 1511 '/draft': function (conn, req, res, params) {
bsw@0 1512 requireAccessLevel(conn, req, res, 'member', function() {
bsw@0 1513 var area_id = parseInt(params.area_id);
bsw@0 1514 var policy_id = parseInt(params.policy_id);
bsw@0 1515 var issue_id = parseInt(params.issue_id);
bsw@0 1516 var initiative_id = parseInt(params.initiative_id);
bsw@0 1517 var initiative_name = params.initiative_name;
bsw@0 1518 var initiative_discussion_url = params.initiative_discussion_url;
bsw@0 1519 var formatting_engine = params.formatting_engine;
bsw@0 1520 var content = params.content;
bsw@0 1521
bsw@0 1522 if (!initiative_discussion_url) initiative_discussion_url = null;
bsw@0 1523
bsw@0 1524 // check parameters
bsw@0 1525 if (!formatting_engine) {
bsw@0 1526 respond('json', conn, req, res, 'unprocessable', null, 'No formatting_engine supplied.');
bsw@0 1527 return;
bsw@0 1528 } else if (formatting_engine != 'rocketwiki' && formatting_engine != 'compat') {
bsw@0 1529 respond('json', conn, req, res, 'unprocessable', null, 'Invalid formatting engine supplied.');
bsw@0 1530 return;
bsw@0 1531 };
bsw@0 1532
bsw@0 1533 if (!content) {
bsw@0 1534 respond('json', conn, req, res, 'unprocessable', null, 'No draft content supplied.');
bsw@0 1535 return;
bsw@0 1536 };
bsw@0 1537
bsw@0 1538 lockMemberById(conn, req, res, req.current_member_id, function() {
bsw@0 1539
bsw@0 1540 // new draft in new initiative in new issue
bsw@0 1541 if (area_id && !issue_id && !initiative_id) {
bsw@0 1542
bsw@0 1543 // check parameters for new issue
bsw@0 1544 if (!policy_id) {
bsw@0 1545 respond('json', conn, req, res, 'unprocessable', null, 'No policy supplied.');
bsw@0 1546 return;
bsw@0 1547 }
bsw@0 1548
bsw@0 1549 if (!initiative_name) {
bsw@0 1550 respond('json', conn, req, res, 'unprocessable', null, 'No initiative name supplied.');
bsw@0 1551 return;
bsw@0 1552 }
bsw@0 1553
bsw@0 1554 requireAreaPrivilege(conn, req, res, area_id, function() {
bsw@0 1555
bsw@0 1556 // check if policy is allowed in this area and if area and policy are active
bsw@0 1557 var query = new selector.Selector();
bsw@0 1558 query.from('allowed_policy');
bsw@0 1559 query.join('area', null, 'area.id = allowed_policy.area_id AND area.active');
bsw@0 1560 query.join('policy', null, 'policy.id = allowed_policy.policy_id AND policy.active');
bsw@0 1561 query.addField('NULL');
bsw@0 1562 query.addWhere(['area.id = ? AND policy.id = ?', area_id, policy_id]);
bsw@0 1563 db.query(conn, req, res, query, function (result, conn) {
bsw@0 1564 if (result.rows.length != 1) {
bsw@0 1565 respond('json', conn, req, res, 'unprocessable', null, 'Area and/or policy doesn\'t exist, area and/or policy is not active or policy is not allowed in this area.');
bsw@0 1566 return;
bsw@0 1567 };
bsw@0 1568
bsw@0 1569 // check contingent
bsw@0 1570 requireContingentLeft(conn, req, res, true, function() {
bsw@0 1571
bsw@0 1572 // insert new issue
bsw@0 1573 var query = new selector.SQLInsert('issue');
bsw@0 1574 query.addValues({
bsw@0 1575 area_id: area_id,
bsw@0 1576 policy_id: policy_id
bsw@0 1577 });
bsw@0 1578 query.addReturning('id');
bsw@0 1579 db.query(conn, req, res, query, function(result) {
bsw@0 1580 var issue_id = result.rows[0].id;
bsw@0 1581
bsw@0 1582 // insert new initiative
bsw@0 1583 var query = new selector.SQLInsert('initiative');
bsw@0 1584 query.addValues({
bsw@0 1585 issue_id: issue_id,
bsw@0 1586 name: initiative_name,
bsw@0 1587 discussion_url: initiative_discussion_url
bsw@0 1588 });
bsw@0 1589 query.addReturning('id');
bsw@0 1590 db.query(conn, req, res, query, function(result) {
bsw@0 1591 var initiative_id = result.rows[0].id;
bsw@0 1592
bsw@0 1593 // insert initiator
bsw@0 1594 var query = new selector.SQLInsert('initiator');
bsw@0 1595 query.addValues({ initiative_id: initiative_id, member_id: req.current_member_id, accepted: true });
bsw@0 1596 db.query(conn, req, res, query, function(result) {
bsw@0 1597
bsw@0 1598 // insert new draft
bsw@0 1599 var query = new selector.SQLInsert('draft');
bsw@0 1600 query.addValues({
bsw@0 1601 initiative_id: initiative_id,
bsw@0 1602 author_id: req.current_member_id,
bsw@0 1603 formatting_engine: formatting_engine,
bsw@0 1604 content: content
bsw@0 1605 });
bsw@0 1606 query.addReturning('id');
bsw@0 1607 db.query(conn, req, res, query, function (result, conn) {
bsw@0 1608 var draft_id = result.rows[0].id;
bsw@0 1609
bsw@0 1610 respond('json', conn, req, res, 'ok', { issue_id: issue_id, initiative_id: initiative_id, draft_id: draft_id } );
bsw@0 1611 });
bsw@0 1612 });
bsw@0 1613 });
bsw@0 1614 });
bsw@0 1615 });
bsw@0 1616 });
bsw@0 1617 });
bsw@0 1618
bsw@0 1619 // new draft in new initiative in existant issue
bsw@0 1620 } else if (issue_id && !area_id && !initiative_id) {
bsw@0 1621
bsw@3 1622 if (!initiative_name) {
bsw@3 1623 respond('json', conn, req, res, 'unprocessable', null, 'No initiative name supplied.');
bsw@3 1624 return;
bsw@3 1625 }
bsw@3 1626
bsw@0 1627 // check privilege
bsw@0 1628 requireIssuePrivilege(conn, req, res, issue_id, function() {
bsw@0 1629
bsw@0 1630 // check issue state
bsw@0 1631 requireIssueState(conn, req, res, issue_id, ['admission', 'discussion', 'verification'], function() {
bsw@0 1632
bsw@0 1633 // check contingent
bsw@0 1634 requireContingentLeft(conn, req, res, true, function() {
bsw@0 1635
bsw@0 1636 // insert initiative
bsw@0 1637 var query = new selector.SQLInsert('initiative');
bsw@0 1638 query.addValues({
bsw@0 1639 issue_id: issue_id,
bsw@0 1640 name: initiative_name,
bsw@0 1641 discussion_url: initiative_discussion_url
bsw@0 1642 });
bsw@0 1643 query.addReturning('id');
bsw@0 1644 db.query(conn, req, res, query, function(result) {
bsw@0 1645 var initiative_id = result.rows[0].id;
bsw@0 1646
bsw@0 1647 // insert initiator
bsw@0 1648 var query = new selector.SQLInsert('initiator');
bsw@0 1649 query.addValues({
bsw@0 1650 initiative_id: initiative_id,
bsw@0 1651 member_id: req.current_member_id,
bsw@0 1652 accepted: true
bsw@0 1653 });
bsw@0 1654 db.query(conn, req, res, query, function(result) {
bsw@0 1655
bsw@0 1656 // insert draft
bsw@0 1657 var query = new selector.SQLInsert('draft');
bsw@0 1658 query.addValues({
bsw@0 1659 initiative_id: initiative_id,
bsw@0 1660 author_id: req.current_member_id,
bsw@0 1661 formatting_engine: formatting_engine,
bsw@0 1662 content: content
bsw@0 1663 });
bsw@0 1664 query.addReturning('id');
bsw@0 1665 db.query(conn, req, res, query, function (result, conn) {
bsw@0 1666
bsw@0 1667 var draft_id = result.rows[0].id;
bsw@0 1668 respond('json', conn, req, res, 'ok', { initiative_id: initiative_id, draft_id: draft_id } );
bsw@0 1669
bsw@0 1670 });
bsw@0 1671 });
bsw@0 1672 });
bsw@0 1673 });
bsw@0 1674 });
bsw@0 1675 });
bsw@0 1676
bsw@0 1677 // new draft in existant initiative
bsw@0 1678 } else if (initiative_id && !area_id && !issue_id ) {
bsw@0 1679
bsw@0 1680 // check privilege
bsw@0 1681 requireInitiativePrivilege(conn, req, res, initiative_id, function() {
bsw@0 1682
bsw@0 1683 // check issue state
bsw@0 1684 requireIssueStateForInitiative(conn, req, res, initiative_id, ['admission', 'discussion'], function() {
bsw@0 1685
bsw@0 1686
bsw@0 1687 // get initiator
bsw@0 1688 var query = new selector.Selector();
bsw@0 1689 query.from('initiator');
bsw@0 1690 query.addField('accepted');
bsw@0 1691 query.addWhere(['initiative_id = ? AND member_id = ?', initiative_id, req.current_member_id]);
bsw@0 1692 db.query(conn, req, res, query, function (result, conn) {
bsw@0 1693
bsw@0 1694 // if member is not initiator, deny creating new draft
bsw@0 1695 if (result.rows.length != 1) {
bsw@0 1696 respond('json', conn, req, res, 'forbidden', null, 'You are not initiator of this initiative and not allowed to update its draft.');
bsw@0 1697 return;
bsw@0 1698 }
bsw@0 1699 var initiator = result.rows[0];
bsw@0 1700 if (!initiator.accepted) {
bsw@0 1701 respond('json', conn, req, res, 'forbidden', null, 'You have been invited as initiator, but haven\'t accepted invitation and you are not allowed to update this initiative.');
bsw@0 1702 return;
bsw@0 1703 };
bsw@0 1704
bsw@0 1705 // check contingent
bsw@0 1706 requireContingentLeft(conn, req, res, false, function() {
bsw@0 1707
bsw@0 1708 // insert new draft
bsw@0 1709 var query = new selector.SQLInsert('draft');
bsw@0 1710 query.addValues({
bsw@0 1711 initiative_id: initiative_id,
bsw@0 1712 author_id: req.current_member_id,
bsw@0 1713 formatting_engine: formatting_engine,
bsw@0 1714 content: content
bsw@0 1715 });
bsw@0 1716 query.addReturning('id');
bsw@0 1717 db.query(conn, req, res, query, function (result, conn) {
bsw@0 1718
bsw@0 1719 var draft_id = result.rows[0].id;
bsw@0 1720 respond('json', conn, req, res, 'ok', { draft_id: draft_id } );
bsw@0 1721 });
bsw@0 1722 });
bsw@0 1723 });
bsw@0 1724 });
bsw@0 1725 });
bsw@0 1726
bsw@0 1727 // none of them (invalid request)
bsw@0 1728 } else {
bsw@0 1729 respond('json', conn, req, res, 'unprocessable', null, 'Excactly one of area_id, issue_id or initiative_id must be supplied!');
bsw@0 1730 };
bsw@0 1731
bsw@0 1732 });
bsw@0 1733 });
bsw@0 1734 },
bsw@0 1735
bsw@0 1736 '/suggestion': function (conn, req, res, params) {
bsw@0 1737 requireAccessLevel(conn, req, res, 'member', function() {
bsw@0 1738 // TODO
bsw@0 1739 });
bsw@0 1740 },
bsw@0 1741
bsw@0 1742 '/opinion': function (conn, req, res, params) {
bsw@0 1743 requireAccessLevel(conn, req, res, 'member', function() {
bsw@0 1744 // TODO
bsw@0 1745 });
bsw@0 1746 },
bsw@0 1747
bsw@0 1748 '/delegation': function (conn, req, res, params) {
bsw@0 1749 requireAccessLevel(conn, req, res, 'member', function() {
bsw@0 1750 var unit_id = parseInt(params.unit_id);
bsw@0 1751 var area_id = parseInt(params.area_id);
bsw@0 1752 var issue_id = parseInt(params.issue_id);
bsw@0 1753 var trustee_id;
bsw@0 1754
bsw@0 1755 if (params.trustee_id == '') {
bsw@0 1756 trustee_id = null;
bsw@0 1757 } else {
bsw@0 1758 trustee_id = parseInt(params.trustee_id);
bsw@0 1759 }
bsw@0 1760
bsw@0 1761 lockMemberById(conn, req, res, req.current_member_id, function() {
bsw@0 1762
bsw@0 1763 if (params.delete) {
bsw@0 1764 var query = new selector.SQLDelete('delegation')
bsw@0 1765 if (unit_id && !area_id && !issue_id) {
bsw@0 1766 query.addWhere(['unit_id = ?', unit_id]);
bsw@0 1767 } else if (!unit_id && area_id && !issue_id) {
bsw@0 1768 query.addWhere(['area_id = ?', area_id]);
bsw@0 1769 } else if (!unit_id && !area_id && issue_id) {
bsw@0 1770 query.addWhere(['issue_id = ?', issue_id]);
bsw@0 1771 } else {
bsw@0 1772 respond('json', conn, req, res, 'unprocessable', null, 'Excactly one of unit, area_id, issue_id must be supplied!');
bsw@0 1773 return;
bsw@0 1774 }
bsw@0 1775 query.addWhere(['truster_id = ?', req.current_member_id]);
bsw@0 1776 db.query(conn, req, res, query, function(result) { respond('json', conn, req, res, 'ok'); });
bsw@0 1777 } else {
bsw@0 1778 var query = new selector.Upserter('delegation', ['truster_id']);
bsw@0 1779 query.addValues({
bsw@0 1780 truster_id: req.current_member_id,
bsw@0 1781 trustee_id: trustee_id
bsw@0 1782 });
bsw@0 1783 if (unit_id && !area_id && !issue_id) {
bsw@0 1784
bsw@0 1785 // check privilege
bsw@0 1786 requireUnitPrivilege(conn, req, res, unit_id, function() {
bsw@0 1787
bsw@0 1788 query.addKeys(['unit_id'])
bsw@0 1789 query.addValues({ unit_id: unit_id, scope: 'unit' });
bsw@0 1790 db.query(conn, req, res, query, function(result) { respond('json', conn, req, res, 'ok'); });
bsw@0 1791 });
bsw@0 1792
bsw@0 1793 } else if (!unit_id && area_id && !issue_id) {
bsw@0 1794
bsw@0 1795 // check privilege
bsw@0 1796 requireAreaPrivilege(conn, req, res, area_id, function() {
bsw@0 1797
bsw@0 1798 query.addKeys(['area_id'])
bsw@0 1799 query.addValues({ area_id: area_id, scope: 'area' });
bsw@0 1800 db.query(conn, req, res, query, function(result) { respond('json', conn, req, res, 'ok'); });
bsw@0 1801 });
bsw@0 1802
bsw@0 1803 } else if (!unit_id && !area_id && issue_id) {
bsw@0 1804
bsw@0 1805 // check privilege
bsw@0 1806 requireIssuePrivilege(conn, req, res, issue_id, function() {
bsw@0 1807
bsw@0 1808 // check issue state
bsw@0 1809 requireIssueState(conn, req, res, issue_id, ['admission', 'discussion', 'verification', 'voting'], function() {
bsw@0 1810
bsw@0 1811 query.addKeys(['issue_id'])
bsw@0 1812 query.addValues({ issue_id: issue_id, scope: 'issue' });
bsw@0 1813 db.query(conn, req, res, query, function(result) { respond('json', conn, req, res, 'ok'); });
bsw@0 1814 });
bsw@0 1815 });
bsw@0 1816 } else {
bsw@0 1817 respond('json', conn, req, res, 'unprocessable', null, 'Excactly one of unit_id, area_id, issue_id must be supplied!');
bsw@0 1818 return;
bsw@0 1819 }
bsw@0 1820 }
bsw@0 1821
bsw@0 1822 });
bsw@0 1823
bsw@0 1824 });
bsw@0 1825 },
bsw@0 1826
bsw@0 1827 };

Impressum / About Us