lfapi

annotate lfapi/main.js @ 29:1956fe9e9d62

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

Impressum / About Us