lfapi

annotate lfapi/main.js @ 21:2fcdef9f0e9c

Added support for delegating population
author bsw
date Sun Nov 06 19:40:56 2011 +0100 (2011-11-06)
parents da041f00018a
children fef5d8aad4aa
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@11 93 var content_type = 'application/json; charset=UTF-8';
bsw@0 94 if (req.params && req.params.callback) {
bsw@0 95 body = req.params.callback + '(' + body + ')';
bsw@11 96 content_type = 'text/javascript; charset=UTF-8';
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@11 114 'Content-Type': 'text/html; charset=UTF-8',
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@12 321 // GET 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@15 650 '/population': function (conn, req, res, params) {
bsw@15 651 requireAccessLevel(conn, req, res, 'pseudonym', function() {
bsw@15 652 var query = new selector.Selector();
bsw@21 653 if (params.delegating == '1') {
bsw@21 654 query.from('delegating_population_snapshot', 'population');
bsw@21 655 if (params.delegate_member_id) {
bsw@21 656 query.addWhere(['population.delegate_member_ids @> array[?::int]', params.delegate_member_id]);
bsw@21 657 }
bsw@21 658 if (params.direct_delegate_member_id) {
bsw@21 659 query.addWhere(['population.delegate_member_ids[1] = ?', params.direct_delegate_member_id]);
bsw@21 660 }
bsw@21 661 } else {
bsw@21 662 query.from('direct_population_snapshot', 'population');
bsw@21 663 }
bsw@15 664 switch (params.snapshot) {
bsw@15 665 case 'latest':
bsw@15 666 query.addWhere('population.event = issue.latest_snapshot_event');
bsw@15 667 break;
bsw@15 668
bsw@15 669 case 'end_of_admission':
bsw@15 670 case 'half_freeze':
bsw@15 671 case 'full_freeze':
bsw@15 672 query.addWhere(['population.event = ?', params.snapshot]);
bsw@15 673 break;
bsw@15 674
bsw@15 675 default:
bsw@18 676 respond('json', conn, req, res, 'unprocessable', null, 'Invalid snapshot type');
bsw@15 677 return;
bsw@15 678
bsw@15 679 };
bsw@15 680 query.addField('population.*');
bsw@15 681 query.join('member', null, 'member.id = population.member_id');
bsw@15 682 query.join('issue', null, 'population.issue_id = issue.id');
bsw@15 683 query.join('policy', null, 'policy.id = issue.policy_id');
bsw@15 684 query.join('area', null, 'area.id = issue.area_id');
bsw@15 685 query.join('unit', null, 'area.unit_id = unit.id');
bsw@15 686 general_params.addMemberOptions(req, query, params);
bsw@15 687 general_params.addIssueOptions(req, query, params);
bsw@15 688 query.addOrderBy('population.issue_id, population.member_id');
bsw@15 689 general_params.addLimitAndOffset(query, params);
bsw@15 690 db.query(conn, req, res, query, function (population_result, conn) {
bsw@15 691 console.log(population_result);
bsw@15 692 var result = { result: population_result.rows }
bsw@15 693 includes = [];
bsw@15 694 if (params.include_members) includes.push({ class: 'member', objects: 'result'});
bsw@15 695 if (params.include_issues) includes.push({ class: 'issue', objects: 'result'});
bsw@15 696 if (params.include_areas) includes.push({ class: 'area', objects: 'areas'});
bsw@15 697 if (params.include_units) includes.push({ class: 'unit', objects: 'areas'});
bsw@15 698 if (params.include_policies) includes.push({ class: 'policy', objects: 'issues' });
bsw@15 699 addRelatedData(conn, req, res, result, includes);
bsw@15 700 });
bsw@15 701 });
bsw@15 702 },
bsw@15 703
bsw@0 704 '/interest': function (conn, req, res, params) {
bsw@0 705 requireAccessLevel(conn, req, res, 'pseudonym', function() {
bsw@0 706 var query = new selector.Selector();
bsw@14 707 switch (params.snapshot) {
bsw@14 708 case 'latest':
bsw@14 709 query.from('direct_interest_snapshot', 'interest');
bsw@14 710 query.addWhere('interest.event = issue.latest_snapshot_event');
bsw@14 711 break;
bsw@14 712
bsw@14 713 case 'end_of_admission':
bsw@14 714 case 'half_freeze':
bsw@14 715 case 'full_freeze':
bsw@14 716 query.from('direct_interest_snapshot', 'interest');
bsw@17 717 query.addWhere(['interest.event = ?', params.snapshot]);
bsw@14 718 break;
bsw@14 719
bsw@14 720 case undefined:
bsw@18 721 if (! req.current_member_id) {
bsw@18 722 respond('json', conn, req, res, 'unprocessable', null, 'No snapshot type given and not beeing member');
bsw@18 723 return;
bsw@18 724 };
bsw@14 725 query.from('interest');
bsw@18 726 query.addWhere(['interest.member_id = ?', req.current_member_id]);
bsw@14 727 break;
bsw@14 728
bsw@14 729 default:
bsw@18 730 respond('json', conn, req, res, 'unprocessable', null, 'Invalid snapshot type');
bsw@14 731 return;
bsw@14 732
bsw@3 733 };
bsw@0 734 query.addField('interest.*');
bsw@3 735 query.join('member', null, 'member.id = interest.member_id');
bsw@3 736 query.join('issue', null, 'interest.issue_id = issue.id');
bsw@3 737 query.join('policy', null, 'policy.id = issue.policy_id');
bsw@3 738 query.join('area', null, 'area.id = issue.area_id');
bsw@3 739 query.join('unit', null, 'area.unit_id = unit.id');
bsw@0 740 general_params.addMemberOptions(req, query, params);
bsw@0 741 general_params.addIssueOptions(req, query, params);
bsw@0 742 query.addOrderBy('interest.issue_id, interest.member_id');
bsw@0 743 general_params.addLimitAndOffset(query, params);
bsw@0 744 db.query(conn, req, res, query, function (interest_result, conn) {
bsw@0 745 var result = { result: interest_result.rows }
bsw@0 746 includes = [];
bsw@0 747 if (params.include_members) includes.push({ class: 'member', objects: 'result'});
bsw@0 748 if (params.include_issues) includes.push({ class: 'issue', objects: 'result'});
bsw@0 749 if (params.include_areas) includes.push({ class: 'area', objects: 'issues'});
bsw@0 750 if (params.include_units) includes.push({ class: 'unit', objects: 'areas'});
bsw@0 751 if (params.include_policies) includes.push({ class: 'policy', objects: 'issues' });
bsw@0 752 addRelatedData(conn, req, res, result, includes);
bsw@0 753 });
bsw@0 754 });
bsw@0 755 },
bsw@0 756
bsw@0 757 '/issue_comment': function (conn, req, res, params) {
bsw@0 758 requireAccessLevel(conn, req, res, 'pseudonym', function() {
bsw@0 759 var query = new selector.Selector();
bsw@0 760 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 761 query.addField('issue_comment.*');
bsw@0 762 general_params.addMemberOptions(req, query, params);
bsw@0 763 general_params.addIssueOptions(req, query, params);
bsw@0 764 query.addOrderBy('issue_comment.issue_id, issue_comment.member_id');
bsw@0 765 general_params.addLimitAndOffset(query, params);
bsw@0 766 db.query(conn, req, res, query, function (issue_comment_result, conn) {
bsw@0 767 var result = { result: issue_comment_result.rows }
bsw@0 768 includes = [];
bsw@0 769 if (params.include_members) includes.push({ class: 'member', objects: 'result'});
bsw@0 770 if (params.include_issues) includes.push({ class: 'issue', objects: 'result'});
bsw@0 771 if (params.include_areas) includes.push({ class: 'area', objects: 'issues'});
bsw@0 772 if (params.include_units) includes.push({ class: 'unit', objects: 'areas'});
bsw@0 773 if (params.include_policies) includes.push({ class: 'policy', objects: 'issues' });
bsw@0 774 addRelatedData(conn, req, res, result, includes);
bsw@0 775 });
bsw@0 776 });
bsw@0 777 },
bsw@0 778
bsw@0 779 '/initiative': function (conn, req, res, params) {
bsw@0 780 requireAccessLevel(conn, req, res, 'anonymous', function() {
bsw@0 781 var query = new selector.Selector();
bsw@0 782 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 783 fields.addObjectFields(query, 'initiative');
bsw@3 784 query.addOrderBy('initiative.id');
bsw@0 785 general_params.addInitiativeOptions(req, query, params);
bsw@0 786 general_params.addLimitAndOffset(query, params);
bsw@0 787 db.query(conn, req, res, query, function (initiative_result, conn) {
bsw@0 788 var result = { result: initiative_result.rows }
bsw@0 789 includes = [];
bsw@0 790 if (params.include_issues) includes.push({ class: 'issue', objects: 'result'});
bsw@0 791 if (params.include_areas) includes.push({ class: 'area', objects: 'issues'});
bsw@0 792 if (params.include_units) includes.push({ class: 'unit', objects: 'areas'});
bsw@0 793 if (params.include_policies) includes.push({ class: 'policy', objects: 'issues' });
bsw@0 794 addRelatedData(conn, req, res, result, includes);
bsw@0 795 });
bsw@0 796 });
bsw@0 797 },
bsw@0 798
bsw@0 799 '/initiator': function (conn, req, res, params) {
bsw@0 800 requireAccessLevel(conn, req, res, 'pseudonym', function() {
bsw@0 801 var fields = ['initiator.initiative_id', 'initiator.member_id'];
bsw@0 802 var query = new selector.Selector();
bsw@0 803 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 804 query.addWhere('initiator.accepted');
bsw@0 805 fields.forEach( function(field) {
bsw@0 806 query.addField(field, null, ['grouped']);
bsw@0 807 });
bsw@0 808 general_params.addMemberOptions(req, query, params);
bsw@0 809 general_params.addInitiativeOptions(req, query, params);
bsw@0 810 query.addOrderBy('initiator.initiative_id, initiator.member_id');
bsw@0 811 general_params.addLimitAndOffset(query, params);
bsw@0 812 db.query(conn, req, res, query, function (initiator, conn) {
bsw@0 813 var result = { result: initiator.rows }
bsw@0 814 includes = [];
bsw@0 815 if (params.include_initiatives) includes.push({ class: 'initiative', objects: 'result'});
bsw@0 816 if (params.include_issues) includes.push({ class: 'issue', objects: 'initiatives'});
bsw@0 817 if (params.include_areas) includes.push({ class: 'area', objects: 'issues'});
bsw@0 818 if (params.include_units) includes.push({ class: 'unit', objects: 'areas'});
bsw@0 819 if (params.include_policies) includes.push({ class: 'policy', objects: 'issues' });
bsw@0 820 addRelatedData(conn, req, res, result, includes);
bsw@0 821 });
bsw@0 822 });
bsw@0 823 },
bsw@0 824
bsw@0 825
bsw@0 826 '/supporter': function (conn, req, res, params) {
bsw@0 827 requireAccessLevel(conn, req, res, 'pseudonym', function() {
bsw@0 828 var fields = ['supporter.issue_id', 'supporter.initiative_id', 'supporter.member_id', 'supporter.draft_id'];
bsw@0 829 var query = new selector.Selector();
bsw@0 830 query.from('supporter')
bsw@0 831 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 832 fields.forEach( function(field) {
bsw@0 833 query.addField(field, null, ['grouped']);
bsw@0 834 });
bsw@0 835 general_params.addMemberOptions(req, query, params);
bsw@0 836 general_params.addInitiativeOptions(req, query, params);
bsw@0 837 query.addOrderBy('supporter.issue_id, supporter.initiative_id, supporter.member_id');
bsw@0 838 general_params.addLimitAndOffset(query, params);
bsw@0 839 db.query(conn, req, res, query, function (supporter, conn) {
bsw@0 840 var result = { result: supporter.rows }
bsw@0 841 includes = [];
bsw@0 842 if (params.include_initiatives) includes.push({ class: 'initiative', objects: 'result'});
bsw@0 843 if (params.include_issues) includes.push({ class: 'issue', objects: 'initiatives'});
bsw@0 844 if (params.include_areas) includes.push({ class: 'area', objects: 'issues'});
bsw@0 845 if (params.include_units) includes.push({ class: 'unit', objects: 'areas'});
bsw@0 846 if (params.include_policies) includes.push({ class: 'policy', objects: 'issues' });
bsw@0 847 addRelatedData(conn, req, res, result, includes);
bsw@0 848 });
bsw@0 849 });
bsw@0 850 },
bsw@0 851
bsw@0 852 '/battle': function (conn, req, res, params) {
bsw@0 853 requireAccessLevel(conn, req, res, 'anonymous', function() {
bsw@0 854 var query = new selector.Selector();
bsw@0 855 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 856 query.addField('battle.*');
bsw@0 857 general_params.addInitiativeOptions(req, query, params);
bsw@0 858 query.addOrderBy('battle.issue_id, battle.winning_initiative_id, battle.losing_initiative_id');
bsw@0 859 general_params.addLimitAndOffset(query, params);
bsw@0 860 db.query(conn, req, res, query, function (result, conn) {
bsw@0 861 var result = { result: result.rows }
bsw@0 862 includes = [];
bsw@0 863 if (params.include_initiatives) includes.push({ class: 'initiative', objects: 'result'});
bsw@0 864 if (params.include_issues) includes.push({ class: 'issue', objects: 'initiatives'});
bsw@0 865 if (params.include_areas) includes.push({ class: 'area', objects: 'issues'});
bsw@0 866 if (params.include_units) includes.push({ class: 'unit', objects: 'areas'});
bsw@0 867 if (params.include_policies) includes.push({ class: 'policy', objects: 'issues' });
bsw@0 868 addRelatedData(conn, req, res, result, includes);
bsw@0 869 });
bsw@0 870 });
bsw@0 871 },
bsw@0 872
bsw@0 873 '/draft': function (conn, req, res, params) {
bsw@0 874 requireAccessLevel(conn, req, res, 'anonymous', function() {
bsw@0 875 var fields = ['draft.initiative_id', 'draft.id', 'draft.formatting_engine', 'draft.content', 'draft.author_id'];
bsw@0 876 var query = new selector.Selector();
bsw@0 877 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 878 fields.forEach( function(field) {
bsw@0 879 query.addField(field, null, ['grouped']);
bsw@0 880 });
bsw@0 881 if (req.current_access_level != 'anonymous' || req.current_member_id) {
bsw@0 882 query.addField('draft.author_id');
bsw@0 883 }
bsw@0 884 if (params.draft_id) {
bsw@0 885 query.addWhere('draft.id = ?', params.draft_id);
bsw@0 886 }
bsw@0 887 if (params.current_draft) {
bsw@0 888 query.join('current_draft', null, 'current_draft.initiative_id = initiative.id AND current_draft.id = draft.id')
bsw@0 889 }
bsw@0 890 general_params.addInitiativeOptions(req, query, params);
bsw@0 891 query.addOrderBy('draft.initiative_id, draft.id');
bsw@0 892 general_params.addLimitAndOffset(query, params);
bsw@0 893 db.query(conn, req, res, query, function (result, conn) {
bsw@0 894 var result = { result: result.rows }
bsw@0 895 includes = [];
bsw@0 896 if (params.include_initiatives) includes.push({ class: 'initiative', objects: 'result'});
bsw@0 897 if (params.include_issues) includes.push({ class: 'issue', objects: 'initiatives'});
bsw@0 898 if (params.include_areas) includes.push({ class: 'area', objects: 'issues'});
bsw@0 899 if (params.include_units) includes.push({ class: 'unit', objects: 'areas'});
bsw@0 900 if (params.include_policies) includes.push({ class: 'policy', objects: 'issues' });
bsw@0 901 addRelatedData(conn, req, res, result, includes);
bsw@0 902 });
bsw@0 903 });
bsw@0 904 },
bsw@0 905
bsw@0 906 '/suggestion': function (conn, req, res, params) {
bsw@0 907 requireAccessLevel(conn, req, res, 'anonymous', function() {
bsw@0 908 var query = new selector.Selector();
bsw@0 909 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 910 if (req.current_access_level == 'anonymous' && !req.current_member_id ) {
bsw@0 911 fields.addObjectFields(query, 'suggestion', 'suggestion_pseudonym');
bsw@0 912 } else {
bsw@0 913 fields.addObjectFields(query, 'suggestion');
bsw@0 914 }
bsw@0 915 general_params.addSuggestionOptions(req, query, params);
bsw@0 916 query.addOrderBy('suggestion.initiative_id, suggestion.id');
bsw@0 917 general_params.addLimitAndOffset(query, params);
bsw@0 918 db.query(conn, req, res, query, function (result, conn) {
bsw@0 919 var result = { result: result.rows }
bsw@0 920 includes = [];
bsw@0 921 if (params.include_initiatives) includes.push({ class: 'initiative', objects: 'result'});
bsw@0 922 if (params.include_issues) includes.push({ class: 'issue', objects: 'initiatives'});
bsw@0 923 if (params.include_areas) includes.push({ class: 'area', objects: 'issues'});
bsw@0 924 if (params.include_units) includes.push({ class: 'unit', objects: 'areas'});
bsw@0 925 if (params.include_policies) includes.push({ class: 'policy', objects: 'issues' });
bsw@0 926 addRelatedData(conn, req, res, result, includes);
bsw@0 927 });
bsw@0 928 });
bsw@0 929 },
bsw@0 930
bsw@0 931 '/opinion': function (conn, req, res, params) {
bsw@0 932 requireAccessLevel(conn, req, res, 'pseudonym', function() {
bsw@0 933 var fields = ['opinion.initiative_id', 'opinion.suggestion_id', 'opinion.member_id', 'opinion.degree', 'opinion.fulfilled']
bsw@0 934 var query = new selector.Selector();
bsw@0 935 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 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.addSuggestionOptions(req, query, params);
bsw@0 941 query.addOrderBy = ['opinion.initiative_id, opinion.suggestion_id, opinion.member_id'];
bsw@0 942 general_params.addLimitAndOffset(query, params);
bsw@0 943 db.query(conn, req, res, query, function (result, conn) {
bsw@0 944 var result = { result: result.rows }
bsw@0 945 includes = [];
bsw@0 946 if (params.include_suggestions) includes.push({ class: 'suggestion', objects: 'result'});
bsw@0 947 if (params.include_initiatives) includes.push({ class: 'initiative', objects: 'suggestions'});
bsw@0 948 if (params.include_issues) includes.push({ class: 'issue', objects: 'initiatives'});
bsw@0 949 if (params.include_areas) includes.push({ class: 'area', objects: 'issues'});
bsw@0 950 if (params.include_units) includes.push({ class: 'unit', objects: 'areas'});
bsw@0 951 if (params.include_policies) includes.push({ class: 'policy', objects: 'issues' });
bsw@0 952 addRelatedData(conn, req, res, result, includes);
bsw@0 953 });
bsw@0 954 });
bsw@0 955 },
bsw@0 956
bsw@0 957 '/delegation': function (conn, req, res, params) {
bsw@0 958 requireAccessLevel(conn, req, res, 'pseudonym', function() {
bsw@0 959 var fields = ['delegation.id', 'delegation.truster_id', 'delegation.trustee_id', 'delegation.scope', 'delegation.area_id', 'delegation.issue_id', 'delegation.unit_id'];
bsw@0 960 var query = new selector.Selector();
bsw@0 961 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 962 fields.forEach( function(field) {
bsw@0 963 query.addField(field, null, ['grouped']);
bsw@0 964 });
bsw@0 965 if (params.direction) {
bsw@0 966 switch (params.direction) {
bsw@0 967 case 'in':
bsw@0 968 query.join('member', null, 'member.id = delegation.trustee_id');
bsw@0 969 break;
bsw@0 970 case 'out':
bsw@0 971 query.join('member', null, 'member.id = delegation.truster_id');
bsw@0 972 break;
bsw@0 973 default:
bsw@0 974 respond('json', conn, req, res, 'unprocessable', 'Direction must be "in" or "out" if set.');
bsw@0 975 }
bsw@0 976 } else {
bsw@0 977 query.join('member', null, 'member.id = delegation.truster_id OR member.id = delegation.trustee_id');
bsw@0 978 }
bsw@0 979 general_params.addMemberOptions(req, query, params);
bsw@0 980 general_params.addIssueOptions(req, query, params);
bsw@0 981 if (params.scope) {
bsw@0 982 query.addWhere(['delegation.scope IN (??)', params.scope.split(',')]);
bsw@0 983 };
bsw@0 984 query.addOrderBy = ['delegation.id'];
bsw@0 985 general_params.addLimitAndOffset(query, params);
bsw@0 986 db.query(conn, req, res, query, function (result, conn) {
bsw@0 987 respond('json', conn, req, res, 'ok', { result: result.rows });
bsw@0 988 });
bsw@0 989 });
bsw@0 990 },
bsw@0 991
bsw@0 992 '/vote': function (conn, req, res, params) {
bsw@0 993 requireAccessLevel(conn, req, res, 'pseudonym', function() {
bsw@0 994 var query = new selector.Selector();
bsw@0 995 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 996 query.addField('vote.*');
bsw@0 997 query.addWhere('issue.closed_at NOTNULL');
bsw@0 998 general_params.addMemberOptions(req, query, params);
bsw@0 999 general_params.addInitiativeOptions(req, query, params);
bsw@0 1000 general_params.addLimitAndOffset(query, params);
bsw@0 1001 db.query(conn, req, res, query, function (result, conn) {
bsw@0 1002 respond('json', conn, req, res, 'ok', { result: result.rows });
bsw@0 1003 });
bsw@0 1004 });
bsw@0 1005 },
bsw@0 1006
bsw@14 1007 '/event': function (conn, req, res, params) {
bsw@14 1008 requireAccessLevel(conn, req, res, 'anonymous', function() {
bsw@14 1009 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@14 1010 var query = new selector.Selector();
bsw@14 1011 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@14 1012 fields.forEach( function(field) {
bsw@14 1013 query.addField(field, null, ['grouped']);
bsw@14 1014 });
bsw@14 1015 general_params.addMemberOptions(req, query, params);
bsw@14 1016 general_params.addInitiativeOptions(req, query, params);
bsw@14 1017 query.addOrderBy('event.id');
bsw@14 1018 general_params.addLimitAndOffset(query, params);
bsw@14 1019 db.query(conn, req, res, query, function (events, conn) {
bsw@14 1020 var result = { result: events.rows }
bsw@14 1021 includes = [];
bsw@14 1022 if (params.include_initiatives) includes.push({ class: 'initiative', objects: 'result'});
bsw@14 1023 if (params.include_issues) includes.push({ class: 'issue', objects: 'result'});
bsw@14 1024 if (params.include_areas) includes.push({ class: 'area', objects: 'issues'});
bsw@14 1025 if (params.include_units) includes.push({ class: 'unit', objects: 'areas'});
bsw@14 1026 if (params.include_policies) includes.push({ class: 'policy', objects: 'issues' });
bsw@14 1027 addRelatedData(conn, req, res, result, includes);
bsw@14 1028 });
bsw@0 1029 });
bsw@14 1030 },
bsw@0 1031
bsw@0 1032 // TODO add interfaces for data structure:
bsw@0 1033 // ignored_member requireAccessLevel(conn, req, res, 'member');
bsw@0 1034 // ignored_initiative requireAccessLevel(conn, req, res, 'member');
bsw@0 1035 // setting requireAccessLevel(conn, req, res, 'member');
bsw@0 1036
bsw@0 1037 };
bsw@0 1038
bsw@0 1039 // ==========================================================================
bsw@0 1040 // POST methods
bsw@0 1041 // ==========================================================================
bsw@0 1042
bsw@0 1043
bsw@0 1044
bsw@0 1045 exports.post = {
bsw@0 1046
bsw@0 1047 '/echo_test': function (conn, req, res, params) { requireAccessLevel(conn, req, res, 'anonymous', function() {
bsw@0 1048 respond('json', conn, req, res, 'ok', { result: params });
bsw@0 1049 }); },
bsw@0 1050
bsw@0 1051 '/register_test': function (conn, req, res, params) {
bsw@0 1052 var understood = params.understood;
bsw@0 1053 var member_login = randomString(16);
bsw@0 1054 var member_name = params.name;
bsw@0 1055 var member_password = randomString(16);
bsw@0 1056 var member_notify_email = params.email;
bsw@0 1057 var member_notify_email_secret = randomString(24);
bsw@0 1058 var api_key_member = randomString(24);
bsw@0 1059 var api_key_full = randomString(24);
bsw@0 1060 var api_key_pseudonym = randomString(24);
bsw@0 1061 var api_key_anonymous = randomString(24);
bsw@0 1062
bsw@0 1063 if (understood != 'understood') {
bsw@0 1064 respond('html', conn, req, res, 'unprocessable', null, 'You didn\'t checked the checkbox! Please hit back in your browser and try again.');
bsw@0 1065 return;
bsw@0 1066 }
bsw@0 1067
bsw@0 1068 // add member
bsw@0 1069 var query = new selector.SQLInsert('member');
bsw@0 1070 query.addValues({
bsw@0 1071 login: member_login,
bsw@0 1072 password: member_password, // TODO hashing of password
bsw@0 1073 notify_email_unconfirmed: member_notify_email,
bsw@0 1074 notify_email_secret: member_notify_email_secret,
bsw@0 1075 name: member_name
bsw@0 1076 });
bsw@0 1077 query.addReturning('id');
bsw@0 1078 db.query(conn, req, res, query, function (result, conn) {
bsw@0 1079 var member_id = result.rows[0].id;
bsw@0 1080
bsw@0 1081 // add privilege for root unit
bsw@0 1082 var query = new selector.SQLInsert('privilege');
bsw@0 1083 query.addValues({ unit_id: 1, member_id: member_id, voting_right: true });
bsw@0 1084 db.query(conn, req, res, query, function (result, conn) {
bsw@0 1085
bsw@0 1086 var location = params.location;
bsw@0 1087 var unit_id;
bsw@0 1088 switch(location) {
bsw@0 1089 case 'earth':
bsw@0 1090 unit_id = 3;
bsw@0 1091 break;
bsw@0 1092 case 'moon':
bsw@0 1093 unit_id = 4;
bsw@0 1094 break;
bsw@0 1095 case 'mars':
bsw@0 1096 unit_id = 5;
bsw@0 1097 break;
bsw@0 1098 }
bsw@0 1099
bsw@0 1100 // add privilege for selected planet
bsw@0 1101 var query = new selector.SQLInsert('privilege');
bsw@0 1102 query.addValues({ unit_id: unit_id, member_id: member_id, voting_right: true });
bsw@0 1103 db.query(conn, req, res, query, function (result, conn) {
bsw@0 1104
bsw@0 1105 // add application key
bsw@0 1106 var query = new selector.SQLInsert('member_application');
bsw@0 1107 query.addValues({
bsw@0 1108 member_id: member_id,
bsw@0 1109 name: 'member',
bsw@0 1110 comment: 'access_level member',
bsw@0 1111 access_level: 'member',
bsw@0 1112 key: api_key_member
bsw@0 1113 });
bsw@0 1114 query.addReturning('id');
bsw@0 1115
bsw@0 1116 db.query(conn, req, res, query, function (result, conn) {
bsw@0 1117
bsw@9 1118 nodemailer.sendmail = '/usr/sbin/sendmail';
bsw@5 1119
bsw@0 1120 // send email to user
bsw@5 1121 nodemailer.send_mail({
bsw@10 1122 sender: config.mail.from,
bsw@0 1123 subject: config.mail.subject_prefix + "Your LiquidFeedback API alpha test account needs confirmation",
bsw@0 1124 to: member_notify_email,
bsw@0 1125 body: "\
bsw@0 1126 Hello " + member_name + ",\n\
bsw@0 1127 \n\
bsw@0 1128 thank you for registering at the public alpha test of the LiquidFeedback\n\
bsw@0 1129 application programming interface. To complete the registration process,\n\
bsw@0 1130 you need to confirm your email address by opening the following URL:\n\
bsw@0 1131 \n\
bsw@0 1132 " + config.public_url_path + "register_test_confirm?secret=" + member_notify_email_secret + "\n\
bsw@0 1133 \n\
bsw@0 1134 \n\
bsw@0 1135 After you've confirmed your email address, your account will be automatically\n\
bsw@0 1136 activated.\n\
bsw@0 1137 \n\
bsw@0 1138 Your account name is: " + member_name + "\n\
bsw@0 1139 \n\
bsw@0 1140 \n\
bsw@0 1141 You will need the following login and password to register and unregister\n\
bsw@0 1142 applications for your account later. This function is currently not\n\
bsw@0 1143 implemented, but please keep the credentials for future use.\n\
bsw@0 1144 \n\
bsw@0 1145 Account ID: " + member_id + "\n\
bsw@0 1146 Login: " + member_login + "\n\
bsw@0 1147 Password: " + member_password + "\n\
bsw@0 1148 \n\
bsw@0 1149 \n\
bsw@0 1150 To make you able to actually access the API interface, we added the following\n\
bsw@0 1151 application key with full member access privileges to your account:\n\
bsw@0 1152 \n\
bsw@0 1153 API Key: " + api_key_member + "\n\
bsw@0 1154 \n\
bsw@0 1155 \n\
bsw@0 1156 The base address of the public test is: " + config.public_url_path + "\n\
bsw@0 1157 \n\
bsw@0 1158 The programming interface is described in the LiquidFeedback API\n\
bsw@0 1159 specification: http://dev.liquidfeedback.org/trac/lf/wiki/API\n\
bsw@0 1160 \n\
bsw@0 1161 The current implementation status of lfapi is published at the LiquidFeedback\n\
bsw@0 1162 API server page: http://dev.liquidfeedback.org/trac/lf/wiki/lfapi\n\
bsw@0 1163 \n\
bsw@0 1164 If you have any questions or suggestions, please use our public mailing list\n\
bsw@0 1165 at http://dev.liquidfeedback.org/cgi-bin/mailman/listinfo/main\n\
bsw@0 1166 \n\
bsw@0 1167 For issues regarding your test account, contact us via email at\n\
bsw@0 1168 lqfb-maintainers@public-software-group.org\n\
bsw@0 1169 \n\
bsw@0 1170 \n\
bsw@0 1171 Sincerely,\n\
bsw@0 1172 \n\
bsw@0 1173 Your LiquidFeedback maintainers",
bsw@0 1174 },
bsw@0 1175 function(err, result){
bsw@0 1176 if(err){ console.log(err); }
bsw@0 1177 });
bsw@0 1178
bsw@0 1179 respond('html', conn, req, res, 'ok', 'Account created. Please check your mailbox!<br /><br /><br /><a href="/">Back to start page</a>');
bsw@0 1180 });
bsw@0 1181 });
bsw@0 1182 });
bsw@0 1183 });
bsw@0 1184 },
bsw@0 1185
bsw@0 1186 /*
bsw@0 1187 '/register': function (conn, req, res, params) {
bsw@0 1188 var invite_key = params.invite_key;
bsw@0 1189 var login = params.login;
bsw@0 1190 var password = params.password;
bsw@0 1191 var name = params.name;
bsw@0 1192 var notify_email = params.notify_email;
bsw@0 1193 if (!invite_key) {
bsw@0 1194 respond('json', conn, req, res, 'unprocessable', null, 'No invite_key supplied.');
bsw@0 1195 return;
bsw@0 1196 };
bsw@0 1197 if (!login) {
bsw@0 1198 respond('json', conn, req, res, 'unprocessable', null, 'No login supplied.');
bsw@0 1199 return;
bsw@0 1200 };
bsw@0 1201 if (!password) {
bsw@0 1202 respond('json', conn, req, res, 'unprocessable', null, 'No password supplied.');
bsw@0 1203 return;
bsw@0 1204 };
bsw@0 1205 if (!name) {
bsw@0 1206 respond('json', conn, req, res, 'unprocessable', null, 'No name supplied.');
bsw@0 1207 return;
bsw@0 1208 };
bsw@0 1209 if (!notify_email) {
bsw@0 1210 respond('json', conn, req, res, 'unprocessable', null, 'No notify_email supplied.');
bsw@0 1211 return;
bsw@0 1212 };
bsw@0 1213 // check if akey is valid and get member_id for akey
bsw@0 1214 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 1215 if (result.rows.length != 1) {
bsw@0 1216 respond('json', conn, req, res, 'forbidden', null, 'Supplied invite_key is not valid.');
bsw@0 1217 return;
bsw@0 1218 };
bsw@0 1219 var member_id = result.rows[0].id;
bsw@0 1220 // check if name is available
bsw@0 1221 db.query(conn, req, res, { select: ['NULL'], from: ['member'], where: ['member.name = ' + db.pgEncode(name)] }, function (result, conn) {
bsw@0 1222 if (result.rows.length > 0) {
bsw@0 1223 respond('json', conn, req, res, 'forbidden', null, 'Login name is not available, choose another one.');
bsw@0 1224 return;
bsw@0 1225 };
bsw@0 1226 // check if login is available
bsw@0 1227 db.query(conn, req, res, { select: ['NULL'], from: ['member'], where: ['member.login = ' + db.pgEncode(login)] }, function (result, conn) {
bsw@0 1228 if (result.rows.length > 0) {
bsw@0 1229 respond('json', conn, req, res, 'forbidden', null, 'Name is not available, choose another one.');
bsw@0 1230 return;
bsw@0 1231 };
bsw@0 1232 var query = { update: 'member', set: { activation: 'now', active: true, } };
bsw@0 1233
bsw@0 1234 });
bsw@0 1235 });
bsw@0 1236 });
bsw@0 1237 },
bsw@0 1238 */
bsw@0 1239
bsw@0 1240 '/session': function (conn, req, res, params) {
bsw@0 1241 var key = params.key;
bsw@0 1242 if (!key) {
bsw@0 1243 respond('json', conn, req, res, 'unprocessable', null, 'No application key supplied.');
bsw@0 1244 return;
bsw@0 1245 };
bsw@0 1246 var query = new selector.Selector();
bsw@0 1247 query.from('member');
bsw@0 1248 query.join('member_application', null, 'member_application.member_id = member.id');
bsw@0 1249 query.addField('member.id');
bsw@0 1250 query.addWhere(['member.active AND member_application.key = ?', key]);
bsw@0 1251 if (params.interactive) {
bsw@0 1252 query.forUpdateOf('member');
bsw@0 1253 }
bsw@0 1254 db.query(conn, req, res, query, function (result, conn) {
bsw@0 1255 if (result.rows.length != 1) {
bsw@0 1256 respond('json', conn, req, res, 'forbidden', null, 'Supplied application key is not valid.');
bsw@0 1257 return;
bsw@0 1258 };
bsw@0 1259 var member_id = result.rows[0].id;
bsw@0 1260 var session_key = randomString(16);
bsw@0 1261 req.sessions[session_key] = member_id;
bsw@0 1262 var query;
bsw@0 1263 if (params.interactive) {
bsw@0 1264 query = new selector.SQLUpdate('member');
bsw@0 1265 query.addWhere(['member.id = ?', member_id]);
bsw@0 1266 query.addValues({ last_activity: 'now' });
bsw@0 1267 }
bsw@0 1268 db.query(conn, req, res, query, function (result, conn) {
bsw@0 1269 respond('json', conn, req, res, 'ok', { session_key: session_key });
bsw@0 1270 });
bsw@0 1271 });
bsw@0 1272 },
bsw@0 1273
bsw@0 1274 '/member': function (conn, req, res, params) {
bsw@0 1275 var fields = ['organizational_unit', 'internal_posts', 'realname', 'birthday', 'address', 'email', 'xmpp_address', 'website', 'phone', 'mobile_phone', 'profession', 'external_memberships', 'external_posts', 'statement']
bsw@0 1276 requireAccessLevel(conn, req, res, 'member', function() {
bsw@0 1277 var query = new selector.SQLUpdate('member');
bsw@0 1278 query.addWhere(['member.id = ?', req.current_member_id]);
bsw@0 1279 fields.forEach( function(field) {
bsw@0 1280 if (typeof(params[field]) != 'undefined') {
bsw@3 1281 query.addValues({ field: params[field] });
bsw@0 1282 } else {
bsw@3 1283 query.addValues({ field: null });
bsw@0 1284 }
bsw@0 1285 });
bsw@0 1286 db.query(conn, req, res, query, function(result) { respond('json', conn, req, res, 'ok'); });
bsw@0 1287 });
bsw@0 1288 },
bsw@0 1289
bsw@0 1290 '/membership': function (conn, req, res, params) {
bsw@0 1291 requireAccessLevel(conn, req, res, 'member', function() {
bsw@0 1292
bsw@0 1293 // check if area_id is set
bsw@0 1294 var area_id = parseInt(params.area_id);
bsw@0 1295 if (!area_id) {
bsw@0 1296 respond('json', conn, req, res, 'unprocessable', null, 'You need to supply an area_id.');
bsw@0 1297 return;
bsw@0 1298 }
bsw@0 1299
bsw@0 1300 // delete membership
bsw@0 1301 if (params.delete) {
bsw@0 1302 var query;
bsw@0 1303 query = new selector.SQLDelete('membership');
bsw@0 1304 query.addWhere(['area_id = ?', area_id]);
bsw@0 1305 query.addWhere(['member_id = ?', req.current_member_id]);
bsw@0 1306 db.query(conn, req, res, query, function(result) { respond('json', conn, req, res, 'ok'); });
bsw@0 1307
bsw@0 1308 // add membership
bsw@0 1309 } else {
bsw@0 1310
bsw@0 1311 // lock member for upsert
bsw@0 1312 lockMemberById(conn, req, res, req.current_member_id, function() {
bsw@0 1313
bsw@0 1314 // check and lock privilege
bsw@0 1315 requireAreaPrivilege(conn, req, res, area_id, function() {
bsw@0 1316
bsw@0 1317 // upsert membership
bsw@0 1318 var query = new selector.Upserter('membership', ['area_id', 'member_id']);
bsw@0 1319 query.addValues({ area_id: area_id, member_id: req.current_member_id });
bsw@0 1320 db.query(conn, req, res, query, function(result) {
bsw@0 1321 respond('json', conn, req, res, 'ok');
bsw@0 1322 });
bsw@0 1323 });
bsw@0 1324 });
bsw@0 1325 }
bsw@0 1326 });
bsw@0 1327 },
bsw@0 1328
bsw@0 1329 '/interest': function (conn, req, res, params) {
bsw@0 1330 requireAccessLevel(conn, req, res, 'member', function() {
bsw@0 1331 var query;
bsw@0 1332
bsw@0 1333 // check if issue_id is set
bsw@0 1334 var issue_id = parseInt(params.issue_id);
bsw@0 1335 if (!issue_id) {
bsw@0 1336 respond('json', conn, req, res, 'unprocessable', null, 'You need to supply an issue_id.');
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 // delete interest
bsw@0 1344 if (params.delete) {
bsw@0 1345
bsw@0 1346 // check issue state
bsw@0 1347 requireIssueState(conn, req, res, issue_id, ['admission', 'discussion', 'verification'], function() {
bsw@0 1348
bsw@0 1349 // delete interest
bsw@0 1350 query = new selector.SQLDelete('interest');
bsw@0 1351 query.addWhere(['issue_id = ?', issue_id]);
bsw@0 1352 query.addWhere(['member_id = ?', req.current_member_id]);
bsw@0 1353 db.query(conn, req, res, query, function(result) { respond('json', conn, req, res, 'ok'); });
bsw@0 1354 });
bsw@0 1355
bsw@0 1356 // add interest
bsw@0 1357 } else {
bsw@0 1358
bsw@0 1359 // check and lock privilege
bsw@0 1360 requireIssuePrivilege(conn, req, res, issue_id, function() {
bsw@0 1361
bsw@0 1362 // check issue state
bsw@0 1363 requireIssueState(conn, req, res, issue_id, ['admission', 'discussion', 'verification'], function() {
bsw@0 1364
bsw@0 1365 // upsert interest
bsw@0 1366 var query = new selector.Upserter('interest', ['issue_id', 'member_id']);
bsw@0 1367 query.addValues({ issue_id: issue_id, member_id: req.current_member_id });
bsw@0 1368 db.query(conn, req, res, query, function(result) {
bsw@0 1369 respond('json', conn, req, res, 'ok');
bsw@0 1370 });
bsw@0 1371 });
bsw@0 1372 });
bsw@0 1373 };
bsw@0 1374 });
bsw@0 1375 });
bsw@0 1376 },
bsw@0 1377
bsw@0 1378 '/issue_comment': function (conn, req, res, params) {
bsw@0 1379 requireAccessLevel(conn, req, res, 'member', function() {
bsw@0 1380
bsw@0 1381 var issue_id = parseInt(params.issue_id);
bsw@0 1382 var formatting_engine = params.formatting_engine
bsw@0 1383 var content = params.content;
bsw@0 1384
bsw@0 1385 if (!issue_id) {
bsw@0 1386 respond('json', conn, req, res, 'unprocessable', null, 'You need to supply an issue_id.');
bsw@0 1387 return;
bsw@0 1388 }
bsw@0 1389
bsw@0 1390 // delete issue comment
bsw@0 1391 if (params.delete) {
bsw@0 1392 var query;
bsw@0 1393 query = new selector.SQLDelete('issue_comment');
bsw@0 1394 query.addWhere(['issue_id = ?', params.issue_id]);
bsw@0 1395 query.addWhere(['member_id = ?', req.current_member_id]);
bsw@0 1396 db.query(conn, req, res, query, function(result) { respond('json', conn, req, res, 'ok'); });
bsw@0 1397
bsw@0 1398 // upsert issue comment
bsw@0 1399 } else {
bsw@0 1400
bsw@0 1401 // check if formatting engine is supplied and valid
bsw@0 1402 if (!formatting_engine) {
bsw@0 1403 respond('json', conn, req, res, 'unprocessable', null, 'No formatting engine supplied.');
bsw@0 1404 return;
bsw@0 1405 } else if (formatting_engine != 'rocketwiki' && formatting_engine != 'compat') {
bsw@0 1406 respond('json', conn, req, res, 'unprocessable', null, 'Invalid formatting engine supplied.');
bsw@0 1407 return;
bsw@0 1408 };
bsw@0 1409
bsw@0 1410 // check if content is supplied
bsw@0 1411 if (!content) {
bsw@0 1412 respond('json', conn, req, res, 'unprocessable', null, 'No content supplied.');
bsw@0 1413 return;
bsw@0 1414 }
bsw@0 1415
bsw@0 1416 // lock member for upsert
bsw@0 1417 lockMemberById(conn, req, res, req.current_member_id, function() {
bsw@0 1418
bsw@0 1419 // check and lock privilege
bsw@0 1420 requireIssuePrivilege(conn, req, res, issue_id, function() {
bsw@0 1421
bsw@0 1422 // upsert issue comment
bsw@0 1423 var query = new selector.Upserter('issue_comment', ['issue_id', 'member_id']);
bsw@0 1424 query.addValues({
bsw@0 1425 issue_id: issue_id,
bsw@0 1426 member_id: req.current_member_id,
bsw@0 1427 changed: 'now',
bsw@0 1428 formatting_engine: formatting_engine,
bsw@0 1429 content: content
bsw@0 1430 });
bsw@0 1431
bsw@0 1432 db.query(conn, req, res, query, function(result) {
bsw@0 1433 respond('json', conn, req, res, 'ok');
bsw@0 1434 });
bsw@0 1435
bsw@0 1436 });
bsw@0 1437 });
bsw@0 1438
bsw@0 1439 }
bsw@0 1440
bsw@0 1441 });
bsw@0 1442 },
bsw@0 1443
bsw@0 1444 '/voting_comment': function (conn, req, res, params) {
bsw@0 1445 requireAccessLevel(conn, req, res, 'member', function() {
bsw@0 1446
bsw@0 1447 var issue_id = parseInt(params.issue_id);
bsw@0 1448 var formatting_engine = params.formatting_engine
bsw@0 1449 var content = params.content;
bsw@0 1450
bsw@0 1451 if (!issue_id) {
bsw@0 1452 respond('json', conn, req, res, 'unprocessable', null, 'You need to supply an issue_id.');
bsw@0 1453 return;
bsw@0 1454 }
bsw@0 1455
bsw@0 1456
bsw@0 1457 // delete voting comment
bsw@0 1458 if (params.delete) {
bsw@0 1459 var query;
bsw@0 1460 query = new selector.SQLDelete('voting_comment');
bsw@0 1461 query.addWhere(['issue_id = ?', params.issue_id]);
bsw@0 1462 query.addWhere(['member_id = ?', req.current_member_id]);
bsw@0 1463 db.query(conn, req, res, query, function(result) { respond('json', conn, req, res, 'ok'); });
bsw@0 1464
bsw@0 1465 // upsert voting comment
bsw@0 1466 } else {
bsw@0 1467
bsw@0 1468 // check if formatting engine is supplied and valid
bsw@0 1469 if (!formatting_engine) {
bsw@0 1470 respond('json', conn, req, res, 'unprocessable', null, 'No formatting engine supplied.');
bsw@0 1471 return;
bsw@0 1472 } else if (formatting_engine != 'rocketwiki' && formatting_engine != 'compat') {
bsw@0 1473 respond('json', conn, req, res, 'unprocessable', null, 'Invalid formatting engine supplied.');
bsw@0 1474 return;
bsw@0 1475 };
bsw@0 1476
bsw@0 1477 // check if content is supplied
bsw@0 1478 if (!content) {
bsw@0 1479 respond('json', conn, req, res, 'unprocessable', null, 'No content supplied.');
bsw@0 1480 return;
bsw@0 1481 }
bsw@0 1482
bsw@0 1483 // lock member for upsert
bsw@0 1484 lockMemberById(conn, req, res, req.current_member_id, function() {
bsw@0 1485
bsw@0 1486 // check and lock privilege
bsw@0 1487 requireIssuePrivilege(conn, req, res, issue_id, function() {
bsw@0 1488
bsw@0 1489 // check issue state
bsw@0 1490 requireIssueState(conn, req, res, issue_id, ['voting', 'finished_with_winner', 'finished_without_winner'], function() {
bsw@0 1491
bsw@0 1492 // upsert voting comment
bsw@0 1493 var query = new selector.Upserter('voting_comment', ['issue_id', 'member_id']);
bsw@0 1494 query.addValues({
bsw@0 1495 issue_id: issue_id,
bsw@0 1496 member_id: req.current_member_id,
bsw@0 1497 changed: 'now',
bsw@0 1498 formatting_engine: formatting_engine,
bsw@0 1499 content: content
bsw@0 1500 });
bsw@0 1501
bsw@0 1502 db.query(conn, req, res, query, function(result) {
bsw@0 1503 respond('json', conn, req, res, 'ok');
bsw@0 1504 });
bsw@0 1505
bsw@0 1506 });
bsw@0 1507 });
bsw@0 1508 })
bsw@0 1509 };
bsw@0 1510 });
bsw@0 1511 },
bsw@0 1512
bsw@0 1513 '/supporter': function (conn, req, res, params) {
bsw@0 1514 requireAccessLevel(conn, req, res, 'member', function() {
bsw@0 1515 var initiative_id = parseInt(params.initiative_id);
bsw@0 1516 var draft_id = parseInt(params.draft_id);
bsw@0 1517
bsw@0 1518 // check if needed arguments are supplied
bsw@0 1519 if (!initiative_id) {
bsw@0 1520 respond('json', conn, req, res, 'unprocessable', null, 'You need to supply an initiative_id.');
bsw@0 1521 return;
bsw@0 1522 }
bsw@0 1523
bsw@0 1524 if (!draft_id) {
bsw@0 1525 respond('json', conn, req, res, 'unprocessable', null, 'You need to supply an draft_id.');
bsw@0 1526 return;
bsw@0 1527 }
bsw@0 1528
bsw@0 1529 // lock member for upsert
bsw@0 1530 lockMemberById(conn, req, res, req.current_member_id, function() {
bsw@0 1531
bsw@0 1532 // delete supporter
bsw@0 1533 if (params.delete) {
bsw@0 1534
bsw@0 1535 // check issue state
bsw@0 1536 requireIssueStateForInitiative(conn, req, res, initiative_id, ['admission', 'discussion', 'verification'], function() {
bsw@0 1537
bsw@0 1538 // delete supporter
bsw@0 1539 var query = new selector.SQLDelete('supporter');
bsw@0 1540 query.addWhere(['initiative_id = ?', initiative_id]);
bsw@0 1541 query.addWhere(['member_id = ?', req.current_member_id]);
bsw@0 1542 db.query(conn, req, res, query, function(result) { respond('json', conn, req, res, 'ok'); });
bsw@0 1543
bsw@0 1544 });
bsw@0 1545
bsw@0 1546 // upsert supporter
bsw@0 1547 } else {
bsw@0 1548
bsw@0 1549 // check and lock privilege
bsw@0 1550 requireInitiativePrivilege(conn, req, res, initiative_id, function() {
bsw@0 1551
bsw@0 1552 // check issue state
bsw@0 1553 requireIssueStateForInitiative(conn, req, res, initiative_id, ['admission', 'discussion', 'verification'], function() {
bsw@0 1554
bsw@0 1555 // check if given draft is the current one
bsw@0 1556 var query = new selector.Selector('current_draft');
bsw@0 1557 query.addField('NULL');
bsw@0 1558 query.addWhere(['current_draft.initiative_id = ?', initiative_id]);
bsw@0 1559 query.addWhere(['current_draft.id = ?', draft_id]);
bsw@0 1560
bsw@0 1561 db.query(conn, req, res, query, function(result) {
bsw@0 1562 if (result.rows.length != 1) {
bsw@0 1563 respond('json', conn, req, res, 'conflict', null, 'The draft with the supplied draft_id is not the current one anymore!');
bsw@0 1564 return;
bsw@0 1565 }
bsw@0 1566
bsw@0 1567 // upsert supporter
bsw@0 1568 var query = new selector.Upserter('supporter', ['initiative_id', 'member_id']);
bsw@0 1569 query.addValues({
bsw@0 1570 initiative_id: initiative_id,
bsw@0 1571 member_id: req.current_member_id,
bsw@0 1572 draft_id: draft_id
bsw@0 1573 });
bsw@0 1574
bsw@0 1575 db.query(conn, req, res, query, function(result) {
bsw@0 1576 respond('json', conn, req, res, 'ok');
bsw@0 1577 });
bsw@0 1578
bsw@0 1579 });
bsw@0 1580 });
bsw@0 1581 });
bsw@0 1582 };
bsw@0 1583 });
bsw@0 1584 });
bsw@0 1585 },
bsw@0 1586
bsw@0 1587 '/draft': function (conn, req, res, params) {
bsw@0 1588 requireAccessLevel(conn, req, res, 'member', function() {
bsw@0 1589 var area_id = parseInt(params.area_id);
bsw@0 1590 var policy_id = parseInt(params.policy_id);
bsw@0 1591 var issue_id = parseInt(params.issue_id);
bsw@0 1592 var initiative_id = parseInt(params.initiative_id);
bsw@0 1593 var initiative_name = params.initiative_name;
bsw@0 1594 var initiative_discussion_url = params.initiative_discussion_url;
bsw@0 1595 var formatting_engine = params.formatting_engine;
bsw@0 1596 var content = params.content;
bsw@0 1597
bsw@0 1598 if (!initiative_discussion_url) initiative_discussion_url = null;
bsw@0 1599
bsw@0 1600 // check parameters
bsw@0 1601 if (!formatting_engine) {
bsw@0 1602 respond('json', conn, req, res, 'unprocessable', null, 'No formatting_engine supplied.');
bsw@0 1603 return;
bsw@0 1604 } else if (formatting_engine != 'rocketwiki' && formatting_engine != 'compat') {
bsw@0 1605 respond('json', conn, req, res, 'unprocessable', null, 'Invalid formatting engine supplied.');
bsw@0 1606 return;
bsw@0 1607 };
bsw@0 1608
bsw@0 1609 if (!content) {
bsw@0 1610 respond('json', conn, req, res, 'unprocessable', null, 'No draft content supplied.');
bsw@0 1611 return;
bsw@0 1612 };
bsw@0 1613
bsw@0 1614 lockMemberById(conn, req, res, req.current_member_id, function() {
bsw@0 1615
bsw@0 1616 // new draft in new initiative in new issue
bsw@0 1617 if (area_id && !issue_id && !initiative_id) {
bsw@0 1618
bsw@0 1619 // check parameters for new issue
bsw@0 1620 if (!policy_id) {
bsw@0 1621 respond('json', conn, req, res, 'unprocessable', null, 'No policy supplied.');
bsw@0 1622 return;
bsw@0 1623 }
bsw@0 1624
bsw@0 1625 if (!initiative_name) {
bsw@0 1626 respond('json', conn, req, res, 'unprocessable', null, 'No initiative name supplied.');
bsw@0 1627 return;
bsw@0 1628 }
bsw@0 1629
bsw@0 1630 requireAreaPrivilege(conn, req, res, area_id, function() {
bsw@0 1631
bsw@0 1632 // check if policy is allowed in this area and if area and policy are active
bsw@0 1633 var query = new selector.Selector();
bsw@0 1634 query.from('allowed_policy');
bsw@0 1635 query.join('area', null, 'area.id = allowed_policy.area_id AND area.active');
bsw@0 1636 query.join('policy', null, 'policy.id = allowed_policy.policy_id AND policy.active');
bsw@0 1637 query.addField('NULL');
bsw@0 1638 query.addWhere(['area.id = ? AND policy.id = ?', area_id, policy_id]);
bsw@0 1639 db.query(conn, req, res, query, function (result, conn) {
bsw@0 1640 if (result.rows.length != 1) {
bsw@0 1641 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 1642 return;
bsw@0 1643 };
bsw@0 1644
bsw@0 1645 // check contingent
bsw@0 1646 requireContingentLeft(conn, req, res, true, function() {
bsw@0 1647
bsw@0 1648 // insert new issue
bsw@0 1649 var query = new selector.SQLInsert('issue');
bsw@0 1650 query.addValues({
bsw@0 1651 area_id: area_id,
bsw@0 1652 policy_id: policy_id
bsw@0 1653 });
bsw@0 1654 query.addReturning('id');
bsw@0 1655 db.query(conn, req, res, query, function(result) {
bsw@0 1656 var issue_id = result.rows[0].id;
bsw@0 1657
bsw@0 1658 // insert new initiative
bsw@0 1659 var query = new selector.SQLInsert('initiative');
bsw@0 1660 query.addValues({
bsw@0 1661 issue_id: issue_id,
bsw@0 1662 name: initiative_name,
bsw@0 1663 discussion_url: initiative_discussion_url
bsw@0 1664 });
bsw@0 1665 query.addReturning('id');
bsw@0 1666 db.query(conn, req, res, query, function(result) {
bsw@0 1667 var initiative_id = result.rows[0].id;
bsw@0 1668
bsw@0 1669 // insert initiator
bsw@0 1670 var query = new selector.SQLInsert('initiator');
bsw@0 1671 query.addValues({ initiative_id: initiative_id, member_id: req.current_member_id, accepted: true });
bsw@0 1672 db.query(conn, req, res, query, function(result) {
bsw@0 1673
bsw@0 1674 // insert new draft
bsw@0 1675 var query = new selector.SQLInsert('draft');
bsw@0 1676 query.addValues({
bsw@0 1677 initiative_id: initiative_id,
bsw@0 1678 author_id: req.current_member_id,
bsw@0 1679 formatting_engine: formatting_engine,
bsw@0 1680 content: content
bsw@0 1681 });
bsw@0 1682 query.addReturning('id');
bsw@0 1683 db.query(conn, req, res, query, function (result, conn) {
bsw@0 1684 var draft_id = result.rows[0].id;
bsw@0 1685
bsw@0 1686 respond('json', conn, req, res, 'ok', { issue_id: issue_id, initiative_id: initiative_id, draft_id: draft_id } );
bsw@0 1687 });
bsw@0 1688 });
bsw@0 1689 });
bsw@0 1690 });
bsw@0 1691 });
bsw@0 1692 });
bsw@0 1693 });
bsw@0 1694
bsw@0 1695 // new draft in new initiative in existant issue
bsw@0 1696 } else if (issue_id && !area_id && !initiative_id) {
bsw@0 1697
bsw@3 1698 if (!initiative_name) {
bsw@3 1699 respond('json', conn, req, res, 'unprocessable', null, 'No initiative name supplied.');
bsw@3 1700 return;
bsw@3 1701 }
bsw@3 1702
bsw@0 1703 // check privilege
bsw@0 1704 requireIssuePrivilege(conn, req, res, issue_id, function() {
bsw@0 1705
bsw@0 1706 // check issue state
bsw@0 1707 requireIssueState(conn, req, res, issue_id, ['admission', 'discussion', 'verification'], function() {
bsw@0 1708
bsw@0 1709 // check contingent
bsw@0 1710 requireContingentLeft(conn, req, res, true, function() {
bsw@0 1711
bsw@0 1712 // insert initiative
bsw@0 1713 var query = new selector.SQLInsert('initiative');
bsw@0 1714 query.addValues({
bsw@0 1715 issue_id: issue_id,
bsw@0 1716 name: initiative_name,
bsw@0 1717 discussion_url: initiative_discussion_url
bsw@0 1718 });
bsw@0 1719 query.addReturning('id');
bsw@0 1720 db.query(conn, req, res, query, function(result) {
bsw@0 1721 var initiative_id = result.rows[0].id;
bsw@0 1722
bsw@0 1723 // insert initiator
bsw@0 1724 var query = new selector.SQLInsert('initiator');
bsw@0 1725 query.addValues({
bsw@0 1726 initiative_id: initiative_id,
bsw@0 1727 member_id: req.current_member_id,
bsw@0 1728 accepted: true
bsw@0 1729 });
bsw@0 1730 db.query(conn, req, res, query, function(result) {
bsw@0 1731
bsw@0 1732 // insert draft
bsw@0 1733 var query = new selector.SQLInsert('draft');
bsw@0 1734 query.addValues({
bsw@0 1735 initiative_id: initiative_id,
bsw@0 1736 author_id: req.current_member_id,
bsw@0 1737 formatting_engine: formatting_engine,
bsw@0 1738 content: content
bsw@0 1739 });
bsw@0 1740 query.addReturning('id');
bsw@0 1741 db.query(conn, req, res, query, function (result, conn) {
bsw@0 1742
bsw@0 1743 var draft_id = result.rows[0].id;
bsw@0 1744 respond('json', conn, req, res, 'ok', { initiative_id: initiative_id, draft_id: draft_id } );
bsw@0 1745
bsw@0 1746 });
bsw@0 1747 });
bsw@0 1748 });
bsw@0 1749 });
bsw@0 1750 });
bsw@0 1751 });
bsw@0 1752
bsw@0 1753 // new draft in existant initiative
bsw@0 1754 } else if (initiative_id && !area_id && !issue_id ) {
bsw@0 1755
bsw@0 1756 // check privilege
bsw@0 1757 requireInitiativePrivilege(conn, req, res, initiative_id, function() {
bsw@0 1758
bsw@0 1759 // check issue state
bsw@0 1760 requireIssueStateForInitiative(conn, req, res, initiative_id, ['admission', 'discussion'], function() {
bsw@0 1761
bsw@0 1762
bsw@0 1763 // get initiator
bsw@0 1764 var query = new selector.Selector();
bsw@0 1765 query.from('initiator');
bsw@0 1766 query.addField('accepted');
bsw@0 1767 query.addWhere(['initiative_id = ? AND member_id = ?', initiative_id, req.current_member_id]);
bsw@0 1768 db.query(conn, req, res, query, function (result, conn) {
bsw@0 1769
bsw@0 1770 // if member is not initiator, deny creating new draft
bsw@0 1771 if (result.rows.length != 1) {
bsw@0 1772 respond('json', conn, req, res, 'forbidden', null, 'You are not initiator of this initiative and not allowed to update its draft.');
bsw@0 1773 return;
bsw@0 1774 }
bsw@0 1775 var initiator = result.rows[0];
bsw@0 1776 if (!initiator.accepted) {
bsw@0 1777 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 1778 return;
bsw@0 1779 };
bsw@0 1780
bsw@0 1781 // check contingent
bsw@0 1782 requireContingentLeft(conn, req, res, false, function() {
bsw@0 1783
bsw@0 1784 // insert new draft
bsw@0 1785 var query = new selector.SQLInsert('draft');
bsw@0 1786 query.addValues({
bsw@0 1787 initiative_id: initiative_id,
bsw@0 1788 author_id: req.current_member_id,
bsw@0 1789 formatting_engine: formatting_engine,
bsw@0 1790 content: content
bsw@0 1791 });
bsw@0 1792 query.addReturning('id');
bsw@0 1793 db.query(conn, req, res, query, function (result, conn) {
bsw@0 1794
bsw@0 1795 var draft_id = result.rows[0].id;
bsw@0 1796 respond('json', conn, req, res, 'ok', { draft_id: draft_id } );
bsw@0 1797 });
bsw@0 1798 });
bsw@0 1799 });
bsw@0 1800 });
bsw@0 1801 });
bsw@0 1802
bsw@0 1803 // none of them (invalid request)
bsw@0 1804 } else {
bsw@0 1805 respond('json', conn, req, res, 'unprocessable', null, 'Excactly one of area_id, issue_id or initiative_id must be supplied!');
bsw@0 1806 };
bsw@0 1807
bsw@0 1808 });
bsw@0 1809 });
bsw@0 1810 },
bsw@0 1811
bsw@0 1812 '/suggestion': function (conn, req, res, params) {
bsw@0 1813 requireAccessLevel(conn, req, res, 'member', function() {
bsw@0 1814 // TODO
bsw@0 1815 });
bsw@0 1816 },
bsw@0 1817
bsw@0 1818 '/opinion': function (conn, req, res, params) {
bsw@0 1819 requireAccessLevel(conn, req, res, 'member', function() {
bsw@0 1820 // TODO
bsw@0 1821 });
bsw@0 1822 },
bsw@0 1823
bsw@0 1824 '/delegation': function (conn, req, res, params) {
bsw@0 1825 requireAccessLevel(conn, req, res, 'member', function() {
bsw@0 1826 var unit_id = parseInt(params.unit_id);
bsw@0 1827 var area_id = parseInt(params.area_id);
bsw@0 1828 var issue_id = parseInt(params.issue_id);
bsw@0 1829 var trustee_id;
bsw@0 1830
bsw@0 1831 if (params.trustee_id == '') {
bsw@0 1832 trustee_id = null;
bsw@0 1833 } else {
bsw@0 1834 trustee_id = parseInt(params.trustee_id);
bsw@0 1835 }
bsw@0 1836
bsw@0 1837 lockMemberById(conn, req, res, req.current_member_id, function() {
bsw@0 1838
bsw@0 1839 if (params.delete) {
bsw@0 1840 var query = new selector.SQLDelete('delegation')
bsw@0 1841 if (unit_id && !area_id && !issue_id) {
bsw@0 1842 query.addWhere(['unit_id = ?', unit_id]);
bsw@0 1843 } else if (!unit_id && area_id && !issue_id) {
bsw@0 1844 query.addWhere(['area_id = ?', area_id]);
bsw@0 1845 } else if (!unit_id && !area_id && issue_id) {
bsw@0 1846 query.addWhere(['issue_id = ?', issue_id]);
bsw@0 1847 } else {
bsw@0 1848 respond('json', conn, req, res, 'unprocessable', null, 'Excactly one of unit, area_id, issue_id must be supplied!');
bsw@0 1849 return;
bsw@0 1850 }
bsw@0 1851 query.addWhere(['truster_id = ?', req.current_member_id]);
bsw@0 1852 db.query(conn, req, res, query, function(result) { respond('json', conn, req, res, 'ok'); });
bsw@0 1853 } else {
bsw@0 1854 var query = new selector.Upserter('delegation', ['truster_id']);
bsw@0 1855 query.addValues({
bsw@0 1856 truster_id: req.current_member_id,
bsw@0 1857 trustee_id: trustee_id
bsw@0 1858 });
bsw@0 1859 if (unit_id && !area_id && !issue_id) {
bsw@0 1860
bsw@0 1861 // check privilege
bsw@0 1862 requireUnitPrivilege(conn, req, res, unit_id, function() {
bsw@0 1863
bsw@0 1864 query.addKeys(['unit_id'])
bsw@0 1865 query.addValues({ unit_id: unit_id, scope: 'unit' });
bsw@0 1866 db.query(conn, req, res, query, function(result) { respond('json', conn, req, res, 'ok'); });
bsw@0 1867 });
bsw@0 1868
bsw@0 1869 } else if (!unit_id && area_id && !issue_id) {
bsw@0 1870
bsw@0 1871 // check privilege
bsw@0 1872 requireAreaPrivilege(conn, req, res, area_id, function() {
bsw@0 1873
bsw@0 1874 query.addKeys(['area_id'])
bsw@0 1875 query.addValues({ area_id: area_id, scope: 'area' });
bsw@0 1876 db.query(conn, req, res, query, function(result) { respond('json', conn, req, res, 'ok'); });
bsw@0 1877 });
bsw@0 1878
bsw@0 1879 } else if (!unit_id && !area_id && issue_id) {
bsw@0 1880
bsw@0 1881 // check privilege
bsw@0 1882 requireIssuePrivilege(conn, req, res, issue_id, function() {
bsw@0 1883
bsw@0 1884 // check issue state
bsw@0 1885 requireIssueState(conn, req, res, issue_id, ['admission', 'discussion', 'verification', 'voting'], function() {
bsw@0 1886
bsw@0 1887 query.addKeys(['issue_id'])
bsw@0 1888 query.addValues({ issue_id: issue_id, scope: 'issue' });
bsw@0 1889 db.query(conn, req, res, query, function(result) { respond('json', conn, req, res, 'ok'); });
bsw@0 1890 });
bsw@0 1891 });
bsw@0 1892 } else {
bsw@0 1893 respond('json', conn, req, res, 'unprocessable', null, 'Excactly one of unit_id, area_id, issue_id must be supplied!');
bsw@0 1894 return;
bsw@0 1895 }
bsw@0 1896 }
bsw@0 1897
bsw@0 1898 });
bsw@0 1899
bsw@0 1900 });
bsw@0 1901 },
bsw@0 1902
bsw@0 1903 };

Impressum / About Us