Compare commits
3 commits
d556a00cb0
...
6282f7807a
Author | SHA1 | Date | |
---|---|---|---|
6282f7807a | |||
36e91ff03e | |||
677dfe25af |
8 changed files with 293 additions and 122 deletions
25
.envrc.example
Normal file
25
.envrc.example
Normal file
|
@ -0,0 +1,25 @@
|
|||
export DEBUG="hostr*"
|
||||
|
||||
export NODE_ENV=development
|
||||
export PORT=4040
|
||||
export WEB_BASE_URL=http://localhost:$PORT
|
||||
export API_BASE_URL=$WEB_BASE_URL/api
|
||||
export UPLOAD_STORAGE_PATH=$HOME/.hostr/uploads
|
||||
export COOKIE_KEY=INSECURE
|
||||
export EMAIL_FROM=
|
||||
export EMAIL_NAME=
|
||||
|
||||
export STATSD_HOST=localhost
|
||||
export DATABASE_URL=postgresql://hostr:hostr@database:5432/hostr
|
||||
export REDIS_URL=redis://localhost:6379
|
||||
export SENDGRID_KEY=
|
||||
export STRIPE_SECRET_KEY=
|
||||
export STRIPE_PUBLIC_KEY=
|
||||
|
||||
# optional, some functionality will be disabled
|
||||
export AWS_ENDPOINT= # only for AWS-like providers, not AWS
|
||||
export AWS_ACCESS_KEY_ID=
|
||||
export AWS_SECRET_ACCESS_KEY=
|
||||
export AWS_BUCKET=
|
||||
export VIRUSTOTAL_KEY=
|
||||
export SENTRY_DSN=
|
|
@ -1,40 +0,0 @@
|
|||
name: ci
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: main
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened]
|
||||
jobs:
|
||||
build-image:
|
||||
runs-on: self-hosted
|
||||
steps:
|
||||
- name: Set current date as env variable
|
||||
run: echo "NOW=$(date +'%Y%m%d-%H%M%S')" >> $GITHUB_ENV
|
||||
- name: Fix for bad os check
|
||||
run: echo "RUNNER_OS=Linux" >> $GITHUB_ENV
|
||||
- name: Login to Forgejo Registry
|
||||
uses: https://cremin.dev/actions/podman-login@v1
|
||||
with:
|
||||
registry: cremin.dev
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.FORGEJO_REGISTRY_TOKEN }}
|
||||
- name: Check out repository
|
||||
uses: https://cremin.dev/actions/checkout@v4
|
||||
- name: Build image
|
||||
uses: https://cremin.dev/actions/buildah-build@v2
|
||||
with:
|
||||
containerfiles: ./Containerfile
|
||||
context: ./
|
||||
oci: true
|
||||
layers: true
|
||||
image: hostr
|
||||
tags: latest ${{ github.sha }}
|
||||
- name: Push image
|
||||
uses: https://cremin.dev/actions/push-to-registry@v2
|
||||
with:
|
||||
registry: cremin.dev/jonathan
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.FORGEJO_REGISTRY_TOKEN }}
|
||||
image: hostr
|
||||
tags: latest ${{ github.sha }}
|
79
.forgejo/workflows/ci.yml
Normal file
79
.forgejo/workflows/ci.yml
Normal file
|
@ -0,0 +1,79 @@
|
|||
name: ci
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened]
|
||||
|
||||
jobs:
|
||||
build-image:
|
||||
runs-on: self-hosted
|
||||
steps:
|
||||
- name: Set current date as env variable
|
||||
run: echo "NOW=$(date +'%Y%m%d-%H%M%S')" >> $GITHUB_ENV
|
||||
- name: Fix for bad os check
|
||||
run: echo "RUNNER_OS=Linux" >> $GITHUB_ENV
|
||||
- name: Login to Forgejo Registry
|
||||
uses: https://cremin.dev/actions/podman-login@v1
|
||||
with:
|
||||
registry: cremin.dev
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.FORGEJO_REGISTRY_TOKEN }}
|
||||
logout: false
|
||||
- name: Check out repository
|
||||
uses: https://cremin.dev/actions/checkout@v4
|
||||
- name: Build image
|
||||
uses: https://cremin.dev/actions/buildah-build@v2
|
||||
with:
|
||||
containerfiles: ./Containerfile
|
||||
context: ./
|
||||
oci: true
|
||||
layers: true
|
||||
image: cremin.dev/jonathan/hostr
|
||||
tags: latest ${{ github.sha }}
|
||||
- name: Push image
|
||||
uses: https://cremin.dev/actions/push-to-registry@v2
|
||||
with:
|
||||
registry: cremin.dev
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.FORGEJO_REGISTRY_TOKEN }}
|
||||
image: jonathan/hostr
|
||||
tags: latest ${{ github.sha }}
|
||||
test-image:
|
||||
runs-on: self-hosted
|
||||
needs: build-image
|
||||
services:
|
||||
database:
|
||||
image: postgres:14-alpine
|
||||
env:
|
||||
POSTGRES_PASSWORD: hostr
|
||||
POSTGRES_USER: hostr
|
||||
POSTGRES_DB: hostr
|
||||
redis:
|
||||
image: redis:4.0.2-alpine
|
||||
minio:
|
||||
image: minio/minio
|
||||
env:
|
||||
MINIO_ACCESS_KEY: 7HYV3KPRGQ8Z5YCDNWC6
|
||||
MINIO_SECRET_KEY: 0kWP/ZkgIwQzgL9t4SGv9Uc93rO//OdyqMH329b/
|
||||
cmd: ["server", "/export"]
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: https://cremin.dev/actions/checkout@v4
|
||||
- name: Test image
|
||||
env:
|
||||
WEB_BASE_URL: http://localhost:3000
|
||||
API_BASE_URL: http://localhost:3000/api
|
||||
UPLOAD_STORAGE_PATH: /hostr/uploads
|
||||
COOKIE_KEY: TESTING
|
||||
EMAIL_FROM: jonathan@hostr.co
|
||||
EMAIL_NAME: "Jonathan from Hostr"
|
||||
DATABASE_URL: postgresql://hostr:hostr@database:5432/hostr
|
||||
REDIS_URL: redis://redis:6379
|
||||
AWS_ENDPOINT: http://minio:9000
|
||||
AWS_ACCESS_KEY_ID: 7HYV3KPRGQ8Z5YCDNWC6
|
||||
AWS_SECRET_ACCESS_KEY: 0kWP/ZkgIwQzgL9t4SGv9Uc93rO//OdyqMH329b/
|
||||
AWS_BUCKET: hostr
|
||||
run: |
|
||||
podman run --rm --env-host -it cremin.dev/jonathan/hostr:${{ github.sha }} yarn test
|
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -1,4 +1,4 @@
|
|||
.env*
|
||||
.envrc
|
||||
.DS_Store
|
||||
.sass-cache/
|
||||
node_modules
|
||||
|
@ -7,6 +7,7 @@ jspm_packages
|
|||
npm-debug.log
|
||||
web/public/build
|
||||
web/public/styles/*.css
|
||||
web/public/styles/*.css.map
|
||||
*.gz
|
||||
minigun*.json
|
||||
test*.json
|
||||
|
|
22
Makefile
22
Makefile
|
@ -10,36 +10,36 @@ help:
|
|||
|
||||
.PHONY: build
|
||||
build: ## Run `yarn run build`
|
||||
docker-compose run --rm app yarn run build
|
||||
podman compose run --rm app yarn run build
|
||||
|
||||
.PHONY: test
|
||||
test: ## Run tests
|
||||
docker-compose run --rm app yarn test
|
||||
podman compose run --rm app yarn test
|
||||
|
||||
.PHONY: logs
|
||||
logs: ## Tail the app and worker logs
|
||||
docker-compose logs -f app worker
|
||||
podman compose logs -f app worker
|
||||
|
||||
.PHONY: migrate
|
||||
migrate: ## Migrate database schema
|
||||
docker-compose run --rm app yarn run initdb
|
||||
podman compose run --rm app yarn run initdb
|
||||
|
||||
.PHONY: init
|
||||
init: ## Migrate database schema
|
||||
docker-compose run --rm app yarn run init
|
||||
podman compose run --rm app yarn run init
|
||||
|
||||
.PHONY: watch-frontend
|
||||
watch-frontend: ## Build and watch for changes
|
||||
docker-compose run --rm app yarn run watch
|
||||
podman compose run --rm app yarn run watch
|
||||
|
||||
.PHONY: docker-compose-up
|
||||
docker-compose-up: ## Start (and create) docker containers
|
||||
docker-compose up -d
|
||||
.PHONY: podman compose-up
|
||||
podman compose-up: ## Start (and create) docker containers
|
||||
podman compose up -d
|
||||
|
||||
.PHONY: yarn
|
||||
yarn: ## Update yarn dependencies
|
||||
docker-compose run --rm app yarn
|
||||
podman compose run --rm app yarn
|
||||
|
||||
.PHONY: shell
|
||||
shell: ## Run shell
|
||||
docker-compose run --rm app sh
|
||||
podman compose run --rm app sh
|
||||
|
|
|
@ -61,7 +61,7 @@ services:
|
|||
- "3001:3000"
|
||||
command: yarn run worker
|
||||
database:
|
||||
image: "postgres:10-alpine"
|
||||
image: "postgres:14-alpine"
|
||||
ports:
|
||||
- "5432:5432"
|
||||
environment:
|
||||
|
@ -69,7 +69,7 @@ services:
|
|||
POSTGRES_USER: "hostr"
|
||||
POSTGRES_DB: "hostr"
|
||||
redis:
|
||||
image: "redis:4.0.2-alpine"
|
||||
image: "redis:8-alpine"
|
||||
ports:
|
||||
- "6379:6379"
|
||||
minio:
|
||||
|
|
113
web/lib/auth.js
113
web/lib/auth.js
|
@ -1,29 +1,29 @@
|
|||
import crypto from 'crypto';
|
||||
import { join } from 'path';
|
||||
import passwords from 'passwords';
|
||||
import uuid from 'node-uuid';
|
||||
import views from 'co-views';
|
||||
import debugname from 'debug';
|
||||
import sendgrid from '@sendgrid/mail';
|
||||
import models from '../../models';
|
||||
import crypto from "crypto";
|
||||
import { join } from "path";
|
||||
import passwords from "passwords";
|
||||
import uuid from "node-uuid";
|
||||
import views from "co-views";
|
||||
import debugname from "debug";
|
||||
import sendgrid from "@sendgrid/mail";
|
||||
import models from "../../models";
|
||||
|
||||
const render = views(join(__dirname, '..', 'views'), { default: 'ejs' });
|
||||
const debug = debugname('hostr-web:auth');
|
||||
const render = views(join(__dirname, "..", "views"), { default: "ejs" });
|
||||
const debug = debugname("hostr-web:auth");
|
||||
sendgrid.setApiKey(process.env.SENDGRID_KEY);
|
||||
|
||||
const from = process.env.EMAIL_FROM;
|
||||
const fromname = process.env.EMAIL_NAME;
|
||||
|
||||
export async function authenticate(email, password) {
|
||||
const remoteIp = this.headers['x-forwarded-for'] || this.ip;
|
||||
const remoteIp = this.headers["x-forwarded-for"] || this.ip;
|
||||
|
||||
if (!password || password.length < 6) {
|
||||
debug('No password, or password too short');
|
||||
return new Error('Invalid login details');
|
||||
debug("No password, or password too short");
|
||||
return new Error("Invalid login details");
|
||||
}
|
||||
const count = await models.login.count({
|
||||
where: {
|
||||
ip: remoteIp.split(',')[0],
|
||||
ip: remoteIp.split(",")[0],
|
||||
successful: false,
|
||||
createdAt: {
|
||||
$gt: Math.ceil(Date.now()) - 600000,
|
||||
|
@ -32,8 +32,8 @@ export async function authenticate(email, password) {
|
|||
});
|
||||
|
||||
if (count > 25) {
|
||||
debug('Throttling brute force');
|
||||
return new Error('Invalid login details');
|
||||
debug("Throttling brute force");
|
||||
return new Error("Invalid login details");
|
||||
}
|
||||
const user = await models.user.findOne({
|
||||
where: {
|
||||
|
@ -43,30 +43,29 @@ export async function authenticate(email, password) {
|
|||
});
|
||||
|
||||
const login = await models.login.create({
|
||||
ip: remoteIp.split(',')[0],
|
||||
ip: remoteIp.split(",")[0],
|
||||
successful: false,
|
||||
});
|
||||
|
||||
if (user && user.password) {
|
||||
login.userId = user.id;
|
||||
if (await passwords.verify(password, user.password)) {
|
||||
debug('Password verified');
|
||||
debug("Password verified");
|
||||
login.successful = true;
|
||||
await login.save();
|
||||
return user;
|
||||
}
|
||||
debug('Password invalid');
|
||||
debug("Password invalid");
|
||||
}
|
||||
await login.save();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
export async function setupSession(user) {
|
||||
debug('Setting up session');
|
||||
debug("Setting up session");
|
||||
const token = uuid.v4();
|
||||
debug(user)
|
||||
await this.redis.set(token, user.id, 'EX', 604800);
|
||||
|
||||
await this.redis.set(token, user.id, "EX", 604800);
|
||||
|
||||
const sessionUser = {
|
||||
id: user.id,
|
||||
|
@ -76,27 +75,26 @@ export async function setupSession(user) {
|
|||
joined: user.createdAt,
|
||||
plan: user.plan,
|
||||
uploadsToday: await models.file.count({ userId: user.id }),
|
||||
md5: crypto.createHash('md5').update(user.email).digest('hex'),
|
||||
md5: crypto.createHash("md5").update(user.email).digest("hex"),
|
||||
token,
|
||||
};
|
||||
|
||||
if (sessionUser.plan === 'Pro') {
|
||||
if (sessionUser.plan === "Pro") {
|
||||
sessionUser.maxFileSize = 524288000;
|
||||
sessionUser.dailyUploadAllowance = 'unlimited';
|
||||
sessionUser.dailyUploadAllowance = "unlimited";
|
||||
}
|
||||
|
||||
this.session.user = sessionUser;
|
||||
if (this.request.body.remember && this.request.body.remember === 'on') {
|
||||
if (this.request.body.remember && this.request.body.remember === "on") {
|
||||
const remember = await models.remember.create({
|
||||
id: uuid(),
|
||||
userId: user.id,
|
||||
});
|
||||
this.cookies.set('r', remember.id, { maxAge: 1209600000, httpOnly: true });
|
||||
this.cookies.set("r", remember.id, { maxAge: 1209600000, httpOnly: true });
|
||||
}
|
||||
debug('Session set up');
|
||||
debug("Session set up");
|
||||
}
|
||||
|
||||
|
||||
export async function signup(email, password, ip) {
|
||||
const existingUser = await models.user.findOne({
|
||||
where: {
|
||||
|
@ -105,26 +103,29 @@ export async function signup(email, password, ip) {
|
|||
},
|
||||
});
|
||||
if (existingUser) {
|
||||
debug('Email already in use.');
|
||||
throw new Error('Email already in use.');
|
||||
debug("Email already in use.");
|
||||
throw new Error("Email already in use.");
|
||||
}
|
||||
const cryptedPassword = await passwords.crypt(password);
|
||||
const user = await models.user.create({
|
||||
email,
|
||||
password: cryptedPassword,
|
||||
ip,
|
||||
plan: 'Free',
|
||||
activation: {
|
||||
id: uuid(),
|
||||
const user = await models.user.create(
|
||||
{
|
||||
email,
|
||||
password: cryptedPassword,
|
||||
ip,
|
||||
plan: "Free",
|
||||
activation: {
|
||||
id: uuid(),
|
||||
email,
|
||||
},
|
||||
},
|
||||
}, {
|
||||
include: [models.activation],
|
||||
});
|
||||
{
|
||||
include: [models.activation],
|
||||
},
|
||||
);
|
||||
|
||||
await user.save();
|
||||
|
||||
const html = await render('email/inlined/activate', {
|
||||
const html = await render("email/inlined/activate", {
|
||||
activationUrl: `${process.env.WEB_BASE_URL}/activate/${user.activation.id}`,
|
||||
});
|
||||
const text = `Thanks for signing up to Hostr!
|
||||
|
@ -136,18 +137,15 @@ ${process.env.WEB_BASE_URL}/activate/${user.activation.id}
|
|||
`;
|
||||
sendgrid.send({
|
||||
to: user.email,
|
||||
subject: 'Welcome to Hostr',
|
||||
subject: "Welcome to Hostr",
|
||||
from,
|
||||
fromname,
|
||||
html,
|
||||
text,
|
||||
categories: [
|
||||
'activate',
|
||||
],
|
||||
categories: ["activate"],
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
export async function sendResetToken(email) {
|
||||
const user = await models.user.findOne({
|
||||
where: {
|
||||
|
@ -159,7 +157,7 @@ export async function sendResetToken(email) {
|
|||
id: uuid.v4(),
|
||||
userId: user.id,
|
||||
});
|
||||
const html = await render('email/inlined/forgot', {
|
||||
const html = await render("email/inlined/forgot", {
|
||||
forgotUrl: `${process.env.WEB_BASE_URL}/forgot/${reset.id}`,
|
||||
});
|
||||
const text = `It seems you've forgotten your password :(
|
||||
|
@ -167,38 +165,32 @@ Visit ${process.env.WEB_BASE_URL}/forgot/${reset.id} to set a new one.
|
|||
`;
|
||||
sendgrid.send({
|
||||
to: user.email,
|
||||
from: 'jonathan@hostr.co',
|
||||
fromname: 'Jonathan from Hostr',
|
||||
subject: 'Hostr Password Reset',
|
||||
from: "jonathan@hostr.co",
|
||||
fromname: "Jonathan from Hostr",
|
||||
subject: "Hostr Password Reset",
|
||||
html,
|
||||
text,
|
||||
categories: [
|
||||
'password-reset',
|
||||
],
|
||||
categories: ["password-reset"],
|
||||
});
|
||||
} else {
|
||||
throw new Error('There was an error looking up your email address.');
|
||||
throw new Error("There was an error looking up your email address.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export async function fromToken(token) {
|
||||
const userId = await this.redis.get(token);
|
||||
return models.user.findByPk(userId);
|
||||
}
|
||||
|
||||
|
||||
export async function fromCookie(rememberId) {
|
||||
const userId = await models.remember.findByPk(rememberId);
|
||||
return models.user.findByPk(userId);
|
||||
}
|
||||
|
||||
|
||||
export async function validateResetToken(resetId) {
|
||||
return models.reset.findByPk(resetId);
|
||||
}
|
||||
|
||||
|
||||
export async function updatePassword(userId, password) {
|
||||
const cryptedPassword = await passwords.crypt(password);
|
||||
const user = await models.user.findByPk(userId);
|
||||
|
@ -206,7 +198,6 @@ export async function updatePassword(userId, password) {
|
|||
await user.save();
|
||||
}
|
||||
|
||||
|
||||
export async function activateUser(code) {
|
||||
const activation = await models.activation.findOne({
|
||||
where: {
|
||||
|
|
129
yarn.lock
129
yarn.lock
|
@ -1156,7 +1156,7 @@ async@0.9.x:
|
|||
asynckit@^0.4.0:
|
||||
version "0.4.0"
|
||||
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
|
||||
integrity sha1-x57Zf380y48robyXkLzDZkdLS3k=
|
||||
integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==
|
||||
|
||||
atob@^2.1.2:
|
||||
version "2.1.2"
|
||||
|
@ -1731,6 +1731,14 @@ cache-content-type@^1.0.0:
|
|||
mime-types "^2.1.18"
|
||||
ylru "^1.2.0"
|
||||
|
||||
call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz#4b5428c222be985d79c3d82657479dbe0b59b2d6"
|
||||
integrity sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==
|
||||
dependencies:
|
||||
es-errors "^1.3.0"
|
||||
function-bind "^1.1.2"
|
||||
|
||||
callsites@^3.0.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
|
||||
|
@ -2526,7 +2534,7 @@ define-property@^2.0.2:
|
|||
delayed-stream@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
|
||||
integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk=
|
||||
integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
|
||||
|
||||
delegates@^1.0.0:
|
||||
version "1.0.0"
|
||||
|
@ -2661,6 +2669,15 @@ dropzone@~5.7.0:
|
|||
resolved "https://registry.yarnpkg.com/dropzone/-/dropzone-5.7.1.tgz#8e41a85879ff145562e8fcce39c6ff619dce81be"
|
||||
integrity sha512-eqcJafupMKRlVUihZtsLkzLn02WTPUMHeImP5ZtWm3ERObC/dv15te0qqn/X2rEKaSqRC0pNTHUBPgrPWcP52w==
|
||||
|
||||
dunder-proto@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a"
|
||||
integrity sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==
|
||||
dependencies:
|
||||
call-bind-apply-helpers "^1.0.1"
|
||||
es-errors "^1.3.0"
|
||||
gopd "^1.2.0"
|
||||
|
||||
duplexify@^3.4.2, duplexify@^3.6.0:
|
||||
version "3.7.1"
|
||||
resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309"
|
||||
|
@ -2816,6 +2833,16 @@ es-array-method-boxes-properly@^1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz#873f3e84418de4ee19c5be752990b2e44718d09e"
|
||||
integrity sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==
|
||||
|
||||
es-define-property@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.1.tgz#983eb2f9a6724e9303f61addf011c72e09e0b0fa"
|
||||
integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==
|
||||
|
||||
es-errors@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f"
|
||||
integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==
|
||||
|
||||
es-get-iterator@^1.0.2:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/es-get-iterator/-/es-get-iterator-1.1.0.tgz#bb98ad9d6d63b31aacdc8f89d5d0ee57bcb5b4c8"
|
||||
|
@ -2829,6 +2856,23 @@ es-get-iterator@^1.0.2:
|
|||
is-string "^1.0.5"
|
||||
isarray "^2.0.5"
|
||||
|
||||
es-object-atoms@^1.0.0, es-object-atoms@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz#1c4f2c4837327597ce69d2ca190a7fdd172338c1"
|
||||
integrity sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==
|
||||
dependencies:
|
||||
es-errors "^1.3.0"
|
||||
|
||||
es-set-tostringtag@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz#f31dbbe0c183b00a6d26eb6325c810c0fd18bd4d"
|
||||
integrity sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==
|
||||
dependencies:
|
||||
es-errors "^1.3.0"
|
||||
get-intrinsic "^1.2.6"
|
||||
has-tostringtag "^1.0.2"
|
||||
hasown "^2.0.2"
|
||||
|
||||
es-to-primitive@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a"
|
||||
|
@ -3510,13 +3554,14 @@ form-data@^2.3.1:
|
|||
mime-types "^2.1.12"
|
||||
|
||||
form-data@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.0.tgz#31b7e39c85f1355b7139ee0c647cf0de7f83c682"
|
||||
integrity sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.3.tgz#349c8f2c9d8f8f0c879ee0eb7cc0d300018d6b09"
|
||||
integrity sha512-q5YBMeWy6E2Un0nMGWMgI65MAKtaylxfNJGJxpGh45YDciZB4epbWpaAfImil6CPAPTYB4sh0URQNDRIZG5F2w==
|
||||
dependencies:
|
||||
asynckit "^0.4.0"
|
||||
combined-stream "^1.0.8"
|
||||
mime-types "^2.1.12"
|
||||
es-set-tostringtag "^2.1.0"
|
||||
mime-types "^2.1.35"
|
||||
|
||||
formidable@^1.2.0:
|
||||
version "1.2.2"
|
||||
|
@ -3608,6 +3653,11 @@ function-bind@^1.1.1:
|
|||
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
|
||||
integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
|
||||
|
||||
function-bind@^1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c"
|
||||
integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==
|
||||
|
||||
functional-red-black-tree@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327"
|
||||
|
@ -3623,6 +3673,22 @@ get-caller-file@^2.0.1:
|
|||
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
|
||||
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
|
||||
|
||||
get-intrinsic@^1.2.6:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz#743f0e3b6964a93a5491ed1bffaae054d7f98d01"
|
||||
integrity sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==
|
||||
dependencies:
|
||||
call-bind-apply-helpers "^1.0.2"
|
||||
es-define-property "^1.0.1"
|
||||
es-errors "^1.3.0"
|
||||
es-object-atoms "^1.1.1"
|
||||
function-bind "^1.1.2"
|
||||
get-proto "^1.0.1"
|
||||
gopd "^1.2.0"
|
||||
has-symbols "^1.1.0"
|
||||
hasown "^2.0.2"
|
||||
math-intrinsics "^1.1.0"
|
||||
|
||||
get-paths@0.0.7:
|
||||
version "0.0.7"
|
||||
resolved "https://registry.yarnpkg.com/get-paths/-/get-paths-0.0.7.tgz#15331086752077cf130166ccd233a1cdbeefcf38"
|
||||
|
@ -3630,6 +3696,14 @@ get-paths@0.0.7:
|
|||
dependencies:
|
||||
pify "^4.0.1"
|
||||
|
||||
get-proto@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/get-proto/-/get-proto-1.0.1.tgz#150b3f2743869ef3e851ec0c49d15b1d14d00ee1"
|
||||
integrity sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==
|
||||
dependencies:
|
||||
dunder-proto "^1.0.1"
|
||||
es-object-atoms "^1.0.0"
|
||||
|
||||
get-stream@^4.0.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5"
|
||||
|
@ -3784,6 +3858,11 @@ globby@^11.0.0, globby@^11.0.1:
|
|||
merge2 "^1.3.0"
|
||||
slash "^3.0.0"
|
||||
|
||||
gopd@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1"
|
||||
integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==
|
||||
|
||||
graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.4:
|
||||
version "4.2.4"
|
||||
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb"
|
||||
|
@ -3816,6 +3895,18 @@ has-symbols@^1.0.0, has-symbols@^1.0.1:
|
|||
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8"
|
||||
integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==
|
||||
|
||||
has-symbols@^1.0.3, has-symbols@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.1.0.tgz#fc9c6a783a084951d0b971fe1018de813707a338"
|
||||
integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==
|
||||
|
||||
has-tostringtag@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc"
|
||||
integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==
|
||||
dependencies:
|
||||
has-symbols "^1.0.3"
|
||||
|
||||
has-value@^0.3.1:
|
||||
version "0.3.1"
|
||||
resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f"
|
||||
|
@ -3870,6 +3961,13 @@ hash.js@^1.0.0, hash.js@^1.0.3:
|
|||
inherits "^2.0.3"
|
||||
minimalistic-assert "^1.0.1"
|
||||
|
||||
hasown@^2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003"
|
||||
integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==
|
||||
dependencies:
|
||||
function-bind "^1.1.2"
|
||||
|
||||
he@1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
|
||||
|
@ -5166,6 +5264,11 @@ map-visit@^1.0.0:
|
|||
dependencies:
|
||||
object-visit "^1.0.0"
|
||||
|
||||
math-intrinsics@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9"
|
||||
integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==
|
||||
|
||||
math-random@^1.0.1:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.4.tgz#5dd6943c938548267016d4e34f057583080c514c"
|
||||
|
@ -5292,7 +5395,19 @@ mime-db@1.44.0, "mime-db@>= 1.43.0 < 2":
|
|||
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92"
|
||||
integrity sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==
|
||||
|
||||
mime-types@^2.1.12, mime-types@^2.1.18, mime-types@^2.1.26, mime-types@~2.1.24:
|
||||
mime-db@1.52.0:
|
||||
version "1.52.0"
|
||||
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
|
||||
integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
|
||||
|
||||
mime-types@^2.1.12, mime-types@^2.1.35:
|
||||
version "2.1.35"
|
||||
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
|
||||
integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
|
||||
dependencies:
|
||||
mime-db "1.52.0"
|
||||
|
||||
mime-types@^2.1.18, mime-types@^2.1.26, mime-types@~2.1.24:
|
||||
version "2.1.27"
|
||||
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.27.tgz#47949f98e279ea53119f5722e0f34e529bec009f"
|
||||
integrity sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue