Auto linting on commit

This commit is contained in:
Justin Reynolds 2019-06-26 19:15:59 -05:00
parent 7d86af2b00
commit 3d63b6006b
17 changed files with 23 additions and 415 deletions

1
.eslintignore Normal file
View file

@ -0,0 +1 @@
packages/*

View file

@ -4,10 +4,29 @@
"description": "Open-Source kanban",
"private": true,
"scripts": {
"lint": "eslint --ignore-pattern 'packages/*' .",
"lint": "eslint --cache --ext .js --ignore-path .eslintignore .",
"lint:eslint:fix": "eslint --ext .js --ignore-path .eslintignore --fix .",
"lint:staged": "lint-staged",
"prettify": "prettier --write '**/*.js' '**/*.jsx'",
"test": "npm run --silent lint"
},
"lint-staged": {
"*.js": [
"meteor npm run prettify",
"meteor npm run lint:eslint:fix",
"git add --force"
],
"*.jsx": [
"meteor npm run prettify",
"meteor npm run lint:eslint:fix",
"git add --force"
],
"*.json": [
"prettier --write",
"git add --force"
]
},
"pre-commit": "lint:staged",
"eslintConfig": {
"extends": "@meteorjs/eslint-config-meteor"
},
@ -28,6 +47,8 @@
"eslint-plugin-import": "^2.18.0",
"eslint-plugin-meteor": "^4.2.2",
"eslint-plugin-prettier": "^3.1.0",
"lint-staged": "^7.3.0",
"pre-commit": "^1.2.2",
"prettier": "^1.18.2",
"prettier-eslint": "^8.8.2"
},

@ -1 +0,0 @@
Subproject commit e105dcc9c3424beee0ff0a9db9ca543a6d4b7f85

View file

@ -1 +0,0 @@
.versions

View file

@ -1,14 +0,0 @@
Copyright (C) 2016 SWITCH
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View file

@ -1,75 +0,0 @@
# salleman:accounts-oidc package
A Meteor login service for OpenID Connect (OIDC).
## Installation
meteor add salleman:accounts-oidc
## Usage
`Meteor.loginWithOidc(options, callback)`
* `options` - object containing options, see below (optional)
* `callback` - callback function (optional)
#### Example
```js
Template.myTemplateName.events({
'click #login-button': function() {
Meteor.loginWithOidc();
}
);
```
## Options
These options override service configuration stored in the database.
* `loginStyle`: `redirect` or `popup`
* `redirectUrl`: Where to redirect after successful login. Only used if `loginStyle` is set to `redirect`
## Manual Configuration Setup
You can manually configure this package by upserting the service configuration on startup. First, add the `service-configuration` package:
meteor add service-configuration
### Service Configuration
The following service configuration are available:
* `clientId`: OIDC client identifier
* `secret`: OIDC client shared secret
* `serverUrl`: URL of the OIDC server. e.g. `https://openid.example.org:8443`
* `authorizationEndpoint`: Endpoint of the OIDC authorization service, e.g. `/oidc/authorize`
* `tokenEndpoint`: Endpoint of the OIDC token service, e.g. `/oidc/token`
* `userinfoEndpoint`: Endpoint of the OIDC userinfo service, e.g. `/oidc/userinfo`
* `idTokenWhitelistFields`: A list of fields from IDToken to be added to Meteor.user().services.oidc object
### Project Configuration
Then in your project:
```js
if (Meteor.isServer) {
Meteor.startup(function () {
ServiceConfiguration.configurations.upsert(
{ service: 'oidc' },
{
$set: {
loginStyle: 'redirect',
clientId: 'my-client-id-registered-with-the-oidc-server',
secret: 'my-client-shared-secret',
serverUrl: 'https://openid.example.org',
authorizationEndpoint: '/oidc/authorize',
tokenEndpoint: '/oidc/token',
userinfoEndpoint: '/oidc/userinfo',
idTokenWhitelistFields: []
}
}
);
});
}
```

View file

@ -1,22 +0,0 @@
Accounts.oauth.registerService('oidc');
if (Meteor.isClient) {
Meteor.loginWithOidc = function(options, callback) {
// support a callback without options
if (! callback && typeof options === "function") {
callback = options;
options = null;
}
var credentialRequestCompleteCallback = Accounts.oauth.credentialRequestCompleteHandler(callback);
Oidc.requestCredential(options, credentialRequestCompleteCallback);
};
} else {
Accounts.addAutopublishFields({
// not sure whether the OIDC api can be used from the browser,
// thus not sure if we should be sending access tokens; but we do it
// for all other oauth2 providers, and it may come in handy.
forLoggedInUser: ['services.oidc'],
forOtherUsers: ['services.oidc.id']
});
}

View file

@ -1,3 +0,0 @@
#login-buttons-image-oidc {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACQUlEQVQ4T5WTy2taQRTGv4kSXw0IoYIihCjFmhhfhUqW9a+o0I2LInTRRbtw05V2I9KQuuimi24KXQqChIhQQcQgGGNz0YpvMCG1yL1tGqvBZsKMIIXcjQcOcznnfL+ZOecOEUVx4/Ly8mQ6neqxhKlUKmltbc1Nut2uqJ/bEnJAkiTmEhEEgVqtViiVyjuAP70j/Pj6Htbglzu52WyGdrsNUq1Wqc1mk939+9sHPP7wTVM232g0QMrlMrXb7bIFndgcbAk3ZPP1eh2kVCrRra2tRcFoNEK1WoXf78fg3Rxsfl3H3t4e3G43dnd3wWrMZjNqtRpIsVhcAFKpFPL5PBfF43H8TDj49/2XAvb393F2dgaNRgNKKaLR6ByQz+epw+HAwcEBisUijEYjgsEg1Go1pA9ODtC/+MZFDCKKIo9FIhEIggCSy+Xozs4OYrEY2ChDoRAIIVww/ujhxdrnFTSbTX6Cfr+Pi4sLhMNhnJ6egmSzWepyuZBIJGAwGBAIBLiY2ezTI74qg2UoFIqFr6ys4OrqiveKHB4eckAmk8FgMMD29jZ8Ph8XKj4/5uu/ZyXZKXBAOp2mHo+H/0isD6zDOp0Om5ubsAuvcA+/8ffpkSygUqmApFIp6vV6+b2ZsNfrodVqYTgcwqXtwul04pfhiSzg+PgYJJlMUovFwhvIbHV1lTs70c3NDSaTCa6vr+8A2FvodDr8CmwuepPJtIDIbvdfkInPz89ZRCKFQmFjNBqdjMfjpZ6jVquV1tfX3bcYegI7CyIWlgAAAABJRU5ErkJggg==');
}

View file

@ -1,19 +0,0 @@
Package.describe({
summary: "OpenID Connect (OIDC) for Meteor accounts",
version: "1.0.10",
name: "wekan-accounts-oidc",
git: "https://github.com/wekan/meteor-accounts-oidc.git",
});
Package.onUse(function(api) {
api.use('accounts-base@1.2.0', ['client', 'server']);
// Export Accounts (etc) to packages using this one.
api.imply('accounts-base', ['client', 'server']);
api.use('accounts-oauth@1.1.0', ['client', 'server']);
api.use('wekan-oidc@1.0.10', ['client', 'server']);
api.addFiles('oidc_login_button.css', 'client');
api.addFiles('oidc.js');
});

View file

@ -1 +0,0 @@
.versions

View file

@ -1,14 +0,0 @@
Copyright (C) 2016 SWITCH
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View file

@ -1,7 +0,0 @@
# salleman:oidc package
A Meteor implementation of OpenID Connect Login flow
## Usage and Documentation
Look at the `salleman:accounts-oidc` package for the documentation about using OpenID Connect with Meteor.

View file

@ -1,68 +0,0 @@
Oidc = {};
// Request OpenID Connect credentials for the user
// @param options {optional}
// @param credentialRequestCompleteCallback {Function} Callback function to call on
// completion. Takes one argument, credentialToken on success, or Error on
// error.
Oidc.requestCredential = function (options, credentialRequestCompleteCallback) {
// support both (options, callback) and (callback).
if (!credentialRequestCompleteCallback && typeof options === 'function') {
credentialRequestCompleteCallback = options;
options = {};
}
var config = ServiceConfiguration.configurations.findOne({service: 'oidc'});
if (!config) {
credentialRequestCompleteCallback && credentialRequestCompleteCallback(
new ServiceConfiguration.ConfigError('Service oidc not configured.'));
return;
}
var credentialToken = Random.secret();
var loginStyle = OAuth._loginStyle('oidc', config, options);
var scope = config.requestPermissions || ['openid', 'profile', 'email'];
// options
options = options || {};
options.client_id = config.clientId;
options.response_type = options.response_type || 'code';
options.redirect_uri = OAuth._redirectUri('oidc', config);
options.state = OAuth._stateParam(loginStyle, credentialToken, options.redirectUrl);
options.scope = scope.join(' ');
if (config.loginStyle && config.loginStyle == 'popup') {
options.display = 'popup';
}
var loginUrl = config.serverUrl + config.authorizationEndpoint;
// check if the loginUrl already contains a "?"
var first = loginUrl.indexOf('?') === -1;
for (var k in options) {
if (first) {
loginUrl += '?';
first = false;
}
else {
loginUrl += '&'
}
loginUrl += encodeURIComponent(k) + '=' + encodeURIComponent(options[k]);
}
//console.log('XXX: loginURL: ' + loginUrl)
options.popupOptions = options.popupOptions || {};
var popupOptions = {
width: options.popupOptions.width || 320,
height: options.popupOptions.height || 450
};
OAuth.launchLogin({
loginService: 'oidc',
loginStyle: loginStyle,
loginUrl: loginUrl,
credentialRequestCompleteCallback: credentialRequestCompleteCallback,
credentialToken: credentialToken,
popupOptions: popupOptions,
});
};

View file

@ -1,6 +0,0 @@
<template name="configureLoginServiceDialogForOidc">
<p>
You'll need to create an OpenID Connect client configuration with your provider.
Set App Callbacks URLs to: <span class="url">{{siteUrl}}_oauth/oidc</span>
</p>
</template>

View file

@ -1,17 +0,0 @@
Template.configureLoginServiceDialogForOidc.helpers({
siteUrl: function () {
return Meteor.absoluteUrl();
}
});
Template.configureLoginServiceDialogForOidc.fields = function () {
return [
{ property: 'clientId', label: 'Client ID'},
{ property: 'secret', label: 'Client Secret'},
{ property: 'serverUrl', label: 'OIDC Server URL'},
{ property: 'authorizationEndpoint', label: 'Authorization Endpoint'},
{ property: 'tokenEndpoint', label: 'Token Endpoint'},
{ property: 'userinfoEndpoint', label: 'Userinfo Endpoint'},
{ property: 'idTokenWhitelistFields', label: 'Id Token Fields'}
];
};

View file

@ -1,143 +0,0 @@
Oidc = {};
OAuth.registerService('oidc', 2, null, function (query) {
var debug = process.env.DEBUG || false;
var token = getToken(query);
if (debug) console.log('XXX: register token:', token);
var accessToken = token.access_token || token.id_token;
var expiresAt = (+new Date) + (1000 * parseInt(token.expires_in, 10));
var userinfo = getUserInfo(accessToken);
if (debug) console.log('XXX: userinfo:', userinfo);
var serviceData = {};
serviceData.id = userinfo[process.env.OAUTH2_ID_MAP] || userinfo[id];
serviceData.username = userinfo[process.env.OAUTH2_USERNAME_MAP] || userinfo[uid];
serviceData.fullname = userinfo[process.env.OAUTH2_FULLNAME_MAP] || userinfo[displayName];
serviceData.accessToken = accessToken;
serviceData.expiresAt = expiresAt;
serviceData.email = userinfo[process.env.OAUTH2_EMAIL_MAP] || userinfo[email];
if (accessToken) {
var tokenContent = getTokenContent(accessToken);
var fields = _.pick(tokenContent, getConfiguration().idTokenWhitelistFields);
_.extend(serviceData, fields);
}
if (token.refresh_token)
serviceData.refreshToken = token.refresh_token;
if (debug) console.log('XXX: serviceData:', serviceData);
var profile = {};
profile.name = userinfo[process.env.OAUTH2_FULLNAME_MAP] || userinfo[displayName];
profile.email = userinfo[process.env.OAUTH2_EMAIL_MAP] || userinfo[email];
if (debug) console.log('XXX: profile:', profile);
return {
serviceData: serviceData,
options: { profile: profile }
};
});
var userAgent = "Meteor";
if (Meteor.release) {
userAgent += "/" + Meteor.release;
}
var getToken = function (query) {
var debug = process.env.DEBUG || false;
var config = getConfiguration();
var serverTokenEndpoint = config.serverUrl + config.tokenEndpoint;
var response;
try {
response = HTTP.post(
serverTokenEndpoint,
{
headers: {
Accept: 'application/json',
"User-Agent": userAgent
},
params: {
code: query.code,
client_id: config.clientId,
client_secret: OAuth.openSecret(config.secret),
redirect_uri: OAuth._redirectUri('oidc', config),
grant_type: 'authorization_code',
state: query.state
}
}
);
} catch (err) {
throw _.extend(new Error("Failed to get token from OIDC " + serverTokenEndpoint + ": " + err.message),
{ response: err.response });
}
if (response.data.error) {
// if the http response was a json object with an error attribute
throw new Error("Failed to complete handshake with OIDC " + serverTokenEndpoint + ": " + response.data.error);
} else {
if (debug) console.log('XXX: getToken response: ', response.data);
return response.data;
}
};
var getUserInfo = function (accessToken) {
var debug = process.env.DEBUG || false;
var config = getConfiguration();
// Some userinfo endpoints use a different base URL than the authorization or token endpoints.
// This logic allows the end user to override the setting by providing the full URL to userinfo in their config.
if (config.userinfoEndpoint.includes("https://")) {
var serverUserinfoEndpoint = config.userinfoEndpoint;
} else {
var serverUserinfoEndpoint = config.serverUrl + config.userinfoEndpoint;
}
var response;
try {
response = HTTP.get(
serverUserinfoEndpoint,
{
headers: {
"User-Agent": userAgent,
"Authorization": "Bearer " + accessToken
}
}
);
} catch (err) {
throw _.extend(new Error("Failed to fetch userinfo from OIDC " + serverUserinfoEndpoint + ": " + err.message),
{response: err.response});
}
if (debug) console.log('XXX: getUserInfo response: ', response.data);
return response.data;
};
var getConfiguration = function () {
var config = ServiceConfiguration.configurations.findOne({ service: 'oidc' });
if (!config) {
throw new ServiceConfiguration.ConfigError('Service oidc not configured.');
}
return config;
};
var getTokenContent = function (token) {
var content = null;
if (token) {
try {
var parts = token.split('.');
var header = JSON.parse(new Buffer(parts[0], 'base64').toString());
content = JSON.parse(new Buffer(parts[1], 'base64').toString());
var signature = new Buffer(parts[2], 'base64');
var signed = parts[0] + '.' + parts[1];
} catch (err) {
this.content = {
exp: 0
};
}
}
return content;
}
Oidc.retrieveCredential = function (credentialToken, credentialSecret) {
return OAuth.retrieveCredential(credentialToken, credentialSecret);
};

View file

@ -1,23 +0,0 @@
Package.describe({
summary: "OpenID Connect (OIDC) flow for Meteor",
version: "1.0.12",
name: "wekan-oidc",
git: "https://github.com/wekan/meteor-accounts-oidc.git",
});
Package.onUse(function(api) {
api.use('oauth2@1.1.0', ['client', 'server']);
api.use('oauth@1.1.0', ['client', 'server']);
api.use('http@1.1.0', ['server']);
api.use('underscore@1.0.0', 'client');
api.use('templating@1.1.0', 'client');
api.use('random@1.0.0', 'client');
api.use('service-configuration@1.0.0', ['client', 'server']);
api.export('Oidc');
api.addFiles(['oidc_configure.html', 'oidc_configure.js'], 'client');
api.addFiles('oidc_server.js', 'server');
api.addFiles('oidc_client.js', 'client');
});