diff --git a/docker-compose.yml b/docker-compose.yml index af9fce8..cf06c2d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -156,6 +156,7 @@ services: - NODE_ENV image: "frontend:${TAG}-${STAGE}" environment: + - MONGO_NODE_DRIVER_HOST=mongo - REACT_APP_BACKEND_SERVER - REACT_APP_FRONTEND_SERVER - REACT_APP_SITE_NAME diff --git a/frontend/Dockerfile b/frontend/Dockerfile index 7e0b1ad..e5b8aea 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -15,7 +15,10 @@ RUN npm run build # production environment FROM node:13.12.0-alpine RUN mkdir -p /app/public +COPY ./package.json /tmp +RUN cd /tmp && npm install +RUN cp -a /tmp/node_modules /app WORKDIR /app -RUN npm install -g serve +COPY server /app COPY --from=build /app/build /app/public -CMD serve -s public -l 3000 +CMD ["node", "index.js"] \ No newline at end of file diff --git a/frontend/package.json b/frontend/package.json index b06ba2b..d6fab2b 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -9,8 +9,11 @@ "@testing-library/react": "^9.3.2", "@testing-library/user-event": "^7.1.2", "axios": "0.21.1", + "connect-mongo": "3.2.0", "connected-react-router": "6.8.0", "date-fns": "2.16.1", + "ejs": "3.1.6", + "mongoose": "5.11.17", "react": "^17.0.1", "react-audio-player": "0.14.0", "react-datepicker": "3.3.0", diff --git a/frontend/public/card.js b/frontend/public/card.js new file mode 100644 index 0000000..8f06a9c --- /dev/null +++ b/frontend/public/card.js @@ -0,0 +1,34 @@ +'use strict'; + +// Create an instance +let wavesurfer; + +// Init & load audio file +document.addEventListener('DOMContentLoaded', function() { + // Init + wavesurfer = WaveSurfer.create({ + container: document.querySelector('#waveform'), + waveColor: '#A8DBA8', + progressColor: '#3B8686', + backend: 'MediaElement', + mediaControls: false + }); + + wavesurfer.once('ready', function() { + console.log('Using wavesurfer.js ' + WaveSurfer.VERSION); + }); + + wavesurfer.on('error', function(e) { + console.warn(e); + }); + + // Load audio from URL + wavesurfer.load('https://s3.us-west-1.wasabisys.com/openmhz-west/media/dcfd-1039-1613917169.m4a'); + + // toggle play button + document + .querySelector('[data-action="play"]') + .addEventListener('click', wavesurfer.playPause.bind(wavesurfer)); + + +}); \ No newline at end of file diff --git a/frontend/server/card.ejs b/frontend/server/card.ejs new file mode 100644 index 0000000..b836133 --- /dev/null +++ b/frontend/server/card.ejs @@ -0,0 +1,30 @@ + + + + + + wavesurfer.js | Media Element Example + + + + + + +
+
+ +
+ +
+ +
+
+ + + \ No newline at end of file diff --git a/frontend/server/config/express.js b/frontend/server/config/express.js new file mode 100644 index 0000000..6372621 --- /dev/null +++ b/frontend/server/config/express.js @@ -0,0 +1,67 @@ +const path = require("path"); +const express = require("express"); +const secrets = require("./secrets"); + + +var cookie_domain = process.env['REACT_APP_COOKIE_DOMAIN'] != null ? process.env['REACT_APP_COOKIE_DOMAIN'] : '.openmhz.com'; //'https://s3.amazonaws.com/robotastic'; +var backend_server = process.env['REACT_APP_BACKEND_SERVER'] != null ? process.env['REACT_APP_BACKEND_SERVER'] : 'https://api.openmhz.com'; +var frontend_server = process.env['REACT_APP_FRONTEND_SERVER'] != null ? process.env['REACT_APP_FRONTEND_SERVER'] : 'https://openmhz.com'; +var socket_server = process.env['REACT_APP_SOCKET_SERVER'] != null ? process.env['REACT_APP_SOCKET_SERVER'] : 'wss://socket.openmhz.com'; //'https://s3.amazonaws.com/robotastic'; +var account_server = process.env['REACT_APP_ACCOUNT_SERVER'] != null ? process.env['REACT_APP_ACCOUNT_SERVER'] : 'https://account.openmhz.com'; //'https://s3.amazonaws.com/robotastic'; +var dev_server = frontend_server + ":3000" + +module.exports = function(app) { + app.set("port", 3000) + + // X-Powered-By header has no functional value. + // Keeping it makes it easier for an attacker to build the site's profile + // It can be removed safely + app.disable("x-powered-by") + app.enable('trust proxy') + + app.use(express.static(path.join(process.cwd(), 'public'))); + app.set('view engine', 'ejs') + app.set('views', './') + + var node_env = process.env.NODE_ENV; + console.log('--------------------------'); + console.log('===> 😊 Starting Server . . .'); + console.log('===> Environment: ' + node_env); + if(node_env === 'production') { + console.log('===> 🚦 Note: In order for authentication to work in production'); + console.log('===> you will need a secure HTTPS connection'); + + } + + + + app.use('/*', function(req, res, next) { + var allowedOrigins = [ account_server]; + allowedOrigins.push(frontend_server); + allowedOrigins.push(backend_server); + allowedOrigins.push(socket_server); + allowedOrigins.push(dev_server); + var origin = req.headers.origin; + + + if (allowedOrigins.indexOf(origin) > -1) { + res.setHeader('Access-Control-Allow-Origin', origin); + } else if (req.headers["user-agent"] == 'TrunkRecorder1.0') { + res.setHeader('Access-Control-Allow-Origin', "*"); + } else { + res.setHeader('Access-Control-Allow-Origin', "*"); + if (origin) { + console.warn("forcing CORS for: " + origin + " referer: " + req.headers.referer); + } + } + res.header("Access-Control-Allow-Headers", "X-Requested-With"); + res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS,WEBSOCKET'); + res.header('Access-Control-Allow-Credentials', 'true'); + res.header("Access-Control-Allow-Headers", "Access-Control-Allow-Headers, Access-Control-Allow-Credentials, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers, Access-Control-Max-Age"); + res.header('Access-Control-Max-Age', '600'); + next(); + }); + + + +} diff --git a/frontend/server/config/secrets.js b/frontend/server/config/secrets.js new file mode 100644 index 0000000..a7d2c54 --- /dev/null +++ b/frontend/server/config/secrets.js @@ -0,0 +1,15 @@ +/** Important **/ +/** You should not be committing this file to GitHub **/ +/** Repeat: DO! NOT! COMMIT! THIS! FILE! TO! YOUR! REPO! **/ +var host = process.env['MONGO_NODE_DRIVER_HOST'] != null ? process.env['MONGO_NODE_DRIVER_HOST'] : 'localhost'; +var port = process.env['MONGO_NODE_DRIVER_PORT'] != null ? process.env['MONGO_NODE_DRIVER_PORT'] : 27017; +var mongoUrl = 'mongodb://' + host + ':' + port + '/scanner'; + + + +const secrets = { + db: mongoUrl, + sessionSecret: "letthisbeyoursecret" +} + +module.exports = secrets diff --git a/frontend/server/db.js b/frontend/server/db.js new file mode 100644 index 0000000..4e36c5e --- /dev/null +++ b/frontend/server/db.js @@ -0,0 +1,39 @@ +var MongoClient = require('mongodb').MongoClient; + + +var host = process.env['MONGO_NODE_DRIVER_HOST'] != null ? process.env['MONGO_NODE_DRIVER_HOST'] : 'localhost'; +var port = process.env['MONGO_NODE_DRIVER_PORT'] != null ? process.env['MONGO_NODE_DRIVER_PORT'] : 27017; +var dbUser = process.env['MONGO_TRUNK_FRONTEND_USER'] != null ? process.env['MONGO_TRUNK_FRONTEND_USER'] : null; +var dbPass = process.env['MONGO_TRUNK_FRONTEND_PASS'] != null ? process.env['MONGO_TRUNK_FRONTEND_PASS'] : null; + +var state = { + db: null, +} + +exports.connect = function(done) { + if (state.db) return done() + + var url = 'mongodb://' + host + ':' + port; + + MongoClient.connect(url, function(err, client) { + if (err) return done(err) + + //test.equal(true, result); + state.db = client.db('scanner'); + done(); + }) +} + +exports.get = function() { + return state.db +} + +exports.close = function(done) { + if (state.db) { + state.db.close(function(err, result) { + state.db = null + state.mode = null + done(err) + }) + } +} \ No newline at end of file diff --git a/frontend/server/index.ejs b/frontend/server/index.ejs new file mode 100644 index 0000000..f0abcfb --- /dev/null +++ b/frontend/server/index.ejs @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + %REACT_APP_SITE_NAME% + + + +
+ + + diff --git a/frontend/server/index.js b/frontend/server/index.js new file mode 100644 index 0000000..d049688 --- /dev/null +++ b/frontend/server/index.js @@ -0,0 +1,146 @@ +var ObjectID = require('mongodb').ObjectID; +var db = require('./db'); +const express = require("express"); +const path = require("path"); +const secrets = require("./config/secrets"); +const configureExpress = require("./config/express"); + + +// ------------------------------------------- + +const app = express() + +// ------------------------------------------- + +// ------------------------------------------- + +// Connect to Mongo on start +db.connect(function (err) { + if (err) { + console.log('Unable to connect to Mongo.') + process.exit(1) + } +}) +// ------------------------------------------- + +const isDev = process.env.NODE_ENV === "development" + + + + + + + + +// ------------------------------------------- + + +configureExpress(app) + + +function getCard(req, res, next) { + var objectId = req.params.id; + try { + var o_id = ObjectID.createFromHexString(objectId); + } catch (err) { + console.warn("Error - /card/:id generating ObjectID " + err); + res.status(500); + res.send(JSON.stringify({ + error: err, + "_id": objectId + })); + return; + } + + db.get().collection('calls', function (err, transCollection) { + transCollection.findOne({ + '_id': o_id + }, + function (err, item) { + if (item) { + var time = new Date(item.time); + var timeString = time.toLocaleTimeString("en-US"); + var dateString = time.toDateString(); + res.render('card.ejs', { + item: item, + url: item.url, + time: timeString, + date: dateString + }); + } else { + console.warn("Error - /card/:id Could not find Item " + err); + res.send(404, 'Sorry, we cannot find that!'); + } + }); + }); +} + +/* +exports.get_card = function(req, res) { + var objectId = req.params.id; + try { + var o_id = ObjectID.createFromHexString(objectId); + } catch (err) { + console.warn("Error - /card/:id generating ObjectID " + err); + res.status(500); + res.send(JSON.stringify({ + error: err, + "_id": objectId + })); + return; + } + db.get().collection('calls', function(err, transCollection) { + transCollection.findOne({ + '_id': o_id + }, + function(err, item) { + //console.log(util.inspect(item)); + if (item) { + var time = new Date(item.time); + var timeString = time.toLocaleTimeString("en-US"); + var dateString = time.toDateString(); + res.render('card', { + item: item, + channel: channels[item.talkgroupNum], + time: timeString, + date: dateString + }); + } else { + console.warn("Error - /card/:id Could not find Item " + err); + res.send(404, 'Sorry, we cannot find that!'); + } + }); + }); +} +*/ + +function getCalls(req, res, next) { + for (const key in req.query) { + console.log(key, req.query[key]) + } + if (req.query && req.query["call-id"]) { + const callId = req.query["call-id"]; + res.render("index.ejs", { PUBLIC_URL: "/", REACT_APP_SITE_NAME: process.env["REACT_APP_SITE_NAME"], REACT_APP_BACKEND_SERVER: process.env["REACT_APP_BACKEND_SERVER"], CALL_ID: callId, CALL_URL: "https://s3.us-west-1.wasabisys.com/openmhz-west/media/dcfd-1039-1613917169.m4a" }) + } else { + next() + } + +} +// ------------------------------------------- +app.use(express.static(path.join(__dirname, "public"))); + +app.get("/systems/:shortName", getCalls) +app.get("/cards/:id", getCard) + +app.get("*", (req, res, next) => { + res.sendFile(__dirname + '/public/index.html'); +}); + +// start listening to incoming requests +app.listen(app.get("port"), app.get("host"), (err) => { + if (err) { + console.err(err.stack) + } else { + console.log(`App listening on port ${app.get("port")} [${process.env.NODE_ENV} mode]`) + } +}) diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 7c7d8fe..dfc92a1 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -1553,6 +1553,12 @@ dependencies: "@babel/types" "^7.3.0" +"@types/bson@*": + version "4.0.3" + resolved "https://registry.yarnpkg.com/@types/bson/-/bson-4.0.3.tgz#30889d2ffde6262abbe38659364c631454999fbf" + dependencies: + "@types/node" "*" + "@types/eslint@^7.2.4": version "7.2.5" resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-7.2.5.tgz#92172ecf490c2fce4b076739693d75f30376d610" @@ -1620,6 +1626,13 @@ version "3.0.3" resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" +"@types/mongodb@^3.5.27": + version "3.6.8" + resolved "https://registry.yarnpkg.com/@types/mongodb/-/mongodb-3.6.8.tgz#f80f0a3022c44d8db659a936434403ca3f4661df" + dependencies: + "@types/bson" "*" + "@types/node" "*" + "@types/node@*": version "14.14.9" resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.9.tgz#04afc9a25c6ff93da14deabd65dc44485b53c8d6" @@ -2234,6 +2247,10 @@ async-limiter@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" +async@0.9.x: + version "0.9.2" + resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d" + async@^2.6.2: version "2.6.3" resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff" @@ -2490,6 +2507,17 @@ bindings@^1.5.0: dependencies: file-uri-to-path "1.0.0" +bl@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/bl/-/bl-2.2.1.tgz#8c11a7b730655c5d56898cdc871224f40fd901d5" + dependencies: + readable-stream "^2.3.5" + safe-buffer "^5.1.1" + +bluebird@3.5.1: + version "3.5.1" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9" + bluebird@^3.5.5: version "3.7.2" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" @@ -2648,6 +2676,10 @@ bser@2.1.1: dependencies: node-int64 "^0.4.0" +bson@^1.1.4: + version "1.1.5" + resolved "https://registry.yarnpkg.com/bson/-/bson-1.1.5.tgz#2aaae98fcdf6750c0848b0cba1ddec3c73060a34" + buffer-from@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" @@ -3083,6 +3115,12 @@ connect-history-api-fallback@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz#8b32089359308d111115d81cad3fceab888f97bc" +connect-mongo@3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/connect-mongo/-/connect-mongo-3.2.0.tgz#20f776c7f2a9d8144fc76cfdcbf33edb05eb4d52" + dependencies: + mongodb "^3.1.0" + connected-react-router@6.8.0: version "6.8.0" resolved "https://registry.yarnpkg.com/connected-react-router/-/connected-react-router-6.8.0.tgz#ddc687b31d498322445d235d660798489fa56cae" @@ -3093,10 +3131,6 @@ console-browserify@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" -"consolidated-events@^1.1.0 || ^2.0.0": - version "2.0.2" - resolved "https://registry.yarnpkg.com/consolidated-events/-/consolidated-events-2.0.2.tgz#da8d8f8c2b232831413d9e190dc11669c79f4a91" - constants-browserify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" @@ -3514,6 +3548,12 @@ debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.9: dependencies: ms "2.0.0" +debug@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" + dependencies: + ms "2.0.0" + debug@^3.1.1, debug@^3.2.5: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" @@ -3609,6 +3649,10 @@ delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" +denque@^1.4.1: + version "1.5.0" + resolved "https://registry.yarnpkg.com/denque/-/denque-1.5.0.tgz#773de0686ff2d8ec2ff92914316a47b73b1c73de" + depd@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" @@ -3801,6 +3845,12 @@ ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" +ejs@3.1.6: + version "3.1.6" + resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.6.tgz#5bfd0a0689743bb5268b3550cceeebbc1702822a" + dependencies: + jake "^10.6.1" + ejs@^2.6.1: version "2.7.4" resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.7.4.tgz#48661287573dcc53e366c7a1ae52c3a120eec9ba" @@ -4436,6 +4486,12 @@ file-uri-to-path@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" +filelist@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/filelist/-/filelist-1.0.2.tgz#80202f21462d4d1c2e214119b1807c1bc0380e5b" + dependencies: + minimatch "^3.0.4" + filesize@6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/filesize/-/filesize-6.1.0.tgz#e81bdaa780e2451d714d71c0d7a4f3238d37ad00" @@ -5524,6 +5580,15 @@ istanbul-reports@^3.0.2: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" +jake@^10.6.1: + version "10.8.2" + resolved "https://registry.yarnpkg.com/jake/-/jake-10.8.2.tgz#ebc9de8558160a66d82d0eadc6a2e58fbc500a7b" + dependencies: + async "0.9.x" + chalk "^2.4.2" + filelist "^1.0.1" + minimatch "^3.0.4" + jest-changed-files@^26.6.2: version "26.6.2" resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-26.6.2.tgz#f6198479e1cc66f22f9ae1e22acaa0b429c042d0" @@ -6077,6 +6142,10 @@ jsprim@^1.2.2: array-includes "^3.1.1" object.assign "^4.1.1" +kareem@2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/kareem/-/kareem-2.3.2.tgz#78c4508894985b8d38a0dc15e1a8e11078f2ca93" + keyboard-key@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/keyboard-key/-/keyboard-key-1.1.0.tgz#6f2e8e37fa11475bb1f1d65d5174f1b35653f5b7" @@ -6343,6 +6412,10 @@ memory-fs@^0.5.0: errno "^0.1.3" readable-stream "^2.0.1" +memory-pager@^1.0.2: + version "1.5.0" + resolved "https://registry.yarnpkg.com/memory-pager/-/memory-pager-1.5.0.tgz#d8751655d22d384682741c972f2c3d6dfa3e66b5" + merge-descriptors@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" @@ -6522,6 +6595,39 @@ mkdirp@^1.0.3, mkdirp@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" +mongodb@3.6.4, mongodb@^3.1.0: + version "3.6.4" + resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-3.6.4.tgz#ca59fd65b06831308262372ef9df6b78f9da97be" + dependencies: + bl "^2.2.1" + bson "^1.1.4" + denque "^1.4.1" + require_optional "^1.0.1" + safe-buffer "^5.1.2" + optionalDependencies: + saslprep "^1.0.0" + +mongoose-legacy-pluralize@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz#3ba9f91fa507b5186d399fb40854bff18fb563e4" + +mongoose@5.11.17: + version "5.11.17" + resolved "https://registry.yarnpkg.com/mongoose/-/mongoose-5.11.17.tgz#260b1e669d07a65f96c00b2d22f556f1f5771741" + dependencies: + "@types/mongodb" "^3.5.27" + bson "^1.1.4" + kareem "2.3.2" + mongodb "3.6.4" + mongoose-legacy-pluralize "1.0.2" + mpath "0.8.3" + mquery "3.2.4" + ms "2.1.2" + regexp-clone "1.0.0" + safe-buffer "5.2.1" + sift "7.0.1" + sliced "1.0.1" + move-concurrently@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" @@ -6533,6 +6639,20 @@ move-concurrently@^1.0.1: rimraf "^2.5.4" run-queue "^1.0.3" +mpath@0.8.3: + version "0.8.3" + resolved "https://registry.yarnpkg.com/mpath/-/mpath-0.8.3.tgz#828ac0d187f7f42674839d74921970979abbdd8f" + +mquery@3.2.4: + version "3.2.4" + resolved "https://registry.yarnpkg.com/mquery/-/mquery-3.2.4.tgz#9c5c2e285ea6c6f20673f3528973c99ee1aaa1a0" + dependencies: + bluebird "3.5.1" + debug "3.1.0" + regexp-clone "^1.0.0" + safe-buffer "5.1.2" + sliced "1.0.1" + ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -7856,7 +7976,7 @@ prompts@2.4.0, prompts@^2.0.1: kleur "^3.0.3" sisteransi "^1.0.5" -prop-types@^15.0.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2: +prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2: version "15.7.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" dependencies: @@ -8196,7 +8316,6 @@ react-scripts@4.0.1: optionalDependencies: fsevents "^2.1.3" - react@^17.0.1: version "17.0.1" resolved "https://registry.yarnpkg.com/react/-/react-17.0.1.tgz#6e0600416bd57574e3f86d92edba3d9008726127" @@ -8236,7 +8355,7 @@ read-pkg@^5.2.0: parse-json "^5.0.0" type-fest "^0.6.0" -"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6: +"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.6: version "2.3.7" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" dependencies: @@ -8329,6 +8448,10 @@ regex-parser@^2.2.11: version "2.2.11" resolved "https://registry.yarnpkg.com/regex-parser/-/regex-parser-2.2.11.tgz#3b37ec9049e19479806e878cabe7c1ca83ccfe58" +regexp-clone@1.0.0, regexp-clone@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/regexp-clone/-/regexp-clone-1.0.0.tgz#222db967623277056260b992626354a04ce9bf63" + regexp.prototype.flags@^1.2.0, regexp.prototype.flags@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz#7aba89b3c13a64509dabcf3ca8d9fbb9bdf5cb75" @@ -8434,6 +8557,13 @@ require-main-filename@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" +require_optional@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/require_optional/-/require_optional-1.0.1.tgz#4cf35a4247f64ca3df8c2ef208cc494b1ca8fc2e" + dependencies: + resolve-from "^2.0.0" + semver "^5.1.0" + requires-port@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" @@ -8454,6 +8584,10 @@ resolve-cwd@^3.0.0: dependencies: resolve-from "^5.0.0" +resolve-from@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-2.0.0.tgz#9480ab20e94ffa1d9e80a804c7ea147611966b57" + resolve-from@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" @@ -8608,7 +8742,7 @@ safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" -safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: +safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" @@ -8640,6 +8774,12 @@ sanitize.css@^10.0.0: version "10.0.0" resolved "https://registry.yarnpkg.com/sanitize.css/-/sanitize.css-10.0.0.tgz#b5cb2547e96d8629a60947544665243b1dc3657a" +saslprep@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/saslprep/-/saslprep-1.0.3.tgz#4c02f946b56cf54297e347ba1093e7acac4cf226" + dependencies: + sparse-bitfield "^3.0.3" + sass-loader@8.0.2: version "8.0.2" resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-8.0.2.tgz#debecd8c3ce243c76454f2e8290482150380090d" @@ -8725,7 +8865,7 @@ semantic-ui-react@2.0.1: react-popper "^2.2.3" shallowequal "^1.1.0" -"semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0: +"semver@2 || 3 || 4 || 5", semver@^5.1.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" @@ -8869,6 +9009,10 @@ side-channel@^1.0.2, side-channel@^1.0.3: es-abstract "^1.18.0-next.0" object-inspect "^1.8.0" +sift@7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/sift/-/sift-7.0.1.tgz#47d62c50b159d316f1372f8b53f9c10cd21a4b08" + signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.3" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" @@ -8895,6 +9039,10 @@ slice-ansi@^2.1.0: astral-regex "^1.0.0" is-fullwidth-code-point "^2.0.0" +sliced@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/sliced/-/sliced-1.0.1.tgz#0b3a662b5d04c3177b1926bea82b03f837a2ef41" + snapdragon-node@^2.0.1: version "2.1.1" resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" @@ -8988,6 +9136,12 @@ sourcemap-codec@^1.4.4: version "1.4.8" resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" +sparse-bitfield@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz#ff4ae6e68656056ba4b3e792ab3334d38273ca11" + dependencies: + memory-pager "^1.0.2" + spdx-correct@^3.0.0: version "3.1.1" resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9"