This commit is contained in:
William Mantly 2018-02-14 03:15:19 -05:00
parent 5800a0603e
commit 64b0def088
Signed by: wmantly
GPG Key ID: E1EEC7650BA97160
7 changed files with 159 additions and 68 deletions

View File

@ -3,7 +3,7 @@ const Users = require('../models/users');
async function auth(req, res, next){ async function auth(req, res, next){
if(req.header('auth-token')){ if(req.header('auth-token')){
let user = await Users.checkToken({token: req.header('auth-token')}); let user = await Users.checkToken({token: req.header('auth-token')});
if(user){ if(user.username){
req.user = user; req.user = user;
return next(); return next();
} }

46
models/hosts.js Normal file
View File

@ -0,0 +1,46 @@
'use strict';
const {promisify} = require('util');
const client = require('../redis');
async function getInfo(data){
let info = await client.HGETALL('host_' + data.host);
return info
}
async function listAll(){
try{
let hosts = await client.SMEMBERS('hosts');
return hosts;
}catch(error){
return new Error(error);
}
}
async function add(data){
try{
await client.SADD('hosts', data.host);
await client.HSET('host_' + data.host, 'ip', data.ip);
await client.HSET('host_' + data.host, 'updated', (new Date).getTime());
await client.HSET('host_' + data.host, 'username', data.username);
} catch (error){
return new Error(error);
}
}
async function remove(data){
try{
await client.SREM('hosts', data.host);
let count = await client.DEL('host_' + data.host);
return count;
} catch(error) {
return new Error(error);
}
}
module.exports = {getInfo, listAll, add, remove};

View File

@ -1,10 +1,20 @@
'use strict';
const {promisify} = require('util'); const {promisify} = require('util');
const client = require('../redis');
const linuxUser = require('linux-user'); const linuxUser = require('linux-user');
const pam = require('authenticate-pam'); const pam = require('authenticate-pam');
const client = require('../redis');
const UUID = function b(a){return a?(a^Math.random()*16>>a/4).toString(16):([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,b)}; const UUID = function b(a){return a?(a^Math.random()*16>>a/4).toString(16):([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,b)};
const authenticate = promisify(pam.authenticate);
const addSSHtoUser = promisify(linuxUser.addSSHtoUser)
const getUserGroups = promisify(linuxUser.getUserGroups);
const verifySSHKey = promisify(linuxUser.verifySSHKey);
const addUser = promisify(linuxUser.addUser);
const setPassword = promisify(linuxUser.setPassword);
/* /*
Invite Invite
*/ */
@ -19,14 +29,14 @@ async function makeInviteToken(data){
return token; return token;
} }
async function checkInviteToken(data){ async function checkInvite(data){
let token = await client.HGET('users_tokens', data.token); let token = await client.HGET('users_tokens', data.token);
return JSON.parse(token); return JSON.parse(token);
} }
async function useInviteToken(data){ async function consumeInvite(data){
let invite = await checkInviteToken(data); let invite = await checkInvite(data);
invite.invited = data.username; invite.invited = data.username;
@ -38,14 +48,10 @@ async function useInviteToken(data){
*/ */
async function login(data){ async function login(data){
const authenticate = promisify(pam.authenticate);
const getUserGroups = promisify(linuxUser.getUserGroups);
try{ try{
await authenticate(data.username, data.password); await authenticate(data.username, data.password);
let groups = await getUserGroups(data.username);
console.log('groups', groups) return await getUserGroups(data.username);
return true;
}catch(error){ }catch(error){
return false; return false;
} }
@ -61,7 +67,20 @@ async function addToken(data){
async function checkToken(data){ async function checkToken(data){
let user = await client.HGET('users_tokens', data.token); let user = await client.HGET('users_tokens', data.token);
return user; return {
username: user,
groups: (user && await getUserGroups(user))
}
}
async function addSSHkey(data){
try{
let user = await addSSHtoUser(data.username, data.key);
return true;
} catch (error) {
return error;
}
} }
/* /*
@ -69,18 +88,20 @@ async function checkToken(data){
*/ */
async function add(data) { async function add(data) {
const addUser = promisify(linuxUser.addUser);
const setPassword = promisify(linuxUser.setPassword);
let systemUser = await addUser(data.username); let systemUser = await addUser(data.username);
let systemUserPassword = await setPassword(data.username, data.password); let systemUserPassword = await setPassword(data.username, data.password);
} }
async function verifyKey(data){
return await verifySSHKey(key)
}
async function ifUserExists(data){ async function ifUserExists(data){
const getUserInfo = promisify(linuxUser.getUserInfo); const getUserInfo = promisify(linuxUser.getUserInfo);
return await getUserInfo(data.username); return await getUserInfo(data.username);
} }
module.exports = {login, add, addToken, checkToken, ifUserExists, module.exports = {login, add, addToken, checkToken, ifUserExists,
makeInviteToken, checkInviteToken, useInviteToken}; makeInviteToken, checkInvite, consumeInvite, addSSHkey, verifyKey};

View File

@ -16,4 +16,6 @@ module.exports = {
HGET: promisify(_client.HGET).bind(_client), HGET: promisify(_client.HGET).bind(_client),
SADD: promisify(_client.SADD).bind(_client), SADD: promisify(_client.SADD).bind(_client),
HSET: promisify(_client.HSET).bind(_client), HSET: promisify(_client.HSET).bind(_client),
HGETALL: promisify(_client.HGETALL).bind(_client),
SMEMBERS: promisify(_client.SMEMBERS).bind(_client),
}; };

View File

@ -1,16 +1,16 @@
'use strict'; 'use strict';
const router = require('express').Router(); const router = require('express').Router();
const linuxUser = require('linux-user');
const {promisify} = require('util');
const Users = require('../models/users'); const Users = require('../models/users');
/*
Password login
*/
router.post('/login', async function(req, res){ router.post('/login', async function(req, res){
let username = req.body.username; let username = req.body.username;
let password = req.body.password; let password = req.body.password;
let groups = await Users.login({username, password}) let groups = await Users.login({username, password});
if(groups){ if(groups){
return res.json({ return res.json({
@ -26,16 +26,15 @@ router.post('/login', async function(req, res){
}); });
/*
verify public ssh key
*/
router.post('/verifykey', async function(req, res){ router.post('/verifykey', async function(req, res){
let key = req.body.key; let key = req.body.key;
const verifySSHKey = promisify(linuxUser.verifySSHKey);
let isValid;
try{ try{
isValid = await verifySSHKey(key);
return res.json({ return res.json({
info: isValid info: await Users.verifyKey(key)
}); });
}catch(error){ }catch(error){
return res.status(400).json({ return res.status(400).json({
@ -45,14 +44,14 @@ router.post('/verifykey', async function(req, res){
}); });
router.post('/:token', async function(req, res, next) {
router.post('/invite/:token', async function(req, res, next) {
let username = req.body.username; let username = req.body.username;
let password = req.body.password; let password = req.body.password;
let token = req.params.token; let token = req.params.token;
let invite = await Users.checkInviteToken({token}); // make sure invite token is valid
let invite = await Users.checkInvite({token});
console.log('invite', invite)
if(!invite || invite.invited){ if(!invite || invite.invited){
return res.status(401).json({ return res.status(401).json({
@ -60,23 +59,31 @@ router.post('/:token', async function(req, res, next) {
}); });
} }
// make sure requires fields are in
if(!username || !password){ if(!username || !password){
return res.status(400).json({ return res.status(400).json({
message: 'Missing fields' message: 'Missing fields'
}); });
} }
// make sure the requested user name can be used
if(await Users.ifUserExists({username})){ if(await Users.ifUserExists({username})){
return res.json({ return res.status(409).json({
message: 'username taken' message: 'Username taken'
}); });
} }
// create the new user
await Users.add({username, password, isAdmin: invite.isAdmin}); await Users.add({username, password, isAdmin: invite.isAdmin});
await Users.useInviteToken({token, username}); // consume the invite token
await Users.consumeInvite({token, username});
return res.json({user:username}); // send back API token for the new user
return res.json({
user: username,
token: await Users.addToken({username})
});
}); });

View File

@ -1,23 +1,27 @@
const client = require('../redis'); 'use strict';
const router = require('express').Router(); const router = require('express').Router();
const app = require('../app');
const Host = require('../models/hosts');
router.get('/:host', async function(req, res){ router.get('/:host', async function(req, res){
client.HGETALL('host_' + req.params.host, function (error, results) { let host = req.params.host;
res.json({
let info = await Host.getInfo({host});
return res.status(info ? 200 : 404).json({
host: req.params.host, host: req.params.host,
results: results results: info
});
}); });
}); });
router.get('/', async function(req, res){ router.get('/', async function(req, res){
client.SMEMBERS('hosts', function(error, results){ try{
if(error){ let hosts = await Host.listAll();
return res.json({hosts: hosts});
}catch(error){
return res.status(500).json({message: `ERROR ${error}`}); return res.status(500).json({message: `ERROR ${error}`});
} }
return res.json({hosts: results});
});
}); });
router.post('/', async function(req, res){ router.post('/', async function(req, res){
@ -28,37 +32,36 @@ router.post('/', async function(req, res){
return res.status(400).json({ return res.status(400).json({
message: `Missing fields: ${!host ? 'host' : ''} ${!ip ? 'ip' : ''}` message: `Missing fields: ${!host ? 'host' : ''} ${!ip ? 'ip' : ''}`
}); });
}else{ }
try{ try{
await client.SADD('hosts', host); Host.add({host, ip, username: req.user.username});
await client.HSET('host_' + host, 'ip', ip);
await client.HSET('host_' + host, 'updated', (new Date).getTime());
return res.json({
message: `Host ${host} Added`
});
} catch (error){ } catch (error){
return res.status(500).json({ return res.status(500).json({
message: `ERROR: ${error}` message: `ERROR: ${error}`
}); });
} }
return res.json({
message: `Host ${host} Added`
});
}
}); });
router.delete('/', async function(req, res){ router.delete('/', async function(req, res){
let host = req.body.host; let host = req.body.host;
let count;
if(!host){ if(!host){
return res.status(400).json({ return res.status(400).json({
message: `Missing fields: ${!host ? 'host' : ''}` message: `Missing fields: ${!host ? 'host' : ''}`
}); });
}else{ }
try{ try{
await client.SREM('hosts', host); count = await Host.remove({host});
await client.DEL('host_' + host);
}catch(error){ }catch(error){
return res.status(500).json({ return res.status(500).json({
message: `ERROR: ${error}` message: `ERROR: ${error}`
@ -66,9 +69,8 @@ router.delete('/', async function(req, res){
} }
return res.json({ return res.json({
message: `Host ${host} deleted` message: `Host ${host} deleted`,
}); });
}
}); });
module.exports = router; module.exports = router;

View File

@ -5,9 +5,22 @@ const Users = require('../models/users');
router.post('/invite', async function(req, res){ router.post('/invite', async function(req, res){
let token = await Users.makeInviteToken({ let token = await Users.makeInviteToken({
username: res.user username: res.user
});
return res.json({token:token});
});
router.post('/key', async function(req, res){
let added = await Users.addSSHkey({
username: req.user.username,
key: req.body.key
});
return res.status(added === true ? 200 : 400).json({
message: added
}); });
return res.json({token:token})
}); });
module.exports = router; module.exports = router;