diff --git a/src/main/java/jasper/repository/spec/OriginSpec.java b/src/main/java/jasper/repository/spec/OriginSpec.java index 45eb25ef..e35060ad 100644 --- a/src/main/java/jasper/repository/spec/OriginSpec.java +++ b/src/main/java/jasper/repository/spec/OriginSpec.java @@ -3,6 +3,8 @@ import jasper.domain.proj.HasOrigin; import org.springframework.data.jpa.domain.Specification; +import java.util.List; + public class OriginSpec { public static Specification isOrigin(String origin) { @@ -13,6 +15,15 @@ public static Specification isOrigin(String origin) { origin.equals("@") ? "" : origin); } + public static Specification isAnyOrigin(List origins) { + if (origins == null || origins.isEmpty()) return null; + for (var o : origins) if (o.equals("@*")) return any(); + if (origins.size() == 1) return isOrigin(origins.get(0)); + return (root, query, cb) -> + root.get("origin") + .in(origins); + } + public static Specification any() { return (root, query, cb) -> cb.conjunction(); diff --git a/src/main/java/jasper/security/Auth.java b/src/main/java/jasper/security/Auth.java index 78e3c7fe..c1459fee 100644 --- a/src/main/java/jasper/security/Auth.java +++ b/src/main/java/jasper/security/Auth.java @@ -41,6 +41,7 @@ import java.util.Set; import java.util.stream.Stream; +import static jasper.repository.spec.OriginSpec.isAnyOrigin; import static jasper.repository.spec.OriginSpec.isOrigin; import static jasper.repository.spec.QualifiedTag.originSelector; import static jasper.repository.spec.QualifiedTag.qt; @@ -136,6 +137,7 @@ public class Auth { protected Client client; protected Optional user; protected List publicTags; + protected List tenantAccessOrigins; protected List readAccess; protected List writeAccess; protected List tagReadAccess; @@ -586,7 +588,9 @@ public Specification tagReadSpec() { if (isLoggedIn()) { spec = spec.or(getUserTag().spec()); } - return spec.or(isAnyQualifiedTag(getTagReadAccess())); + return spec + .or(Specification.where(isAnyOrigin(getTenantAccessOrigins())).and(notPrivateTag())) + .or(isAnyQualifiedTag(getTagReadAccess())); } protected boolean tagWriteAccessCaptures(String tag) { @@ -721,8 +725,7 @@ public List getPublicTags() { if (publicTags == null) { if (props.isMultiTenant()) { publicTags = new ArrayList<>(List.of(qt("public" + getOrigin()))); - if (getClient().getTenantAccess() == null) return publicTags; - for (var t : getClient().getTenantAccess()) { + for (var t : getTenantAccessOrigins()) { publicTags.add(qt("public" + t)); } } else { @@ -732,6 +735,22 @@ public List getPublicTags() { return publicTags; } + public List getTenantAccessOrigins() { + if (tenantAccessOrigins == null) { + if (props.isMultiTenant()) { + tenantAccessOrigins = new ArrayList<>(List.of(getOrigin())); + if (getClient().getTenantAccess() == null) return tenantAccessOrigins; + for (var t : getClient().getTenantAccess()) { + if (isBlank(t) || t.equals("@") || t.equals("default")) t = ""; + tenantAccessOrigins.add(t); + } + } else { + tenantAccessOrigins = List.of("@*"); + } + } + return tenantAccessOrigins; + } + protected String getMultiTenantOrigin() { return props.isMultiTenant() ? getOrigin() : "@*"; }