View Javadoc
1   package de.dlr.shepard.common.filters;
2   
3   import static org.mockito.ArgumentMatchers.any;
4   import static org.mockito.Mockito.never;
5   import static org.mockito.Mockito.verify;
6   import static org.mockito.Mockito.when;
7   
8   import de.dlr.shepard.auth.security.JWTPrincipal;
9   import de.dlr.shepard.auth.security.UserLastSeenCache;
10  import de.dlr.shepard.auth.security.Userinfo;
11  import de.dlr.shepard.auth.security.UserinfoService;
12  import de.dlr.shepard.auth.users.entities.User;
13  import de.dlr.shepard.auth.users.services.UserService;
14  import de.dlr.shepard.common.exceptions.ShepardProcessingException;
15  import io.quarkus.test.InjectMock;
16  import io.quarkus.test.component.QuarkusComponentTest;
17  import jakarta.inject.Inject;
18  import jakarta.ws.rs.container.ContainerRequestContext;
19  import jakarta.ws.rs.core.HttpHeaders;
20  import jakarta.ws.rs.core.SecurityContext;
21  import jakarta.ws.rs.core.UriInfo;
22  import java.io.IOException;
23  import java.net.URISyntaxException;
24  import java.security.Principal;
25  import org.junit.jupiter.api.BeforeEach;
26  import org.junit.jupiter.api.Test;
27  import org.mockito.ArgumentCaptor;
28  import org.mockito.Captor;
29  
30  @QuarkusComponentTest
31  public class UserFilterTest {
32  
33    @InjectMock
34    ContainerRequestContext requestContext;
35  
36    @InjectMock
37    SecurityContext securityContext;
38  
39    @InjectMock
40    UserService userService;
41  
42    @InjectMock
43    UserinfoService userinfoService;
44  
45    @InjectMock
46    UserLastSeenCache userLastSeenCache;
47  
48    @InjectMock
49    UriInfo uriInfo;
50  
51    @Inject
52    UserFilter filter;
53  
54    @Captor
55    ArgumentCaptor<JWTPrincipal> userCaptor;
56  
57    @BeforeEach
58    public void prepareSpy() throws IllegalAccessException {
59      when(requestContext.getSecurityContext()).thenReturn(securityContext);
60    }
61  
62    @Test
63    public void testFilterPublic_publicRoute() throws URISyntaxException, IOException {
64      String relativePath = "/versionz";
65      when(uriInfo.getPath()).thenReturn(relativePath);
66      when(requestContext.getUriInfo()).thenReturn(uriInfo);
67      filter.filter(requestContext);
68      verify(requestContext, never()).abortWith(any());
69    }
70  
71    @Test
72    public void testFilterPublic_privateRoute() throws URISyntaxException, IOException {
73      String relativePath = "/versionsz";
74      when(uriInfo.getPath()).thenReturn(relativePath);
75      when(requestContext.getUriInfo()).thenReturn(uriInfo);
76      filter.filter(requestContext);
77      verify(requestContext).abortWith(any());
78    }
79  
80    @Test
81    public void testFilter_Successful() throws IOException, ShepardProcessingException {
82      Principal p = new JWTPrincipal("bob", "MyKeyId");
83      Userinfo ui = new Userinfo("bob", "name", "john.doe@example.com", "John", "Doe", "doe_jo");
84      User u = new User("bob", "John", "Doe", "john.doe@example.com");
85  
86      when(requestContext.getHeaderString(HttpHeaders.AUTHORIZATION)).thenReturn("Bearer abc");
87      String relativePath = "/projects";
88      when(uriInfo.getPath()).thenReturn(relativePath);
89      when(requestContext.getUriInfo()).thenReturn(uriInfo);
90  
91      when(securityContext.getUserPrincipal()).thenReturn(p);
92      when(userinfoService.fetchUserinfo("Bearer abc")).thenReturn(ui);
93      when(userService.createOrUpdateUser(u)).thenReturn(u);
94  
95      filter.filter(requestContext);
96      verify(userService).createOrUpdateUser(u);
97      verify(userLastSeenCache).cacheKey("bob");
98      verify(requestContext, never()).abortWith(any());
99    }
100 
101   @Test
102   public void testFilter_SuccessfulUsernameConversion() throws IOException, ShepardProcessingException {
103     Principal p = new JWTPrincipal("bob", "MyKeyId");
104     Userinfo ui = new Userinfo("f:123:bob", "name", "john.doe@example.com", "John", "Doe", "doe_jo");
105     User u = new User("bob", "John", "Doe", "john.doe@example.com");
106 
107     when(requestContext.getHeaderString(HttpHeaders.AUTHORIZATION)).thenReturn("Bearer abc");
108     when(securityContext.getUserPrincipal()).thenReturn(p);
109     when(userinfoService.fetchUserinfo("Bearer abc")).thenReturn(ui);
110     when(userService.createOrUpdateUser(u)).thenReturn(u);
111     String relativePath = "/projects";
112     when(uriInfo.getPath()).thenReturn(relativePath);
113     when(requestContext.getUriInfo()).thenReturn(uriInfo);
114 
115     filter.filter(requestContext);
116     verify(userService).createOrUpdateUser(u);
117     verify(userLastSeenCache).cacheKey("bob");
118     verify(requestContext, never()).abortWith(any());
119   }
120 
121   @Test
122   public void testFilter_GracePeriod() throws IOException {
123     Principal p = new JWTPrincipal("bob", "MyKeyId");
124 
125     when(requestContext.getHeaderString(HttpHeaders.AUTHORIZATION)).thenReturn("Bearer abc");
126     when(securityContext.getUserPrincipal()).thenReturn(p);
127     when(userLastSeenCache.isKeyCached("bob")).thenReturn(true);
128     String relativePath = "/projects";
129     when(uriInfo.getPath()).thenReturn(relativePath);
130     when(requestContext.getUriInfo()).thenReturn(uriInfo);
131 
132     filter.filter(requestContext);
133     verify(userService, never()).createOrUpdateUser(any());
134     verify(userLastSeenCache, never()).cacheKey(any());
135   }
136 
137   @Test
138   public void testFilter_NoPrincipal() throws IOException {
139     when(requestContext.getHeaderString(HttpHeaders.AUTHORIZATION)).thenReturn("Bearer abc");
140     when(securityContext.getUserPrincipal()).thenReturn(null);
141     String relativePath = "/projects";
142     when(uriInfo.getPath()).thenReturn(relativePath);
143     when(requestContext.getUriInfo()).thenReturn(uriInfo);
144 
145     filter.filter(requestContext);
146     verify(userService, never()).createOrUpdateUser(any());
147     verify(userLastSeenCache, never()).cacheKey(any());
148     verify(requestContext).abortWith(any());
149   }
150 
151   @Test
152   public void testFilter_InvalidPrincipal() throws IOException {
153     Principal p = new Principal() {
154       @Override
155       public String getName() {
156         return "myName";
157       }
158     };
159 
160     when(requestContext.getHeaderString(HttpHeaders.AUTHORIZATION)).thenReturn("Bearer abc");
161     when(securityContext.getUserPrincipal()).thenReturn(p);
162     String relativePath = "/projects";
163     when(uriInfo.getPath()).thenReturn(relativePath);
164     when(requestContext.getUriInfo()).thenReturn(uriInfo);
165 
166     filter.filter(requestContext);
167     verify(userService, never()).createOrUpdateUser(any());
168     verify(userLastSeenCache, never()).cacheKey(any());
169     verify(requestContext).abortWith(any());
170   }
171 
172   @Test
173   public void testFilter_noHeader() throws IOException {
174     Principal p = new JWTPrincipal("bob", "MyKeyId");
175 
176     when(securityContext.getUserPrincipal()).thenReturn(p);
177     when(requestContext.getHeaderString(HttpHeaders.AUTHORIZATION)).thenReturn(null);
178     String relativePath = "/projects";
179     when(uriInfo.getPath()).thenReturn(relativePath);
180     when(requestContext.getUriInfo()).thenReturn(uriInfo);
181 
182     filter.filter(requestContext);
183     verify(userService, never()).createOrUpdateUser(any());
184     verify(userLastSeenCache, never()).cacheKey(any());
185   }
186 
187   @Test
188   public void testFilter_invalidHeader() throws IOException {
189     Principal p = new JWTPrincipal("bob", "MyKeyId");
190 
191     when(securityContext.getUserPrincipal()).thenReturn(p);
192     when(requestContext.getHeaderString(HttpHeaders.AUTHORIZATION)).thenReturn("invalid");
193     String relativePath = "/projects";
194     when(uriInfo.getPath()).thenReturn(relativePath);
195     when(requestContext.getUriInfo()).thenReturn(uriInfo);
196 
197     filter.filter(requestContext);
198     verify(userService, never()).createOrUpdateUser(any());
199     verify(userLastSeenCache, never()).cacheKey(any());
200   }
201 
202   @Test
203   public void testFilter_ProcessingException() throws IOException, ShepardProcessingException {
204     Principal p = new JWTPrincipal("bob", "MyKeyId");
205 
206     when(requestContext.getHeaderString(HttpHeaders.AUTHORIZATION)).thenReturn("Bearer abc");
207     when(securityContext.getUserPrincipal()).thenReturn(p);
208     when(userinfoService.fetchUserinfo("Bearer abc")).thenThrow(new ShepardProcessingException("Message"));
209     String relativePath = "/projects";
210     when(uriInfo.getPath()).thenReturn(relativePath);
211     when(requestContext.getUriInfo()).thenReturn(uriInfo);
212 
213     filter.filter(requestContext);
214     verify(userService, never()).createOrUpdateUser(any());
215     verify(userLastSeenCache, never()).cacheKey(any());
216     verify(requestContext).abortWith(any());
217   }
218 
219   @Test
220   public void testFilter_InconsistentUsernames() throws IOException, ShepardProcessingException {
221     Principal p = new JWTPrincipal("bob", "MyKeyId");
222     Userinfo ui = new Userinfo("claus", "name", "john.doe@example.com", "John", "Doe", "doe_jo");
223 
224     when(requestContext.getHeaderString(HttpHeaders.AUTHORIZATION)).thenReturn("Bearer abc");
225     when(securityContext.getUserPrincipal()).thenReturn(p);
226     when(userinfoService.fetchUserinfo("Bearer abc")).thenReturn(ui);
227     String relativePath = "/projects";
228     when(uriInfo.getPath()).thenReturn(relativePath);
229     when(requestContext.getUriInfo()).thenReturn(uriInfo);
230 
231     filter.filter(requestContext);
232     verify(userService, never()).createOrUpdateUser(any());
233     verify(userLastSeenCache, never()).cacheKey(any());
234     verify(requestContext).abortWith(any());
235   }
236 
237   @Test
238   public void testFilter_UpdatedFailed() throws IOException, ShepardProcessingException {
239     Principal p = new JWTPrincipal("bob", "MyKeyId");
240     Userinfo ui = new Userinfo("bob", "name", "john.doe@example.com", "John", "Doe", "doe_jo");
241     User u = new User("bob", "John", "Doe", "john.doe@example.com");
242 
243     when(requestContext.getHeaderString(HttpHeaders.AUTHORIZATION)).thenReturn("Bearer abc");
244     when(securityContext.getUserPrincipal()).thenReturn(p);
245     when(userinfoService.fetchUserinfo("Bearer abc")).thenReturn(ui);
246     when(userService.createOrUpdateUser(u)).thenReturn(null);
247     String relativePath = "/projects";
248     when(uriInfo.getPath()).thenReturn(relativePath);
249     when(requestContext.getUriInfo()).thenReturn(uriInfo);
250 
251     filter.filter(requestContext);
252     verify(userLastSeenCache, never()).cacheKey(any());
253     verify(requestContext).abortWith(any());
254   }
255 }