Skip to content

Commit

Permalink
[ODS-6615] API only allows tenant1's profiles when different profiles…
Browse files Browse the repository at this point in the history
… are set up for different tenants (#1214)

Co-authored-by: Matthew Jackson <[email protected]>
  • Loading branch information
semalaiappan and mjaksn authored Jan 30, 2025
1 parent b6c4ad1 commit 81dab0b
Show file tree
Hide file tree
Showing 53 changed files with 1,032 additions and 88 deletions.
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
2 changes: 1 addition & 1 deletion .github/workflows/Pkg EdFi.Ods.Populated.Template.TPDM.yml
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

0 comments on commit 81dab0b

Please sign in to comment.