1 package de.dlr.shepard.common.filters;
2
3 import de.dlr.shepard.auth.permission.services.PermissionsService;
4 import de.dlr.shepard.common.neo4j.io.HasIdIO;
5 import de.dlr.shepard.common.subscription.entities.Subscription;
6 import de.dlr.shepard.common.subscription.io.EventIO;
7 import de.dlr.shepard.common.subscription.io.SubscriptionIO;
8 import de.dlr.shepard.common.subscription.services.SubscriptionService;
9 import de.dlr.shepard.common.util.AccessType;
10 import de.dlr.shepard.common.util.HasId;
11 import de.dlr.shepard.common.util.RequestMethod;
12 import io.quarkus.logging.Log;
13 import jakarta.enterprise.context.RequestScoped;
14 import jakarta.inject.Inject;
15 import jakarta.ws.rs.ProcessingException;
16 import jakarta.ws.rs.client.ClientBuilder;
17 import jakarta.ws.rs.client.Entity;
18 import jakarta.ws.rs.container.ContainerRequestContext;
19 import jakarta.ws.rs.container.ContainerResponseContext;
20 import jakarta.ws.rs.container.ContainerResponseFilter;
21 import jakarta.ws.rs.core.MediaType;
22 import jakarta.ws.rs.ext.Provider;
23 import java.util.List;
24 import java.util.regex.Pattern;
25
26 @Subscribable
27 @Provider
28 @RequestScoped
29 public class SubscriptionFilter implements ContainerResponseFilter {
30
31 @Inject
32 ExecutorFactory executorFactory;
33
34 @Inject
35 PermissionsService permissionsService;
36
37 @Inject
38 SubscriptionService subscriptionService;
39
40 @Override
41 public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) {
42
43 var status = responseContext.getStatus();
44 if (!(status >= 200 && status < 300)) {
45 Log.debug("Skip subscriptions since the http status code is not between 200 and 299");
46 return;
47 }
48
49
50 EventIO event = new EventIO(
51 requestContext.getUriInfo().getAbsolutePath().toString(),
52 RequestMethod.valueOf(requestContext.getMethod())
53 );
54
55 Object entity = responseContext.getEntity();
56 if (entity instanceof HasId hasId) {
57 event.setSubscribedObject(new HasIdIO(hasId));
58 }
59
60 List<Subscription> subs = subscriptionService.getMatchingSubscriptions(event.getRequestMethod());
61 for (Subscription sub : subs) {
62
63 Pattern pattern = Pattern.compile(sub.getSubscribedURL());
64 if (
65 pattern.matcher(event.getUrl()).matches() &&
66 permissionsService.isAllowed(requestContext, AccessType.Read, sub.getCreatedBy().getUsername())
67 ) {
68 EventIO e = new EventIO(event);
69 e.setSubscription(new SubscriptionIO(sub));
70 Log.debugf("%s was triggered with %s", sub, e);
71 executorFactory.getInstance().execute(() -> sendCallback(sub, e));
72 }
73 }
74 }
75
76 private void sendCallback(Subscription sub, EventIO event) {
77 var client = ClientBuilder.newClient();
78 var webTarget = client.target(sub.getCallbackURL());
79
80 try {
81 var entity = Entity.entity(event, MediaType.APPLICATION_JSON);
82 var response = webTarget.request().buildPost(entity).invoke();
83 Log.infof("Notification has been send to %s with response code: %s", sub.getCallbackURL(), response.getStatus());
84 } catch (ProcessingException e) {
85 Log.error("Could not execute notification request");
86 } finally {
87 client.close();
88 }
89 }
90 }