Browse Source

A ton of work on refactoring the code to be more modular and use routes.

pull/6/head
jrtechs 5 years ago
parent
commit
ead85a4f7a
16 changed files with 358 additions and 177 deletions
  1. +13
    -0
      configManager.js
  2. +1
    -1
      html/home.html
  3. +1
    -1
      html/login.html
  4. +6
    -6
      html/users.html
  5. +1
    -1
      html/videos.html
  6. +17
    -2
      routes/users/addUser.js
  7. +16
    -2
      routes/users/edituser.js
  8. +24
    -0
      routes/users/index.js
  9. +14
    -3
      routes/users/login.js
  10. +4
    -3
      routes/users/logout.js
  11. +12
    -1
      routes/users/removeuser.js
  12. +14
    -2
      routes/users/revokeAPI.js
  13. +14
    -2
      routes/users/updateUser.js
  14. +112
    -112
      server.js
  15. +50
    -41
      user.js
  16. +59
    -0
      utils.js

+ 13
- 0
configManager.js View File

@ -0,0 +1,13 @@
module.exports =
{
getConfiguration: function()
{
},
syncToDisk: function()
{
}
};

+ 1
- 1
html/home.html View File

@ -7,7 +7,7 @@
<div class="card-body">
<p>Welcome {username}.</p>
<br>
<form action="/logout" method ="post" class="p-2">
<form action="/user/logout" method ="post" class="p-2">
<div class="text-center">
<button class="btn btn-lg btn-secondary">LogOut</button>
</div>

+ 1
- 1
html/login.html View File

@ -4,7 +4,7 @@
<h2>Login</h2>
</div>
<div class="card-body">
<form action="/login" method ="post" class="p-2">
<form action="/user/login" method ="post" class="p-2">
<div class="form-group">
<label for="username">User Name</label>
<input class="form-control" type="text" id="username" name="username" placeholder="Enter username" required>

+ 6
- 6
html/users.html View File

@ -17,7 +17,7 @@
<h3 class="text-center">Edit User</h3>
</div>
<div class="card-body">
<form action="/edituser" method ="post" class="p-2">
<form action="/user/edituser" method ="post" class="p-2">
<div class="form-group">
<input class="form-control" id="useridLabel" type="text" name="id" required>
<label>User ID</label>
@ -56,7 +56,7 @@
<h4>Current API Key</h4>
<p id="apiDisplay"></p>
<form action="/revokeAPI" method ="post" class="p-2">
<form action="/user/revokeAPI" method ="post" class="p-2">
<input class="form-control" id="revokeAPIUsername" type="text" name="username" value="" hidden>
<div class="text-center">
<input type="submit" name="revoke_api" value="Generate New API Key"
@ -98,7 +98,7 @@
<button onclick="editHostForm({user.id}, '{user.username}', '{user.api}')" class="btn btn-secondary">Edit User</button>
</td>
<td>
<form action="/removeuser" method ="post" >
<form action="/user/removeuser" method ="post" >
<input type="submit" name="submit" value="Delete" class="btn btn-secondary"/>
<input type='hidden' name='id' value='{user.id}' />
</form>
@ -118,7 +118,7 @@
<h3 class="text-center">Add New User</h3>
</div>
<div class="card-body">
<form action="/addUser" method ="post" class="p-2">
<form action="/user/addUser" method ="post" class="p-2">
<div class="form-group">
<label> User Name
<input class="form-control w-100" type="text" name="username" required>
@ -153,7 +153,7 @@
<h3 class="text-center">Update Profile</h3>
</div>
<div class="card-body">
<form action="/updateUser" method ="post" class="p-2">
<form action="/user/updateUser" method ="post" class="p-2">
<div class="form-group">
<input class="form-control" id="usernameLabel" type="text" name="username" value="{username}" required>
<label>User Name</label>
@ -181,7 +181,7 @@
<h4>Current API Key</h4>
<p>{apiKey}</p>
<form action="/revokeAPI" method ="post" class="p-2">
<form action="/user/revokeAPI" method ="post" class="p-2">
<div class="text-center">
<input type="submit" name="revoke_api" value="Generate New API Key"
class="btn btn-lg btn-secondary"/>

+ 1
- 1
html/videos.html View File

@ -1,4 +1,4 @@
<h1 class="text-center">Videos</h1>
<script src="../server.js"></script><h1 class="text-center">Videos</h1>
<input id="videoFilter" class="form-control mr-sm-2" type="search" placeholder="Search" aria-label="Search">
<table class="table table-striped">

+ 17
- 2
routes/users/addUser.js View File

@ -1,10 +1,25 @@
const routes = require('express').Router();
const utils = require("../../utils");
const userUtils = require("../../user");
routes.get('/', (request, result) =>
routes.post('/', (request, result) =>
{
if(utils.checkPrivilege(request) === utils.PRIVILEGE.ADMIN)
{
console.log(request.body);
var admin = false;
if(request.body.admin === 'on')
admin = true;
userUtils.addUser(request.body.username, request.body.password,admin);
result.redirect('/users');
}
else
{
result.status(401);
result.send('None shall pass');
}
});
module.exports = routes;

+ 16
- 2
routes/users/edituser.js View File

@ -1,10 +1,24 @@
const routes = require('express').Router();
const utils = require("../../utils");
const userUtils = require("../../user");
routes.get('/', (request, result) =>
routes.post('/', (request, result) =>
{
if(utils.checkPrivilege(request) === utils.PRIVILEGE.ADMIN)
{
var admin = false;
if(request.body.admin === 'on')
admin = true;
userUtils.editUser(request.body.id, request.body.username, request.body.password,admin);
result.redirect('/users');
}
else
{
result.status(401);
result.send('None shall pass');
}
});
module.exports = routes;

+ 24
- 0
routes/users/index.js View File

@ -2,6 +2,30 @@ const routes = require('express').Router();
const utils = require("../../utils");
const addUser = require('./addUser');
routes.get('/addUser', addUser);
const editUser = require('./edituser');
routes.get('/edituser', editUser);
const login = require('./login');
routes.get('/login', login);
const logout = require('./logout');
routes.get('/logout', logout);
const removeuser = require('./removeuser');
routes.get('/removeuser', removeuser);
const revokeAPI = require('./revokeAPI');
routes.get('/revokeAPI', revokeAPI);
const updateUser = require('./updateUser');
routes.get('/updateUser', updateUser);
routes.get('/', (request, result) =>
{
utils.renderHTML(request, result, "users.html", getUserInformation);

+ 14
- 3
routes/users/login.js View File

@ -1,10 +1,21 @@
const routes = require('express').Router();
const userUtils = require("../../user");
routes.get('/', (request, result) =>
routes.post('/', (request, result) =>
{
if(userUtils.checkLogin(request.body.username, request.body.password))
{
request.session.login = true;
request.session.username = request.body.username;
request.session.userID = userUtils.getID(request.body.username);
request.session.API = userUtils.getAPIKEY(request.body.username);
if(userUtils.isAdmin(request.body.username))
{
request.session.admin = true;
}
}
result.redirect('/');
});
module.exports = routes;

+ 4
- 3
routes/users/logout.js View File

@ -1,10 +1,11 @@
const routes = require('express').Router();
routes.get('/', (request, result) =>
routes.post('/', (request, result) =>
{
request.session.login = false;
request.session.admin = false;
result.redirect('/');
});
module.exports = routes;

+ 12
- 1
routes/users/removeuser.js View File

@ -1,10 +1,21 @@
const routes = require('express').Router();
const utils = require("../../utils");
const userUtils = require("../../user");
routes.get('/', (request, result) =>
{
if(utils.checkPrivilege(request) === utils.PRIVILEGE.ADMIN)
{
userUtils.removeUser(request.body.id);
result.redirect('/users');
}
else
{
result.status(401);
result.send('None shall pass');
}
});
module.exports = routes;

+ 14
- 2
routes/users/revokeAPI.js View File

@ -1,10 +1,22 @@
const routes = require('express').Router();
const utils = require("../../utils");
const userUtils = require("../../user");
routes.get('/', (request, result) =>
routes.post('/', (request, result) =>
{
if(utils.checkPrivilege(request) === utils.PRIVILEGE.ADMIN)
{
userUtils.revokeAPI(request.body.username, config);
request.session.API = userUtils.getAPIKEY(request.session.username);
}
else if (checkPrivilege(request) === PRIVILEGE.MEMBER)
{
userUtils.revokeAPI(request.session.username);
request.session.API = userUtils.getAPIKEY(request.session.username);
}
result.redirect('/users');
});
module.exports = routes;

+ 14
- 2
routes/users/updateUser.js View File

@ -1,10 +1,22 @@
const routes = require('express').Router();
const utils = require("../../utils");
const userUtils = require("../../user");
routes.get('/', (request, result) =>
routes.post('/', (request, result) =>
{
if(utils.checkPrivilege(request) >= utils.PRIVILEGE.MEMBER)
{
var admin = false;
userUtils.editUser(request.session.userID, request.body.username, request.body.password,admin);
result.redirect('/users');
}
else
{
result.status(401);
result.send('None shall pass');
}
});
module.exports = routes;

+ 112
- 112
server.js View File

@ -244,129 +244,129 @@ app.get('/video/', function(request, result)
});
app.post('/revokeAPI', function(request, result)
{
if(checkPrivilege(request) === PRIVILEGE.ADMIN)
{
userUtils.revokeAPI(request.body.username, config);
request.session.API = userUtils.getAPIKEY(request.session.username, config);
fileIO.writeJSONToFile(CONFIG_FILE_NAME, config);
}
else if (checkPrivilege(request) === PRIVILEGE.MEMBER)
{
userUtils.revokeAPI(request.session.username, config);
request.session.API = userUtils.getAPIKEY(request.session.username, config);
fileIO.writeJSONToFile(CONFIG_FILE_NAME, config);
}
result.redirect('/users');
});
// app.post('/revokeAPI', function(request, result)
// {
// if(checkPrivilege(request) === PRIVILEGE.ADMIN)
// {
// userUtils.revokeAPI(request.body.username, config);
// request.session.API = userUtils.getAPIKEY(request.session.username, config);
// fileIO.writeJSONToFile(CONFIG_FILE_NAME, config);
// }
// else if (checkPrivilege(request) === PRIVILEGE.MEMBER)
// {
// userUtils.revokeAPI(request.session.username, config);
// request.session.API = userUtils.getAPIKEY(request.session.username, config);
// fileIO.writeJSONToFile(CONFIG_FILE_NAME, config);
// }
// result.redirect('/users');
// });
app.post('/addUser', function(request, result)
{
if(checkPrivilege(request) === PRIVILEGE.ADMIN)
{
console.log(request.body);
var admin = false;
if(request.body.admin === 'on')
admin = true;
userUtils.addUser(request.body.username, request.body.password,admin, config);
fileIO.writeJSONToFile(CONFIG_FILE_NAME, config);
result.redirect('/users');
}
else
{
result.status(401);
result.send('None shall pass');
}
});
// app.post('/addUser', function(request, result)
// {
// if(checkPrivilege(request) === PRIVILEGE.ADMIN)
// {
// console.log(request.body);
// var admin = false;
// if(request.body.admin === 'on')
// admin = true;
// userUtils.addUser(request.body.username, request.body.password,admin, config);
// fileIO.writeJSONToFile(CONFIG_FILE_NAME, config);
// result.redirect('/users');
// }
// else
// {
// result.status(401);
// result.send('None shall pass');
// }
// });
app.post('/edituser', function(request, result)
{
if(checkPrivilege(request) === PRIVILEGE.ADMIN)
{
var admin = false;
if(request.body.admin === 'on')
admin = true;
userUtils.editUser(request.body.id, request.body.username, request.body.password,admin, config);
fileIO.writeJSONToFile(CONFIG_FILE_NAME, config);
result.redirect('/users');
}
else
{
result.status(401);
result.send('None shall pass');
}
});
// app.post('/edituser', function(request, result)
// {
// if(checkPrivilege(request) === PRIVILEGE.ADMIN)
// {
// var admin = false;
// if(request.body.admin === 'on')
// admin = true;
// userUtils.editUser(request.body.id, request.body.username, request.body.password,admin, config);
// fileIO.writeJSONToFile(CONFIG_FILE_NAME, config);
// result.redirect('/users');
// }
// else
// {
// result.status(401);
// result.send('None shall pass');
// }
// });
app.post('/updateUser', function(request, result)
{
if(checkPrivilege(request) >= PRIVILEGE.MEMBER)
{
console.log(request.session.userID);
var admin = false;
userUtils.editUser(request.session.userID, request.body.username, request.body.password,admin, config);
fileIO.writeJSONToFile(CONFIG_FILE_NAME, config);
result.redirect('/users');
}
else
{
result.status(401);
result.send('None shall pass');
}
});
// app.post('/updateUser', function(request, result)
// {
// if(checkPrivilege(request) >= PRIVILEGE.MEMBER)
// {
// console.log(request.session.userID);
// var admin = false;
// userUtils.editUser(request.session.userID, request.body.username, request.body.password,admin, config);
// fileIO.writeJSONToFile(CONFIG_FILE_NAME, config);
// result.redirect('/users');
// }
// else
// {
// result.status(401);
// result.send('None shall pass');
// }
// });
const PRIVILEGE = {NOBODY: 0, MEMBER: 1, ADMIN: 2};
const checkPrivilege = function(request)
{
if(request.session.login !== true)
return PRIVILEGE.NOBODY;
else if(request.session.admin === true)
return PRIVILEGE.ADMIN;
return PRIVILEGE.MEMBER;
};
app.post('/removeuser', function(request, result)
{
if(checkPrivilege(request) === PRIVILEGE.ADMIN)
{
userUtils.removeUser(request.body.id, config);
fileIO.writeJSONToFile(CONFIG_FILE_NAME, config);
result.redirect('/users');
}
else
{
result.status(401);
result.send('None shall pass');
}
});
// const PRIVILEGE = {NOBODY: 0, MEMBER: 1, ADMIN: 2};
// const checkPrivilege = function(request)
// {
// if(request.session.login !== true)
// return PRIVILEGE.NOBODY;
// else if(request.session.admin === true)
// return PRIVILEGE.ADMIN;
// return PRIVILEGE.MEMBER;
// };
// app.post('/removeuser', function(request, result)
// {
// if(checkPrivilege(request) === PRIVILEGE.ADMIN)
// {
// userUtils.removeUser(request.body.id, config);
// fileIO.writeJSONToFile(CONFIG_FILE_NAME, config);
// result.redirect('/users');
// }
// else
// {
// result.status(401);
// result.send('None shall pass');
// }
// });
app.post('/logout', function(request, result)
{
request.session.login = false;
request.session.admin = false;
result.redirect('/');
});
// app.post('/logout', function(request, result)
// {
// request.session.login = false;
// request.session.admin = false;
// result.redirect('/');
// });
app.post('/login', function(request, result)
{
if(userUtils.checkLogin(request.body.username, request.body.password, config))
{
request.session.login = true;
request.session.username = request.body.username;
request.session.userID = userUtils.getID(request.body.username, config);
request.session.API = userUtils.getAPIKEY(request.body.username, config);
if(userUtils.isAdmin(request.body.username, config))
{
request.session.admin = true;
}
}
result.redirect('/');
});
// app.post('/login', function(request, result)
// {
// if(userUtils.checkLogin(request.body.username, request.body.password, config))
// {
// request.session.login = true;
// request.session.username = request.body.username;
// request.session.userID = userUtils.getID(request.body.username, config);
// request.session.API = userUtils.getAPIKEY(request.body.username, config);
// if(userUtils.isAdmin(request.body.username, config))
// {
// request.session.admin = true;
// }
// }
// result.redirect('/');
// });
app.listen(config.port, () => console.log(`App listening on port ${config.port}!`));

+ 50
- 41
user.js View File

@ -1,6 +1,12 @@
/** Crypto package used for hashing */
const crypto = require('crypto');
const configManager = require("./configManager");
var users = configManager.getConfiguration().users;
/**
* Helper function to generate a hashed password
* from a given plain text password.
@ -52,13 +58,13 @@ const hashPassword = function(password, salt)
* Fetches the index of the user in the configuration. If the
* user does not exists a -1 is returned.
*/
const getIndexOfUser = function(username, configuration)
const getIndexOfUser = function(username)
{
for(var i = 0; i < configuration.users.length; i++)
for(var i = 0; i < users.length; i++)
{
if (username === configuration.users[i].username)
if (username === users[i].username)
{
if(username === configuration.users[i].username)
if(username === users[i].username)
{
return i;
}
@ -71,11 +77,11 @@ const getIndexOfUser = function(username, configuration)
module.exports =
{
isValidAPI: function(apiKey, configuration)
isValidAPI: function(apiKey)
{
for(var i = 0; i < configuration.users.length; i++)
for(var i = 0; i < users.length; i++)
{
if(configuration.users[i].api === apiKey)
if(users[i].api === apiKey)
{
return true;
}
@ -83,41 +89,42 @@ module.exports =
return false;
},
isAdmin: function(username, configuration)
isAdmin: function(username)
{
var index = getIndexOfUser(username, configuration);
var index = getIndexOfUser(username);
if(index !== -1)
{
return configuration.users[index].admin;
return users[index].admin;
}
return false;
},
getID: function(username, configuration)
getID: function(username)
{
var index = getIndexOfUser(username, configuration);
return configuration.users[index].id;
var index = getIndexOfUser(username);
return users[index].id;
},
revokeAPI: function(username, configuration)
revokeAPI: function(username)
{
var index = getIndexOfUser(username, configuration);
var index = getIndexOfUser(username);
if(index !== -1)
{
configuration.users[index].api = generateRandomAPIKey();
users[index].api = generateRandomAPIKey();
}
configManager.syncToDisk();
},
getAPIKEY: function(username, configuration)
getAPIKEY: function(username)
{
var index = getIndexOfUser(username, configuration);
var index = getIndexOfUser(username);
if(index !== -1)
return configuration.users[index].api;
return users[index].api;
return 0;
},
@ -126,17 +133,16 @@ module.exports =
*
* @param username
* @param password
* @param configuration
* @returns {boolean}
*/
checkLogin: function(username, password, configuration)
checkLogin: function(username, password)
{
const userIndex = getIndexOfUser(username, configuration);
const userIndex = getIndexOfUser(username);
if(userIndex === -1)
return false;
const hashedPassword = hashPassword(password, configuration.users[userIndex].salt);
return configuration.users[userIndex].password == hashedPassword;
const hashedPassword = hashPassword(password, users[userIndex].salt);
return users[userIndex].password == hashedPassword;
},
@ -145,28 +151,29 @@ module.exports =
*
* @param username
* @param password
* @param configuration
* @returns {boolean}
*/
addUser: function(username, password, admin, configuration)
addUser: function(username, password, admin)
{
const userIndex = getIndexOfUser(username, configuration);
const userIndex = getIndexOfUser(username);
if(userIndex !== -1)
return false; // user already exists
var newUser = new Object();
newUser.username = username;
newUser.api = generateRandomAPIKey();
if(configuration.users.length === 0)
if(users.length === 0)
newUser.id = 1;
else
newUser.id = configuration.users[configuration.users.length -1].id + 1;
newUser.id = users[users.length -1].id + 1;
const passObject = createHashedPasswordObject(password);
newUser.salt = passObject.salt;
newUser.password = passObject.pass;
newUser.admin = admin;
configuration.users.push(newUser);
users.push(newUser);
configManager.syncToDisk();
return true;
},
@ -177,36 +184,38 @@ module.exports =
* @param id
* @param userName
* @param password
* @param configuration
*/
editUser: function(id, userName, password, admin, configuration)
editUser: function(id, userName, password, admin)
{
for(var i = 0; i < configuration.users.length; i++)
for(var i = 0; i < users.length; i++)
{
if (configuration.users[i].id=== id)
if (users[i].id=== id)
{
console.log("User account updated.");
configuration.users[i].username = userName;
configuration.users[i].admin = admin;
users[i].username = userName;
users[i].admin = admin;
var passObj = createHashedPasswordObject(password);
configuration.users[i].salt = passObj.salt;
configuration.users[i].password = passObj.pass;
users[i].salt = passObj.salt;
users[i].password = passObj.pass;
}
}
configManager.syncToDisk();
},
/**
* Removes a user account from the configuration
* @param id
* @param configuration
*/
removeUser: function(id, configuration)
removeUser: function(id)
{
configuration.users = configuration.users.filter(function(value, index, arr)
users = users.filter(function(value, index, arr)
{
return value.id + "" !== id
});
configManager.syncToDisk();
}
};

+ 59
- 0
utils.js View File

@ -0,0 +1,59 @@
function fetchInTemplate(templateContext, templateKey, filename)
{
templateContext[templateKey] = fileIO.getFile(filename);
}
const PRIVILEGE = {NOBODY: 0, MEMBER: 1, ADMIN: 2};
/** Template engine */
const whiskers = require('whiskers');
module.exports =
{
renderHTML: function(request, result, templateFile, templateDependencyFunction)
{
var templateContext = Object();
var prom = [];
prom.push(fileIO.getFile("./html/mainTemplate.html"));
prom.push(fetchInTemplate(templateContext, "header", "./html/header.html"));
prom.push(fetchInTemplate(templateContext, "footer", "./html/footer.html"));
if(checkPrivilege(request) >= PRIVILEGE.MEMBER)
{
templateContext.loggedIn = true;
if(checkPrivilege(request) === PRIVILEGE.ADMIN)
templateContext.admin = true;
if(templateDependencyFunction !== null)
prom.push(templateDependencyFunction(templateContext, request));
prom.push(fetchInTemplate(templateContext, "main","./html/" + templateFile));
}
else
{
prom.push(fetchInTemplate(templateContext, "login","./html/login.html"));
}
Promise.all(prom).then(function(content)
{
result.write(whiskers.render(content[0], templateContext));
result.end();
});
},
PRIVILEGE:
{
NOBODY: 0,
MEMBER: 1,
ADMIN: 2
},
checkPrivilege: function(request)
{
if(request.session.login !== true)
return module.exports.PRIVILEGE.NOBODY;
else if(request.session.admin === true)
return module.exports.PRIVILEGE.ADMIN;
return module.exports.RIVILEGE.MEMBER;
}
};

Loading…
Cancel
Save