Skip to content

Commit 423c2ec

Browse files
committedFeb 17, 2023
feat: add session auth with redis cache
- style: sort imports - chore: delete jwt
1 parent 74a13e1 commit 423c2ec

31 files changed

+229
-205
lines changed
 

‎.eslintrc.js

+9
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,14 @@ module.exports = {
2121
'@typescript-eslint/explicit-function-return-type': 'off',
2222
'@typescript-eslint/explicit-module-boundary-types': 'off',
2323
'@typescript-eslint/no-explicit-any': 'off',
24+
'sort-imports': [
25+
'error',
26+
{
27+
ignoreCase: false,
28+
ignoreDeclarationSort: false,
29+
ignoreMemberSort: false,
30+
allowSeparatedGroups: true,
31+
},
32+
],
2433
},
2534
};

‎package.json

+3-3
Original file line numberDiff line numberDiff line change
@@ -25,21 +25,21 @@
2525
"dependencies": {
2626
"@nestjs/common": "^9.0.0",
2727
"@nestjs/core": "^9.0.0",
28-
"@nestjs/jwt": "^10.0.2",
2928
"@nestjs/passport": "^9.0.1",
3029
"@nestjs/platform-express": "^9.0.0",
3130
"@nestjs/sequelize": "^9.0.0",
3231
"@nestjs/swagger": "^6.1.4",
3332
"bindings": "^1.5.0",
3433
"class-transformer": "^0.5.1",
3534
"class-validator": "^0.14.0",
35+
"connect-redis": "^6.1.3",
3636
"express-session": "^1.17.3",
37+
"ioredis": "^5.3.1",
3738
"lodash": "^4.17.21",
3839
"mysql2": "^3.1.0",
3940
"node-addon-api": "^5.1.0",
4041
"openid-client": "^5.3.2",
4142
"passport": "^0.6.0",
42-
"passport-jwt": "^4.0.1",
4343
"passport-local": "^1.0.0",
4444
"pg": "^8.9.0",
4545
"reflect-metadata": "^0.1.13",
@@ -54,13 +54,13 @@
5454
"@nestjs/schematics": "^9.0.0",
5555
"@nestjs/testing": "^9.0.0",
5656
"@types/bindings": "^1.5.1",
57+
"@types/connect-redis": "^0.0.20",
5758
"@types/express": "^4.17.13",
5859
"@types/express-session": "^1.17.6",
5960
"@types/jest": "29.2.4",
6061
"@types/lodash": "^4.14.191",
6162
"@types/node": "18.11.18",
6263
"@types/passport": "^1.0.12",
63-
"@types/passport-jwt": "^3.0.8",
6464
"@types/passport-local": "^1.0.35",
6565
"@types/sequelize": "^4.28.14",
6666
"@types/supertest": "^2.0.11",

‎pnpm-lock.yaml

+92-91
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎src/app.module.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ import { Module } from '@nestjs/common';
22

33
import { DatabaseConfig } from '@/config/database.config';
44

5-
import { SupernodeModule } from '@/modules/supernode/supernode.module';
6-
import { OidcModule } from '@/auth/oidc/oidc.module';
7-
import { UserModule } from '@/modules/user/user.module';
85
import { AuditModule } from '@/modules/audit/audit.module';
96
import { LocalAuthModule } from '@/auth/local/local.module';
7+
import { OidcModule } from '@/auth/oidc/oidc.module';
8+
import { SupernodeModule } from '@/modules/supernode/supernode.module';
9+
import { UserModule } from '@/modules/user/user.module';
1010

1111
@Module({
1212
imports: [

‎src/auth/jwt/jwt.module.ts

-15
This file was deleted.

‎src/auth/jwt/jwt.strategy.ts

-18
This file was deleted.

‎src/auth/local/local.controller.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
import { LocalAuthGuard } from '@/common/guards/local-auth.guard';
2-
import { Controller, Delete, Post, Req, UseGuards } from '@nestjs/common';
31
import { ApiOperation, ApiTags } from '@nestjs/swagger';
2+
import { Controller, Delete, Post, Req, UseGuards } from '@nestjs/common';
3+
4+
import { LocalAuthGuard } from '@/common/guards/local-auth.guard';
5+
46
import { LocalAuthService } from './local.service';
57

68
@ApiTags('Auth')

‎src/auth/local/local.module.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import { Module } from '@nestjs/common';
22
import { PassportModule } from '@nestjs/passport';
33

4-
import { UserModule } from '@/modules/user/user.module';
54
import { SessionSerializer } from '@/auth/session/session.serializer';
5+
import { UserModule } from '@/modules/user/user.module';
66

7-
import { LocalAuthStrategy } from './local.strategy';
8-
import { LocalAuthService } from './local.service';
97
import { LocalAuthController } from './local.controller';
8+
import { LocalAuthService } from './local.service';
9+
import { LocalAuthStrategy } from './local.strategy';
1010

1111
@Module({
1212
imports: [UserModule, PassportModule.register({ session: true })],

‎src/auth/local/local.service.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Injectable } from '@nestjs/common';
22

3-
import { UserService } from '@/modules/user/user.service';
43
import { User as UserModel } from '@/modules/user/entities/user.entity';
4+
import { UserService } from '@/modules/user/user.service';
55

66
@Injectable()
77
export class LocalAuthService {

‎src/auth/local/local.strategy.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import { Strategy } from 'passport-local';
2-
import { PassportStrategy } from '@nestjs/passport';
31
import { Injectable, UnauthorizedException } from '@nestjs/common';
2+
import { PassportStrategy } from '@nestjs/passport';
3+
import { Strategy } from 'passport-local';
4+
45
import { LocalAuthService } from './local.service';
56

67
@Injectable()

‎src/auth/oidc/oidc.controller.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
1-
import { Controller, Delete, Get, Req, Res, UseGuards } from '@nestjs/common';
21
import { ApiOperation, ApiTags } from '@nestjs/swagger';
2+
import { Controller, Delete, Get, Req, Res, UseGuards } from '@nestjs/common';
33
import { Request, Response } from 'express';
4+
import { Issuer } from 'openid-client';
45

5-
import { OidcGuard } from '@/common/guards/oidc.guard';
6+
import { AuthenticatedGuard } from '@/common/guards/authenticated.guard';
67
import { LoggerProvider } from '@/utils/logger.util';
7-
8-
import { OidcService } from './oidc.service';
8+
import { OidcGuard } from '@/common/guards/oidc.guard';
99
import { OidcUserDto } from '@/modules/user/dto/oidc-user.dto';
10-
import { AuthenticatedGuard } from '@/common/guards/authenticated.guard';
11-
import { Issuer } from 'openid-client';
1210
import { useConfig } from '@/utils/config.util';
1311

12+
import { OidcService } from './oidc.service';
13+
1414
@ApiTags('Auth')
1515
@Controller()
1616
export class OidcController extends LoggerProvider {

‎src/auth/oidc/oidc.module.ts

+3-5
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
import { Module } from '@nestjs/common';
22
import { PassportModule } from '@nestjs/passport';
33

4-
import { useConfig } from '@/utils/config.util';
54
import { AuditModule } from '@/modules/audit/audit.module';
5+
import { SessionSerializer } from '@/auth/session/session.serializer';
66
import { UserModule } from '@/modules/user/user.module';
7-
import { JwtAuthModule } from '@/auth/jwt/jwt.module';
7+
import { useConfig } from '@/utils/config.util';
88

99
import { OidcStrategy, buildOpenIdClient } from './oidc.strategy';
10-
import { OidcService } from './oidc.service';
1110
import { OidcController } from './oidc.controller';
12-
import { SessionSerializer } from '../session/session.serializer';
11+
import { OidcService } from './oidc.service';
1312

1413
const config = useConfig();
1514

@@ -30,7 +29,6 @@ const OidcStrategyFactory = {
3029
PassportModule.register({ session: true }),
3130
AuditModule,
3231
UserModule,
33-
JwtAuthModule,
3432
],
3533
controllers: [OidcController],
3634
providers: [OidcStrategyFactory, OidcService, SessionSerializer],

‎src/auth/oidc/oidc.strategy.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ import { useConfig } from '@/utils/config.util';
33
import { UnauthorizedException } from '@nestjs/common';
44
import { PassportStrategy } from '@nestjs/passport';
55
import {
6-
Strategy,
76
Client,
8-
UserinfoResponse,
9-
TokenSet,
107
Issuer,
8+
Strategy,
9+
TokenSet,
10+
UserinfoResponse,
1111
} from 'openid-client';
1212
import { OidcService } from './oidc.service';
1313

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
2+
3+
@Injectable()
4+
export class AdministrationGuard implements CanActivate {
5+
async canActivate(context: ExecutionContext) {
6+
const request = context.switchToHttp().getRequest();
7+
return request.user.isAdmin;
8+
}
9+
}

‎src/common/guards/authenticated.guard.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ExecutionContext, Injectable, CanActivate } from '@nestjs/common';
1+
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
22

33
@Injectable()
44
export class AuthenticatedGuard implements CanActivate {

‎src/common/guards/jwt-auth.guard.ts

-5
This file was deleted.

‎src/common/pipes/validation.pipe.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import {
22
ArgumentMetadata,
3+
BadRequestException,
34
Injectable,
45
PipeTransform,
5-
BadRequestException,
66
} from '@nestjs/common';
77
import { validate } from 'class-validator';
88
import { plainToClass } from 'class-transformer';

‎src/main.ts

+17-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
import * as ConnectRedis from 'connect-redis';
2+
import * as passport from 'passport';
3+
import * as session from 'express-session';
4+
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
15
import { NestFactory } from '@nestjs/core';
2-
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
6+
import { Redis } from 'ioredis';
37
import { VersioningType } from '@nestjs/common';
4-
import * as session from 'express-session';
5-
import * as passport from 'passport';
68

79
import { LogLevels } from '@/utils/logger.util';
810
import { useConfig } from '@/utils/config.util';
@@ -14,10 +16,12 @@ async function bootstrap() {
1416
const app = await NestFactory.create(AppModule, {
1517
logger: LogLevels.slice(0, config.app.logLevel),
1618
});
19+
1720
// Versioning API
1821
app.enableVersioning({
1922
type: VersioningType.URI,
2023
});
24+
2125
// Swagger & OpenAPI
2226
const swaggerBuilder = new DocumentBuilder()
2327
.setTitle('Supernode server')
@@ -26,22 +30,31 @@ async function bootstrap() {
2630
.build();
2731
const document = SwaggerModule.createDocument(app, swaggerBuilder);
2832
SwaggerModule.setup('swagger', app, document);
33+
2934
// Session & Authentication
35+
const RedisSessionStore = ConnectRedis(session);
3036
app.use(
3137
session({
38+
store: config.cache.redisUrl
39+
? new RedisSessionStore({
40+
client: new Redis(config.cache.redisUrl),
41+
logErrors: true,
42+
})
43+
: new session.MemoryStore(),
3244
secret: 'secret', // to sign session id
3345
resave: false, // will default to false in near future: https://github.com/expressjs/session#resave
3446
saveUninitialized: false, // will default to false in near future: https://github.com/expressjs/session#saveuninitialized
3547
rolling: true, // keep session alive
3648
cookie: {
37-
maxAge: 30 * 60 * 1000, // session expires in 1hr, refreshed by `rolling: true` option.
49+
maxAge: 60 * 60 * 1000, // session expires in 1hr, refreshed by `rolling: true` option.
3850
httpOnly: true, // so that cookie can't be accessed via client-side script
3951
},
4052
}),
4153
);
4254
app.use(passport.initialize());
4355
app.use(passport.session());
4456

57+
// Start app
4558
await app.listen(3000);
4659
}
4760
bootstrap();

‎src/modules/audit/audit.controller.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Controller, Get, Query } from '@nestjs/common';
22
import { ApiOperation, ApiTags } from '@nestjs/swagger';
33

4-
import { PaginationOptions, Pagination } from '@/utils/pagination.util';
4+
import { Pagination, PaginationOptions } from '@/utils/pagination.util';
55

66
import { AuditService } from './audit.service';
77
import { AuditLog as AuditLogModel } from './entities/audit.entity';

‎src/modules/audit/entities/audit.entity.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import {
2-
Table,
3-
Model,
4-
Column,
52
BelongsTo,
3+
Column,
64
ForeignKey,
5+
Model,
6+
Table,
77
} from 'sequelize-typescript';
88

99
import { User } from '@/modules/user/entities/user.entity';

‎src/modules/supernode/community.entity.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import {
2-
Model,
3-
Table,
4-
Column,
5-
HasMany,
62
BelongsTo,
3+
Column,
74
ForeignKey,
5+
HasMany,
6+
Model,
7+
Table,
88
} from 'sequelize-typescript';
99

1010
@Table

‎src/modules/supernode/supernode.module.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import { Module } from '@nestjs/common';
2-
import { SupernodeService } from './supernode.service';
3-
import { SupernodeControllerV1 } from './supernode.controller';
42
import { SequelizeModule } from '@nestjs/sequelize';
3+
54
import { Community, CommunityUser } from './community.entity';
5+
import { SupernodeControllerV1 } from './supernode.controller';
6+
import { SupernodeService } from './supernode.service';
67

78
@Module({
89
imports: [SequelizeModule.forFeature([Community, CommunityUser])],

‎src/modules/supernode/supernode.service.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import { Injectable, OnModuleDestroy, OnModuleInit } from '@nestjs/common';
22
import { InjectModel } from '@nestjs/sequelize';
33
import {
4+
Community as NativeCommunity,
45
createServer,
6+
getCommunities,
57
loadCommunities,
68
startServer,
79
stopServer,
8-
getCommunities,
9-
Community as NativeCommunity,
1010
} from '@/utils/native.util';
1111
import { LoggerProvider } from '@/utils/logger.util';
1212
import { Community as CommunityModal } from './community.entity';

‎src/modules/user/dto/create-user.dto.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { ApiProperty } from '@nestjs/swagger';
21
import {
32
Equals,
43
IsBoolean,
@@ -7,6 +6,7 @@ import {
76
IsOptional,
87
IsString,
98
} from 'class-validator';
9+
import { ApiProperty } from '@nestjs/swagger';
1010

1111
export class CreateUserDto {
1212
@ApiProperty({ example: 'username', description: '用户名' })

‎src/modules/user/dto/update-user.dto.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
import { ApiProperty } from '@nestjs/swagger';
21
import {
3-
IsOptional,
4-
IsString,
52
IsBoolean,
6-
IsEmpty,
73
IsEmail,
4+
IsEmpty,
5+
IsOptional,
6+
IsString,
87
} from 'class-validator';
8+
import { ApiProperty } from '@nestjs/swagger';
99

1010
export class UpdateUserDto {
1111
@ApiProperty({ example: 'username', description: '用户名', required: false })

‎src/modules/user/entities/user.entity.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Table, Column, Model, Default } from 'sequelize-typescript';
1+
import { Column, Default, Model, Table } from 'sequelize-typescript';
22

33
@Table
44
export class User extends Model {

‎src/modules/user/user.controller.ts

+29-11
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { ApiOperation, ApiTags } from '@nestjs/swagger';
12
import {
23
Body,
34
Controller,
@@ -7,19 +8,20 @@ import {
78
Post,
89
Put,
910
Query,
11+
Req,
1012
UseGuards,
1113
UsePipes,
1214
ValidationPipe,
1315
} from '@nestjs/common';
14-
import { ApiOperation, ApiTags } from '@nestjs/swagger';
1516

1617
import { Pagination, PaginationOptions } from '@/utils/pagination.util';
18+
import { AdministrationGuard } from '@/common/guards/administration.guard';
19+
import { AuthenticatedGuard } from '@/common/guards/authenticated.guard';
1720

18-
import { User as UserModel } from './entities/user.entity';
1921
import { CreateUserDto } from './dto/create-user.dto';
2022
import { UpdateUserDto } from './dto/update-user.dto';
23+
import { User as UserModel } from './entities/user.entity';
2124
import { UserService } from './user.service';
22-
import { AuthenticatedGuard } from '@/common/guards/authenticated.guard';
2325

2426
@ApiTags('Users')
2527
@Controller({
@@ -30,7 +32,7 @@ export class UserControllerV1 {
3032
constructor(private readonly _userService: UserService) {}
3133

3234
@ApiOperation({ summary: '列出用户列表' })
33-
@UseGuards(AuthenticatedGuard)
35+
@UseGuards(AuthenticatedGuard, AdministrationGuard)
3436
@UsePipes(new ValidationPipe({ transform: true }))
3537
@Get()
3638
async list(
@@ -40,34 +42,50 @@ export class UserControllerV1 {
4042
}
4143

4244
@ApiOperation({ summary: '获取特定id的用户' })
43-
@UseGuards(AuthenticatedGuard)
45+
@UseGuards(AuthenticatedGuard, AdministrationGuard)
4446
@UsePipes(new ValidationPipe({ transform: true }))
4547
@Get(':id')
4648
async get(@Param('id') userId: number): Promise<UserModel> {
4749
return await this._userService.get(userId);
4850
}
4951

5052
@ApiOperation({ summary: '添加用户' })
51-
@UseGuards(AuthenticatedGuard)
52-
@Post()
53+
@UseGuards(AuthenticatedGuard, AdministrationGuard)
5354
@UsePipes(new ValidationPipe({ transform: true }))
55+
@Post()
5456
async create(@Body() body: CreateUserDto) {
5557
return await this._userService.create(body);
5658
}
5759

5860
@ApiOperation({ summary: '更新用户' })
59-
@UseGuards(AuthenticatedGuard)
60-
@Put(':id')
61+
@UseGuards(AuthenticatedGuard, AdministrationGuard)
6162
@UsePipes(new ValidationPipe({ transform: true }))
63+
@Put(':id')
6264
async update(@Param('id') userId: number, @Body() body: UpdateUserDto) {
6365
return await this._userService.update(userId, body);
6466
}
6567

6668
@ApiOperation({ summary: '删除用户' })
67-
@UseGuards(AuthenticatedGuard)
68-
@Delete(':id')
69+
@UseGuards(AuthenticatedGuard, AdministrationGuard)
6970
@UsePipes(new ValidationPipe({ transform: true }))
71+
@Delete(':id')
7072
async destroy(@Param('id') userId: number) {
7173
return await this._userService.destroy(userId);
7274
}
75+
76+
@ApiOperation({ summary: '获取自己的用户信息' })
77+
@UseGuards(AuthenticatedGuard)
78+
@Get('me')
79+
async me(@Req() req: any) {
80+
return req.user;
81+
}
82+
83+
@ApiOperation({ summary: '更新自己的用户信息' })
84+
@UseGuards(AuthenticatedGuard)
85+
@UsePipes(new ValidationPipe({ transform: true }))
86+
@Put('me')
87+
async updateMe(@Req() req: any, @Body() body: UpdateUserDto) {
88+
const userId = req.user.userId;
89+
return await this._userService.update(userId, body);
90+
}
7391
}

‎src/modules/user/user.module.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ import { SequelizeModule } from '@nestjs/sequelize';
33

44
import { AuditModule } from '@/modules/audit/audit.module';
55

6-
import { UserControllerV1 } from './user.controller';
76
import { User } from './entities/user.entity';
7+
import { UserControllerV1 } from './user.controller';
88
import { UserService } from './user.service';
99

1010
@Module({

‎src/modules/user/user.service.ts

+6-5
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,22 @@
11
import { Injectable, NotFoundException } from '@nestjs/common';
22
import { InjectModel } from '@nestjs/sequelize';
3+
import { Op } from 'sequelize';
34
import { isNull } from 'lodash';
45

5-
import { LoggerProvider } from '@/utils/logger.util';
66
import {
77
Pagination,
88
PaginationMeta,
99
PaginationOptions,
1010
} from '@/utils/pagination.util';
11+
import { LoggerProvider } from '@/utils/logger.util';
12+
import { useConfig } from '@/utils/config.util';
13+
1114
import { AuditService } from '@/modules/audit/audit.service';
1215

13-
import { User as UserModel } from './entities/user.entity';
1416
import { CreateUserDto } from './dto/create-user.dto';
15-
import { UpdateUserDto } from './dto/update-user.dto';
16-
import { Op } from 'sequelize';
1717
import { OidcUserDto } from './dto/oidc-user.dto';
18-
import { useConfig } from '@/utils/config.util';
18+
import { UpdateUserDto } from './dto/update-user.dto';
19+
import { User as UserModel } from './entities/user.entity';
1920

2021
@Injectable()
2122
export class UserService extends LoggerProvider {

‎src/utils/config.util.ts

+13-5
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
1-
import yaml from 'yaml';
2-
import path from 'path';
31
import * as fs from 'fs';
4-
import { PartialDeep } from '@/utils/type.util';
5-
import { LogLevel } from '@/utils/logger.util';
2+
import type { Dialect } from 'sequelize';
3+
import path from 'path';
64
import { set } from 'lodash';
5+
import yaml from 'yaml';
76

8-
import type { Dialect } from 'sequelize';
7+
import { LogLevel } from '@/utils/logger.util';
8+
import { PartialDeep } from '@/utils/type.util';
99

1010
export interface Config {
1111
app: AppConfig;
1212
dataSource: DataSourceConfig;
1313
oidc: OidcConfig;
14+
cache: CacheConfig;
1415
}
1516

1617
export interface AppConfig {
@@ -41,6 +42,10 @@ export interface DataSourceConfig {
4142
storage?: string;
4243
}
4344

45+
export interface CacheConfig {
46+
redisUrl?: string;
47+
}
48+
4449
const defaultConfig: Config = {
4550
app: {
4651
logLevel: LogLevel.log,
@@ -66,6 +71,7 @@ const defaultConfig: Config = {
6671
database: '',
6772
storage: 'data.sqlite',
6873
},
74+
cache: {},
6975
};
7076

7177
const envConfigMap: Record<string, string> = {
@@ -90,6 +96,8 @@ const envConfigMap: Record<string, string> = {
9096
DATA_SOURCE_DATABASE: 'dataSource.database',
9197
DATA_SOURCE_SCHEMA: 'dataSource.schema',
9298
DATA_SOURCE_STORAGE: 'dataSource.storage',
99+
100+
CACHE_REDIS_URL: 'cache.redisUrl',
93101
};
94102

95103
let computedConfig: Config | undefined = undefined;

‎test/app.e2e-spec.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1+
import * as request from 'supertest';
12
import { Test, TestingModule } from '@nestjs/testing';
23
import { INestApplication } from '@nestjs/common';
3-
import * as request from 'supertest';
4-
import { AppModule } from './../src/app.module';
4+
5+
import { AppModule } from '@/app.module';
56

67
describe('AppController (e2e)', () => {
78
let app: INestApplication;

0 commit comments

Comments
 (0)
Please sign in to comment.