use of com.bakdata.conquery.util.QueryUtils.NamespacedIdentifiableCollector in project conquery by bakdata.
the class QueryDescription method addVisitors.
/**
* Allows the implementation to add visitors that traverse the QueryTree.
* All visitors are concatenated so only a single traverse needs to be done.
* @param visitors The structure to which new visitors need to be added.
*/
default void addVisitors(@NonNull ClassToInstanceMap<QueryVisitor> visitors) {
// Register visitors for permission checks
visitors.putInstance(NamespacedIdentifiableCollector.class, new NamespacedIdentifiableCollector());
visitors.putInstance(QueryUtils.ExternalIdChecker.class, new QueryUtils.ExternalIdChecker());
}
use of com.bakdata.conquery.util.QueryUtils.NamespacedIdentifiableCollector in project conquery by bakdata.
the class QueryProcessor method postQuery.
/**
* Creates a query for all datasets, then submits it for execution on the
* intended dataset.
*/
public ManagedExecution<?> postQuery(Dataset dataset, QueryDescription query, Subject subject) {
log.info("Query posted on Dataset[{}] by User[{{}].", dataset.getId(), subject.getId());
// This maps works as long as we have query visitors that are not configured in anyway.
// So adding a visitor twice would replace the previous one but both would have yielded the same result.
// For the future a better data structure might be desired that also regards similar QueryVisitors of different configuration
ClassToInstanceMap<QueryVisitor> visitors = MutableClassToInstanceMap.create();
query.addVisitors(visitors);
// Initialize checks that need to traverse the query tree
visitors.putInstance(QueryUtils.OnlyReusingChecker.class, new QueryUtils.OnlyReusingChecker());
visitors.putInstance(NamespacedIdentifiableCollector.class, new NamespacedIdentifiableCollector());
final String primaryGroupName = AuthorizationHelper.getPrimaryGroup(subject, storage).map(Group::getName).orElse("none");
visitors.putInstance(ExecutionMetrics.QueryMetricsReporter.class, new ExecutionMetrics.QueryMetricsReporter(primaryGroupName));
// Chain all Consumers
Consumer<Visitable> consumerChain = QueryUtils.getNoOpEntryPoint();
for (QueryVisitor visitor : visitors.values()) {
consumerChain = consumerChain.andThen(visitor);
}
// Apply consumers to the query tree
query.visit(consumerChain);
query.authorize(subject, dataset, visitors);
// After all authorization checks we can now use the actual subject to invoke the query and do not to bubble down the Userish in methods
ExecutionMetrics.reportNamespacedIds(visitors.getInstance(NamespacedIdentifiableCollector.class).getIdentifiables(), primaryGroupName);
ExecutionMetrics.reportQueryClassUsage(query.getClass(), primaryGroupName);
final Namespace namespace = datasetRegistry.get(dataset.getId());
final ExecutionManager executionManager = namespace.getExecutionManager();
// If this is only a re-executing query, try to execute the underlying query instead.
{
final Optional<ManagedExecutionId> executionId = visitors.getInstance(QueryUtils.OnlyReusingChecker.class).getOnlyReused();
final Optional<ManagedExecution<?>> execution = executionId.map(id -> tryReuse(query, id, datasetRegistry, config, executionManager, subject.getUser()));
if (execution.isPresent()) {
return execution.get();
}
}
// Execute the query
return executionManager.runQuery(datasetRegistry, query, subject.getUser(), dataset, config);
}
use of com.bakdata.conquery.util.QueryUtils.NamespacedIdentifiableCollector in project conquery by bakdata.
the class AuthorizationHelper method authorizeDownloadDatasets.
/**
* Checks if an execution is allowed to be downloaded by a user.
* This checks all used {@link DatasetId}s for the {@link Ability#DOWNLOAD} on the user.
*/
public static void authorizeDownloadDatasets(@NonNull Subject subject, @NonNull Visitable visitable) {
NamespacedIdentifiableCollector collector = new NamespacedIdentifiableCollector();
visitable.visit(collector);
Set<Dataset> datasets = collector.getIdentifiables().stream().map(NamespacedIdentifiable::getDataset).collect(Collectors.toSet());
subject.authorize(datasets, Ability.DOWNLOAD);
}
use of com.bakdata.conquery.util.QueryUtils.NamespacedIdentifiableCollector in project conquery by bakdata.
the class ManagedQuery method getUsedNamespacedIds.
@Override
@JsonIgnore
public Set<NamespacedIdentifiable<?>> getUsedNamespacedIds() {
NamespacedIdentifiableCollector collector = new NamespacedIdentifiableCollector();
query.visit(collector);
return collector.getIdentifiables();
}
use of com.bakdata.conquery.util.QueryUtils.NamespacedIdentifiableCollector in project conquery by bakdata.
the class ManagedExecution method setAdditionalFieldsForStatusWithSource.
/**
* Sets additional fields of an {@link ExecutionStatus} when a more specific status is requested.
*/
protected void setAdditionalFieldsForStatusWithSource(Subject subject, FullExecutionStatus status) {
QueryDescription query = getSubmitted();
NamespacedIdentifiableCollector namespacesIdCollector = new NamespacedIdentifiableCollector();
query.visit(namespacesIdCollector);
final Set<Concept> concepts = namespacesIdCollector.getIdentifiables().stream().filter(ConceptElement.class::isInstance).map(ConceptElement.class::cast).map(ConceptElement::getConcept).collect(Collectors.toSet());
boolean canExpand = subject.isPermittedAll(concepts, Ability.READ);
status.setCanExpand(canExpand);
status.setQuery(canExpand ? getSubmitted() : null);
}
Aggregations