@solidxai/core 0.1.13-beta.18 → 0.1.13-beta.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/CHANGELOG.md +582 -0
  2. package/dist/config/cache.options.d.ts.map +1 -1
  3. package/dist/config/cache.options.js +2 -2
  4. package/dist/config/cache.options.js.map +1 -1
  5. package/dist/controllers/authentication.controller.d.ts +1 -1
  6. package/dist/controllers/authentication.controller.d.ts.map +1 -1
  7. package/dist/controllers/authentication.controller.js +4 -3
  8. package/dist/controllers/authentication.controller.js.map +1 -1
  9. package/dist/helpers/solid-microservice-adapter.service.d.ts.map +1 -1
  10. package/dist/helpers/solid-microservice-adapter.service.js +1 -1
  11. package/dist/helpers/solid-microservice-adapter.service.js.map +1 -1
  12. package/dist/interfaces/active-user-data.interface.d.ts +1 -0
  13. package/dist/interfaces/active-user-data.interface.d.ts.map +1 -1
  14. package/dist/interfaces/active-user-data.interface.js.map +1 -1
  15. package/dist/services/api-key.service.d.ts.map +1 -1
  16. package/dist/services/api-key.service.js +1 -1
  17. package/dist/services/api-key.service.js.map +1 -1
  18. package/dist/services/authentication.service.d.ts +5 -4
  19. package/dist/services/authentication.service.d.ts.map +1 -1
  20. package/dist/services/authentication.service.js +50 -19
  21. package/dist/services/authentication.service.js.map +1 -1
  22. package/dist/services/refresh-token-ids-storage.service.d.ts +25 -6
  23. package/dist/services/refresh-token-ids-storage.service.d.ts.map +1 -1
  24. package/dist/services/refresh-token-ids-storage.service.js +80 -42
  25. package/dist/services/refresh-token-ids-storage.service.js.map +1 -1
  26. package/package.json +2 -2
  27. package/src/config/cache.options.ts +9 -1
  28. package/src/controllers/authentication.controller.ts +5 -2
  29. package/src/helpers/solid-microservice-adapter.service.ts +6 -1
  30. package/src/interfaces/active-user-data.interface.ts +9 -0
  31. package/src/services/api-key.service.ts +13 -1
  32. package/src/services/authentication.service.ts +127 -36
  33. package/src/services/refresh-token-ids-storage.service.ts +229 -90
@@ -61,8 +61,8 @@ let AuthenticationController = AuthenticationController_1 = class Authentication
61
61
  me(activeUser) {
62
62
  return this.authService.me(activeUser);
63
63
  }
64
- async logout(refreshToken) {
65
- return this.authService.logout(refreshToken);
64
+ async logout(refreshToken, allDevices) {
65
+ return this.authService.logout(refreshToken, allDevices === true);
66
66
  }
67
67
  generateApiKey(dto, activeUser) {
68
68
  return this.apiKeyService.generate(activeUser.sub, dto);
@@ -169,8 +169,9 @@ __decorate([
169
169
  (0, common_1.HttpCode)(common_1.HttpStatus.OK),
170
170
  openapi.ApiResponse({ status: common_1.HttpStatus.OK }),
171
171
  __param(0, (0, common_1.Body)('refreshToken')),
172
+ __param(1, (0, common_1.Body)('allDevices')),
172
173
  __metadata("design:type", Function),
173
- __metadata("design:paramtypes", [String]),
174
+ __metadata("design:paramtypes", [String, Boolean]),
174
175
  __metadata("design:returntype", Promise)
175
176
  ], AuthenticationController.prototype, "logout", null);
176
177
  __decorate([
@@ -1 +1 @@
1
- {"version":3,"file":"authentication.controller.js","sourceRoot":"","sources":["../../src/controllers/authentication.controller.ts"],"names":[],"mappings":"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","sourcesContent":["import { Body, Controller, Get, HttpCode, HttpStatus, Logger, Param, ParseIntPipe, Patch, Post, Res, Headers } from '@nestjs/common';\nimport { ApiBearerAuth, ApiHeader, ApiTags } from '@nestjs/swagger';\nimport { Response } from 'express';\nimport { ActiveUser } from \"../decorators/active-user.decorator\";\nimport { Public } from '../decorators/public.decorator';\nimport { ChangePasswordDto } from \"../dtos/change-password.dto\";\nimport { ConfirmForgotPasswordDto } from '../dtos/confirm-forgot-password.dto';\nimport { CreateApiKeyDto } from '../dtos/create-api-key.dto';\nimport { UpdateApiKeyDto } from '../dtos/update-api-key.dto';\nimport { InitiateForgotPasswordDto } from '../dtos/initiate-forgot-password.dto';\nimport { RefreshTokenDto } from '../dtos/refresh-token.dto';\nimport { SsoExchangeDto } from '../dtos/sso-exchange.dto';\nimport { SignInDto } from '../dtos/sign-in.dto';\nimport { RegisterPrivateDto } from '../dtos/register-private.dto';\nimport { SignUpDto } from '../dtos/sign-up.dto';\nimport { ActiveUserData } from \"../interfaces/active-user-data.interface\";\nimport { ApiKeyService } from '../services/api-key.service';\nimport { AuthenticationService } from '../services/authentication.service';\n\n\n// @Auth(AuthType.None)\n@Controller('iam')\n@ApiTags(\"Solid Core\")\n// @UseGuards(ThrottlerGuard)\n// @SkipThrottle({login: true, short: true, burst: true, sustained: true}) // disable all sets by default for this controller\nexport class AuthenticationController {\n private readonly logger = new Logger(AuthenticationController.name);\n\n constructor(\n private readonly authService: AuthenticationService,\n private readonly apiKeyService: ApiKeyService,\n ) { }\n\n @Public()\n // @SkipThrottle({ login: false, short: true, burst: true, sustained: true }) //Enable the login throttle only\n @Post('register')\n signUp(@Body() signUpDto: SignUpDto) {\n return this.authService.signUp(signUpDto);\n }\n\n @ApiBearerAuth(\"jwt\")\n @Post('register-private')\n signUpPrivate(@Body() signUpDto: RegisterPrivateDto, @ActiveUser() activeUser: ActiveUserData) {\n return this.authService.signUp(signUpDto, activeUser);\n }\n\n @Public()\n // @SkipThrottle({ login: false, short: true, burst: true, sustained: true }) //Enable the login throttle only\n @HttpCode(HttpStatus.OK) // by default @Post does 201, we wanted 200 - hence using @HttpCode(HttpStatus.OK)\n @Post('authenticate')\n async signIn(\n @Res({ passthrough: true }) response: Response,\n @Body() signInDto: SignInDto\n ) {\n // This means that we are passing the token back in plain text. \n // This is less secure. \n // console.log(\"signInDto in Signin Controller\", signInDto);\n\n return this.authService.signIn(signInDto);\n\n // This means we are setting the token as a http only cookie.\n // const accessToken = await this.authService.signIn(signInDto);\n // response.cookie('accessToken', accessToken, {\n // secure: true,\n // httpOnly: true,\n // sameSite: true,\n // });\n }\n\n @Public()\n // @SkipThrottle({ login: false, short: true, burst: true, sustained: true }) //Enable the login throttle only\n @HttpCode(HttpStatus.OK) // changed since the default is 201\n @Post('refresh-tokens')\n refreshTokens(@Body() refreshTokenDto: RefreshTokenDto) {\n return this.authService.refreshTokens(refreshTokenDto);\n }\n\n @Public()\n // @SkipThrottle({ login: false, short: true, burst: true, sustained: true }) //Enable the login throttle only\n @Post('initiate/forgot-password')\n initiateForgotPassword(@Body() initiateForgotPasswordDto: InitiateForgotPasswordDto) {\n return this.authService.initiateForgotPassword(initiateForgotPasswordDto);\n }\n\n @Public()\n // @SkipThrottle({ login: false, short: true, burst: true, sustained: true }) //Enable the login throttle only\n @Post('confirm/forgot-password')\n confirmForgotPassword(@Body() confirmForgotPasswordDto: ConfirmForgotPasswordDto) {\n return this.authService.confirmForgotPassword(confirmForgotPasswordDto);\n }\n\n @ApiBearerAuth(\"jwt\")\n @Post('change-password')\n changePassword(@Body() changePasswordDto: ChangePasswordDto, @ActiveUser() activeUser: ActiveUserData) {\n return this.authService.changePassword(changePasswordDto, activeUser);\n }\n\n @ApiBearerAuth(\"jwt\")\n @Get('me')\n me(\n @ActiveUser() activeUser: ActiveUserData\n ) {\n return this.authService.me(activeUser);\n }\n\n @ApiBearerAuth(\"jwt\")\n @Post('logout')\n @Public()\n @HttpCode(HttpStatus.OK)\n async logout(@Body('refreshToken') refreshToken: string) {\n return this.authService.logout(refreshToken);\n }\n\n @ApiBearerAuth(\"jwt\")\n @Post('api-keys')\n @HttpCode(HttpStatus.CREATED)\n generateApiKey(\n @Body() dto: CreateApiKeyDto,\n @ActiveUser() activeUser: ActiveUserData,\n ) {\n return this.apiKeyService.generate(activeUser.sub, dto);\n }\n\n @ApiBearerAuth(\"jwt\")\n @Post('api-keys/users/:userId')\n @HttpCode(HttpStatus.CREATED)\n generateApiKeyForUser(\n @Param('userId', ParseIntPipe) userId: number,\n @Body() dto: CreateApiKeyDto,\n ) {\n return this.apiKeyService.generate(userId, dto);\n }\n\n @ApiBearerAuth(\"jwt\")\n @Patch('api-keys/:id')\n @HttpCode(HttpStatus.OK)\n updateApiKey(\n @Param('id', ParseIntPipe) id: number,\n @Body() dto: UpdateApiKeyDto,\n @ActiveUser() activeUser: ActiveUserData,\n ) {\n return this.apiKeyService.updateKey(id, activeUser.sub, dto);\n }\n\n @Public()\n @ApiHeader({ name: 'solidx-api-key', required: true, description: 'API key for authenticating the request' })\n @Get('api-keys/me')\n async apiKeyMe(@Headers('solidx-api-key') apiKey: string) {\n return this.apiKeyService.apiKeyMe(apiKey);\n }\n\n @Post('sso/code')\n @HttpCode(HttpStatus.OK)\n generateSsoCode(\n @ActiveUser() activeUser: ActiveUserData, \n @Headers('authorization') authorization: string,\n ) {\n const rawAccessToken = authorization?.replace(/^Bearer\\s+/i, '');\n return this.authService.generateSsoCode(activeUser, rawAccessToken);\n }\n\n @Public()\n @Post('sso/exchange')\n @HttpCode(HttpStatus.OK)\n exchangeSsoCode(@Body() ssoExchangeDto: SsoExchangeDto) {\n return this.authService.exchangeSsoCode(ssoExchangeDto.code);\n }\n}\n"]}
1
+ {"version":3,"file":"authentication.controller.js","sourceRoot":"","sources":["../../src/controllers/authentication.controller.ts"],"names":[],"mappings":"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","sourcesContent":["import { Body, Controller, Get, HttpCode, HttpStatus, Logger, Param, ParseIntPipe, Patch, Post, Res, Headers } from '@nestjs/common';\nimport { ApiBearerAuth, ApiHeader, ApiTags } from '@nestjs/swagger';\nimport { Response } from 'express';\nimport { ActiveUser } from \"../decorators/active-user.decorator\";\nimport { Public } from '../decorators/public.decorator';\nimport { ChangePasswordDto } from \"../dtos/change-password.dto\";\nimport { ConfirmForgotPasswordDto } from '../dtos/confirm-forgot-password.dto';\nimport { CreateApiKeyDto } from '../dtos/create-api-key.dto';\nimport { UpdateApiKeyDto } from '../dtos/update-api-key.dto';\nimport { InitiateForgotPasswordDto } from '../dtos/initiate-forgot-password.dto';\nimport { RefreshTokenDto } from '../dtos/refresh-token.dto';\nimport { SsoExchangeDto } from '../dtos/sso-exchange.dto';\nimport { SignInDto } from '../dtos/sign-in.dto';\nimport { RegisterPrivateDto } from '../dtos/register-private.dto';\nimport { SignUpDto } from '../dtos/sign-up.dto';\nimport { ActiveUserData } from \"../interfaces/active-user-data.interface\";\nimport { ApiKeyService } from '../services/api-key.service';\nimport { AuthenticationService } from '../services/authentication.service';\n\n\n// @Auth(AuthType.None)\n@Controller('iam')\n@ApiTags(\"Solid Core\")\n// @UseGuards(ThrottlerGuard)\n// @SkipThrottle({login: true, short: true, burst: true, sustained: true}) // disable all sets by default for this controller\nexport class AuthenticationController {\n private readonly logger = new Logger(AuthenticationController.name);\n\n constructor(\n private readonly authService: AuthenticationService,\n private readonly apiKeyService: ApiKeyService,\n ) { }\n\n @Public()\n // @SkipThrottle({ login: false, short: true, burst: true, sustained: true }) //Enable the login throttle only\n @Post('register')\n signUp(@Body() signUpDto: SignUpDto) {\n return this.authService.signUp(signUpDto);\n }\n\n @ApiBearerAuth(\"jwt\")\n @Post('register-private')\n signUpPrivate(@Body() signUpDto: RegisterPrivateDto, @ActiveUser() activeUser: ActiveUserData) {\n return this.authService.signUp(signUpDto, activeUser);\n }\n\n @Public()\n // @SkipThrottle({ login: false, short: true, burst: true, sustained: true }) //Enable the login throttle only\n @HttpCode(HttpStatus.OK) // by default @Post does 201, we wanted 200 - hence using @HttpCode(HttpStatus.OK)\n @Post('authenticate')\n async signIn(\n @Res({ passthrough: true }) response: Response,\n @Body() signInDto: SignInDto\n ) {\n // This means that we are passing the token back in plain text. \n // This is less secure. \n // console.log(\"signInDto in Signin Controller\", signInDto);\n\n return this.authService.signIn(signInDto);\n\n // This means we are setting the token as a http only cookie.\n // const accessToken = await this.authService.signIn(signInDto);\n // response.cookie('accessToken', accessToken, {\n // secure: true,\n // httpOnly: true,\n // sameSite: true,\n // });\n }\n\n @Public()\n // @SkipThrottle({ login: false, short: true, burst: true, sustained: true }) //Enable the login throttle only\n @HttpCode(HttpStatus.OK) // changed since the default is 201\n @Post('refresh-tokens')\n refreshTokens(@Body() refreshTokenDto: RefreshTokenDto) {\n return this.authService.refreshTokens(refreshTokenDto);\n }\n\n @Public()\n // @SkipThrottle({ login: false, short: true, burst: true, sustained: true }) //Enable the login throttle only\n @Post('initiate/forgot-password')\n initiateForgotPassword(@Body() initiateForgotPasswordDto: InitiateForgotPasswordDto) {\n return this.authService.initiateForgotPassword(initiateForgotPasswordDto);\n }\n\n @Public()\n // @SkipThrottle({ login: false, short: true, burst: true, sustained: true }) //Enable the login throttle only\n @Post('confirm/forgot-password')\n confirmForgotPassword(@Body() confirmForgotPasswordDto: ConfirmForgotPasswordDto) {\n return this.authService.confirmForgotPassword(confirmForgotPasswordDto);\n }\n\n @ApiBearerAuth(\"jwt\")\n @Post('change-password')\n changePassword(@Body() changePasswordDto: ChangePasswordDto, @ActiveUser() activeUser: ActiveUserData) {\n return this.authService.changePassword(changePasswordDto, activeUser);\n }\n\n @ApiBearerAuth(\"jwt\")\n @Get('me')\n me(\n @ActiveUser() activeUser: ActiveUserData\n ) {\n return this.authService.me(activeUser);\n }\n\n @ApiBearerAuth(\"jwt\")\n @Post('logout')\n @Public()\n @HttpCode(HttpStatus.OK)\n async logout(\n @Body('refreshToken') refreshToken: string,\n @Body('allDevices') allDevices?: boolean,\n ) {\n return this.authService.logout(refreshToken, allDevices === true);\n }\n\n @ApiBearerAuth(\"jwt\")\n @Post('api-keys')\n @HttpCode(HttpStatus.CREATED)\n generateApiKey(\n @Body() dto: CreateApiKeyDto,\n @ActiveUser() activeUser: ActiveUserData,\n ) {\n return this.apiKeyService.generate(activeUser.sub, dto);\n }\n\n @ApiBearerAuth(\"jwt\")\n @Post('api-keys/users/:userId')\n @HttpCode(HttpStatus.CREATED)\n generateApiKeyForUser(\n @Param('userId', ParseIntPipe) userId: number,\n @Body() dto: CreateApiKeyDto,\n ) {\n return this.apiKeyService.generate(userId, dto);\n }\n\n @ApiBearerAuth(\"jwt\")\n @Patch('api-keys/:id')\n @HttpCode(HttpStatus.OK)\n updateApiKey(\n @Param('id', ParseIntPipe) id: number,\n @Body() dto: UpdateApiKeyDto,\n @ActiveUser() activeUser: ActiveUserData,\n ) {\n return this.apiKeyService.updateKey(id, activeUser.sub, dto);\n }\n\n @Public()\n @ApiHeader({ name: 'solidx-api-key', required: true, description: 'API key for authenticating the request' })\n @Get('api-keys/me')\n async apiKeyMe(@Headers('solidx-api-key') apiKey: string) {\n return this.apiKeyService.apiKeyMe(apiKey);\n }\n\n @Post('sso/code')\n @HttpCode(HttpStatus.OK)\n generateSsoCode(\n @ActiveUser() activeUser: ActiveUserData, \n @Headers('authorization') authorization: string,\n ) {\n const rawAccessToken = authorization?.replace(/^Bearer\\s+/i, '');\n return this.authService.generateSsoCode(activeUser, rawAccessToken);\n }\n\n @Public()\n @Post('sso/exchange')\n @HttpCode(HttpStatus.OK)\n exchangeSsoCode(@Body() ssoExchangeDto: SsoExchangeDto) {\n return this.authService.exchangeSsoCode(ssoExchangeDto.code);\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"solid-microservice-adapter.service.d.ts","sourceRoot":"","sources":["../../src/helpers/solid-microservice-adapter.service.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAEtC,MAAM,WAAW,oBAAoB;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,mBAAmB,EAAE,OAAO,CAAC;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,aAAa,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,iBAAiB,CAAC;CACzB;AAED,qBACa,wBAAwB;IAIA,OAAO,CAAC,QAAQ,CAAC,YAAY;IAHhE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA6C;IACpE,OAAO,CAAC,OAAO,CAAC,CAAS;gBAE2B,YAAY,EAAE,KAAK;IAEvE,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAK3B,YAAY,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,oBAAoB,GAAG,OAAO,CAAC,qBAAqB,CAAC;IA0CvG,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,gBAAgB;IAgBxB,OAAO,CAAC,iBAAiB;CAK1B"}
1
+ {"version":3,"file":"solid-microservice-adapter.service.d.ts","sourceRoot":"","sources":["../../src/helpers/solid-microservice-adapter.service.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAEtC,MAAM,WAAW,oBAAoB;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,mBAAmB,EAAE,OAAO,CAAC;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,aAAa,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,iBAAiB,CAAC;CACzB;AAED,qBACa,wBAAwB;IAIA,OAAO,CAAC,QAAQ,CAAC,YAAY;IAHhE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA6C;IACpE,OAAO,CAAC,OAAO,CAAC,CAAS;gBAE2B,YAAY,EAAE,KAAK;IAEvE,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAK3B,YAAY,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,oBAAoB,GAAG,OAAO,CAAC,qBAAqB,CAAC;IA+CvG,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,gBAAgB;IAgBxB,OAAO,CAAC,iBAAiB;CAK1B"}
@@ -61,7 +61,7 @@ let SolidMicroserviceAdapter = SolidMicroserviceAdapter_1 = class SolidMicroserv
61
61
  const responseData = response.data;
62
62
  const ttlSeconds = this.getJwtTtlSeconds(responseData?.data?.accessToken);
63
63
  if (ttlSeconds && ttlSeconds > 0) {
64
- await this.cacheManager.set(cacheKey, responseData, ttlSeconds);
64
+ await this.cacheManager.set(cacheKey, responseData, ttlSeconds * 1000);
65
65
  }
66
66
  return responseData;
67
67
  }
@@ -1 +1 @@
1
- {"version":3,"file":"solid-microservice-adapter.service.js","sourceRoot":"","sources":["../../src/helpers/solid-microservice-adapter.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;AAAA,yDAAsD;AACtD,2CAAmE;AACnE,kDAA0B;AAgCnB,IAAM,wBAAwB,gCAA9B,MAAM,wBAAwB;IAInC,YAAmC,YAAoC;QAAnB,iBAAY,GAAZ,YAAY,CAAO;QAHtD,WAAM,GAAG,IAAI,eAAM,CAAC,0BAAwB,CAAC,IAAI,CAAC,CAAC;IAGM,CAAC;IAE3E,UAAU,CAAC,OAAe;QACxB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAwB;QACpE,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;QACjE,CAAC;QACD,IAAI,CAAC,KAAK,IAAI,CAAC,QAAQ,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;QAC1E,CAAC;QAED,MAAM,QAAQ,GAAG,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;QACvD,MAAM,cAAc,GAAG,CAAC,MAAM,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAsC,CAAC;QACpG,IAAI,cAAc,EAAE,CAAC;YACnB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,0BAA0B,QAAQ,EAAE,CAAC,CAAC;YACxD,OAAO,cAAc,CAAC;QACxB,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,2BAA2B,QAAQ,EAAE,CAAC,CAAC;QAEzD,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;QACnE,CAAC;QAED,MAAM,OAAO,GAAyB,EAAE,QAAQ,EAAE,CAAC;QACnD,IAAI,KAAK;YAAE,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC;QACjC,IAAI,QAAQ;YAAE,OAAO,CAAC,QAAQ,GAAG,QAAQ,CAAC;QAE1C,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,oCAAoC,IAAI,CAAC,OAAO,uBAAuB,CAAC,CAAC;QAE3F,MAAM,QAAQ,GAAG,MAAM,eAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,OAAO,uBAAuB,EAAE,OAAO,EAAE;YACjF,OAAO,EAAE,KAAK;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;aACnC;SACF,CAAC,CAAC;QAEH,MAAM,YAAY,GAAG,QAAQ,CAAC,IAA6B,CAAC;QAC5D,MAAM,UAAU,GAAG,IAAI,CAAC,gBAAgB,CAAC,YAAY,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC;QAC1E,IAAI,UAAU,IAAI,UAAU,GAAG,CAAC,EAAE,CAAC;YACjC,MAAM,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,EAAE,YAAY,EAAE,UAAU,CAAC,CAAC;QAClE,CAAC;QAED,OAAO,YAAY,CAAC;IACtB,CAAC;IAEO,eAAe,CAAC,KAAc,EAAE,QAAiB;QACvD,OAAO,YAAY,KAAK,IAAI,EAAE,IAAI,QAAQ,IAAI,EAAE,EAAE,CAAC;IACrD,CAAC;IAEO,gBAAgB,CAAC,WAAoB;QAC3C,IAAI,CAAC,WAAW;YAAE,OAAO,SAAS,CAAC;QACnC,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACrC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,SAAS,CAAC;QACvC,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YAC9F,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAqB,CAAC;YAC5D,IAAI,CAAC,OAAO,EAAE,GAAG,IAAI,OAAO,OAAO,CAAC,GAAG,KAAK,QAAQ;gBAAE,OAAO,SAAS,CAAC;YACvE,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;YACjD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,GAAG,UAAU,GAAG,EAAE,CAAC;YAC1C,OAAO,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;QACnC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,SAAS,CAAC;QACnB,CAAC;IACH,CAAC;IAEO,iBAAiB,CAAC,KAAa;QACrC,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QAC/D,MAAM,SAAS,GAAG,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QACpD,OAAO,UAAU,GAAG,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAC5C,CAAC;CACF,CAAA;AA9EY,4DAAwB;mCAAxB,wBAAwB;IADpC,IAAA,mBAAU,EAAC,EAAE,KAAK,EAAE,cAAK,CAAC,SAAS,EAAE,CAAC;IAKxB,WAAA,IAAA,eAAM,EAAC,6BAAa,CAAC,CAAA;;GAJvB,wBAAwB,CA8EpC","sourcesContent":["import { CACHE_MANAGER } from '@nestjs/cache-manager';\nimport { Inject, Injectable, Logger, Scope } from '@nestjs/common';\nimport axios from 'axios';\nimport { Cache } from 'cache-manager';\n\nexport interface SolidxIamAuthRequest {\n email?: string;\n username?: string;\n password: string;\n}\n\nexport interface SolidxIamUser {\n email: string;\n mobile: string;\n username: string;\n forcePasswordChange: boolean;\n id: number;\n roles: string[];\n}\n\nexport interface SolidxIamAuthData {\n user: SolidxIamUser;\n accessToken: string;\n refreshToken: string;\n}\n\nexport interface SolidxIamAuthResponse {\n statusCode: number;\n message: string[];\n error: string;\n data: SolidxIamAuthData;\n}\n\n@Injectable({ scope: Scope.TRANSIENT })\nexport class SolidMicroserviceAdapter {\n private readonly logger = new Logger(SolidMicroserviceAdapter.name);\n private baseUrl?: string;\n\n constructor(@Inject(CACHE_MANAGER) private readonly cacheManager: Cache) {}\n\n setBaseUrl(baseUrl: string): this {\n this.baseUrl = baseUrl;\n return this;\n }\n\n async authenticate({ email, username, password }: SolidxIamAuthRequest): Promise<SolidxIamAuthResponse> {\n if (!password) {\n throw new Error('password is required for IAM authentication');\n }\n if (!email && !username) {\n throw new Error('email or username is required for IAM authentication');\n }\n\n const cacheKey = this.getAuthCacheKey(email, username);\n const cachedResponse = (await this.cacheManager.get(cacheKey)) as SolidxIamAuthResponse | undefined;\n if (cachedResponse) {\n this.logger.debug(`IAM auth cache hit for ${cacheKey}`);\n return cachedResponse;\n }\n this.logger.debug(`IAM auth cache miss for ${cacheKey}`);\n\n if (!this.baseUrl) {\n throw new Error('baseUrl must be set before IAM authentication');\n }\n\n const payload: SolidxIamAuthRequest = { password };\n if (email) payload.email = email;\n if (username) payload.username = username;\n\n this.logger.debug(`Requesting IAM access token from ${this.baseUrl}/api/iam/authenticate`);\n\n const response = await axios.post(`${this.baseUrl}/api/iam/authenticate`, payload, {\n timeout: 10000,\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n\n const responseData = response.data as SolidxIamAuthResponse;\n const ttlSeconds = this.getJwtTtlSeconds(responseData?.data?.accessToken);\n if (ttlSeconds && ttlSeconds > 0) {\n await this.cacheManager.set(cacheKey, responseData, ttlSeconds);\n }\n\n return responseData;\n }\n\n private getAuthCacheKey(email?: string, username?: string): string {\n return `iam-auth:${email ?? ''}:${username ?? ''}`;\n }\n\n private getJwtTtlSeconds(accessToken?: string): number | undefined {\n if (!accessToken) return undefined;\n const parts = accessToken.split('.');\n if (parts.length < 2) return undefined;\n try {\n const payloadJson = Buffer.from(this.base64UrlToBase64(parts[1]), 'base64').toString('utf-8');\n const payload = JSON.parse(payloadJson) as { exp?: number };\n if (!payload?.exp || typeof payload.exp !== 'number') return undefined;\n const nowSeconds = Math.floor(Date.now() / 1000);\n const ttl = payload.exp - nowSeconds - 10;\n return ttl > 0 ? ttl : undefined;\n } catch {\n return undefined;\n }\n }\n\n private base64UrlToBase64(value: string): string {\n const normalized = value.replace(/-/g, '+').replace(/_/g, '/');\n const padLength = (4 - (normalized.length % 4)) % 4;\n return normalized + '='.repeat(padLength);\n }\n}\n"]}
1
+ {"version":3,"file":"solid-microservice-adapter.service.js","sourceRoot":"","sources":["../../src/helpers/solid-microservice-adapter.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { CACHE_MANAGER } from '@nestjs/cache-manager';\nimport { Inject, Injectable, Logger, Scope } from '@nestjs/common';\nimport axios from 'axios';\nimport { Cache } from 'cache-manager';\n\nexport interface SolidxIamAuthRequest {\n email?: string;\n username?: string;\n password: string;\n}\n\nexport interface SolidxIamUser {\n email: string;\n mobile: string;\n username: string;\n forcePasswordChange: boolean;\n id: number;\n roles: string[];\n}\n\nexport interface SolidxIamAuthData {\n user: SolidxIamUser;\n accessToken: string;\n refreshToken: string;\n}\n\nexport interface SolidxIamAuthResponse {\n statusCode: number;\n message: string[];\n error: string;\n data: SolidxIamAuthData;\n}\n\n@Injectable({ scope: Scope.TRANSIENT })\nexport class SolidMicroserviceAdapter {\n private readonly logger = new Logger(SolidMicroserviceAdapter.name);\n private baseUrl?: string;\n\n constructor(@Inject(CACHE_MANAGER) private readonly cacheManager: Cache) {}\n\n setBaseUrl(baseUrl: string): this {\n this.baseUrl = baseUrl;\n return this;\n }\n\n async authenticate({ email, username, password }: SolidxIamAuthRequest): Promise<SolidxIamAuthResponse> {\n if (!password) {\n throw new Error('password is required for IAM authentication');\n }\n if (!email && !username) {\n throw new Error('email or username is required for IAM authentication');\n }\n\n const cacheKey = this.getAuthCacheKey(email, username);\n const cachedResponse = (await this.cacheManager.get(cacheKey)) as SolidxIamAuthResponse | undefined;\n if (cachedResponse) {\n this.logger.debug(`IAM auth cache hit for ${cacheKey}`);\n return cachedResponse;\n }\n this.logger.debug(`IAM auth cache miss for ${cacheKey}`);\n\n if (!this.baseUrl) {\n throw new Error('baseUrl must be set before IAM authentication');\n }\n\n const payload: SolidxIamAuthRequest = { password };\n if (email) payload.email = email;\n if (username) payload.username = username;\n\n this.logger.debug(`Requesting IAM access token from ${this.baseUrl}/api/iam/authenticate`);\n\n const response = await axios.post(`${this.baseUrl}/api/iam/authenticate`, payload, {\n timeout: 10000,\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n\n const responseData = response.data as SolidxIamAuthResponse;\n const ttlSeconds = this.getJwtTtlSeconds(responseData?.data?.accessToken);\n if (ttlSeconds && ttlSeconds > 0) {\n // cache-manager v5 expects milliseconds. This previously passed seconds,\n // which the old Redis store discarded outright - so the entry simply\n // never expired. Now that TTLs are honoured, passing seconds unconverted\n // would expire the cached token ~1000x too early and re-authenticate\n // against IAM on nearly every call.\n await this.cacheManager.set(cacheKey, responseData, ttlSeconds * 1000);\n }\n\n return responseData;\n }\n\n private getAuthCacheKey(email?: string, username?: string): string {\n return `iam-auth:${email ?? ''}:${username ?? ''}`;\n }\n\n private getJwtTtlSeconds(accessToken?: string): number | undefined {\n if (!accessToken) return undefined;\n const parts = accessToken.split('.');\n if (parts.length < 2) return undefined;\n try {\n const payloadJson = Buffer.from(this.base64UrlToBase64(parts[1]), 'base64').toString('utf-8');\n const payload = JSON.parse(payloadJson) as { exp?: number };\n if (!payload?.exp || typeof payload.exp !== 'number') return undefined;\n const nowSeconds = Math.floor(Date.now() / 1000);\n const ttl = payload.exp - nowSeconds - 10;\n return ttl > 0 ? ttl : undefined;\n } catch {\n return undefined;\n }\n }\n\n private base64UrlToBase64(value: string): string {\n const normalized = value.replace(/-/g, '+').replace(/_/g, '/');\n const padLength = (4 - (normalized.length % 4)) % 4;\n return normalized + '='.repeat(padLength);\n }\n}\n"]}
@@ -3,6 +3,7 @@ export interface ActiveUserData {
3
3
  username: string;
4
4
  email: string;
5
5
  sessionId?: string;
6
+ deviceKey?: string;
6
7
  roles: string[];
7
8
  permissions: string[];
8
9
  }
@@ -1 +1 @@
1
- {"version":3,"file":"active-user-data.interface.d.ts","sourceRoot":"","sources":["../../src/interfaces/active-user-data.interface.ts"],"names":[],"mappings":"AACA,MAAM,WAAW,cAAc;IAK7B,GAAG,EAAE,MAAM,CAAC;IAKZ,QAAQ,EAAE,MAAM,CAAC;IAKjB,KAAK,EAAE,MAAM,CAAC;IAMd,SAAS,CAAC,EAAE,MAAM,CAAC;IAMnB,KAAK,EAAE,MAAM,EAAE,CAAC;IAOhB,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB"}
1
+ {"version":3,"file":"active-user-data.interface.d.ts","sourceRoot":"","sources":["../../src/interfaces/active-user-data.interface.ts"],"names":[],"mappings":"AACA,MAAM,WAAW,cAAc;IAK7B,GAAG,EAAE,MAAM,CAAC;IAKZ,QAAQ,EAAE,MAAM,CAAC;IAKjB,KAAK,EAAE,MAAM,CAAC;IAMd,SAAS,CAAC,EAAE,MAAM,CAAC;IASnB,SAAS,CAAC,EAAE,MAAM,CAAC;IAMnB,KAAK,EAAE,MAAM,EAAE,CAAC;IAOhB,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB"}
@@ -1 +1 @@
1
- {"version":3,"file":"active-user-data.interface.js","sourceRoot":"","sources":["../../src/interfaces/active-user-data.interface.ts"],"names":[],"mappings":"","sourcesContent":["\nexport interface ActiveUserData {\n /**\n * The \"subject\" of the token. The value of this property is the user ID\n * that granted this token.\n */\n sub: number;\n\n /**\n * The subject's (user) username.\n */\n username: string;\n\n /**\n * The subject's (user) email.\n */\n email: string;\n\n /**\n * Logical login session identifier used to invalidate older sessions when\n * concurrent logins are disabled.\n */\n sessionId?: string;\n\n /**\n * The subject's (user) roles.\n * These are part of the JWT token, we simply decode them.\n */\n roles: string[];\n\n /**\n * The subject's (user) permissions.\n * These are not part of the JWT token, we query them from the database each time the access-token guard is run. \n * So basically each time an authenticated request is initiated, we end up loading all the users permissions.\n */\n permissions: string[];\n}\n"]}
1
+ {"version":3,"file":"active-user-data.interface.js","sourceRoot":"","sources":["../../src/interfaces/active-user-data.interface.ts"],"names":[],"mappings":"","sourcesContent":["\nexport interface ActiveUserData {\n /**\n * The \"subject\" of the token. The value of this property is the user ID\n * that granted this token.\n */\n sub: number;\n\n /**\n * The subject's (user) username.\n */\n username: string;\n\n /**\n * The subject's (user) email.\n */\n email: string;\n\n /**\n * Logical login session identifier used to invalidate older sessions when\n * concurrent logins are disabled.\n */\n sessionId?: string;\n\n /**\n * Identifies which per-device refresh-token bucket this session belongs to.\n * Present only while concurrent logins are permitted; mutually exclusive with\n * sessionId, which exists only when they are not. Carried on the access token\n * so bearer-authenticated endpoints that need this session's refresh token\n * can find it.\n */\n deviceKey?: string;\n\n /**\n * The subject's (user) roles.\n * These are part of the JWT token, we simply decode them.\n */\n roles: string[];\n\n /**\n * The subject's (user) permissions.\n * These are not part of the JWT token, we query them from the database each time the access-token guard is run. \n * So basically each time an authenticated request is initiated, we end up loading all the users permissions.\n */\n permissions: string[];\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"api-key.service.d.ts","sourceRoot":"","sources":["../../src/services/api-key.service.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAE,MAAM,kCAAkC,CAAC;AAE9D,OAAO,EAAE,cAAc,EAAE,MAAM,2CAA2C,CAAC;AAC3E,OAAO,EAAE,oBAAoB,EAAE,MAAM,wCAAwC,CAAC;AAC9E,OAAO,EAAE,yBAAyB,EAAE,MAAM,0CAA0C,CAAC;AACrF,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAEhE,qBACa,aAAa;IAIlB,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IACjC,OAAO,CAAC,QAAQ,CAAC,yBAAyB;IAC1C,OAAO,CAAC,QAAQ,CAAC,qBAAqB;IACtC,OAAO,CAAC,QAAQ,CAAC,cAAc;IANnC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkC;gBAGpC,gBAAgB,EAAE,oBAAoB,EACtC,yBAAyB,EAAE,yBAAyB,EACpD,qBAAqB,EAAE,qBAAqB,EAC5C,cAAc,EAAE,cAAc;IAG7C,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,UAAU,CAAA;KAAE,CAAC;IA+B/F,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAkCjD,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAkB1E,QAAQ,CAAC,MAAM,EAAE,MAAM;;;;;;;;;;;;IAoC7B,OAAO,CAAC,IAAI;CAGf"}
1
+ {"version":3,"file":"api-key.service.d.ts","sourceRoot":"","sources":["../../src/services/api-key.service.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,UAAU,EAAE,MAAM,kCAAkC,CAAC;AAE9D,OAAO,EAAE,cAAc,EAAE,MAAM,2CAA2C,CAAC;AAC3E,OAAO,EAAE,oBAAoB,EAAE,MAAM,wCAAwC,CAAC;AAC9E,OAAO,EAAE,yBAAyB,EAAE,MAAM,0CAA0C,CAAC;AACrF,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAEhE,qBACa,aAAa;IAIlB,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IACjC,OAAO,CAAC,QAAQ,CAAC,yBAAyB;IAC1C,OAAO,CAAC,QAAQ,CAAC,qBAAqB;IACtC,OAAO,CAAC,QAAQ,CAAC,cAAc;IANnC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkC;gBAGpC,gBAAgB,EAAE,oBAAoB,EACtC,yBAAyB,EAAE,yBAAyB,EACpD,qBAAqB,EAAE,qBAAqB,EAC5C,cAAc,EAAE,cAAc;IAG7C,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,UAAU,CAAA;KAAE,CAAC;IA+B/F,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAkCjD,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAkB1E,QAAQ,CAAC,MAAM,EAAE,MAAM;;;;;;;;;;;;IAgD7B,OAAO,CAAC,IAAI;CAGf"}
@@ -106,7 +106,7 @@ let ApiKeyService = ApiKeyService_1 = class ApiKeyService {
106
106
  throw new common_1.UnauthorizedException(error_messages_1.ERROR_MESSAGES.INVALID_CREDENTIALS);
107
107
  }
108
108
  const user = apiKeyRecord.user;
109
- const tokens = await this.authenticationService.generateTokens(user);
109
+ const tokens = await this.authenticationService.generateTokens(user, `apikey-${apiKeyRecord.id}`);
110
110
  return {
111
111
  user: {
112
112
  email: user.email,
@@ -1 +1 @@
1
- {"version":3,"file":"api-key.service.js","sourceRoot":"","sources":["../../src/services/api-key.service.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n ForbiddenException,\n Injectable,\n Logger,\n NotFoundException,\n UnauthorizedException,\n} from '@nestjs/common';\nimport { createHash, randomBytes } from 'crypto';\nimport { ERROR_MESSAGES } from 'src/constants/error-messages';\nimport { CreateApiKeyDto } from 'src/dtos/create-api-key.dto';\nimport { UpdateApiKeyDto } from 'src/dtos/update-api-key.dto';\nimport { UserApiKey } from 'src/entities/user-api-key.entity';\nimport { User } from 'src/entities/user.entity';\nimport { ActiveUserData } from 'src/interfaces/active-user-data.interface';\nimport { UserApiKeyRepository } from 'src/repository/user-api-key.repository';\nimport { PermissionMetadataService } from 'src/services/permission-metadata.service';\nimport { AuthenticationService } from './authentication.service';\nimport { UserRepository } from 'src/repository/user.repository';\n\n@Injectable()\nexport class ApiKeyService {\n private readonly logger = new Logger(ApiKeyService.name);\n\n constructor(\n private readonly apiKeyRepository: UserApiKeyRepository,\n private readonly permissionMetadataService: PermissionMetadataService,\n private readonly authenticationService: AuthenticationService,\n private readonly userRepository: UserRepository,\n ) { }\n\n async generate(userId: number, dto: CreateApiKeyDto): Promise<{ apiKey: string; record: UserApiKey }> {\n const user = await this.apiKeyRepository.manager.findOne(User, {\n where: { id: userId },\n select: ['id', 'isAllowedToGenerateApiKeys'],\n });\n\n if (!user?.isAllowedToGenerateApiKeys) {\n throw new ForbiddenException('You are not allowed to generate API keys');\n }\n\n const rawKey = 'sldx_' + randomBytes(32).toString('hex');\n const hashedKey = this.hash(rawKey);\n const maskedKey = 'sldx_****' + rawKey.slice(-4);\n\n const record = this.apiKeyRepository.create({\n name: dto.name,\n hashedKey,\n maskedKey,\n isActive: true,\n expiresAt: dto.expiresAt ? new Date(dto.expiresAt) : null,\n user,\n });\n\n await this.apiKeyRepository.save(record);\n\n // Strip hashedKey from the returned record — maskedKey is all the UI needs\n delete (record as any).hashedKey;\n\n return { apiKey: rawKey, record };\n }\n\n async validate(rawKey: string): Promise<ActiveUserData> {\n const hashedKey = this.hash(rawKey);\n\n // Bypass security rules for auth validation — must find the key regardless of caller context\n const keyRecord = await this.apiKeyRepository.findOne({\n where: { hashedKey, isActive: true },\n relations: ['user', 'user.roles'],\n });\n\n if (!keyRecord) {\n throw new UnauthorizedException();\n }\n\n if (keyRecord.expiresAt && keyRecord.expiresAt < new Date()) {\n throw new UnauthorizedException('API key expired');\n }\n\n // Fire-and-forget — does not need security rule context\n this.apiKeyRepository.update(keyRecord.id, { lastUsedAt: new Date() }).catch((err) => {\n this.logger.warn(`Failed to update lastUsedAt for key ${keyRecord.id}: ${err.message}`);\n });\n\n const roles = (keyRecord.user.roles ?? []).map((r) => r.name);\n const permissions = await this.permissionMetadataService.findAllUsingRoles(roles);\n\n return {\n sub: keyRecord.user.id,\n username: keyRecord.user.username,\n email: keyRecord.user.email,\n roles,\n permissions: permissions.map((p) => p.name),\n };\n }\n\n async updateKey(id: number, userId: number, dto: UpdateApiKeyDto): Promise<void> {\n const keyRecord = await this.apiKeyRepository.findOne({\n where: { id, user: { id: userId } },\n });\n\n if (!keyRecord) {\n throw new NotFoundException('API key not found');\n }\n\n await this.apiKeyRepository.manager\n .createQueryBuilder()\n .update(UserApiKey)\n .set({ isActive: dto.isActive })\n .where('id = :id', { id })\n .execute();\n }\n\n\n async apiKeyMe(apiKey: string) {\n\n const hasedKey = this.hash(apiKey);\n const apiKeyRecord = await this.apiKeyRepository.findOne({\n where: {\n hashedKey: hasedKey,\n },\n relations: {\n user: {\n roles: true\n }\n }\n });\n\n if (!apiKeyRecord) {\n throw new UnauthorizedException(ERROR_MESSAGES.INVALID_CREDENTIALS);\n }\n\n const user = apiKeyRecord.user;\n\n const tokens = await this.authenticationService.generateTokens(user);\n\n\n return {\n user: {\n email: user.email,\n mobile: user.mobile,\n username: user.username,\n forcePasswordChange: user.forcePasswordChange,\n id: user.id,\n roles: user.roles.map((role) => role.name)\n },\n ...tokens\n }\n }\n\n private hash(rawKey: string): string {\n return createHash('sha256').update(rawKey).digest('hex');\n }\n}\n"]}
1
+ {"version":3,"file":"api-key.service.js","sourceRoot":"","sources":["../../src/services/api-key.service.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n ForbiddenException,\n Injectable,\n Logger,\n NotFoundException,\n UnauthorizedException,\n} from '@nestjs/common';\nimport { createHash, randomBytes } from 'crypto';\nimport { ERROR_MESSAGES } from 'src/constants/error-messages';\nimport { CreateApiKeyDto } from 'src/dtos/create-api-key.dto';\nimport { UpdateApiKeyDto } from 'src/dtos/update-api-key.dto';\nimport { UserApiKey } from 'src/entities/user-api-key.entity';\nimport { User } from 'src/entities/user.entity';\nimport { ActiveUserData } from 'src/interfaces/active-user-data.interface';\nimport { UserApiKeyRepository } from 'src/repository/user-api-key.repository';\nimport { PermissionMetadataService } from 'src/services/permission-metadata.service';\nimport { AuthenticationService } from './authentication.service';\nimport { UserRepository } from 'src/repository/user.repository';\n\n@Injectable()\nexport class ApiKeyService {\n private readonly logger = new Logger(ApiKeyService.name);\n\n constructor(\n private readonly apiKeyRepository: UserApiKeyRepository,\n private readonly permissionMetadataService: PermissionMetadataService,\n private readonly authenticationService: AuthenticationService,\n private readonly userRepository: UserRepository,\n ) { }\n\n async generate(userId: number, dto: CreateApiKeyDto): Promise<{ apiKey: string; record: UserApiKey }> {\n const user = await this.apiKeyRepository.manager.findOne(User, {\n where: { id: userId },\n select: ['id', 'isAllowedToGenerateApiKeys'],\n });\n\n if (!user?.isAllowedToGenerateApiKeys) {\n throw new ForbiddenException('You are not allowed to generate API keys');\n }\n\n const rawKey = 'sldx_' + randomBytes(32).toString('hex');\n const hashedKey = this.hash(rawKey);\n const maskedKey = 'sldx_****' + rawKey.slice(-4);\n\n const record = this.apiKeyRepository.create({\n name: dto.name,\n hashedKey,\n maskedKey,\n isActive: true,\n expiresAt: dto.expiresAt ? new Date(dto.expiresAt) : null,\n user,\n });\n\n await this.apiKeyRepository.save(record);\n\n // Strip hashedKey from the returned record — maskedKey is all the UI needs\n delete (record as any).hashedKey;\n\n return { apiKey: rawKey, record };\n }\n\n async validate(rawKey: string): Promise<ActiveUserData> {\n const hashedKey = this.hash(rawKey);\n\n // Bypass security rules for auth validation — must find the key regardless of caller context\n const keyRecord = await this.apiKeyRepository.findOne({\n where: { hashedKey, isActive: true },\n relations: ['user', 'user.roles'],\n });\n\n if (!keyRecord) {\n throw new UnauthorizedException();\n }\n\n if (keyRecord.expiresAt && keyRecord.expiresAt < new Date()) {\n throw new UnauthorizedException('API key expired');\n }\n\n // Fire-and-forget — does not need security rule context\n this.apiKeyRepository.update(keyRecord.id, { lastUsedAt: new Date() }).catch((err) => {\n this.logger.warn(`Failed to update lastUsedAt for key ${keyRecord.id}: ${err.message}`);\n });\n\n const roles = (keyRecord.user.roles ?? []).map((r) => r.name);\n const permissions = await this.permissionMetadataService.findAllUsingRoles(roles);\n\n return {\n sub: keyRecord.user.id,\n username: keyRecord.user.username,\n email: keyRecord.user.email,\n roles,\n permissions: permissions.map((p) => p.name),\n };\n }\n\n async updateKey(id: number, userId: number, dto: UpdateApiKeyDto): Promise<void> {\n const keyRecord = await this.apiKeyRepository.findOne({\n where: { id, user: { id: userId } },\n });\n\n if (!keyRecord) {\n throw new NotFoundException('API key not found');\n }\n\n await this.apiKeyRepository.manager\n .createQueryBuilder()\n .update(UserApiKey)\n .set({ isActive: dto.isActive })\n .where('id = :id', { id })\n .execute();\n }\n\n\n async apiKeyMe(apiKey: string) {\n\n const hasedKey = this.hash(apiKey);\n const apiKeyRecord = await this.apiKeyRepository.findOne({\n where: {\n hashedKey: hasedKey,\n },\n relations: {\n user: {\n roles: true\n }\n }\n });\n\n if (!apiKeyRecord) {\n throw new UnauthorizedException(ERROR_MESSAGES.INVALID_CREDENTIALS);\n }\n\n const user = apiKeyRecord.user;\n\n // Keyed on the API key record so every call for this key reuses one\n // refresh-token bucket. Without it each call mints a fresh key and\n // therefore a new bucket with a refreshTokenTtl lifetime - a client\n // polling this endpoint would accumulate them without bound.\n //\n // The consequence is that replicas sharing one API key share one\n // bucket and invalidate each other, which is exactly the behaviour\n // before per-device sessions existed, and is benign here: an API key\n // is a permanent credential, so a failed refresh just re-mints.\n const tokens = await this.authenticationService.generateTokens(\n user,\n `apikey-${apiKeyRecord.id}`,\n );\n\n\n return {\n user: {\n email: user.email,\n mobile: user.mobile,\n username: user.username,\n forcePasswordChange: user.forcePasswordChange,\n id: user.id,\n roles: user.roles.map((role) => role.name)\n },\n ...tokens\n }\n }\n\n private hash(rawKey: string): string {\n return createHash('sha256').update(rawKey).digest('hex');\n }\n}\n"]}
@@ -160,12 +160,12 @@ export declare class AuthenticationService {
160
160
  data: {};
161
161
  }>;
162
162
  private notifyUserOnPasswordChanged;
163
- generateTokens(user: User): Promise<{
163
+ generateTokens(user: User, deviceId?: string): Promise<{
164
164
  accessToken: string;
165
165
  refreshToken: string;
166
166
  }>;
167
- generateAccessToken(user: User, sessionId?: string): Promise<string>;
168
- generateRefreshToken(user: User, previousRefreshToken?: string): Promise<string>;
167
+ generateAccessToken(user: User, sessionId?: string, deviceKey?: string): Promise<string>;
168
+ generateRefreshToken(user: User, previousRefreshToken?: string, deviceKey?: string): Promise<string>;
169
169
  refreshTokens(refreshTokenDto: RefreshTokenDto): Promise<{
170
170
  accessToken: string;
171
171
  refreshToken: string;
@@ -235,9 +235,10 @@ export declare class AuthenticationService {
235
235
  private checkAccountBlocked;
236
236
  private incrementFailedAttempts;
237
237
  private resetFailedAttempts;
238
- logout(refreshToken: string): Promise<{
238
+ logout(refreshToken: string, allDevices?: boolean): Promise<{
239
239
  message: string;
240
240
  }>;
241
+ private verifyRefreshTokenForLogout;
241
242
  activateUser(userId: number): Promise<void>;
242
243
  me(activeUser: ActiveUserData): Promise<{
243
244
  user: {
@@ -1 +1 @@
1
- {"version":3,"file":"authentication.service.d.ts","sourceRoot":"","sources":["../../src/services/authentication.service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"authentication.service.d.ts","sourceRoot":"","sources":["../../src/services/authentication.service.ts"],"names":[],"mappings":"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"}
@@ -1101,7 +1101,7 @@ let AuthenticationService = AuthenticationService_1 = class AuthenticationServic
1101
1101
  }, this.settingService.getConfigValue("shouldQueueSms"));
1102
1102
  }
1103
1103
  }
1104
- async generateTokens(user) {
1104
+ async generateTokens(user, deviceId) {
1105
1105
  const sessionId = this.shouldPreventConcurrentLogins()
1106
1106
  ? (0, crypto_1.randomUUID)()
1107
1107
  : undefined;
@@ -1111,16 +1111,19 @@ let AuthenticationService = AuthenticationService_1 = class AuthenticationServic
1111
1111
  else {
1112
1112
  await this.activeSessionStorage.clearActiveSession(user.id);
1113
1113
  }
1114
+ const deviceKey = this.refreshTokenIdsStorage.areConcurrentLoginsAllowed()
1115
+ ? deviceId ?? (0, crypto_1.randomUUID)()
1116
+ : undefined;
1114
1117
  const [accessToken, refreshToken] = await Promise.all([
1115
- await this.generateAccessToken(user, sessionId),
1116
- await this.generateRefreshToken(user),
1118
+ await this.generateAccessToken(user, sessionId, deviceKey),
1119
+ await this.generateRefreshToken(user, undefined, deviceKey),
1117
1120
  ]);
1118
1121
  return {
1119
1122
  accessToken,
1120
1123
  refreshToken,
1121
1124
  };
1122
1125
  }
1123
- async generateAccessToken(user, sessionId) {
1126
+ async generateAccessToken(user, sessionId, deviceKey) {
1124
1127
  const userRoleNames = user.roles.map((role) => role.name);
1125
1128
  const resolvedSessionId = this.shouldPreventConcurrentLogins()
1126
1129
  ? sessionId ?? (await this.activeSessionStorage.getActiveSession(user.id))
@@ -1131,16 +1134,22 @@ let AuthenticationService = AuthenticationService_1 = class AuthenticationServic
1131
1134
  email: user.email,
1132
1135
  roles: userRoleNames,
1133
1136
  ...(resolvedSessionId ? { sessionId: resolvedSessionId } : {}),
1137
+ ...(deviceKey ? { deviceKey } : {}),
1134
1138
  });
1135
1139
  return accessToken;
1136
1140
  }
1137
- async generateRefreshToken(user, previousRefreshToken) {
1141
+ async generateRefreshToken(user, previousRefreshToken, deviceKey) {
1138
1142
  const refreshTokenId = (0, crypto_1.randomUUID)();
1139
1143
  const refreshTokenTtl = this.settingService.getConfigValue("refreshTokenTtl");
1144
+ const epoch = deviceKey
1145
+ ? await this.refreshTokenIdsStorage.getEpoch(user.id)
1146
+ : undefined;
1140
1147
  const refreshToken = await this.signToken(user.id, refreshTokenTtl, {
1141
1148
  refreshTokenId,
1149
+ ...(deviceKey ? { deviceKey } : {}),
1150
+ ...(epoch !== undefined ? { epoch } : {}),
1142
1151
  });
1143
- await this.refreshTokenIdsStorage.insert(user.id, refreshToken, previousRefreshToken);
1152
+ await this.refreshTokenIdsStorage.insert(user.id, refreshToken, previousRefreshToken, deviceKey);
1144
1153
  return refreshToken;
1145
1154
  }
1146
1155
  async refreshTokens(refreshTokenDto) {
@@ -1148,7 +1157,7 @@ let AuthenticationService = AuthenticationService_1 = class AuthenticationServic
1148
1157
  const secret = this.settingService.getConfigValue("secret");
1149
1158
  const audience = this.settingService.getConfigValue("audience");
1150
1159
  const issuer = this.settingService.getConfigValue("issuer");
1151
- const { sub } = await this.jwtService.verifyAsync(refreshTokenDto.refreshToken, {
1160
+ const { sub, deviceKey, epoch } = await this.jwtService.verifyAsync(refreshTokenDto.refreshToken, {
1152
1161
  secret,
1153
1162
  audience,
1154
1163
  issuer,
@@ -1164,11 +1173,11 @@ let AuthenticationService = AuthenticationService_1 = class AuthenticationServic
1164
1173
  if (!user) {
1165
1174
  throw new common_1.UnauthorizedException(error_messages_1.ERROR_MESSAGES.SESSION_INVALID);
1166
1175
  }
1167
- const currentRefreshToken = await this.refreshTokenIdsStorage.validateAndRotate(user, refreshTokenDto.refreshToken);
1176
+ const rotated = await this.refreshTokenIdsStorage.validateAndRotate(user, refreshTokenDto.refreshToken, { deviceKey, epoch });
1168
1177
  await this.userActivityHistoryService.logEvent("tokenRefreshed", user);
1169
1178
  return {
1170
- accessToken: await this.generateAccessToken(user),
1171
- refreshToken: currentRefreshToken,
1179
+ accessToken: await this.generateAccessToken(user, undefined, rotated.deviceKey),
1180
+ refreshToken: rotated.refreshToken,
1172
1181
  };
1173
1182
  }
1174
1183
  catch (err) {
@@ -1471,21 +1480,29 @@ let AuthenticationService = AuthenticationService_1 = class AuthenticationServic
1471
1480
  user.failedLoginAttempts = 0;
1472
1481
  await this.userRepository.update(user.id, { failedLoginAttempts: 0 });
1473
1482
  }
1474
- async logout(refreshToken) {
1483
+ async logout(refreshToken, allDevices = false) {
1475
1484
  try {
1476
- const payload = this.jwtService.decode(refreshToken);
1477
- if (!payload || !payload.sub) {
1478
- throw new common_1.UnauthorizedException(error_messages_1.ERROR_MESSAGES.INVALID_REFRESH_TOKEN);
1485
+ const payload = await this.verifyRefreshTokenForLogout(refreshToken);
1486
+ if (!payload?.sub) {
1487
+ this.logger.warn("logout called with an unverifiable refresh token");
1488
+ return { message: success_messages_1.SUCCESS_MESSAGES.LOGOUT_SUCCESS };
1479
1489
  }
1480
1490
  const userId = payload.sub;
1481
- await this.refreshTokenIdsStorage.invalidate(userId);
1491
+ if (allDevices) {
1492
+ await this.refreshTokenIdsStorage.invalidateAll(userId);
1493
+ }
1494
+ else {
1495
+ await this.refreshTokenIdsStorage.invalidate(userId, payload.deviceKey);
1496
+ }
1482
1497
  await this.activeSessionStorage.clearActiveSession(userId);
1483
1498
  const user = await this.userRepository.findOne({
1484
1499
  where: {
1485
1500
  id: userId,
1486
1501
  },
1487
1502
  });
1488
- await this.userActivityHistoryService.logEvent("logout", user);
1503
+ if (user) {
1504
+ await this.userActivityHistoryService.logEvent("logout", user);
1505
+ }
1489
1506
  return { message: success_messages_1.SUCCESS_MESSAGES.LOGOUT_SUCCESS };
1490
1507
  }
1491
1508
  catch (err) {
@@ -1495,6 +1512,20 @@ let AuthenticationService = AuthenticationService_1 = class AuthenticationServic
1495
1512
  : new common_1.InternalServerErrorException(error_messages_1.ERROR_MESSAGES.LOGOUT_FAILED);
1496
1513
  }
1497
1514
  }
1515
+ async verifyRefreshTokenForLogout(refreshToken) {
1516
+ try {
1517
+ const payload = await this.jwtService.verifyAsync(refreshToken, {
1518
+ secret: this.settingService.getConfigValue("secret"),
1519
+ audience: this.settingService.getConfigValue("audience"),
1520
+ issuer: this.settingService.getConfigValue("issuer"),
1521
+ ignoreExpiration: true,
1522
+ });
1523
+ return payload?.refreshTokenId ? payload : null;
1524
+ }
1525
+ catch {
1526
+ return null;
1527
+ }
1528
+ }
1498
1529
  async activateUser(userId) {
1499
1530
  const user = await this.userService.findOne(userId, {});
1500
1531
  if (!user) {
@@ -1512,7 +1543,7 @@ let AuthenticationService = AuthenticationService_1 = class AuthenticationServic
1512
1543
  roles: true,
1513
1544
  },
1514
1545
  });
1515
- const refreshTokenState = await this.refreshTokenIdsStorage.getCurrentRefreshTokenState(user.id);
1546
+ const refreshTokenState = await this.refreshTokenIdsStorage.getCurrentRefreshTokenState(user.id, activeUser.deviceKey);
1516
1547
  const response = {
1517
1548
  user: {
1518
1549
  email: user.email,
@@ -1521,12 +1552,12 @@ let AuthenticationService = AuthenticationService_1 = class AuthenticationServic
1521
1552
  id: user.id,
1522
1553
  roles: user.roles.map((role) => role.name),
1523
1554
  },
1524
- refreshToken: refreshTokenState.currentRefreshToken,
1555
+ refreshToken: refreshTokenState?.currentRefreshToken ?? null,
1525
1556
  };
1526
1557
  return response;
1527
1558
  }
1528
1559
  async generateSsoCode(activeUser, rawAccessToken) {
1529
- const refreshTokenState = await this.refreshTokenIdsStorage.getCurrentRefreshTokenState(activeUser.sub);
1560
+ const refreshTokenState = await this.refreshTokenIdsStorage.getCurrentRefreshTokenState(activeUser.sub, activeUser.deviceKey);
1530
1561
  if (!refreshTokenState?.currentRefreshToken) {
1531
1562
  throw new common_1.UnauthorizedException("No active session found");
1532
1563
  }