|
49 | 49 | import org.elasticsearch.indices.InvalidIndexNameException; |
50 | 50 | import org.elasticsearch.license.XPackLicenseState; |
51 | 51 | import org.elasticsearch.search.crossproject.CrossProjectModeDecider; |
| 52 | +import org.elasticsearch.search.crossproject.CrossProjectRoutingResolver; |
52 | 53 | import org.elasticsearch.search.crossproject.NoMatchingProjectException; |
| 54 | +import org.elasticsearch.search.crossproject.ProjectRoutingInfo; |
53 | 55 | import org.elasticsearch.search.crossproject.TargetProjects; |
54 | 56 | import org.elasticsearch.threadpool.ThreadPool; |
55 | 57 | import org.elasticsearch.transport.LinkedProjectConfigService; |
|
106 | 108 | import java.util.Map; |
107 | 109 | import java.util.Set; |
108 | 110 | import java.util.function.Consumer; |
| 111 | +import java.util.function.Predicate; |
109 | 112 | import java.util.function.Supplier; |
110 | 113 |
|
111 | 114 | import static org.elasticsearch.action.support.ContextPreservingActionListener.wrapPreservingContext; |
@@ -504,12 +507,38 @@ private void authorizeAction( |
504 | 507 | final SubscribableListener<TargetProjects> targetProjectListener; |
505 | 508 | if (indicesAndAliasesResolver.resolvesCrossProject(request)) { |
506 | 509 | targetProjectListener = new SubscribableListener<>(); |
| 510 | + // Get list of projects from cluster state |
| 511 | + // Remove projects from list that user lacks permissions to access |
507 | 512 | authorizedProjectsResolver.resolveAuthorizedProjects(targetProjectListener); |
| 513 | + |
| 514 | + // project routing resolution could go here |
| 515 | + // regardless of location, it would look something like... |
| 516 | + targetProjectListener.andThenApply(targetProjects -> { |
| 517 | + // we'd inject the CrossProjectRoutingResolver |
| 518 | + // we somehow pipe project_routing through to here, |
| 519 | + // perhaps setting it in the SearchRequest so we can access it via RequestInfo.getRequest() |
| 520 | + var projectRoutingInfos = new CrossProjectRoutingResolver().resolve( |
| 521 | + "*", |
| 522 | + targetProjects.originProject(), |
| 523 | + targetProjects.linkedProjects() |
| 524 | + ); |
| 525 | + var originOrNull = projectRoutingInfos.stream() |
| 526 | + .filter(targetProjects.originProject()::equals) |
| 527 | + .findAny() |
| 528 | + .orElse(null); |
| 529 | + var linkedProjects = projectRoutingInfos.stream() |
| 530 | + .filter(Predicate.not(targetProjects.originProject()::equals)) |
| 531 | + .toList(); |
| 532 | + // perhaps we change the CrossProjectRoutingResolver API to accept and return TargetProjects? |
| 533 | + return new TargetProjects(originOrNull, linkedProjects); |
| 534 | + }); |
508 | 535 | } else { |
509 | 536 | targetProjectListener = SubscribableListener.newSucceeded(TargetProjects.LOCAL_ONLY_FOR_CPS_DISABLED); |
510 | 537 | } |
511 | 538 |
|
512 | 539 | targetProjectListener.addListener(ActionListener.wrap(targetProjects -> { |
| 540 | + // this will eventually rewrite the index expression based on the targetProjects, |
| 541 | + // so filtering by project_routing should go before here |
513 | 542 | final AsyncSupplier<ResolvedIndices> resolvedIndicesAsyncSupplier = makeResolvedIndicesAsyncSupplier( |
514 | 543 | targetProjects, |
515 | 544 | requestInfo, |
|
0 commit comments