1
+ package ubic .gemma .core .security .jackson ;
2
+
3
+ import com .fasterxml .jackson .core .JsonProcessingException ;
4
+ import com .fasterxml .jackson .databind .ObjectMapper ;
5
+ import gemma .gsec .model .Securable ;
6
+ import org .junit .After ;
7
+ import org .junit .Before ;
8
+ import org .junit .Test ;
9
+ import org .mockito .ArgumentCaptor ;
10
+ import org .springframework .beans .factory .annotation .Autowired ;
11
+ import org .springframework .context .annotation .Bean ;
12
+ import org .springframework .context .annotation .Configuration ;
13
+ import org .springframework .security .access .AccessDecisionManager ;
14
+ import org .springframework .security .access .AccessDeniedException ;
15
+ import org .springframework .security .access .ConfigAttribute ;
16
+ import org .springframework .security .test .context .support .WithMockUser ;
17
+ import org .springframework .test .context .ContextConfiguration ;
18
+ import org .springframework .test .context .junit4 .AbstractJUnit4SpringContextTests ;
19
+ import ubic .gemma .model .annotations .SecuredField ;
20
+ import ubic .gemma .model .common .auditAndSecurity .curation .AbstractCuratableValueObject ;
21
+ import ubic .gemma .model .expression .experiment .ExpressionExperimentValueObject ;
22
+ import ubic .gemma .persistence .util .TestComponent ;
23
+
24
+ import java .util .Collection ;
25
+
26
+ import static org .assertj .core .api .Assertions .assertThat ;
27
+ import static org .mockito .Mockito .*;
28
+
29
+ @ ContextConfiguration
30
+ public class SecuredFieldModuleTest extends AbstractJUnit4SpringContextTests {
31
+
32
+ @ Configuration
33
+ @ TestComponent
34
+ static class SecuredJsonSerializerTestContextConfiguration {
35
+
36
+ @ Bean
37
+ public ObjectMapper objectMapper ( AccessDecisionManager accessDecisionManager ) {
38
+ return new ObjectMapper ()
39
+ .registerModule ( new SecuredFieldModule ( accessDecisionManager ) );
40
+ }
41
+
42
+ @ Bean
43
+ public AccessDecisionManager accessDecisionManager () {
44
+ return mock ( AccessDecisionManager .class );
45
+ }
46
+ }
47
+
48
+ @ Autowired
49
+ private ObjectMapper objectMapper ;
50
+
51
+ @ Autowired
52
+ private AccessDecisionManager accessDecisionManager ;
53
+
54
+ private AbstractCuratableValueObject <?> curatableVo ;
55
+
56
+ @ Before
57
+ public void setUp () {
58
+ curatableVo = new ExpressionExperimentValueObject ();
59
+ curatableVo .setCurationNote ( "Reserved for curators" );
60
+ }
61
+
62
+ @ After
63
+ public void tearDown () {
64
+ reset ( accessDecisionManager );
65
+ }
66
+
67
+ @ Test
68
+ @ WithMockUser (authorities = "GROUP_ADMIN" )
69
+ public void testCuratable () throws JsonProcessingException {
70
+ //noinspection unchecked
71
+ ArgumentCaptor <Collection <ConfigAttribute >> captor = ArgumentCaptor .forClass ( Collection .class );
72
+ doNothing ()
73
+ .when ( accessDecisionManager )
74
+ .decide ( any (), any (), captor .capture () );
75
+ assertThat ( objectMapper .writeValueAsString ( curatableVo ) ).contains ( "Reserved for curators" );
76
+ verify ( accessDecisionManager , atLeastOnce () ).decide ( any (), same ( curatableVo ), anyCollection () );
77
+ assertThat ( captor .getValue () ).anySatisfy ( ca -> assertThat ( ca .getAttribute () ).isEqualTo ( "GROUP_ADMIN" ) );
78
+ }
79
+
80
+ @ Test
81
+ @ WithMockUser (authorities = "GROUP_USER" )
82
+ public void testCuratableAsNonAdmin () throws JsonProcessingException {
83
+ doThrow ( AccessDeniedException .class )
84
+ .when ( accessDecisionManager )
85
+ .decide ( any (), any (), anyCollection () );
86
+ assertThat ( objectMapper .writeValueAsString ( curatableVo ) )
87
+ .doesNotContain ( "Reserved for curators" );
88
+ }
89
+
90
+ @ Test
91
+ @ WithMockUser (authorities = "IS_AUTHENTICATED_ANONYMOUSLY" )
92
+ public void testCuratableAsAnonymous () throws JsonProcessingException {
93
+ doThrow ( AccessDeniedException .class )
94
+ .when ( accessDecisionManager )
95
+ .decide ( any (), any (), anyCollection () );
96
+ assertThat ( objectMapper .writeValueAsString ( curatableVo ) )
97
+ .doesNotContain ( "Reserved for curators" );
98
+ }
99
+
100
+ static class Entity implements Securable {
101
+ private Long id ;
102
+ @ SecuredField ({ "GROUP_ADMIN" })
103
+ private String foo ;
104
+ private Entity nestedEntity ;
105
+
106
+ @ Override
107
+ public Long getId () {
108
+ return id ;
109
+ }
110
+
111
+ public String getFoo () {
112
+ return foo ;
113
+ }
114
+
115
+ public Entity getNestedEntity () {
116
+ return nestedEntity ;
117
+ }
118
+ }
119
+
120
+ @ Test
121
+ public void testSecuredFieldInASecurableEntity () throws JsonProcessingException {
122
+ Entity entity = new Entity ();
123
+ entity .id = 1L ;
124
+ entity .foo = "test" ;
125
+ entity .nestedEntity = new Entity ();
126
+ entity .nestedEntity .id = 2L ;
127
+ entity .nestedEntity .foo = "test" ;
128
+ objectMapper .writeValueAsString ( entity );
129
+ verify ( accessDecisionManager ).decide ( any (), same ( entity ), anyCollection () );
130
+ verify ( accessDecisionManager ).decide ( any (), same ( entity .nestedEntity ), anyCollection () );
131
+ }
132
+ }
0 commit comments