From 06a9f47a6aab202def23eaf0cf0bb1e3eea42ba1 Mon Sep 17 00:00:00 2001 From: Roland Bernard <rolbernard@unibz.it> Date: Thu, 15 Apr 2021 22:27:08 +0200 Subject: [PATCH] Added basic user registration and authentication --- server/knexfile.ts | 41 +------- server/package.json | 7 ++ server/src/config.ts | 10 ++ server/src/database.ts | 14 +-- server/src/index.ts | 20 +++- server/src/keys.ts | 22 +++++ server/src/knexconfig.ts | 40 ++++++++ server/src/util.ts | 31 ++++++ server/src/v1/auth.ts | 135 +++++++++++++++++++++++++ server/src/v1/index.ts | 12 +++ server/yarn.lock | 208 ++++++++++++++++++++++++++++++++++++--- 11 files changed, 480 insertions(+), 60 deletions(-) create mode 100644 server/src/config.ts create mode 100644 server/src/keys.ts create mode 100644 server/src/knexconfig.ts create mode 100644 server/src/util.ts create mode 100644 server/src/v1/auth.ts create mode 100644 server/src/v1/index.ts diff --git a/server/knexfile.ts b/server/knexfile.ts index 9cf3fd3..76db070 100644 --- a/server/knexfile.ts +++ b/server/knexfile.ts @@ -1,40 +1,5 @@ -module.exports = { - development: { - client: "sqlite3", - connection: { - filename: "./dev.sqlite3" - } - }, - staging: { - client: "postgresql", - connection: { - database: "my_db", - user: "username", - password: "password" - }, - pool: { - min: 2, - max: 10 - }, - migrations: { - tableName: "knex_migrations" - } - }, - production: { - client: "postgresql", - connection: { - database: "my_db", - user: "username", - password: "password" - }, - pool: { - min: 2, - max: 10 - }, - migrations: { - tableName: "knex_migrations" - } - } -}; +import config from './src/knexconfig'; + +export default config; diff --git a/server/package.json b/server/package.json index 8f82388..89c56c1 100644 --- a/server/package.json +++ b/server/package.json @@ -8,7 +8,10 @@ "private": true, "main": "src/index.ts", "dependencies": { + "bcrypt": "^5.0.1", + "body-parser": "^1.19.0", "express": "^4.17.1", + "jsonwebtoken": "^8.5.1", "knex": "^0.95.4", "sqlite3": "^5.0.2", "uuid": "^8.3.2" @@ -19,9 +22,13 @@ "test": "jest --watch --config ./jest.config.json" }, "devDependencies": { + "@types/bcrypt": "^3.0.1", + "@types/body-parser": "^1.19.0", "@types/express": "^4.17.11", "@types/jest": "^26.0.22", + "@types/jsonwebtoken": "^8.5.1", "@types/node": "^14.14.37", + "@types/uuid": "^8.3.0", "jest": "^26.6.3", "nodemon": "^2.0.7", "ts-jest": "^26.5.4", diff --git a/server/src/config.ts b/server/src/config.ts new file mode 100644 index 0000000..f083c08 --- /dev/null +++ b/server/src/config.ts @@ -0,0 +1,10 @@ + +export const port = "development"; + +export const keys = { + private: '/etc/ssl/localcerts/cert.key', + public: '/etc/ssl/localcerts/cert.pem' +}; + +export const environment = "development"; + diff --git a/server/src/database.ts b/server/src/database.ts index c26f030..b83616d 100644 --- a/server/src/database.ts +++ b/server/src/database.ts @@ -1,15 +1,11 @@ import knex from 'knex'; -const database = knex({ - client: 'sqlite3', - connection: { - filename: './database.db' - } -}); +import { environment } from './config'; +import config from './knexconfig'; + +const database = knex(config[environment]); database.migrate.latest(); -export default function getDatabase() { - return database; -} +export default database; diff --git a/server/src/index.ts b/server/src/index.ts index 1072dfb..449cb1c 100644 --- a/server/src/index.ts +++ b/server/src/index.ts @@ -1,9 +1,25 @@ -import express from 'express'; +import express, { Request, Response, NextFunction } from 'express'; +import { json as bodyJson } from 'body-parser'; + +import v1 from './v1'; const app = express(); const PORT = 8000; -app.get('/', (_, res) => res.send('Hello world!')); + +app.use(bodyJson()); + +app.use('/v1', v1); + +app.use((_req, res) => { + res.sendStatus(404); +}); + +app.use((_err: Error, _req: Request, res: Response, _next: NextFunction) => { + return res.status(400).json({ + status: 'error', + }); +}); app.listen(PORT, () => { console.log(`[server] Server is running at https://localhost:${PORT}`); diff --git a/server/src/keys.ts b/server/src/keys.ts new file mode 100644 index 0000000..8b42a1b --- /dev/null +++ b/server/src/keys.ts @@ -0,0 +1,22 @@ + +import { readFileBuffer } from './util'; +import { keys } from './config'; + +let privateKey: Buffer; + +export async function getPrivateKey(): Promise<Buffer> { + if (!privateKey) { + privateKey = await readFileBuffer(keys.private); + } + return privateKey; +} + +let publicKey: Buffer; + +export async function getPublicKey(): Promise<Buffer> { + if (!publicKey) { + publicKey = await readFileBuffer(keys.public); + } + return publicKey; +} + diff --git a/server/src/knexconfig.ts b/server/src/knexconfig.ts new file mode 100644 index 0000000..eaefee8 --- /dev/null +++ b/server/src/knexconfig.ts @@ -0,0 +1,40 @@ + +export default { + development: { + client: "sqlite3", + connection: { + filename: "./dev.sqlite3" + } + }, + staging: { + client: "postgresql", + connection: { + database: "my_db", + user: "username", + password: "password" + }, + pool: { + min: 2, + max: 10 + }, + migrations: { + tableName: "knex_migrations" + } + }, + production: { + client: "postgresql", + connection: { + database: "my_db", + user: "username", + password: "password" + }, + pool: { + min: 2, + max: 10 + }, + migrations: { + tableName: "knex_migrations" + } + } +}; + diff --git a/server/src/util.ts b/server/src/util.ts new file mode 100644 index 0000000..6ae83da --- /dev/null +++ b/server/src/util.ts @@ -0,0 +1,31 @@ + +import { readFile } from 'fs'; + +export const isOfType = <T>( + varToBeChecked: any, + propertyToCheckFor: (keyof T)[] +): varToBeChecked is T => { + for (const key of propertyToCheckFor) { + if (!(varToBeChecked as T)[key]) { + return false; + } + } + return true; +} + +export function readFileBuffer(filename: string): Promise<Buffer> { + return asyncify(readFile, filename); +} + +export function asyncify<T extends any[], E, R>(func: (...args: [...T, (err: E, result: R) => any]) => any, ...args: T): Promise<R> { + return new Promise((res, rej) => { + func(...args, (err: E, result: R) => { + if (err) { + rej(err); + } else { + res(result); + } + }); + }); +} + diff --git a/server/src/v1/auth.ts b/server/src/v1/auth.ts new file mode 100644 index 0000000..247d7ae --- /dev/null +++ b/server/src/v1/auth.ts @@ -0,0 +1,135 @@ + +import express, { NextFunction, Request, Response } from 'express'; +import { v4 as uuid } from 'uuid'; +import { hash, compare } from 'bcrypt' +import { sign, verify } from 'jsonwebtoken'; + +import database from '../database'; +import { isOfType, asyncify } from '../util'; +import { getPublicKey, getPrivateKey } from '../keys'; + +const auth = express(); + +interface RegisterBody { + username: string; + password: string; +} + +auth.post('/register', async (req, res) => { + if (isOfType<RegisterBody>(req.body, ['username', 'password'])) { + const body: RegisterBody = req.body; + const id = uuid(); + const passwdHash = await hash(body.password, 10); + try { + await database('users').insert({ + id: id, + user_name: body.username, + passwd_hash: passwdHash + }); + res.status(200).json({ + status: 'success', + }); + } catch (e) { + res.status(400).json({ + status: 'error', + message: 'failed to create user', + }); + } + } else { + res.status(400).json({ + status: 'error', + message: 'missing request fields', + }); + } +}); + +interface TokenBody { + username: string; + password: string; +} + +auth.post('/token', async (req, res) => { + if (isOfType<TokenBody>(req.body, ['username', 'password'])) { + const body: TokenBody = req.body; + try { + const user = await database('users').where({ user_name: body.username }); + if (user.length === 1) { + if (await compare(body.password, user[0].passwd_hash)) { + const token = await asyncify(sign, { + id: user[0].id, + }, await getPrivateKey(), { algorithm: "ES384", expiresIn: 60 * 60 }); + res.status(200).json({ + status: 'success', + token: token, + }); + } else { + res.status(400).json({ + status: 'error', + message: 'wrong username or password', + }); + } + } else { + res.status(400).json({ + status: 'error', + message: 'username not found', + }); + } + } catch (e) { + console.error(e); + res.status(400).json({ + status: 'error', + message: 'failed to acquire token', + }); + } + } else { + res.status(400).json({ + status: 'error', + message: 'missing request fields', + }); + } +}); + +auth.get("/extend", async function (req, res) { + if (req.body?.token) { + const token = await asyncify(sign, { + id: req.body.token.id, + }, await getPrivateKey(), { algorithm: "ES384", expiresIn: 60 * 60 }); + res.status(200).json({ + status: 'success', + token: token, + }); + } else { + res.status(403).json({ + status: 'error', + message: 'authentication failed', + }); + } +}); + +export async function tokenVerification(req: Request, res: Response, next: NextFunction) { + const header = req.headers?.authorization; + let token: string | null = null; + if (header) { + const bearer = header.split(' '); + token = bearer[1]; + } else if (req.body?.token) { + token = req.body?.token; + } + if (token) { + try { + const decoded = await asyncify(verify, token, await getPublicKey(), { algorithms: ["ES384"] }); + req.body.token = decoded; + next(); + } catch (err) { + res.status(403).json({ + status: 'error', + message: 'authentication failed', + }); + } + } else { + next(); + } +} + +export default auth; + diff --git a/server/src/v1/index.ts b/server/src/v1/index.ts new file mode 100644 index 0000000..2a13b9b --- /dev/null +++ b/server/src/v1/index.ts @@ -0,0 +1,12 @@ + +import express from 'express'; + +import auth, { tokenVerification } from './auth'; + +const v1 = express(); + +v1.use(tokenVerification); +v1.use('/auth', auth); + +export default v1; + diff --git a/server/yarn.lock b/server/yarn.lock index 172d18f..a283166 100644 --- a/server/yarn.lock +++ b/server/yarn.lock @@ -483,6 +483,21 @@ "@types/yargs" "^15.0.0" chalk "^4.0.0" +"@mapbox/node-pre-gyp@^1.0.0": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.3.tgz#c740c23ec1007b9278d4c28f767b6e843a88c3d3" + integrity sha512-9dTIfQW8HVCxLku5QrJ/ysS/b2MdYngs9+/oPrOTLvp3TrggdANYVW2h8FGJGDf0J7MYfp44W+c90cVJx+ASuA== + dependencies: + detect-libc "^1.0.3" + https-proxy-agent "^5.0.0" + make-dir "^3.1.0" + node-fetch "^2.6.1" + nopt "^5.0.0" + npmlog "^4.1.2" + rimraf "^3.0.2" + semver "^7.3.4" + tar "^6.1.0" + "@sindresorhus/is@^0.14.0": version "0.14.0" resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" @@ -542,7 +557,12 @@ dependencies: "@babel/types" "^7.3.0" -"@types/body-parser@*": +"@types/bcrypt@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/bcrypt/-/bcrypt-3.0.1.tgz#9c767594e31aa1c4ce78d23aa4351984403ca28f" + integrity sha512-SwBrq5wb6jXP0o3O3jStdPWbKpimTImfdFD/OZE3uW+jhGpds/l5wMX9lfYOTDOa5Bod2QmOgo9ln+tMp2XP/w== + +"@types/body-parser@*", "@types/body-parser@^1.19.0": version "1.19.0" resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.0.tgz#0685b3c47eb3006ffed117cdd55164b61f80538f" integrity sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ== @@ -610,6 +630,13 @@ jest-diff "^26.0.0" pretty-format "^26.0.0" +"@types/jsonwebtoken@^8.5.1": + version "8.5.1" + resolved "https://registry.yarnpkg.com/@types/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz#56958cb2d80f6d74352bd2e501a018e2506a8a84" + integrity sha512-rNAPdomlIUX0i0cg2+I+Q1wOUr531zHBQ+cV/28PJ39bSPKjahatZZ2LMuhiguETkCgLVzfruw/ZvNMNkKoSzw== + dependencies: + "@types/node" "*" + "@types/mime@^1": version "1.3.2" resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a" @@ -653,6 +680,11 @@ resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.0.tgz#7036640b4e21cc2f259ae826ce843d277dad8cff" integrity sha512-RJJrrySY7A8havqpGObOB4W92QXKJo63/jFLLgpvOtsGUqbQZ9Sbgl35KMm1DjC6j7AvmmU2bIno+3IyEaemaw== +"@types/uuid@^8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.0.tgz#215c231dff736d5ba92410e6d602050cce7e273f" + integrity sha512-eQ9qFW/fhfGJF8WKHGEHZEyVWfZxrT+6CLIJGBcZPfxUh/+BnEj+UCGYMlr9qZuX/2AltsvwrGqp0LhEW8D0zQ== + "@types/yargs-parser@*": version "20.2.0" resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-20.2.0.tgz#dd3e6699ba3237f0348cd085e4698780204842f9" @@ -706,6 +738,13 @@ acorn@^8.1.0: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.1.0.tgz#52311fd7037ae119cbb134309e901aa46295b3fe" integrity sha512-LWCF/Wn0nfHOmJ9rzQApGnxnvgfROzGilS8936rqN/lfcYkY9MYZzdMqN+2NJ4SlTc+m5HiSa+kNfDtI64dwUA== +agent-base@6: + version "6.0.2" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== + dependencies: + debug "4" + ajv@^6.12.3: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" @@ -953,6 +992,14 @@ bcrypt-pbkdf@^1.0.0: dependencies: tweetnacl "^0.14.3" +bcrypt@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/bcrypt/-/bcrypt-5.0.1.tgz#f1a2c20f208e2ccdceea4433df0c8b2c54ecdf71" + integrity sha512-9BTgmrhZM2t1bNuDtrtIMVSmmxZBrJ71n8Wg+YgdjHuIWYF7SjjmCPZFB+/5i/o/PIeRpwVJR3P+NrpIItUjqw== + dependencies: + "@mapbox/node-pre-gyp" "^1.0.0" + node-addon-api "^3.1.0" + binary-extensions@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" @@ -965,7 +1012,7 @@ block-stream@*: dependencies: inherits "~2.0.0" -body-parser@1.19.0: +body-parser@1.19.0, body-parser@^1.19.0: version "1.19.0" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw== @@ -1056,6 +1103,11 @@ bser@2.1.1: dependencies: node-int64 "^0.4.0" +buffer-equal-constant-time@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" + integrity sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk= + buffer-from@1.x, buffer-from@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" @@ -1176,6 +1228,11 @@ chownr@^1.1.1: resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== +chownr@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" + integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== + ci-info@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" @@ -1422,7 +1479,7 @@ debug@2.6.9, debug@^2.2.0, debug@^2.3.3: dependencies: ms "2.0.0" -debug@4.3.1, debug@^4.1.0, debug@^4.1.1: +debug@4, debug@4.3.1, debug@^4.1.0, debug@^4.1.1: version "4.3.1" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== @@ -1520,7 +1577,7 @@ destroy@~1.0.4: resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= -detect-libc@^1.0.2: +detect-libc@^1.0.2, detect-libc@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= @@ -1567,6 +1624,13 @@ ecc-jsbn@~0.1.1: jsbn "~0.1.0" safer-buffer "^2.1.0" +ecdsa-sig-formatter@1.0.11: + version "1.0.11" + resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf" + integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ== + dependencies: + safe-buffer "^5.0.1" + ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" @@ -1919,6 +1983,13 @@ fs-minipass@^1.2.5: dependencies: minipass "^2.6.0" +fs-minipass@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" + integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== + dependencies: + minipass "^3.0.0" + fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -2186,6 +2257,14 @@ http-signature@~1.2.0: jsprim "^1.2.2" sshpk "^1.7.0" +https-proxy-agent@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2" + integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA== + dependencies: + agent-base "6" + debug "4" + human-signals@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" @@ -3001,6 +3080,22 @@ json5@2.x, json5@^2.1.2: dependencies: minimist "^1.2.5" +jsonwebtoken@^8.5.1: + version "8.5.1" + resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz#00e71e0b8df54c2121a1f26137df2280673bcc0d" + integrity sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w== + dependencies: + jws "^3.2.2" + lodash.includes "^4.3.0" + lodash.isboolean "^3.0.3" + lodash.isinteger "^4.0.4" + lodash.isnumber "^3.0.3" + lodash.isplainobject "^4.0.6" + lodash.isstring "^4.0.1" + lodash.once "^4.0.0" + ms "^2.1.1" + semver "^5.6.0" + jsprim@^1.2.2: version "1.4.1" resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" @@ -3011,6 +3106,23 @@ jsprim@^1.2.2: json-schema "0.2.3" verror "1.10.0" +jwa@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a" + integrity sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA== + dependencies: + buffer-equal-constant-time "1.0.1" + ecdsa-sig-formatter "1.0.11" + safe-buffer "^5.0.1" + +jws@^3.2.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304" + integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA== + dependencies: + jwa "^1.4.1" + safe-buffer "^5.0.1" + keyv@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" @@ -3098,6 +3210,41 @@ locate-path@^5.0.0: dependencies: p-locate "^4.1.0" +lodash.includes@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" + integrity sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8= + +lodash.isboolean@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6" + integrity sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY= + +lodash.isinteger@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343" + integrity sha1-YZwK89A/iwTDH1iChAt3sRzWg0M= + +lodash.isnumber@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc" + integrity sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w= + +lodash.isplainobject@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" + integrity sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs= + +lodash.isstring@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" + integrity sha1-1SfftUVuynzJu5XV2ur4i6VKVFE= + +lodash.once@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" + integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w= + lodash@4.x, lodash@^4.17.19, lodash@^4.17.21, lodash@^4.7.0: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" @@ -3120,7 +3267,7 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" -make-dir@^3.0.0: +make-dir@^3.0.0, make-dir@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== @@ -3245,6 +3392,13 @@ minipass@^2.6.0, minipass@^2.8.6, minipass@^2.9.0: safe-buffer "^5.1.2" yallist "^3.0.0" +minipass@^3.0.0: + version "3.1.3" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.3.tgz#7d42ff1f39635482e15f9cdb53184deebd5815fd" + integrity sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg== + dependencies: + yallist "^4.0.0" + minizlib@^1.2.1: version "1.3.3" resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d" @@ -3252,6 +3406,14 @@ minizlib@^1.2.1: dependencies: minipass "^2.9.0" +minizlib@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" + integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== + dependencies: + minipass "^3.0.0" + yallist "^4.0.0" + mixin-deep@^1.2.0: version "1.3.2" resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" @@ -3260,7 +3422,7 @@ mixin-deep@^1.2.0: for-in "^1.0.2" is-extendable "^1.0.1" -mkdirp@1.x: +mkdirp@1.x, mkdirp@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== @@ -3333,11 +3495,16 @@ nice-try@^1.0.4: resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== -node-addon-api@^3.0.0: +node-addon-api@^3.0.0, node-addon-api@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-3.1.0.tgz#98b21931557466c6729e51cb77cd39c965f42239" integrity sha512-flmrDNB06LIl5lywUz7YlNGZH/5p0M7W28k8hzd9Lshtdh1wshD2Y+U4h9LD6KObOy1f+fEVdgprPrEymjM5uw== +node-fetch@^2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" + integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== + node-gyp@3.x: version "3.8.0" resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-3.8.0.tgz#540304261c330e80d0d5edce253a68cb3964218c" @@ -3430,6 +3597,13 @@ nopt@^4.0.1: abbrev "1" osenv "^0.1.4" +nopt@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-5.0.0.tgz#530942bb58a512fccafe53fe210f13a25355dc88" + integrity sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ== + dependencies: + abbrev "1" + nopt@~1.0.10: version "1.0.10" resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee" @@ -3499,7 +3673,7 @@ npm-run-path@^4.0.0: dependencies: path-key "^3.0.0" -"npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.2: +"npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.2, npmlog@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== @@ -4026,7 +4200,7 @@ rimraf@2, rimraf@^2.6.1: dependencies: glob "^7.1.3" -rimraf@^3.0.0: +rimraf@^3.0.0, rimraf@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== @@ -4094,12 +4268,12 @@ semver-diff@^3.1.1: dependencies: semver "^6.3.0" -"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.5.0, semver@^5.7.1: +"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.5.0, semver@^5.6.0, semver@^5.7.1: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== -semver@7.x, semver@^7.3.2: +semver@7.x, semver@^7.3.2, semver@^7.3.4: version "7.3.5" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== @@ -4513,6 +4687,18 @@ tar@^4: safe-buffer "^5.1.2" yallist "^3.0.3" +tar@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.0.tgz#d1724e9bcc04b977b18d5c573b333a2207229a83" + integrity sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA== + dependencies: + chownr "^2.0.0" + fs-minipass "^2.0.0" + minipass "^3.0.0" + minizlib "^2.1.1" + mkdirp "^1.0.3" + yallist "^4.0.0" + tarn@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/tarn/-/tarn-3.0.1.tgz#ebac2c6dbc6977d34d4526e0a7814200386a8aec" -- GitLab