Skip to content

Commit

Permalink
Maintenance permissions (#101)
Browse files Browse the repository at this point in the history
- only WTG members have permission to configure maintenance setting
- change RnE references to EC
- change permissions verification
  • Loading branch information
kochman authored and jlyon1 committed Feb 20, 2019
1 parent 64cef12 commit 55fa5e3
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 99 deletions.
89 changes: 45 additions & 44 deletions app.js
Expand Up @@ -46,20 +46,20 @@ var sessionStore = new MySQLStore({}, functions.dbConnect());

// Set up an Express session, which is required for CASAuthentication.
app.use(session({
secret: process.env.SESSION_SECRET || 'super secret key',
resave: false,
saveUninitialized: true,
store: sessionStore
secret: process.env.SESSION_SECRET || 'super secret key',
resave: false,
saveUninitialized: true,
store: sessionStore
}));

// Create a new instance of CASAuthentication.
var cas = new CASAuthentication({
cas_url: 'https://cas-auth.rpi.edu/cas',
service_url: config.service_url,
cas_version: '2.0',
is_dev_mode: config.cas_dev_mode,
dev_mode_user: config.cas_dev_mode_user,
destroy_session: true,
cas_url: 'https://cas-auth.rpi.edu/cas',
service_url: config.service_url,
cas_version: '2.0',
is_dev_mode: config.cas_dev_mode,
dev_mode_user: config.cas_dev_mode_user,
destroy_session: true,
});

// determine where we're running
Expand Down Expand Up @@ -88,16 +88,16 @@ winston.configure({
}
}
if (Object.keys(meta).length !== 0) {
msg += ` ${util.inspect(meta, {colors: true})}`;
msg += ` ${util.inspect(meta, { colors: true })}`;
}
return msg;
})
)
});

app.use(logger('dev'));
app.use(bodyParser.json({type: ['application/json', 'application/csp-report']}));
app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json({ type: ['application/json', 'application/csp-report'] }));
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(csp);

Expand All @@ -114,34 +114,35 @@ app.use('/api/settings', settings);
app.use('/api/elections', elections);

app.get('/login', cas.bounce, function (req, res) {
if (!req.session || !req.session.cas_user) {
res.redirect('/logout');
if (!req.session || !req.session.cas_user) {
res.redirect('/logout');
}

var rcs_id = req.session.cas_user.toLowerCase();

Q.all([
cms.getWTG(rcs_id),
cms.getEC(rcs_id)
]).then(function (responses) {
var wtg_status = JSON.parse(responses[0]).result,
ec_status = JSON.parse(responses[1]).result;

if (wtg_status || ec_status) {
var logger_desc = "Granted admin access by CMS for ";
if (wtg_status) logger_desc += "WTG ";
if (wtg_status && ec_status) logger_desc += "and ";
if (ec_status) logger_desc += "EC ";
logger_desc += "membership";

custom_logger.write(null, req.session.cas_user, 'CMS_ADMIN', logger_desc);
}

var rcs_id = req.session.cas_user.toLowerCase();
req.session.is_authenticated = true;
req.session.ec_member = ec_status;
req.session.wtg_member = wtg_status;

Q.all([
cms.getWTG(rcs_id),
cms.getRNE(rcs_id)
]).then(function (responses) {
var wtg_status = JSON.parse(responses[0]).result,
rne_status = JSON.parse(responses[1]).result;

if(wtg_status || rne_status) {
var logger_desc = "Granted admin access by CMS for ";
if(wtg_status) logger_desc += "WTG ";
if(wtg_status && rne_status) logger_desc += "and ";
if(rne_status) logger_desc += "RNE ";
logger_desc += "membership";

custom_logger.write(null, req.session.cas_user, 'CMS_ADMIN', logger_desc);
}

req.session.admin_rights = wtg_status || rne_status;
req.session.is_authenticated = true;

res.redirect('/');
});
res.redirect('/');
});
});
app.get('/logout', cas.logout);

Expand All @@ -167,9 +168,9 @@ if (environment === 'production') {

// catch 404 and forward to error handler
app.use(function (req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
var err = new Error('Not Found');
err.status = 404;
next(err);
});

// error handlers
Expand All @@ -179,15 +180,15 @@ app.use(function (req, res, next) {
if (app.get('env') === 'development') {
app.use(function (err, req, res, next) {
res.status(err.status || 500).send("<!DOCTYPE html><html><body><h1>There's an error (" + err.status + ")!</h1>" +
"<p>" + err.message + "</p><p>" + err + "</p></body></html>");
"<p>" + err.message + "</p><p>" + err + "</p></body></html>");
});
}

// production error handler
// no stacktraces leaked to user
app.use(function (err, req, res, next) {
res.status(err.status || 500).send("<!DOCTYPE html><html><body><h1>There's an error (" + err.status + ")!</h1>" +
"<p>" + err.message + "</p></body></html>");
res.status(err.status || 500).send("<!DOCTYPE html><html><body><h1>There's an error (" + err.status + ")!</h1>" +
"<p>" + err.message + "</p></body></html>");
});

module.exports = app;
22 changes: 11 additions & 11 deletions cms.js
Expand Up @@ -16,34 +16,34 @@ var endpoints = {
rcs: '/api/users/view_rcs/%/',
rin: '/api/users/view_rin/%/',
wtg: '/api/users/get_if_wtg/%/',
rne: '/api/users/get_if_rne/%/'
ec: '/api/users/get_if_rne/%/'
};

var execute = function(path) {
var execute = function (path) {
var options = {
method: defaults.method,
host: defaults.host,
path: path,
headers: defaults.headers
};

var deferred = Q.defer();
var deferred = Q.defer();

var req = https.request(options, function(response) {
var req = https.request(options, function (response) {
response.setEncoding('utf8');

var responseData = '';

response.on('data', function(data) {
response.on('data', function (data) {
responseData += data;
});

response.on('end', function() {
response.on('end', function () {
deferred.resolve(responseData);
});
});

req.on('error', function(err) {
req.on('error', function (err) {
deferred.reject(err);
});

Expand All @@ -59,10 +59,10 @@ module.exports = {
getRIN: function (rin) {
return execute(endpoints.rin.replace(/%/g, rin));
},
getWTG: function(rcs_id) {
getWTG: function (rcs_id) {
return execute(endpoints.wtg.replace(/%/g, rcs_id));
},
getRNE: function(rcs_id) {
return execute(endpoints.rne.replace(/%/g, rcs_id));
getEC: function (rcs_id) {
return execute(endpoints.ec.replace(/%/g, rcs_id));
}
};
};
36 changes: 18 additions & 18 deletions functions.js
Expand Up @@ -10,13 +10,13 @@ module.exports = {
dbConnect: function (res) {
var connection = mysql.createConnection(db);
connection.on('error', err => {
databasedebug(err)
databasedebug(err)
});
connection.connect();
connection.query("USE " + db_name, function (err) {
if (err) {
console.error(err);
if(res) {
if (res) {
res.status(500);
}
}
Expand All @@ -40,13 +40,13 @@ module.exports = {
constructSQLArray: function (values) {
var array = '(';

values.forEach(function(elem, index) {
array += mysql.escape(elem) + ( index < values.length -1 ? ', ' : ')');
values.forEach(function (elem, index) {
array += mysql.escape(elem) + (index < values.length - 1 ? ', ' : ')');
});

return array;
},
verifyPermissions: function(req) {
verifyPermissions: function (req) {
if (!req.session || !req.session.cas_user || !req.session.is_authenticated) {
return {
'authenticated': false,
Expand All @@ -58,27 +58,27 @@ module.exports = {
return {
authenticated: req.session.is_authenticated,
username: req.session.cas_user.toLowerCase(),
admin: req.session.admin_rights
admin: req.session.ec_member || req.session.wtg_member
};
},
log: function (connection, rcsid, type, description) {

/*Not sure if connection is needed now*/
/*Can rcsid be replaced with a session variable?*/
var providedConnection = true;
/*Not sure if connection is needed now*/
/*Can rcsid be replaced with a session variable?*/
var providedConnection = true;

if(!connection) {
providedConnection = false;
connection = functions.dbConnect();
}
if (!connection) {
providedConnection = false;
connection = functions.dbConnect();
}

connection.query("INSERT INTO log (rcs_id, type, description, time) VALUES ('" + rcsid + "', '" + type + "', '" + description + "', NOW())");
connection.query("INSERT INTO log (rcs_id, type, description, time) VALUES ('" + rcsid + "', '" + type + "', '" + description + "', NOW())");

if(!providedConnection) {
connection.end();
}
if (!providedConnection) {
connection.end();
}
},
determineCMSPromise: function(rcs_id) {
determineCMSPromise: function (rcs_id) {
console.log(rcs_id);
return isNaN(parseInt(rcs_id)) ? cms.getRCS(rcs_id) : cms.getRIN(rcs_id);
},
Expand Down
12 changes: 7 additions & 5 deletions public/components/Main/MainController.js
Expand Up @@ -19,28 +19,30 @@ app.controller('MainController', ['$scope', '$location', '$http', '$templateCach
};

$scope.editPermissions = false;
$scope.maintenancePermissions = false;
$scope.authenticated = false;
$scope.username = null;
$scope.maintenanceMode = false;
$scope.maintenanceMessage = "";
$scope.partiesEnabled = true;

$http.get("/api/users/").then(function (response) {
$scope.editPermissions = response.data.admin;
$scope.editPermissions = response.data.ec || response.data.wtg;
$scope.maintenancePermissions = response.data.wtg;
$scope.authenticated = response.data.authenticated;
$scope.username = response.data.username;
});
$http.get("/api/settings/maintenance_mode").then(function (response) {
$scope.maintenanceMode = response.data[0].value/1;
$scope.maintenanceMode = response.data[0].value / 1;
});
$http.get("/api/settings/maintenance_message").then(function (response) {
$scope.maintenanceMessage = response.data[0].value;
if (!$scope.maintenanceMessage) {
$scope.maintenanceMessage = "The site is under maintenance. Check back soon!"
$scope.maintenanceMessage = "The site is under maintenance. Check back soon!"
}
});
$http.get("/api/settings/parties_enabled").then(function (response) {
$scope.partiesEnabled = response.data[0].value/1;
$scope.partiesEnabled = response.data[0].value / 1;
});

$scope.formatTime = function (time) {
Expand All @@ -53,7 +55,7 @@ app.controller('MainController', ['$scope', '$location', '$http', '$templateCach
};

$scope.isPastEvent = function (date) {
return date.toISOString().substr(0,10) < new Date().toISOString().substr(0,10);
return date.toISOString().substr(0, 10) < new Date().toISOString().substr(0, 10);
};

/**
Expand Down
38 changes: 20 additions & 18 deletions public/components/Settings/settings.html
Expand Up @@ -142,25 +142,27 @@ <h3>Manage Elections</h3>
</div>
</div>
</div>
<hr>
<div class="row">
<div class="col-sm-12 col-md-4">
<h3>Maintenance Mode</h3>
</div>
</div>
<div class="row">
<div class="col-md-2">
<button type="button" class="btn btn-danger" ng-click="toggleMaintenance()">
<span ng-if="!maintenanceMode">Turn on</span>
<span ng-if="maintenanceMode">Turn off</span>
</button>
</div>
<label for="maintenanceModeMessage" class="col-md-3 control-label">Show a message to visitors:<br>(if blank, uses default)</label>
<div class="col-md-6">
<input name="maintenanceModeMessage" placeholder="The site is under maintenance. Check back soon!" ng-model="new.maintenance_message" class="form-control"></input>
<div ng-if="maintenancePermissions">
<hr>
<div class="row">
<div class="col-sm-12 col-md-6">
<h3>Maintenance Mode <small>for maintenance only</small></h3>
</div>
</div>
<div class="col-md-1">
<button type="button" class="btn btn-success" ng-click="saveMaintenanceMessage()">Save</button>
<div class="row">
<div class="col-md-2">
<button type="button" class="btn btn-danger" ng-click="toggleMaintenance()">
<span ng-if="!maintenanceMode">Turn on</span>
<span ng-if="maintenanceMode">Turn off</span>
</button>
</div>
<label for="maintenanceModeMessage" class="col-md-3 control-label">Show a message to visitors:<br>(if blank, uses default)</label>
<div class="col-md-6">
<input name="maintenanceModeMessage" placeholder="The site is under maintenance. Check back soon!" ng-model="new.maintenance_message" class="form-control"></input>
</div>
<div class="col-md-1">
<button type="button" class="btn btn-success" ng-click="saveMaintenanceMessage()">Save</button>
</div>
</div>
</div>
<hr>
Expand Down
8 changes: 5 additions & 3 deletions routes/users.js
Expand Up @@ -8,18 +8,20 @@ var express = require('express'),

module.exports = router;

router.get('/', function(req, res) {
router.get('/', function (req, res) {
if (!req.session || !req.session.cas_user || !req.session.is_authenticated) {
res.json({
authenticated: false,
username: null,
admin: false
ec: false,
wtg: false
});
} else {
res.json({
authenticated: req.session.is_authenticated,
username: req.session.cas_user.toLowerCase(),
admin: req.session.admin_rights
ec: req.session.ec_member,
wtg: req.session.wtg_member
});
}
});
Expand Down

0 comments on commit 55fa5e3

Please sign in to comment.