chore(repo) init AppAuth module
This commit is contained in:
parent
580de7d81b
commit
60b1701d01
22
apps/ebitemp-api/.tomg-config
Normal file
22
apps/ebitemp-api/.tomg-config
Normal file
@ -0,0 +1,22 @@
|
||||
[
|
||||
{
|
||||
"pluralizeNames": true,
|
||||
"noConfigs": true,
|
||||
"convertCaseFile": "none",
|
||||
"convertCaseEntity": "pascal",
|
||||
"convertCaseProperty": "camel",
|
||||
"convertEol": "LF",
|
||||
"propertyVisibility": "none",
|
||||
"lazy": false,
|
||||
"activeRecord": false,
|
||||
"generateConstructor": true,
|
||||
"customNamingStrategyPath": ".tomg-naming-strategy.js",
|
||||
"relationIds": false,
|
||||
"strictMode": "none",
|
||||
"skipSchema": true,
|
||||
"indexFile": false,
|
||||
"exportType": "named",
|
||||
"skipNonPrimaryKeyIndexes": true,
|
||||
"removeColumnsInRelation": false
|
||||
}
|
||||
]
|
39
apps/ebitemp-api/.tomg-naming-strategy.js
Normal file
39
apps/ebitemp-api/.tomg-naming-strategy.js
Normal file
@ -0,0 +1,39 @@
|
||||
/**
|
||||
* @typedef {import('typeorm-model-generator').Column} Column
|
||||
* @typedef {import('typeorm-model-generator').Entity} Entity
|
||||
*/
|
||||
|
||||
/**
|
||||
* Customizes the entity name.
|
||||
* @param {string} oldEntityName - The default entity name.
|
||||
* @param {Entity} entity - The entity.
|
||||
* @returns {string} The new entity name.
|
||||
*/
|
||||
function entityName(oldEntityName, entity) {
|
||||
return oldEntityName + 'Entity';
|
||||
}
|
||||
|
||||
/**
|
||||
* Customizes the column name.
|
||||
* @param {string} oldColumnName - The default column name.
|
||||
* @param {Column} column - The column.
|
||||
* @returns {string} The new column name.
|
||||
*/
|
||||
function columnName(oldColumnName, column) {
|
||||
return oldColumnName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Customizes the file name.
|
||||
* @param {string} oldFileName - The default file name.
|
||||
* @returns {string} The new file name.
|
||||
*/
|
||||
function fileName(oldFileName) {
|
||||
return oldFileName.replace('Entity', '.entity');
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
entityName,
|
||||
columnName,
|
||||
fileName,
|
||||
};
|
@ -1,6 +1,8 @@
|
||||
import { Controller, Get } from '@nestjs/common';
|
||||
import { AppService } from './app.service';
|
||||
import { Public } from './modules/auth/strategies/jwt/jwt-auth.guard';
|
||||
|
||||
@Public()
|
||||
@Controller()
|
||||
export class AppController {
|
||||
constructor(private readonly appService: AppService) {}
|
||||
|
@ -2,6 +2,7 @@ import { Module } from '@nestjs/common';
|
||||
import { AppController } from './app.controller';
|
||||
import { AppService } from './app.service';
|
||||
|
||||
import { AppAuthModule } from './modules/auth/auth.module';
|
||||
import { AppConfigModule } from './modules/config/config.module';
|
||||
import { AppDatabaseModule } from './modules/database/database.module';
|
||||
import { EnumifyModule } from './modules/enumify/enumify.module';
|
||||
@ -20,6 +21,7 @@ import { AppValidationModule } from './modules/validation/validation.module';
|
||||
AppFileTransactionsModule,
|
||||
AppScheduleModule,
|
||||
AppValidationModule,
|
||||
AppAuthModule,
|
||||
EnumifyModule,
|
||||
],
|
||||
controllers: [AppController],
|
||||
|
31
apps/ebitemp-api/src/app/modules/auth/auth.config.ts
Normal file
31
apps/ebitemp-api/src/app/modules/auth/auth.config.ts
Normal file
@ -0,0 +1,31 @@
|
||||
import { registerAs } from '@nestjs/config';
|
||||
import { z } from 'zod';
|
||||
import coerceRecordTypes from '../config/utils/coerce-record-types';
|
||||
|
||||
export const authSchema = z.object({
|
||||
accessToken: z.object({
|
||||
secret: z.string(),
|
||||
expTimeInSecs: z.number().finite().nonnegative(),
|
||||
}),
|
||||
refreshToken: z.object({
|
||||
secret: z.string(),
|
||||
expTimeInSecs: z.number().finite().nonnegative(),
|
||||
}),
|
||||
});
|
||||
export type AuthConfig = z.infer<typeof authSchema>;
|
||||
|
||||
export const authConfig = registerAs('auth', () => {
|
||||
const env = coerceRecordTypes(process.env);
|
||||
|
||||
const config: AuthConfig = authSchema.strict().parse({
|
||||
accessToken: {
|
||||
secret: env['JWT_ACCESS_TOKEN_SECRET'],
|
||||
expTimeInSecs: env['JWT_ACCESS_TOKEN_EXPIRATION_TIME_IN_SECONDS'],
|
||||
},
|
||||
refreshToken: {
|
||||
secret: env['JWT_REFRESH_TOKEN_SECRET'],
|
||||
expTimeInSecs: env['JWT_REFRESH_TOKEN_EXPIRATION_TIME_IN_SECONDS'],
|
||||
}
|
||||
});
|
||||
return config;
|
||||
});
|
36
apps/ebitemp-api/src/app/modules/auth/auth.controller.ts
Normal file
36
apps/ebitemp-api/src/app/modules/auth/auth.controller.ts
Normal file
@ -0,0 +1,36 @@
|
||||
import { Body, Controller, HttpCode, HttpStatus, Post, UseGuards } from '@nestjs/common';
|
||||
import { ApiBearerAuth } from '@nestjs/swagger';
|
||||
import { AccountsEntity } from '../database/entities';
|
||||
import { LoginDto, LoginResDto } from './auth.dto';
|
||||
import { AuthService } from './auth.service';
|
||||
import { AuthenticatedUser } from './authenticated-user.decorator';
|
||||
import { Public } from './strategies/jwt/jwt-auth.guard';
|
||||
import { LocalAuthGuard } from './strategies/local/local-auth.guard';
|
||||
|
||||
@ApiBearerAuth()
|
||||
@Controller('auth')
|
||||
export class AuthController {
|
||||
constructor(private readonly authService: AuthService) {}
|
||||
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@UseGuards(LocalAuthGuard)
|
||||
@Public()
|
||||
@Post('login')
|
||||
async logIn(@AuthenticatedUser() user: AccountsEntity, @Body() body: LoginDto): Promise<LoginResDto> {
|
||||
const { accessToken, refreshToken } = await this.authService.signJwts(user);
|
||||
return {
|
||||
accessToken: accessToken,
|
||||
refreshToken: refreshToken,
|
||||
};
|
||||
}
|
||||
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@Post('refresh')
|
||||
async refresh(@AuthenticatedUser() user: AccountsEntity): Promise<LoginResDto> {
|
||||
const { accessToken, refreshToken } = await this.authService.signJwts(user);
|
||||
return {
|
||||
accessToken: accessToken,
|
||||
refreshToken: refreshToken,
|
||||
};
|
||||
}
|
||||
}
|
16
apps/ebitemp-api/src/app/modules/auth/auth.dto.ts
Normal file
16
apps/ebitemp-api/src/app/modules/auth/auth.dto.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import { createZodDto } from '@anatine/zod-nestjs';
|
||||
import { z } from 'zod';
|
||||
|
||||
export const loginSchema = z.object({
|
||||
username: z.string(),
|
||||
password: z.string().nonempty(),
|
||||
});
|
||||
export type Login = z.infer<typeof loginSchema>;
|
||||
export class LoginDto extends createZodDto(loginSchema) {}
|
||||
|
||||
export const loginResSchema = z.object({
|
||||
accessToken: z.string().jwt(),
|
||||
refreshToken: z.string().jwt(),
|
||||
})
|
||||
export type LoginRes = z.infer<typeof loginResSchema>;
|
||||
export class LoginResDto extends createZodDto(loginResSchema) {}
|
37
apps/ebitemp-api/src/app/modules/auth/auth.module.ts
Normal file
37
apps/ebitemp-api/src/app/modules/auth/auth.module.ts
Normal file
@ -0,0 +1,37 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { APP_GUARD, Reflector } from '@nestjs/core';
|
||||
import { PassportModule } from '@nestjs/passport';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { AccountsEntity } from '../database/entities';
|
||||
import { AuthController } from './auth.controller';
|
||||
import { AuthService } from './auth.service';
|
||||
import { JwtAccessTokenAuthStrategy } from './strategies/jwt/jwt-access-token-auth.strategy';
|
||||
import { JwtAccessTokenModule } from './strategies/jwt/jwt-access-token.module';
|
||||
import { JwtAuthGuard } from './strategies/jwt/jwt-auth.guard';
|
||||
import { JwtRefreshTokenAuthStrategy } from './strategies/jwt/jwt-refresh-token-auth.strategy';
|
||||
import { JwtRefreshTokenModule } from './strategies/jwt/jwt-refresh-token.module';
|
||||
import { LocalAuthStrategy } from './strategies/local/local-auth.strategy';
|
||||
import { UsersAuthModule } from './users/users.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([AccountsEntity]),
|
||||
JwtAccessTokenModule,
|
||||
JwtRefreshTokenModule,
|
||||
PassportModule,
|
||||
UsersAuthModule,
|
||||
],
|
||||
controllers: [AuthController],
|
||||
providers: [
|
||||
{
|
||||
provide: APP_GUARD,
|
||||
useFactory: (reflector) => new JwtAuthGuard(reflector),
|
||||
inject: [Reflector],
|
||||
},
|
||||
AuthService,
|
||||
LocalAuthStrategy,
|
||||
JwtAccessTokenAuthStrategy,
|
||||
JwtRefreshTokenAuthStrategy,
|
||||
],
|
||||
})
|
||||
export class AppAuthModule {}
|
50
apps/ebitemp-api/src/app/modules/auth/auth.service.ts
Normal file
50
apps/ebitemp-api/src/app/modules/auth/auth.service.ts
Normal file
@ -0,0 +1,50 @@
|
||||
import { Inject, Injectable, Logger, UnauthorizedException } from '@nestjs/common';
|
||||
import { JwtService } from '@nestjs/jwt';
|
||||
import * as bcrypt from 'bcrypt';
|
||||
import { isEmpty } from 'lodash';
|
||||
import { AccountsEntity } from '../database/entities';
|
||||
import { ACCESS_TOKEN_JWT_SERVICE } from './strategies/jwt/jwt-access-token.module';
|
||||
import { REFRESH_TOKEN_JWT_SERVICE } from './strategies/jwt/jwt-refresh-token.module';
|
||||
import { UsersAuthService } from './users/users-auth.service';
|
||||
|
||||
@Injectable()
|
||||
export class AuthService {
|
||||
private readonly logger = new Logger(AuthService.name);
|
||||
|
||||
constructor(
|
||||
private readonly usersAuthService: UsersAuthService,
|
||||
@Inject(ACCESS_TOKEN_JWT_SERVICE) private readonly accessTokenJwtService: JwtService,
|
||||
@Inject(REFRESH_TOKEN_JWT_SERVICE) private readonly refreshTokenJwtService: JwtService
|
||||
) {}
|
||||
|
||||
public async signJwts(user: AccountsEntity) {
|
||||
const payload = { username: user.username, sub: user.id };
|
||||
|
||||
const accessToken = await this.accessTokenJwtService.signAsync(payload);
|
||||
|
||||
const refreshToken = await this.refreshTokenJwtService.signAsync(payload);
|
||||
await this.usersAuthService.setCurrentRefreshTokenHash(user.id, refreshToken);
|
||||
|
||||
return { accessToken, refreshToken };
|
||||
}
|
||||
|
||||
public async getAuthenticatedUser(username: string, password: string): Promise<AccountsEntity> {
|
||||
try {
|
||||
const account = await this.usersAuthService.getUserByUsername(username);
|
||||
if (!account) throw new UnauthorizedException(`Username not found`);
|
||||
await this.verifyPassword(password, account.password);
|
||||
return account;
|
||||
} catch (error) {
|
||||
this.logger.error(error);
|
||||
throw new UnauthorizedException(`Unknown error`);
|
||||
}
|
||||
}
|
||||
|
||||
private async verifyPassword(plainTextPassword: string, hashedPassword: string | null) {
|
||||
const isPasswordMatching =
|
||||
hashedPassword && !isEmpty(hashedPassword) ? await bcrypt.compare(plainTextPassword, hashedPassword) : null;
|
||||
if (!isPasswordMatching) {
|
||||
throw new UnauthorizedException(`Wrong credentials`);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
import { createParamDecorator, ExecutionContext } from '@nestjs/common';
|
||||
import { RequestWithUser } from './constants/request-with-user';
|
||||
|
||||
export const AuthenticatedUser = createParamDecorator((data: unknown, ctx: ExecutionContext) => {
|
||||
const request = ctx.switchToHttp().getRequest<RequestWithUser>();
|
||||
|
||||
return request.user;
|
||||
});
|
@ -0,0 +1,6 @@
|
||||
import { FastifyRequest } from "fastify";
|
||||
import { AccountsEntity } from "../../database/entities";
|
||||
|
||||
export interface RequestWithUser extends FastifyRequest {
|
||||
user: AccountsEntity;
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
export interface TokenPayload {
|
||||
userId: number;
|
||||
iat?: number;
|
||||
exp?: number;
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
import { Inject, Injectable, UnauthorizedException } from '@nestjs/common';
|
||||
import { PassportStrategy } from '@nestjs/passport';
|
||||
import { ExtractJwt, Strategy } from 'passport-jwt';
|
||||
import { AuthConfig, authConfig } from '../../auth.config';
|
||||
import { RequestWithUser } from '../../constants/request-with-user';
|
||||
import { TokenPayload } from '../../constants/token-payload.interface';
|
||||
import { UsersAuthService } from '../../users/users-auth.service';
|
||||
|
||||
@Injectable()
|
||||
export class JwtAccessTokenAuthStrategy extends PassportStrategy(Strategy, 'jwt-access-token') {
|
||||
constructor(@Inject(authConfig.KEY) authConfig: AuthConfig, private readonly userAuthService: UsersAuthService) {
|
||||
super({
|
||||
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
|
||||
secretOrKey: authConfig.accessToken.secret,
|
||||
passReqToCallback: true,
|
||||
});
|
||||
}
|
||||
|
||||
async validate(request: RequestWithUser, payload: TokenPayload) {
|
||||
const account = await this.userAuthService.getUserById(payload.userId);
|
||||
if (!account) throw new UnauthorizedException('Access Token Guard');
|
||||
return account;
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { JwtService, JwtModule as NestJwtModule } from '@nestjs/jwt';
|
||||
import { authConfig, AuthConfig } from '../../auth.config';
|
||||
import { ConfigModule } from '@nestjs/config';
|
||||
|
||||
export const ACCESS_TOKEN_JWT_SERVICE = Symbol('ACCESS_TOKEN_JWT_SERVICE');
|
||||
const accessTokenJwtProvider = {
|
||||
provide: ACCESS_TOKEN_JWT_SERVICE,
|
||||
useFactory: (jwtService: JwtService) => jwtService,
|
||||
inject: [JwtService],
|
||||
};
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
ConfigModule.forFeature(authConfig),
|
||||
NestJwtModule.registerAsync({
|
||||
imports: [...authConfig.asProvider().imports],
|
||||
useFactory: async (authConfig: AuthConfig) => ({
|
||||
secret: authConfig.accessToken.secret,
|
||||
signOptions: {
|
||||
expiresIn: `${authConfig.accessToken.expTimeInSecs}s`,
|
||||
},
|
||||
}),
|
||||
inject: [authConfig.KEY],
|
||||
}),
|
||||
],
|
||||
providers: [accessTokenJwtProvider],
|
||||
exports: [ConfigModule, accessTokenJwtProvider],
|
||||
})
|
||||
export class JwtAccessTokenModule {}
|
@ -0,0 +1,36 @@
|
||||
import { applyDecorators, ExecutionContext, SetMetadata } from '@nestjs/common';
|
||||
import { Reflector } from '@nestjs/core';
|
||||
import { AuthGuard } from '@nestjs/passport';
|
||||
import { OpenAPIObject } from '@nestjs/swagger';
|
||||
|
||||
export const IS_PUBLIC_KEY = 'isPublic';
|
||||
export const Public = () =>
|
||||
applyDecorators(SetMetadata(IS_PUBLIC_KEY, true), SetMetadata('swagger/apiSecurity', ['public']));
|
||||
|
||||
export const patchPublicDecoratorSupport = (document: OpenAPIObject) => {
|
||||
Object.values(document.paths).forEach((path: any) => {
|
||||
Object.values(path).forEach((method: any) => {
|
||||
if (Array.isArray(method.security) && method.security.includes('public')) {
|
||||
method.security = [];
|
||||
}
|
||||
});
|
||||
});
|
||||
return document;
|
||||
};
|
||||
|
||||
export class JwtAuthGuard extends AuthGuard(['jwt-access-token', 'jwt-refresh-token']) {
|
||||
constructor(private reflector: Reflector) {
|
||||
super();
|
||||
}
|
||||
|
||||
canActivate(context: ExecutionContext) {
|
||||
const isPublic = this.reflector.getAllAndOverride<boolean>(IS_PUBLIC_KEY, [
|
||||
context.getHandler(),
|
||||
context.getClass(),
|
||||
]);
|
||||
if (isPublic) {
|
||||
return true;
|
||||
}
|
||||
return super.canActivate(context);
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
import { Inject, Injectable, UnauthorizedException } from '@nestjs/common';
|
||||
import { PassportStrategy } from '@nestjs/passport';
|
||||
import { FastifyRequest } from 'fastify';
|
||||
import { ExtractJwt, Strategy } from 'passport-jwt';
|
||||
import { authConfig, AuthConfig } from '../../auth.config';
|
||||
import { RequestWithUser } from '../../constants/request-with-user';
|
||||
import { TokenPayload } from '../../constants/token-payload.interface';
|
||||
import { UsersAuthService } from '../../users/users-auth.service';
|
||||
|
||||
@Injectable()
|
||||
export class JwtRefreshTokenAuthStrategy extends PassportStrategy(Strategy, 'jwt-refresh-token') {
|
||||
constructor(@Inject(authConfig.KEY) authConfig: AuthConfig, private readonly usersAuthService: UsersAuthService) {
|
||||
super({
|
||||
jwtFromRequest: ExtractJwt.fromExtractors([
|
||||
(request: FastifyRequest) => {
|
||||
return request?.headers?.Bearer as string;
|
||||
},
|
||||
]),
|
||||
secretOrKey: authConfig.refreshToken.secret,
|
||||
passReqToCallback: true,
|
||||
});
|
||||
}
|
||||
|
||||
async validate(request: RequestWithUser, payload: TokenPayload) {
|
||||
const refreshToken = request.headers?.Refresh as string;
|
||||
const account = this.usersAuthService.getUserByIdAndRefreshTokenPair(payload.userId, refreshToken);
|
||||
if (!account) throw new UnauthorizedException('Refresh Token Guard');
|
||||
return account;
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { ConfigModule } from '@nestjs/config';
|
||||
import { JwtService, JwtModule as NestJwtModule } from '@nestjs/jwt';
|
||||
import { authConfig, AuthConfig } from '../../auth.config';
|
||||
|
||||
export const REFRESH_TOKEN_JWT_SERVICE = Symbol('REFRESH_TOKEN_JWT_SERVICE');
|
||||
const refreshTokenJwtProvider = {
|
||||
provide: REFRESH_TOKEN_JWT_SERVICE,
|
||||
useFactory: (jwtService: JwtService) => jwtService,
|
||||
inject: [JwtService],
|
||||
};
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
ConfigModule.forFeature(authConfig),
|
||||
NestJwtModule.registerAsync({
|
||||
imports: [...authConfig.asProvider().imports],
|
||||
useFactory: async (authConfig: AuthConfig) => ({
|
||||
secret: authConfig.refreshToken.secret,
|
||||
signOptions: {
|
||||
expiresIn: `${authConfig.refreshToken.expTimeInSecs}s`,
|
||||
},
|
||||
}),
|
||||
inject: [authConfig.KEY],
|
||||
}),
|
||||
],
|
||||
providers: [refreshTokenJwtProvider],
|
||||
exports: [ConfigModule, refreshTokenJwtProvider],
|
||||
})
|
||||
export class JwtRefreshTokenModule {}
|
@ -0,0 +1,5 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { AuthGuard } from '@nestjs/passport';
|
||||
|
||||
@Injectable()
|
||||
export class LocalAuthGuard extends AuthGuard('local') {}
|
@ -0,0 +1,22 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { PassportStrategy } from '@nestjs/passport';
|
||||
import { Strategy } from 'passport-local';
|
||||
import { AuthService } from '../../auth.service';
|
||||
import { RequestWithUser } from '../../constants/request-with-user';
|
||||
import { AccountsEntity } from '../../../database/entities';
|
||||
|
||||
@Injectable()
|
||||
export class LocalAuthStrategy extends PassportStrategy(Strategy, 'local') {
|
||||
constructor(private readonly authService: AuthService) {
|
||||
super({
|
||||
usernameField: 'username',
|
||||
passwordField: 'password',
|
||||
passReqToCallback: true,
|
||||
});
|
||||
}
|
||||
|
||||
async validate(request: RequestWithUser, username: string, password: string): Promise<AccountsEntity> {
|
||||
const account = await this.authService.getAuthenticatedUser(username, password);
|
||||
return account;
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import bcrypt from 'bcrypt';
|
||||
import { Repository } from 'typeorm';
|
||||
import { AccountsEntity } from '../../database/entities';
|
||||
|
||||
@Injectable()
|
||||
export class UsersAuthService {
|
||||
constructor(
|
||||
@InjectRepository(AccountsEntity)
|
||||
private readonly accountsRepository: Repository<AccountsEntity>
|
||||
) {}
|
||||
|
||||
async getUserById(accountId: number) {
|
||||
return await this.accountsRepository.findOne({
|
||||
relations: { profili: { ruolo: true } },
|
||||
where: { id: accountId },
|
||||
});
|
||||
}
|
||||
|
||||
async getUserByUsername(username: string) {
|
||||
return await this.accountsRepository.findOne({
|
||||
relations: { profili: { ruolo: true } },
|
||||
where: { username: username },
|
||||
});
|
||||
}
|
||||
|
||||
async getUserByIdAndRefreshTokenPair(accountId: number, refreshToken: string) {
|
||||
const accountById = await this.getUserById(accountId);
|
||||
if (!accountById?.ultimoHashRefreshToken) return null;
|
||||
|
||||
const isRefreshTokenMatching = await bcrypt.compare(refreshToken, accountById.ultimoHashRefreshToken);
|
||||
return isRefreshTokenMatching ? accountById : null;
|
||||
}
|
||||
|
||||
async setCurrentRefreshTokenHash(accountId: number, refreshToken: string | null) {
|
||||
const hash = refreshToken ? await bcrypt.hash(refreshToken, 10) : null;
|
||||
await this.accountsRepository.update(accountId, {
|
||||
ultimoHashRefreshToken: hash,
|
||||
});
|
||||
}
|
||||
}
|
13
apps/ebitemp-api/src/app/modules/auth/users/users.module.ts
Normal file
13
apps/ebitemp-api/src/app/modules/auth/users/users.module.ts
Normal file
@ -0,0 +1,13 @@
|
||||
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { UsersAuthService } from './users-auth.service';
|
||||
import { AccountsEntity } from '../../database/entities';
|
||||
|
||||
@Module({
|
||||
imports: [TypeOrmModule.forFeature([AccountsEntity])],
|
||||
controllers: [],
|
||||
providers: [UsersAuthService],
|
||||
exports: [UsersAuthService],
|
||||
})
|
||||
export class UsersAuthModule {}
|
@ -6,6 +6,7 @@ import { DatabaseConfig, databaseConfig } from './database.config';
|
||||
import { APP_DATASOURCES } from './database.constants';
|
||||
import { typeormTransactionalDataSourceFactory } from './utils/typeorm-data-source-factory';
|
||||
import { typeormModuleOptionsFactory } from './utils/typeorm-module-options-factory';
|
||||
import { typeormEntitiesFromImport } from './utils/typeorm-import-entities';
|
||||
|
||||
const dataSources: DataSource[] = [];
|
||||
|
||||
@ -14,7 +15,7 @@ const typeormModules = [
|
||||
imports: databaseConfig.asProvider().imports,
|
||||
dataSourceFactory: typeormTransactionalDataSourceFactory(),
|
||||
useFactory: async (dbConfig: DatabaseConfig) => {
|
||||
const config = await typeormModuleOptionsFactory(dbConfig);
|
||||
const config = await typeormModuleOptionsFactory(dbConfig, await typeormEntitiesFromImport(await import('./entities')));
|
||||
return config;
|
||||
},
|
||||
inject: [databaseConfig.KEY],
|
||||
|
@ -0,0 +1,41 @@
|
||||
import { Column, Entity, Index, OneToMany } from 'typeorm';
|
||||
import { ProfiliEntity } from './profili.entity';
|
||||
|
||||
@Index('pk_accounts', ['id'], { unique: true })
|
||||
@Entity('accounts')
|
||||
export class AccountsEntity {
|
||||
@Column('int', { primary: true, name: 'id' })
|
||||
id: number;
|
||||
|
||||
@Column('varchar', { name: 'username', unique: true, length: 255 })
|
||||
username: string;
|
||||
|
||||
@Column('varchar', { name: 'password', nullable: true, length: 255 })
|
||||
password: string | null;
|
||||
|
||||
@Column('varchar', { name: 'nome', length: 255 })
|
||||
nome: string;
|
||||
|
||||
@Column('date', { name: 'data_creazione' })
|
||||
dataCreazione: Date;
|
||||
|
||||
@Column('date', { name: 'data_scadenza', nullable: true })
|
||||
dataScadenza: Date | null;
|
||||
|
||||
@Column('bit', { name: 'flag_primo_accesso', default: () => '(1)' })
|
||||
flagPrimoAccesso: boolean;
|
||||
|
||||
@Column('varchar', {
|
||||
name: 'ultimo_hash_refresh_token',
|
||||
nullable: true,
|
||||
length: 1024,
|
||||
})
|
||||
ultimoHashRefreshToken: string | null;
|
||||
|
||||
@OneToMany(() => ProfiliEntity, (profiliEntity) => profiliEntity.account)
|
||||
profili: ProfiliEntity[];
|
||||
|
||||
constructor(init?: Partial<AccountsEntity>) {
|
||||
Object.assign(this, init);
|
||||
}
|
||||
}
|
@ -1 +1,4 @@
|
||||
export { TipiJobsEntity } from './tipi_jobs.entity';
|
||||
export * from './accounts.entity';
|
||||
export * from './profili.entity';
|
||||
export * from './ruoli.entity';
|
||||
export * from './tipi_jobs.entity';
|
||||
|
@ -0,0 +1,28 @@
|
||||
import { Column, Entity, Index, JoinColumn, ManyToOne } from 'typeorm';
|
||||
import { AccountsEntity } from './accounts.entity';
|
||||
import { RuoliEntity } from './ruoli.entity';
|
||||
|
||||
@Index('pk_profili', ['id'], { unique: true })
|
||||
@Entity('profili')
|
||||
export class ProfiliEntity {
|
||||
@Column('int', { primary: true, name: 'id' })
|
||||
id: number;
|
||||
|
||||
@Column('int', { name: 'id_account', unique: true })
|
||||
idAccount: number;
|
||||
|
||||
@Column('int', { name: 'id_ruolo', unique: true })
|
||||
idRuolo: number;
|
||||
|
||||
@ManyToOne(() => AccountsEntity, (accountsEntity) => accountsEntity.profili)
|
||||
@JoinColumn([{ name: 'id_account', referencedColumnName: 'id' }])
|
||||
account: AccountsEntity;
|
||||
|
||||
@ManyToOne(() => RuoliEntity, (ruoliEntity) => ruoliEntity.profili)
|
||||
@JoinColumn([{ name: 'id_ruolo', referencedColumnName: 'id' }])
|
||||
ruolo: RuoliEntity;
|
||||
|
||||
constructor(init?: Partial<ProfiliEntity>) {
|
||||
Object.assign(this, init);
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
import { Column, Entity, Index, OneToMany } from 'typeorm';
|
||||
import { ProfiliEntity } from './profili.entity';
|
||||
|
||||
@Index('pk_ruoli', ['id'], { unique: true })
|
||||
@Entity('ruoli')
|
||||
export class RuoliEntity {
|
||||
@Column('int', { primary: true, name: 'id' })
|
||||
id: number;
|
||||
|
||||
@Column('varchar', { name: 'nome', unique: true, length: 255 })
|
||||
nome: string;
|
||||
|
||||
@Column('varchar', { name: 'descrizione', length: 255 })
|
||||
descrizione: string;
|
||||
|
||||
@OneToMany(() => ProfiliEntity, (profiliEntity) => profiliEntity.ruolo)
|
||||
profili: ProfiliEntity[];
|
||||
|
||||
constructor(init?: Partial<RuoliEntity>) {
|
||||
Object.assign(this, init);
|
||||
}
|
||||
}
|
@ -15,6 +15,7 @@ export class InviaMailSeErrori {
|
||||
cc: string | null;
|
||||
}
|
||||
|
||||
@Index('pk_tipi_jobs', ['id'], { unique: true })
|
||||
@Entity('tipi_jobs')
|
||||
export class TipiJobsEntity extends Enumify {
|
||||
static _ = TipiJobsEntity.closeEnum();
|
||||
|
@ -4,6 +4,7 @@ import { SnakeNamingStrategy } from 'typeorm-naming-strategies';
|
||||
|
||||
export const typeormModuleOptionsFactory = async (
|
||||
databaseConfig: DatabaseConfig,
|
||||
entities: any[],
|
||||
name?: string
|
||||
): Promise<TypeOrmModuleOptions> => {
|
||||
return {
|
||||
@ -14,7 +15,7 @@ export const typeormModuleOptionsFactory = async (
|
||||
username: databaseConfig.username,
|
||||
password: databaseConfig.password,
|
||||
database: databaseConfig.database,
|
||||
autoLoadEntities: true,
|
||||
entities: entities,
|
||||
synchronize: false,
|
||||
logging: process.env['NODE_ENV'] !== 'production',
|
||||
namingStrategy: new SnakeNamingStrategy(),
|
||||
|
@ -6,7 +6,9 @@ import {
|
||||
MemoryHealthIndicator,
|
||||
TypeOrmHealthIndicator,
|
||||
} from '@nestjs/terminus';
|
||||
import { Public } from '../auth/strategies/jwt/jwt-auth.guard';
|
||||
|
||||
@Public()
|
||||
@Controller('health')
|
||||
export class HealthController {
|
||||
constructor(
|
||||
|
@ -3,11 +3,13 @@ import { NestFactory } from '@nestjs/core';
|
||||
import { FastifyAdapter, NestFastifyApplication } from '@nestjs/platform-fastify';
|
||||
import { Logger as PinoLogger } from 'nestjs-pino';
|
||||
|
||||
import { DocumentBuilder, SwaggerDocumentOptions, SwaggerModule } from '@nestjs/swagger';
|
||||
import { flow } from 'lodash';
|
||||
import { AppModule } from './app/app.module';
|
||||
import { patchPublicDecoratorSupport } from './app/modules/auth/strategies/jwt/jwt-auth.guard';
|
||||
import { LocalConfig, localConfig } from './app/modules/config/local.config';
|
||||
import { patchTypeOrm } from './app/modules/database/utils/typeorm-patch';
|
||||
import { patchNestjsSwagger } from './app/modules/validation/utils/nestjs-swagger-patches';
|
||||
import { DocumentBuilder, SwaggerDocumentOptions, SwaggerModule } from '@nestjs/swagger';
|
||||
|
||||
async function bootstrap() {
|
||||
await patchTypeOrm();
|
||||
@ -23,7 +25,9 @@ async function bootstrap() {
|
||||
const app = await NestFactory.create<NestFastifyApplication>(AppModule, new FastifyAdapter(appOpts));
|
||||
const globalPrefix = 'v1';
|
||||
app.setGlobalPrefix(globalPrefix, {
|
||||
exclude: [{ path: 'health', method: RequestMethod.GET }],
|
||||
exclude: [
|
||||
{ path: '', method: RequestMethod.ALL },
|
||||
{ path: 'health', method: RequestMethod.ALL }],
|
||||
});
|
||||
app.enableShutdownHooks();
|
||||
|
||||
@ -32,15 +36,17 @@ async function bootstrap() {
|
||||
|
||||
app.useLogger(app.get(PinoLogger));
|
||||
|
||||
const swaggerConfig = new DocumentBuilder()
|
||||
.addBearerAuth()
|
||||
.build();
|
||||
const swaggerConfig = new DocumentBuilder().addBearerAuth().build();
|
||||
const swaggerOptions = {
|
||||
operationIdFactory: (controllerKey: string, methodKey: string) => {
|
||||
return `${controllerKey}_${methodKey}`;
|
||||
},
|
||||
} satisfies SwaggerDocumentOptions;
|
||||
const document = SwaggerModule.createDocument(app, swaggerConfig, swaggerOptions);
|
||||
const document = flow(
|
||||
() => SwaggerModule.createDocument(app, swaggerConfig, swaggerOptions),
|
||||
patchPublicDecoratorSupport
|
||||
)();
|
||||
|
||||
SwaggerModule.setup(`${globalPrefix}/docs`, app, document, {
|
||||
swaggerOptions: {
|
||||
operationsSorter: 'alpha',
|
||||
|
@ -6,9 +6,9 @@ module.exports = {
|
||||
output: {
|
||||
path: join(__dirname, '../../dist/apps/ebitemp-api'),
|
||||
devtoolModuleFilenameTemplate(info) {
|
||||
const rel = relative(workspaceRoot, info.absoluteResourcePath);
|
||||
return `webpack:///./${rel}`;
|
||||
},
|
||||
const rel = relative(workspaceRoot, info.absoluteResourcePath);
|
||||
return `webpack:///./${rel}`;
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
new NxAppWebpackPlugin({
|
||||
@ -20,6 +20,9 @@ module.exports = {
|
||||
optimization: false,
|
||||
outputHashing: 'none',
|
||||
generatePackageJson: true,
|
||||
transformers: [
|
||||
{ name: '@nestjs/swagger/plugin', options: { introspectComments: true } }
|
||||
],
|
||||
}),
|
||||
],
|
||||
};
|
||||
|
@ -20,6 +20,8 @@
|
||||
"@nestjs/common": "^11.0.8",
|
||||
"@nestjs/config": "^4.0.0",
|
||||
"@nestjs/core": "^11.0.8",
|
||||
"@nestjs/jwt": "^11.0.0",
|
||||
"@nestjs/passport": "^11.0.5",
|
||||
"@nestjs/platform-express": "^11.0.8",
|
||||
"@nestjs/platform-fastify": "^11.0.8",
|
||||
"@nestjs/schedule": "^5.0.1",
|
||||
@ -28,14 +30,18 @@
|
||||
"@nestjs/typeorm": "^11.0.0",
|
||||
"@nx/devkit": "20.4.2",
|
||||
"axios": "^1.7.9",
|
||||
"bcrypt": "^5.1.1",
|
||||
"cacheable": "^1.8.8",
|
||||
"connection-string": "^4.4.0",
|
||||
"cron": "^3.5.0",
|
||||
"dayjs": "^1.11.13",
|
||||
"fastify": "^5.2.1",
|
||||
"flatted": "^3.3.2",
|
||||
"lodash": "^4.17.21",
|
||||
"nestjs-pino": "^4.3.0",
|
||||
"openapi3-ts": "^4.4.0",
|
||||
"passport-jwt": "^4.0.1",
|
||||
"passport-local": "^1.0.0",
|
||||
"patch-package": "^8.0.0",
|
||||
"pino-http": "^10.4.0",
|
||||
"pino-pretty": "^13.0.0",
|
||||
@ -65,9 +71,11 @@
|
||||
"@swc/cli": "~0.3.12",
|
||||
"@swc/core": "~1.10.15",
|
||||
"@swc/helpers": "~0.5.11",
|
||||
"@types/bcrypt": "^5.0.2",
|
||||
"@types/jest": "^29.5.14",
|
||||
"@types/lodash": "^4.17.15",
|
||||
"@types/node": "~18.16.9",
|
||||
"@types/passport-jwt": "^4.0.1",
|
||||
"eslint": "^9.20.0",
|
||||
"eslint-config-prettier": "^9.0.0",
|
||||
"execa": "5.1.1",
|
||||
|
343
pnpm-lock.yaml
generated
343
pnpm-lock.yaml
generated
@ -35,6 +35,12 @@ dependencies:
|
||||
'@nestjs/core':
|
||||
specifier: ^11.0.8
|
||||
version: 11.0.8(@nestjs/common@11.0.8)(@nestjs/platform-express@11.0.8)(reflect-metadata@0.2.2)(rxjs@7.8.1)
|
||||
'@nestjs/jwt':
|
||||
specifier: ^11.0.0
|
||||
version: 11.0.0(@nestjs/common@11.0.8)
|
||||
'@nestjs/passport':
|
||||
specifier: ^11.0.5
|
||||
version: 11.0.5(@nestjs/common@11.0.8)(passport@0.7.0)
|
||||
'@nestjs/platform-express':
|
||||
specifier: ^11.0.8
|
||||
version: 11.0.8(@nestjs/common@11.0.8)(@nestjs/core@11.0.8)
|
||||
@ -59,6 +65,9 @@ dependencies:
|
||||
axios:
|
||||
specifier: ^1.7.9
|
||||
version: 1.7.9
|
||||
bcrypt:
|
||||
specifier: ^5.1.1
|
||||
version: 5.1.1
|
||||
cacheable:
|
||||
specifier: ^1.8.8
|
||||
version: 1.8.8
|
||||
@ -71,6 +80,9 @@ dependencies:
|
||||
dayjs:
|
||||
specifier: ^1.11.13
|
||||
version: 1.11.13
|
||||
fastify:
|
||||
specifier: ^5.2.1
|
||||
version: 5.2.1
|
||||
flatted:
|
||||
specifier: ^3.3.2
|
||||
version: 3.3.2
|
||||
@ -83,6 +95,12 @@ dependencies:
|
||||
openapi3-ts:
|
||||
specifier: ^4.4.0
|
||||
version: 4.4.0
|
||||
passport-jwt:
|
||||
specifier: ^4.0.1
|
||||
version: 4.0.1
|
||||
passport-local:
|
||||
specifier: ^1.0.0
|
||||
version: 1.0.0
|
||||
patch-package:
|
||||
specifier: ^8.0.0
|
||||
version: 8.0.0
|
||||
@ -166,6 +184,9 @@ devDependencies:
|
||||
'@swc/helpers':
|
||||
specifier: ~0.5.11
|
||||
version: 0.5.15
|
||||
'@types/bcrypt':
|
||||
specifier: ^5.0.2
|
||||
version: 5.0.2
|
||||
'@types/jest':
|
||||
specifier: ^29.5.14
|
||||
version: 29.5.14
|
||||
@ -175,6 +196,9 @@ devDependencies:
|
||||
'@types/node':
|
||||
specifier: ~18.16.9
|
||||
version: 18.16.20
|
||||
'@types/passport-jwt':
|
||||
specifier: ^4.0.1
|
||||
version: 4.0.1
|
||||
eslint:
|
||||
specifier: ^9.20.0
|
||||
version: 9.20.0
|
||||
@ -2328,6 +2352,24 @@ packages:
|
||||
engines: {node: '>=8'}
|
||||
dev: false
|
||||
|
||||
/@mapbox/node-pre-gyp@1.0.11:
|
||||
resolution: {integrity: sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
detect-libc: 2.0.3
|
||||
https-proxy-agent: 5.0.1
|
||||
make-dir: 3.1.0
|
||||
node-fetch: 2.7.0
|
||||
nopt: 5.0.0
|
||||
npmlog: 5.0.1
|
||||
rimraf: 3.0.2
|
||||
semver: 7.7.1
|
||||
tar: 6.2.1
|
||||
transitivePeerDependencies:
|
||||
- encoding
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
/@microsoft/tsdoc@0.15.0:
|
||||
resolution: {integrity: sha512-HZpPoABogPvjeJOdzCOSJsXeL/SMCBgBZMVC3X3d7YYp2gf31MfxhUoYUNwf1ERPJOnQc0wkFn9trqI6ZEdZuA==}
|
||||
dev: false
|
||||
@ -2583,6 +2625,16 @@ packages:
|
||||
tslib: 2.8.1
|
||||
uid: 2.0.2
|
||||
|
||||
/@nestjs/jwt@11.0.0(@nestjs/common@11.0.8):
|
||||
resolution: {integrity: sha512-v7YRsW3Xi8HNTsO+jeHSEEqelX37TVWgwt+BcxtkG/OfXJEOs6GZdbdza200d6KqId1pJQZ6UPj1F0M6E+mxaA==}
|
||||
peerDependencies:
|
||||
'@nestjs/common': ^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0
|
||||
dependencies:
|
||||
'@nestjs/common': 11.0.8(reflect-metadata@0.2.2)(rxjs@7.8.1)
|
||||
'@types/jsonwebtoken': 9.0.7
|
||||
jsonwebtoken: 9.0.2
|
||||
dev: false
|
||||
|
||||
/@nestjs/mapped-types@2.1.0(@nestjs/common@11.0.8)(reflect-metadata@0.2.2):
|
||||
resolution: {integrity: sha512-W+n+rM69XsFdwORF11UqJahn4J3xi4g/ZEOlJNL6KoW5ygWSmBB2p0S2BZ4FQeS/NDH72e6xIcu35SfJnE8bXw==}
|
||||
peerDependencies:
|
||||
@ -2600,6 +2652,16 @@ packages:
|
||||
reflect-metadata: 0.2.2
|
||||
dev: false
|
||||
|
||||
/@nestjs/passport@11.0.5(@nestjs/common@11.0.8)(passport@0.7.0):
|
||||
resolution: {integrity: sha512-ulQX6mbjlws92PIM15Naes4F4p2JoxGnIJuUsdXQPT+Oo2sqQmENEZXM7eYuimocfHnKlcfZOuyzbA33LwUlOQ==}
|
||||
peerDependencies:
|
||||
'@nestjs/common': ^10.0.0 || ^11.0.0
|
||||
passport: ^0.5.0 || ^0.6.0 || ^0.7.0
|
||||
dependencies:
|
||||
'@nestjs/common': 11.0.8(reflect-metadata@0.2.2)(rxjs@7.8.1)
|
||||
passport: 0.7.0
|
||||
dev: false
|
||||
|
||||
/@nestjs/platform-express@11.0.8(@nestjs/common@11.0.8)(@nestjs/core@11.0.8):
|
||||
resolution: {integrity: sha512-Ru7seOYYglKNGQFzNALE5ilLqkdtX/ge6AJDKLMt+WI7iElZ7lXjT40fE3+HVUiZODunmeKQ7jVxcQyZwLafVA==}
|
||||
peerDependencies:
|
||||
@ -3813,6 +3875,12 @@ packages:
|
||||
'@babel/types': 7.26.7
|
||||
dev: true
|
||||
|
||||
/@types/bcrypt@5.0.2:
|
||||
resolution: {integrity: sha512-6atioO8Y75fNcbmj0G7UjI9lXN2pQ/IGJ2FWT4a/btd0Lk9lQalHLKhkgKVZ3r+spnmWUKfbMi1GEe9wyHQfNQ==}
|
||||
dependencies:
|
||||
'@types/node': 18.16.20
|
||||
dev: true
|
||||
|
||||
/@types/body-parser@1.19.5:
|
||||
resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==}
|
||||
dependencies:
|
||||
@ -3946,6 +4014,19 @@ packages:
|
||||
resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
|
||||
dev: true
|
||||
|
||||
/@types/jsonwebtoken@9.0.7:
|
||||
resolution: {integrity: sha512-ugo316mmTYBl2g81zDFnZ7cfxlut3o+/EQdaP7J8QN2kY6lJ22hmQYCK5EHcJHbrW+dkCGSCPgbG8JtYj6qSrg==}
|
||||
dependencies:
|
||||
'@types/node': 18.16.20
|
||||
dev: false
|
||||
|
||||
/@types/jsonwebtoken@9.0.8:
|
||||
resolution: {integrity: sha512-7fx54m60nLFUVYlxAB1xpe9CBWX2vSrk50Y6ogRJ1v5xxtba7qXTg5BgYDN5dq+yuQQ9HaVlHJyAAt1/mxryFg==}
|
||||
dependencies:
|
||||
'@types/ms': 2.1.0
|
||||
'@types/node': 18.16.20
|
||||
dev: true
|
||||
|
||||
/@types/keyv@3.1.4:
|
||||
resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==}
|
||||
dependencies:
|
||||
@ -3964,6 +4045,10 @@ packages:
|
||||
resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==}
|
||||
dev: true
|
||||
|
||||
/@types/ms@2.1.0:
|
||||
resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==}
|
||||
dev: true
|
||||
|
||||
/@types/node-forge@1.3.11:
|
||||
resolution: {integrity: sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==}
|
||||
dependencies:
|
||||
@ -3977,6 +4062,26 @@ packages:
|
||||
resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==}
|
||||
dev: true
|
||||
|
||||
/@types/passport-jwt@4.0.1:
|
||||
resolution: {integrity: sha512-Y0Ykz6nWP4jpxgEUYq8NoVZeCQPo1ZndJLfapI249g1jHChvRfZRO/LS3tqu26YgAS/laI1qx98sYGz0IalRXQ==}
|
||||
dependencies:
|
||||
'@types/jsonwebtoken': 9.0.8
|
||||
'@types/passport-strategy': 0.2.38
|
||||
dev: true
|
||||
|
||||
/@types/passport-strategy@0.2.38:
|
||||
resolution: {integrity: sha512-GC6eMqqojOooq993Tmnmp7AUTbbQSgilyvpCYQjT+H6JfG/g6RGc7nXEniZlp0zyKJ0WUdOiZWLBZft9Yug1uA==}
|
||||
dependencies:
|
||||
'@types/express': 4.17.21
|
||||
'@types/passport': 1.0.17
|
||||
dev: true
|
||||
|
||||
/@types/passport@1.0.17:
|
||||
resolution: {integrity: sha512-aciLyx+wDwT2t2/kJGJR2AEeBz0nJU4WuRX04Wu9Dqc5lSUtwu0WERPHYsLhF9PtseiAMPBGNUOtFjxZ56prsg==}
|
||||
dependencies:
|
||||
'@types/express': 4.17.21
|
||||
dev: true
|
||||
|
||||
/@types/qs@6.9.18:
|
||||
resolution: {integrity: sha512-kK7dgTYDyGqS+e2Q4aK9X3D7q234CIZ1Bv0q/7Z5IwRDoADNU81xXJK/YVyLbLTZCoIwUoDoffFeF+p/eIklAA==}
|
||||
dev: true
|
||||
@ -4335,6 +4440,10 @@ packages:
|
||||
dependencies:
|
||||
argparse: 2.0.1
|
||||
|
||||
/abbrev@1.1.1:
|
||||
resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==}
|
||||
dev: false
|
||||
|
||||
/abort-controller@3.0.0:
|
||||
resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==}
|
||||
engines: {node: '>=6.5'}
|
||||
@ -4384,6 +4493,15 @@ packages:
|
||||
engines: {node: '>= 10.0.0'}
|
||||
dev: true
|
||||
|
||||
/agent-base@6.0.2:
|
||||
resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==}
|
||||
engines: {node: '>= 6.0.0'}
|
||||
dependencies:
|
||||
debug: 4.4.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
/agent-base@7.1.3:
|
||||
resolution: {integrity: sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==}
|
||||
engines: {node: '>= 14'}
|
||||
@ -4526,10 +4644,23 @@ packages:
|
||||
/append-field@1.0.0:
|
||||
resolution: {integrity: sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==}
|
||||
|
||||
/aproba@2.0.0:
|
||||
resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==}
|
||||
dev: false
|
||||
|
||||
/arch@2.2.0:
|
||||
resolution: {integrity: sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==}
|
||||
dev: true
|
||||
|
||||
/are-we-there-yet@2.0.0:
|
||||
resolution: {integrity: sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==}
|
||||
engines: {node: '>=10'}
|
||||
deprecated: This package is no longer supported.
|
||||
dependencies:
|
||||
delegates: 1.0.0
|
||||
readable-stream: 3.6.2
|
||||
dev: false
|
||||
|
||||
/arg@4.1.3:
|
||||
resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==}
|
||||
|
||||
@ -4793,6 +4924,18 @@ packages:
|
||||
resolution: {integrity: sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==}
|
||||
dev: true
|
||||
|
||||
/bcrypt@5.1.1:
|
||||
resolution: {integrity: sha512-AGBHOG5hPYZ5Xl9KXzU5iKq9516yEmvCKDg3ecP5kX2aB6UqTeXZxk2ELnDgDm6BQSMlLt9rDB4LoSMx0rYwww==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
requiresBuild: true
|
||||
dependencies:
|
||||
'@mapbox/node-pre-gyp': 1.0.11
|
||||
node-addon-api: 5.1.0
|
||||
transitivePeerDependencies:
|
||||
- encoding
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
/big.js@5.2.2:
|
||||
resolution: {integrity: sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==}
|
||||
dev: true
|
||||
@ -5131,6 +5274,11 @@ packages:
|
||||
readdirp: 4.1.1
|
||||
dev: true
|
||||
|
||||
/chownr@2.0.0:
|
||||
resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==}
|
||||
engines: {node: '>=10'}
|
||||
dev: false
|
||||
|
||||
/chrome-trace-event@1.0.4:
|
||||
resolution: {integrity: sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==}
|
||||
engines: {node: '>=6.0'}
|
||||
@ -5242,6 +5390,11 @@ packages:
|
||||
/color-name@1.1.4:
|
||||
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
|
||||
|
||||
/color-support@1.1.3:
|
||||
resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==}
|
||||
hasBin: true
|
||||
dev: false
|
||||
|
||||
/colord@2.9.3:
|
||||
resolution: {integrity: sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==}
|
||||
dev: true
|
||||
@ -5353,6 +5506,10 @@ packages:
|
||||
resolution: {integrity: sha512-EiPU8G6dQG0GFHNR8ljnZFki/8a+cQwEQ+7wpxdChl02Q8HXlwEZWD5lqAF8vC2sEC3Tehr8hy7vErz88LHyUA==}
|
||||
engines: {node: ^14.18.0 || >=16.10.0}
|
||||
|
||||
/console-control-strings@1.1.0:
|
||||
resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==}
|
||||
dev: false
|
||||
|
||||
/constant-case@3.0.4:
|
||||
resolution: {integrity: sha512-I2hSBi7Vvs7BEuJDr5dDHfzb/Ruj3FyvFyh7KLilAjNQw3Be+xgqUBA2W6scVEcL0hL1dwPRtIqEPVUCKkSsyQ==}
|
||||
dependencies:
|
||||
@ -5796,6 +5953,10 @@ packages:
|
||||
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
|
||||
engines: {node: '>=0.4.0'}
|
||||
|
||||
/delegates@1.0.0:
|
||||
resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==}
|
||||
dev: false
|
||||
|
||||
/depd@1.1.2:
|
||||
resolution: {integrity: sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==}
|
||||
engines: {node: '>= 0.6'}
|
||||
@ -5822,6 +5983,11 @@ packages:
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/detect-libc@2.0.3:
|
||||
resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==}
|
||||
engines: {node: '>=8'}
|
||||
dev: false
|
||||
|
||||
/detect-newline@3.1.0:
|
||||
resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==}
|
||||
engines: {node: '>=8'}
|
||||
@ -6736,6 +6902,13 @@ packages:
|
||||
jsonfile: 6.1.0
|
||||
universalify: 2.0.1
|
||||
|
||||
/fs-minipass@2.1.0:
|
||||
resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==}
|
||||
engines: {node: '>= 8'}
|
||||
dependencies:
|
||||
minipass: 3.3.6
|
||||
dev: false
|
||||
|
||||
/fs-monkey@1.0.6:
|
||||
resolution: {integrity: sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==}
|
||||
dev: true
|
||||
@ -6754,6 +6927,22 @@ packages:
|
||||
/function-bind@1.1.2:
|
||||
resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
|
||||
|
||||
/gauge@3.0.2:
|
||||
resolution: {integrity: sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==}
|
||||
engines: {node: '>=10'}
|
||||
deprecated: This package is no longer supported.
|
||||
dependencies:
|
||||
aproba: 2.0.0
|
||||
color-support: 1.1.3
|
||||
console-control-strings: 1.1.0
|
||||
has-unicode: 2.0.1
|
||||
object-assign: 4.1.1
|
||||
signal-exit: 3.0.7
|
||||
string-width: 4.2.3
|
||||
strip-ansi: 6.0.1
|
||||
wide-align: 1.1.5
|
||||
dev: false
|
||||
|
||||
/generic-pool@3.9.0:
|
||||
resolution: {integrity: sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==}
|
||||
engines: {node: '>= 4'}
|
||||
@ -6960,6 +7149,10 @@ packages:
|
||||
resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
/has-unicode@2.0.1:
|
||||
resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==}
|
||||
dev: false
|
||||
|
||||
/hasown@2.0.2:
|
||||
resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@ -7118,6 +7311,16 @@ packages:
|
||||
resolve-alpn: 1.2.1
|
||||
dev: true
|
||||
|
||||
/https-proxy-agent@5.0.1:
|
||||
resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==}
|
||||
engines: {node: '>= 6'}
|
||||
dependencies:
|
||||
agent-base: 6.0.2
|
||||
debug: 4.4.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
/https-proxy-agent@7.0.6:
|
||||
resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==}
|
||||
engines: {node: '>= 14'}
|
||||
@ -8306,6 +8509,13 @@ packages:
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/make-dir@3.1.0:
|
||||
resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
semver: 6.3.1
|
||||
dev: false
|
||||
|
||||
/make-dir@4.0.0:
|
||||
resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==}
|
||||
engines: {node: '>=10'}
|
||||
@ -8480,10 +8690,30 @@ packages:
|
||||
/minimist@1.2.8:
|
||||
resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
|
||||
|
||||
/minipass@3.3.6:
|
||||
resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
yallist: 4.0.0
|
||||
dev: false
|
||||
|
||||
/minipass@5.0.0:
|
||||
resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==}
|
||||
engines: {node: '>=8'}
|
||||
dev: false
|
||||
|
||||
/minipass@7.1.2:
|
||||
resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==}
|
||||
engines: {node: '>=16 || 14 >=14.17'}
|
||||
|
||||
/minizlib@2.1.2:
|
||||
resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==}
|
||||
engines: {node: '>= 8'}
|
||||
dependencies:
|
||||
minipass: 3.3.6
|
||||
yallist: 4.0.0
|
||||
dev: false
|
||||
|
||||
/mkdirp@0.5.6:
|
||||
resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==}
|
||||
hasBin: true
|
||||
@ -8494,7 +8724,6 @@ packages:
|
||||
resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==}
|
||||
engines: {node: '>=10'}
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/mkdirp@2.1.6:
|
||||
resolution: {integrity: sha512-+hEnITedc8LAtIP9u3HJDFIdcLV2vXP33sqLLIzkv1Db1zO/1OxbvYf0Y1OC/S/Qo5dxHXepofhmxL02PsKe+A==}
|
||||
@ -8627,12 +8856,28 @@ packages:
|
||||
resolution: {integrity: sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==}
|
||||
dev: true
|
||||
|
||||
/node-addon-api@5.1.0:
|
||||
resolution: {integrity: sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==}
|
||||
dev: false
|
||||
|
||||
/node-addon-api@7.1.1:
|
||||
resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==}
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/node-fetch@2.7.0:
|
||||
resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==}
|
||||
engines: {node: 4.x || >=6.0.0}
|
||||
peerDependencies:
|
||||
encoding: ^0.1.0
|
||||
peerDependenciesMeta:
|
||||
encoding:
|
||||
optional: true
|
||||
dependencies:
|
||||
whatwg-url: 5.0.0
|
||||
dev: false
|
||||
|
||||
/node-forge@1.3.1:
|
||||
resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==}
|
||||
engines: {node: '>= 6.13.0'}
|
||||
@ -8649,6 +8894,14 @@ packages:
|
||||
resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==}
|
||||
dev: true
|
||||
|
||||
/nopt@5.0.0:
|
||||
resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==}
|
||||
engines: {node: '>=6'}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
abbrev: 1.1.1
|
||||
dev: false
|
||||
|
||||
/normalize-path@3.0.0:
|
||||
resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@ -8687,6 +8940,16 @@ packages:
|
||||
dependencies:
|
||||
path-key: 3.1.1
|
||||
|
||||
/npmlog@5.0.1:
|
||||
resolution: {integrity: sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==}
|
||||
deprecated: This package is no longer supported.
|
||||
dependencies:
|
||||
are-we-there-yet: 2.0.0
|
||||
console-control-strings: 1.1.0
|
||||
gauge: 3.0.2
|
||||
set-blocking: 2.0.0
|
||||
dev: false
|
||||
|
||||
/nth-check@2.1.1:
|
||||
resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==}
|
||||
dependencies:
|
||||
@ -9031,6 +9294,34 @@ packages:
|
||||
tslib: 2.8.1
|
||||
dev: true
|
||||
|
||||
/passport-jwt@4.0.1:
|
||||
resolution: {integrity: sha512-UCKMDYhNuGOBE9/9Ycuoyh7vP6jpeTp/+sfMJl7nLff/t6dps+iaeE0hhNkKN8/HZHcJ7lCdOyDxHdDoxoSvdQ==}
|
||||
dependencies:
|
||||
jsonwebtoken: 9.0.2
|
||||
passport-strategy: 1.0.0
|
||||
dev: false
|
||||
|
||||
/passport-local@1.0.0:
|
||||
resolution: {integrity: sha512-9wCE6qKznvf9mQYYbgJ3sVOHmCWoUNMVFoZzNoznmISbhnNNPhN9xfY3sLmScHMetEJeoY7CXwfhCe7argfQow==}
|
||||
engines: {node: '>= 0.4.0'}
|
||||
dependencies:
|
||||
passport-strategy: 1.0.0
|
||||
dev: false
|
||||
|
||||
/passport-strategy@1.0.0:
|
||||
resolution: {integrity: sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==}
|
||||
engines: {node: '>= 0.4.0'}
|
||||
dev: false
|
||||
|
||||
/passport@0.7.0:
|
||||
resolution: {integrity: sha512-cPLl+qZpSc+ireUvt+IzqbED1cHHkDoVYMo30jbJIdOOjQ1MQYZBPiNvmi8UM6lJuOpTPXJGZQk0DtC4y61MYQ==}
|
||||
engines: {node: '>= 0.4.0'}
|
||||
dependencies:
|
||||
passport-strategy: 1.0.0
|
||||
pause: 0.0.1
|
||||
utils-merge: 1.0.1
|
||||
dev: false
|
||||
|
||||
/patch-package@8.0.0:
|
||||
resolution: {integrity: sha512-da8BVIhzjtgScwDJ2TtKsfT5JFWz1hYoBl9rUQ1f38MC2HwnEIkK8VN3dKMKcP7P7bvvgzNDbfNHtx3MsQb5vA==}
|
||||
engines: {node: '>=14', npm: '>5'}
|
||||
@ -9115,6 +9406,10 @@ packages:
|
||||
engines: {node: '>=8'}
|
||||
dev: true
|
||||
|
||||
/pause@0.0.1:
|
||||
resolution: {integrity: sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==}
|
||||
dev: false
|
||||
|
||||
/peek-readable@5.4.2:
|
||||
resolution: {integrity: sha512-peBp3qZyuS6cNIJ2akRNG1uo1WJ1d0wTxg/fxMdZ0BqCVhx242bSFHM9eNqflfJVS9SsgkzgT/1UgnsurBOTMg==}
|
||||
engines: {node: '>=14.16'}
|
||||
@ -9994,6 +10289,14 @@ packages:
|
||||
glob: 7.2.3
|
||||
dev: false
|
||||
|
||||
/rimraf@3.0.2:
|
||||
resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==}
|
||||
deprecated: Rimraf versions prior to v4 are no longer supported
|
||||
hasBin: true
|
||||
dependencies:
|
||||
glob: 7.2.3
|
||||
dev: false
|
||||
|
||||
/router@2.0.0:
|
||||
resolution: {integrity: sha512-dIM5zVoG8xhC6rnSN8uoAgFARwTE7BQs8YwHEvK0VCmfxQXMaOuA1uiR1IPwsW7JyK5iTt7Od/TC9StasS2NPQ==}
|
||||
engines: {node: '>= 0.10'}
|
||||
@ -10158,7 +10461,6 @@ packages:
|
||||
/semver@6.3.1:
|
||||
resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/semver@7.7.1:
|
||||
resolution: {integrity: sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==}
|
||||
@ -10261,6 +10563,10 @@ packages:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
/set-blocking@2.0.0:
|
||||
resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==}
|
||||
dev: false
|
||||
|
||||
/set-cookie-parser@2.7.1:
|
||||
resolution: {integrity: sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==}
|
||||
dev: false
|
||||
@ -10722,6 +11028,18 @@ packages:
|
||||
inherits: 2.0.4
|
||||
readable-stream: 3.6.2
|
||||
|
||||
/tar@6.2.1:
|
||||
resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==}
|
||||
engines: {node: '>=10'}
|
||||
dependencies:
|
||||
chownr: 2.0.0
|
||||
fs-minipass: 2.1.0
|
||||
minipass: 5.0.0
|
||||
minizlib: 2.1.2
|
||||
mkdirp: 1.0.4
|
||||
yallist: 4.0.0
|
||||
dev: false
|
||||
|
||||
/tarn@3.0.2:
|
||||
resolution: {integrity: sha512-51LAVKUSZSVfI05vjPESNc5vwqqZpbXCsU+/+wxlOrUjk2SnFTt97v9ZgQrD4YmxYW1Px6w2KjaDitCfkvgxMQ==}
|
||||
engines: {node: '>=8.0.0'}
|
||||
@ -10867,6 +11185,10 @@ packages:
|
||||
ieee754: 1.2.1
|
||||
dev: true
|
||||
|
||||
/tr46@0.0.3:
|
||||
resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==}
|
||||
dev: false
|
||||
|
||||
/tree-dump@1.0.2(tslib@2.8.1):
|
||||
resolution: {integrity: sha512-dpev9ABuLWdEubk+cIaI9cHwRNNDjkBBLXTwI4UCUFdQ5xXKqNXoK4FEciw/vxf+NQ7Cb7sGUyeUtORvHIdRXQ==}
|
||||
engines: {node: '>=10.0'}
|
||||
@ -11464,6 +11786,10 @@ packages:
|
||||
dependencies:
|
||||
defaults: 1.0.4
|
||||
|
||||
/webidl-conversions@3.0.1:
|
||||
resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
|
||||
dev: false
|
||||
|
||||
/webpack-cli@5.1.4(webpack@5.97.1):
|
||||
resolution: {integrity: sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==}
|
||||
engines: {node: '>=14.15.0'}
|
||||
@ -11658,6 +11984,13 @@ packages:
|
||||
iconv-lite: 0.6.3
|
||||
dev: true
|
||||
|
||||
/whatwg-url@5.0.0:
|
||||
resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==}
|
||||
dependencies:
|
||||
tr46: 0.0.3
|
||||
webidl-conversions: 3.0.1
|
||||
dev: false
|
||||
|
||||
/which@1.3.1:
|
||||
resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==}
|
||||
hasBin: true
|
||||
@ -11672,6 +12005,12 @@ packages:
|
||||
dependencies:
|
||||
isexe: 2.0.0
|
||||
|
||||
/wide-align@1.1.5:
|
||||
resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==}
|
||||
dependencies:
|
||||
string-width: 4.2.3
|
||||
dev: false
|
||||
|
||||
/widest-line@3.1.0:
|
||||
resolution: {integrity: sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==}
|
||||
engines: {node: '>=8'}
|
||||
|
Reference in New Issue
Block a user