diff --git a/.gitignore b/.gitignore index e2f92125..d1821376 100644 --- a/.gitignore +++ b/.gitignore @@ -53,6 +53,7 @@ typings/ # dotenv environment variable files .env* +./docker/kratos/config/kratos.yml # Mac files .DS_Store @@ -82,3 +83,13 @@ docker/nginx/conf.d/server-override/* __pycache__ /.idea/ /venv* + +# CockroachDB certificates +docker/cockroach/certs/*.crt +docker/cockroach/certs/*.key +docker/kratos/cr_certs/*.crt +docker/kratos/cr_certs/*.key + +# Oathkeeper JWKS signing token +docker/kratos/oathkeeper/id_token.jwks.json +/docker/kratos/config/kratos.yml diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 00000000..6ec8e548 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,2 @@ +/package.json +/package-lock.json \ No newline at end of file diff --git a/README.md b/README.md index 8cd84d05..59c2e5df 100644 --- a/README.md +++ b/README.md @@ -26,12 +26,160 @@ following Siacoin address: `fb6c9320bc7e01fbb9cd8d8c3caaa371386928793c736837832e634aaaa484650a3177d6714a` +### MongoDB Setup + +Mongo needs a couple of extra steps in order to start a secure cluster. + +- Open port 27017 on all nodes that will take part in the cluster. Ideally, you would only open the port for the other + nodes in the cluster. +- Manually run an initialisation `docker run` with extra environment variables that will initialise the admin user with + a password (example below). +- Manually add a `mgkey` file under `./docker/data/mongo` with the respective secret ( + see [Mongo's keyfile access control](https://docs.mongodb.com/manual/tutorial/enforce-keyfile-access-control-in-existing-replica-set/) + for details). +- During the initialisation run mentioned above, we need to make two extra steps within the container: + - Change the ownership of `mgkey` to `mongodb:mongodb` + - Change its permissions to 400 +- After these steps are done we can open a mongo shell on the master node and run `rs.add()` in order to add the new + node to the cluster. + +Example initialisation docker run command: + +``` +docker run \ + --rm \ + --name mg \ + -p 27017:27017 \ + -e MONGO_INITDB_ROOT_USERNAME= \ + -e MONGO_INITDB_ROOT_PASSWORD= \ + -v /home/user/skynet-webportal/docker/data/mongo/db:/data/db \ + -v /home/user/skynet-webportal/docker/data/mongo/mgkey:/data/mgkey \ + mongo --keyFile=/data/mgkey --replSet=skynet +``` + +Regular docker run command: + +``` +docker run \ + --rm \ + --name mg \ + -p 27017:27017 \ + -v /home/user/skynet-webportal/docker/data/mongo/db:/data/db \ + -v /home/user/skynet-webportal/docker/data/mongo/mgkey:/data/mgkey \ + mongo --keyFile=/data/mgkey --replSet=skynet +``` + +Cluster initialisation mongo command: + +``` +rs.initiate( + { + _id : "skynet", + members: [ + { _id : 0, host : "mongo:27017" } + ] + } +) +``` + +Add more nodes when they are ready: + +``` +rs.add("second.node.net:27017") +``` + +### Kratos & Oathkeeper Setup + +[Kratos](https://www.ory.sh/kratos) is our user management system of choice and +[Oathkeeper](https://www.ory.sh/oathkeeper) is the identity and access proxy. + +Most of the needed config is already under `docker/kratos`. The only two things that need to be changed are the config +for Kratos that might contain you email server password, and the JWKS Oathkeeper uses to sign its JWT tokens. + +Make sure to create your own`docker/kratos/config/kratos.yml` by copying the `kratos.yml.sample` in the same directory. +Also make sure to never add that file to source control because it will most probably contain your email password in +plain text! + +To override the JWKS you will need to directly edit +`docker/kratos/oathkeeper/id_token.jwks.json` and replace it with your generated key set. If you don't know how to +generate a key set you can use this code: + +```go +package main + +import ( + "encoding/json" + "log" + "os" + + "github.com/ory/hydra/jwk" +) + +func main() { + gen := jwk.RS256Generator{ + KeyLength: 2048, + } + jwks, err := gen.Generate("", "sig") + if err != nil { + log.Fatal(err) + } + jsonbuf, err := json.MarshalIndent(jwks, "", " ") + if err != nil { + log.Fatal("failed to generate JSON: %s", err) + } + os.Stdout.Write(jsonbuf) +} +``` + +While you can directly put the output of this programme into the file mentioned above, you can also remove the public +key from the set and change the `kid` of the private key to not include the prefix `private:`. + +### CockroachDB Setup + +Kratos uses CockroachDB to store its data. For that data to be shared across all nodes that comprise your portal cluster +setup, we need to set up a CockroachDB cluster, complete with secure communication. + +#### Generate the certificates for secure communication + +For a detailed walk-through, please check [this guide](https://www.cockroachlabs.com/docs/v20.2/secure-a-cluster.html) +out. + +Steps: + +1. Start a local cockroach docker instance: + `docker run -d -v ":/cockroach/cockroach-secure" --name=crdb cockroachdb/cockroach start --insecure` +1. Get a shall into that instance: `docker exec -it crdb /bin/bash` +1. Go to the directory we which we mapped to a local dir: `cd /cockroach/cockroach-secure` +1. Create the subdirectories in which to create certificates and keys: `mkdir certs my-safe-directory` +1. Create the CA (Certificate Authority) certificate and key + pair: `cockroach cert create-ca --certs-dir=certs --ca-key=my-safe-directory/ca.key` +1. Create a client certificate and key pair for the root + user: `cockroach cert create-client root --certs-dir=certs --ca-key=my-safe-directory/ca.key` +1. Create the certificate and key pair for your + nodes: `cockroach cert create-node cockroach mynode.siasky.net --certs-dir=certs --ca-key=my-safe-directory/ca.key`. + Don't forget the `cockroach` node name - it's needed by our docker-compose setup. If you want to create certificates + for more nodes, just delete the `node.*` files (after you've finished the next steps for this node!) and re-run the + above command with the new node name. +1. Put the contents of the `certs` folder under `docker/cockroach/certs/*` under your portal's root dir and store the + content of `my-safe-directory` somewhere safe. +1. Put _another copy_ of those certificates under `docker/kratos/cr_certs` and change permissions of the `*.key` files, + so they can be read by anyone (644). + +#### Configure your CockroachDB node + +There is some configuration that needs to be added to your `.env`file, namely: + +1. CR_NODE - the name of your node +1. CR_IP - the public IP of your node +1. CR_CLUSTER_NODES - a list of IPs and ports which make up your cluster, e.g. + `95.216.13.185:26257,147.135.37.21:26257,144.76.136.122:26257`. This will be the list of nodes that will make up your + cluster, so make sure those are accurate. + ## Contributing ### Testing Your Code -Before pushing your code you should verify that it will pass our online test -suite. +Before pushing your code, you should verify that it will pass our online test suite. **Cypress Tests** Verify the Cypress test suite by doing the following: diff --git a/docker-compose.accounts.yml b/docker-compose.accounts.yml new file mode 100644 index 00000000..22d24541 --- /dev/null +++ b/docker-compose.accounts.yml @@ -0,0 +1,167 @@ +version: "3.7" + +x-logging: &default-logging + driver: json-file + options: + max-size: "10m" + max-file: "3" + +services: + webapp: + build: + args: + WITH_ACCOUNTS: 1 # enable accounts frontend + + nginx: + environment: + - ACCOUNTS_ENABLED=1 + volumes: + - ./docker/accounts/nginx.account.conf:/etc/nginx/conf.extra.d/nginx.account.conf:ro + depends_on: + - accounts + + accounts: + build: + context: ./docker/accounts + dockerfile: Dockerfile + container_name: accounts + restart: unless-stopped + logging: *default-logging + env_file: + - .env + environment: + - SKYNET_DB_HOST=${SKYNET_DB_HOST} + - SKYNET_DB_PORT=${SKYNET_DB_PORT} + - SKYNET_DB_USER=${SKYNET_DB_USER} + - SKYNET_DB_PASS=${SKYNET_DB_PASS} + - COOKIE_DOMAIN=${COOKIE_DOMAIN} + - COOKIE_HASH_KEY=${COOKIE_HASH_KEY} + - COOKIE_ENC_KEY=${COOKIE_ENC_KEY} + - STRIPE_API_KEY=${STRIPE_API_KEY} + - STRIPE_WEBHOOK_SECRET=${STRIPE_WEBHOOK_SECRET} + - SKYNET_ACCOUNTS_LOG_LEVEL=${SKYNET_ACCOUNTS_LOG_LEVEL} + - KRATOS_ADDR=${KRATOS_ADDR} + - OATHKEEPER_ADDR=${OATHKEEPER_ADDR} + expose: + - 3000 + networks: + shared: + ipv4_address: 10.10.10.70 + depends_on: + - mongo + - oathkeeper + + mongo: + image: mongo:4.4.1 + command: --keyFile=/data/mgkey --replSet=skynet + container_name: mongo + restart: unless-stopped + logging: *default-logging + volumes: + - ./docker/data/mongo/db:/data/db + - ./docker/data/mongo/mgkey:/data/mgkey:rw + networks: + shared: + ipv4_address: 10.10.10.71 + ports: + - "27017:27017" + + kratos-migrate: + image: oryd/kratos:v0.5.5-alpha.1 + container_name: kratos-migrate + restart: "no" + logging: *default-logging + environment: + - DSN=cockroach://root@cockroach:26257/defaultdb?max_conns=20&max_idle_conns=4&sslmode=verify-full&sslcert=/certs/node.crt&sslkey=/certs/node.key&sslrootcert=/certs/ca.crt + - SQA_OPT_OUT=true + volumes: + - ./docker/kratos/config:/etc/config/kratos + - ./docker/data/cockroach/sqlite:/var/lib/sqlite + - ./docker/kratos/cr_certs:/certs + command: -c /etc/config/kratos/kratos.yml migrate sql -e --yes + networks: + shared: + ipv4_address: 10.10.10.80 + depends_on: + - cockroach + + kratos: + image: oryd/kratos:v0.5.5-alpha.1 + container_name: kratos + restart: unless-stopped + logging: *default-logging + expose: + - 4433 # public + - 4434 # admin + environment: + - DSN=cockroach://root@cockroach:26257/defaultdb?max_conns=20&max_idle_conns=4&sslmode=verify-full&sslcert=/certs/node.crt&sslkey=/certs/node.key&sslrootcert=/certs/ca.crt + - LOG_LEVEL=trace + - SERVE_PUBLIC_BASE_URL=${SKYNET_DASHBOARD_URL}/.ory/kratos/public/ + - SQA_OPT_OUT=true + command: serve -c /etc/config/kratos/kratos.yml + volumes: + - ./docker/kratos/config:/etc/config/kratos + - ./docker/data/cockroach/sqlite:/var/lib/sqlite + - ./docker/kratos/cr_certs:/certs + networks: + shared: + ipv4_address: 10.10.10.81 + depends_on: + - kratos-migrate + + dashboard: + build: + context: ./packages/dashboard + dockerfile: Dockerfile + container_name: dashboard + restart: unless-stopped + logging: *default-logging + env_file: + - .env + environment: + - NEXT_PUBLIC_SKYNET_PORTAL_API=${SKYNET_PORTAL_API} + - NEXT_PUBLIC_SKYNET_DASHBOARD_URL=${SKYNET_DASHBOARD_URL} + - NEXT_PUBLIC_KRATOS_BROWSER_URL=${SKYNET_DASHBOARD_URL}/.ory/kratos/public + - NEXT_PUBLIC_KRATOS_PUBLIC_URL=${SKYNET_DASHBOARD_URL}/.ory/kratos/public + - NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=${STRIPE_PUBLISHABLE_KEY} + volumes: + - ./docker/data/dashboard/.next:/usr/app/.next + networks: + shared: + ipv4_address: 10.10.10.85 + expose: + - 3000 + + oathkeeper: + image: oryd/oathkeeper:v0.38 + container_name: oathkeeper + expose: + - 4455 + - 4456 + command: serve proxy -c "/etc/config/oathkeeper/oathkeeper.yml" + environment: + - LOG_LEVEL=debug + volumes: + - ./docker/kratos/oathkeeper:/etc/config/oathkeeper + restart: on-failure + networks: + shared: + ipv4_address: 10.10.10.83 + depends_on: + - kratos + + cockroach: + image: cockroachdb/cockroach:v20.2.3 + container_name: cockroach + env_file: + - .env + command: start --advertise-addr=${CR_IP} --join=${CR_CLUSTER_NODES} --certs-dir=/certs --listen-addr=0.0.0.0:26257 --http-addr=0.0.0.0:8080 + volumes: + - ./docker/data/cockroach/sqlite:/cockroach/cockroach-data + - ./docker/cockroach/certs:/certs + ports: + - "4080:8080" + - "26257:26257" + networks: + shared: + ipv4_address: 10.10.10.84 diff --git a/docker-compose.uploads.yml b/docker-compose.uploads.yml new file mode 100644 index 00000000..c7d3043a --- /dev/null +++ b/docker-compose.uploads.yml @@ -0,0 +1,12 @@ +version: "3.7" + +services: + nginx: + build: + context: ./docker/nginx + dockerfile: Dockerfile.bionic + args: + RESTY_ADD_PACKAGE_BUILDDEPS: git + RESTY_EVAL_PRE_CONFIGURE: git clone https://github.com/fdintino/nginx-upload-module /tmp/nginx-upload-module + RESTY_CONFIG_OPTIONS_MORE: --add-module=/tmp/nginx-upload-module + RESTY_EVAL_POST_MAKE: /usr/local/openresty/luajit/bin/luarocks install luasocket diff --git a/docker-compose.yml b/docker-compose.yml index 12597890..5671efad 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -13,9 +13,6 @@ networks: config: - subnet: 10.10.10.0/24 -volumes: - webapp: - services: sia: build: @@ -76,7 +73,6 @@ services: - ./docker/data/nginx/logs:/usr/local/openresty/nginx/logs - ./docker/data/nginx/skynet:/data/nginx/skynet:ro - ./docker/data/sia/apipassword:/data/sia/apipassword:ro - - webapp:/var/www/webportal:ro networks: shared: ipv4_address: 10.10.10.30 @@ -94,9 +90,13 @@ services: container_name: webapp restart: unless-stopped logging: *default-logging - tty: true volumes: - - webapp:/usr/app/public + - ./docker/data/webapp/.cache:/usr/app/.cache + networks: + shared: + ipv4_address: 10.10.10.35 + expose: + - 9000 handshake: build: @@ -163,18 +163,3 @@ services: depends_on: - handshake - handshake-api - - mongo: - image: mongo:4.4.1 - command: --keyFile=/data/mgkey --replSet=skynet - container_name: mongo - restart: unless-stopped - logging: *default-logging - volumes: - - ./docker/data/mongo/db:/data/db - - ./docker/data/mongo/mgkey:/data/mgkey:rw - networks: - shared: - ipv4_address: 10.10.10.70 - ports: - - "27017:27017" diff --git a/docker/accounts/Dockerfile b/docker/accounts/Dockerfile new file mode 100644 index 00000000..8be44370 --- /dev/null +++ b/docker/accounts/Dockerfile @@ -0,0 +1,20 @@ +FROM golang:1.15 +LABEL maintainer="NebulousLabs " + +ENV GOOS linux +ENV GOARCH amd64 + +WORKDIR /root + +RUN git clone --single-branch --branch main https://github.com/NebulousLabs/skynet-accounts.git && \ + cd skynet-accounts && \ + go mod download && \ + make release + +ENV SKYNET_DB_HOST="localhost" +ENV SKYNET_DB_PORT="27017" +ENV SKYNET_DB_USER="username" +ENV SKYNET_DB_PASS="password" +ENV SKYNET_ACCOUNTS_PORT=3000 + +ENTRYPOINT ["skynet-accounts"] diff --git a/docker/accounts/nginx.account.conf b/docker/accounts/nginx.account.conf new file mode 100644 index 00000000..f3705200 --- /dev/null +++ b/docker/accounts/nginx.account.conf @@ -0,0 +1,20 @@ +server { + listen 80; + listen [::]:80; + server_name account.*; + + location / { + proxy_redirect http://127.0.0.1/ https://$host/; + proxy_pass http://oathkeeper:4455; + } +} + +server { + listen 80; + listen [::]:80; + server_name secure.*; + + if ($host ~ secure.(.*)) { + return 301 $scheme://account.$1$request_uri; + } +} diff --git a/docker/cockroach/certs/README.md b/docker/cockroach/certs/README.md new file mode 100644 index 00000000..fd957133 --- /dev/null +++ b/docker/cockroach/certs/README.md @@ -0,0 +1,2 @@ +This directory needs to contain all certificates needed by this cockroachdb node. Those can be generated by the steps +outlined in the README in the root directory, under "Setting up CockroachDB". diff --git a/docker/handshake/Dockerfile b/docker/handshake/Dockerfile index 09525735..39ca14f2 100644 --- a/docker/handshake/Dockerfile +++ b/docker/handshake/Dockerfile @@ -1,8 +1,8 @@ -FROM node:15.8.0-alpine +FROM node:15.12.0-alpine WORKDIR /opt/hsd -RUN apk add --no-cache bash unbound-dev gmp-dev g++ gcc make python2 git +RUN apk update && apk add bash unbound-dev gmp-dev g++ gcc make python2 git RUN git clone https://github.com/handshake-org/hsd.git /opt/hsd RUN npm install --production diff --git a/docker/kratos/config/identity.schema.json b/docker/kratos/config/identity.schema.json new file mode 100644 index 00000000..781fc761 --- /dev/null +++ b/docker/kratos/config/identity.schema.json @@ -0,0 +1,31 @@ +{ + "$id": "https://schemas.ory.sh/presets/kratos/quickstart/email-password/identity.schema.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Person", + "type": "object", + "properties": { + "traits": { + "type": "object", + "properties": { + "email": { + "type": "string", + "format": "email", + "title": "E-Mail", + "minLength": 3, + "ory.sh/kratos": { + "credentials": { + "password": { + "identifier": true + } + }, + "recovery": { + "via": "email" + } + } + } + }, + "required": ["email"], + "additionalProperties": true + } + } +} diff --git a/docker/kratos/config/kratos.yml.sample b/docker/kratos/config/kratos.yml.sample new file mode 100644 index 00000000..15442f0f --- /dev/null +++ b/docker/kratos/config/kratos.yml.sample @@ -0,0 +1,86 @@ +version: v0.5.5-alpha.1 + +dsn: memory + +serve: + public: + base_url: http://127.0.0.1/ + cors: + enabled: true + admin: + base_url: http://127.0.0.1/admin/ + +selfservice: + default_browser_return_url: http://127.0.0.1/ + whitelisted_return_urls: + - http://127.0.0.1/ + + methods: + password: + enabled: true + + flows: + error: + ui_url: http://127.0.0.1/error + + settings: + ui_url: http://127.0.0.1/settings + privileged_session_max_age: 15m + + recovery: + enabled: true + ui_url: http://127.0.0.1/recovery + + verification: + enabled: true + ui_url: http://127.0.0.1/verify + after: + default_browser_return_url: http://127.0.0.1/ + + logout: + after: + default_browser_return_url: http://127.0.0.1/auth/login + + login: + ui_url: http://127.0.0.1/auth/login + lifespan: 10m + + registration: + lifespan: 10m + ui_url: http://127.0.0.1/auth/registration + after: + password: + hooks: + - hook: session + +log: + level: debug + format: text + leak_sensitive_values: true + +password: + max_breaches: 100 + +secrets: + cookie: + - PLEASE-CHANGE-ME-I-AM-VERY-INSECURE + +session: + cookie: + domain: account.siasky.net + lifespan: "720h" + +hashers: + argon2: + parallelism: 1 + memory: 131072 + iterations: 2 + salt_length: 16 + key_length: 16 + +identity: + default_schema_url: file:///etc/config/kratos/identity.schema.json + +courier: + smtp: + connection_uri: smtps://test:test@mailslurper:1025/?skip_ssl_verify=true diff --git a/docker/kratos/config/oidc/identity.traits.schema.json b/docker/kratos/config/oidc/identity.traits.schema.json new file mode 100644 index 00000000..62de3d1b --- /dev/null +++ b/docker/kratos/config/oidc/identity.traits.schema.json @@ -0,0 +1,37 @@ +{ + "$id": "https://schemas.ory.sh/presets/kratos/quickstart/email-password/identity.schema.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Person", + "type": "object", + "properties": { + "traits": { + "type": "object", + "properties": { + "email": { + "type": "string", + "format": "email", + "title": "E-Mail", + "minLength": 3, + "ory.sh/kratos": { + "credentials": { + "password": { + "identifier": true + } + }, + "verification": { + "via": "email" + }, + "recovery": { + "via": "email" + } + } + }, + "website": { + "type": "object" + } + }, + "required": ["website", "email"], + "additionalProperties": false + } + } +} diff --git a/docker/kratos/config/oidc/oidc.github.jsonnet b/docker/kratos/config/oidc/oidc.github.jsonnet new file mode 100644 index 00000000..06b92bf9 --- /dev/null +++ b/docker/kratos/config/oidc/oidc.github.jsonnet @@ -0,0 +1,17 @@ +local claims = { + email_verified: false +} + std.extVar('claims'); + +{ + identity: { + traits: { + // Allowing unverified email addresses enables account + // enumeration attacks, especially if the value is used for + // e.g. verification or as a password login identifier. + // + // Therefore we only return the email if it (a) exists and (b) is marked verified + // by GitHub. + [if "email" in claims && claims.email_verified then "email" else null]: claims.email, + }, + }, +} diff --git a/docker/kratos/cr_certs/README.md b/docker/kratos/cr_certs/README.md new file mode 100644 index 00000000..47c143eb --- /dev/null +++ b/docker/kratos/cr_certs/README.md @@ -0,0 +1,7 @@ +This directory needs to contain all certificates needed by this cockroachdb node. Those can be generated by the steps +outlined in the README in the root directory, under "Setting up CockroachDB". + +The only difference between the files here and those under +`docker/cockroach/certs` is that the files here need to be readable by anyone, while the files under `cockroach` need to +have their original access rights +(all *.key files should be 600 instead of 644 there). diff --git a/docker/kratos/oathkeeper/access-rules.yml b/docker/kratos/oathkeeper/access-rules.yml new file mode 100644 index 00000000..020b6a27 --- /dev/null +++ b/docker/kratos/oathkeeper/access-rules.yml @@ -0,0 +1,116 @@ +- id: "ory:kratos:public" + upstream: + preserve_host: true + url: "http://kratos:4433" + strip_path: /.ory/kratos/public + match: + url: "http://oathkeeper:4455/.ory/kratos/public/<**>" + methods: + - GET + - POST + - PUT + - DELETE + - PATCH + authenticators: + - handler: noop + authorizer: + handler: allow + mutators: + - handler: noop + +- id: "dashboard:anonymous" + upstream: + preserve_host: true + url: "http://dashboard:3000" + match: + url: "http://oathkeeper:4455/<{_next/*,auth/*,recovery,verify,error,favicon.ico}{/,}>" + methods: + - GET + authenticators: + - handler: anonymous + authorizer: + handler: allow + mutators: + - handler: noop + +- id: "dashboard:protected" + upstream: + preserve_host: true + url: "http://dashboard:3000" + match: + url: "http://oathkeeper:4455/<{,api/*,settings,uploads,downloads,payments}>" + methods: + - GET + - POST + - PUT + - DELETE + - PATCH + authenticators: + - handler: cookie_session + authorizer: + handler: allow + mutators: + - handler: id_token + - handler: header + config: + headers: + X-User: "{{ print .Subject }}" + errors: + - handler: redirect + config: + to: http://127.0.0.1/auth/login + +- id: "accounts:anonymous" + upstream: + preserve_host: true + url: "http://accounts:3000" + match: + url: "http://oathkeeper<{,:4455}>/<{stripe/prices,stripe/webhook}>" + methods: + - GET + - POST + authenticators: + - handler: anonymous + authorizer: + handler: allow + mutators: + - handler: noop + +- id: "accounts:public" + upstream: + preserve_host: true + url: "http://accounts:3000" + match: + url: "http://oathkeeper<{,:4455}>/<{user/limits}>" + methods: + - GET + authenticators: + - handler: cookie_session + - handler: noop + authorizer: + handler: allow + mutators: + - handler: id_token + +- id: "accounts:protected" + upstream: + preserve_host: true + url: "http://accounts:3000" + match: + url: "http://oathkeeper<{,:4455}>/<{login,logout,user,user/uploads,user/downloads,user/stats}>" + methods: + - GET + - POST + - PUT + - DELETE + - PATCH + authenticators: + - handler: cookie_session + authorizer: + handler: allow + mutators: + - handler: id_token + errors: + - handler: redirect + config: + to: http://127.0.0.1/auth/login diff --git a/docker/kratos/oathkeeper/oathkeeper.yml b/docker/kratos/oathkeeper/oathkeeper.yml new file mode 100644 index 00000000..6436c2ee --- /dev/null +++ b/docker/kratos/oathkeeper/oathkeeper.yml @@ -0,0 +1,94 @@ +log: + level: debug + format: json + +serve: + proxy: + cors: + enabled: true + allowed_origins: + - "*" + allowed_methods: + - POST + - GET + - PUT + - PATCH + - DELETE + allowed_headers: + - Authorization + - Content-Type + exposed_headers: + - Content-Type + allow_credentials: true + debug: true + +errors: + fallback: + - json + + handlers: + redirect: + enabled: true + config: + to: http://127.0.0.1/auth/login + when: + - error: + - unauthorized + - forbidden + request: + header: + accept: + - text/html + json: + enabled: true + config: + verbose: true + +access_rules: + matching_strategy: glob + repositories: + - file:///etc/config/oathkeeper/access-rules.yml + +authenticators: + anonymous: + enabled: true + config: + subject: guest + + cookie_session: + enabled: true + config: + check_session_url: http://kratos:4433/sessions/whoami + preserve_path: true + extra_from: "@this" + subject_from: "identity.id" + only: + - ory_kratos_session + + noop: + enabled: true + +authorizers: + allow: + enabled: true + +mutators: + noop: + enabled: true + + header: + enabled: true + config: + headers: + X-User: "{{ print .Subject }}" + + id_token: + enabled: true + config: + issuer_url: http://oathkeeper:4455/ + jwks_url: file:///etc/config/oathkeeper/id_token.jwks.json + ttl: 720h + claims: | + { + "session": {{ .Extra | toJson }} + } diff --git a/docker/nginx/Dockerfile b/docker/nginx/Dockerfile index 71e45a70..bba36f7b 100644 --- a/docker/nginx/Dockerfile +++ b/docker/nginx/Dockerfile @@ -1,7 +1,7 @@ FROM openresty/openresty:1.19.3.1-2-bionic # RUN apt-get update -qq && apt-get install cron logrotate -qq -# RUN luarocks install luasocket +RUN luarocks install luasocket # CMD ["sh", "-c", "service cron start;", "/usr/local/openresty/bin/openresty -g daemon off;"] CMD ["/usr/local/openresty/bin/openresty", "-g", "daemon off;"] diff --git a/docker/nginx/Dockerfile.bionic b/docker/nginx/Dockerfile.bionic new file mode 100644 index 00000000..d51e4c8a --- /dev/null +++ b/docker/nginx/Dockerfile.bionic @@ -0,0 +1,185 @@ +# Dockerfile - Ubuntu Bionic +# https://github.com/openresty/docker-openresty + +ARG RESTY_IMAGE_BASE="ubuntu" +ARG RESTY_IMAGE_TAG="bionic" + +FROM ${RESTY_IMAGE_BASE}:${RESTY_IMAGE_TAG} + +LABEL maintainer="Evan Wies " + +# Docker Build Arguments +ARG RESTY_IMAGE_BASE="ubuntu" +ARG RESTY_IMAGE_TAG="bionic" +ARG RESTY_VERSION="1.19.3.1" +ARG RESTY_LUAROCKS_VERSION="3.5.0" +ARG RESTY_OPENSSL_VERSION="1.1.1i" +ARG RESTY_OPENSSL_PATCH_VERSION="1.1.1f" +ARG RESTY_OPENSSL_URL_BASE="https://www.openssl.org/source" +ARG RESTY_PCRE_VERSION="8.44" +ARG RESTY_J="1" +ARG RESTY_CONFIG_OPTIONS="\ + --with-compat \ + --with-file-aio \ + --with-http_addition_module \ + --with-http_auth_request_module \ + --with-http_dav_module \ + --with-http_flv_module \ + --with-http_geoip_module=dynamic \ + --with-http_gunzip_module \ + --with-http_gzip_static_module \ + --with-http_image_filter_module=dynamic \ + --with-http_mp4_module \ + --with-http_random_index_module \ + --with-http_realip_module \ + --with-http_secure_link_module \ + --with-http_slice_module \ + --with-http_ssl_module \ + --with-http_stub_status_module \ + --with-http_sub_module \ + --with-http_v2_module \ + --with-http_xslt_module=dynamic \ + --with-ipv6 \ + --with-mail \ + --with-mail_ssl_module \ + --with-md5-asm \ + --with-pcre-jit \ + --with-sha1-asm \ + --with-stream \ + --with-stream_ssl_module \ + --with-threads \ + " +ARG RESTY_CONFIG_OPTIONS_MORE="" +ARG RESTY_LUAJIT_OPTIONS="--with-luajit-xcflags='-DLUAJIT_NUMMODE=2 -DLUAJIT_ENABLE_LUA52COMPAT'" + +ARG RESTY_ADD_PACKAGE_BUILDDEPS="" +ARG RESTY_ADD_PACKAGE_RUNDEPS="" +ARG RESTY_EVAL_PRE_CONFIGURE="" +ARG RESTY_EVAL_POST_MAKE="" + +# These are not intended to be user-specified +ARG _RESTY_CONFIG_DEPS="--with-pcre \ + --with-cc-opt='-DNGX_LUA_ABORT_AT_PANIC -I/usr/local/openresty/pcre/include -I/usr/local/openresty/openssl/include' \ + --with-ld-opt='-L/usr/local/openresty/pcre/lib -L/usr/local/openresty/openssl/lib -Wl,-rpath,/usr/local/openresty/pcre/lib:/usr/local/openresty/openssl/lib' \ + " + +LABEL resty_image_base="${RESTY_IMAGE_BASE}" +LABEL resty_image_tag="${RESTY_IMAGE_TAG}" +LABEL resty_version="${RESTY_VERSION}" +LABEL resty_luarocks_version="${RESTY_LUAROCKS_VERSION}" +LABEL resty_openssl_version="${RESTY_OPENSSL_VERSION}" +LABEL resty_openssl_patch_version="${RESTY_OPENSSL_PATCH_VERSION}" +LABEL resty_openssl_url_base="${RESTY_OPENSSL_URL_BASE}" +LABEL resty_pcre_version="${RESTY_PCRE_VERSION}" +LABEL resty_config_options="${RESTY_CONFIG_OPTIONS}" +LABEL resty_config_options_more="${RESTY_CONFIG_OPTIONS_MORE}" +LABEL resty_config_deps="${_RESTY_CONFIG_DEPS}" +LABEL resty_add_package_builddeps="${RESTY_ADD_PACKAGE_BUILDDEPS}" +LABEL resty_add_package_rundeps="${RESTY_ADD_PACKAGE_RUNDEPS}" +LABEL resty_eval_pre_configure="${RESTY_EVAL_PRE_CONFIGURE}" +LABEL resty_eval_post_make="${RESTY_EVAL_POST_MAKE}" + + +RUN DEBIAN_FRONTEND=noninteractive apt-get update \ + && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + build-essential \ + ca-certificates \ + curl \ + gettext-base \ + libgd-dev \ + libgeoip-dev \ + libncurses5-dev \ + libperl-dev \ + libreadline-dev \ + libxslt1-dev \ + make \ + perl \ + unzip \ + zlib1g-dev \ + ${RESTY_ADD_PACKAGE_BUILDDEPS} \ + ${RESTY_ADD_PACKAGE_RUNDEPS} \ + && cd /tmp \ + && if [ -n "${RESTY_EVAL_PRE_CONFIGURE}" ]; then eval $(echo ${RESTY_EVAL_PRE_CONFIGURE}); fi \ + && curl -fSL "${RESTY_OPENSSL_URL_BASE}/openssl-${RESTY_OPENSSL_VERSION}.tar.gz" -o openssl-${RESTY_OPENSSL_VERSION}.tar.gz \ + && tar xzf openssl-${RESTY_OPENSSL_VERSION}.tar.gz \ + && cd openssl-${RESTY_OPENSSL_VERSION} \ + && if [ $(echo ${RESTY_OPENSSL_VERSION} | cut -c 1-5) = "1.1.1" ] ; then \ + echo 'patching OpenSSL 1.1.1 for OpenResty' \ + && curl -s https://raw.githubusercontent.com/openresty/openresty/master/patches/openssl-${RESTY_OPENSSL_PATCH_VERSION}-sess_set_get_cb_yield.patch | patch -p1 ; \ + fi \ + && if [ $(echo ${RESTY_OPENSSL_VERSION} | cut -c 1-5) = "1.1.0" ] ; then \ + echo 'patching OpenSSL 1.1.0 for OpenResty' \ + && curl -s https://raw.githubusercontent.com/openresty/openresty/ed328977028c3ec3033bc25873ee360056e247cd/patches/openssl-1.1.0j-parallel_build_fix.patch | patch -p1 \ + && curl -s https://raw.githubusercontent.com/openresty/openresty/master/patches/openssl-${RESTY_OPENSSL_PATCH_VERSION}-sess_set_get_cb_yield.patch | patch -p1 ; \ + fi \ + && ./config \ + no-threads shared zlib -g \ + enable-ssl3 enable-ssl3-method \ + --prefix=/usr/local/openresty/openssl \ + --libdir=lib \ + -Wl,-rpath,/usr/local/openresty/openssl/lib \ + && make -j${RESTY_J} \ + && make -j${RESTY_J} install_sw \ + && cd /tmp \ + && curl -fSL https://ftp.pcre.org/pub/pcre/pcre-${RESTY_PCRE_VERSION}.tar.gz -o pcre-${RESTY_PCRE_VERSION}.tar.gz \ + && tar xzf pcre-${RESTY_PCRE_VERSION}.tar.gz \ + && cd /tmp/pcre-${RESTY_PCRE_VERSION} \ + && ./configure \ + --prefix=/usr/local/openresty/pcre \ + --disable-cpp \ + --enable-jit \ + --enable-utf \ + --enable-unicode-properties \ + && make -j${RESTY_J} \ + && make -j${RESTY_J} install \ + && cd /tmp \ + && curl -fSL https://openresty.org/download/openresty-${RESTY_VERSION}.tar.gz -o openresty-${RESTY_VERSION}.tar.gz \ + && tar xzf openresty-${RESTY_VERSION}.tar.gz \ + && cd /tmp/openresty-${RESTY_VERSION} \ + && eval ./configure -j${RESTY_J} ${_RESTY_CONFIG_DEPS} ${RESTY_CONFIG_OPTIONS} ${RESTY_CONFIG_OPTIONS_MORE} ${RESTY_LUAJIT_OPTIONS} \ + && make -j${RESTY_J} \ + && make -j${RESTY_J} install \ + && cd /tmp \ + && rm -rf \ + openssl-${RESTY_OPENSSL_VERSION}.tar.gz openssl-${RESTY_OPENSSL_VERSION} \ + pcre-${RESTY_PCRE_VERSION}.tar.gz pcre-${RESTY_PCRE_VERSION} \ + openresty-${RESTY_VERSION}.tar.gz openresty-${RESTY_VERSION} \ + && curl -fSL https://luarocks.github.io/luarocks/releases/luarocks-${RESTY_LUAROCKS_VERSION}.tar.gz -o luarocks-${RESTY_LUAROCKS_VERSION}.tar.gz \ + && tar xzf luarocks-${RESTY_LUAROCKS_VERSION}.tar.gz \ + && cd luarocks-${RESTY_LUAROCKS_VERSION} \ + && ./configure \ + --prefix=/usr/local/openresty/luajit \ + --with-lua=/usr/local/openresty/luajit \ + --lua-suffix=jit-2.1.0-beta3 \ + --with-lua-include=/usr/local/openresty/luajit/include/luajit-2.1 \ + && make build \ + && make install \ + && cd /tmp \ + && if [ -n "${RESTY_EVAL_POST_MAKE}" ]; then eval $(echo ${RESTY_EVAL_POST_MAKE}); fi \ + && rm -rf luarocks-${RESTY_LUAROCKS_VERSION} luarocks-${RESTY_LUAROCKS_VERSION}.tar.gz \ + && if [ -n "${RESTY_ADD_PACKAGE_BUILDDEPS}" ]; then DEBIAN_FRONTEND=noninteractive apt-get remove -y --purge ${RESTY_ADD_PACKAGE_BUILDDEPS} ; fi \ + && DEBIAN_FRONTEND=noninteractive apt-get autoremove -y \ + && mkdir -p /var/run/openresty \ + && ln -sf /dev/stdout /usr/local/openresty/nginx/logs/access.log \ + && ln -sf /dev/stderr /usr/local/openresty/nginx/logs/error.log + +# Add additional binaries into PATH for convenience +ENV PATH=$PATH:/usr/local/openresty/luajit/bin:/usr/local/openresty/nginx/sbin:/usr/local/openresty/bin + +# Add LuaRocks paths +# If OpenResty changes, these may need updating: +# /usr/local/openresty/bin/resty -e 'print(package.path)' +# /usr/local/openresty/bin/resty -e 'print(package.cpath)' +ENV LUA_PATH="/usr/local/openresty/site/lualib/?.ljbc;/usr/local/openresty/site/lualib/?/init.ljbc;/usr/local/openresty/lualib/?.ljbc;/usr/local/openresty/lualib/?/init.ljbc;/usr/local/openresty/site/lualib/?.lua;/usr/local/openresty/site/lualib/?/init.lua;/usr/local/openresty/lualib/?.lua;/usr/local/openresty/lualib/?/init.lua;./?.lua;/usr/local/openresty/luajit/share/luajit-2.1.0-beta3/?.lua;/usr/local/share/lua/5.1/?.lua;/usr/local/share/lua/5.1/?/init.lua;/usr/local/openresty/luajit/share/lua/5.1/?.lua;/usr/local/openresty/luajit/share/lua/5.1/?/init.lua" + +ENV LUA_CPATH="/usr/local/openresty/site/lualib/?.so;/usr/local/openresty/lualib/?.so;./?.so;/usr/local/lib/lua/5.1/?.so;/usr/local/openresty/luajit/lib/lua/5.1/?.so;/usr/local/lib/lua/5.1/loadall.so;/usr/local/openresty/luajit/lib/lua/5.1/?.so" + +# Copy nginx configuration files +COPY nginx.conf /usr/local/openresty/nginx/conf/nginx.conf +COPY nginx.vh.default.conf /etc/nginx/conf.d/default.conf + +CMD ["/usr/local/openresty/bin/openresty", "-g", "daemon off;"] + +# Use SIGQUIT instead of default SIGTERM to cleanly drain requests +# See https://github.com/openresty/docker-openresty/blob/master/README.md#tips--pitfalls +STOPSIGNAL SIGQUIT \ No newline at end of file diff --git a/docker/nginx/conf.d/client.conf b/docker/nginx/conf.d/client.conf index ca3fc9ce..fd28971f 100644 --- a/docker/nginx/conf.d/client.conf +++ b/docker/nginx/conf.d/client.conf @@ -24,8 +24,8 @@ limit_conn_zone $binary_remote_addr zone=downloads_by_ip:10m; limit_req_status 429; limit_conn_status 429; -# since we are proxying request to nginx from caddy, access logs will contain caddy's ip address -# as the request address so we need to use real_ip_header module to use ip address from +# since we are proxying request to nginx from caddy, access logs will contain caddy's ip address +# as the request address so we need to use real_ip_header module to use ip address from # X-Forwarded-For header as a real ip address of the request set_real_ip_from 10.0.0.0/8; set_real_ip_from 127.0.0.1/32; @@ -57,6 +57,7 @@ server { rewrite ^/portals /skynet/portals permanent; rewrite ^/stats /skynet/stats permanent; rewrite ^/skynet/blacklist /skynet/blocklist permanent; + rewrite ^/account/(.*) https://account.$domain.$tld/$1 permanent; location / { # This is only safe workaround to reroute based on some conditions @@ -77,7 +78,7 @@ server { include /etc/nginx/conf.d/include/cors; - root /var/www/webportal; + proxy_pass http://webapp:9000; } location /docs { @@ -113,11 +114,11 @@ server { local file_exists = io.open("/data/nginx/skynet/prevstats.lua") if file_exists then file_exists.close() - + -- because response data is chunked, we need to concat ngx.arg[1] until -- last chunk is received (when ngx.arg[2] is set to true) ngx.var.response_body = ngx.var.response_body .. ngx.arg[1] - + if ngx.arg[2] then local json = require('cjson') local prevstats = require('/data/nginx/skynet/prevstats') @@ -153,11 +154,11 @@ server { # variable definititions - we need to define a variable to be able to access it in lua by ngx.var.something set $skylink ''; # placeholder for the raw 46 bit skylink set $rest ''; # placeholder for the rest of the url that gets appended to skylink (path and args) - + # resolve handshake domain by requesting to /hnsres endpoint and assign correct values to $skylink and $rest access_by_lua_block { local json = require('cjson') - + -- match the request_uri and extract the hns domain and anything that is passed in the uri after it -- example: /hns/something/foo/bar?baz=1 matches: -- > hns_domain_name: something @@ -222,9 +223,6 @@ server { end } - # overwrite the Cache-Control header to only cache for 60s in case the domain gets updated - more_set_headers 'Cache-Control: public, max-age=60'; - # we proxy to another nginx location rather than directly to siad because we don't want to deal with caching here proxy_pass http://127.0.0.1/$skylink$rest; @@ -255,7 +253,7 @@ server { # and we are using it currently for caching registry resolutions from /hns calls location /skynet/registry/cached { internal; # internal endpoint only - access_log off; # do not log traffic + access_log off; # do not log traffic proxy_cache skynet; proxy_cache_key publickey=$arg_publickey&datakey=$arg_datakey; # cache based on publickey and datakey @@ -276,6 +274,40 @@ server { proxy_set_header User-Agent: Sia-Agent; proxy_read_timeout 600; # siad should timeout with 404 after 5 minutes proxy_pass http://siad/skynet/registry; + + access_by_lua_block { + -- this block runs only when accounts are enabled + if os.getenv("ACCOUNTS_ENABLED", "0") == "0" then return end + + local res = ngx.location.capture("/accounts/user/limits", { copy_all_vars = true }) + if res.status == ngx.HTTP_OK then + local json = require('cjson') + local limits = json.decode(res.body) + if limits.registry > 0 then + ngx.sleep(limits.registry / 1000) + end + end + } + + # register the registry access in accounts service (cookies should contain jwt) + log_by_lua_block { + -- this block runs only when accounts are enabled + if os.getenv("ACCOUNTS_ENABLED", "0") == "0" then return end + + if ngx.status == ngx.HTTP_OK or ngx.status == ngx.HTTP_NOT_FOUND then + local http = require("socket.http") + local headers = { Cookie = ngx.req.get_headers()["Cookie"] } + local method = ngx.req.get_method() == ngx.HTTP_GET and "read" or "write" + local ok, statusCode, headers, statusText = http.request { + url = "http://accounts:3000/track/registry/" .. method, + method = "POST", + headers = headers + } + if statusCode ~= ngx.HTTP_NO_CONTENT and statusCode ~= ngx.HTTP_UNAUTHORIZED then + ngx.log(ngx.ERR, "accounts endpoint /track/registry/" .. method .. " failed with error " .. statusCode) + end + end + } } location /skynet/skyfile { @@ -306,8 +338,37 @@ server { set $dir3 $3; } + # access_by_lua_block { + # -- this block runs only when accounts are enabled + # if os.getenv("ACCOUNTS_ENABLED", "0") == "0" then return end + + # ngx.var.upload_limit_rate = 5 * 1024 * 1024 + # local res = ngx.location.capture("/accounts/user", { copy_all_vars = true }) + # if res.status == ngx.HTTP_OK then + # local json = require('cjson') + # local user = json.decode(res.body) + # ngx.var.upload_limit_rate = ngx.var.upload_limit_rate * (user.tier + 1) + # end + # } + # proxy this call to siad endpoint (make sure the ip is correct) proxy_pass http://siad/skynet/skyfile/$dir1/$dir2/$dir3$is_args$args; + + # register the upload in accounts service (cookies should contain jwt) + log_by_lua_block { + -- this block runs only when accounts are enabled + if os.getenv("ACCOUNTS_ENABLED", "0") == "0" then return end + + local skylink = ngx.header["Skynet-Skylink"] + if skylink and ngx.status >= ngx.HTTP_OK and ngx.status < ngx.HTTP_SPECIAL_RESPONSE then + local http = require("socket.http") + local headers = { Cookie = ngx.req.get_headers()["Cookie"] } + local ok, statusCode, headers, statusText = http.request { url = "http://accounts:3000/track/upload/" .. skylink, method = "POST", headers = headers } + if statusCode ~= ngx.HTTP_NO_CONTENT and statusCode ~= ngx.HTTP_UNAUTHORIZED then + ngx.log(ngx.ERR, "accounts endpoint /track/upload/" .. skylink .. " failed with error " .. statusCode) + end + end + } } location ~ "^/(([a-zA-Z0-9-_]{46}|[a-z0-9]{55})(/.*)?)$" { @@ -322,12 +383,44 @@ server { } limit_conn downloads_by_ip 100; # ddos protection: max 100 downloads at a time - add_header Cache-Control "public, max-age=86400"; # allow consumer to cache response # we need to explicitly use set directive here because $1 will contain the skylink with # decoded whitespaces and set will re-encode it for us before passing it to proxy_pass set $skylink $1; + access_by_lua_block { + -- this block runs only when accounts are enabled + if os.getenv("ACCOUNTS_ENABLED", "0") == "0" then return end + + local res = ngx.location.capture("/accounts/user/limits", { copy_all_vars = true }) + if res.status == ngx.HTTP_OK then + local json = require('cjson') + local limits = json.decode(res.body) + ngx.var.limit_rate = limits.download + end + } + + # register the download in accounts service (cookies should contain jwt) + log_by_lua_block { + -- this block runs only when accounts are enabled + if os.getenv("ACCOUNTS_ENABLED", "0") == "0" then return end + + local skylink = ngx.header["Skynet-Skylink"] + if skylink and ngx.status >= ngx.HTTP_OK and ngx.status < ngx.HTTP_SPECIAL_RESPONSE then + local http = require("socket.http") + local headers = { Cookie = ngx.req.get_headers()["Cookie"] } + local query = table.concat({ "status=" .. ngx.status, "bytes=" .. ngx.var.body_bytes_sent }, "&") + local ok, statusCode, headers, statusText = http.request { + url = "http://accounts:3000/track/download/" .. skylink .. "?" .. query, + method = "POST", + headers = headers + } + if statusCode ~= ngx.HTTP_NO_CONTENT and statusCode ~= ngx.HTTP_UNAUTHORIZED then + ngx.log(ngx.ERR, "accounts endpoint /track/download/" .. skylink .. " failed with error " .. statusCode) + end + end + } + proxy_read_timeout 600; proxy_set_header User-Agent: Sia-Agent; # proxy this call to siad /skynet/skylink/ endpoint (make sure the ip is correct) @@ -365,6 +458,14 @@ server { proxy_pass http://127.0.0.1/$uri?attachment=true&$args; } + location /accounts { + internal; # internal endpoint only + access_log off; # do not log traffic + + rewrite /accounts(.*) $1 break; # drop the /accounts prefix from uri + proxy_pass http://accounts:3000; + } + # include custom locations, specific to the server include /etc/nginx/conf.d/server-override/*; } diff --git a/docker/nginx/nginx.conf b/docker/nginx/nginx.conf index 3a5b885e..4fcea569 100644 --- a/docker/nginx/nginx.conf +++ b/docker/nginx/nginx.conf @@ -26,6 +26,7 @@ worker_processes 1; #pid logs/nginx.pid; env SKYNET_PORTAL_API; # declare env variable to use it in config +env ACCOUNTS_ENABLED; # declare env variable to use it in config events { worker_connections 1024; @@ -67,4 +68,5 @@ http { header_filter_by_lua 'ngx.header["Skynet-Portal-Api"] = os.getenv("SKYNET_PORTAL_API")'; include /etc/nginx/conf.d/*.conf; + include /etc/nginx/conf.extra.d/*.conf; } diff --git a/docker/nginx/nginx.vh.default.conf b/docker/nginx/nginx.vh.default.conf new file mode 100644 index 00000000..d4aa8d5a --- /dev/null +++ b/docker/nginx/nginx.vh.default.conf @@ -0,0 +1,58 @@ +# nginx.vh.default.conf -- docker-openresty +# +# This file is installed to: +# `/etc/nginx/conf.d/default.conf` +# +# It tracks the `server` section of the upstream OpenResty's `nginx.conf`. +# +# This config (and any other configs in `etc/nginx/conf.d/`) is loaded by +# default by the `include` directive in `/usr/local/openresty/nginx/conf/nginx.conf`. +# +# See https://github.com/openresty/docker-openresty/blob/master/README.md#nginx-config-files +# + + +server { + listen 80; + server_name localhost; + + #charset koi8-r; + #access_log /var/log/nginx/host.access.log main; + + location / { + root /usr/local/openresty/nginx/html; + index index.html index.htm; + } + + #error_page 404 /404.html; + + # redirect server error pages to the static page /50x.html + # + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root /usr/local/openresty/nginx/html; + } + + # proxy the PHP scripts to Apache listening on 127.0.0.1:80 + # + #location ~ \.php$ { + # proxy_pass http://127.0.0.1; + #} + + # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 + # + #location ~ \.php$ { + # root /usr/local/openresty/nginx/html; + # fastcgi_pass 127.0.0.1:9000; + # fastcgi_index index.php; + # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; + # include fastcgi_params; + #} + + # deny access to .htaccess files, if Apache's document root + # concurs with nginx's one + # + #location ~ /\.ht { + # deny all; + #} +} \ No newline at end of file diff --git a/package.json b/package.json index 06108e34..71155372 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,10 @@ "packages/*" ], "dependencies": { - "sharp": "^0.27.2" + "@tailwindcss/forms": "^0.2.1", + "autoprefixer": "^10.2.4", + "postcss": "^8.2.6", + "sharp": "^0.27.2", + "tailwindcss": "^2.0.4" } } diff --git a/packages/dashboard/.env b/packages/dashboard/.env new file mode 100644 index 00000000..bb640cd8 --- /dev/null +++ b/packages/dashboard/.env @@ -0,0 +1,4 @@ +NEXT_PUBLIC_SKYNET_PORTAL_API=https://siasky.net +NEXT_PUBLIC_SKYNET_DASHBOARD_URL=https://account.siasky.net +NEXT_PUBLIC_KRATOS_BROWSER_URL=https://account.siasky.net/.ory/kratos/public +NEXT_PUBLIC_KRATOS_PUBLIC_URL=https://account.siasky.net/.ory/kratos/public diff --git a/packages/dashboard/.gitignore b/packages/dashboard/.gitignore new file mode 100644 index 00000000..ea47d16a --- /dev/null +++ b/packages/dashboard/.gitignore @@ -0,0 +1,38 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# env defaults +!.env + +# local env files +.env.local +.env.development.local +.env.test.local +.env.production.local + +# vercel +.vercel +.next diff --git a/packages/dashboard/.prettierignore b/packages/dashboard/.prettierignore new file mode 100644 index 00000000..571a2ec1 --- /dev/null +++ b/packages/dashboard/.prettierignore @@ -0,0 +1,3 @@ +.next +package.json +package-lock.json diff --git a/packages/dashboard/.prettierrc b/packages/dashboard/.prettierrc new file mode 100644 index 00000000..963354f2 --- /dev/null +++ b/packages/dashboard/.prettierrc @@ -0,0 +1,3 @@ +{ + "printWidth": 120 +} diff --git a/packages/dashboard/Dockerfile b/packages/dashboard/Dockerfile new file mode 100644 index 00000000..d5dd31eb --- /dev/null +++ b/packages/dashboard/Dockerfile @@ -0,0 +1,16 @@ +FROM node:15.12.0-alpine + +WORKDIR /usr/app + +COPY package.json . + +ENV NEXT_TELEMETRY_DISABLED 1 +RUN yarn --no-lockfile + +COPY public ./public +COPY src ./src +COPY styles ./styles +COPY postcss.config.js . +COPY tailwind.config.js . + +CMD ["sh", "-c", "env | grep -E 'NEXT_PUBLIC|KRATOS|STRIPE' > .env.local && yarn build && yarn start"] diff --git a/packages/dashboard/README.md b/packages/dashboard/README.md new file mode 100644 index 00000000..4b412a3c --- /dev/null +++ b/packages/dashboard/README.md @@ -0,0 +1,34 @@ +This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). + +## Getting Started + +First, run the development server: + +```bash +npm run dev +# or +yarn dev +``` + +Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. + +You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file. + +[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.js`. + +The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages. + +## Learn More + +To learn more about Next.js, take a look at the following resources: + +- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. +- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. + +You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! + +## Deploy on Vercel + +The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/import?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. + +Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. diff --git a/packages/dashboard/package.json b/packages/dashboard/package.json new file mode 100644 index 00000000..38f0fd0e --- /dev/null +++ b/packages/dashboard/package.json @@ -0,0 +1,43 @@ +{ + "name": "dashboard", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start" + }, + "dependencies": { + "@fontsource/metropolis": "^4.1.0", + "@ory/kratos-client": "^0.5.4-alpha.1", + "@stripe/react-stripe-js": "^1.4.0", + "@stripe/stripe-js": "^1.13.0", + "@tailwindcss/forms": "^0.2.1", + "autoprefixer": "^10.2.5", + "classnames": "^2.2.6", + "clipboardy": "^2.3.0", + "dayjs": "^1.10.4", + "express-jwt": "^6.0.0", + "fast-levenshtein": "^3.0.0", + "formik": "^2.2.6", + "http-status-codes": "^2.1.4", + "jwks-rsa": "^1.12.2", + "ky": "0.25.1", + "next": "^10.0.8", + "postcss": "^8.2.8", + "prettier": "^2.2.1", + "pretty-bytes": "^5.5.0", + "react": "17.0.1", + "react-dom": "17.0.1", + "skynet-js": "^3.0.0", + "square": "^9.0.0", + "stripe": "^8.137.0", + "superagent": "^6.1.0", + "swr": "^0.5.0", + "tailwindcss": "^2.0.3", + "yup": "^0.32.9" + }, + "devDependencies": { + "@tailwindcss/forms": "^0.2.1" + } +} diff --git a/packages/dashboard/postcss.config.js b/packages/dashboard/postcss.config.js new file mode 100644 index 00000000..12a703d9 --- /dev/null +++ b/packages/dashboard/postcss.config.js @@ -0,0 +1,6 @@ +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; diff --git a/packages/dashboard/public/favicon.ico b/packages/dashboard/public/favicon.ico new file mode 100644 index 00000000..9229fbf7 Binary files /dev/null and b/packages/dashboard/public/favicon.ico differ diff --git a/packages/dashboard/src/components/Form/Message.js b/packages/dashboard/src/components/Form/Message.js new file mode 100644 index 00000000..e8ebb7e8 --- /dev/null +++ b/packages/dashboard/src/components/Form/Message.js @@ -0,0 +1,62 @@ +const types = { + error: { + backgroundColor: "bg-red-50", + titleColor: "text-red-800", + detailsColor: "text-red-700", + iconColor: "text-red-400", + icon: ( + + ), + }, + info: { + backgroundColor: "bg-blue-50", + titleColor: "text-blue-800", + detailsColor: "text-blue-700", + iconColor: "text-blue-400", + icon: ( + + ), + }, +}; + +export default function Message({ type = "info", title, items = [] }) { + const { backgroundColor, titleColor, detailsColor, iconColor, icon } = types[type]; + + return ( +
+
+
+ +
+
+ {title &&

{title}

} + {items.length > 0 && ( +
+
    1 ? "list-disc pl-5 space-y-1" : ""}`}> + {items.map((item, index) => ( +
  • {item}
  • + ))} +
+
+ )} +
+
+
+ ); +} diff --git a/packages/dashboard/src/components/Form/SelfServiceForm.js b/packages/dashboard/src/components/Form/SelfServiceForm.js new file mode 100644 index 00000000..e00f27ac --- /dev/null +++ b/packages/dashboard/src/components/Form/SelfServiceForm.js @@ -0,0 +1,104 @@ +import { useFormik, getIn, setIn } from "formik"; +import classnames from "classnames"; +import SelfServiceMessages from "./SelfServiceMessages"; + +export default function SelfServiceForm({ flow, config, fieldsConfig, title, button = "Submit" }) { + const fields = config.fields + .map((field) => ({ ...field, ...fieldsConfig[field.name] })) + .sort((a, b) => (a.position < b.position ? -1 : 1)); + const formik = useFormik({ + initialValues: fields.reduce((acc, field) => setIn(acc, field.name, field.value ?? ""), {}), + }); + + return ( +
+ {title &&

{title}

} +
+
+ {fields.map((field) => ( +
+ +
+ + + + + {field.checks && ( +
+
    + {field.checks.map((check, index) => ( +
  • +
    + + + + + +
    +
    +

    {check.label}

    +
    +
    +
    +
  • + ))} +
+
+ )} +
+
+ ))} + + + + + + {flow && } + +
+
+ ); +} diff --git a/packages/dashboard/src/components/Form/SelfServiceMessages.js b/packages/dashboard/src/components/Form/SelfServiceMessages.js new file mode 100644 index 00000000..9395e227 --- /dev/null +++ b/packages/dashboard/src/components/Form/SelfServiceMessages.js @@ -0,0 +1,45 @@ +import classnames from "classnames"; + +// const types = { +// error: { +// backgroundColor: "bg-red-50", +// titleColor: "text-red-800", +// detailsColor: "text-red-700", +// iconColor: "text-red-400", +// icon: ( +// +// ), +// }, +// info: { +// backgroundColor: "bg-blue-50", +// titleColor: "text-blue-800", +// detailsColor: "text-blue-700", +// iconColor: "text-blue-400", +// icon: ( +// +// ), +// }, +// }; + +export default function SelfServiceMessages({ messages = [] }) { + if (!messages) return null; // make sure we don't throw on invalid data + + return messages.map(({ text, type }) => ( +

+ {text} +

+ )); +} diff --git a/packages/dashboard/src/components/Layout.js b/packages/dashboard/src/components/Layout.js new file mode 100644 index 00000000..1d7fe6c2 --- /dev/null +++ b/packages/dashboard/src/components/Layout.js @@ -0,0 +1,327 @@ +import Link from "next/link"; +import { useRouter } from "next/router"; +import Head from "next/head"; +import ky from "ky/umd"; +import { useState } from "react"; +import config from "../../src/config"; + +export default function Layout({ title, children }) { + const [menuOpen, openMenu] = useState(false); + const [avatarDropdownOpen, openAvatarDropdown] = useState(false); + const router = useRouter(); + const handleSignOut = async (e) => { + e.preventDefault(); + + try { + await ky.post("/logout"); + + window.location = `${config.kratos.browser}/self-service/browser/flows/logout`; + } catch (error) { + console.log(error); // todo: handle errors with a message + } + }; + + return ( +
+ + Skynet - {title} + +
+ +
+
+

{title}

+
+
+
+ +
+
+ {children || ( +
+
+
+ )} +
+
+ +
+

© 2021 Skynet Labs Inc. All rights reserved.

+
+
+ ); +} diff --git a/packages/dashboard/src/components/Table.js b/packages/dashboard/src/components/Table.js new file mode 100644 index 00000000..e3ae6d5e --- /dev/null +++ b/packages/dashboard/src/components/Table.js @@ -0,0 +1,128 @@ +import { useEffect } from "react"; +import classnames from "classnames"; + +function Button({ children, disabled, className, ...props }) { + return ( + + ); +} + +export default function Table({ items, count, headers, actions, offset, setOffset, pageSize = 10 }) { + useEffect(() => { + if (offset < 0) setOffset(0); + else if (offset >= count && count > 0) setOffset(Math.floor(count / pageSize - 1) * pageSize); + else if (offset % pageSize) setOffset(offset - (offset % pageSize)); + }, [offset, pageSize, setOffset]); + + return ( +
+
+
+
+ + + + {headers.map(({ key, name }) => ( + + ))} + {actions.map(({ key, name }) => ( + + ))} + + + + {items && items.length ? ( + items.map((row, index) => ( + + {headers.map(({ key, formatter, href, nowrap = true }) => ( + + ))} + {actions.map(({ key, name, action }) => ( + + ))} + + )) + ) : ( + + + + )} + +
+ {name} + + {name} +
+ {(formatter ? ( + formatter(row, key) + ) : href ? ( + + {row[key]} + + ) : ( + row[key] + )) || <>—} + + + {name} + +
+ no entries +
+ {/* This example requires Tailwind CSS v2.0+ */} + +
+
+
+
+ ); +} diff --git a/packages/dashboard/src/config.js b/packages/dashboard/src/config.js new file mode 100644 index 00000000..326ec4e9 --- /dev/null +++ b/packages/dashboard/src/config.js @@ -0,0 +1,14 @@ +export default { + // https://github.com/ory/kratos-selfservice-ui-node#configuration + kratos: { + // The URL where ORY Kratos's Public API is located at. If this app and ORY Kratos are running in the same + // private network, this should be the private network address (e.g. kratos-public.svc.cluster.local) + public: process.env.NEXT_PUBLIC_KRATOS_PUBLIC_URL.replace(/\/+$/, ""), + // The URL where ORY Kratos's public API is located, when accessible from the public internet via ORY Oathkeeper. + // This could be for example http://kratos.my-app.com/. + browser: process.env.NEXT_PUBLIC_KRATOS_BROWSER_URL.replace(/\/+$/, ""), + }, + tiers: { + starter: { id: "starter", tier: 1, name: "Free", description: "Pin up to 100GB" }, + }, +}; diff --git a/packages/dashboard/src/pages/_app.js b/packages/dashboard/src/pages/_app.js new file mode 100644 index 00000000..5be206d2 --- /dev/null +++ b/packages/dashboard/src/pages/_app.js @@ -0,0 +1,21 @@ +import { Elements } from "@stripe/react-stripe-js"; +import { loadStripe } from "@stripe/stripe-js"; +import Head from "next/head"; +import "tailwindcss/tailwind.css"; +import "@fontsource/metropolis/all.css"; + +const stripePromise = loadStripe(process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY); + +function MyApp({ Component, pageProps }) { + return ( + + + + Skynet + + + + ); +} + +export default MyApp; diff --git a/packages/dashboard/src/pages/api/accounts/login.js b/packages/dashboard/src/pages/api/accounts/login.js new file mode 100644 index 00000000..4890d52b --- /dev/null +++ b/packages/dashboard/src/pages/api/accounts/login.js @@ -0,0 +1,19 @@ +import superagent from "superagent"; + +export default async (req, res) => { + if (req.cookies.ory_kratos_session) { + try { + const { header } = await superagent + .post("http://oathkeeper:4455/login") + .set("cookie", `ory_kratos_session=${req.cookies.ory_kratos_session}`); + + res.setHeader("Set-Cookie", header["set-cookie"]); + res.redirect(req.query.return_to ?? "/"); + } catch (error) { + // credentials were correct but accounts service failed + res.redirect("/.ory/kratos/public/self-service/browser/flows/logout"); + } + } else { + res.redirect("/auth/login"); // redirect to login page if kratos session is missing + } +}; diff --git a/packages/dashboard/src/pages/api/square/cards.js b/packages/dashboard/src/pages/api/square/cards.js new file mode 100644 index 00000000..603da8f4 --- /dev/null +++ b/packages/dashboard/src/pages/api/square/cards.js @@ -0,0 +1,58 @@ +import { Client, Environment } from "square"; +import { StatusCodes } from "http-status-codes"; + +const client = new Client({ + environment: Environment.Sandbox, + accessToken: process.env.SQUARE_ACCESS_TOKEN, +}); + +const api = { + GET: async (req, res) => { + const user = "R7R0NY1Z8WT11D43564EEFKTYR"; // req.headers["x-user"]; + + try { + const { result: customerResult } = await client.customersApi.retrieveCustomer(user); + const { customer } = customerResult; + + res.json(customer.cards); + } catch (error) { + res.json([]); + } + }, + // POST: async (req, res) => { + // const user = req.headers["x-user"]; + // const card = { + // cardNonce: "YOUR_CARD_NONCE", + // cardholderName: "Amelia Earhart", + // billingAddress: {}, + // verificationToken: "verification_token0", + // }; + + // card.bodyBillingAddress.addressLine1 = "500 Electric Ave"; + // card.bodyBillingAddress.addressLine2 = "Suite 600"; + // card.bodyBillingAddress.addressLine3 = "address_line_38"; + // card.bodyBillingAddress.locality = "New York"; + // card.bodyBillingAddress.sublocality = "sublocality2"; + // card.bodyBillingAddress.administrativeDistrictLevel1 = "NY"; + // card.bodyBillingAddress.postalCode = "10003"; + // card.bodyBillingAddress.country = "US"; + + // try { + // const { result } = await client.customersApi.createCustomerCard(user, card); + + // res.status(StatusCodes.NO_CONTENT); + // } catch (error) { + // console.log(Object.keys(error)); + + // res.status(StatusCodes.BAD_REQUEST); + // } + // }, +}; + +export default (req, res) => { + if (req.method in api) { + api[req.method](req, res); + } else { + res.status(StatusCodes.NOT_FOUND); + } +}; diff --git a/packages/dashboard/src/pages/api/square/invoices.js b/packages/dashboard/src/pages/api/square/invoices.js new file mode 100644 index 00000000..1ad8471a --- /dev/null +++ b/packages/dashboard/src/pages/api/square/invoices.js @@ -0,0 +1,45 @@ +import { Client, Environment } from "square"; +import { StatusCodes } from "http-status-codes"; + +const client = new Client({ + environment: Environment.Sandbox, + accessToken: process.env.SQUARE_ACCESS_TOKEN, +}); + +const api = { + GET: async (req, res) => { + const user = "NBE7TRXZPGZXNBD64JB6DR5AGR"; // req.headers["x-user"]; + + try { + // get locations for invoices search query + const { result: locationsResponse } = await client.locationsApi.listLocations(); + const { locations } = locationsResponse; + + // create invoices serach query + const locationIds = locations.map(({ id }) => id); + const customerIds = [user]; + const filter = { locationIds, customerIds }; + const sort = { field: "INVOICE_SORT_DATE", order: "DESC" }; + const query = { filter, sort }; + + // query invoices with given search criteria + const { result: invoicesResponse } = await client.invoicesApi.searchInvoices({ query, limit: 10 }); + const { invoices } = invoicesResponse; + + res.json(invoices); + } catch (error) { + console.log(error); + console.log(error?.errors); + + res.json([]); // todo: error handling + } + }, +}; + +export default (req, res) => { + if (req.method in api) { + return api[req.method](req, res); + } + + return res.status(StatusCodes.NOT_FOUND); +}; diff --git a/packages/dashboard/src/pages/api/square/subscription.js b/packages/dashboard/src/pages/api/square/subscription.js new file mode 100644 index 00000000..5ece9e68 --- /dev/null +++ b/packages/dashboard/src/pages/api/square/subscription.js @@ -0,0 +1,46 @@ +import { Client, Environment } from "square"; +import { StatusCodes } from "http-status-codes"; + +const client = new Client({ + environment: Environment.Sandbox, + accessToken: process.env.SQUARE_ACCESS_TOKEN, +}); + +const api = { + GET: async (req, res) => { + try { + const user = "NBE7TRXZPGZXNBD64JB6DR5AGR"; // req.headers["x-user"]; + + // create subscriptions search query + const query = { filter: { customerIds: [user] } }; + + // query subscriptions with given search criteria + const { result: subscriptionsResponse } = await client.subscriptionsApi.searchSubscriptions({ query }); + const { subscriptions } = subscriptionsResponse; + + // get active subscription + const subscription = subscriptions.find(({ status }) => status === "ACTIVE"); + + if (!subscription) { + return res.status(StatusCodes.NO_CONTENT).end(); // no active subscription found + } + + console.log("....", subscription); + + return res.json(subscription); + } catch (error) { + console.log(error); + console.log(error?.errors); + + return res.status(StatusCodes.BAD_REQUEST).end(); // todo: error handling + } + }, +}; + +export default (req, res) => { + if (req.method in api) { + return api[req.method](req, res); + } + + return res.status(StatusCodes.NOT_FOUND).end(); +}; diff --git a/packages/dashboard/src/pages/api/square/subscription/cancel.js b/packages/dashboard/src/pages/api/square/subscription/cancel.js new file mode 100644 index 00000000..9b2f017c --- /dev/null +++ b/packages/dashboard/src/pages/api/square/subscription/cancel.js @@ -0,0 +1,55 @@ +import { Client, Environment } from "square"; +import { StatusCodes } from "http-status-codes"; + +const client = new Client({ + environment: Environment.Sandbox, + accessToken: process.env.SQUARE_ACCESS_TOKEN, +}); + +const cancelSubscription = async (id) => { + const { result: subscriptionsResponse } = await client.subscriptionsApi.cancelSubscription(id); + const { subscription } = subscriptionsResponse; + + return subscription; +}; + +const getActiveSubscription = async (customerId) => { + // create subscriptions search query + const query = { filter: { customerIds: [customerId] } }; + + // query subscriptions with given search criteria + const { result: subscriptionsResponse } = await client.subscriptionsApi.searchSubscriptions({ query }); + const { subscriptions } = subscriptionsResponse; + + // get active subscription with a set cancellation date + return subscriptions.find(({ status, canceledDate }) => status === "ACTIVE" && !canceledDate); +}; + +const api = { + POST: async (req, res) => { + try { + const user = "NBE7TRXZPGZXNBD64JB6DR5AGR"; // req.headers["x-user"]; + const subscription = await getActiveSubscription(user); + + if (!subscription) { + return res.status(StatusCodes.BAD_REQUEST).end(); // no active subscription found + } + + const canceledSubscription = await cancelSubscription(subscription.id); + + return res.json(canceledSubscription); + } catch (error) { + console.log(error.errors); + + return res.status(StatusCodes.BAD_REQUEST).end(); // todo: error handling + } + }, +}; + +export default (req, res) => { + if (req.method in api) { + return api[req.method](req, res); + } + + return res.status(StatusCodes.NOT_FOUND).end(); +}; diff --git a/packages/dashboard/src/pages/api/square/subscription/restore.js b/packages/dashboard/src/pages/api/square/subscription/restore.js new file mode 100644 index 00000000..8cac9dfc --- /dev/null +++ b/packages/dashboard/src/pages/api/square/subscription/restore.js @@ -0,0 +1,58 @@ +import { Client, Environment } from "square"; +import { StatusCodes } from "http-status-codes"; + +const client = new Client({ + environment: Environment.Sandbox, + accessToken: process.env.SQUARE_ACCESS_TOKEN, +}); + +const updateSubscription = async (id, body) => { + const { result: subscriptionsResponse } = await client.subscriptionsApi.updateSubscription(id, body); + const { subscription } = subscriptionsResponse; + + return subscription; +}; + +const getActiveCanceledSubscription = async (customerId) => { + // create subscriptions search query + const query = { filter: { customerIds: [customerId] } }; + + // query subscriptions with given search criteria + const { result: subscriptionsResponse } = await client.subscriptionsApi.searchSubscriptions({ query }); + const { subscriptions } = subscriptionsResponse; + + // get active subscription with a set cancellation date + return subscriptions.find(({ status, canceledDate }) => status === "ACTIVE" && canceledDate); +}; + +const api = { + POST: async (req, res) => { + try { + const user = "NBE7TRXZPGZXNBD64JB6DR5AGR"; // req.headers["x-user"]; + const subscription = await getActiveCanceledSubscription(user); + + if (!subscription) { + return res.status(StatusCodes.BAD_REQUEST).end(); // no active subscription with cancel date found + } + + // update the subscription setting empty canceledDate + const updatedSubscription = await updateSubscription(subscription.id, { + subscription: { ...subscription, canceledDate: "" }, + }); + + return res.json(updatedSubscription); + } catch (error) { + console.log(error.errors); + + return res.status(StatusCodes.BAD_REQUEST).end(); // todo: error handling + } + }, +}; + +export default (req, res) => { + if (req.method in api) { + return api[req.method](req, res); + } + + return res.status(StatusCodes.NOT_FOUND).end(); +}; diff --git a/packages/dashboard/src/pages/api/stripe/billing.js b/packages/dashboard/src/pages/api/stripe/billing.js new file mode 100644 index 00000000..0c855ec4 --- /dev/null +++ b/packages/dashboard/src/pages/api/stripe/billing.js @@ -0,0 +1,28 @@ +import ky from "ky/umd"; +import Stripe from "stripe"; +import { StatusCodes } from "http-status-codes"; + +const stripe = new Stripe(process.env.STRIPE_SECRET_KEY); + +const getStripeCustomer = (stripeCustomerId = null) => { + if (stripeCustomerId) { + return stripe.customers.retrieve(stripeCustomerId); + } + return stripe.customers.create(); +}; + +export default async (req, res) => { + try { + const authorization = req.headers.authorization; // authorization header from request + const { stripeCustomerId } = await ky("http://accounts:3000/user", { headers: { authorization } }).json(); + const customer = await getStripeCustomer(stripeCustomerId); + const session = await stripe.billingPortal.sessions.create({ + customer: customer.id, + return_url: `${process.env.SKYNET_DASHBOARD_URL}/payments`, + }); + + res.redirect(session.url); + } catch ({ message }) { + res.status(StatusCodes.BAD_REQUEST).json({ error: { message } }); + } +}; diff --git a/packages/dashboard/src/pages/api/stripe/checkout.js b/packages/dashboard/src/pages/api/stripe/checkout.js new file mode 100644 index 00000000..4ddf17a9 --- /dev/null +++ b/packages/dashboard/src/pages/api/stripe/checkout.js @@ -0,0 +1,59 @@ +import ky from "ky/umd"; +import Stripe from "stripe"; +import { StatusCodes } from "http-status-codes"; +import { isPaidTier } from "../../../services/tiers"; + +const stripe = new Stripe(process.env.STRIPE_SECRET_KEY); + +const getStripeCustomer = async (user, authorization) => { + if (user.stripeCustomerId) { + return stripe.customers.retrieve(user.stripeCustomerId); + } + + const customer = await stripe.customers.create(); + + // update user instance and include the customer id once created + await ky.put(`http://accounts:3000/user`, { headers: { authorization }, json: { stripeCustomerId: customer.id } }); + + return customer; +}; + +export default async (req, res) => { + if (req.method !== "POST") { + return res.status(StatusCodes.NOT_FOUND).end(); + } + + const { price } = req.body; + + if (!price) { + return res.status(StatusCodes.BAD_REQUEST).json({ error: { message: "Missing 'price' attribute" } }); + } + + try { + const authorization = req.headers.authorization; // authorization header from request + const user = await ky("http://accounts:3000/user", { headers: { authorization } }).json(); + + if (isPaidTier(user.tier)) { + const message = `Customer can have only one active subscription at a time, use Stripe Customer Portal to manage active subscription`; + + return res.status(StatusCodes.BAD_REQUEST).json({ error: { message } }); + } + + const customer = await getStripeCustomer(user, authorization); + const session = await stripe.checkout.sessions.create({ + mode: "subscription", + payment_method_types: ["card"], + line_items: [{ price, quantity: 1 }], + customer: customer.id, + client_reference_id: user.sub, + allow_promotion_codes: true, + success_url: `${process.env.SKYNET_DASHBOARD_URL}/payments?session_id={CHECKOUT_SESSION_ID}`, + cancel_url: `${process.env.SKYNET_DASHBOARD_URL}/payments`, + }); + + res.json({ sessionId: session.id }); + } catch (error) { + console.log(error); + res.status(StatusCodes.BAD_REQUEST).json({ error: { message: error.message } }); + } +}; diff --git a/packages/dashboard/src/pages/api/stripe/subscription.js b/packages/dashboard/src/pages/api/stripe/subscription.js new file mode 100644 index 00000000..3526d5ac --- /dev/null +++ b/packages/dashboard/src/pages/api/stripe/subscription.js @@ -0,0 +1,23 @@ +import ky from "ky/umd"; +import Stripe from "stripe"; +import { StatusCodes } from "http-status-codes"; + +const stripe = new Stripe(process.env.STRIPE_SECRET_KEY); + +export default async (req, res) => { + try { + const authorization = req.headers.authorization; // authorization header from request + const { stripeCustomerId } = await ky("http://accounts:3000/user", { headers: { authorization } }).json(); + const stripeCustomer = await stripe.customers.retrieve(stripeCustomerId, { expand: ["subscriptions"] }); + const { subscriptions } = stripeCustomer; + + // todo: find a better way to get current subscription + if (subscriptions.total_count) { + return res.json(subscriptions.data[0]); + } + + res.status(StatusCodes.NO_CONTENT).end(); + } catch ({ message }) { + res.status(StatusCodes.BAD_REQUEST).json({ error: { message } }); + } +}; diff --git a/packages/dashboard/src/pages/api/stubs/stripe/prices.js b/packages/dashboard/src/pages/api/stubs/stripe/prices.js new file mode 100644 index 00000000..ebf013a3 --- /dev/null +++ b/packages/dashboard/src/pages/api/stubs/stripe/prices.js @@ -0,0 +1,37 @@ +export default (req, res) => { + res.json([ + { + id: "price_1IReYFIzjULiPWN6DqN2DwjN", + name: "Skynet Extreme", + description: "Skynet Extreme description", + tier: 4, + price: 80, + currency: "usd", + stripe: "price_1IReYFIzjULiPWN6DqN2DwjN", + productId: "prod_J3m6IuVyh3XOc5", + livemode: false, + }, + { + id: "price_1IReY5IzjULiPWN6AxPytHEG", + name: "Skynet Pro", + description: "Skynet Pro description", + tier: 3, + price: 20, + currency: "usd", + stripe: "price_1IReY5IzjULiPWN6AxPytHEG", + productId: "prod_J3m6ioQg90kZj5", + livemode: false, + }, + { + id: "price_1IReXpIzjULiPWN66PvsxHL4", + name: "Skynet Plus", + description: "Skynet Plus description", + tier: 2, + price: 5, + currency: "usd", + stripe: "price_1IReXpIzjULiPWN66PvsxHL4", + productId: "prod_J3m6xMfDiz2LGE", + livemode: false, + }, + ]); +}; diff --git a/packages/dashboard/src/pages/api/stubs/user.js b/packages/dashboard/src/pages/api/stubs/user.js new file mode 100644 index 00000000..409bf333 --- /dev/null +++ b/packages/dashboard/src/pages/api/stubs/user.js @@ -0,0 +1,5 @@ +import user from "./user.json"; + +export default (req, res) => { + res.json(user); +}; diff --git a/packages/dashboard/src/pages/api/stubs/user.json b/packages/dashboard/src/pages/api/stubs/user.json new file mode 100644 index 00000000..f41dab0e --- /dev/null +++ b/packages/dashboard/src/pages/api/stubs/user.json @@ -0,0 +1,12 @@ +{ + "firstName": "John", + "lastName": "Doe", + "email": "john@example.com", + "sub": "ab776d6d-f324-4fa7-4k21-7587d5215481", + "tier": 1, + "subscribedUntil": "0001-01-01T00:00:00Z", + "subscriptionStatus": "active", + "subscriptionCancelAt": "2021-04-21T00:00:00Z", + "subscriptionCancelAtPeriodEnd": true, + "stripeCustomerId": "cus_J0iYnAp6LRgsTI" +} diff --git a/packages/dashboard/src/pages/api/stubs/user/downloads.js b/packages/dashboard/src/pages/api/stubs/user/downloads.js new file mode 100644 index 00000000..c4a24c03 --- /dev/null +++ b/packages/dashboard/src/pages/api/stubs/user/downloads.js @@ -0,0 +1,8 @@ +import items from "./downloads.json"; + +export default (req, res) => { + const offset = parseInt(req.query?.offset ?? 0, 10); + const pageSize = parseInt(req.query?.pageSize ?? 10, 10); + + res.json({ items: items.slice(offset, offset + pageSize), count: items.length, pageSize, offset }); +}; diff --git a/packages/dashboard/src/pages/api/stubs/user/downloads.json b/packages/dashboard/src/pages/api/stubs/user/downloads.json new file mode 100644 index 00000000..edf6ff0d --- /dev/null +++ b/packages/dashboard/src/pages/api/stubs/user/downloads.json @@ -0,0 +1,44 @@ +[ + { + "id": 1111, + "skylink": "PAL0w4SdA5rFCDGEutgpeQ50Om-YkBabtXVOJAkmedslKw", + "name": "ugabuga.pdf", + "size": 123123, + "downloadedOn": "2020-04-02T08:02:17-05:00" + }, + { + "id": 2222, + "skylink": "XABvi7JtJbQSMAcDwnUnmp2FKDPjg8_tTTFP4BwMSxVdEg", + "name": "ugabuga.pdf", + "size": 8912739812, + "downloadedOn": "2020-04-02T08:02:17-05:00" + }, + { + "id": 3333, + "skylink": "IADUs8d9CQjUO34LmdaaNPK_STuZo24rpKVfYW3wPPM2uQ", + "name": "ugabuga.pdf", + "size": 123123, + "downloadedOn": "2020-04-02T08:02:17-05:00" + }, + { + "id": 4444, + "skylink": "_A2zt5SKoqwnnZU4cBF8uBycSKULXMyeg1c5ZISBr2Q3dA", + "name": "ugabuga.pdf", + "size": 83943, + "downloadedOn": "2020-04-02T08:02:17-05:00" + }, + { + "id": 5555, + "skylink": "AAC0uO43g64ULpyrW0zO3bjEknSFbAhm8c-RFP21EQlmSQ", + "name": "ugabuga.pdf", + "size": 3290489120, + "downloadedOn": "2020-04-02T08:02:17-05:00" + }, + { + "id": 6666, + "skylink": "CACqf4NlIMlA0CCCieYGjpViPGyfyJ4v1x3bmuCKZX8FKA", + "name": "ugabuga.pdf", + "size": 1290389, + "downloadedOn": "2020-04-02T08:02:17-05:00" + } +] diff --git a/packages/dashboard/src/pages/api/stubs/user/stats.js b/packages/dashboard/src/pages/api/stubs/user/stats.js new file mode 100644 index 00000000..81a65545 --- /dev/null +++ b/packages/dashboard/src/pages/api/stubs/user/stats.js @@ -0,0 +1,5 @@ +import stats from "./stats.json"; + +export default (req, res) => { + res.json(stats); +}; diff --git a/packages/dashboard/src/pages/api/stubs/user/stats.json b/packages/dashboard/src/pages/api/stubs/user/stats.json new file mode 100644 index 00000000..29696ca2 --- /dev/null +++ b/packages/dashboard/src/pages/api/stubs/user/stats.json @@ -0,0 +1,13 @@ +{ + "storageUsed": 809500672, + "numRegReads": 0, + "numRegWrites": 0, + "numUploads": 13, + "numDownloads": 78, + "totalUploadsSize": 618649028, + "totalDownloadsSize": 32307956843, + "bwUploads": 2810183680, + "bwDownloads": 32323934976, + "bwRegReads": 0, + "bwRegWrites": 0 +} diff --git a/packages/dashboard/src/pages/api/stubs/user/uploads.js b/packages/dashboard/src/pages/api/stubs/user/uploads.js new file mode 100644 index 00000000..ad8b3d20 --- /dev/null +++ b/packages/dashboard/src/pages/api/stubs/user/uploads.js @@ -0,0 +1,8 @@ +import items from "./uploads.json"; + +export default (req, res) => { + const offset = parseInt(req.query?.offset ?? 0, 10); + const pageSize = parseInt(req.query?.pageSize ?? 10, 10); + + res.json({ items: items.slice(offset, offset + pageSize), count: items.length, pageSize, offset }); +}; diff --git a/packages/dashboard/src/pages/api/stubs/user/uploads.json b/packages/dashboard/src/pages/api/stubs/user/uploads.json new file mode 100644 index 00000000..efc42359 --- /dev/null +++ b/packages/dashboard/src/pages/api/stubs/user/uploads.json @@ -0,0 +1,44 @@ +[ + { + "id": 1111, + "skylink": "PAL0w4SdA5rFCDGEutgpeQ50Om-YkBabtXVOJAkmedslKw", + "name": "ugabuga.pdf", + "size": 123123, + "uploadedOn": "2020-04-02T08:02:17-05:00" + }, + { + "id": 2222, + "skylink": "XABvi7JtJbQSMAcDwnUnmp2FKDPjg8_tTTFP4BwMSxVdEg", + "name": "ugabuga.pdf", + "size": 8912739812, + "uploadedOn": "2020-04-02T08:02:17-05:00" + }, + { + "id": 3333, + "skylink": "IADUs8d9CQjUO34LmdaaNPK_STuZo24rpKVfYW3wPPM2uQ", + "name": "ugabuga.pdf", + "size": 123123, + "uploadedOn": "2020-04-02T08:02:17-05:00" + }, + { + "id": 4444, + "skylink": "_A2zt5SKoqwnnZU4cBF8uBycSKULXMyeg1c5ZISBr2Q3dA", + "name": "ugabuga.pdf", + "size": 83943, + "uploadedOn": "2020-04-02T08:02:17-05:00" + }, + { + "id": 5555, + "skylink": "AAC0uO43g64ULpyrW0zO3bjEknSFbAhm8c-RFP21EQlmSQ", + "name": "ugabuga.pdf", + "size": 3290489120, + "uploadedOn": "2020-04-02T08:02:17-05:00" + }, + { + "id": 6666, + "skylink": "CACqf4NlIMlA0CCCieYGjpViPGyfyJ4v1x3bmuCKZX8FKA", + "name": "ugabuga.pdf", + "size": 1290389, + "uploadedOn": "2020-04-02T08:02:17-05:00" + } +] diff --git a/packages/dashboard/src/pages/auth/login.js b/packages/dashboard/src/pages/auth/login.js new file mode 100644 index 00000000..481f8d44 --- /dev/null +++ b/packages/dashboard/src/pages/auth/login.js @@ -0,0 +1,96 @@ +import Link from "next/link"; +import { Configuration, PublicApi } from "@ory/kratos-client"; +import config from "../../config"; +import SelfServiceForm from "../../components/Form/SelfServiceForm"; + +const kratos = new PublicApi(new Configuration({ basePath: config.kratos.public })); + +export async function getServerSideProps(context) { + const flow = context.query.flow; + const redirect = encodeURIComponent(`/api/accounts/login?return_to=${context.query.return_to ?? "/"}`); + + if (process.env.NODE_ENV === "development") { + return { props: { flow: require("../../../stubs/login.json") } }; + } + + // The flow is used to identify the login and registration flow and + // return data like the csrf_token and so on. + if (!flow || typeof flow !== "string") { + // No flow ID found in URL, initializing login flow. + return { + redirect: { + permanent: false, + destination: `${config.kratos.browser}/self-service/login/browser?return_to=${redirect}`, + }, + }; + } + + try { + const { status, data } = await kratos.getSelfServiceLoginFlow(flow); + + if (status === 200) return { props: { flow: data } }; + + throw new Error(`Failed to retrieve flow ${flow} with code ${status}`); + } catch (error) { + return { + redirect: { + permanent: false, + destination: `${config.kratos.browser}/self-service/login/browser?return_to=${redirect}`, + }, + }; + } +} + +const fieldsConfig = { + identifier: { + label: "Email address", + autoComplete: "email", + position: 0, + }, + password: { + label: "Password", + autoComplete: "current-password", + position: 1, + }, + csrf_token: { + position: 99, + }, +}; + +export default function Login({ flow }) { + return ( +
+
+ + + +

Sign in to your account

+

+ or{" "} + + sign up + {" "} + if you don't have one yet +

+
+ + + + +
+ ); +} diff --git a/packages/dashboard/src/pages/auth/registration.js b/packages/dashboard/src/pages/auth/registration.js new file mode 100644 index 00000000..33230c54 --- /dev/null +++ b/packages/dashboard/src/pages/auth/registration.js @@ -0,0 +1,113 @@ +import Link from "next/link"; +import { Configuration, PublicApi } from "@ory/kratos-client"; +import { getIn } from "formik"; +import config from "../../config"; +import levenshtein from "fast-levenshtein"; +import lcs from "../../services/longestCommonSequence"; +import SelfServiceForm from "../../components/Form/SelfServiceForm"; + +const kratos = new PublicApi(new Configuration({ basePath: config.kratos.public })); + +export async function getServerSideProps(context) { + const flow = context.query.flow; + const redirect = encodeURIComponent(`/api/accounts/login?return_to=${context.query.return_to ?? "/"}`); + + if (process.env.NODE_ENV === "development") { + return { props: { flow: require("../../../stubs/registration.json") } }; + } + + // The flow is used to identify the login and registration flow and + // return data like the csrf_token and so on. + if (!flow || typeof flow !== "string") { + // No flow ID found in URL, initializing registration flow. + return { + redirect: { + permanent: false, + destination: `${config.kratos.browser}/self-service/registration/browser?return_to=${redirect}`, + }, + }; + } + + try { + const { status, data } = await kratos.getSelfServiceRegistrationFlow(flow); + + if (status === 200) return { props: { flow: data } }; + + throw new Error(`Failed to retrieve flow ${flow} with code ${status}`); + } catch (error) { + return { + redirect: { + permanent: false, + destination: `${config.kratos.browser}/self-service/registration/browser?return_to=${redirect}`, + }, + }; + } +} + +const fieldsConfig = { + "traits.email": { + label: "Email address", + autoComplete: "email", + position: 0, + }, + password: { + label: "Password", + autoComplete: "new-password", + position: 1, + checks: [ + { + label: "At least 6 characters long", + validate: (values, field) => { + const value = getIn(values, field); + + return value && value.length > 5; + }, + }, + { + label: "Significantly different from the email", + validate: (values, field) => { + const value = getIn(values, field); + const email = getIn(values, "traits.email"); + + // levenshtein distance higher than 5 and longest common sequence shorter than half of the password + return value && email && levenshtein.get(value, email) > 5 && lcs(value, email).length / value.length <= 0.5; + }, + }, + ], + }, + csrf_token: { + position: 99, + }, +}; + +export default function Registration({ flow }) { + return ( +
+
+ + + +

Sign up for a new account

+

+ or{" "} + + sign in + {" "} + if you already have one +

+
+ + +
+ ); +} diff --git a/packages/dashboard/src/pages/downloads.js b/packages/dashboard/src/pages/downloads.js new file mode 100644 index 00000000..942efd11 --- /dev/null +++ b/packages/dashboard/src/pages/downloads.js @@ -0,0 +1,44 @@ +import dayjs from "dayjs"; +import prettyBytes from "pretty-bytes"; +import { useState } from "react"; +import Layout from "../components/Layout"; +import Table from "../components/Table"; +import authServerSideProps from "../services/authServerSideProps"; +import { SkynetClient } from "skynet-js"; +import useAccountsApi from "../services/useAccountsApi"; + +const skynetClient = new SkynetClient(process.env.NEXT_PUBLIC_SKYNET_PORTAL_API); +const apiPrefix = process.env.NODE_ENV === "development" ? "/api/stubs" : ""; +const getSkylinkLink = ({ skylink }) => skynetClient.getSkylinkUrl(skylink); +const getRelativeDate = ({ downloadedOn }) => dayjs(downloadedOn).format("YYYY-MM-DD HH:mm:ss"); +const headers = [ + { key: "name", name: "Name", nowrap: false, href: getSkylinkLink }, + { key: "skylink", name: "Skylink" }, + { key: "size", name: "Size", formatter: ({ size }) => prettyBytes(size) }, + { key: "downloadedOn", name: "Accessed on", formatter: getRelativeDate }, +]; +const actions = []; + +export const getServerSideProps = authServerSideProps(async (context, api) => { + const initialData = await api.get("user/downloads?pageSize=10&offset=0").json(); + + return { props: { initialData } }; +}); + +export default function Downloads({ initialData }) { + const [offset, setOffset] = useState(0); + const { data } = useAccountsApi(`${apiPrefix}/user/downloads?pageSize=10&offset=${offset}`, { + initialData: offset === 0 ? initialData : undefined, + revalidateOnMount: true, + }); + + // preload next page if it exists (based on the response from the current page query) + const nextPageOffset = data && data.offset + data.pageSize < data.count ? data.offset + data.pageSize : offset; + useAccountsApi(`${apiPrefix}/user/downloads?pageSize=10&offset=${nextPageOffset}`); + + return ( + + + + ); +} diff --git a/packages/dashboard/src/pages/error.js b/packages/dashboard/src/pages/error.js new file mode 100644 index 00000000..19a1e7b1 --- /dev/null +++ b/packages/dashboard/src/pages/error.js @@ -0,0 +1,68 @@ +import Link from "next/link"; +import { Configuration, PublicApi } from "@ory/kratos-client"; +import config from "../config"; + +const kratos = new PublicApi(new Configuration({ basePath: config.kratos.public })); + +export async function getServerSideProps(context) { + const error = context.query.error; + + // No error was send, redirecting back to home. + if (!error || typeof error !== "string") { + console.log("No error ID found in URL, redirecting to homepage."); + + return { redirect: { permanent: false, destination: "/" } }; + } + + try { + const { status, data } = await kratos.getSelfServiceError(error); + + if ("errors" in data) return { props: { errors: data.errors } }; + + throw new Error(`Expected error ${error} to contain "errors" but got ${JSON.stringify(data)}`); + } catch (error) { + return { redirect: { permanent: false, destination: "/" } }; + } +} + +export default function Error({ errors }) { + return ( +
+
+ + + +

An error occurred

+
+
+
+ {errors.map((error, index) => ( +
1 ? "mt-3 sm:mt-5" : ""} text-center`}> + +
+

{error.reason}

+
+
+ ))} +
+
+ +
+ ); +} diff --git a/packages/dashboard/src/pages/index.js b/packages/dashboard/src/pages/index.js new file mode 100644 index 00000000..696ece24 --- /dev/null +++ b/packages/dashboard/src/pages/index.js @@ -0,0 +1,276 @@ +import dayjs from "dayjs"; +import relativeTime from "dayjs/plugin/relativeTime"; +import prettyBytes from "pretty-bytes"; +import Link from "next/link"; +import Layout from "../components/Layout"; +import authServerSideProps from "../services/authServerSideProps"; +import { SkynetClient } from "skynet-js"; +import config from "../config"; +import useAccountsApi from "../services/useAccountsApi"; +import { isFreeTier } from "../services/tiers"; +import { write } from "clipboardy"; + +dayjs.extend(relativeTime); + +const skynetClient = new SkynetClient(process.env.NEXT_PUBLIC_SKYNET_PORTAL_API); +const apiPrefix = process.env.NODE_ENV === "development" ? "/api/stubs" : ""; + +export const getServerSideProps = authServerSideProps(async (context, api) => { + const stripe = await api.get("stripe/prices").json(); + const plans = [config.tiers.starter, ...stripe].sort((a, b) => a.tier - b.tier); + + return { props: { plans } }; +}); + +function SkylinkList({ items = [], timestamp }) { + return ( +
    + {items.slice(0, 3).map((item) => ( +
  • +
    +
    + + {item.name || "— file name not available —"} + + write(`sia://${item.skylink}`)} + > + sia://{item.skylink.substr(0, 5)}…{item.skylink.substr(-5)} + +
    +
    +
    +

    + + + + {prettyBytes(item.size)} +

    +
    +
    + + + + + {item[timestamp] && } +
    +
    +
    +
  • + ))} + + {!items.length && ( +
  • +
    +

    no entries yet

    +
    +
  • + )} +
+ ); +} + +export default function Home({ plans }) { + const { data: user } = useAccountsApi(`${apiPrefix}/user`); + const { data: stats } = useAccountsApi(`${apiPrefix}/user/stats`); + const { data: downloads } = useAccountsApi(`${apiPrefix}/user/downloads?pageSize=3&offset=0`); + const { data: uploads } = useAccountsApi(`${apiPrefix}/user/uploads?pageSize=3&offset=0`); + + const activePlan = plans.find(({ tier }) => (user ? user.tier === tier : isFreeTier(tier))); + + return ( + +
+
+
+
+
+
+ {/* Heroicon name: outline/users */} + +
+
+
Current plan
+
+
{activePlan.name}
+
+
+
+
+ +
+
+
+
+
+ + + +
+
+
Storage used
+
+
{prettyBytes(stats?.storageUsed ?? 0)}
+
+
+
+
+
+ +
+
+ {/*
+
+
+
+ + + +
+
+
Bandwidth used
+
+
{prettyBytes(stats?.bwDownloads ?? 0)}
+
+
+
+
+
+ +
+
*/} +
+ + {/* ============ */} + +
+
+

Recent downloads

+ + {/* This example requires Tailwind CSS v2.0+ */} +
+ +
+
+
+

Recent uploads

+ + {/* This example requires Tailwind CSS v2.0+ */} +
+ +
+
+
+
+
+ ); +} diff --git a/packages/dashboard/src/pages/payments.js b/packages/dashboard/src/pages/payments.js new file mode 100644 index 00000000..c36fe039 --- /dev/null +++ b/packages/dashboard/src/pages/payments.js @@ -0,0 +1,193 @@ +import dayjs from "dayjs"; +import Layout from "../components/Layout"; +import ky from "ky/umd"; +import { useEffect, useState } from "react"; +import authServerSideProps from "../services/authServerSideProps"; +import classnames from "classnames"; +import prettyBytes from "pretty-bytes"; +import config from "../config"; +import useAccountsApi from "../services/useAccountsApi"; +import { isFreeTier, isPaidTier } from "../services/tiers"; + +const apiPrefix = process.env.NODE_ENV === "development" ? "/api/stubs" : ""; + +const ActiveBadge = () => { + return ( + + active + + ); +}; + +export const getServerSideProps = authServerSideProps(async (context, api) => { + const [user, stats, stripe] = await Promise.all([ + api.get("user").json(), + api.get("user/stats").json(), + api.get("stripe/prices").json(), + ]); + const plans = [config.tiers.starter, ...stripe].sort((a, b) => a.tier - b.tier); + + return { props: { plans, user, stats } }; +}); + +export default function Payments({ plans, user: initialUserData, stats: initialStatsData }) { + const { data: user } = useAccountsApi(`${apiPrefix}/user`, { initialData: initialUserData }); + const { data: stats } = useAccountsApi(`${apiPrefix}/user/stats`, { initialData: initialStatsData }); + const [selectedPlan, setSelectedPlan] = useState(plans.find(({ tier }) => isFreeTier(tier))); + const activePlan = plans.find(({ tier }) => (user ? user.tier === tier : isFreeTier(tier))); + const handleSubscribe = async () => { + try { + const price = selectedPlan.stripe; + const { sessionId } = await ky.post("/api/stripe/checkout", { json: { price } }).json(); + const stripe = new Stripe(process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY); + await stripe.redirectToCheckout({ sessionId }); + } catch (error) { + console.log(error); // todo: handle error + } + }; + + useEffect(() => { + if (activePlan && isPaidTier(activePlan.tier)) { + setSelectedPlan(activePlan); + } + }, [activePlan, selectedPlan, setSelectedPlan]); + + return ( + +
+
+
+
+
+
Current plan
+
{activePlan?.name || "—"}
+
+
+ +
+
+
Subscription status
+
+ {isFreeTier(activePlan?.tier) ? "—" : user?.subscriptionStatus} +
+
+ {user?.subscriptionCancelAtPeriodEnd && ( +
+
+ Your plan will be cancelled on {dayjs(user.subscriptionCancelAt).format("D MMM YYYY")}. +
+
+ )} +
+ +
+
+
Storage used
+
{prettyBytes(stats.storageUsed)}
+
+
+
+ +
+
+
+
+
+
+

+ Plan +

+
+
+
+ Pricing plans +
    + {plans.map((plan, index) => ( +
  • + +
  • + ))} +
+
+
+
+ {user && isPaidTier(user.tier) ? ( +
+ + Use Stripe Customer Portal to manage your active subscription, payment methods and view your + billing history + + + Stripe Customer Portal + +
+ ) : ( + + )} +
+
+ +
+
+
+
+ ); +} diff --git a/packages/dashboard/src/pages/plans.js b/packages/dashboard/src/pages/plans.js new file mode 100644 index 00000000..ee319e69 --- /dev/null +++ b/packages/dashboard/src/pages/plans.js @@ -0,0 +1,389 @@ +import Layout from "../components/Layout"; + +export default function Payments() { + return ( + + {/* This example requires Tailwind CSS v2.0+ */} +
+
+
+

+ Start using for free, then add a plan to improve the experience. Account plans unlock additional features. +

+
+ + +
+
+
+
+
+

Free

+

All the basics for starting a new business

+

+ no cost +

+ + Active + +
+
+

What's included

+
    +
  • + {/* Heroicon name: solid/check */} + + Potenti felis, in cras at at ligula nunc. +
  • +
  • + {/* Heroicon name: solid/check */} + + Orci neque eget pellentesque. +
  • +
+
+
+
+
+

Skynet Plus

+

All the basics for starting a new business

+

+ $5 + /mo +

+ + Buy Skynet Plus + +
+
+

What's included

+
    +
  • + {/* Heroicon name: solid/check */} + + Potenti felis, in cras at at ligula nunc. +
  • +
  • + {/* Heroicon name: solid/check */} + + Orci neque eget pellentesque. +
  • +
  • + {/* Heroicon name: solid/check */} + + Donec mauris sit in eu tincidunt etiam. +
  • +
+
+
+
+
+

Skynet Pro

+

All the basics for starting a new business

+

+ $20 + /mo +

+ + Buy Skynet Pro + +
+
+

What's included

+
    +
  • + {/* Heroicon name: solid/check */} + + Potenti felis, in cras at at ligula nunc. +
  • +
  • + {/* Heroicon name: solid/check */} + + Orci neque eget pellentesque. +
  • +
  • + {/* Heroicon name: solid/check */} + + Donec mauris sit in eu tincidunt etiam. +
  • +
  • + {/* Heroicon name: solid/check */} + + Faucibus volutpat magna. +
  • +
+
+
+
+
+

Skynet Extreme

+

All the basics for starting a new business

+

+ $80 + /mo +

+ + Buy Skynet Extreme + +
+
+

What's included

+
    +
  • + {/* Heroicon name: solid/check */} + + Potenti felis, in cras at at ligula nunc. +
  • +
  • + {/* Heroicon name: solid/check */} + + Orci neque eget pellentesque. +
  • +
  • + {/* Heroicon name: solid/check */} + + Donec mauris sit in eu tincidunt etiam. +
  • +
  • + {/* Heroicon name: solid/check */} + + Faucibus volutpat magna. +
  • +
  • + {/* Heroicon name: solid/check */} + + Id sed tellus in varius quisque. +
  • +
  • + {/* Heroicon name: solid/check */} + + Risus egestas faucibus. +
  • +
  • + {/* Heroicon name: solid/check */} + + Risus cursus ullamcorper. +
  • +
+
+
+
+
+
+
+ ); +} diff --git a/packages/dashboard/src/pages/recovery.js b/packages/dashboard/src/pages/recovery.js new file mode 100644 index 00000000..e64a4213 --- /dev/null +++ b/packages/dashboard/src/pages/recovery.js @@ -0,0 +1,95 @@ +import Link from "next/link"; +import { Configuration, PublicApi } from "@ory/kratos-client"; +import config from "../config"; +import SelfServiceForm from "../components/Form/SelfServiceForm"; + +const kratos = new PublicApi(new Configuration({ basePath: config.kratos.public })); + +export async function getServerSideProps(context) { + const flow = context.query.flow; + + if (process.env.NODE_ENV === "development") { + return { props: { flow: require("../../stubs/recovery.json") } }; + } + + // The flow is used to identify the login and registration flow and + // return data like the csrf_token and so on. + if (!flow || typeof flow !== "string") { + // No flow ID found in URL, initializing recovery flow. + return { + redirect: { + permanent: false, + destination: `${config.kratos.browser}/self-service/recovery/browser`, + }, + }; + } + + try { + const { status, data } = await kratos.getSelfServiceRecoveryFlow(flow); + + if (status === 200) return { props: { flow: data } }; + + throw new Error(`Failed to retrieve flow ${flow} with code ${status}`); + } catch (error) { + return { + redirect: { + permanent: false, + destination: `${config.kratos.browser}/self-service/recovery/browser`, + }, + }; + } +} + +const fieldsConfig = { + email: { + label: "Your email", + autoComplete: "email", + position: 0, + }, + csrf_token: { + position: 99, + }, +}; + +export default function Recovery({ flow }) { + return ( +
+
+ + + +

Recover your account

+

+ + sign in + {" "} + if you suddenly remembered your password +

+

+ or{" "} + + sign up + {" "} + for a new account +

+
+ + +
+ ); +} diff --git a/packages/dashboard/src/pages/settings.js b/packages/dashboard/src/pages/settings.js new file mode 100644 index 00000000..6f314ca5 --- /dev/null +++ b/packages/dashboard/src/pages/settings.js @@ -0,0 +1,83 @@ +import { Configuration, PublicApi } from "@ory/kratos-client"; +import Layout from "../components/Layout"; +import config from "../config"; +import SelfServiceForm from "../components/Form/SelfServiceForm"; +import authServerSideProps from "../services/authServerSideProps"; + +const kratos = new PublicApi(new Configuration({ basePath: config.kratos.public })); + +export const getServerSideProps = authServerSideProps(async (context) => { + const flow = context.query.flow; + + if (process.env.NODE_ENV === "development") { + return { props: { flow: require("../../stubs/settings.json") } }; + } + + // The flow is used to identify the login and registration flow and + // return data like the csrf_token and so on. + if (!flow || typeof flow !== "string") { + // No flow ID found in URL, initializing settings flow. + return { + redirect: { + permanent: false, + destination: `${config.kratos.browser}/self-service/settings/browser`, + }, + }; + } + + try { + const { status, data } = await kratos.getSelfServiceSettingsFlow(flow, { + headers: { cookie: context.req.headers.cookie }, + }); + + console.log(flow, status, data); + + if (status === 200) return { props: { flow: data } }; + + throw new Error(`Failed to retrieve flow ${flow} with code ${status}`); + } catch (error) { + console.log(error); + + return { + redirect: { + permanent: false, + destination: `${config.kratos.browser}/self-service/settings/browser`, + }, + }; + } +}); + +const fieldsConfig = { + "traits.email": { + label: "Email address", + autoComplete: "email", + position: 0, + }, + password: { + label: "Password", + autoComplete: "new-password", + position: 1, + }, + csrf_token: { + position: 99, + }, +}; + +export default function Settings({ flow }) { + const profileConfig = flow.methods.profile.config; + const passwordConfig = flow.methods.password.config; + + return ( + +
+ + +
+
+ ); +} diff --git a/packages/dashboard/src/pages/uploads.js b/packages/dashboard/src/pages/uploads.js new file mode 100644 index 00000000..d78288f7 --- /dev/null +++ b/packages/dashboard/src/pages/uploads.js @@ -0,0 +1,44 @@ +import dayjs from "dayjs"; +import prettyBytes from "pretty-bytes"; +import { useState } from "react"; +import Layout from "../components/Layout"; +import Table from "../components/Table"; +import authServerSideProps from "../services/authServerSideProps"; +import { SkynetClient } from "skynet-js"; +import useAccountsApi from "../services/useAccountsApi"; + +const skynetClient = new SkynetClient(process.env.NEXT_PUBLIC_SKYNET_PORTAL_API); +const apiPrefix = process.env.NODE_ENV === "development" ? "/api/stubs" : ""; +const getSkylinkLink = ({ skylink }) => skynetClient.getSkylinkUrl(skylink); +const getRelativeDate = ({ uploadedOn }) => dayjs(uploadedOn).format("YYYY-MM-DD HH:mm:ss"); +const headers = [ + { key: "name", name: "Name", nowrap: false, href: getSkylinkLink }, + { key: "skylink", name: "Skylink" }, + { key: "size", name: "Size", formatter: ({ size }) => prettyBytes(size) }, + { key: "uploadedOn", name: "Uploaded on", formatter: getRelativeDate }, +]; +const actions = []; + +export const getServerSideProps = authServerSideProps(async (context, api) => { + const initialData = await api.get("user/uploads?pageSize=10&offset=0").json(); + + return { props: { initialData } }; +}); + +export default function Uploads({ initialData }) { + const [offset, setOffset] = useState(0); + const { data } = useAccountsApi(`${apiPrefix}/user/uploads?pageSize=10&offset=${offset}`, { + initialData: offset === 0 ? initialData : undefined, + revalidateOnMount: true, + }); + + // preload next page if it exists (based on the response from the current page query) + const nextPageOffset = data && data.offset + data.pageSize < data.count ? data.offset + data.pageSize : offset; + useAccountsApi(`${apiPrefix}/user/uploads?pageSize=10&offset=${nextPageOffset}`); + + return ( + +
+ + ); +} diff --git a/packages/dashboard/src/pages/verify.js b/packages/dashboard/src/pages/verify.js new file mode 100644 index 00000000..adcde201 --- /dev/null +++ b/packages/dashboard/src/pages/verify.js @@ -0,0 +1,103 @@ +import Link from "next/link"; +import { Configuration, PublicApi } from "@ory/kratos-client"; +import config from "../config"; +import SelfServiceForm from "../components/Form/SelfServiceForm"; +import { useEffect } from "react"; + +const kratos = new PublicApi(new Configuration({ basePath: config.kratos.public })); + +export async function getServerSideProps(context) { + const flow = context.query.flow; + + // if (process.env.NODE_ENV === "development") { + // return { props: { flow: require("../../stubs/recovery.json") } }; + // } + + if (!flow || typeof flow !== "string") { + return { + redirect: { + permanent: false, + destination: `${config.kratos.browser}/self-service/verification/browser`, + }, + }; + } + + try { + const { status, data } = await kratos.getSelfServiceVerificationFlow(flow); + + if (status === 200) return { props: { flow: data } }; + + throw new Error(`Failed to retrieve flow ${flow} with code ${status}`); + } catch (error) { + return { + redirect: { + permanent: false, + destination: `${config.kratos.browser}/self-service/verification/browser`, + }, + }; + } +} + +const fieldsConfig = { + email: { + label: "Your email", + autoComplete: "email", + position: 0, + }, + csrf_token: { + position: 99, + }, +}; + +export default function Verify({ flow }) { + const state = flow.state; + + useEffect(() => { + if (state === "passed_challenge") { + setTimeout(() => (window.location = "/"), 5000); + } + }, [state]); + + return ( +
+
+ + + +

+ {flow.state === "passed_challenge" ? "Verification successful!" : "Account verification"} +

+ + {flow.state === "passed_challenge" && ( + <> +

You will be redirected automatically

+

+ + go to dashboard + +

+ + )} +
+ + {flow.state !== "passed_challenge" && ( + + )} +
+ ); +} diff --git a/packages/dashboard/src/services/authServerSideProps.js b/packages/dashboard/src/services/authServerSideProps.js new file mode 100644 index 00000000..bc7bf43c --- /dev/null +++ b/packages/dashboard/src/services/authServerSideProps.js @@ -0,0 +1,27 @@ +import ky from "ky/umd"; + +const isProduction = process.env.NODE_ENV === "production"; + +export default function authServerSideProps(getServerSideProps) { + return function authenticate(context) { + if (isProduction && (!("ory_kratos_session" in context.req.cookies) || !("skynet-jwt" in context.req.cookies))) { + return { + redirect: { + permanent: false, + destination: `/api/accounts/login?return_to=${encodeURIComponent(context.resolvedUrl)}`, + }, + }; + } + + if (getServerSideProps) { + const api = ky.create({ + headers: { cookie: context.req.headers.cookie }, + prefixUrl: isProduction ? "http://oathkeeper:4455" : "http://localhost:3000/api/stubs", + }); + + return getServerSideProps(context, api); + } + + return { props: {} }; + }; +} diff --git a/packages/dashboard/src/services/longestCommonSequence.js b/packages/dashboard/src/services/longestCommonSequence.js new file mode 100644 index 00000000..5c5f5143 --- /dev/null +++ b/packages/dashboard/src/services/longestCommonSequence.js @@ -0,0 +1,65 @@ +// @source https://github.com/trekhleb/javascript-algorithms/blob/master/src/algorithms/sets/longest-common-subsequence/longestCommonSubsequence.js +// @license MIT https://github.com/trekhleb/javascript-algorithms/blob/master/LICENSE + +/** + * @param {string[]} set1 + * @param {string[]} set2 + * @return {string[]} + */ +export default function longestCommonSubsequence(set1, set2) { + // Init LCS matrix. + const lcsMatrix = Array(set2.length + 1) + .fill(null) + .map(() => Array(set1.length + 1).fill(null)); + + // Fill first row with zeros. + for (let columnIndex = 0; columnIndex <= set1.length; columnIndex += 1) { + lcsMatrix[0][columnIndex] = 0; + } + + // Fill first column with zeros. + for (let rowIndex = 0; rowIndex <= set2.length; rowIndex += 1) { + lcsMatrix[rowIndex][0] = 0; + } + + // Fill rest of the column that correspond to each of two strings. + for (let rowIndex = 1; rowIndex <= set2.length; rowIndex += 1) { + for (let columnIndex = 1; columnIndex <= set1.length; columnIndex += 1) { + if (set1[columnIndex - 1] === set2[rowIndex - 1]) { + lcsMatrix[rowIndex][columnIndex] = lcsMatrix[rowIndex - 1][columnIndex - 1] + 1; + } else { + lcsMatrix[rowIndex][columnIndex] = Math.max( + lcsMatrix[rowIndex - 1][columnIndex], + lcsMatrix[rowIndex][columnIndex - 1] + ); + } + } + } + + // Calculate LCS based on LCS matrix. + if (!lcsMatrix[set2.length][set1.length]) { + // If the length of largest common string is zero then return empty string. + return [""]; + } + + const longestSequence = []; + let columnIndex = set1.length; + let rowIndex = set2.length; + + while (columnIndex > 0 || rowIndex > 0) { + if (set1[columnIndex - 1] === set2[rowIndex - 1]) { + // Move by diagonal left-top. + longestSequence.unshift(set1[columnIndex - 1]); + columnIndex -= 1; + rowIndex -= 1; + } else if (lcsMatrix[rowIndex][columnIndex] === lcsMatrix[rowIndex][columnIndex - 1]) { + // Move left. + columnIndex -= 1; + } else { + // Move up. + rowIndex -= 1; + } + } + + return longestSequence; +} diff --git a/packages/dashboard/src/services/tiers.js b/packages/dashboard/src/services/tiers.js new file mode 100644 index 00000000..4e561e2b --- /dev/null +++ b/packages/dashboard/src/services/tiers.js @@ -0,0 +1,2 @@ +export const isFreeTier = (tier) => tier === 1; +export const isPaidTier = (tier) => tier > 1; diff --git a/packages/dashboard/src/services/useAccountsApi.js b/packages/dashboard/src/services/useAccountsApi.js new file mode 100644 index 00000000..169b12d9 --- /dev/null +++ b/packages/dashboard/src/services/useAccountsApi.js @@ -0,0 +1,15 @@ +import useSWR from "swr"; +import { StatusCodes } from "http-status-codes"; + +const fetcher = (url) => + fetch(url).then((res) => { + if (res.status === StatusCodes.UNAUTHORIZED) { + window.location.href = `/auth/login?return_to=${encodeURIComponent(window.location.href)}`; + } + + return res.json(); + }); + +export default function useAccountsApi(key, config) { + return useSWR(key, fetcher, config); +} diff --git a/packages/dashboard/stubs/login.json b/packages/dashboard/stubs/login.json new file mode 100644 index 00000000..bb136cd8 --- /dev/null +++ b/packages/dashboard/stubs/login.json @@ -0,0 +1,45 @@ +{ + "id": "bda73c77-1e21-4bfd-b85a-322fce2e4576", + "expires_at": "2020-01-28T13:48:04.690715Z", + "issued_at": "2020-01-28T13:38:04.690732Z", + "request_url": "http://127.0.0.1:4455/auth/browser/login", + "methods": { + "oidc": { + "method": "oidc", + "config": { + "action": "http://127.0.0.1:4455/.ory/kratos/public/auth/browser/methods/oidc/auth/bda73c77-1e21-4bfd-b85a-322fce2e4576", + "method": "POST", + "fields": [ + { + "name": "csrf_token", + "type": "hidden", + "required": true, + "value": "QJreyXtUD4oUSJfGNjA/+6ydsQyq0o/rfTL6QK86VadVFg6mwgX5x1QHVQ6uRqKxmwAcavQup3ILCSwl7ke97g==" + } + ] + } + }, + "password": { + "method": "password", + "config": { + "action": "http://127.0.0.1:4455/.ory/kratos/public/auth/browser/methods/password/login?request=bda73c77-1e21-4bfd-b85a-322fce2e4576", + "method": "POST", + "fields": [ + { + "name": "csrf_token", + "type": "hidden", + "required": true, + "value": "M1gAKA8fIhw4JOpQ/5m9mKARBAvKhzWkyhbxjtZNLG8m1NBHtk7UUXhrKJhn7yDSl4ypbZR7HT28LSfrlzDEJg==" + }, + { "name": "identifier", "type": "text", "required": true, "value": "asfdasdffads" }, + { "name": "password", "type": "password", "required": true } + ], + "errors": [ + { + "message": "The provided credentials are invalid. Check for spelling mistakes in your password or username, email address, or phone number." + } + ] + } + } + } +} diff --git a/packages/dashboard/stubs/recovery.json b/packages/dashboard/stubs/recovery.json new file mode 100644 index 00000000..28fde87a --- /dev/null +++ b/packages/dashboard/stubs/recovery.json @@ -0,0 +1,31 @@ +{ + "id": "01e21a99-8e69-41f9-b3ba-4967f714c8eb", + "type": "browser", + "expires_at": "2021-03-18T15:46:30.634635Z", + "issued_at": "2021-03-18T14:46:30.634635Z", + "request_url": "http://oathkeeper:4455/self-service/recovery/browser", + "messages": null, + "methods": { + "link": { + "method": "link", + "config": { + "action": "http://127.0.0.1:4455/.ory/kratos/public/self-service/recovery/methods/link?flow=01e21a99-8e69-41f9-b3ba-4967f714c8eb", + "method": "POST", + "fields": [ + { + "name": "csrf_token", + "type": "hidden", + "required": true, + "value": "XvPfLJzxmcTWnr2rmLzFcED9Ef1PIkqSBQgx5t0yu0WuIp2S6ll+B9cQ0ClIcLQ==" + }, + { + "name": "email", + "type": "email", + "required": true + } + ] + } + } + }, + "state": "choose_method" +} diff --git a/packages/dashboard/stubs/registration.json b/packages/dashboard/stubs/registration.json new file mode 100644 index 00000000..4fe796ae --- /dev/null +++ b/packages/dashboard/stubs/registration.json @@ -0,0 +1,58 @@ +{ + "id": "dbff7b96-8116-42c5-8624-f9fb28f1db15", + "expires_at": "2020-01-28T13:49:01.2274112Z", + "issued_at": "2020-01-28T13:39:01.2274261Z", + "request_url": "http://127.0.0.1:4455/auth/browser/registration", + "methods": { + "oidc": { + "method": "oidc", + "config": { + "action": "http://127.0.0.1:4455/.ory/kratos/public/auth/browser/methods/oidc/auth/dbff7b96-8116-42c5-8624-f9fb28f1db15", + "method": "POST", + "fields": [ + { + "name": "csrf_token", + "type": "hidden", + "required": true, + "value": "xwb6A6iHdsguYwkAM6m3jj196E7TcmiWpAavIRxuAgXSiipsEdaAhW4sy8ir3yrECuBFKI2OQA/SPXlEXRPqTA==" + } + ] + } + }, + "password": { + "method": "password", + "config": { + "errors": [ + { + "message": "The provided credentials are invalid. Check for spelling mistakes in your password or username, email address, or phone number." + } + ], + "action": "http://127.0.0.1:4455/.ory/kratos/public/auth/browser/methods/password/registration?request=dbff7b96-8116-42c5-8624-f9fb28f1db15", + "method": "POST", + "fields": [ + { + "name": "csrf_token", + "type": "hidden", + "required": true, + "value": "xLg4B9WnuC0Ue+j9ay5EQvleaJpOl0H9xJJ7W3+Bwv7RNOhobPZOYFQ0KjXzWNkIzsPF/BBraWSyqa0+Pvwqtw==" + }, + { + "name": "password", + "type": "password", + "required": true, + "errors": [{ "message": "password: Is required" }] + }, + { + "name": "traits.email", + "type": "text", + "value": "", + "errors": [ + { "message": "traits.email: String length must be greater than or equal to 3" }, + { "message": "traits.email: Does not match format 'email'" } + ] + } + ] + } + } + } +} diff --git a/packages/dashboard/stubs/settings.json b/packages/dashboard/stubs/settings.json new file mode 100644 index 00000000..c7502b31 --- /dev/null +++ b/packages/dashboard/stubs/settings.json @@ -0,0 +1,49 @@ +{ + "id": "e01f6bf9-845c-4c4b-a3ce-60691dd7a97c", + "type": "browser", + "expires_at": "2021-02-18T13:31:43.947193Z", + "issued_at": "2021-02-18T12:31:43.947193Z", + "request_url": "http://oathkeeper:4455/self-service/settings/browser", + "messages": null, + "methods": { + "password": { + "method": "password", + "config": { + "action": "https://account.siasky.xyz/.ory/kratos/public/self-service/settings/methods/password?flow=e01f6bf9-845c-4c4b-a3ce-60691dd7a97c", + "method": "POST", + "fields": [ + { "name": "password", "type": "password", "required": true }, + { + "name": "csrf_token", + "type": "hidden", + "required": true, + "value": "i33iydUBN6jqwrkHlLPZ3ap7Ah4uC0UrTadn7zKT0jyouDpr+DF0/1Hbkshye9t7IKwyzOcLt7i6oR/OoEVg+g==" + } + ] + } + }, + "profile": { + "method": "profile", + "config": { + "action": "https://account.siasky.xyz/.ory/kratos/public/self-service/settings/methods/profile?flow=e01f6bf9-845c-4c4b-a3ce-60691dd7a97c", + "method": "POST", + "fields": [ + { + "name": "csrf_token", + "type": "hidden", + "required": true, + "value": "i33iydUBN6jqwrkHlLPZ3ap7Ah4uC0UrTadn7zKT0jyouDpr+DF0/1Hbkshye9t7IKwyzOcLt7i6oR/OoEVg+g==" + }, + { "name": "traits.email", "type": "email", "value": "karol@nebulous.tech" } + ] + } + } + }, + "identity": { + "id": "ab776d6d-f324-4fa7-a728-7587d5215481", + "schema_id": "default", + "schema_url": "", + "traits": { "email": "karol@nebulous.tech" } + }, + "state": "show_form" +} diff --git a/packages/dashboard/styles/Home.module.css b/packages/dashboard/styles/Home.module.css new file mode 100644 index 00000000..80745811 --- /dev/null +++ b/packages/dashboard/styles/Home.module.css @@ -0,0 +1,122 @@ +.container { + min-height: 100vh; + padding: 0 0.5rem; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +} + +.main { + padding: 5rem 0; + flex: 1; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +} + +.footer { + width: 100%; + height: 100px; + border-top: 1px solid #eaeaea; + display: flex; + justify-content: center; + align-items: center; +} + +.footer img { + margin-left: 0.5rem; +} + +.footer a { + display: flex; + justify-content: center; + align-items: center; +} + +.title a { + color: #0070f3; + text-decoration: none; +} + +.title a:hover, +.title a:focus, +.title a:active { + text-decoration: underline; +} + +.title { + margin: 0; + line-height: 1.15; + font-size: 4rem; +} + +.title, +.description { + text-align: center; +} + +.description { + line-height: 1.5; + font-size: 1.5rem; +} + +.code { + background: #fafafa; + border-radius: 5px; + padding: 0.75rem; + font-size: 1.1rem; + font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, + monospace; +} + +.grid { + display: flex; + align-items: center; + justify-content: center; + flex-wrap: wrap; + max-width: 800px; + margin-top: 3rem; +} + +.card { + margin: 1rem; + flex-basis: 45%; + padding: 1.5rem; + text-align: left; + color: inherit; + text-decoration: none; + border: 1px solid #eaeaea; + border-radius: 10px; + transition: color 0.15s ease, border-color 0.15s ease; +} + +.card:hover, +.card:focus, +.card:active { + color: #0070f3; + border-color: #0070f3; +} + +.card h3 { + margin: 0 0 1rem 0; + font-size: 1.5rem; +} + +.card p { + margin: 0; + font-size: 1.25rem; + line-height: 1.5; +} + +.logo { + height: 1em; +} + +@media (max-width: 600px) { + .grid { + width: 100%; + flex-direction: column; + } +} diff --git a/packages/dashboard/styles/globals.css b/packages/dashboard/styles/globals.css new file mode 100644 index 00000000..e2e6d0f0 --- /dev/null +++ b/packages/dashboard/styles/globals.css @@ -0,0 +1,16 @@ +html, +body { + padding: 0; + margin: 0; + font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, + Helvetica Neue, sans-serif; +} + +a { + color: inherit; + text-decoration: none; +} + +* { + box-sizing: border-box; +} diff --git a/packages/dashboard/tailwind.config.js b/packages/dashboard/tailwind.config.js new file mode 100644 index 00000000..09477280 --- /dev/null +++ b/packages/dashboard/tailwind.config.js @@ -0,0 +1,18 @@ +module.exports = { + purge: ["./src/**/*.js"], + darkMode: false, // or 'media' or 'class' + theme: { + extend: { + fontFamily: { + sans: ["Metropolis", "Helvetica", "Arial", "Sans-Serif"], + }, + }, + }, + variants: { + extend: { + backgroundColor: ["disabled"], + textColor: ["disabled"], + }, + }, + plugins: [require("@tailwindcss/forms")], +}; diff --git a/packages/handshake-api/Dockerfile b/packages/handshake-api/Dockerfile index 1104cb21..4903f90f 100644 --- a/packages/handshake-api/Dockerfile +++ b/packages/handshake-api/Dockerfile @@ -1,4 +1,4 @@ -FROM node:15.8.0-alpine +FROM node:15.12.0-alpine WORKDIR /usr/app diff --git a/packages/health-check/Dockerfile b/packages/health-check/Dockerfile index 9ecc2f14..d543bbff 100644 --- a/packages/health-check/Dockerfile +++ b/packages/health-check/Dockerfile @@ -1,4 +1,4 @@ -FROM node:15.8.0-alpine +FROM node:15.12.0-alpine WORKDIR /usr/app diff --git a/packages/webapp/Dockerfile b/packages/webapp/Dockerfile index db09d2d7..a732c64d 100644 --- a/packages/webapp/Dockerfile +++ b/packages/webapp/Dockerfile @@ -1,15 +1,24 @@ -FROM node:15.8.0-alpine +FROM node:15.12.0-alpine -RUN apk add --no-cache autoconf automake libtool gcc make g++ zlib-dev file nasm util-linux +RUN apk update && apk add autoconf automake libtool gcc make g++ zlib-dev file nasm util-linux WORKDIR /usr/app +COPY package.json . + +ENV CYPRESS_INSTALL_BINARY 0 + +RUN yarn --no-lockfile + COPY src ./src COPY static ./static COPY gatsby-config.js . -COPY package.json . -ENV CYPRESS_INSTALL_BINARY 0 +ARG WITH_ACCOUNTS=0 + ENV GATSBY_TELEMETRY_DISABLED 1 -RUN yarn --no-lockfile -RUN yarn build +ENV GATSBY_WITH_ACCOUNTS $WITH_ACCOUNTS + +EXPOSE 9000 + +CMD [ "sh", "-c", "yarn build && yarn serve --host 0.0.0.0" ] diff --git a/packages/webapp/package.json b/packages/webapp/package.json index d90f8d64..c920b110 100644 --- a/packages/webapp/package.json +++ b/packages/webapp/package.json @@ -6,6 +6,7 @@ "dependencies": { "@fontsource/metropolis": "^4.2.1", "axios": "0.21.1", + "boolean": "^3.0.2", "bytes": "3.1.0", "classnames": "2.2.6", "gatsby": "^3.0.4", @@ -17,6 +18,7 @@ "gatsby-plugin-sass": "^4.0.2", "gatsby-source-filesystem": "^3.0.0", "http-status-codes": "2.1.4", + "js-cookie": "^2.2.1", "jsonp": "0.2.1", "node-sass": "5.0.0", "path-browserify": "1.0.1", diff --git a/packages/webapp/src/components/HomeTop/HomeTop.js b/packages/webapp/src/components/HomeTop/HomeTop.js index 42e53788..4d1590a3 100644 --- a/packages/webapp/src/components/HomeTop/HomeTop.js +++ b/packages/webapp/src/components/HomeTop/HomeTop.js @@ -1,4 +1,5 @@ import React from "react"; +import { boolean } from "boolean"; import logo from "../../images/logo.svg"; import "./HomeTop.scss"; import { Skynet, Deco1, Deco2 } from "../../svg"; @@ -15,6 +16,18 @@ export default function HomeTop() { The decentralized CDN and file sharing platform for devs. Skynet is the storage foundation for a Free Internet!

+ {boolean(process.env.GATSBY_WITH_ACCOUNTS) && ( +

+ + Sign up now! + {" "} + Already have an account? Go to your{" "} + + dashboard + +

+ )} + diff --git a/packages/webapp/src/components/HomeTop/HomeTop.scss b/packages/webapp/src/components/HomeTop/HomeTop.scss index 572292c3..046c636d 100644 --- a/packages/webapp/src/components/HomeTop/HomeTop.scss +++ b/packages/webapp/src/components/HomeTop/HomeTop.scss @@ -36,10 +36,22 @@ max-width: 560px; margin: 0 auto; + &.auth-links { + font-size: 18px; + + .link { + font-weight: bold; + } + } + @media (min-width: $largebp) { font-size: 24px; max-width: 670px; } + + & + p { + margin-top: 24px; + } } } diff --git a/scripts/crdb_backup.sh b/scripts/crdb_backup.sh new file mode 100644 index 00000000..a216d9db --- /dev/null +++ b/scripts/crdb_backup.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +# Get current working directory (pwd doesn't cut it) +cwd=$(cd -P -- "$(dirname -- "$0")" && pwd -P) +# Set the environment: +set -o allexport +source $cwd/../.env +set +o allexport +# Check for AWS credentials: +if [[ $AWS_ACCESS_KEY_ID == "" || $AWS_SECRET_ACCESS_KEY == "" ]]; then + echo "Missing AWS credentials!" + exit 1 +fi +# Take the current datetime: +DT=`date +%Y-%m-%d` +# Create the backup: +docker exec cockroach \ + cockroach sql \ + --host cockroach:26257 \ + --certs-dir=/certs \ + --execute="BACKUP TO 's3://skynet-crdb-backups/backups/cockroach/$DT?AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID&AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY';" diff --git a/scripts/crdb_restore.sh b/scripts/crdb_restore.sh new file mode 100644 index 00000000..a316984f --- /dev/null +++ b/scripts/crdb_restore.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +BACKUP=$1 +if [[ $BACKUP == "" ]]; then + echo "No backup name given. It should look like '2020-01-29'." + exit 1 +fi + +# Get current working directory (pwd doesn't cut it) +cwd=$(cd -P -- "$(dirname -- "$0")" && pwd -P) +# Set the environment: +set -o allexport +source $cwd/../.env +set +o allexport +# Check for AWS credentials: +if [[ $AWS_ACCESS_KEY_ID == "" || $AWS_SECRET_ACCESS_KEY == "" ]]; then + echo "Missing AWS credentials!" + exit 1 +fi +# Restore the backup: +docker exec cockroach \ + cockroach sql \ + --host cockroach:26257 \ + --certs-dir=/certs \ + --execute="RESTORE DATABASE defaultdb FROM 's3://skynet-crdb-backups/backups/cockroach/$DT?AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID&AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY';" diff --git a/scripts/mongo_backup.sh b/scripts/mongo_backup.sh new file mode 100644 index 00000000..9867bbc3 --- /dev/null +++ b/scripts/mongo_backup.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +# Get current working directory (pwd doesn't cut it) +cwd=$(cd -P -- "$(dirname -- "$0")" && pwd -P) +# Set the environment: +set -o allexport +source $cwd/../.env +set +o allexport +# Check for AWS credentials: +if [[ $AWS_ACCESS_KEY_ID == "" || $AWS_SECRET_ACCESS_KEY == "" ]]; then + echo "Missing AWS credentials!" + exit 1 +fi +# Take the current datetime: +DT=`date +%Y-%m-%d` +# Check if a backup already exists: +totalFoundObjects=$(aws s3 ls s3://skynet-crdb-backups/backups/mongo/ --recursive --summarize | grep "$DT.tgz" | wc -l) +if [ "$totalFoundObjects" -eq "1" ]; then + echo "Backup already exists for today. Exiting." + exit 0 +fi +# Create the backup: +docker exec mongo \ + mongodump \ + -o /data/db/backups/$DT \ + mongodb://$SKYNET_DB_USER:$SKYNET_DB_PASS@$SKYNET_DB_HOST:$SKYNET_DB_PORT +# Compress the backup: +cd $cwd/../docker/data/mongo/db/backups/ && tar -czf $DT.tgz $DT && cd - +# Upload the backup to S3: +aws s3 cp $DT.tgz s3://skynet-crdb-backups/backups/mongo/ +# Clean up +rm -rf $DT.tgz $cwd/../docker/data/mongo/db/backups/$DT diff --git a/scripts/mongo_restore.sh b/scripts/mongo_restore.sh new file mode 100644 index 00000000..f9f4396c --- /dev/null +++ b/scripts/mongo_restore.sh @@ -0,0 +1,40 @@ +#!/bin/bash + +BACKUP=$1 +if [[ $BACKUP == "" ]]; then + echo "No backup name given. It should look like '2020-01-29'." + exit 1 +fi + +# Get current working directory (pwd doesn't cut it) +cwd=$(cd -P -- "$(dirname -- "$0")" && pwd -P) +# Set the environment: +set -o allexport +source $cwd/../.env +set +o allexport +# Check for AWS credentials: +if [[ $AWS_ACCESS_KEY_ID == "" || $AWS_SECRET_ACCESS_KEY == "" ]]; then + echo "Missing AWS credentials!" + exit 1 +fi +# Check if the backup exists: +totalFoundObjects=$(aws s3 ls s3://skynet-crdb-backups/backups/mongo/ --recursive --summarize | grep "$DT.tgz" | wc -l) +if [ "$totalFoundObjects" -eq "0" ]; then + echo "This backup doesn't exist!" + exit 1 +fi +# Get the backup from S3: +aws s3 cp s3://skynet-crdb-backups/backups/mongo/$BACKUP.tgz $BACKUP.tgz +# Prepare a clean `to_restore` dir: +rm -rf $cwd/../docker/data/mongo/db/backups/to_restore +mkdir -p $cwd/../docker/data/mongo/db/backups/to_restore +# Decompress the backup: +tar -xzf $BACKUP.tgz -C $cwd/../docker/data/mongo/db/backups/to_restore +rm $BACKUP.tgz +# Restore the backup: +docker exec mongo \ + mongorestore \ + mongodb://$SKYNET_DB_USER:$SKYNET_DB_PASS@$SKYNET_DB_HOST:$SKYNET_DB_PORT \ + /data/db/backups/to_restore/$BACKUP +# Clean up: +rm -rf $cwd/../docker/data/mongo/db/backups/to_restore diff --git a/setup-scripts/README.md b/setup-scripts/README.md index 7d047421..c6407c61 100644 --- a/setup-scripts/README.md +++ b/setup-scripts/README.md @@ -19,6 +19,8 @@ You may want to fork this repository and replace ssh keys in - [handshake](https://handshake.org) ([github](https://github.com/handshake-org/hsd)): full handshake node - [handshake-api](https://github.com/NebulousLabs/skynet-webportal/tree/master/packages/handshake-api): simple API talking to the handshake node - [read more](https://github.com/NebulousLabs/skynet-webportal/blob/master/packages/handshake-api/README.md) - [webapp](https://github.com/NebulousLabs/skynet-webportal/tree/master/packages/webapp): portal frontend application - [read more](https://github.com/NebulousLabs/skynet-webportal/blob/master/packages/webapp/README.md) + - [kratos](https://www.ory.sh/kratos/): user account management system + - [oathkeeper](https://www.ory.sh/oathkeeper/): identity and access proxy - discord integration - [funds-checker](funds-checker.py): script that checks wallet balance and sends status messages to discord periodically - [health-checker](health-checker.py): script that monitors health-check service for server health issues and reports them to discord periodically @@ -83,10 +85,21 @@ At this point we have almost everything running, we just need to set up your wal - `CLOUDFLARE_AUTH_TOKEN` (optional) if using cloudflare as dns loadbalancer (need to change it in Caddyfile too) - `AWS_ACCESS_KEY_ID` (optional) if using route53 as a dns loadbalancer - `AWS_SECRET_ACCESS_KEY` (optional) if using route53 as a dns loadbalancer + - `PORTAL_NAME` (optional) e.g. `siasky.xyz` + - `DISCORD_BOT_TOKEN` (optional) if you're using Discord notifications for health checks and such + - `SKYNET_DB_USER` (optional) if using `accounts` this is the MongoDB username + - `SKYNET_DB_PASS` (optional) if using `accounts` this is the MongoDB password + - `SKYNET_DB_HOST` (optional) if using `accounts` this is the MongoDB address or container name + - `SKYNET_DB_PORT` (optional) if using `accounts` this is the MongoDB port + - `COOKIE_DOMAIN` (optional) if using `accounts` this is the domain to which your cookies will be issued + - `COOKIE_HASH_KEY` (optional) if using `accounts` hashing secret, at least 32 bytes + - `COOKIE_ENC_KEY` (optional) if using `accounts` encryption key, at least 32 bytes + 1. if you have a custom domain and you configured it in `DOMAIN_NAME`, edit `/home/user/skynet-webportal/docker/caddy/Caddyfile` and uncomment `import custom.domain` 1. only for siasky.net domain instances: edit `/home/user/skynet-webportal/docker/caddy/Caddyfile`, uncomment `import siasky.net` 1. `docker-compose up -d` to restart the services so they pick up new env variables 1. `docker exec caddy caddy reload --config /etc/caddy/Caddyfile` to reload Caddyfile configuration +1. add your custom Kratos configuration to `/home/user/skynet-webportal/docker/kratos/config/kratos.yml` (in particular, the credentials for your mail server should be here, rather than in your source control). For a starting point you can take `docker/kratos/config/kratos.yml.sample`. ## Subdomains diff --git a/setup-scripts/setup-docker-services.sh b/setup-scripts/setup-docker-services.sh index c9aecebd..44728e02 100755 --- a/setup-scripts/setup-docker-services.sh +++ b/setup-scripts/setup-docker-services.sh @@ -23,17 +23,27 @@ docker-compose --version # sanity check # Create dummy .env file for docker-compose usage with variables # * DOMAIN_NAME - the domain name your server is using ie. example.com # * SKYNET_PORTAL_API - absolute url to the portal api ie. https://example.com +# * SKYNET_DASHBOARD_URL - (optional) absolute url to the portal dashboard ie. https://account.example.com # * EMAIL_ADDRESS - this is the administrator contact email you need to supply for communication regarding SSL certification # * HSD_API_KEY - this is auto generated secure key for your handshake service integration -# * CLOUDFLARE_AUTH_TOKEN` - (optional) if using cloudflare as dns loadbalancer (need to change it in Caddyfile too) +# * CLOUDFLARE_AUTH_TOKEN - (optional) if using cloudflare as dns loadbalancer (need to change it in Caddyfile too) # * AWS_ACCESS_KEY_ID - (optional) if using route53 as a dns loadbalancer # * AWS_SECRET_ACCESS_KEY - (optional) if using route53 as a dns loadbalancer # * API_PORT - (optional) the port on which siad is listening, defaults to 9980 # * PORTAL_NAME - the name of the portal, required by the discord bot -# * DISCORD_BOT_TOKEN - required by the discord bot +# * DISCORD_BOT_TOKEN - (optional) only required if you're using the discord notifications integration +# * SKYNET_DB_USER - (optional) if using `accounts` this is the MongoDB username +# * SKYNET_DB_PASS - (optional) if using `accounts` this is the MongoDB password +# * SKYNET_DB_HOST - (optional) if using `accounts` this is the MongoDB address or container name +# * SKYNET_DB_PORT - (optional) if using `accounts` this is the MongoDB port +# * COOKIE_DOMAIN - (optional) if using `accounts` this is the domain to which your cookies will be issued +# * COOKIE_HASH_KEY - (optional) if using `accounts` hashing secret, at least 32 bytes +# * COOKIE_ENC_KEY - (optional) if using `accounts` encryption key, at least 32 bytes +# * CR_IP - (optional) if using `accounts` the public IP/domain of your server, e.g. `helsinki.siasky.net` +# * CR_CLUSTER_NODES - (optional) if using `accounts` the list of servers (with ports) which make up your CockroachDB cluster, e.g. `helsinki.siasky.net:26257,germany.siasky.net:26257,us-east.siasky.net:26257` if ! [ -f /home/user/skynet-webportal/.env ]; then HSD_API_KEY=$(openssl rand -base64 32) # generate safe random key for handshake - printf "DOMAIN_NAME=example.com\nSKYNET_PORTAL_API=https://example.com\nEMAIL_ADDRESS=email@example.com\nSIA_WALLET_PASSWORD=\nHSD_API_KEY=${HSD_API_KEY}\nCLOUDFLARE_AUTH_TOKEN=\nAWS_ACCESS_KEY_ID=\nAWS_SECRET_ACCESS_KEY=\nPORTAL_NAME=\nDISCORD_BOT_TOKEN=\n" > /home/user/skynet-webportal/.env + printf "DOMAIN_NAME=example.com\nSKYNET_PORTAL_API=https://example.com\nSKYNET_DASHBOARD_URL=https://account.example.com\nEMAIL_ADDRESS=email@example.com\nSIA_WALLET_PASSWORD=\nHSD_API_KEY=${HSD_API_KEY}\nCLOUDFLARE_AUTH_TOKEN=\nAWS_ACCESS_KEY_ID=\nAWS_SECRET_ACCESS_KEY=\nPORTAL_NAME=\nDISCORD_BOT_TOKEN=\n" > /home/user/skynet-webportal/.env fi # Start docker container with nginx and client diff --git a/setup-scripts/setup-server.sh b/setup-scripts/setup-server.sh index aaaa97f3..e9e865fe 100755 --- a/setup-scripts/setup-server.sh +++ b/setup-scripts/setup-server.sh @@ -14,7 +14,7 @@ mkdir -p /home/user/.ssh # Install apt packages sudo apt-get update -sudo apt-get -y install ufw tmux ranger htop nload gcc g++ make git vim unzip curl +sudo apt-get -y install ufw tmux ranger htop nload gcc g++ make git vim unzip curl awscli # Setup GIT credentials (so commands like git stash would work) git config --global user.email "devs@nebulous.tech" diff --git a/yarn.lock b/yarn.lock index d81afcb2..3b09c020 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,13 @@ # yarn lockfile v1 +"@apimatic/schema@^0.5.1": + version "0.5.1" + resolved "https://registry.yarnpkg.com/@apimatic/schema/-/schema-0.5.1.tgz#673aa4ddcf31311ba9dfbf0e514cb35ab3b3b9f9" + integrity sha512-ZtAtLOjDEqxot017qRGK+gvNbZv5tNNDmYiYOpBhFiZwulTZUHT9NwJG+V5nIhdEqIpy5E8ty1C4tTzangfNoQ== + dependencies: + lodash.flatten "^4.4.0" + "@ardatan/aggregate-error@0.0.6": version "0.0.6" resolved "https://registry.yarnpkg.com/@ardatan/aggregate-error/-/aggregate-error-0.0.6.tgz#fe6924771ea40fc98dc7a7045c2e872dc8527609" @@ -953,7 +960,14 @@ core-js-pure "^3.0.0" regenerator-runtime "^0.13.4" -"@babel/runtime@^7.10.0", "@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.3.1", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4": +"@babel/runtime@7.12.5": + version "7.12.5" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.12.5.tgz#410e7e487441e1b360c29be715d870d9b985882e" + integrity sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg== + dependencies: + regenerator-runtime "^0.13.4" + +"@babel/runtime@^7.10.0", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.5", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.3.1", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4": version "7.13.10" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.13.10.tgz#47d42a57b6095f4468da440388fdbad8bebf0d7d" integrity sha512-4QPkjJq6Ns3V/RgpEahRk+AGfL0eO6RHHtTWoNNr5mO49G6B5+X6d6THgWEAvTrznU5xYpbAlVKRYcsCgh/Akw== @@ -989,6 +1003,15 @@ globals "^11.1.0" lodash "^4.17.19" +"@babel/types@7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.8.3.tgz#5a383dffa5416db1b73dedffd311ffd0788fb31c" + integrity sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg== + dependencies: + esutils "^2.0.2" + lodash "^4.17.13" + to-fast-properties "^2.0.0" + "@babel/types@^7.0.0-beta.49", "@babel/types@^7.10.5", "@babel/types@^7.12.1", "@babel/types@^7.12.13", "@babel/types@^7.12.17", "@babel/types@^7.12.6", "@babel/types@^7.13.0", "@babel/types@^7.4.4": version "7.13.0" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.13.0.tgz#74424d2816f0171b4100f0ab34e9a374efdf7f80" @@ -1067,11 +1090,18 @@ minimatch "^3.0.4" strip-json-comments "^3.1.1" -"@fontsource/metropolis@^4.2.1": +"@fontsource/metropolis@^4.1.0", "@fontsource/metropolis@^4.2.1": version "4.2.1" resolved "https://registry.yarnpkg.com/@fontsource/metropolis/-/metropolis-4.2.1.tgz#49b69c0e3ff940bf2d94ee45627fa1fe3528f59f" integrity sha512-PhXqIWHqD+HyTkZr1XT7irKhaObRmHLz+d0js/NuoI30md0X4LXMxkolCL5EbmSDXNXW36nT+A1HCKW71oyd6w== +"@fullhuman/postcss-purgecss@^3.1.3": + version "3.1.3" + resolved "https://registry.yarnpkg.com/@fullhuman/postcss-purgecss/-/postcss-purgecss-3.1.3.tgz#47af7b87c9bfb3de4bc94a38f875b928fffdf339" + integrity sha512-kwOXw8fZ0Lt1QmeOOrd+o4Ibvp4UTEBFQbzvWldjlKv5n+G9sXfIPn1hh63IQIL8K8vbvv1oYMJiIUbuy9bGaA== + dependencies: + purgecss "^3.1.3" + "@gatsbyjs/reach-router@^1.3.6": version "1.3.6" resolved "https://registry.yarnpkg.com/@gatsbyjs/reach-router/-/reach-router-1.3.6.tgz#4e8225836959be247890b66f21a3198a0589e34d" @@ -1223,11 +1253,26 @@ is-promise "4.0.0" tslib "~2.0.1" +"@hapi/accept@5.0.1": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@hapi/accept/-/accept-5.0.1.tgz#068553e867f0f63225a506ed74e899441af53e10" + integrity sha512-fMr4d7zLzsAXo28PRRQPXR1o2Wmu+6z+VY1UzDp0iFo13Twj8WePakwXBiqn3E1aAlTpSNzCXdnnQXFhst8h8Q== + dependencies: + "@hapi/boom" "9.x.x" + "@hapi/hoek" "9.x.x" + "@hapi/address@2.x.x": version "2.1.4" resolved "https://registry.yarnpkg.com/@hapi/address/-/address-2.1.4.tgz#5d67ed43f3fd41a69d4b9ff7b56e7c0d1d0a81e5" integrity sha512-QD1PhQk+s31P1ixsX0H0Suoupp3VMXzIVMSwobR3F3MSUO2YCV0B7xqLcUw/Bh8yuvd3LhpyqLQWTNcRmp6IdQ== +"@hapi/boom@9.x.x": + version "9.1.1" + resolved "https://registry.yarnpkg.com/@hapi/boom/-/boom-9.1.1.tgz#89e6f0e01637c2a4228da0d113e8157c93677b04" + integrity sha512-VNR8eDbBrOxBgbkddRYIe7+8DZ+vSbV6qlmaN2x7eWjsUjy2VmQgChkOKcVZIeupEZYj+I0dqNg430OhwzagjA== + dependencies: + "@hapi/hoek" "9.x.x" + "@hapi/bourne@1.x.x": version "1.3.2" resolved "https://registry.yarnpkg.com/@hapi/bourne/-/bourne-1.3.2.tgz#0a7095adea067243ce3283e1b56b8a8f453b242a" @@ -1238,7 +1283,7 @@ resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-8.5.1.tgz#fde96064ca446dec8c55a8c2f130957b070c6e06" integrity sha512-yN7kbciD87WzLGc5539Tn0sApjyiGHAJgKvG9W8C7O+6c7qmoQMfVs0W4bX17eqz6C78QJqqFrtgdK5EWf6Qow== -"@hapi/hoek@^9.0.0": +"@hapi/hoek@9.x.x", "@hapi/hoek@^9.0.0": version "9.1.1" resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.1.1.tgz#9daf5745156fd84b8e9889a2dc721f0c58e894aa" integrity sha512-CAEbWH7OIur6jEOzaai83jq3FmKmv4PmX1JYfs9IrYcGEVI/lyL1EXJGCj7eFVJ0bg5QR8LMxBlEtA+xKiLpFw== @@ -1292,6 +1337,38 @@ resolved "https://registry.yarnpkg.com/@mikaelkristiansson/domready/-/domready-1.0.11.tgz#6a4b5891dccb6402ff4e944de843036ee1ffd4f5" integrity sha512-nEBLOa0JgtqahmPrnJZ18epLiFBzxhdKgo4uhN3TaBFRmM30pEVrS9FAEV4tg92d8PTdU+dYQx2lnpPyFMgMcg== +"@next/env@10.0.8": + version "10.0.8" + resolved "https://registry.yarnpkg.com/@next/env/-/env-10.0.8.tgz#3306c9de20ef187438affbafce0ef966c9e43c3b" + integrity sha512-vWdxAHD6gJn52tN5bxj1VoRgu5lNtRPc/HyYf7V014k2GZ9eKhqoFQGSSMNGHB7WgdUxLVw75+o9Ek9ClOOAjw== + +"@next/polyfill-module@10.0.8": + version "10.0.8" + resolved "https://registry.yarnpkg.com/@next/polyfill-module/-/polyfill-module-10.0.8.tgz#1d033f390389591f227499e286911e3db14c484b" + integrity sha512-JCUGB4/SKQ4LXniv7LKGrpW+W2DGH/CLkrgXgSo/Ze+EJdMDLxC/VFhiuW+TgAaAWLE4gryoswlZBNyHtkPGQA== + +"@next/react-dev-overlay@10.0.8": + version "10.0.8" + resolved "https://registry.yarnpkg.com/@next/react-dev-overlay/-/react-dev-overlay-10.0.8.tgz#a8e841647b74f9720cc60d3e3bd3da225ad12533" + integrity sha512-ygVsvkzYTYIuME+dUUSjCxbNjrJ+Up9Y+CrWEmSSk6HuxajUvrB9vN6RT+PeAzEOQ5er1sWxmVHVdPknQPVWyQ== + dependencies: + "@babel/code-frame" "7.12.11" + anser "1.4.9" + chalk "4.0.0" + classnames "2.2.6" + css.escape "1.5.1" + data-uri-to-buffer "3.0.1" + platform "1.3.6" + shell-quote "1.7.2" + source-map "0.8.0-beta.0" + stacktrace-parser "0.1.10" + strip-ansi "6.0.0" + +"@next/react-refresh-utils@10.0.8": + version "10.0.8" + resolved "https://registry.yarnpkg.com/@next/react-refresh-utils/-/react-refresh-utils-10.0.8.tgz#6129d633e2c0a9b5760de002e998932f08c8baae" + integrity sha512-ZMO77Xs2ioGV/nZB4GRDHgsNT2jhOp+cZIh6c7wf0xw9o/1KoTWN8nxWzwU/laAtkoSS+E6YdhuR4Mw3Ar3CSg== + "@nodelib/fs.scandir@2.1.4": version "2.1.4" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz#d4b3549a5db5de2683e0c1071ab4f140904bbf69" @@ -1321,6 +1398,25 @@ mkdirp "^1.0.4" rimraf "^3.0.2" +"@opentelemetry/api@0.14.0": + version "0.14.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-0.14.0.tgz#4e17d8d2f1da72b19374efa7b6526aa001267cae" + integrity sha512-L7RMuZr5LzMmZiQSQDy9O1jo0q+DaLy6XpYJfIGfYSfoJA5qzYwUP3sP1uMIQ549DvxAgM3ng85EaPTM/hUHwQ== + dependencies: + "@opentelemetry/context-base" "^0.14.0" + +"@opentelemetry/context-base@^0.14.0": + version "0.14.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/context-base/-/context-base-0.14.0.tgz#c67fc20a4d891447ca1a855d7d70fa79a3533001" + integrity sha512-sDOAZcYwynHFTbLo6n8kIbLiVF3a3BLkrmehJUyEbT9F+Smbi47kLGS2gG2g0fjBLR/Lr1InPD7kXL7FaTqEkw== + +"@ory/kratos-client@^0.5.4-alpha.1": + version "0.5.4-alpha.1" + resolved "https://registry.yarnpkg.com/@ory/kratos-client/-/kratos-client-0.5.4-alpha.1.tgz#6a87a90fd858fc4cb792253b109ea53884098107" + integrity sha512-koqwcEtEtGoHdX/WU3O4u6UmbMzbmbA06t5qIZv9S4YauxHZIVZM3VMws1ZK5ObgAMI6O5dCs4WYJrJq+QN48g== + dependencies: + axios "^0.19.2" + "@pmmmwh/react-refresh-webpack-plugin@^0.4.3": version "0.4.3" resolved "https://registry.yarnpkg.com/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.4.3.tgz#1eec460596d200c0236bf195b078a5d1df89b766" @@ -1383,6 +1479,18 @@ escape-string-regexp "^2.0.0" lodash.deburr "^4.1.0" +"@stripe/react-stripe-js@^1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@stripe/react-stripe-js/-/react-stripe-js-1.4.0.tgz#a67e72202297fc409dc2c8c4f3fb98e0b61fa06d" + integrity sha512-Pz5QmG8PgJ3pi8gOWxlngk+ns63p2L1Ds192fn55ykZNRKfGz3G6sfssUVThHn/NAt2Hp1eCEsy/hvlKnXJI6g== + dependencies: + prop-types "^15.7.2" + +"@stripe/stripe-js@^1.13.0": + version "1.13.1" + resolved "https://registry.yarnpkg.com/@stripe/stripe-js/-/stripe-js-1.13.1.tgz#71384666dbd575f154bcdf923f5aa0f7be22d31c" + integrity sha512-mmW+38/RJiWP0B7jmekL+MTDpkDMi34ygZ3j0NIoGa/h6eAXlGDA4lOqqg6aMH9Jd2RzDUndKxvSPPQnFnpdqw== + "@szmarczak/http-timer@^1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" @@ -1390,11 +1498,23 @@ dependencies: defer-to-connect "^1.0.1" +"@tailwindcss/forms@^0.2.1": + version "0.2.1" + resolved "https://registry.yarnpkg.com/@tailwindcss/forms/-/forms-0.2.1.tgz#3244b185854fae1a7cbe8d2456314d8b2d98cf43" + integrity sha512-czfvEdY+J2Ogfd6RUSr/ZSUmDxTujr34M++YLnp2cCPC3oJ4kFvFMaRXA6cEXKw7F1hJuapdjXRjsXIEXGgORg== + dependencies: + mini-svg-data-uri "^1.2.3" + "@tokenizer/token@^0.1.1": version "0.1.1" resolved "https://registry.yarnpkg.com/@tokenizer/token/-/token-0.1.1.tgz#f0d92c12f87079ddfd1b29f614758b9696bc29e3" integrity sha512-XO6INPbZCxdprl+9qa/AAbFFOMzzwqYxpjPgLICrMD6C2FCw6qfJOPcBk6JqqPLSaZ/Qx87qn4rpPmPMwaAK6w== +"@tootallnate/once@1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" + integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw== + "@turist/fetch@^7.1.7": version "7.1.7" resolved "https://registry.yarnpkg.com/@turist/fetch/-/fetch-7.1.7.tgz#a2b1f7ec0265e6fe0946c51eef34bad9b9efc865" @@ -1407,6 +1527,14 @@ resolved "https://registry.yarnpkg.com/@turist/time/-/time-0.0.1.tgz#57637d2a7d1860adb9f9cecbdcc966ce4f551d63" integrity sha512-M2BiThcbxMxSKX8W4z5u9jKZn6datnM3+FpEU+eYw0//l31E2xhqi7vTAuJ/Sf0P3yhp66SDJgPu3bRRpvrdQQ== +"@types/body-parser@*": + version "1.19.0" + resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.0.tgz#0685b3c47eb3006ffed117cdd55164b61f80538f" + integrity sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ== + dependencies: + "@types/connect" "*" + "@types/node" "*" + "@types/common-tags@^1.8.0": version "1.8.0" resolved "https://registry.yarnpkg.com/@types/common-tags/-/common-tags-1.8.0.tgz#79d55e748d730b997be5b7fce4b74488d8b26a6b" @@ -1422,6 +1550,13 @@ resolved "https://registry.yarnpkg.com/@types/configstore/-/configstore-2.1.1.tgz#cd1e8553633ad3185c3f2f239ecff5d2643e92b6" integrity sha1-zR6FU2M60xhcPy8jns/10mQ+krY= +"@types/connect@*": + version "3.4.34" + resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.34.tgz#170a40223a6d666006d93ca128af2beb1d9b1901" + integrity sha512-ePPA/JuI+X0vb+gSWlPKOY0NdNAie/rPUqX2GUPpbZwiKTkSPhjXWuee47E4MtE54QVzGCQMQkAL6JhV2E1+cQ== + dependencies: + "@types/node" "*" + "@types/cookie@^0.4.0": version "0.4.0" resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.4.0.tgz#14f854c0f93d326e39da6e3b6f34f7d37513d108" @@ -1468,6 +1603,40 @@ resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7" integrity sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g== +"@types/express-jwt@0.0.42": + version "0.0.42" + resolved "https://registry.yarnpkg.com/@types/express-jwt/-/express-jwt-0.0.42.tgz#4f04e1fadf9d18725950dc041808a4a4adf7f5ae" + integrity sha512-WszgUddvM1t5dPpJ3LhWNH8kfNN8GPIBrAGxgIYXVCEGx6Bx4A036aAuf/r5WH9DIEdlmp7gHOYvSM6U87B0ag== + dependencies: + "@types/express" "*" + "@types/express-unless" "*" + +"@types/express-serve-static-core@^4.17.18": + version "4.17.18" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.18.tgz#8371e260f40e0e1ca0c116a9afcd9426fa094c40" + integrity sha512-m4JTwx5RUBNZvky/JJ8swEJPKFd8si08pPF2PfizYjGZOKr/svUWPcoUmLow6MmPzhasphB7gSTINY67xn3JNA== + dependencies: + "@types/node" "*" + "@types/qs" "*" + "@types/range-parser" "*" + +"@types/express-unless@*": + version "0.5.1" + resolved "https://registry.yarnpkg.com/@types/express-unless/-/express-unless-0.5.1.tgz#4f440b905e42bbf53382b8207bc337dc5ff9fd1f" + integrity sha512-5fuvg7C69lemNgl0+v+CUxDYWVPSfXHhJPst4yTLcqi4zKJpORCxnDrnnilk3k0DTq/WrAUdvXFs01+vUqUZHw== + dependencies: + "@types/express" "*" + +"@types/express@*": + version "4.17.11" + resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.11.tgz#debe3caa6f8e5fcda96b47bd54e2f40c4ee59545" + integrity sha512-no+R6rW60JEc59977wIxreQVsIEOAYwgCqldrA/vkpCnbD7MqTefO97lmoBe4WE0F156bC4uLSP1XHDOySnChg== + dependencies: + "@types/body-parser" "*" + "@types/express-serve-static-core" "^4.17.18" + "@types/qs" "*" + "@types/serve-static" "*" + "@types/get-port@^3.2.0": version "3.2.0" resolved "https://registry.yarnpkg.com/@types/get-port/-/get-port-3.2.0.tgz#f9e0a11443cc21336470185eae3dfba4495d29bc" @@ -1534,11 +1703,16 @@ resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4= -"@types/lodash@^4.14.92": +"@types/lodash@^4.14.165", "@types/lodash@^4.14.92": version "4.14.168" resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.168.tgz#fe24632e79b7ade3f132891afff86caa5e5ce008" integrity sha512-oVfRvqHV/V6D1yifJbVRU3TMp8OT6o6BG+U9MkwuJ3U8/CsDHvalRpsxBqivn71ztOFZBTfJMvETbqHiaNSj7Q== +"@types/mime@^1": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a" + integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw== + "@types/minimatch@*": version "3.0.3" resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" @@ -1564,7 +1738,7 @@ "@types/node" "*" form-data "^3.0.0" -"@types/node@*", "@types/node@^14.14.10": +"@types/node@*", "@types/node@>=8.1.0", "@types/node@^14.14.10", "@types/node@^14.14.30": version "14.14.33" resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.33.tgz#9e4f8c64345522e4e8ce77b334a8aaa64e2b6c78" integrity sha512-oJqcTrgPUF29oUP8AsUqbXGJNuPutsetaa9kTQAQce5Lx5dTYWV02ScBiT/k1BX/Z7pKeqedmvp39Wu4zR7N7g== @@ -1599,6 +1773,16 @@ resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.4.tgz#15925414e0ad2cd765bfef58842f7e26a7accb24" integrity sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug== +"@types/qs@*": + version "6.9.6" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.6.tgz#df9c3c8b31a247ec315e6996566be3171df4b3b1" + integrity sha512-0/HnwIfW4ki2D8L8c9GVcG5I72s9jP5GSLVF0VIXDW00kmIpA6O33G7a8n59Tmh7Nz0WUC3rSb7PTY/sdW2JzA== + +"@types/range-parser@*": + version "1.2.3" + resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c" + integrity sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA== + "@types/reach__router@^1.3.7": version "1.3.7" resolved "https://registry.yarnpkg.com/@types/reach__router/-/reach__router-1.3.7.tgz#de8ab374259ae7f7499fc1373b9697a5f3cd6428" @@ -1636,6 +1820,14 @@ resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.1.tgz#18845205e86ff0038517aab7a18a62a6b9f71275" integrity sha512-EaCxbanVeyxDRTQBkdLb3Bvl/HK7PBK6UJjsSixB0iHKoWxE5uu2Q/DgtpOhPIojN0Zl1whvOd7PoHs2P0s5eA== +"@types/serve-static@*": + version "1.13.9" + resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.9.tgz#aacf28a85a05ee29a11fb7c3ead935ac56f33e4e" + integrity sha512-ZFqF6qa48XsPdjXV5Gsz0Zqmux2PerNd3a/ktL45mHpa19cuMi/cL8tcxdAx497yRh+QtYPuofjT9oWw9P7nkA== + dependencies: + "@types/mime" "^1" + "@types/node" "*" + "@types/sinonjs__fake-timers@^6.0.1": version "6.0.2" resolved "https://registry.yarnpkg.com/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-6.0.2.tgz#3a84cf5ec3249439015e14049bd3161419bf9eae" @@ -1899,7 +2091,21 @@ acorn-jsx@^5.3.1: resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.1.tgz#fc8661e11b7ac1539c47dbfea2e72b3af34d267b" integrity sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng== -acorn@^7.4.0: +acorn-node@^1.6.1: + version "1.8.2" + resolved "https://registry.yarnpkg.com/acorn-node/-/acorn-node-1.8.2.tgz#114c95d64539e53dede23de8b9d96df7c7ae2af8" + integrity sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A== + dependencies: + acorn "^7.0.0" + acorn-walk "^7.0.0" + xtend "^4.0.2" + +acorn-walk@^7.0.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" + integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== + +acorn@^7.0.0, acorn@^7.4.0: version "7.4.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== @@ -1922,6 +2128,13 @@ adjust-sourcemap-loader@3.0.0: loader-utils "^2.0.0" regex-parser "^2.2.11" +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" + aggregate-error@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" @@ -1970,6 +2183,11 @@ amdefine@>=0.0.4: resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU= +anser@1.4.9: + version "1.4.9" + resolved "https://registry.yarnpkg.com/anser/-/anser-1.4.9.tgz#1f85423a5dcf8da4631a341665ff675b96845760" + integrity sha512-AI+BjTeGt2+WFk4eWcqbQ7snZpDBt8SaLlj0RT2h5xfdWaiy51OjYvqwMrNzJLGy8iOAL6nKDITWO+rd4MkYEA== + anser@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/anser/-/anser-2.0.1.tgz#8d9069291fee18306ffaf2e364a690dcc8ed78ad" @@ -2214,6 +2432,16 @@ arrify@^2.0.1: resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa" integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug== +asn1.js@^5.2.0: + version "5.4.1" + resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07" + integrity sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA== + dependencies: + bn.js "^4.0.0" + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + safer-buffer "^2.1.0" + asn1@~0.2.3: version "0.2.4" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" @@ -2226,6 +2454,14 @@ assert-plus@1.0.0, assert-plus@^1.0.0: resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= +assert@^1.1.1: + version "1.5.0" + resolved "https://registry.yarnpkg.com/assert/-/assert-1.5.0.tgz#55c109aaf6e0aefdb3dc4b71240c70bf574b18eb" + integrity sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA== + dependencies: + object-assign "^4.1.1" + util "0.10.3" + assign-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" @@ -2236,6 +2472,11 @@ ast-types-flow@^0.0.7: resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad" integrity sha1-9wtzXGvKGlycItmCw+Oef+ujva0= +ast-types@0.13.2: + version "0.13.2" + resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.13.2.tgz#df39b677a911a83f3a049644fb74fdded23cea48" + integrity sha512-uWMHxJxtfj/1oZClOxDEV1sQ1HCDkA4MG8Gr69KKeBjEVH0R84WlejZ0y2DcwyBlpAEMltmVYkVgqfLFb2oyiA== + astral-regex@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" @@ -2268,7 +2509,7 @@ async-retry-ng@^2.0.1: resolved "https://registry.yarnpkg.com/async-retry-ng/-/async-retry-ng-2.0.1.tgz#f5285ec1c52654a2ba6a505d0c18b1eadfaebd41" integrity sha512-iitlc2murdQ3/A5Re3CcplQBEf7vOmFrFQ6RFn3+/+zZUyIHYkZnnEziMSa6YIb2Bs2EJEPZWReTxjHqvQbDbw== -async@1.5.2: +async@1.5.2, async@^1.5.0: version "1.5.2" resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo= @@ -2305,7 +2546,7 @@ attr-accept@^2.2.1: resolved "https://registry.yarnpkg.com/attr-accept/-/attr-accept-2.2.2.tgz#646613809660110749e92f2c10833b70968d929b" integrity sha512-7prDjvt9HmqiZ0cl5CRjtS84sEyhsHP2coDkaZKRKVfCDo9s7iw7ChVmar78Gu9pC4SoR/28wFu/G5JJhTnqEg== -autoprefixer@^10.2.4: +autoprefixer@^10.2.4, autoprefixer@^10.2.5: version "10.2.5" resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.2.5.tgz#096a0337dbc96c0873526d7fef5de4428d05382d" integrity sha512-7H4AJZXvSsn62SqZyJCP+1AWwOuoYpUfK6ot9vm0e87XD6mT8lDywc9D9OTJPMULyGcvmIxzTAMeG2Cc+YX+fA== @@ -2339,6 +2580,13 @@ axios@0.21.1, axios@^0.21.0, axios@^0.21.1: dependencies: follow-redirects "^1.10.0" +axios@^0.19.2: + version "0.19.2" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.2.tgz#3ea36c5d8818d0d5f8a8a97a6d36b86cdc00cb27" + integrity sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA== + dependencies: + follow-redirects "1.5.10" + axobject-query@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.2.0.tgz#943d47e10c0b704aa42275e20edf3722648989be" @@ -2415,6 +2663,11 @@ babel-plugin-remove-graphql-queries@^3.0.0: resolved "https://registry.yarnpkg.com/babel-plugin-remove-graphql-queries/-/babel-plugin-remove-graphql-queries-3.0.0.tgz#b5c4e5e29b3bd2110b55a36d5b9076da15b5805e" integrity sha512-eKyztf9FDm4U+aEojPXKlYbE0VM4L2fxU+xHAn21lx13ZR7jT+N5qQNeZk+wR7I/NzwFBy1nuHFui4oXa/Kr0A== +babel-plugin-syntax-jsx@6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946" + integrity sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY= + babel-plugin-transform-react-remove-prop-types@^0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz#f2edaf9b4c6a5fbe5c1d678bfb531078c1555f3a" @@ -2466,7 +2719,7 @@ base64-arraybuffer@0.1.4: resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.1.4.tgz#9818c79e059b1355f97e0428a017c838e90ba812" integrity sha1-mBjHngWbE1X5fgQooBfIOOkLqBI= -base64-js@^1.3.1: +base64-js@^1.0.2, base64-js@^1.3.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== @@ -2543,6 +2796,11 @@ big.js@^5.2.2: resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== +bignumber.js@^9.0.0: + version "9.0.1" + resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.1.tgz#8d7ba124c882bfd8e43260c67475518d0689e4e5" + integrity sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA== + binary-extensions@^1.0.0: version "1.13.1" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" @@ -2584,6 +2842,16 @@ bluebird@^3.7.2: resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== +bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.9: + version "4.12.0" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" + integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== + +bn.js@^5.0.0, bn.js@^5.1.1: + version "5.2.0" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.0.tgz#358860674396c6997771a9d051fcc1b57d4ae002" + integrity sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw== + 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" @@ -2617,6 +2885,11 @@ boolbase@^1.0.0, boolbase@~1.0.0: resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= +boolean@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/boolean/-/boolean-3.0.2.tgz#df1baa18b6a2b0e70840475e1d93ec8fe75b2570" + integrity sha512-RwywHlpCRc3/Wh81MiCKun4ydaIFyW5Ea6JbL6sRCVx5q5irDw7pMXBUFYF/jArQ6YrG36q0kpovc9P/Kd3I4g== + boxen@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/boxen/-/boxen-4.2.0.tgz#e411b62357d6d6d36587c8ac3d5d974daa070e64" @@ -2676,6 +2949,72 @@ braces@^3.0.1, braces@~3.0.2: dependencies: fill-range "^7.0.1" +brorand@^1.0.1, brorand@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= + +browserify-aes@^1.0.0, browserify-aes@^1.0.4: + version "1.2.0" + resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" + integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== + dependencies: + buffer-xor "^1.0.3" + cipher-base "^1.0.0" + create-hash "^1.1.0" + evp_bytestokey "^1.0.3" + inherits "^2.0.1" + safe-buffer "^5.0.1" + +browserify-cipher@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" + integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== + dependencies: + browserify-aes "^1.0.4" + browserify-des "^1.0.0" + evp_bytestokey "^1.0.0" + +browserify-des@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" + integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== + dependencies: + cipher-base "^1.0.1" + des.js "^1.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.1.0.tgz#b2fd06b5b75ae297f7ce2dc651f918f5be158c8d" + integrity sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog== + dependencies: + bn.js "^5.0.0" + randombytes "^2.0.1" + +browserify-sign@^4.0.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.1.tgz#eaf4add46dd54be3bb3b36c0cf15abbeba7956c3" + integrity sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg== + dependencies: + bn.js "^5.1.1" + browserify-rsa "^4.0.1" + create-hash "^1.2.0" + create-hmac "^1.1.7" + elliptic "^6.5.3" + inherits "^2.0.4" + parse-asn1 "^5.1.5" + readable-stream "^3.6.0" + safe-buffer "^5.2.0" + +browserify-zlib@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" + integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA== + dependencies: + pako "~1.0.5" + browserslist@4.14.2: version "4.14.2" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.14.2.tgz#1b3cec458a1ba87588cc5e9be62f19b6d48813ce" @@ -2686,6 +3025,17 @@ browserslist@4.14.2: escalade "^3.0.2" node-releases "^1.1.61" +browserslist@4.16.1: + version "4.16.1" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.1.tgz#bf757a2da376b3447b800a16f0f1c96358138766" + integrity sha512-UXhDrwqsNcpTYJBTZsbGATDxZbiVDsx6UjpmRUmtnP10pr8wAYr5LgFoEFw9ixriQH2mv/NX2SfGzE/o8GndLA== + dependencies: + caniuse-lite "^1.0.30001173" + colorette "^1.2.1" + electron-to-chromium "^1.3.634" + escalade "^3.1.1" + node-releases "^1.1.69" + browserslist@^4.0.0, browserslist@^4.12.2, browserslist@^4.14.5, browserslist@^4.16.3: version "4.16.3" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.3.tgz#340aa46940d7db878748567c5dea24a48ddf3717" @@ -2721,6 +3071,11 @@ buffer-crc32@~0.2.3: resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI= +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.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" @@ -2731,6 +3086,28 @@ buffer-indexof@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-indexof/-/buffer-indexof-1.1.1.tgz#52fabcc6a606d1a00302802648ef68f639da268c" integrity sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g== +buffer-xor@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" + integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= + +buffer@5.6.0: + version "5.6.0" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.6.0.tgz#a31749dc7d81d84db08abf937b6b8c4033f62786" + integrity sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw== + dependencies: + base64-js "^1.0.2" + ieee754 "^1.1.4" + +buffer@^4.3.0: + version "4.9.2" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8" + integrity sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg== + dependencies: + base64-js "^1.0.2" + ieee754 "^1.1.4" + isarray "^1.0.0" + buffer@^5.5.0, buffer@^5.7.0: version "5.7.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" @@ -2747,6 +3124,11 @@ buffer@^6.0.1: base64-js "^1.3.1" ieee754 "^1.2.1" +builtin-status-codes@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" + integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug= + busboy@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/busboy/-/busboy-0.3.1.tgz#170899274c5bf38aae27d5c62b71268cd585fd1b" @@ -2759,7 +3141,7 @@ bytes@3.0.0: resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= -bytes@3.1.0: +bytes@3.1.0, bytes@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== @@ -2890,6 +3272,11 @@ camel-case@4.1.2: pascal-case "^3.1.2" tslib "^2.0.3" +camelcase-css@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5" + integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA== + camelcase-keys@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7" @@ -2932,7 +3319,7 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001125, caniuse-lite@^1.0.30001181, caniuse-lite@^1.0.30001196: +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001125, caniuse-lite@^1.0.30001173, caniuse-lite@^1.0.30001179, caniuse-lite@^1.0.30001181, caniuse-lite@^1.0.30001196: version "1.0.30001198" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001198.tgz#ed2d9b5f060322ba2efa42afdc56dee3255473f4" integrity sha512-r5GGgESqOPZzwvdLVER374FpQu2WluCF1Z2DSiFJ89KSmGjT0LVKjgv4NcAqHmGWF9ihNpqRI9KXO9Ex4sKsgA== @@ -2956,6 +3343,14 @@ chalk@2.4.2, chalk@^2.0.0, chalk@^2.4.1, chalk@^2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" +chalk@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.0.0.tgz#6e98081ed2d17faab615eb52ac66ec1fe6209e72" + integrity sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" @@ -3013,6 +3408,21 @@ check-more-types@^2.24.0: resolved "https://registry.yarnpkg.com/check-more-types/-/check-more-types-2.24.0.tgz#1420ffb10fd444dcfc79b43891bbfffd32a84600" integrity sha1-FCD/sQ/URNz8ebQ4kbv//TKoRgA= +chokidar@3.5.1, chokidar@^3.4.2, chokidar@^3.4.3, chokidar@^3.5.1: + version "3.5.1" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.1.tgz#ee9ce7bbebd2b79f49f304799d5468e31e14e68a" + integrity sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw== + dependencies: + anymatch "~3.1.1" + braces "~3.0.2" + glob-parent "~5.1.0" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.5.0" + optionalDependencies: + fsevents "~2.3.1" + chokidar@^2.1.8: version "2.1.8" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" @@ -3032,21 +3442,6 @@ chokidar@^2.1.8: optionalDependencies: fsevents "^1.2.7" -chokidar@^3.4.2, chokidar@^3.4.3, chokidar@^3.5.1: - version "3.5.1" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.1.tgz#ee9ce7bbebd2b79f49f304799d5468e31e14e68a" - integrity sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw== - dependencies: - anymatch "~3.1.1" - braces "~3.0.2" - glob-parent "~5.1.0" - is-binary-path "~2.1.0" - is-glob "~4.0.1" - normalize-path "~3.0.0" - readdirp "~3.5.0" - optionalDependencies: - fsevents "~2.3.1" - chownr@^1.1.1: version "1.1.4" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" @@ -3069,6 +3464,14 @@ ci-info@2.0.0, ci-info@^2.0.0: resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== +cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" + integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + class-utils@^0.3.5: version "0.3.6" resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" @@ -3079,7 +3482,7 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" -classnames@2.2.6: +classnames@2.2.6, classnames@^2.2.6: version "2.2.6" resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce" integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q== @@ -3316,7 +3719,7 @@ commander@^5.1.0: resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae" integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg== -commander@^6.2.0: +commander@^6.0.0, commander@^6.2.0: version "6.2.1" resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c" integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA== @@ -3405,11 +3808,21 @@ connect-history-api-fallback@^1.6.0: resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz#8b32089359308d111115d81cad3fceab888f97bc" integrity sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg== +console-browserify@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" + integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA== + console-control-strings@^1.0.0, console-control-strings@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= +constants-browserify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" + integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U= + contains-path@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" @@ -3576,11 +3989,42 @@ countup.js@^1.9.3: resolved "https://registry.yarnpkg.com/countup.js/-/countup.js-1.9.3.tgz#ce3e50cd7160441e478f07da31895edcc0f1c9dd" integrity sha1-zj5QzXFgRB5HjwfaMYle3MDxyd0= +create-ecdh@^4.0.0: + version "4.0.4" + resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" + integrity sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A== + dependencies: + bn.js "^4.1.0" + elliptic "^6.5.3" + create-gatsby@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/create-gatsby/-/create-gatsby-1.0.0.tgz#f977ffcf5e005c9885f6a89efcf6a9bbdd92ac17" integrity sha512-eDa6rpm6sNrqrnzZDBRsbiCvEvUibAswliYcwqEP1ibgljQ88TXZP4FLnX6//Epj4zTwpUPVYALWVluOgBNGCA== +create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" + integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== + dependencies: + cipher-base "^1.0.1" + inherits "^2.0.1" + md5.js "^1.3.4" + ripemd160 "^2.0.1" + sha.js "^2.4.0" + +create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" + integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== + dependencies: + cipher-base "^1.0.3" + create-hash "^1.1.0" + inherits "^2.0.1" + ripemd160 "^2.0.0" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + create-require@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" @@ -3613,6 +4057,23 @@ cross-spawn@^6.0.0, cross-spawn@^6.0.5: shebang-command "^1.2.0" which "^1.2.9" +crypto-browserify@3.12.0, crypto-browserify@^3.11.0: + version "3.12.0" + resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" + integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== + dependencies: + browserify-cipher "^1.0.0" + browserify-sign "^4.0.0" + create-ecdh "^4.0.0" + create-hash "^1.1.0" + create-hmac "^1.1.0" + diffie-hellman "^5.0.0" + inherits "^2.0.1" + pbkdf2 "^3.0.3" + public-encrypt "^4.0.0" + randombytes "^2.0.0" + randomfill "^1.0.3" + crypto-random-string@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5" @@ -3695,12 +4156,17 @@ css-tree@^1.1.2: mdn-data "2.0.14" source-map "^0.6.1" +css-unit-converter@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/css-unit-converter/-/css-unit-converter-1.1.2.tgz#4c77f5a1954e6dbff60695ecb214e3270436ab21" + integrity sha512-IiJwMC8rdZE0+xiEZHeru6YoONC4rfPMqGm2W85jMIbkFvv5nFTwJVFHam2eFrN6txmoUYFAFXiv8ICVeTO0MA== + css-what@^3.2.1: version "3.4.2" resolved "https://registry.yarnpkg.com/css-what/-/css-what-3.4.2.tgz#ea7026fcb01777edbde52124e21f327e7ae950e4" integrity sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ== -css.escape@^1.5.1: +css.escape@1.5.1, css.escape@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/css.escape/-/css.escape-1.5.1.tgz#42e27d4fa04ae32f931a4b4d4191fa9cddee97cb" integrity sha1-QuJ9T6BK4y+TGktNQZH6nN3ul8s= @@ -3761,6 +4227,22 @@ cssnano-preset-default@^4.0.7: postcss-svgo "^4.0.2" postcss-unique-selectors "^4.0.1" +cssnano-preset-simple@1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/cssnano-preset-simple/-/cssnano-preset-simple-1.2.2.tgz#c631bf79ffec7fdfc4069e2f2da3ca67d99d8413" + integrity sha512-gtvrcRSGtP3hA/wS8mFVinFnQdEsEpm3v4I/s/KmNjpdWaThV/4E5EojAzFXxyT5OCSRPLlHR9iQexAqKHlhGQ== + dependencies: + caniuse-lite "^1.0.30001179" + postcss "^7.0.32" + +cssnano-simple@1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/cssnano-simple/-/cssnano-simple-1.2.2.tgz#72c2c3970e67123c3b4130894a30dc1050267007" + integrity sha512-4slyYc1w4JhSbhVX5xi9G0aQ42JnRyPg+7l7cqoNyoIDzfWx40Rq3JQZnoAWDu60A4AvKVp9ln/YSUOdhDX68g== + dependencies: + cssnano-preset-simple "1.2.2" + postcss "^7.0.32" + cssnano-util-get-arguments@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/cssnano-util-get-arguments/-/cssnano-util-get-arguments-4.0.0.tgz#ed3a08299f21d75741b20f3b81f194ed49cc150f" @@ -3885,6 +4367,11 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" +data-uri-to-buffer@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-3.0.1.tgz#594b8973938c5bc2c33046535785341abc4f3636" + integrity sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og== + dataloader@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/dataloader/-/dataloader-2.0.0.tgz#41eaf123db115987e21ca93c005cd7753c55fe6f" @@ -3900,18 +4387,25 @@ date-fns@^2.14.0: resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.19.0.tgz#65193348635a28d5d916c43ec7ce6fbd145059e1" integrity sha512-X3bf2iTPgCAQp9wvjOQytnf5vO5rESYRXlPIVcgSbtT5OTScPcsf9eZU+B/YIkKAtYr5WeCii58BgATrNitlWg== -dayjs@^1.9.3: +dayjs@^1.10.4, dayjs@^1.9.3: version "1.10.4" resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.10.4.tgz#8e544a9b8683f61783f570980a8a80eaf54ab1e2" integrity sha512-RI/Hh4kqRc1UKLOAf/T5zdMMX5DQIlDxwUe3wSyMMnEbGunnpENCdbUgM+dW7kXidZqCttBrmw7BhN4TMddkCw== -debug@2.6.9, debug@^2.1.3, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.9: +debug@2, debug@2.6.9, debug@^2.1.3, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== dependencies: ms "2.0.0" +debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.2.0, debug@^4.3.1, debug@~4.3.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" + integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== + dependencies: + ms "2.1.2" + debug@4.3.2: version "4.3.2" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b" @@ -3919,6 +4413,13 @@ debug@4.3.2: dependencies: ms "2.1.2" +debug@=3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" + integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== + dependencies: + ms "2.0.0" + debug@^3.0.0, debug@^3.1.0, debug@^3.1.1, debug@^3.2.6, debug@^3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" @@ -3926,13 +4427,6 @@ debug@^3.0.0, debug@^3.1.0, debug@^3.1.1, debug@^3.2.6, debug@^3.2.7: dependencies: ms "^2.1.1" -debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.2.0, debug@^4.3.1, debug@~4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" - integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== - dependencies: - ms "2.1.2" - decamelize-keys@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9" @@ -4004,6 +4498,11 @@ deep-object-diff@^1.1.0: resolved "https://registry.yarnpkg.com/deep-object-diff/-/deep-object-diff-1.1.0.tgz#d6fabf476c2ed1751fc94d5ca693d2ed8c18bc5a" integrity sha512-b+QLs5vHgS+IoSNcUE4n9HP2NwcHj7aqnJWsjPtuG75Rh5TOaGt0OjAYInh77d5T16V5cRDC+Pw/6ZZZiETBGw== +deepmerge@^2.1.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-2.2.1.tgz#5d3ff22a01c00f645405a2fbc17d0778a1801170" + integrity sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA== + default-gateway@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-4.2.0.tgz#167104c7500c2115f6dd69b0a536bb8ed720552b" @@ -4046,6 +4545,11 @@ define-property@^2.0.2: is-descriptor "^1.0.2" isobject "^3.0.1" +defined@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" + integrity sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM= + del@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/del/-/del-4.1.1.tgz#9e8f117222ea44a31ff3a156c049b99052a9f0b4" @@ -4093,6 +4597,14 @@ depd@~1.1.2: resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= +des.js@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843" + integrity sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA== + dependencies: + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + destroy@~1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" @@ -4132,6 +4644,15 @@ detect-port@^1.3.0: address "^1.0.1" debug "^2.6.0" +detective@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/detective/-/detective-5.2.0.tgz#feb2a77e85b904ecdea459ad897cc90a99bd2a7b" + integrity sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg== + dependencies: + acorn-node "^1.6.1" + defined "^1.0.0" + minimist "^1.1.1" + devcert@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/devcert/-/devcert-1.1.3.tgz#ff8119efae52ebf2449531b7482ae0f7211542e9" @@ -4167,6 +4688,11 @@ dicer@0.3.0: dependencies: streamsearch "0.1.2" +didyoumean@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/didyoumean/-/didyoumean-1.2.1.tgz#e92edfdada6537d484d73c0172fd1eba0c4976ff" + integrity sha1-6S7f2tplN9SE1zwBcv0eugxJdv8= + diff-sequences@^25.2.6: version "25.2.6" resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-25.2.6.tgz#5f467c00edd35352b7bca46d7927d60e687a76dd" @@ -4177,6 +4703,15 @@ diff@^4.0.1: resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== +diffie-hellman@^5.0.0: + version "5.0.3" + resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" + integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== + dependencies: + bn.js "^4.1.0" + miller-rabin "^4.0.0" + randombytes "^2.0.0" + dir-glob@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" @@ -4241,6 +4776,11 @@ dom-serializer@0: domelementtype "^2.0.1" entities "^2.0.0" +domain-browser@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" + integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== + domelementtype@1, domelementtype@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" @@ -4296,12 +4836,19 @@ 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" integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= -electron-to-chromium@^1.3.564, electron-to-chromium@^1.3.649: +electron-to-chromium@^1.3.564, electron-to-chromium@^1.3.634, electron-to-chromium@^1.3.649: version "1.3.685" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.685.tgz#f636d17c9c232c925f8bbfbff4f86303da091ff9" integrity sha512-C3oFZNkJ8lz85ADqr3hzpjBc2ciejMRN2SCd/D0hwcqpr6MGxfdN/j89VN6l+ERTuCUvhg0VYsf40Q4qTz4bhQ== @@ -4311,6 +4858,19 @@ elegant-spinner@^1.0.1: resolved "https://registry.yarnpkg.com/elegant-spinner/-/elegant-spinner-1.0.1.tgz#db043521c95d7e303fd8f345bedc3349cfb0729e" integrity sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4= +elliptic@^6.5.3: + version "6.5.4" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" + integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== + dependencies: + bn.js "^4.11.9" + brorand "^1.1.0" + hash.js "^1.0.0" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" + emoji-regex@^7.0.1: version "7.0.3" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" @@ -4788,7 +5348,7 @@ esutils@^2.0.2: resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== -etag@~1.8.1: +etag@1.8.1, etag@~1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= @@ -4816,7 +5376,7 @@ eventemitter3@^4.0.0: resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== -events@^3.2.0: +events@^3.0.0, events@^3.2.0: version "3.3.0" resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== @@ -4828,6 +5388,14 @@ eventsource@1.0.7, eventsource@^1.0.7: dependencies: original "^1.0.0" +evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" + integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== + dependencies: + md5.js "^1.3.4" + safe-buffer "^5.1.1" + execa@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" @@ -4912,6 +5480,21 @@ express-graphql@^0.9.0: http-errors "^1.7.3" raw-body "^2.4.1" +express-jwt@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/express-jwt/-/express-jwt-6.0.0.tgz#20886c730983ffb1c706a4383235df86eff349b8" + integrity sha512-C26y9myRjx7CyhZ+BAT3p+gQyRCoDZ7qo8plCvLDaRT6je6ALIAQknT6XLVQGFKwIy/Ux7lvM2MNap5dt0T7gA== + dependencies: + async "^1.5.0" + express-unless "^0.3.0" + jsonwebtoken "^8.1.0" + lodash.set "^4.0.0" + +express-unless@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/express-unless/-/express-unless-0.3.1.tgz#2557c146e75beb903e2d247f9b5ba01452696e20" + integrity sha1-JVfBRudb65A+LSR/m1ugFFJpbiA= + express@^4.17.1: version "4.17.1" resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" @@ -5055,12 +5638,19 @@ fast-levenshtein@^2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= +fast-levenshtein@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-3.0.0.tgz#37b899ae47e1090e40e3fd2318e4d5f0142ca912" + integrity sha512-hKKNajm46uNmTlhHSyZkmToAc56uZJwYq7yrciZjqOxnlfQwERDQJmHPUp7m1m9wx8vgOe8IaCKZ5Kv2k1DdCQ== + dependencies: + fastest-levenshtein "^1.0.7" + fast-safe-stringify@^2.0.7: version "2.0.7" resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz#124aa885899261f68aedb42a7c080de9da608743" integrity sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA== -fastest-levenshtein@^1.0.12: +fastest-levenshtein@^1.0.12, fastest-levenshtein@^1.0.7: version "1.0.12" resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz#9990f7d3a88cc5a9ffd1f1745745251700d497e2" integrity sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow== @@ -5197,7 +5787,7 @@ finalhandler@~1.1.2: statuses "~1.5.0" unpipe "~1.0.0" -find-cache-dir@^3.3.1: +find-cache-dir@3.3.1, find-cache-dir@^3.3.1: version "3.3.1" resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.1.tgz#89b33fad4a4670daa94f855f7fbe31d6d84fe880" integrity sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ== @@ -5264,6 +5854,13 @@ flatted@^3.1.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.1.1.tgz#c4b489e80096d9df1dfc97c79871aea7c617c469" integrity sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA== +follow-redirects@1.5.10: + version "1.5.10" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.10.tgz#7b7a9f9aea2fdff36786a94ff643ed07f4ff5e2a" + integrity sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ== + dependencies: + debug "=3.1.0" + follow-redirects@^1.0.0, follow-redirects@^1.10.0: version "1.13.3" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.3.tgz#e5598ad50174c1bc4e872301e82ac2cd97f90267" @@ -5336,6 +5933,19 @@ formidable@^1.2.2: resolved "https://registry.yarnpkg.com/formidable/-/formidable-1.2.2.tgz#bf69aea2972982675f00865342b982986f6b8dd9" integrity sha512-V8gLm+41I/8kguQ4/o1D3RIHRmhYFG4pnNyonvua+40rqcEmT4+V71yaZ3B457xbbgCsCfjSPi65u/W6vK1U5Q== +formik@^2.2.6: + version "2.2.6" + resolved "https://registry.yarnpkg.com/formik/-/formik-2.2.6.tgz#378a4bafe4b95caf6acf6db01f81f3fe5147559d" + integrity sha512-Kxk2zQRafy56zhLmrzcbryUpMBvT0tal5IvcifK5+4YNGelKsnrODFJ0sZQRMQboblWNym4lAW3bt+tf2vApSA== + dependencies: + deepmerge "^2.1.1" + hoist-non-react-statics "^3.3.0" + lodash "^4.17.14" + lodash-es "^4.17.14" + react-fast-compare "^2.0.1" + tiny-warning "^1.0.2" + tslib "^1.10.0" + forwarded@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" @@ -5390,7 +6000,7 @@ fs-extra@^8.1.0: jsonfile "^4.0.0" universalify "^0.1.0" -fs-extra@^9.0.0, fs-extra@^9.0.1: +fs-extra@^9.0.0, fs-extra@^9.0.1, fs-extra@^9.1.0: version "9.1.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== @@ -5934,6 +6544,13 @@ get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: has "^1.0.3" has-symbols "^1.0.1" +get-orientation@1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/get-orientation/-/get-orientation-1.1.2.tgz#20507928951814f8a91ded0a0e67b29dfab98947" + integrity sha512-/pViTfifW+gBbh/RnlFYHINvELT9Znt+SYyDKAUL6uV6By019AK/s+i9XP4jSwq7lwP38Fd8HVeTxym3+hkwmQ== + dependencies: + stream-parser "^0.3.1" + get-own-enumerable-property-symbols@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz#b5fde77f22cbe35f390b4e089922c50bce6ef664" @@ -6380,6 +6997,23 @@ has@^1.0.0, has@^1.0.3: dependencies: function-bind "^1.1.1" +hash-base@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" + integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== + dependencies: + inherits "^2.0.4" + readable-stream "^3.6.0" + safe-buffer "^5.2.0" + +hash.js@^1.0.0, hash.js@^1.0.3: + version "1.1.7" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" + integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.1" + hasha@^5.2.0: version "5.2.2" resolved "https://registry.yarnpkg.com/hasha/-/hasha-5.2.2.tgz#a48477989b3b327aea3c04f53096d816d97522a1" @@ -6404,6 +7038,11 @@ hastscript@^6.0.0: property-information "^5.0.0" space-separated-tokens "^1.0.0" +he@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + hex-color-regex@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e" @@ -6422,6 +7061,22 @@ highlight.js@^10.4.1, highlight.js@~10.6.0: resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.6.0.tgz#0073aa71d566906965ba6e1b7be7b2682f5e18b6" integrity sha512-8mlRcn5vk/r4+QcqerapwBYTe+iPL5ih6xrNylxrnBdHQiijDETfXX7VIxC3UiCRiINBJfANBAsPzAvRQj8RpQ== +hmac-drbg@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= + dependencies: + hash.js "^1.0.3" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.1" + +hoist-non-react-statics@^3.3.0: + version "3.3.2" + resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" + integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== + dependencies: + react-is "^16.7.0" + hosted-git-info@^2.1.4: version "2.8.8" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488" @@ -6478,6 +7133,11 @@ html-entities@^2.1.0: resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.1.0.tgz#f5de1f8d5e1f16859a74aa73a90f0db502ca723a" integrity sha512-u+OHVGMH5P1HlaTFp3M4HolRnWepgx5rAnYBo+7/TrBZahuJjgQ4TMv2GjQ4IouGDzkgXYeOI/NQuF95VOUOsQ== +html-tags@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.1.0.tgz#7b5e6f7e665e9fb41f30007ed9e0d41e97fb2140" + integrity sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg== + htmlparser2@^3.10.1: version "3.10.1" resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f" @@ -6553,6 +7213,15 @@ http-parser-js@>=0.5.1: resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.3.tgz#01d2709c79d41698bb01d4decc5e9da4e4a033d9" integrity sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg== +http-proxy-agent@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz#8a8c8ef7f5932ccf953c296ca8291b95aa74aa3a" + integrity sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg== + dependencies: + "@tootallnate/once" "1" + agent-base "6" + debug "4" + http-proxy-middleware@0.19.1: version "0.19.1" resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz#183c7dc4aa1479150306498c210cdaf96080a43a" @@ -6581,11 +7250,24 @@ http-signature@~1.2.0: jsprim "^1.2.2" sshpk "^1.7.0" -http-status-codes@2.1.4, http-status-codes@^2.1.2: +http-status-codes@2.1.4, http-status-codes@^2.1.2, http-status-codes@^2.1.4: version "2.1.4" resolved "https://registry.yarnpkg.com/http-status-codes/-/http-status-codes-2.1.4.tgz#453d99b4bd9424254c4f6a9a3a03715923052798" integrity sha512-MZVIsLKGVOVE1KEnldppe6Ij+vmemMuApDfjhVSLzyYP+td0bREEYyAoIw9yFePoBXManCuBqmiNP5FqJS5Xkg== +https-browserify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" + integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= + +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" @@ -6619,7 +7301,7 @@ icss-utils@^5.0.0, icss-utils@^5.1.0: resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae" integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA== -ieee754@^1.1.13, ieee754@^1.2.1: +ieee754@^1.1.13, ieee754@^1.1.4, ieee754@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== @@ -6715,11 +7397,16 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.4, inherits@^2.0.0, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3: +inherits@2, inherits@2.0.4, inherits@^2.0.0, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3, inherits@~2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== +inherits@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" + integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE= + inherits@2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" @@ -7396,7 +8083,7 @@ jest-get-type@^25.2.6: resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-25.2.6.tgz#0b0a32fab8908b44d508be81681487dbabb8d877" integrity sha512-DxjtyzOHjObRM+sM1knti6or+eOgcGU4xVSb2HNP1TqO4ahsT+rqZg+nyqHWJSvWgKC5cG3QjGFBqxLghiF/Ig== -jest-worker@^24.9.0: +jest-worker@24.9.0, jest-worker@^24.9.0: version "24.9.0" resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-24.9.0.tgz#5dbfdb5b2d322e98567898238a9697bcce67b3e5" integrity sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw== @@ -7429,6 +8116,11 @@ js-base64@^2.1.8: resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.6.4.tgz#f4e686c5de1ea1f867dbcad3d46d969428df98c4" integrity sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ== +js-cookie@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/js-cookie/-/js-cookie-2.2.1.tgz#69e106dc5d5806894562902aa5baec3744e9b2b8" + integrity sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ== + "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -7457,6 +8149,13 @@ jsesc@~0.5.0: resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= +json-bigint@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-bigint/-/json-bigint-1.0.0.tgz#ae547823ac0cad8398667f8cd9ef4730f5b01ff1" + integrity sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ== + dependencies: + bignumber.js "^9.0.0" + json-buffer@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" @@ -7544,6 +8243,22 @@ jsonp@0.2.1, jsonp@^0.2.1: dependencies: debug "^2.1.3" +jsonwebtoken@^8.1.0, 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" @@ -7562,6 +8277,39 @@ jsprim@^1.2.2: array-includes "^3.1.2" object.assign "^4.1.2" +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" + +jwks-rsa@^1.12.2: + version "1.12.3" + resolved "https://registry.yarnpkg.com/jwks-rsa/-/jwks-rsa-1.12.3.tgz#40232f85d16734cb82837f38bb3e350a34435400" + integrity sha512-cFipFDeYYaO9FhhYJcZWX/IyZgc0+g316rcHnDpT2dNRNIE/lMOmWKKqp09TkJoYlNFzrEVODsR4GgXJMgWhnA== + dependencies: + "@types/express-jwt" "0.0.42" + axios "^0.21.1" + debug "^4.1.0" + http-proxy-agent "^4.0.1" + https-proxy-agent "^5.0.0" + jsonwebtoken "^8.5.1" + limiter "^1.1.5" + lru-memoizer "^2.1.2" + ms "^2.1.2" + proxy-from-env "^1.1.0" + +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.0.0" resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.0.0.tgz#44923ba39e68b12a7cec7df6c3268c031f2ef373" @@ -7615,6 +8363,11 @@ klona@^2.0.4: resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.4.tgz#7bb1e3affb0cb8624547ef7e8f6708ea2e39dfc0" integrity sha512-ZRbnvdg/NxqzC7L9Uyqzf4psi1OM4Cuc+sJAkQPjO6XkQIJTNbfK2Rsmbw8fx1p2mkZdp2FZYo2+LwXYY/uwIA== +ky@0.25.1: + version "0.25.1" + resolved "https://registry.yarnpkg.com/ky/-/ky-0.25.1.tgz#0df0bd872a9cc57e31acd5dbc1443547c881bfbc" + integrity sha512-PjpCEWlIU7VpiMVrTwssahkYXX1by6NCT0fhTUX34F3DTinARlgMpriuroolugFPcMgpPWrOW4mTb984Qm1RXA== + language-subtag-registry@~0.3.2: version "0.3.21" resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.21.tgz#04ac218bea46f04cb039084602c6da9e788dd45a" @@ -7647,6 +8400,19 @@ levn@^0.4.1: prelude-ls "^1.2.1" type-check "~0.4.0" +limiter@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/limiter/-/limiter-1.1.5.tgz#8f92a25b3b16c6131293a0cc834b4a838a2aa7c2" + integrity sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA== + +line-column@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/line-column/-/line-column-1.0.2.tgz#d25af2936b6f4849172b312e4792d1d987bc34a2" + integrity sha1-0lryk2tvSEkXKzEuR5LR2Ye8NKI= + dependencies: + isarray "^1.0.0" + isobject "^2.0.0" + lines-and-columns@^1.1.6: version "1.1.6" resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" @@ -7820,7 +8586,12 @@ lock@^1.0.0: resolved "https://registry.yarnpkg.com/lock/-/lock-1.1.0.tgz#53157499d1653b136ca66451071fca615703fa55" integrity sha1-UxV0mdFlOxNspmRRBx/KYVcD+lU= -lodash.clonedeep@4.5.0: +lodash-es@^4.17.14, lodash-es@^4.17.15: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee" + integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw== + +lodash.clonedeep@4.5.0, lodash.clonedeep@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8= @@ -7840,6 +8611,11 @@ lodash.every@^4.6.0: resolved "https://registry.yarnpkg.com/lodash.every/-/lodash.every-4.6.0.tgz#eb89984bebc4364279bb3aefbbd1ca19bfa6c6a7" integrity sha1-64mYS+vENkJ5uzrvu9HKGb+mxqc= +lodash.flatmap@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.flatmap/-/lodash.flatmap-4.5.0.tgz#ef8cbf408f6e48268663345305c6acc0b778702e" + integrity sha1-74y/QI9uSCaGYzRTBcaswLd4cC4= + lodash.flatten@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f" @@ -7860,11 +8636,36 @@ lodash.get@^4: resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= +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.map@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.map/-/lodash.map-4.6.0.tgz#771ec7839e3473d9c4cde28b19394c3562f4f6d3" @@ -7880,11 +8681,26 @@ lodash.memoize@^4.1.2: resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= -lodash.once@^4.1.1: +lodash.once@^4.0.0, lodash.once@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w= +lodash.set@^4.0.0: + version "4.3.2" + resolved "https://registry.yarnpkg.com/lodash.set/-/lodash.set-4.3.2.tgz#d8757b1da807dde24816b0d6a84bea1a76230b23" + integrity sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM= + +lodash.sortby@^4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" + integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg= + +lodash.toarray@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.toarray/-/lodash.toarray-4.4.0.tgz#24c4bfcd6b2fba38bfd0594db1179d8e9b656561" + integrity sha1-JMS/zWsvuji/0FlNsRedjptlZWE= + lodash.uniq@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" @@ -7895,7 +8711,7 @@ lodash.without@^4.4.0: resolved "https://registry.yarnpkg.com/lodash.without/-/lodash.without-4.4.0.tgz#3cd4574a00b67bae373a94b748772640507b7aac" integrity sha1-PNRXSgC2e643OpS3SHcmQFB7eqw= -lodash@4, lodash@^4.0.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@~4.17.10: +lodash@4, lodash@^4.0.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@~4.17.10: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -8022,6 +8838,22 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" +lru-cache@~4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.0.2.tgz#1d17679c069cda5d040991a09dbc2c0db377e55e" + integrity sha1-HRdnnAac2l0ECZGgnbwsDbN35V4= + dependencies: + pseudomap "^1.0.1" + yallist "^2.0.0" + +lru-memoizer@^2.1.2: + version "2.1.4" + resolved "https://registry.yarnpkg.com/lru-memoizer/-/lru-memoizer-2.1.4.tgz#b864d92b557f00b1eeb322156a0409cb06dafac6" + integrity sha512-IXAq50s4qwrOBrXJklY+KhgZF+5y98PDaNo0gi/v2KQBFLyWr+JyFvijZXkGKjQj/h9c0OwoE+JZbwUXce76hQ== + dependencies: + lodash.clonedeep "^4.5.0" + lru-cache "~4.0.0" + lru-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/lru-queue/-/lru-queue-0.1.0.tgz#2738bd9f0d3cf4f84490c5736c48699ac632cda3" @@ -8087,6 +8919,15 @@ md5-file@^5.0.0: resolved "https://registry.yarnpkg.com/md5-file/-/md5-file-5.0.0.tgz#e519f631feca9c39e7f9ea1780b63c4745012e20" integrity sha512-xbEFXCYVWrSx/gEKS1VPlg84h/4L20znVIulKw6kMfmBUAZNAnF00eczz9ICMl+/hjQGo5KSXRxbL/47X3rmMw== +md5.js@^1.3.4: + version "1.3.5" + resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" + integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + mdast-util-compact@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/mdast-util-compact/-/mdast-util-compact-2.0.1.tgz#cabc69a2f43103628326f35b1acf735d55c99490" @@ -8236,6 +9077,14 @@ micromatch@^4.0.2: braces "^3.0.1" picomatch "^2.0.5" +miller-rabin@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" + integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== + dependencies: + bn.js "^4.0.0" + brorand "^1.0.1" + mime-db@1.46.0, "mime-db@>= 1.43.0 < 2", mime-db@^1.45.0: version "1.46.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.46.0.tgz#6267748a7f799594de3cbc8cde91def349661cee" @@ -8302,11 +9151,21 @@ mini-css-extract-plugin@1.3.9: schema-utils "^3.0.0" webpack-sources "^1.1.0" -minimalistic-assert@^1.0.0: +mini-svg-data-uri@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/mini-svg-data-uri/-/mini-svg-data-uri-1.2.3.tgz#e16baa92ad55ddaa1c2c135759129f41910bc39f" + integrity sha512-zd6KCAyXgmq6FV1mR10oKXYtvmA9vRoB6xPSTUJTbFApCtkefDnYueVR1gkof3KcdLZo1Y8mjF2DFmQMIxsHNQ== + +minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== +minimalistic-crypto-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= + minimatch@3.0.4, minimatch@^3.0.3, minimatch@^3.0.4, minimatch@~3.0.2: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" @@ -8323,7 +9182,7 @@ minimist-options@4.1.0: is-plain-obj "^1.1.0" kind-of "^6.0.3" -minimist@^1.1.0, minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5: +minimist@^1.1.0, minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== @@ -8394,6 +9253,11 @@ mkdirp@^1.0.3, mkdirp@^1.0.4: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== +modern-normalize@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/modern-normalize/-/modern-normalize-1.0.0.tgz#539d84a1e141338b01b346f3e27396d0ed17601e" + integrity sha512-1lM+BMLGuDfsdwf3rsgBSrxJwAZHFIrQ8YR61xIqdHo0uNKI9M52wNpHSrliZATJp51On6JD0AfRxd4YGSU0lw== + moment@^2.27.0, moment@^2.29.1: version "2.29.1" resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3" @@ -8414,7 +9278,7 @@ ms@2.1.2: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -ms@^2.1.1: +ms@^2.1.1, ms@^2.1.2: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== @@ -8447,7 +9311,12 @@ nan@^2.12.1, nan@^2.13.2: resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19" integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ== -nanoid@^3.1.20: +nanoclone@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/nanoclone/-/nanoclone-0.2.1.tgz#dd4090f8f1a110d26bb32c49ed2f5b9235209ed4" + integrity sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA== + +nanoid@^3.1.16, nanoid@^3.1.20: version "3.1.20" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.20.tgz#badc263c6b1dcf14b71efaa85f6ab4c1d6cfc788" integrity sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw== @@ -8474,6 +9343,13 @@ napi-build-utils@^1.0.1: resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-1.0.2.tgz#b1fddc0b2c46e380a0b7a76f984dd47c41a13806" integrity sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg== +native-url@0.3.4: + version "0.3.4" + resolved "https://registry.yarnpkg.com/native-url/-/native-url-0.3.4.tgz#29c943172aed86c63cee62c8c04db7f5756661f8" + integrity sha512-6iM8R99ze45ivyH8vybJ7X0yekIcPf5GgLV5K0ENCbmRcaRIDoj37BC8iLEmaaBfqqb8enuZ5p0uhY+lVAbAcA== + dependencies: + querystring "^0.2.0" + native-url@^0.2.6: version "0.2.6" resolved "https://registry.yarnpkg.com/native-url/-/native-url-0.2.6.tgz#ca1258f5ace169c716ff44eccbddb674e10399ae" @@ -8506,6 +9382,49 @@ next-tick@~1.0.0: resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" integrity sha1-yobR/ogoFpsBICCOPchCS524NCw= +next@^10.0.8: + version "10.0.8" + resolved "https://registry.yarnpkg.com/next/-/next-10.0.8.tgz#a2232c11ffad974d67f3d572b8db2acaa5ddedd7" + integrity sha512-iDY65ce4Prn/9EnQpJGFMb5QJvtGWzZPk6KQqT7vDNu4D+jkivkk9NaAs/k1hR73pXdJHmhHer1s0YxLSghAKQ== + dependencies: + "@babel/runtime" "7.12.5" + "@hapi/accept" "5.0.1" + "@next/env" "10.0.8" + "@next/polyfill-module" "10.0.8" + "@next/react-dev-overlay" "10.0.8" + "@next/react-refresh-utils" "10.0.8" + "@opentelemetry/api" "0.14.0" + ast-types "0.13.2" + browserslist "4.16.1" + buffer "5.6.0" + caniuse-lite "^1.0.30001179" + chalk "2.4.2" + chokidar "3.5.1" + crypto-browserify "3.12.0" + cssnano-simple "1.2.2" + etag "1.8.1" + find-cache-dir "3.3.1" + get-orientation "1.1.2" + jest-worker "24.9.0" + native-url "0.3.4" + node-fetch "2.6.1" + node-html-parser "1.4.9" + node-libs-browser "^2.2.1" + p-limit "3.1.0" + path-browserify "1.0.1" + pnp-webpack-plugin "1.6.4" + postcss "8.1.7" + process "0.11.10" + prop-types "15.7.2" + raw-body "2.4.1" + react-is "16.13.1" + react-refresh "0.8.3" + stream-browserify "3.0.0" + styled-jsx "3.3.2" + use-subscription "1.5.1" + vm-browserify "1.1.2" + watchpack "2.1.1" + nice-try@^1.0.4: version "1.0.5" resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" @@ -8538,6 +9457,13 @@ node-cache@^5.1.2: dependencies: clone "2.x" +node-emoji@^1.8.1: + version "1.10.0" + resolved "https://registry.yarnpkg.com/node-emoji/-/node-emoji-1.10.0.tgz#8886abd25d9c7bb61802a658523d1f8d2a89b2da" + integrity sha512-Yt3384If5H6BYGVHiHwTL+99OzJKHhgp82S8/dktEK73T26BazdgZ4JZh92xSVtGNJvz9UbXdNAc5hcrXV42vw== + dependencies: + lodash.toarray "^4.4.0" + node-eta@^0.9.0: version "0.9.0" resolved "https://registry.yarnpkg.com/node-eta/-/node-eta-0.9.0.tgz#9fb0b099bcd2a021940e603c64254dc003d9a7a8" @@ -8569,12 +9495,48 @@ node-gyp@^7.1.0: tar "^6.0.2" which "^2.0.2" +node-html-parser@1.4.9: + version "1.4.9" + resolved "https://registry.yarnpkg.com/node-html-parser/-/node-html-parser-1.4.9.tgz#3c8f6cac46479fae5800725edb532e9ae8fd816c" + integrity sha512-UVcirFD1Bn0O+TSmloHeHqZZCxHjvtIeGdVdGMhyZ8/PWlEiZaZ5iJzR189yKZr8p0FXN58BUeC7RHRkf/KYGw== + dependencies: + he "1.2.0" + +node-libs-browser@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425" + integrity sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q== + dependencies: + assert "^1.1.1" + browserify-zlib "^0.2.0" + buffer "^4.3.0" + console-browserify "^1.1.0" + constants-browserify "^1.0.0" + crypto-browserify "^3.11.0" + domain-browser "^1.1.1" + events "^3.0.0" + https-browserify "^1.0.0" + os-browserify "^0.3.0" + path-browserify "0.0.1" + process "^0.11.10" + punycode "^1.2.4" + querystring-es3 "^0.2.0" + readable-stream "^2.3.3" + stream-browserify "^2.0.1" + stream-http "^2.7.2" + string_decoder "^1.0.0" + timers-browserify "^2.0.4" + tty-browserify "0.0.0" + url "^0.11.0" + util "^0.11.0" + vm-browserify "^1.0.1" + node-object-hash@^2.0.0: version "2.3.1" resolved "https://registry.yarnpkg.com/node-object-hash/-/node-object-hash-2.3.1.tgz#5e4a6ac7f932cec4f90aff2fbdb953cb83344416" integrity sha512-ab7pm34jqISawXpJ+fHjj2E9CmzDtm2fTTdurgzbWXIrdTEk2q2cSZRzoeGrwa0cvq6Sqezq6S9bhOBYPHRzuQ== -node-releases@^1.1.61, node-releases@^1.1.70: +node-releases@^1.1.61, node-releases@^1.1.69, node-releases@^1.1.70: version "1.1.71" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.71.tgz#cb1334b179896b1c89ecfdd4b725fb7bbdfc7dbb" integrity sha512-zR6HoT6LrLCRBwukmrVbHv0EpEQjksO6GmFcZQQuCAy139BEsoVKPYnf3jongYW83fAa1torLGYwxxky/p28sg== @@ -8908,6 +9870,11 @@ original@^1.0.0: dependencies: url-parse "^1.4.3" +os-browserify@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" + integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= + os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" @@ -9055,6 +10022,11 @@ package-json@^6.3.0: registry-url "^5.0.0" semver "^6.2.0" +pako@~1.0.5: + version "1.0.11" + resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" + integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== + parent-module@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" @@ -9062,6 +10034,17 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" +parse-asn1@^5.0.0, parse-asn1@^5.1.5: + version "5.1.6" + resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.6.tgz#385080a3ec13cb62a62d39409cb3e88844cdaed4" + integrity sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw== + dependencies: + asn1.js "^5.2.0" + browserify-aes "^1.0.0" + evp_bytestokey "^1.0.0" + pbkdf2 "^3.0.3" + safe-buffer "^5.1.1" + parse-entities@^1.1.0: version "1.2.2" resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-1.2.2.tgz#c31bf0f653b6661354f8973559cb86dd1d5edf50" @@ -9167,6 +10150,11 @@ password-prompt@^1.0.4: ansi-escapes "^3.1.0" cross-spawn "^6.0.5" +path-browserify@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a" + integrity sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ== + path-browserify@1.0.1, path-browserify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd" @@ -9245,6 +10233,17 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== +pbkdf2@^3.0.3: + version "3.1.1" + resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.1.tgz#cb8724b0fada984596856d1a6ebafd3584654b94" + integrity sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg== + dependencies: + create-hash "^1.1.2" + create-hmac "^1.1.4" + ripemd160 "^2.0.1" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + peek-readable@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/peek-readable/-/peek-readable-3.1.3.tgz#932480d46cf6aa553c46c68566c4fb69a82cd2b1" @@ -9332,7 +10331,7 @@ pkg-up@3.1.0: dependencies: find-up "^3.0.0" -platform@^1.3.6: +platform@1.3.6, platform@^1.3.6: version "1.3.6" resolved "https://registry.yarnpkg.com/platform/-/platform-1.3.6.tgz#48b4ce983164b209c2d45a107adb31f473a6e7a7" integrity sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg== @@ -9344,7 +10343,7 @@ please-upgrade-node@^3.2.0: dependencies: semver-compare "^1.0.0" -pnp-webpack-plugin@^1.6.4: +pnp-webpack-plugin@1.6.4, pnp-webpack-plugin@^1.6.4: version "1.6.4" resolved "https://registry.yarnpkg.com/pnp-webpack-plugin/-/pnp-webpack-plugin-1.6.4.tgz#c9711ac4dc48a685dabafc86f8b6dd9f8df84149" integrity sha512-7Wjy+9E3WwLOEL30D+m8TSTF7qJJUJLONBnwQp0518siuMxUQUbgZwssaFX+QKlZkjHZcw/IpZCt/H0srrntSg== @@ -9426,6 +10425,24 @@ postcss-flexbugs-fixes@^5.0.2: resolved "https://registry.yarnpkg.com/postcss-flexbugs-fixes/-/postcss-flexbugs-fixes-5.0.2.tgz#2028e145313074fc9abe276cb7ca14e5401eb49d" integrity sha512-18f9voByak7bTktR2QgDveglpn9DTbBWPUzSOe9g0N4WR/2eSt6Vrcbf0hmspvMI6YWGywz6B9f7jzpFNJJgnQ== +postcss-functions@^3: + version "3.0.0" + resolved "https://registry.yarnpkg.com/postcss-functions/-/postcss-functions-3.0.0.tgz#0e94d01444700a481de20de4d55fb2640564250e" + integrity sha1-DpTQFERwCkgd4g3k1V+yZAVkJQ4= + dependencies: + glob "^7.1.2" + object-assign "^4.1.1" + postcss "^6.0.9" + postcss-value-parser "^3.3.0" + +postcss-js@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/postcss-js/-/postcss-js-3.0.3.tgz#2f0bd370a2e8599d45439f6970403b5873abda33" + integrity sha512-gWnoWQXKFw65Hk/mi2+WTQTHdPD5UJdDXZmX073EY/B3BWnYjO4F4t0VneTCnCGQ5E5GsCdMkzPaTXwl3r5dJw== + dependencies: + camelcase-css "^2.0.1" + postcss "^8.1.6" + postcss-loader@^5.0.0: version "5.1.0" resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-5.1.0.tgz#8a36f18b8989bee94172626b25f2b9cc6160fb43" @@ -9525,6 +10542,13 @@ postcss-modules-values@^4.0.0: dependencies: icss-utils "^5.0.0" +postcss-nested@^5.0.1: + version "5.0.5" + resolved "https://registry.yarnpkg.com/postcss-nested/-/postcss-nested-5.0.5.tgz#f0a107d33a9fab11d7637205f5321e27223e3603" + integrity sha512-GSRXYz5bccobpTzLQZXOnSOfKl6TwVr5CyAQJUPub4nuRJSOECK5AqurxVgmtxP48p0Kc/ndY/YyS1yqldX0Ew== + dependencies: + postcss-selector-parser "^6.0.4" + postcss-normalize-charset@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz#8b35add3aee83a136b0471e0d59be58a50285dd4" @@ -9673,7 +10697,7 @@ postcss-unique-selectors@^4.0.1: postcss "^7.0.0" uniqs "^2.0.0" -postcss-value-parser@^3.0.0: +postcss-value-parser@^3.0.0, postcss-value-parser@^3.3.0: version "3.3.1" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ== @@ -9692,6 +10716,16 @@ postcss@7.0.21: source-map "^0.6.1" supports-color "^6.1.0" +postcss@8.1.7: + version "8.1.7" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.1.7.tgz#ff6a82691bd861f3354fd9b17b2332f88171233f" + integrity sha512-llCQW1Pz4MOPwbZLmOddGM9eIJ8Bh7SZ2Oj5sxZva77uVaotYDsYTch1WBTNu7fUY0fpWp0fdt7uW40D4sRiiQ== + dependencies: + colorette "^1.2.1" + line-column "^1.0.2" + nanoid "^3.1.16" + source-map "^0.6.1" + postcss@8.2.6: version "8.2.6" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.2.6.tgz#5d69a974543b45f87e464bc4c3e392a97d6be9fe" @@ -9701,7 +10735,16 @@ postcss@8.2.6: nanoid "^3.1.20" source-map "^0.6.1" -postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.27: +postcss@^6.0.9: + version "6.0.23" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.23.tgz#61c82cc328ac60e677645f979054eb98bc0e3324" + integrity sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag== + dependencies: + chalk "^2.4.1" + source-map "^0.6.1" + supports-color "^5.4.0" + +postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.27, postcss@^7.0.32: version "7.0.35" resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.35.tgz#d2be00b998f7f211d8a276974079f2e92b970e24" integrity sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg== @@ -9710,7 +10753,7 @@ postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.27: source-map "^0.6.1" supports-color "^6.1.0" -postcss@^8.2.8: +postcss@^8.1.6, postcss@^8.2.1, postcss@^8.2.6, postcss@^8.2.8: version "8.2.8" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.2.8.tgz#0b90f9382efda424c4f0f69a2ead6f6830d08ece" integrity sha512-1F0Xb2T21xET7oQV9eKuctbM9S7BC0fetoHCc4H13z0PT6haiRLP4T0ZY4XWh7iLP0usgqykT6p9B2RtOf4FPw== @@ -9755,7 +10798,7 @@ prettier@2.2.1, prettier@^2.0.5, prettier@^2.2.1: resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.2.1.tgz#795a1a78dd52f073da0cd42b21f9c91381923ff5" integrity sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q== -pretty-bytes@^5.4.1: +pretty-bytes@^5.4.1, pretty-bytes@^5.5.0: version "5.6.0" resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb" integrity sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg== @@ -9778,6 +10821,11 @@ pretty-format@^25.5.0: ansi-styles "^4.0.0" react-is "^16.12.0" +pretty-hrtime@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1" + integrity sha1-t+PqQkNaTJsnWdmeDyAesZWALuE= + prismjs@^1.22.0, prismjs@~1.23.0: version "1.23.0" resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.23.0.tgz#d3b3967f7d72440690497652a9d40ff046067f33" @@ -9790,6 +10838,11 @@ process-nextick-args@~2.0.0: resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== +process@0.11.10, process@^0.11.10: + version "0.11.10" + resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" + integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= + progress@^2.0.0, progress@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" @@ -9826,6 +10879,11 @@ proper-lockfile@^4.1.1: retry "^0.12.0" signal-exit "^3.0.2" +property-expr@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/property-expr/-/property-expr-2.0.4.tgz#37b925478e58965031bb612ec5b3260f8241e910" + integrity sha512-sFPkHQjVKheDNnPvotjQmm3KD3uk1fWKUN7CrpdbwmUx3CrG3QiM8QpTSimvig5vTXmTvjz7+TDvXOI9+4rkcg== + property-information@^5.0.0: version "5.6.0" resolved "https://registry.yarnpkg.com/property-information/-/property-information-5.6.0.tgz#61675545fb23002f245c6540ec46077d4da3ed69" @@ -9846,6 +10904,11 @@ proxy-addr@~2.0.5: forwarded "~0.1.2" ipaddr.js "1.9.1" +proxy-from-env@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== + prr@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" @@ -9861,6 +10924,18 @@ psl@^1.1.28: resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== +public-encrypt@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" + integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== + dependencies: + bn.js "^4.1.0" + browserify-rsa "^4.0.0" + create-hash "^1.1.0" + parse-asn1 "^5.0.0" + randombytes "^2.0.1" + safe-buffer "^5.1.2" + pump@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" @@ -9874,6 +10949,11 @@ punycode@1.3.2: resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= +punycode@^1.2.4: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= + punycode@^2.1.0, punycode@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" @@ -9886,6 +10966,16 @@ pupa@^2.1.1: dependencies: escape-goat "^2.0.0" +purgecss@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/purgecss/-/purgecss-3.1.3.tgz#26987ec09d12eeadc318e22f6e5a9eb0be094f41" + integrity sha512-hRSLN9mguJ2lzlIQtW4qmPS2kh6oMnA9RxdIYK8sz18QYqd6ePp4GNDl18oWHA1f2v2NEQIh51CO8s/E3YGckQ== + dependencies: + commander "^6.0.0" + glob "^7.0.0" + postcss "^8.2.1" + postcss-selector-parser "^6.0.2" + q@^1.1.2: version "1.5.1" resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" @@ -9896,7 +10986,7 @@ qs@6.7.0: resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== -qs@^6.9.4: +qs@^6.6.0, qs@^6.9.4: version "6.9.6" resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.6.tgz#26ed3c8243a431b2924aca84cc90471f35d5a0ee" integrity sha512-TIRk4aqYLNoJUbd+g2lEdz5kLWIuTMRagAXxl78Q0RiVjAOugHmeKNGdd3cwo/ktpf9aL9epCfFqWDEKysUlLQ== @@ -9925,6 +11015,11 @@ query-string@^6.13.1, query-string@^6.13.8: split-on-first "^1.0.0" strict-uri-encode "^2.0.0" +querystring-es3@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" + integrity sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM= + querystring@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" @@ -9955,13 +11050,21 @@ ramda@~0.27.1: resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.27.1.tgz#66fc2df3ef873874ffc2da6aa8984658abacf5c9" integrity sha512-PgIdVpn5y5Yns8vqb8FzBUEYn98V3xcPgawAkkgj0YJ0qDsnHCiNmZYfOGMgOvoB0eWFLpYbhxUR3mxfDIMvpw== -randombytes@^2.1.0: +randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== dependencies: safe-buffer "^5.1.0" +randomfill@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" + integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== + dependencies: + randombytes "^2.0.5" + safe-buffer "^5.1.0" + range-parser@^1.2.1, range-parser@~1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" @@ -9977,7 +11080,7 @@ raw-body@2.4.0: iconv-lite "0.4.24" unpipe "1.0.0" -raw-body@^2.4.1: +raw-body@2.4.1, raw-body@^2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.1.tgz#30ac82f98bb5ae8c152e67149dac8d55153b168c" integrity sha512-9WmIKF6mkvA0SLmA2Knm9+qj89e+j1zqgyn8aXGd7+nAduPoqgI9lO57SAZNn/Byzo5P7JhXTyg9PzaJbH73bA== @@ -10067,6 +11170,11 @@ react-error-overlay@^6.0.9: resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.9.tgz#3c743010c9359608c375ecd6bc76f35d93995b0a" integrity sha512-nQTTcUu+ATDbrSD1BZHr5kgSD4oF8OFjxun8uAaL8RwPBacGBNPf/yAuVVdx17N8XNzRDMrZ9XcKZHCjPW+9ew== +react-fast-compare@^2.0.1: + version "2.0.4" + resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-2.0.4.tgz#e84b4d455b0fec113e0402c329352715196f81f9" + integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw== + react-fast-compare@^3.1.1: version "3.2.0" resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.0.tgz#641a9da81b6a6320f270e89724fb45a0b39e43bb" @@ -10082,7 +11190,7 @@ react-helmet@6.1.0: react-fast-compare "^3.1.1" react-side-effect "^2.1.0" -react-is@^16.12.0, react-is@^16.8.1: +react-is@16.13.1, react-is@^16.12.0, react-is@^16.7.0, react-is@^16.8.1: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== @@ -10108,6 +11216,11 @@ react-mailchimp-subscribe@^2.1.3: prop-types "^15.5.10" to-querystring "^1.0.4" +react-refresh@0.8.3: + version "0.8.3" + resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.8.3.tgz#721d4657672d400c5e3c75d063c4a85fb2d5d68f" + integrity sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg== + react-refresh@^0.9.0: version "0.9.0" resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.9.0.tgz#71863337adc3e5c2f8a6bfddd12ae3bfe32aafbf" @@ -10204,7 +11317,7 @@ read@^1.0.7: dependencies: mute-stream "~0.0.4" -readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.2.2, readable-stream@~2.3.6: +readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6: version "2.3.7" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== @@ -10217,7 +11330,7 @@ readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0: +readable-stream@^3.0.6, readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.5.0, readable-stream@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== @@ -10283,6 +11396,14 @@ redent@^3.0.0: indent-string "^4.0.0" strip-indent "^3.0.0" +reduce-css-calc@^2.1.8: + version "2.1.8" + resolved "https://registry.yarnpkg.com/reduce-css-calc/-/reduce-css-calc-2.1.8.tgz#7ef8761a28d614980dc0c982f772c93f7a99de03" + integrity sha512-8liAVezDmUcH+tdzoEGrhfbGcP7nOV4NkGE3a74+qqvE7nt9i4sKLGBuZNOnpI4WiGksiNPklZxva80061QiPg== + dependencies: + css-unit-converter "^1.1.1" + postcss-value-parser "^3.3.0" + redux-thunk@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.3.0.tgz#51c2c19a185ed5187aaa9a2d08b666d0d6467622" @@ -10597,7 +11718,7 @@ resolve-url@^0.2.1: resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= -resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.14.2, resolve@^1.17.0, resolve@^1.18.1, resolve@^1.3.2: +resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.14.2, resolve@^1.17.0, resolve@^1.18.1, resolve@^1.19.0, resolve@^1.3.2: version "1.20.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== @@ -10688,6 +11809,14 @@ rimraf@^3.0.0, rimraf@^3.0.2: dependencies: glob "^7.1.3" +ripemd160@^2.0.0, ripemd160@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" + integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + run-async@^2.4.0: version "2.4.1" resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" @@ -10707,7 +11836,7 @@ rxjs@^6.3.3, rxjs@^6.6.0, rxjs@^6.6.6: dependencies: tslib "^1.9.0" -safe-buffer@*, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.2.0: +safe-buffer@*, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== @@ -10918,6 +12047,11 @@ set-value@^2.0.0, set-value@^2.0.1: is-plain-object "^2.0.3" split-string "^3.0.1" +setimmediate@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= + setprototypeof@1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" @@ -10933,6 +12067,14 @@ setprototypeof@1.2.0: resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== +sha.js@^2.4.0, sha.js@^2.4.8: + version "2.4.11" + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" + integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + shallow-clone@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" @@ -11046,7 +12188,7 @@ sisteransi@^1.0.5: resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== -skynet-js@3.0.0: +skynet-js@3.0.0, skynet-js@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/skynet-js/-/skynet-js-3.0.0.tgz#5d4caa55bf540fe91f6ec1d10bde1bb4c0eb3821" integrity sha512-lRQK+vnNWhlC2OyiWiLrQoJ6EKudxvAeetUlB7GmuRSbArOlN8B5lLvy/DtnXVr+oaNX7oXV555wVe7csrXz4g== @@ -11236,6 +12378,13 @@ source-map@0.7.3, source-map@^0.7.3, source-map@~0.7.2: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== +source-map@0.8.0-beta.0: + version "0.8.0-beta.0" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.8.0-beta.0.tgz#d4c1bb42c3f7ee925f005927ba10709e0d1d1f11" + integrity sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA== + dependencies: + whatwg-url "^7.0.0" + source-map@^0.4.2: version "0.4.4" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b" @@ -11319,6 +12468,20 @@ sprintf-js@~1.0.2: resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= +square@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/square/-/square-9.0.0.tgz#41cb05539c5a28bde85329c89c64fa00058ffc2b" + integrity sha512-nHstJi+45Ea0RsOkO1Og47vvWO2I8BVg6675o0ZXtv543rT3kGGVop5rXxMRzXYCThwkrF5t0i6X1U57tfB9Sg== + dependencies: + "@apimatic/schema" "^0.5.1" + "@types/node" "^14.14.30" + axios "^0.21.1" + detect-node "^2.0.4" + form-data "^3.0.0" + json-bigint "^1.0.0" + lodash.flatmap "^4.5.0" + tiny-warning "^1.0.3" + sse-z@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/sse-z/-/sse-z-0.3.0.tgz#e215db7c303d6c4a4199d80cb63811cc28fa55b9" @@ -11374,6 +12537,13 @@ stackframe@^1.1.1: resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.2.0.tgz#52429492d63c62eb989804c11552e3d22e779303" integrity sha512-GrdeshiRmS1YLMYgzF16olf2jJ/IzxXY9lhKOskuVziubpTYcYqyOwYeJKzQkwy7uN0fYSsbsC4RQaXf9LCrYA== +stacktrace-parser@0.1.10: + version "0.1.10" + resolved "https://registry.yarnpkg.com/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz#29fb0cae4e0d0b85155879402857a1639eb6051a" + integrity sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg== + dependencies: + type-fest "^0.7.1" + state-toggle@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/state-toggle/-/state-toggle-1.0.3.tgz#e123b16a88e143139b09c6852221bc9815917dfe" @@ -11406,6 +12576,40 @@ steno@^0.4.1: dependencies: graceful-fs "^4.1.3" +stream-browserify@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-3.0.0.tgz#22b0a2850cdf6503e73085da1fc7b7d0c2122f2f" + integrity sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA== + dependencies: + inherits "~2.0.4" + readable-stream "^3.5.0" + +stream-browserify@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b" + integrity sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg== + dependencies: + inherits "~2.0.1" + readable-stream "^2.0.2" + +stream-http@^2.7.2: + version "2.8.3" + resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc" + integrity sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw== + dependencies: + builtin-status-codes "^3.0.0" + inherits "^2.0.1" + readable-stream "^2.3.6" + to-arraybuffer "^1.0.0" + xtend "^4.0.0" + +stream-parser@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/stream-parser/-/stream-parser-0.3.1.tgz#1618548694420021a1182ff0af1911c129761773" + integrity sha1-FhhUhpRCACGhGC/wrxkRwSl2F3M= + dependencies: + debug "2" + streamsearch@0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-0.1.2.tgz#808b9d0e56fc273d809ba57338e929919a1a9f1a" @@ -11431,6 +12635,11 @@ string-env-interpolation@1.0.1: resolved "https://registry.yarnpkg.com/string-env-interpolation/-/string-env-interpolation-1.0.1.tgz#ad4397ae4ac53fe6c91d1402ad6f6a52862c7152" integrity sha512-78lwMoCcn0nNu8LszbP1UA7g55OeE4v7rCeWnM5B453rnNr4aq+5it3FEYtZrSEiMvHZOZ9Jlqb0OD0M2VInqg== +string-hash@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/string-hash/-/string-hash-1.1.3.tgz#e8aafc0ac1855b4666929ed7dd1275df5d6c811b" + integrity sha1-6Kr8CsGFW0Zmkp7X3RJ1311sgRs= + string-natural-compare@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/string-natural-compare/-/string-natural-compare-3.0.1.tgz#7a42d58474454963759e8e8b7ae63d71c1e7fdf4" @@ -11511,7 +12720,7 @@ string.prototype.trimstart@^1.0.4: call-bind "^1.0.2" define-properties "^1.1.3" -string_decoder@^1.1.1: +string_decoder@^1.0.0, string_decoder@^1.1.1: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== @@ -11622,6 +12831,14 @@ strip-json-comments@~2.0.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= +stripe@^8.137.0: + version "8.138.0" + resolved "https://registry.yarnpkg.com/stripe/-/stripe-8.138.0.tgz#032ad239cda2058ab0cc391874b4d40e449cafdb" + integrity sha512-Cr+jzcacXOlL1Wrd7xxcE9nk9OBF0l73Z/oCAlBHXldtRr2FRflg/2h4g4Na3LTlcLRYtx+jnKs64/WPOqmpsA== + dependencies: + "@types/node" ">=8.1.0" + qs "^6.6.0" + strtok3@^6.0.3: version "6.0.8" resolved "https://registry.yarnpkg.com/strtok3/-/strtok3-6.0.8.tgz#c839157f615c10ba0f4ae35067dad9959eeca346" @@ -11646,6 +12863,20 @@ style-to-object@^0.3.0: dependencies: inline-style-parser "0.1.1" +styled-jsx@3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-3.3.2.tgz#2474601a26670a6049fb4d3f94bd91695b3ce018" + integrity sha512-daAkGd5mqhbBhLd6jYAjYBa9LpxYCzsgo/f6qzPdFxVB8yoGbhxvzQgkC0pfmCVvW3JuAEBn0UzFLBfkHVZG1g== + dependencies: + "@babel/types" "7.8.3" + babel-plugin-syntax-jsx "6.18.0" + convert-source-map "1.7.0" + loader-utils "1.2.3" + source-map "0.7.3" + string-hash "1.1.3" + stylis "3.5.4" + stylis-rule-sheet "0.0.10" + stylehacks@^4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-4.0.3.tgz#6718fcaf4d1e07d8a1318690881e8d96726a71d5" @@ -11655,12 +12886,22 @@ stylehacks@^4.0.0: postcss "^7.0.0" postcss-selector-parser "^3.0.0" +stylis-rule-sheet@0.0.10: + version "0.0.10" + resolved "https://registry.yarnpkg.com/stylis-rule-sheet/-/stylis-rule-sheet-0.0.10.tgz#44e64a2b076643f4b52e5ff71efc04d8c3c4a430" + integrity sha512-nTbZoaqoBnmK+ptANthb10ZRZOGC+EmTLLUxeYIuHNkEKcmKgXX1XWKkUBT2Ac4es3NybooPe0SmvKdhKJZAuw== + +stylis@3.5.4: + version "3.5.4" + resolved "https://registry.yarnpkg.com/stylis/-/stylis-3.5.4.tgz#f665f25f5e299cf3d64654ab949a57c768b73fbe" + integrity sha512-8/3pSmthWM7lsPBKv7NXkzn2Uc9W7NotcwGNpJaa3k7WMM1XDCA4MgT5k/8BIexd5ydZdboXtU90XH9Ec4Bv/Q== + sudo-prompt@^8.2.0: version "8.2.5" resolved "https://registry.yarnpkg.com/sudo-prompt/-/sudo-prompt-8.2.5.tgz#cc5ef3769a134bb94b24a631cc09628d4d53603e" integrity sha512-rlBo3HU/1zAJUrkY6jNxDOC9eVYliG6nS4JA8u8KAshITd07tafMc/Br7xQwCSseXwJ2iCcHCE8SNWX3q8Z+kw== -superagent@^6.0.0: +superagent@^6.0.0, superagent@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/superagent/-/superagent-6.1.0.tgz#09f08807bc41108ef164cfb4be293cebd480f4a6" integrity sha512-OUDHEssirmplo3F+1HWKUrUjvnQuA+nZI6i/JJBdXb5eq9IyEQwPyPpqND+SSsxf6TygpBEkUjISVRN4/VOpeg== @@ -11682,7 +12923,7 @@ supports-color@^2.0.0: resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= -supports-color@^5.3.0: +supports-color@^5.3.0, supports-color@^5.4.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== @@ -11722,6 +12963,11 @@ svgo@^1.0.0: unquote "~1.1.1" util.promisify "~1.0.0" +swr@^0.5.0: + version "0.5.2" + resolved "https://registry.yarnpkg.com/swr/-/swr-0.5.2.tgz#b7b32c3b10237ca0b4b167accfa7ce37dda356f8" + integrity sha512-uHCk7XmA8EGJOv9m2NRQLaiCo+JTsSdlSXc0dqyuLRKG3gzep0iOTwyz7XKL+3iC8ZyUjq+w6Kl/SneqIL1ncA== + symbol-observable@^1.1.0, symbol-observable@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" @@ -11745,6 +12991,32 @@ table@^6.0.4: slice-ansi "^4.0.0" string-width "^4.2.0" +tailwindcss@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-2.0.3.tgz#f8d07797d1f89dc4b171673c26237b58783c2c86" + integrity sha512-s8NEqdLBiVbbdL0a5XwTb8jKmIonOuI4RMENEcKLR61jw6SdKvBss7NWZzwCaD+ZIjlgmesv8tmrjXEp7C0eAQ== + dependencies: + "@fullhuman/postcss-purgecss" "^3.1.3" + bytes "^3.0.0" + chalk "^4.1.0" + color "^3.1.3" + detective "^5.2.0" + didyoumean "^1.2.1" + fs-extra "^9.1.0" + html-tags "^3.1.0" + lodash "^4.17.20" + modern-normalize "^1.0.0" + node-emoji "^1.8.1" + object-hash "^2.1.1" + postcss-functions "^3" + postcss-js "^3.0.3" + postcss-nested "^5.0.1" + postcss-selector-parser "^6.0.4" + postcss-value-parser "^4.1.0" + pretty-hrtime "^1.0.3" + reduce-css-calc "^2.1.8" + resolve "^1.19.0" + tapable@^1.0.0: version "1.1.3" resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" @@ -11847,6 +13119,13 @@ timed-out@^4.0.1: resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" integrity sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8= +timers-browserify@^2.0.4: + version "2.0.12" + resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.12.tgz#44a45c11fbf407f34f97bccd1577c652361b00ee" + integrity sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ== + dependencies: + setimmediate "^1.0.4" + timers-ext@^0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/timers-ext/-/timers-ext-0.1.7.tgz#6f57ad8578e07a3fb9f91d9387d65647555e25c6" @@ -11865,6 +13144,11 @@ tiny-emitter@^2.0.0: resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz#1d1a56edfc51c43e863cbb5382a72330e3555423" integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q== +tiny-warning@^1.0.2, tiny-warning@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" + integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== + tmp@^0.0.33: version "0.0.33" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" @@ -11879,6 +13163,11 @@ tmp@^0.2.1, tmp@~0.2.1: dependencies: rimraf "^3.0.0" +to-arraybuffer@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" + integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M= + to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" @@ -11939,6 +13228,11 @@ token-types@^2.0.0: "@tokenizer/token" "^0.1.1" ieee754 "^1.2.1" +toposort@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/toposort/-/toposort-2.0.2.tgz#ae21768175d1559d48bef35420b2f4962f09c330" + integrity sha1-riF2gXXRVZ1IvvNUILL0li8JwzA= + tough-cookie@~2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" @@ -11947,6 +13241,13 @@ tough-cookie@~2.5.0: psl "^1.1.28" punycode "^2.1.1" +tr46@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09" + integrity sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk= + dependencies: + punycode "^2.1.0" + trim-newlines@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" @@ -12033,6 +13334,11 @@ tsutils@^3.17.1: dependencies: tslib "^1.8.1" +tty-browserify@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" + integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY= + tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" @@ -12072,6 +13378,11 @@ type-fest@^0.6.0: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg== +type-fest@^0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.7.1.tgz#8dda65feaf03ed78f0a3f9678f1869147f7c5c48" + integrity sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg== + type-fest@^0.8.0, type-fest@^0.8.1: version "0.8.1" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" @@ -12391,6 +13702,13 @@ url@^0.11.0: punycode "1.3.2" querystring "0.2.0" +use-subscription@1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/use-subscription/-/use-subscription-1.5.1.tgz#73501107f02fad84c6dd57965beb0b75c68c42d1" + integrity sha512-Xv2a1P/yReAjAbhylMfFplFKj9GssgTwN7RlcTxBujFQcloStWNDQdc4g4NRWH9xS4i/FDk04vQBptAXoF3VcA== + dependencies: + object-assign "^4.1.1" + use@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" @@ -12422,6 +13740,20 @@ util.promisify@~1.0.0: has-symbols "^1.0.1" object.getownpropertydescriptors "^2.1.0" +util@0.10.3: + version "0.10.3" + resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" + integrity sha1-evsa/lCAUkZInj23/g7TeTNqwPk= + dependencies: + inherits "2.0.1" + +util@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/util/-/util-0.11.1.tgz#3236733720ec64bb27f6e26f421aaa2e1b588d61" + integrity sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ== + dependencies: + inherits "2.0.3" + utila@~0.4: version "0.4.0" resolved "https://registry.yarnpkg.com/utila/-/utila-0.4.0.tgz#8a16a05d445657a3aea5eecc5b12a4fa5379772c" @@ -12497,6 +13829,11 @@ vfile@^4.0.0: unist-util-stringify-position "^2.0.0" vfile-message "^2.0.0" +vm-browserify@1.1.2, vm-browserify@^1.0.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" + integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== + warning@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/warning/-/warning-4.0.3.tgz#16e9e077eb8a86d6af7d64aa1e05fd85b4678ca3" @@ -12504,7 +13841,7 @@ warning@^4.0.3: dependencies: loose-envify "^1.0.0" -watchpack@^2.0.0: +watchpack@2.1.1, watchpack@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.1.1.tgz#e99630550fca07df9f90a06056987baa40a689c7" integrity sha512-Oo7LXCmc1eE1AjyuSBmtC3+Wy4HcV8PxWh2kP6fOl8yTlNS7r0K9l1ao2lrrUza7V39Y3D/BbJgY8VeSlc5JKw== @@ -12519,6 +13856,11 @@ wbuf@^1.1.0, wbuf@^1.7.3: dependencies: minimalistic-assert "^1.0.0" +webidl-conversions@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" + integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg== + webpack-dev-middleware@^3.7.2: version "3.7.3" resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.7.3.tgz#0639372b143262e2b84ab95d3b91a7597061c2c5" @@ -12668,6 +14010,15 @@ websocket-extensions@>=0.1.1: resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== +whatwg-url@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-7.1.0.tgz#c2c492f1eca612988efd3d2266be1b9fc6170d06" + integrity sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg== + dependencies: + lodash.sortby "^4.7.0" + tr46 "^1.0.1" + webidl-conversions "^4.0.2" + which-boxed-primitive@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" @@ -12824,7 +14175,7 @@ xstate@^4.11.0, xstate@^4.14.0, xstate@^4.9.1: resolved "https://registry.yarnpkg.com/xstate/-/xstate-4.16.2.tgz#d6b973b1253b8c85f50f68601837287d59d4bf34" integrity sha512-EY39NNZnwM4tRYNmQAi1c2qHuZ1lJmuDpEo1jxiRcfS+1jPtKRAjGRLNx3fYKcK0ohW6mL41Wze3mdCF0SqavA== -xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.1: +xtend@^4.0.0, xtend@^4.0.1, xtend@^4.0.2, xtend@~4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== @@ -12959,6 +14310,19 @@ yoga-layout-prebuilt@^1.9.6: dependencies: "@types/yoga-layout" "1.9.2" +yup@^0.32.9: + version "0.32.9" + resolved "https://registry.yarnpkg.com/yup/-/yup-0.32.9.tgz#9367bec6b1b0e39211ecbca598702e106019d872" + integrity sha512-Ci1qN+i2H0XpY7syDQ0k5zKQ/DoxO0LzPg8PAR/X4Mpj6DqaeCoIYEEjDJwhArh3Fa7GWbQQVDZKeXYlSH4JMg== + dependencies: + "@babel/runtime" "^7.10.5" + "@types/lodash" "^4.14.165" + lodash "^4.17.20" + lodash-es "^4.17.15" + nanoclone "^0.2.1" + property-expr "^2.0.4" + toposort "^2.0.2" + yurnalist@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/yurnalist/-/yurnalist-2.1.0.tgz#44cf7ea5a33a8fab4968cc8c2970489f93760902"