From ab108ebec8f0b78b1c2810693c346b338ff2d4a1 Mon Sep 17 00:00:00 2001 From: William Mantly Date: Sun, 12 Apr 2020 19:19:36 -0400 Subject: [PATCH 1/3] user redis --- nodejs/middleware/auth.js | 2 +- nodejs/models/{auth.js => auth_pam.js} | 0 nodejs/models/auth_red.js | 55 +++ nodejs/models/auth_redis.js | 62 ++++ nodejs/models/host.js | 2 +- nodejs/models/{user.js => user_pam.js} | 0 nodejs/models/user_redis.js | 100 +++++ nodejs/routes/auth.js | 4 +- nodejs/routes/user.js | 6 +- nodejs/utils/redis_model.js | 17 +- package-lock.json | 491 +++++++++++++++++++++++++ 11 files changed, 728 insertions(+), 11 deletions(-) rename nodejs/models/{auth.js => auth_pam.js} (100%) mode change 100755 => 100644 create mode 100644 nodejs/models/auth_red.js create mode 100644 nodejs/models/auth_redis.js rename nodejs/models/{user.js => user_pam.js} (100%) mode change 100755 => 100644 create mode 100644 nodejs/models/user_redis.js create mode 100644 package-lock.json diff --git a/nodejs/middleware/auth.js b/nodejs/middleware/auth.js index 6b98731..777620b 100755 --- a/nodejs/middleware/auth.js +++ b/nodejs/middleware/auth.js @@ -1,6 +1,6 @@ 'use strict'; -const {Auth} = require('../models/auth'); +const {Auth} = require('../models/auth_redis'); async function auth(req, res, next){ try{ diff --git a/nodejs/models/auth.js b/nodejs/models/auth_pam.js old mode 100755 new mode 100644 similarity index 100% rename from nodejs/models/auth.js rename to nodejs/models/auth_pam.js diff --git a/nodejs/models/auth_red.js b/nodejs/models/auth_red.js new file mode 100644 index 0000000..4c1eb80 --- /dev/null +++ b/nodejs/models/auth_red.js @@ -0,0 +1,55 @@ +const {promisify} = require('util'); +const pam = require('authenticate-pam'); +const authenticate = promisify(pam.authenticate); + +const {User} = require('./user'); +const {Token, AuthToken} = require('./token'); + +Auth = {} +Auth.errors = {} + +Auth.errors.login = function(){ + let error = new Error('PamLoginFailed'); + error.name = 'PamLoginFailed'; + error.message = `Invalid Credentials, login failed.`; + error.status = 401; + + return error; +} + +Auth.login = async function(data){ + try{ + let auth = await authenticate(data.username, data.password); + let user = await User.get(data); + let token = await AuthToken.add(user); + + return {user, token} + }catch(error){ + if (error == 'Authentication failure'){ + throw this.errors.login() + } + throw error; + } +}; + +Auth.checkToken = async function(data){ + try{ + let token = await AuthToken.get(data); + if(token.is_valid){ + return await User.get(token.created_by); + } + }catch(error){ + throw this.errors.login(); + } +}; + +Auth.logOut = async function(data){ + try{ + let token = await AuthToken.get(data); + await token.remove(); + }catch(error){ + throw error; + } +} + +module.exports = {Auth, AuthToken}; diff --git a/nodejs/models/auth_redis.js b/nodejs/models/auth_redis.js new file mode 100644 index 0000000..4c01934 --- /dev/null +++ b/nodejs/models/auth_redis.js @@ -0,0 +1,62 @@ +'use strict'; + +const bcrypt = require('bcrypt'); +const saltRounds = 10; + +const {User} = require('./user_redis'); +const {Token, AuthToken} = require('./token'); + +var Auth = {} +Auth.errors = {} + +Auth.errors.login = function(){ + let error = new Error('ResisLoginFailed'); + error.name = 'RedisLoginFailed'; + error.message = `Invalid Credentials, login failed.`; + error.status = 401; + + return error; +} + +Auth.login = async function(data){ + try{ + let user = await User.get(data); + + let auth = await bcrypt.compare(data.password, user.password); + + if(auth){ + let token = await AuthToken.add(user); + + return {user, token} + }else{ + throw this.errors.login(); + } + }catch(error){ + if (error == 'Authentication failure'){ + throw this.errors.login() + } + throw error; + } +}; + +Auth.checkToken = async function(data){ + try{ + let token = await AuthToken.get(data); + if(token.is_valid){ + return await User.get(token.created_by); + } + }catch(error){ + throw this.errors.login(); + } +}; + +Auth.logOut = async function(data){ + try{ + let token = await AuthToken.get(data); + await token.remove(); + }catch(error){ + throw error; + } +} + +module.exports = {Auth, AuthToken}; diff --git a/nodejs/models/host.js b/nodejs/models/host.js index b8dd169..910661b 100755 --- a/nodejs/models/host.js +++ b/nodejs/models/host.js @@ -1,6 +1,6 @@ 'use strict'; -const Host = require('../utils/redis_model')({ +const Host = new require('../utils/redis_model')({ _name: 'host', _key: 'host', _keyMap: { diff --git a/nodejs/models/user.js b/nodejs/models/user_pam.js old mode 100755 new mode 100644 similarity index 100% rename from nodejs/models/user.js rename to nodejs/models/user_pam.js diff --git a/nodejs/models/user_redis.js b/nodejs/models/user_redis.js new file mode 100644 index 0000000..e9fdb06 --- /dev/null +++ b/nodejs/models/user_redis.js @@ -0,0 +1,100 @@ +'use strict'; + +const objValidate = require('../utils/object_validate'); +const {Token, InviteToken} = require('./token'); +const bcrypt = require('bcrypt'); +const saltRounds = 10; + +const User = require('../utils/redis_model')({ + _name: 'user', + _key: 'username', + _keyMap: { + 'created_by': {isRequired: true, type: 'string', min: 3, max: 500}, + 'created_on': {default: function(){return (new Date).getTime()}}, + 'updated_by': {default:"__NONE__", isRequired: false, type: 'string',}, + 'updated_on': {default: function(){return (new Date).getTime()}, always: true}, + 'username': {isRequired: true, type: 'string', min: 3, max: 500}, + 'password': {isRequired: true, type: 'string', min: 3, max: 500}, + 'backing': {default:"redis", isRequired: false, type: 'string',}, + } +}); + +User.add = async function(data) { + try{ + data['password'] = await bcrypt.hash(data['password'], saltRounds); + data['backing'] = data['backing'] || 'redis'; + + + return this.__proto__.add(data); + + }catch(error){ + throw error; + } +}; + +User.addByInvite = async function(data){ + try{ + let token = await InviteToken.get(data.token); + + if(!token.is_valid){ + let error = new Error('Token Invalid'); + error.name = 'Token Invalid'; + error.message = `Token is not valid or as allready been used. ${data.token}`; + error.status = 401; + throw error; + } + + let user = await this.add(data); + + if(user){ + await token.consume({claimed_by: user.username}); + return user; + } + + }catch(error){ + throw error; + } + +}; + +User.setPassword = async function(data){ + try{ + data['password'] = await bcrypt.hash(data['password'], saltRounds); + + return this.__proto__.update(data); + }catch(error){ + throw error; + } +}; + +User.invite = async function(){ + try{ + let token = await InviteToken.add({created_by: this.username}); + + return token; + + }catch(error){ + throw error; + } +}; + +module.exports = {User}; + + +(async function(){ + try{ + await User.get('proxyadmin1'); + console.info('proxyadmin1 user exists'); + }catch(error){ + try{ + let user = await User.add({ + username:'proxyadmin1', + password: 'proxyadmin1', + created_by:'proxyadmin1' + }); + console.log('proxyadmin1 created', user); + }catch(error){ + console.error(error) + } + } +})(); \ No newline at end of file diff --git a/nodejs/routes/auth.js b/nodejs/routes/auth.js index 3c5aa0d..d4c41a0 100755 --- a/nodejs/routes/auth.js +++ b/nodejs/routes/auth.js @@ -1,8 +1,8 @@ 'use strict'; const router = require('express').Router(); -const {User} = require('../models/user'); -const {Auth, AuthToken} = require('../models/auth'); +const {User} = require('../models/user_redis'); +const {Auth, AuthToken} = require('../models/auth_redis'); router.post('/login', async function(req, res, next){ diff --git a/nodejs/routes/user.js b/nodejs/routes/user.js index 7a09a4b..645e3d9 100755 --- a/nodejs/routes/user.js +++ b/nodejs/routes/user.js @@ -1,11 +1,13 @@ 'use strict'; const router = require('express').Router(); -const {User} = require('../models/user'); +const {User} = require('../models/user_redis'); router.get('/', async function(req, res, next){ try{ - return res.json({results: await User.list()}); + return res.json({ + results: await User[req.query.detail ? "listDetail" : "list"]() + }); }catch(error){ next(error); } diff --git a/nodejs/utils/redis_model.js b/nodejs/utils/redis_model.js index 792b102..ed33062 100644 --- a/nodejs/utils/redis_model.js +++ b/nodejs/utils/redis_model.js @@ -88,6 +88,7 @@ table.add = async function(data){ try{ // Validate the passed data by the keyMap schema. + data = objValidate.processKeys(this._keyMap, data); // Do not allow the caller to overwrite an existing index key, @@ -176,15 +177,21 @@ table.remove = async function(data){ } }; +table.createInstance = function(data){ + + // this.__proto__ = data; + + return this +} + + function Table(data){ // Create a table instance. - let obj = Object.create(table); - - // Insert the user assigned options - Object.assign(obj, data); + let instance = Object.create(data); + Object.assign(instance, table); // Return the table instance to the caller. - return obj; + return Object.create(instance); }; diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..9ff046a --- /dev/null +++ b/package-lock.json @@ -0,0 +1,491 @@ +{ + "requires": true, + "lockfileVersion": 1, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "bcrypt": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-4.0.1.tgz", + "integrity": "sha512-hSIZHkUxIDS5zA2o00Kf2O5RfVbQ888n54xQoF/eIaquU4uaLxK8vhhBdktd0B3n2MjkcAWzv4mnhogykBKOUQ==", + "requires": { + "node-addon-api": "^2.0.0", + "node-pre-gyp": "0.14.0" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "requires": { + "ms": "^2.1.1" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + }, + "detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" + }, + "fs-minipass": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", + "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", + "requires": { + "minipass": "^2.6.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore-walk": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz", + "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + }, + "minipass": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", + "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "requires": { + "minipass": "^2.9.0" + } + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "requires": { + "minimist": "^1.2.5" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "needle": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/needle/-/needle-2.4.1.tgz", + "integrity": "sha512-x/gi6ijr4B7fwl6WYL9FwlCvRQKGlUNvnceho8wxkwXqN8jvVmmmATTmZPRRG7b/yC1eode26C2HO9jl78Du9g==", + "requires": { + "debug": "^3.2.6", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-addon-api": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.0.tgz", + "integrity": "sha512-ASCL5U13as7HhOExbT6OlWJJUV/lLzL2voOSP1UVehpRD8FbSrSDjfScK/KwAvVTI5AS6r4VwbOMlIqtvRidnA==" + }, + "node-pre-gyp": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.14.0.tgz", + "integrity": "sha512-+CvDC7ZttU/sSt9rFjix/P05iS43qHCOOGzcr3Ry99bXG7VX953+vFyEuph/tfqoYu8dttBkE86JSKBO2OzcxA==", + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4.4.2" + } + }, + "nopt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", + "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz", + "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==", + "requires": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npm-normalize-package-bin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", + "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==" + }, + "npm-packlist": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz", + "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==", + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1", + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + }, + "osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "tar": { + "version": "4.4.13", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", + "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.8.6", + "minizlib": "^1.2.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.3" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + } + } +} From 7d9ea08ec953de5d949f865407d8aa37ad924c4d Mon Sep 17 00:00:00 2001 From: William Mantly Date: Sun, 12 Apr 2020 19:24:55 -0400 Subject: [PATCH 2/3] fixed issue with user creation --- nodejs/models/host.js | 2 +- nodejs/routes/user.js | 2 ++ nodejs/utils/redis_model.js | 8 -------- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/nodejs/models/host.js b/nodejs/models/host.js index 910661b..b8dd169 100755 --- a/nodejs/models/host.js +++ b/nodejs/models/host.js @@ -1,6 +1,6 @@ 'use strict'; -const Host = new require('../utils/redis_model')({ +const Host = require('../utils/redis_model')({ _name: 'host', _key: 'host', _keyMap: { diff --git a/nodejs/routes/user.js b/nodejs/routes/user.js index 645e3d9..c607c49 100755 --- a/nodejs/routes/user.js +++ b/nodejs/routes/user.js @@ -15,6 +15,8 @@ router.get('/', async function(req, res, next){ router.post('/', async function(req, res, next){ try{ + req.body.created_by = req.user.username + return res.json({results: await User.add(req.body)}); }catch(error){ next(error); diff --git a/nodejs/utils/redis_model.js b/nodejs/utils/redis_model.js index ed33062..dffe9d0 100644 --- a/nodejs/utils/redis_model.js +++ b/nodejs/utils/redis_model.js @@ -177,14 +177,6 @@ table.remove = async function(data){ } }; -table.createInstance = function(data){ - - // this.__proto__ = data; - - return this -} - - function Table(data){ // Create a table instance. let instance = Object.create(data); From 607a5f33afab9d370f278a1f843fb7b708b5fe92 Mon Sep 17 00:00:00 2001 From: William Mantly Date: Fri, 1 May 2020 17:57:25 -0400 Subject: [PATCH 3/3] ldap user --- .gitignore | 5 +- nodejs/app.js | 13 +- nodejs/conf/base.js | 13 ++ nodejs/conf/conf.js | 32 ++++ nodejs/middleware/auth.js | 2 +- nodejs/models/{auth_pam.js => auth.js} | 11 +- nodejs/models/auth_red.js | 55 ------ nodejs/models/auth_redis.js | 62 ------- nodejs/models/user.js | 7 + nodejs/models/user_ldap.js | 235 +++++++++++++++++++++++++ nodejs/models/user_pam.js | 19 ++ nodejs/models/user_redis.js | 22 +++ nodejs/package.json | 2 + nodejs/routes/auth.js | 4 +- nodejs/routes/user.js | 2 +- 15 files changed, 349 insertions(+), 135 deletions(-) create mode 100644 nodejs/conf/base.js create mode 100644 nodejs/conf/conf.js rename nodejs/models/{auth_pam.js => auth.js} (73%) delete mode 100644 nodejs/models/auth_red.js delete mode 100644 nodejs/models/auth_redis.js create mode 100644 nodejs/models/user.js create mode 100644 nodejs/models/user_ldap.js diff --git a/.gitignore b/.gitignore index 2d49c1f..e901d22 100755 --- a/.gitignore +++ b/.gitignore @@ -81,4 +81,7 @@ Berksfile.lock .zero-knife.rb Policyfile.lock.json -ops/cookbooks/vendor \ No newline at end of file +ops/cookbooks/vendor + +secrets.json +secrets.js diff --git a/nodejs/app.js b/nodejs/app.js index 08fddb7..1cf6f5f 100755 --- a/nodejs/app.js +++ b/nodejs/app.js @@ -3,11 +3,19 @@ const path = require('path'); const ejs = require('ejs') const express = require('express'); -const middleware = require('./middleware/auth'); // Set up the express app. const app = express(); +// Allow the express app to be exported into other files. +module.exports = app; + +// Build the conf object from the conf files. +app.conf = require('./conf/conf'); + +// Hold onto the auth middleware +const middleware = require('./middleware/auth'); + // load the JSON parser middleware. Express will parse JSON into native objects // for any request that has JSON in its content type. app.use(express.json()); @@ -51,6 +59,3 @@ app.use(function(err, req, res, next) { res.status(err.status || 500); res.json({name: err.name, message: err.message}); }); - -// Allow the express app to be exported into other files. -module.exports = app; \ No newline at end of file diff --git a/nodejs/conf/base.js b/nodejs/conf/base.js new file mode 100644 index 0000000..73ef0c9 --- /dev/null +++ b/nodejs/conf/base.js @@ -0,0 +1,13 @@ +'use strict'; + +module.exports = { + userModel: 'redis', // pam, redis, ldap + ldap: { + url: 'ldap://192.168.1.55:389', + bindDN: 'cn=ldapclient service,ou=people,dc=theta42,dc=com', + bindPassword: '__IN SRECREST FILE__', + searchBase: 'ou=people,dc=theta42,dc=com', + userFilter: '(objectClass=inetOrgPerson)', + userNameAttribute: 'uid' + } +}; diff --git a/nodejs/conf/conf.js b/nodejs/conf/conf.js new file mode 100644 index 0000000..ce09580 --- /dev/null +++ b/nodejs/conf/conf.js @@ -0,0 +1,32 @@ +'use strict'; + +const extend = require('extend'); + +const environment = process.env.NODE_ENV || 'development'; + +function load(filePath, required){ + try { + return require(filePath); + } catch(error){ + if(error.name === 'SyntaxError'){ + console.error(`Loading ${filePath} file failed!\n`, error); + process.exit(1); + } else if (error.code === 'MODULE_NOT_FOUND'){ + console.warn(`No config file ${filePath} FOUND! This may cause issues...`); + if (required){ + process.exit(1); + } + return {}; + }else{ + console.dir(`Unknown error in loading ${filePath} config file.\n`, error); + } + } +}; + +module.exports = extend( + true, // enable deep copy + load('./base', true), + load(`./${environment}`), + load('./secrets'), + {environment} +); diff --git a/nodejs/middleware/auth.js b/nodejs/middleware/auth.js index 777620b..6b98731 100755 --- a/nodejs/middleware/auth.js +++ b/nodejs/middleware/auth.js @@ -1,6 +1,6 @@ 'use strict'; -const {Auth} = require('../models/auth_redis'); +const {Auth} = require('../models/auth'); async function auth(req, res, next){ try{ diff --git a/nodejs/models/auth_pam.js b/nodejs/models/auth.js similarity index 73% rename from nodejs/models/auth_pam.js rename to nodejs/models/auth.js index 4c1eb80..e5d68af 100644 --- a/nodejs/models/auth_pam.js +++ b/nodejs/models/auth.js @@ -1,7 +1,3 @@ -const {promisify} = require('util'); -const pam = require('authenticate-pam'); -const authenticate = promisify(pam.authenticate); - const {User} = require('./user'); const {Token, AuthToken} = require('./token'); @@ -19,19 +15,16 @@ Auth.errors.login = function(){ Auth.login = async function(data){ try{ - let auth = await authenticate(data.username, data.password); - let user = await User.get(data); + let user = await User.login(data); let token = await AuthToken.add(user); return {user, token} }catch(error){ - if (error == 'Authentication failure'){ - throw this.errors.login() - } throw error; } }; + Auth.checkToken = async function(data){ try{ let token = await AuthToken.get(data); diff --git a/nodejs/models/auth_red.js b/nodejs/models/auth_red.js deleted file mode 100644 index 4c1eb80..0000000 --- a/nodejs/models/auth_red.js +++ /dev/null @@ -1,55 +0,0 @@ -const {promisify} = require('util'); -const pam = require('authenticate-pam'); -const authenticate = promisify(pam.authenticate); - -const {User} = require('./user'); -const {Token, AuthToken} = require('./token'); - -Auth = {} -Auth.errors = {} - -Auth.errors.login = function(){ - let error = new Error('PamLoginFailed'); - error.name = 'PamLoginFailed'; - error.message = `Invalid Credentials, login failed.`; - error.status = 401; - - return error; -} - -Auth.login = async function(data){ - try{ - let auth = await authenticate(data.username, data.password); - let user = await User.get(data); - let token = await AuthToken.add(user); - - return {user, token} - }catch(error){ - if (error == 'Authentication failure'){ - throw this.errors.login() - } - throw error; - } -}; - -Auth.checkToken = async function(data){ - try{ - let token = await AuthToken.get(data); - if(token.is_valid){ - return await User.get(token.created_by); - } - }catch(error){ - throw this.errors.login(); - } -}; - -Auth.logOut = async function(data){ - try{ - let token = await AuthToken.get(data); - await token.remove(); - }catch(error){ - throw error; - } -} - -module.exports = {Auth, AuthToken}; diff --git a/nodejs/models/auth_redis.js b/nodejs/models/auth_redis.js deleted file mode 100644 index 4c01934..0000000 --- a/nodejs/models/auth_redis.js +++ /dev/null @@ -1,62 +0,0 @@ -'use strict'; - -const bcrypt = require('bcrypt'); -const saltRounds = 10; - -const {User} = require('./user_redis'); -const {Token, AuthToken} = require('./token'); - -var Auth = {} -Auth.errors = {} - -Auth.errors.login = function(){ - let error = new Error('ResisLoginFailed'); - error.name = 'RedisLoginFailed'; - error.message = `Invalid Credentials, login failed.`; - error.status = 401; - - return error; -} - -Auth.login = async function(data){ - try{ - let user = await User.get(data); - - let auth = await bcrypt.compare(data.password, user.password); - - if(auth){ - let token = await AuthToken.add(user); - - return {user, token} - }else{ - throw this.errors.login(); - } - }catch(error){ - if (error == 'Authentication failure'){ - throw this.errors.login() - } - throw error; - } -}; - -Auth.checkToken = async function(data){ - try{ - let token = await AuthToken.get(data); - if(token.is_valid){ - return await User.get(token.created_by); - } - }catch(error){ - throw this.errors.login(); - } -}; - -Auth.logOut = async function(data){ - try{ - let token = await AuthToken.get(data); - await token.remove(); - }catch(error){ - throw error; - } -} - -module.exports = {Auth, AuthToken}; diff --git a/nodejs/models/user.js b/nodejs/models/user.js new file mode 100644 index 0000000..67338a0 --- /dev/null +++ b/nodejs/models/user.js @@ -0,0 +1,7 @@ +'use strict'; + +const conf = require('../app').conf; + +const User = require(`./user_${conf.userModel}`) + +module.exports = User; diff --git a/nodejs/models/user_ldap.js b/nodejs/models/user_ldap.js new file mode 100644 index 0000000..7d8f993 --- /dev/null +++ b/nodejs/models/user_ldap.js @@ -0,0 +1,235 @@ +'use strict'; + +const { Client, Attribute, Change } = require('ldapts'); +const {Token, InviteToken} = require('./token'); +const conf = require('../app').conf.ldap; + +const client = new Client({ + url: conf.url, +}); + + +const user_parse = function(data){ + if(data[conf.userNameAttribute]){ + data.username = data[conf.userNameAttribute] + delete data[conf.userNameAttribute]; + } + + if(data.uidNumber){ + data.uid = data.uidNumber; + delete data.uidNumber; + } + + return data; +} + +var User = {} + +User.backing = "LDAP"; + +User.keyMap = { + 'username': {isRequired: true, type: 'string', min: 3, max: 500}, + 'password': {isRequired: true, type: 'string', min: 3, max: 500}, +} + +User.list = async function(){ + try{ + await client.bind(conf.bindDN, conf.bindPassword); + + const res = await client.search(conf.searchBase, { + scope: 'sub', + filter: conf.userFilter, + }); + + await client.unbind(); + + return res.searchEntries.map(function(user){return user.uid}); + }catch(error){ + throw error; + } +}; + +User.listDetail = async function(){ + try{ + await client.bind(conf.bindDN, conf.bindPassword); + + const res = await client.search(conf.searchBase, { + scope: 'sub', + filter: conf.userFilter, + }); + + await client.unbind(); + + let users = [] + + for(let user of res.searchEntries){ + let obj = Object.create(this); + Object.assign(obj, user_parse(user)); + + users.push(obj) + + } + + return users; + + }catch(error){ + throw error; + } +}; + +User.get = async function(data){ + try{ + if(typeof data !== 'object'){ + let username = data; + data = {}; + data.username = username; + } + + await client.bind(conf.bindDN, conf.bindPassword); + + let filter = `(&${conf.userFilter}(${conf.userNameAttribute}=${data.username}))`; + + const res = await client.search(conf.searchBase, { + scope: 'sub', + filter: filter, + }); + + await client.unbind(); + + let user = res.searchEntries[0] + + if(user){ + let obj = Object.create(this); + Object.assign(obj, user_parse(user)); + + return obj; + }else{ + let error = new Error('UserNotFound'); + error.name = 'UserNotFound'; + error.message = `LDAP:${data.username} does not exists`; + error.status = 404; + throw error; + } + }catch(error){ + throw error; + } +}; + +User.exists = async function(data){ + // Return true or false if the requested entry exists ignoring error's. + try{ + await this.get(data); + + return true + }catch(error){ + return false; + } +}; + +// User.add = async function(data) { +// try{ +// data = objValidate.processKeys(this.keyMap, data); +// let systemUser = await linuxUser.addUser(data.username); +// await require('util').promisify(setTimeout)(500) +// let systemUserPassword = await linuxUser.setPassword(data.username, data.password); + +// return this.get(data.username); + +// }catch(error){ +// if(error.message.includes('exists')){ +// let error = new Error('UserNameUsed'); +// error.name = 'UserNameUsed'; +// error.message = `PAM:${data.username} already exists`; +// error.status = 409; + +// throw error; +// } +// throw error; +// } +// }; + +// User.addByInvite = async function(data){ +// try{ +// let token = await InviteToken.get(data.token); + +// if(!token.is_valid){ +// let error = new Error('Token Invalid'); +// error.name = 'Token Invalid'; +// error.message = `Token is not valid or as allready been used. ${data.token}`; +// error.status = 401; +// throw error; +// } + +// let user = await this.add(data); + +// if(user){ +// await token.consume({claimed_by: user.username}); +// return user; +// } + +// }catch(error){ +// throw error; +// } + +// }; + +// User.remove = async function(data){ +// try{ +// return await linuxUser.removeUser(this.username); +// }catch(error){ +// throw error; +// } +// }; + +// User.setPassword = async function(data){ +// try{ +// await linuxUser.setPassword(this.username, data.password); + +// return this; +// }catch(error){ +// throw error; +// } +// }; + +User.invite = async function(){ + try{ + let token = await InviteToken.add({created_by: this.username}); + + return token; + + }catch(error){ + throw error; + } +}; + +User.login = async function(data){ + try{ + let user = await this.get(data.username); + + await client.bind(user.dn, data.password); + + await client.unbind(); + + return user; + + }catch(error){ + throw error; + } +}; + + +module.exports = {User}; + + +// (async function(){ +// try{ +// console.log(await User.list()); + +// console.log(await User.listDetail()); + +// console.log(await User.get('wmantly')) + +// }catch(error){ +// console.error(error) +// } +// })() \ No newline at end of file diff --git a/nodejs/models/user_pam.js b/nodejs/models/user_pam.js index b68e768..998e940 100644 --- a/nodejs/models/user_pam.js +++ b/nodejs/models/user_pam.js @@ -3,6 +3,9 @@ const linuxUser = require('linux-sys-user').promise(); const objValidate = require('../utils/object_validate'); const {Token, InviteToken} = require('./token'); +const {promisify} = require('util'); +const pam = require('authenticate-pam'); +const authenticate = promisify(pam.authenticate); var User = {} @@ -11,6 +14,8 @@ User.keyMap = { 'password': {isRequired: true, type: 'string', min: 3, max: 500}, } +User.backing = "PAM"; + User.list = async function(){ try{ let users = await linuxUser.getUsers(); @@ -139,4 +144,18 @@ User.invite = async function(){ } }; +User.login = async function(data){ + try{ + let auth = await authenticate(data.username, data.password); + let user = await User.get(data); + + return user; + }catch(error){ + if (error == 'Authentication failure'){ + throw this.errors.login() + } + throw error; + } +}; + module.exports = {User}; diff --git a/nodejs/models/user_redis.js b/nodejs/models/user_redis.js index e9fdb06..f76fc3c 100644 --- a/nodejs/models/user_redis.js +++ b/nodejs/models/user_redis.js @@ -19,6 +19,9 @@ const User = require('../utils/redis_model')({ } }); +User.backing = "redis"; + + User.add = async function(data) { try{ data['password'] = await bcrypt.hash(data['password'], saltRounds); @@ -78,6 +81,25 @@ User.invite = async function(){ } }; +User.login = async function(data){ + try{ + let user = await User.get(data); + + let auth = await bcrypt.compare(data.password, user.password); + + if(auth){ + return user + }else{ + throw this.errors.login(); + } + }catch(error){ + if (error == 'Authentication failure'){ + throw this.errors.login() + } + throw error; + } +}; + module.exports = {User}; diff --git a/nodejs/package.json b/nodejs/package.json index fac02f4..9dae9e2 100755 --- a/nodejs/package.json +++ b/nodejs/package.json @@ -13,6 +13,8 @@ }, "dependencies": { "authenticate-pam": "github:WeiAnAn/node-authenticate-pam", + "ldapts": "^2.2.1", + "extend": "^3.0.2", "ejs": "^3.0.1", "express": "~4.16.1", "linux-sys-user": "^1.1.0", diff --git a/nodejs/routes/auth.js b/nodejs/routes/auth.js index d4c41a0..3c5aa0d 100755 --- a/nodejs/routes/auth.js +++ b/nodejs/routes/auth.js @@ -1,8 +1,8 @@ 'use strict'; const router = require('express').Router(); -const {User} = require('../models/user_redis'); -const {Auth, AuthToken} = require('../models/auth_redis'); +const {User} = require('../models/user'); +const {Auth, AuthToken} = require('../models/auth'); router.post('/login', async function(req, res, next){ diff --git a/nodejs/routes/user.js b/nodejs/routes/user.js index c607c49..121a61f 100755 --- a/nodejs/routes/user.js +++ b/nodejs/routes/user.js @@ -1,7 +1,7 @@ 'use strict'; const router = require('express').Router(); -const {User} = require('../models/user_redis'); +const {User} = require('../models/user'); router.get('/', async function(req, res, next){ try{