Skip to content

Commit 223a946

Browse files
committed
tests for model and factory method added
1 parent 025fdc1 commit 223a946

3 files changed

Lines changed: 387 additions & 21 deletions

File tree

src/models/user.ts

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -456,7 +456,7 @@ export default class UserModel extends AbstractModel<Omit<UserDBScheme, '_id'>>
456456

457457
await this.update(
458458
{ _id: new ObjectId(this._id) },
459-
{ $set: updateData }
459+
updateData
460460
);
461461

462462
/**
@@ -472,26 +472,6 @@ export default class UserModel extends AbstractModel<Omit<UserDBScheme, '_id'>>
472472
}
473473
}
474474

475-
/**
476-
* Find user by SAML identity
477-
*
478-
* @param collection - users collection
479-
* @param workspaceId - workspace ID
480-
* @param samlId - NameID value from IdP
481-
* @returns UserModel or null if not found
482-
*/
483-
public static async findBySamlIdentity(
484-
collection: Collection<UserDBScheme>,
485-
workspaceId: string,
486-
samlId: string
487-
): Promise<UserModel | null> {
488-
const userData = await collection.findOne({
489-
[`identities.${workspaceId}.saml.id`]: samlId,
490-
});
491-
492-
return userData ? new UserModel(userData) : null;
493-
}
494-
495475
/**
496476
* Get SAML identity for workspace
497477
*

test/models/user.test.ts

Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
1+
import '../../src/env-test';
2+
import UserModel from '../../src/models/user';
3+
import UsersFactory from '../../src/models/usersFactory';
4+
import * as mongo from '../../src/mongo';
5+
import DataLoaders from '../../src/dataLoaders';
6+
7+
beforeAll(async () => {
8+
await mongo.setupConnections();
9+
});
10+
11+
describe('UserModel SSO identities', () => {
12+
let usersFactory: UsersFactory;
13+
let testUser: UserModel;
14+
const testWorkspaceId = '507f1f77bcf86cd799439011';
15+
const testSamlId = 'test-saml-name-id-123';
16+
const testEmail = 'test-sso@example.com';
17+
18+
beforeEach(async () => {
19+
/**
20+
* Create factory instance
21+
*/
22+
usersFactory = new UsersFactory(
23+
mongo.databases.hawk as any,
24+
new DataLoaders(mongo.databases.hawk as any)
25+
);
26+
27+
/**
28+
* Create test user
29+
*/
30+
testUser = await usersFactory.create(testEmail, 'test-password-123');
31+
});
32+
33+
afterEach(async () => {
34+
/**
35+
* Clean up test user
36+
*/
37+
if (testUser && testUser.email) {
38+
await usersFactory.deleteByEmail(testUser.email);
39+
}
40+
});
41+
42+
describe('linkSamlIdentity', () => {
43+
it('should link SAML identity to user and update local state', async () => {
44+
/**
45+
* Initially, user should not have any identities
46+
*/
47+
expect(testUser.identities).toBeUndefined();
48+
49+
/**
50+
* Link SAML identity
51+
*/
52+
await testUser.linkSamlIdentity(testWorkspaceId, testSamlId, testEmail);
53+
54+
/**
55+
* Check that local state is updated
56+
*/
57+
expect(testUser.identities).toBeDefined();
58+
expect(testUser.identities![testWorkspaceId]).toBeDefined();
59+
expect(testUser.identities![testWorkspaceId].saml).toEqual({
60+
id: testSamlId,
61+
email: testEmail,
62+
});
63+
});
64+
65+
it('should persist SAML identity in database', async () => {
66+
/**
67+
* Link SAML identity
68+
*/
69+
await testUser.linkSamlIdentity(testWorkspaceId, testSamlId, testEmail);
70+
71+
/**
72+
* Reload user from database to verify persistence
73+
*/
74+
const reloadedUser = await usersFactory.findById(testUser._id.toString());
75+
76+
expect(reloadedUser).not.toBeNull();
77+
expect(reloadedUser!.identities).toBeDefined();
78+
expect(reloadedUser!.identities![testWorkspaceId]).toBeDefined();
79+
expect(reloadedUser!.identities![testWorkspaceId].saml).toEqual({
80+
id: testSamlId,
81+
email: testEmail,
82+
});
83+
});
84+
85+
it('should allow linking identities for multiple workspaces', async () => {
86+
const workspaceId2 = '507f1f77bcf86cd799439012';
87+
const samlId2 = 'test-saml-name-id-456';
88+
const email2 = 'test-sso-2@example.com';
89+
90+
/**
91+
* Link identity for first workspace
92+
*/
93+
await testUser.linkSamlIdentity(testWorkspaceId, testSamlId, testEmail);
94+
95+
/**
96+
* Link identity for second workspace
97+
*/
98+
await testUser.linkSamlIdentity(workspaceId2, samlId2, email2);
99+
100+
/**
101+
* Check that both identities are present
102+
*/
103+
expect(testUser.identities![testWorkspaceId].saml).toEqual({
104+
id: testSamlId,
105+
email: testEmail,
106+
});
107+
expect(testUser.identities![workspaceId2].saml).toEqual({
108+
id: samlId2,
109+
email: email2,
110+
});
111+
112+
/**
113+
* Verify in database
114+
*/
115+
const reloadedUser = await usersFactory.findById(testUser._id.toString());
116+
expect(reloadedUser!.identities![testWorkspaceId].saml.id).toBe(testSamlId);
117+
expect(reloadedUser!.identities![workspaceId2].saml.id).toBe(samlId2);
118+
});
119+
120+
it('should update existing SAML identity for the same workspace', async () => {
121+
const newSamlId = 'updated-saml-name-id-789';
122+
const newEmail = 'updated-email@example.com';
123+
124+
/**
125+
* Link initial identity
126+
*/
127+
await testUser.linkSamlIdentity(testWorkspaceId, testSamlId, testEmail);
128+
129+
/**
130+
* Update identity for the same workspace
131+
*/
132+
await testUser.linkSamlIdentity(testWorkspaceId, newSamlId, newEmail);
133+
134+
/**
135+
* Check that identity is updated (not duplicated)
136+
*/
137+
expect(testUser.identities![testWorkspaceId].saml).toEqual({
138+
id: newSamlId,
139+
email: newEmail,
140+
});
141+
142+
/**
143+
* Verify in database
144+
*/
145+
const reloadedUser = await usersFactory.findById(testUser._id.toString());
146+
expect(reloadedUser!.identities![testWorkspaceId].saml).toEqual({
147+
id: newSamlId,
148+
email: newEmail,
149+
});
150+
});
151+
});
152+
153+
describe('getSamlIdentity', () => {
154+
it('should return null when identity does not exist', () => {
155+
/**
156+
* User without any identities
157+
*/
158+
const identity = testUser.getSamlIdentity(testWorkspaceId);
159+
expect(identity).toBeNull();
160+
});
161+
162+
it('should return null for non-existent workspace', async () => {
163+
/**
164+
* Link identity for one workspace
165+
*/
166+
await testUser.linkSamlIdentity(testWorkspaceId, testSamlId, testEmail);
167+
168+
/**
169+
* Try to get identity for different workspace
170+
*/
171+
const nonExistentWorkspaceId = '507f1f77bcf86cd799439099';
172+
const identity = testUser.getSamlIdentity(nonExistentWorkspaceId);
173+
expect(identity).toBeNull();
174+
});
175+
176+
it('should return SAML identity when it exists', async () => {
177+
/**
178+
* Link SAML identity
179+
*/
180+
await testUser.linkSamlIdentity(testWorkspaceId, testSamlId, testEmail);
181+
182+
/**
183+
* Get identity
184+
*/
185+
const identity = testUser.getSamlIdentity(testWorkspaceId);
186+
187+
expect(identity).not.toBeNull();
188+
expect(identity).toEqual({
189+
id: testSamlId,
190+
email: testEmail,
191+
});
192+
});
193+
194+
it('should return correct identity for specific workspace when multiple exist', async () => {
195+
const workspaceId2 = '507f1f77bcf86cd799439012';
196+
const samlId2 = 'test-saml-name-id-456';
197+
const email2 = 'test-sso-2@example.com';
198+
199+
/**
200+
* Link identities for two workspaces
201+
*/
202+
await testUser.linkSamlIdentity(testWorkspaceId, testSamlId, testEmail);
203+
await testUser.linkSamlIdentity(workspaceId2, samlId2, email2);
204+
205+
/**
206+
* Get identity for first workspace
207+
*/
208+
const identity1 = testUser.getSamlIdentity(testWorkspaceId);
209+
expect(identity1).toEqual({
210+
id: testSamlId,
211+
email: testEmail,
212+
});
213+
214+
/**
215+
* Get identity for second workspace
216+
*/
217+
const identity2 = testUser.getSamlIdentity(workspaceId2);
218+
expect(identity2).toEqual({
219+
id: samlId2,
220+
email: email2,
221+
});
222+
});
223+
});
224+
225+
});
226+
227+
afterAll(async done => {
228+
await mongo.mongoClients.hawk?.close();
229+
await mongo.mongoClients.events?.close();
230+
231+
done();
232+
});
233+

0 commit comments

Comments
 (0)