blob: 90597e26fc4a5abce875958d4caf6d44db24dc29 [file] [log] [blame]
margarethae20a2802022-04-21 12:37:38 +02001package de.ids_mannheim.korap.web.controller;
2
Marc Kupietzd43a98d2023-09-22 17:11:46 +02003import static org.junit.jupiter.api.Assertions.assertEquals;
4import static org.junit.jupiter.api.Assertions.assertFalse;
5import static org.junit.jupiter.api.Assertions.assertNotNull;
6import static org.junit.jupiter.api.Assertions.assertTrue;
7import static org.junit.jupiter.api.Assertions.fail;
margarethae20a2802022-04-21 12:37:38 +02008
margarethad4841562022-06-01 12:24:47 +02009import java.io.IOException;
margaretha8fe51e92023-09-20 11:22:20 +020010import java.util.ArrayList;
11import java.util.List;
12import java.util.concurrent.Callable;
13import java.util.concurrent.ExecutionException;
14import java.util.concurrent.ExecutorService;
15import java.util.concurrent.Executors;
16import java.util.concurrent.Future;
17import java.util.concurrent.TimeUnit;
margarethad4841562022-06-01 12:24:47 +020018
margaretha96c309d2023-08-16 12:24:12 +020019import jakarta.ws.rs.ProcessingException;
20import jakarta.ws.rs.client.Entity;
21import jakarta.ws.rs.core.Form;
22import jakarta.ws.rs.core.Response;
23import jakarta.ws.rs.core.Response.Status;
margarethae20a2802022-04-21 12:37:38 +020024
margarethae20a2802022-04-21 12:37:38 +020025import org.apache.http.entity.ContentType;
Marc Kupietzd43a98d2023-09-22 17:11:46 +020026import org.junit.jupiter.api.Test;
margaretha68ccf1e2022-05-04 09:59:54 +020027import org.springframework.beans.factory.annotation.Autowired;
margarethae20a2802022-04-21 12:37:38 +020028import com.fasterxml.jackson.databind.JsonNode;
29import com.google.common.net.HttpHeaders;
margarethae20a2802022-04-21 12:37:38 +020030import de.ids_mannheim.korap.authentication.http.HttpAuthorizationHandler;
31import de.ids_mannheim.korap.config.Attributes;
margaretha68ccf1e2022-05-04 09:59:54 +020032import de.ids_mannheim.korap.entity.InstalledPlugin;
margarethae20a2802022-04-21 12:37:38 +020033import de.ids_mannheim.korap.exceptions.KustvaktException;
34import de.ids_mannheim.korap.exceptions.StatusCodes;
35import de.ids_mannheim.korap.oauth2.constant.OAuth2ClientType;
36import de.ids_mannheim.korap.oauth2.constant.OAuth2Error;
margaretha68ccf1e2022-05-04 09:59:54 +020037import de.ids_mannheim.korap.oauth2.dao.InstalledPluginDao;
margarethae20a2802022-04-21 12:37:38 +020038import de.ids_mannheim.korap.utils.JsonUtils;
margaretha79f01442022-05-04 12:03:47 +020039import de.ids_mannheim.korap.utils.TimeUtils;
margarethae20a2802022-04-21 12:37:38 +020040import de.ids_mannheim.korap.web.input.OAuth2ClientJson;
41
42public class OAuth2PluginTest extends OAuth2TestBase {
43
44 private String username = "plugin-user";
Marc Kupietzd43a98d2023-09-22 17:11:46 +020045
margaretha68ccf1e2022-05-04 09:59:54 +020046 @Autowired
47 private InstalledPluginDao pluginDao;
margaretha35e1ca22023-11-16 22:00:01 +010048
margarethae20a2802022-04-21 12:37:38 +020049 @Test
margaretha35e1ca22023-11-16 22:00:01 +010050 public void testRegisterPlugin ()
51 throws ProcessingException, KustvaktException {
margarethae20a2802022-04-21 12:37:38 +020052 JsonNode source = JsonUtils.readTree("{ \"plugin\" : \"source\"}");
margaretha79f01442022-05-04 12:03:47 +020053 int refreshTokenExpiry = TimeUtils.convertTimeToSeconds("90D");
margarethae20a2802022-04-21 12:37:38 +020054 String clientName = "Plugin";
55 OAuth2ClientJson json = new OAuth2ClientJson();
56 json.setName(clientName);
57 json.setType(OAuth2ClientType.CONFIDENTIAL);
58 json.setDescription("This is a plugin test client.");
59 json.setSource(source);
margaretha79f01442022-05-04 12:03:47 +020060 json.setRefreshTokenExpiry(refreshTokenExpiry);
abcpro173fe8f22022-11-08 19:56:52 +000061 Response response = registerClient(username, json);
margarethae20a2802022-04-21 12:37:38 +020062 assertEquals(Status.OK.getStatusCode(), response.getStatus());
abcpro173fe8f22022-11-08 19:56:52 +000063 JsonNode node = JsonUtils.readTree(response.readEntity(String.class));
margarethae20a2802022-04-21 12:37:38 +020064 String clientId = node.at("/client_id").asText();
65 String clientSecret = node.at("/client_secret").asText();
66 assertNotNull(clientId);
67 assertNotNull(clientSecret);
margarethad5527322022-05-03 07:52:54 +020068 testInstallPluginNotPermitted(clientId);
margarethad4841562022-06-01 12:24:47 +020069 testRetrievePluginInfo(clientId, refreshTokenExpiry);
margarethae20a2802022-04-21 12:37:38 +020070 node = listPlugins(false);
71 assertEquals(3, node.size());
Marc Kupietzd43a98d2023-09-22 17:11:46 +020072 // permitted only
73 node = listPlugins(true);
margarethae20a2802022-04-21 12:37:38 +020074 assertEquals(2, node.size());
margaretha35e1ca22023-11-16 22:00:01 +010075 testListUserRegisteredPlugins(username, clientId, clientName,
76 refreshTokenExpiry);
margarethad4841562022-06-01 12:24:47 +020077 deregisterClient(username, clientId);
margarethae20a2802022-04-21 12:37:38 +020078 }
79
margarethad4841562022-06-01 12:24:47 +020080 @Test
margaretha35e1ca22023-11-16 22:00:01 +010081 public void testRegisterPublicPlugin () throws KustvaktException {
margarethad4841562022-06-01 12:24:47 +020082 JsonNode source = JsonUtils.readTree("{ \"plugin\" : \"source\"}");
83 String clientName = "Public Plugin";
84 OAuth2ClientJson json = new OAuth2ClientJson();
85 json.setName(clientName);
86 json.setType(OAuth2ClientType.PUBLIC);
87 json.setDescription("This is a public plugin.");
88 json.setSource(source);
abcpro173fe8f22022-11-08 19:56:52 +000089 Response response = registerClient(username, json);
90 JsonNode node = JsonUtils.readTree(response.readEntity(String.class));
margaretha4ff862a2022-06-03 12:40:21 +020091 assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
92 assertEquals(OAuth2Error.INVALID_REQUEST, node.at("/error").asText());
93 assertFalse(node.at("/error_description").isMissingNode());
Marc Kupietzd43a98d2023-09-22 17:11:46 +020094 // assertEquals(Status.OK.getStatusCode(), response.getStatus());
95 // String clientId = node.at("/client_id").asText();
96 // assertTrue(node.at("/client_secret").isMissingNode());
97 //
98 // deregisterClient(username, clientId);
margarethad4841562022-06-01 12:24:47 +020099 }
100
margaretha35e1ca22023-11-16 22:00:01 +0100101 private void testRetrievePluginInfo (String clientId,
102 int refreshTokenExpiry)
103 throws ProcessingException, KustvaktException {
margarethae20a2802022-04-21 12:37:38 +0200104 JsonNode clientInfo = retrieveClientInfo(clientId, username);
margaretha79f01442022-05-04 12:03:47 +0200105 assertEquals(clientId, clientInfo.at("/client_id").asText());
Marc Kupietzd43a98d2023-09-22 17:11:46 +0200106 assertEquals(clientInfo.at("/client_name").asText(), "Plugin");
margaretha35e1ca22023-11-16 22:00:01 +0100107 assertEquals(OAuth2ClientType.CONFIDENTIAL.name(),
108 clientInfo.at("/client_type").asText());
margaretha79f01442022-05-04 12:03:47 +0200109 assertNotNull(clientInfo.at("/client_description").asText());
margaretha977fabe2022-04-28 09:23:47 +0200110 assertNotNull(clientInfo.at("/source").asText());
111 assertFalse(clientInfo.at("/permitted").asBoolean());
margarethae20a2802022-04-21 12:37:38 +0200112 assertEquals(username, clientInfo.at("/registered_by").asText());
113 assertNotNull(clientInfo.at("/registration_date"));
margaretha35e1ca22023-11-16 22:00:01 +0100114 assertEquals(refreshTokenExpiry,
115 clientInfo.at("/refresh_token_expiry").asInt());
margarethae20a2802022-04-21 12:37:38 +0200116 }
117
margaretha35e1ca22023-11-16 22:00:01 +0100118 private void testListUserRegisteredPlugins (String username,
119 String clientId, String clientName, int refreshTokenExpiry)
120 throws ProcessingException, KustvaktException {
margarethae20a2802022-04-21 12:37:38 +0200121 JsonNode node = listUserRegisteredClients(username);
122 assertEquals(1, node.size());
123 assertEquals(clientId, node.at("/0/client_id").asText());
124 assertEquals(clientName, node.at("/0/client_name").asText());
margaretha35e1ca22023-11-16 22:00:01 +0100125 assertEquals(OAuth2ClientType.CONFIDENTIAL.name(),
126 node.at("/0/client_type").asText());
margarethae20a2802022-04-21 12:37:38 +0200127 assertFalse(node.at("/0/permitted").asBoolean());
128 assertFalse(node.at("/0/registration_date").isMissingNode());
129 assertFalse(node.at("/0/source").isMissingNode());
margaretha35e1ca22023-11-16 22:00:01 +0100130 assertEquals(refreshTokenExpiry,
131 node.at("/0/refresh_token_expiry").asInt());
margarethae20a2802022-04-21 12:37:38 +0200132 }
133
134 @Test
margaretha35e1ca22023-11-16 22:00:01 +0100135 public void testListPluginsUnauthorizedPublic ()
136 throws ProcessingException, KustvaktException {
abcpro173fe8f22022-11-08 19:56:52 +0000137 Form form = new Form();
138 form.param("super_client_id", publicClientId);
margarethae20a2802022-04-21 12:37:38 +0200139 testListPluginsClientUnauthorized(form);
140 }
141
142 @Test
margaretha35e1ca22023-11-16 22:00:01 +0100143 public void testListPluginsUnauthorizedConfidential ()
144 throws ProcessingException, KustvaktException {
abcpro173fe8f22022-11-08 19:56:52 +0000145 Form form = new Form();
146 form.param("super_client_id", confidentialClientId2);
147 form.param("super_client_secret", clientSecret);
margarethae20a2802022-04-21 12:37:38 +0200148 testListPluginsClientUnauthorized(form);
149 }
150
151 @Test
margaretha35e1ca22023-11-16 22:00:01 +0100152 public void testListPluginsMissingClientSecret ()
153 throws ProcessingException, KustvaktException {
abcpro173fe8f22022-11-08 19:56:52 +0000154 Form form = new Form();
155 form.param("super_client_id", confidentialClientId);
margaretha35e1ca22023-11-16 22:00:01 +0100156 Response response = target().path(API_VERSION).path("plugins").request()
157 .header(Attributes.AUTHORIZATION, HttpAuthorizationHandler
158 .createBasicAuthorizationHeaderValue(username, "pass"))
159 .header(HttpHeaders.CONTENT_TYPE,
160 ContentType.APPLICATION_FORM_URLENCODED)
161 .post(Entity.form(form));
abcpro173fe8f22022-11-08 19:56:52 +0000162 String entity = response.readEntity(String.class);
margarethae20a2802022-04-21 12:37:38 +0200163 JsonNode node = JsonUtils.readTree(entity);
margarethae20a2802022-04-21 12:37:38 +0200164 assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
margarethae20a2802022-04-21 12:37:38 +0200165 assertEquals(OAuth2Error.INVALID_REQUEST, node.at("/error").asText());
166 assertFalse(node.at("/error_description").isMissingNode());
167 }
168
margaretha35e1ca22023-11-16 22:00:01 +0100169 private void testListPluginsClientUnauthorized (Form form)
170 throws ProcessingException, KustvaktException {
171 Response response = target().path(API_VERSION).path("plugins").request()
172 .header(Attributes.AUTHORIZATION, HttpAuthorizationHandler
173 .createBasicAuthorizationHeaderValue(username, "pass"))
174 .header(HttpHeaders.CONTENT_TYPE,
175 ContentType.APPLICATION_FORM_URLENCODED)
176 .post(Entity.form(form));
abcpro173fe8f22022-11-08 19:56:52 +0000177 String entity = response.readEntity(String.class);
margarethae20a2802022-04-21 12:37:38 +0200178 JsonNode node = JsonUtils.readTree(entity);
margarethae20a2802022-04-21 12:37:38 +0200179 assertEquals(Status.UNAUTHORIZED.getStatusCode(), response.getStatus());
margaretha35e1ca22023-11-16 22:00:01 +0100180 assertEquals(OAuth2Error.UNAUTHORIZED_CLIENT,
181 node.at("/error").asText());
margarethae20a2802022-04-21 12:37:38 +0200182 assertFalse(node.at("/error_description").isMissingNode());
183 }
184
185 @Test
margaretha35e1ca22023-11-16 22:00:01 +0100186 public void testListPluginsUserUnauthorized ()
187 throws ProcessingException, KustvaktException {
abcpro173fe8f22022-11-08 19:56:52 +0000188 Form form = getSuperClientForm();
margaretha35e1ca22023-11-16 22:00:01 +0100189 Response response = target().path(API_VERSION).path("plugins").request()
190 .header(Attributes.AUTHORIZATION, "Bearer blahblah")
191 .header(HttpHeaders.CONTENT_TYPE,
192 ContentType.APPLICATION_FORM_URLENCODED)
193 .post(Entity.form(form));
abcpro173fe8f22022-11-08 19:56:52 +0000194 String entity = response.readEntity(String.class);
margarethae20a2802022-04-21 12:37:38 +0200195 JsonNode node = JsonUtils.readTree(entity);
margarethae20a2802022-04-21 12:37:38 +0200196 assertEquals(Status.UNAUTHORIZED.getStatusCode(), response.getStatus());
margaretha35e1ca22023-11-16 22:00:01 +0100197 assertEquals(StatusCodes.INVALID_ACCESS_TOKEN,
198 node.at("/errors/0/0").asInt());
margarethae20a2802022-04-21 12:37:38 +0200199 }
200
margaretha8fe51e92023-09-20 11:22:20 +0200201 @Test
margaretha35e1ca22023-11-16 22:00:01 +0100202 public void testListPluginsConcurrent () throws InterruptedException {
margaretha8fe51e92023-09-20 11:22:20 +0200203 ExecutorService executorService = Executors.newFixedThreadPool(3);
204 List<Future<Void>> futures = new ArrayList<>();
margaretha8fe51e92023-09-20 11:22:20 +0200205 for (int i = 0; i < 3; i++) {
margaretha35e1ca22023-11-16 22:00:01 +0100206 futures.add(executorService
207 .submit(new PluginListCallable("Thread " + (i + 1))));
margaretha8fe51e92023-09-20 11:22:20 +0200208 }
margaretha8fe51e92023-09-20 11:22:20 +0200209 executorService.shutdown();
210 executorService.awaitTermination(2, TimeUnit.SECONDS);
margaretha8fe51e92023-09-20 11:22:20 +0200211 for (Future<Void> future : futures) {
212 try {
Marc Kupietzd43a98d2023-09-22 17:11:46 +0200213 // This will re-throw any exceptions
214 future.get();
215 // that occurred in threads
margaretha35e1ca22023-11-16 22:00:01 +0100216 }
217 catch (ExecutionException e) {
margaretha8fe51e92023-09-20 11:22:20 +0200218 fail("Test failed: " + e.getCause().getMessage());
219 }
220 }
221 }
222
223 class PluginListCallable implements Callable<Void> {
Marc Kupietzd43a98d2023-09-22 17:11:46 +0200224
margaretha8fe51e92023-09-20 11:22:20 +0200225 private final String name;
226
margaretha35e1ca22023-11-16 22:00:01 +0100227 public PluginListCallable (String name) {
margaretha8fe51e92023-09-20 11:22:20 +0200228 this.name = name;
229 }
230
231 @Override
margaretha35e1ca22023-11-16 22:00:01 +0100232 public Void call () {
margaretha8fe51e92023-09-20 11:22:20 +0200233 Form form = getSuperClientForm();
234 try {
margaretha35e1ca22023-11-16 22:00:01 +0100235 Response response = target().path(API_VERSION).path("plugins")
236 .request()
237 .header(Attributes.AUTHORIZATION,
238 HttpAuthorizationHandler
239 .createBasicAuthorizationHeaderValue(
240 username, "pass"))
241 .header(HttpHeaders.CONTENT_TYPE,
242 ContentType.APPLICATION_FORM_URLENCODED)
243 .post(Entity.form(form));
margaretha8fe51e92023-09-20 11:22:20 +0200244 assertEquals(Status.OK.getStatusCode(), response.getStatus());
margaretha8fe51e92023-09-20 11:22:20 +0200245 String entity = response.readEntity(String.class);
246 JsonNode node = JsonUtils.readTree(entity);
247 assertEquals(2, node.size());
margaretha35e1ca22023-11-16 22:00:01 +0100248 }
249 catch (KustvaktException e) {
margaretha8fe51e92023-09-20 11:22:20 +0200250 e.printStackTrace();
251 throw new RuntimeException(name, e);
252 }
253 return null;
254 }
255 }
Marc Kupietzd43a98d2023-09-22 17:11:46 +0200256
margarethae20a2802022-04-21 12:37:38 +0200257 @Test
margaretha35e1ca22023-11-16 22:00:01 +0100258 public void testListAllPlugins ()
259 throws ProcessingException, KustvaktException {
margarethae20a2802022-04-21 12:37:38 +0200260 JsonNode node = listPlugins(false);
261 assertEquals(2, node.size());
262 assertFalse(node.at("/0/client_id").isMissingNode());
263 assertFalse(node.at("/0/client_name").isMissingNode());
264 assertFalse(node.at("/0/client_description").isMissingNode());
265 assertFalse(node.at("/0/client_type").isMissingNode());
266 assertFalse(node.at("/0/permitted").isMissingNode());
267 assertFalse(node.at("/0/registration_date").isMissingNode());
268 assertFalse(node.at("/0/source").isMissingNode());
margaretha977fabe2022-04-28 09:23:47 +0200269 assertFalse(node.at("/0/refresh_token_expiry").isMissingNode());
margarethad4841562022-06-01 12:24:47 +0200270 // assertTrue(node.at("/1/refresh_token_expiry").isMissingNode());
margarethae20a2802022-04-21 12:37:38 +0200271 }
272
margaretha35e1ca22023-11-16 22:00:01 +0100273 private JsonNode listPlugins (boolean permitted_only)
274 throws ProcessingException, KustvaktException {
abcpro173fe8f22022-11-08 19:56:52 +0000275 Form form = getSuperClientForm();
margarethae20a2802022-04-21 12:37:38 +0200276 if (permitted_only) {
abcpro173fe8f22022-11-08 19:56:52 +0000277 form.param("permitted_only", Boolean.toString(permitted_only));
margarethae20a2802022-04-21 12:37:38 +0200278 }
margaretha35e1ca22023-11-16 22:00:01 +0100279 Response response = target().path(API_VERSION).path("plugins").request()
280 .header(Attributes.AUTHORIZATION, HttpAuthorizationHandler
281 .createBasicAuthorizationHeaderValue(username, "pass"))
282 .header(HttpHeaders.CONTENT_TYPE,
283 ContentType.APPLICATION_FORM_URLENCODED)
284 .post(Entity.form(form));
margarethae20a2802022-04-21 12:37:38 +0200285 assertEquals(Status.OK.getStatusCode(), response.getStatus());
abcpro173fe8f22022-11-08 19:56:52 +0000286 String entity = response.readEntity(String.class);
margarethae20a2802022-04-21 12:37:38 +0200287 return JsonUtils.readTree(entity);
288 }
289
margaretha35e1ca22023-11-16 22:00:01 +0100290 private void testInstallConfidentialPlugin (String superClientId,
291 String clientId, String username)
292 throws ProcessingException, KustvaktException {
abcpro173fe8f22022-11-08 19:56:52 +0000293 Form form = getSuperClientForm();
294 form.param("client_id", clientId);
295 Response response = installPlugin(form);
abcpro173fe8f22022-11-08 19:56:52 +0000296 String entity = response.readEntity(String.class);
margaretha7da23902022-05-02 08:38:45 +0200297 JsonNode node = JsonUtils.readTree(entity);
margarethad4841562022-06-01 12:24:47 +0200298 assertEquals(clientId, node.at("/client_id").asText());
margaretha68ccf1e2022-05-04 09:59:54 +0200299 assertEquals(superClientId, node.at("/super_client_id").asText());
margaretha7da23902022-05-02 08:38:45 +0200300 assertFalse(node.at("/name").isMissingNode());
301 assertFalse(node.at("/description").isMissingNode());
302 assertFalse(node.at("/url").isMissingNode());
303 assertFalse(node.at("/installed_date").isMissingNode());
margaretha7da23902022-05-02 08:38:45 +0200304 assertEquals(Status.OK.getStatusCode(), response.getStatus());
margarethad4841562022-06-01 12:24:47 +0200305 testRetrieveInstalledPlugin(superClientId, clientId, username);
margaretha7da23902022-05-02 08:38:45 +0200306 }
margarethad4841562022-06-01 12:24:47 +0200307
margaretha7da23902022-05-02 08:38:45 +0200308 @Test
margaretha35e1ca22023-11-16 22:00:01 +0100309 public void testInstallPublicPlugin ()
310 throws ProcessingException, KustvaktException {
abcpro173fe8f22022-11-08 19:56:52 +0000311 Form form = getSuperClientForm();
312 form.param("client_id", publicClientId2);
313 Response response = installPlugin(form);
abcpro173fe8f22022-11-08 19:56:52 +0000314 String entity = response.readEntity(String.class);
margaretha7da23902022-05-02 08:38:45 +0200315 JsonNode node = JsonUtils.readTree(entity);
316 assertEquals(publicClientId2, node.at("/client_id").asText());
margaretha68ccf1e2022-05-04 09:59:54 +0200317 assertEquals(superClientId, node.at("/super_client_id").asText());
margaretha7da23902022-05-02 08:38:45 +0200318 assertFalse(node.at("/name").isMissingNode());
319 assertFalse(node.at("/description").isMissingNode());
320 assertFalse(node.at("/url").isMissingNode());
321 assertFalse(node.at("/installed_date").isMissingNode());
margaretha7da23902022-05-02 08:38:45 +0200322 assertEquals(Status.OK.getStatusCode(), response.getStatus());
margarethad5527322022-05-03 07:52:54 +0200323 testInstallPluginRedundant(form);
margarethad4841562022-06-01 12:24:47 +0200324 testRetrieveInstalledPlugin(superClientId, publicClientId2, username);
margarethad4841562022-06-01 12:24:47 +0200325 response = uninstallPlugin(publicClientId2, username);
326 assertEquals(Status.OK.getStatusCode(), response.getStatus());
327 node = retrieveUserInstalledPlugin(getSuperClientForm());
328 assertTrue(node.isEmpty());
margarethad5527322022-05-03 07:52:54 +0200329 }
margarethad4841562022-06-01 12:24:47 +0200330
margaretha35e1ca22023-11-16 22:00:01 +0100331 private void testInstallPluginRedundant (Form form)
332 throws ProcessingException, KustvaktException {
abcpro173fe8f22022-11-08 19:56:52 +0000333 Response response = installPlugin(form);
334 String entity = response.readEntity(String.class);
margarethad5527322022-05-03 07:52:54 +0200335 JsonNode node = JsonUtils.readTree(entity);
margaretha35e1ca22023-11-16 22:00:01 +0100336 assertEquals(StatusCodes.PLUGIN_HAS_BEEN_INSTALLED,
337 node.at("/errors/0/0").asInt());
margarethad5527322022-05-03 07:52:54 +0200338 assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
margaretha7da23902022-05-02 08:38:45 +0200339 }
340
margaretha35e1ca22023-11-16 22:00:01 +0100341 private void testInstallPluginNotPermitted (String clientId)
342 throws ProcessingException, KustvaktException {
abcpro173fe8f22022-11-08 19:56:52 +0000343 Form form = getSuperClientForm();
344 form.param("client_id", clientId);
345 Response response = installPlugin(form);
346 String entity = response.readEntity(String.class);
margarethad5527322022-05-03 07:52:54 +0200347 JsonNode node = JsonUtils.readTree(entity);
margaretha35e1ca22023-11-16 22:00:01 +0100348 assertEquals(StatusCodes.PLUGIN_NOT_PERMITTED,
349 node.at("/errors/0/0").asInt());
margarethad5527322022-05-03 07:52:54 +0200350 assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
351 }
margarethad4841562022-06-01 12:24:47 +0200352
margaretha7da23902022-05-02 08:38:45 +0200353 @Test
margaretha35e1ca22023-11-16 22:00:01 +0100354 public void testInstallPluginMissingClientId ()
355 throws ProcessingException, KustvaktException {
abcpro173fe8f22022-11-08 19:56:52 +0000356 Form form = getSuperClientForm();
357 Response response = installPlugin(form);
358 String entity = response.readEntity(String.class);
margaretha7da23902022-05-02 08:38:45 +0200359 JsonNode node = JsonUtils.readTree(entity);
margaretha35e1ca22023-11-16 22:00:01 +0100360 assertEquals(StatusCodes.INVALID_ARGUMENT,
361 node.at("/errors/0/0").asInt());
margaretha7da23902022-05-02 08:38:45 +0200362 assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
363 }
margarethad4841562022-06-01 12:24:47 +0200364
margaretha7da23902022-05-02 08:38:45 +0200365 @Test
margaretha35e1ca22023-11-16 22:00:01 +0100366 public void testInstallPluginInvalidClientId ()
367 throws ProcessingException, KustvaktException {
abcpro173fe8f22022-11-08 19:56:52 +0000368 Form form = getSuperClientForm();
369 form.param("client_id", "unknown");
370 Response response = installPlugin(form);
371 String entity = response.readEntity(String.class);
margaretha7da23902022-05-02 08:38:45 +0200372 JsonNode node = JsonUtils.readTree(entity);
margaretha35e1ca22023-11-16 22:00:01 +0100373 assertEquals(node.at("/error_description").asText(),
374 "Unknown client: unknown");
Marc Kupietzd43a98d2023-09-22 17:11:46 +0200375 assertEquals(node.at("/error").asText(), "invalid_client");
margaretha7da23902022-05-02 08:38:45 +0200376 assertEquals(Status.UNAUTHORIZED.getStatusCode(), response.getStatus());
377 }
margarethad4841562022-06-01 12:24:47 +0200378
margaretha7da23902022-05-02 08:38:45 +0200379 @Test
margaretha35e1ca22023-11-16 22:00:01 +0100380 public void testInstallPluginMissingSuperClientSecret ()
381 throws ProcessingException, KustvaktException {
abcpro173fe8f22022-11-08 19:56:52 +0000382 Form form = new Form();
383 form.param("super_client_id", superClientId);
abcpro173fe8f22022-11-08 19:56:52 +0000384 Response response = installPlugin(form);
385 String entity = response.readEntity(String.class);
margaretha7da23902022-05-02 08:38:45 +0200386 JsonNode node = JsonUtils.readTree(entity);
margaretha35e1ca22023-11-16 22:00:01 +0100387 assertEquals(node.at("/error_description").asText(),
388 "Missing parameter: super_client_secret");
Marc Kupietzd43a98d2023-09-22 17:11:46 +0200389 assertEquals(node.at("/error").asText(), "invalid_request");
margaretha7da23902022-05-02 08:38:45 +0200390 assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
391 }
margarethad4841562022-06-01 12:24:47 +0200392
margaretha7da23902022-05-02 08:38:45 +0200393 @Test
margaretha35e1ca22023-11-16 22:00:01 +0100394 public void testInstallPluginMissingSuperClientId ()
395 throws ProcessingException, KustvaktException {
abcpro173fe8f22022-11-08 19:56:52 +0000396 Form form = new Form();
397 Response response = installPlugin(form);
398 String entity = response.readEntity(String.class);
margaretha7da23902022-05-02 08:38:45 +0200399 JsonNode node = JsonUtils.readTree(entity);
margaretha35e1ca22023-11-16 22:00:01 +0100400 assertEquals(node.at("/error_description").asText(),
401 "Missing parameter: super_client_id");
Marc Kupietzd43a98d2023-09-22 17:11:46 +0200402 assertEquals(node.at("/error").asText(), "invalid_request");
margaretha7da23902022-05-02 08:38:45 +0200403 assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
404 }
margarethad4841562022-06-01 12:24:47 +0200405
margaretha7da23902022-05-02 08:38:45 +0200406 @Test
margaretha35e1ca22023-11-16 22:00:01 +0100407 public void testInstallPluginUnauthorizedClient ()
408 throws ProcessingException, KustvaktException {
abcpro173fe8f22022-11-08 19:56:52 +0000409 Form form = new Form();
410 form.param("super_client_id", confidentialClientId);
411 form.param("super_client_secret", clientSecret);
abcpro173fe8f22022-11-08 19:56:52 +0000412 Response response = installPlugin(form);
413 String entity = response.readEntity(String.class);
margaretha7da23902022-05-02 08:38:45 +0200414 JsonNode node = JsonUtils.readTree(entity);
Marc Kupietzd43a98d2023-09-22 17:11:46 +0200415 assertEquals(node.at("/error").asText(), "unauthorized_client");
margaretha7da23902022-05-02 08:38:45 +0200416 assertEquals(Status.UNAUTHORIZED.getStatusCode(), response.getStatus());
417 }
418
margaretha35e1ca22023-11-16 22:00:01 +0100419 private Response installPlugin (Form form)
420 throws ProcessingException, KustvaktException {
421 return target().path(API_VERSION).path("plugins").path("install")
422 .request()
423 .header(Attributes.AUTHORIZATION, HttpAuthorizationHandler
424 .createBasicAuthorizationHeaderValue(username, "pass"))
425 .header(HttpHeaders.CONTENT_TYPE,
426 ContentType.APPLICATION_FORM_URLENCODED)
427 .post(Entity.form(form));
margaretha7da23902022-05-02 08:38:45 +0200428 }
margarethad4841562022-06-01 12:24:47 +0200429
margaretha35e1ca22023-11-16 22:00:01 +0100430 private Response uninstallPlugin (String clientId, String username)
431 throws ProcessingException, KustvaktException {
abcpro173fe8f22022-11-08 19:56:52 +0000432 Form form = getSuperClientForm();
433 form.param("client_id", clientId);
margaretha35e1ca22023-11-16 22:00:01 +0100434 return target().path(API_VERSION).path("plugins").path("uninstall")
435 .request()
436 .header(Attributes.AUTHORIZATION, HttpAuthorizationHandler
437 .createBasicAuthorizationHeaderValue(username, "pass"))
438 .header(HttpHeaders.CONTENT_TYPE,
439 ContentType.APPLICATION_FORM_URLENCODED)
440 .post(Entity.form(form));
margarethad4841562022-06-01 12:24:47 +0200441 }
442
margaretha35e1ca22023-11-16 22:00:01 +0100443 private void testRetrieveInstalledPlugin (String superClientId,
444 String clientId, String installedBy) throws KustvaktException {
445 InstalledPlugin plugin = pluginDao
446 .retrieveInstalledPlugin(superClientId, clientId, installedBy);
margaretha68ccf1e2022-05-04 09:59:54 +0200447 assertEquals(clientId, plugin.getClient().getId());
448 assertEquals(superClientId, plugin.getSuperClient().getId());
449 assertEquals(installedBy, plugin.getInstalledBy());
margarethad4841562022-06-01 12:24:47 +0200450 assertTrue(plugin.getId() > 0);
451 assertTrue(plugin.getInstalledDate() != null);
452 }
453
454 @Test
margaretha35e1ca22023-11-16 22:00:01 +0100455 public void testListUserInstalledPlugins ()
456 throws ProcessingException, KustvaktException, IOException {
457 testInstallConfidentialPlugin(superClientId, confidentialClientId,
458 username);
margarethad4841562022-06-01 12:24:47 +0200459 JsonNode node = testRequestAccessToken(confidentialClientId);
Marc Kupietzd43a98d2023-09-22 17:11:46 +0200460 String accessToken = node.at("/access_token").asText();
margarethad4841562022-06-01 12:24:47 +0200461 String refreshToken = node.at("/refresh_token").asText();
462 testSearchWithOAuth2Token(accessToken);
margaretha35e1ca22023-11-16 22:00:01 +0100463 testInstallConfidentialPlugin(superClientId, confidentialClientId2,
464 username);
margarethad4841562022-06-01 12:24:47 +0200465 node = retrieveUserInstalledPlugin(getSuperClientForm());
466 assertEquals(2, node.size());
Marc Kupietzd43a98d2023-09-22 17:11:46 +0200467 Response response = uninstallPlugin(confidentialClientId, username);
margarethad4841562022-06-01 12:24:47 +0200468 assertEquals(Status.OK.getStatusCode(), response.getStatus());
469 node = retrieveUserInstalledPlugin(getSuperClientForm());
470 assertEquals(1, node.size());
margaretha35e1ca22023-11-16 22:00:01 +0100471 testRequestTokenWithRevokedRefreshToken(confidentialClientId,
472 clientSecret, refreshToken);
margarethad4841562022-06-01 12:24:47 +0200473 testSearchWithRevokedAccessToken(accessToken);
margarethad4841562022-06-01 12:24:47 +0200474 response = uninstallPlugin(confidentialClientId2, username);
475 assertEquals(Status.OK.getStatusCode(), response.getStatus());
476 node = retrieveUserInstalledPlugin(getSuperClientForm());
477 assertEquals(0, node.size());
margarethad7cac1d2023-02-10 10:51:45 +0100478 testReinstallUninstalledPlugin();
margarethad4841562022-06-01 12:24:47 +0200479 testUninstallNotInstalledPlugin();
480 }
Marc Kupietzd43a98d2023-09-22 17:11:46 +0200481
margaretha35e1ca22023-11-16 22:00:01 +0100482 private void testReinstallUninstalledPlugin ()
483 throws ProcessingException, KustvaktException {
484 testInstallConfidentialPlugin(superClientId, confidentialClientId2,
485 username);
margarethad7cac1d2023-02-10 10:51:45 +0100486 JsonNode node = retrieveUserInstalledPlugin(getSuperClientForm());
487 assertEquals(1, node.size());
margarethad7cac1d2023-02-10 10:51:45 +0100488 Response response = uninstallPlugin(confidentialClientId2, username);
489 assertEquals(Status.OK.getStatusCode(), response.getStatus());
margarethad7cac1d2023-02-10 10:51:45 +0100490 node = retrieveUserInstalledPlugin(getSuperClientForm());
491 assertEquals(0, node.size());
492 }
493
margaretha35e1ca22023-11-16 22:00:01 +0100494 private JsonNode testRequestAccessToken (String clientId)
495 throws KustvaktException {
496 String userAuthHeader = HttpAuthorizationHandler
497 .createBasicAuthorizationHeaderValue(username, "password");
margarethad4841562022-06-01 12:24:47 +0200498 String code = requestAuthorizationCode(clientId, userAuthHeader);
margaretha35e1ca22023-11-16 22:00:01 +0100499 Response response = requestTokenWithAuthorizationCodeAndForm(clientId,
500 clientSecret, code);
abcpro173fe8f22022-11-08 19:56:52 +0000501 JsonNode node = JsonUtils.readTree(response.readEntity(String.class));
margarethad4841562022-06-01 12:24:47 +0200502 assertEquals(Status.OK.getStatusCode(), response.getStatus());
503 return node;
504 }
505
margaretha35e1ca22023-11-16 22:00:01 +0100506 private void testUninstallNotInstalledPlugin ()
507 throws ProcessingException, KustvaktException {
Marc Kupietzd43a98d2023-09-22 17:11:46 +0200508 Response response = uninstallPlugin(confidentialClientId2, username);
margarethad4841562022-06-01 12:24:47 +0200509 assertEquals(Status.NOT_FOUND.getStatusCode(), response.getStatus());
abcpro173fe8f22022-11-08 19:56:52 +0000510 JsonNode node = JsonUtils.readTree(response.readEntity(String.class));
margaretha35e1ca22023-11-16 22:00:01 +0100511 assertEquals(StatusCodes.NO_RESOURCE_FOUND,
512 node.at("/errors/0/0").asInt());
margarethad4841562022-06-01 12:24:47 +0200513 }
514
margaretha35e1ca22023-11-16 22:00:01 +0100515 private JsonNode retrieveUserInstalledPlugin (Form form)
516 throws ProcessingException, KustvaktException {
517 Response response = target().path(API_VERSION).path("plugins")
518 .path("installed").request()
519 .header(Attributes.AUTHORIZATION, HttpAuthorizationHandler
520 .createBasicAuthorizationHeaderValue(username, "pass"))
521 .header(HttpHeaders.CONTENT_TYPE,
522 ContentType.APPLICATION_FORM_URLENCODED)
523 .post(Entity.form(form));
abcpro173fe8f22022-11-08 19:56:52 +0000524 String entity = response.readEntity(String.class);
margarethad4841562022-06-01 12:24:47 +0200525 return JsonUtils.readTree(entity);
margaretha68ccf1e2022-05-04 09:59:54 +0200526 }
margarethae20a2802022-04-21 12:37:38 +0200527}