View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.juneau.rest.annotation;
18  
19  import org.apache.juneau.*;
20  import org.apache.juneau.rest.client.*;
21  import org.apache.juneau.rest.mock.*;
22  import org.junit.jupiter.api.*;
23  
24  class Restx_RoleGuard_Test extends TestBase {
25  
26  	private static RestOperation[] ops(RestOperation...ops) {
27  		return ops;
28  	}
29  
30  	private static RestOperation op(String method, String url) {
31  		return RestOperation.of(method, url);
32  	}
33  
34  	//-----------------------------------------------------------------------------------------------------------------
35  	// Simple guard on class
36  	//-----------------------------------------------------------------------------------------------------------------
37  
38  	@Rest(roleGuard="foo")
39  	public static class A1 {
40  		@RestOp
41  		public String a() {
42  			return "OK";
43  		}
44  		@RestGet
45  		public String b() {
46  			return "OK";
47  		}
48  		@RestPut
49  		public String c() {
50  			return "OK";
51  		}
52  		@RestPost
53  		public String d() {
54  			return "OK";
55  		}
56  		@RestDelete
57  		public String e() {
58  			return "OK";
59  		}
60  	}
61  
62  	@Test void a01a_onClass_simple() throws Exception {
63  		var a1 = MockRestClient.buildLax(A1.class);
64  
65  		for (RestOperation op : ops(op("get","/a"),op("get","/b"),op("put","/c"),op("post","/d"),op("delete","/e"))) {
66  			a1.request(op).roles("foo").run().assertStatus(200);
67  			a1.request(op).roles("foo","bar").run().assertStatus(200);
68  			a1.request(op).roles("bar","foo").run().assertStatus(200);
69  			a1.request(op).run().assertStatus(403);
70  			a1.request(op).roles("foo2").run().assertStatus(403);
71  			a1.request(op).roles("foo2","bar").run().assertStatus(403);
72  		}
73  	}
74  
75  	//-----------------------------------------------------------------------------------------------------------------
76  	// Simple guard on method
77  	//-----------------------------------------------------------------------------------------------------------------
78  
79  	@Rest
80  	public static class A2 {
81  		@RestOp(roleGuard="foo")
82  		public String a() {
83  			return "OK";
84  		}
85  		@RestGet(roleGuard="foo")
86  		public String b() {
87  			return "OK";
88  		}
89  		@RestPut(roleGuard="foo")
90  		public String c() {
91  			return "OK";
92  		}
93  		@RestPost(roleGuard="foo")
94  		public String d() {
95  			return "OK";
96  		}
97  		@RestDelete(roleGuard="foo")
98  		public String e() {
99  			return "OK";
100 		}
101 	}
102 
103 	@Test void a02a_onMethod_simple() throws Exception {
104 		var a2 = MockRestClient.buildLax(A2.class);
105 
106 		for (RestOperation op : ops(op("get","/a"),op("get","/b"),op("put","/c"),op("post","/d"),op("delete","/e"))) {
107 			a2.request(op).roles("foo").run().assertStatus(200);
108 			a2.request(op).roles("foo","bar").run().assertStatus(200);
109 			a2.request(op).roles("bar","foo").run().assertStatus(200);
110 			a2.request(op).run().assertStatus(403);
111 			a2.request(op).roles("foo2").run().assertStatus(403);
112 			a2.request(op).roles("foo2","bar").run().assertStatus(403);
113 		}
114 	}
115 
116 	//-----------------------------------------------------------------------------------------------------------------
117 	// Simple guards on class and method
118 	//-----------------------------------------------------------------------------------------------------------------
119 
120 	@Rest(roleGuard="foo")
121 	public static class A3 {
122 		@RestOp(roleGuard="bar")
123 		public String a() {
124 			return "OK";
125 		}
126 		@RestGet(roleGuard="bar")
127 		public String b() {
128 			return "OK";
129 		}
130 		@RestPut(roleGuard="bar")
131 		public String c() {
132 			return "OK";
133 		}
134 		@RestPost(roleGuard="bar")
135 		public String d() {
136 			return "OK";
137 		}
138 		@RestDelete(roleGuard="bar")
139 		public String e() {
140 			return "OK";
141 		}
142 	}
143 
144 	@Test void a03a_onBoth_simple() throws Exception {
145 		var a3 = MockRestClient.buildLax(A3.class);
146 
147 		for (RestOperation op : ops(op("get","/a"),op("get","/b"),op("put","/c"),op("post","/d"),op("delete","/e"))) {
148 			a3.request(op).roles("foo","bar").run().assertStatus(200);
149 			a3.request(op).roles("bar","foo").run().assertStatus(200);
150 			a3.request(op).roles("bar","foo","baz").run().assertStatus(200);
151 			a3.request(op).run().assertStatus(403);
152 			a3.request(op).roles("foo").run().assertStatus(403);
153 			a3.request(op).roles("bar").run().assertStatus(403);
154 			a3.request(op).roles("foo2").run().assertStatus(403);
155 			a3.request(op).roles("foo2","bar").run().assertStatus(403);
156 		}
157 	}
158 
159 	//-----------------------------------------------------------------------------------------------------------------
160 	// Simple guards on class and method, inherited
161 	//-----------------------------------------------------------------------------------------------------------------
162 
163 	@Rest(roleGuard="foo")
164 	public static class A4a {
165 		@RestOp(roleGuard="bar")
166 		public String a() {
167 			return "OK";
168 		}
169 		@RestGet(roleGuard="bar")
170 		public String b() {
171 			return "OK";
172 		}
173 		@RestPut(roleGuard="bar")
174 		public String c() {
175 			return "OK";
176 		}
177 		@RestPost(roleGuard="bar")
178 		public String d() {
179 			return "OK";
180 		}
181 		@RestDelete(roleGuard="bar")
182 		public String e() {
183 			return "OK";
184 		}
185 	}
186 
187 	@Rest(roleGuard="baz")
188 	public static class A4b extends A4a {
189 		@Override
190 		@RestOp(roleGuard="qux")
191 		public String a() {
192 			return "OK";
193 		}
194 		@Override
195 		@RestGet(roleGuard="qux")
196 		public String b() {
197 			return "OK";
198 		}
199 		@Override
200 		@RestPut(roleGuard="qux")
201 		public String c() {
202 			return "OK";
203 		}
204 		@Override
205 		@RestPost(roleGuard="qux")
206 		public String d() {
207 			return "OK";
208 		}
209 		@Override
210 		@RestDelete(roleGuard="qux")
211 		public String e() {
212 			return "OK";
213 		}
214 	}
215 
216 	@Test void a04a_inheritence_simple() throws Exception {
217 		var a4 = MockRestClient.buildLax(A4b.class);
218 
219 		for (RestOperation op : ops(op("get","/a"),op("get","/b"),op("put","/c"),op("post","/d"),op("delete","/e"))) {
220 			a4.request(op).roles("foo","bar","baz","qux").run().assertStatus(200);
221 			a4.request(op).roles("foo","bar","baz","qux","quux").run().assertStatus(200);
222 			a4.request(op).roles("foo","bar","baz").run().assertStatus(403);
223 			a4.request(op).roles("foo","bar","qux").run().assertStatus(403);
224 			a4.request(op).roles("foo","baz","qux").run().assertStatus(403);
225 			a4.request(op).roles("bar","baz","qux").run().assertStatus(403);
226 		}
227 	}
228 
229 	//-----------------------------------------------------------------------------------------------------------------
230 	// @Rest(roleGuard), multiple guards on class
231 	//-----------------------------------------------------------------------------------------------------------------
232 
233 	@Rest
234 	public static class B1 {
235 		@RestOp
236 		public String a() {
237 			return "OK";
238 		}
239 		@RestGet
240 		public String b() {
241 			return "OK";
242 		}
243 		@RestPut
244 		public String c() {
245 			return "OK";
246 		}
247 		@RestPost
248 		public String d() {
249 			return "OK";
250 		}
251 		@RestDelete
252 		public String e() {
253 			return "OK";
254 		}
255 	}
256 
257 	@Rest(roleGuard="foo,bar")
258 	public static class B1a extends B1 {}
259 
260 	@Test void b01a_orsWithComma_pass() throws Exception {
261 		var b1a = MockRestClient.buildLax(B1a.class);
262 
263 		for (RestOperation op : ops(op("get","/a"),op("get","/b"),op("put","/c"),op("post","/d"),op("delete","/e"))) {
264 			b1a.request(op).roles("foo").run().assertStatus(200);
265 			b1a.request(op).roles("bar").run().assertStatus(200);
266 			b1a.request(op).roles("foo","bar").run().assertStatus(200);
267 			b1a.request(op).roles("foo","bar","baz").run().assertStatus(200);
268 			b1a.request(op).roles().run().assertStatus(403);
269 			b1a.request(op).roles("baz").run().assertStatus(403);
270 		}
271 	}
272 
273 	@Rest(roleGuard="foo | bar")
274 	public static class B1b extends B1 {}
275 
276 	@Test void b01b_orsWithSinglePipe_pass() throws Exception {
277 		var b1b = MockRestClient.buildLax(B1b.class);
278 
279 		for (RestOperation op : ops(op("get","/a"),op("get","/b"),op("put","/c"),op("post","/d"),op("delete","/e"))) {
280 			b1b.request(op).roles("foo").run().assertStatus(200);
281 			b1b.request(op).roles("bar").run().assertStatus(200);
282 			b1b.request(op).roles("foo","bar").run().assertStatus(200);
283 			b1b.request(op).roles("foo","bar","baz").run().assertStatus(200);
284 			b1b.request(op).roles().run().assertStatus(403);
285 			b1b.request(op).roles("baz").run().assertStatus(403);
286 		}
287 	}
288 
289 	@Rest(roleGuard="foo || bar")
290 	public static class B1c extends B1 {}
291 
292 	@Test void b01c_orsWithDoublePipe_pass() throws Exception {
293 		var b1c = MockRestClient.buildLax(B1c.class);
294 
295 		for (RestOperation op : ops(op("get","/a"),op("get","/b"),op("put","/c"),op("post","/d"),op("delete","/e"))) {
296 			b1c.request(op).roles("foo").run().assertStatus(200);
297 			b1c.request(op).roles("bar").run().assertStatus(200);
298 			b1c.request(op).roles("foo","bar").run().assertStatus(200);
299 			b1c.request(op).roles("foo","bar","baz").run().assertStatus(200);
300 			b1c.request(op).roles().run().assertStatus(403);
301 			b1c.request(op).roles("baz").run().assertStatus(403);
302 		}
303 	}
304 
305 	@Rest(roleGuard="foo & bar")
306 	public static class B1d extends B1 {}
307 
308 	@Test void b01d_andsWithSingleAmp_pass() throws Exception {
309 		var b1d = MockRestClient.buildLax(B1d.class);
310 
311 		for (RestOperation op : ops(op("get","/a"),op("get","/b"),op("put","/c"),op("post","/d"),op("delete","/e"))) {
312 			b1d.request(op).roles("foo","bar").run().assertStatus(200);
313 			b1d.request(op).roles("foo","bar","baz").run().assertStatus(200);
314 			b1d.request(op).roles().run().assertStatus(403);
315 			b1d.request(op).roles("foo").run().assertStatus(403);
316 			b1d.request(op).roles("bar").run().assertStatus(403);
317 			b1d.request(op).roles("baz").run().assertStatus(403);
318 		}
319 	}
320 
321 	@Rest(roleGuard="foo && bar")
322 	public static class B1e extends B1 {}
323 
324 	@Test void b01e_andsWithDoubleAmp_pass() throws Exception {
325 		var b1e = MockRestClient.buildLax(B1e.class);
326 
327 		for (RestOperation op : ops(op("get","/a"),op("get","/b"),op("put","/c"),op("post","/d"),op("delete","/e"))) {
328 			b1e.request(op).roles("foo","bar").run().assertStatus(200);
329 			b1e.request(op).roles("foo","bar","baz").run().assertStatus(200);
330 			b1e.request(op).roles().run().assertStatus(403);
331 			b1e.request(op).roles("foo").run().assertStatus(403);
332 			b1e.request(op).roles("bar").run().assertStatus(403);
333 			b1e.request(op).roles("baz").run().assertStatus(403);
334 		}
335 	}
336 
337 	@Rest(roleGuard="(foo) && (bar)")
338 	public static class B1f extends B1 {}
339 
340 	@Test void b01f_andsWithDoubleAmpAndParens_pass() throws Exception {
341 		var b1f = MockRestClient.buildLax(B1f.class);
342 
343 		for (RestOperation op : ops(op("get","/a"),op("get","/b"),op("put","/c"),op("post","/d"),op("delete","/e"))) {
344 			b1f.request(op).roles("foo","bar").run().assertStatus(200);
345 			b1f.request(op).roles("foo","bar","baz").run().assertStatus(200);
346 			b1f.request(op).roles().run().assertStatus(403);
347 			b1f.request(op).roles("foo").run().assertStatus(403);
348 			b1f.request(op).roles("bar").run().assertStatus(403);
349 			b1f.request(op).roles("baz").run().assertStatus(403);
350 		}
351 	}
352 
353 	@Rest(roleGuard="foo && (bar || baz)")
354 	public static class B1g extends B1 {}
355 
356 	@Test void b01g_complex_pass() throws Exception {
357 		var b1g = MockRestClient.buildLax(B1g.class);
358 
359 		for (RestOperation op : ops(op("get","/a"),op("get","/b"),op("put","/c"),op("post","/d"),op("delete","/e"))) {
360 			b1g.request(op).roles("foo","bar").run().assertStatus(200);
361 			b1g.request(op).roles("foo","baz").run().assertStatus(200);
362 			b1g.request(op).roles("foo","bar","baz").run().assertStatus(200);
363 			b1g.request(op).roles().run().assertStatus(403);
364 			b1g.request(op).roles("foo").run().assertStatus(403);
365 			b1g.request(op).roles("bar","baz").run().assertStatus(403);
366 			b1g.request(op).roles("baz").run().assertStatus(403);
367 		}
368 	}
369 
370 	@Rest(roleGuard="foo || (bar && baz)")
371 	public static class B1h extends B1 {}
372 
373 	@Test void b01h_complex_pass() throws Exception {
374 		var b1h = MockRestClient.buildLax(B1h.class);
375 
376 		for (RestOperation op : ops(op("get","/a"),op("get","/b"),op("put","/c"),op("post","/d"),op("delete","/e"))) {
377 			b1h.request(op).roles("foo").run().assertStatus(200);
378 			b1h.request(op).roles("bar","baz").run().assertStatus(200);
379 			b1h.request(op).roles("foo","bar","baz").run().assertStatus(200);
380 			b1h.request(op).roles().run().assertStatus(403);
381 			b1h.request(op).roles("bar").run().assertStatus(403);
382 			b1h.request(op).roles("baz").run().assertStatus(403);
383 		}
384 	}
385 
386 	//-----------------------------------------------------------------------------------------------------------------
387 	// @RestOp(roleGuard), multiple guards on method
388 	//-----------------------------------------------------------------------------------------------------------------
389 
390 	@Rest
391 	public static class B2a {
392 		@RestOp(roleGuard="foo,bar")
393 		public String a() {
394 			return "OK";
395 		}
396 		@RestGet(roleGuard="foo,bar")
397 		public String b() {
398 			return "OK";
399 		}
400 		@RestPut(roleGuard="foo,bar")
401 		public String c() {
402 			return "OK";
403 		}
404 		@RestPost(roleGuard="foo,bar")
405 		public String d() {
406 			return "OK";
407 		}
408 		@RestDelete(roleGuard="foo,bar")
409 		public String e() {
410 			return "OK";
411 		}
412 	}
413 
414 	@Test void b02a_orsWithComma_pass() throws Exception {
415 		var b2a = MockRestClient.buildLax(B2a.class);
416 
417 		for (RestOperation op : ops(op("get","/a"),op("get","/b"),op("put","/c"),op("post","/d"),op("delete","/e"))) {
418 			b2a.request(op).roles("foo").run().assertStatus(200);
419 			b2a.request(op).roles("bar").run().assertStatus(200);
420 			b2a.request(op).roles("foo","bar").run().assertStatus(200);
421 			b2a.request(op).roles("foo","bar","baz").run().assertStatus(200);
422 			b2a.request(op).roles().run().assertStatus(403);
423 			b2a.request(op).roles("baz").run().assertStatus(403);
424 		}
425 	}
426 
427 	@Rest
428 	public static class B2b {
429 		@RestOp(roleGuard="foo | bar")
430 		public String a() {
431 			return "OK";
432 		}
433 		@RestGet(roleGuard="foo | bar")
434 		public String b() {
435 			return "OK";
436 		}
437 		@RestPut(roleGuard="foo | bar")
438 		public String c() {
439 			return "OK";
440 		}
441 		@RestPost(roleGuard="foo | bar")
442 		public String d() {
443 			return "OK";
444 		}
445 		@RestDelete(roleGuard="foo | bar")
446 		public String e() {
447 			return "OK";
448 		}
449 	}
450 
451 	@Test void b02b_orsWithSinglePipe_pass() throws Exception {
452 		var b2b = MockRestClient.buildLax(B2b.class);
453 
454 		for (RestOperation op : ops(op("get","/a"),op("get","/b"),op("put","/c"),op("post","/d"),op("delete","/e"))) {
455 			b2b.request(op).roles("foo").run().assertStatus(200);
456 			b2b.request(op).roles("bar").run().assertStatus(200);
457 			b2b.request(op).roles("foo","bar").run().assertStatus(200);
458 			b2b.request(op).roles("foo","bar","baz").run().assertStatus(200);
459 			b2b.request(op).roles().run().assertStatus(403);
460 			b2b.request(op).roles("baz").run().assertStatus(403);
461 		}
462 	}
463 
464 	@Rest
465 	public static class B2c {
466 		@RestOp(roleGuard="foo || bar")
467 		public String a() {
468 			return "OK";
469 		}
470 		@RestGet(roleGuard="foo || bar")
471 		public String b() {
472 			return "OK";
473 		}
474 		@RestPut(roleGuard="foo || bar")
475 		public String c() {
476 			return "OK";
477 		}
478 		@RestPost(roleGuard="foo || bar")
479 		public String d() {
480 			return "OK";
481 		}
482 		@RestDelete(roleGuard="foo || bar")
483 		public String e() {
484 			return "OK";
485 		}
486 	}
487 
488 	@Test void b02c_orsWithDoublePipe_pass() throws Exception {
489 		var b2c = MockRestClient.buildLax(B2c.class);
490 
491 		for (RestOperation op : ops(op("get","/a"),op("get","/b"),op("put","/c"),op("post","/d"),op("delete","/e"))) {
492 			b2c.request(op).roles("foo").run().assertStatus(200);
493 			b2c.request(op).roles("bar").run().assertStatus(200);
494 			b2c.request(op).roles("foo","bar").run().assertStatus(200);
495 			b2c.request(op).roles("foo","bar","baz").run().assertStatus(200);
496 			b2c.request(op).roles().run().assertStatus(403);
497 			b2c.request(op).roles("baz").run().assertStatus(403);
498 		}
499 	}
500 
501 	@Rest
502 	public static class B2d {
503 		@RestOp(roleGuard="foo & bar")
504 		public String a() {
505 			return "OK";
506 		}
507 		@RestGet(roleGuard="foo & bar")
508 		public String b() {
509 			return "OK";
510 		}
511 		@RestPut(roleGuard="foo & bar")
512 		public String c() {
513 			return "OK";
514 		}
515 		@RestPost(roleGuard="foo & bar")
516 		public String d() {
517 			return "OK";
518 		}
519 		@RestDelete(roleGuard="foo & bar")
520 		public String e() {
521 			return "OK";
522 		}
523 	}
524 
525 	@Test void b02d_andsWithSingleAmp_pass() throws Exception {
526 		var b2d = MockRestClient.buildLax(B2d.class);
527 
528 		for (RestOperation op : ops(op("get","/a"),op("get","/b"),op("put","/c"),op("post","/d"),op("delete","/e"))) {
529 			b2d.request(op).roles("foo","bar").run().assertStatus(200);
530 			b2d.request(op).roles("foo","bar","baz").run().assertStatus(200);
531 			b2d.request(op).roles().run().assertStatus(403);
532 			b2d.request(op).roles("foo").run().assertStatus(403);
533 			b2d.request(op).roles("bar").run().assertStatus(403);
534 			b2d.request(op).roles("baz").run().assertStatus(403);
535 		}
536 	}
537 
538 	@Rest
539 	public static class B2e {
540 		@RestOp(roleGuard="foo && bar")
541 		public String a() {
542 			return "OK";
543 		}
544 		@RestGet(roleGuard="foo && bar")
545 		public String b() {
546 			return "OK";
547 		}
548 		@RestPut(roleGuard="foo && bar")
549 		public String c() {
550 			return "OK";
551 		}
552 		@RestPost(roleGuard="foo && bar")
553 		public String d() {
554 			return "OK";
555 		}
556 		@RestDelete(roleGuard="foo && bar")
557 		public String e() {
558 			return "OK";
559 		}
560 	}
561 
562 	@Test void b02e_andsWithDoubleAmp_pass() throws Exception {
563 		var b2e = MockRestClient.buildLax(B2e.class);
564 
565 		for (RestOperation op : ops(op("get","/a"),op("get","/b"),op("put","/c"),op("post","/d"),op("delete","/e"))) {
566 			b2e.request(op).roles("foo","bar").run().assertStatus(200);
567 			b2e.request(op).roles("foo","bar","baz").run().assertStatus(200);
568 			b2e.request(op).roles().run().assertStatus(403);
569 			b2e.request(op).roles("foo").run().assertStatus(403);
570 			b2e.request(op).roles("bar").run().assertStatus(403);
571 			b2e.request(op).roles("baz").run().assertStatus(403);
572 		}
573 	}
574 
575 	@Rest
576 	public static class B2f {
577 		@RestOp(roleGuard="(foo) && (bar)")
578 		public String get() {
579 			return "OK";
580 		}
581 	}
582 
583 	@Test void b02f_andsWithDoubleAmpAndParens_pass() throws Exception {
584 		var b2f = MockRestClient.buildLax(B2f.class);
585 		b2f.get().roles("foo","bar").run().assertStatus(200);
586 		b2f.get().roles("foo","bar","baz").run().assertStatus(200);
587 		b2f.get().roles().run().assertStatus(403);
588 		b2f.get().roles("foo").run().assertStatus(403);
589 		b2f.get().roles("bar").run().assertStatus(403);
590 		b2f.get().roles("baz").run().assertStatus(403);
591 	}
592 
593 	@Rest
594 	public static class B2g {
595 		@RestOp(roleGuard="foo && (bar || baz)")
596 		public String get() {
597 			return "OK";
598 		}
599 	}
600 
601 	@Test void b02g_complex_pass() throws Exception {
602 		var b2g = MockRestClient.buildLax(B2g.class);
603 		b2g.get().roles("foo","bar").run().assertStatus(200);
604 		b2g.get().roles("foo","baz").run().assertStatus(200);
605 		b2g.get().roles("foo","bar","baz").run().assertStatus(200);
606 		b2g.get().roles().run().assertStatus(403);
607 		b2g.get().roles("foo").run().assertStatus(403);
608 		b2g.get().roles("bar","baz").run().assertStatus(403);
609 		b2g.get().roles("baz").run().assertStatus(403);
610 	}
611 
612 	@Rest
613 	public static class B2h {
614 		@RestOp(roleGuard="foo || (bar && baz)")
615 		public String get() {
616 			return "OK";
617 		}
618 	}
619 
620 	@Test void b02h_complex_pass() throws Exception {
621 		var b2h = MockRestClient.buildLax(B2h.class);
622 		b2h.get().roles("foo").run().assertStatus(200);
623 		b2h.get().roles("bar","baz").run().assertStatus(200);
624 		b2h.get().roles("foo","bar","baz").run().assertStatus(200);
625 		b2h.get().roles().run().assertStatus(403);
626 		b2h.get().roles("bar").run().assertStatus(403);
627 		b2h.get().roles("baz").run().assertStatus(403);
628 	}
629 
630 	//-----------------------------------------------------------------------------------------------------------------
631 	// @Rest(roleGuard), pattern guards on class
632 	//-----------------------------------------------------------------------------------------------------------------
633 
634 	@Rest(rolesDeclared="foo,bar,baz")
635 	public static class C1 {
636 		@RestOp
637 		public String a() {
638 			return "OK";
639 		}
640 		@RestGet
641 		public String b() {
642 			return "OK";
643 		}
644 		@RestPut
645 		public String c() {
646 			return "OK";
647 		}
648 		@RestPost
649 		public String d() {
650 			return "OK";
651 		}
652 		@RestDelete
653 		public String e() {
654 			return "OK";
655 		}
656 	}
657 
658 	@Rest(roleGuard="fo*,*ar")
659 	public static class C1a extends C1 {}
660 
661 	@Test void c01a_orPatternsWithComma_pass() throws Exception {
662 		var c1a = MockRestClient.buildLax(C1a.class);
663 
664 		for (RestOperation op : ops(op("get","/a"),op("get","/b"),op("put","/c"),op("post","/d"),op("delete","/e"))) {
665 			c1a.request(op).roles("foo").run().assertStatus(200);
666 			c1a.request(op).roles("bar").run().assertStatus(200);
667 			c1a.request(op).roles("foo","bar").run().assertStatus(200);
668 			c1a.request(op).roles("foo","bar","baz").run().assertStatus(200);
669 			c1a.request(op).roles().run().assertStatus(403);
670 			c1a.request(op).roles("baz").run().assertStatus(403);
671 		}
672 	}
673 
674 	@Rest(roleGuard="fo* | *ar")
675 	public static class C1b extends C1 {}
676 
677 	@Test void c01b_orPatternsWithSinglePipe_pass() throws Exception {
678 		var c1b = MockRestClient.buildLax(C1b.class);
679 
680 		for (RestOperation op : ops(op("get","/a"),op("get","/b"),op("put","/c"),op("post","/d"),op("delete","/e"))) {
681 			c1b.request(op).roles("foo").run().assertStatus(200);
682 			c1b.request(op).roles("bar").run().assertStatus(200);
683 			c1b.request(op).roles("foo","bar").run().assertStatus(200);
684 			c1b.request(op).roles("foo","bar","baz").run().assertStatus(200);
685 			c1b.request(op).roles().run().assertStatus(403);
686 			c1b.request(op).roles("baz").run().assertStatus(403);
687 		}
688 	}
689 
690 	@Rest(roleGuard="fo* || *ar")
691 	public static class C1c extends C1 {}
692 
693 	@Test void c01c_orPatternsWithDoublePipe_pass() throws Exception {
694 		var c1c = MockRestClient.buildLax(C1c.class);
695 
696 		for (RestOperation op : ops(op("get","/a"),op("get","/b"),op("put","/c"),op("post","/d"),op("delete","/e"))) {
697 			c1c.request(op).roles("foo").run().assertStatus(200);
698 			c1c.request(op).roles("bar").run().assertStatus(200);
699 			c1c.request(op).roles("foo","bar").run().assertStatus(200);
700 			c1c.request(op).roles("foo","bar","baz").run().assertStatus(200);
701 			c1c.request(op).roles().run().assertStatus(403);
702 			c1c.request(op).roles("baz").run().assertStatus(403);
703 		}
704 	}
705 
706 	@Rest(roleGuard="fo* & *ar")
707 	public static class C1d extends C1 {}
708 
709 	@Test void c01d_andPatternsWithSingleAmp_pass() throws Exception {
710 		var c1d = MockRestClient.buildLax(C1d.class);
711 
712 		for (RestOperation op : ops(op("get","/a"),op("get","/b"),op("put","/c"),op("post","/d"),op("delete","/e"))) {
713 			c1d.request(op).roles("foo","bar").run().assertStatus(200);
714 			c1d.request(op).roles("foo","bar","baz").run().assertStatus(200);
715 			c1d.request(op).roles().run().assertStatus(403);
716 			c1d.request(op).roles("foo").run().assertStatus(403);
717 			c1d.request(op).roles("bar").run().assertStatus(403);
718 			c1d.request(op).roles("baz").run().assertStatus(403);
719 		}
720 	}
721 
722 	@Rest(roleGuard="fo* && *ar")
723 	public static class C1e extends C1 {}
724 
725 	@Test void c01e_andPatternsWithDoubleAmp_pass() throws Exception {
726 		var c1e = MockRestClient.buildLax(C1e.class);
727 
728 		for (RestOperation op : ops(op("get","/a"),op("get","/b"),op("put","/c"),op("post","/d"),op("delete","/e"))) {
729 			c1e.request(op).roles("foo","bar").run().assertStatus(200);
730 			c1e.request(op).roles("foo","bar","baz").run().assertStatus(200);
731 			c1e.request(op).roles().run().assertStatus(403);
732 			c1e.request(op).roles("foo").run().assertStatus(403);
733 			c1e.request(op).roles("bar").run().assertStatus(403);
734 			c1e.request(op).roles("baz").run().assertStatus(403);
735 		}
736 	}
737 
738 	@Rest(roleGuard="(fo*) && (*ar)")
739 	public static class C1f extends C1 {}
740 
741 	@Test void c01f_andPatternsWithDoubleAmpAndParens_pass() throws Exception {
742 		var c1f = MockRestClient.buildLax(C1f.class);
743 
744 		for (RestOperation op : ops(op("get","/a"),op("get","/b"),op("put","/c"),op("post","/d"),op("delete","/e"))) {
745 			c1f.request(op).roles("foo","bar").run().assertStatus(200);
746 			c1f.request(op).roles("foo","bar","baz").run().assertStatus(200);
747 			c1f.request(op).roles().run().assertStatus(403);
748 			c1f.request(op).roles("foo").run().assertStatus(403);
749 			c1f.request(op).roles("bar").run().assertStatus(403);
750 			c1f.request(op).roles("baz").run().assertStatus(403);
751 		}
752 	}
753 
754 	@Rest(roleGuard="fo* && (*ar || *az)")
755 	public static class C1g extends C1 {}
756 
757 	@Test void c01g_complexPatterns_pass() throws Exception {
758 		var c1g = MockRestClient.buildLax(C1g.class);
759 
760 		for (RestOperation op : ops(op("get","/a"),op("get","/b"),op("put","/c"),op("post","/d"),op("delete","/e"))) {
761 			c1g.request(op).roles("foo","bar").run().assertStatus(200);
762 			c1g.request(op).roles("foo","baz").run().assertStatus(200);
763 			c1g.request(op).roles("foo","bar","baz").run().assertStatus(200);
764 			c1g.request(op).roles().run().assertStatus(403);
765 			c1g.request(op).roles("foo").run().assertStatus(403);
766 			c1g.request(op).roles("bar","baz").run().assertStatus(403);
767 			c1g.request(op).roles("baz").run().assertStatus(403);
768 		}
769 	}
770 
771 	@Rest(roleGuard="fo* || (*ar && *az)")
772 	public static class C1h extends C1 {}
773 
774 	@Test void c01h_complexPatterns_pass() throws Exception {
775 		var c1h = MockRestClient.buildLax(C1h.class);
776 
777 		for (RestOperation op : ops(op("get","/a"),op("get","/b"),op("put","/c"),op("post","/d"),op("delete","/e"))) {
778 			c1h.request(op).roles("foo").run().assertStatus(200);
779 			c1h.request(op).roles("bar","baz").run().assertStatus(200);
780 			c1h.request(op).roles("foo","bar","baz").run().assertStatus(200);
781 			c1h.request(op).roles().run().assertStatus(403);
782 			c1h.request(op).roles("bar").run().assertStatus(403);
783 			c1h.request(op).roles("baz").run().assertStatus(403);
784 		}
785 	}
786 
787 	//-----------------------------------------------------------------------------------------------------------------
788 	// @RestOp(roleGuard), pattern guards on method
789 	//-----------------------------------------------------------------------------------------------------------------
790 
791 	@Rest
792 	public static class C2a {
793 		@RestOp(roleGuard="fo*,*ar",rolesDeclared="foo,bar,baz")
794 		public String a() {
795 			return "OK";
796 		}
797 		@RestGet(roleGuard="fo*,*ar",rolesDeclared="foo,bar,baz")
798 		public String b() {
799 			return "OK";
800 		}
801 		@RestPut(roleGuard="fo*,*ar",rolesDeclared="foo,bar,baz")
802 		public String c() {
803 			return "OK";
804 		}
805 		@RestPost(roleGuard="fo*,*ar",rolesDeclared="foo,bar,baz")
806 		public String d() {
807 			return "OK";
808 		}
809 		@RestDelete(roleGuard="fo*,*ar",rolesDeclared="foo,bar,baz")
810 		public String e() {
811 			return "OK";
812 		}
813 	}
814 
815 	@Test void c02a_orPatternsWithComma_pass() throws Exception {
816 		var c2a = MockRestClient.buildLax(C2a.class);
817 
818 		for (RestOperation op : ops(op("get","/a"),op("get","/b"),op("put","/c"),op("post","/d"),op("delete","/e"))) {
819 			c2a.request(op).roles("foo").run().assertStatus(200);
820 			c2a.request(op).roles("bar").run().assertStatus(200);
821 			c2a.request(op).roles("foo","bar").run().assertStatus(200);
822 			c2a.request(op).roles("foo","bar","baz").run().assertStatus(200);
823 			c2a.request(op).roles().run().assertStatus(403);
824 			c2a.request(op).roles("baz").run().assertStatus(403);
825 		}
826 	}
827 
828 	@Rest
829 	public static class C2b {
830 		@RestOp(roleGuard="fo* | *ar",rolesDeclared="foo,bar,baz")
831 		public String get() {
832 			return "OK";
833 		}
834 	}
835 
836 	@Test void c02b_orPatternsWithSinglePipe_pass() throws Exception {
837 		var c2b = MockRestClient.buildLax(C2b.class);
838 		c2b.get().roles("foo").run().assertStatus(200);
839 		c2b.get().roles("bar").run().assertStatus(200);
840 		c2b.get().roles("foo","bar").run().assertStatus(200);
841 		c2b.get().roles("foo","bar","baz").run().assertStatus(200);
842 		c2b.get().roles().run().assertStatus(403);
843 		c2b.get().roles("baz").run().assertStatus(403);
844 	}
845 
846 	@Rest
847 	public static class C2c {
848 		@RestOp(roleGuard="fo* || *ar",rolesDeclared="foo,bar,baz")
849 		public String get() {
850 			return "OK";
851 		}
852 	}
853 
854 	@Test void c02c_orPatternsWithDoublePipe_pass() throws Exception {
855 		var c2c = MockRestClient.buildLax(C2c.class);
856 		c2c.get().roles("foo").run().assertStatus(200);
857 		c2c.get().roles("bar").run().assertStatus(200);
858 		c2c.get().roles("foo","bar").run().assertStatus(200);
859 		c2c.get().roles("foo","bar","baz").run().assertStatus(200);
860 		c2c.get().roles().run().assertStatus(403);
861 		c2c.get().roles("baz").run().assertStatus(403);
862 	}
863 
864 	@Rest
865 	public static class C2d {
866 		@RestOp(roleGuard="fo* & *ar",rolesDeclared="foo,bar,baz")
867 		public String get() {
868 			return "OK";
869 		}
870 	}
871 
872 	@Test void c02d_andPatternsWithSingleAmp_pass() throws Exception {
873 		var c2d = MockRestClient.buildLax(C2d.class);
874 		c2d.get().roles("foo","bar").run().assertStatus(200);
875 		c2d.get().roles("foo","bar","baz").run().assertStatus(200);
876 		c2d.get().roles().run().assertStatus(403);
877 		c2d.get().roles("foo").run().assertStatus(403);
878 		c2d.get().roles("bar").run().assertStatus(403);
879 		c2d.get().roles("baz").run().assertStatus(403);
880 	}
881 
882 	@Rest
883 	public static class C2e {
884 		@RestOp(roleGuard="fo* && *ar",rolesDeclared="foo,bar,baz")
885 		public String get() {
886 			return "OK";
887 		}
888 	}
889 
890 	@Test void c02e_andPatternsWithDoubleAmp_pass() throws Exception {
891 		var c2e = MockRestClient.buildLax(C2e.class);
892 		c2e.get().roles("foo","bar").run().assertStatus(200);
893 		c2e.get().roles("foo","bar","baz").run().assertStatus(200);
894 		c2e.get().roles().run().assertStatus(403);
895 		c2e.get().roles("foo").run().assertStatus(403);
896 		c2e.get().roles("bar").run().assertStatus(403);
897 		c2e.get().roles("baz").run().assertStatus(403);
898 	}
899 
900 	@Rest
901 	public static class C2f {
902 		@RestOp(roleGuard="(fo*) && (*ar)",rolesDeclared="foo,bar,baz")
903 		public String get() {
904 			return "OK";
905 		}
906 	}
907 
908 	@Test void c02f_andPatternsWithDoubleAmpAndParens_pass() throws Exception {
909 		var c2f = MockRestClient.buildLax(C2f.class);
910 		c2f.get().roles("foo","bar").run().assertStatus(200);
911 		c2f.get().roles("foo","bar","baz").run().assertStatus(200);
912 		c2f.get().roles().run().assertStatus(403);
913 		c2f.get().roles("foo").run().assertStatus(403);
914 		c2f.get().roles("bar").run().assertStatus(403);
915 		c2f.get().roles("baz").run().assertStatus(403);
916 	}
917 
918 	@Rest
919 	public static class C2g {
920 		@RestOp(roleGuard="fo* && (*ar || *az)",rolesDeclared="foo,bar,baz")
921 		public String get() {
922 			return "OK";
923 		}
924 	}
925 
926 	@Test void c02g_complexPatterns_pass() throws Exception {
927 		var c2g = MockRestClient.buildLax(C2g.class);
928 		c2g.get().roles("foo","bar").run().assertStatus(200);
929 		c2g.get().roles("foo","baz").run().assertStatus(200);
930 		c2g.get().roles("foo","bar","baz").run().assertStatus(200);
931 		c2g.get().roles().run().assertStatus(403);
932 		c2g.get().roles("foo").run().assertStatus(403);
933 		c2g.get().roles("bar","baz").run().assertStatus(403);
934 		c2g.get().roles("baz").run().assertStatus(403);
935 	}
936 
937 	@Rest
938 	public static class C2h {
939 		@RestOp(roleGuard="fo* || (*ar && *az)",rolesDeclared="foo,bar,baz")
940 		public String get() {
941 			return "OK";
942 		}
943 	}
944 
945 	@Test void c02h_complexPatterns_pass() throws Exception {
946 		var c2h = MockRestClient.buildLax(C2h.class);
947 		c2h.get().roles("foo").run().assertStatus(200);
948 		c2h.get().roles("bar","baz").run().assertStatus(200);
949 		c2h.get().roles("foo","bar","baz").run().assertStatus(200);
950 		c2h.get().roles().run().assertStatus(403);
951 		c2h.get().roles("bar").run().assertStatus(403);
952 		c2h.get().roles("baz").run().assertStatus(403);
953 	}
954 
955 	//-----------------------------------------------------------------------------------------------------------------
956 	// @RestOp(roleGuard), pattern guards on method but no roles defined
957 	//-----------------------------------------------------------------------------------------------------------------
958 
959 	@Rest
960 	public static class D {
961 		@RestOp(roleGuard="fo*,*ar")
962 		public String a() {
963 			return "OK";
964 		}
965 		@RestGet(roleGuard="fo*,*ar")
966 		public String b() {
967 			return "OK";
968 		}
969 		@RestPut(roleGuard="fo*,*ar")
970 		public String c() {
971 			return "OK";
972 		}
973 		@RestPost(roleGuard="fo*,*ar")
974 		public String d() {
975 			return "OK";
976 		}
977 		@RestDelete(roleGuard="fo*,*ar")
978 		public String e() {
979 			return "OK";
980 		}
981 	}
982 
983 	@Test void d01_patternsWithoutRoles() throws Exception {
984 		var d = MockRestClient.buildLax(D.class);
985 
986 		for (RestOperation op : ops(op("get","/a"),op("get","/b"),op("put","/c"),op("post","/d"),op("delete","/e"))) {
987 			d.request(op).roles().run().assertStatus(403);
988 			d.request(op).roles("foo").run().assertStatus(403);
989 			d.request(op).roles("bar").run().assertStatus(403);
990 			d.request(op).roles("baz").run().assertStatus(403);
991 			d.request(op).roles("foo","bar").run().assertStatus(403);
992 		}
993 	}
994 
995 	//-----------------------------------------------------------------------------------------------------------------
996 	// @RestOp(roleGuard), any role.
997 	//-----------------------------------------------------------------------------------------------------------------
998 
999 	@Rest(rolesDeclared="foo,bar,baz")
1000 	public static class E {
1001 		@RestOp(roleGuard="*")
1002 		public String get() {
1003 			return "OK";
1004 		}
1005 	}
1006 
1007 	@Test void e01_anyRole_pass() throws Exception {
1008 		var e = MockRestClient.buildLax(E.class);
1009 		e.get().roles("foo").run().assertStatus(200);
1010 		e.get().roles("bar").run().assertStatus(200);
1011 		e.get().roles("baz").run().assertStatus(200);
1012 		e.get().roles("foo","bar").run().assertStatus(200);
1013 		e.get().roles().run().assertStatus(403);
1014 	}
1015 }