Skip to content

Commit 5e4206d

Browse files
committed
fix sonar qube findings and add tests
1 parent 8acf8db commit 5e4206d

File tree

6 files changed

+302
-27
lines changed

6 files changed

+302
-27
lines changed

src/users/db/dbusers.service.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,19 @@
1-
import { HttpException, HttpStatus } from '@nestjs/common';
1+
import { HttpException, HttpStatus, Logger } from '@nestjs/common';
22
import { CreateUserDto } from '../dto/user-create.dto';
33
import { UserLoginResponseDto } from '../dto/user-login-response.dto';
44
import { PrismaService } from '../../prisma/prisma.service';
55
import { User } from '@prisma/client';
66
import { UpdateUserDto } from '../dto/user-update.dto';
77
import { AuthService } from '../../auth/auth.service';
88
import { UserLoginRequestDto } from '../dto/user-login-request.dto';
9-
import { Logger } from '@nestjs/common';
109
import { Users } from '../users.interface';
1110

1211
export class DbUsersService implements Users {
1312
private readonly logger: Logger = new Logger(DbUsersService.name);
1413

1514
constructor(
16-
private prismaService: PrismaService,
17-
private authService: AuthService
15+
private readonly prismaService: PrismaService,
16+
private readonly authService: AuthService
1817
) {}
1918

2019
async create(createUserDto: CreateUserDto): Promise<UserLoginResponseDto> {
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
import { Test, TestingModule } from '@nestjs/testing';
2+
import { LdapUsersService } from './ldapusers.service';
3+
import { AuthService } from '../../auth/auth.service';
4+
import { PrismaService } from '../../prisma/prisma.service';
5+
import { ConfigService } from '@nestjs/config';
6+
import { Role, User } from '@prisma/client';
7+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
8+
import { Entry as LdapEntry, Client as LdapClient, SearchOptions, SearchResult } from 'ldapts';
9+
10+
jest.mock('ldapts', () => {
11+
const mockLdapClient = {
12+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
13+
search: jest.fn((_searchDN, searchOptions: SearchOptions): Promise<SearchResult> => {
14+
if (searchOptions.filter.toString().includes('[email protected]')) {
15+
return Promise.resolve({
16+
searchEntries: [
17+
{
18+
dn: 'dn',
19+
LDAP_ATTRIBUTE_MAIL: '[email protected]',
20+
LDAP_ATTRIBUTE_FIRST_NAME: 'first',
21+
LDAP_ATTRIBUTE_LAST_NAME: 'last',
22+
},
23+
],
24+
searchReferences: [],
25+
});
26+
} else {
27+
return Promise.resolve({ searchEntries: [], searchReferences: [] });
28+
}
29+
}),
30+
bind: jest.fn(),
31+
unbind: jest.fn(),
32+
};
33+
34+
return {
35+
Client: jest.fn(() => mockLdapClient),
36+
};
37+
});
38+
39+
const user: User = {
40+
id: '1',
41+
42+
firstName: 'John',
43+
lastName: 'Doe',
44+
apiKey: 'generatedApiKey',
45+
password: 'encryptedPassword',
46+
isActive: true,
47+
role: Role.editor,
48+
updatedAt: new Date(),
49+
createdAt: new Date(),
50+
};
51+
52+
describe('LdapUsersService match from ldap', () => {
53+
let service: LdapUsersService;
54+
let prismaService: PrismaService;
55+
let configService: ConfigService;
56+
let authService: AuthService;
57+
58+
beforeEach(async () => {
59+
const module: TestingModule = await Test.createTestingModule({
60+
providers: [
61+
{
62+
provide: ConfigService,
63+
useValue: {
64+
get: jest.fn().mockReturnValue('true'),
65+
getOrThrow: jest.fn((string) => (string === 'LDAP_USERS_SEARCH_FILTER' ? '(&(mail={{email}}))' : string)),
66+
},
67+
},
68+
{
69+
provide: PrismaService,
70+
useValue: {
71+
user: {
72+
findMany: jest.fn().mockResolvedValueOnce([]),
73+
findUnique: jest.fn(),
74+
create: jest.fn(),
75+
update: jest.fn(),
76+
},
77+
},
78+
},
79+
{
80+
provide: AuthService,
81+
useValue: {
82+
generateApiKey: jest.fn(() => 'generatedApiKey'),
83+
encryptPassword: jest.fn(() => 'encryptedPassword'),
84+
signToken: jest.fn(() => 'token'),
85+
},
86+
},
87+
],
88+
}).compile();
89+
configService = module.get<ConfigService>(ConfigService);
90+
prismaService = module.get<PrismaService>(PrismaService);
91+
authService = module.get<AuthService>(AuthService);
92+
service = new LdapUsersService(configService, prismaService, authService);
93+
});
94+
95+
it('should be defined', () => {
96+
expect(service).toBeDefined();
97+
});
98+
99+
it('should create new user on login', async () => {
100+
jest.spyOn(prismaService.user, 'findUnique').mockResolvedValue(undefined);
101+
const prismaUserCreateMock = jest.spyOn(prismaService.user, 'create').mockResolvedValue(user);
102+
await service.login({ email: '[email protected]', password: 'password' });
103+
expect(prismaUserCreateMock).toBeCalled();
104+
});
105+
106+
it('should login with user already in db', async () => {
107+
jest.spyOn(prismaService.user, 'findUnique').mockResolvedValue(user);
108+
const prismaUserCreateMock = jest.spyOn(prismaService.user, 'create');
109+
await service.login({ email: '[email protected]', password: 'password' });
110+
expect(prismaUserCreateMock).not.toBeCalled();
111+
});
112+
});
113+
114+
describe('LdapUsersService with no results from ldap', () => {
115+
let service: LdapUsersService;
116+
let prismaService: PrismaService;
117+
let configService: ConfigService;
118+
let authService: AuthService;
119+
120+
beforeEach(async () => {
121+
const module: TestingModule = await Test.createTestingModule({
122+
providers: [
123+
{
124+
provide: ConfigService,
125+
useValue: {
126+
get: jest.fn().mockReturnValue('true'),
127+
getOrThrow: jest.fn().mockReturnValue('string'),
128+
},
129+
},
130+
{
131+
provide: PrismaService,
132+
useValue: {
133+
user: {
134+
findMany: jest.fn().mockResolvedValueOnce([]),
135+
create: jest.fn(),
136+
update: jest.fn(),
137+
},
138+
},
139+
},
140+
{
141+
provide: AuthService,
142+
useValue: {
143+
generateApiKey: jest.fn(() => 'generatedApiKey'),
144+
encryptPassword: jest.fn(() => 'encryptedPassword'),
145+
},
146+
},
147+
],
148+
}).compile();
149+
configService = module.get<ConfigService>(ConfigService);
150+
prismaService = module.get<PrismaService>(PrismaService);
151+
authService = module.get<AuthService>(AuthService);
152+
service = new LdapUsersService(configService, prismaService, authService);
153+
});
154+
155+
it('should be defined', () => {
156+
expect(service).toBeDefined();
157+
});
158+
159+
it('should never change a password', async () => {
160+
const prismaUserCreateMock = jest.spyOn(prismaService.user, 'create');
161+
const prismaUserUpdateMock = jest.spyOn(prismaService.user, 'update');
162+
const result = await service.changePassword(user, 'newPassword');
163+
expect(prismaUserCreateMock).not.toBeCalled();
164+
expect(prismaUserUpdateMock).not.toBeCalled();
165+
expect(result).toBe(true);
166+
});
167+
168+
it('should not login when ldap search results are empty', async () => {
169+
expect.assertions(1);
170+
try {
171+
await service.login({ email: 'testÜ*()\\\[email protected]', password: 'password' });
172+
} catch (e) {
173+
expect(e.message).toBe('Invalid email or password.');
174+
}
175+
});
176+
});

src/users/ldap/ldapusers.service.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
1-
import { HttpException, HttpStatus } from '@nestjs/common';
1+
import { HttpException, HttpStatus, Logger } from '@nestjs/common';
22
import { CreateUserDto } from '../dto/user-create.dto';
33
import { UserLoginResponseDto } from '../dto/user-login-response.dto';
44
import { PrismaService } from '../../prisma/prisma.service';
55
import { Role, User } from '@prisma/client';
66
import { UpdateUserDto } from '../dto/user-update.dto';
77
import { AuthService } from '../../auth/auth.service';
88
import { UserLoginRequestDto } from '../dto/user-login-request.dto';
9-
import { Logger } from '@nestjs/common';
109
import { Entry as LdapEntry, Client as LdapClient } from 'ldapts';
1110
import { Users } from '../users.interface';
1211
import { ConfigService } from '@nestjs/config';
@@ -29,9 +28,9 @@ export class LdapUsersService implements Users {
2928
private readonly ldapConfig: LDAPConfig;
3029

3130
constructor(
32-
private configService: ConfigService,
33-
private prismaService: PrismaService,
34-
private authService: AuthService
31+
private readonly configService: ConfigService,
32+
private readonly prismaService: PrismaService,
33+
private readonly authService: AuthService
3534
) {
3635
this.ldapConfig = {
3736
url: this.configService.getOrThrow<string>('LDAP_URL'),

src/users/users.factory.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ export class UsersFactoryService {
1111
private readonly logger: Logger = new Logger(UsersFactoryService.name);
1212

1313
constructor(
14-
private configService: ConfigService,
15-
private prismaService: PrismaService,
16-
private authService: AuthService
14+
private readonly configService: ConfigService,
15+
private readonly prismaService: PrismaService,
16+
private readonly authService: AuthService
1717
) {}
1818

1919
getUsersService(): Users {

0 commit comments

Comments
 (0)