@boarteam/boar-pack-users-backend 5.4.0 → 6.0.0-alpha.0

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@boarteam/boar-pack-users-backend",
3
- "version": "5.4.0",
3
+ "version": "6.0.0-alpha.0",
4
4
  "description": "NestJS Users module including permissions system, authentication strategies etc",
5
5
  "main": "src/index",
6
6
  "files": [
@@ -14,42 +14,44 @@
14
14
  "access": "public"
15
15
  },
16
16
  "dependencies": {
17
- "@boarteam/boar-pack-common-backend": "^2.2.0",
18
- "@casl/ability": "^6.7.0",
19
- "@nestjs/common": "^9.0.0",
20
- "@nestjs/config": "^3.2.0",
21
- "@nestjs/core": "^9.0.0",
22
- "@nestjs/jwt": "^10.2.0",
23
- "@nestjs/passport": "^10.0.3",
24
- "@nestjs/platform-express": "^9.0.0",
25
- "@nestjs/schedule": "^4.1.1",
26
- "@nestjs/swagger": "^7.3.0",
27
- "@nestjs/typeorm": "^10.0.2",
17
+ "@boarteam/boar-pack-common-backend": "^3.0.0-alpha.0",
18
+ "@casl/ability": "^6.7.3",
19
+ "@dataui/crud": "^5.3.4",
20
+ "@dataui/crud-typeorm": "^5.3.4",
21
+ "@nestjs/common": "^11.0.10",
22
+ "@nestjs/config": "^4.0.0",
23
+ "@nestjs/core": "^11.0.10",
24
+ "@nestjs/jwt": "^11.0.0",
25
+ "@nestjs/passport": "^11.0.5",
26
+ "@nestjs/platform-express": "^11.0.10",
27
+ "@nestjs/schedule": "^5.0.1",
28
+ "@nestjs/swagger": "^11.0.4",
29
+ "@nestjs/typeorm": "^11.0.0",
28
30
  "@nestjsx/crud": "^5.0.0-alpha.3",
29
31
  "@nestjsx/crud-typeorm": "^5.0.0-alpha.3",
30
32
  "bcrypt": "^5.1.1",
31
- "joi": "^17.12.2",
33
+ "joi": "^17.13.3",
32
34
  "lodash": "^4.17.21",
33
35
  "moment": "^2.30.1",
34
- "moment-timezone": "^0.5.45",
35
- "nestjs-joi": "^1.10.0",
36
+ "moment-timezone": "^0.5.47",
37
+ "nestjs-joi": "^1.10.1",
36
38
  "openapi-typescript-codegen": "^0.29.0",
37
39
  "passport": "^0.7.0",
38
40
  "passport-http-bearer": "^1.0.1",
39
41
  "passport-jwt": "^4.0.1",
40
42
  "passport-local": "^1.0.0",
41
- "pg": "^8.13.1",
43
+ "pg": "^8.13.3",
42
44
  "typeorm": "^0.3.20",
43
- "ws": "^8.16.0"
45
+ "ws": "^8.18.0"
44
46
  },
45
47
  "devDependencies": {
46
48
  "@nestjs/platform-express": "^10.4.15",
47
49
  "@types/bcrypt": "^5.0.2",
48
- "@types/passport-google-oauth20": "^2.0.14",
50
+ "@types/passport-google-oauth20": "^2.0.16",
49
51
  "@types/passport-http-bearer": "^1.0.41",
50
52
  "@types/passport-jwt": "^4.0.1",
51
53
  "@types/passport-local": "^1.0.38",
52
- "@types/ws": "^8.5.10",
54
+ "@types/ws": "^8.5.14",
53
55
  "class-transformer": "^0.5.1",
54
56
  "openapi-typescript-codegen": "^0.29.0",
55
57
  "passport-azure-ad-oauth2": "^0.0.4",
@@ -60,5 +62,5 @@
60
62
  "yalc:push": "yalc push",
61
63
  "gen-types": "SWAGGER=true JWT_SECRET=swagger nest start"
62
64
  },
63
- "gitHead": "acc7ba1cd1fa8a4972efed9ece60a50740370396"
65
+ "gitHead": "fe24b636ace6e71cc60a3f65126f8520f926aba1"
64
66
  }
@@ -1,4 +1,4 @@
1
- import { Column, CreateDateColumn, Entity, Index, ManyToOne, PrimaryGeneratedColumn, UpdateDateColumn, } from 'typeorm';
1
+ import { Column, CreateDateColumn, Entity, ManyToOne, PrimaryGeneratedColumn, UpdateDateColumn, } from 'typeorm';
2
2
  import { User } from "../../users";
3
3
 
4
4
  export enum LogType {
@@ -113,7 +113,6 @@ export class EventLog {
113
113
  })
114
114
  statusCode: number | null;
115
115
 
116
- @Index()
117
116
  @Column({
118
117
  default: 'main'
119
118
  })
@@ -1,6 +1,6 @@
1
1
  import { Controller, Get, Query } from '@nestjs/common';
2
2
  import { ApiExtraModels, ApiOkResponse, ApiTags, getSchemaPath } from '@nestjs/swagger';
3
- import { Crud, CrudController } from '@nestjsx/crud';
3
+ import { Crud, CrudController } from '@dataui/crud';
4
4
  import { EventLogsService } from './event-logs.service';
5
5
  import { EventLog } from './entities/event-log.entity';
6
6
  import { EventLogCreateDto } from './dto/event-log-create.dto';
@@ -65,16 +65,4 @@ export class EventLogsController implements CrudController<EventLog>{
65
65
  const end = query.endTime ? new Date(query.endTime) : undefined;
66
66
  return this.service.getTimeline(start, end, query.timezone);
67
67
  }
68
-
69
- @CheckPolicies(new ViewEventLogsPolicy())
70
- @Get('service-names')
71
- @ApiOkResponse({
72
- schema: {
73
- type: 'array',
74
- items: { type: 'string' },
75
- },
76
- })
77
- async getServiceNames(): Promise<string[]> {
78
- return this.service.getServiceNames();
79
- }
80
68
  }
@@ -57,13 +57,17 @@ export class EventLogInterceptor implements NestInterceptor {
57
57
  logEntry.duration = Date.now() - now;
58
58
  logEntry.statusCode = response.statusCode;
59
59
  logEntry.logLevel = response.statusCode >= 500 ? LogLevel.ERROR : (response.statusCode >= 400 ? LogLevel.WARNING : LogLevel.INFO);
60
- this.eventLogService.audit(logEntry, request);
60
+ this.eventLogService.audit(logEntry, request).catch((error) => {
61
+ this.logger.error(`Failed to log event: ${error.message}`);
62
+ });
61
63
  }),
62
64
  catchError((error: HttpException) => {
63
65
  logEntry.duration = Date.now() - now;
64
66
  logEntry.statusCode = error?.getStatus?.() || 500;
65
67
  logEntry.logLevel = logEntry.statusCode >= 500 ? LogLevel.ERROR : LogLevel.WARNING;
66
- this.eventLogService.audit(logEntry, request);
68
+ this.eventLogService.audit(logEntry, request).catch((error) => {
69
+ this.logger.error(`Failed to log event: ${error.message}`);
70
+ });
67
71
  return throwError(() => error);
68
72
  }),
69
73
  );
@@ -50,7 +50,9 @@ export class EventLogMiddleware implements NestMiddleware {
50
50
  ? LogLevel.WARNING
51
51
  : LogLevel.INFO;
52
52
 
53
- this.eventLogService.audit(logEntry, req);
53
+ this.eventLogService.audit(logEntry, req).catch((error) => {
54
+ this.logger.error(`Failed to log event: ${error.message}`);
55
+ });
54
56
  });
55
57
 
56
58
  next();
@@ -12,7 +12,6 @@ import { CONFIGURE_EVENTS_MIDDLEWARE, SERVICE_CONFIG_TOKEN } from "./event-logs.
12
12
  import { TEventLogServiceConfig } from "./event-logs.types";
13
13
  import { EventLogsLogger } from "./event-logs.logger";
14
14
  import { EventLogMiddleware } from "./event-logs.middleware";
15
- import { ScheduleModule } from "@nestjs/schedule";
16
15
 
17
16
  @Module({})
18
17
  export class EventLogsModule implements NestModule {
@@ -50,7 +49,6 @@ export class EventLogsModule implements NestModule {
50
49
  module: EventLogsModule,
51
50
  imports: [
52
51
  CaslModule.forFeature(),
53
- ScheduleModule.forRoot(),
54
52
  TypeOrmModule.forFeature([EventLog], config.dataSourceName),
55
53
  ],
56
54
  providers: [
@@ -1,11 +1,10 @@
1
1
  import { Injectable, Logger } from '@nestjs/common';
2
- import { TypeOrmCrudService } from '@nestjsx/crud-typeorm';
2
+ import { TypeOrmCrudService } from '@dataui/crud-typeorm';
3
3
  import { EventLog, LogLevel, LogType, UserRole } from './entities/event-log.entity';
4
4
  import { DataSource, Repository } from 'typeorm';
5
5
  import { Request } from 'express';
6
6
  import { Roles } from "../users";
7
7
  import { EventLogTimelineDto } from "./dto/event-log-timeline.dto";
8
- import { Cron, CronExpression } from "@nestjs/schedule";
9
8
  import moment from "moment";
10
9
  import 'moment-timezone';
11
10
 
@@ -14,7 +13,6 @@ type TInterval = 'second' | 'minute' | 'hour' | 'day' | 'week';
14
13
  @Injectable()
15
14
  export class EventLogsService extends TypeOrmCrudService<EventLog> {
16
15
  private static requestHandled = Symbol('requestHandled');
17
- private logsStore: Partial<EventLog>[] = [];
18
16
 
19
17
  private readonly logger = new Logger(EventLogsService.name);
20
18
 
@@ -30,37 +28,7 @@ export class EventLogsService extends TypeOrmCrudService<EventLog> {
30
28
  super(repo);
31
29
  }
32
30
 
33
- @Cron(CronExpression.EVERY_10_SECONDS)
34
- private async saveAccumulatedLogs(): Promise<void> {
35
- if (this.logsStore.length > 0) {
36
- const logs = [...this.logsStore];
37
- this.logger.verbose('Reset event logs store variable');
38
- this.logsStore = [];
39
-
40
- await this.repo.save(logs).catch(e => {
41
- // DO NOT USE LOGGER HERE - it will cause infinite loop
42
- console.error('Error while saving logs');
43
- console.error(e);
44
- });
45
- }
46
- }
47
-
48
- @Cron(CronExpression.EVERY_WEEK)
49
- private async deleteOldEventLogs() {
50
- const threeMonthsAgo = new Date();
51
- threeMonthsAgo.setMonth(threeMonthsAgo.getMonth() - 2);
52
-
53
- const result = await this.repo
54
- .createQueryBuilder()
55
- .delete()
56
- .from(EventLog)
57
- .where('created_at <= :threeMonthsAgo', { threeMonthsAgo })
58
- .execute();
59
-
60
- this.logger.debug(`Removed ${result.affected} expired records from event_logs table.`);
61
- }
62
-
63
- audit(eventLog: Partial<EventLog>, request?: Request): void {
31
+ async audit(eventLog: Partial<EventLog>, request?: Request): Promise<void> {
64
32
  // @ts-ignore
65
33
  if (request?.[EventLogsService.requestHandled]) {
66
34
  this.logger.debug('Request already handled');
@@ -86,7 +54,7 @@ export class EventLogsService extends TypeOrmCrudService<EventLog> {
86
54
  request[EventLogsService.requestHandled] = true;
87
55
  }
88
56
 
89
- this.logsStore.push({
57
+ await this.repo.save({
90
58
  ...logPartial,
91
59
  ...eventLog,
92
60
  logType: LogType.AUDIT,
@@ -98,9 +66,8 @@ export class EventLogsService extends TypeOrmCrudService<EventLog> {
98
66
  return request?.[EventLogsService.requestHandled];
99
67
  }
100
68
 
101
- // TODO: Remove async in the next major version (breaking change)
102
69
  async operationalLog(eventLog: Partial<EventLog>): Promise<void> {
103
- this.logsStore.push({
70
+ await this.repo.save({
104
71
  logLevel: LogLevel.INFO,
105
72
  userRole: UserRole.SYSTEM,
106
73
  ...eventLog,
@@ -109,11 +76,15 @@ export class EventLogsService extends TypeOrmCrudService<EventLog> {
109
76
  }
110
77
 
111
78
  public applicationLog(eventLog: Partial<EventLog>): void {
112
- this.logsStore.push({
79
+ this.repo.save({
113
80
  logLevel: LogLevel.INFO,
114
81
  userRole: UserRole.SYSTEM,
115
82
  ...eventLog,
116
83
  logType: LogType.APPLICATION,
84
+ }).catch(e => {
85
+ // DO NOT USE LOGGER HERE - it will cause infinite loop
86
+ console.error('Error while saving application log');
87
+ console.error(e);
117
88
  });
118
89
  }
119
90
 
@@ -163,15 +134,6 @@ export class EventLogsService extends TypeOrmCrudService<EventLog> {
163
134
  ]);
164
135
  }
165
136
 
166
- async getServiceNames(): Promise<string[]> {
167
- const result = await this.repo
168
- .createQueryBuilder('event_logs')
169
- .select('event_logs.service')
170
- .distinctOn(['service'])
171
- .getMany();
172
- return result.map((data) => data.service);
173
- }
174
-
175
137
  private async getOldestLogDate(): Promise<Date> {
176
138
  const oldestLog = await this.repo.createQueryBuilder('event_log')
177
139
  .select('MIN(event_log.createdAt)', 'min')
@@ -1,6 +1,6 @@
1
1
  import { Body, Controller, Req } from '@nestjs/common';
2
2
  import { ApiTags } from '@nestjs/swagger';
3
- import { Crud, CrudAuth, CrudController, type CrudRequest, Override, ParsedRequest } from '@nestjsx/crud';
3
+ import { Crud, CrudAuth, CrudController, type CrudRequest, Override, ParsedRequest } from '@dataui/crud';
4
4
  import { TokensService } from './tokens.service';
5
5
  import { Token } from './entities/token.entity';
6
6
  import { ManageMyTokensPolicy } from "./policies/manage-my-tokens.policy";
@@ -1,6 +1,6 @@
1
1
  import { Controller } from '@nestjs/common';
2
2
  import { ApiTags } from '@nestjs/swagger';
3
- import { Crud, CrudController } from '@nestjsx/crud';
3
+ import { Crud, CrudController } from '@dataui/crud';
4
4
  import { TokensService } from './tokens.service';
5
5
  import { Token } from './entities/token.entity';
6
6
  import { TokenUpdateDto } from "./dto/token-update.dto";
@@ -1,5 +1,5 @@
1
1
  import { Injectable } from '@nestjs/common';
2
- import { TypeOrmCrudService } from '@nestjsx/crud-typeorm';
2
+ import { TypeOrmCrudService } from '@dataui/crud-typeorm';
3
3
  import { Token } from './entities/token.entity';
4
4
  import { Repository } from 'typeorm';
5
5
 
@@ -1,4 +1,4 @@
1
- import { Crud, CrudAuth, CrudController, type CrudRequest, Override, ParsedRequest, } from '@nestjsx/crud';
1
+ import { Crud, CrudAuth, CrudController, type CrudRequest, Override, ParsedRequest, } from '@dataui/crud';
2
2
  import { TUser, User } from './entities/user.entity';
3
3
  import { Controller, Req } from '@nestjs/common';
4
4
  import type { Request } from 'express';
@@ -7,7 +7,7 @@ import {
7
7
  Logger,
8
8
  } from '@nestjs/common';
9
9
  import { Request } from 'express';
10
- import { getAction } from "@nestjsx/crud";
10
+ import { getAction } from "@dataui/crud";
11
11
  import { isEqual } from 'lodash';
12
12
 
13
13
  @Injectable()
@@ -1,6 +1,6 @@
1
1
  import { Controller, UseFilters, UseGuards } from '@nestjs/common';
2
2
  import { UsersService } from './users.service';
3
- import { Crud } from '@nestjsx/crud';
3
+ import { Crud } from '@dataui/crud';
4
4
  import { User } from './entities/user.entity';
5
5
  import { CheckPolicies, ManageAllPolicy } from '../casl';
6
6
  import { UserCreateDto } from './dto/user-create.dto';
@@ -1,5 +1,5 @@
1
1
  import { Injectable } from '@nestjs/common';
2
- import { TypeOrmCrudService } from '@nestjsx/crud-typeorm';
2
+ import { TypeOrmCrudService } from '@dataui/crud-typeorm';
3
3
  import { User } from './entities/user.entity';
4
4
  import { Repository } from 'typeorm';
5
5