generated from nhcarrigan/template
feat: auth
This commit is contained in:
@@ -0,0 +1,53 @@
|
|||||||
|
# Authentication Flow
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
This API uses Discord OAuth for authentication and JWT tokens for session management. Only the admin user can perform create/update/delete operations, while public read access is available to everyone.
|
||||||
|
|
||||||
|
## Environment Variables
|
||||||
|
Set up your `prod.env` file with 1Password references:
|
||||||
|
- `DATABASE_URL` - MongoDB connection string
|
||||||
|
- `JWT_SECRET` - Secret for signing JWT tokens
|
||||||
|
- `DISCORD_CLIENT_ID` - Discord OAuth app client ID
|
||||||
|
- `DISCORD_CLIENT_SECRET` - Discord OAuth app client secret
|
||||||
|
- `ADMIN_DISCORD_ID` - Your Discord user ID for admin access
|
||||||
|
- `API_URL` - API base URL (e.g., http://localhost:3000)
|
||||||
|
- `FRONTEND_URL` - Frontend URL to redirect after login
|
||||||
|
|
||||||
|
## Running the API
|
||||||
|
```bash
|
||||||
|
# Start with 1Password secrets
|
||||||
|
op run --env-file=prod.env -- nx serve api
|
||||||
|
```
|
||||||
|
|
||||||
|
## Auth Endpoints
|
||||||
|
|
||||||
|
### 1. Login
|
||||||
|
`GET /api/auth/login` - Redirects to Discord OAuth
|
||||||
|
|
||||||
|
### 2. Callback
|
||||||
|
`GET /api/auth/callback` - Discord redirects here after auth
|
||||||
|
- Creates/updates user in database
|
||||||
|
- Generates JWT token
|
||||||
|
- Sets httpOnly cookie `auth-token`
|
||||||
|
- Redirects to frontend
|
||||||
|
|
||||||
|
### 3. Get Current User
|
||||||
|
`GET /api/auth/me` - Returns authenticated user (requires auth)
|
||||||
|
|
||||||
|
### 4. Logout
|
||||||
|
`POST /api/auth/logout` - Clears auth cookie
|
||||||
|
|
||||||
|
## Protected Routes
|
||||||
|
Example: Games API
|
||||||
|
- `GET /api/games` - Public (list all games)
|
||||||
|
- `GET /api/games/:id` - Public (get single game)
|
||||||
|
- `POST /api/games` - Admin only (create game)
|
||||||
|
- `PUT /api/games/:id` - Admin only (update game)
|
||||||
|
- `DELETE /api/games/:id` - Admin only (delete game)
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
1. Set up Discord OAuth app at https://discord.com/developers/applications
|
||||||
|
2. Add redirect URI: `http://localhost:3000/api/auth/callback`
|
||||||
|
3. Copy client ID and secret to 1Password
|
||||||
|
4. Run the API and visit `http://localhost:3000/api/auth/login`
|
||||||
|
5. After Discord auth, you'll be redirected to frontend with auth cookie set
|
||||||
@@ -80,3 +80,14 @@ enum MusicStatus {
|
|||||||
COMPLETED
|
COMPLETED
|
||||||
WANT_TO_LISTEN
|
WANT_TO_LISTEN
|
||||||
}
|
}
|
||||||
|
|
||||||
|
model User {
|
||||||
|
id String @id @default(auto()) @map("_id") @db.ObjectId
|
||||||
|
discordId String @unique
|
||||||
|
username String
|
||||||
|
email String @unique
|
||||||
|
avatar String?
|
||||||
|
isAdmin Boolean @default(false)
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
updatedAt DateTime @updatedAt
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
# Database
|
||||||
|
DATABASE_URL=op://Personal/MongoDB Atlas - Library/connection string
|
||||||
|
|
||||||
|
# JWT Secret
|
||||||
|
JWT_SECRET=op://Personal/Library API Secrets/jwt_secret
|
||||||
|
|
||||||
|
# Discord OAuth
|
||||||
|
DISCORD_CLIENT_ID=op://Personal/Library Discord OAuth/client_id
|
||||||
|
DISCORD_CLIENT_SECRET=op://Personal/Library Discord OAuth/client_secret
|
||||||
|
|
||||||
|
# Admin Configuration
|
||||||
|
ADMIN_DISCORD_ID=op://Personal/Library API Secrets/admin_discord_id
|
||||||
|
|
||||||
|
# API Configuration
|
||||||
|
API_URL=op://Personal/Library API Secrets/api_url
|
||||||
|
FRONTEND_URL=op://Personal/Library API Secrets/frontend_url
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
/**
|
||||||
|
* @copyright 2026 NHCarrigan
|
||||||
|
* @license Naomi's Public License
|
||||||
|
* @author Naomi Carrigan
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { FastifyReply, FastifyRequest } from "fastify";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Middleware to check if the authenticated user is an admin.
|
||||||
|
* Must be used after app.authenticate.
|
||||||
|
*/
|
||||||
|
export async function adminGuard(
|
||||||
|
request: FastifyRequest,
|
||||||
|
reply: FastifyReply
|
||||||
|
): Promise<void> {
|
||||||
|
const user = request.user as any;
|
||||||
|
if (!user || !user.isAdmin) {
|
||||||
|
return reply.code(403).send({ error: "Forbidden: Admin access required" });
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
import { FastifyPluginAsync, FastifyRequest } from "fastify";
|
||||||
|
import fastifyPlugin from "fastify-plugin";
|
||||||
|
import fastifyJwt from "@fastify/jwt";
|
||||||
|
import fastifyCookie from "@fastify/cookie";
|
||||||
|
import fastifyOauth2 from "@fastify/oauth2";
|
||||||
|
|
||||||
|
declare module "fastify" {
|
||||||
|
interface FastifyInstance {
|
||||||
|
authenticate: (request: FastifyRequest) => Promise<void>;
|
||||||
|
oauth2Discord: any;
|
||||||
|
}
|
||||||
|
interface FastifyRequest {
|
||||||
|
user?: any;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const authPlugin: FastifyPluginAsync = async (app) => {
|
||||||
|
// Register JWT plugin
|
||||||
|
app.register(fastifyJwt, {
|
||||||
|
secret: process.env.JWT_SECRET || "your-secret-key",
|
||||||
|
cookie: {
|
||||||
|
cookieName: "auth-token",
|
||||||
|
signed: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Register cookie plugin
|
||||||
|
app.register(fastifyCookie);
|
||||||
|
|
||||||
|
// Register Discord OAuth2
|
||||||
|
app.register(fastifyOauth2, {
|
||||||
|
name: "oauth2Discord",
|
||||||
|
credentials: {
|
||||||
|
client: {
|
||||||
|
id: process.env.DISCORD_CLIENT_ID || "",
|
||||||
|
secret: process.env.DISCORD_CLIENT_SECRET || "",
|
||||||
|
},
|
||||||
|
auth: fastifyOauth2.DISCORD_CONFIGURATION,
|
||||||
|
},
|
||||||
|
startRedirectPath: "/api/auth/login",
|
||||||
|
callbackUri: `${process.env.API_URL || "http://localhost:3000"}/api/auth/callback`,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Authentication decorator
|
||||||
|
app.decorate("authenticate", async (request: FastifyRequest) => {
|
||||||
|
try {
|
||||||
|
await request.jwtVerify();
|
||||||
|
} catch (err) {
|
||||||
|
throw app.httpErrors.unauthorized("Invalid token");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export default fastifyPlugin(authPlugin);
|
||||||
@@ -1,3 +1,9 @@
|
|||||||
|
/**
|
||||||
|
* @copyright 2026 NHCarrigan
|
||||||
|
* @license Naomi's Public License
|
||||||
|
* @author Naomi Carrigan
|
||||||
|
*/
|
||||||
|
|
||||||
import { FastifyInstance } from 'fastify';
|
import { FastifyInstance } from 'fastify';
|
||||||
import fp from 'fastify-plugin';
|
import fp from 'fastify-plugin';
|
||||||
import sensible from '@fastify/sensible';
|
import sensible from '@fastify/sensible';
|
||||||
|
|||||||
@@ -0,0 +1,86 @@
|
|||||||
|
import { FastifyPluginAsync } from "fastify";
|
||||||
|
import { AuthService } from "../services/auth.service";
|
||||||
|
import { AuthResponse } from "@library/shared-types";
|
||||||
|
|
||||||
|
const authRoutes: FastifyPluginAsync = async (app) => {
|
||||||
|
const authService = new AuthService(app);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initiate Discord OAuth login.
|
||||||
|
*/
|
||||||
|
app.get("/login", async (request, reply) => {
|
||||||
|
const authUrl = app.oauth2Discord.generateAuthorizationUri({
|
||||||
|
scope: ["identify", "email"],
|
||||||
|
});
|
||||||
|
|
||||||
|
return reply.redirect(authUrl);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Discord OAuth callback.
|
||||||
|
*/
|
||||||
|
app.get("/callback", async (request, reply) => {
|
||||||
|
try {
|
||||||
|
const token = await app.oauth2Discord.getAccessTokenFromAuthorizationCodeFlow(
|
||||||
|
request
|
||||||
|
);
|
||||||
|
|
||||||
|
// Get user data from Discord
|
||||||
|
const userData = await app.oauth2Discord.userinfo(token.access_token);
|
||||||
|
|
||||||
|
// Create or update user in database
|
||||||
|
const user = await authService.createOrUpdateUserFromDiscord(userData);
|
||||||
|
|
||||||
|
// Generate JWT
|
||||||
|
const jwt = await authService.generateToken(user);
|
||||||
|
|
||||||
|
// Set cookie and redirect to frontend
|
||||||
|
reply
|
||||||
|
.setCookie("auth-token", jwt, {
|
||||||
|
path: "/",
|
||||||
|
httpOnly: true,
|
||||||
|
secure: process.env.NODE_ENV === "production",
|
||||||
|
sameSite: "lax",
|
||||||
|
maxAge: 7 * 24 * 60 * 60, // 7 days
|
||||||
|
})
|
||||||
|
.redirect(process.env.FRONTEND_URL || "http://localhost:4200");
|
||||||
|
} catch (error) {
|
||||||
|
app.log.error(error);
|
||||||
|
reply
|
||||||
|
.code(401)
|
||||||
|
.send({ error: "Authentication failed" });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get current user.
|
||||||
|
*/
|
||||||
|
app.get<{ Reply: AuthResponse | { error: string } }>(
|
||||||
|
"/me",
|
||||||
|
{
|
||||||
|
preValidation: [app.authenticate],
|
||||||
|
},
|
||||||
|
async (request) => {
|
||||||
|
const user = request.user as any;
|
||||||
|
const token = await authService.generateToken(user);
|
||||||
|
|
||||||
|
return {
|
||||||
|
user,
|
||||||
|
accessToken: token,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logout.
|
||||||
|
*/
|
||||||
|
app.post("/logout", async (request, reply) => {
|
||||||
|
reply
|
||||||
|
.clearCookie("auth-token", {
|
||||||
|
path: "/",
|
||||||
|
})
|
||||||
|
.send({ message: "Logged out successfully" });
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export default authRoutes;
|
||||||
@@ -0,0 +1,109 @@
|
|||||||
|
/**
|
||||||
|
* @copyright 2026 NHCarrigan
|
||||||
|
* @license Naomi's Public License
|
||||||
|
* @author Naomi Carrigan
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { FastifyPluginAsync } from "fastify";
|
||||||
|
import { PrismaClient } from "../../../generated/prisma";
|
||||||
|
import { Game, GameStatus } from "@library/shared-types";
|
||||||
|
import { adminGuard } from "../../middleware/admin-guard";
|
||||||
|
|
||||||
|
const gamesRoutes: FastifyPluginAsync = async (app) => {
|
||||||
|
const prisma = new PrismaClient();
|
||||||
|
|
||||||
|
// Get all games (public route)
|
||||||
|
app.get<{ Reply: Game[] }>("/", async () => {
|
||||||
|
const games = await prisma.game.findMany({
|
||||||
|
orderBy: { updatedAt: "desc" },
|
||||||
|
});
|
||||||
|
return games.map((game) => ({
|
||||||
|
...game,
|
||||||
|
status: game.status.toLowerCase() as GameStatus,
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
// Get single game (public route)
|
||||||
|
app.get<{ Params: { id: string }; Reply: Game | null }>(
|
||||||
|
"/:id",
|
||||||
|
async (request) => {
|
||||||
|
const { id } = request.params;
|
||||||
|
const game = await prisma.game.findUnique({
|
||||||
|
where: { id },
|
||||||
|
});
|
||||||
|
if (!game) return null;
|
||||||
|
return {
|
||||||
|
...game,
|
||||||
|
status: game.status.toLowerCase() as GameStatus,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// Create game (protected admin route)
|
||||||
|
app.post<{ Body: Omit<Game, "id" | "createdAt" | "updatedAt">; Reply: Game }>(
|
||||||
|
"/",
|
||||||
|
{
|
||||||
|
preValidation: [app.authenticate, adminGuard],
|
||||||
|
},
|
||||||
|
async (request, reply) => {
|
||||||
|
|
||||||
|
const game = await prisma.game.create({
|
||||||
|
data: {
|
||||||
|
...request.body,
|
||||||
|
status: request.body.status.toUpperCase() as any,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
...game,
|
||||||
|
status: game.status.toLowerCase() as GameStatus,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// Update game (protected admin route)
|
||||||
|
app.put<{
|
||||||
|
Params: { id: string };
|
||||||
|
Body: Partial<Omit<Game, "id" | "createdAt" | "updatedAt">>;
|
||||||
|
Reply: Game | null;
|
||||||
|
}>(
|
||||||
|
"/:id",
|
||||||
|
{
|
||||||
|
preValidation: [app.authenticate, adminGuard],
|
||||||
|
},
|
||||||
|
async (request, reply) => {
|
||||||
|
|
||||||
|
const { id } = request.params;
|
||||||
|
const updateData = { ...request.body };
|
||||||
|
if (updateData.status) {
|
||||||
|
updateData.status = updateData.status.toUpperCase() as any;
|
||||||
|
}
|
||||||
|
|
||||||
|
const game = await prisma.game.update({
|
||||||
|
where: { id },
|
||||||
|
data: updateData,
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
...game,
|
||||||
|
status: game.status.toLowerCase() as GameStatus,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// Delete game (protected admin route)
|
||||||
|
app.delete<{ Params: { id: string }; Reply: { success: boolean } }>(
|
||||||
|
"/:id",
|
||||||
|
{
|
||||||
|
preValidation: [app.authenticate, adminGuard],
|
||||||
|
},
|
||||||
|
async (request, reply) => {
|
||||||
|
|
||||||
|
const { id } = request.params;
|
||||||
|
await prisma.game.delete({
|
||||||
|
where: { id },
|
||||||
|
});
|
||||||
|
return { success: true };
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default gamesRoutes;
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
import { FastifyInstance } from "fastify";
|
||||||
|
import { JwtPayload, User } from "@library/shared-types";
|
||||||
|
import { PrismaClient } from "../../generated/prisma";
|
||||||
|
|
||||||
|
export class AuthService {
|
||||||
|
private prisma: PrismaClient;
|
||||||
|
|
||||||
|
constructor(private readonly app: FastifyInstance) {
|
||||||
|
this.prisma = new PrismaClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate JWT token for user.
|
||||||
|
*/
|
||||||
|
async generateToken(user: User): Promise<string> {
|
||||||
|
const payload: JwtPayload = {
|
||||||
|
sub: user.id,
|
||||||
|
email: user.email,
|
||||||
|
username: user.username,
|
||||||
|
isAdmin: user.isAdmin,
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.app.jwt.sign(payload, {
|
||||||
|
expiresIn: "7d",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify JWT token.
|
||||||
|
*/
|
||||||
|
async verifyToken(token: string): Promise<JwtPayload> {
|
||||||
|
return this.app.jwt.verify(token) as JwtPayload;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create or update user from Discord OAuth data.
|
||||||
|
*/
|
||||||
|
async createOrUpdateUserFromDiscord(discordData: DiscordUser): Promise<User> {
|
||||||
|
const avatarUrl = discordData.avatar
|
||||||
|
? `https://cdn.discordapp.com/avatars/${discordData.id}/${discordData.avatar}.png`
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
// Upsert user in database
|
||||||
|
const dbUser = await this.prisma.user.upsert({
|
||||||
|
where: {
|
||||||
|
discordId: discordData.id,
|
||||||
|
},
|
||||||
|
create: {
|
||||||
|
discordId: discordData.id,
|
||||||
|
username: discordData.username,
|
||||||
|
email: discordData.email,
|
||||||
|
avatar: avatarUrl,
|
||||||
|
isAdmin: discordData.id === process.env.ADMIN_DISCORD_ID,
|
||||||
|
},
|
||||||
|
update: {
|
||||||
|
username: discordData.username,
|
||||||
|
email: discordData.email,
|
||||||
|
avatar: avatarUrl,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: dbUser.id,
|
||||||
|
discordId: dbUser.discordId,
|
||||||
|
username: dbUser.username,
|
||||||
|
email: dbUser.email,
|
||||||
|
avatarUrl: dbUser.avatar || undefined,
|
||||||
|
isAdmin: dbUser.isAdmin,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface DiscordUser {
|
||||||
|
id: string;
|
||||||
|
username: string;
|
||||||
|
email: string;
|
||||||
|
avatar?: string;
|
||||||
|
}
|
||||||
+5
-1
@@ -16,7 +16,10 @@
|
|||||||
"@angular/platform-browser": "21.1.2",
|
"@angular/platform-browser": "21.1.2",
|
||||||
"@angular/router": "21.1.2",
|
"@angular/router": "21.1.2",
|
||||||
"@fastify/autoload": "6.0.3",
|
"@fastify/autoload": "6.0.3",
|
||||||
"@fastify/sensible": "6.0.4",
|
"@fastify/cookie": "^11.0.2",
|
||||||
|
"@fastify/jwt": "^10.0.0",
|
||||||
|
"@fastify/oauth2": "^8.1.2",
|
||||||
|
"@fastify/sensible": "5.6.0",
|
||||||
"@prisma/client": "7.3.0",
|
"@prisma/client": "7.3.0",
|
||||||
"fastify": "5.2.2",
|
"fastify": "5.2.2",
|
||||||
"fastify-plugin": "5.0.1",
|
"fastify-plugin": "5.0.1",
|
||||||
@@ -46,6 +49,7 @@
|
|||||||
"@swc/core": "1.5.29",
|
"@swc/core": "1.5.29",
|
||||||
"@swc/helpers": "0.5.18",
|
"@swc/helpers": "0.5.18",
|
||||||
"@types/jest": "30.0.0",
|
"@types/jest": "30.0.0",
|
||||||
|
"@types/jsonwebtoken": "^9.0.10",
|
||||||
"@types/node": "20.19.9",
|
"@types/node": "20.19.9",
|
||||||
"@typescript-eslint/utils": "8.54.0",
|
"@typescript-eslint/utils": "8.54.0",
|
||||||
"angular-eslint": "21.1.0",
|
"angular-eslint": "21.1.0",
|
||||||
|
|||||||
Generated
+232
-8
@@ -29,9 +29,18 @@ importers:
|
|||||||
'@fastify/autoload':
|
'@fastify/autoload':
|
||||||
specifier: 6.0.3
|
specifier: 6.0.3
|
||||||
version: 6.0.3
|
version: 6.0.3
|
||||||
|
'@fastify/cookie':
|
||||||
|
specifier: ^11.0.2
|
||||||
|
version: 11.0.2
|
||||||
|
'@fastify/jwt':
|
||||||
|
specifier: ^10.0.0
|
||||||
|
version: 10.0.0
|
||||||
|
'@fastify/oauth2':
|
||||||
|
specifier: ^8.1.2
|
||||||
|
version: 8.1.2
|
||||||
'@fastify/sensible':
|
'@fastify/sensible':
|
||||||
specifier: 6.0.4
|
specifier: 5.6.0
|
||||||
version: 6.0.4
|
version: 5.6.0
|
||||||
'@prisma/client':
|
'@prisma/client':
|
||||||
specifier: 7.3.0
|
specifier: 7.3.0
|
||||||
version: 7.3.0(prisma@7.3.0(@types/react@19.2.10)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(typescript@5.9.3)
|
version: 7.3.0(prisma@7.3.0(@types/react@19.2.10)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(typescript@5.9.3)
|
||||||
@@ -114,6 +123,9 @@ importers:
|
|||||||
'@types/jest':
|
'@types/jest':
|
||||||
specifier: 30.0.0
|
specifier: 30.0.0
|
||||||
version: 30.0.0
|
version: 30.0.0
|
||||||
|
'@types/jsonwebtoken':
|
||||||
|
specifier: ^9.0.10
|
||||||
|
version: 9.0.10
|
||||||
'@types/node':
|
'@types/node':
|
||||||
specifier: 20.19.9
|
specifier: 20.19.9
|
||||||
version: 20.19.9
|
version: 20.19.9
|
||||||
@@ -1537,6 +1549,9 @@ packages:
|
|||||||
'@fastify/autoload@6.0.3':
|
'@fastify/autoload@6.0.3':
|
||||||
resolution: {integrity: sha512-/wM2pmI7jP2fGah3YuP14i9vuaijpD4gQYLiyd+eD7gUxpA3B4R6/0QIXQS2eJaYD9aIX4ZFRzPmrZsaetfcWw==}
|
resolution: {integrity: sha512-/wM2pmI7jP2fGah3YuP14i9vuaijpD4gQYLiyd+eD7gUxpA3B4R6/0QIXQS2eJaYD9aIX4ZFRzPmrZsaetfcWw==}
|
||||||
|
|
||||||
|
'@fastify/cookie@11.0.2':
|
||||||
|
resolution: {integrity: sha512-GWdwdGlgJxyvNv+QcKiGNevSspMQXncjMZ1J8IvuDQk0jvkzgWWZFNC2En3s+nHndZBGV8IbLwOI/sxCZw/mzA==}
|
||||||
|
|
||||||
'@fastify/error@4.2.0':
|
'@fastify/error@4.2.0':
|
||||||
resolution: {integrity: sha512-RSo3sVDXfHskiBZKBPRgnQTtIqpi/7zhJOEmAxCiBcM7d0uwdGdxLlsCaLzGs8v8NnxIRlfG0N51p5yFaOentQ==}
|
resolution: {integrity: sha512-RSo3sVDXfHskiBZKBPRgnQTtIqpi/7zhJOEmAxCiBcM7d0uwdGdxLlsCaLzGs8v8NnxIRlfG0N51p5yFaOentQ==}
|
||||||
|
|
||||||
@@ -1546,14 +1561,38 @@ packages:
|
|||||||
'@fastify/forwarded@3.0.1':
|
'@fastify/forwarded@3.0.1':
|
||||||
resolution: {integrity: sha512-JqDochHFqXs3C3Ml3gOY58zM7OqO9ENqPo0UqAjAjH8L01fRZqwX9iLeX34//kiJubF7r2ZQHtBRU36vONbLlw==}
|
resolution: {integrity: sha512-JqDochHFqXs3C3Ml3gOY58zM7OqO9ENqPo0UqAjAjH8L01fRZqwX9iLeX34//kiJubF7r2ZQHtBRU36vONbLlw==}
|
||||||
|
|
||||||
|
'@fastify/jwt@10.0.0':
|
||||||
|
resolution: {integrity: sha512-2Qka3NiyNNcsfejMUvyzot1T4UYIzzcbkFGDdVyrl344fRZ/WkD6VFXOoXhxe2Pzf3LpJNkoSxUM4Ru4DVgkYA==}
|
||||||
|
|
||||||
'@fastify/merge-json-schemas@0.2.1':
|
'@fastify/merge-json-schemas@0.2.1':
|
||||||
resolution: {integrity: sha512-OA3KGBCy6KtIvLf8DINC5880o5iBlDX4SxzLQS8HorJAbqluzLRn80UXU0bxZn7UOFhFgpRJDasfwn9nG4FG4A==}
|
resolution: {integrity: sha512-OA3KGBCy6KtIvLf8DINC5880o5iBlDX4SxzLQS8HorJAbqluzLRn80UXU0bxZn7UOFhFgpRJDasfwn9nG4FG4A==}
|
||||||
|
|
||||||
|
'@fastify/oauth2@8.1.2':
|
||||||
|
resolution: {integrity: sha512-XZWFRWTZE2fkZ2pjuHNGtpFn1tOFgcJbU0205kHbfd16dn9xRc/6HmG0gHtN/g/BNkEL3EsQ54+pYEdh8dnBgA==}
|
||||||
|
|
||||||
'@fastify/proxy-addr@5.1.0':
|
'@fastify/proxy-addr@5.1.0':
|
||||||
resolution: {integrity: sha512-INS+6gh91cLUjB+PVHfu1UqcB76Sqtpyp7bnL+FYojhjygvOPA9ctiD/JDKsyD9Xgu4hUhCSJBPig/w7duNajw==}
|
resolution: {integrity: sha512-INS+6gh91cLUjB+PVHfu1UqcB76Sqtpyp7bnL+FYojhjygvOPA9ctiD/JDKsyD9Xgu4hUhCSJBPig/w7duNajw==}
|
||||||
|
|
||||||
'@fastify/sensible@6.0.4':
|
'@fastify/sensible@5.6.0':
|
||||||
resolution: {integrity: sha512-1vxcCUlPMew6WroK8fq+LVOwbsLtX+lmuRuqpcp6eYqu6vmkLwbKTdBWAZwbeaSgCfW4tzUpTIHLLvTiQQ1BwQ==}
|
resolution: {integrity: sha512-Vq6Z2ZQy10GDqON+hvLF52K99s9et5gVVxTul5n3SIAf0Kq5QjPRUKkAMT3zPAiiGvoHtS3APa/3uaxfDgCODQ==}
|
||||||
|
|
||||||
|
'@hapi/boom@10.0.1':
|
||||||
|
resolution: {integrity: sha512-ERcCZaEjdH3OgSJlyjVk8pHIFeus91CjKP3v+MpgBNp5IvGzP2l/bRiD78nqYcKPaZdbKkK5vDBVPd2ohHBlsA==}
|
||||||
|
|
||||||
|
'@hapi/bourne@3.0.0':
|
||||||
|
resolution: {integrity: sha512-Waj1cwPXJDucOib4a3bAISsKJVb15MKi9IvmTI/7ssVEm6sywXGjVJDhl6/umt1pK1ZS7PacXU3A1PmFKHEZ2w==}
|
||||||
|
|
||||||
|
'@hapi/hoek@11.0.7':
|
||||||
|
resolution: {integrity: sha512-HV5undWkKzcB4RZUusqOpcgxOaq6VOAH7zhhIr2g3G8NF/MlFO75SjOr2NfuSx0Mh40+1FqCkagKLJRykUWoFQ==}
|
||||||
|
|
||||||
|
'@hapi/hoek@9.3.0':
|
||||||
|
resolution: {integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==}
|
||||||
|
|
||||||
|
'@hapi/topo@5.1.0':
|
||||||
|
resolution: {integrity: sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==}
|
||||||
|
|
||||||
|
'@hapi/wreck@18.1.0':
|
||||||
|
resolution: {integrity: sha512-0z6ZRCmFEfV/MQqkQomJ7sl/hyxvcZM7LtuVqN3vdAO4vM9eBbowl0kaqQj9EJJQab+3Uuh1GxbGIBFy4NfJ4w==}
|
||||||
|
|
||||||
'@hono/node-server@1.19.9':
|
'@hono/node-server@1.19.9':
|
||||||
resolution: {integrity: sha512-vHL6w3ecZsky+8P5MD+eFfaGTyCeOHUIFYMGpQGbrBTSmNNoxv0if69rEZ5giu36weC5saFuznL411gRX7bJDw==}
|
resolution: {integrity: sha512-vHL6w3ecZsky+8P5MD+eFfaGTyCeOHUIFYMGpQGbrBTSmNNoxv0if69rEZ5giu36weC5saFuznL411gRX7bJDw==}
|
||||||
@@ -3050,6 +3089,15 @@ packages:
|
|||||||
resolution: {integrity: sha512-kxwxhCIUrj7DfzEtDSs/pi/w+aII/WQLpPfLgoQCWE8/95v60WnTfd1afmsXsFoxikKPxkwoPWtU2YbhSoX9MQ==}
|
resolution: {integrity: sha512-kxwxhCIUrj7DfzEtDSs/pi/w+aII/WQLpPfLgoQCWE8/95v60WnTfd1afmsXsFoxikKPxkwoPWtU2YbhSoX9MQ==}
|
||||||
engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'}
|
engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'}
|
||||||
|
|
||||||
|
'@sideway/address@4.1.5':
|
||||||
|
resolution: {integrity: sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==}
|
||||||
|
|
||||||
|
'@sideway/formula@3.0.1':
|
||||||
|
resolution: {integrity: sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==}
|
||||||
|
|
||||||
|
'@sideway/pinpoint@2.0.0':
|
||||||
|
resolution: {integrity: sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==}
|
||||||
|
|
||||||
'@sigstore/bundle@4.0.0':
|
'@sigstore/bundle@4.0.0':
|
||||||
resolution: {integrity: sha512-NwCl5Y0V6Di0NexvkTqdoVfmjTaQwoLM236r89KEojGmq/jMls8S+zb7yOwAPdXvbwfKDlP+lmXgAL4vKSQT+A==}
|
resolution: {integrity: sha512-NwCl5Y0V6Di0NexvkTqdoVfmjTaQwoLM236r89KEojGmq/jMls8S+zb7yOwAPdXvbwfKDlP+lmXgAL4vKSQT+A==}
|
||||||
engines: {node: ^20.17.0 || >=22.9.0}
|
engines: {node: ^20.17.0 || >=22.9.0}
|
||||||
@@ -3294,9 +3342,15 @@ packages:
|
|||||||
'@types/json5@0.0.29':
|
'@types/json5@0.0.29':
|
||||||
resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==}
|
resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==}
|
||||||
|
|
||||||
|
'@types/jsonwebtoken@9.0.10':
|
||||||
|
resolution: {integrity: sha512-asx5hIG9Qmf/1oStypjanR7iKTv0gXQ1Ov/jfrX6kS/EO0OFni8orbmGCn0672NHR3kXHwpAwR+B368ZGN/2rA==}
|
||||||
|
|
||||||
'@types/mime@1.3.5':
|
'@types/mime@1.3.5':
|
||||||
resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==}
|
resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==}
|
||||||
|
|
||||||
|
'@types/ms@2.1.0':
|
||||||
|
resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==}
|
||||||
|
|
||||||
'@types/node-forge@1.3.14':
|
'@types/node-forge@1.3.14':
|
||||||
resolution: {integrity: sha512-mhVF2BnD4BO+jtOp7z1CdzaK4mbuK0LLQYAvdOLqHTavxFNq4zA1EmYkpnFjP8HOUzedfQkRnp0E2ulSAYSzAw==}
|
resolution: {integrity: sha512-mhVF2BnD4BO+jtOp7z1CdzaK4mbuK0LLQYAvdOLqHTavxFNq4zA1EmYkpnFjP8HOUzedfQkRnp0E2ulSAYSzAw==}
|
||||||
|
|
||||||
@@ -3912,6 +3966,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==}
|
resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
|
asn1.js@5.4.1:
|
||||||
|
resolution: {integrity: sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==}
|
||||||
|
|
||||||
asn1@0.2.6:
|
asn1@0.2.6:
|
||||||
resolution: {integrity: sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==}
|
resolution: {integrity: sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==}
|
||||||
|
|
||||||
@@ -4104,6 +4161,9 @@ packages:
|
|||||||
bluebird@3.7.2:
|
bluebird@3.7.2:
|
||||||
resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==}
|
resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==}
|
||||||
|
|
||||||
|
bn.js@4.12.2:
|
||||||
|
resolution: {integrity: sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==}
|
||||||
|
|
||||||
body-parser@1.20.4:
|
body-parser@1.20.4:
|
||||||
resolution: {integrity: sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==}
|
resolution: {integrity: sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==}
|
||||||
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
|
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
|
||||||
@@ -4835,6 +4895,9 @@ packages:
|
|||||||
ecc-jsbn@0.1.2:
|
ecc-jsbn@0.1.2:
|
||||||
resolution: {integrity: sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==}
|
resolution: {integrity: sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==}
|
||||||
|
|
||||||
|
ecdsa-sig-formatter@1.0.11:
|
||||||
|
resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==}
|
||||||
|
|
||||||
ee-first@1.1.1:
|
ee-first@1.1.1:
|
||||||
resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
|
resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
|
||||||
|
|
||||||
@@ -5251,6 +5314,10 @@ packages:
|
|||||||
fast-json-stringify@6.2.0:
|
fast-json-stringify@6.2.0:
|
||||||
resolution: {integrity: sha512-Eaf/KNIDwHkzfyeQFNfLXJnQ7cl1XQI3+zRqmPlvtkMigbXnAcasTrvJQmquBSxKfFGeRA6PFog8t+hFmpDoWw==}
|
resolution: {integrity: sha512-Eaf/KNIDwHkzfyeQFNfLXJnQ7cl1XQI3+zRqmPlvtkMigbXnAcasTrvJQmquBSxKfFGeRA6PFog8t+hFmpDoWw==}
|
||||||
|
|
||||||
|
fast-jwt@6.1.0:
|
||||||
|
resolution: {integrity: sha512-cGK/TXlud8INL49Iv7yRtZy0PHzNJId1shfqNCqdF0gOlWiy+1FPgjxX+ZHp/CYxFYDaoNnxeYEGzcXSkahUEQ==}
|
||||||
|
engines: {node: '>=20'}
|
||||||
|
|
||||||
fast-levenshtein@2.0.6:
|
fast-levenshtein@2.0.6:
|
||||||
resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==}
|
resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==}
|
||||||
|
|
||||||
@@ -5260,15 +5327,28 @@ packages:
|
|||||||
fast-uri@3.1.0:
|
fast-uri@3.1.0:
|
||||||
resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==}
|
resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==}
|
||||||
|
|
||||||
|
fastfall@1.5.1:
|
||||||
|
resolution: {integrity: sha512-KH6p+Z8AKPXnmA7+Iz2Lh8ARCMr+8WNPVludm1LGkZoD2MjY6LVnRMtTKhkdzI+jr0RzQWXKzKyBJm1zoHEL4Q==}
|
||||||
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
|
fastify-plugin@4.5.1:
|
||||||
|
resolution: {integrity: sha512-stRHYGeuqpEZTL1Ef0Ovr2ltazUT9g844X5z/zEBFLG8RYlpDiOCIG+ATvYEp+/zmc7sN29mcIMp8gvYplYPIQ==}
|
||||||
|
|
||||||
fastify-plugin@5.0.1:
|
fastify-plugin@5.0.1:
|
||||||
resolution: {integrity: sha512-HCxs+YnRaWzCl+cWRYFnHmeRFyR5GVnJTAaCJQiYzQSDwK9MgJdyAsuL3nh0EWRCYMgQ5MeziymvmAhUHYHDUQ==}
|
resolution: {integrity: sha512-HCxs+YnRaWzCl+cWRYFnHmeRFyR5GVnJTAaCJQiYzQSDwK9MgJdyAsuL3nh0EWRCYMgQ5MeziymvmAhUHYHDUQ==}
|
||||||
|
|
||||||
fastify@5.2.2:
|
fastify@5.2.2:
|
||||||
resolution: {integrity: sha512-22T/PnhquWozuFXg3Ish4md5ipsF1Nx1mJ9ulLdZPXSk14WFj/wMlyNB/yll9sQOojKRgOIxT2inK3Xpjg5hyw==}
|
resolution: {integrity: sha512-22T/PnhquWozuFXg3Ish4md5ipsF1Nx1mJ9ulLdZPXSk14WFj/wMlyNB/yll9sQOojKRgOIxT2inK3Xpjg5hyw==}
|
||||||
|
|
||||||
|
fastparallel@2.4.1:
|
||||||
|
resolution: {integrity: sha512-qUmhxPgNHmvRjZKBFUNI0oZuuH9OlSIOXmJ98lhKPxMZZ7zS/Fi0wRHOihDSz0R1YiIOjxzOY4bq65YTcdBi2Q==}
|
||||||
|
|
||||||
fastq@1.20.1:
|
fastq@1.20.1:
|
||||||
resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==}
|
resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==}
|
||||||
|
|
||||||
|
fastseries@1.7.2:
|
||||||
|
resolution: {integrity: sha512-dTPFrPGS8SNSzAt7u/CbMKCJ3s01N04s4JFbORHcmyvVfVKmbhMD1VtRbh5enGHxkaQDqWyLefiKOGGmohGDDQ==}
|
||||||
|
|
||||||
faye-websocket@0.11.4:
|
faye-websocket@0.11.4:
|
||||||
resolution: {integrity: sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==}
|
resolution: {integrity: sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==}
|
||||||
engines: {node: '>=0.8.0'}
|
engines: {node: '>=0.8.0'}
|
||||||
@@ -6263,6 +6343,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==}
|
resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
joi@17.13.3:
|
||||||
|
resolution: {integrity: sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==}
|
||||||
|
|
||||||
jose@6.1.3:
|
jose@6.1.3:
|
||||||
resolution: {integrity: sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ==}
|
resolution: {integrity: sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ==}
|
||||||
|
|
||||||
@@ -6742,6 +6825,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==}
|
resolution: {integrity: sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==}
|
||||||
engines: {node: '>= 18'}
|
engines: {node: '>= 18'}
|
||||||
|
|
||||||
|
mnemonist@0.40.3:
|
||||||
|
resolution: {integrity: sha512-Vjyr90sJ23CKKH/qPAgUKicw/v6pRoamxIEDFOF8uSgFME7DqPRpHgRTejWVjkdGg5dXj0/NyxZHZ9bcjH+2uQ==}
|
||||||
|
|
||||||
mrmime@2.0.1:
|
mrmime@2.0.1:
|
||||||
resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==}
|
resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
@@ -6954,6 +7040,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==}
|
resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
|
obliterator@2.0.5:
|
||||||
|
resolution: {integrity: sha512-42CPE9AhahZRsMNslczq0ctAEtqk8Eka26QofnqC346BZdHDySk3LWka23LI7ULIw11NmltpiLagIq8gBozxTw==}
|
||||||
|
|
||||||
obuf@1.1.2:
|
obuf@1.1.2:
|
||||||
resolution: {integrity: sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==}
|
resolution: {integrity: sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==}
|
||||||
|
|
||||||
@@ -8109,6 +8198,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-/fUgUhYghuLzVT/gaJoeVehLCgZiUxPCPMcyVNY0lIf/cTCz58K/WTI7PefDarXxp9nUKpEwg1yyz3eSBMTtgA==}
|
resolution: {integrity: sha512-/fUgUhYghuLzVT/gaJoeVehLCgZiUxPCPMcyVNY0lIf/cTCz58K/WTI7PefDarXxp9nUKpEwg1yyz3eSBMTtgA==}
|
||||||
engines: {node: ^20.17.0 || >=22.9.0}
|
engines: {node: ^20.17.0 || >=22.9.0}
|
||||||
|
|
||||||
|
simple-oauth2@5.1.0:
|
||||||
|
resolution: {integrity: sha512-gWDa38Ccm4MwlG5U7AlcJxPv3lvr80dU7ARJWrGdgvOKyzSj1gr3GBPN1rABTedAYvC/LsGYoFuFxwDBPtGEbw==}
|
||||||
|
|
||||||
slash@3.0.0:
|
slash@3.0.0:
|
||||||
resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==}
|
resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
@@ -8247,6 +8339,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==}
|
resolution: {integrity: sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
|
steed@1.1.3:
|
||||||
|
resolution: {integrity: sha512-EUkci0FAUiE4IvGTSKcDJIQ/eRUP2JJb56+fvZ4sdnguLTqIdKjSxUe138poW8mkvKWXW2sFPrgTsxqoISnmoA==}
|
||||||
|
|
||||||
stop-iteration-iterator@1.1.0:
|
stop-iteration-iterator@1.1.0:
|
||||||
resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==}
|
resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
@@ -9088,6 +9183,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-g/eziiSUNBSsdDJtCLB8bdYEUMj4jR7AGeUo96p/3dTafgjHhpF4RiCFPiRILwjQoDXx5MqkBr4fwWtR3Ky4Wg==}
|
resolution: {integrity: sha512-g/eziiSUNBSsdDJtCLB8bdYEUMj4jR7AGeUo96p/3dTafgjHhpF4RiCFPiRILwjQoDXx5MqkBr4fwWtR3Ky4Wg==}
|
||||||
engines: {node: '>=20'}
|
engines: {node: '>=20'}
|
||||||
|
|
||||||
|
xtend@4.0.2:
|
||||||
|
resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==}
|
||||||
|
engines: {node: '>=0.4'}
|
||||||
|
|
||||||
y18n@5.0.8:
|
y18n@5.0.8:
|
||||||
resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
|
resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
@@ -11317,6 +11416,11 @@ snapshots:
|
|||||||
|
|
||||||
'@fastify/autoload@6.0.3': {}
|
'@fastify/autoload@6.0.3': {}
|
||||||
|
|
||||||
|
'@fastify/cookie@11.0.2':
|
||||||
|
dependencies:
|
||||||
|
cookie: 1.1.1
|
||||||
|
fastify-plugin: 5.0.1
|
||||||
|
|
||||||
'@fastify/error@4.2.0': {}
|
'@fastify/error@4.2.0': {}
|
||||||
|
|
||||||
'@fastify/fast-json-stringify-compiler@5.0.3':
|
'@fastify/fast-json-stringify-compiler@5.0.3':
|
||||||
@@ -11325,25 +11429,61 @@ snapshots:
|
|||||||
|
|
||||||
'@fastify/forwarded@3.0.1': {}
|
'@fastify/forwarded@3.0.1': {}
|
||||||
|
|
||||||
|
'@fastify/jwt@10.0.0':
|
||||||
|
dependencies:
|
||||||
|
'@fastify/error': 4.2.0
|
||||||
|
'@lukeed/ms': 2.0.2
|
||||||
|
fast-jwt: 6.1.0
|
||||||
|
fastify-plugin: 5.0.1
|
||||||
|
steed: 1.1.3
|
||||||
|
|
||||||
'@fastify/merge-json-schemas@0.2.1':
|
'@fastify/merge-json-schemas@0.2.1':
|
||||||
dependencies:
|
dependencies:
|
||||||
dequal: 2.0.3
|
dequal: 2.0.3
|
||||||
|
|
||||||
|
'@fastify/oauth2@8.1.2':
|
||||||
|
dependencies:
|
||||||
|
'@fastify/cookie': 11.0.2
|
||||||
|
fastify-plugin: 5.0.1
|
||||||
|
simple-oauth2: 5.1.0
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
|
||||||
'@fastify/proxy-addr@5.1.0':
|
'@fastify/proxy-addr@5.1.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@fastify/forwarded': 3.0.1
|
'@fastify/forwarded': 3.0.1
|
||||||
ipaddr.js: 2.3.0
|
ipaddr.js: 2.3.0
|
||||||
|
|
||||||
'@fastify/sensible@6.0.4':
|
'@fastify/sensible@5.6.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@lukeed/ms': 2.0.2
|
'@lukeed/ms': 2.0.2
|
||||||
dequal: 2.0.3
|
fast-deep-equal: 3.1.3
|
||||||
fastify-plugin: 5.0.1
|
fastify-plugin: 4.5.1
|
||||||
forwarded: 0.2.0
|
forwarded: 0.2.0
|
||||||
http-errors: 2.0.1
|
http-errors: 2.0.1
|
||||||
type-is: 2.0.1
|
type-is: 1.6.18
|
||||||
vary: 1.1.2
|
vary: 1.1.2
|
||||||
|
|
||||||
|
'@hapi/boom@10.0.1':
|
||||||
|
dependencies:
|
||||||
|
'@hapi/hoek': 11.0.7
|
||||||
|
|
||||||
|
'@hapi/bourne@3.0.0': {}
|
||||||
|
|
||||||
|
'@hapi/hoek@11.0.7': {}
|
||||||
|
|
||||||
|
'@hapi/hoek@9.3.0': {}
|
||||||
|
|
||||||
|
'@hapi/topo@5.1.0':
|
||||||
|
dependencies:
|
||||||
|
'@hapi/hoek': 9.3.0
|
||||||
|
|
||||||
|
'@hapi/wreck@18.1.0':
|
||||||
|
dependencies:
|
||||||
|
'@hapi/boom': 10.0.1
|
||||||
|
'@hapi/bourne': 3.0.0
|
||||||
|
'@hapi/hoek': 11.0.7
|
||||||
|
|
||||||
'@hono/node-server@1.19.9(hono@4.11.4)':
|
'@hono/node-server@1.19.9(hono@4.11.4)':
|
||||||
dependencies:
|
dependencies:
|
||||||
hono: 4.11.4
|
hono: 4.11.4
|
||||||
@@ -13437,6 +13577,14 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- chokidar
|
- chokidar
|
||||||
|
|
||||||
|
'@sideway/address@4.1.5':
|
||||||
|
dependencies:
|
||||||
|
'@hapi/hoek': 9.3.0
|
||||||
|
|
||||||
|
'@sideway/formula@3.0.1': {}
|
||||||
|
|
||||||
|
'@sideway/pinpoint@2.0.0': {}
|
||||||
|
|
||||||
'@sigstore/bundle@4.0.0':
|
'@sigstore/bundle@4.0.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@sigstore/protobuf-specs': 0.5.0
|
'@sigstore/protobuf-specs': 0.5.0
|
||||||
@@ -13705,8 +13853,15 @@ snapshots:
|
|||||||
|
|
||||||
'@types/json5@0.0.29': {}
|
'@types/json5@0.0.29': {}
|
||||||
|
|
||||||
|
'@types/jsonwebtoken@9.0.10':
|
||||||
|
dependencies:
|
||||||
|
'@types/ms': 2.1.0
|
||||||
|
'@types/node': 20.19.9
|
||||||
|
|
||||||
'@types/mime@1.3.5': {}
|
'@types/mime@1.3.5': {}
|
||||||
|
|
||||||
|
'@types/ms@2.1.0': {}
|
||||||
|
|
||||||
'@types/node-forge@1.3.14':
|
'@types/node-forge@1.3.14':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/node': 20.19.9
|
'@types/node': 20.19.9
|
||||||
@@ -14419,6 +14574,13 @@ snapshots:
|
|||||||
get-intrinsic: 1.3.0
|
get-intrinsic: 1.3.0
|
||||||
is-array-buffer: 3.0.5
|
is-array-buffer: 3.0.5
|
||||||
|
|
||||||
|
asn1.js@5.4.1:
|
||||||
|
dependencies:
|
||||||
|
bn.js: 4.12.2
|
||||||
|
inherits: 2.0.4
|
||||||
|
minimalistic-assert: 1.0.1
|
||||||
|
safer-buffer: 2.1.2
|
||||||
|
|
||||||
asn1@0.2.6:
|
asn1@0.2.6:
|
||||||
dependencies:
|
dependencies:
|
||||||
safer-buffer: 2.1.2
|
safer-buffer: 2.1.2
|
||||||
@@ -14672,6 +14834,8 @@ snapshots:
|
|||||||
|
|
||||||
bluebird@3.7.2: {}
|
bluebird@3.7.2: {}
|
||||||
|
|
||||||
|
bn.js@4.12.2: {}
|
||||||
|
|
||||||
body-parser@1.20.4:
|
body-parser@1.20.4:
|
||||||
dependencies:
|
dependencies:
|
||||||
bytes: 3.1.2
|
bytes: 3.1.2
|
||||||
@@ -15445,6 +15609,10 @@ snapshots:
|
|||||||
jsbn: 0.1.1
|
jsbn: 0.1.1
|
||||||
safer-buffer: 2.1.2
|
safer-buffer: 2.1.2
|
||||||
|
|
||||||
|
ecdsa-sig-formatter@1.0.11:
|
||||||
|
dependencies:
|
||||||
|
safe-buffer: 5.2.1
|
||||||
|
|
||||||
ee-first@1.1.1: {}
|
ee-first@1.1.1: {}
|
||||||
|
|
||||||
effect@3.18.4:
|
effect@3.18.4:
|
||||||
@@ -16105,6 +16273,13 @@ snapshots:
|
|||||||
json-schema-ref-resolver: 3.0.0
|
json-schema-ref-resolver: 3.0.0
|
||||||
rfdc: 1.4.1
|
rfdc: 1.4.1
|
||||||
|
|
||||||
|
fast-jwt@6.1.0:
|
||||||
|
dependencies:
|
||||||
|
'@lukeed/ms': 2.0.2
|
||||||
|
asn1.js: 5.4.1
|
||||||
|
ecdsa-sig-formatter: 1.0.11
|
||||||
|
mnemonist: 0.40.3
|
||||||
|
|
||||||
fast-levenshtein@2.0.6: {}
|
fast-levenshtein@2.0.6: {}
|
||||||
|
|
||||||
fast-querystring@1.1.2:
|
fast-querystring@1.1.2:
|
||||||
@@ -16113,6 +16288,12 @@ snapshots:
|
|||||||
|
|
||||||
fast-uri@3.1.0: {}
|
fast-uri@3.1.0: {}
|
||||||
|
|
||||||
|
fastfall@1.5.1:
|
||||||
|
dependencies:
|
||||||
|
reusify: 1.1.0
|
||||||
|
|
||||||
|
fastify-plugin@4.5.1: {}
|
||||||
|
|
||||||
fastify-plugin@5.0.1: {}
|
fastify-plugin@5.0.1: {}
|
||||||
|
|
||||||
fastify@5.2.2:
|
fastify@5.2.2:
|
||||||
@@ -16133,10 +16314,20 @@ snapshots:
|
|||||||
semver: 7.7.3
|
semver: 7.7.3
|
||||||
toad-cache: 3.7.0
|
toad-cache: 3.7.0
|
||||||
|
|
||||||
|
fastparallel@2.4.1:
|
||||||
|
dependencies:
|
||||||
|
reusify: 1.1.0
|
||||||
|
xtend: 4.0.2
|
||||||
|
|
||||||
fastq@1.20.1:
|
fastq@1.20.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
reusify: 1.1.0
|
reusify: 1.1.0
|
||||||
|
|
||||||
|
fastseries@1.7.2:
|
||||||
|
dependencies:
|
||||||
|
reusify: 1.1.0
|
||||||
|
xtend: 4.0.2
|
||||||
|
|
||||||
faye-websocket@0.11.4:
|
faye-websocket@0.11.4:
|
||||||
dependencies:
|
dependencies:
|
||||||
websocket-driver: 0.7.4
|
websocket-driver: 0.7.4
|
||||||
@@ -17349,6 +17540,14 @@ snapshots:
|
|||||||
|
|
||||||
jiti@2.6.1: {}
|
jiti@2.6.1: {}
|
||||||
|
|
||||||
|
joi@17.13.3:
|
||||||
|
dependencies:
|
||||||
|
'@hapi/hoek': 9.3.0
|
||||||
|
'@hapi/topo': 5.1.0
|
||||||
|
'@sideway/address': 4.1.5
|
||||||
|
'@sideway/formula': 3.0.1
|
||||||
|
'@sideway/pinpoint': 2.0.0
|
||||||
|
|
||||||
jose@6.1.3: {}
|
jose@6.1.3: {}
|
||||||
|
|
||||||
js-tokens@4.0.0: {}
|
js-tokens@4.0.0: {}
|
||||||
@@ -17860,6 +18059,10 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
minipass: 7.1.2
|
minipass: 7.1.2
|
||||||
|
|
||||||
|
mnemonist@0.40.3:
|
||||||
|
dependencies:
|
||||||
|
obliterator: 2.0.5
|
||||||
|
|
||||||
mrmime@2.0.1: {}
|
mrmime@2.0.1: {}
|
||||||
|
|
||||||
ms@2.0.0: {}
|
ms@2.0.0: {}
|
||||||
@@ -18142,6 +18345,8 @@ snapshots:
|
|||||||
define-properties: 1.2.1
|
define-properties: 1.2.1
|
||||||
es-object-atoms: 1.1.1
|
es-object-atoms: 1.1.1
|
||||||
|
|
||||||
|
obliterator@2.0.5: {}
|
||||||
|
|
||||||
obuf@1.1.2: {}
|
obuf@1.1.2: {}
|
||||||
|
|
||||||
obug@2.1.1: {}
|
obug@2.1.1: {}
|
||||||
@@ -19403,6 +19608,15 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
|
simple-oauth2@5.1.0:
|
||||||
|
dependencies:
|
||||||
|
'@hapi/hoek': 11.0.7
|
||||||
|
'@hapi/wreck': 18.1.0
|
||||||
|
debug: 4.4.3(supports-color@8.1.1)
|
||||||
|
joi: 17.13.3
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
|
||||||
slash@3.0.0: {}
|
slash@3.0.0: {}
|
||||||
|
|
||||||
slash@4.0.0: {}
|
slash@4.0.0: {}
|
||||||
@@ -19564,6 +19778,14 @@ snapshots:
|
|||||||
|
|
||||||
stdin-discarder@0.2.2: {}
|
stdin-discarder@0.2.2: {}
|
||||||
|
|
||||||
|
steed@1.1.3:
|
||||||
|
dependencies:
|
||||||
|
fastfall: 1.5.1
|
||||||
|
fastparallel: 2.4.1
|
||||||
|
fastq: 1.20.1
|
||||||
|
fastseries: 1.7.2
|
||||||
|
reusify: 1.1.0
|
||||||
|
|
||||||
stop-iteration-iterator@1.1.0:
|
stop-iteration-iterator@1.1.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
es-errors: 1.3.0
|
es-errors: 1.3.0
|
||||||
@@ -20579,6 +20801,8 @@ snapshots:
|
|||||||
is-wsl: 3.1.0
|
is-wsl: 3.1.0
|
||||||
powershell-utils: 0.1.0
|
powershell-utils: 0.1.0
|
||||||
|
|
||||||
|
xtend@4.0.2: {}
|
||||||
|
|
||||||
y18n@5.0.8: {}
|
y18n@5.0.8: {}
|
||||||
|
|
||||||
yallist@3.1.1: {}
|
yallist@3.1.1: {}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ export interface User {
|
|||||||
username: string;
|
username: string;
|
||||||
avatarUrl?: string;
|
avatarUrl?: string;
|
||||||
discordId: string;
|
discordId: string;
|
||||||
|
isAdmin: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface JwtPayload {
|
export interface JwtPayload {
|
||||||
@@ -19,6 +20,7 @@ export interface JwtPayload {
|
|||||||
sub: string;
|
sub: string;
|
||||||
email: string;
|
email: string;
|
||||||
username: string;
|
username: string;
|
||||||
|
isAdmin: boolean;
|
||||||
iat?: number;
|
iat?: number;
|
||||||
exp?: number;
|
exp?: number;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user