@@ -8,32 +8,120 @@ chai.use(chaiHttp);
8
8
chai . should ( ) ;
9
9
const expect = chai . expect ;
10
10
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
+
11
55
describe ( 'auth' , async ( ) => {
12
56
let app ;
13
57
let cookie ;
14
58
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
+ } ;
18
67
68
+ const login = async function ( username , password ) {
69
+ console . log ( `logging in as ${ username } ...` ) ;
19
70
const res = await chai . request ( app ) . post ( '/api/auth/login' ) . send ( {
20
- username : 'admin' ,
21
- password : 'admin' ,
71
+ username : username ,
72
+ password : password ,
22
73
} ) ;
23
-
74
+ res . should . have . status ( 200 ) ;
24
75
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 } ` ) ;
25
85
res . should . have . status ( 200 ) ;
86
+ cookie = null ;
87
+ } ;
26
88
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 ,
32
100
} ) ;
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 ( ) ;
33
114
} ) ;
34
115
35
116
describe ( 'test push API' , async function ( ) {
117
+ afterEach ( async function ( ) {
118
+ await db . deletePush ( TEST_PUSH . id ) ;
119
+ await logout ( ) ;
120
+ } ) ;
121
+
36
122
it ( 'should get 404 for unknown push' , async function ( ) {
123
+ await loginAsApprover ( ) ;
124
+
37
125
const commitId =
38
126
'0000000000000000000000000000000000000000__79b4d8953cbc324bcc1eb53d6412ff89666c241f' ; // eslint-disable-line max-len
39
127
const res = await chai
@@ -42,12 +130,188 @@ describe('auth', async () => {
42
130
. set ( 'Cookie' , `${ cookie } ` ) ;
43
131
res . should . have . status ( 404 ) ;
44
132
} ) ;
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
+ } ) ;
45
304
} ) ;
46
305
47
306
after ( async function ( ) {
48
307
const res = await chai . request ( app ) . post ( '/api/auth/logout' ) . set ( 'Cookie' , `${ cookie } ` ) ;
49
308
res . should . have . status ( 200 ) ;
50
309
51
310
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 ) ;
52
316
} ) ;
53
317
} ) ;
0 commit comments