├── .example.env ├── .gitignore ├── README.md ├── app.js ├── assets └── no-image.jpg ├── controllers ├── auth.js ├── buscar.js ├── categorias.js ├── productos.js ├── uploads.js └── usuarios.js ├── database └── config.js ├── helpers ├── db-validators.js ├── generar-jwt.js ├── google-verify.js ├── index.js └── subir-archivo.js ├── middlewares ├── index.js ├── validar-archivo.js ├── validar-campos.js ├── validar-jwt.js └── validar-roles.js ├── models ├── categoria.js ├── chat-mensajes.js ├── index.js ├── producto.js ├── role.js ├── server.js └── usuario.js ├── package-lock.json ├── package.json ├── public ├── chat.html ├── index.html └── js │ ├── auth.js │ └── chat.js ├── routes ├── auth.js ├── buscar.js ├── categorias.js ├── productos.js ├── uploads.js └── usuarios.js ├── sockets └── controller.js └── uploads └── readme.md /.example.env: -------------------------------------------------------------------------------- 1 | PORT=8080 2 | MONGODB_CNN= 3 | SECRETORPRIVATEKEY= 4 | 5 | 6 | GOOGLE_CLIENT_ID= 7 | GOOGLE_SECRET_ID= 8 | 9 | 10 | CLOUDINARY_URL= -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | 3 | node_modules/ 4 | 5 | .env 6 | 7 | uploads/productos/**.* 8 | uploads/usuarios/**.* -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WebServer + RestServer 2 | 3 | Recuerden que deben de ejecutar ```npm install``` para reconstruir los módulos de Node. 4 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config(); 2 | const Server = require('./models/server'); 3 | 4 | 5 | const server = new Server(); 6 | 7 | 8 | 9 | server.listen(); -------------------------------------------------------------------------------- /assets/no-image.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Klerith/curso-node-socket-chat/1243bb4d424be6a3096f93e6e1a24e589e5801a1/assets/no-image.jpg -------------------------------------------------------------------------------- /controllers/auth.js: -------------------------------------------------------------------------------- 1 | const { response } = require('express'); 2 | const bcryptjs = require('bcryptjs') 3 | 4 | const Usuario = require('../models/usuario'); 5 | 6 | const { generarJWT } = require('../helpers/generar-jwt'); 7 | const { googleVerify } = require('../helpers/google-verify'); 8 | 9 | 10 | const login = async(req, res = response) => { 11 | 12 | const { correo, password } = req.body; 13 | 14 | try { 15 | 16 | // Verificar si el email existe 17 | const usuario = await Usuario.findOne({ correo }); 18 | if ( !usuario ) { 19 | return res.status(400).json({ 20 | msg: 'Usuario / Password no son correctos - correo' 21 | }); 22 | } 23 | 24 | // SI el usuario está activo 25 | if ( !usuario.estado ) { 26 | return res.status(400).json({ 27 | msg: 'Usuario / Password no son correctos - estado: false' 28 | }); 29 | } 30 | 31 | // Verificar la contraseña 32 | const validPassword = bcryptjs.compareSync( password, usuario.password ); 33 | if ( !validPassword ) { 34 | return res.status(400).json({ 35 | msg: 'Usuario / Password no son correctos - password' 36 | }); 37 | } 38 | 39 | // Generar el JWT 40 | const token = await generarJWT( usuario.id ); 41 | 42 | res.json({ 43 | usuario, 44 | token 45 | }) 46 | 47 | } catch (error) { 48 | console.log(error) 49 | res.status(500).json({ 50 | msg: 'Hable con el administrador' 51 | }); 52 | } 53 | 54 | } 55 | 56 | 57 | const googleSignin = async(req, res = response) => { 58 | 59 | const { id_token } = req.body; 60 | 61 | try { 62 | const { correo, nombre, img } = await googleVerify( id_token ); 63 | 64 | let usuario = await Usuario.findOne({ correo }); 65 | 66 | if ( !usuario ) { 67 | // Tengo que crearlo 68 | const data = { 69 | nombre, 70 | correo, 71 | password: ':P', 72 | img, 73 | google: true 74 | }; 75 | 76 | usuario = new Usuario( data ); 77 | await usuario.save(); 78 | } 79 | 80 | // Si el usuario en DB 81 | if ( !usuario.estado ) { 82 | return res.status(401).json({ 83 | msg: 'Hable con el administrador, usuario bloqueado' 84 | }); 85 | } 86 | 87 | // Generar el JWT 88 | const token = await generarJWT( usuario.id ); 89 | 90 | res.json({ 91 | usuario, 92 | token 93 | }); 94 | 95 | } catch (error) { 96 | 97 | res.status(400).json({ 98 | msg: 'Token de Google no es válido' 99 | }) 100 | 101 | } 102 | 103 | 104 | 105 | } 106 | 107 | 108 | const renovarToken = async( req, res = response ) =>{ 109 | 110 | const { usuario } = req; 111 | 112 | // Generar el JWT 113 | const token = await generarJWT( usuario.id ); 114 | 115 | res.json({ 116 | usuario, 117 | token 118 | }) 119 | } 120 | 121 | 122 | module.exports = { 123 | login, 124 | googleSignin, 125 | renovarToken 126 | } 127 | -------------------------------------------------------------------------------- /controllers/buscar.js: -------------------------------------------------------------------------------- 1 | const { response } = require('express'); 2 | const { ObjectId } = require('mongoose').Types; 3 | 4 | const { Usuario, Categoria, Producto } = require('../models'); 5 | 6 | const coleccionesPermitidas = [ 7 | 'usuarios', 8 | 'categorias', 9 | 'productos', 10 | 'roles' 11 | ]; 12 | 13 | const buscarUsuarios = async( termino = '', res = response ) => { 14 | 15 | const esMongoID = ObjectId.isValid( termino ); // TRUE 16 | 17 | if ( esMongoID ) { 18 | const usuario = await Usuario.findById(termino); 19 | return res.json({ 20 | results: ( usuario ) ? [ usuario ] : [] 21 | }); 22 | } 23 | 24 | const regex = new RegExp( termino, 'i' ); 25 | const usuarios = await Usuario.find({ 26 | $or: [{ nombre: regex }, { correo: regex }], 27 | $and: [{ estado: true }] 28 | }); 29 | 30 | res.json({ 31 | results: usuarios 32 | }); 33 | 34 | } 35 | 36 | const buscarCategorias = async( termino = '', res = response ) => { 37 | 38 | const esMongoID = ObjectId.isValid( termino ); // TRUE 39 | 40 | if ( esMongoID ) { 41 | const categoria = await Categoria.findById(termino); 42 | return res.json({ 43 | results: ( categoria ) ? [ categoria ] : [] 44 | }); 45 | } 46 | 47 | const regex = new RegExp( termino, 'i' ); 48 | const categorias = await Categoria.find({ nombre: regex, estado: true }); 49 | 50 | res.json({ 51 | results: categorias 52 | }); 53 | 54 | } 55 | 56 | const buscarProductos = async( termino = '', res = response ) => { 57 | 58 | const esMongoID = ObjectId.isValid( termino ); // TRUE 59 | 60 | if ( esMongoID ) { 61 | const producto = await Producto.findById(termino) 62 | .populate('categoria','nombre'); 63 | return res.json({ 64 | results: ( producto ) ? [ producto ] : [] 65 | }); 66 | } 67 | 68 | const regex = new RegExp( termino, 'i' ); 69 | const productos = await Producto.find({ nombre: regex, estado: true }) 70 | .populate('categoria','nombre') 71 | 72 | res.json({ 73 | results: productos 74 | }); 75 | 76 | } 77 | 78 | 79 | const buscar = ( req, res = response ) => { 80 | 81 | const { coleccion, termino } = req.params; 82 | 83 | if ( !coleccionesPermitidas.includes( coleccion ) ) { 84 | return res.status(400).json({ 85 | msg: `Las colecciones permitidas son: ${ coleccionesPermitidas }` 86 | }) 87 | } 88 | 89 | switch (coleccion) { 90 | case 'usuarios': 91 | buscarUsuarios(termino, res); 92 | break; 93 | case 'categorias': 94 | buscarCategorias(termino, res); 95 | break; 96 | case 'productos': 97 | buscarProductos(termino, res); 98 | break; 99 | 100 | default: 101 | res.status(500).json({ 102 | msg: 'Se le olvido hacer esta búsquda' 103 | }) 104 | } 105 | 106 | } 107 | 108 | 109 | 110 | module.exports = { 111 | buscar 112 | } -------------------------------------------------------------------------------- /controllers/categorias.js: -------------------------------------------------------------------------------- 1 | const { response } = require('express'); 2 | const { Categoria } = require('../models'); 3 | 4 | 5 | const obtenerCategorias = async(req, res = response ) => { 6 | 7 | const { limite = 5, desde = 0 } = req.query; 8 | const query = { estado: true }; 9 | 10 | const [ total, categorias ] = await Promise.all([ 11 | Categoria.countDocuments(query), 12 | Categoria.find(query) 13 | .populate('usuario', 'nombre') 14 | .skip( Number( desde ) ) 15 | .limit(Number( limite )) 16 | ]); 17 | 18 | res.json({ 19 | total, 20 | categorias 21 | }); 22 | } 23 | 24 | const obtenerCategoria = async(req, res = response ) => { 25 | 26 | const { id } = req.params; 27 | const categoria = await Categoria.findById( id ) 28 | .populate('usuario', 'nombre'); 29 | 30 | res.json( categoria ); 31 | 32 | } 33 | 34 | const crearCategoria = async(req, res = response ) => { 35 | 36 | const nombre = req.body.nombre.toUpperCase(); 37 | 38 | const categoriaDB = await Categoria.findOne({ nombre }); 39 | 40 | if ( categoriaDB ) { 41 | return res.status(400).json({ 42 | msg: `La categoria ${ categoriaDB.nombre }, ya existe` 43 | }); 44 | } 45 | 46 | // Generar la data a guardar 47 | const data = { 48 | nombre, 49 | usuario: req.usuario._id 50 | } 51 | 52 | const categoria = new Categoria( data ); 53 | 54 | // Guardar DB 55 | await categoria.save(); 56 | 57 | res.status(201).json(categoria); 58 | 59 | } 60 | 61 | const actualizarCategoria = async( req, res = response ) => { 62 | 63 | const { id } = req.params; 64 | const { estado, usuario, ...data } = req.body; 65 | 66 | data.nombre = data.nombre.toUpperCase(); 67 | data.usuario = req.usuario._id; 68 | 69 | const categoria = await Categoria.findByIdAndUpdate(id, data, { new: true }); 70 | 71 | res.json( categoria ); 72 | 73 | } 74 | 75 | const borrarCategoria = async(req, res =response ) => { 76 | 77 | const { id } = req.params; 78 | const categoriaBorrada = await Categoria.findByIdAndUpdate( id, { estado: false }, {new: true }); 79 | 80 | res.json( categoriaBorrada ); 81 | } 82 | 83 | 84 | 85 | 86 | module.exports = { 87 | crearCategoria, 88 | obtenerCategorias, 89 | obtenerCategoria, 90 | actualizarCategoria, 91 | borrarCategoria 92 | } -------------------------------------------------------------------------------- /controllers/productos.js: -------------------------------------------------------------------------------- 1 | const { response } = require('express'); 2 | const { Producto } = require('../models'); 3 | 4 | 5 | const obtenerProductos = async(req, res = response ) => { 6 | 7 | const { limite = 5, desde = 0 } = req.query; 8 | const query = { estado: true }; 9 | 10 | const [ total, productos ] = await Promise.all([ 11 | Producto.countDocuments(query), 12 | Producto.find(query) 13 | .populate('usuario', 'nombre') 14 | .populate('categoria', 'nombre') 15 | .skip( Number( desde ) ) 16 | .limit(Number( limite )) 17 | ]); 18 | 19 | res.json({ 20 | total, 21 | productos 22 | }); 23 | } 24 | 25 | const obtenerProducto = async(req, res = response ) => { 26 | 27 | const { id } = req.params; 28 | const producto = await Producto.findById( id ) 29 | .populate('usuario', 'nombre') 30 | .populate('categoria', 'nombre'); 31 | 32 | res.json( producto ); 33 | 34 | } 35 | 36 | const crearProducto = async(req, res = response ) => { 37 | 38 | const { estado, usuario, ...body } = req.body; 39 | 40 | const productoDB = await Producto.findOne({ nombre: body.nombre }); 41 | 42 | if ( productoDB ) { 43 | return res.status(400).json({ 44 | msg: `El producto ${ productoDB.nombre }, ya existe` 45 | }); 46 | } 47 | 48 | // Generar la data a guardar 49 | const data = { 50 | ...body, 51 | nombre: body.nombre.toUpperCase(), 52 | usuario: req.usuario._id 53 | } 54 | 55 | const producto = new Producto( data ); 56 | 57 | // Guardar DB 58 | await producto.save(); 59 | 60 | res.status(201).json(producto); 61 | 62 | } 63 | 64 | const actualizarProducto = async( req, res = response ) => { 65 | 66 | const { id } = req.params; 67 | const { estado, usuario, ...data } = req.body; 68 | 69 | if( data.nombre ) { 70 | data.nombre = data.nombre.toUpperCase(); 71 | } 72 | 73 | data.usuario = req.usuario._id; 74 | 75 | const producto = await Producto.findByIdAndUpdate(id, data, { new: true }); 76 | 77 | res.json( producto ); 78 | 79 | } 80 | 81 | const borrarProducto = async(req, res = response ) => { 82 | 83 | const { id } = req.params; 84 | const productoBorrado = await Producto.findByIdAndUpdate( id, { estado: false }, {new: true }); 85 | 86 | res.json( productoBorrado ); 87 | } 88 | 89 | 90 | 91 | 92 | module.exports = { 93 | crearProducto, 94 | obtenerProductos, 95 | obtenerProducto, 96 | actualizarProducto, 97 | borrarProducto 98 | } -------------------------------------------------------------------------------- /controllers/uploads.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const fs = require('fs'); 3 | 4 | const cloudinary = require('cloudinary').v2 5 | cloudinary.config( process.env.CLOUDINARY_URL ); 6 | 7 | const { response } = require('express'); 8 | const { subirArchivo } = require('../helpers'); 9 | 10 | const { Usuario, Producto } = require('../models'); 11 | 12 | 13 | const cargarArchivo = async(req, res = response) => { 14 | 15 | 16 | try { 17 | 18 | // txt, md 19 | // const nombre = await subirArchivo( req.files, ['txt','md'], 'textos' ); 20 | const nombre = await subirArchivo( req.files, undefined, 'imgs' ); 21 | res.json({ nombre }); 22 | 23 | } catch (msg) { 24 | res.status(400).json({ msg }); 25 | } 26 | 27 | } 28 | 29 | 30 | const actualizarImagen = async(req, res = response ) => { 31 | 32 | const { id, coleccion } = req.params; 33 | 34 | let modelo; 35 | 36 | switch ( coleccion ) { 37 | case 'usuarios': 38 | modelo = await Usuario.findById(id); 39 | if ( !modelo ) { 40 | return res.status(400).json({ 41 | msg: `No existe un usuario con el id ${ id }` 42 | }); 43 | } 44 | 45 | break; 46 | 47 | case 'productos': 48 | modelo = await Producto.findById(id); 49 | if ( !modelo ) { 50 | return res.status(400).json({ 51 | msg: `No existe un producto con el id ${ id }` 52 | }); 53 | } 54 | 55 | break; 56 | 57 | default: 58 | return res.status(500).json({ msg: 'Se me olvidó validar esto'}); 59 | } 60 | 61 | 62 | // Limpiar imágenes previas 63 | if ( modelo.img ) { 64 | // Hay que borrar la imagen del servidor 65 | const pathImagen = path.join( __dirname, '../uploads', coleccion, modelo.img ); 66 | if ( fs.existsSync( pathImagen ) ) { 67 | fs.unlinkSync( pathImagen ); 68 | } 69 | } 70 | 71 | 72 | const nombre = await subirArchivo( req.files, undefined, coleccion ); 73 | modelo.img = nombre; 74 | 75 | await modelo.save(); 76 | 77 | 78 | res.json( modelo ); 79 | 80 | } 81 | 82 | 83 | const actualizarImagenCloudinary = async(req, res = response ) => { 84 | 85 | const { id, coleccion } = req.params; 86 | 87 | let modelo; 88 | 89 | switch ( coleccion ) { 90 | case 'usuarios': 91 | modelo = await Usuario.findById(id); 92 | if ( !modelo ) { 93 | return res.status(400).json({ 94 | msg: `No existe un usuario con el id ${ id }` 95 | }); 96 | } 97 | 98 | break; 99 | 100 | case 'productos': 101 | modelo = await Producto.findById(id); 102 | if ( !modelo ) { 103 | return res.status(400).json({ 104 | msg: `No existe un producto con el id ${ id }` 105 | }); 106 | } 107 | 108 | break; 109 | 110 | default: 111 | return res.status(500).json({ msg: 'Se me olvidó validar esto'}); 112 | } 113 | 114 | 115 | // Limpiar imágenes previas 116 | if ( modelo.img ) { 117 | const nombreArr = modelo.img.split('/'); 118 | const nombre = nombreArr[ nombreArr.length - 1 ]; 119 | const [ public_id ] = nombre.split('.'); 120 | cloudinary.uploader.destroy( public_id ); 121 | } 122 | 123 | 124 | const { tempFilePath } = req.files.archivo 125 | const { secure_url } = await cloudinary.uploader.upload( tempFilePath ); 126 | modelo.img = secure_url; 127 | 128 | await modelo.save(); 129 | 130 | 131 | res.json( modelo ); 132 | 133 | } 134 | 135 | const mostrarImagen = async(req, res = response ) => { 136 | 137 | const { id, coleccion } = req.params; 138 | 139 | let modelo; 140 | 141 | switch ( coleccion ) { 142 | case 'usuarios': 143 | modelo = await Usuario.findById(id); 144 | if ( !modelo ) { 145 | return res.status(400).json({ 146 | msg: `No existe un usuario con el id ${ id }` 147 | }); 148 | } 149 | 150 | break; 151 | 152 | case 'productos': 153 | modelo = await Producto.findById(id); 154 | if ( !modelo ) { 155 | return res.status(400).json({ 156 | msg: `No existe un producto con el id ${ id }` 157 | }); 158 | } 159 | 160 | break; 161 | 162 | default: 163 | return res.status(500).json({ msg: 'Se me olvidó validar esto'}); 164 | } 165 | 166 | 167 | // Limpiar imágenes previas 168 | if ( modelo.img ) { 169 | // Hay que borrar la imagen del servidor 170 | const pathImagen = path.join( __dirname, '../uploads', coleccion, modelo.img ); 171 | if ( fs.existsSync( pathImagen ) ) { 172 | return res.sendFile( pathImagen ) 173 | } 174 | } 175 | 176 | const pathImagen = path.join( __dirname, '../assets/no-image.jpg'); 177 | res.sendFile( pathImagen ); 178 | } 179 | 180 | 181 | 182 | 183 | module.exports = { 184 | cargarArchivo, 185 | actualizarImagen, 186 | mostrarImagen, 187 | actualizarImagenCloudinary 188 | } -------------------------------------------------------------------------------- /controllers/usuarios.js: -------------------------------------------------------------------------------- 1 | const { response, request } = require('express'); 2 | const bcryptjs = require('bcryptjs'); 3 | 4 | 5 | const Usuario = require('../models/usuario'); 6 | 7 | 8 | 9 | const usuariosGet = async(req = request, res = response) => { 10 | 11 | const { limite = 5, desde = 0 } = req.query; 12 | const query = { estado: true }; 13 | 14 | const [ total, usuarios ] = await Promise.all([ 15 | Usuario.countDocuments(query), 16 | Usuario.find(query) 17 | .skip( Number( desde ) ) 18 | .limit(Number( limite )) 19 | ]); 20 | 21 | res.json({ 22 | total, 23 | usuarios 24 | }); 25 | } 26 | 27 | const usuariosPost = async(req, res = response) => { 28 | 29 | const { nombre, correo, password, rol } = req.body; 30 | const usuario = new Usuario({ nombre, correo, password, rol }); 31 | 32 | // Encriptar la contraseña 33 | const salt = bcryptjs.genSaltSync(); 34 | usuario.password = bcryptjs.hashSync( password, salt ); 35 | 36 | // Guardar en BD 37 | await usuario.save(); 38 | 39 | res.json({ 40 | usuario 41 | }); 42 | } 43 | 44 | const usuariosPut = async(req, res = response) => { 45 | 46 | const { id } = req.params; 47 | const { _id, password, google, correo, ...resto } = req.body; 48 | 49 | if ( password ) { 50 | // Encriptar la contraseña 51 | const salt = bcryptjs.genSaltSync(); 52 | resto.password = bcryptjs.hashSync( password, salt ); 53 | } 54 | 55 | const usuario = await Usuario.findByIdAndUpdate( id, resto ); 56 | 57 | res.json(usuario); 58 | } 59 | 60 | const usuariosPatch = (req, res = response) => { 61 | res.json({ 62 | msg: 'patch API - usuariosPatch' 63 | }); 64 | } 65 | 66 | const usuariosDelete = async(req, res = response) => { 67 | 68 | const { id } = req.params; 69 | const usuario = await Usuario.findByIdAndUpdate( id, { estado: false } ); 70 | 71 | 72 | res.json(usuario); 73 | } 74 | 75 | 76 | 77 | 78 | module.exports = { 79 | usuariosGet, 80 | usuariosPost, 81 | usuariosPut, 82 | usuariosPatch, 83 | usuariosDelete, 84 | } -------------------------------------------------------------------------------- /database/config.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | 3 | 4 | 5 | const dbConnection = async() => { 6 | 7 | try { 8 | 9 | await mongoose.connect( process.env.MONGODB_CNN, { 10 | useNewUrlParser: true, 11 | useUnifiedTopology: true, 12 | useCreateIndex: true, 13 | useFindAndModify: false 14 | }); 15 | 16 | console.log('Base de datos online'); 17 | 18 | } catch (error) { 19 | console.log(error); 20 | throw new Error('Error a la hora de iniciar la base de datos'); 21 | } 22 | 23 | 24 | } 25 | 26 | 27 | 28 | module.exports = { 29 | dbConnection 30 | } 31 | -------------------------------------------------------------------------------- /helpers/db-validators.js: -------------------------------------------------------------------------------- 1 | const Role = require('../models/role'); 2 | const { Usuario, Categoria, Producto } = require('../models'); 3 | 4 | const esRoleValido = async(rol = '') => { 5 | 6 | const existeRol = await Role.findOne({ rol }); 7 | if ( !existeRol ) { 8 | throw new Error(`El rol ${ rol } no está registrado en la BD`); 9 | } 10 | } 11 | 12 | const emailExiste = async( correo = '' ) => { 13 | 14 | // Verificar si el correo existe 15 | const existeEmail = await Usuario.findOne({ correo }); 16 | if ( existeEmail ) { 17 | throw new Error(`El correo: ${ correo }, ya está registrado`); 18 | } 19 | } 20 | 21 | const existeUsuarioPorId = async( id ) => { 22 | 23 | // Verificar si el correo existe 24 | const existeUsuario = await Usuario.findById(id); 25 | if ( !existeUsuario ) { 26 | throw new Error(`El id no existe ${ id }`); 27 | } 28 | } 29 | 30 | /** 31 | * Categorias 32 | */ 33 | const existeCategoriaPorId = async( id ) => { 34 | 35 | // Verificar si el correo existe 36 | const existeCategoria = await Categoria.findById(id); 37 | if ( !existeCategoria ) { 38 | throw new Error(`El id no existe ${ id }`); 39 | } 40 | } 41 | 42 | /** 43 | * Productos 44 | */ 45 | const existeProductoPorId = async( id ) => { 46 | 47 | // Verificar si el correo existe 48 | const existeProducto = await Producto.findById(id); 49 | if ( !existeProducto ) { 50 | throw new Error(`El id no existe ${ id }`); 51 | } 52 | } 53 | 54 | /** 55 | * Validar colecciones permitidas 56 | */ 57 | const coleccionesPermitidas = ( coleccion = '', colecciones = []) => { 58 | 59 | const incluida = colecciones.includes( coleccion ); 60 | if ( !incluida ) { 61 | throw new Error(`La colección ${ coleccion } no es permitida, ${ colecciones }`); 62 | } 63 | return true; 64 | } 65 | 66 | 67 | module.exports = { 68 | esRoleValido, 69 | emailExiste, 70 | existeUsuarioPorId, 71 | existeCategoriaPorId, 72 | existeProductoPorId, 73 | coleccionesPermitidas 74 | } 75 | 76 | -------------------------------------------------------------------------------- /helpers/generar-jwt.js: -------------------------------------------------------------------------------- 1 | const jwt = require('jsonwebtoken'); 2 | const { Usuario } = require('../models') 3 | 4 | 5 | 6 | const generarJWT = ( uid = '' ) => { 7 | 8 | return new Promise( (resolve, reject) => { 9 | 10 | const payload = { uid }; 11 | 12 | jwt.sign( payload, process.env.SECRETORPRIVATEKEY, { 13 | expiresIn: '4h' 14 | }, ( err, token ) => { 15 | 16 | if ( err ) { 17 | console.log(err); 18 | reject( 'No se pudo generar el token' ) 19 | } else { 20 | resolve( token ); 21 | } 22 | }) 23 | 24 | }) 25 | } 26 | 27 | 28 | const comprobarJWT = async( token = '') => { 29 | 30 | try { 31 | 32 | if( token.length < 10 ) { 33 | return null; 34 | } 35 | 36 | const { uid } = jwt.verify( token, process.env.SECRETORPRIVATEKEY ); 37 | const usuario = await Usuario.findById( uid ); 38 | 39 | if ( usuario ) { 40 | if ( usuario.estado ) { 41 | return usuario; 42 | } else { 43 | return null; 44 | } 45 | } else { 46 | return null; 47 | } 48 | 49 | } catch (error) { 50 | return null; 51 | } 52 | 53 | } 54 | 55 | 56 | 57 | 58 | module.exports = { 59 | generarJWT, 60 | comprobarJWT 61 | } 62 | 63 | -------------------------------------------------------------------------------- /helpers/google-verify.js: -------------------------------------------------------------------------------- 1 | const { OAuth2Client } = require('google-auth-library'); 2 | 3 | const client = new OAuth2Client( process.env.GOOGLE_CLIENT_ID ); 4 | 5 | const googleVerify = async( idToken = '' ) => { 6 | 7 | const ticket = await client.verifyIdToken({ 8 | idToken, 9 | audience: process.env.GOOGLE_CLIENT_ID, // Specify the CLIENT_ID of the app that accesses the backend 10 | // Or, if multiple clients access the backend: 11 | //[CLIENT_ID_1, CLIENT_ID_2, CLIENT_ID_3] 12 | }); 13 | 14 | const { name: nombre, 15 | picture: img, 16 | email: correo 17 | } = ticket.getPayload(); 18 | 19 | return { nombre, img, correo }; 20 | 21 | } 22 | 23 | 24 | module.exports = { 25 | googleVerify 26 | } -------------------------------------------------------------------------------- /helpers/index.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | const dbValidators = require('./db-validators'); 4 | const generarJWT = require('./generar-jwt'); 5 | const googleVerify = require('./google-verify'); 6 | const subirArchivo = require('./subir-archivo'); 7 | 8 | 9 | module.exports = { 10 | ...dbValidators, 11 | ...generarJWT, 12 | ...googleVerify, 13 | ...subirArchivo, 14 | } -------------------------------------------------------------------------------- /helpers/subir-archivo.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const { v4: uuidv4 } = require('uuid'); 3 | 4 | const subirArchivo = ( files, extensionesValidas = ['png','jpg','jpeg','gif'], carpeta = '' ) => { 5 | 6 | return new Promise( (resolve, reject) => { 7 | 8 | const { archivo } = files; 9 | const nombreCortado = archivo.name.split('.'); 10 | const extension = nombreCortado[ nombreCortado.length - 1 ]; 11 | 12 | // Validar la extension 13 | if ( !extensionesValidas.includes( extension ) ) { 14 | return reject(`La extensión ${ extension } no es permitida - ${ extensionesValidas }`); 15 | } 16 | 17 | const nombreTemp = uuidv4() + '.' + extension; 18 | const uploadPath = path.join( __dirname, '../uploads/', carpeta, nombreTemp ); 19 | 20 | archivo.mv(uploadPath, (err) => { 21 | if (err) { 22 | reject(err); 23 | } 24 | 25 | resolve( nombreTemp ); 26 | }); 27 | 28 | }); 29 | 30 | } 31 | 32 | 33 | 34 | module.exports = { 35 | subirArchivo 36 | } -------------------------------------------------------------------------------- /middlewares/index.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | const validaCampos = require('../middlewares/validar-campos'); 4 | const validarJWT = require('../middlewares/validar-jwt'); 5 | const validaRoles = require('../middlewares/validar-roles'); 6 | const validarArchivo = require('../middlewares/validar-archivo'); 7 | 8 | module.exports = { 9 | ...validaCampos, 10 | ...validarJWT, 11 | ...validaRoles, 12 | ...validarArchivo 13 | } -------------------------------------------------------------------------------- /middlewares/validar-archivo.js: -------------------------------------------------------------------------------- 1 | const { response } = require("express") 2 | 3 | 4 | const validarArchivoSubir = (req, res = response, next ) => { 5 | 6 | if (!req.files || Object.keys(req.files).length === 0 || !req.files.archivo ) { 7 | return res.status(400).json({ 8 | msg: 'No hay archivos que subir - validarArchivoSubir' 9 | }); 10 | } 11 | 12 | next(); 13 | 14 | } 15 | 16 | 17 | module.exports = { 18 | validarArchivoSubir 19 | } 20 | -------------------------------------------------------------------------------- /middlewares/validar-campos.js: -------------------------------------------------------------------------------- 1 | const { validationResult } = require('express-validator'); 2 | 3 | 4 | const validarCampos = ( req, res, next ) => { 5 | 6 | const errors = validationResult(req); 7 | if( !errors.isEmpty() ){ 8 | return res.status(400).json(errors); 9 | } 10 | 11 | next(); 12 | } 13 | 14 | 15 | 16 | module.exports = { 17 | validarCampos 18 | } 19 | -------------------------------------------------------------------------------- /middlewares/validar-jwt.js: -------------------------------------------------------------------------------- 1 | const { response, request } = require('express'); 2 | const jwt = require('jsonwebtoken'); 3 | 4 | const Usuario = require('../models/usuario'); 5 | 6 | 7 | const validarJWT = async( req = request, res = response, next ) => { 8 | 9 | const token = req.header('x-token'); 10 | 11 | if ( !token ) { 12 | return res.status(401).json({ 13 | msg: 'No hay token en la petición' 14 | }); 15 | } 16 | 17 | try { 18 | 19 | const { uid } = jwt.verify( token, process.env.SECRETORPRIVATEKEY ); 20 | 21 | // leer el usuario que corresponde al uid 22 | const usuario = await Usuario.findById( uid ); 23 | 24 | if( !usuario ) { 25 | return res.status(401).json({ 26 | msg: 'Token no válido - usuario no existe DB' 27 | }) 28 | } 29 | 30 | // Verificar si el uid tiene estado true 31 | if ( !usuario.estado ) { 32 | return res.status(401).json({ 33 | msg: 'Token no válido - usuario con estado: false' 34 | }) 35 | } 36 | 37 | 38 | req.usuario = usuario; 39 | next(); 40 | 41 | } catch (error) { 42 | 43 | console.log(error); 44 | res.status(401).json({ 45 | msg: 'Token no válido' 46 | }) 47 | } 48 | 49 | } 50 | 51 | 52 | 53 | 54 | module.exports = { 55 | validarJWT 56 | } -------------------------------------------------------------------------------- /middlewares/validar-roles.js: -------------------------------------------------------------------------------- 1 | const { response } = require('express') 2 | 3 | 4 | const esAdminRole = ( req, res = response, next ) => { 5 | 6 | if ( !req.usuario ) { 7 | return res.status(500).json({ 8 | msg: 'Se quiere verificar el role sin validar el token primero' 9 | }); 10 | } 11 | 12 | const { rol, nombre } = req.usuario; 13 | 14 | if ( rol !== 'ADMIN_ROLE' ) { 15 | return res.status(401).json({ 16 | msg: `${ nombre } no es administrador - No puede hacer esto` 17 | }); 18 | } 19 | 20 | next(); 21 | } 22 | 23 | 24 | const tieneRole = ( ...roles ) => { 25 | return (req, res = response, next) => { 26 | 27 | if ( !req.usuario ) { 28 | return res.status(500).json({ 29 | msg: 'Se quiere verificar el role sin validar el token primero' 30 | }); 31 | } 32 | 33 | if ( !roles.includes( req.usuario.rol ) ) { 34 | return res.status(401).json({ 35 | msg: `El servicio requiere uno de estos roles ${ roles }` 36 | }); 37 | } 38 | 39 | 40 | next(); 41 | } 42 | } 43 | 44 | 45 | 46 | module.exports = { 47 | esAdminRole, 48 | tieneRole 49 | } -------------------------------------------------------------------------------- /models/categoria.js: -------------------------------------------------------------------------------- 1 | const { Schema, model } = require('mongoose'); 2 | 3 | const CategoriaSchema = Schema({ 4 | nombre: { 5 | type: String, 6 | required: [true, 'El nombre es obligatorio'], 7 | unique: true 8 | }, 9 | estado: { 10 | type: Boolean, 11 | default: true, 12 | required: true 13 | }, 14 | usuario: { 15 | type: Schema.Types.ObjectId, 16 | ref: 'Usuario', 17 | required: true 18 | } 19 | }); 20 | 21 | 22 | CategoriaSchema.methods.toJSON = function() { 23 | const { __v, estado, ...data } = this.toObject(); 24 | return data; 25 | } 26 | 27 | 28 | module.exports = model( 'Categoria', CategoriaSchema ); 29 | -------------------------------------------------------------------------------- /models/chat-mensajes.js: -------------------------------------------------------------------------------- 1 | class Mensaje { 2 | constructor( uid, nombre, mensaje ) { 3 | this.uid = uid; 4 | this.nombre = nombre; 5 | this.mensaje = mensaje; 6 | } 7 | } 8 | 9 | 10 | class ChatMensajes { 11 | 12 | constructor() { 13 | this.mensajes = []; 14 | this.usuarios = {}; 15 | } 16 | 17 | get ultimos10() { 18 | this.mensajes = this.mensajes.splice(0,10); 19 | return this.mensajes; 20 | } 21 | 22 | get usuariosArr() { 23 | return Object.values( this.usuarios ); // [ {}, {}, {}] 24 | } 25 | 26 | enviarMensaje( uid, nombre, mensaje ) { 27 | this.mensajes.unshift( 28 | new Mensaje(uid, nombre, mensaje) 29 | ); 30 | } 31 | 32 | conectarUsuario( usuario ) { 33 | this.usuarios[usuario.id] = usuario 34 | } 35 | 36 | desconectarUsuario( id ) { 37 | delete this.usuarios[id]; 38 | } 39 | 40 | } 41 | 42 | module.exports = ChatMensajes; -------------------------------------------------------------------------------- /models/index.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | const Categoria = require('./categoria'); 4 | const ChatMensajes = require('./chat-mensajes') 5 | const Producto = require('./producto'); 6 | const Role = require('./role'); 7 | const Server = require('./server'); 8 | const Usuario = require('./usuario'); 9 | 10 | 11 | 12 | module.exports = { 13 | Categoria, 14 | ChatMensajes, 15 | Producto, 16 | Role, 17 | Server, 18 | Usuario, 19 | } 20 | 21 | -------------------------------------------------------------------------------- /models/producto.js: -------------------------------------------------------------------------------- 1 | const { Schema, model } = require('mongoose'); 2 | 3 | const ProductoSchema = Schema({ 4 | nombre: { 5 | type: String, 6 | required: [true, 'El nombre es obligatorio'], 7 | unique: true 8 | }, 9 | estado: { 10 | type: Boolean, 11 | default: true, 12 | required: true 13 | }, 14 | usuario: { 15 | type: Schema.Types.ObjectId, 16 | ref: 'Usuario', 17 | required: true 18 | }, 19 | precio: { 20 | type: Number, 21 | default: 0 22 | }, 23 | categoria: { 24 | type: Schema.Types.ObjectId, 25 | ref: 'Categoria', 26 | required: true 27 | }, 28 | descripcion: { type: String }, 29 | disponible: { type: Boolean, defult: true }, 30 | img: { type: String }, 31 | }); 32 | 33 | 34 | ProductoSchema.methods.toJSON = function() { 35 | const { __v, estado, ...data } = this.toObject(); 36 | return data; 37 | } 38 | 39 | 40 | module.exports = model( 'Producto', ProductoSchema ); 41 | -------------------------------------------------------------------------------- /models/role.js: -------------------------------------------------------------------------------- 1 | const { Schema, model } = require('mongoose'); 2 | 3 | const RoleSchema = Schema({ 4 | rol: { 5 | type: String, 6 | required: [true, 'El rol es obligatorio'] 7 | } 8 | }); 9 | 10 | 11 | module.exports = model( 'Role', RoleSchema ); 12 | -------------------------------------------------------------------------------- /models/server.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const cors = require('cors'); 3 | const fileUpload = require('express-fileupload'); 4 | const { createServer } = require('http'); 5 | 6 | const { dbConnection } = require('../database/config'); 7 | const { socketController } = require('../sockets/controller'); 8 | 9 | class Server { 10 | 11 | constructor() { 12 | this.app = express(); 13 | this.port = process.env.PORT; 14 | this.server = createServer( this.app ); 15 | this.io = require('socket.io')(this.server) 16 | 17 | this.paths = { 18 | auth: '/api/auth', 19 | buscar: '/api/buscar', 20 | categorias: '/api/categorias', 21 | productos: '/api/productos', 22 | usuarios: '/api/usuarios', 23 | uploads: '/api/uploads', 24 | } 25 | 26 | 27 | // Conectar a base de datos 28 | this.conectarDB(); 29 | 30 | // Middlewares 31 | this.middlewares(); 32 | 33 | // Rutas de mi aplicación 34 | this.routes(); 35 | 36 | // Sockets 37 | this.sockets(); 38 | } 39 | 40 | async conectarDB() { 41 | await dbConnection(); 42 | } 43 | 44 | 45 | middlewares() { 46 | 47 | // CORS 48 | this.app.use( cors() ); 49 | 50 | // Lectura y parseo del body 51 | this.app.use( express.json() ); 52 | 53 | // Directorio Público 54 | this.app.use( express.static('public') ); 55 | 56 | // Fileupload - Carga de archivos 57 | this.app.use( fileUpload({ 58 | useTempFiles : true, 59 | tempFileDir : '/tmp/', 60 | createParentPath: true 61 | })); 62 | 63 | } 64 | 65 | routes() { 66 | 67 | this.app.use( this.paths.auth, require('../routes/auth')); 68 | this.app.use( this.paths.buscar, require('../routes/buscar')); 69 | this.app.use( this.paths.categorias, require('../routes/categorias')); 70 | this.app.use( this.paths.productos, require('../routes/productos')); 71 | this.app.use( this.paths.usuarios, require('../routes/usuarios')); 72 | this.app.use( this.paths.uploads, require('../routes/uploads')); 73 | 74 | } 75 | 76 | 77 | sockets() { 78 | this.io.on('connection', ( socket ) => socketController(socket, this.io ) ) 79 | } 80 | 81 | listen() { 82 | this.server.listen( this.port, () => { 83 | console.log('Servidor corriendo en puerto', this.port ); 84 | }); 85 | } 86 | 87 | } 88 | 89 | 90 | 91 | 92 | module.exports = Server; 93 | -------------------------------------------------------------------------------- /models/usuario.js: -------------------------------------------------------------------------------- 1 | 2 | const { Schema, model } = require('mongoose'); 3 | 4 | const UsuarioSchema = Schema({ 5 | nombre: { 6 | type: String, 7 | required: [true, 'El nombre es obligatorio'] 8 | }, 9 | correo: { 10 | type: String, 11 | required: [true, 'El correo es obligatorio'], 12 | unique: true 13 | }, 14 | password: { 15 | type: String, 16 | required: [true, 'La contraseña es obligatoria'], 17 | }, 18 | img: { 19 | type: String, 20 | }, 21 | rol: { 22 | type: String, 23 | required: true, 24 | default: 'USER_ROLE', 25 | emun: ['ADMIN_ROLE', 'USER_ROLE'] 26 | }, 27 | estado: { 28 | type: Boolean, 29 | default: true 30 | }, 31 | google: { 32 | type: Boolean, 33 | default: false 34 | }, 35 | }); 36 | 37 | 38 | 39 | UsuarioSchema.methods.toJSON = function() { 40 | const { __v, password, _id, ...usuario } = this.toObject(); 41 | usuario.uid = _id; 42 | return usuario; 43 | } 44 | 45 | module.exports = model( 'Usuario', UsuarioSchema ); 46 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "07-restserver", 3 | "version": "1.0.0", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "07-restserver", 9 | "version": "1.0.0", 10 | "license": "ISC", 11 | "dependencies": { 12 | "bcryptjs": "^2.4.3", 13 | "cloudinary": "^1.24.0", 14 | "cors": "^2.8.5", 15 | "dotenv": "^8.2.0", 16 | "express": "^4.17.1", 17 | "express-fileupload": "^1.2.1", 18 | "express-validator": "^6.9.2", 19 | "google-auth-library": "^6.1.6", 20 | "jsonwebtoken": "^8.5.1", 21 | "mongoose": "^5.11.15", 22 | "socket.io": "^3.1.1", 23 | "uuid": "^8.3.2" 24 | } 25 | }, 26 | "node_modules/@types/bson": { 27 | "version": "4.0.3", 28 | "resolved": "https://registry.npmjs.org/@types/bson/-/bson-4.0.3.tgz", 29 | "integrity": "sha512-mVRvYnTOZJz3ccpxhr3wgxVmSeiYinW+zlzQz3SXWaJmD1DuL05Jeq7nKw3SnbKmbleW5qrLG5vdyWe/A9sXhw==", 30 | "dependencies": { 31 | "@types/node": "*" 32 | } 33 | }, 34 | "node_modules/@types/component-emitter": { 35 | "version": "1.2.10", 36 | "resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.10.tgz", 37 | "integrity": "sha512-bsjleuRKWmGqajMerkzox19aGbscQX5rmmvvXl3wlIp5gMG1HgkiwPxsN5p070fBDKTNSPgojVbuY1+HWMbFhg==" 38 | }, 39 | "node_modules/@types/cookie": { 40 | "version": "0.4.0", 41 | "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.0.tgz", 42 | "integrity": "sha512-y7mImlc/rNkvCRmg8gC3/lj87S7pTUIJ6QGjwHR9WQJcFs+ZMTOaoPrkdFA/YdbuqVEmEbb5RdhVxMkAcgOnpg==" 43 | }, 44 | "node_modules/@types/cors": { 45 | "version": "2.8.9", 46 | "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.9.tgz", 47 | "integrity": "sha512-zurD1ibz21BRlAOIKP8yhrxlqKx6L9VCwkB5kMiP6nZAhoF5MvC7qS1qPA7nRcr1GJolfkQC7/EAL4hdYejLtg==" 48 | }, 49 | "node_modules/@types/mongodb": { 50 | "version": "3.6.6", 51 | "resolved": "https://registry.npmjs.org/@types/mongodb/-/mongodb-3.6.6.tgz", 52 | "integrity": "sha512-ghYevKiSh/TGk2MAwSRZP7T1ilR9Pw8Fa7pT9GGVGZPUsWKdZjZ4G6LG3MqK2iXKdNba994F8W9ikA+qx2Eo3A==", 53 | "dependencies": { 54 | "@types/bson": "*", 55 | "@types/node": "*" 56 | } 57 | }, 58 | "node_modules/@types/node": { 59 | "version": "14.14.25", 60 | "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.25.tgz", 61 | "integrity": "sha512-EPpXLOVqDvisVxtlbvzfyqSsFeQxltFbluZNRndIb8tr9KiBnYNLzrc1N3pyKUCww2RNrfHDViqDWWE1LCJQtQ==" 62 | }, 63 | "node_modules/abort-controller": { 64 | "version": "3.0.0", 65 | "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", 66 | "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", 67 | "dependencies": { 68 | "event-target-shim": "^5.0.0" 69 | }, 70 | "engines": { 71 | "node": ">=6.5" 72 | } 73 | }, 74 | "node_modules/accepts": { 75 | "version": "1.3.7", 76 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", 77 | "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", 78 | "dependencies": { 79 | "mime-types": "~2.1.24", 80 | "negotiator": "0.6.2" 81 | }, 82 | "engines": { 83 | "node": ">= 0.6" 84 | } 85 | }, 86 | "node_modules/agent-base": { 87 | "version": "6.0.2", 88 | "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", 89 | "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", 90 | "dependencies": { 91 | "debug": "4" 92 | }, 93 | "engines": { 94 | "node": ">= 6.0.0" 95 | } 96 | }, 97 | "node_modules/agent-base/node_modules/debug": { 98 | "version": "4.3.1", 99 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", 100 | "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", 101 | "dependencies": { 102 | "ms": "2.1.2" 103 | }, 104 | "engines": { 105 | "node": ">=6.0" 106 | } 107 | }, 108 | "node_modules/agent-base/node_modules/ms": { 109 | "version": "2.1.2", 110 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 111 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 112 | }, 113 | "node_modules/array-flatten": { 114 | "version": "1.1.1", 115 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 116 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 117 | }, 118 | "node_modules/arrify": { 119 | "version": "2.0.1", 120 | "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", 121 | "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", 122 | "engines": { 123 | "node": ">=8" 124 | } 125 | }, 126 | "node_modules/base64-arraybuffer": { 127 | "version": "0.1.4", 128 | "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.4.tgz", 129 | "integrity": "sha1-mBjHngWbE1X5fgQooBfIOOkLqBI=", 130 | "engines": { 131 | "node": ">= 0.6.0" 132 | } 133 | }, 134 | "node_modules/base64-js": { 135 | "version": "1.5.1", 136 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", 137 | "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" 138 | }, 139 | "node_modules/base64id": { 140 | "version": "2.0.0", 141 | "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", 142 | "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", 143 | "engines": { 144 | "node": "^4.5.0 || >= 5.9" 145 | } 146 | }, 147 | "node_modules/bcryptjs": { 148 | "version": "2.4.3", 149 | "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", 150 | "integrity": "sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms=" 151 | }, 152 | "node_modules/bignumber.js": { 153 | "version": "9.0.1", 154 | "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.1.tgz", 155 | "integrity": "sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA==", 156 | "engines": { 157 | "node": "*" 158 | } 159 | }, 160 | "node_modules/bl": { 161 | "version": "2.2.1", 162 | "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz", 163 | "integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==", 164 | "dependencies": { 165 | "readable-stream": "^2.3.5", 166 | "safe-buffer": "^5.1.1" 167 | } 168 | }, 169 | "node_modules/bluebird": { 170 | "version": "3.5.1", 171 | "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", 172 | "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==" 173 | }, 174 | "node_modules/body-parser": { 175 | "version": "1.19.0", 176 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", 177 | "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", 178 | "dependencies": { 179 | "bytes": "3.1.0", 180 | "content-type": "~1.0.4", 181 | "debug": "2.6.9", 182 | "depd": "~1.1.2", 183 | "http-errors": "1.7.2", 184 | "iconv-lite": "0.4.24", 185 | "on-finished": "~2.3.0", 186 | "qs": "6.7.0", 187 | "raw-body": "2.4.0", 188 | "type-is": "~1.6.17" 189 | }, 190 | "engines": { 191 | "node": ">= 0.8" 192 | } 193 | }, 194 | "node_modules/bson": { 195 | "version": "1.1.5", 196 | "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.5.tgz", 197 | "integrity": "sha512-kDuEzldR21lHciPQAIulLs1LZlCXdLziXI6Mb/TDkwXhb//UORJNPXgcRs2CuO4H0DcMkpfT3/ySsP3unoZjBg==", 198 | "engines": { 199 | "node": ">=0.6.19" 200 | } 201 | }, 202 | "node_modules/buffer-equal-constant-time": { 203 | "version": "1.0.1", 204 | "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", 205 | "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" 206 | }, 207 | "node_modules/busboy": { 208 | "version": "0.3.1", 209 | "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.3.1.tgz", 210 | "integrity": "sha512-y7tTxhGKXcyBxRKAni+awqx8uqaJKrSFSNFSeRG5CsWNdmy2BIK+6VGWEW7TZnIO/533mtMEA4rOevQV815YJw==", 211 | "dependencies": { 212 | "dicer": "0.3.0" 213 | }, 214 | "engines": { 215 | "node": ">=4.5.0" 216 | } 217 | }, 218 | "node_modules/bytes": { 219 | "version": "3.1.0", 220 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", 221 | "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", 222 | "engines": { 223 | "node": ">= 0.8" 224 | } 225 | }, 226 | "node_modules/cloudinary": { 227 | "version": "1.24.0", 228 | "resolved": "https://registry.npmjs.org/cloudinary/-/cloudinary-1.24.0.tgz", 229 | "integrity": "sha512-bILjdVB/FCv5Zyypuhp5IdKeoDDMbA/8ybq8kILV9At5l2AV3ZwdjvYSNF04hTg9+Zan1d5id6LmV5liGsx1bw==", 230 | "dependencies": { 231 | "cloudinary-core": "^2.10.2", 232 | "core-js": "3.6.5", 233 | "lodash": "^4.17.11", 234 | "q": "^1.5.1" 235 | }, 236 | "engines": { 237 | "node": ">=0.6" 238 | } 239 | }, 240 | "node_modules/cloudinary-core": { 241 | "version": "2.11.3", 242 | "resolved": "https://registry.npmjs.org/cloudinary-core/-/cloudinary-core-2.11.3.tgz", 243 | "integrity": "sha512-ZRnpjSgvx+LbSf+aEz5NKzxDB4Z0436aY/0BSDa90kAHiwAyd84VyEi95I74SE80e15Ri9t5S2xtksTXpzk9Xw==" 244 | }, 245 | "node_modules/component-emitter": { 246 | "version": "1.3.0", 247 | "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", 248 | "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" 249 | }, 250 | "node_modules/content-disposition": { 251 | "version": "0.5.3", 252 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", 253 | "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", 254 | "dependencies": { 255 | "safe-buffer": "5.1.2" 256 | }, 257 | "engines": { 258 | "node": ">= 0.6" 259 | } 260 | }, 261 | "node_modules/content-type": { 262 | "version": "1.0.4", 263 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 264 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", 265 | "engines": { 266 | "node": ">= 0.6" 267 | } 268 | }, 269 | "node_modules/cookie": { 270 | "version": "0.4.0", 271 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", 272 | "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", 273 | "engines": { 274 | "node": ">= 0.6" 275 | } 276 | }, 277 | "node_modules/cookie-signature": { 278 | "version": "1.0.6", 279 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 280 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" 281 | }, 282 | "node_modules/core-js": { 283 | "version": "3.6.5", 284 | "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.5.tgz", 285 | "integrity": "sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA==", 286 | "hasInstallScript": true 287 | }, 288 | "node_modules/core-util-is": { 289 | "version": "1.0.2", 290 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 291 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" 292 | }, 293 | "node_modules/cors": { 294 | "version": "2.8.5", 295 | "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", 296 | "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", 297 | "dependencies": { 298 | "object-assign": "^4", 299 | "vary": "^1" 300 | }, 301 | "engines": { 302 | "node": ">= 0.10" 303 | } 304 | }, 305 | "node_modules/debug": { 306 | "version": "2.6.9", 307 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 308 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 309 | "dependencies": { 310 | "ms": "2.0.0" 311 | } 312 | }, 313 | "node_modules/denque": { 314 | "version": "1.5.0", 315 | "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.0.tgz", 316 | "integrity": "sha512-CYiCSgIF1p6EUByQPlGkKnP1M9g0ZV3qMIrqMqZqdwazygIA/YP2vrbcyl1h/WppKJTdl1F85cXIle+394iDAQ==", 317 | "engines": { 318 | "node": ">=0.10" 319 | } 320 | }, 321 | "node_modules/depd": { 322 | "version": "1.1.2", 323 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", 324 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", 325 | "engines": { 326 | "node": ">= 0.6" 327 | } 328 | }, 329 | "node_modules/destroy": { 330 | "version": "1.0.4", 331 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", 332 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" 333 | }, 334 | "node_modules/dicer": { 335 | "version": "0.3.0", 336 | "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.3.0.tgz", 337 | "integrity": "sha512-MdceRRWqltEG2dZqO769g27N/3PXfcKl04VhYnBlo2YhH7zPi88VebsjTKclaOyiuMaGU72hTfw3VkUitGcVCA==", 338 | "dependencies": { 339 | "streamsearch": "0.1.2" 340 | }, 341 | "engines": { 342 | "node": ">=4.5.0" 343 | } 344 | }, 345 | "node_modules/dotenv": { 346 | "version": "8.2.0", 347 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz", 348 | "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==", 349 | "engines": { 350 | "node": ">=8" 351 | } 352 | }, 353 | "node_modules/ecdsa-sig-formatter": { 354 | "version": "1.0.11", 355 | "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", 356 | "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", 357 | "dependencies": { 358 | "safe-buffer": "^5.0.1" 359 | } 360 | }, 361 | "node_modules/ee-first": { 362 | "version": "1.1.1", 363 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 364 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 365 | }, 366 | "node_modules/encodeurl": { 367 | "version": "1.0.2", 368 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 369 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", 370 | "engines": { 371 | "node": ">= 0.8" 372 | } 373 | }, 374 | "node_modules/engine.io": { 375 | "version": "4.1.1", 376 | "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-4.1.1.tgz", 377 | "integrity": "sha512-t2E9wLlssQjGw0nluF6aYyfX8LwYU8Jj0xct+pAhfWfv/YrBn6TSNtEYsgxHIfaMqfrLx07czcMg9bMN6di+3w==", 378 | "dependencies": { 379 | "accepts": "~1.3.4", 380 | "base64id": "2.0.0", 381 | "cookie": "~0.4.1", 382 | "cors": "~2.8.5", 383 | "debug": "~4.3.1", 384 | "engine.io-parser": "~4.0.0", 385 | "ws": "~7.4.2" 386 | }, 387 | "engines": { 388 | "node": ">=10.0.0" 389 | } 390 | }, 391 | "node_modules/engine.io-parser": { 392 | "version": "4.0.2", 393 | "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-4.0.2.tgz", 394 | "integrity": "sha512-sHfEQv6nmtJrq6TKuIz5kyEKH/qSdK56H/A+7DnAuUPWosnIZAS2NHNcPLmyjtY3cGS/MqJdZbUjW97JU72iYg==", 395 | "dependencies": { 396 | "base64-arraybuffer": "0.1.4" 397 | }, 398 | "engines": { 399 | "node": ">=8.0.0" 400 | } 401 | }, 402 | "node_modules/engine.io/node_modules/cookie": { 403 | "version": "0.4.1", 404 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", 405 | "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", 406 | "engines": { 407 | "node": ">= 0.6" 408 | } 409 | }, 410 | "node_modules/engine.io/node_modules/debug": { 411 | "version": "4.3.1", 412 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", 413 | "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", 414 | "dependencies": { 415 | "ms": "2.1.2" 416 | }, 417 | "engines": { 418 | "node": ">=6.0" 419 | }, 420 | "peerDependenciesMeta": { 421 | "supports-color": { 422 | "optional": true 423 | } 424 | } 425 | }, 426 | "node_modules/engine.io/node_modules/ms": { 427 | "version": "2.1.2", 428 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 429 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 430 | }, 431 | "node_modules/escape-html": { 432 | "version": "1.0.3", 433 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 434 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" 435 | }, 436 | "node_modules/etag": { 437 | "version": "1.8.1", 438 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 439 | "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", 440 | "engines": { 441 | "node": ">= 0.6" 442 | } 443 | }, 444 | "node_modules/event-target-shim": { 445 | "version": "5.0.1", 446 | "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", 447 | "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", 448 | "engines": { 449 | "node": ">=6" 450 | } 451 | }, 452 | "node_modules/express": { 453 | "version": "4.17.1", 454 | "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", 455 | "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", 456 | "dependencies": { 457 | "accepts": "~1.3.7", 458 | "array-flatten": "1.1.1", 459 | "body-parser": "1.19.0", 460 | "content-disposition": "0.5.3", 461 | "content-type": "~1.0.4", 462 | "cookie": "0.4.0", 463 | "cookie-signature": "1.0.6", 464 | "debug": "2.6.9", 465 | "depd": "~1.1.2", 466 | "encodeurl": "~1.0.2", 467 | "escape-html": "~1.0.3", 468 | "etag": "~1.8.1", 469 | "finalhandler": "~1.1.2", 470 | "fresh": "0.5.2", 471 | "merge-descriptors": "1.0.1", 472 | "methods": "~1.1.2", 473 | "on-finished": "~2.3.0", 474 | "parseurl": "~1.3.3", 475 | "path-to-regexp": "0.1.7", 476 | "proxy-addr": "~2.0.5", 477 | "qs": "6.7.0", 478 | "range-parser": "~1.2.1", 479 | "safe-buffer": "5.1.2", 480 | "send": "0.17.1", 481 | "serve-static": "1.14.1", 482 | "setprototypeof": "1.1.1", 483 | "statuses": "~1.5.0", 484 | "type-is": "~1.6.18", 485 | "utils-merge": "1.0.1", 486 | "vary": "~1.1.2" 487 | }, 488 | "engines": { 489 | "node": ">= 0.10.0" 490 | } 491 | }, 492 | "node_modules/express-fileupload": { 493 | "version": "1.2.1", 494 | "resolved": "https://registry.npmjs.org/express-fileupload/-/express-fileupload-1.2.1.tgz", 495 | "integrity": "sha512-fWPNAkBj+Azt9Itmcz/Reqdg3LeBfaXptDEev2JM8bCC0yDptglCnlizhf0YZauyU5X/g6v7v4Xxqhg8tmEfEA==", 496 | "dependencies": { 497 | "busboy": "^0.3.1" 498 | }, 499 | "engines": { 500 | "node": ">=8.0.0" 501 | } 502 | }, 503 | "node_modules/express-validator": { 504 | "version": "6.9.2", 505 | "resolved": "https://registry.npmjs.org/express-validator/-/express-validator-6.9.2.tgz", 506 | "integrity": "sha512-Yqlsw2/uBobtBVkP+gnds8OMmVAEb3uTI4uXC93l0Ym5JGHgr8Vd4ws7oSo7GGYpWn5YCq4UePMEppKchURXrw==", 507 | "dependencies": { 508 | "lodash": "^4.17.20", 509 | "validator": "^13.5.2" 510 | }, 511 | "engines": { 512 | "node": ">= 8.0.0" 513 | } 514 | }, 515 | "node_modules/extend": { 516 | "version": "3.0.2", 517 | "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", 518 | "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" 519 | }, 520 | "node_modules/fast-text-encoding": { 521 | "version": "1.0.3", 522 | "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.3.tgz", 523 | "integrity": "sha512-dtm4QZH9nZtcDt8qJiOH9fcQd1NAgi+K1O2DbE6GG1PPCK/BWfOH3idCTRQ4ImXRUOyopDEgDEnVEE7Y/2Wrig==" 524 | }, 525 | "node_modules/finalhandler": { 526 | "version": "1.1.2", 527 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", 528 | "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", 529 | "dependencies": { 530 | "debug": "2.6.9", 531 | "encodeurl": "~1.0.2", 532 | "escape-html": "~1.0.3", 533 | "on-finished": "~2.3.0", 534 | "parseurl": "~1.3.3", 535 | "statuses": "~1.5.0", 536 | "unpipe": "~1.0.0" 537 | }, 538 | "engines": { 539 | "node": ">= 0.8" 540 | } 541 | }, 542 | "node_modules/forwarded": { 543 | "version": "0.1.2", 544 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", 545 | "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", 546 | "engines": { 547 | "node": ">= 0.6" 548 | } 549 | }, 550 | "node_modules/fresh": { 551 | "version": "0.5.2", 552 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 553 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", 554 | "engines": { 555 | "node": ">= 0.6" 556 | } 557 | }, 558 | "node_modules/gaxios": { 559 | "version": "4.1.0", 560 | "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-4.1.0.tgz", 561 | "integrity": "sha512-vb0to8xzGnA2qcgywAjtshOKKVDf2eQhJoiL6fHhgW5tVN7wNk7egnYIO9zotfn3lQ3De1VPdf7V5/BWfCtCmg==", 562 | "dependencies": { 563 | "abort-controller": "^3.0.0", 564 | "extend": "^3.0.2", 565 | "https-proxy-agent": "^5.0.0", 566 | "is-stream": "^2.0.0", 567 | "node-fetch": "^2.3.0" 568 | }, 569 | "engines": { 570 | "node": ">=10" 571 | } 572 | }, 573 | "node_modules/gcp-metadata": { 574 | "version": "4.2.1", 575 | "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-4.2.1.tgz", 576 | "integrity": "sha512-tSk+REe5iq/N+K+SK1XjZJUrFPuDqGZVzCy2vocIHIGmPlTGsa8owXMJwGkrXr73NO0AzhPW4MF2DEHz7P2AVw==", 577 | "dependencies": { 578 | "gaxios": "^4.0.0", 579 | "json-bigint": "^1.0.0" 580 | }, 581 | "engines": { 582 | "node": ">=10" 583 | } 584 | }, 585 | "node_modules/google-auth-library": { 586 | "version": "6.1.6", 587 | "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-6.1.6.tgz", 588 | "integrity": "sha512-Q+ZjUEvLQj/lrVHF/IQwRo6p3s8Nc44Zk/DALsN+ac3T4HY/g/3rrufkgtl+nZ1TW7DNAw5cTChdVp4apUXVgQ==", 589 | "dependencies": { 590 | "arrify": "^2.0.0", 591 | "base64-js": "^1.3.0", 592 | "ecdsa-sig-formatter": "^1.0.11", 593 | "fast-text-encoding": "^1.0.0", 594 | "gaxios": "^4.0.0", 595 | "gcp-metadata": "^4.2.0", 596 | "gtoken": "^5.0.4", 597 | "jws": "^4.0.0", 598 | "lru-cache": "^6.0.0" 599 | }, 600 | "engines": { 601 | "node": ">=10" 602 | } 603 | }, 604 | "node_modules/google-auth-library/node_modules/jwa": { 605 | "version": "2.0.0", 606 | "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", 607 | "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", 608 | "dependencies": { 609 | "buffer-equal-constant-time": "1.0.1", 610 | "ecdsa-sig-formatter": "1.0.11", 611 | "safe-buffer": "^5.0.1" 612 | } 613 | }, 614 | "node_modules/google-auth-library/node_modules/jws": { 615 | "version": "4.0.0", 616 | "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", 617 | "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", 618 | "dependencies": { 619 | "jwa": "^2.0.0", 620 | "safe-buffer": "^5.0.1" 621 | } 622 | }, 623 | "node_modules/google-p12-pem": { 624 | "version": "3.0.3", 625 | "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.0.3.tgz", 626 | "integrity": "sha512-wS0ek4ZtFx/ACKYF3JhyGe5kzH7pgiQ7J5otlumqR9psmWMYc+U9cErKlCYVYHoUaidXHdZ2xbo34kB+S+24hA==", 627 | "dependencies": { 628 | "node-forge": "^0.10.0" 629 | }, 630 | "bin": { 631 | "gp12-pem": "build/src/bin/gp12-pem.js" 632 | }, 633 | "engines": { 634 | "node": ">=10" 635 | } 636 | }, 637 | "node_modules/gtoken": { 638 | "version": "5.2.1", 639 | "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-5.2.1.tgz", 640 | "integrity": "sha512-OY0BfPKe3QnMsY9MzTHTSKn+Vl2l1CcLe6BwDEQj00mbbkl5nyQ/7EUREstg4fQNZ8iYE7br4JJ7TdKeDOPWmw==", 641 | "dependencies": { 642 | "gaxios": "^4.0.0", 643 | "google-p12-pem": "^3.0.3", 644 | "jws": "^4.0.0" 645 | }, 646 | "engines": { 647 | "node": ">=10" 648 | } 649 | }, 650 | "node_modules/gtoken/node_modules/jwa": { 651 | "version": "2.0.0", 652 | "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", 653 | "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", 654 | "dependencies": { 655 | "buffer-equal-constant-time": "1.0.1", 656 | "ecdsa-sig-formatter": "1.0.11", 657 | "safe-buffer": "^5.0.1" 658 | } 659 | }, 660 | "node_modules/gtoken/node_modules/jws": { 661 | "version": "4.0.0", 662 | "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", 663 | "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", 664 | "dependencies": { 665 | "jwa": "^2.0.0", 666 | "safe-buffer": "^5.0.1" 667 | } 668 | }, 669 | "node_modules/http-errors": { 670 | "version": "1.7.2", 671 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", 672 | "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", 673 | "dependencies": { 674 | "depd": "~1.1.2", 675 | "inherits": "2.0.3", 676 | "setprototypeof": "1.1.1", 677 | "statuses": ">= 1.5.0 < 2", 678 | "toidentifier": "1.0.0" 679 | }, 680 | "engines": { 681 | "node": ">= 0.6" 682 | } 683 | }, 684 | "node_modules/https-proxy-agent": { 685 | "version": "5.0.0", 686 | "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", 687 | "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", 688 | "dependencies": { 689 | "agent-base": "6", 690 | "debug": "4" 691 | }, 692 | "engines": { 693 | "node": ">= 6" 694 | } 695 | }, 696 | "node_modules/https-proxy-agent/node_modules/debug": { 697 | "version": "4.3.1", 698 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", 699 | "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", 700 | "dependencies": { 701 | "ms": "2.1.2" 702 | }, 703 | "engines": { 704 | "node": ">=6.0" 705 | } 706 | }, 707 | "node_modules/https-proxy-agent/node_modules/ms": { 708 | "version": "2.1.2", 709 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 710 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 711 | }, 712 | "node_modules/iconv-lite": { 713 | "version": "0.4.24", 714 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 715 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 716 | "dependencies": { 717 | "safer-buffer": ">= 2.1.2 < 3" 718 | }, 719 | "engines": { 720 | "node": ">=0.10.0" 721 | } 722 | }, 723 | "node_modules/inherits": { 724 | "version": "2.0.3", 725 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 726 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 727 | }, 728 | "node_modules/ipaddr.js": { 729 | "version": "1.9.1", 730 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 731 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", 732 | "engines": { 733 | "node": ">= 0.10" 734 | } 735 | }, 736 | "node_modules/is-stream": { 737 | "version": "2.0.0", 738 | "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", 739 | "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", 740 | "engines": { 741 | "node": ">=8" 742 | } 743 | }, 744 | "node_modules/isarray": { 745 | "version": "1.0.0", 746 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 747 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" 748 | }, 749 | "node_modules/json-bigint": { 750 | "version": "1.0.0", 751 | "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", 752 | "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", 753 | "dependencies": { 754 | "bignumber.js": "^9.0.0" 755 | } 756 | }, 757 | "node_modules/jsonwebtoken": { 758 | "version": "8.5.1", 759 | "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", 760 | "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", 761 | "dependencies": { 762 | "jws": "^3.2.2", 763 | "lodash.includes": "^4.3.0", 764 | "lodash.isboolean": "^3.0.3", 765 | "lodash.isinteger": "^4.0.4", 766 | "lodash.isnumber": "^3.0.3", 767 | "lodash.isplainobject": "^4.0.6", 768 | "lodash.isstring": "^4.0.1", 769 | "lodash.once": "^4.0.0", 770 | "ms": "^2.1.1", 771 | "semver": "^5.6.0" 772 | }, 773 | "engines": { 774 | "node": ">=4", 775 | "npm": ">=1.4.28" 776 | } 777 | }, 778 | "node_modules/jsonwebtoken/node_modules/ms": { 779 | "version": "2.1.3", 780 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 781 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" 782 | }, 783 | "node_modules/jwa": { 784 | "version": "1.4.1", 785 | "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", 786 | "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", 787 | "dependencies": { 788 | "buffer-equal-constant-time": "1.0.1", 789 | "ecdsa-sig-formatter": "1.0.11", 790 | "safe-buffer": "^5.0.1" 791 | } 792 | }, 793 | "node_modules/jws": { 794 | "version": "3.2.2", 795 | "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", 796 | "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", 797 | "dependencies": { 798 | "jwa": "^1.4.1", 799 | "safe-buffer": "^5.0.1" 800 | } 801 | }, 802 | "node_modules/kareem": { 803 | "version": "2.3.2", 804 | "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.3.2.tgz", 805 | "integrity": "sha512-STHz9P7X2L4Kwn72fA4rGyqyXdmrMSdxqHx9IXon/FXluXieaFA6KJ2upcHAHxQPQ0LeM/OjLrhFxifHewOALQ==" 806 | }, 807 | "node_modules/lodash": { 808 | "version": "4.17.20", 809 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", 810 | "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" 811 | }, 812 | "node_modules/lodash.includes": { 813 | "version": "4.3.0", 814 | "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", 815 | "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=" 816 | }, 817 | "node_modules/lodash.isboolean": { 818 | "version": "3.0.3", 819 | "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", 820 | "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=" 821 | }, 822 | "node_modules/lodash.isinteger": { 823 | "version": "4.0.4", 824 | "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", 825 | "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=" 826 | }, 827 | "node_modules/lodash.isnumber": { 828 | "version": "3.0.3", 829 | "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", 830 | "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=" 831 | }, 832 | "node_modules/lodash.isplainobject": { 833 | "version": "4.0.6", 834 | "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", 835 | "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" 836 | }, 837 | "node_modules/lodash.isstring": { 838 | "version": "4.0.1", 839 | "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", 840 | "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=" 841 | }, 842 | "node_modules/lodash.once": { 843 | "version": "4.1.1", 844 | "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", 845 | "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=" 846 | }, 847 | "node_modules/lru-cache": { 848 | "version": "6.0.0", 849 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", 850 | "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", 851 | "dependencies": { 852 | "yallist": "^4.0.0" 853 | }, 854 | "engines": { 855 | "node": ">=10" 856 | } 857 | }, 858 | "node_modules/media-typer": { 859 | "version": "0.3.0", 860 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 861 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", 862 | "engines": { 863 | "node": ">= 0.6" 864 | } 865 | }, 866 | "node_modules/memory-pager": { 867 | "version": "1.5.0", 868 | "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", 869 | "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", 870 | "optional": true 871 | }, 872 | "node_modules/merge-descriptors": { 873 | "version": "1.0.1", 874 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 875 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" 876 | }, 877 | "node_modules/methods": { 878 | "version": "1.1.2", 879 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 880 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", 881 | "engines": { 882 | "node": ">= 0.6" 883 | } 884 | }, 885 | "node_modules/mime": { 886 | "version": "1.6.0", 887 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 888 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", 889 | "bin": { 890 | "mime": "cli.js" 891 | }, 892 | "engines": { 893 | "node": ">=4" 894 | } 895 | }, 896 | "node_modules/mime-db": { 897 | "version": "1.45.0", 898 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz", 899 | "integrity": "sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==", 900 | "engines": { 901 | "node": ">= 0.6" 902 | } 903 | }, 904 | "node_modules/mime-types": { 905 | "version": "2.1.28", 906 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.28.tgz", 907 | "integrity": "sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ==", 908 | "dependencies": { 909 | "mime-db": "1.45.0" 910 | }, 911 | "engines": { 912 | "node": ">= 0.6" 913 | } 914 | }, 915 | "node_modules/mongodb": { 916 | "version": "3.6.3", 917 | "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.3.tgz", 918 | "integrity": "sha512-rOZuR0QkodZiM+UbQE5kDsJykBqWi0CL4Ec2i1nrGrUI3KO11r6Fbxskqmq3JK2NH7aW4dcccBuUujAP0ERl5w==", 919 | "dependencies": { 920 | "bl": "^2.2.1", 921 | "bson": "^1.1.4", 922 | "denque": "^1.4.1", 923 | "require_optional": "^1.0.1", 924 | "safe-buffer": "^5.1.2" 925 | }, 926 | "engines": { 927 | "node": ">=4" 928 | }, 929 | "optionalDependencies": { 930 | "saslprep": "^1.0.0" 931 | } 932 | }, 933 | "node_modules/mongoose": { 934 | "version": "5.11.15", 935 | "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.11.15.tgz", 936 | "integrity": "sha512-8T4bT6eCGB7MqCm40oVhnhT/1AyAdwe+y1rYUhdl3ljsks3BpYz8whZgcMkIoh6VoCCjipOXRqZqdk1UByvlYA==", 937 | "dependencies": { 938 | "@types/mongodb": "^3.5.27", 939 | "bson": "^1.1.4", 940 | "kareem": "2.3.2", 941 | "mongodb": "3.6.3", 942 | "mongoose-legacy-pluralize": "1.0.2", 943 | "mpath": "0.8.3", 944 | "mquery": "3.2.3", 945 | "ms": "2.1.2", 946 | "regexp-clone": "1.0.0", 947 | "safe-buffer": "5.2.1", 948 | "sift": "7.0.1", 949 | "sliced": "1.0.1" 950 | }, 951 | "engines": { 952 | "node": ">=4.0.0" 953 | } 954 | }, 955 | "node_modules/mongoose-legacy-pluralize": { 956 | "version": "1.0.2", 957 | "resolved": "https://registry.npmjs.org/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz", 958 | "integrity": "sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ==" 959 | }, 960 | "node_modules/mongoose/node_modules/ms": { 961 | "version": "2.1.2", 962 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 963 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 964 | }, 965 | "node_modules/mongoose/node_modules/safe-buffer": { 966 | "version": "5.2.1", 967 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 968 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" 969 | }, 970 | "node_modules/mpath": { 971 | "version": "0.8.3", 972 | "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.8.3.tgz", 973 | "integrity": "sha512-eb9rRvhDltXVNL6Fxd2zM9D4vKBxjVVQNLNijlj7uoXUy19zNDsIif5zR+pWmPCWNKwAtqyo4JveQm4nfD5+eA==", 974 | "engines": { 975 | "node": ">=4.0.0" 976 | } 977 | }, 978 | "node_modules/mquery": { 979 | "version": "3.2.3", 980 | "resolved": "https://registry.npmjs.org/mquery/-/mquery-3.2.3.tgz", 981 | "integrity": "sha512-cIfbP4TyMYX+SkaQ2MntD+F2XbqaBHUYWk3j+kqdDztPWok3tgyssOZxMHMtzbV1w9DaSlvEea0Iocuro41A4g==", 982 | "dependencies": { 983 | "bluebird": "3.5.1", 984 | "debug": "3.1.0", 985 | "regexp-clone": "^1.0.0", 986 | "safe-buffer": "5.1.2", 987 | "sliced": "1.0.1" 988 | }, 989 | "engines": { 990 | "node": ">=4.0.0" 991 | } 992 | }, 993 | "node_modules/mquery/node_modules/debug": { 994 | "version": "3.1.0", 995 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", 996 | "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", 997 | "dependencies": { 998 | "ms": "2.0.0" 999 | } 1000 | }, 1001 | "node_modules/ms": { 1002 | "version": "2.0.0", 1003 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 1004 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 1005 | }, 1006 | "node_modules/negotiator": { 1007 | "version": "0.6.2", 1008 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", 1009 | "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", 1010 | "engines": { 1011 | "node": ">= 0.6" 1012 | } 1013 | }, 1014 | "node_modules/node-fetch": { 1015 | "version": "2.6.1", 1016 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", 1017 | "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", 1018 | "engines": { 1019 | "node": "4.x || >=6.0.0" 1020 | } 1021 | }, 1022 | "node_modules/node-forge": { 1023 | "version": "0.10.0", 1024 | "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz", 1025 | "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==", 1026 | "engines": { 1027 | "node": ">= 6.0.0" 1028 | } 1029 | }, 1030 | "node_modules/object-assign": { 1031 | "version": "4.1.1", 1032 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 1033 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", 1034 | "engines": { 1035 | "node": ">=0.10.0" 1036 | } 1037 | }, 1038 | "node_modules/on-finished": { 1039 | "version": "2.3.0", 1040 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 1041 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 1042 | "dependencies": { 1043 | "ee-first": "1.1.1" 1044 | }, 1045 | "engines": { 1046 | "node": ">= 0.8" 1047 | } 1048 | }, 1049 | "node_modules/parseurl": { 1050 | "version": "1.3.3", 1051 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 1052 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", 1053 | "engines": { 1054 | "node": ">= 0.8" 1055 | } 1056 | }, 1057 | "node_modules/path-to-regexp": { 1058 | "version": "0.1.7", 1059 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 1060 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" 1061 | }, 1062 | "node_modules/process-nextick-args": { 1063 | "version": "2.0.1", 1064 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", 1065 | "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" 1066 | }, 1067 | "node_modules/proxy-addr": { 1068 | "version": "2.0.6", 1069 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", 1070 | "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", 1071 | "dependencies": { 1072 | "forwarded": "~0.1.2", 1073 | "ipaddr.js": "1.9.1" 1074 | }, 1075 | "engines": { 1076 | "node": ">= 0.10" 1077 | } 1078 | }, 1079 | "node_modules/q": { 1080 | "version": "1.5.1", 1081 | "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", 1082 | "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", 1083 | "engines": { 1084 | "node": ">=0.6.0", 1085 | "teleport": ">=0.2.0" 1086 | } 1087 | }, 1088 | "node_modules/qs": { 1089 | "version": "6.7.0", 1090 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", 1091 | "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", 1092 | "engines": { 1093 | "node": ">=0.6" 1094 | } 1095 | }, 1096 | "node_modules/range-parser": { 1097 | "version": "1.2.1", 1098 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 1099 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", 1100 | "engines": { 1101 | "node": ">= 0.6" 1102 | } 1103 | }, 1104 | "node_modules/raw-body": { 1105 | "version": "2.4.0", 1106 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", 1107 | "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", 1108 | "dependencies": { 1109 | "bytes": "3.1.0", 1110 | "http-errors": "1.7.2", 1111 | "iconv-lite": "0.4.24", 1112 | "unpipe": "1.0.0" 1113 | }, 1114 | "engines": { 1115 | "node": ">= 0.8" 1116 | } 1117 | }, 1118 | "node_modules/readable-stream": { 1119 | "version": "2.3.7", 1120 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", 1121 | "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", 1122 | "dependencies": { 1123 | "core-util-is": "~1.0.0", 1124 | "inherits": "~2.0.3", 1125 | "isarray": "~1.0.0", 1126 | "process-nextick-args": "~2.0.0", 1127 | "safe-buffer": "~5.1.1", 1128 | "string_decoder": "~1.1.1", 1129 | "util-deprecate": "~1.0.1" 1130 | } 1131 | }, 1132 | "node_modules/regexp-clone": { 1133 | "version": "1.0.0", 1134 | "resolved": "https://registry.npmjs.org/regexp-clone/-/regexp-clone-1.0.0.tgz", 1135 | "integrity": "sha512-TuAasHQNamyyJ2hb97IuBEif4qBHGjPHBS64sZwytpLEqtBQ1gPJTnOaQ6qmpET16cK14kkjbazl6+p0RRv0yw==" 1136 | }, 1137 | "node_modules/require_optional": { 1138 | "version": "1.0.1", 1139 | "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz", 1140 | "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==", 1141 | "dependencies": { 1142 | "resolve-from": "^2.0.0", 1143 | "semver": "^5.1.0" 1144 | } 1145 | }, 1146 | "node_modules/resolve-from": { 1147 | "version": "2.0.0", 1148 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", 1149 | "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=", 1150 | "engines": { 1151 | "node": ">=0.10.0" 1152 | } 1153 | }, 1154 | "node_modules/safe-buffer": { 1155 | "version": "5.1.2", 1156 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 1157 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 1158 | }, 1159 | "node_modules/safer-buffer": { 1160 | "version": "2.1.2", 1161 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 1162 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 1163 | }, 1164 | "node_modules/saslprep": { 1165 | "version": "1.0.3", 1166 | "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", 1167 | "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", 1168 | "optional": true, 1169 | "dependencies": { 1170 | "sparse-bitfield": "^3.0.3" 1171 | }, 1172 | "engines": { 1173 | "node": ">=6" 1174 | } 1175 | }, 1176 | "node_modules/semver": { 1177 | "version": "5.7.1", 1178 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", 1179 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", 1180 | "bin": { 1181 | "semver": "bin/semver" 1182 | } 1183 | }, 1184 | "node_modules/send": { 1185 | "version": "0.17.1", 1186 | "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", 1187 | "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", 1188 | "dependencies": { 1189 | "debug": "2.6.9", 1190 | "depd": "~1.1.2", 1191 | "destroy": "~1.0.4", 1192 | "encodeurl": "~1.0.2", 1193 | "escape-html": "~1.0.3", 1194 | "etag": "~1.8.1", 1195 | "fresh": "0.5.2", 1196 | "http-errors": "~1.7.2", 1197 | "mime": "1.6.0", 1198 | "ms": "2.1.1", 1199 | "on-finished": "~2.3.0", 1200 | "range-parser": "~1.2.1", 1201 | "statuses": "~1.5.0" 1202 | }, 1203 | "engines": { 1204 | "node": ">= 0.8.0" 1205 | } 1206 | }, 1207 | "node_modules/send/node_modules/ms": { 1208 | "version": "2.1.1", 1209 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", 1210 | "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" 1211 | }, 1212 | "node_modules/serve-static": { 1213 | "version": "1.14.1", 1214 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", 1215 | "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", 1216 | "dependencies": { 1217 | "encodeurl": "~1.0.2", 1218 | "escape-html": "~1.0.3", 1219 | "parseurl": "~1.3.3", 1220 | "send": "0.17.1" 1221 | }, 1222 | "engines": { 1223 | "node": ">= 0.8.0" 1224 | } 1225 | }, 1226 | "node_modules/setprototypeof": { 1227 | "version": "1.1.1", 1228 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", 1229 | "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" 1230 | }, 1231 | "node_modules/sift": { 1232 | "version": "7.0.1", 1233 | "resolved": "https://registry.npmjs.org/sift/-/sift-7.0.1.tgz", 1234 | "integrity": "sha512-oqD7PMJ+uO6jV9EQCl0LrRw1OwsiPsiFQR5AR30heR+4Dl7jBBbDLnNvWiak20tzZlSE1H7RB30SX/1j/YYT7g==" 1235 | }, 1236 | "node_modules/sliced": { 1237 | "version": "1.0.1", 1238 | "resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz", 1239 | "integrity": "sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E=" 1240 | }, 1241 | "node_modules/socket.io": { 1242 | "version": "3.1.1", 1243 | "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-3.1.1.tgz", 1244 | "integrity": "sha512-7cBWdsDC7bbyEF6WbBqffjizc/H4YF1wLdZoOzuYfo2uMNSFjJKuQ36t0H40o9B20DO6p+mSytEd92oP4S15bA==", 1245 | "dependencies": { 1246 | "@types/cookie": "^0.4.0", 1247 | "@types/cors": "^2.8.8", 1248 | "@types/node": "^14.14.10", 1249 | "accepts": "~1.3.4", 1250 | "base64id": "~2.0.0", 1251 | "debug": "~4.3.1", 1252 | "engine.io": "~4.1.0", 1253 | "socket.io-adapter": "~2.1.0", 1254 | "socket.io-parser": "~4.0.3" 1255 | }, 1256 | "engines": { 1257 | "node": ">=10.0.0" 1258 | } 1259 | }, 1260 | "node_modules/socket.io-adapter": { 1261 | "version": "2.1.0", 1262 | "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.1.0.tgz", 1263 | "integrity": "sha512-+vDov/aTsLjViYTwS9fPy5pEtTkrbEKsw2M+oVSoFGw6OD1IpvlV1VPhUzNbofCQ8oyMbdYJqDtGdmHQK6TdPg==" 1264 | }, 1265 | "node_modules/socket.io-parser": { 1266 | "version": "4.0.4", 1267 | "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.4.tgz", 1268 | "integrity": "sha512-t+b0SS+IxG7Rxzda2EVvyBZbvFPBCjJoyHuE0P//7OAsN23GItzDRdWa6ALxZI/8R5ygK7jAR6t028/z+7295g==", 1269 | "dependencies": { 1270 | "@types/component-emitter": "^1.2.10", 1271 | "component-emitter": "~1.3.0", 1272 | "debug": "~4.3.1" 1273 | }, 1274 | "engines": { 1275 | "node": ">=10.0.0" 1276 | } 1277 | }, 1278 | "node_modules/socket.io-parser/node_modules/debug": { 1279 | "version": "4.3.1", 1280 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", 1281 | "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", 1282 | "dependencies": { 1283 | "ms": "2.1.2" 1284 | }, 1285 | "engines": { 1286 | "node": ">=6.0" 1287 | }, 1288 | "peerDependenciesMeta": { 1289 | "supports-color": { 1290 | "optional": true 1291 | } 1292 | } 1293 | }, 1294 | "node_modules/socket.io-parser/node_modules/ms": { 1295 | "version": "2.1.2", 1296 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 1297 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 1298 | }, 1299 | "node_modules/socket.io/node_modules/debug": { 1300 | "version": "4.3.1", 1301 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", 1302 | "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", 1303 | "dependencies": { 1304 | "ms": "2.1.2" 1305 | }, 1306 | "engines": { 1307 | "node": ">=6.0" 1308 | }, 1309 | "peerDependenciesMeta": { 1310 | "supports-color": { 1311 | "optional": true 1312 | } 1313 | } 1314 | }, 1315 | "node_modules/socket.io/node_modules/ms": { 1316 | "version": "2.1.2", 1317 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 1318 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 1319 | }, 1320 | "node_modules/sparse-bitfield": { 1321 | "version": "3.0.3", 1322 | "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", 1323 | "integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=", 1324 | "optional": true, 1325 | "dependencies": { 1326 | "memory-pager": "^1.0.2" 1327 | } 1328 | }, 1329 | "node_modules/statuses": { 1330 | "version": "1.5.0", 1331 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", 1332 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", 1333 | "engines": { 1334 | "node": ">= 0.6" 1335 | } 1336 | }, 1337 | "node_modules/streamsearch": { 1338 | "version": "0.1.2", 1339 | "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", 1340 | "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=", 1341 | "engines": { 1342 | "node": ">=0.8.0" 1343 | } 1344 | }, 1345 | "node_modules/string_decoder": { 1346 | "version": "1.1.1", 1347 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", 1348 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", 1349 | "dependencies": { 1350 | "safe-buffer": "~5.1.0" 1351 | } 1352 | }, 1353 | "node_modules/toidentifier": { 1354 | "version": "1.0.0", 1355 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", 1356 | "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", 1357 | "engines": { 1358 | "node": ">=0.6" 1359 | } 1360 | }, 1361 | "node_modules/type-is": { 1362 | "version": "1.6.18", 1363 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 1364 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 1365 | "dependencies": { 1366 | "media-typer": "0.3.0", 1367 | "mime-types": "~2.1.24" 1368 | }, 1369 | "engines": { 1370 | "node": ">= 0.6" 1371 | } 1372 | }, 1373 | "node_modules/unpipe": { 1374 | "version": "1.0.0", 1375 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 1376 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", 1377 | "engines": { 1378 | "node": ">= 0.8" 1379 | } 1380 | }, 1381 | "node_modules/util-deprecate": { 1382 | "version": "1.0.2", 1383 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 1384 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" 1385 | }, 1386 | "node_modules/utils-merge": { 1387 | "version": "1.0.1", 1388 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 1389 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", 1390 | "engines": { 1391 | "node": ">= 0.4.0" 1392 | } 1393 | }, 1394 | "node_modules/uuid": { 1395 | "version": "8.3.2", 1396 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", 1397 | "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", 1398 | "bin": { 1399 | "uuid": "dist/bin/uuid" 1400 | } 1401 | }, 1402 | "node_modules/validator": { 1403 | "version": "13.5.2", 1404 | "resolved": "https://registry.npmjs.org/validator/-/validator-13.5.2.tgz", 1405 | "integrity": "sha512-mD45p0rvHVBlY2Zuy3F3ESIe1h5X58GPfAtslBjY7EtTqGquZTj+VX/J4RnHWN8FKq0C9WRVt1oWAcytWRuYLQ==", 1406 | "engines": { 1407 | "node": ">= 0.10" 1408 | } 1409 | }, 1410 | "node_modules/vary": { 1411 | "version": "1.1.2", 1412 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 1413 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", 1414 | "engines": { 1415 | "node": ">= 0.8" 1416 | } 1417 | }, 1418 | "node_modules/ws": { 1419 | "version": "7.4.3", 1420 | "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.3.tgz", 1421 | "integrity": "sha512-hr6vCR76GsossIRsr8OLR9acVVm1jyfEWvhbNjtgPOrfvAlKzvyeg/P6r8RuDjRyrcQoPQT7K0DGEPc7Ae6jzA==", 1422 | "engines": { 1423 | "node": ">=8.3.0" 1424 | }, 1425 | "peerDependencies": { 1426 | "bufferutil": "^4.0.1", 1427 | "utf-8-validate": "^5.0.2" 1428 | }, 1429 | "peerDependenciesMeta": { 1430 | "bufferutil": { 1431 | "optional": true 1432 | }, 1433 | "utf-8-validate": { 1434 | "optional": true 1435 | } 1436 | } 1437 | }, 1438 | "node_modules/yallist": { 1439 | "version": "4.0.0", 1440 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", 1441 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" 1442 | } 1443 | }, 1444 | "dependencies": { 1445 | "@types/bson": { 1446 | "version": "4.0.3", 1447 | "resolved": "https://registry.npmjs.org/@types/bson/-/bson-4.0.3.tgz", 1448 | "integrity": "sha512-mVRvYnTOZJz3ccpxhr3wgxVmSeiYinW+zlzQz3SXWaJmD1DuL05Jeq7nKw3SnbKmbleW5qrLG5vdyWe/A9sXhw==", 1449 | "requires": { 1450 | "@types/node": "*" 1451 | } 1452 | }, 1453 | "@types/component-emitter": { 1454 | "version": "1.2.10", 1455 | "resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.10.tgz", 1456 | "integrity": "sha512-bsjleuRKWmGqajMerkzox19aGbscQX5rmmvvXl3wlIp5gMG1HgkiwPxsN5p070fBDKTNSPgojVbuY1+HWMbFhg==" 1457 | }, 1458 | "@types/cookie": { 1459 | "version": "0.4.0", 1460 | "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.0.tgz", 1461 | "integrity": "sha512-y7mImlc/rNkvCRmg8gC3/lj87S7pTUIJ6QGjwHR9WQJcFs+ZMTOaoPrkdFA/YdbuqVEmEbb5RdhVxMkAcgOnpg==" 1462 | }, 1463 | "@types/cors": { 1464 | "version": "2.8.9", 1465 | "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.9.tgz", 1466 | "integrity": "sha512-zurD1ibz21BRlAOIKP8yhrxlqKx6L9VCwkB5kMiP6nZAhoF5MvC7qS1qPA7nRcr1GJolfkQC7/EAL4hdYejLtg==" 1467 | }, 1468 | "@types/mongodb": { 1469 | "version": "3.6.6", 1470 | "resolved": "https://registry.npmjs.org/@types/mongodb/-/mongodb-3.6.6.tgz", 1471 | "integrity": "sha512-ghYevKiSh/TGk2MAwSRZP7T1ilR9Pw8Fa7pT9GGVGZPUsWKdZjZ4G6LG3MqK2iXKdNba994F8W9ikA+qx2Eo3A==", 1472 | "requires": { 1473 | "@types/bson": "*", 1474 | "@types/node": "*" 1475 | } 1476 | }, 1477 | "@types/node": { 1478 | "version": "14.14.25", 1479 | "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.25.tgz", 1480 | "integrity": "sha512-EPpXLOVqDvisVxtlbvzfyqSsFeQxltFbluZNRndIb8tr9KiBnYNLzrc1N3pyKUCww2RNrfHDViqDWWE1LCJQtQ==" 1481 | }, 1482 | "abort-controller": { 1483 | "version": "3.0.0", 1484 | "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", 1485 | "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", 1486 | "requires": { 1487 | "event-target-shim": "^5.0.0" 1488 | } 1489 | }, 1490 | "accepts": { 1491 | "version": "1.3.7", 1492 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", 1493 | "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", 1494 | "requires": { 1495 | "mime-types": "~2.1.24", 1496 | "negotiator": "0.6.2" 1497 | } 1498 | }, 1499 | "agent-base": { 1500 | "version": "6.0.2", 1501 | "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", 1502 | "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", 1503 | "requires": { 1504 | "debug": "4" 1505 | }, 1506 | "dependencies": { 1507 | "debug": { 1508 | "version": "4.3.1", 1509 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", 1510 | "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", 1511 | "requires": { 1512 | "ms": "2.1.2" 1513 | } 1514 | }, 1515 | "ms": { 1516 | "version": "2.1.2", 1517 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 1518 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 1519 | } 1520 | } 1521 | }, 1522 | "array-flatten": { 1523 | "version": "1.1.1", 1524 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 1525 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 1526 | }, 1527 | "arrify": { 1528 | "version": "2.0.1", 1529 | "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", 1530 | "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==" 1531 | }, 1532 | "base64-arraybuffer": { 1533 | "version": "0.1.4", 1534 | "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.4.tgz", 1535 | "integrity": "sha1-mBjHngWbE1X5fgQooBfIOOkLqBI=" 1536 | }, 1537 | "base64-js": { 1538 | "version": "1.5.1", 1539 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", 1540 | "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" 1541 | }, 1542 | "base64id": { 1543 | "version": "2.0.0", 1544 | "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", 1545 | "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==" 1546 | }, 1547 | "bcryptjs": { 1548 | "version": "2.4.3", 1549 | "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", 1550 | "integrity": "sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms=" 1551 | }, 1552 | "bignumber.js": { 1553 | "version": "9.0.1", 1554 | "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.1.tgz", 1555 | "integrity": "sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA==" 1556 | }, 1557 | "bl": { 1558 | "version": "2.2.1", 1559 | "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz", 1560 | "integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==", 1561 | "requires": { 1562 | "readable-stream": "^2.3.5", 1563 | "safe-buffer": "^5.1.1" 1564 | } 1565 | }, 1566 | "bluebird": { 1567 | "version": "3.5.1", 1568 | "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", 1569 | "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==" 1570 | }, 1571 | "body-parser": { 1572 | "version": "1.19.0", 1573 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", 1574 | "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", 1575 | "requires": { 1576 | "bytes": "3.1.0", 1577 | "content-type": "~1.0.4", 1578 | "debug": "2.6.9", 1579 | "depd": "~1.1.2", 1580 | "http-errors": "1.7.2", 1581 | "iconv-lite": "0.4.24", 1582 | "on-finished": "~2.3.0", 1583 | "qs": "6.7.0", 1584 | "raw-body": "2.4.0", 1585 | "type-is": "~1.6.17" 1586 | } 1587 | }, 1588 | "bson": { 1589 | "version": "1.1.5", 1590 | "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.5.tgz", 1591 | "integrity": "sha512-kDuEzldR21lHciPQAIulLs1LZlCXdLziXI6Mb/TDkwXhb//UORJNPXgcRs2CuO4H0DcMkpfT3/ySsP3unoZjBg==" 1592 | }, 1593 | "buffer-equal-constant-time": { 1594 | "version": "1.0.1", 1595 | "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", 1596 | "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" 1597 | }, 1598 | "busboy": { 1599 | "version": "0.3.1", 1600 | "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.3.1.tgz", 1601 | "integrity": "sha512-y7tTxhGKXcyBxRKAni+awqx8uqaJKrSFSNFSeRG5CsWNdmy2BIK+6VGWEW7TZnIO/533mtMEA4rOevQV815YJw==", 1602 | "requires": { 1603 | "dicer": "0.3.0" 1604 | } 1605 | }, 1606 | "bytes": { 1607 | "version": "3.1.0", 1608 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", 1609 | "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" 1610 | }, 1611 | "cloudinary": { 1612 | "version": "1.24.0", 1613 | "resolved": "https://registry.npmjs.org/cloudinary/-/cloudinary-1.24.0.tgz", 1614 | "integrity": "sha512-bILjdVB/FCv5Zyypuhp5IdKeoDDMbA/8ybq8kILV9At5l2AV3ZwdjvYSNF04hTg9+Zan1d5id6LmV5liGsx1bw==", 1615 | "requires": { 1616 | "cloudinary-core": "^2.10.2", 1617 | "core-js": "3.6.5", 1618 | "lodash": "^4.17.11", 1619 | "q": "^1.5.1" 1620 | } 1621 | }, 1622 | "cloudinary-core": { 1623 | "version": "2.11.3", 1624 | "resolved": "https://registry.npmjs.org/cloudinary-core/-/cloudinary-core-2.11.3.tgz", 1625 | "integrity": "sha512-ZRnpjSgvx+LbSf+aEz5NKzxDB4Z0436aY/0BSDa90kAHiwAyd84VyEi95I74SE80e15Ri9t5S2xtksTXpzk9Xw==" 1626 | }, 1627 | "component-emitter": { 1628 | "version": "1.3.0", 1629 | "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", 1630 | "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" 1631 | }, 1632 | "content-disposition": { 1633 | "version": "0.5.3", 1634 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", 1635 | "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", 1636 | "requires": { 1637 | "safe-buffer": "5.1.2" 1638 | } 1639 | }, 1640 | "content-type": { 1641 | "version": "1.0.4", 1642 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 1643 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" 1644 | }, 1645 | "cookie": { 1646 | "version": "0.4.0", 1647 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", 1648 | "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" 1649 | }, 1650 | "cookie-signature": { 1651 | "version": "1.0.6", 1652 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 1653 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" 1654 | }, 1655 | "core-js": { 1656 | "version": "3.6.5", 1657 | "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.5.tgz", 1658 | "integrity": "sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA==" 1659 | }, 1660 | "core-util-is": { 1661 | "version": "1.0.2", 1662 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 1663 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" 1664 | }, 1665 | "cors": { 1666 | "version": "2.8.5", 1667 | "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", 1668 | "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", 1669 | "requires": { 1670 | "object-assign": "^4", 1671 | "vary": "^1" 1672 | } 1673 | }, 1674 | "debug": { 1675 | "version": "2.6.9", 1676 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 1677 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 1678 | "requires": { 1679 | "ms": "2.0.0" 1680 | } 1681 | }, 1682 | "denque": { 1683 | "version": "1.5.0", 1684 | "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.0.tgz", 1685 | "integrity": "sha512-CYiCSgIF1p6EUByQPlGkKnP1M9g0ZV3qMIrqMqZqdwazygIA/YP2vrbcyl1h/WppKJTdl1F85cXIle+394iDAQ==" 1686 | }, 1687 | "depd": { 1688 | "version": "1.1.2", 1689 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", 1690 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" 1691 | }, 1692 | "destroy": { 1693 | "version": "1.0.4", 1694 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", 1695 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" 1696 | }, 1697 | "dicer": { 1698 | "version": "0.3.0", 1699 | "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.3.0.tgz", 1700 | "integrity": "sha512-MdceRRWqltEG2dZqO769g27N/3PXfcKl04VhYnBlo2YhH7zPi88VebsjTKclaOyiuMaGU72hTfw3VkUitGcVCA==", 1701 | "requires": { 1702 | "streamsearch": "0.1.2" 1703 | } 1704 | }, 1705 | "dotenv": { 1706 | "version": "8.2.0", 1707 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz", 1708 | "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==" 1709 | }, 1710 | "ecdsa-sig-formatter": { 1711 | "version": "1.0.11", 1712 | "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", 1713 | "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", 1714 | "requires": { 1715 | "safe-buffer": "^5.0.1" 1716 | } 1717 | }, 1718 | "ee-first": { 1719 | "version": "1.1.1", 1720 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 1721 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 1722 | }, 1723 | "encodeurl": { 1724 | "version": "1.0.2", 1725 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 1726 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" 1727 | }, 1728 | "engine.io": { 1729 | "version": "4.1.1", 1730 | "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-4.1.1.tgz", 1731 | "integrity": "sha512-t2E9wLlssQjGw0nluF6aYyfX8LwYU8Jj0xct+pAhfWfv/YrBn6TSNtEYsgxHIfaMqfrLx07czcMg9bMN6di+3w==", 1732 | "requires": { 1733 | "accepts": "~1.3.4", 1734 | "base64id": "2.0.0", 1735 | "cookie": "~0.4.1", 1736 | "cors": "~2.8.5", 1737 | "debug": "~4.3.1", 1738 | "engine.io-parser": "~4.0.0", 1739 | "ws": "~7.4.2" 1740 | }, 1741 | "dependencies": { 1742 | "cookie": { 1743 | "version": "0.4.1", 1744 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", 1745 | "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==" 1746 | }, 1747 | "debug": { 1748 | "version": "4.3.1", 1749 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", 1750 | "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", 1751 | "requires": { 1752 | "ms": "2.1.2" 1753 | } 1754 | }, 1755 | "ms": { 1756 | "version": "2.1.2", 1757 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 1758 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 1759 | } 1760 | } 1761 | }, 1762 | "engine.io-parser": { 1763 | "version": "4.0.2", 1764 | "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-4.0.2.tgz", 1765 | "integrity": "sha512-sHfEQv6nmtJrq6TKuIz5kyEKH/qSdK56H/A+7DnAuUPWosnIZAS2NHNcPLmyjtY3cGS/MqJdZbUjW97JU72iYg==", 1766 | "requires": { 1767 | "base64-arraybuffer": "0.1.4" 1768 | } 1769 | }, 1770 | "escape-html": { 1771 | "version": "1.0.3", 1772 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 1773 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" 1774 | }, 1775 | "etag": { 1776 | "version": "1.8.1", 1777 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 1778 | "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" 1779 | }, 1780 | "event-target-shim": { 1781 | "version": "5.0.1", 1782 | "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", 1783 | "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==" 1784 | }, 1785 | "express": { 1786 | "version": "4.17.1", 1787 | "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", 1788 | "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", 1789 | "requires": { 1790 | "accepts": "~1.3.7", 1791 | "array-flatten": "1.1.1", 1792 | "body-parser": "1.19.0", 1793 | "content-disposition": "0.5.3", 1794 | "content-type": "~1.0.4", 1795 | "cookie": "0.4.0", 1796 | "cookie-signature": "1.0.6", 1797 | "debug": "2.6.9", 1798 | "depd": "~1.1.2", 1799 | "encodeurl": "~1.0.2", 1800 | "escape-html": "~1.0.3", 1801 | "etag": "~1.8.1", 1802 | "finalhandler": "~1.1.2", 1803 | "fresh": "0.5.2", 1804 | "merge-descriptors": "1.0.1", 1805 | "methods": "~1.1.2", 1806 | "on-finished": "~2.3.0", 1807 | "parseurl": "~1.3.3", 1808 | "path-to-regexp": "0.1.7", 1809 | "proxy-addr": "~2.0.5", 1810 | "qs": "6.7.0", 1811 | "range-parser": "~1.2.1", 1812 | "safe-buffer": "5.1.2", 1813 | "send": "0.17.1", 1814 | "serve-static": "1.14.1", 1815 | "setprototypeof": "1.1.1", 1816 | "statuses": "~1.5.0", 1817 | "type-is": "~1.6.18", 1818 | "utils-merge": "1.0.1", 1819 | "vary": "~1.1.2" 1820 | } 1821 | }, 1822 | "express-fileupload": { 1823 | "version": "1.2.1", 1824 | "resolved": "https://registry.npmjs.org/express-fileupload/-/express-fileupload-1.2.1.tgz", 1825 | "integrity": "sha512-fWPNAkBj+Azt9Itmcz/Reqdg3LeBfaXptDEev2JM8bCC0yDptglCnlizhf0YZauyU5X/g6v7v4Xxqhg8tmEfEA==", 1826 | "requires": { 1827 | "busboy": "^0.3.1" 1828 | } 1829 | }, 1830 | "express-validator": { 1831 | "version": "6.9.2", 1832 | "resolved": "https://registry.npmjs.org/express-validator/-/express-validator-6.9.2.tgz", 1833 | "integrity": "sha512-Yqlsw2/uBobtBVkP+gnds8OMmVAEb3uTI4uXC93l0Ym5JGHgr8Vd4ws7oSo7GGYpWn5YCq4UePMEppKchURXrw==", 1834 | "requires": { 1835 | "lodash": "^4.17.20", 1836 | "validator": "^13.5.2" 1837 | } 1838 | }, 1839 | "extend": { 1840 | "version": "3.0.2", 1841 | "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", 1842 | "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" 1843 | }, 1844 | "fast-text-encoding": { 1845 | "version": "1.0.3", 1846 | "resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.3.tgz", 1847 | "integrity": "sha512-dtm4QZH9nZtcDt8qJiOH9fcQd1NAgi+K1O2DbE6GG1PPCK/BWfOH3idCTRQ4ImXRUOyopDEgDEnVEE7Y/2Wrig==" 1848 | }, 1849 | "finalhandler": { 1850 | "version": "1.1.2", 1851 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", 1852 | "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", 1853 | "requires": { 1854 | "debug": "2.6.9", 1855 | "encodeurl": "~1.0.2", 1856 | "escape-html": "~1.0.3", 1857 | "on-finished": "~2.3.0", 1858 | "parseurl": "~1.3.3", 1859 | "statuses": "~1.5.0", 1860 | "unpipe": "~1.0.0" 1861 | } 1862 | }, 1863 | "forwarded": { 1864 | "version": "0.1.2", 1865 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", 1866 | "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" 1867 | }, 1868 | "fresh": { 1869 | "version": "0.5.2", 1870 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 1871 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" 1872 | }, 1873 | "gaxios": { 1874 | "version": "4.1.0", 1875 | "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-4.1.0.tgz", 1876 | "integrity": "sha512-vb0to8xzGnA2qcgywAjtshOKKVDf2eQhJoiL6fHhgW5tVN7wNk7egnYIO9zotfn3lQ3De1VPdf7V5/BWfCtCmg==", 1877 | "requires": { 1878 | "abort-controller": "^3.0.0", 1879 | "extend": "^3.0.2", 1880 | "https-proxy-agent": "^5.0.0", 1881 | "is-stream": "^2.0.0", 1882 | "node-fetch": "^2.3.0" 1883 | } 1884 | }, 1885 | "gcp-metadata": { 1886 | "version": "4.2.1", 1887 | "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-4.2.1.tgz", 1888 | "integrity": "sha512-tSk+REe5iq/N+K+SK1XjZJUrFPuDqGZVzCy2vocIHIGmPlTGsa8owXMJwGkrXr73NO0AzhPW4MF2DEHz7P2AVw==", 1889 | "requires": { 1890 | "gaxios": "^4.0.0", 1891 | "json-bigint": "^1.0.0" 1892 | } 1893 | }, 1894 | "google-auth-library": { 1895 | "version": "6.1.6", 1896 | "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-6.1.6.tgz", 1897 | "integrity": "sha512-Q+ZjUEvLQj/lrVHF/IQwRo6p3s8Nc44Zk/DALsN+ac3T4HY/g/3rrufkgtl+nZ1TW7DNAw5cTChdVp4apUXVgQ==", 1898 | "requires": { 1899 | "arrify": "^2.0.0", 1900 | "base64-js": "^1.3.0", 1901 | "ecdsa-sig-formatter": "^1.0.11", 1902 | "fast-text-encoding": "^1.0.0", 1903 | "gaxios": "^4.0.0", 1904 | "gcp-metadata": "^4.2.0", 1905 | "gtoken": "^5.0.4", 1906 | "jws": "^4.0.0", 1907 | "lru-cache": "^6.0.0" 1908 | }, 1909 | "dependencies": { 1910 | "jwa": { 1911 | "version": "2.0.0", 1912 | "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", 1913 | "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", 1914 | "requires": { 1915 | "buffer-equal-constant-time": "1.0.1", 1916 | "ecdsa-sig-formatter": "1.0.11", 1917 | "safe-buffer": "^5.0.1" 1918 | } 1919 | }, 1920 | "jws": { 1921 | "version": "4.0.0", 1922 | "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", 1923 | "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", 1924 | "requires": { 1925 | "jwa": "^2.0.0", 1926 | "safe-buffer": "^5.0.1" 1927 | } 1928 | } 1929 | } 1930 | }, 1931 | "google-p12-pem": { 1932 | "version": "3.0.3", 1933 | "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.0.3.tgz", 1934 | "integrity": "sha512-wS0ek4ZtFx/ACKYF3JhyGe5kzH7pgiQ7J5otlumqR9psmWMYc+U9cErKlCYVYHoUaidXHdZ2xbo34kB+S+24hA==", 1935 | "requires": { 1936 | "node-forge": "^0.10.0" 1937 | } 1938 | }, 1939 | "gtoken": { 1940 | "version": "5.2.1", 1941 | "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-5.2.1.tgz", 1942 | "integrity": "sha512-OY0BfPKe3QnMsY9MzTHTSKn+Vl2l1CcLe6BwDEQj00mbbkl5nyQ/7EUREstg4fQNZ8iYE7br4JJ7TdKeDOPWmw==", 1943 | "requires": { 1944 | "gaxios": "^4.0.0", 1945 | "google-p12-pem": "^3.0.3", 1946 | "jws": "^4.0.0" 1947 | }, 1948 | "dependencies": { 1949 | "jwa": { 1950 | "version": "2.0.0", 1951 | "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", 1952 | "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", 1953 | "requires": { 1954 | "buffer-equal-constant-time": "1.0.1", 1955 | "ecdsa-sig-formatter": "1.0.11", 1956 | "safe-buffer": "^5.0.1" 1957 | } 1958 | }, 1959 | "jws": { 1960 | "version": "4.0.0", 1961 | "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", 1962 | "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", 1963 | "requires": { 1964 | "jwa": "^2.0.0", 1965 | "safe-buffer": "^5.0.1" 1966 | } 1967 | } 1968 | } 1969 | }, 1970 | "http-errors": { 1971 | "version": "1.7.2", 1972 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", 1973 | "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", 1974 | "requires": { 1975 | "depd": "~1.1.2", 1976 | "inherits": "2.0.3", 1977 | "setprototypeof": "1.1.1", 1978 | "statuses": ">= 1.5.0 < 2", 1979 | "toidentifier": "1.0.0" 1980 | } 1981 | }, 1982 | "https-proxy-agent": { 1983 | "version": "5.0.0", 1984 | "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", 1985 | "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", 1986 | "requires": { 1987 | "agent-base": "6", 1988 | "debug": "4" 1989 | }, 1990 | "dependencies": { 1991 | "debug": { 1992 | "version": "4.3.1", 1993 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", 1994 | "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", 1995 | "requires": { 1996 | "ms": "2.1.2" 1997 | } 1998 | }, 1999 | "ms": { 2000 | "version": "2.1.2", 2001 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 2002 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 2003 | } 2004 | } 2005 | }, 2006 | "iconv-lite": { 2007 | "version": "0.4.24", 2008 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 2009 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 2010 | "requires": { 2011 | "safer-buffer": ">= 2.1.2 < 3" 2012 | } 2013 | }, 2014 | "inherits": { 2015 | "version": "2.0.3", 2016 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 2017 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 2018 | }, 2019 | "ipaddr.js": { 2020 | "version": "1.9.1", 2021 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 2022 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" 2023 | }, 2024 | "is-stream": { 2025 | "version": "2.0.0", 2026 | "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", 2027 | "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==" 2028 | }, 2029 | "isarray": { 2030 | "version": "1.0.0", 2031 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 2032 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" 2033 | }, 2034 | "json-bigint": { 2035 | "version": "1.0.0", 2036 | "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", 2037 | "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", 2038 | "requires": { 2039 | "bignumber.js": "^9.0.0" 2040 | } 2041 | }, 2042 | "jsonwebtoken": { 2043 | "version": "8.5.1", 2044 | "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", 2045 | "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", 2046 | "requires": { 2047 | "jws": "^3.2.2", 2048 | "lodash.includes": "^4.3.0", 2049 | "lodash.isboolean": "^3.0.3", 2050 | "lodash.isinteger": "^4.0.4", 2051 | "lodash.isnumber": "^3.0.3", 2052 | "lodash.isplainobject": "^4.0.6", 2053 | "lodash.isstring": "^4.0.1", 2054 | "lodash.once": "^4.0.0", 2055 | "ms": "^2.1.1", 2056 | "semver": "^5.6.0" 2057 | }, 2058 | "dependencies": { 2059 | "ms": { 2060 | "version": "2.1.3", 2061 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 2062 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" 2063 | } 2064 | } 2065 | }, 2066 | "jwa": { 2067 | "version": "1.4.1", 2068 | "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", 2069 | "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", 2070 | "requires": { 2071 | "buffer-equal-constant-time": "1.0.1", 2072 | "ecdsa-sig-formatter": "1.0.11", 2073 | "safe-buffer": "^5.0.1" 2074 | } 2075 | }, 2076 | "jws": { 2077 | "version": "3.2.2", 2078 | "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", 2079 | "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", 2080 | "requires": { 2081 | "jwa": "^1.4.1", 2082 | "safe-buffer": "^5.0.1" 2083 | } 2084 | }, 2085 | "kareem": { 2086 | "version": "2.3.2", 2087 | "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.3.2.tgz", 2088 | "integrity": "sha512-STHz9P7X2L4Kwn72fA4rGyqyXdmrMSdxqHx9IXon/FXluXieaFA6KJ2upcHAHxQPQ0LeM/OjLrhFxifHewOALQ==" 2089 | }, 2090 | "lodash": { 2091 | "version": "4.17.20", 2092 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", 2093 | "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" 2094 | }, 2095 | "lodash.includes": { 2096 | "version": "4.3.0", 2097 | "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", 2098 | "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=" 2099 | }, 2100 | "lodash.isboolean": { 2101 | "version": "3.0.3", 2102 | "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", 2103 | "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=" 2104 | }, 2105 | "lodash.isinteger": { 2106 | "version": "4.0.4", 2107 | "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", 2108 | "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=" 2109 | }, 2110 | "lodash.isnumber": { 2111 | "version": "3.0.3", 2112 | "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", 2113 | "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=" 2114 | }, 2115 | "lodash.isplainobject": { 2116 | "version": "4.0.6", 2117 | "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", 2118 | "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" 2119 | }, 2120 | "lodash.isstring": { 2121 | "version": "4.0.1", 2122 | "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", 2123 | "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=" 2124 | }, 2125 | "lodash.once": { 2126 | "version": "4.1.1", 2127 | "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", 2128 | "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=" 2129 | }, 2130 | "lru-cache": { 2131 | "version": "6.0.0", 2132 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", 2133 | "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", 2134 | "requires": { 2135 | "yallist": "^4.0.0" 2136 | } 2137 | }, 2138 | "media-typer": { 2139 | "version": "0.3.0", 2140 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 2141 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" 2142 | }, 2143 | "memory-pager": { 2144 | "version": "1.5.0", 2145 | "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", 2146 | "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", 2147 | "optional": true 2148 | }, 2149 | "merge-descriptors": { 2150 | "version": "1.0.1", 2151 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 2152 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" 2153 | }, 2154 | "methods": { 2155 | "version": "1.1.2", 2156 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 2157 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" 2158 | }, 2159 | "mime": { 2160 | "version": "1.6.0", 2161 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 2162 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" 2163 | }, 2164 | "mime-db": { 2165 | "version": "1.45.0", 2166 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz", 2167 | "integrity": "sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==" 2168 | }, 2169 | "mime-types": { 2170 | "version": "2.1.28", 2171 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.28.tgz", 2172 | "integrity": "sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ==", 2173 | "requires": { 2174 | "mime-db": "1.45.0" 2175 | } 2176 | }, 2177 | "mongodb": { 2178 | "version": "3.6.3", 2179 | "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.3.tgz", 2180 | "integrity": "sha512-rOZuR0QkodZiM+UbQE5kDsJykBqWi0CL4Ec2i1nrGrUI3KO11r6Fbxskqmq3JK2NH7aW4dcccBuUujAP0ERl5w==", 2181 | "requires": { 2182 | "bl": "^2.2.1", 2183 | "bson": "^1.1.4", 2184 | "denque": "^1.4.1", 2185 | "require_optional": "^1.0.1", 2186 | "safe-buffer": "^5.1.2", 2187 | "saslprep": "^1.0.0" 2188 | } 2189 | }, 2190 | "mongoose": { 2191 | "version": "5.11.15", 2192 | "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.11.15.tgz", 2193 | "integrity": "sha512-8T4bT6eCGB7MqCm40oVhnhT/1AyAdwe+y1rYUhdl3ljsks3BpYz8whZgcMkIoh6VoCCjipOXRqZqdk1UByvlYA==", 2194 | "requires": { 2195 | "@types/mongodb": "^3.5.27", 2196 | "bson": "^1.1.4", 2197 | "kareem": "2.3.2", 2198 | "mongodb": "3.6.3", 2199 | "mongoose-legacy-pluralize": "1.0.2", 2200 | "mpath": "0.8.3", 2201 | "mquery": "3.2.3", 2202 | "ms": "2.1.2", 2203 | "regexp-clone": "1.0.0", 2204 | "safe-buffer": "5.2.1", 2205 | "sift": "7.0.1", 2206 | "sliced": "1.0.1" 2207 | }, 2208 | "dependencies": { 2209 | "ms": { 2210 | "version": "2.1.2", 2211 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 2212 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 2213 | }, 2214 | "safe-buffer": { 2215 | "version": "5.2.1", 2216 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 2217 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" 2218 | } 2219 | } 2220 | }, 2221 | "mongoose-legacy-pluralize": { 2222 | "version": "1.0.2", 2223 | "resolved": "https://registry.npmjs.org/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz", 2224 | "integrity": "sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ==" 2225 | }, 2226 | "mpath": { 2227 | "version": "0.8.3", 2228 | "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.8.3.tgz", 2229 | "integrity": "sha512-eb9rRvhDltXVNL6Fxd2zM9D4vKBxjVVQNLNijlj7uoXUy19zNDsIif5zR+pWmPCWNKwAtqyo4JveQm4nfD5+eA==" 2230 | }, 2231 | "mquery": { 2232 | "version": "3.2.3", 2233 | "resolved": "https://registry.npmjs.org/mquery/-/mquery-3.2.3.tgz", 2234 | "integrity": "sha512-cIfbP4TyMYX+SkaQ2MntD+F2XbqaBHUYWk3j+kqdDztPWok3tgyssOZxMHMtzbV1w9DaSlvEea0Iocuro41A4g==", 2235 | "requires": { 2236 | "bluebird": "3.5.1", 2237 | "debug": "3.1.0", 2238 | "regexp-clone": "^1.0.0", 2239 | "safe-buffer": "5.1.2", 2240 | "sliced": "1.0.1" 2241 | }, 2242 | "dependencies": { 2243 | "debug": { 2244 | "version": "3.1.0", 2245 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", 2246 | "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", 2247 | "requires": { 2248 | "ms": "2.0.0" 2249 | } 2250 | } 2251 | } 2252 | }, 2253 | "ms": { 2254 | "version": "2.0.0", 2255 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 2256 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 2257 | }, 2258 | "negotiator": { 2259 | "version": "0.6.2", 2260 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", 2261 | "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" 2262 | }, 2263 | "node-fetch": { 2264 | "version": "2.6.1", 2265 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", 2266 | "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==" 2267 | }, 2268 | "node-forge": { 2269 | "version": "0.10.0", 2270 | "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz", 2271 | "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==" 2272 | }, 2273 | "object-assign": { 2274 | "version": "4.1.1", 2275 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 2276 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" 2277 | }, 2278 | "on-finished": { 2279 | "version": "2.3.0", 2280 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 2281 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 2282 | "requires": { 2283 | "ee-first": "1.1.1" 2284 | } 2285 | }, 2286 | "parseurl": { 2287 | "version": "1.3.3", 2288 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 2289 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" 2290 | }, 2291 | "path-to-regexp": { 2292 | "version": "0.1.7", 2293 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 2294 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" 2295 | }, 2296 | "process-nextick-args": { 2297 | "version": "2.0.1", 2298 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", 2299 | "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" 2300 | }, 2301 | "proxy-addr": { 2302 | "version": "2.0.6", 2303 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", 2304 | "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", 2305 | "requires": { 2306 | "forwarded": "~0.1.2", 2307 | "ipaddr.js": "1.9.1" 2308 | } 2309 | }, 2310 | "q": { 2311 | "version": "1.5.1", 2312 | "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", 2313 | "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=" 2314 | }, 2315 | "qs": { 2316 | "version": "6.7.0", 2317 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", 2318 | "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" 2319 | }, 2320 | "range-parser": { 2321 | "version": "1.2.1", 2322 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 2323 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" 2324 | }, 2325 | "raw-body": { 2326 | "version": "2.4.0", 2327 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", 2328 | "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", 2329 | "requires": { 2330 | "bytes": "3.1.0", 2331 | "http-errors": "1.7.2", 2332 | "iconv-lite": "0.4.24", 2333 | "unpipe": "1.0.0" 2334 | } 2335 | }, 2336 | "readable-stream": { 2337 | "version": "2.3.7", 2338 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", 2339 | "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", 2340 | "requires": { 2341 | "core-util-is": "~1.0.0", 2342 | "inherits": "~2.0.3", 2343 | "isarray": "~1.0.0", 2344 | "process-nextick-args": "~2.0.0", 2345 | "safe-buffer": "~5.1.1", 2346 | "string_decoder": "~1.1.1", 2347 | "util-deprecate": "~1.0.1" 2348 | } 2349 | }, 2350 | "regexp-clone": { 2351 | "version": "1.0.0", 2352 | "resolved": "https://registry.npmjs.org/regexp-clone/-/regexp-clone-1.0.0.tgz", 2353 | "integrity": "sha512-TuAasHQNamyyJ2hb97IuBEif4qBHGjPHBS64sZwytpLEqtBQ1gPJTnOaQ6qmpET16cK14kkjbazl6+p0RRv0yw==" 2354 | }, 2355 | "require_optional": { 2356 | "version": "1.0.1", 2357 | "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz", 2358 | "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==", 2359 | "requires": { 2360 | "resolve-from": "^2.0.0", 2361 | "semver": "^5.1.0" 2362 | } 2363 | }, 2364 | "resolve-from": { 2365 | "version": "2.0.0", 2366 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", 2367 | "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=" 2368 | }, 2369 | "safe-buffer": { 2370 | "version": "5.1.2", 2371 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 2372 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 2373 | }, 2374 | "safer-buffer": { 2375 | "version": "2.1.2", 2376 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 2377 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 2378 | }, 2379 | "saslprep": { 2380 | "version": "1.0.3", 2381 | "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", 2382 | "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", 2383 | "optional": true, 2384 | "requires": { 2385 | "sparse-bitfield": "^3.0.3" 2386 | } 2387 | }, 2388 | "semver": { 2389 | "version": "5.7.1", 2390 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", 2391 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" 2392 | }, 2393 | "send": { 2394 | "version": "0.17.1", 2395 | "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", 2396 | "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", 2397 | "requires": { 2398 | "debug": "2.6.9", 2399 | "depd": "~1.1.2", 2400 | "destroy": "~1.0.4", 2401 | "encodeurl": "~1.0.2", 2402 | "escape-html": "~1.0.3", 2403 | "etag": "~1.8.1", 2404 | "fresh": "0.5.2", 2405 | "http-errors": "~1.7.2", 2406 | "mime": "1.6.0", 2407 | "ms": "2.1.1", 2408 | "on-finished": "~2.3.0", 2409 | "range-parser": "~1.2.1", 2410 | "statuses": "~1.5.0" 2411 | }, 2412 | "dependencies": { 2413 | "ms": { 2414 | "version": "2.1.1", 2415 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", 2416 | "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" 2417 | } 2418 | } 2419 | }, 2420 | "serve-static": { 2421 | "version": "1.14.1", 2422 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", 2423 | "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", 2424 | "requires": { 2425 | "encodeurl": "~1.0.2", 2426 | "escape-html": "~1.0.3", 2427 | "parseurl": "~1.3.3", 2428 | "send": "0.17.1" 2429 | } 2430 | }, 2431 | "setprototypeof": { 2432 | "version": "1.1.1", 2433 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", 2434 | "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" 2435 | }, 2436 | "sift": { 2437 | "version": "7.0.1", 2438 | "resolved": "https://registry.npmjs.org/sift/-/sift-7.0.1.tgz", 2439 | "integrity": "sha512-oqD7PMJ+uO6jV9EQCl0LrRw1OwsiPsiFQR5AR30heR+4Dl7jBBbDLnNvWiak20tzZlSE1H7RB30SX/1j/YYT7g==" 2440 | }, 2441 | "sliced": { 2442 | "version": "1.0.1", 2443 | "resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz", 2444 | "integrity": "sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E=" 2445 | }, 2446 | "socket.io": { 2447 | "version": "3.1.1", 2448 | "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-3.1.1.tgz", 2449 | "integrity": "sha512-7cBWdsDC7bbyEF6WbBqffjizc/H4YF1wLdZoOzuYfo2uMNSFjJKuQ36t0H40o9B20DO6p+mSytEd92oP4S15bA==", 2450 | "requires": { 2451 | "@types/cookie": "^0.4.0", 2452 | "@types/cors": "^2.8.8", 2453 | "@types/node": "^14.14.10", 2454 | "accepts": "~1.3.4", 2455 | "base64id": "~2.0.0", 2456 | "debug": "~4.3.1", 2457 | "engine.io": "~4.1.0", 2458 | "socket.io-adapter": "~2.1.0", 2459 | "socket.io-parser": "~4.0.3" 2460 | }, 2461 | "dependencies": { 2462 | "debug": { 2463 | "version": "4.3.1", 2464 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", 2465 | "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", 2466 | "requires": { 2467 | "ms": "2.1.2" 2468 | } 2469 | }, 2470 | "ms": { 2471 | "version": "2.1.2", 2472 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 2473 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 2474 | } 2475 | } 2476 | }, 2477 | "socket.io-adapter": { 2478 | "version": "2.1.0", 2479 | "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.1.0.tgz", 2480 | "integrity": "sha512-+vDov/aTsLjViYTwS9fPy5pEtTkrbEKsw2M+oVSoFGw6OD1IpvlV1VPhUzNbofCQ8oyMbdYJqDtGdmHQK6TdPg==" 2481 | }, 2482 | "socket.io-parser": { 2483 | "version": "4.0.4", 2484 | "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.4.tgz", 2485 | "integrity": "sha512-t+b0SS+IxG7Rxzda2EVvyBZbvFPBCjJoyHuE0P//7OAsN23GItzDRdWa6ALxZI/8R5ygK7jAR6t028/z+7295g==", 2486 | "requires": { 2487 | "@types/component-emitter": "^1.2.10", 2488 | "component-emitter": "~1.3.0", 2489 | "debug": "~4.3.1" 2490 | }, 2491 | "dependencies": { 2492 | "debug": { 2493 | "version": "4.3.1", 2494 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", 2495 | "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", 2496 | "requires": { 2497 | "ms": "2.1.2" 2498 | } 2499 | }, 2500 | "ms": { 2501 | "version": "2.1.2", 2502 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 2503 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 2504 | } 2505 | } 2506 | }, 2507 | "sparse-bitfield": { 2508 | "version": "3.0.3", 2509 | "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", 2510 | "integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=", 2511 | "optional": true, 2512 | "requires": { 2513 | "memory-pager": "^1.0.2" 2514 | } 2515 | }, 2516 | "statuses": { 2517 | "version": "1.5.0", 2518 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", 2519 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" 2520 | }, 2521 | "streamsearch": { 2522 | "version": "0.1.2", 2523 | "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", 2524 | "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=" 2525 | }, 2526 | "string_decoder": { 2527 | "version": "1.1.1", 2528 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", 2529 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", 2530 | "requires": { 2531 | "safe-buffer": "~5.1.0" 2532 | } 2533 | }, 2534 | "toidentifier": { 2535 | "version": "1.0.0", 2536 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", 2537 | "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" 2538 | }, 2539 | "type-is": { 2540 | "version": "1.6.18", 2541 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 2542 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 2543 | "requires": { 2544 | "media-typer": "0.3.0", 2545 | "mime-types": "~2.1.24" 2546 | } 2547 | }, 2548 | "unpipe": { 2549 | "version": "1.0.0", 2550 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 2551 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" 2552 | }, 2553 | "util-deprecate": { 2554 | "version": "1.0.2", 2555 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 2556 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" 2557 | }, 2558 | "utils-merge": { 2559 | "version": "1.0.1", 2560 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 2561 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" 2562 | }, 2563 | "uuid": { 2564 | "version": "8.3.2", 2565 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", 2566 | "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" 2567 | }, 2568 | "validator": { 2569 | "version": "13.5.2", 2570 | "resolved": "https://registry.npmjs.org/validator/-/validator-13.5.2.tgz", 2571 | "integrity": "sha512-mD45p0rvHVBlY2Zuy3F3ESIe1h5X58GPfAtslBjY7EtTqGquZTj+VX/J4RnHWN8FKq0C9WRVt1oWAcytWRuYLQ==" 2572 | }, 2573 | "vary": { 2574 | "version": "1.1.2", 2575 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 2576 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" 2577 | }, 2578 | "ws": { 2579 | "version": "7.4.3", 2580 | "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.3.tgz", 2581 | "integrity": "sha512-hr6vCR76GsossIRsr8OLR9acVVm1jyfEWvhbNjtgPOrfvAlKzvyeg/P6r8RuDjRyrcQoPQT7K0DGEPc7Ae6jzA==", 2582 | "requires": {} 2583 | }, 2584 | "yallist": { 2585 | "version": "4.0.0", 2586 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", 2587 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" 2588 | } 2589 | } 2590 | } 2591 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "07-restserver", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "node app" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "bcryptjs": "^2.4.3", 14 | "cloudinary": "^1.24.0", 15 | "cors": "^2.8.5", 16 | "dotenv": "^8.2.0", 17 | "express": "^4.17.1", 18 | "express-fileupload": "^1.2.1", 19 | "express-validator": "^6.9.2", 20 | "google-auth-library": "^6.1.6", 21 | "jsonwebtoken": "^8.5.1", 22 | "mongoose": "^5.11.15", 23 | "socket.io": "^3.1.1", 24 | "uuid": "^8.3.2" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /public/chat.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | ---- 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 |
18 |

Enviar mensaje

19 |
20 | 25 | 26 | 31 | 32 |

Usuarios

33 |
34 | 37 |
38 | 39 | 40 |
41 |

Chat completo

42 |
43 | 46 | 47 | 48 |
49 | 50 | 51 |
52 | 53 | 54 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Google Signin 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |
17 |

Google Signin

18 |
19 |
20 |
21 |
22 | Sign out 23 |
24 | 25 |
26 |

Login manual

27 |
28 | 29 |
30 | 31 | 32 | 33 | 36 |
37 | 38 |
39 |
40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /public/js/auth.js: -------------------------------------------------------------------------------- 1 | 2 | const miFormulario = document.querySelector('form'); 3 | 4 | 5 | const url = ( window.location.hostname.includes('localhost') ) 6 | ? 'http://localhost:8080/api/auth/' 7 | : 'https://restserver-curso-fher.herokuapp.com/api/auth/'; 8 | 9 | 10 | 11 | miFormulario.addEventListener('submit', ev => { 12 | ev.preventDefault(); 13 | const formData = {}; 14 | 15 | for( let el of miFormulario.elements ) { 16 | if ( el.name.length > 0 ) 17 | formData[el.name] = el.value 18 | } 19 | 20 | fetch( url + 'login', { 21 | method: 'POST', 22 | body: JSON.stringify( formData ), 23 | headers: { 'Content-Type': 'application/json' } 24 | }) 25 | .then( resp => resp.json() ) 26 | .then( ({ msg, token }) => { 27 | if( msg ){ 28 | return console.error( msg ); 29 | } 30 | 31 | localStorage.setItem('token', token); 32 | window.location = 'chat.html'; 33 | }) 34 | .catch( err => { 35 | console.log(err) 36 | }) 37 | 38 | }); 39 | 40 | 41 | 42 | 43 | 44 | 45 | function onSignIn(googleUser) { 46 | 47 | // var profile = googleUser.getBasicProfile(); 48 | // console.log('ID: ' + profile.getId()); // Do not send to your backend! Use an ID token instead. 49 | // console.log('Name: ' + profile.getName()); 50 | // console.log('Image URL: ' + profile.getImageUrl()); 51 | // console.log('Email: ' + profile.getEmail()); // This is null if the 'email' scope is not present. 52 | 53 | var id_token = googleUser.getAuthResponse().id_token; 54 | const data = { id_token }; 55 | 56 | fetch( url + 'google', { 57 | method: 'POST', 58 | headers: { 'Content-Type': 'application/json' }, 59 | body: JSON.stringify( data ) 60 | }) 61 | .then( resp => resp.json() ) 62 | .then( ({ token }) => { 63 | localStorage.setItem('token',token); 64 | window.location = 'chat.html'; 65 | }) 66 | .catch( console.log ); 67 | 68 | } 69 | 70 | function signOut() { 71 | var auth2 = gapi.auth2.getAuthInstance(); 72 | auth2.signOut().then(function () { 73 | console.log('User signed out.'); 74 | }); 75 | } -------------------------------------------------------------------------------- /public/js/chat.js: -------------------------------------------------------------------------------- 1 | const url = ( window.location.hostname.includes('localhost') ) 2 | ? 'http://localhost:8080/api/auth/' 3 | : 'https://restserver-curso-fher.herokuapp.com/api/auth/'; 4 | 5 | let usuario = null; 6 | let socket = null; 7 | 8 | // Referencias HTML 9 | const txtUid = document.querySelector('#txtUid'); 10 | const txtMensaje = document.querySelector('#txtMensaje'); 11 | const ulUsuarios = document.querySelector('#ulUsuarios'); 12 | const ulMensajes = document.querySelector('#ulMensajes'); 13 | const btnSalir = document.querySelector('#btnSalir'); 14 | 15 | 16 | 17 | // Validar el token del localstorage 18 | const validarJWT = async() => { 19 | 20 | const token = localStorage.getItem('token') || ''; 21 | 22 | if ( token.length <= 10 ) { 23 | window.location = 'index.html'; 24 | throw new Error('No hay token en el servidor'); 25 | } 26 | 27 | const resp = await fetch( url, { 28 | headers: { 'x-token': token } 29 | }); 30 | 31 | const { usuario: userDB, token: tokenDB } = await resp.json(); 32 | localStorage.setItem('token', tokenDB ); 33 | usuario = userDB; 34 | document.title = usuario.nombre; 35 | 36 | await conectarSocket(); 37 | 38 | } 39 | 40 | const conectarSocket = async() => { 41 | 42 | socket = io({ 43 | 'extraHeaders': { 44 | 'x-token': localStorage.getItem('token') 45 | } 46 | }); 47 | 48 | socket.on('connect', () =>{ 49 | console.log('Sockets online') 50 | }); 51 | 52 | socket.on('disconnect', () =>{ 53 | console.log('Sockets offline') 54 | }); 55 | 56 | socket.on('recibir-mensajes', dibujarMensajes ); 57 | socket.on('usuarios-activos', dibujarUsuarios ); 58 | 59 | socket.on('mensaje-privado', ( payload ) => { 60 | console.log('Privado:', payload ) 61 | }); 62 | 63 | 64 | } 65 | 66 | const dibujarUsuarios = ( usuarios = []) => { 67 | 68 | let usersHtml = ''; 69 | usuarios.forEach( ({ nombre, uid }) => { 70 | 71 | usersHtml += ` 72 |
  • 73 |

    74 |

    ${ nombre }
    75 | ${ uid } 76 |

    77 |
  • 78 | `; 79 | }); 80 | 81 | ulUsuarios.innerHTML = usersHtml; 82 | 83 | } 84 | 85 | 86 | const dibujarMensajes = ( mensajes = []) => { 87 | 88 | let mensajesHTML = ''; 89 | mensajes.forEach( ({ nombre, mensaje }) => { 90 | 91 | mensajesHTML += ` 92 |
  • 93 |

    94 | ${ nombre }: 95 | ${ mensaje } 96 |

    97 |
  • 98 | `; 99 | }); 100 | 101 | ulMensajes.innerHTML = mensajesHTML; 102 | 103 | } 104 | 105 | 106 | txtMensaje.addEventListener('keyup', ({ keyCode }) => { 107 | 108 | const mensaje = txtMensaje.value; 109 | const uid = txtUid.value; 110 | 111 | if( keyCode !== 13 ){ return; } 112 | if( mensaje.length === 0 ){ return; } 113 | 114 | socket.emit('enviar-mensaje', { mensaje, uid }); 115 | 116 | txtMensaje.value = ''; 117 | 118 | }) 119 | 120 | 121 | btnSalir.addEventListener('click', ()=> { 122 | 123 | localStorage.removeItem('token'); 124 | 125 | const auth2 = gapi.auth2.getAuthInstance(); 126 | auth2.signOut().then( () => { 127 | console.log('User signed out.'); 128 | window.location = 'index.html'; 129 | }); 130 | }); 131 | 132 | const main = async() => { 133 | // Validar JWT 134 | await validarJWT(); 135 | } 136 | 137 | (()=>{ 138 | gapi.load('auth2', () => { 139 | gapi.auth2.init(); 140 | main(); 141 | }); 142 | })(); 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | // main(); 151 | 152 | -------------------------------------------------------------------------------- /routes/auth.js: -------------------------------------------------------------------------------- 1 | const { Router } = require('express'); 2 | const { check } = require('express-validator'); 3 | 4 | 5 | const { validarCampos, validarJWT } = require('../middlewares'); 6 | 7 | 8 | const { login, googleSignin, renovarToken } = require('../controllers/auth'); 9 | 10 | 11 | const router = Router(); 12 | 13 | router.post('/login',[ 14 | check('correo', 'El correo es obligatorio').isEmail(), 15 | check('password', 'La contraseña es obligatoria').not().isEmpty(), 16 | validarCampos 17 | ],login ); 18 | 19 | router.post('/google',[ 20 | check('id_token', 'El id_token es necesario').not().isEmpty(), 21 | validarCampos 22 | ], googleSignin ); 23 | 24 | router.get('/', validarJWT, renovarToken ); 25 | 26 | 27 | 28 | module.exports = router; -------------------------------------------------------------------------------- /routes/buscar.js: -------------------------------------------------------------------------------- 1 | const { Router } = require('express'); 2 | const { buscar } = require('../controllers/buscar'); 3 | 4 | const router = Router(); 5 | 6 | 7 | router.get('/:coleccion/:termino', buscar ) 8 | 9 | 10 | 11 | 12 | module.exports = router; -------------------------------------------------------------------------------- /routes/categorias.js: -------------------------------------------------------------------------------- 1 | const { Router } = require('express'); 2 | const { check } = require('express-validator'); 3 | 4 | const { validarJWT, validarCampos, esAdminRole } = require('../middlewares'); 5 | 6 | const { crearCategoria, 7 | obtenerCategorias, 8 | obtenerCategoria, 9 | actualizarCategoria, 10 | borrarCategoria } = require('../controllers/categorias'); 11 | const { existeCategoriaPorId } = require('../helpers/db-validators'); 12 | 13 | const router = Router(); 14 | 15 | /** 16 | * {{url}}/api/categorias 17 | */ 18 | 19 | // Obtener todas las categorias - publico 20 | router.get('/', obtenerCategorias ); 21 | 22 | // Obtener una categoria por id - publico 23 | router.get('/:id',[ 24 | check('id', 'No es un id de Mongo válido').isMongoId(), 25 | check('id').custom( existeCategoriaPorId ), 26 | validarCampos, 27 | ], obtenerCategoria ); 28 | 29 | // Crear categoria - privado - cualquier persona con un token válido 30 | router.post('/', [ 31 | validarJWT, 32 | check('nombre','El nombre es obligatorio').not().isEmpty(), 33 | validarCampos 34 | ], crearCategoria ); 35 | 36 | // Actualizar - privado - cualquiera con token válido 37 | router.put('/:id',[ 38 | validarJWT, 39 | check('nombre','El nombre es obligatorio').not().isEmpty(), 40 | check('id').custom( existeCategoriaPorId ), 41 | validarCampos 42 | ],actualizarCategoria ); 43 | 44 | // Borrar una categoria - Admin 45 | router.delete('/:id',[ 46 | validarJWT, 47 | esAdminRole, 48 | check('id', 'No es un id de Mongo válido').isMongoId(), 49 | check('id').custom( existeCategoriaPorId ), 50 | validarCampos, 51 | ],borrarCategoria); 52 | 53 | 54 | 55 | module.exports = router; -------------------------------------------------------------------------------- /routes/productos.js: -------------------------------------------------------------------------------- 1 | const { Router } = require('express'); 2 | const { check } = require('express-validator'); 3 | 4 | const { validarJWT, validarCampos, esAdminRole } = require('../middlewares'); 5 | 6 | const { crearProducto, 7 | obtenerProductos, 8 | obtenerProducto, 9 | actualizarProducto, 10 | borrarProducto } = require('../controllers/productos'); 11 | 12 | const { existeCategoriaPorId, existeProductoPorId } = require('../helpers/db-validators'); 13 | 14 | const router = Router(); 15 | 16 | /** 17 | * {{url}}/api/categorias 18 | */ 19 | 20 | // Obtener todas las categorias - publico 21 | router.get('/', obtenerProductos ); 22 | 23 | // Obtener una categoria por id - publico 24 | router.get('/:id',[ 25 | check('id', 'No es un id de Mongo válido').isMongoId(), 26 | check('id').custom( existeProductoPorId ), 27 | validarCampos, 28 | ], obtenerProducto ); 29 | 30 | // Crear categoria - privado - cualquier persona con un token válido 31 | router.post('/', [ 32 | validarJWT, 33 | check('nombre','El nombre es obligatorio').not().isEmpty(), 34 | check('categoria','No es un id de Mongo').isMongoId(), 35 | check('categoria').custom( existeCategoriaPorId ), 36 | validarCampos 37 | ], crearProducto ); 38 | 39 | // Actualizar - privado - cualquiera con token válido 40 | router.put('/:id',[ 41 | validarJWT, 42 | // check('categoria','No es un id de Mongo').isMongoId(), 43 | check('id').custom( existeProductoPorId ), 44 | validarCampos 45 | ], actualizarProducto ); 46 | 47 | // Borrar una categoria - Admin 48 | router.delete('/:id',[ 49 | validarJWT, 50 | esAdminRole, 51 | check('id', 'No es un id de Mongo válido').isMongoId(), 52 | check('id').custom( existeProductoPorId ), 53 | validarCampos, 54 | ], borrarProducto); 55 | 56 | 57 | module.exports = router; -------------------------------------------------------------------------------- /routes/uploads.js: -------------------------------------------------------------------------------- 1 | const { Router } = require('express'); 2 | const { check } = require('express-validator'); 3 | 4 | const { validarCampos, validarArchivoSubir } = require('../middlewares'); 5 | const { cargarArchivo, actualizarImagen, mostrarImagen, actualizarImagenCloudinary } = require('../controllers/uploads'); 6 | const { coleccionesPermitidas } = require('../helpers'); 7 | 8 | 9 | const router = Router(); 10 | 11 | 12 | router.post( '/', validarArchivoSubir, cargarArchivo ); 13 | 14 | router.put('/:coleccion/:id', [ 15 | validarArchivoSubir, 16 | check('id','El id debe de ser de mongo').isMongoId(), 17 | check('coleccion').custom( c => coleccionesPermitidas( c, ['usuarios','productos'] ) ), 18 | validarCampos 19 | ], actualizarImagenCloudinary ) 20 | // ], actualizarImagen ) 21 | 22 | router.get('/:coleccion/:id', [ 23 | check('id','El id debe de ser de mongo').isMongoId(), 24 | check('coleccion').custom( c => coleccionesPermitidas( c, ['usuarios','productos'] ) ), 25 | validarCampos 26 | ], mostrarImagen ) 27 | 28 | 29 | 30 | module.exports = router; -------------------------------------------------------------------------------- /routes/usuarios.js: -------------------------------------------------------------------------------- 1 | 2 | const { Router } = require('express'); 3 | const { check } = require('express-validator'); 4 | 5 | const { 6 | validarCampos, 7 | validarJWT, 8 | esAdminRole, 9 | tieneRole 10 | } = require('../middlewares'); 11 | 12 | 13 | const { esRoleValido, emailExiste, existeUsuarioPorId } = require('../helpers/db-validators'); 14 | 15 | const { usuariosGet, 16 | usuariosPut, 17 | usuariosPost, 18 | usuariosDelete, 19 | usuariosPatch } = require('../controllers/usuarios'); 20 | 21 | const router = Router(); 22 | 23 | 24 | router.get('/', usuariosGet ); 25 | 26 | router.put('/:id',[ 27 | check('id', 'No es un ID válido').isMongoId(), 28 | check('id').custom( existeUsuarioPorId ), 29 | check('rol').custom( esRoleValido ), 30 | validarCampos 31 | ],usuariosPut ); 32 | 33 | router.post('/',[ 34 | check('nombre', 'El nombre es obligatorio').not().isEmpty(), 35 | check('password', 'El password debe de ser más de 6 letras').isLength({ min: 6 }), 36 | check('correo', 'El correo no es válido').isEmail(), 37 | check('correo').custom( emailExiste ), 38 | // check('rol', 'No es un rol válido').isIn(['ADMIN_ROLE','USER_ROLE']), 39 | check('rol').custom( esRoleValido ), 40 | validarCampos 41 | ], usuariosPost ); 42 | 43 | router.delete('/:id',[ 44 | validarJWT, 45 | // esAdminRole, 46 | tieneRole('ADMIN_ROLE', 'VENTAR_ROLE','OTRO_ROLE'), 47 | check('id', 'No es un ID válido').isMongoId(), 48 | check('id').custom( existeUsuarioPorId ), 49 | validarCampos 50 | ],usuariosDelete ); 51 | 52 | router.patch('/', usuariosPatch ); 53 | 54 | 55 | 56 | 57 | 58 | module.exports = router; -------------------------------------------------------------------------------- /sockets/controller.js: -------------------------------------------------------------------------------- 1 | const { Socket } = require('socket.io'); 2 | const { comprobarJWT } = require('../helpers'); 3 | const { ChatMensajes } = require('../models'); 4 | 5 | const chatMensajes = new ChatMensajes(); 6 | 7 | 8 | const socketController = async( socket = new Socket(), io ) => { 9 | 10 | const usuario = await comprobarJWT(socket.handshake.headers['x-token']); 11 | if ( !usuario ) { 12 | return socket.disconnect(); 13 | } 14 | 15 | // Agregar el usuario conectado 16 | chatMensajes.conectarUsuario( usuario ); 17 | io.emit('usuarios-activos', chatMensajes.usuariosArr ); 18 | socket.emit('recibir-mensajes', chatMensajes.ultimos10 ); 19 | 20 | // Conectarlo a una sala especial 21 | socket.join( usuario.id ); // global, socket.id, usuario.id 22 | 23 | 24 | // Limpiar cuando alguien se desconeta 25 | socket.on('disconnect', () => { 26 | chatMensajes.desconectarUsuario( usuario.id ); 27 | io.emit('usuarios-activos', chatMensajes.usuariosArr ); 28 | }) 29 | 30 | socket.on('enviar-mensaje', ({ uid, mensaje }) => { 31 | 32 | if ( uid ) { 33 | // Mensaje privado 34 | socket.to( uid ).emit( 'mensaje-privado', { de: usuario.nombre, mensaje }); 35 | } else { 36 | chatMensajes.enviarMensaje(usuario.id, usuario.nombre, mensaje ); 37 | io.emit('recibir-mensajes', chatMensajes.ultimos10 ); 38 | } 39 | 40 | }) 41 | 42 | 43 | } 44 | 45 | 46 | 47 | module.exports = { 48 | socketController 49 | } -------------------------------------------------------------------------------- /uploads/readme.md: -------------------------------------------------------------------------------- 1 | # Nota 2 | Aquí van a guardarse todas las imagenes --------------------------------------------------------------------------------