Skip to content

Commit 6ab293c

Browse files
author
Lasim
committed
feat: add cross-user permissions tests and update test context structure
1 parent 6c0c303 commit 6ab293c

File tree

4 files changed

+543
-1
lines changed

4 files changed

+543
-1
lines changed
Lines changed: 384 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,384 @@
1+
import request from 'supertest';
2+
import { FastifyInstance } from 'fastify';
3+
import { getTestContext, updateTestContext } from './testContext';
4+
5+
describe('Cloud Credentials Cross-User Permissions E2E Tests', () => {
6+
let server: FastifyInstance;
7+
let port: number;
8+
9+
beforeAll(() => {
10+
// Access the server instance and port from test context
11+
const context = getTestContext();
12+
server = context.server!;
13+
port = context.port;
14+
});
15+
16+
it('should register test_credentials_user_1 and assign global_user role', async () => {
17+
// Register the first test user for credentials testing
18+
const testUser1Data = {
19+
username: 'test_credentials_user_1',
20+
21+
password: 'SecurePassword123!',
22+
first_name: 'Test',
23+
last_name: 'CredentialsUser1'
24+
};
25+
26+
const registerResponse = await request(server.server)
27+
.post('/api/auth/email/register')
28+
.send(testUser1Data);
29+
30+
expect(registerResponse.status).toBe(201);
31+
expect(registerResponse.body).toHaveProperty('success', true);
32+
expect(registerResponse.body).toHaveProperty('user');
33+
34+
const user = registerResponse.body.user;
35+
expect(user.username).toBe(testUser1Data.username);
36+
expect(user.email).toBe(testUser1Data.email);
37+
expect(user.first_name).toBe(testUser1Data.first_name);
38+
expect(user.last_name).toBe(testUser1Data.last_name);
39+
40+
// Verify the user gets global_user role (not admin since this isn't the first user)
41+
expect(user.role_id).toBe('global_user');
42+
43+
// Verify user has a session cookie
44+
expect(registerResponse.headers['set-cookie']).toBeDefined();
45+
46+
// Store user ID and cookie for later tests
47+
updateTestContext({
48+
testCredentialsUser1Id: user.id,
49+
testCredentialsUser1Cookie: registerResponse.headers['set-cookie'][0]
50+
});
51+
});
52+
53+
it('should register test_credentials_user_2 and assign global_user role', async () => {
54+
// Register the second test user for credentials testing
55+
const testUser2Data = {
56+
username: 'test_credentials_user_2',
57+
58+
password: 'SecurePassword456!',
59+
first_name: 'Test',
60+
last_name: 'CredentialsUser2'
61+
};
62+
63+
const registerResponse = await request(server.server)
64+
.post('/api/auth/email/register')
65+
.send(testUser2Data);
66+
67+
expect(registerResponse.status).toBe(201);
68+
expect(registerResponse.body).toHaveProperty('success', true);
69+
expect(registerResponse.body).toHaveProperty('user');
70+
71+
const user = registerResponse.body.user;
72+
expect(user.username).toBe(testUser2Data.username);
73+
expect(user.email).toBe(testUser2Data.email);
74+
expect(user.first_name).toBe(testUser2Data.first_name);
75+
expect(user.last_name).toBe(testUser2Data.last_name);
76+
77+
// Verify the user gets global_user role
78+
expect(user.role_id).toBe('global_user');
79+
80+
// Verify user has a session cookie
81+
expect(registerResponse.headers['set-cookie']).toBeDefined();
82+
83+
// Store user ID and cookie for later tests
84+
updateTestContext({
85+
testCredentialsUser2Id: user.id,
86+
testCredentialsUser2Cookie: registerResponse.headers['set-cookie'][0]
87+
});
88+
});
89+
90+
it('should verify both test users have their own default teams', async () => {
91+
const context = getTestContext();
92+
93+
// Check test_credentials_user_1's teams
94+
const user1TeamsResponse = await request(server.server)
95+
.get('/api/teams/me')
96+
.set('Cookie', context.testCredentialsUser1Cookie!);
97+
98+
expect(user1TeamsResponse.status).toBe(200);
99+
expect(user1TeamsResponse.body).toHaveProperty('success', true);
100+
expect(user1TeamsResponse.body).toHaveProperty('data');
101+
expect(user1TeamsResponse.body.data).toHaveLength(1);
102+
103+
const user1Team = user1TeamsResponse.body.data[0];
104+
expect(user1Team.name).toBe('test_credentials_user_1'); // Default team name is username
105+
expect(user1Team.owner_id).toBe(context.testCredentialsUser1Id);
106+
expect(user1Team.role).toBe('team_admin'); // User is admin of their own team
107+
108+
// Check test_credentials_user_2's teams
109+
const user2TeamsResponse = await request(server.server)
110+
.get('/api/teams/me')
111+
.set('Cookie', context.testCredentialsUser2Cookie!);
112+
113+
expect(user2TeamsResponse.status).toBe(200);
114+
expect(user2TeamsResponse.body).toHaveProperty('success', true);
115+
expect(user2TeamsResponse.body).toHaveProperty('data');
116+
expect(user2TeamsResponse.body.data).toHaveLength(1);
117+
118+
const user2Team = user2TeamsResponse.body.data[0];
119+
expect(user2Team.name).toBe('test_credentials_user_2'); // Default team name is username
120+
expect(user2Team.owner_id).toBe(context.testCredentialsUser2Id);
121+
expect(user2Team.role).toBe('team_admin'); // User is admin of their own team
122+
123+
// Store team IDs for later tests
124+
updateTestContext({
125+
testCredentialsUser1TeamId: user1Team.id,
126+
testCredentialsUser2TeamId: user2Team.id
127+
});
128+
});
129+
130+
it('should allow test_credentials_user_1 to create cloud credentials in their team', async () => {
131+
const context = getTestContext();
132+
133+
const credentialData = {
134+
providerId: 'aws',
135+
name: 'User1 Test Credentials',
136+
comment: 'Test credentials for cross-user permission testing',
137+
credentials: {
138+
access_key_id: 'AKIAUSER1TEST123456',
139+
secret_access_key: 'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEYuser1'
140+
}
141+
};
142+
143+
const response = await request(server.server)
144+
.post(`/teams/${context.testCredentialsUser1TeamId}/cloud-credentials`)
145+
.set('Cookie', context.testCredentialsUser1Cookie!)
146+
.send(credentialData);
147+
148+
expect(response.status).toBe(201);
149+
expect(response.body.success).toBe(true);
150+
expect(response.body.data).toBeDefined();
151+
expect(response.body.message).toBeDefined();
152+
153+
const credential = response.body.data;
154+
expect(credential.id).toBeDefined();
155+
expect(credential.teamId).toBe(context.testCredentialsUser1TeamId);
156+
expect(credential.providerId).toBe('aws');
157+
expect(credential.name).toBe(credentialData.name);
158+
expect(credential.comment).toBe(credentialData.comment);
159+
expect(credential.createdBy).toBe(context.testCredentialsUser1Id);
160+
161+
// Verify provider information
162+
expect(credential.provider.id).toBe('aws');
163+
expect(credential.provider.name).toBe('Amazon Web Services');
164+
165+
// Verify fields structure - team admin should see placeholder for non-secret fields
166+
expect(credential.fields).toBeDefined();
167+
expect(credential.fields.access_key_id).toBeDefined();
168+
expect(credential.fields.access_key_id.hasValue).toBe(true);
169+
expect(credential.fields.access_key_id.secret).toBe(false);
170+
expect(credential.fields.access_key_id.value).toBe('PLACEHOLDER_VALUE');
171+
172+
expect(credential.fields.secret_access_key).toBeDefined();
173+
expect(credential.fields.secret_access_key.hasValue).toBe(true);
174+
expect(credential.fields.secret_access_key.secret).toBe(true);
175+
expect(credential.fields.secret_access_key.value).toBeUndefined(); // Secret field never shows value
176+
177+
// Store credential ID for cross-user access tests
178+
updateTestContext({
179+
testCredentialsUser1CredentialId: credential.id
180+
});
181+
});
182+
183+
it('should prevent test_credentials_user_2 from listing user_1 team credentials', async () => {
184+
const context = getTestContext();
185+
186+
// User 2 attempts to list User 1's team credentials
187+
const response = await request(server.server)
188+
.get(`/teams/${context.testCredentialsUser1TeamId}/cloud-credentials`)
189+
.set('Cookie', context.testCredentialsUser2Cookie!);
190+
191+
// Should be forbidden - User 2 is not a member of User 1's team
192+
expect(response.status).toBe(403);
193+
expect(response.body.success).toBe(false);
194+
expect(response.body.error).toBeDefined();
195+
});
196+
197+
it('should prevent test_credentials_user_2 from viewing specific user_1 credential', async () => {
198+
const context = getTestContext();
199+
200+
// User 2 attempts to view User 1's specific credential
201+
const response = await request(server.server)
202+
.get(`/teams/${context.testCredentialsUser1TeamId}/cloud-credentials/${context.testCredentialsUser1CredentialId}`)
203+
.set('Cookie', context.testCredentialsUser2Cookie!);
204+
205+
// Should be forbidden - User 2 is not a member of User 1's team
206+
expect(response.status).toBe(403);
207+
expect(response.body.success).toBe(false);
208+
expect(response.body.error).toBeDefined();
209+
});
210+
211+
it('should prevent test_credentials_user_2 from updating user_1 credentials', async () => {
212+
const context = getTestContext();
213+
214+
const updateData = {
215+
name: 'Malicious Update Attempt',
216+
comment: 'This should not work',
217+
credentials: {
218+
access_key_id: 'AKIAMALICIOUS123456'
219+
}
220+
};
221+
222+
// User 2 attempts to update User 1's credential
223+
const response = await request(server.server)
224+
.put(`/teams/${context.testCredentialsUser1TeamId}/cloud-credentials/${context.testCredentialsUser1CredentialId}`)
225+
.set('Cookie', context.testCredentialsUser2Cookie!)
226+
.send(updateData);
227+
228+
// Should be forbidden - User 2 is not a member of User 1's team
229+
expect(response.status).toBe(403);
230+
expect(response.body.success).toBe(false);
231+
expect(response.body.error).toBeDefined();
232+
});
233+
234+
it('should prevent test_credentials_user_2 from deleting user_1 credentials', async () => {
235+
const context = getTestContext();
236+
237+
// User 2 attempts to delete User 1's credential
238+
const response = await request(server.server)
239+
.delete(`/teams/${context.testCredentialsUser1TeamId}/cloud-credentials/${context.testCredentialsUser1CredentialId}`)
240+
.set('Cookie', context.testCredentialsUser2Cookie!);
241+
242+
// Should be forbidden - User 2 is not a member of User 1's team
243+
expect(response.status).toBe(403);
244+
expect(response.body.success).toBe(false);
245+
expect(response.body.error).toBeDefined();
246+
});
247+
248+
it('should verify user_1 credentials remain intact after unauthorized access attempts', async () => {
249+
const context = getTestContext();
250+
251+
// User 1 verifies their credential still exists and is unchanged
252+
const response = await request(server.server)
253+
.get(`/teams/${context.testCredentialsUser1TeamId}/cloud-credentials/${context.testCredentialsUser1CredentialId}`)
254+
.set('Cookie', context.testCredentialsUser1Cookie!);
255+
256+
expect(response.status).toBe(200);
257+
expect(response.body.success).toBe(true);
258+
expect(response.body.data).toBeDefined();
259+
260+
const credential = response.body.data;
261+
expect(credential.name).toBe('User1 Test Credentials'); // Original name unchanged
262+
expect(credential.comment).toBe('Test credentials for cross-user permission testing'); // Original comment unchanged
263+
expect(credential.createdBy).toBe(context.testCredentialsUser1Id);
264+
expect(credential.teamId).toBe(context.testCredentialsUser1TeamId);
265+
266+
// Verify fields are still intact
267+
expect(credential.fields.access_key_id.hasValue).toBe(true);
268+
expect(credential.fields.secret_access_key.hasValue).toBe(true);
269+
});
270+
271+
it('should allow test_credentials_user_2 to manage their own credentials', async () => {
272+
const context = getTestContext();
273+
274+
// User 2 creates their own credentials in their own team
275+
const credentialData = {
276+
providerId: 'aws',
277+
name: 'User2 Test Credentials',
278+
comment: 'Test credentials for user 2 own team',
279+
credentials: {
280+
access_key_id: 'AKIAUSER2TEST123456',
281+
secret_access_key: 'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEYuser2'
282+
}
283+
};
284+
285+
const createResponse = await request(server.server)
286+
.post(`/teams/${context.testCredentialsUser2TeamId}/cloud-credentials`)
287+
.set('Cookie', context.testCredentialsUser2Cookie!)
288+
.send(credentialData);
289+
290+
expect(createResponse.status).toBe(201);
291+
expect(createResponse.body.success).toBe(true);
292+
expect(createResponse.body.data).toBeDefined();
293+
294+
const credential = createResponse.body.data;
295+
expect(credential.teamId).toBe(context.testCredentialsUser2TeamId);
296+
expect(credential.createdBy).toBe(context.testCredentialsUser2Id);
297+
expect(credential.name).toBe(credentialData.name);
298+
299+
const user2CredentialId = credential.id;
300+
301+
// User 2 can list their own team's credentials
302+
const listResponse = await request(server.server)
303+
.get(`/teams/${context.testCredentialsUser2TeamId}/cloud-credentials`)
304+
.set('Cookie', context.testCredentialsUser2Cookie!);
305+
306+
expect(listResponse.status).toBe(200);
307+
expect(listResponse.body.success).toBe(true);
308+
expect(listResponse.body.data).toHaveLength(1);
309+
expect(listResponse.body.data[0].id).toBe(user2CredentialId);
310+
311+
// User 2 can view their own credential
312+
const viewResponse = await request(server.server)
313+
.get(`/teams/${context.testCredentialsUser2TeamId}/cloud-credentials/${user2CredentialId}`)
314+
.set('Cookie', context.testCredentialsUser2Cookie!);
315+
316+
expect(viewResponse.status).toBe(200);
317+
expect(viewResponse.body.success).toBe(true);
318+
expect(viewResponse.body.data.id).toBe(user2CredentialId);
319+
320+
// User 2 can update their own credential
321+
const updateData = {
322+
name: 'User2 Updated Credentials',
323+
comment: 'Updated comment for user 2'
324+
};
325+
326+
const updateResponse = await request(server.server)
327+
.put(`/teams/${context.testCredentialsUser2TeamId}/cloud-credentials/${user2CredentialId}`)
328+
.set('Cookie', context.testCredentialsUser2Cookie!)
329+
.send(updateData);
330+
331+
expect(updateResponse.status).toBe(200);
332+
expect(updateResponse.body.success).toBe(true);
333+
expect(updateResponse.body.data.name).toBe(updateData.name);
334+
expect(updateResponse.body.data.comment).toBe(updateData.comment);
335+
336+
// User 2 can delete their own credential
337+
const deleteResponse = await request(server.server)
338+
.delete(`/teams/${context.testCredentialsUser2TeamId}/cloud-credentials/${user2CredentialId}`)
339+
.set('Cookie', context.testCredentialsUser2Cookie!);
340+
341+
expect(deleteResponse.status).toBe(200);
342+
expect(deleteResponse.body.success).toBe(true);
343+
expect(deleteResponse.body.message).toBeDefined();
344+
});
345+
346+
it('should verify complete isolation between user teams', async () => {
347+
const context = getTestContext();
348+
349+
// User 1 should not be able to access User 2's team
350+
const user1AccessUser2TeamResponse = await request(server.server)
351+
.get(`/teams/${context.testCredentialsUser2TeamId}/cloud-credentials`)
352+
.set('Cookie', context.testCredentialsUser1Cookie!);
353+
354+
expect(user1AccessUser2TeamResponse.status).toBe(403);
355+
expect(user1AccessUser2TeamResponse.body.success).toBe(false);
356+
357+
// User 2 should not be able to access User 1's team
358+
const user2AccessUser1TeamResponse = await request(server.server)
359+
.get(`/teams/${context.testCredentialsUser1TeamId}/cloud-credentials`)
360+
.set('Cookie', context.testCredentialsUser2Cookie!);
361+
362+
expect(user2AccessUser1TeamResponse.status).toBe(403);
363+
expect(user2AccessUser1TeamResponse.body.success).toBe(false);
364+
365+
// Verify User 1's credential still exists and is accessible only to User 1
366+
const user1CredentialResponse = await request(server.server)
367+
.get(`/teams/${context.testCredentialsUser1TeamId}/cloud-credentials`)
368+
.set('Cookie', context.testCredentialsUser1Cookie!);
369+
370+
expect(user1CredentialResponse.status).toBe(200);
371+
expect(user1CredentialResponse.body.success).toBe(true);
372+
expect(user1CredentialResponse.body.data).toHaveLength(1);
373+
expect(user1CredentialResponse.body.data[0].name).toBe('User1 Test Credentials');
374+
375+
// Verify User 2's team is empty (they deleted their credential)
376+
const user2CredentialResponse = await request(server.server)
377+
.get(`/teams/${context.testCredentialsUser2TeamId}/cloud-credentials`)
378+
.set('Cookie', context.testCredentialsUser2Cookie!);
379+
380+
expect(user2CredentialResponse.status).toBe(200);
381+
expect(user2CredentialResponse.body.success).toBe(true);
382+
expect(user2CredentialResponse.body.data).toHaveLength(0);
383+
});
384+
});

0 commit comments

Comments
 (0)