diff --git a/Application/EdFi.Ods.Api/Security/Authorization/Repositories/AggregateRootQueryBuilderProviderAuthorizationDecorator.cs b/Application/EdFi.Ods.Api/Security/Authorization/Repositories/AggregateRootQueryBuilderProviderAuthorizationDecorator.cs index d177ee310..c5ba5fa3c 100644 --- a/Application/EdFi.Ods.Api/Security/Authorization/Repositories/AggregateRootQueryBuilderProviderAuthorizationDecorator.cs +++ b/Application/EdFi.Ods.Api/Security/Authorization/Repositories/AggregateRootQueryBuilderProviderAuthorizationDecorator.cs @@ -215,6 +215,7 @@ bool TryApplyFilters( filterDefinition.CriteriaApplicator( queryBuilder, conjunctionQueryBuilder, + authorizationPlan.RequestContext.Resource, filterContext.SubjectEndpointNames, parameterValues, joinType, diff --git a/Application/EdFi.Ods.Api/Security/AuthorizationStrategies/NamespaceBased/NamespaceBasedAuthorizationFilterDefinitionsFactory.cs b/Application/EdFi.Ods.Api/Security/AuthorizationStrategies/NamespaceBased/NamespaceBasedAuthorizationFilterDefinitionsFactory.cs index a4ade76d5..76c2aa143 100644 --- a/Application/EdFi.Ods.Api/Security/AuthorizationStrategies/NamespaceBased/NamespaceBasedAuthorizationFilterDefinitionsFactory.cs +++ b/Application/EdFi.Ods.Api/Security/AuthorizationStrategies/NamespaceBased/NamespaceBasedAuthorizationFilterDefinitionsFactory.cs @@ -15,6 +15,7 @@ using EdFi.Ods.Common.Infrastructure.Filtering; using EdFi.Ods.Common.Models; using EdFi.Ods.Common.Models.Resource; +using EdFi.Ods.Common.Providers.Queries; using EdFi.Ods.Common.Security.Authorization; using EdFi.Ods.Common.Security.Claims; @@ -65,6 +66,7 @@ public IReadOnlyList CreatePredefinedAuthorizatio private static void ApplyAuthorizationCriteria( QueryBuilder queryBuilder, QueryBuilder whereBuilder, + Resource resource, string[] subjectEndpointNames, IDictionary parameters, JoinType joinType, @@ -87,14 +89,16 @@ private static void ApplyAuthorizationCriteria( // Ensure the Namespace parameter is represented as an object array var namespacePrefixes = parameterValue as object[] ?? [parameterValue]; + var alias = resource.Entity.RootTableAlias(); + // Add the final namespaces criteria to the supplied WHERE clause (junction) - whereBuilder.WhereNotNull(subjectEndpointName) + whereBuilder.WhereNotNull($"{alias}.{subjectEndpointName}") .Where( qb => { foreach (var namespacePrefix in namespacePrefixes) { - qb.OrWhereLike(subjectEndpointName, namespacePrefix, MatchMode.Start); + qb.OrWhereLike($"{alias}.{subjectEndpointName}", namespacePrefix, MatchMode.Start); } return qb; diff --git a/Application/EdFi.Ods.Api/Security/AuthorizationStrategies/OwnershipBased/OwnershipBasedAuthorizationFilterDefinitionsFactory.cs b/Application/EdFi.Ods.Api/Security/AuthorizationStrategies/OwnershipBased/OwnershipBasedAuthorizationFilterDefinitionsFactory.cs index 0664bc723..8f30471fe 100644 --- a/Application/EdFi.Ods.Api/Security/AuthorizationStrategies/OwnershipBased/OwnershipBasedAuthorizationFilterDefinitionsFactory.cs +++ b/Application/EdFi.Ods.Api/Security/AuthorizationStrategies/OwnershipBased/OwnershipBasedAuthorizationFilterDefinitionsFactory.cs @@ -49,6 +49,7 @@ public IReadOnlyList CreatePredefinedAuthorizatio private static void ApplyAuthorizationCriteria( QueryBuilder queryBuilder, QueryBuilder whereQueryBuilder, + Resource resource, string[] subjectEndpointNames, IDictionary parameters, JoinType joinType, diff --git a/Application/EdFi.Ods.Api/Security/AuthorizationStrategies/Relationships/Filters/ViewBasedAuthorizationFilterDefinition.cs b/Application/EdFi.Ods.Api/Security/AuthorizationStrategies/Relationships/Filters/ViewBasedAuthorizationFilterDefinition.cs index be3ae80f3..b60fe0c65 100644 --- a/Application/EdFi.Ods.Api/Security/AuthorizationStrategies/Relationships/Filters/ViewBasedAuthorizationFilterDefinition.cs +++ b/Application/EdFi.Ods.Api/Security/AuthorizationStrategies/Relationships/Filters/ViewBasedAuthorizationFilterDefinition.cs @@ -44,7 +44,7 @@ public ViewBasedAuthorizationFilterDefinition( SELECT {{newAlias1}}.{viewTargetEndpointName} FROM {GetFullNameForView($"auth_{viewName}")} {{newAlias1}} WHERE {{newAlias1}}.{viewSourceEndpointName} IN (:{RelationshipAuthorizationConventions.ClaimsParameterName}))", - (queryBuilder, @where, subjectEndpointNames, parameters, joinType, authorizationStrategy) => + (queryBuilder, @where, resource, subjectEndpointNames, parameters, joinType, authorizationStrategy) => { if (subjectEndpointNames?.Length != 1) { @@ -89,7 +89,7 @@ public ViewBasedAuthorizationFilterDefinition( : base( filterName, null, // HQL condition (not supported by view-based authorization) - (criteria, @where, subjectEndpointNames, parameters, joinType, authorizationStrategy) + (criteria, @where, resource, subjectEndpointNames, parameters, joinType, authorizationStrategy) => criteria.ApplyCustomViewJoinFilter( viewName, subjectEndpointNames, diff --git a/Application/EdFi.Ods.Common/Infrastructure/Filtering/AuthorizationFilterDefinition.cs b/Application/EdFi.Ods.Common/Infrastructure/Filtering/AuthorizationFilterDefinition.cs index 8b410a47a..3e35342d8 100644 --- a/Application/EdFi.Ods.Common/Infrastructure/Filtering/AuthorizationFilterDefinition.cs +++ b/Application/EdFi.Ods.Common/Infrastructure/Filtering/AuthorizationFilterDefinition.cs @@ -37,7 +37,7 @@ public class AuthorizationFilterDefinition public AuthorizationFilterDefinition( string filterName, string friendlyHqlConditionFormat, - Action, JoinType, IAuthorizationStrategy> criteriaApplicator, + Action, JoinType, IAuthorizationStrategy> criteriaApplicator, Action trackedChangesCriteriaApplicator, Func authorizeInstance) { @@ -58,7 +58,7 @@ public AuthorizationFilterDefinition( /// /// Gets the function for applying the filter using NHibernate's API. /// - public Action, JoinType, IAuthorizationStrategy> CriteriaApplicator { get; protected set; } + public Action, JoinType, IAuthorizationStrategy> CriteriaApplicator { get; protected set; } /// /// Gets the function for applying the filter to the for tracked changes queries. diff --git a/Application/EdFi.Ods.Common/Providers/Queries/EntityExtensions.cs b/Application/EdFi.Ods.Common/Providers/Queries/EntityExtensions.cs new file mode 100644 index 000000000..577c022e5 --- /dev/null +++ b/Application/EdFi.Ods.Common/Providers/Queries/EntityExtensions.cs @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: Apache-2.0 +// Licensed to the Ed-Fi Alliance under one or more agreements. +// The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0. +// See the LICENSE and NOTICES files in the project root for more information. + +using EdFi.Ods.Common.Models.Domain; + +namespace EdFi.Ods.Common.Providers.Queries; + +public static class EntityExtensions +{ + private const string _baseAlias = "b"; + private const string _standardAlias = "r"; + + public static string RootTableAlias(this Entity aggregateRootEntity) + { + return aggregateRootEntity.IsDerived ? _baseAlias : _standardAlias; + } +}