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

[ODS-6615] API only allows tenant1's profiles when different profiles are set up for different tenants #1214

Merged
merged 6 commits into from
Jan 30, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/Cleanup Caches by a branch.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
name: Cleanup Caches by a branch
on:
pull_request:
branches: [main, 'ODS-*',b-v*-patch*]
branches: [main, b-v*-patch*]
types: [ closed ]

env:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Lib EdFi.Admin.DataAccess Pull request build and test

on:
pull_request:
branches: [main, 'ODS-*',b-v*-patch*]
branches: [main, b-v*-patch*]

env:
INFORMATIONAL_VERSION: "7.1"
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/Lib edFi.common pullrequest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Lib EdFi.Common Pull request build and test

on:
pull_request:
branches: [main, 'ODS-*',b-v*-patch*]
branches: [main, b-v*-patch*]

env:
INFORMATIONAL_VERSION: "7.1"
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/Lib edFi.loadtools pullrequest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Lib EdFi.LoadTools Pull request build and test

on:
pull_request:
branches: [main, 'ODS-*',b-v*-patch*]
branches: [main, b-v*-patch*]

env:
INFORMATIONAL_VERSION: "7.1"
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/Lib edFi.ods.api pullrequest .yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Lib EdFi.Ods.Api Pull request build and test

on:
pull_request:
branches: [main, 'ODS-*',b-v*-patch*]
branches: [main, b-v*-patch*]

env:
INFORMATIONAL_VERSION: "7.1"
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/Lib edFi.ods.common pullrequest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Lib EdFi.Ods.Common Pull request build and test

on:
pull_request:
branches: [main, 'ODS-*',b-v*-patch*]
branches: [main, b-v*-patch*]

env:
INFORMATIONAL_VERSION: "7.1"
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/Lib edFi.ods.standard pullrequest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Lib EdFi.Ods.Standard Pull request build and test

on:
pull_request:
branches: [main, 'ODS-*',b-v*-patch*]
branches: [main, b-v*-patch*]

env:
INFORMATIONAL_VERSION: "7.1"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Lib EdFi.Security.DataAccess Pull request build and test

on:
pull_request:
branches: [main, 'ODS-*',b-v*-patch*]
branches: [main, b-v*-patch*]

env:
INFORMATIONAL_VERSION: "7.1"
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/Pkg EdFi.Database.Admin.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ name: Pkg EdFi.Database.Admin
on:
push:
branches:
[main, 'ODS-*',b-v*-patch*]
[main, b-v*-patch*]
paths:
- '**.sql'
workflow_dispatch:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/Pkg EdFi.Database.Security.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ name: Pkg EdFi.Database.Security
on:
push:
branches:
[main, 'ODS-*',b-v*-patch*]
[main, b-v*-patch*]
paths:
- '**.sql'
workflow_dispatch:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/Pkg EdFi.Ods.CodeGen.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ name: Pkg EdFi.Ods.CodeGen

on:
pull_request:
branches: [main, 'ODS-*',b-v*-patch*]
branches: [main, b-v*-patch*]
push:
branches:
[main, 'ODS-*',b-v*-patch*]
[main, b-v*-patch*]
workflow_dispatch:
inputs:
distinct_id:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ name: Pkg EdFi.Ods.Minimal.Template.PostgreSQL
on:
push:
branches:
[main, 'ODS-*',b-v*-patch*]
[main, b-v*-patch*]
workflow_dispatch:
inputs:
distinct_id:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ name: Pkg EdFi.Ods.Minimal.Template.TPDM.PostgreSQL
on:
push:
branches:
[main, 'ODS-*',b-v*-patch*]
[main, b-v*-patch*]
workflow_dispatch:
inputs:
distinct_id:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/Pkg EdFi.Ods.Minimal.Template.TPDM.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ name: Pkg EdFi.Ods.Minimal.Template.TPDM
on:
push:
branches:
[main, 'ODS-*',b-v*-patch*]
[main, b-v*-patch*]
workflow_dispatch:
inputs:
distinct_id:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/Pkg EdFi.Ods.Minimal.Template.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ name: Pkg EdFi.Ods.Minimal.Template
on:
push:
branches:
[main, 'ODS-*',b-v*-patch*]
[main, b-v*-patch*]
workflow_dispatch:
inputs:
distinct_id:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ name: Pkg EdFi.Ods.Populated.Template.PostgreSQL
on:
push:
branches:
[main, 'ODS-*',b-v*-patch*]
[main, b-v*-patch*]
workflow_dispatch:
inputs:
distinct_id:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ name: Pkg EdFi.Ods.Populated.Template.TPDM.PostgreSQL
on:
push:
branches:
[main, 'ODS-*',b-v*-patch*]
[main, b-v*-patch*]
workflow_dispatch:
inputs:
distinct_id:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ name: Pkg EdFi.Ods.Populated.Template.TPDM
on:
push:
branches:
[main, 'ODS-*',b-v*-patch*]
[main, b-v*-patch*]
workflow_dispatch:
inputs:
distinct_id:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/Pkg EdFi.Ods.Populated.Template.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ name: Pkg EdFi.Ods.Populated.Template
on:
push:
branches:
[main, 'ODS-*',b-v*-patch*]
[main, b-v*-patch*]
workflow_dispatch:
inputs:
distinct_id:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Trgr InitDev workflows in Implementation repo

on:
pull_request:
branches: [main, 'ODS-*',b-v*-patch*]
branches: [main, b-v*-patch*]
workflow_dispatch:

env:
Expand Down
2 changes: 1 addition & 1 deletion Application/EdFi.Ods.Api/Jobs/DeleteExpiredTokensJob.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
using System.Threading.Tasks;
using EdFi.Admin.DataAccess.Authentication;
using EdFi.Common;
using EdFi.Ods.Api.Middleware;
using EdFi.Ods.Common.Configuration;
using EdFi.Ods.Common.Context;
using log4net;
using Quartz;
Expand Down
1 change: 1 addition & 0 deletions Application/EdFi.Ods.Api/Jobs/TenantSpecificJobBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using EdFi.Ods.Api.Middleware;
using EdFi.Ods.Common.Configuration;
using EdFi.Ods.Common.Context;
using log4net;
using Quartz;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Collections.Generic;
using Autofac.Extras.DynamicProxy;
using Castle.DynamicProxy;
using EdFi.Ods.Common.Configuration;

namespace EdFi.Ods.Api.Middleware;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
// See the LICENSE and NOTICES files in the project root for more information.

using System.Threading.Tasks;
using EdFi.Ods.Api.Extensions;
using EdFi.Ods.Common.Configuration;
using EdFi.Ods.Common.Context;
using log4net;
using Microsoft.AspNetCore.Http;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using System.Linq;
using System.Reflection;
using EdFi.Ods.Common;
using EdFi.Ods.Common.Configuration;
using EdFi.Ods.Common.Context;
using EdFi.Ods.Common.Models;
using EdFi.Ods.Common.Models.Domain;
Expand Down Expand Up @@ -37,6 +38,7 @@ public class ProfilesAwareContractResolver : DefaultContractResolver
private readonly ConcurrentDictionary<Type, FullName> _fullNameByType = new();
private readonly IContextProvider<ProfileContentTypeContext> _profileContentTypeContextProvider;

private readonly IContextProvider<TenantConfiguration> _tenantConfigurationContextProvider;
private readonly IProfileResourceModelProvider _profileResourceModelProvider;
private readonly string _resourcesNamespacePrefix = $"{Namespaces.Resources.BaseNamespace}.";
private readonly ISchemaNameMapProvider _schemaNameMapProvider;
Expand All @@ -46,6 +48,7 @@ public class ProfilesAwareContractResolver : DefaultContractResolver
public ProfilesAwareContractResolver(
IContextProvider<ProfileContentTypeContext> profileContentTypeContextProvider,
IContextProvider<DataManagementResourceContext> dataManagementResourceContextProvider,
IContextProvider<TenantConfiguration> tenantConfigurationContextProvider,
IProfileResourceModelProvider profileResourceModelProvider,
ISchemaNameMapProvider schemaNameMapProvider)
{
Expand All @@ -55,6 +58,8 @@ public ProfilesAwareContractResolver(
_profileResourceModelProvider = profileResourceModelProvider
?? throw new ArgumentNullException(nameof(profileResourceModelProvider));

_tenantConfigurationContextProvider = tenantConfigurationContextProvider;

_schemaNameMapProvider = schemaNameMapProvider ?? throw new ArgumentNullException(nameof(schemaNameMapProvider));

_profileContentTypeContextProvider = profileContentTypeContextProvider
Expand All @@ -79,11 +84,14 @@ public override JsonContract ResolveContract(Type type)

var resourceClassFullName = GetFullNameFromResourceTypeNamespace(type);

var tenantName = _tenantConfigurationContextProvider?.Get()?.TenantIdentifier;

var mappingContractKey = new MappingContractKey(
resourceClassFullName,
profileContentTypeContext.ProfileName,
_dataManagementResourceContextProvider.Get().Resource.FullName,
profileContentTypeContext.ContentTypeUsage);
profileContentTypeContext.ContentTypeUsage,
tenantName);

var contract = _contractByKey.GetOrAdd(mappingContractKey,
static (k, args) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
using EdFi.Ods.Common.Extensions;
using Standart.Hash.xxHash;

namespace EdFi.Ods.Api.Middleware;
namespace EdFi.Ods.Common.Configuration;

/// <summary>
/// Contains details related to the tenant configuration and associated database connection strings.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,23 @@ private XDocument[] LazyInitializeXDocuments()

private IDictionary<string, XElement> LazyInitializeProfileDefinitions()
{
return _allDocs.Value.SelectMany(x => x.Descendants("Profile"))
var profileDefinitions = _allDocs.Value.SelectMany(x => x.Descendants("Profile")).ToArray();

var profilesWithDuplicateDefinitions = profileDefinitions
.GroupBy(x => x.AttributeValue("name"), StringComparer.OrdinalIgnoreCase)
.Where(x => x.Count() > 1)
.SelectMany(x => profileDefinitions.Where(y => y.AttributeValue("name").Equals(x.Key, StringComparison.OrdinalIgnoreCase)))
.ToArray();

if (profilesWithDuplicateDefinitions.Any())
{
var duplicateProfileNames = string.Join(", ", profilesWithDuplicateDefinitions.Select(x => x.AttributeValue("name")).Distinct(StringComparer.OrdinalIgnoreCase));

_logger.Error(
$"The following profile names were not loaded from plugin assemblies because multiple XML definitions were provided through embedded resources: {duplicateProfileNames}");
}

return profileDefinitions.Except(profilesWithDuplicateDefinitions)
.ToDictionary(x => x.AttributeValue("name"), x => x, StringComparer.InvariantCultureIgnoreCase);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public interface IProfileMetadataProvider
/// <summary>
/// Collection of valid profile definitions, organized by name.
/// </summary>
IReadOnlyDictionary<string, XElement> ProfileDefinitionsByName { get; }
IReadOnlyDictionary<string, XElement> GetProfileDefinitionsByName();

/// <summary>
/// Gets the validation results for all profile metadata that has been loaded (or attempted to be loaded).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,27 @@ public ProfileMetadataProvider(IProfileDefinitionsProvider[] profileDefinitionsP
/// <summary>
/// Collection of valid profile definitions, organized by name.
/// </summary>
public IReadOnlyDictionary<string, XElement> ProfileDefinitionsByName =>
_profileDefinitionsProviders.SelectMany(x => x.GetProfileDefinitions()).ToDictionary(x => x.Key, x => x.Value, StringComparer.OrdinalIgnoreCase);
public IReadOnlyDictionary<string, XElement> GetProfileDefinitionsByName()
{
var profileDefinitions = _profileDefinitionsProviders.SelectMany(x => x.GetProfileDefinitions()).ToArray();

var profilesWithDuplicateDefinitions = profileDefinitions
.GroupBy(x => x.Key, StringComparer.OrdinalIgnoreCase)
.Where(x => x.Count() > 1)
.SelectMany(x => profileDefinitions.Where(y => y.Key.Equals(x.Key, StringComparison.OrdinalIgnoreCase)))
.ToArray();

if (profilesWithDuplicateDefinitions.Any())
{
var duplicateProfileNames = string.Join(", ", profilesWithDuplicateDefinitions.Select(x => x.Key).Distinct(StringComparer.OrdinalIgnoreCase));

_logger.Error(
$"The following profile names were not loaded because multiple XML definitions were provided: {duplicateProfileNames}");
}

return profileDefinitions.Except(profilesWithDuplicateDefinitions).ToDictionary(
x => x.Key, x => x.Value, StringComparer.OrdinalIgnoreCase);
}

/// <inheritdoc cref="IProfileMetadataProvider.GetValidationResults" />
public MetadataValidationResult[] GetValidationResults()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,24 +52,6 @@ public ValidationResult Validate(XDocument profilesDefinition)
{
return new ValidationResult(validationFailures);
}

// Find duplicate profiles names
var duplicateProfileNames = profilesDefinition.XPathSelectElements("//Profile")
.Select(e => e.AttributeValue("name"))
.GroupBy(n => n, n => n)
.Where(x => x.Count() > 1)
.Select(x => x.Key)
.OrderBy(n => n)
.ToArray();

if (duplicateProfileNames.Any())
{
validationFailures.Add(new ValidationFailure(
string.Empty,
$"Duplicate profile name(s) encountered: '{string.Join("', '", duplicateProfileNames)}'"));

return new ValidationResult(validationFailures);
}

// Resource model validation
var resourceModel = _resourceModelProvider.GetResourceModel();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public List<ProfileAndResourceNames> GetProfileResourceNames()
_logger.Debug("Initializing Profile and resource names...");
}

return _profileMetadataProvider.ProfileDefinitionsByName.Values.SelectMany(CreateNameTuples).ToList();
return _profileMetadataProvider.GetProfileDefinitionsByName().Values.SelectMany(CreateNameTuples).ToList();

IEnumerable<ProfileAndResourceNames> CreateNameTuples(XElement profileElt)
{
Expand Down
Loading
Loading