add jwt & crypto service
This commit is contained in:
@@ -27,6 +27,7 @@
|
|||||||
"@nestjs/core": "^11.0.1",
|
"@nestjs/core": "^11.0.1",
|
||||||
"@nestjs/passport": "^11.0.5",
|
"@nestjs/passport": "^11.0.5",
|
||||||
"@nestjs/platform-express": "^11.0.1",
|
"@nestjs/platform-express": "^11.0.1",
|
||||||
|
"@types/jsonwebtoken": "^9.0.10",
|
||||||
"@types/passport-local": "^1.0.38",
|
"@types/passport-local": "^1.0.38",
|
||||||
"argon2": "^0.44.0",
|
"argon2": "^0.44.0",
|
||||||
"dayjs": "^1.11.13",
|
"dayjs": "^1.11.13",
|
||||||
@@ -34,6 +35,7 @@
|
|||||||
"ejs": "^3.1.10",
|
"ejs": "^3.1.10",
|
||||||
"i18next": "^25.3.2",
|
"i18next": "^25.3.2",
|
||||||
"i18next-fs-backend": "^2.6.0",
|
"i18next-fs-backend": "^2.6.0",
|
||||||
|
"jsonwebtoken": "^9.0.2",
|
||||||
"kysely": "^0.28.3",
|
"kysely": "^0.28.3",
|
||||||
"nodemailer": "^7.0.5",
|
"nodemailer": "^7.0.5",
|
||||||
"passport": "^0.7.0",
|
"passport": "^0.7.0",
|
||||||
|
|||||||
@@ -1,20 +1,23 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { AuthRegistry } from './auth-registry';
|
import { AuthRegistry } from './auth-registry';
|
||||||
import { generateSecureToken } from '../../../lib/crypto';
|
|
||||||
import * as dayjs from 'dayjs';
|
import * as dayjs from 'dayjs';
|
||||||
import { isDefined, ResetAuth } from '@my-monorepo/common';
|
import { isDefined, ResetAuth } from '@my-monorepo/common';
|
||||||
|
import { CryptoService } from '../../../services/core/crypto/crypto.service';
|
||||||
|
|
||||||
const RESET_TOKEN_VALIDITY_MINUTES = 15;
|
const RESET_TOKEN_VALIDITY_MINUTES = 15;
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class AuthCoreService {
|
export class AuthCoreService {
|
||||||
constructor(private authRegistry: AuthRegistry) {}
|
constructor(
|
||||||
|
private authRegistry: AuthRegistry,
|
||||||
|
private cryptoService: CryptoService,
|
||||||
|
) {}
|
||||||
|
|
||||||
async addNewResetToken(
|
async addNewResetToken(
|
||||||
userId: string,
|
userId: string,
|
||||||
): Promise<{ token: string; user_id: string }> {
|
): Promise<{ token: string; user_id: string }> {
|
||||||
const res = await this.authRegistry.addResetToken({
|
const res = await this.authRegistry.addResetToken({
|
||||||
token: generateSecureToken(),
|
token: this.cryptoService.generateSecureToken(),
|
||||||
userId,
|
userId,
|
||||||
validUntil: dayjs().add(RESET_TOKEN_VALIDITY_MINUTES, 'minutes'),
|
validUntil: dayjs().add(RESET_TOKEN_VALIDITY_MINUTES, 'minutes'),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -6,13 +6,14 @@ import {
|
|||||||
import { UsersCoreService } from '../../users/users-core/users-core.service';
|
import { UsersCoreService } from '../../users/users-core/users-core.service';
|
||||||
import { AuthCoreService } from '../auth-core/auth-core.service';
|
import { AuthCoreService } from '../auth-core/auth-core.service';
|
||||||
import { ResetAuth } from '@my-monorepo/common';
|
import { ResetAuth } from '@my-monorepo/common';
|
||||||
import { hashPassword } from '../../../lib/crypto';
|
import { CryptoService } from '../../../services/core/crypto/crypto.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class AuthControllerService {
|
export class AuthControllerService {
|
||||||
constructor(
|
constructor(
|
||||||
private userCoreService: UsersCoreService,
|
private userCoreService: UsersCoreService,
|
||||||
private authCoreService: AuthCoreService,
|
private authCoreService: AuthCoreService,
|
||||||
|
private cryptoService: CryptoService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async verifyCredentials() {
|
async verifyCredentials() {
|
||||||
@@ -30,7 +31,7 @@ export class AuthControllerService {
|
|||||||
}
|
}
|
||||||
await this.userCoreService.setHashPassword(
|
await this.userCoreService.setHashPassword(
|
||||||
resetData.userId,
|
resetData.userId,
|
||||||
await hashPassword(resetData.newPassword),
|
await this.cryptoService.hashPassword(resetData.newPassword),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
import * as crypto from 'crypto';
|
|
||||||
import * as argon2 from 'argon2';
|
|
||||||
|
|
||||||
export function generateSecureToken(length = 32): string {
|
|
||||||
return crypto.randomBytes(length).toString('hex');
|
|
||||||
}
|
|
||||||
|
|
||||||
export function hashPassword(password: string): Promise<string> {
|
|
||||||
return argon2.hash(password);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function verifyPassword(
|
|
||||||
passwordHash: string,
|
|
||||||
clearTextPassword: string,
|
|
||||||
): Promise<boolean> {
|
|
||||||
return argon2.verify(passwordHash, clearTextPassword);
|
|
||||||
}
|
|
||||||
@@ -6,6 +6,7 @@ import { LoggerService } from './logger/logger.service';
|
|||||||
import { MailerService } from './mailer/mailer.service';
|
import { MailerService } from './mailer/mailer.service';
|
||||||
import { TemplateRendererService } from './template-renderer/template-renderer.service';
|
import { TemplateRendererService } from './template-renderer/template-renderer.service';
|
||||||
import { LinkBuilderService } from './link-builder/link-builder.service';
|
import { LinkBuilderService } from './link-builder/link-builder.service';
|
||||||
|
import { CryptoService } from './crypto/crypto.service';
|
||||||
|
|
||||||
const DECLARATIONS = [
|
const DECLARATIONS = [
|
||||||
DatabaseService,
|
DatabaseService,
|
||||||
@@ -15,6 +16,7 @@ const DECLARATIONS = [
|
|||||||
MailerService,
|
MailerService,
|
||||||
TemplateRendererService,
|
TemplateRendererService,
|
||||||
LinkBuilderService,
|
LinkBuilderService,
|
||||||
|
CryptoService,
|
||||||
];
|
];
|
||||||
|
|
||||||
@Global()
|
@Global()
|
||||||
|
|||||||
18
apps/backend/src/services/core/crypto/crypto.service.spec.ts
Normal file
18
apps/backend/src/services/core/crypto/crypto.service.spec.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
|
import { CryptoService } from './crypto.service';
|
||||||
|
|
||||||
|
describe('CryptoService', () => {
|
||||||
|
let service: CryptoService;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
const module: TestingModule = await Test.createTestingModule({
|
||||||
|
providers: [CryptoService],
|
||||||
|
}).compile();
|
||||||
|
|
||||||
|
service = module.get<CryptoService>(CryptoService);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be defined', () => {
|
||||||
|
expect(service).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
41
apps/backend/src/services/core/crypto/crypto.service.ts
Normal file
41
apps/backend/src/services/core/crypto/crypto.service.ts
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import * as crypto from 'crypto';
|
||||||
|
import * as argon2 from 'argon2';
|
||||||
|
import * as jwt from 'jsonwebtoken';
|
||||||
|
import { EnvService } from '../env/env.service';
|
||||||
|
import { isDefined } from '@my-monorepo/common';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class CryptoService {
|
||||||
|
constructor(private envService: EnvService) {}
|
||||||
|
|
||||||
|
generateSecureToken(length = 32): string {
|
||||||
|
return crypto.randomBytes(length).toString('hex');
|
||||||
|
}
|
||||||
|
|
||||||
|
hashPassword(password: string): Promise<string> {
|
||||||
|
return argon2.hash(password);
|
||||||
|
}
|
||||||
|
|
||||||
|
verifyPassword(
|
||||||
|
passwordHash: string,
|
||||||
|
clearTextPassword: string,
|
||||||
|
): Promise<boolean> {
|
||||||
|
return argon2.verify(passwordHash, clearTextPassword);
|
||||||
|
}
|
||||||
|
|
||||||
|
createJwt(payload: string | object): string {
|
||||||
|
return jwt.sign(payload, this.envService.config.secrets.authSign);
|
||||||
|
}
|
||||||
|
|
||||||
|
async verifyJwt(token: string): Promise<string | object | undefined> {
|
||||||
|
return await new Promise<string | object | undefined>((resolve) => {
|
||||||
|
jwt.verify(
|
||||||
|
token,
|
||||||
|
this.envService.config.secrets.authSign,
|
||||||
|
(err, decoded) =>
|
||||||
|
resolve(!isDefined(err) && isDefined(decoded) ? decoded : undefined),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,6 +14,7 @@ const envParser = z
|
|||||||
MAIL_USER: z.string().email(),
|
MAIL_USER: z.string().email(),
|
||||||
MAIL_PASSWORD: z.string(),
|
MAIL_PASSWORD: z.string(),
|
||||||
APP_FRONTEND_URL: z.string(),
|
APP_FRONTEND_URL: z.string(),
|
||||||
|
SECRET_AUTH_SIGN: z.string(),
|
||||||
})
|
})
|
||||||
.transform((parsed) => ({
|
.transform((parsed) => ({
|
||||||
database: {
|
database: {
|
||||||
@@ -32,6 +33,9 @@ const envParser = z
|
|||||||
app: {
|
app: {
|
||||||
frontendUrl: parsed.APP_FRONTEND_URL,
|
frontendUrl: parsed.APP_FRONTEND_URL,
|
||||||
},
|
},
|
||||||
|
secrets: {
|
||||||
|
authSign: parsed.SECRET_AUTH_SIGN,
|
||||||
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export type EnvConfig = Readonly<z.infer<typeof envParser>>;
|
export type EnvConfig = Readonly<z.infer<typeof envParser>>;
|
||||||
|
|||||||
109
pnpm-lock.yaml
generated
109
pnpm-lock.yaml
generated
@@ -25,6 +25,9 @@ importers:
|
|||||||
'@nestjs/platform-express':
|
'@nestjs/platform-express':
|
||||||
specifier: ^11.0.1
|
specifier: ^11.0.1
|
||||||
version: 11.1.3(@nestjs/common@11.1.3(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.3)
|
version: 11.1.3(@nestjs/common@11.1.3(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.3)
|
||||||
|
'@types/jsonwebtoken':
|
||||||
|
specifier: ^9.0.10
|
||||||
|
version: 9.0.10
|
||||||
'@types/passport-local':
|
'@types/passport-local':
|
||||||
specifier: ^1.0.38
|
specifier: ^1.0.38
|
||||||
version: 1.0.38
|
version: 1.0.38
|
||||||
@@ -46,6 +49,9 @@ importers:
|
|||||||
i18next-fs-backend:
|
i18next-fs-backend:
|
||||||
specifier: ^2.6.0
|
specifier: ^2.6.0
|
||||||
version: 2.6.0
|
version: 2.6.0
|
||||||
|
jsonwebtoken:
|
||||||
|
specifier: ^9.0.2
|
||||||
|
version: 9.0.2
|
||||||
kysely:
|
kysely:
|
||||||
specifier: ^0.28.3
|
specifier: ^0.28.3
|
||||||
version: 0.28.3
|
version: 0.28.3
|
||||||
@@ -1081,12 +1087,18 @@ packages:
|
|||||||
'@types/json-schema@7.0.15':
|
'@types/json-schema@7.0.15':
|
||||||
resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
|
resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
|
||||||
|
|
||||||
|
'@types/jsonwebtoken@9.0.10':
|
||||||
|
resolution: {integrity: sha512-asx5hIG9Qmf/1oStypjanR7iKTv0gXQ1Ov/jfrX6kS/EO0OFni8orbmGCn0672NHR3kXHwpAwR+B368ZGN/2rA==}
|
||||||
|
|
||||||
'@types/methods@1.1.4':
|
'@types/methods@1.1.4':
|
||||||
resolution: {integrity: sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ==}
|
resolution: {integrity: sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ==}
|
||||||
|
|
||||||
'@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@22.16.3':
|
'@types/node@22.16.3':
|
||||||
resolution: {integrity: sha512-sr4Xz74KOUeYadexo1r8imhRtlVXcs+j3XK3TcoiYk7B1t3YRVJgtaD3cwX73NYb71pmVuMLNRhJ9XKdoDB74g==}
|
resolution: {integrity: sha512-sr4Xz74KOUeYadexo1r8imhRtlVXcs+j3XK3TcoiYk7B1t3YRVJgtaD3cwX73NYb71pmVuMLNRhJ9XKdoDB74g==}
|
||||||
|
|
||||||
@@ -1480,6 +1492,9 @@ packages:
|
|||||||
buffer-crc32@0.2.13:
|
buffer-crc32@0.2.13:
|
||||||
resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==}
|
resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==}
|
||||||
|
|
||||||
|
buffer-equal-constant-time@1.0.1:
|
||||||
|
resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==}
|
||||||
|
|
||||||
buffer-from@1.1.2:
|
buffer-from@1.1.2:
|
||||||
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
|
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
|
||||||
|
|
||||||
@@ -1792,6 +1807,9 @@ packages:
|
|||||||
eastasianwidth@0.2.0:
|
eastasianwidth@0.2.0:
|
||||||
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
|
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
|
||||||
|
|
||||||
|
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==}
|
||||||
|
|
||||||
@@ -2556,6 +2574,16 @@ packages:
|
|||||||
jsonfile@6.1.0:
|
jsonfile@6.1.0:
|
||||||
resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==}
|
resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==}
|
||||||
|
|
||||||
|
jsonwebtoken@9.0.2:
|
||||||
|
resolution: {integrity: sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==}
|
||||||
|
engines: {node: '>=12', npm: '>=6'}
|
||||||
|
|
||||||
|
jwa@1.4.2:
|
||||||
|
resolution: {integrity: sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==}
|
||||||
|
|
||||||
|
jws@3.2.2:
|
||||||
|
resolution: {integrity: sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==}
|
||||||
|
|
||||||
keyv@4.5.4:
|
keyv@4.5.4:
|
||||||
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
|
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
|
||||||
|
|
||||||
@@ -2633,12 +2661,33 @@ packages:
|
|||||||
resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
|
resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
|
|
||||||
|
lodash.includes@4.3.0:
|
||||||
|
resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==}
|
||||||
|
|
||||||
|
lodash.isboolean@3.0.3:
|
||||||
|
resolution: {integrity: sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==}
|
||||||
|
|
||||||
|
lodash.isinteger@4.0.4:
|
||||||
|
resolution: {integrity: sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==}
|
||||||
|
|
||||||
|
lodash.isnumber@3.0.3:
|
||||||
|
resolution: {integrity: sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==}
|
||||||
|
|
||||||
|
lodash.isplainobject@4.0.6:
|
||||||
|
resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==}
|
||||||
|
|
||||||
|
lodash.isstring@4.0.1:
|
||||||
|
resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==}
|
||||||
|
|
||||||
lodash.memoize@4.1.2:
|
lodash.memoize@4.1.2:
|
||||||
resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==}
|
resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==}
|
||||||
|
|
||||||
lodash.merge@4.6.2:
|
lodash.merge@4.6.2:
|
||||||
resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
|
resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
|
||||||
|
|
||||||
|
lodash.once@4.1.1:
|
||||||
|
resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==}
|
||||||
|
|
||||||
lodash@4.17.21:
|
lodash@4.17.21:
|
||||||
resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
|
resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
|
||||||
|
|
||||||
@@ -3183,11 +3232,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
|
resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
semver@7.7.1:
|
|
||||||
resolution: {integrity: sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
hasBin: true
|
|
||||||
|
|
||||||
semver@7.7.2:
|
semver@7.7.2:
|
||||||
resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==}
|
resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
@@ -4870,10 +4914,17 @@ snapshots:
|
|||||||
|
|
||||||
'@types/json-schema@7.0.15': {}
|
'@types/json-schema@7.0.15': {}
|
||||||
|
|
||||||
|
'@types/jsonwebtoken@9.0.10':
|
||||||
|
dependencies:
|
||||||
|
'@types/ms': 2.1.0
|
||||||
|
'@types/node': 22.16.3
|
||||||
|
|
||||||
'@types/methods@1.1.4': {}
|
'@types/methods@1.1.4': {}
|
||||||
|
|
||||||
'@types/mime@1.3.5': {}
|
'@types/mime@1.3.5': {}
|
||||||
|
|
||||||
|
'@types/ms@2.1.0': {}
|
||||||
|
|
||||||
'@types/node@22.16.3':
|
'@types/node@22.16.3':
|
||||||
dependencies:
|
dependencies:
|
||||||
undici-types: 6.21.0
|
undici-types: 6.21.0
|
||||||
@@ -5446,6 +5497,8 @@ snapshots:
|
|||||||
|
|
||||||
buffer-crc32@0.2.13: {}
|
buffer-crc32@0.2.13: {}
|
||||||
|
|
||||||
|
buffer-equal-constant-time@1.0.1: {}
|
||||||
|
|
||||||
buffer-from@1.1.2: {}
|
buffer-from@1.1.2: {}
|
||||||
|
|
||||||
buffer@5.7.1:
|
buffer@5.7.1:
|
||||||
@@ -5713,6 +5766,10 @@ snapshots:
|
|||||||
|
|
||||||
eastasianwidth@0.2.0: {}
|
eastasianwidth@0.2.0: {}
|
||||||
|
|
||||||
|
ecdsa-sig-formatter@1.0.11:
|
||||||
|
dependencies:
|
||||||
|
safe-buffer: 5.2.1
|
||||||
|
|
||||||
ee-first@1.1.1: {}
|
ee-first@1.1.1: {}
|
||||||
|
|
||||||
ejs@3.1.10:
|
ejs@3.1.10:
|
||||||
@@ -6312,7 +6369,7 @@ snapshots:
|
|||||||
'@babel/parser': 7.28.0
|
'@babel/parser': 7.28.0
|
||||||
'@istanbuljs/schema': 0.1.3
|
'@istanbuljs/schema': 0.1.3
|
||||||
istanbul-lib-coverage: 3.2.2
|
istanbul-lib-coverage: 3.2.2
|
||||||
semver: 7.7.1
|
semver: 7.7.2
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
@@ -6699,6 +6756,30 @@ snapshots:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
graceful-fs: 4.2.11
|
graceful-fs: 4.2.11
|
||||||
|
|
||||||
|
jsonwebtoken@9.0.2:
|
||||||
|
dependencies:
|
||||||
|
jws: 3.2.2
|
||||||
|
lodash.includes: 4.3.0
|
||||||
|
lodash.isboolean: 3.0.3
|
||||||
|
lodash.isinteger: 4.0.4
|
||||||
|
lodash.isnumber: 3.0.3
|
||||||
|
lodash.isplainobject: 4.0.6
|
||||||
|
lodash.isstring: 4.0.1
|
||||||
|
lodash.once: 4.1.1
|
||||||
|
ms: 2.1.3
|
||||||
|
semver: 7.7.2
|
||||||
|
|
||||||
|
jwa@1.4.2:
|
||||||
|
dependencies:
|
||||||
|
buffer-equal-constant-time: 1.0.1
|
||||||
|
ecdsa-sig-formatter: 1.0.11
|
||||||
|
safe-buffer: 5.2.1
|
||||||
|
|
||||||
|
jws@3.2.2:
|
||||||
|
dependencies:
|
||||||
|
jwa: 1.4.2
|
||||||
|
safe-buffer: 5.2.1
|
||||||
|
|
||||||
keyv@4.5.4:
|
keyv@4.5.4:
|
||||||
dependencies:
|
dependencies:
|
||||||
json-buffer: 3.0.1
|
json-buffer: 3.0.1
|
||||||
@@ -6747,10 +6828,24 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
p-locate: 5.0.0
|
p-locate: 5.0.0
|
||||||
|
|
||||||
|
lodash.includes@4.3.0: {}
|
||||||
|
|
||||||
|
lodash.isboolean@3.0.3: {}
|
||||||
|
|
||||||
|
lodash.isinteger@4.0.4: {}
|
||||||
|
|
||||||
|
lodash.isnumber@3.0.3: {}
|
||||||
|
|
||||||
|
lodash.isplainobject@4.0.6: {}
|
||||||
|
|
||||||
|
lodash.isstring@4.0.1: {}
|
||||||
|
|
||||||
lodash.memoize@4.1.2: {}
|
lodash.memoize@4.1.2: {}
|
||||||
|
|
||||||
lodash.merge@4.6.2: {}
|
lodash.merge@4.6.2: {}
|
||||||
|
|
||||||
|
lodash.once@4.1.1: {}
|
||||||
|
|
||||||
lodash@4.17.21: {}
|
lodash@4.17.21: {}
|
||||||
|
|
||||||
log-symbols@4.1.0:
|
log-symbols@4.1.0:
|
||||||
@@ -7216,8 +7311,6 @@ snapshots:
|
|||||||
|
|
||||||
semver@6.3.1: {}
|
semver@6.3.1: {}
|
||||||
|
|
||||||
semver@7.7.1: {}
|
|
||||||
|
|
||||||
semver@7.7.2: {}
|
semver@7.7.2: {}
|
||||||
|
|
||||||
send@1.2.0:
|
send@1.2.0:
|
||||||
|
|||||||
Reference in New Issue
Block a user