Skip to content

Commit

Permalink
Moving validation of DW search to gl-server
Browse files Browse the repository at this point in the history
  • Loading branch information
luk-kaminski committed Dec 17, 2024
1 parent 63e03d9 commit 6152085
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright (C) 2020 Graylog, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the Server Side Public License, version 1,
* as published by MongoDB, Inc.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* Server Side Public License for more details.
*
* You should have received a copy of the Server Side Public License
* along with this program. If not, see
* <http://www.mongodb.com/licensing/server-side-public-license>.
*/
package org.graylog.plugins.views.search;

/**
* Marker interface for search types that are not search engine related, but Data Warehouse/Iceberg related
*/
public interface DataWarehouseSearchType extends SearchType {

String PREFIX = "data_warehouse_";
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import org.graylog.plugins.views.search.engine.normalization.DecorateQueryStringsNormalizer;
import org.graylog.plugins.views.search.engine.normalization.PluggableSearchNormalization;
import org.graylog.plugins.views.search.engine.normalization.SearchNormalization;
import org.graylog.plugins.views.search.engine.validation.DataWarehouseSearchValidator;
import org.graylog.plugins.views.search.engine.validation.PluggableSearchValidation;
import org.graylog.plugins.views.search.engine.validation.SearchValidation;
import org.graylog.plugins.views.search.engine.validation.TimeRangeValidator;
Expand All @@ -34,5 +35,7 @@ protected void configure() {
// Triggering set binder explicitly, so no injection errors are being caused if no implementation is bound.
searchPostValidationNormalizerBinder();
registerSearchValidator(TimeRangeValidator.class);
//while DW searches are enterprise only, the validation should probably be present in gl-server, i.e. to discover invalid searches even if a client has lost the license
registerSearchValidator(DataWarehouseSearchValidator.class);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*
* Copyright (C) 2020 Graylog, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the Server Side Public License, version 1,
* as published by MongoDB, Inc.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* Server Side Public License for more details.
*
* You should have received a copy of the Server Side Public License
* along with this program. If not, see
* <http://www.mongodb.com/licensing/server-side-public-license>.
*/
package org.graylog.plugins.views.search.engine.validation;

import com.google.common.collect.ImmutableSet;
import org.graylog.plugins.views.search.DataWarehouseSearchType;
import org.graylog.plugins.views.search.Query;
import org.graylog.plugins.views.search.Search;
import org.graylog.plugins.views.search.SearchType;
import org.graylog.plugins.views.search.errors.QueryError;
import org.graylog.plugins.views.search.errors.SearchError;
import org.graylog.plugins.views.search.errors.SearchTypeError;
import org.graylog.plugins.views.search.permissions.SearchUser;

import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

public class DataWarehouseSearchValidator implements SearchValidator {

@Override
public Set<SearchError> validate(final Search search,
final SearchUser searchUser) {
//this should be either validated elsewhere or impossible
assert search.queries() != null;
assert !search.queries().isEmpty();

if (containsDataWarehouseSearchElements(search)) {
if (search.queries().size() > 1) {
return wholeSearchInvalid(search, "Data Warehouse elements present in Search, only 1 query allowed for those type of searches");
}
return validate(search.queries().stream().findFirst().get(), searchUser);
} else {
return Set.of();
}
}

@Override
public Set<SearchError> validate(final Query query,
final SearchUser searchUser) {
if (containsDataWarehouseSearchElements(query)) {
final ImmutableSet<SearchType> searchTypes = query.searchTypes();
if (searchTypes.size() != 1) {
return Set.of(new QueryError(query, "Data Warehouse query can contain only one search type"));
}
final Optional<SearchType> first = searchTypes.stream().findFirst();
if (!(first.get() instanceof DataWarehouseSearchType)) {
return Set.of(new SearchTypeError(query, first.get().id(), "Data Warehouse query can contain only data warehouse search types"));
} else {
final Set<String> streams = first.get().streams();
if (streams == null || streams.size() > 1) {
return Set.of(new SearchTypeError(query, first.get().id(), "Data Warehouse preview can be executed on only 1 stream, search type contained more"));
}
}
}
return Set.of();
}

private boolean containsDataWarehouseSearchElements(final Search search) {
return search.queries().stream().anyMatch(this::containsDataWarehouseSearchElements);
}

private boolean containsDataWarehouseSearchElements(final Query query) {
return (query.query().type().startsWith(DataWarehouseSearchType.PREFIX))
|| (query.searchTypes().stream().anyMatch(searchType -> searchType instanceof DataWarehouseSearchType));
}

private Set<SearchError> wholeSearchInvalid(final Search search, final String explanation) {
return search.queries()
.stream()
.map(query -> new QueryError(query, explanation))
.collect(Collectors.toSet());
}
}

0 comments on commit 6152085

Please sign in to comment.