refactor: ( passenger-api.auth ) remove the existing auth module

This commit is contained in:
Abubeker Yasin
2026-06-03 10:12:08 +03:00
parent 092199f536
commit 785623fcbb
9 changed files with 209 additions and 115 deletions

View File

@@ -36,8 +36,8 @@
"@nestjs/swagger": "^7.4.0",
"@nestjs/typeorm": "^11.0.1",
"@sendgrid/mail": "^8.1.0",
"@tria-plc/api-common": "^0.1.4",
"@tria-plc/iamapi-common": "^0.1.6",
"@tria-plc/api-common": "1.2.3",
"@tria-plc/iamapi-common": "^0.4.1",
"amqp-connection-manager": "^5.0.0",
"amqplib": "^2.0.1",
"axios": "^1.7.7",

View File

@@ -1,4 +1,9 @@
import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common';
import {
MiddlewareConsumer,
Module,
NestModule,
OnApplicationBootstrap,
} from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { ScheduleModule } from '@nestjs/schedule';
import { EventEmitterModule } from '@nestjs/event-emitter';
@@ -6,6 +11,7 @@ import { TypeOrmModule, TypeOrmModuleOptions } from '@nestjs/typeorm';
// Subpath import: the @tria-plc/iamapi-common barrel does not resolve under moduleResolution:"Node".
// Aliased to avoid clashing with the app's existing custom ./common/iam.module (remote IamGuard).
import { IamModule as TriaIamModule } from '@tria-plc/iamapi-common/iam.module';
import { DataSeeder } from '@tria-plc/iamapi-common/db/seed/seeder';
import { PrismaModule } from './common/prisma.module';
import { I18nModule } from './common/i18n/i18n.module';
import { LocaleMiddleware } from './common/i18n/locale.middleware';
@@ -18,7 +24,6 @@ import ebirrConfig from './config/ebirr.config';
import cardConfig from './config/card.config';
import waafiConfig from './config/waafi.config';
import faydaConfig from './config/fayda.config';
import { AuthModule } from './modules/auth/auth.module';
import { StationsModule } from './modules/stations/stations.module';
import { FleetModule } from './modules/fleet/fleet.module';
import { SchedulesModule } from './modules/schedules/schedules.module';
@@ -61,22 +66,14 @@ import { VerifaydaModule } from './modules/verifayda/verifayda.module';
}),
ScheduleModule.forRoot(),
EventEmitterModule.forRoot(),
// TypeORM root DataSource for the shared `iam` schema (coexists with Prisma's `passenger`
// schema). Required so @tria-plc/api-common's JwtGuard can read `iam.sessions`, and so
// IamModule's forFeature repositories resolve. Options come from the `database` config
// namespace (see config/database.config.ts → iam-typeorm.config.ts).
TypeOrmModule.forRootAsync({
inject: [ConfigService],
useFactory: (config: ConfigService): TypeOrmModuleOptions =>
config.get<TypeOrmModuleOptions>('iamDatabase')!,
}),
// Mount the @tria-plc IAM module (auth/user/org-structure). Registers the IAM REST API under
// /v1/* (URI versioning). NOTE: SharedAuthModule (global JwtGuard) is intentionally added later
// in the route-protection phase, so public passenger routes are not 401'd before then.
TriaIamModule.forRoot(),
PrismaModule,
I18nModule,
// AuthModule,
StationsModule,
FleetModule,
SchedulesModule,
@@ -102,8 +99,16 @@ import { VerifaydaModule } from './modules/verifayda/verifayda.module';
VerifaydaModule,
],
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer.apply(LocaleMiddleware).forRoutes('*');
export class AppModule implements OnApplicationBootstrap {
constructor(
private readonly seeder: DataSeeder,
// private readonly edrOrgSeeder: EdrOrgSeeder,
// private readonly demoUsersSeeder: DemoUsersSeeder,
) { }
async onApplicationBootstrap() {
await this.seeder.run();
// await this.edrOrgSeeder.run();
// await this.demoUsersSeeder.run();
}
}

View File

@@ -1,5 +1,4 @@
import { Injectable } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
@Injectable()
export class JwtGuard extends AuthGuard('jwt') {}
// Compatibility alias while passenger auth moves to @tria-plc IAM.
// Existing controllers can keep importing `../../common/jwt.guard`, but the
// guard now validates IAM-issued session tokens from `iam.sessions`.
export { JwtGuard } from '@tria-plc/api-common/modules/auth/services/jwt.guard';

View File

@@ -1,21 +1,30 @@
import { Injectable } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { InjectDataSource } from '@nestjs/typeorm';
import { JwtGuard as IamJwtGuard } from '@tria-plc/api-common/modules/auth/services/jwt.guard';
import { DataSource } from 'typeorm';
/**
* Like {@link JwtGuard}, but never rejects the request.
* Like the IAM JwtGuard, but never rejects the request.
*
* When a valid `Authorization: Bearer <jwt>` is present, `request.user` is
* populated from the JWT strategy (`{ userId, ... }`). When the token is
* missing or invalid, the request still proceeds with `request.user`
* undefined — the handler decides what to do.
*
* Used on `POST /fayda/verification/start`, which must work for both
* logged-in users (who can opt to save the verification to their account)
* and guests (anchored to a booking only).
* When a valid IAM bearer token is present, `request.user` is populated with
* the package `TCurrentUser`. Missing or invalid tokens continue as guests.
*/
@Injectable()
export class OptionalJwtGuard extends AuthGuard('jwt') {
handleRequest<TUser = unknown>(_err: unknown, user: TUser): TUser {
return (user ?? null) as TUser;
export class OptionalJwtGuard extends IamJwtGuard implements CanActivate {
constructor(
reflector: Reflector,
@InjectDataSource() dataSource: DataSource,
) {
super(reflector, dataSource);
}
async canActivate(context: ExecutionContext): Promise<boolean> {
try {
await super.canActivate(context);
} catch {
context.switchToHttp().getRequest().user = undefined;
}
return true;
}
}

View File

@@ -15,6 +15,7 @@ import {
ApiOperation,
ApiTags,
} from '@nestjs/swagger';
import type { TCurrentUser } from '@tria-plc/api-common/modules/auth/types/current-user.type';
import { JwtGuard } from '../../common/jwt.guard';
import { OptionalJwtGuard } from './optional-jwt.guard';
import {
@@ -25,21 +26,13 @@ import {
} from './verifayda.dto';
import { VerifaydaService } from './verifayda.service';
/** Shape the JWT strategy puts on `request.user` (see common/jwt.strategy.ts). */
interface AuthedUser {
userId: string;
email?: string;
role?: string;
passengerId?: string;
}
/** Minimal slices of the Express req we touch (avoids a hard dependency on
* `@types/express`, which isn't resolved in this package). */
interface RequestWithOptionalUser {
user?: AuthedUser;
user?: TCurrentUser;
}
interface RequestWithUser {
user: AuthedUser;
user: TCurrentUser;
}
@ApiTags('Fayda Verification')
@@ -75,7 +68,7 @@ export class VerifaydaController {
const authorizationUrl = await this.service.startVerification({
purpose: dto.purpose ?? 'PURCHASE',
platform: dto.platform ?? 'WEB',
userId: req.user?.userId,
userId: req.user?.id,
bookingId: dto.bookingId,
saveToAccount: dto.saveToAccount,
});
@@ -106,6 +99,6 @@ export class VerifaydaController {
async status(
@Req() req: RequestWithUser,
): Promise<VerificationStatusDto> {
return this.service.getVerificationStatus(req.user.userId);
return this.service.getVerificationStatus(req.user.id);
}
}

View File

@@ -2,12 +2,9 @@ import { Module } from '@nestjs/common';
import { VerifaydaController } from './verifayda.controller';
import { VerifaydaService } from './verifayda.service';
import { PrismaModule } from '../../common/prisma.module';
import { AuthModule } from '../auth/auth.module';
@Module({
// AuthModule re-exports JwtModule, giving us JwtService (same secret/expiry
// config as /auth/login) to mint tokens for the LOGIN flow.
imports: [PrismaModule, AuthModule],
imports: [PrismaModule],
controllers: [VerifaydaController],
providers: [VerifaydaService],
exports: [VerifaydaService],

View File

@@ -1,5 +1,4 @@
import { ConfigService } from '@nestjs/config';
import { JwtService } from '@nestjs/jwt';
import { exportJWK, generateKeyPair, type JWK } from 'jose';
import { PrismaService } from '../../common/prisma.service';
import { FaydaConfig } from '../../config/fayda.config';
@@ -30,12 +29,6 @@ function buildPrismaMock() {
};
}
function buildJwtMock(): jest.Mocked<JwtService> {
return {
sign: jest.fn(() => 'signed.jwt.token'),
} as unknown as jest.Mocked<JwtService>;
}
function buildConfig(overrides?: Partial<FaydaConfig>): FaydaConfig {
return {
enabled: true,
@@ -65,7 +58,6 @@ function buildConfigService(faydaConfig: FaydaConfig): jest.Mocked<ConfigService
describe('VerifaydaService (OIDC, client-callback)', () => {
let prisma: ReturnType<typeof buildPrismaMock>;
let jwt: jest.Mocked<JwtService>;
let service: VerifaydaService;
let realPrivateJwk: JWK;
@@ -77,12 +69,10 @@ describe('VerifaydaService (OIDC, client-callback)', () => {
beforeEach(() => {
prisma = buildPrismaMock();
jwt = buildJwtMock();
const cfg = buildConfig({ privateJwk: realPrivateJwk as FaydaConfig['privateJwk'] });
service = new VerifaydaService(
buildConfigService(cfg),
prisma as unknown as PrismaService,
jwt,
);
(global as any).fetch = jest.fn();
});
@@ -136,7 +126,6 @@ describe('VerifaydaService (OIDC, client-callback)', () => {
const disabledService = new VerifaydaService(
buildConfigService(buildConfig({ enabled: false })),
prisma as unknown as PrismaService,
jwt,
);
await expect(
disabledService.startVerification({ purpose: 'PURCHASE' }),
@@ -433,7 +422,7 @@ describe('VerifaydaService (OIDC, client-callback)', () => {
prisma.faydaVerificationSession.findUnique.mockResolvedValue(loginSession());
});
it('creates a new user when no match and returns { token, user }', async () => {
it('creates a new user but rejects legacy local token issuance', async () => {
const fullUser = {
id: 'new-user',
email: 'new@example.com',
@@ -452,17 +441,12 @@ describe('VerifaydaService (OIDC, client-callback)', () => {
mockLoginFetch({ sub: 'login-sub-1', name: 'New Person', email: 'new@example.com' });
const result = await service.completeVerification({
await expect(
service.completeVerification({
code: 'c',
state: 'state-login',
});
expect(result).toMatchObject({
purpose: 'LOGIN',
verified: true,
token: 'signed.jwt.token',
user: { id: 'new-user', passengerId: 'p-new' },
});
}),
).rejects.toMatchObject({ status: 401 });
expect(prisma.user.create).toHaveBeenCalledWith(
expect.objectContaining({
data: expect.objectContaining({
@@ -473,12 +457,9 @@ describe('VerifaydaService (OIDC, client-callback)', () => {
}),
);
expect(prisma.passenger.create).toHaveBeenCalled();
expect(jwt.sign).toHaveBeenCalledWith(
expect.objectContaining({ sub: 'new-user', passengerId: 'p-new' }),
);
});
it('logs in an existing user already linked by faydaSub', async () => {
it('resolves an existing linked user but rejects legacy local token issuance', async () => {
const fullUser = {
id: 'known-user',
email: 'k@example.com',
@@ -491,16 +472,16 @@ describe('VerifaydaService (OIDC, client-callback)', () => {
mockLoginFetch({ sub: 'login-sub-2', name: 'Known' });
const result = await service.completeVerification({
await expect(
service.completeVerification({
code: 'c',
state: 'state-login',
});
expect(result.user?.id).toBe('known-user');
}),
).rejects.toMatchObject({ status: 401 });
expect(prisma.user.create).not.toHaveBeenCalled();
});
it('links Fayda to an existing account matched by email', async () => {
it('links Fayda to an existing account matched by email but rejects legacy local token issuance', async () => {
const fullUser = {
id: 'acc-1',
email: 'match@example.com',
@@ -515,12 +496,12 @@ describe('VerifaydaService (OIDC, client-callback)', () => {
mockLoginFetch({ sub: 'login-sub-3', email: 'match@example.com' });
const result = await service.completeVerification({
await expect(
service.completeVerification({
code: 'c',
state: 'state-login',
});
expect(result.user?.id).toBe('acc-1');
}),
).rejects.toMatchObject({ status: 401 });
expect(prisma.user.update).toHaveBeenCalledWith(
expect.objectContaining({
where: { id: 'acc-1' },

View File

@@ -6,7 +6,6 @@ import {
UnauthorizedException,
} from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { JwtService } from '@nestjs/jwt';
import axios, { AxiosInstance } from 'axios';
import * as bcrypt from 'bcrypt';
import { randomBytes } from 'crypto';
@@ -88,7 +87,6 @@ export class VerifaydaService {
constructor(
private readonly config: ConfigService,
private readonly prisma: PrismaService,
private readonly jwt: JwtService,
) {
const fayda = this.config.get<FaydaConfig>('fayda');
if (!fayda) {
@@ -274,16 +272,15 @@ export class VerifaydaService {
passengerId: user.passenger?.id,
agentId: user.agent?.id,
};
const token = this.jwt.sign({
sub: summary.id,
email: summary.email,
role: summary.role,
passengerId: summary.passengerId,
agentId: summary.agentId,
});
this.logger.log(`Fayda login issued token for user ${user.id}`);
return { token, user: summary };
this.logger.warn(
`Legacy passenger Fayda login reached for user ${user.id}; use IAM /v1/auth Fayda login to issue tokens.`,
);
throw new UnauthorizedException({
code: 'FAYDA_LOGIN_MIGRATED_TO_IAM',
message: 'Fayda login tokens are issued by the IAM package auth endpoints.',
user: summary,
});
}
async getVerificationStatus(userId: string): Promise<VerificationStatusDto> {

141
pnpm-lock.yaml generated
View File

@@ -69,11 +69,11 @@ importers:
specifier: ^8.1.0
version: 8.1.6
'@tria-plc/api-common':
specifier: ^0.1.4
version: 0.1.4(296a75716ddf658d3d4f5879ef7db3cb)
specifier: 1.2.3
version: 1.2.3(82de1fa22df14d2f8c974e73e7d5a000)
'@tria-plc/iamapi-common':
specifier: ^0.1.6
version: 0.1.6(efb6e02fa9b4108b3ff4c3ae477b6dad)
specifier: ^0.4.1
version: 0.4.1(c31a38bece4d321b4fae6a2e7e5e96b1)
amqp-connection-manager:
specifier: ^5.0.0
version: 5.0.0(amqplib@2.0.1)
@@ -1397,8 +1397,8 @@ packages:
'@tokenizer/token@0.3.0':
resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==}
'@tria-plc/api-common@0.1.4':
resolution: {integrity: sha512-lm9esp5PDxUyggqxYXbx2CQhZKwtcAaAcGFuuUURw3u5DlzGUNwMOFkQkDLM/fbgN+33+s1RKC7UynnG9NZFww==, tarball: https://npm.pkg.github.com/download/@tria-plc/api-common/0.1.4/de160e4bb61a882efd9c877b4614028f1ffd7cb8}
'@tria-plc/api-common@1.2.3':
resolution: {integrity: sha512-J30YmV/IAZjoQAB8o0yvisUwhclOWDdkqmLfVpvRc142Cv4nFnpynms+rO6IXSWwqI8bXRJg4qa+XauUrwzu5A==, tarball: https://npm.pkg.github.com/download/@tria-plc/api-common/1.2.3/7910a45187963d4a40ac0f7a6ab802fc974b708e}
peerDependencies:
'@nestjs/common': ^11.0.0
'@nestjs/core': ^11.0.0
@@ -1408,13 +1408,13 @@ packages:
'@nestjs/swagger': ^11.0.0
'@nestjs/throttler': ^6.0.0
'@nestjs/typeorm': ^11.0.0
'@tria-plc/iamapi-common': '*'
'@tria-plc/iamapi-common': ^0.1.0
reflect-metadata: ^0.2.0
rxjs: ^7.8.0
typeorm: ^0.3.0
'@tria-plc/iamapi-common@0.1.6':
resolution: {integrity: sha512-qaCLZ1TgbcQ5XciRuA/aZjRCM/GmGYgcmsyDDIlhiMNw3FL3DCiR/QiFuQpERvV4FqgQNBJg66+S/jXO3I2jbw==, tarball: https://npm.pkg.github.com/download/@tria-plc/iamapi-common/0.1.6/e2a8f3357b650bb9477facae4aaa7044382acebf}
'@tria-plc/iamapi-common@0.4.1':
resolution: {integrity: sha512-DnO9bCBGpo6wRt39zXzWuJG99qZ9yCy1x1DQOAs48G5Z9wwv/EYILXpb5dkoq/oV+c4If0UYSlKMnWQCv9RhVA==, tarball: https://npm.pkg.github.com/download/@tria-plc/iamapi-common/0.4.1/78c88f7322f9cb84a38941d94d1494b5ce6e2ddf}
engines: {node: '>=20'}
peerDependencies:
'@nestjs/axios': ^4.0.0
@@ -1426,7 +1426,7 @@ packages:
'@nestjs/swagger': ^11.0.0
'@nestjs/throttler': ^6.0.0
'@nestjs/typeorm': ^11.0.0
'@tria-plc/api-common': ^0.1.0
'@tria-plc/api-common': '*'
axios: ^1.9.0
class-transformer: ^0.5.1
class-validator: ^0.14.1
@@ -2128,6 +2128,9 @@ packages:
resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
engines: {node: '>= 8'}
api-common@1.2.2:
resolution: {integrity: sha512-2A3NpFNlOOvPY8Vq+g8Pokj6PdMk8fJpg58JpI/QuSXeB9JrS4YbRgzdexPBnJIUCNDHnjr+7S1vOsRRctHzyw==}
app-root-path@3.1.0:
resolution: {integrity: sha512-biN3PwB2gUtjaYy/isrU3aNWI5w+fAfvHkSvCKeQGxhmYpwKFUxudR3Yya+KqVRHBmEDYh+/lTozYCFbmzX4nA==}
engines: {node: '>= 6.0.0'}
@@ -2247,6 +2250,9 @@ packages:
resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==}
engines: {node: '>= 0.4'}
async@2.6.4:
resolution: {integrity: sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==}
async@3.2.6:
resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==}
@@ -2601,6 +2607,10 @@ packages:
colorette@2.0.20:
resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==}
colors@1.0.3:
resolution: {integrity: sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw==}
engines: {node: '>=0.1.90'}
combined-stream@1.0.8:
resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
engines: {node: '>= 0.8'}
@@ -2763,6 +2773,10 @@ packages:
csstype@3.2.3:
resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==}
cycle@1.0.3:
resolution: {integrity: sha512-TVF6svNzeQCOpjCqsy0/CSy8VgObG3wXusJ73xW2GbG5rGx7lC8zxDSURicsXI2UsGdi2L0QNRCi745/wUDvsA==}
engines: {node: '>=0.4.0'}
d3-array@3.2.4:
resolution: {integrity: sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==}
engines: {node: '>=12'}
@@ -3080,6 +3094,12 @@ packages:
resolution: {integrity: sha512-VyjaKxUmeDX/m2lxm/aknsJ1GWDWUO2Ze2Ad8S1Pb9dykAm9TjSKp5CjrNyltYqZ5W/PO6TInAmO2/BfwMyT1g==}
engines: {node: '>=0.10.0'}
error-tojson@0.0.1:
resolution: {integrity: sha512-zhtlVKgW0CgzltibgAlgi6oljh7L8k7jo61NuATFXodGMI2aiqAusW5FaiAtMcT8OLzdPkfhqh34I2XjxPI+Aw==}
errors@0.3.0:
resolution: {integrity: sha512-/4VTzspBdKkY8DE7VnjGYdHaSZdnQqQyOwYv3o2lwaKLhTvQmVATmoUCvFIFLVrn5kJqDHZl5ZltOu1Bit8rvg==}
es-abstract@1.24.2:
resolution: {integrity: sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==}
engines: {node: '>= 0.4'}
@@ -3336,6 +3356,10 @@ packages:
resolution: {integrity: sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==}
engines: {node: '>=0.10.0'}
eyes@0.1.8:
resolution: {integrity: sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ==}
engines: {node: '> 0.1.90'}
falsey@0.3.2:
resolution: {integrity: sha512-lxEuefF5MBIVDmE6XeqCdM4BWk1+vYmGZtkbKZ/VFcg6uBBw6fXNEbWmxCjDdQlFc9hy450nkiWwM3VAW6G1qg==}
engines: {node: '>=0.10.0'}
@@ -4072,6 +4096,9 @@ packages:
resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==}
engines: {node: '>=0.10.0'}
isstream@0.1.2:
resolution: {integrity: sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==}
istanbul-lib-coverage@3.2.2:
resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==}
engines: {node: '>=8'}
@@ -4347,6 +4374,9 @@ packages:
jws@4.0.1:
resolution: {integrity: sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==}
jwt-decode@2.2.0:
resolution: {integrity: sha512-86GgN2vzfUu7m9Wcj63iUkuDzFNYFVmjeDm2GzWpUk+opB0pEpMsw6ePCMrhYkumz2C1ihqtZzOMAg7FiXcNoQ==}
keyv@4.5.4:
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
@@ -4703,6 +4733,9 @@ packages:
resolution: {integrity: sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==}
engines: {node: '>=16 || 14 >=14.17'}
minimist@0.0.8:
resolution: {integrity: sha512-miQKw5Hv4NS1Psg2517mV4e4dYNaO3++hjAvLOAzKqZ61rH8NS1SK+vbfBWZ5PY/Me/bEWhUwqMghEW5Fb9T7Q==}
minimist@1.2.8:
resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
@@ -4730,6 +4763,11 @@ packages:
resolution: {integrity: sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==}
engines: {node: '>=0.10.0'}
mkdirp@0.5.1:
resolution: {integrity: sha512-SknJC52obPfGQPnjIkXbmA6+5H15E+fR+E4iR2oQ3zzCLbd7/ONua69R/Gw7AgkTLsRG+r5fzksYwWe1AgTyWA==}
deprecated: Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)
hasBin: true
mkdirp@0.5.6:
resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==}
hasBin: true
@@ -5137,6 +5175,10 @@ packages:
pkg-types@2.3.1:
resolution: {integrity: sha512-y+ichcgc2LrADuhLNAx8DFjVfgz91pRxfZdI3UDhxHvcVEZsenLO+7XaU5vOp0u/7V/wZ+plyuQxtrDlZJ+yeg==}
pkginfo@0.4.1:
resolution: {integrity: sha512-8xCNE/aT/EXKenuMDZ+xTVwkT8gsoHN2z/Q29l80u0ppGEXVvsKRzNMbtKhg8LS8k1tJLAHHylf6p4VFmP6XUQ==}
engines: {node: '>= 0.4.0'}
pluralize@8.0.0:
resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==}
engines: {node: '>=4'}
@@ -5601,6 +5643,9 @@ packages:
resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
engines: {node: '>=8'}
short-id-gen@1.1.2:
resolution: {integrity: sha512-rIxGIHcAhbf8jCgB6LYTeFC8jXffu4m0g+SXTljxGLkNhlMAq4jgQYPxvURtIX+tyqAx8YXuuh7j1qDVxJSZIA==}
side-channel-list@1.0.1:
resolution: {integrity: sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==}
engines: {node: '>= 0.4'}
@@ -5711,6 +5756,9 @@ packages:
stable-hash@0.0.5:
resolution: {integrity: sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==}
stack-trace@0.0.10:
resolution: {integrity: sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==}
stack-utils@2.0.6:
resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==}
engines: {node: '>=10'}
@@ -6397,6 +6445,15 @@ packages:
wide-align@1.1.5:
resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==}
winston-daily-rotate-file@1.7.2:
resolution: {integrity: sha512-bUkpSyWuDZVD2L7Ci/JrH09sIeqpwhQvmDrIAJ9PhUaewIbv9FTDTCvFnE2AFIIfDcTm7+AKiEKK4EP5lRL3fg==}
peerDependencies:
winston: 2.x
winston@2.4.7:
resolution: {integrity: sha512-vLB4BqzCKDnnZH9PHGoS2ycawueX4HLqENXQitvFHczhgW2vFpSOn31LZtVr1KU8YTw7DS4tM+cqyovxo8taVg==}
engines: {node: '>= 0.10.0'}
wmf@1.0.2:
resolution: {integrity: sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==}
engines: {node: '>=0.8'}
@@ -7690,7 +7747,7 @@ snapshots:
'@tokenizer/token@0.3.0': {}
'@tria-plc/api-common@0.1.4(296a75716ddf658d3d4f5879ef7db3cb)':
'@tria-plc/api-common@1.2.3(82de1fa22df14d2f8c974e73e7d5a000)':
dependencies:
'@nestjs/axios': 4.0.1(@nestjs/common@11.1.23(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(axios@1.16.1)(rxjs@7.8.2)
'@nestjs/common': 11.1.23(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2)
@@ -7701,7 +7758,7 @@ snapshots:
'@nestjs/swagger': 7.4.2(@nestjs/common@11.1.23(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.23)(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)
'@nestjs/throttler': 6.5.0(@nestjs/common@11.1.23(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.23)(reflect-metadata@0.2.2)
'@nestjs/typeorm': 11.0.1(@nestjs/common@11.1.23(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.23)(reflect-metadata@0.2.2)(rxjs@7.8.2)(typeorm@0.3.30(pg@8.21.0)(ts-node@10.9.2(@types/node@20.19.41)(typescript@5.9.3)))
'@tria-plc/iamapi-common': 0.1.6(efb6e02fa9b4108b3ff4c3ae477b6dad)
'@tria-plc/iamapi-common': 0.4.1(c31a38bece4d321b4fae6a2e7e5e96b1)
argon2: 0.43.1
axios: 1.16.1
change-case: 5.4.4
@@ -7734,7 +7791,7 @@ snapshots:
- debug
- supports-color
'@tria-plc/iamapi-common@0.1.6(efb6e02fa9b4108b3ff4c3ae477b6dad)':
'@tria-plc/iamapi-common@0.4.1(c31a38bece4d321b4fae6a2e7e5e96b1)':
dependencies:
'@nestjs/axios': 4.0.1(@nestjs/common@11.1.23(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(axios@1.16.1)(rxjs@7.8.2)
'@nestjs/common': 11.1.23(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2)
@@ -7745,7 +7802,8 @@ snapshots:
'@nestjs/swagger': 7.4.2(@nestjs/common@11.1.23(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.23)(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)
'@nestjs/throttler': 6.5.0(@nestjs/common@11.1.23(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.23)(reflect-metadata@0.2.2)
'@nestjs/typeorm': 11.0.1(@nestjs/common@11.1.23(class-transformer@0.5.1)(class-validator@0.14.4)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.23)(reflect-metadata@0.2.2)(rxjs@7.8.2)(typeorm@0.3.30(pg@8.21.0)(ts-node@10.9.2(@types/node@20.19.41)(typescript@5.9.3)))
'@tria-plc/api-common': 0.1.4(296a75716ddf658d3d4f5879ef7db3cb)
'@tria-plc/api-common': 1.2.3(82de1fa22df14d2f8c974e73e7d5a000)
api-common: 1.2.2
argon2: 0.43.1
axios: 1.16.1
class-transformer: 0.5.1
@@ -8495,6 +8553,17 @@ snapshots:
normalize-path: 3.0.0
picomatch: 2.3.2
api-common@1.2.2:
dependencies:
error-tojson: 0.0.1
errors: 0.3.0
jwt-decode: 2.2.0
moment: 2.30.1
pkginfo: 0.4.1
short-id-gen: 1.1.2
winston: 2.4.7
winston-daily-rotate-file: 1.7.2(winston@2.4.7)
app-root-path@3.1.0: {}
append-field@1.0.0: {}
@@ -8653,6 +8722,10 @@ snapshots:
async-function@1.0.0: {}
async@2.6.4:
dependencies:
lodash: 4.18.1
async@3.2.6: {}
asynckit@0.4.0: {}
@@ -9071,6 +9144,8 @@ snapshots:
colorette@2.0.20: {}
colors@1.0.3: {}
combined-stream@1.0.8:
dependencies:
delayed-stream: 1.0.0
@@ -9228,6 +9303,8 @@ snapshots:
csstype@3.2.3: {}
cycle@1.0.3: {}
d3-array@3.2.4:
dependencies:
internmap: 2.0.3
@@ -9490,6 +9567,10 @@ snapshots:
error-symbol@0.1.0: {}
error-tojson@0.0.1: {}
errors@0.3.0: {}
es-abstract@1.24.2:
dependencies:
array-buffer-byte-length: 1.0.2
@@ -9949,6 +10030,8 @@ snapshots:
transitivePeerDependencies:
- supports-color
eyes@0.1.8: {}
falsey@0.3.2:
dependencies:
kind-of: 5.1.0
@@ -10719,6 +10802,8 @@ snapshots:
isobject@3.0.1: {}
isstream@0.1.2: {}
istanbul-lib-coverage@3.2.2: {}
istanbul-lib-instrument@5.2.1:
@@ -11215,6 +11300,8 @@ snapshots:
jwa: 2.0.1
safe-buffer: 5.2.1
jwt-decode@2.2.0: {}
keyv@4.5.4:
dependencies:
json-buffer: 3.0.1
@@ -11545,6 +11632,8 @@ snapshots:
dependencies:
brace-expansion: 2.1.0
minimist@0.0.8: {}
minimist@1.2.8: {}
minio@7.1.3:
@@ -11582,6 +11671,10 @@ snapshots:
for-in: 1.0.2
is-extendable: 1.0.1
mkdirp@0.5.1:
dependencies:
minimist: 0.0.8
mkdirp@0.5.6:
dependencies:
minimist: 1.2.8
@@ -11990,6 +12083,8 @@ snapshots:
exsolve: 1.0.8
pathe: 2.0.3
pkginfo@0.4.1: {}
pluralize@8.0.0: {}
pngjs@5.0.0: {}
@@ -12481,6 +12576,8 @@ snapshots:
shebang-regex@3.0.0: {}
short-id-gen@1.1.2: {}
side-channel-list@1.0.1:
dependencies:
es-errors: 1.3.0
@@ -12598,6 +12695,8 @@ snapshots:
stable-hash@0.0.5: {}
stack-trace@0.0.10: {}
stack-utils@2.0.6:
dependencies:
escape-string-regexp: 2.0.0
@@ -13376,6 +13475,20 @@ snapshots:
dependencies:
string-width: 4.2.3
winston-daily-rotate-file@1.7.2(winston@2.4.7):
dependencies:
mkdirp: 0.5.1
winston: 2.4.7
winston@2.4.7:
dependencies:
async: 2.6.4
colors: 1.0.3
cycle: 1.0.3
eyes: 0.1.8
isstream: 0.1.2
stack-trace: 0.0.10
wmf@1.0.2: {}
word-wrap@1.2.5: {}