@@ -149,88 +149,231 @@ describe('API retros', () => {
149149 } ) ;
150150 } ) ;
151151
152- describe ( 'PUT /api/retros/retro-id/password ' , ( ) => {
153- it ( 'changes the retro password ' , async ( props ) => {
152+ describe ( 'GET /api/retros/retro-id' , ( ) => {
153+ it ( 'returns the current retro state ' , async ( props ) => {
154154 const { server, hooks } = props . getTyped ( PROPS ) ;
155155
156156 const id = ( await hooks . retroService . getRetroIdForSlug ( 'my-retro' ) ) ! ;
157- const grant1 = await hooks . retroAuthService . grantForPassword (
157+ const retroToken = await getRetroToken ( hooks , id ) ;
158+
159+ const response = await request ( server )
160+ . get ( `/api/retros/${ id } ` )
161+ . set ( 'Authorization' , `Bearer ${ retroToken } ` )
162+ . expect ( 200 ) ;
163+
164+ expect ( response . body ) . toEqual ( {
158165 id,
159- 'password1' ,
160- ) ;
161- if ( ! grant1 ) {
162- throw new Error ( 'failed to get retro token' ) ;
163- }
166+ slug : 'my-retro' ,
167+ name : 'My Retro' ,
168+ ownerId : 'nobody' ,
169+ state : { } ,
170+ groupStates : { } ,
171+ format : 'mood' ,
172+ options : { } ,
173+ items : [ ] ,
174+ } ) ;
175+ } ) ;
164176
165- await request ( server )
166- . put ( `/api/retros/${ id } /password` )
167- . send ( { password : 'password2' , evictUsers : false } )
168- . set ( 'Authorization' , `Bearer ${ grant1 . token } ` )
169- . expect ( 200 )
170- . expect ( 'Content-Type' , / a p p l i c a t i o n \/ j s o n / ) ;
177+ it ( 'responds HTTP Unauthorized if no credentials are given' , async ( props ) => {
178+ const { server, hooks } = props . getTyped ( PROPS ) ;
171179
172- // existing token is still valid
173- expect (
174- await hooks . retroAuthService . readAndVerifyToken ( id , grant1 . token ) ,
175- ) . isTruthy ( ) ;
180+ const id = ( await hooks . retroService . getRetroIdForSlug ( 'my-retro' ) ) ! ;
181+ await request ( server ) . get ( `/api/retros/${ id } ` ) . expect ( 401 ) ;
182+ } ) ;
176183
177- // new token requests must use new password
178- expect (
179- await hooks . retroAuthService . grantForPassword ( id , 'password1' ) ,
180- ) . isNull ( ) ;
184+ it ( 'responds HTTP Unauthorized if credentials are incorrect' , async ( props ) => {
185+ const { server, hooks } = props . getTyped ( PROPS ) ;
181186
182- const grant2 = await hooks . retroAuthService . grantForPassword (
183- id ,
184- 'password2' ,
185- ) ;
186- expect ( grant2 ) . isTruthy ( ) ;
187- expect (
188- await hooks . retroAuthService . readAndVerifyToken ( id , grant2 ! . token ) ,
189- ) . isTruthy ( ) ;
187+ const id = ( await hooks . retroService . getRetroIdForSlug ( 'my-retro' ) ) ! ;
188+ await request ( server )
189+ . get ( `/api/retros/${ id } ` )
190+ . set ( 'Authorization' , 'Bearer Foo' )
191+ . expect ( 401 ) ;
190192 } ) ;
191193
192- it ( 'voids existing tokens if requested ' , async ( props ) => {
194+ it ( 'responds HTTP Forbidden if scope is not "read" ' , async ( props ) => {
193195 const { server, hooks } = props . getTyped ( PROPS ) ;
194196
195197 const id = ( await hooks . retroService . getRetroIdForSlug ( 'my-retro' ) ) ! ;
196- const grant1 = await hooks . retroAuthService . grantForPassword (
197- id ,
198- 'password1' ,
199- ) ;
200- if ( ! grant1 ) {
201- throw new Error ( 'failed to get retro token' ) ;
202- }
198+ const retroToken = await getRetroToken ( hooks , id , {
199+ read : false ,
200+ } ) ;
203201
204202 await request ( server )
205- . put ( `/api/retros/${ id } /password ` )
206- . send ( { password : 'password2 ', evictUsers : true } )
207- . set ( 'Authorization' , `Bearer ${ grant1 . token } ` )
208- . expect ( 200 )
209- . expect ( 'Content-Type' , / a p p l i c a t i o n \/ j s o n / ) ;
203+ . get ( `/api/retros/${ id } ` )
204+ . set ( 'Authorization ', `Bearer ${ retroToken } ` )
205+ . expect ( 403 ) ;
206+ } ) ;
207+ } ) ;
210208
211- // existing token is no longer valid
212- expect (
213- await hooks . retroAuthService . readAndVerifyToken ( id , grant1 . token ) ,
214- ) . isNull ( ) ;
209+ describe ( 'PATCH /api/retros/retro-id' , ( ) => {
210+ describe ( 'with retro spec' , ( ) => {
211+ it ( 'applies the spec to the retro' , async ( props ) => {
212+ const { server , hooks } = props . getTyped ( PROPS ) ;
215213
216- // new tokens are valid
217- const grant2 = await hooks . retroAuthService . grantForPassword (
218- id ,
219- 'password2' ,
220- ) ;
221- expect ( grant2 ) . isTruthy ( ) ;
222- expect (
223- await hooks . retroAuthService . readAndVerifyToken ( id , grant2 ! . token ) ,
224- ) . isTruthy ( ) ;
214+ const id = ( await hooks . retroService . getRetroIdForSlug ( 'my-retro' ) ) ! ;
215+ const retroToken = await getRetroToken ( hooks , id ) ;
216+
217+ await request ( server )
218+ . patch ( `/api/retros/${ id } ` )
219+ . send ( { change : { state : [ '=' , { foo : 'bar' } ] } } )
220+ . set ( 'Authorization' , `Bearer ${ retroToken } ` )
221+ . expect ( 200 ) ;
222+
223+ const retro = await hooks . retroService . getRetro ( id ) ;
224+ expect ( retro ?. state ) . toEqual ( { foo : 'bar' } ) ;
225+ } ) ;
226+
227+ it ( 'does not require "manage" scope' , async ( props ) => {
228+ const { server, hooks } = props . getTyped ( PROPS ) ;
229+
230+ const id = ( await hooks . retroService . getRetroIdForSlug ( 'my-retro' ) ) ! ;
231+ const retroToken = await getRetroToken ( hooks , id , {
232+ manage : false ,
233+ } ) ;
234+
235+ await request ( server )
236+ . patch ( `/api/retros/${ id } ` )
237+ . send ( { change : { state : [ '=' , { foo : 'bar' } ] } } )
238+ . set ( 'Authorization' , `Bearer ${ retroToken } ` )
239+ . expect ( 200 ) ;
240+
241+ const retro = await hooks . retroService . getRetro ( id ) ;
242+ expect ( retro ?. state ) . toEqual ( { foo : 'bar' } ) ;
243+ } ) ;
244+
245+ it ( 'responds HTTP Forbidden if scope is not "write"' , async ( props ) => {
246+ const { server, hooks } = props . getTyped ( PROPS ) ;
247+
248+ const id = ( await hooks . retroService . getRetroIdForSlug ( 'my-retro' ) ) ! ;
249+ const retroToken = await getRetroToken ( hooks , id , {
250+ write : false ,
251+ } ) ;
252+
253+ await request ( server )
254+ . patch ( `/api/retros/${ id } ` )
255+ . send ( { change : { state : [ '=' , { foo : 'bar' } ] } } )
256+ . set ( 'Authorization' , `Bearer ${ retroToken } ` )
257+ . expect ( 403 ) ;
258+
259+ const retro = await hooks . retroService . getRetro ( id ) ;
260+ expect ( retro ?. state ) . toEqual ( { } ) ;
261+ } ) ;
262+ } ) ;
263+
264+ describe ( 'with new password' , ( ) => {
265+ it ( 'changes the retro password' , async ( props ) => {
266+ const { server, hooks } = props . getTyped ( PROPS ) ;
267+
268+ const id = ( await hooks . retroService . getRetroIdForSlug ( 'my-retro' ) ) ! ;
269+ const grant1 = await hooks . retroAuthService . grantForPassword (
270+ id ,
271+ 'password1' ,
272+ ) ;
273+ if ( ! grant1 ) {
274+ throw new Error ( 'failed to get retro token' ) ;
275+ }
276+
277+ await request ( server )
278+ . patch ( `/api/retros/${ id } ` )
279+ . send ( { setPassword : { password : 'password2' , evictUsers : false } } )
280+ . set ( 'Authorization' , `Bearer ${ grant1 . token } ` )
281+ . expect ( 200 )
282+ . expect ( 'Content-Type' , / a p p l i c a t i o n \/ j s o n / ) ;
283+
284+ // existing token is still valid
285+ expect (
286+ await hooks . retroAuthService . readAndVerifyToken ( id , grant1 . token ) ,
287+ ) . isTruthy ( ) ;
288+
289+ // new token requests must use new password
290+ expect (
291+ await hooks . retroAuthService . grantForPassword ( id , 'password1' ) ,
292+ ) . isNull ( ) ;
293+
294+ const grant2 = await hooks . retroAuthService . grantForPassword (
295+ id ,
296+ 'password2' ,
297+ ) ;
298+ expect ( grant2 ) . isTruthy ( ) ;
299+ expect (
300+ await hooks . retroAuthService . readAndVerifyToken ( id , grant2 ! . token ) ,
301+ ) . isTruthy ( ) ;
302+ } ) ;
303+
304+ it ( 'voids existing tokens if requested' , async ( props ) => {
305+ const { server, hooks } = props . getTyped ( PROPS ) ;
306+
307+ const id = ( await hooks . retroService . getRetroIdForSlug ( 'my-retro' ) ) ! ;
308+ const grant1 = await hooks . retroAuthService . grantForPassword (
309+ id ,
310+ 'password1' ,
311+ ) ;
312+ if ( ! grant1 ) {
313+ throw new Error ( 'failed to get retro token' ) ;
314+ }
315+
316+ await request ( server )
317+ . patch ( `/api/retros/${ id } ` )
318+ . send ( { setPassword : { password : 'password2' , evictUsers : true } } )
319+ . set ( 'Authorization' , `Bearer ${ grant1 . token } ` )
320+ . expect ( 200 )
321+ . expect ( 'Content-Type' , / a p p l i c a t i o n \/ j s o n / ) ;
322+
323+ // existing token is no longer valid
324+ expect (
325+ await hooks . retroAuthService . readAndVerifyToken ( id , grant1 . token ) ,
326+ ) . isNull ( ) ;
327+
328+ // new tokens are valid
329+ const grant2 = await hooks . retroAuthService . grantForPassword (
330+ id ,
331+ 'password2' ,
332+ ) ;
333+ expect ( grant2 ) . isTruthy ( ) ;
334+ expect (
335+ await hooks . retroAuthService . readAndVerifyToken ( id , grant2 ! . token ) ,
336+ ) . isTruthy ( ) ;
337+ } ) ;
338+
339+ it ( 'does not require "write" scope' , async ( props ) => {
340+ const { server, hooks } = props . getTyped ( PROPS ) ;
341+
342+ const id = ( await hooks . retroService . getRetroIdForSlug ( 'my-retro' ) ) ! ;
343+ const retroToken = await getRetroToken ( hooks , id , {
344+ write : false ,
345+ } ) ;
346+
347+ await request ( server )
348+ . patch ( `/api/retros/${ id } ` )
349+ . send ( { setPassword : { password : 'password2' , evictUsers : false } } )
350+ . set ( 'Authorization' , `Bearer ${ retroToken } ` )
351+ . expect ( 200 ) ;
352+ } ) ;
353+
354+ it ( 'responds HTTP Forbidden if scope is not "manage"' , async ( props ) => {
355+ const { server, hooks } = props . getTyped ( PROPS ) ;
356+
357+ const id = ( await hooks . retroService . getRetroIdForSlug ( 'my-retro' ) ) ! ;
358+ const retroToken = await getRetroToken ( hooks , id , {
359+ manage : false ,
360+ } ) ;
361+
362+ await request ( server )
363+ . patch ( `/api/retros/${ id } ` )
364+ . send ( { setPassword : { password : 'password2' , evictUsers : false } } )
365+ . set ( 'Authorization' , `Bearer ${ retroToken } ` )
366+ . expect ( 403 ) ;
367+ } ) ;
225368 } ) ;
226369
227370 it ( 'responds HTTP Unauthorized if no credentials are given' , async ( props ) => {
228371 const { server, hooks } = props . getTyped ( PROPS ) ;
229372
230373 const id = ( await hooks . retroService . getRetroIdForSlug ( 'my-retro' ) ) ! ;
231374 await request ( server )
232- . put ( `/api/retros/${ id } /password ` )
233- . send ( { password : 'password2' , evictUsers : false } )
375+ . patch ( `/api/retros/${ id } ` )
376+ . send ( { setPassword : { password : 'password2' , evictUsers : false } } )
234377 . expect ( 401 ) ;
235378 } ) ;
236379
@@ -239,26 +382,11 @@ describe('API retros', () => {
239382
240383 const id = ( await hooks . retroService . getRetroIdForSlug ( 'my-retro' ) ) ! ;
241384 await request ( server )
242- . put ( `/api/retros/${ id } /password ` )
243- . send ( { password : 'password2' , evictUsers : false } )
385+ . patch ( `/api/retros/${ id } ` )
386+ . send ( { setPassword : { password : 'password2' , evictUsers : false } } )
244387 . set ( 'Authorization' , 'Bearer Foo' )
245388 . expect ( 401 ) ;
246389 } ) ;
247-
248- it ( 'responds HTTP Forbidden if scope is not "manage"' , async ( props ) => {
249- const { server, hooks } = props . getTyped ( PROPS ) ;
250-
251- const id = ( await hooks . retroService . getRetroIdForSlug ( 'my-retro' ) ) ! ;
252- const retroToken = await getRetroToken ( hooks , id , {
253- manage : false ,
254- } ) ;
255-
256- await request ( server )
257- . put ( `/api/retros/${ id } /password` )
258- . send ( { password : 'password2' , evictUsers : false } )
259- . set ( 'Authorization' , `Bearer ${ retroToken } ` )
260- . expect ( 403 ) ;
261- } ) ;
262390 } ) ;
263391} ) ;
264392
0 commit comments