@tomei/sso 0.1.2 → 0.2.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/README.md +7 -2
- package/__tests__/unit/components/login-history/login-history.repository.spec.ts +95 -0
- package/__tests__/unit/components/login-user/login-user.spec.ts +223 -0
- package/__tests__/unit/components/login-user/user.repository.spec.ts +81 -0
- package/__tests__/unit/components/password-hash/password-hash.service.spec.ts +33 -0
- package/__tests__/unit/components/system/system.repository.spec.ts +88 -0
- package/__tests__/unit/components/system-access/system-access.repository.spec.ts +78 -0
- package/__tests__/unit/redis-client/redis.service.spec.ts +24 -0
- package/__tests__/unit/session/session.service.spec.ts +27 -0
- package/create-sso-user.sql +1 -0
- package/dist/__tests__/unit/components/login-user/login-user.spec.d.ts +1 -0
- package/dist/__tests__/unit/components/login-user/login-user.spec.js +208 -0
- package/dist/__tests__/unit/components/login-user/login-user.spec.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/jest.config.js +15 -0
- package/package.json +21 -3
- package/prisma/migrations/0_init/migration.sql +41 -42
- package/prisma/migrations/20230528161352_create_user_user_group_and_add_new_column/migration.sql +2 -2
- package/prisma/migrations/20230606091407_create_login_histories_table/migration.sql +17 -0
- package/prisma/schema.prisma +46 -33
- package/sampledotenv +8 -0
- package/src/components/index.ts +7 -0
- package/src/components/login-history/index.ts +1 -0
- package/src/components/login-history/login-history.repository.ts +33 -0
- package/src/components/login-user/index.ts +4 -0
- package/src/components/login-user/interfaces/index.ts +1 -0
- package/src/components/login-user/interfaces/user-info.interface.ts +9 -0
- package/src/components/login-user/login-user.ts +427 -0
- package/src/components/login-user/user.repository.ts +33 -0
- package/src/components/password-hash/index.ts +2 -0
- package/src/components/password-hash/interfaces/index.ts +1 -0
- package/src/components/password-hash/interfaces/password-hash-service.interface.ts +4 -0
- package/src/components/password-hash/password-hash.service.ts +14 -0
- package/src/components/system/index.ts +1 -0
- package/src/components/system/system.repository.ts +33 -0
- package/src/components/system-access/index.ts +1 -0
- package/src/components/system-access/system-access.repository.ts +33 -0
- package/src/components/user-group/index.ts +1 -0
- package/src/components/user-group/user-group.repository.ts +33 -0
- package/src/components/user-user-group/index.ts +1 -0
- package/src/components/user-user-group/user-user-group.repository.ts +33 -0
- package/src/index.ts +7 -0
- package/src/interfaces/index.ts +2 -0
- package/src/interfaces/system-login.interface.ts +6 -0
- package/src/interfaces/user-session.interface.ts +5 -0
- package/src/mail/index.ts +2 -0
- package/src/mail/interfaces/index.ts +2 -0
- package/src/mail/interfaces/send-mail.interface.ts +8 -0
- package/src/mail/interfaces/send-new-login-alert.interface.ts +6 -0
- package/src/mail/mail.service.ts +33 -0
- package/src/mail/mail.ts +40 -0
- package/src/prisma-client/__mocks__/prisma.ts +15 -0
- package/src/prisma-client/client.ts +3 -0
- package/src/prisma-client/index.ts +1 -0
- package/src/redis-client/__mocks__/jest-initial-setup.ts +2 -0
- package/src/redis-client/__mocks__/redis-mock.ts +28 -0
- package/src/redis-client/index.ts +1 -0
- package/src/redis-client/redis.service.ts +48 -0
- package/src/session/index.ts +2 -0
- package/src/session/interfaces/index.ts +1 -0
- package/src/session/interfaces/session-service.interface.ts +6 -0
- package/src/session/session.service.ts +45 -0
- package/tsconfig.json +7 -3
- package/dist/index.d.ts +0 -0
- package/dist/index.js +0 -1
- package/dist/index.js.map +0 -1
package/README.md
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
### How to use
|
4
4
|
- run `npm i`
|
5
|
-
- Make sure you set the
|
5
|
+
- Make sure you set the environment in .sampledotenv in your project `.env` file
|
6
6
|
- run `npm run start:dev`
|
7
7
|
|
8
8
|
### How create a new migration
|
@@ -11,8 +11,13 @@
|
|
11
11
|
- Create a database user
|
12
12
|
- Grant the above user privileges to alter sso tables and shadow database. The user should have access to the sso table and shadow database only. Use `create-sso-user.sql` as an example to create the user and grant privileges
|
13
13
|
- Make changes to the `schema.prisma` file
|
14
|
-
- Run `npx prisma migrate dev --name <migration-name> --preview-feature --create-only` to create the migration. The migration will be created in the `migrations` folder.
|
14
|
+
- Run `npx prisma migrate dev --name <migration-name> --preview-feature --create-only` to create the migration. The migration will be created in the `migrations` folder.
|
15
|
+
- open the newly created migration. review the migration and make changes if necessary.
|
16
|
+
|
17
|
+
notes:
|
18
|
+
- if you create a new table, after migration has been created, change the default character set to `latin1` from `utf8mb4` and remove COLLATE phrase.please also add it to the `create-sso-user.sql` file for references
|
15
19
|
|
16
20
|
### How to run migration
|
17
21
|
- run `npx prisma migrate deploy` to run the migration
|
22
|
+
- run `npx prisma generate` to generate the prisma client
|
18
23
|
|
@@ -0,0 +1,95 @@
|
|
1
|
+
import { LoginHistory } from '@prisma/client';
|
2
|
+
import { LoginHistoryRepository } from '../../../../src/components/login-history/login-history.repository';
|
3
|
+
import { prismaMock } from '../../../../src/prisma-client/__mocks__/prisma';
|
4
|
+
|
5
|
+
describe('login-history.repository', () => {
|
6
|
+
afterEach(() => {
|
7
|
+
jest.restoreAllMocks()
|
8
|
+
})
|
9
|
+
describe('findAll', () => {
|
10
|
+
it('should return list of login history', async () => {
|
11
|
+
const data = [{
|
12
|
+
userId: 1,
|
13
|
+
systemId: 1,
|
14
|
+
originIp: '1.1.1.1',
|
15
|
+
createdAt: new Date(),
|
16
|
+
}]
|
17
|
+
prismaMock.loginHistory.findMany.mockResolvedValueOnce(data as LoginHistory[])
|
18
|
+
const loginHistoryRepository = new LoginHistoryRepository()
|
19
|
+
expect(await loginHistoryRepository.findAll({})).toEqual(data)
|
20
|
+
})
|
21
|
+
})
|
22
|
+
|
23
|
+
describe('findOne', () => {
|
24
|
+
it('should return login history', async () => {
|
25
|
+
const data = {
|
26
|
+
userId: 1,
|
27
|
+
systemId: 1,
|
28
|
+
originIp: '1.1.1.1',
|
29
|
+
createdAt: new Date(),
|
30
|
+
}
|
31
|
+
prismaMock.loginHistory.findFirst.mockResolvedValueOnce(data as LoginHistory)
|
32
|
+
const loginHistoryRepository = new LoginHistoryRepository()
|
33
|
+
expect(await loginHistoryRepository.findOne({
|
34
|
+
where: {
|
35
|
+
userId_systemId: {
|
36
|
+
userId: data.userId,
|
37
|
+
systemId: data.systemId,
|
38
|
+
},
|
39
|
+
},
|
40
|
+
})).toEqual(data)
|
41
|
+
})
|
42
|
+
})
|
43
|
+
|
44
|
+
describe('create', () => {
|
45
|
+
it('should create login history', async () => {
|
46
|
+
const data = {
|
47
|
+
userId: 1,
|
48
|
+
systemId: 1,
|
49
|
+
originIp: '1.1.1.1',
|
50
|
+
createdAt: new Date(),
|
51
|
+
}
|
52
|
+
prismaMock.loginHistory.create.mockResolvedValueOnce(data as LoginHistory)
|
53
|
+
const loginHistoryRepository = new LoginHistoryRepository()
|
54
|
+
expect(await loginHistoryRepository.create({data})).toEqual(data)
|
55
|
+
})
|
56
|
+
})
|
57
|
+
|
58
|
+
describe('update', () => {
|
59
|
+
it('should update login history', async () => {
|
60
|
+
const data = {
|
61
|
+
userId: 1,
|
62
|
+
systemId: 1,
|
63
|
+
originIp: '1.1.1.1',
|
64
|
+
createdAt: new Date(),
|
65
|
+
}
|
66
|
+
prismaMock.loginHistory.update.mockResolvedValueOnce(data as LoginHistory)
|
67
|
+
const loginHistoryRepository = new LoginHistoryRepository()
|
68
|
+
expect(await loginHistoryRepository.update({
|
69
|
+
where: {
|
70
|
+
userId: data.userId
|
71
|
+
}, data: data
|
72
|
+
}, data)).toEqual(data)
|
73
|
+
})
|
74
|
+
})
|
75
|
+
|
76
|
+
describe('delete', () => {
|
77
|
+
it('should delete login history', async () => {
|
78
|
+
const data = {
|
79
|
+
userId: 1,
|
80
|
+
systemId: 1,
|
81
|
+
originIp: '1.1.1.1',
|
82
|
+
createdAt: new Date(),
|
83
|
+
}
|
84
|
+
prismaMock.loginHistory.delete.mockResolvedValueOnce(data as LoginHistory)
|
85
|
+
const loginHistoryRepository = new LoginHistoryRepository()
|
86
|
+
expect(await loginHistoryRepository.delete({
|
87
|
+
where: {
|
88
|
+
userId: data.userId
|
89
|
+
}
|
90
|
+
})).toEqual(data)
|
91
|
+
})
|
92
|
+
})
|
93
|
+
|
94
|
+
})
|
95
|
+
|
@@ -0,0 +1,223 @@
|
|
1
|
+
import { IUserSession } from '../../../../src/interfaces/user-session.interface';
|
2
|
+
import { LoginHistoryRepository, SessionService, SystemAccessRepository, SystemRepository } from '../../../../src';
|
3
|
+
import { LoginUser } from '../../../../src/components/login-user/login-user';
|
4
|
+
import { UserRepository } from '../../../../src/components/login-user/user.repository';
|
5
|
+
import { PasswordHashService } from '../../../../src/components/password-hash/password-hash.service';
|
6
|
+
import { MailService } from '../../../../src/mail/mail.service';
|
7
|
+
describe('login-user', () => {
|
8
|
+
const user = {
|
9
|
+
id: 755,
|
10
|
+
email: 'ezcash+florence@tomei.com.my',
|
11
|
+
password:
|
12
|
+
'$argon2id$v=19$m=4096,t=3,p=1$571ilUAi9n5g393m/NqKbQ$2bMnLtMCIVTjHWHGEDxI2wo+A3mrL3N5rTxDJ6ydPi8',
|
13
|
+
status: null,
|
14
|
+
defaultPasswordChanged: false,
|
15
|
+
firstLoginAt: new Date('2023-01-10T07:57:10.000Z'),
|
16
|
+
createdAt: new Date('2023-01-10T07:57:10.000Z'),
|
17
|
+
updatedAt: new Date('2023-01-10T08:58:15.000Z'),
|
18
|
+
groupCode: 'EZCFT',
|
19
|
+
staffs: [
|
20
|
+
{
|
21
|
+
id: 740,
|
22
|
+
staffId: 'EZC003',
|
23
|
+
fullName: 'EZC Florence',
|
24
|
+
preferredName: 'EZC Florence',
|
25
|
+
email: 'ezcash+florence@tomei.com.my',
|
26
|
+
staffTypeId: 1,
|
27
|
+
jobTitle: 'EZC Finance',
|
28
|
+
carPlate: '',
|
29
|
+
mobile: '60123456',
|
30
|
+
floor: null,
|
31
|
+
extension: null,
|
32
|
+
isCharge: false,
|
33
|
+
status: 'active',
|
34
|
+
userId: 755,
|
35
|
+
buildingId: 20,
|
36
|
+
departmentId: 110,
|
37
|
+
companyId: 70,
|
38
|
+
createdById: 74,
|
39
|
+
updatedById: 74,
|
40
|
+
createdAt: new Date('2023-01-10T07:57:10.000Z'),
|
41
|
+
updatedAt: new Date('2023-01-10T07:57:10.000Z'),
|
42
|
+
image: null,
|
43
|
+
idNo: '123123123',
|
44
|
+
fullAddress: 'Lorem Address',
|
45
|
+
},
|
46
|
+
],
|
47
|
+
userSystemPrivileges: [
|
48
|
+
{
|
49
|
+
userId: 22,
|
50
|
+
privilegeId: 'ckymxuh8t000137t011w89zgk',
|
51
|
+
isInheritedYN: 'N',
|
52
|
+
isRevokedYN: 'N',
|
53
|
+
createdAt: new Date('2022-04-18T04:07:40.000Z'),
|
54
|
+
updatedAt: new Date('2022-04-18T04:07:40.000Z'),
|
55
|
+
systemPrivilege: {
|
56
|
+
privilegeId: 'ckymxuh8t000137t011w89zgk',
|
57
|
+
systemId: 11,
|
58
|
+
code: 'Own',
|
59
|
+
module: null,
|
60
|
+
description:
|
61
|
+
'Allows the user to only view consignments belonging to themselves',
|
62
|
+
createdAt: new Date('2022-01-20T12:16:26.000Z'),
|
63
|
+
updatedAt: new Date('2022-01-20T12:16:26.000Z'),
|
64
|
+
},
|
65
|
+
},
|
66
|
+
],
|
67
|
+
};
|
68
|
+
|
69
|
+
const system = {
|
70
|
+
id: 175,
|
71
|
+
code: 'EZC',
|
72
|
+
name: 'EzCash',
|
73
|
+
description: 'Tomei Money Lending System',
|
74
|
+
accessUrl: 'https://app.ezcash.com.my:22443/staff/login',
|
75
|
+
googlePlayUrl: '',
|
76
|
+
appleStoreUrl: '',
|
77
|
+
apiKey: 'VqS9ks2Lwvqd7HrVUMMIP2q7zaEH689HCPaEaFUQLmiRoZnt',
|
78
|
+
logo: 'https://sso-api.tomei.com.my/upload/2023/01/10/FJ3DoHdRZKjf2bGkgA4E-BrowserIcon.png',
|
79
|
+
status: 'active',
|
80
|
+
visible: true,
|
81
|
+
createdAt: new Date('2023-01-09T00:45:57.000Z'),
|
82
|
+
updatedAt: new Date('2023-01-10T06:28:56.000Z'),
|
83
|
+
apiSecret:
|
84
|
+
'$argon2id$v=19$m=4096,t=3,p=1$lqxfk/ujftswf2jSEu156g$j2IShE/BZUUoH/1jrvt3GGRSy0rA8HilJvK17e6vdFY',
|
85
|
+
updatedById: 61,
|
86
|
+
createdById: 100,
|
87
|
+
};
|
88
|
+
|
89
|
+
const systemAccess = {
|
90
|
+
userId: 755,
|
91
|
+
systemId: 175,
|
92
|
+
updatedAt: new Date('2023-01-09T00:45:57.000'),
|
93
|
+
};
|
94
|
+
|
95
|
+
const session: IUserSession = {
|
96
|
+
systemLogins: [
|
97
|
+
{
|
98
|
+
id: '175',
|
99
|
+
code: 'EZC',
|
100
|
+
sessionId: 'ckymxuh8t000137t011w89zgk',
|
101
|
+
privileges: [
|
102
|
+
'Terminate',
|
103
|
+
'Download - Agreement',
|
104
|
+
'Disbursement - Confirmation',
|
105
|
+
'Invoice Payment Received',
|
106
|
+
'Download - Disbursement Receipt',
|
107
|
+
'Download - Stamping Receipt',
|
108
|
+
'Installment Payment Received',
|
109
|
+
'View Transaction History',
|
110
|
+
'Menu - Loans',
|
111
|
+
'Loan - Full Settlement',
|
112
|
+
'View Billing',
|
113
|
+
'Loan - Retrieve List',
|
114
|
+
'Loan - View Details',
|
115
|
+
'Loan - Retrieve Outstanding',
|
116
|
+
'Loan - View Mandate Details',
|
117
|
+
'Loan Document - Retrieve List',
|
118
|
+
'Loan Document - View',
|
119
|
+
'Loan Document - Download',
|
120
|
+
'Application - View Details',
|
121
|
+
'Simple Loan Schedule - Get Overdue Schedules',
|
122
|
+
'Simple Loan Schedule - Get Schedule Payment Details',
|
123
|
+
'Retrieve Media List',
|
124
|
+
'Retrieve Customer List',
|
125
|
+
'View Loan Activity',
|
126
|
+
'Activate Installment',
|
127
|
+
'Manual Payment Receipt',
|
128
|
+
'Customer Documents - View',
|
129
|
+
],
|
130
|
+
},
|
131
|
+
],
|
132
|
+
};
|
133
|
+
|
134
|
+
jest.mock('crypto', () => {
|
135
|
+
return {
|
136
|
+
randomUUID: jest.fn().mockReturnValue('ckymxuh8t000137t011w89zgk'),
|
137
|
+
};
|
138
|
+
});
|
139
|
+
|
140
|
+
jest
|
141
|
+
.spyOn(UserRepository.prototype, 'findOne')
|
142
|
+
.mockImplementation(async () => {
|
143
|
+
return user;
|
144
|
+
});
|
145
|
+
|
146
|
+
jest
|
147
|
+
.spyOn(PasswordHashService.prototype, 'verify')
|
148
|
+
.mockImplementation(async (password, hash) => {
|
149
|
+
if (password === 'Abcd@1234') {
|
150
|
+
return true;
|
151
|
+
} else {
|
152
|
+
return false;
|
153
|
+
}
|
154
|
+
});
|
155
|
+
|
156
|
+
jest
|
157
|
+
.spyOn(SystemRepository .prototype, 'findOne')
|
158
|
+
.mockImplementation(async () => {
|
159
|
+
return system;
|
160
|
+
});
|
161
|
+
|
162
|
+
jest
|
163
|
+
.spyOn(MailService.prototype, 'sendNewLoginAlertEmail')
|
164
|
+
.mockImplementation(async () => {});
|
165
|
+
|
166
|
+
jest
|
167
|
+
.spyOn(LoginUser.prototype, 'getPrivileges')
|
168
|
+
.mockImplementation(async () => {
|
169
|
+
return session.systemLogins[0].privileges;
|
170
|
+
});
|
171
|
+
|
172
|
+
jest
|
173
|
+
.spyOn(SystemAccessRepository.prototype, 'findOne')
|
174
|
+
.mockImplementation(async () => {
|
175
|
+
return systemAccess;
|
176
|
+
});
|
177
|
+
|
178
|
+
jest
|
179
|
+
.spyOn(LoginHistoryRepository.prototype, 'findAll')
|
180
|
+
.mockImplementation(async () => {
|
181
|
+
const data = [];
|
182
|
+
return data;
|
183
|
+
})
|
184
|
+
|
185
|
+
it('should return login-user service when instansiated', async () => {
|
186
|
+
const loginUser = await LoginUser.init();
|
187
|
+
expect(loginUser).toBeDefined();
|
188
|
+
});
|
189
|
+
|
190
|
+
it('should able to do login process when no session is already available', async () => {
|
191
|
+
const loginUser = await LoginUser.init('755');
|
192
|
+
const result = await loginUser.login(
|
193
|
+
'EZC',
|
194
|
+
'ezcash+florence@tomei.com.my',
|
195
|
+
'Abcd@1234',
|
196
|
+
'1.1.1.1',
|
197
|
+
);
|
198
|
+
expect(result).toEqual('ckymxuh8t000137t011w89zgk');
|
199
|
+
});
|
200
|
+
|
201
|
+
it('should able to do login process when session is already available', async () => {
|
202
|
+
jest
|
203
|
+
.spyOn(SessionService.prototype, 'retrieveUserSession')
|
204
|
+
.mockImplementationOnce(async (userId: string) => {
|
205
|
+
if (userId === '755') {
|
206
|
+
return session;
|
207
|
+
} else {
|
208
|
+
return {
|
209
|
+
systemLogins: [],
|
210
|
+
};
|
211
|
+
}
|
212
|
+
});
|
213
|
+
|
214
|
+
const loginUser = await LoginUser.init('755');
|
215
|
+
const result = await loginUser.login(
|
216
|
+
'EZC',
|
217
|
+
'ezcash+florence@tomei.com.my',
|
218
|
+
'Abcd@1234',
|
219
|
+
'1.1.1.1',
|
220
|
+
);
|
221
|
+
expect(result).toEqual('ckymxuh8t000137t011w89zgk');
|
222
|
+
});
|
223
|
+
});
|
@@ -0,0 +1,81 @@
|
|
1
|
+
import { UserRepository } from '../../../../src/components/login-user/user.repository';
|
2
|
+
import { prismaMock } from '../../../../src/prisma-client/__mocks__/prisma';
|
3
|
+
|
4
|
+
describe('system-access.repository', () => {
|
5
|
+
const data = {
|
6
|
+
id: 1,
|
7
|
+
email: 'test@test.email.com',
|
8
|
+
password: '@H34f5yRE',
|
9
|
+
status: 'Active',
|
10
|
+
defaultPasswordChanged: false,
|
11
|
+
firstLoginAt: new Date(),
|
12
|
+
createdAt: new Date(),
|
13
|
+
updatedAt: new Date(),
|
14
|
+
groupCode: 'RDAS',
|
15
|
+
};
|
16
|
+
|
17
|
+
afterEach(() => {
|
18
|
+
jest.restoreAllMocks();
|
19
|
+
});
|
20
|
+
describe('findAll', () => {
|
21
|
+
it('should return list of user', async () => {
|
22
|
+
prismaMock.user.findMany.mockResolvedValueOnce([data]);
|
23
|
+
const userRepository = new UserRepository();
|
24
|
+
expect(await userRepository.findAll({})).toEqual([data]);
|
25
|
+
});
|
26
|
+
});
|
27
|
+
|
28
|
+
describe('findOne', () => {
|
29
|
+
it('should return user', async () => {
|
30
|
+
prismaMock.user.findFirst.mockResolvedValueOnce(data);
|
31
|
+
const userRepository = new UserRepository();
|
32
|
+
expect(
|
33
|
+
await userRepository.findOne({
|
34
|
+
where: {
|
35
|
+
id: data.id,
|
36
|
+
},
|
37
|
+
}),
|
38
|
+
).toEqual(data);
|
39
|
+
});
|
40
|
+
});
|
41
|
+
|
42
|
+
describe('create', () => {
|
43
|
+
it('should create user', async () => {
|
44
|
+
prismaMock.user.create.mockResolvedValueOnce(data);
|
45
|
+
const userRepository = new UserRepository();
|
46
|
+
expect(await userRepository.create(data)).toEqual(data);
|
47
|
+
});
|
48
|
+
});
|
49
|
+
|
50
|
+
describe('update', () => {
|
51
|
+
it('should update user', async () => {
|
52
|
+
prismaMock.user.update.mockResolvedValueOnce(data);
|
53
|
+
const userRepository = new UserRepository();
|
54
|
+
expect(
|
55
|
+
await userRepository.update(
|
56
|
+
{
|
57
|
+
where: {
|
58
|
+
id: data.id,
|
59
|
+
},
|
60
|
+
data: data,
|
61
|
+
},
|
62
|
+
data,
|
63
|
+
),
|
64
|
+
).toEqual(data);
|
65
|
+
});
|
66
|
+
});
|
67
|
+
|
68
|
+
describe('delete', () => {
|
69
|
+
it('should delete user', async () => {
|
70
|
+
prismaMock.user.delete.mockResolvedValueOnce(data);
|
71
|
+
const userRepository = new UserRepository();
|
72
|
+
expect(
|
73
|
+
await userRepository.delete({
|
74
|
+
where: {
|
75
|
+
id: data.id,
|
76
|
+
},
|
77
|
+
}),
|
78
|
+
).toEqual(data);
|
79
|
+
});
|
80
|
+
});
|
81
|
+
});
|
@@ -0,0 +1,33 @@
|
|
1
|
+
import { PasswordHashService } from "../../../../src/components/password-hash/password-hash.service";
|
2
|
+
import * as argon2 from 'argon2';
|
3
|
+
|
4
|
+
jest.mock('argon2', () => {
|
5
|
+
return {
|
6
|
+
hash: jest.fn((passowrd) => {
|
7
|
+
return `hash${passowrd}`;
|
8
|
+
}),
|
9
|
+
verify: jest.fn().mockResolvedValue(true)
|
10
|
+
}
|
11
|
+
})
|
12
|
+
|
13
|
+
describe('password-hash.service', () => {
|
14
|
+
const passwordHashService = new PasswordHashService();
|
15
|
+
afterEach(() => {
|
16
|
+
jest.clearAllMocks();
|
17
|
+
});
|
18
|
+
|
19
|
+
it('should return hash password', async () => {
|
20
|
+
const password = 'password';
|
21
|
+
const hash = await passwordHashService.hashPassword(password);
|
22
|
+
expect(hash).toEqual('hashpassword');
|
23
|
+
})
|
24
|
+
|
25
|
+
it('should return true when verify password', async () => {
|
26
|
+
const password = 'password';
|
27
|
+
const hash = 'hashpassword10';
|
28
|
+
const result = await passwordHashService.verify(password, hash);
|
29
|
+
expect(result).toEqual(true);
|
30
|
+
});
|
31
|
+
|
32
|
+
|
33
|
+
})
|
@@ -0,0 +1,88 @@
|
|
1
|
+
import { SystemRepository } from '../../../../src/components/system/system.repository';
|
2
|
+
import { prismaMock } from '../../../../src/prisma-client/__mocks__/prisma';
|
3
|
+
|
4
|
+
describe('system.repository', () => {
|
5
|
+
const data = {
|
6
|
+
id: 175,
|
7
|
+
code: 'EZC',
|
8
|
+
name: 'EzCash',
|
9
|
+
description: 'Tomei Money Lending System',
|
10
|
+
accessUrl: 'https://app.ezcash.com.my:22443/staff/login',
|
11
|
+
googlePlayUrl: '',
|
12
|
+
appleStoreUrl: '',
|
13
|
+
apiKey: 'f3fef257jt',
|
14
|
+
logo: 'https://sso-api.tomei.com.my/upload/2023/01/10/FJ3DoHdRZKjf2bGkgA4E-BrowserIcon.png',
|
15
|
+
status: 'active',
|
16
|
+
visible: true,
|
17
|
+
createdAt: new Date(),
|
18
|
+
updatedAt: new Date(),
|
19
|
+
apiSecret: '12345',
|
20
|
+
updatedById: 61,
|
21
|
+
createdById: 100,
|
22
|
+
};
|
23
|
+
|
24
|
+
afterEach(() => {
|
25
|
+
jest.restoreAllMocks();
|
26
|
+
});
|
27
|
+
describe('findAll', () => {
|
28
|
+
it('should return list of system', async () => {
|
29
|
+
prismaMock.system.findMany.mockResolvedValueOnce([data]);
|
30
|
+
const systemRepository = new SystemRepository();
|
31
|
+
expect(await systemRepository.findAll({})).toEqual([data]);
|
32
|
+
});
|
33
|
+
});
|
34
|
+
|
35
|
+
describe('findOne', () => {
|
36
|
+
it('should return system', async () => {
|
37
|
+
prismaMock.system.findFirst.mockResolvedValueOnce(data);
|
38
|
+
const systemRepository = new SystemRepository();
|
39
|
+
expect(
|
40
|
+
await systemRepository.findOne({
|
41
|
+
where: {
|
42
|
+
id: data.id,
|
43
|
+
},
|
44
|
+
}),
|
45
|
+
).toEqual(data);
|
46
|
+
});
|
47
|
+
});
|
48
|
+
|
49
|
+
describe('create', () => {
|
50
|
+
it('should create system', async () => {
|
51
|
+
prismaMock.system.create.mockResolvedValueOnce(data);
|
52
|
+
const systemRepository = new SystemRepository();
|
53
|
+
expect(await systemRepository.create(data)).toEqual(data);
|
54
|
+
});
|
55
|
+
});
|
56
|
+
|
57
|
+
describe('update', () => {
|
58
|
+
it('should update system', async () => {
|
59
|
+
prismaMock.system.update.mockResolvedValueOnce(data);
|
60
|
+
const systemRepository = new SystemRepository();
|
61
|
+
expect(
|
62
|
+
await systemRepository.update(
|
63
|
+
{
|
64
|
+
where: {
|
65
|
+
id: data.id,
|
66
|
+
},
|
67
|
+
data: data,
|
68
|
+
},
|
69
|
+
data,
|
70
|
+
),
|
71
|
+
).toEqual(data);
|
72
|
+
});
|
73
|
+
});
|
74
|
+
|
75
|
+
describe('delete', () => {
|
76
|
+
it('should delete system', async () => {
|
77
|
+
prismaMock.system.delete.mockResolvedValueOnce(data);
|
78
|
+
const systemRepository = new SystemRepository();
|
79
|
+
expect(
|
80
|
+
await systemRepository.delete({
|
81
|
+
where: {
|
82
|
+
id: data.id,
|
83
|
+
},
|
84
|
+
}),
|
85
|
+
).toEqual(data);
|
86
|
+
});
|
87
|
+
});
|
88
|
+
});
|
@@ -0,0 +1,78 @@
|
|
1
|
+
import { SystemAccessRepository } from '../../../../src/components/system-access/system-access.repository';
|
2
|
+
import { prismaMock } from '../../../../src/prisma-client/__mocks__/prisma';
|
3
|
+
|
4
|
+
describe('system-access.repository', () => {
|
5
|
+
const data = {
|
6
|
+
userId: 1,
|
7
|
+
systemId: 175,
|
8
|
+
updatedAt: new Date(),
|
9
|
+
};
|
10
|
+
|
11
|
+
afterEach(() => {
|
12
|
+
jest.restoreAllMocks();
|
13
|
+
});
|
14
|
+
describe('findAll', () => {
|
15
|
+
it('should return list of system access', async () => {
|
16
|
+
prismaMock.systemAccess.findMany.mockResolvedValueOnce([data]);
|
17
|
+
const systemAccessRepository = new SystemAccessRepository();
|
18
|
+
expect(await systemAccessRepository.findAll({})).toEqual([data]);
|
19
|
+
});
|
20
|
+
});
|
21
|
+
|
22
|
+
describe('findOne', () => {
|
23
|
+
it('should return system access', async () => {
|
24
|
+
prismaMock.systemAccess.findFirst.mockResolvedValueOnce(data);
|
25
|
+
const systemAccessRepository = new SystemAccessRepository();
|
26
|
+
expect(
|
27
|
+
await systemAccessRepository.findOne({
|
28
|
+
where: {
|
29
|
+
userId: data.userId,
|
30
|
+
systemId: data.systemId,
|
31
|
+
},
|
32
|
+
}),
|
33
|
+
).toEqual(data);
|
34
|
+
});
|
35
|
+
});
|
36
|
+
|
37
|
+
describe('create', () => {
|
38
|
+
it('should create system access', async () => {
|
39
|
+
prismaMock.systemAccess.create.mockResolvedValueOnce(data);
|
40
|
+
const systemAccessRepository = new SystemAccessRepository();
|
41
|
+
expect(await systemAccessRepository.create(data)).toEqual(data);
|
42
|
+
});
|
43
|
+
});
|
44
|
+
|
45
|
+
describe('update', () => {
|
46
|
+
it('should update system access', async () => {
|
47
|
+
prismaMock.systemAccess.update.mockResolvedValueOnce(data);
|
48
|
+
const systemAccessRepository = new SystemAccessRepository();
|
49
|
+
expect(
|
50
|
+
await systemAccessRepository.update(
|
51
|
+
{
|
52
|
+
where: {
|
53
|
+
userId: data.userId,
|
54
|
+
systemId: data.systemId,
|
55
|
+
},
|
56
|
+
data: data,
|
57
|
+
},
|
58
|
+
data,
|
59
|
+
),
|
60
|
+
).toEqual(data);
|
61
|
+
});
|
62
|
+
});
|
63
|
+
|
64
|
+
describe('delete', () => {
|
65
|
+
it('should delete system access', async () => {
|
66
|
+
prismaMock.systemAccess.delete.mockResolvedValueOnce(data);
|
67
|
+
const systemAccessRepository = new SystemAccessRepository();
|
68
|
+
expect(
|
69
|
+
await systemAccessRepository.delete({
|
70
|
+
where: {
|
71
|
+
userId: data.userId,
|
72
|
+
systemId: data.systemId,
|
73
|
+
},
|
74
|
+
}),
|
75
|
+
).toEqual(data);
|
76
|
+
});
|
77
|
+
});
|
78
|
+
});
|
@@ -0,0 +1,24 @@
|
|
1
|
+
import { RedisService } from "../../../src/redis-client/redis.service";
|
2
|
+
require('dotenv').config()
|
3
|
+
// nneed to figure out how to mock redis
|
4
|
+
describe('redis.service', () => {
|
5
|
+
|
6
|
+
afterEach(() => {
|
7
|
+
jest.restoreAllMocks()
|
8
|
+
})
|
9
|
+
|
10
|
+
it('should return redis service when instansiated', async () => {
|
11
|
+
const redisService = await RedisService.init();
|
12
|
+
expect(redisService).toBeDefined();
|
13
|
+
});
|
14
|
+
|
15
|
+
it('should able to write and read redis', async () => {
|
16
|
+
const data = {
|
17
|
+
test: 'test'
|
18
|
+
}
|
19
|
+
const redisService = await RedisService.init();
|
20
|
+
await redisService.set("test", data, 60 * 60 * 24 * 1)
|
21
|
+
const result = await redisService.get("test");
|
22
|
+
expect(result).toEqual(JSON.stringify(data));
|
23
|
+
});
|
24
|
+
});
|
@@ -0,0 +1,27 @@
|
|
1
|
+
import { IUserSession } from '../../../src/interfaces/user-session.interface';
|
2
|
+
import { SessionService } from '../../../src/session/session.service';
|
3
|
+
require('dotenv').config()
|
4
|
+
|
5
|
+
describe('session.service', () => {
|
6
|
+
it('should return session service when instansiated', async () => {
|
7
|
+
const sessionService = await SessionService.init();
|
8
|
+
expect(sessionService).toBeDefined();
|
9
|
+
});
|
10
|
+
|
11
|
+
it('should able to write session data', async () => {
|
12
|
+
const data: IUserSession = {
|
13
|
+
systemLogins: [
|
14
|
+
{
|
15
|
+
id: '1',
|
16
|
+
code: 'EZC',
|
17
|
+
sessionId: 'test1',
|
18
|
+
privileges: ['PRIVILEGE1', 'PRIVILEGE2'],
|
19
|
+
},
|
20
|
+
],
|
21
|
+
};
|
22
|
+
const sessionService = await SessionService.init();
|
23
|
+
await sessionService.setUserSession("1", data)
|
24
|
+
const result = await sessionService.retrieveUserSession("1");
|
25
|
+
expect(result).toEqual(data);
|
26
|
+
});
|
27
|
+
});
|
package/create-sso-user.sql
CHANGED
@@ -32,6 +32,7 @@ GRANT CREATE, ALTER, DROP, INSERT, UPDATE, DELETE, SELECT, REFERENCES on product
|
|
32
32
|
GRANT CREATE, ALTER, DROP, INSERT, UPDATE, DELETE, SELECT, REFERENCES on production.sso_users TO 'sso_user'@'localhost' WITH GRANT OPTION;
|
33
33
|
GRANT CREATE, ALTER, DROP, INSERT, UPDATE, DELETE, SELECT, REFERENCES on production.sso_usersystemprivilege TO 'sso_user'@'localhost' WITH GRANT OPTION;
|
34
34
|
GRANT CREATE, ALTER, DROP, INSERT, UPDATE, DELETE, SELECT, REFERENCES on production.sso_usersystemrole TO 'sso_user'@'localhost' WITH GRANT OPTION;
|
35
|
+
GRANT CREATE, ALTER, DROP, INSERT, UPDATE, DELETE, SELECT, REFERENCES on production.sso_UserUserGroup TO 'sso_user'@'localhost' WITH GRANT OPTION;
|
35
36
|
GRANT CREATE, ALTER, DROP, INSERT, UPDATE, DELETE, SELECT, REFERENCES on production._prisma_migrations TO 'sso_user'@'localhost' WITH GRANT OPTION;
|
36
37
|
|
37
38
|
|
@@ -0,0 +1 @@
|
|
1
|
+
export {};
|