Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MODFQMMGR-456: Check whether entity type is cross-tenant when retrieving definition #434

Merged
merged 1 commit into from
Sep 27, 2024

Conversation

bvsharp
Copy link
Collaborator

@bvsharp bvsharp commented Sep 24, 2024

Purpose

MODFQMMGR-456: Check whether entity type is cross-tenant when retrieving definition

@bvsharp bvsharp force-pushed the MODFQMMGR-456-take-3 branch 4 times, most recently from bc0a1b3 to 7204a0f Compare September 25, 2024 17:12
Comment on lines -30 to +33
if (!forceCrossTenantQuery && !Boolean.TRUE.equals(entityType.getCrossTenantQueriesEnabled())) {
if (!forceCrossTenantQuery
&& !Boolean.TRUE.equals(entityType.getCrossTenantQueriesEnabled())
&& !COMPOSITE_INSTANCES_ID.equals(entityType.getId())) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I hate how complicated this condition is getting, but we do need all these checks. The new check for the composite instances ID is due to the fact that cross-tenant queries will be disabled for non-central tenants, but we DO still need to run a (pseudo) cross tenant query for composite instances in member tenants in order to get the shared instances from the central tenant.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is going to run into issues with the tenant ID dropdown menu for instances, since the entity type that gets passed in is simple_instances, which doesn't have cross-tenant queries enabled :(

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we end up needing to check both composite and simple instances in 2 places in this method, I think I'd make a private static final Set<String> to hold the IDs, then do a contains(entityType.getId()) instead of checking both IDs separately

Copy link
Collaborator Author

@bvsharp bvsharp Sep 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This situation actually gets handled by the forceCrossTenantQuery parameter! When we get the tenant ID values, we pass forceCrossTenantQuery=true to this method. Since it's true, we skip this block. From there:

  1. If ECS is not enabled, we return only the current tenant.
  2. If ECS is enabled but we're not in the central tenant AND the entity type is composite/simple instances, we return the current tenant plus the central tenant (in order to get the shared instances).
  3. If ECS is enabled and we're in the central tenant, then we query everything we have permission for.

So I think everything related to the tenant ID dropdown is handled. The only thing that the current code doesn't handle is running a (non-tenant ID related) query on the simple_instances entity from a member tenant. In that situation, we'd only be querying the member tenant, so we wouldn't see the shared records from the central tenant (although this is counter-balanced by the fact that simple_instances doesn't have an additionalEcsConditions defined either, meaning that we wouldn't be filtering out shadow instances. So in this situation we'd see ALMOST the same thing as for composite_instances, only we'd be seeing the shadow instances instead of the shared ones).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And I don't think we'd want to include simple_instances in the first check (at least the way we have the definitions set up right now), due to the fact the simple_instances doesn't filter out the shadow instances. So if we added the simple_instance check to the first block, we'd end up with duplicate instance records in the query results (one shadow version and one shared version for each shared instance).

@bvsharp bvsharp marked this pull request as ready for review September 25, 2024 18:29
Comment on lines +90 to +91
boolean crossTenantEnabled = Boolean.TRUE.equals(entityType.getCrossTenantQueriesEnabled())
&& crossTenantQueryService.isCentralTenant();
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kind of a weird way to do it, but this essentially overwrites the crossTenantQueriesEnabled property, so that non-central tenants have it set to false, even if it's true in the original definition. This will allow us to avoid forcing lists for cross-tenant entity types to be private in member tenants, and instead only apply that effect to lists in the central tenant. Still not crazy about this approach but it seems to be the simplest option for now.

Comment on lines 119 to 122
public boolean isCentralTenant() {
return executionContext.getTenantId().equals(getCentralTenantId());
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd follow the pattern that the other method here use, where there's overloaded with a private version that takes the Map<String, String> ecsTenantInfo parameter. Then, I'd update getTenantsToQuery() to use the private version, so that all of the "is this the central tenant?" logic runs through that one method

@bvsharp bvsharp force-pushed the MODFQMMGR-456-take-3 branch 3 times, most recently from 9dd919c to a5bdafb Compare September 26, 2024 21:25
Comment on lines +1 to +26
package org.folio.fqm.service;

import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.folio.fqm.client.SimpleHttpClient;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.Map;

/**
* Service wrapper for caching responses from user-tenants API.
*/
@Service
@RequiredArgsConstructor
@Log4j2
public class UserTenantService {

private final SimpleHttpClient userTenantsClient;

@Cacheable(value="userTenantCache", key="#tenantId")
public String getUserTenantsResponse(String tenantId) {
log.info("Retrieving user-tenants information for tenant {}", tenantId);
return userTenantsClient.get("user-tenants", Map.of("limit", String.valueOf(1)));
}
}
Copy link
Collaborator Author

@bvsharp bvsharp Sep 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added this class to allow for convenient caching for the user-tenants responses. We use the /user-tenants endpoint in both the EntityTypeFlatteningService and the CrossTenantQueryService, so I figured adding a service wrapper made the most sense to allow us to:

  1. Cache the user-tenants responses in a convenient way regardless of what class the request is made from, and without code duplication.
  2. Avoid caching responses on any of the other SimpleHttpClient requests.

@@ -75,6 +75,7 @@ coffee-boots:
cache:
spec:
queryCache: maximumSize=500,expireAfterWrite=1m
userTenantCache: maximumSize=100,expireAfterWrite=5h
Copy link
Collaborator Author

@bvsharp bvsharp Sep 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Picked a fairly arbitrary expire time, and am open to any other values for this cache. Also open to making it a configurable value, though I didn't do make it configurable for the time being, since I'm not sure there's any value in doing so.

Copy link

sonarcloud bot commented Sep 26, 2024

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call on breaking this out into a separate service!

@bvsharp bvsharp merged commit 5280cfa into master Sep 27, 2024
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants