Skip to content

Commit 8634211

Browse files
committed
Alerts : Pagination Backend
1 parent 34dba8b commit 8634211

File tree

3 files changed

+97
-4
lines changed

3 files changed

+97
-4
lines changed

src/main/java/com/airbus_cyber_security/graylog/wizard/alert/business/AlertRuleService.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,13 @@
1919

2020
import com.airbus_cyber_security.graylog.wizard.alert.model.AlertRule;
2121
import com.mongodb.BasicDBObject;
22+
import org.bson.conversions.Bson;
2223
import org.graylog2.bindings.providers.MongoJackObjectMapperProvider;
2324
import org.graylog2.database.MongoConnection;
2425
import org.graylog2.database.NotFoundException;
2526
import org.graylog2.database.PaginatedDbService;
27+
import org.graylog2.database.PaginatedList;
28+
import org.graylog2.search.SearchQuery;
2629
import org.mongojack.DBCursor;
2730
import org.mongojack.DBQuery;
2831
import org.slf4j.Logger;
@@ -33,6 +36,7 @@
3336
import jakarta.validation.Validator;
3437
import java.util.List;
3538
import java.util.Set;
39+
import java.util.function.Predicate;
3640

3741

3842
// TODO split this into AlertRuleCollection and move it down in the persistence namespace
@@ -90,4 +94,19 @@ public AlertRule load(String title) throws NotFoundException {
9094
public boolean isPresent(String title) {
9195
return (this.db.getCount(DBQuery.is(TITLE, title)) > 0);
9296
}
97+
98+
public PaginatedList<AlertRule> searchPaginated(SearchQuery query, Predicate<AlertRule> filter,
99+
Bson sort, int page, int perPage) {
100+
final Bson dbQuery = query.toBson();
101+
final PaginatedList<AlertRule> list = filter == null ?
102+
findPaginatedWithQueryAndSort(dbQuery, sort, page, perPage) :
103+
findPaginatedWithQueryFilterAndSort(dbQuery, filter, sort, page, perPage);
104+
105+
return new PaginatedList<>(
106+
list,
107+
list.pagination().total(),
108+
page,
109+
perPage
110+
);
111+
}
93112
}

src/main/java/com/airbus_cyber_security/graylog/wizard/alert/rest/AlertRuleResource.java

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import com.airbus_cyber_security.graylog.wizard.config.rest.ImportPolicyType;
4141
import com.airbus_cyber_security.graylog.wizard.permissions.AlertRuleRestPermissions;
4242
import com.codahale.metrics.annotation.Timed;
43+
import com.google.common.collect.ImmutableMap;
4344
import com.mongodb.MongoException;
4445
import io.swagger.annotations.Api;
4546
import io.swagger.annotations.ApiOperation;
@@ -49,25 +50,35 @@
4950
import jakarta.ws.rs.BadRequestException;
5051
import jakarta.ws.rs.Consumes;
5152
import jakarta.ws.rs.DELETE;
53+
import jakarta.ws.rs.DefaultValue;
5254
import jakarta.ws.rs.GET;
5355
import jakarta.ws.rs.POST;
5456
import jakarta.ws.rs.PUT;
5557
import jakarta.ws.rs.Path;
5658
import jakarta.ws.rs.PathParam;
5759
import jakarta.ws.rs.Produces;
60+
import jakarta.ws.rs.QueryParam;
5861
import org.apache.shiro.authz.annotation.RequiresAuthentication;
5962
import org.apache.shiro.authz.annotation.RequiresPermissions;
6063
import org.graylog.events.notifications.NotificationDto;
6164
import org.graylog.events.processor.EventDefinition;
6265
import org.graylog.events.processor.EventDefinitionDto;
6366
import org.graylog.events.processor.EventProcessorConfig;
64-
import org.graylog.events.processor.aggregation.AggregationEventProcessorConfig;
6567
import org.graylog.events.rest.EventNotificationsResource;
6668
import org.graylog.security.UserContext;
6769
import org.graylog2.audit.jersey.AuditEvent;
6870
import org.graylog2.database.NotFoundException;
71+
import org.graylog2.database.PaginatedList;
6972
import org.graylog2.plugin.database.ValidationException;
7073
import org.graylog2.plugin.rest.PluginRestResource;
74+
import org.graylog2.rest.models.SortOrder;
75+
import org.graylog2.rest.models.tools.responses.PageListResponse;
76+
import org.graylog2.rest.resources.entities.EntityAttribute;
77+
import org.graylog2.rest.resources.entities.EntityDefaults;
78+
import org.graylog2.rest.resources.entities.Sorting;
79+
import org.graylog2.search.SearchQuery;
80+
import org.graylog2.search.SearchQueryField;
81+
import org.graylog2.search.SearchQueryParser;
7182
import org.graylog2.shared.rest.resources.RestResource;
7283
import org.joda.time.DateTime;
7384
import org.joda.time.DateTimeZone;
@@ -83,6 +94,7 @@
8394
import java.io.UnsupportedEncodingException;
8495
import java.util.ArrayList;
8596
import java.util.List;
97+
import java.util.Locale;
8698
import java.util.Map;
8799
import java.util.Optional;
88100

@@ -96,6 +108,22 @@ public class AlertRuleResource extends RestResource implements PluginRestResourc
96108
private static final String ENCODING = "UTF-8";
97109
private static final String TITLE = "title";
98110

111+
private static final String DEFAULT_SORT_FIELD = "title";
112+
private static final String DEFAULT_SORT_DIRECTION = "asc";
113+
private static final ImmutableMap<String, SearchQueryField> SEARCH_FIELD_MAPPING = ImmutableMap.<String, SearchQueryField>builder()
114+
.put("id", SearchQueryField.create("_id", SearchQueryField.Type.OBJECT_ID))
115+
.put("title", SearchQueryField.create(GetDataAlertRule.FIELD_TITLE))
116+
.put("description", SearchQueryField.create(GetDataAlertRule.FIELD_DESCRIPTION))
117+
.build();
118+
private static final List<EntityAttribute> attributes = List.of(
119+
EntityAttribute.builder().id("title").title("Title").build(),
120+
EntityAttribute.builder().id("description").title("Description").build(),
121+
EntityAttribute.builder().id("priority").title("Priority").type(SearchQueryField.Type.INT).build()
122+
);
123+
private static final EntityDefaults settings = EntityDefaults.builder()
124+
.sort(Sorting.create(DEFAULT_SORT_FIELD, Sorting.Direction.valueOf(DEFAULT_SORT_DIRECTION.toUpperCase(Locale.ROOT))))
125+
.build();
126+
99127
// TODO try to remove this field => move it down in business
100128
private final AlertWizardConfigurationService configurationService;
101129

@@ -108,6 +136,8 @@ public class AlertRuleResource extends RestResource implements PluginRestResourc
108136
private final TriggeringConditionsService triggeringConditionsService;
109137
private final NotificationService notificationService;
110138

139+
private final SearchQueryParser searchQueryParser;
140+
111141
@Inject
112142
public AlertRuleResource(AlertRuleService alertRuleService,
113143
TriggeringConditionsService triggeringConditionsService,
@@ -125,6 +155,7 @@ public AlertRuleResource(AlertRuleService alertRuleService,
125155

126156
this.conversions = conversions;
127157
this.notificationService = notificationService;
158+
this.searchQueryParser = new SearchQueryParser(GetDataAlertRule.FIELD_TITLE, SEARCH_FIELD_MAPPING);
128159
}
129160

130161
private AlertRuleStream constructAlertRuleStream(TriggeringConditions conditions) {
@@ -574,4 +605,44 @@ private String createNotificationFromCloneRequest(String alertTitle, UserContext
574605
return this.notificationService.createNotification(alertTitle, userContext);
575606
}
576607
}
608+
609+
// This method is based on method getPage in class org.graylog.events.rest.EventDefinitionsResource
610+
@GET
611+
@Timed
612+
@Path("/paginated")
613+
@ApiOperation(value = "Get a paginated list of alerts")
614+
@Produces(MediaType.APPLICATION_JSON)
615+
public PageListResponse<GetDataAlertRule> getPage(@ApiParam(name = "page") @QueryParam("page") @DefaultValue("1") int page,
616+
@ApiParam(name = "per_page") @QueryParam("per_page") @DefaultValue("50") int perPage,
617+
@ApiParam(name = "query") @QueryParam("query") @DefaultValue("") String query,
618+
@ApiParam(name = "sort",
619+
value = "The field to sort the result on",
620+
required = true,
621+
allowableValues = "title,description,priority")
622+
@DefaultValue(DEFAULT_SORT_FIELD) @QueryParam("sort") String sort,
623+
@ApiParam(name = "order", value = "The sort direction", allowableValues = "asc, desc")
624+
@DefaultValue(DEFAULT_SORT_DIRECTION) @QueryParam("order") SortOrder order) {
625+
626+
SearchQuery searchQuery;
627+
try {
628+
searchQuery = searchQueryParser.parse(query);
629+
} catch (IllegalArgumentException e) {
630+
throw new BadRequestException("Invalid argument in search query: " + e.getMessage());
631+
}
632+
final PaginatedList<AlertRule> result = this.alertRuleService.searchPaginated(
633+
searchQuery,
634+
alertRule -> true,
635+
order.toBsonSort(sort),
636+
page,
637+
perPage);
638+
639+
PaginatedList<AlertRule> alertRules = new PaginatedList<>(
640+
result.delegate(), result.pagination().total(), result.pagination().page(), result.pagination().perPage()
641+
);
642+
643+
List<GetDataAlertRule> elements = result.delegate().stream().map(this::constructDataAlertRule).toList();
644+
645+
return PageListResponse.create(query, alertRules.pagination(),
646+
result.grandTotal().orElse(0L), sort, order, elements, attributes, settings);
647+
}
577648
}

src/main/java/com/airbus_cyber_security/graylog/wizard/alert/rest/models/responses/GetDataAlertRule.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,16 +34,19 @@
3434
@AutoValue
3535
@JsonAutoDetect
3636
public abstract class GetDataAlertRule {
37+
public static final String FIELD_TITLE = "title";
38+
public static final String FIELD_PRIORITY = "priority";
39+
public static final String FIELD_DESCRIPTION = "description";
3740

38-
@JsonProperty("title")
41+
@JsonProperty(FIELD_TITLE)
3942
@NotNull
4043
public abstract String getTitle();
4144

42-
@JsonProperty("priority")
45+
@JsonProperty(FIELD_PRIORITY)
4346
@Nullable
4447
public abstract Integer getPriority();
4548

46-
@JsonProperty("description")
49+
@JsonProperty(FIELD_DESCRIPTION)
4750
@Nullable
4851
public abstract String getDescription();
4952

0 commit comments

Comments
 (0)