Skip to content

Commit fbc2406

Browse files
committed
test: coverage for push API calls
1 parent 7326a4c commit fbc2406

File tree

2 files changed

+277
-14
lines changed

2 files changed

+277
-14
lines changed

src/service/routes/push.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,13 @@ router.get('/:id', async (req, res) => {
3636
router.post('/:id/reject', async (req, res) => {
3737
if (req.user) {
3838
const id = req.params.id;
39-
console.log({ id });
4039

4140
// Get the push request
4241
const push = await db.getPush(id);
43-
console.log({ push });
4442

4543
// Get the committer of the push via their email
4644
const committerEmail = push.userEmail;
4745
const list = await db.getUsers({ email: committerEmail });
48-
console.log({ list });
4946

5047
if (list.length === 0) {
5148
res.status(401).send({
@@ -86,6 +83,8 @@ router.post('/:id/authorise', async (req, res) => {
8683
const questions = req.body.params?.attestation;
8784
console.log({ questions });
8885

86+
// TODO: compare attestation to configuration and ensure all questions are answered
87+
// - we shouldn't go on the definition in the request!
8988
const attestationComplete = questions?.every((question) => !!question.checked);
9089
console.log({ attestationComplete });
9190

test/testPush.test.js

Lines changed: 275 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,32 +8,120 @@ chai.use(chaiHttp);
88
chai.should();
99
const expect = chai.expect;
1010

11+
// dummy repo
12+
const TEST_ORG = 'finos';
13+
const TEST_REPO = 'test-push';
14+
const TEST_URL = 'https://github.com/finos/test-push.git';
15+
// approver user
16+
const TEST_USERNAME_1 = 'push-test';
17+
const TEST_EMAIL_1 = '[email protected]';
18+
const TEST_PASSWORD_1 = 'test1234';
19+
// committer user
20+
const TEST_USERNAME_2 = 'push-test-2';
21+
const TEST_EMAIL_2 = '[email protected]';
22+
const TEST_PASSWORD_2 = 'test5678';
23+
// unknown user
24+
const TEST_USERNAME_3 = 'push-test-3';
25+
const TEST_EMAIL_3 = '[email protected]';
26+
27+
const TEST_PUSH = {
28+
steps: [],
29+
error: false,
30+
blocked: false,
31+
allowPush: false,
32+
authorised: false,
33+
canceled: false,
34+
rejected: false,
35+
autoApproved: false,
36+
autoRejected: false,
37+
commitData: [],
38+
id: '0000000000000000000000000000000000000000__1744380874110',
39+
type: 'push',
40+
method: 'get',
41+
timestamp: 1744380903338,
42+
project: TEST_ORG,
43+
repoName: TEST_REPO + '.git',
44+
url: TEST_REPO,
45+
repo: TEST_ORG + '/' + TEST_REPO + '.git',
46+
user: TEST_USERNAME_2,
47+
userEmail: TEST_EMAIL_2,
48+
lastStep: null,
49+
blockedMessage:
50+
'\n\n\nGitProxy has received your push:\n\nhttp://localhost:8080/requests/0000000000000000000000000000000000000000__1744380874110\n\n\n',
51+
_id: 'GIMEz8tU2KScZiTz',
52+
attestation: null,
53+
};
54+
1155
describe('auth', async () => {
1256
let app;
1357
let cookie;
1458

15-
before(async function () {
16-
app = await service.start();
17-
await db.deleteUser('login-test-user');
59+
const setCookie = function (res) {
60+
res.headers['set-cookie'].forEach((x) => {
61+
if (x.startsWith('connect')) {
62+
const value = x.split(';')[0];
63+
cookie = value;
64+
}
65+
});
66+
};
1867

68+
const login = async function (username, password) {
69+
console.log(`logging in as ${username}...`);
1970
const res = await chai.request(app).post('/api/auth/login').send({
20-
username: 'admin',
21-
password: 'admin',
71+
username: username,
72+
password: password,
2273
});
23-
74+
res.should.have.status(200);
2475
expect(res).to.have.cookie('connect.sid');
76+
setCookie(res);
77+
};
78+
79+
const loginAsApprover = () => login(TEST_USERNAME_1, TEST_PASSWORD_1);
80+
const loginAsCommitter = () => login(TEST_USERNAME_2, TEST_PASSWORD_2);
81+
const loginAsAdmin = () => login('admin', 'admin');
82+
83+
const logout = async function () {
84+
const res = await chai.request(app).post('/api/auth/logout').set('Cookie', `${cookie}`);
2585
res.should.have.status(200);
86+
cookie = null;
87+
};
2688

27-
// Get the connect cooie
28-
res.headers['set-cookie'].forEach((x) => {
29-
if (x.startsWith('connect')) {
30-
cookie = x.split(';')[0];
31-
}
89+
before(async function () {
90+
app = await service.start();
91+
await loginAsAdmin();
92+
93+
// set up a repo, user and push to test against
94+
await db.deleteRepo(TEST_REPO);
95+
await db.deleteUser(TEST_USERNAME_1);
96+
await db.createRepo({
97+
project: TEST_ORG,
98+
name: TEST_REPO,
99+
url: TEST_URL,
32100
});
101+
102+
// Create a new user for the approver
103+
console.log('creating approver');
104+
await db.createUser(TEST_USERNAME_1, TEST_PASSWORD_1, TEST_EMAIL_1, TEST_USERNAME_1, false);
105+
await db.addUserCanAuthorise(TEST_REPO, TEST_USERNAME_1);
106+
107+
// create a new user for the committer
108+
console.log('creating committer');
109+
await db.createUser(TEST_USERNAME_2, TEST_PASSWORD_2, TEST_EMAIL_2, TEST_USERNAME_2, false);
110+
await db.addUserCanPush(TEST_REPO, TEST_USERNAME_2);
111+
112+
// logout of admin account
113+
await logout();
33114
});
34115

35116
describe('test push API', async function () {
117+
afterEach(async function () {
118+
await db.deletePush(TEST_PUSH.id);
119+
await logout();
120+
});
121+
36122
it('should get 404 for unknown push', async function () {
123+
await loginAsApprover();
124+
37125
const commitId =
38126
'0000000000000000000000000000000000000000__79b4d8953cbc324bcc1eb53d6412ff89666c241f'; // eslint-disable-line max-len
39127
const res = await chai
@@ -42,12 +130,188 @@ describe('auth', async () => {
42130
.set('Cookie', `${cookie}`);
43131
res.should.have.status(404);
44132
});
133+
134+
it('should allow an authorizer to approve a push', async function () {
135+
await db.writeAudit(TEST_PUSH);
136+
await loginAsApprover();
137+
const res = await chai
138+
.request(app)
139+
.post(`/api/v1/push/${TEST_PUSH.id}/authorise`)
140+
.set('Cookie', `${cookie}`)
141+
.set('content-type', 'application/x-www-form-urlencoded')
142+
.send({
143+
params: {
144+
attestation: [
145+
{
146+
label: 'I am happy for this to be pushed to the upstream repository',
147+
tooltip: {
148+
text: 'Are you happy for this contribution to be pushed upstream?',
149+
links: [],
150+
},
151+
checked: true,
152+
},
153+
],
154+
},
155+
});
156+
res.should.have.status(200);
157+
});
158+
159+
it('should NOT allow an authorizer to approve if attestation is incomplete', async function () {
160+
// make the approver also the committer
161+
const testPush = { ...TEST_PUSH };
162+
testPush.user = TEST_USERNAME_1;
163+
testPush.userEmail = TEST_EMAIL_1;
164+
await db.writeAudit(testPush);
165+
await loginAsApprover();
166+
const res = await chai
167+
.request(app)
168+
.post(`/api/v1/push/${TEST_PUSH.id}/authorise`)
169+
.set('Cookie', `${cookie}`)
170+
.set('content-type', 'application/x-www-form-urlencoded')
171+
.send({
172+
params: {
173+
attestation: [
174+
{
175+
label: 'I am happy for this to be pushed to the upstream repository',
176+
tooltip: {
177+
text: 'Are you happy for this contribution to be pushed upstream?',
178+
links: [],
179+
},
180+
checked: false,
181+
},
182+
],
183+
},
184+
});
185+
res.should.have.status(401);
186+
});
187+
188+
it('should NOT allow an authorizer to approve if committer is unknown', async function () {
189+
// make the approver also the committer
190+
const testPush = { ...TEST_PUSH };
191+
testPush.user = TEST_USERNAME_3;
192+
testPush.userEmail = TEST_EMAIL_3;
193+
await db.writeAudit(testPush);
194+
await loginAsApprover();
195+
const res = await chai
196+
.request(app)
197+
.post(`/api/v1/push/${TEST_PUSH.id}/authorise`)
198+
.set('Cookie', `${cookie}`)
199+
.set('content-type', 'application/x-www-form-urlencoded')
200+
.send({
201+
params: {
202+
attestation: [
203+
{
204+
label: 'I am happy for this to be pushed to the upstream repository',
205+
tooltip: {
206+
text: 'Are you happy for this contribution to be pushed upstream?',
207+
links: [],
208+
},
209+
checked: true,
210+
},
211+
],
212+
},
213+
});
214+
res.should.have.status(401);
215+
});
216+
217+
it('should NOT allow an authorizer to approve their own push', async function () {
218+
// make the approver also the committer
219+
const testPush = { ...TEST_PUSH };
220+
testPush.user = TEST_USERNAME_1;
221+
testPush.userEmail = TEST_EMAIL_1;
222+
await db.writeAudit(testPush);
223+
await loginAsApprover();
224+
const res = await chai
225+
.request(app)
226+
.post(`/api/v1/push/${TEST_PUSH.id}/authorise`)
227+
.set('Cookie', `${cookie}`)
228+
.set('content-type', 'application/x-www-form-urlencoded')
229+
.send({
230+
params: {
231+
attestation: [
232+
{
233+
label: 'I am happy for this to be pushed to the upstream repository',
234+
tooltip: {
235+
text: 'Are you happy for this contribution to be pushed upstream?',
236+
links: [],
237+
},
238+
checked: true,
239+
},
240+
],
241+
},
242+
});
243+
res.should.have.status(401);
244+
});
245+
246+
it('should NOT allow a non-authorizer to approve a push', async function () {
247+
await db.writeAudit(TEST_PUSH);
248+
await loginAsCommitter();
249+
const res = await chai
250+
.request(app)
251+
.post(`/api/v1/push/${TEST_PUSH.id}/authorise`)
252+
.set('Cookie', `${cookie}`)
253+
.set('content-type', 'application/x-www-form-urlencoded')
254+
.send({
255+
params: {
256+
attestation: [
257+
{
258+
label: 'I am happy for this to be pushed to the upstream repository',
259+
tooltip: {
260+
text: 'Are you happy for this contribution to be pushed upstream?',
261+
links: [],
262+
},
263+
checked: true,
264+
},
265+
],
266+
},
267+
});
268+
res.should.have.status(401);
269+
});
270+
271+
it('should allow an authorizer to reject a push', async function () {
272+
await db.writeAudit(TEST_PUSH);
273+
await loginAsApprover();
274+
const res = await chai
275+
.request(app)
276+
.post(`/api/v1/push/${TEST_PUSH.id}/reject`)
277+
.set('Cookie', `${cookie}`);
278+
res.should.have.status(200);
279+
});
280+
281+
it('should NOT allow an authorizer to reject their own push', async function () {
282+
// make the approver also the committer
283+
const testPush = { ...TEST_PUSH };
284+
testPush.user = TEST_USERNAME_1;
285+
testPush.userEmail = TEST_EMAIL_1;
286+
await db.writeAudit(testPush);
287+
await loginAsApprover();
288+
const res = await chai
289+
.request(app)
290+
.post(`/api/v1/push/${TEST_PUSH.id}/reject`)
291+
.set('Cookie', `${cookie}`);
292+
res.should.have.status(401);
293+
});
294+
295+
it('should NOT allow a non-authorizer to reject a push', async function () {
296+
await db.writeAudit(TEST_PUSH);
297+
await loginAsCommitter();
298+
const res = await chai
299+
.request(app)
300+
.post(`/api/v1/push/${TEST_PUSH.id}/reject`)
301+
.set('Cookie', `${cookie}`);
302+
res.should.have.status(401);
303+
});
45304
});
46305

47306
after(async function () {
48307
const res = await chai.request(app).post('/api/auth/logout').set('Cookie', `${cookie}`);
49308
res.should.have.status(200);
50309

51310
await service.httpServer.close();
311+
312+
await db.deleteRepo(TEST_REPO);
313+
await db.deleteUser(TEST_USERNAME_1);
314+
await db.deleteUser(TEST_USERNAME_2);
315+
await db.deletePush(TEST_PUSH.id);
52316
});
53317
});

0 commit comments

Comments
 (0)