Skip to content

Commit

Permalink
Merge pull request #476 from Strongminds/release/11.4.2
Browse files Browse the repository at this point in the history
Release/11.4.2
  • Loading branch information
mrjsawdk authored Feb 14, 2023
2 parents 396f765 + 3da91d6 commit 3f40bcf
Show file tree
Hide file tree
Showing 286 changed files with 5,311 additions and 1,426 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
using System;
using Core.Abstractions.Types;


namespace Infrastructure.Services.Caching
namespace Core.Abstractions.Caching
{
public interface IObjectCache
{
Expand Down
2 changes: 2 additions & 0 deletions Core.Abstractions/Core.Abstractions.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Caching\IObjectCache.cs" />
<Compile Include="Exceptions\OperationErrorException.cs" />
<Compile Include="Extensions\DictionaryExtensions.cs" />
<Compile Include="Extensions\EnumerableExtensions.cs" />
Expand All @@ -51,6 +52,7 @@
<Compile Include="Extensions\ResultExtensions.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Types\DetailedOperationError.cs" />
<Compile Include="Types\EnumMap.cs" />
<Compile Include="Types\Factory.cs" />
<Compile Include="Types\Maybe.cs" />
<Compile Include="Types\OperationError.cs" />
Expand Down
23 changes: 23 additions & 0 deletions Core.Abstractions/Extensions/EnumerableExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Core.Abstractions.Types;

namespace Core.Abstractions.Extensions
{
Expand Down Expand Up @@ -85,5 +86,27 @@ public static void MirrorTo<T, TIdentity>(this IEnumerable<T> newState, ICollect
.ComputeDelta(newState, withIdentity)
.ApplyTo(existingState);
}

/// <summary>
/// Equivalent to FirstOrDefault but for clients using the <see cref="Maybe{T}"/>
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="src"></param>
/// <param name="predicate"></param>
/// <returns></returns>
public static Maybe<T> FirstOrNone<T>(this IEnumerable<T> src, Func<T, bool> predicate = null)
{
var condition = predicate ?? (_ => true);

//This works better than firstOrDefault since this works for both reference and value types
foreach (var item in src)
{
if (condition(item))
{
return item;
}
}
return Maybe<T>.None;
}
}
}
40 changes: 40 additions & 0 deletions Core.Abstractions/Types/EnumMap.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Core.Abstractions.Extensions;

namespace Core.Abstractions.Types
{
public class EnumMap<TLeft, TRight>
where TLeft : Enum
where TRight : Enum
{
private readonly IReadOnlyDictionary<TLeft, TRight> _leftToRightMap;
private readonly IReadOnlyDictionary<TRight, TLeft> _rightToLeftMap;

public EnumMap(params (TLeft left, TRight right)[] mappings)
{
_leftToRightMap = mappings
.ToDictionary(x => x.left, x => x.right)
.AsReadOnly();

_rightToLeftMap = _leftToRightMap
.ToDictionary(kvp => kvp.Value, kvp => kvp.Key)
.AsReadOnly();
}

public TRight FromLeftToRight(TLeft value)
{
return _leftToRightMap.TryGetValue(value, out var result)
? result
: throw new ArgumentException($@"Unmapped 'Left'->'Right':{value:G}", nameof(value));
}

public TLeft FromRightToLeft(TRight value)
{
return _rightToLeftMap.TryGetValue(value, out var result)
? result
: throw new ArgumentException($@"Unmapped 'Right'->'Left' value:{value:G}", nameof(value));
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using System;
using Infrastructure.Services.Caching;
using Core.Abstractions.Caching;

namespace Core.ApplicationServices.Authorization
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using Core.Abstractions.Types;
using Core.DomainModel;

namespace Core.ApplicationServices.Authorization
{
public class ResourcePermissionsResult
{
private static readonly ResourcePermissionsResult Empty = new(false, false, false);

public bool Read { get; }
public bool Modify { get; }
public bool Delete { get; }

public ResourcePermissionsResult(bool read, bool modify, bool delete)
{
Read = read;
Modify = modify;
Delete = delete;
}

public static Result<ResourcePermissionsResult, OperationError> FromResolutionResult<T>(
Result<T, OperationError> getEntityResult,
IAuthorizationContext authorizationContext) where T : IEntity
{
return getEntityResult
.Select(entity => new ResourcePermissionsResult(true, authorizationContext.AllowModify(entity), authorizationContext.AllowDelete(entity)))
.Match<Result<ResourcePermissionsResult, OperationError>>
(
result => result,
error => error.FailureType == OperationFailure.Forbidden ? Empty : error
);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ private Maybe<OperationError> UpdateNoticePeriodMonthsUuid(ItContract contract,
private Maybe<OperationError> UpdateExternalReferences(ItContract contract, IEnumerable<UpdatedExternalReferenceProperties> externalReferences)
{
return _referenceService
.BatchUpdateExternalReferences(
.UpdateExternalReferences(
ReferenceRootType.Contract,
contract.Id,
externalReferences.ToList())
Expand Down Expand Up @@ -400,7 +400,7 @@ private Maybe<OperationError> UpdateSystemAssignments(ItContract contract, IEnum
"system usage",
contract,
systemUsageUuids.FromNullable(),
(systemUsageUuid) => _usageService.GetByUuid(systemUsageUuid),
(systemUsageUuid) => _usageService.GetReadableItSystemUsageByUuid(systemUsageUuid),
itContract => itContract.AssociatedSystemUsages.Select(x => x.ItSystemUsage).ToList(),
(itContract, usage) => itContract.AssignSystemUsage(usage),
(itContract, usage) => itContract.RemoveSystemUsage(usage)
Expand Down
5 changes: 5 additions & 0 deletions Core.ApplicationServices/Core.ApplicationServices.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@
<Compile Include="Authorization\Permissions\DefineOrganizationTypePermission.cs" />
<Compile Include="Authorization\Permissions\SystemUsageMigrationPermission.cs" />
<Compile Include="Authorization\Permissions\VisibilityControlPermission.cs" />
<Compile Include="Authorization\ResourcePermissionsResult.cs" />
<Compile Include="Authorization\UnauthenticatedAuthorizationContext.cs" />
<Compile Include="Authorization\UnauthenticatedUserContext.cs" />
<Compile Include="Authorization\UserContextFactory.cs" />
Expand Down Expand Up @@ -131,6 +132,8 @@
<Compile Include="Helpers\NamedEntityMappingHelper.cs" />
<Compile Include="IAdviceService.cs" />
<Compile Include="IUserService.cs" />
<Compile Include="Messages\IPublicMessagesService.cs" />
<Compile Include="Messages\PublicMessagesService.cs" />
<Compile Include="Model\Contracts\ContractOptions.cs" />
<Compile Include="Model\Contracts\Write\ItContractAgreementPeriodModificationParameters.cs" />
<Compile Include="Model\Contracts\Write\ItContractGeneralDataModificationParameters.cs" />
Expand All @@ -150,6 +153,8 @@
<Compile Include="Model\GDPR\Write\UpdatedDataProcessingRegistrationOversightDataParameters.cs" />
<Compile Include="Model\GDPR\Write\UpdatedDataProcessingRegistrationOversightDate.cs" />
<Compile Include="Model\GDPR\Write\UpdatedDataProcessingRegistrationRoles.cs" />
<Compile Include="Model\Messages\WritePublicMessagesParams.cs" />
<Compile Include="Model\Messages\PublicMessages.cs" />
<Compile Include="Model\Notification\GlobalAdminNotification.cs" />
<Compile Include="Model\Notification\GlobalAdminNotificationMessage.cs" />
<Compile Include="Model\Organizations\OrganizationUnitRegistrationChangeParameters.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,26 @@ public static IEnumerable<StsOrganizationConsequenceLog> ConvertConsequencesToCo
logs.AddRange(MapMovedOrganizationUnits(consequences));
logs.AddRange(MapRemovedOrganizationUnits(consequences));
logs.AddRange(MapConvertedOrganizationUnits(consequences));
logs.AddRange(MapRootChange(consequences));

return logs;
}

private static IEnumerable<StsOrganizationConsequenceLog> MapRootChange(OrganizationTreeUpdateConsequences consequences)
{
var rootChangeEntry = consequences.RootChange.Select(rootChange => new StsOrganizationConsequenceLog
{
Name = rootChange.CurrentRoot.Name,
Type = ConnectionUpdateOrganizationUnitChangeType.RootChanged,
ExternalUnitUuid = rootChange.CurrentRoot.ExternalOriginUuid.GetValueOrDefault(),
Description = $"Organisationsroden ændres fra '{rootChange.CurrentRoot.Name}' til '{rootChange.NewRoot.Name}'"
});
if (rootChangeEntry.HasValue)
{
yield return rootChangeEntry.Value;
}
}

private static IEnumerable<StsOrganizationConsequenceLog> MapConvertedOrganizationUnits(OrganizationTreeUpdateConsequences consequences)
{
return consequences
Expand Down Expand Up @@ -80,12 +96,28 @@ private static IEnumerable<StsOrganizationConsequenceLog> MapMovedOrganizationUn
.Select(moved =>
{
var (movedUnit, oldParent, newParent) = moved;
string description;
if (newParent == null)
{
description = $"'{movedUnit.Name}' flyttes fra at være underenhed til '{oldParent.Name}' til at være organisationsroden";
}
else if (oldParent == null)
{
description = $"'{movedUnit.Name}' flyttes til fremover at være underenhed for {newParent.Name}";
}
else
{
description = $"'{movedUnit.Name}' flyttes fra at være underenhed til '{oldParent.Name}' til fremover at være underenhed for {newParent.Name}";
}
return new StsOrganizationConsequenceLog
{
Name = movedUnit.Name,
Type = ConnectionUpdateOrganizationUnitChangeType.Moved,
ExternalUnitUuid = movedUnit.ExternalOriginUuid.GetValueOrDefault(),
Description = $"'{movedUnit.Name}' flyttes fra at være underenhed til '{oldParent.Name}' til fremover at være underenhed for {newParent.Name}"
Description = description
};
})
.ToList();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ private Result<DataProcessingRegistration, OperationError> PerformUpdates(DataPr

private Result<DataProcessingRegistration, OperationError> PerformReferencesUpdate(DataProcessingRegistration dpr, IEnumerable<UpdatedExternalReferenceProperties> externalReferences)
{
var updateResult = _referenceService.BatchUpdateExternalReferences(
var updateResult = _referenceService.UpdateExternalReferences(
ReferenceRootType.DataProcessingRegistration,
dpr.Id,
externalReferences.ToList());
Expand All @@ -153,7 +153,7 @@ private Result<DataProcessingRegistration, OperationError> UpdateRoles(DataProce
return new OperationError($"Duplicates of 'User Role Pairs' are not allowed", OperationFailure.BadInput);
}

var existingRightsList = dpr.Rights.Select(x => new UserRolePair { RoleUuid = x.Role.Uuid, UserUuid = x.User.Uuid }).ToList();
var existingRightsList = dpr.Rights.Select(x => new UserRolePair(x.User.Uuid,x.Role.Uuid)).ToList();

foreach (var (delta, item) in existingRightsList.ComputeDelta(newRightsList, x => x))
{
Expand Down
13 changes: 13 additions & 0 deletions Core.ApplicationServices/Messages/IPublicMessagesService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using Core.Abstractions.Types;
using Core.ApplicationServices.Authorization;
using Core.ApplicationServices.Model.Messages;

namespace Core.ApplicationServices.Messages
{
public interface IPublicMessagesService
{
ResourcePermissionsResult GetPermissions();
PublicMessages Read();
Result<PublicMessages, OperationError> Write(WritePublicMessagesParams parameters);
}
}
100 changes: 100 additions & 0 deletions Core.ApplicationServices/Messages/PublicMessagesService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
using System.Collections.Generic;
using System.Linq;
using Core.Abstractions.Types;
using Core.ApplicationServices.Authorization;
using Core.ApplicationServices.Model.Messages;
using Core.ApplicationServices.Model.Shared;
using Core.DomainModel;
using Core.DomainServices;
using Serilog;

namespace Core.ApplicationServices.Messages
{
public class PublicMessagesService : IPublicMessagesService
{
private readonly IGenericRepository<Text> _repository;
private readonly IOrganizationalUserContext _organizationalUserContext;
private readonly ILogger _logger;

public PublicMessagesService(
IGenericRepository<Text> repository,
IOrganizationalUserContext organizationalUserContext,
ILogger logger)
{
_repository = repository;
_organizationalUserContext = organizationalUserContext;
_logger = logger;
}

public ResourcePermissionsResult GetPermissions()
{
var allowModify = _organizationalUserContext.IsGlobalAdmin();
return new ResourcePermissionsResult(true, allowModify, false);
}

public PublicMessages Read()
{
var texts = GetTextsLookup();
return MapPublicMessages(texts);
}

private PublicMessages MapPublicMessages(IReadOnlyDictionary<int, Text> texts)
{
return new PublicMessages(
MapText(texts, Text.SectionIds.About),
MapText(texts, Text.SectionIds.Guides),
MapText(texts, Text.SectionIds.StatusMessages),
MapText(texts, Text.SectionIds.Misc),
MapText(texts, Text.SectionIds.ContactInfo)
);
}

public Result<PublicMessages, OperationError> Write(WritePublicMessagesParams parameters)
{
if (!GetPermissions().Modify)
{
return new OperationError(OperationFailure.Forbidden);
}
var texts = GetTextsLookup();
WriteChange(parameters.About, Text.SectionIds.About, texts);
WriteChange(parameters.ContactInfo, Text.SectionIds.ContactInfo, texts);
WriteChange(parameters.Guides, Text.SectionIds.Guides, texts);
WriteChange(parameters.Misc, Text.SectionIds.Misc, texts);
WriteChange(parameters.StatusMessages, Text.SectionIds.StatusMessages, texts);
_repository.Save();

return MapPublicMessages(texts);
}

private void WriteChange(OptionalValueChange<string> change, int textId, Dictionary<int, Text> texts)
{
if (change.HasChange)
{
if (texts.TryGetValue(textId, out var text))
{
text.Value = change.NewValue;
}
else
{
_logger.Error("Missing text id for the front page {textId}. Not able to change unknown text", textId);
}
}
}

private Dictionary<int, Text> GetTextsLookup()
{
return _repository.AsQueryable().ToDictionary(x => x.Id, x => x);
}

private string MapText(IReadOnlyDictionary<int, Text> textMap, int textId)
{
if (textMap.TryGetValue(textId, out var text))
{
return text.Value ?? string.Empty;
}

_logger.Error("Missing text id for the front page {textId}. Returning empty text", textId);
return string.Empty;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using Core.ApplicationServices.Authorization;
using Core.Abstractions.Caching;
using Core.ApplicationServices.Authorization;
using Core.DomainModel.Events;
using Core.DomainModel.Organization.DomainEvents;
using Infrastructure.Services.Caching;

namespace Core.ApplicationServices.Model.EventHandler
{
Expand Down
Loading

0 comments on commit 3f40bcf

Please sign in to comment.