lfapi

annotate lfapi/main.js @ 32:be8ca05d0315

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

Impressum / About Us