From 64b0def088e26364fd0a4ab3a5711693f9abc020 Mon Sep 17 00:00:00 2001 From: William Mantly Date: Wed, 14 Feb 2018 03:15:19 -0500 Subject: [PATCH] more --- middleware/auth.js | 2 +- models/hosts.js | 46 +++++++++++++++++++++++++++++ models/users.js | 49 ++++++++++++++++++++++--------- redis.js | 2 ++ routes/auth.js | 41 +++++++++++++++----------- routes/routes.js | 72 ++++++++++++++++++++++++---------------------- routes/users.js | 15 +++++++++- 7 files changed, 159 insertions(+), 68 deletions(-) create mode 100644 models/hosts.js diff --git a/middleware/auth.js b/middleware/auth.js index 77038fc..8076a9d 100644 --- a/middleware/auth.js +++ b/middleware/auth.js @@ -3,7 +3,7 @@ const Users = require('../models/users'); async function auth(req, res, next){ if(req.header('auth-token')){ let user = await Users.checkToken({token: req.header('auth-token')}); - if(user){ + if(user.username){ req.user = user; return next(); } diff --git a/models/hosts.js b/models/hosts.js new file mode 100644 index 0000000..751925e --- /dev/null +++ b/models/hosts.js @@ -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}; diff --git a/models/users.js b/models/users.js index 2dacdb0..1fe6a37 100644 --- a/models/users.js +++ b/models/users.js @@ -1,10 +1,20 @@ +'use strict'; + const {promisify} = require('util'); +const client = require('../redis'); const linuxUser = require('linux-user'); 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 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 */ @@ -19,14 +29,14 @@ async function makeInviteToken(data){ return token; } -async function checkInviteToken(data){ +async function checkInvite(data){ let token = await client.HGET('users_tokens', data.token); return JSON.parse(token); } -async function useInviteToken(data){ - let invite = await checkInviteToken(data); +async function consumeInvite(data){ + let invite = await checkInvite(data); invite.invited = data.username; @@ -38,14 +48,10 @@ async function useInviteToken(data){ */ async function login(data){ - const authenticate = promisify(pam.authenticate); - const getUserGroups = promisify(linuxUser.getUserGroups); - try{ await authenticate(data.username, data.password); - let groups = await getUserGroups(data.username); - console.log('groups', groups) - return true; + + return await getUserGroups(data.username); }catch(error){ return false; } @@ -61,7 +67,20 @@ async function addToken(data){ async function checkToken(data){ 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) { - const addUser = promisify(linuxUser.addUser); - const setPassword = promisify(linuxUser.setPassword); let systemUser = await addUser(data.username); let systemUserPassword = await setPassword(data.username, data.password); } +async function verifyKey(data){ + return await verifySSHKey(key) +} + async function ifUserExists(data){ const getUserInfo = promisify(linuxUser.getUserInfo); return await getUserInfo(data.username); } module.exports = {login, add, addToken, checkToken, ifUserExists, - makeInviteToken, checkInviteToken, useInviteToken}; + makeInviteToken, checkInvite, consumeInvite, addSSHkey, verifyKey}; diff --git a/redis.js b/redis.js index 5f02fdb..4ea88c1 100644 --- a/redis.js +++ b/redis.js @@ -16,4 +16,6 @@ module.exports = { HGET: promisify(_client.HGET).bind(_client), SADD: promisify(_client.SADD).bind(_client), HSET: promisify(_client.HSET).bind(_client), + HGETALL: promisify(_client.HGETALL).bind(_client), + SMEMBERS: promisify(_client.SMEMBERS).bind(_client), }; diff --git a/routes/auth.js b/routes/auth.js index a0aaa61..ed77ae3 100644 --- a/routes/auth.js +++ b/routes/auth.js @@ -1,16 +1,16 @@ 'use strict'; const router = require('express').Router(); -const linuxUser = require('linux-user'); -const {promisify} = require('util'); - const Users = require('../models/users'); +/* + Password login +*/ router.post('/login', async function(req, res){ let username = req.body.username; let password = req.body.password; - let groups = await Users.login({username, password}) + let groups = await Users.login({username, password}); if(groups){ 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){ let key = req.body.key; - const verifySSHKey = promisify(linuxUser.verifySSHKey); - - let isValid; try{ - isValid = await verifySSHKey(key); return res.json({ - info: isValid + info: await Users.verifyKey(key) }); }catch(error){ 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 password = req.body.password; let token = req.params.token; - let invite = await Users.checkInviteToken({token}); - - console.log('invite', invite) + // make sure invite token is valid + let invite = await Users.checkInvite({token}); if(!invite || invite.invited){ 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){ return res.status(400).json({ message: 'Missing fields' }); } + // make sure the requested user name can be used if(await Users.ifUserExists({username})){ - return res.json({ - message: 'username taken' + return res.status(409).json({ + message: 'Username taken' }); } + // create the new user 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}) + }); }); diff --git a/routes/routes.js b/routes/routes.js index 5c54b81..74649c4 100644 --- a/routes/routes.js +++ b/routes/routes.js @@ -1,23 +1,27 @@ -const client = require('../redis'); +'use strict'; + const router = require('express').Router(); -const app = require('../app'); + +const Host = require('../models/hosts'); router.get('/:host', async function(req, res){ - client.HGETALL('host_' + req.params.host, function (error, results) { - res.json({ - host: req.params.host, - results: results - }); + let host = req.params.host; + + let info = await Host.getInfo({host}); + + return res.status(info ? 200 : 404).json({ + host: req.params.host, + results: info }); }); router.get('/', async function(req, res){ - client.SMEMBERS('hosts', function(error, results){ - if(error){ - return res.status(500).json({message: `ERROR ${error}`}); - } - return res.json({hosts: results}); - }); + try{ + let hosts = await Host.listAll(); + return res.json({hosts: hosts}); + }catch(error){ + return res.status(500).json({message: `ERROR ${error}`}); + } }); router.post('/', async function(req, res){ @@ -28,47 +32,45 @@ router.post('/', async function(req, res){ return res.status(400).json({ message: `Missing fields: ${!host ? 'host' : ''} ${!ip ? 'ip' : ''}` }); - }else{ + } - try{ - await client.SADD('hosts', host); - await client.HSET('host_' + host, 'ip', ip); - await client.HSET('host_' + host, 'updated', (new Date).getTime()); - - } catch (error){ - return res.status(500).json({ - message: `ERROR: ${error}` - }); - } + try{ + Host.add({host, ip, username: req.user.username}); return res.json({ message: `Host ${host} Added` }); + } catch (error){ + + return res.status(500).json({ + message: `ERROR: ${error}` + }); } + }); router.delete('/', async function(req, res){ let host = req.body.host; + let count; if(!host){ return res.status(400).json({ message: `Missing fields: ${!host ? 'host' : ''}` }); - }else{ + } - try{ - await client.SREM('hosts', host); - await client.DEL('host_' + host); - }catch(error){ - return res.status(500).json({ - message: `ERROR: ${error}` - }); - } + try{ + count = await Host.remove({host}); - return res.json({ - message: `Host ${host} deleted` + }catch(error){ + return res.status(500).json({ + message: `ERROR: ${error}` }); } + + return res.json({ + message: `Host ${host} deleted`, + }); }); module.exports = router; diff --git a/routes/users.js b/routes/users.js index a549af6..9c1a408 100644 --- a/routes/users.js +++ b/routes/users.js @@ -5,9 +5,22 @@ const Users = require('../models/users'); router.post('/invite', async function(req, res){ let token = await Users.makeInviteToken({ 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;