mirror of
https://github.com/plankanban/planka.git
synced 2025-08-09 07:25:24 +02:00
wip: SAML support (backend)
This commit is contained in:
parent
513f9a8ee5
commit
8af873f0bd
19 changed files with 729 additions and 7 deletions
|
@ -9,6 +9,11 @@ SECRET_KEY=notsecretkey
|
|||
# TRUST_PROXY=0
|
||||
# TOKEN_EXPIRES_IN=365 # In days
|
||||
|
||||
# Uncomment for SAML login
|
||||
#SAML_CONFIG=[{"id": "sso", "name": "My SSO Provider", "idp": {"sso_login_url": "https://idp.example.com/sls", "sso_logout_url": "https://idp.example.com/slo", "certificates": "<PEM idp cert"}, "sp": {"entity_id": "http://localhost:3000/", "assert_endpoint": "http://localhost:1337/api/saml/sso/acs", "certificate": "<sp PEM cert>", "private_key": "<sp PEM key>"}, "bindings": {"username": "username", "full_name": "fullname", "email": "email", "admin": ["groups", "admin"]}}]
|
||||
|
||||
DISABLE_LOCAL_AUTH=0
|
||||
|
||||
## Do not edit this
|
||||
|
||||
TZ=UTC
|
||||
|
|
|
@ -10,6 +10,9 @@ const Errors = {
|
|||
INVALID_PASSWORD: {
|
||||
invalidPassword: 'Invalid password',
|
||||
},
|
||||
LOCAL_AUTH_DISABLED: {
|
||||
localAuthDisabled: 'Local authentication is disabled',
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
|
@ -37,9 +40,16 @@ module.exports = {
|
|||
invalidPassword: {
|
||||
responseType: 'unauthorized',
|
||||
},
|
||||
localAuthDisabled: {
|
||||
responseType: 'unauthorized',
|
||||
},
|
||||
},
|
||||
|
||||
async fn(inputs) {
|
||||
if (!sails.config.custom.localAuth) {
|
||||
throw Errors.LOCAL_AUTH_DISABLED;
|
||||
}
|
||||
|
||||
const remoteAddress = getRemoteAddress(this.req);
|
||||
|
||||
const user = await sails.helpers.users.getOneByEmailOrUsername(inputs.emailOrUsername);
|
||||
|
|
|
@ -1,16 +1,38 @@
|
|||
module.exports = {
|
||||
async fn() {
|
||||
const { accessToken } = this.req;
|
||||
const { accessToken, currentUser } = this.req;
|
||||
|
||||
await Session.updateOne({
|
||||
const session = await Session.updateOne({
|
||||
accessToken,
|
||||
deletedAt: null,
|
||||
}).set({
|
||||
deletedAt: new Date().toUTCString(),
|
||||
});
|
||||
|
||||
return {
|
||||
const result = {
|
||||
item: accessToken,
|
||||
};
|
||||
|
||||
if (currentUser.ssoId) {
|
||||
try {
|
||||
const { sp, idp } = await sails.helpers.saml.getConfig(currentUser.ssoId);
|
||||
|
||||
const ssoUrl = await new Promise((resolve, reject) => {
|
||||
sp.create_logout_request_url(idp, { session_index: session.sso_id }, (err, url) => {
|
||||
if (err) {
|
||||
reject();
|
||||
} else {
|
||||
resolve(url);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Object.assign(result, { ssoUrl });
|
||||
} catch (e) {
|
||||
// not saml or bad config
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
};
|
||||
|
|
8
server/api/controllers/authentication/index.js
Normal file
8
server/api/controllers/authentication/index.js
Normal file
|
@ -0,0 +1,8 @@
|
|||
module.exports = {
|
||||
async fn() {
|
||||
return {
|
||||
local: sails.config.custom.localAuth,
|
||||
saml: sails.config.custom.samlConfig.map((config) => _.pick(config, ['id', 'name'])),
|
||||
};
|
||||
},
|
||||
};
|
87
server/api/controllers/authentication/saml/acs.js
Normal file
87
server/api/controllers/authentication/saml/acs.js
Normal file
|
@ -0,0 +1,87 @@
|
|||
const { getRemoteAddress } = require('../../../../utils/remoteAddress');
|
||||
|
||||
const Errors = {
|
||||
INVALID_ID: {
|
||||
invalidId: 'Invalid authentication provider ID',
|
||||
},
|
||||
BAD_SAML_RESPONSE: {
|
||||
badSAMLResponse: 'Bad SAML response',
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
inputs: {
|
||||
id: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
},
|
||||
SAMLResponse: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
|
||||
exits: {
|
||||
invalidId: {
|
||||
responseType: 'notFound',
|
||||
},
|
||||
badSAMLResponse: {
|
||||
responseType: 'forbidden',
|
||||
},
|
||||
},
|
||||
|
||||
async fn(inputs) {
|
||||
const { sp, idp, bindings } = await sails.helpers.saml.getConfig(inputs.id);
|
||||
|
||||
const options = { request_body: { SAMLResponse: inputs.SAMLResponse } };
|
||||
|
||||
const response = await new Promise((resolve, reject) => {
|
||||
sp.post_assert(idp, options, (err, res) => {
|
||||
if (err !== null) {
|
||||
reject(Errors.BAD_SAML_RESPONSE);
|
||||
return;
|
||||
}
|
||||
resolve(res);
|
||||
});
|
||||
});
|
||||
|
||||
let user = await sails.helpers.users.getOne({
|
||||
ssoId: inputs.id,
|
||||
ssoName: response.user.name_id,
|
||||
});
|
||||
|
||||
const values = await sails.helpers.saml.parseAttributes(bindings, response.user.attributes);
|
||||
|
||||
if (user === undefined) {
|
||||
Object.assign(values, { ssoId: inputs.id, ssoName: response.user.name_id });
|
||||
user = await User.create(values);
|
||||
} else if (!_.isEqual(_.pick(user, Object.keys(values)), values)) {
|
||||
user = await User.updateOne(_.pick(user, ['id'])).set(values);
|
||||
}
|
||||
|
||||
const accessToken = sails.helpers.utils.createToken(user.id);
|
||||
|
||||
await Session.create({
|
||||
accessToken,
|
||||
remoteAddress: getRemoteAddress(this.req),
|
||||
userId: user.id,
|
||||
userAgent: this.req.headers['user-agent'],
|
||||
ssoId: response.user.session_index,
|
||||
});
|
||||
|
||||
this.res.cookie('accessToken', accessToken, {
|
||||
secure: true,
|
||||
sameSite: 'strict',
|
||||
maxAge: sails.config.custom.tokenExpiresIn * 86400000,
|
||||
});
|
||||
this.res.cookie('accessTokenVersion', 1, {
|
||||
secure: true,
|
||||
sameSite: 'strict',
|
||||
maxAge: sails.config.custom.tokenExpiresIn * 86400000,
|
||||
});
|
||||
|
||||
return this.res.redirect(
|
||||
sails.config.custom.baseUrl || (env.NODE_ENV === 'prod' ? '/' : 'http://localhost:3000/'),
|
||||
);
|
||||
},
|
||||
};
|
41
server/api/controllers/authentication/saml/login-request.js
Normal file
41
server/api/controllers/authentication/saml/login-request.js
Normal file
|
@ -0,0 +1,41 @@
|
|||
const Errors = {
|
||||
INVALID_ID: {
|
||||
invalidId: 'Invalid authentication provider ID',
|
||||
},
|
||||
BAD_CONFIGURATION: {
|
||||
badConfiguration: 'Bad SAML configuration',
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
inputs: {
|
||||
id: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
|
||||
exits: {
|
||||
invalidId: {
|
||||
responseType: 'notFound',
|
||||
},
|
||||
badConfiguration: {
|
||||
responseType: 'serverError',
|
||||
},
|
||||
},
|
||||
|
||||
async fn(inputs) {
|
||||
const { sp, idp } = await sails.helpers.saml.getConfig(inputs.id);
|
||||
|
||||
const url = await new Promise((resolve, reject) => {
|
||||
sp.create_login_request_url(idp, {}, (err, loginUrl) => {
|
||||
if (err != null) {
|
||||
reject(Errors.BAD_CONFIGURATION);
|
||||
}
|
||||
resolve(loginUrl);
|
||||
});
|
||||
});
|
||||
|
||||
return { item: url };
|
||||
},
|
||||
};
|
22
server/api/controllers/authentication/saml/metadata.js
Normal file
22
server/api/controllers/authentication/saml/metadata.js
Normal file
|
@ -0,0 +1,22 @@
|
|||
module.exports = {
|
||||
inputs: {
|
||||
id: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
|
||||
exits: {
|
||||
invalidId: {
|
||||
responseType: 'notFound',
|
||||
},
|
||||
},
|
||||
|
||||
async fn(inputs) {
|
||||
const { sp } = await sails.helpers.saml.getConfig(inputs.id);
|
||||
|
||||
this.res.setHeader('Content-Type', 'text/xml');
|
||||
|
||||
return sp.create_metadata();
|
||||
},
|
||||
};
|
29
server/api/helpers/saml/get-config.js
Normal file
29
server/api/helpers/saml/get-config.js
Normal file
|
@ -0,0 +1,29 @@
|
|||
const saml2 = require('saml2-js');
|
||||
|
||||
module.exports = {
|
||||
inputs: {
|
||||
id: {
|
||||
type: 'string',
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
|
||||
exits: {
|
||||
invalidId: {},
|
||||
},
|
||||
|
||||
async fn(inputs) {
|
||||
for (let i = 0, l = sails.config.custom.samlConfig.length; i < l; i += 1) {
|
||||
const config = sails.config.custom.samlConfig[i];
|
||||
if (config.id === inputs.id) {
|
||||
return {
|
||||
sp: new saml2.ServiceProvider(config.sp),
|
||||
idp: new saml2.IdentityProvider(config.idp),
|
||||
bindings: config.bindings,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
throw 'invalidId';
|
||||
},
|
||||
};
|
36
server/api/helpers/saml/parse-attributes.js
Normal file
36
server/api/helpers/saml/parse-attributes.js
Normal file
|
@ -0,0 +1,36 @@
|
|||
module.exports = {
|
||||
inputs: {
|
||||
bindings: {
|
||||
type: 'ref',
|
||||
required: true,
|
||||
},
|
||||
attributes: {
|
||||
type: 'ref',
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
|
||||
async fn({ bindings, attributes }) {
|
||||
const values = { password: 'SSO' };
|
||||
|
||||
if ('email' in bindings) {
|
||||
[values.email] = attributes[bindings.email];
|
||||
}
|
||||
|
||||
if ('full_name' in bindings) {
|
||||
[values.name] = attributes[bindings.full_name];
|
||||
} else if ('first_name' in bindings && 'last_name' in bindings) {
|
||||
values.name = `${attributes[bindings.first_name][0]} ${attributes[bindings.last_name][0]}`;
|
||||
}
|
||||
|
||||
if ('username' in bindings) {
|
||||
[values.username] = attributes[bindings.username];
|
||||
}
|
||||
|
||||
if ('admin' in bindings) {
|
||||
values.isAdmin = _.includes(attributes[bindings.admin[0]], bindings.admin[1]);
|
||||
}
|
||||
|
||||
return values;
|
||||
},
|
||||
};
|
|
@ -4,13 +4,21 @@ module.exports = {
|
|||
type: 'string',
|
||||
required: true,
|
||||
},
|
||||
includeSSOUsers: {
|
||||
type: 'boolean',
|
||||
defaultsTo: true,
|
||||
},
|
||||
},
|
||||
|
||||
async fn(inputs) {
|
||||
const fieldName = inputs.emailOrUsername.includes('@') ? 'email' : 'username';
|
||||
|
||||
return sails.helpers.users.getOne({
|
||||
[fieldName]: inputs.emailOrUsername.toLowerCase(),
|
||||
});
|
||||
const conditions = { [fieldName]: inputs.emailOrUsername.toLowerCase() };
|
||||
|
||||
if (includeSSOUsers) {
|
||||
conditions[ssoId] = null;
|
||||
}
|
||||
|
||||
return sails.helpers.users.getOne(conditions);
|
||||
},
|
||||
};
|
||||
|
|
|
@ -31,6 +31,10 @@ module.exports = {
|
|||
type: 'ref',
|
||||
columnName: 'deleted_at',
|
||||
},
|
||||
ssoId: {
|
||||
type: 'string',
|
||||
columnName: 'sso_id',
|
||||
},
|
||||
|
||||
// ╔═╗╔╦╗╔╗ ╔═╗╔╦╗╔═╗
|
||||
// ║╣ ║║║╠╩╗║╣ ║║╚═╗
|
||||
|
|
|
@ -71,6 +71,16 @@ module.exports = {
|
|||
type: 'ref',
|
||||
columnName: 'password_changed_at',
|
||||
},
|
||||
ssoId: {
|
||||
type: 'string',
|
||||
columnName: 'sso_id',
|
||||
allowNull: true,
|
||||
},
|
||||
ssoName: {
|
||||
type: 'string',
|
||||
columnName: 'sso_name',
|
||||
allowNull: true,
|
||||
},
|
||||
|
||||
// ╔═╗╔╦╗╔╗ ╔═╗╔╦╗╔═╗
|
||||
// ║╣ ║║║╠╩╗║╣ ║║╚═╗
|
||||
|
@ -106,7 +116,7 @@ module.exports = {
|
|||
|
||||
customToJSON() {
|
||||
return {
|
||||
..._.omit(this, ['password', 'avatarDirname', 'passwordChangedAt']),
|
||||
..._.omit(this, ['password', 'avatarDirname', 'passwordChangedAt', 'ssoName']),
|
||||
avatarUrl:
|
||||
this.avatarDirname &&
|
||||
`${sails.config.custom.userAvatarsUrl}/${this.avatarDirname}/square-100.jpg`,
|
||||
|
|
36
server/api/responses/serverError.js
Normal file
36
server/api/responses/serverError.js
Normal file
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
* serverError.js
|
||||
*
|
||||
* A custom response.
|
||||
*
|
||||
* Example usage:
|
||||
* ```
|
||||
* return res.serverError();
|
||||
* // -or-
|
||||
* return res.serverError(optionalData);
|
||||
* ```
|
||||
*
|
||||
* Or with actions2:
|
||||
* ```
|
||||
* exits: {
|
||||
* somethingHappened: {
|
||||
* responseType: 'serverError'
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* ```
|
||||
* throw 'somethingHappened';
|
||||
* // -or-
|
||||
* throw { somethingHappened: optionalData }
|
||||
* ```
|
||||
*/
|
||||
|
||||
module.exports = function serverError(message) {
|
||||
const { res } = this;
|
||||
|
||||
return res.status(500).json({
|
||||
code: 'E_SERVER_ERROR',
|
||||
message,
|
||||
});
|
||||
};
|
|
@ -30,4 +30,7 @@ module.exports.custom = {
|
|||
|
||||
attachmentsPath: path.join(sails.config.appPath, 'private', 'attachments'),
|
||||
attachmentsUrl: `${process.env.BASE_URL}/attachments`,
|
||||
|
||||
samlConfig: JSON.parse(process.env.SAML_CONFIG || '[]'),
|
||||
localAuth: !process.env.DISABLE_LOCAL_ENV,
|
||||
};
|
||||
|
|
|
@ -24,4 +24,8 @@ module.exports.policies = {
|
|||
'projects/create': ['is-authenticated', 'is-admin'],
|
||||
|
||||
'access-tokens/create': true,
|
||||
'authentication/saml/login-request': true,
|
||||
'authentication/saml/metadata': true,
|
||||
'authentication/saml/acs': true,
|
||||
'authentication/index': true,
|
||||
};
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
*/
|
||||
|
||||
module.exports.routes = {
|
||||
'GET /api/auth': 'authentication/index',
|
||||
|
||||
'POST /api/access-tokens': 'access-tokens/create',
|
||||
'DELETE /api/access-tokens/me': 'access-tokens/delete',
|
||||
|
||||
|
@ -77,6 +79,10 @@ module.exports.routes = {
|
|||
'GET /api/notifications/:id': 'notifications/show',
|
||||
'PATCH /api/notifications/:ids': 'notifications/update',
|
||||
|
||||
'GET /api/saml/:id/login': 'authentication/saml/login-request',
|
||||
'GET /api/saml/:id/metadata': 'authentication/saml/metadata',
|
||||
'POST /api/saml/:id/acs': 'authentication/saml/acs',
|
||||
|
||||
'GET /attachments/:id/download/:filename': {
|
||||
action: 'attachments/download',
|
||||
skipAssets: false,
|
||||
|
|
21
server/db/migrations/20221009201347_add_sso_fields.js
Normal file
21
server/db/migrations/20221009201347_add_sso_fields.js
Normal file
|
@ -0,0 +1,21 @@
|
|||
module.exports.up = async (knex) => {
|
||||
await knex.schema.table('user_account', (table) => {
|
||||
table.text('sso_id');
|
||||
table.text('sso_name');
|
||||
});
|
||||
|
||||
await knex.schema.table('session', (table) => {
|
||||
table.text('sso_id');
|
||||
});
|
||||
};
|
||||
|
||||
module.exports.down = (knex) => {
|
||||
knex.schema.table('user_account', (table) => {
|
||||
table.dropColumn('sso_id');
|
||||
table.dropColumn('sso_name');
|
||||
});
|
||||
|
||||
knex.schema.table('session', (table) => {
|
||||
table.dropColumn('sso_id');
|
||||
});
|
||||
};
|
368
server/package-lock.json
generated
368
server/package-lock.json
generated
|
@ -20,6 +20,7 @@
|
|||
"sails-hook-orm": "^4.0.1",
|
||||
"sails-hook-sockets": "^2.0.1",
|
||||
"sails-postgresql-redacted": "^1.0.2-9",
|
||||
"saml2-js": "^3.0.1",
|
||||
"sharp": "^0.30.7",
|
||||
"stream-to-array": "^2.3.0",
|
||||
"uuid": "^8.3.2",
|
||||
|
@ -120,6 +121,50 @@
|
|||
"node-pre-gyp": "bin/node-pre-gyp"
|
||||
}
|
||||
},
|
||||
"node_modules/@oozcitak/dom": {
|
||||
"version": "1.15.8",
|
||||
"resolved": "https://registry.npmjs.org/@oozcitak/dom/-/dom-1.15.8.tgz",
|
||||
"integrity": "sha512-MoOnLBNsF+ok0HjpAvxYxR4piUhRDCEWK0ot3upwOOHYudJd30j6M+LNcE8RKpwfnclAX9T66nXXzkytd29XSw==",
|
||||
"dependencies": {
|
||||
"@oozcitak/infra": "1.0.8",
|
||||
"@oozcitak/url": "1.0.4",
|
||||
"@oozcitak/util": "8.3.8"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@oozcitak/infra": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/@oozcitak/infra/-/infra-1.0.8.tgz",
|
||||
"integrity": "sha512-JRAUc9VR6IGHOL7OGF+yrvs0LO8SlqGnPAMqyzOuFZPSZSXI7Xf2O9+awQPSMXgIWGtgUf/dA6Hs6X6ySEaWTg==",
|
||||
"dependencies": {
|
||||
"@oozcitak/util": "8.3.8"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@oozcitak/url": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@oozcitak/url/-/url-1.0.4.tgz",
|
||||
"integrity": "sha512-kDcD8y+y3FCSOvnBI6HJgl00viO/nGbQoCINmQ0h98OhnGITrWR3bOGfwYCthgcrV8AnTJz8MzslTQbC3SOAmw==",
|
||||
"dependencies": {
|
||||
"@oozcitak/infra": "1.0.8",
|
||||
"@oozcitak/util": "8.3.8"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@oozcitak/util": {
|
||||
"version": "8.3.8",
|
||||
"resolved": "https://registry.npmjs.org/@oozcitak/util/-/util-8.3.8.tgz",
|
||||
"integrity": "sha512-T8TbSnGsxo6TDBJx/Sgv/BlVJL3tshxZP7Aq5R1mSnM5OcHY2dQaxLMu2+E8u3gN0MLOzdjurqN4ZRVuzQycOQ==",
|
||||
"engines": {
|
||||
"node": ">=8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@sailshq/binary-search-tree": {
|
||||
"version": "0.2.7",
|
||||
"resolved": "https://registry.npmjs.org/@sailshq/binary-search-tree/-/binary-search-tree-0.2.7.tgz",
|
||||
|
@ -156,12 +201,25 @@
|
|||
"integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "18.7.16",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.16.tgz",
|
||||
"integrity": "sha512-EQHhixfu+mkqHMZl1R2Ovuvn47PUw18azMJOTwSZr9/fhzHNGXAJ0ma0dayRVchprpCj0Kc1K1xKoWaATWF1qg=="
|
||||
},
|
||||
"node_modules/@ungap/promise-all-settled": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz",
|
||||
"integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@xmldom/xmldom": {
|
||||
"version": "0.7.5",
|
||||
"resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.7.5.tgz",
|
||||
"integrity": "sha512-V3BIhmY36fXZ1OtVcI9W+FxQqxVLsPKcNjWigIaa81dLC9IolJl5Mt4Cvhmr0flUnjSpTdrbMTSbXqYqV5dT6A==",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/abbrev": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
|
||||
|
@ -1929,6 +1987,18 @@
|
|||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/esprima": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
|
||||
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
|
||||
"bin": {
|
||||
"esparse": "bin/esparse.js",
|
||||
"esvalidate": "bin/esvalidate.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/esquery": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz",
|
||||
|
@ -4509,6 +4579,14 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/node-forge": {
|
||||
"version": "0.10.0",
|
||||
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz",
|
||||
"integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==",
|
||||
"engines": {
|
||||
"node": ">= 6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/nodemon": {
|
||||
"version": "2.0.19",
|
||||
"resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.19.tgz",
|
||||
|
@ -6142,6 +6220,34 @@
|
|||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/saml2-js": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/saml2-js/-/saml2-js-3.0.1.tgz",
|
||||
"integrity": "sha512-wRiRUg1M+1Tae6Tcc6Ccps4dQZOu7obrTM86IaZzkCdLULsjjP921SCItAihy1KHGpMCUWlIBFpfxcJibT8u2g==",
|
||||
"dependencies": {
|
||||
"async": "^3.2.0",
|
||||
"debug": "^4.3.0",
|
||||
"underscore": "^1.8.0",
|
||||
"xml-crypto": "^2.0.0",
|
||||
"xml-encryption": "^1.2.1",
|
||||
"xml2js": "^0.4.0",
|
||||
"xmlbuilder2": "^2.4.0",
|
||||
"xmldom": "^0.4.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.x"
|
||||
}
|
||||
},
|
||||
"node_modules/saml2-js/node_modules/async": {
|
||||
"version": "3.2.4",
|
||||
"resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz",
|
||||
"integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ=="
|
||||
},
|
||||
"node_modules/sax": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
|
||||
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
|
||||
},
|
||||
"node_modules/semver": {
|
||||
"version": "7.3.7",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
|
||||
|
@ -7897,6 +8003,101 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/xml-crypto": {
|
||||
"version": "2.1.4",
|
||||
"resolved": "https://registry.npmjs.org/xml-crypto/-/xml-crypto-2.1.4.tgz",
|
||||
"integrity": "sha512-ModFeGOy67L/XXHcuepnYGF7DASEDw7fhvy+qIs1ORoH55G1IIr+fN0kaMtttwvmNFFMskD9AHro8wx352/mUg==",
|
||||
"dependencies": {
|
||||
"@xmldom/xmldom": "^0.7.0",
|
||||
"xpath": "0.0.32"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/xml-encryption": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/xml-encryption/-/xml-encryption-1.3.0.tgz",
|
||||
"integrity": "sha512-3P8C4egMMxSR1BmsRM+fG16a3WzOuUEQKS2U4c3AZ5v7OseIfdUeVkD8dwxIhuLryFZSRWUL5OP6oqkgU7hguA==",
|
||||
"dependencies": {
|
||||
"@xmldom/xmldom": "^0.7.0",
|
||||
"escape-html": "^1.0.3",
|
||||
"node-forge": "^0.10.0",
|
||||
"xpath": "0.0.32"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/xml2js": {
|
||||
"version": "0.4.23",
|
||||
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz",
|
||||
"integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==",
|
||||
"dependencies": {
|
||||
"sax": ">=0.6.0",
|
||||
"xmlbuilder": "~11.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/xmlbuilder": {
|
||||
"version": "11.0.1",
|
||||
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz",
|
||||
"integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==",
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/xmlbuilder2": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/xmlbuilder2/-/xmlbuilder2-2.4.1.tgz",
|
||||
"integrity": "sha512-vliUplZsk5vJnhxXN/mRcij/AE24NObTUm/Zo4vkLusgayO6s3Et5zLEA14XZnY1c3hX5o1ToR0m0BJOPy0UvQ==",
|
||||
"dependencies": {
|
||||
"@oozcitak/dom": "1.15.8",
|
||||
"@oozcitak/infra": "1.0.8",
|
||||
"@oozcitak/util": "8.3.8",
|
||||
"@types/node": "*",
|
||||
"js-yaml": "3.14.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/xmlbuilder2/node_modules/argparse": {
|
||||
"version": "1.0.10",
|
||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
|
||||
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
|
||||
"dependencies": {
|
||||
"sprintf-js": "~1.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/xmlbuilder2/node_modules/js-yaml": {
|
||||
"version": "3.14.0",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz",
|
||||
"integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==",
|
||||
"dependencies": {
|
||||
"argparse": "^1.0.7",
|
||||
"esprima": "^4.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"js-yaml": "bin/js-yaml.js"
|
||||
}
|
||||
},
|
||||
"node_modules/xmlbuilder2/node_modules/sprintf-js": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
|
||||
"integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="
|
||||
},
|
||||
"node_modules/xmldom": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.4.0.tgz",
|
||||
"integrity": "sha512-2E93k08T30Ugs+34HBSTQLVtpi6mCddaY8uO+pMNk1pqSjV5vElzn4mmh6KLxN3hki8rNcHSYzILoh3TEWORvA==",
|
||||
"deprecated": "Deprecated due to CVE-2021-21366 resolved in 0.5.0",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/xmlhttprequest-ssl": {
|
||||
"version": "1.6.3",
|
||||
"resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.6.3.tgz",
|
||||
|
@ -7905,6 +8106,14 @@
|
|||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/xpath": {
|
||||
"version": "0.0.32",
|
||||
"resolved": "https://registry.npmjs.org/xpath/-/xpath-0.0.32.tgz",
|
||||
"integrity": "sha512-rxMJhSIoiO8vXcWvSifKqhvV96GjiD5wYb8/QHdoRyQvraTpp4IEv944nhGausZZ3u7dhQXteZuZbaqfpB7uYw==",
|
||||
"engines": {
|
||||
"node": ">=0.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/xtend": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
||||
|
@ -8058,6 +8267,38 @@
|
|||
"tar": "^6.1.11"
|
||||
}
|
||||
},
|
||||
"@oozcitak/dom": {
|
||||
"version": "1.15.8",
|
||||
"resolved": "https://registry.npmjs.org/@oozcitak/dom/-/dom-1.15.8.tgz",
|
||||
"integrity": "sha512-MoOnLBNsF+ok0HjpAvxYxR4piUhRDCEWK0ot3upwOOHYudJd30j6M+LNcE8RKpwfnclAX9T66nXXzkytd29XSw==",
|
||||
"requires": {
|
||||
"@oozcitak/infra": "1.0.8",
|
||||
"@oozcitak/url": "1.0.4",
|
||||
"@oozcitak/util": "8.3.8"
|
||||
}
|
||||
},
|
||||
"@oozcitak/infra": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/@oozcitak/infra/-/infra-1.0.8.tgz",
|
||||
"integrity": "sha512-JRAUc9VR6IGHOL7OGF+yrvs0LO8SlqGnPAMqyzOuFZPSZSXI7Xf2O9+awQPSMXgIWGtgUf/dA6Hs6X6ySEaWTg==",
|
||||
"requires": {
|
||||
"@oozcitak/util": "8.3.8"
|
||||
}
|
||||
},
|
||||
"@oozcitak/url": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@oozcitak/url/-/url-1.0.4.tgz",
|
||||
"integrity": "sha512-kDcD8y+y3FCSOvnBI6HJgl00viO/nGbQoCINmQ0h98OhnGITrWR3bOGfwYCthgcrV8AnTJz8MzslTQbC3SOAmw==",
|
||||
"requires": {
|
||||
"@oozcitak/infra": "1.0.8",
|
||||
"@oozcitak/util": "8.3.8"
|
||||
}
|
||||
},
|
||||
"@oozcitak/util": {
|
||||
"version": "8.3.8",
|
||||
"resolved": "https://registry.npmjs.org/@oozcitak/util/-/util-8.3.8.tgz",
|
||||
"integrity": "sha512-T8TbSnGsxo6TDBJx/Sgv/BlVJL3tshxZP7Aq5R1mSnM5OcHY2dQaxLMu2+E8u3gN0MLOzdjurqN4ZRVuzQycOQ=="
|
||||
},
|
||||
"@sailshq/binary-search-tree": {
|
||||
"version": "0.2.7",
|
||||
"resolved": "https://registry.npmjs.org/@sailshq/binary-search-tree/-/binary-search-tree-0.2.7.tgz",
|
||||
|
@ -8096,12 +8337,22 @@
|
|||
"integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "18.7.16",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.16.tgz",
|
||||
"integrity": "sha512-EQHhixfu+mkqHMZl1R2Ovuvn47PUw18azMJOTwSZr9/fhzHNGXAJ0ma0dayRVchprpCj0Kc1K1xKoWaATWF1qg=="
|
||||
},
|
||||
"@ungap/promise-all-settled": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz",
|
||||
"integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==",
|
||||
"dev": true
|
||||
},
|
||||
"@xmldom/xmldom": {
|
||||
"version": "0.7.5",
|
||||
"resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.7.5.tgz",
|
||||
"integrity": "sha512-V3BIhmY36fXZ1OtVcI9W+FxQqxVLsPKcNjWigIaa81dLC9IolJl5Mt4Cvhmr0flUnjSpTdrbMTSbXqYqV5dT6A=="
|
||||
},
|
||||
"abbrev": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
|
||||
|
@ -9491,6 +9742,11 @@
|
|||
"eslint-visitor-keys": "^3.3.0"
|
||||
}
|
||||
},
|
||||
"esprima": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
|
||||
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="
|
||||
},
|
||||
"esquery": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz",
|
||||
|
@ -11475,6 +11731,11 @@
|
|||
"whatwg-url": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"node-forge": {
|
||||
"version": "0.10.0",
|
||||
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz",
|
||||
"integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA=="
|
||||
},
|
||||
"nodemon": {
|
||||
"version": "2.0.19",
|
||||
"resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.19.tgz",
|
||||
|
@ -12751,6 +13012,33 @@
|
|||
"resolved": "https://registry.npmjs.org/sails.io.js-dist/-/sails.io.js-dist-1.2.1.tgz",
|
||||
"integrity": "sha512-fBMdntawlqd5N/1xL9Vu6l+J5zvy86jLUf0nFDal5McUeZzUy7PpNqq+Vx/F9KgItAyFJ7RoO3YltO9dD0Q5OQ=="
|
||||
},
|
||||
"saml2-js": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/saml2-js/-/saml2-js-3.0.1.tgz",
|
||||
"integrity": "sha512-wRiRUg1M+1Tae6Tcc6Ccps4dQZOu7obrTM86IaZzkCdLULsjjP921SCItAihy1KHGpMCUWlIBFpfxcJibT8u2g==",
|
||||
"requires": {
|
||||
"async": "^3.2.0",
|
||||
"debug": "^4.3.0",
|
||||
"underscore": "^1.8.0",
|
||||
"xml-crypto": "^2.0.0",
|
||||
"xml-encryption": "^1.2.1",
|
||||
"xml2js": "^0.4.0",
|
||||
"xmlbuilder2": "^2.4.0",
|
||||
"xmldom": "^0.4.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"async": {
|
||||
"version": "3.2.4",
|
||||
"resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz",
|
||||
"integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"sax": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
|
||||
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
|
||||
},
|
||||
"semver": {
|
||||
"version": "7.3.7",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
|
||||
|
@ -14186,11 +14474,91 @@
|
|||
"integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==",
|
||||
"requires": {}
|
||||
},
|
||||
"xml-crypto": {
|
||||
"version": "2.1.4",
|
||||
"resolved": "https://registry.npmjs.org/xml-crypto/-/xml-crypto-2.1.4.tgz",
|
||||
"integrity": "sha512-ModFeGOy67L/XXHcuepnYGF7DASEDw7fhvy+qIs1ORoH55G1IIr+fN0kaMtttwvmNFFMskD9AHro8wx352/mUg==",
|
||||
"requires": {
|
||||
"@xmldom/xmldom": "^0.7.0",
|
||||
"xpath": "0.0.32"
|
||||
}
|
||||
},
|
||||
"xml-encryption": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/xml-encryption/-/xml-encryption-1.3.0.tgz",
|
||||
"integrity": "sha512-3P8C4egMMxSR1BmsRM+fG16a3WzOuUEQKS2U4c3AZ5v7OseIfdUeVkD8dwxIhuLryFZSRWUL5OP6oqkgU7hguA==",
|
||||
"requires": {
|
||||
"@xmldom/xmldom": "^0.7.0",
|
||||
"escape-html": "^1.0.3",
|
||||
"node-forge": "^0.10.0",
|
||||
"xpath": "0.0.32"
|
||||
}
|
||||
},
|
||||
"xml2js": {
|
||||
"version": "0.4.23",
|
||||
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz",
|
||||
"integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==",
|
||||
"requires": {
|
||||
"sax": ">=0.6.0",
|
||||
"xmlbuilder": "~11.0.0"
|
||||
}
|
||||
},
|
||||
"xmlbuilder": {
|
||||
"version": "11.0.1",
|
||||
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz",
|
||||
"integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA=="
|
||||
},
|
||||
"xmlbuilder2": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/xmlbuilder2/-/xmlbuilder2-2.4.1.tgz",
|
||||
"integrity": "sha512-vliUplZsk5vJnhxXN/mRcij/AE24NObTUm/Zo4vkLusgayO6s3Et5zLEA14XZnY1c3hX5o1ToR0m0BJOPy0UvQ==",
|
||||
"requires": {
|
||||
"@oozcitak/dom": "1.15.8",
|
||||
"@oozcitak/infra": "1.0.8",
|
||||
"@oozcitak/util": "8.3.8",
|
||||
"@types/node": "*",
|
||||
"js-yaml": "3.14.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"argparse": {
|
||||
"version": "1.0.10",
|
||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
|
||||
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
|
||||
"requires": {
|
||||
"sprintf-js": "~1.0.2"
|
||||
}
|
||||
},
|
||||
"js-yaml": {
|
||||
"version": "3.14.0",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz",
|
||||
"integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==",
|
||||
"requires": {
|
||||
"argparse": "^1.0.7",
|
||||
"esprima": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"sprintf-js": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
|
||||
"integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"xmldom": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.4.0.tgz",
|
||||
"integrity": "sha512-2E93k08T30Ugs+34HBSTQLVtpi6mCddaY8uO+pMNk1pqSjV5vElzn4mmh6KLxN3hki8rNcHSYzILoh3TEWORvA=="
|
||||
},
|
||||
"xmlhttprequest-ssl": {
|
||||
"version": "1.6.3",
|
||||
"resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.6.3.tgz",
|
||||
"integrity": "sha512-3XfeQE/wNkvrIktn2Kf0869fC0BN6UpydVasGIeSm2B1Llihf7/0UfZM+eCkOw3P7bP4+qPgqhm7ZoxuJtFU0Q=="
|
||||
},
|
||||
"xpath": {
|
||||
"version": "0.0.32",
|
||||
"resolved": "https://registry.npmjs.org/xpath/-/xpath-0.0.32.tgz",
|
||||
"integrity": "sha512-rxMJhSIoiO8vXcWvSifKqhvV96GjiD5wYb8/QHdoRyQvraTpp4IEv944nhGausZZ3u7dhQXteZuZbaqfpB7uYw=="
|
||||
},
|
||||
"xtend": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
"db:migrate": "knex migrate:latest --cwd db",
|
||||
"db:seed": "knex seed:run --cwd db",
|
||||
"lint": "eslint . --max-warnings=0 --report-unused-disable-directives && echo '✔ Your .js files look good.'",
|
||||
"lint-fix": "eslint . --max-warnings=0 --report-unused-disable-directives --fix && echo 'looks good'",
|
||||
"start": "nodemon",
|
||||
"start:prod": "node app.js --prod",
|
||||
"test": "mocha test/lifecycle.test.js test/integration/**/*.test.js test/utils/**/*.test.js"
|
||||
|
@ -52,6 +53,7 @@
|
|||
"sails-hook-orm": "^4.0.1",
|
||||
"sails-hook-sockets": "^2.0.1",
|
||||
"sails-postgresql-redacted": "^1.0.2-9",
|
||||
"saml2-js": "^3.0.1",
|
||||
"sharp": "^0.30.7",
|
||||
"stream-to-array": "^2.3.0",
|
||||
"uuid": "^8.3.2",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue