Compare commits

..

18 Commits

Author SHA1 Message Date
Elias Schneider
aff58da3a2 release: 0.1.0 2022-10-29 23:12:32 +02:00
Elias Schneider
63e0af3484 refactor: run formatter 2022-10-29 23:12:29 +02:00
Elias Schneider
c2ddce6203 fix: infinite loading when file size is small 2022-10-29 23:09:28 +02:00
Elias Schneider
c6e1f07f51 fix: only show not signed in warning if not signed in 2022-10-29 22:55:46 +02:00
Elias Schneider
c8021a42b7 fix: visitor count doesn't get incremented 2022-10-29 22:49:30 +02:00
Elias Schneider
d0901d497b ix: jwt guard when unauthenticated shares are allowed 2022-10-29 22:48:00 +02:00
Elias Schneider
ffdecbd32e Revert "fix: jwt guard when unauthenticated shares are allowed"
This reverts commit c2b87aba5c.
2022-10-29 22:47:23 +02:00
Elias Schneider
712cfe625a feat: add rate limiting 2022-10-24 12:11:10 +02:00
Elias Schneider
c2b87aba5c fix: jwt guard when unauthenticated shares are allowed 2022-10-24 09:25:45 +02:00
Elias Schneider
e4019612f8 Merge pull request #18 from stonith404/feat/allow-unauthenticated-shares
feat: allow unauthenticated shares
2022-10-24 09:15:28 +02:00
Elias Schneider
af6e2b61c0 docs: add ALLOW_UNAUTHENTICATED_SHARES to README 2022-10-24 09:12:12 +02:00
Elias Schneider
7237928844 chore: create database migration 2022-10-18 14:32:40 +02:00
Elias Schneider
38986c971a refactor: run formatter 2022-10-18 14:30:41 +02:00
Elias Schneider
84d29dff68 feat: allow unauthenticated uploads 2022-10-18 14:27:14 +02:00
Elias Schneider
41c3bafbd7 chore: upgrade packages to fix vulnerabilities 2022-10-18 09:43:13 +02:00
Elias Schneider
c52a4d5e3a feat(frontend): remove footer 2022-10-18 09:31:13 +02:00
Elias Schneider
239b18cdae fix: opt out of static site generation to enable publicRuntimeConfig 2022-10-18 09:17:57 +02:00
Elias Schneider
a8a56321dd chore: change changelog generator to conventionalcommits 2022-10-18 09:12:11 +02:00
33 changed files with 582 additions and 2757 deletions

View File

@@ -4,6 +4,7 @@
APP_URL=http://localhost:3000
SHOW_HOME_PAGE=true
ALLOW_REGISTRATION=true
ALLOW_UNAUTHENTICATED_SHARES=false
MAX_FILE_SIZE=1000000000
# SECURITY

View File

@@ -1,4 +1,36 @@
## 0.0.1 (2022-10-17)
## [0.1.0](https://github.com/stonith404/pingvin-share/compare/v0.0.1...v0.1.0) (2022-10-29)
### Features
* add rate limiting ([712cfe6](https://github.com/stonith404/pingvin-share/commit/712cfe625a19dc9790cda5fbc2843fed0836b860))
* allow unauthenticated uploads ([84d29df](https://github.com/stonith404/pingvin-share/commit/84d29dff68d0ea9d76d9a35f9fb7dff95d3dda1b))
* **frontend:** remove footer ([c52a4d5](https://github.com/stonith404/pingvin-share/commit/c52a4d5e3ad717a10d15b7fe1dbf359b041c0976))
### Bug Fixes
* infinite loading when file size is small ([c2ddce6](https://github.com/stonith404/pingvin-share/commit/c2ddce62038e561d292f23fc6089562e64f1ffe9))
* only show not signed in warning if not signed in ([c6e1f07](https://github.com/stonith404/pingvin-share/commit/c6e1f07f51e9cdd914bb70fb19dd81b90a470563))
* opt out of static site generation to enable `publicRuntimeConfig` ([239b18c](https://github.com/stonith404/pingvin-share/commit/239b18cdae6367322bcdacb6b2bbaa1028295cc4))
* visitor count doesn't get incremented ([c8021a4](https://github.com/stonith404/pingvin-share/commit/c8021a42b7fb094e587325bf855fc3133b6b96b0))
### [0.0.1](https://github.com/stonith404/pingvin-share/compare/4bab33ad8a79302fd94c6d92a3ddf87cdff8b214...v0.0.1) (2022-10-17)
### Features
* add `linux/arm/v7` arch for docker image ([d9e5c28](https://github.com/stonith404/pingvin-share/commit/d9e5c286e3b53834276511227f219d0858ca0829))
* add progress indicator for uploading files ([8c84d50](https://github.com/stonith404/pingvin-share/commit/8c84d50159bdabc75a1199ffdf372b9586f67371))
* Added "never" expiration date ([56349c6](https://github.com/stonith404/pingvin-share/commit/56349c6f4cc739d07bcf8ad862b0868e09342883))
* automatically detect hour format ([4e3f6be](https://github.com/stonith404/pingvin-share/commit/4e3f6be8e322929b83a35c7789078260dca9eb58))
* extract logo to component ([58efc48](https://github.com/stonith404/pingvin-share/commit/58efc48ffa559b4bfa03e381bccb552c8fb830b9))
* improve share security ([6358ac3](https://github.com/stonith404/pingvin-share/commit/6358ac3918d1af1cc05aca634d9d32a8f35d251f))
* put db and uploads in same folder ([80cdcda](https://github.com/stonith404/pingvin-share/commit/80cdcda93c385a8f5c1e22c7b84740f5d8119ef1))
* remove appwrite and add nextjs backend ([4bab33a](https://github.com/stonith404/pingvin-share/commit/4bab33ad8a79302fd94c6d92a3ddf87cdff8b214))
* remove postgres & use a single docker container ([388ac39](https://github.com/stonith404/pingvin-share/commit/388ac395ba85aae8a91ddfb5f5637a80a3e6f16b))
* replace tooltip with toast ([a33b5b3](https://github.com/stonith404/pingvin-share/commit/a33b5b37d92071e643a0bf78a9d6ecf29bebc65a))
* use system color theme ([d902aae](https://github.com/stonith404/pingvin-share/commit/d902aae03ff33d39c733cf1bce88ae58ff4cd888))
### Bug Fixes
@@ -28,19 +60,3 @@
* upload volume path ([7522221](https://github.com/stonith404/pingvin-share/commit/7522221ee163cb0bd6144e7b924c77065f223fb9))
* wrong environment configuration for `ALLOW_REGISTRATION` ([759db40](https://github.com/stonith404/pingvin-share/commit/759db40ac9f42ff71a795ceec521a7f9531d71c9))
### Features
* add `linux/arm/v7` arch for docker image ([d9e5c28](https://github.com/stonith404/pingvin-share/commit/d9e5c286e3b53834276511227f219d0858ca0829))
* add progress indicator for uploading files ([8c84d50](https://github.com/stonith404/pingvin-share/commit/8c84d50159bdabc75a1199ffdf372b9586f67371))
* automatically detect hour format ([4e3f6be](https://github.com/stonith404/pingvin-share/commit/4e3f6be8e322929b83a35c7789078260dca9eb58))
* extract logo to component ([58efc48](https://github.com/stonith404/pingvin-share/commit/58efc48ffa559b4bfa03e381bccb552c8fb830b9))
* improve share security ([6358ac3](https://github.com/stonith404/pingvin-share/commit/6358ac3918d1af1cc05aca634d9d32a8f35d251f))
* put db and uploads in same folder ([80cdcda](https://github.com/stonith404/pingvin-share/commit/80cdcda93c385a8f5c1e22c7b84740f5d8119ef1))
* remove appwrite and add nextjs backend ([4bab33a](https://github.com/stonith404/pingvin-share/commit/4bab33ad8a79302fd94c6d92a3ddf87cdff8b214))
* remove postgres & use a single docker container ([388ac39](https://github.com/stonith404/pingvin-share/commit/388ac395ba85aae8a91ddfb5f5637a80a3e6f16b))
* replace tooltip with toast ([a33b5b3](https://github.com/stonith404/pingvin-share/commit/a33b5b37d92071e643a0bf78a9d6ecf29bebc65a))
* use system color theme ([d902aae](https://github.com/stonith404/pingvin-share/commit/d902aae03ff33d39c733cf1bce88ae58ff4cd888))

View File

@@ -31,4 +31,4 @@ WORKDIR /opt/app
RUN npm i -g dotenv-cli
EXPOSE 3000
CMD cd frontend && dotenv -e .env.development node_modules/.bin/next start & cd backend && npm run prod
CMD cd frontend && dotenv node_modules/.bin/next start & cd backend && npm run prod

View File

@@ -28,13 +28,14 @@ The website is now listening available on `http://localhost:3000`, have fun with
### Environment variables
| Variable | Description | Possible values |
| -------------------- | ------------------------------------------------------------------------------------------- | --------------- |
| `APP_URL` | On which URL Pingvin Share is available. E.g http://localhost or https://pingvin-share.com. | URL |
| `SHOW_HOME_PAGE` | Whether the Pingvin Share home page should be shown. | true/false |
| `ALLOW_REGISTRATION` | Whether a new user can create a new account. | true/false |
| `MAX_FILE_SIZE` | Maximum allowed size per file in bytes. | Number |
| `JWT_SECRET` | Long random string to sign the JWT's. | Random string |
| Variable | Description | Possible values |
| ------------------------------ | ------------------------------------------------------------------------------------------- | --------------- |
| `APP_URL` | On which URL Pingvin Share is available. E.g http://localhost or https://pingvin-share.com. | URL |
| `SHOW_HOME_PAGE` | Whether the Pingvin Share home page should be shown. | true/false |
| `ALLOW_REGISTRATION` | Whether a new user can create a new account. | true/false |
| `ALLOW_UNAUTHENTICATED_SHARES` | Whether a user can create a share without being signed in. | true/false |
| `MAX_FILE_SIZE` | Maximum allowed size per file in bytes. | Number |
| `JWT_SECRET` | Long random string to sign the JWT's. | Random string |
### Upgrade to a new version

View File

@@ -2,6 +2,7 @@
APP_URL=http://localhost:3000
ALLOW_REGISTRATION=true
MAX_FILE_SIZE=5000000000
ALLOW_UNAUTHENTICATED_SHARES=false
# SECURITY
JWT_SECRET=random-string

2331
backend/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -18,6 +18,7 @@
"@nestjs/platform-express": "^9.1.2",
"@nestjs/schedule": "^2.1.0",
"@nestjs/swagger": "^6.1.2",
"@nestjs/throttler": "^3.1.0",
"archiver": "^5.3.1",
"argon2": "^0.29.1",
"class-transformer": "^0.5.1",

View File

@@ -0,0 +1,17 @@
-- RedefineTables
PRAGMA foreign_keys=OFF;
CREATE TABLE "new_Share" (
"id" TEXT NOT NULL PRIMARY KEY,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"uploadLocked" BOOLEAN NOT NULL DEFAULT false,
"isZipReady" BOOLEAN NOT NULL DEFAULT false,
"views" INTEGER NOT NULL DEFAULT 0,
"expiration" DATETIME NOT NULL,
"creatorId" TEXT,
CONSTRAINT "Share_creatorId_fkey" FOREIGN KEY ("creatorId") REFERENCES "User" ("id") ON DELETE SET NULL ON UPDATE CASCADE
);
INSERT INTO "new_Share" ("createdAt", "creatorId", "expiration", "id", "isZipReady", "uploadLocked", "views") SELECT "createdAt", "creatorId", "expiration", "id", "isZipReady", "uploadLocked", "views" FROM "Share";
DROP TABLE "Share";
ALTER TABLE "new_Share" RENAME TO "Share";
PRAGMA foreign_key_check;
PRAGMA foreign_keys=ON;

View File

@@ -40,8 +40,8 @@ model Share {
views Int @default(0)
expiration DateTime
creatorId String
creator User @relation(fields: [creatorId], references: [id])
creatorId String?
creator User? @relation(fields: [creatorId], references: [id])
security ShareSecurity?
files File[]
}

View File

@@ -4,6 +4,8 @@ import { ScheduleModule } from "@nestjs/schedule";
import { AuthModule } from "./auth/auth.module";
import { JobsService } from "./jobs/jobs.service";
import { APP_GUARD } from "@nestjs/core";
import { ThrottlerGuard, ThrottlerModule } from "@nestjs/throttler";
import { FileController } from "./file/file.controller";
import { FileModule } from "./file/file.module";
import { PrismaModule } from "./prisma/prisma.module";
@@ -19,9 +21,20 @@ import { UserController } from "./user/user.controller";
FileModule,
PrismaModule,
ConfigModule.forRoot({ isGlobal: true }),
ThrottlerModule.forRoot({
ttl: 60,
limit: 100,
}),
ScheduleModule.forRoot(),
],
providers: [PrismaService, JobsService],
providers: [
PrismaService,
JobsService,
{
provide: APP_GUARD,
useClass: ThrottlerGuard,
},
],
controllers: [UserController, ShareController, FileController],
})
export class AppModule {}

View File

@@ -6,7 +6,7 @@ import {
Post,
} from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import { Throttle } from "@nestjs/throttler";
import { AuthService } from "./auth.service";
import { AuthRegisterDTO } from "./dto/authRegister.dto";
import { AuthSignInDTO } from "./dto/authSignIn.dto";
@@ -19,6 +19,7 @@ export class AuthController {
private config: ConfigService
) {}
@Throttle(10, 5 * 60)
@Post("signUp")
signUp(@Body() dto: AuthRegisterDTO) {
if (this.config.get("ALLOW_REGISTRATION") == "false")
@@ -26,6 +27,7 @@ export class AuthController {
return this.authService.signUp(dto);
}
@Throttle(10, 5 * 60)
@Post("signIn")
@HttpCode(200)
signIn(@Body() dto: AuthSignInDTO) {

View File

@@ -1,7 +1,15 @@
import { ExecutionContext } from "@nestjs/common";
import { AuthGuard } from "@nestjs/passport";
export class JwtGuard extends AuthGuard("jwt") {
constructor() {
super();
}
async canActivate(context: ExecutionContext): Promise<boolean> {
try {
return (await super.canActivate(context)) as boolean;
} catch {
return process.env.ALLOW_UNAUTHENTICATED_SHARES == "true";
}
}
}

View File

@@ -1,12 +1,16 @@
import { ClassSerializerInterceptor, ValidationPipe } from "@nestjs/common";
import { NestFactory, Reflector } from "@nestjs/core";
import { NestExpressApplication } from "@nestjs/platform-express";
import * as fs from "fs";
import { AppModule } from "./app.module";
async function bootstrap() {
const app = await NestFactory.create(AppModule);
const app = await NestFactory.create<NestExpressApplication>(AppModule);
app.useGlobalPipes(new ValidationPipe());
app.useGlobalInterceptors(new ClassSerializerInterceptor(app.get(Reflector)));
app.set("trust proxy", true);
await fs.promises.mkdir("./data/uploads/_temp", { recursive: true });
app.setGlobalPrefix("api");

View File

@@ -28,6 +28,8 @@ export class ShareOwnerGuard implements CanActivate {
if (!share) throw new NotFoundException("Share not found");
if (!share.creatorId) return true;
return share.creatorId == (request.user as User).id;
}
}

View File

@@ -47,7 +47,7 @@ export class ShareSecurityGuard implements CanActivate {
"share_password_required"
);
if (!this.shareService.verifyShareToken(shareId, shareToken))
if (!(await this.shareService.verifyShareToken(shareId, shareToken)))
throw new ForbiddenException(
"Share token required",
"share_token_required"

View File

@@ -8,6 +8,7 @@ import {
Post,
UseGuards,
} from "@nestjs/common";
import { Throttle } from "@nestjs/throttler";
import { User } from "@prisma/client";
import { GetUser } from "src/auth/decorator/getUser.decorator";
import { JwtGuard } from "src/auth/guard/jwt.guard";
@@ -20,7 +21,6 @@ import { ShareOwnerGuard } from "./guard/shareOwner.guard";
import { ShareSecurityGuard } from "./guard/shareSecurity.guard";
import { ShareTokenSecurity } from "./guard/shareTokenSecurity.guard";
import { ShareService } from "./share.service";
@Controller("shares")
export class ShareController {
constructor(private shareService: ShareService) {}
@@ -70,6 +70,7 @@ export class ShareController {
}
@HttpCode(200)
@Throttle(10, 5 * 60)
@UseGuards(ShareTokenSecurity)
@Post(":id/token")
async getShareToken(@Param("id") id: string, @Body() body: SharePasswordDto) {

View File

@@ -24,7 +24,7 @@ export class ShareService {
private jwtService: JwtService
) {}
async create(share: CreateShareDTO, user: User) {
async create(share: CreateShareDTO, user?: User) {
if (!(await this.isShareIdAvailable(share.id)).isAvailable)
throw new BadRequestException("Share id already in use");
@@ -58,7 +58,7 @@ export class ShareService {
data: {
...share,
expiration: expirationDate,
creator: { connect: { id: user.id } },
creator: { connect: user ? { id: user.id } : undefined },
security: { create: share.security },
},
});
@@ -154,6 +154,8 @@ export class ShareService {
});
if (!share) throw new NotFoundException("Share not found");
if (!share.creatorId)
throw new ForbiddenException("Anonymous shares can't be deleted");
await this.fileService.deleteAllFiles(shareId);
await this.prisma.share.delete({ where: { id: shareId } });

View File

@@ -1,3 +1,4 @@
SHOW_HOME_PAGE=true
ALLOW_REGISTRATION=true
MAX_FILE_SIZE=1000000000
ALLOW_UNAUTHENTICATED_SHARES=false

View File

@@ -1,25 +0,0 @@
FROM node:18-alpine AS deps
WORKDIR /opt/app
FROM node:18-alpine AS builder
ENV NODE_ENV=production
WORKDIR /opt/app
COPY . .
COPY --from=deps /opt/app/node_modules ./node_modules
RUN npm run build
FROM node:18-alpine AS runner
WORKDIR /opt/app
ENV NODE_ENV=production
COPY --from=builder /opt/app/next.config.js ./
COPY --from=builder /opt/app/public ./public
COPY --from=builder /opt/app/.next ./.next
COPY --from=builder /opt/app/node_modules ./node_modules
RUN npm i -g dotenv-cli
EXPOSE 3000
CMD dotenv -e .env.development node_modules/.bin/next start

View File

@@ -5,6 +5,7 @@ const nextConfig = {
ALLOW_REGISTRATION: process.env.ALLOW_REGISTRATION,
SHOW_HOME_PAGE: process.env.SHOW_HOME_PAGE,
MAX_FILE_SIZE: process.env.MAX_FILE_SIZE,
ALLOW_UNAUTHENTICATED_SHARES: process.env.ALLOW_UNAUTHENTICATED_SHARES
}
}

View File

@@ -8,6 +8,8 @@
"name": "pingvin-share",
"version": "0.0.1",
"dependencies": {
"@emotion/react": "^11.10.4",
"@emotion/server": "^11.10.0",
"@mantine/core": "^5.5.2",
"@mantine/dropzone": "^5.5.2",
"@mantine/form": "^5.5.2",
@@ -19,7 +21,7 @@
"cookies-next": "^2.0.4",
"file-saver": "^2.0.5",
"jose": "^4.8.1",
"moment": "^2.29.3",
"moment": "^2.29.4",
"next": "^12.3.1",
"next-cookies": "^2.0.3",
"next-http-proxy-middleware": "^1.2.4",
@@ -897,7 +899,6 @@
"version": "7.18.6",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz",
"integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==",
"peer": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.18.6"
},
@@ -1680,7 +1681,6 @@
"version": "11.10.2",
"resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.10.2.tgz",
"integrity": "sha512-xNQ57njWTFVfPAc3cjfuaPdsgLp5QOSuRsj9MA6ndEhH/AzuZM86qIQzt6rq+aGBwj3n5/TkLmU5lhAfdRmogA==",
"peer": true,
"dependencies": {
"@babel/helper-module-imports": "^7.16.7",
"@babel/plugin-syntax-jsx": "^7.17.12",
@@ -1703,7 +1703,6 @@
"version": "11.10.3",
"resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.10.3.tgz",
"integrity": "sha512-Psmp/7ovAa8appWh3g51goxu/z3iVms7JXOreq136D8Bbn6dYraPnmL6mdM8GThEx9vwSn92Fz+mGSjBzN8UPQ==",
"peer": true,
"dependencies": {
"@emotion/memoize": "^0.8.0",
"@emotion/sheet": "^1.2.0",
@@ -1715,20 +1714,17 @@
"node_modules/@emotion/hash": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.0.tgz",
"integrity": "sha512-14FtKiHhy2QoPIzdTcvh//8OyBlknNs2nXRwIhG904opCby3l+9Xaf/wuPvICBF0rc1ZCNBd3nKe9cd2mecVkQ==",
"peer": true
"integrity": "sha512-14FtKiHhy2QoPIzdTcvh//8OyBlknNs2nXRwIhG904opCby3l+9Xaf/wuPvICBF0rc1ZCNBd3nKe9cd2mecVkQ=="
},
"node_modules/@emotion/memoize": {
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.0.tgz",
"integrity": "sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA==",
"peer": true
"integrity": "sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA=="
},
"node_modules/@emotion/react": {
"version": "11.10.4",
"resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.10.4.tgz",
"integrity": "sha512-j0AkMpr6BL8gldJZ6XQsQ8DnS9TxEQu1R+OGmDZiWjBAJtCcbt0tS3I/YffoqHXxH6MjgI7KdMbYKw3MEiU9eA==",
"peer": true,
"dependencies": {
"@babel/runtime": "^7.18.3",
"@emotion/babel-plugin": "^11.10.0",
@@ -1756,7 +1752,6 @@
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.0.tgz",
"integrity": "sha512-F1ZZZW51T/fx+wKbVlwsfchr5q97iW8brAnXmsskz4d0hVB4O3M/SiA3SaeH06x02lSNzkkQv+n3AX3kCXKSFA==",
"peer": true,
"dependencies": {
"@emotion/hash": "^0.9.0",
"@emotion/memoize": "^0.8.0",
@@ -1769,7 +1764,6 @@
"version": "11.10.0",
"resolved": "https://registry.npmjs.org/@emotion/server/-/server-11.10.0.tgz",
"integrity": "sha512-MTvJ21JPo9aS02GdjFW4nhdwOi2tNNpMmAM/YED0pkxzjDNi5WbiTwXqaCnvLc2Lr8NFtjhT0az1vTJyLIHYcw==",
"peer": true,
"dependencies": {
"@emotion/utils": "^1.2.0",
"html-tokenize": "^2.0.0",
@@ -1788,20 +1782,17 @@
"node_modules/@emotion/sheet": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.0.tgz",
"integrity": "sha512-OiTkRgpxescko+M51tZsMq7Puu/KP55wMT8BgpcXVG2hqXc0Vo0mfymJ/Uj24Hp0i083ji/o0aLddh08UEjq8w==",
"peer": true
"integrity": "sha512-OiTkRgpxescko+M51tZsMq7Puu/KP55wMT8BgpcXVG2hqXc0Vo0mfymJ/Uj24Hp0i083ji/o0aLddh08UEjq8w=="
},
"node_modules/@emotion/unitless": {
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.0.tgz",
"integrity": "sha512-VINS5vEYAscRl2ZUDiT3uMPlrFQupiKgHz5AA4bCH1miKBg4qtwkim1qPmJj/4WG6TreYMY111rEFsjupcOKHw==",
"peer": true
"integrity": "sha512-VINS5vEYAscRl2ZUDiT3uMPlrFQupiKgHz5AA4bCH1miKBg4qtwkim1qPmJj/4WG6TreYMY111rEFsjupcOKHw=="
},
"node_modules/@emotion/use-insertion-effect-with-fallbacks": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.0.tgz",
"integrity": "sha512-1eEgUGmkaljiBnRMTdksDV1W4kUnmwgp7X9G8B++9GYwl1lUdqSndSriIrTJ0N7LQaoauY9JJ2yhiOYK5+NI4A==",
"peer": true,
"peerDependencies": {
"react": ">=16.8.0"
}
@@ -1809,14 +1800,12 @@
"node_modules/@emotion/utils": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.0.tgz",
"integrity": "sha512-sn3WH53Kzpw8oQ5mgMmIzzyAaH2ZqFEbozVVBSYp538E06OSE6ytOp7pRAjNQR+Q/orwqdQYJSe2m3hCOeznkw==",
"peer": true
"integrity": "sha512-sn3WH53Kzpw8oQ5mgMmIzzyAaH2ZqFEbozVVBSYp538E06OSE6ytOp7pRAjNQR+Q/orwqdQYJSe2m3hCOeznkw=="
},
"node_modules/@emotion/weak-memoize": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.0.tgz",
"integrity": "sha512-AHPmaAx+RYfZz0eYu6Gviiagpmiyw98ySSlQvCUhVGDRtDFe4DBS0x1bSjdF3gqUDYOczB+yYvBTtEylYSdRhg==",
"peer": true
"integrity": "sha512-AHPmaAx+RYfZz0eYu6Gviiagpmiyw98ySSlQvCUhVGDRtDFe4DBS0x1bSjdF3gqUDYOczB+yYvBTtEylYSdRhg=="
},
"node_modules/@eslint/eslintrc": {
"version": "1.2.1",
@@ -2649,8 +2638,7 @@
"node_modules/@types/parse-json": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz",
"integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==",
"peer": true
"integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA=="
},
"node_modules/@types/prop-types": {
"version": "15.7.5",
@@ -3126,7 +3114,6 @@
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz",
"integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==",
"peer": true,
"dependencies": {
"@babel/runtime": "^7.12.5",
"cosmiconfig": "^7.0.0",
@@ -3244,8 +3231,7 @@
"node_modules/buffer-from": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-0.1.2.tgz",
"integrity": "sha512-RiWIenusJsmI2KcvqQABB83tLxCByE3upSP8QU3rJDMVFGPWLvPQJt/O1Su9moRWeH7d+Q2HYb68f6+v+tw2vg==",
"peer": true
"integrity": "sha512-RiWIenusJsmI2KcvqQABB83tLxCByE3upSP8QU3rJDMVFGPWLvPQJt/O1Su9moRWeH7d+Q2HYb68f6+v+tw2vg=="
},
"node_modules/builtin-modules": {
"version": "3.3.0",
@@ -3449,14 +3435,12 @@
"node_modules/core-util-is": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
"peer": true
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
},
"node_modules/cosmiconfig": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz",
"integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==",
"peer": true,
"dependencies": {
"@types/parse-json": "^4.0.0",
"import-fresh": "^3.2.1",
@@ -3732,7 +3716,6 @@
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz",
"integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==",
"peer": true,
"dependencies": {
"readable-stream": "^2.0.2"
}
@@ -3740,14 +3723,12 @@
"node_modules/duplexer2/node_modules/isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
"peer": true
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="
},
"node_modules/duplexer2/node_modules/readable-stream": {
"version": "2.3.7",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
"integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
"peer": true,
"dependencies": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
@@ -3762,7 +3743,6 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"peer": true,
"dependencies": {
"safe-buffer": "~5.1.0"
}
@@ -3828,7 +3808,6 @@
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
"integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
"peer": true,
"dependencies": {
"is-arrayish": "^0.2.1"
}
@@ -4615,8 +4594,7 @@
"node_modules/find-root": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz",
"integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==",
"peer": true
"integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng=="
},
"node_modules/find-up": {
"version": "2.1.0",
@@ -4896,7 +4874,6 @@
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
"integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
"peer": true,
"dependencies": {
"react-is": "^16.7.0"
}
@@ -4928,7 +4905,6 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/html-tokenize/-/html-tokenize-2.0.1.tgz",
"integrity": "sha512-QY6S+hZ0f5m1WT8WffYN+Hg+xm/w5I8XeUcAq/ZYP5wVC8xbKi4Whhru3FtrAebD5EhBW8rmFzkDI6eCAuFe2w==",
"peer": true,
"dependencies": {
"buffer-from": "~0.1.1",
"inherits": "~2.0.1",
@@ -5043,8 +5019,7 @@
"node_modules/is-arrayish": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
"integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
"peer": true
"integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="
},
"node_modules/is-bigint": {
"version": "1.0.4",
@@ -5290,8 +5265,7 @@
"node_modules/isarray": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
"integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==",
"peer": true
"integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ=="
},
"node_modules/isexe": {
"version": "2.0.0",
@@ -5344,9 +5318,9 @@
}
},
"node_modules/jose": {
"version": "4.8.1",
"resolved": "https://registry.npmjs.org/jose/-/jose-4.8.1.tgz",
"integrity": "sha512-+/hpTbRcCw9YC0TOfN1W47pej4a9lRmltdOVdRLz5FP5UvUq3CenhXjQK7u/8NdMIIShMXYAh9VLPhc7TjhvFw==",
"version": "4.10.0",
"resolved": "https://registry.npmjs.org/jose/-/jose-4.10.0.tgz",
"integrity": "sha512-KEhB/eLGLomWGPTb+/RNbYsTjIyx03JmbqAyIyiXBuNSa7CmNrJd5ysFhblayzs/e/vbOPMUaLnjHUMhGp4yLw==",
"funding": {
"url": "https://github.com/sponsors/panva"
}
@@ -5388,8 +5362,7 @@
"node_modules/json-parse-even-better-errors": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
"integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
"peer": true
"integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="
},
"node_modules/json-schema": {
"version": "0.4.0",
@@ -5498,8 +5471,7 @@
"node_modules/lines-and-columns": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
"peer": true
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="
},
"node_modules/loader-runner": {
"version": "4.3.0",
@@ -5726,9 +5698,9 @@
}
},
"node_modules/moment": {
"version": "2.29.3",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.3.tgz",
"integrity": "sha512-c6YRvhEo//6T2Jz/vVtYzqBzwvPT95JBQ+smCytzf7c50oMZRsR/a4w88aD34I+/QVSfnoAnSBFPJHItlOMJVw==",
"version": "2.29.4",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
"integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==",
"engines": {
"node": "*"
}
@@ -5742,7 +5714,6 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/multipipe/-/multipipe-1.0.2.tgz",
"integrity": "sha512-6uiC9OvY71vzSGX8lZvSqscE7ft9nPupJ8fMjrCNRAUy2LREUW42UL+V/NTrogr6rFgRydUrCX4ZitfpSNkSCQ==",
"peer": true,
"dependencies": {
"duplexer2": "^0.1.2",
"object-assign": "^4.1.0"
@@ -6052,7 +6023,6 @@
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
"integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
"peer": true,
"dependencies": {
"@babel/code-frame": "^7.0.0",
"error-ex": "^1.3.1",
@@ -6289,8 +6259,7 @@
"node_modules/process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
"peer": true
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
},
"node_modules/prop-types": {
"version": "15.8.1",
@@ -6434,7 +6403,6 @@
"version": "1.0.34",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
"integrity": "sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==",
"peer": true,
"dependencies": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.1",
@@ -6774,7 +6742,6 @@
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
"integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
"peer": true,
"engines": {
"node": ">=0.10.0"
}
@@ -6817,8 +6784,7 @@
"node_modules/string_decoder": {
"version": "0.10.31",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
"integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==",
"peer": true
"integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ=="
},
"node_modules/string.prototype.matchall": {
"version": "4.0.7",
@@ -6954,8 +6920,7 @@
"node_modules/stylis": {
"version": "4.0.13",
"resolved": "https://registry.npmjs.org/stylis/-/stylis-4.0.13.tgz",
"integrity": "sha512-xGPXiFVl4YED9Jh7Euv2V220mriG9u4B2TA6Ybjc1catrstKD2PpIdU3U0RKpkVBC2EhmL/F0sPCr9vrFTNRag==",
"peer": true
"integrity": "sha512-xGPXiFVl4YED9Jh7Euv2V220mriG9u4B2TA6Ybjc1catrstKD2PpIdU3U0RKpkVBC2EhmL/F0sPCr9vrFTNRag=="
},
"node_modules/supports-color": {
"version": "7.2.0",
@@ -7117,14 +7082,12 @@
"node_modules/through": {
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
"integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==",
"peer": true
"integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg=="
},
"node_modules/through2": {
"version": "0.4.2",
"resolved": "https://registry.npmjs.org/through2/-/through2-0.4.2.tgz",
"integrity": "sha512-45Llu+EwHKtAZYTPPVn3XZHBgakWMN3rokhEv5hu596XP+cNgplMg+Gj+1nmAvj+L0K7+N49zBKx5rah5u0QIQ==",
"peer": true,
"dependencies": {
"readable-stream": "~1.0.17",
"xtend": "~2.1.1"
@@ -7400,8 +7363,7 @@
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
"peer": true
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
},
"node_modules/v8-compile-cache": {
"version": "2.3.0",
@@ -7838,7 +7800,6 @@
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz",
"integrity": "sha512-vMNKzr2rHP9Dp/e1NQFnLQlwlhp9L/LfvnsVdHxN1f+uggyVI3i08uD14GPvCToPkdsRfyPqIyYGmIk58V98ZQ==",
"peer": true,
"dependencies": {
"object-keys": "~0.4.0"
},
@@ -7849,8 +7810,7 @@
"node_modules/xtend/node_modules/object-keys": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz",
"integrity": "sha512-ncrLw+X55z7bkl5PnUvHwFK9FcGuFYo9gtjws2XtSzL+aZ8tm830P60WJ0dSmFVaSalWieW5MD7kEdnXda9yJw==",
"peer": true
"integrity": "sha512-ncrLw+X55z7bkl5PnUvHwFK9FcGuFYo9gtjws2XtSzL+aZ8tm830P60WJ0dSmFVaSalWieW5MD7kEdnXda9yJw=="
},
"node_modules/yallist": {
"version": "4.0.0",
@@ -7862,7 +7822,6 @@
"version": "1.10.2",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
"integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==",
"peer": true,
"engines": {
"node": ">= 6"
}
@@ -8474,7 +8433,6 @@
"version": "7.18.6",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz",
"integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==",
"peer": true,
"requires": {
"@babel/helper-plugin-utils": "^7.18.6"
}
@@ -9002,7 +8960,6 @@
"version": "11.10.2",
"resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.10.2.tgz",
"integrity": "sha512-xNQ57njWTFVfPAc3cjfuaPdsgLp5QOSuRsj9MA6ndEhH/AzuZM86qIQzt6rq+aGBwj3n5/TkLmU5lhAfdRmogA==",
"peer": true,
"requires": {
"@babel/helper-module-imports": "^7.16.7",
"@babel/plugin-syntax-jsx": "^7.17.12",
@@ -9022,7 +8979,6 @@
"version": "11.10.3",
"resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.10.3.tgz",
"integrity": "sha512-Psmp/7ovAa8appWh3g51goxu/z3iVms7JXOreq136D8Bbn6dYraPnmL6mdM8GThEx9vwSn92Fz+mGSjBzN8UPQ==",
"peer": true,
"requires": {
"@emotion/memoize": "^0.8.0",
"@emotion/sheet": "^1.2.0",
@@ -9034,20 +8990,17 @@
"@emotion/hash": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.0.tgz",
"integrity": "sha512-14FtKiHhy2QoPIzdTcvh//8OyBlknNs2nXRwIhG904opCby3l+9Xaf/wuPvICBF0rc1ZCNBd3nKe9cd2mecVkQ==",
"peer": true
"integrity": "sha512-14FtKiHhy2QoPIzdTcvh//8OyBlknNs2nXRwIhG904opCby3l+9Xaf/wuPvICBF0rc1ZCNBd3nKe9cd2mecVkQ=="
},
"@emotion/memoize": {
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.0.tgz",
"integrity": "sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA==",
"peer": true
"integrity": "sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA=="
},
"@emotion/react": {
"version": "11.10.4",
"resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.10.4.tgz",
"integrity": "sha512-j0AkMpr6BL8gldJZ6XQsQ8DnS9TxEQu1R+OGmDZiWjBAJtCcbt0tS3I/YffoqHXxH6MjgI7KdMbYKw3MEiU9eA==",
"peer": true,
"requires": {
"@babel/runtime": "^7.18.3",
"@emotion/babel-plugin": "^11.10.0",
@@ -9063,7 +9016,6 @@
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.0.tgz",
"integrity": "sha512-F1ZZZW51T/fx+wKbVlwsfchr5q97iW8brAnXmsskz4d0hVB4O3M/SiA3SaeH06x02lSNzkkQv+n3AX3kCXKSFA==",
"peer": true,
"requires": {
"@emotion/hash": "^0.9.0",
"@emotion/memoize": "^0.8.0",
@@ -9076,7 +9028,6 @@
"version": "11.10.0",
"resolved": "https://registry.npmjs.org/@emotion/server/-/server-11.10.0.tgz",
"integrity": "sha512-MTvJ21JPo9aS02GdjFW4nhdwOi2tNNpMmAM/YED0pkxzjDNi5WbiTwXqaCnvLc2Lr8NFtjhT0az1vTJyLIHYcw==",
"peer": true,
"requires": {
"@emotion/utils": "^1.2.0",
"html-tokenize": "^2.0.0",
@@ -9087,33 +9038,28 @@
"@emotion/sheet": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.0.tgz",
"integrity": "sha512-OiTkRgpxescko+M51tZsMq7Puu/KP55wMT8BgpcXVG2hqXc0Vo0mfymJ/Uj24Hp0i083ji/o0aLddh08UEjq8w==",
"peer": true
"integrity": "sha512-OiTkRgpxescko+M51tZsMq7Puu/KP55wMT8BgpcXVG2hqXc0Vo0mfymJ/Uj24Hp0i083ji/o0aLddh08UEjq8w=="
},
"@emotion/unitless": {
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.0.tgz",
"integrity": "sha512-VINS5vEYAscRl2ZUDiT3uMPlrFQupiKgHz5AA4bCH1miKBg4qtwkim1qPmJj/4WG6TreYMY111rEFsjupcOKHw==",
"peer": true
"integrity": "sha512-VINS5vEYAscRl2ZUDiT3uMPlrFQupiKgHz5AA4bCH1miKBg4qtwkim1qPmJj/4WG6TreYMY111rEFsjupcOKHw=="
},
"@emotion/use-insertion-effect-with-fallbacks": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.0.tgz",
"integrity": "sha512-1eEgUGmkaljiBnRMTdksDV1W4kUnmwgp7X9G8B++9GYwl1lUdqSndSriIrTJ0N7LQaoauY9JJ2yhiOYK5+NI4A==",
"peer": true,
"requires": {}
},
"@emotion/utils": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.0.tgz",
"integrity": "sha512-sn3WH53Kzpw8oQ5mgMmIzzyAaH2ZqFEbozVVBSYp538E06OSE6ytOp7pRAjNQR+Q/orwqdQYJSe2m3hCOeznkw==",
"peer": true
"integrity": "sha512-sn3WH53Kzpw8oQ5mgMmIzzyAaH2ZqFEbozVVBSYp538E06OSE6ytOp7pRAjNQR+Q/orwqdQYJSe2m3hCOeznkw=="
},
"@emotion/weak-memoize": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.0.tgz",
"integrity": "sha512-AHPmaAx+RYfZz0eYu6Gviiagpmiyw98ySSlQvCUhVGDRtDFe4DBS0x1bSjdF3gqUDYOczB+yYvBTtEylYSdRhg==",
"peer": true
"integrity": "sha512-AHPmaAx+RYfZz0eYu6Gviiagpmiyw98ySSlQvCUhVGDRtDFe4DBS0x1bSjdF3gqUDYOczB+yYvBTtEylYSdRhg=="
},
"@eslint/eslintrc": {
"version": "1.2.1",
@@ -9695,8 +9641,7 @@
"@types/parse-json": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz",
"integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==",
"peer": true
"integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA=="
},
"@types/prop-types": {
"version": "15.7.5",
@@ -10094,7 +10039,6 @@
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz",
"integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==",
"peer": true,
"requires": {
"@babel/runtime": "^7.12.5",
"cosmiconfig": "^7.0.0",
@@ -10176,8 +10120,7 @@
"buffer-from": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-0.1.2.tgz",
"integrity": "sha512-RiWIenusJsmI2KcvqQABB83tLxCByE3upSP8QU3rJDMVFGPWLvPQJt/O1Su9moRWeH7d+Q2HYb68f6+v+tw2vg==",
"peer": true
"integrity": "sha512-RiWIenusJsmI2KcvqQABB83tLxCByE3upSP8QU3rJDMVFGPWLvPQJt/O1Su9moRWeH7d+Q2HYb68f6+v+tw2vg=="
},
"builtin-modules": {
"version": "3.3.0",
@@ -10322,14 +10265,12 @@
"core-util-is": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
"peer": true
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
},
"cosmiconfig": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz",
"integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==",
"peer": true,
"requires": {
"@types/parse-json": "^4.0.0",
"import-fresh": "^3.2.1",
@@ -10537,7 +10478,6 @@
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz",
"integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==",
"peer": true,
"requires": {
"readable-stream": "^2.0.2"
},
@@ -10545,14 +10485,12 @@
"isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
"peer": true
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="
},
"readable-stream": {
"version": "2.3.7",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
"integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
"peer": true,
"requires": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
@@ -10567,7 +10505,6 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"peer": true,
"requires": {
"safe-buffer": "~5.1.0"
}
@@ -10617,7 +10554,6 @@
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
"integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
"peer": true,
"requires": {
"is-arrayish": "^0.2.1"
}
@@ -11226,8 +11162,7 @@
"find-root": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz",
"integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==",
"peer": true
"integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng=="
},
"find-up": {
"version": "2.1.0",
@@ -11420,7 +11355,6 @@
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
"integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
"peer": true,
"requires": {
"react-is": "^16.7.0"
}
@@ -11449,7 +11383,6 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/html-tokenize/-/html-tokenize-2.0.1.tgz",
"integrity": "sha512-QY6S+hZ0f5m1WT8WffYN+Hg+xm/w5I8XeUcAq/ZYP5wVC8xbKi4Whhru3FtrAebD5EhBW8rmFzkDI6eCAuFe2w==",
"peer": true,
"requires": {
"buffer-from": "~0.1.1",
"inherits": "~2.0.1",
@@ -11536,8 +11469,7 @@
"is-arrayish": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
"integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
"peer": true
"integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="
},
"is-bigint": {
"version": "1.0.4",
@@ -11693,8 +11625,7 @@
"isarray": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
"integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==",
"peer": true
"integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ=="
},
"isexe": {
"version": "2.0.0",
@@ -11734,9 +11665,9 @@
}
},
"jose": {
"version": "4.8.1",
"resolved": "https://registry.npmjs.org/jose/-/jose-4.8.1.tgz",
"integrity": "sha512-+/hpTbRcCw9YC0TOfN1W47pej4a9lRmltdOVdRLz5FP5UvUq3CenhXjQK7u/8NdMIIShMXYAh9VLPhc7TjhvFw=="
"version": "4.10.0",
"resolved": "https://registry.npmjs.org/jose/-/jose-4.10.0.tgz",
"integrity": "sha512-KEhB/eLGLomWGPTb+/RNbYsTjIyx03JmbqAyIyiXBuNSa7CmNrJd5ysFhblayzs/e/vbOPMUaLnjHUMhGp4yLw=="
},
"js-tokens": {
"version": "4.0.0",
@@ -11766,8 +11697,7 @@
"json-parse-even-better-errors": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
"integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
"peer": true
"integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="
},
"json-schema": {
"version": "0.4.0",
@@ -11856,8 +11786,7 @@
"lines-and-columns": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
"peer": true
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="
},
"loader-runner": {
"version": "4.3.0",
@@ -12031,9 +11960,9 @@
"dev": true
},
"moment": {
"version": "2.29.3",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.3.tgz",
"integrity": "sha512-c6YRvhEo//6T2Jz/vVtYzqBzwvPT95JBQ+smCytzf7c50oMZRsR/a4w88aD34I+/QVSfnoAnSBFPJHItlOMJVw=="
"version": "2.29.4",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
"integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w=="
},
"ms": {
"version": "2.1.2",
@@ -12044,7 +11973,6 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/multipipe/-/multipipe-1.0.2.tgz",
"integrity": "sha512-6uiC9OvY71vzSGX8lZvSqscE7ft9nPupJ8fMjrCNRAUy2LREUW42UL+V/NTrogr6rFgRydUrCX4ZitfpSNkSCQ==",
"peer": true,
"requires": {
"duplexer2": "^0.1.2",
"object-assign": "^4.1.0"
@@ -12265,7 +12193,6 @@
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
"integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
"peer": true,
"requires": {
"@babel/code-frame": "^7.0.0",
"error-ex": "^1.3.1",
@@ -12416,8 +12343,7 @@
"process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
"peer": true
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
},
"prop-types": {
"version": "15.8.1",
@@ -12520,7 +12446,6 @@
"version": "1.0.34",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
"integrity": "sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==",
"peer": true,
"requires": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.1",
@@ -12766,8 +12691,7 @@
"source-map": {
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
"integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
"peer": true
"integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
},
"source-map-js": {
"version": "1.0.2",
@@ -12803,8 +12727,7 @@
"string_decoder": {
"version": "0.10.31",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
"integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==",
"peer": true
"integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ=="
},
"string.prototype.matchall": {
"version": "4.0.7",
@@ -12900,8 +12823,7 @@
"stylis": {
"version": "4.0.13",
"resolved": "https://registry.npmjs.org/stylis/-/stylis-4.0.13.tgz",
"integrity": "sha512-xGPXiFVl4YED9Jh7Euv2V220mriG9u4B2TA6Ybjc1catrstKD2PpIdU3U0RKpkVBC2EhmL/F0sPCr9vrFTNRag==",
"peer": true
"integrity": "sha512-xGPXiFVl4YED9Jh7Euv2V220mriG9u4B2TA6Ybjc1catrstKD2PpIdU3U0RKpkVBC2EhmL/F0sPCr9vrFTNRag=="
},
"supports-color": {
"version": "7.2.0",
@@ -13003,14 +12925,12 @@
"through": {
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
"integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==",
"peer": true
"integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg=="
},
"through2": {
"version": "0.4.2",
"resolved": "https://registry.npmjs.org/through2/-/through2-0.4.2.tgz",
"integrity": "sha512-45Llu+EwHKtAZYTPPVn3XZHBgakWMN3rokhEv5hu596XP+cNgplMg+Gj+1nmAvj+L0K7+N49zBKx5rah5u0QIQ==",
"peer": true,
"requires": {
"readable-stream": "~1.0.17",
"xtend": "~2.1.1"
@@ -13198,8 +13118,7 @@
"util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
"peer": true
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
},
"v8-compile-cache": {
"version": "2.3.0",
@@ -13571,7 +13490,6 @@
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz",
"integrity": "sha512-vMNKzr2rHP9Dp/e1NQFnLQlwlhp9L/LfvnsVdHxN1f+uggyVI3i08uD14GPvCToPkdsRfyPqIyYGmIk58V98ZQ==",
"peer": true,
"requires": {
"object-keys": "~0.4.0"
},
@@ -13579,8 +13497,7 @@
"object-keys": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz",
"integrity": "sha512-ncrLw+X55z7bkl5PnUvHwFK9FcGuFYo9gtjws2XtSzL+aZ8tm830P60WJ0dSmFVaSalWieW5MD7kEdnXda9yJw==",
"peer": true
"integrity": "sha512-ncrLw+X55z7bkl5PnUvHwFK9FcGuFYo9gtjws2XtSzL+aZ8tm830P60WJ0dSmFVaSalWieW5MD7kEdnXda9yJw=="
}
}
},
@@ -13593,8 +13510,7 @@
"yaml": {
"version": "1.10.2",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
"integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==",
"peer": true
"integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg=="
},
"yup": {
"version": "0.32.11",

View File

@@ -22,7 +22,7 @@
"cookies-next": "^2.0.4",
"file-saver": "^2.0.5",
"jose": "^4.8.1",
"moment": "^2.29.3",
"moment": "^2.29.4",
"next": "^12.3.1",
"next-cookies": "^2.0.3",
"next-http-proxy-middleware": "^1.2.4",

View File

@@ -1,18 +0,0 @@
import { Anchor, Center, Footer as MFooter, Text } from "@mantine/core";
const Footer = () => {
return (
<MFooter height="auto" p={10}>
<Center>
<Text size="xs" color="dimmed">
Made with 🖤 by{" "}
<Anchor size="xs" href="https://eliasschneider.com" target="_blank">
Elias Schneider
</Anchor>
</Text>
</Center>
</MFooter>
);
};
export default Footer;

View File

@@ -1,219 +0,0 @@
import {
Accordion,
Button,
Checkbox,
Col,
Grid,
NumberInput,
PasswordInput,
Select,
Stack,
Text,
TextInput,
} from "@mantine/core";
import { useForm, yupResolver } from "@mantine/form";
import { useModals } from "@mantine/modals";
import moment from "moment";
import * as yup from "yup";
import shareService from "../../services/share.service";
import { ShareSecurity } from "../../types/share.type";
const PreviewExpiration = ({ form }: { form: any }) => {
const value = form.values.never_expires
? "never"
: form.values.expiration_num + form.values.expiration_unit;
if (value === "never") return "This share will never expire.";
const expirationDate = moment()
.add(
value.split("-")[0],
value.split("-")[1] as moment.unitOfTime.DurationConstructor
)
.toDate();
return `This share will expire on ${moment(expirationDate).format("LLL")}`;
};
const CreateUploadModalBody = ({
uploadCallback,
}: {
uploadCallback: (
id: string,
expiration: string,
security: ShareSecurity
) => void;
}) => {
const modals = useModals();
const validationSchema = yup.object().shape({
link: yup
.string()
.required()
.min(3)
.max(50)
.matches(new RegExp("^[a-zA-Z0-9_-]*$"), {
message: "Can only contain letters, numbers, underscores and hyphens",
}),
password: yup.string().min(3).max(30),
maxViews: yup.number().min(1),
});
const form = useForm({
initialValues: {
link: "",
password: undefined,
maxViews: undefined,
expiration_num: 1,
expiration_unit: "-days",
never_expires: false,
},
validate: yupResolver(validationSchema),
});
return (
<form
onSubmit={form.onSubmit(async (values) => {
if (!(await shareService.isShareIdAvailable(values.link))) {
form.setFieldError("link", "This link is already in use");
} else {
const expiration = form.values.never_expires
? "never"
: form.values.expiration_num + form.values.expiration_unit;
uploadCallback(values.link, expiration, {
password: values.password,
maxViews: values.maxViews,
});
modals.closeAll();
}
})}
>
<Stack align="stretch">
<Grid align={form.errors.link ? "center" : "flex-end"}>
<Col xs={9}>
<TextInput
variant="filled"
label="Link"
placeholder="myAwesomeShare"
{...form.getInputProps("link")}
/>
</Col>
<Col xs={3}>
<Button
variant="outline"
onClick={() =>
form.setFieldValue(
"link",
Buffer.from(Math.random().toString(), "utf8")
.toString("base64")
.substr(10, 7)
)
}
>
Generate
</Button>
</Col>
</Grid>
<Text
italic
size="xs"
sx={(theme) => ({
color: theme.colors.gray[6],
})}
>
{window.location.origin}/share/
{form.values.link == "" ? "myAwesomeShare" : form.values.link}
</Text>
<Grid align={form.errors.link ? "center" : "flex-end"}>
<Col xs={6}>
<NumberInput
min={1}
max={99999}
precision={0}
variant="filled"
label="Expiration"
placeholder="n"
disabled={form.values.never_expires}
{...form.getInputProps("expiration_num")}
/>
</Col>
<Col xs={6}>
<Select
disabled={form.values.never_expires}
{...form.getInputProps("expiration_unit")}
data={[
// Set the label to singular if the number is 1, else plural
{
value: "-minutes",
label:
"Minute" + (form.values.expiration_num == 1 ? "" : "s"),
},
{
value: "-hours",
label: "Hour" + (form.values.expiration_num == 1 ? "" : "s"),
},
{
value: "-days",
label: "Day" + (form.values.expiration_num == 1 ? "" : "s"),
},
{
value: "-weeks",
label: "Week" + (form.values.expiration_num == 1 ? "" : "s"),
},
{
value: "-months",
label: "Month" + (form.values.expiration_num == 1 ? "" : "s"),
},
{
value: "-years",
label: "Year" + (form.values.expiration_num == 1 ? "" : "s"),
},
]}
/>
</Col>
</Grid>
<Checkbox
label="Never Expires"
{...form.getInputProps("never_expires")}
/>
{/* Preview expiration date text */}
<Text
italic
size="xs"
sx={(theme) => ({
color: theme.colors.gray[6],
})}
>
{PreviewExpiration({ form })}
</Text>
<Accordion>
<Accordion.Item value="security" sx={{ borderBottom: "none" }}>
<Accordion.Control>Security options</Accordion.Control>
<Accordion.Panel>
<Stack align="stretch">
<PasswordInput
variant="filled"
placeholder="No password"
label="Password protection"
{...form.getInputProps("password")}
/>
<NumberInput
min={1}
type="number"
variant="filled"
placeholder="No limit"
label="Maximal views"
{...form.getInputProps("maxViews")}
/>
</Stack>
</Accordion.Panel>
</Accordion.Item>
</Accordion>
<Button type="submit">Share</Button>
</Stack>
</form>
);
};
export default CreateUploadModalBody;

View File

@@ -0,0 +1,19 @@
import moment from "moment";
const ExpirationPreview = ({ form }: { form: any }) => {
const value = form.values.never_expires
? "never"
: form.values.expiration_num + form.values.expiration_unit;
if (value === "never") return "This share will never expire.";
const expirationDate = moment()
.add(
value.split("-")[0],
value.split("-")[1] as moment.unitOfTime.DurationConstructor
)
.toDate();
return `This share will expire on ${moment(expirationDate).format("LLL")}`;
};
export default ExpirationPreview;

View File

@@ -13,8 +13,8 @@ import moment from "moment";
import getConfig from "next/config";
import { useRouter } from "next/router";
import { TbCopy } from "react-icons/tb";
import { Share } from "../../types/share.type";
import toast from "../../utils/toast.util";
import { Share } from "../../../types/share.type";
import toast from "../../../utils/toast.util";
const { publicRuntimeConfig } = getConfig();

View File

@@ -0,0 +1,256 @@
import {
Accordion,
Alert,
Button,
Checkbox,
Col,
Grid,
Group,
NumberInput,
PasswordInput,
Select,
Stack,
Text,
TextInput,
Title,
} from "@mantine/core";
import { useForm, yupResolver } from "@mantine/form";
import { useModals } from "@mantine/modals";
import { ModalsContextProps } from "@mantine/modals/lib/context";
import getConfig from "next/config";
import { useState } from "react";
import { TbAlertCircle } from "react-icons/tb";
import * as yup from "yup";
import shareService from "../../../services/share.service";
import { ShareSecurity } from "../../../types/share.type";
import ExpirationPreview from "../ExpirationPreview";
const { publicRuntimeConfig } = getConfig();
const showCreateUploadModal = (
modals: ModalsContextProps,
isSignedIn: boolean,
uploadCallback: (
id: string,
expiration: string,
security: ShareSecurity
) => void
) => {
return modals.openModal({
title: <Title order={4}>Share</Title>,
children: (
<CreateUploadModalBody
isSignedIn={isSignedIn}
uploadCallback={uploadCallback}
/>
),
});
};
const CreateUploadModalBody = ({
uploadCallback,
isSignedIn,
}: {
uploadCallback: (
id: string,
expiration: string,
security: ShareSecurity
) => void;
isSignedIn: boolean;
}) => {
const modals = useModals();
const [showNotSignedInAlert, setShowNotSignedInAlert] = useState(
publicRuntimeConfig.ALLOW_UNAUTHENTICATED_SHARES == "true"
);
const validationSchema = yup.object().shape({
link: yup
.string()
.required()
.min(3)
.max(50)
.matches(new RegExp("^[a-zA-Z0-9_-]*$"), {
message: "Can only contain letters, numbers, underscores and hyphens",
}),
password: yup.string().min(3).max(30),
maxViews: yup.number().min(1),
});
const form = useForm({
initialValues: {
link: "",
password: undefined,
maxViews: undefined,
expiration_num: 1,
expiration_unit: "-days",
never_expires: false,
},
validate: yupResolver(validationSchema),
});
return (
<Group>
{showNotSignedInAlert && !isSignedIn && (
<Alert
withCloseButton
onClose={() => setShowNotSignedInAlert(false)}
icon={<TbAlertCircle size={16} />}
title="You're not signed in"
color="yellow"
>
You will be unable to delete your share manually and view the visitor
count.
</Alert>
)}
<form
onSubmit={form.onSubmit(async (values) => {
if (!(await shareService.isShareIdAvailable(values.link))) {
form.setFieldError("link", "This link is already in use");
} else {
const expiration = form.values.never_expires
? "never"
: form.values.expiration_num + form.values.expiration_unit;
uploadCallback(values.link, expiration, {
password: values.password,
maxViews: values.maxViews,
});
modals.closeAll();
}
})}
>
<Stack align="stretch">
<Grid align={form.errors.link ? "center" : "flex-end"}>
<Col xs={9}>
<TextInput
variant="filled"
label="Link"
placeholder="myAwesomeShare"
{...form.getInputProps("link")}
/>
</Col>
<Col xs={3}>
<Button
variant="outline"
onClick={() =>
form.setFieldValue(
"link",
Buffer.from(Math.random().toString(), "utf8")
.toString("base64")
.substr(10, 7)
)
}
>
Generate
</Button>
</Col>
</Grid>
<Text
italic
size="xs"
sx={(theme) => ({
color: theme.colors.gray[6],
})}
>
{window.location.origin}/share/
{form.values.link == "" ? "myAwesomeShare" : form.values.link}
</Text>
<Grid align={form.errors.link ? "center" : "flex-end"}>
<Col xs={6}>
<NumberInput
min={1}
max={99999}
precision={0}
variant="filled"
label="Expiration"
placeholder="n"
disabled={form.values.never_expires}
{...form.getInputProps("expiration_num")}
/>
</Col>
<Col xs={6}>
<Select
disabled={form.values.never_expires}
{...form.getInputProps("expiration_unit")}
data={[
// Set the label to singular if the number is 1, else plural
{
value: "-minutes",
label:
"Minute" + (form.values.expiration_num == 1 ? "" : "s"),
},
{
value: "-hours",
label:
"Hour" + (form.values.expiration_num == 1 ? "" : "s"),
},
{
value: "-days",
label: "Day" + (form.values.expiration_num == 1 ? "" : "s"),
},
{
value: "-weeks",
label:
"Week" + (form.values.expiration_num == 1 ? "" : "s"),
},
{
value: "-months",
label:
"Month" + (form.values.expiration_num == 1 ? "" : "s"),
},
{
value: "-years",
label:
"Year" + (form.values.expiration_num == 1 ? "" : "s"),
},
]}
/>
</Col>
</Grid>
<Checkbox
label="Never Expires"
{...form.getInputProps("never_expires")}
/>
{/* Preview expiration date text */}
<Text
italic
size="xs"
sx={(theme) => ({
color: theme.colors.gray[6],
})}
>
{ExpirationPreview({ form })}
</Text>
<Accordion>
<Accordion.Item value="security" sx={{ borderBottom: "none" }}>
<Accordion.Control>Security options</Accordion.Control>
<Accordion.Panel>
<Stack align="stretch">
<PasswordInput
variant="filled"
placeholder="No password"
label="Password protection"
{...form.getInputProps("password")}
/>
<NumberInput
min={1}
type="number"
variant="filled"
placeholder="No limit"
label="Maximal views"
{...form.getInputProps("maxViews")}
/>
</Stack>
</Accordion.Panel>
</Accordion.Item>
</Accordion>
<Button type="submit">Share</Button>
</Stack>
</form>
</Group>
);
};
export default showCreateUploadModal;

View File

@@ -1,20 +0,0 @@
import { Title } from "@mantine/core";
import { ModalsContextProps } from "@mantine/modals/lib/context";
import { ShareSecurity } from "../../types/share.type";
import CreateUploadModalBody from "../share/CreateUploadModalBody";
const showCreateUploadModal = (
modals: ModalsContextProps,
uploadCallback: (
id: string,
expiration: string,
security: ShareSecurity
) => void
) => {
return modals.openModal({
title: <Title order={4}>Share</Title>,
children: <CreateUploadModalBody uploadCallback={uploadCallback} />,
});
};
export default showCreateUploadModal;

View File

@@ -3,14 +3,12 @@ import {
Container,
LoadingOverlay,
MantineProvider,
Stack,
} from "@mantine/core";
import { useColorScheme } from "@mantine/hooks";
import { ModalsProvider } from "@mantine/modals";
import { NotificationsProvider } from "@mantine/notifications";
import type { AppProps } from "next/app";
import { useEffect, useState } from "react";
import Footer from "../components/Footer";
import Header from "../components/navBar/NavBar";
import { UserContext } from "../hooks/user.hook";
import authService from "../services/auth.service";
@@ -58,15 +56,10 @@ function App({ Component, pageProps }: AppProps) {
) : (
<UserContext.Provider value={user}>
<LoadingOverlay visible={isLoading} overlayOpacity={1} />
<Stack justify="space-between" sx={{ minHeight: "100vh" }}>
<div>
<Header />
<Container>
<Component {...pageProps} />
</Container>
</div>
<Footer />
</Stack>
<Header />
<Container>
<Component {...pageProps} />
</Container>
</UserContext.Provider>
)}
</GlobalLoadingContext.Provider>
@@ -76,4 +69,9 @@ function App({ Component, pageProps }: AppProps) {
);
}
// Opts out of static site generation to use publicRuntimeConfig
App.getInitialProps = () => {
return {};
};
export default App;

View File

@@ -8,9 +8,11 @@ export const config = {
},
};
// This function can be marked `async` if using `await` inside
export default (req: NextApiRequest, res: NextApiResponse) =>
httpProxyMiddleware(req, res, {
// You can use the `http-proxy` option
export default (req: NextApiRequest, res: NextApiResponse) => {
return httpProxyMiddleware(req, res, {
headers: {
"X-Forwarded-For": req.socket.remoteAddress ?? "",
},
target: "http://localhost:8080",
});
};

View File

@@ -15,6 +15,7 @@ import { useRouter } from "next/router";
import { TbCheck } from "react-icons/tb";
import Meta from "../components/Meta";
import useUser from "../hooks/user.hook";
const { publicRuntimeConfig } = getConfig();
const useStyles = createStyles((theme) => ({
@@ -74,7 +75,7 @@ export default function Home() {
const { classes } = useStyles();
const router = useRouter();
if (user) {
if (user || publicRuntimeConfig.ALLOW_UNAUTHENTICATED_SHARES == "true") {
router.replace("/upload");
} else if (publicRuntimeConfig.SHOW_HOME_PAGE == "false") {
router.replace("/auth/signIn");

View File

@@ -1,19 +1,23 @@
import { Button, Group } from "@mantine/core";
import { useModals } from "@mantine/modals";
import axios from "axios";
import getConfig from "next/config";
import { useRouter } from "next/router";
import { useState } from "react";
import { useEffect, useState } from "react";
import Meta from "../components/Meta";
import Dropzone from "../components/upload/Dropzone";
import FileList from "../components/upload/FileList";
import showCompletedUploadModal from "../components/upload/showCompletedUploadModal";
import showCreateUploadModal from "../components/upload/showCreateUploadModal";
import showCompletedUploadModal from "../components/upload/modals/showCompletedUploadModal";
import showCreateUploadModal from "../components/upload/modals/showCreateUploadModal";
import useUser from "../hooks/user.hook";
import shareService from "../services/share.service";
import { FileUpload } from "../types/File.type";
import { ShareSecurity } from "../types/share.type";
import toast from "../utils/toast.util";
const { publicRuntimeConfig } = getConfig();
let share: any;
const Upload = () => {
const router = useRouter();
const modals = useModals();
@@ -35,7 +39,7 @@ const Upload = () => {
return file;
})
);
const share = await shareService.create(id, expiration, security);
share = await shareService.create(id, expiration, security);
for (let i = 0; i < files.length; i++) {
const progressCallBack = (bytesProgress: number) => {
setFiles((files) => {
@@ -55,27 +59,6 @@ const Upload = () => {
} catch {
files[i].uploadingProgress = -1;
}
if (
files.every(
(file) =>
file.uploadingProgress >= 100 || file.uploadingProgress == -1
)
) {
const fileErrorCount = files.filter(
(file) => file.uploadingProgress == -1
).length;
setisUploading(false);
if (fileErrorCount > 0) {
toast.error(
`${fileErrorCount} file(s) failed to upload. Try again.`
);
} else {
await shareService.completeShare(share.id);
showCompletedUploadModal(modals, share);
setFiles([]);
}
}
}
} catch (e) {
if (axios.isAxiosError(e)) {
@@ -86,7 +69,35 @@ const Upload = () => {
setisUploading(false);
}
};
if (!user) {
useEffect(() => {
if (
files.length > 0 &&
files.every(
(file) => file.uploadingProgress >= 100 || file.uploadingProgress == -1
)
) {
console.log(files.length);
const fileErrorCount = files.filter(
(file) => file.uploadingProgress == -1
).length;
setisUploading(false);
if (fileErrorCount > 0) {
toast.error(`${fileErrorCount} file(s) failed to upload. Try again.`);
} else {
shareService
.completeShare(share.id)
.then(() => {
showCompletedUploadModal(modals, share);
setFiles([]);
})
.catch(() =>
toast.error("An error occured while finishing your share.")
);
}
}
}, [files]);
if (!user && publicRuntimeConfig.ALLOW_UNAUTHENTICATED_SHARES == "false") {
router.replace("/");
} else {
return (
@@ -96,7 +107,9 @@ const Upload = () => {
<Button
loading={isUploading}
disabled={files.length <= 0}
onClick={() => showCreateUploadModal(modals, uploadFiles)}
onClick={() =>
showCreateUploadModal(modals, user ? true : false, uploadFiles)
}
>
Share
</Button>

View File

@@ -1,10 +1,10 @@
{
"name": "pingvin-share",
"version": "0.0.1",
"version": "0.1.0",
"scripts": {
"format": "cd frontend && npm run format && cd ../backend && npm run format",
"lint": "cd frontend && npm run lint && cd ../backend && npm run lint",
"version": "conventional-changelog -p angular -i CHANGELOG.md -s && git add CHANGELOG.md",
"version": "conventional-changelog -p conventionalcommits -i CHANGELOG.md -s && git add CHANGELOG.md",
"release:patch": "npm version patch -m 'release: %s' && git push && git push --tags",
"release:minor": "npm version minor -m 'release: %s' && git push && git push --tags"
}