new version

This commit is contained in:
Evert Prants 2019-09-06 19:03:42 +03:00
commit 1b15b4f3b7
Signed by: evert
GPG Key ID: 1688DA83D222D0B5
8 changed files with 3320 additions and 67 deletions

137
.eslintrc Normal file
View File

@ -0,0 +1,137 @@
{
"extends": "airbnb-base",
"parserOptions": {
"sourceType": "script"
},
"rules": {
// Customized
"handle-callback-err": [ "error","^(e$|(e|(.*(_e|E)))rr)" ],
"comma-dangle": ["error", {
"arrays": "always-multiline",
"objects": "always-multiline",
"imports": "always-multiline",
"exports": "always-multiline",
"functions": "never"
}],
"no-empty": ["error", { "allowEmptyCatch": true }],
"no-underscore-dangle": "off",
"no-console": "off",
"no-mixed-operators": ["error", { "allowSamePrecedence": true }],
"strict": ["error", "global"],
"consistent-return": "off",
"func-names": "off",
"no-tabs": "off",
"indent": ["error", "tab"],
"no-eq-null": "off",
"camelcase": "off",
"no-new": "off",
"no-shadow": "off",
"no-use-before-define": ["error", "nofunc"],
"no-prototype-builtins": "off",
"new-cap": "off",
"no-plusplus": ["error", { "allowForLoopAfterthoughts": true }],
"object-curly-newline": "off",
"no-restricted-globals": "off",
"function-paren-newline": "off",
"import/no-unresolved": "error",
"quotes": ["error", "single", {
"avoidEscape": true,
"allowTemplateLiterals": true
}],
"no-else-return": [ "error", { "allowElseIf": true } ],
"operator-linebreak": [ "error", "after" ],
// ES6
"prefer-rest-params": "off",
"prefer-spread": "off",
"prefer-arrow-callback": "off",
"prefer-template": "off",
"no-var": "off",
"object-shorthand": "off",
"vars-on-top": "off",
"prefer-destructuring": "off",
// TODO
"import/no-extraneous-dependencies": "off",
"import/no-dynamic-require": "off",
"import/newline-after-import": "off",
"no-bitwise": "off",
"global-require": "off",
"max-len": "off",
"no-param-reassign": "off",
"no-restricted-syntax": "off",
"no-script-url": "off",
"default-case": "off",
"linebreak-style": "off",
// "no-multi-assign": "off",
// "one-var": "off",
// "no-undef": "off",
// "max-nested-callbacks": "off",
// "no-mixed-requires": "off",
// "brace-style": "off",
// "max-statements-per-line": "off",
// "no-unused-vars": "off",
// "no-mixed-spaces-and-tabs": "off",
// "no-useless-concat": "off",
// "require-jsdoc": "off",
// "eqeqeq": "off",
// "no-negated-condition": "off",
// "one-var-declaration-per-line": "off",
// "no-lonely-if": "off",
// "radix": "off",
// "no-else-return": "off",
// "no-useless-escape": "off",
// "block-scoped-var": "off",
// "operator-assignment": "off",
// "yoda": "off",
// "no-loop-func": "off",
// "no-void": "off",
// "valid-jsdoc": "off",
// "no-cond-assign": "off",
// "no-redeclare": "off",
// "no-unreachable": "off",
// "no-nested-ternary": "off",
// "operator-linebreak": "off",
// "guard-for-in": "off",
// "no-unneeded-ternary": "off",
// "no-sequences": "off",
// "no-extend-native": "off",
// "no-shadow-restricted-names": "off",
// "no-extra-boolean-cast": "off",
// "no-path-concat": "off",
// "no-unused-expressions": "off",
// "no-return-assign": "off",
// "no-restricted-modules": "off",
// "object-curly-spacing": "off",
// "indent": "off",
// "padded-blocks": "off",
// "eol-last": "off",
// "lines-around-directive": "off",
// "strict": "off",
// "comma-dangle": "off",
// "no-multi-spaces": "off",
// "quotes": "off",
// "keyword-spacing": "off",
// "no-mixed-operators": "off",
// "comma-spacing": "off",
// "no-trailing-spaces": "off",
// "key-spacing": "off",
// "no-multiple-empty-lines": "off",
// "spaced-comment": "off",
// "space-in-parens": "off",
// "block-spacing": "off",
// "quote-props": "off",
// "space-unary-ops": "off",
// "no-empty": "off",
// "dot-notation": "off",
// "func-call-spacing": "off",
// "array-bracket-spacing": "off",
// "object-property-newline": "off",
// "no-continue": "off",
// "no-extra-semi": "off",
// "no-spaced-func": "off",
// "no-useless-return": "off"
}
}

6
.gitignore vendored
View File

@ -216,3 +216,9 @@ pip-log.txt
sftp-config.json sftp-config.json
node_modules/ node_modules/
####################
# JetBrains
####################
.idea

View File

@ -14,4 +14,6 @@ NodeBB Plugin that allows users to login/register via any configured OAuth provi
## Trouble? ## Trouble?
The NodeBB team builds out SSO plugins for a nominal fee. [Reach out to us for a quote.](mailto:sales@nodebb.org)
Find us on [the community forums](http://community.nodebb.org)! Find us on [the community forums](http://community.nodebb.org)!

3
commitlint.config.js Normal file
View File

@ -0,0 +1,3 @@
'use strict';
module.exports = { extends: ['@commitlint/config-angular'] };

View File

@ -1,6 +1,6 @@
(function(module) { 'use strict';
"use strict";
(function (module) {
/* /*
Welcome to the SSO OAuth plugin! If you're inspecting this code, you're probably looking to Welcome to the SSO OAuth plugin! If you're inspecting this code, you're probably looking to
hook up NodeBB with your existing OAuth endpoint. hook up NodeBB with your existing OAuth endpoint.
@ -16,18 +16,16 @@
Step 4: If all goes well, you'll be able to login/register via your OAuth endpoint credentials. Step 4: If all goes well, you'll be able to login/register via your OAuth endpoint credentials.
*/ */
var User = module.parent.require('./user'), const User = require.main.require('./src/user');
Groups = module.parent.require('./groups'), const Groups = require.main.require('./src/groups');
meta = module.parent.require('./meta'), const db = require.main.require('./src/database');
db = module.parent.require('../src/database'), const authenticationController = require.main.require('./src/controllers/authentication');
passport = module.parent.require('passport'),
fs = module.parent.require('fs'),
path = module.parent.require('path'),
nconf = module.parent.require('nconf'),
winston = module.parent.require('winston'),
async = module.parent.require('async');
var authenticationController = module.parent.require('./controllers/authentication'); const async = require('async');
const passport = module.parent.require('passport');
const nconf = module.parent.require('nconf');
const winston = module.parent.require('winston');
/** /**
* REMEMBER * REMEMBER
@ -48,7 +46,7 @@
* `OAUTH__ID=someoauthid OAUTH__SECRET=youroauthsecret node app.js` * `OAUTH__ID=someoauthid OAUTH__SECRET=youroauthsecret node app.js`
*/ */
var constants = Object.freeze({ const constants = Object.freeze({
type: 'oauth2', // Either 'oauth' or 'oauth2' type: 'oauth2', // Either 'oauth' or 'oauth2'
name: 'icynet', // Something unique to your OAuth provider in lowercase, like "github", or "nodebb" name: 'icynet', // Something unique to your OAuth provider in lowercase, like "github", or "nodebb"
scope: 'email privilege', scope: 'email privilege',
@ -66,9 +64,12 @@
clientSecret: nconf.get('oauth:secret'), clientSecret: nconf.get('oauth:secret'),
}, },
userRoute: nconf.get('oauth:provider') + '/oauth2/user' userRoute: nconf.get('oauth:provider') + '/oauth2/user'
}), })
configOk = false,
OAuth = {}, passportOAuth, opts; const OAuth = {};
let configOk = false;
let passportOAuth;
let opts;
if (!constants.name) { if (!constants.name) {
winston.error('[sso-oauth] Please specify a name for your OAuth provider (library.js:32)'); winston.error('[sso-oauth] Please specify a name for your OAuth provider (library.js:32)');
@ -90,8 +91,10 @@
opts.callbackURL = nconf.get('url') + '/auth/' + constants.name + '/callback'; opts.callbackURL = nconf.get('url') + '/auth/' + constants.name + '/callback';
passportOAuth.Strategy.prototype.userProfile = function (token, secret, params, done) { passportOAuth.Strategy.prototype.userProfile = function (token, secret, params, done) {
this._oauth.get(constants.userRoute, token, secret, function(err, body, res) { this._oauth.get(constants.userRoute, token, secret, function (err, body/* , res */) {
if (err) { return done(new InternalOAuthError('failed to fetch user profile', err)); } if (err) {
return done(err);
}
try { try {
var json = JSON.parse(body); var json = JSON.parse(body);
@ -112,8 +115,10 @@
opts.callbackURL = nconf.get('url') + '/auth/' + constants.name + '/callback'; opts.callbackURL = nconf.get('url') + '/auth/' + constants.name + '/callback';
passportOAuth.Strategy.prototype.userProfile = function (accessToken, done) { passportOAuth.Strategy.prototype.userProfile = function (accessToken, done) {
this._oauth2.get(constants.userRoute, accessToken, function(err, body, res) { this._oauth2.get(constants.userRoute, accessToken, function (err, body/* , res */) {
if (err) { return done(new InternalOAuthError('failed to fetch user profile', err)); } if (err) {
return done(err);
}
try { try {
var json = JSON.parse(body); var json = JSON.parse(body);
@ -154,7 +159,7 @@
url: '/auth/' + constants.name, url: '/auth/' + constants.name,
callbackURL: '/auth/' + constants.name + '/callback', callbackURL: '/auth/' + constants.name + '/callback',
icon: 'fa-check-square', icon: 'fa-check-square',
scope: (constants.scope || '').split(',') scope: (constants.scope || '').split(','),
}); });
callback(null, strategies); callback(null, strategies);
@ -185,8 +190,9 @@
//process.stdout.write('===\nAt this point, you\'ll need to customise the above section to id, displayName, and emails into the "profile" object.\n==='); //process.stdout.write('===\nAt this point, you\'ll need to customise the above section to id, displayName, and emails into the "profile" object.\n===');
//return callback(new Error('Congrats! So far so good -- please see server log for details')); //return callback(new Error('Congrats! So far so good -- please see server log for details'));
// eslint-disable-next-line
callback(null, profile); callback(null, profile);
} };
OAuth.login = function (payload, callback) { OAuth.login = function (payload, callback) {
OAuth.getUidByOAuthid(payload.oAuthid, function (err, uid) { OAuth.getUidByOAuthid(payload.oAuthid, function (err, uid) {
@ -197,7 +203,7 @@
if (uid !== null) { if (uid !== null) {
// Existing User // Existing User
callback(null, { callback(null, {
uid: uid uid: uid,
}); });
} else { } else {
// New User // New User
@ -208,13 +214,13 @@
if (payload.isAdmin) { if (payload.isAdmin) {
Groups.join('administrators', uid, function (err) { Groups.join('administrators', uid, function (err) {
callback(null, { callback(err, {
uid: uid uid: uid,
}); });
}); });
} else { } else {
callback(null, { callback(null, {
uid: uid uid: uid,
}); });
} }
}; };
@ -258,7 +264,7 @@
async.apply(User.getUserField, data.uid, constants.name + 'Id'), async.apply(User.getUserField, data.uid, constants.name + 'Id'),
function (oAuthIdToDelete, next) { function (oAuthIdToDelete, next) {
db.deleteObjectField(constants.name + 'Id:uid', oAuthIdToDelete, next); db.deleteObjectField(constants.name + 'Id:uid', oAuthIdToDelete, next);
} },
], function (err) { ], function (err) {
if (err) { if (err) {
winston.error('[sso-oauth] Could not remove OAuthId data for uid ' + data.uid + '. Error: ' + err); winston.error('[sso-oauth] Could not remove OAuthId data for uid ' + data.uid + '. Error: ' + err);
@ -269,5 +275,11 @@
}); });
}; };
// If this filter is not there, the deleteUserData function will fail when getting the oauthId for deletion.
OAuth.whitelistFields = function (params, callback) {
params.whitelist.push(constants.name + 'Id');
callback(null, params);
};
module.exports = OAuth; module.exports = OAuth;
}(module)); }(module));

View File

@ -1,6 +1,6 @@
{ {
"name": "nodebb-plugin-sso-oauth", "name": "nodebb-plugin-sso-oauth",
"version": "0.3.3", "version": "0.3.4",
"description": "NodeBB Generic OAuth SSO", "description": "NodeBB Generic OAuth SSO",
"main": "library.js", "main": "library.js",
"repository": { "repository": {
@ -28,10 +28,32 @@
"readme": "", "readme": "",
"readmeFilename": "README.md", "readmeFilename": "README.md",
"dependencies": { "dependencies": {
"async": "^2",
"passport-oauth": "~1.0.0" "passport-oauth": "~1.0.0"
}, },
"nbbpm": { "nbbpm": {
"compatibility": "^1.0.1", "compatibility": "^1.0.1",
"index": false "index": false
},
"devDependencies": {
"@commitlint/cli": "^8.0.0",
"@commitlint/config-angular": "^7.1.2",
"eslint": "^5.16.0",
"eslint-config-airbnb-base": "^12.1.0",
"eslint-plugin-import": "^2.8.0",
"husky": "^2.4.0",
"lint-staged": "^8.2.0"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged",
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
}
},
"lint-staged": {
"*.js": [
"eslint --fix",
"git add"
]
} }
} }

View File

@ -6,6 +6,7 @@
"library": "./library.js", "library": "./library.js",
"hooks": [ "hooks": [
{ "hook": "static:user.delete", "method": "deleteUserData" }, { "hook": "static:user.delete", "method": "deleteUserData" },
{ "hook": "filter:user.whitelistFields", "method": "whitelistFields" },
{ "hook": "filter:auth.init", "method": "getStrategy" } { "hook": "filter:auth.init", "method": "getStrategy" }
] ]
} }

3070
yarn.lock Normal file

File diff suppressed because it is too large Load Diff