mirror of
https://github.com/ENSL/ensl_gathers.git
synced 2025-04-25 00:41:07 +00:00
Bunch of changes
This commit is contained in:
parent
805b942c5e
commit
9151212c78
35 changed files with 346 additions and 130 deletions
|
@ -5,7 +5,9 @@ var config = {
|
||||||
mongo: {
|
mongo: {
|
||||||
uri: "mongodb://localhost/swsgather_development"
|
uri: "mongodb://localhost/swsgather_development"
|
||||||
},
|
},
|
||||||
secret_token: ""
|
secret_token: "",
|
||||||
|
session_store_name: "_ENSL_session_key_staging",
|
||||||
|
ensl_url: "http://staging.ensl.org/"
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = config;
|
module.exports = config;
|
|
@ -5,7 +5,9 @@ var config = {
|
||||||
mongo: {
|
mongo: {
|
||||||
uri: "" // Set using MONGOLAB_URI
|
uri: "" // Set using MONGOLAB_URI
|
||||||
},
|
},
|
||||||
secret_token: ""
|
secret_token: "",
|
||||||
|
session_store_name: "_ENSL_session_key_staging",
|
||||||
|
ensl_url: "http://www.ensl.org/"
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = config;
|
module.exports = config;
|
|
@ -5,7 +5,9 @@ var config = {
|
||||||
mongo: {
|
mongo: {
|
||||||
uri: "" // Set using MONGOLAB_URI
|
uri: "" // Set using MONGOLAB_URI
|
||||||
},
|
},
|
||||||
secret_token: ""
|
secret_token: "",
|
||||||
|
session_store_name: "_ENSL_session_key_staging",
|
||||||
|
ensl_url: "http://staging.ensl.org/"
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = config;
|
module.exports = config;
|
|
@ -5,7 +5,9 @@ var config = {
|
||||||
mongo: {
|
mongo: {
|
||||||
uri: "mongodb://localhost/swsgather_test"
|
uri: "mongodb://localhost/swsgather_test"
|
||||||
},
|
},
|
||||||
secret_token: "SUPERSECRETFOO"
|
secret_token: "SUPERSECRETFOO",
|
||||||
|
session_store_name: "_ENSL_session_key_staging",
|
||||||
|
ensl_url: "http://staging.ensl.org/"
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = config;
|
module.exports = config;
|
|
@ -8,11 +8,13 @@ var winston = require("winston");
|
||||||
var config = require("./config.js");
|
var config = require("./config.js");
|
||||||
var favicon = require("serve-favicon");
|
var favicon = require("serve-favicon");
|
||||||
var exphbs = require("express-handlebars");
|
var exphbs = require("express-handlebars");
|
||||||
|
var cookieParser = require("cookie-parser");
|
||||||
var env = process.env.NODE_ENV || "development";
|
var env = process.env.NODE_ENV || "development";
|
||||||
var pkg = JSON.parse(fs.readFileSync(path.join(__dirname, "../package.json")));
|
var pkg = JSON.parse(fs.readFileSync(path.join(__dirname, "../package.json")));
|
||||||
|
|
||||||
module.exports = app => {
|
module.exports = app => {
|
||||||
app.use(express.static(path.join(__dirname, '../public')));
|
app.use(express.static(path.join(__dirname, '../public')));
|
||||||
|
app.use(cookieParser());
|
||||||
app.use(favicon(path.join(__dirname, '../public/images/favicon.ico')));
|
app.use(favicon(path.join(__dirname, '../public/images/favicon.ico')));
|
||||||
|
|
||||||
// Use winston on production
|
// Use winston on production
|
||||||
|
|
|
@ -1,13 +1,26 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
var path = require("path");
|
||||||
|
var winston = require("winston");
|
||||||
var config = require("./config.js");
|
var config = require("./config.js");
|
||||||
|
|
||||||
module.exports = app => {
|
module.exports = app => {
|
||||||
app.get("/", (request, response) => {
|
app.get("/", (request, response, next) => {
|
||||||
response.render("index.hbs");
|
response.render("index.hbs");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
app.get("/redirect", (request, response, next) => {
|
||||||
|
response.render("redirect.hbs", {
|
||||||
|
redirect: config.ensl_url
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
app.get("*", (request, response) => {
|
app.get("*", (request, response) => {
|
||||||
response.status(404).render("404.hbs");
|
response.status(404).render("404.hbs");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
app.use(function (error, request, response, next) {
|
||||||
|
winston.error(error);
|
||||||
|
return response.status(500).render("500.hbs");
|
||||||
|
});
|
||||||
};
|
};
|
|
@ -2,13 +2,15 @@
|
||||||
|
|
||||||
var winston = require("winston");
|
var winston = require("winston");
|
||||||
var User = require("../lib/user/user");
|
var User = require("../lib/user/user");
|
||||||
var client = require("../lib/ensl/client")();
|
var config = require("./config");
|
||||||
|
var EnslClient = require("../lib/ensl/client");
|
||||||
|
var client = EnslClient();
|
||||||
var chatController = require("../lib/chat/controller");
|
var chatController = require("../lib/chat/controller");
|
||||||
var gatherController = require("../lib/gather/controller");
|
var gatherController = require("../lib/gather/controller");
|
||||||
var userController = require("../lib/user/controller");
|
var userController = require("../lib/user/controller");
|
||||||
|
|
||||||
var getRandomUser = callback => {
|
var getRandomUser = callback => {
|
||||||
var id = Math.floor(Math.random() * 5000) + 1;
|
let id = Math.floor(Math.random() * 5000) + 1;
|
||||||
client.getUserById({
|
client.getUserById({
|
||||||
id: id
|
id: id
|
||||||
}, (error, response, body) => {
|
}, (error, response, body) => {
|
||||||
|
@ -17,20 +19,41 @@ var getRandomUser = callback => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var parseCookies = (socket) => {
|
||||||
|
let cookieString = socket.request.headers.cookie;
|
||||||
|
if (typeof cookieString !== 'string') return null;
|
||||||
|
let cookies = socket.request.headers.cookie.split(";")
|
||||||
|
.map(cookie => cookie.trim())
|
||||||
|
.reduce((acc, cookie) => {
|
||||||
|
let values = cookie.split("=");
|
||||||
|
let attr = values[0];
|
||||||
|
let val = values[1];
|
||||||
|
if (attr && val) acc[attr] = val;
|
||||||
|
return acc;
|
||||||
|
}, {})
|
||||||
|
return cookies;
|
||||||
|
};
|
||||||
|
|
||||||
module.exports = io => {
|
module.exports = io => {
|
||||||
var rootNamespace = io.of('/')
|
var rootNamespace = io.of('/')
|
||||||
|
|
||||||
// Authorisation
|
// Authentication
|
||||||
io.use((socket, next) => {
|
io.use((socket, next) => {
|
||||||
getRandomUser((error, _, body) => {
|
let session = EnslClient.decodeSession(parseCookies(socket)[config.session_store_name]);
|
||||||
|
|
||||||
|
if (!session || typeof session.user !== 'number') return next(new Error("Authentication Failed"));
|
||||||
|
|
||||||
|
client.getUserById({
|
||||||
|
id: session.user
|
||||||
|
}, (error, response, body) => {
|
||||||
if (error) {
|
if (error) {
|
||||||
winston.error(error);
|
winston.error(error);
|
||||||
return next(error)
|
return next(error)
|
||||||
};
|
};
|
||||||
socket._user = new User(body);
|
socket._user = new User(body);
|
||||||
console.log("You:", body.username, body.id);
|
winston.info("Logged in:", body.username, body.id);
|
||||||
next();
|
return next();
|
||||||
})
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
userController(rootNamespace);
|
userController(rootNamespace);
|
||||||
|
|
|
@ -8,5 +8,6 @@ mongoose.connect(config.mongo.uri);
|
||||||
|
|
||||||
// Load models
|
// Load models
|
||||||
require(path.join(__dirname, "/models/message"));
|
require(path.join(__dirname, "/models/message"));
|
||||||
|
require(path.join(__dirname, "/models/session"));
|
||||||
|
|
||||||
module.exports = mongoose;
|
module.exports = mongoose;
|
|
@ -37,4 +37,4 @@ messageSchema.statics.list = (options, callback) => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = mongoose.model('message', messageSchema);
|
module.exports = mongoose.model('Message', messageSchema);
|
||||||
|
|
18
db/models/session.js
Normal file
18
db/models/session.js
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var mongoose = require("mongoose");
|
||||||
|
var Schema = mongoose.Schema;
|
||||||
|
var crypto = require('crypto');
|
||||||
|
|
||||||
|
var keyGenerator = () => {
|
||||||
|
return crypto.randomBytes(20).toString('hex');
|
||||||
|
};
|
||||||
|
|
||||||
|
var sessionSchema = new Schema({
|
||||||
|
userId: { type: Number, required: true },
|
||||||
|
key: { type: String, required: true, default: keyGenerator }
|
||||||
|
});
|
||||||
|
|
||||||
|
sessionSchema.index({ userId: 1 });
|
||||||
|
|
||||||
|
module.exports = mongoose.model("Session", sessionSchema);
|
|
@ -15,7 +15,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var mongoose = require("mongoose");
|
var mongoose = require("mongoose");
|
||||||
var Message = mongoose.model("message");
|
var Message = mongoose.model("Message");
|
||||||
|
|
||||||
module.exports = namespace => {
|
module.exports = namespace => {
|
||||||
|
|
||||||
|
|
|
@ -78,15 +78,13 @@ EnslClient.decodeSession = sessionCookie => {
|
||||||
if (crypto.createHmac("sha1", SECRET_TOKEN).update(text).digest('hex') !== signature) return null;
|
if (crypto.createHmac("sha1", SECRET_TOKEN).update(text).digest('hex') !== signature) return null;
|
||||||
|
|
||||||
var parsedSession;
|
var parsedSession;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var parsedSession = new Marshal((new Buffer(text, "base64")).toString("ascii"));
|
parsedSession = (new Marshal((new Buffer(text, "base64")).toString("ascii"))).parsed;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.error(e);
|
logger.error(e);
|
||||||
parsedSession = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return parsedSession;
|
return parsedSession || null;
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = EnslClient;
|
module.exports = EnslClient;
|
||||||
|
|
|
@ -55,10 +55,8 @@ module.exports = function (namespace) {
|
||||||
|
|
||||||
// ***** Generate Test Users *****
|
// ***** Generate Test Users *****
|
||||||
var helper = require("./helper");
|
var helper = require("./helper");
|
||||||
helper.createTestUsers({ gather: gather });
|
helper.createTestUsers({ gather: gather }, refreshGather);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
namespace.on("connection", function (socket) {
|
namespace.on("connection", function (socket) {
|
||||||
socket.on("gather:join", function (data) {
|
socket.on("gather:join", function (data) {
|
||||||
if (gather.can("addGatherer")) gather.addGatherer(socket._user);
|
if (gather.can("addGatherer")) gather.addGatherer(socket._user);
|
||||||
|
|
|
@ -4,7 +4,7 @@ var User = require("../user/user");
|
||||||
var client = require("../ensl/client")();
|
var client = require("../ensl/client")();
|
||||||
var async = require("async");
|
var async = require("async");
|
||||||
|
|
||||||
var createTestUsers = options => {
|
var createTestUsers = (options, callback) => {
|
||||||
var gather = options.gather;
|
var gather = options.gather;
|
||||||
|
|
||||||
var getRandomUser = callback => {
|
var getRandomUser = callback => {
|
||||||
|
@ -40,10 +40,11 @@ var createTestUsers = options => {
|
||||||
array[index].leaderVote = array[candidate].id;
|
array[index].leaderVote = array[candidate].id;
|
||||||
});
|
});
|
||||||
console.log("Assigned vote for each gatherer");
|
console.log("Assigned vote for each gatherer");
|
||||||
|
if (typeof callback === 'function') return callback(gather);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
createTestUsers: createTestUsers
|
createTestUsers: createTestUsers
|
||||||
}
|
};
|
|
@ -584,8 +584,8 @@ var Gatherers = React.createClass({
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<tr key={gatherer.user.id}>
|
<tr key={gatherer.user.id} data-userid={gatherer.user.id}>
|
||||||
<td className="col-md-5">{country} {gatherer.user.username} ({gatherer.user.id})</td>
|
<td className="col-md-5">{country} {gatherer.user.username} </td>
|
||||||
<td className="col-md-5">
|
<td className="col-md-5">
|
||||||
{lifeform} {division} {team}
|
{lifeform} {division} {team}
|
||||||
</td>
|
</td>
|
||||||
|
|
|
@ -27,11 +27,37 @@ var initialiseVisibilityMonitoring = (socket) => {
|
||||||
}, false);
|
}, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var removeAuthWidget = () => {
|
||||||
|
$("#authenticating").remove();
|
||||||
|
};
|
||||||
|
|
||||||
|
var showAuthenticationNotice = () => {
|
||||||
|
$("#auth-required").show();
|
||||||
|
};
|
||||||
|
|
||||||
|
var renderPage = (socket) => {
|
||||||
|
initialiseVisibilityMonitoring(socket);
|
||||||
|
React.render(<UserMenu />, document.getElementById('side-menu'));
|
||||||
|
React.render(<Chatroom />, document.getElementById('chatroom'));
|
||||||
|
React.render(<Gather />, document.getElementById('gathers'));
|
||||||
|
React.render(<CurrentUser />, document.getElementById('currentuser'));
|
||||||
|
React.render(<AdminPanel />, document.getElementById('admin-menu'));
|
||||||
|
};
|
||||||
|
|
||||||
var initialiseComponents = () => {
|
var initialiseComponents = () => {
|
||||||
let socketUrl = window.location.protocol + "//" + window.location.host;
|
let socketUrl = window.location.protocol + "//" + window.location.host;
|
||||||
socket = io(socketUrl)
|
socket = io(socketUrl)
|
||||||
.on("connect", () => {
|
.on("connect", () => {
|
||||||
console.log("Connected");
|
console.log("Connected");
|
||||||
|
removeAuthWidget();
|
||||||
|
renderPage(socket);
|
||||||
|
})
|
||||||
|
.on("error", (error, foo) => {
|
||||||
|
console.log(error);
|
||||||
|
if (error === "Authentication Failed") {
|
||||||
|
removeAuthWidget();
|
||||||
|
showAuthenticationNotice();
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.on("reconnect", () => {
|
.on("reconnect", () => {
|
||||||
console.log("Reconnected");
|
console.log("Reconnected");
|
||||||
|
@ -39,13 +65,4 @@ var initialiseComponents = () => {
|
||||||
.on("disconnect", () => {
|
.on("disconnect", () => {
|
||||||
console.log("Disconnected")
|
console.log("Disconnected")
|
||||||
});
|
});
|
||||||
|
|
||||||
initialiseVisibilityMonitoring(socket);
|
|
||||||
|
|
||||||
// Render Page
|
|
||||||
React.render(<UserMenu />, document.getElementById('side-menu'));
|
|
||||||
React.render(<Chatroom />, document.getElementById('chatroom'));
|
|
||||||
React.render(<Gather />, document.getElementById('gathers'));
|
|
||||||
React.render(<CurrentUser />, document.getElementById('currentuser'));
|
|
||||||
React.render(<AdminPanel />, document.getElementById('admin-menu'));
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -27,18 +27,15 @@ var UserLogin = React.createClass({
|
||||||
type="text"
|
type="text"
|
||||||
className="form-control"
|
className="form-control"
|
||||||
ref="authorize_id"
|
ref="authorize_id"
|
||||||
placeholder="Choose an ID..." />
|
placeholder="Change user" />
|
||||||
<span className="input-group-btn">
|
<span className="input-group-btn">
|
||||||
<input
|
<input
|
||||||
type="submit"
|
type="submit"
|
||||||
className="btn btn-primary"
|
className="btn btn-primary"
|
||||||
id="btn-chat"
|
id="btn-chat"
|
||||||
value="Login" />
|
value="Assume ID" />
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="signin">
|
|
||||||
<p className="text-center"><small>Just a temporary measure until genuine authentication is implemented</small></p>
|
|
||||||
</div>
|
|
||||||
</form>
|
</form>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -71,7 +68,6 @@ var UserMenu = React.createClass({
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
{users}
|
{users}
|
||||||
<li><br /><UserLogin /><br /></li>
|
|
||||||
</ul>
|
</ul>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -88,6 +84,7 @@ var AdminPanel = React.createClass({
|
||||||
<li>
|
<li>
|
||||||
<div className="admin-panel">
|
<div className="admin-panel">
|
||||||
<h5>Admin</h5>
|
<h5>Admin</h5>
|
||||||
|
<UserLogin />
|
||||||
<button
|
<button
|
||||||
className="btn btn-danger max-width"
|
className="btn btn-danger max-width"
|
||||||
onClick={this.handleGatherReset}>
|
onClick={this.handleGatherReset}>
|
||||||
|
@ -130,9 +127,6 @@ var CurrentUser = React.createClass({
|
||||||
<li>
|
<li>
|
||||||
<a href="#" data-toggle="modal" data-target="#designmodal">Design Goals</a>
|
<a href="#" data-toggle="modal" data-target="#designmodal">Design Goals</a>
|
||||||
</li>
|
</li>
|
||||||
<li className="divider"></li>
|
|
||||||
<li><a href="login.html"><i className="fa fa-sign-out fa-fw"></i> Logout</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
* Client API
|
* Client API
|
||||||
* users:online - User is on the page
|
* users:online - User is on the page
|
||||||
* users:away - User is away from page
|
* users:away - User is away from page
|
||||||
* users:authorize - Authorize user
|
* users:authorize - Sign on with arbitary user ID (to be enabled for admin only)
|
||||||
* users:refresh - Request new user list
|
* users:refresh - Request new user list
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@ -17,15 +17,17 @@
|
||||||
var userCache = {};
|
var userCache = {};
|
||||||
var User = require("./user");
|
var User = require("./user");
|
||||||
var winston = require("winston");
|
var winston = require("winston");
|
||||||
|
var mongoose = require("mongoose");
|
||||||
|
var Session = mongoose.model("Session");
|
||||||
var enslClient = require("../ensl/client")();
|
var enslClient = require("../ensl/client")();
|
||||||
var _ = require("lodash");
|
var _ = require("lodash");
|
||||||
|
|
||||||
module.exports = function (namespace) {
|
module.exports = namespace => {
|
||||||
var refreshUsers = function (socket) {
|
var refreshUsers = socket => {
|
||||||
var receivers = (socket !== undefined) ? [socket] : namespace.sockets;
|
var receivers = (socket !== undefined) ? [socket] : namespace.sockets;
|
||||||
|
|
||||||
var newCache = {};
|
var newCache = {};
|
||||||
namespace.sockets.forEach(function (socket) {
|
namespace.sockets.forEach(socket => {
|
||||||
var user = socket._user;
|
var user = socket._user;
|
||||||
newCache[user.id] = user;
|
newCache[user.id] = user;
|
||||||
});
|
});
|
||||||
|
@ -39,7 +41,7 @@ module.exports = function (namespace) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
receivers.forEach(function (socket) {
|
receivers.forEach(socket => {
|
||||||
socket.emit('users:update', {
|
socket.emit('users:update', {
|
||||||
count: users.length,
|
count: users.length,
|
||||||
users: users,
|
users: users,
|
||||||
|
@ -48,25 +50,26 @@ module.exports = function (namespace) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace.on('connection', function (socket) {
|
namespace.on('connection', socket => {
|
||||||
refreshUsers();
|
refreshUsers();
|
||||||
|
|
||||||
socket.on('users:refresh', refreshUsers.bind(null, socket));
|
socket.on('users:refresh', refreshUsers.bind(null, socket));
|
||||||
|
|
||||||
socket.on('users:online', function () {
|
socket.on('users:online', () => {
|
||||||
socket._user.online = true;
|
socket._user.online = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('users:away', function () {
|
socket.on('users:away', () => {
|
||||||
socket._user.online = false;
|
socket._user.online = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on("users:authorize", function (data) {
|
socket.on("users:authorize", data => {
|
||||||
|
if (!socket._user.admin) return;
|
||||||
var id = parseInt(data.id, 10);
|
var id = parseInt(data.id, 10);
|
||||||
if (isNaN(id)) return;
|
if (isNaN(id)) return;
|
||||||
enslClient.getUserById({
|
enslClient.getUserById({
|
||||||
id: id
|
id: id
|
||||||
}, function (error, response, body) {
|
}, (error, response, body) => {
|
||||||
if (error || response.statusCode !== 200) {
|
if (error || response.statusCode !== 200) {
|
||||||
winston.error("An error occurred in authorising id", id);
|
winston.error("An error occurred in authorising id", id);
|
||||||
winston.error(error);
|
winston.error(error);
|
||||||
|
@ -78,8 +81,6 @@ module.exports = function (namespace) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('disconnect', function (socket) {
|
socket.on('disconnect', socket => { refreshUsers(); });
|
||||||
refreshUsers();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
17
npm-shrinkwrap.json
generated
17
npm-shrinkwrap.json
generated
|
@ -1049,6 +1049,23 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"cookie-parser": {
|
||||||
|
"version": "1.3.5",
|
||||||
|
"from": "cookie-parser@*",
|
||||||
|
"resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.3.5.tgz",
|
||||||
|
"dependencies": {
|
||||||
|
"cookie": {
|
||||||
|
"version": "0.1.3",
|
||||||
|
"from": "cookie@0.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.1.3.tgz"
|
||||||
|
},
|
||||||
|
"cookie-signature": {
|
||||||
|
"version": "1.0.6",
|
||||||
|
"from": "cookie-signature@1.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"express": {
|
"express": {
|
||||||
"version": "4.13.3",
|
"version": "4.13.3",
|
||||||
"from": "express@~4.13.1",
|
"from": "express@~4.13.1",
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"async": "~1.4.0",
|
"async": "~1.4.0",
|
||||||
"babel": "~5.8.21",
|
"babel": "~5.8.21",
|
||||||
|
"cookie-parser": "^1.3.5",
|
||||||
"express": "~4.13.1",
|
"express": "~4.13.1",
|
||||||
"express-handlebars": "~2.0.1",
|
"express-handlebars": "~2.0.1",
|
||||||
"extend": "~3.0.0",
|
"extend": "~3.0.0",
|
||||||
|
|
|
@ -65,4 +65,16 @@
|
||||||
|
|
||||||
.add-top {
|
.add-top {
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jumbo-auth {
|
||||||
|
margin-top: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jumbo-img {
|
||||||
|
max-height: 150px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spinner {
|
||||||
|
max-height: 30px !important;
|
||||||
}
|
}
|
BIN
public/images/ensl_logo.png
Normal file
BIN
public/images/ensl_logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 96 KiB |
56
public/images/spinner.svg
Normal file
56
public/images/spinner.svg
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
<svg width="105" height="105" viewBox="0 0 105 105" xmlns="http://www.w3.org/2000/svg" fill="#fff">
|
||||||
|
<circle cx="12.5" cy="12.5" r="12.5">
|
||||||
|
<animate attributeName="fill-opacity"
|
||||||
|
begin="0s" dur="1s"
|
||||||
|
values="1;.2;1" calcMode="linear"
|
||||||
|
repeatCount="indefinite" />
|
||||||
|
</circle>
|
||||||
|
<circle cx="12.5" cy="52.5" r="12.5" fill-opacity=".5">
|
||||||
|
<animate attributeName="fill-opacity"
|
||||||
|
begin="100ms" dur="1s"
|
||||||
|
values="1;.2;1" calcMode="linear"
|
||||||
|
repeatCount="indefinite" />
|
||||||
|
</circle>
|
||||||
|
<circle cx="52.5" cy="12.5" r="12.5">
|
||||||
|
<animate attributeName="fill-opacity"
|
||||||
|
begin="300ms" dur="1s"
|
||||||
|
values="1;.2;1" calcMode="linear"
|
||||||
|
repeatCount="indefinite" />
|
||||||
|
</circle>
|
||||||
|
<circle cx="52.5" cy="52.5" r="12.5">
|
||||||
|
<animate attributeName="fill-opacity"
|
||||||
|
begin="600ms" dur="1s"
|
||||||
|
values="1;.2;1" calcMode="linear"
|
||||||
|
repeatCount="indefinite" />
|
||||||
|
</circle>
|
||||||
|
<circle cx="92.5" cy="12.5" r="12.5">
|
||||||
|
<animate attributeName="fill-opacity"
|
||||||
|
begin="800ms" dur="1s"
|
||||||
|
values="1;.2;1" calcMode="linear"
|
||||||
|
repeatCount="indefinite" />
|
||||||
|
</circle>
|
||||||
|
<circle cx="92.5" cy="52.5" r="12.5">
|
||||||
|
<animate attributeName="fill-opacity"
|
||||||
|
begin="400ms" dur="1s"
|
||||||
|
values="1;.2;1" calcMode="linear"
|
||||||
|
repeatCount="indefinite" />
|
||||||
|
</circle>
|
||||||
|
<circle cx="12.5" cy="92.5" r="12.5">
|
||||||
|
<animate attributeName="fill-opacity"
|
||||||
|
begin="700ms" dur="1s"
|
||||||
|
values="1;.2;1" calcMode="linear"
|
||||||
|
repeatCount="indefinite" />
|
||||||
|
</circle>
|
||||||
|
<circle cx="52.5" cy="92.5" r="12.5">
|
||||||
|
<animate attributeName="fill-opacity"
|
||||||
|
begin="500ms" dur="1s"
|
||||||
|
values="1;.2;1" calcMode="linear"
|
||||||
|
repeatCount="indefinite" />
|
||||||
|
</circle>
|
||||||
|
<circle cx="92.5" cy="92.5" r="12.5">
|
||||||
|
<animate attributeName="fill-opacity"
|
||||||
|
begin="200ms" dur="1s"
|
||||||
|
values="1;.2;1" calcMode="linear"
|
||||||
|
repeatCount="indefinite" />
|
||||||
|
</circle>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2 KiB |
|
@ -756,16 +756,14 @@ var Gatherers = React.createClass({
|
||||||
|
|
||||||
return React.createElement(
|
return React.createElement(
|
||||||
"tr",
|
"tr",
|
||||||
{ key: gatherer.user.id },
|
{ key: gatherer.user.id, "data-userid": gatherer.user.id },
|
||||||
React.createElement(
|
React.createElement(
|
||||||
"td",
|
"td",
|
||||||
{ className: "col-md-5" },
|
{ className: "col-md-5" },
|
||||||
country,
|
country,
|
||||||
" ",
|
" ",
|
||||||
gatherer.user.username,
|
gatherer.user.username,
|
||||||
" (",
|
" "
|
||||||
gatherer.user.id,
|
|
||||||
")"
|
|
||||||
),
|
),
|
||||||
React.createElement(
|
React.createElement(
|
||||||
"td",
|
"td",
|
||||||
|
@ -956,19 +954,16 @@ var initialiseVisibilityMonitoring = function initialiseVisibilityMonitoring(soc
|
||||||
}, false);
|
}, false);
|
||||||
};
|
};
|
||||||
|
|
||||||
var initialiseComponents = function initialiseComponents() {
|
var removeAuthWidget = function removeAuthWidget() {
|
||||||
var socketUrl = window.location.protocol + "//" + window.location.host;
|
$("#authenticating").remove();
|
||||||
socket = io(socketUrl).on("connect", function () {
|
};
|
||||||
console.log("Connected");
|
|
||||||
}).on("reconnect", function () {
|
|
||||||
console.log("Reconnected");
|
|
||||||
}).on("disconnect", function () {
|
|
||||||
console.log("Disconnected");
|
|
||||||
});
|
|
||||||
|
|
||||||
|
var showAuthenticationNotice = function showAuthenticationNotice() {
|
||||||
|
$("#auth-required").show();
|
||||||
|
};
|
||||||
|
|
||||||
|
var renderPage = function renderPage(socket) {
|
||||||
initialiseVisibilityMonitoring(socket);
|
initialiseVisibilityMonitoring(socket);
|
||||||
|
|
||||||
// Render Page
|
|
||||||
React.render(React.createElement(UserMenu, null), document.getElementById('side-menu'));
|
React.render(React.createElement(UserMenu, null), document.getElementById('side-menu'));
|
||||||
React.render(React.createElement(Chatroom, null), document.getElementById('chatroom'));
|
React.render(React.createElement(Chatroom, null), document.getElementById('chatroom'));
|
||||||
React.render(React.createElement(Gather, null), document.getElementById('gathers'));
|
React.render(React.createElement(Gather, null), document.getElementById('gathers'));
|
||||||
|
@ -976,6 +971,25 @@ var initialiseComponents = function initialiseComponents() {
|
||||||
React.render(React.createElement(AdminPanel, null), document.getElementById('admin-menu'));
|
React.render(React.createElement(AdminPanel, null), document.getElementById('admin-menu'));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var initialiseComponents = function initialiseComponents() {
|
||||||
|
var socketUrl = window.location.protocol + "//" + window.location.host;
|
||||||
|
socket = io(socketUrl).on("connect", function () {
|
||||||
|
console.log("Connected");
|
||||||
|
removeAuthWidget();
|
||||||
|
renderPage(socket);
|
||||||
|
}).on("error", function (error, foo) {
|
||||||
|
console.log(error);
|
||||||
|
if (error === "Authentication Failed") {
|
||||||
|
removeAuthWidget();
|
||||||
|
showAuthenticationNotice();
|
||||||
|
}
|
||||||
|
}).on("reconnect", function () {
|
||||||
|
console.log("Reconnected");
|
||||||
|
}).on("disconnect", function () {
|
||||||
|
console.log("Disconnected");
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var Chatroom = React.createClass({
|
var Chatroom = React.createClass({
|
||||||
|
@ -1189,7 +1203,7 @@ var UserLogin = React.createClass({
|
||||||
type: "text",
|
type: "text",
|
||||||
className: "form-control",
|
className: "form-control",
|
||||||
ref: "authorize_id",
|
ref: "authorize_id",
|
||||||
placeholder: "Choose an ID..." }),
|
placeholder: "Change user" }),
|
||||||
React.createElement(
|
React.createElement(
|
||||||
"span",
|
"span",
|
||||||
{ className: "input-group-btn" },
|
{ className: "input-group-btn" },
|
||||||
|
@ -1197,20 +1211,7 @@ var UserLogin = React.createClass({
|
||||||
type: "submit",
|
type: "submit",
|
||||||
className: "btn btn-primary",
|
className: "btn btn-primary",
|
||||||
id: "btn-chat",
|
id: "btn-chat",
|
||||||
value: "Login" })
|
value: "Assume ID" })
|
||||||
)
|
|
||||||
),
|
|
||||||
React.createElement(
|
|
||||||
"div",
|
|
||||||
{ className: "signin" },
|
|
||||||
React.createElement(
|
|
||||||
"p",
|
|
||||||
{ className: "text-center" },
|
|
||||||
React.createElement(
|
|
||||||
"small",
|
|
||||||
null,
|
|
||||||
"Just a temporary measure until genuine authentication is implemented"
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
@ -1265,14 +1266,7 @@ var UserMenu = React.createClass({
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
users,
|
users
|
||||||
React.createElement(
|
|
||||||
"li",
|
|
||||||
null,
|
|
||||||
React.createElement("br", null),
|
|
||||||
React.createElement(UserLogin, null),
|
|
||||||
React.createElement("br", null)
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -1299,6 +1293,7 @@ var AdminPanel = React.createClass({
|
||||||
null,
|
null,
|
||||||
"Admin"
|
"Admin"
|
||||||
),
|
),
|
||||||
|
React.createElement(UserLogin, null),
|
||||||
React.createElement(
|
React.createElement(
|
||||||
"button",
|
"button",
|
||||||
{
|
{
|
||||||
|
@ -1390,17 +1385,6 @@ var CurrentUser = React.createClass({
|
||||||
{ href: "#", "data-toggle": "modal", "data-target": "#designmodal" },
|
{ href: "#", "data-toggle": "modal", "data-target": "#designmodal" },
|
||||||
"Design Goals"
|
"Design Goals"
|
||||||
)
|
)
|
||||||
),
|
|
||||||
React.createElement("li", { className: "divider" }),
|
|
||||||
React.createElement(
|
|
||||||
"li",
|
|
||||||
null,
|
|
||||||
React.createElement(
|
|
||||||
"a",
|
|
||||||
{ href: "login.html" },
|
|
||||||
React.createElement("i", { className: "fa fa-sign-out fa-fw" }),
|
|
||||||
" Logout"
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
$(function () {
|
|
||||||
initialiseComponents();
|
|
||||||
});
|
|
|
@ -11,7 +11,8 @@ describe("ENSL Client", function () {
|
||||||
describe (".decodeSession", function () {
|
describe (".decodeSession", function () {
|
||||||
it ("decodes an ENSL session", function () {
|
it ("decodes an ENSL session", function () {
|
||||||
var output = EnslClient.decodeSession(sessionString);
|
var output = EnslClient.decodeSession(sessionString);
|
||||||
assert.isDefined(output.parsed);
|
assert.isNotNull(output);
|
||||||
|
assert.isDefined(output.session_id);
|
||||||
});
|
});
|
||||||
it ("returns null if invalid cookie format", function () {
|
it ("returns null if invalid cookie format", function () {
|
||||||
assert.isNull(EnslClient.decodeSession("foo"));
|
assert.isNull(EnslClient.decodeSession("foo"));
|
||||||
|
|
|
@ -21,7 +21,8 @@ var EnslClient = helpers.EnslClient = require(path.join(__dirname, "../../lib/en
|
||||||
// Mongo & Associated Models
|
// Mongo & Associated Models
|
||||||
var db = require(path.join(__dirname, "../../db/index"));
|
var db = require(path.join(__dirname, "../../db/index"));
|
||||||
var mongoose = require("mongoose");
|
var mongoose = require("mongoose");
|
||||||
var Message = helpers.Message = mongoose.model('message');
|
var Message = helpers.Message = mongoose.model("Message");
|
||||||
|
var Session = helpers.Session = mongoose.model("Session");
|
||||||
|
|
||||||
var async = require("async");
|
var async = require("async");
|
||||||
helpers.clearDb = function (callback) {
|
helpers.clearDb = function (callback) {
|
||||||
|
@ -50,7 +51,7 @@ var createUser = helpers.createUser = (function () {
|
||||||
nickname: "SteamUser" + counter
|
nickname: "SteamUser" + counter
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if (o && typeof o === 'object') {
|
if (o && typeof o === "object") {
|
||||||
defaultUser = extend(defaultUser, o);
|
defaultUser = extend(defaultUser, o);
|
||||||
}
|
}
|
||||||
return new User(defaultUser);
|
return new User(defaultUser);
|
||||||
|
|
|
@ -5,10 +5,10 @@ var request = require("supertest");
|
||||||
var app = helper.app;
|
var app = helper.app;
|
||||||
|
|
||||||
describe("Basic Spec", function () {
|
describe("Basic Spec", function () {
|
||||||
it ("returns 200", function (done) {
|
it ("redirects if user is not authenticated", function (done) {
|
||||||
request(app)
|
request(app)
|
||||||
.get("/")
|
.get("/")
|
||||||
.expect(200)
|
.expect(302)
|
||||||
.end(done);
|
.end(done);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
23
spec/session.js
Normal file
23
spec/session.js
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var helper = require("./helpers/index.js");
|
||||||
|
var Session = helper.Session;
|
||||||
|
var assert = require("chai").assert;
|
||||||
|
var async = require("async");
|
||||||
|
|
||||||
|
describe("Session model", function () {
|
||||||
|
describe(".create", function () {
|
||||||
|
var session;
|
||||||
|
beforeEach(function () {
|
||||||
|
session = { userId: Math.floor(Math.random() * 10000) };
|
||||||
|
});
|
||||||
|
it ("creates a new session", function (done) {
|
||||||
|
Session.create(session, function (error, result) {
|
||||||
|
if (error) return done(error);
|
||||||
|
assert.equal(result.userId, session.userId);
|
||||||
|
assert.isString(result.key);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
10
views/500.hbs
Normal file
10
views/500.hbs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<div id="page-wrapper" style="min-height: 750px;">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-12">
|
||||||
|
<h1 class="page-header">Something went wrong )-:</h1>
|
||||||
|
<p>Find an ENSL admin and get them to fix it!</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -1,12 +1,41 @@
|
||||||
<div id="page-wrapper" style="min-height: 750px;">
|
<div id="wrapper">
|
||||||
<div class="container-fluid">
|
{{>menu}}
|
||||||
<div class="row">
|
<div id="page-wrapper" style="min-height: 750px;">
|
||||||
<div class="col-lg-3 col-md-6" id="gatherCounter">
|
<div class="container-fluid">
|
||||||
|
<div class="row" id="authenticating">
|
||||||
|
<div class="col-lg-6 col-lg-offset-3">
|
||||||
|
<div class="jumbotron jumbo-auth text-center">
|
||||||
|
<div>
|
||||||
|
<img src="/images/ensl_logo.png" class="jumbo-img" alt="ENSL Logo" />
|
||||||
|
</div>
|
||||||
|
<br />
|
||||||
|
<h3>Authenticating your ENSL account</h3>
|
||||||
|
<br />
|
||||||
|
<div>
|
||||||
|
<img src="/images/spinner.svg" class="spinner" alt="Loading" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row" id="auth-required" style="display:none;">
|
||||||
|
<div class="col-lg-6 col-lg-offset-3">
|
||||||
|
<div class="jumbotron jumbo-auth text-center">
|
||||||
|
<div>
|
||||||
|
<img src="/images/ensl_logo.png" alt="ENSL Logo" />
|
||||||
|
</div>
|
||||||
|
<h3>You need to be logged to the ENSL website to access gathers</h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-3 col-md-6" id="gatherCounter">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-6" id="gathers"></div>
|
||||||
|
<div class="col-lg-6" id="chatroom"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-lg-6" id="gathers"></div>
|
|
||||||
<div class="col-lg-6" id="chatroom"></div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{{>foot}}
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
<html>
|
<html>
|
||||||
{{>head}}
|
{{>head}}
|
||||||
<body>
|
<body>
|
||||||
<div id="wrapper">
|
{{{ body }}}
|
||||||
{{>menu}}
|
|
||||||
{{{ body }}}
|
|
||||||
</div>
|
|
||||||
{{>foot}}
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
|
@ -1,2 +1,4 @@
|
||||||
<script src="/js/app.js"></script>
|
<script src="/js/app.js"></script>
|
||||||
<script src="/js/client.js"></script>
|
<script>
|
||||||
|
$(function () { initialiseComponents(); });
|
||||||
|
</script>
|
|
@ -6,7 +6,6 @@
|
||||||
<h4 class="modal-title">Design Goals</h4>
|
<h4 class="modal-title">Design Goals</h4>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<p>This app is made to promote 3 things</p>
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>Create a nice place where the NS2 community can assemble and have fun</li>
|
<li>Create a nice place where the NS2 community can assemble and have fun</li>
|
||||||
<li>Create an efficient, easy-to-use and flexible system to create NS2 gathers</li>
|
<li>Create an efficient, easy-to-use and flexible system to create NS2 gathers</li>
|
||||||
|
|
14
views/redirect.hbs
Normal file
14
views/redirect.hbs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-6 col-lg-offset-3">
|
||||||
|
<div class="jumbotron text-center">
|
||||||
|
<div>
|
||||||
|
<img src="/images/ensl_logo.png" alt="ENSL Logo" />
|
||||||
|
</div>
|
||||||
|
<h2>You need to be logged to the ENSL website to access gathers</h2>
|
||||||
|
<br />
|
||||||
|
<p><a class="btn btn-primary btn-lg" href="{{ redirect }}" role="button">Go to website</a></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
Loading…
Reference in a new issue