14 changed files with 598 additions and 3 deletions
@ -0,0 +1,60 @@ |
|||||
|
// admin/content-report.js
|
||||
|
// Copyright (C) 2022 DTP Technologies, LLC
|
||||
|
// License: Apache-2.0
|
||||
|
|
||||
|
'use strict'; |
||||
|
|
||||
|
const DTP_COMPONENT_NAME = 'admin:content-report'; |
||||
|
|
||||
|
const express = require('express'); |
||||
|
// const multer = require('multer');
|
||||
|
|
||||
|
const { /*SiteError,*/ SiteController } = require('../../../lib/site-lib'); |
||||
|
|
||||
|
class CoreNodeController extends SiteController { |
||||
|
|
||||
|
constructor (dtp) { |
||||
|
super(dtp, DTP_COMPONENT_NAME); |
||||
|
} |
||||
|
|
||||
|
async start ( ) { |
||||
|
// const upload = multer({ dest: `/tmp/${this.dtp.config.site.domainKey}/upload` });
|
||||
|
|
||||
|
const router = express.Router(); |
||||
|
router.use(async (req, res, next) => { |
||||
|
res.locals.currentView = 'admin'; |
||||
|
res.locals.adminView = 'core-node'; |
||||
|
return next(); |
||||
|
}); |
||||
|
|
||||
|
router.post('/connect', this.postCoreNodeConnect.bind(this)); |
||||
|
router.get('/connect', this.getCoreNodeConnectForm.bind(this)); |
||||
|
|
||||
|
router.get('/', this.getIndex.bind(this)); |
||||
|
|
||||
|
return router; |
||||
|
} |
||||
|
|
||||
|
async postCoreNodeConnect (req, res, next) { |
||||
|
// const { coreNode: coreNodeService } = this.dtp.services;
|
||||
|
try { |
||||
|
|
||||
|
} catch (error) { |
||||
|
this.log.error('failed to create Core Node connection request', { error }); |
||||
|
return next(error); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
async getCoreNodeConnectForm (req, res) { |
||||
|
res.render('admin/core-node/connect'); |
||||
|
} |
||||
|
|
||||
|
async getIndex (req, res) { |
||||
|
res.render('admin/core-node/index'); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
module.exports = async (dtp) => { |
||||
|
let controller = new CoreNodeController(dtp); |
||||
|
return controller; |
||||
|
}; |
@ -0,0 +1,64 @@ |
|||||
|
// hive.js
|
||||
|
// Copyright (C) 2022 DTP Technologies, LLC
|
||||
|
// License: Apache-2.0
|
||||
|
|
||||
|
'use strict'; |
||||
|
|
||||
|
const DTP_COMPONENT_NAME = 'hive'; |
||||
|
|
||||
|
const path = require('path'); |
||||
|
const express = require('express'); |
||||
|
|
||||
|
const { SiteController } = require('../../lib/site-lib'); |
||||
|
|
||||
|
class HiveController extends SiteController { |
||||
|
|
||||
|
constructor (dtp) { |
||||
|
super(dtp, DTP_COMPONENT_NAME); |
||||
|
this.services = [ ]; |
||||
|
} |
||||
|
|
||||
|
async start ( ) { |
||||
|
const router = express.Router(); |
||||
|
this.dtp.app.use('/hive', router); |
||||
|
|
||||
|
router.use( |
||||
|
async (req, res, next) => { |
||||
|
res.locals.currentView = 'hive'; |
||||
|
res.locals.hiveView = 'home'; |
||||
|
|
||||
|
/* |
||||
|
* TODO: H1V3 authentication before processing request (HTTP Bearer token) |
||||
|
*/ |
||||
|
|
||||
|
return next(); |
||||
|
}, |
||||
|
); |
||||
|
|
||||
|
router.use('/kaleidoscope',await this.loadChild(path.join(__dirname, 'hive', 'kaleidoscope'))); |
||||
|
this.services.push({ name: 'kaleidoscope', url: '/hive/kaleidoscope' }); |
||||
|
|
||||
|
router.get('/', this.getHiveRoot.bind(this)); |
||||
|
|
||||
|
return router; |
||||
|
} |
||||
|
|
||||
|
async getHiveRoot (req, res) { |
||||
|
res.status(200).json({ |
||||
|
component: DTP_COMPONENT_NAME, |
||||
|
host: this.dtp.pkg.name, |
||||
|
description: this.dtp.pkg.description, |
||||
|
version: this.dtp.pkg.version, |
||||
|
services: this.services, |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
module.exports = { |
||||
|
slug: 'hive', |
||||
|
name: 'hive', |
||||
|
create: async (dtp) => { |
||||
|
let controller = new HiveController(dtp); |
||||
|
return controller; |
||||
|
}, |
||||
|
}; |
@ -0,0 +1,72 @@ |
|||||
|
// hive/kaleidoscope.js
|
||||
|
// Copyright (C) 2022 DTP Technologies, LLC
|
||||
|
// License: Apache-2.0
|
||||
|
|
||||
|
'use strict'; |
||||
|
|
||||
|
const DTP_COMPONENT_NAME = 'hive:kaleidoscope'; |
||||
|
|
||||
|
const express = require('express'); |
||||
|
|
||||
|
const { SiteController } = require('../../../lib/site-lib'); |
||||
|
|
||||
|
class HostController extends SiteController { |
||||
|
|
||||
|
constructor (dtp) { |
||||
|
super(dtp, DTP_COMPONENT_NAME); |
||||
|
|
||||
|
this.methods = [ |
||||
|
{ |
||||
|
name: 'postEvent', |
||||
|
url: '/kaleidoscope/event', |
||||
|
method: 'POST', |
||||
|
}, |
||||
|
]; |
||||
|
} |
||||
|
|
||||
|
async start ( ) { |
||||
|
const router = express.Router(); |
||||
|
router.use(async (req, res, next) => { |
||||
|
res.locals.currentView = 'hive'; |
||||
|
res.locals.hiveView = 'kaleidoscope'; |
||||
|
return next(); |
||||
|
}); |
||||
|
|
||||
|
router.post('/core-node/connect', this.postCoreNodeConnect.bind(this)); |
||||
|
router.post('/event', this.postEvent.bind(this)); |
||||
|
|
||||
|
router.get('/', this.getKaleidoscopeRoot.bind(this)); |
||||
|
|
||||
|
return router; |
||||
|
} |
||||
|
|
||||
|
async postCoreNodeConnect (req, res, next) { |
||||
|
const { coreNode: coreNodeService } = this.dtp.services; |
||||
|
try { |
||||
|
await coreNodeService.connect(req.body); |
||||
|
} catch (error) { |
||||
|
this.log.error('failed to create Core Node connection', { error }); |
||||
|
return next(error); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
async postEvent (req, res) { |
||||
|
this.log.debug('kaleidoscope event received', { event: req.body.event }); |
||||
|
this.emit('kaleidoscope:event', req, res); |
||||
|
res.status(200).json({ success: true }); |
||||
|
} |
||||
|
|
||||
|
async getKaleidoscopeRoot (req, res) { |
||||
|
res.status(200).json({ |
||||
|
component: DTP_COMPONENT_NAME, |
||||
|
version: this.dtp.pkg.version, |
||||
|
services: this.services, |
||||
|
methods: this.methods, |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
module.exports = async (dtp) => { |
||||
|
let controller = new HostController(dtp); |
||||
|
return controller; |
||||
|
}; |
@ -0,0 +1,37 @@ |
|||||
|
// core-node-request.js
|
||||
|
// Copyright (C) 2022 DTP Technologies, LLC
|
||||
|
// License: Apache-2.0
|
||||
|
|
||||
|
'use strict'; |
||||
|
|
||||
|
const mongoose = require('mongoose'); |
||||
|
const Schema = mongoose.Schema; |
||||
|
|
||||
|
/* |
||||
|
* Used for authenticating responses received and gathering performance and use |
||||
|
* metrics for communications with Cores. |
||||
|
* |
||||
|
* When a request is created, an authentication token is generated and |
||||
|
* information about the request is stored. This also provides the request ID. |
||||
|
* |
||||
|
* When a resonse is received for a request, this record is fetched. The token |
||||
|
* claimed status and value are checked. Information about the response is |
||||
|
* recorded, and request execution time information is recorded. |
||||
|
*/ |
||||
|
|
||||
|
const CoreNodeRequestSchema = new Schema({ |
||||
|
created: { type: Date, default: Date.now, required: true, index: 1 }, |
||||
|
core: { type: Schema.ObjectId, required: true, ref: 'CoreNode' }, |
||||
|
token: { |
||||
|
value: { type: String, required: true }, |
||||
|
claimed: { type: Boolean, default: false, required: true }, |
||||
|
}, |
||||
|
url: { type: String }, |
||||
|
response: { |
||||
|
received: { type: Date }, |
||||
|
elapsed: { type: Number }, |
||||
|
isError: { type: Boolean, default: false }, |
||||
|
}, |
||||
|
}); |
||||
|
|
||||
|
module.exports = mongoose.model('CoreNodeRequest', CoreNodeRequestSchema); |
@ -0,0 +1,18 @@ |
|||||
|
// core-node.js
|
||||
|
// Copyright (C) 2022 DTP Technologies, LLC
|
||||
|
// License: Apache-2.0
|
||||
|
|
||||
|
'use strict'; |
||||
|
|
||||
|
const mongoose = require('mongoose'); |
||||
|
const Schema = mongoose.Schema; |
||||
|
|
||||
|
const CoreNodeSchema = new Schema({ |
||||
|
created: { type: Date, default: Date.now, required: true, index: 1 }, |
||||
|
address: { |
||||
|
host: { type: String, required: true }, |
||||
|
port: { type: Number, min: 1, max: 65535, required: true }, |
||||
|
}, |
||||
|
}); |
||||
|
|
||||
|
module.exports = mongoose.model('CoreNode', CoreNodeSchema); |
@ -0,0 +1,97 @@ |
|||||
|
// core-node.js
|
||||
|
// Copyright (C) 2022 DTP Technologies, LLC
|
||||
|
// License: Apache-2.0
|
||||
|
|
||||
|
'use strict'; |
||||
|
|
||||
|
const uuidv4 = require('uuid').v4; |
||||
|
|
||||
|
const mongoose = require('mongoose'); |
||||
|
const fetch = require('node-fetch'); // jshint ignore:line
|
||||
|
|
||||
|
const CoreNode = mongoose.model('CoreNode'); |
||||
|
const CoreNodeRequest = mongoose.model('CoreNodeRequest'); |
||||
|
|
||||
|
const { SiteService, SiteError } = require('../../lib/site-lib'); |
||||
|
|
||||
|
class CoreNodeService extends SiteService { |
||||
|
|
||||
|
constructor (dtp) { |
||||
|
super(dtp, module.exports); |
||||
|
} |
||||
|
|
||||
|
async create (coreDefinition) { |
||||
|
const core = new CoreNode(); |
||||
|
core.created = new Date(); |
||||
|
|
||||
|
core.address = { }; |
||||
|
|
||||
|
if (!coreDefinition.host) { |
||||
|
throw new SiteError(406, 'Must provide Core Node host address'); |
||||
|
} |
||||
|
core.address.host = coreDefinition.host.trim(); |
||||
|
|
||||
|
if (!coreDefinition.port) { |
||||
|
throw new SiteError(406, 'Must provide Core Node TCP port number'); |
||||
|
} |
||||
|
|
||||
|
coreDefinition.port = parseInt(coreDefinition.port, 10); |
||||
|
if (coreDefinition.port < 1 || coreDefinition.port > 65535) { |
||||
|
throw new SiteError(406, 'Core Node port number out of range'); |
||||
|
} |
||||
|
|
||||
|
await core.save(); |
||||
|
|
||||
|
return core.toObject(); |
||||
|
} |
||||
|
|
||||
|
async broadcast (request) { |
||||
|
const results = [ ]; |
||||
|
await CoreNode |
||||
|
.find() |
||||
|
.cursor() |
||||
|
.eachAsync(async (core) => { |
||||
|
try { |
||||
|
const response = await this.sendRequest(core, request); |
||||
|
results.push({ coreId: core._id, request, response }); |
||||
|
} catch (error) { |
||||
|
this.log.error('failed to send Core Node request', { core: core._id, request: request.url, error }); |
||||
|
} |
||||
|
}); |
||||
|
return results; |
||||
|
} |
||||
|
|
||||
|
async sendRequest (core, request) { |
||||
|
const requestUrl = `https://${core.address.host}:${core.address.port}${request.url}`; |
||||
|
|
||||
|
const req = new CoreNodeRequest(); |
||||
|
req.created = new Date(); |
||||
|
req.core = core._id; |
||||
|
req.token = { |
||||
|
value: uuidv4(), |
||||
|
claimed: false, |
||||
|
}; |
||||
|
req.url = request.url; |
||||
|
await req.save(); |
||||
|
|
||||
|
try { |
||||
|
const response = await fetch(requestUrl, { |
||||
|
method: request.method, |
||||
|
body: request.body, |
||||
|
}); |
||||
|
const json = await response.json(); |
||||
|
return { request: req.toObject(), response: json }; |
||||
|
} catch (error) { |
||||
|
this.log.error('failed to send Core Node request', { core: core._id, request: request.url, error }); |
||||
|
throw error; |
||||
|
} |
||||
|
|
||||
|
return req.toObject(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
module.exports = { |
||||
|
slug: 'core-node', |
||||
|
name: 'coreNode', |
||||
|
create: (dtp) => { return new CoreNodeService(dtp); }, |
||||
|
}; |
@ -0,0 +1,191 @@ |
|||||
|
// oauth2.js
|
||||
|
// Copyright (C) 2022 DTP Technologies, LLC
|
||||
|
// License: Apache-2.0
|
||||
|
|
||||
|
'use strict'; |
||||
|
|
||||
|
const passport = require('passport'); |
||||
|
|
||||
|
const mongoose = require('mongoose'); |
||||
|
const Schema = mongoose.Schema; |
||||
|
|
||||
|
const uuidv4 = require('uuid').v4; |
||||
|
const oauth2orize = require('oauth2orize'); |
||||
|
|
||||
|
const { SiteService/*, SiteError*/ } = require('../../lib/site-lib'); |
||||
|
|
||||
|
class OAuth2Service extends SiteService { |
||||
|
|
||||
|
constructor (dtp) { |
||||
|
super(dtp, module.exports); |
||||
|
} |
||||
|
|
||||
|
async start ( ) { |
||||
|
this.models = { }; |
||||
|
|
||||
|
/* |
||||
|
* OAuth2Client Model |
||||
|
*/ |
||||
|
const ClientSchema = new Schema({ |
||||
|
created: { type: Date, default: Date.now, required: true }, |
||||
|
updated: { type: Date, default: Date.now, required: true }, |
||||
|
secret: { type: String, required: true }, |
||||
|
redirectURI: { type: String, required: true }, |
||||
|
}); |
||||
|
this.log.info('registering OAuth2Client model'); |
||||
|
this.models.Client = mongoose.model('OAuth2Client', ClientSchema); |
||||
|
|
||||
|
/* |
||||
|
* OAuth2AuthorizationCode model |
||||
|
*/ |
||||
|
const AuthorizationCodeSchema = new Schema({ |
||||
|
code: { type: String, required: true, index: 1 }, |
||||
|
clientId: { type: Schema.ObjectId, required: true, index: 1 }, |
||||
|
redirectURI: { type: String, required: true }, |
||||
|
user: { type: Schema.ObjectId, required: true, index: 1 }, |
||||
|
scope: { type: [String], required: true }, |
||||
|
}); |
||||
|
this.log.info('registering OAuth2AuthorizationCode model'); |
||||
|
this.models.AuthorizationCode = mongoose.model('OAuth2AuthorizationCode', AuthorizationCodeSchema); |
||||
|
|
||||
|
/* |
||||
|
* OAuth2AccessToken model |
||||
|
*/ |
||||
|
const AccessTokenSchema = new Schema({ |
||||
|
token: { type: String, required: true, unique: true, index: 1 }, |
||||
|
user: { type: Schema.ObjectId, required: true, index: 1 }, |
||||
|
clientId: { type: Schema.ObjectId, required: true, index: 1 }, |
||||
|
scope: { type: [String], required: true }, |
||||
|
}); |
||||
|
this.log.info('registering OAuth2AccessToken model'); |
||||
|
this.models.AccessToken = mongoose.model('OAuth2AccessToken', AccessTokenSchema); |
||||
|
|
||||
|
/* |
||||
|
* Create OAuth2 server instance |
||||
|
*/ |
||||
|
const options = { }; |
||||
|
this.log.info('creating OAuth2 server instance', { options }); |
||||
|
this.server = oauth2orize.createServer(options); |
||||
|
this.server.grant(oauth2orize.grant.code(this.processGrant.bind(this))); |
||||
|
this.server.exchange(oauth2orize.exchange.code(this.processExchange.bind(this))); |
||||
|
|
||||
|
/* |
||||
|
* Register client serialization callbacks |
||||
|
*/ |
||||
|
this.log.info('registering OAuth2 client serialization routines'); |
||||
|
this.server.serializeClient(this.serializeClient.bind(this)); |
||||
|
this.server.deserializeClient(this.deserializeClient.bind(this)); |
||||
|
} |
||||
|
|
||||
|
async serializeClient (client, done) { |
||||
|
return done(null, client.id); |
||||
|
} |
||||
|
|
||||
|
async deserializeClient (clientId, done) { |
||||
|
try { |
||||
|
const client = await this.models.Client.findOne({ _id: clientId }).lean(); |
||||
|
return done(null, client); |
||||
|
} catch (error) { |
||||
|
this.log.error('failed to deserialize OAuth2 client', { clientId, error }); |
||||
|
return done(error); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
attachRoutes (app) { |
||||
|
const { session: sessionService } = this.dtp.services; |
||||
|
|
||||
|
const requireLogin = sessionService.authCheckMiddleware({ requireLogin: true }); |
||||
|
|
||||
|
app.get( |
||||
|
'/dialog/authorize', |
||||
|
requireLogin, |
||||
|
this.server.authorize(this.processAuthorize.bind(this)), |
||||
|
this.renderAuthorizeDialog.bind(this), |
||||
|
); |
||||
|
|
||||
|
app.post( |
||||
|
'/dialog/authorize/decision', |
||||
|
requireLogin, |
||||
|
this.server.decision(), |
||||
|
); |
||||
|
|
||||
|
app.post( |
||||
|
'/token', |
||||
|
passport.authenticate(['basic', 'oauth2-client-password'], { session: false }), |
||||
|
this.server.token(), |
||||
|
this.server.errorHandler(), |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
async renderAuthorizeDialog (req, res) { |
||||
|
res.locals.transactionID = req.oauth2.transactionID; |
||||
|
res.locals.client = req.oauth2.client; |
||||
|
res.render('oauth2/authorize-dialog'); |
||||
|
} |
||||
|
|
||||
|
async processAuthorize (clientID, redirectURI, done) { |
||||
|
try { |
||||
|
const client = await this.models.Clients.findOne({ clientID }); |
||||
|
if (!client) { |
||||
|
return done(null, false); |
||||
|
} |
||||
|
if (client.redirectUri !== redirectURI) { |
||||
|
return done(null, false); |
||||
|
} |
||||
|
return done(null, client, client.redirectURI); |
||||
|
} catch (error) { |
||||
|
this.log.error('failed to process OAuth2 authorize', { error }); |
||||
|
return done(error); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
async processGrant (client, redirectURI, user, ares, done) { |
||||
|
try { |
||||
|
var code = uuidv4(); |
||||
|
var ac = new this.models.AuthorizationCode({ |
||||
|
code, |
||||
|
clientId: client.id, |
||||
|
redirectURI, |
||||
|
user: user.id, |
||||
|
scope: ares.scope, |
||||
|
}); |
||||
|
await ac.save(); |
||||
|
return done(null, code); |
||||
|
} catch (error) { |
||||
|
this.log.error('failed to process OAuth2 grant', { error }); |
||||
|
return done(error); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
async processExchange (client, code, redirectURI, done) { |
||||
|
try { |
||||
|
const ac = await this.models.AuthorizationCode.findOne({ code }); |
||||
|
if (client.id !== ac.clientId) { |
||||
|
return done(null, false); |
||||
|
} |
||||
|
if (redirectURI !== ac.redirectUri) { |
||||
|
return done(null, false); |
||||
|
} |
||||
|
|
||||
|
var token = uuidv4(); |
||||
|
var at = new this.models.AccessToken({ |
||||
|
token, |
||||
|
user: ac.userId, |
||||
|
clientId: ac.clientId, |
||||
|
scope: ac.scope, |
||||
|
}); |
||||
|
await at.save(); |
||||
|
|
||||
|
return done(null, token); |
||||
|
} catch (error) { |
||||
|
this.log.error('failed to process OAuth2 exchange', { error }); |
||||
|
return done(error); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
module.exports = { |
||||
|
slug: 'oauth2', |
||||
|
name: 'oauth2', |
||||
|
create: (dtp) => { return new OAuth2Service(dtp); }, |
||||
|
}; |
@ -0,0 +1,18 @@ |
|||||
|
extends ../layouts/main |
||||
|
block content |
||||
|
|
||||
|
form(method="POST", action="/admin/core-node/connect").uk-form |
||||
|
.uk-card.uk-card-default.uk-card-small |
||||
|
.uk-card-header |
||||
|
h1.uk-card-title Connect to New Core |
||||
|
|
||||
|
.uk-card-body |
||||
|
.uk-margin |
||||
|
label(for="host").uk-form-label Address |
||||
|
input(id="host", name="host", placeholder="Enter host name or address", required).uk-input |
||||
|
.uk-margin |
||||
|
label(for="port").uk-form-label Port Number |
||||
|
input(id="port", name="port", min="1", max="65535", step="1", value="4200", required).uk-input |
||||
|
|
||||
|
.uk-card-footer |
||||
|
button(type="submit").uk-button.uk-button-primary Send Request |
@ -0,0 +1,14 @@ |
|||||
|
extends ../layouts/main |
||||
|
block content |
||||
|
|
||||
|
h1 Core Nodes |
||||
|
a(href="/admin/core-node/connect").uk-button.uk-button-primary Connect Core |
||||
|
|
||||
|
p You can register with one or more Core nodes to exchange information with those nodes. |
||||
|
|
||||
|
if Array.isArray(coreNodes) && (coreNodes.length > 0) |
||||
|
ul.uk-list |
||||
|
each node in coreNodes |
||||
|
pre= JSON.stringify(node, null, 2) |
||||
|
else |
||||
|
p There are no registered core nodes. |
@ -2795,7 +2795,7 @@ date-now@^0.1.4: |
|||||
resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" |
resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" |
||||
integrity sha1-6vQ5/U1ISK105cx9vvIAZyueNFs= |
integrity sha1-6vQ5/U1ISK105cx9vvIAZyueNFs= |
||||
|
|
||||
[email protected], debug@^2.2.0, debug@^2.3.3, debug@~2.6.4: |
[email protected], debug@2.x.x, debug@^2.2.0, debug@^2.3.3, debug@~2.6.4: |
||||
version "2.6.9" |
version "2.6.9" |
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" |
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" |
||||
integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== |
integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== |
||||
@ -6061,6 +6061,15 @@ o-stream@^0.3.0: |
|||||
resolved "https://registry.yarnpkg.com/o-stream/-/o-stream-0.3.0.tgz#204d27bc3fb395164507d79b381e91752e8daedc" |
resolved "https://registry.yarnpkg.com/o-stream/-/o-stream-0.3.0.tgz#204d27bc3fb395164507d79b381e91752e8daedc" |
||||
integrity sha512-gbzl6qCJZ609x/M2t25HqCYQagFzWYCtQ84jcuObGr+V8D1Am4EVubkF4J+XFs6ukfiv96vNeiBb8FrbbMZYiQ== |
integrity sha512-gbzl6qCJZ609x/M2t25HqCYQagFzWYCtQ84jcuObGr+V8D1Am4EVubkF4J+XFs6ukfiv96vNeiBb8FrbbMZYiQ== |
||||
|
|
||||
|
oauth2orize@^1.11.1: |
||||
|
version "1.11.1" |
||||
|
resolved "https://registry.yarnpkg.com/oauth2orize/-/oauth2orize-1.11.1.tgz#00b6cafe2036a0a3aab0380627dc7cfd5b5e9a9c" |
||||
|
integrity sha512-9dSx/Gwm0J2Rvj4RH9+h7iXVnRXZ6biwWRgb2dCeQhCosODS0nYdM9I/G7BUGsjbgn0pHjGcn1zcCRtzj2SlRA== |
||||
|
dependencies: |
||||
|
debug "2.x.x" |
||||
|
uid2 "0.0.x" |
||||
|
utils-merge "1.x.x" |
||||
|
|
||||
object-assign@^4, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: |
object-assign@^4, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: |
||||
version "4.1.1" |
version "4.1.1" |
||||
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" |
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" |
||||
@ -8335,6 +8344,11 @@ [email protected]: |
|||||
resolved "https://registry.yarnpkg.com/uid2/-/uid2-0.0.3.tgz#483126e11774df2f71b8b639dcd799c376162b82" |
resolved "https://registry.yarnpkg.com/uid2/-/uid2-0.0.3.tgz#483126e11774df2f71b8b639dcd799c376162b82" |
||||
integrity sha1-SDEm4Rd03y9xuLY53NeZw3YWK4I= |
integrity sha1-SDEm4Rd03y9xuLY53NeZw3YWK4I= |
||||
|
|
||||
|
[email protected]: |
||||
|
version "0.0.4" |
||||
|
resolved "https://registry.yarnpkg.com/uid2/-/uid2-0.0.4.tgz#033f3b1d5d32505f5ce5f888b9f3b667123c0a44" |
||||
|
integrity sha512-IevTus0SbGwQzYh3+fRsAMTVVPOoIVufzacXcHPmdlle1jUpq7BRL+mw3dgeLanvGZdwwbWhRV6XrcFNdBmjWA== |
||||
|
|
||||
uikit@^3.11.1: |
uikit@^3.11.1: |
||||
version "3.11.1" |
version "3.11.1" |
||||
resolved "https://registry.yarnpkg.com/uikit/-/uikit-3.11.1.tgz#3f0b47f4b2e7610375c5f7cdbf550d086c81e22f" |
resolved "https://registry.yarnpkg.com/uikit/-/uikit-3.11.1.tgz#3f0b47f4b2e7610375c5f7cdbf550d086c81e22f" |
||||
@ -8528,7 +8542,7 @@ util@^0.12.3: |
|||||
safe-buffer "^5.1.2" |
safe-buffer "^5.1.2" |
||||
which-typed-array "^1.1.2" |
which-typed-array "^1.1.2" |
||||
|
|
||||
[email protected]: |
[email protected], [email protected]: |
||||
version "1.0.1" |
version "1.0.1" |
||||
resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" |
resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" |
||||
integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= |
integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= |
||||
|
Loading…
Reference in new issue