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

fix(App&Service)! : email notification fix for offerSubscriptions #239

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
30 changes: 30 additions & 0 deletions src/Portal.Backend.sln
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Keycloak.Seeding", "keycloa
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Keycloak.Seeding.Tests", "..\tests\keycloak\Keycloak.Seeding.Tests\Keycloak.Seeding.Tests.csproj", "{A5BEDD89-7280-466E-8D14-EC5E177AAD07}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mailing.Service", "mailing\Mailing.Service\Mailing.Service.csproj", "{6113B579-C995-47F8-9AC1-4CC6EFDDD883}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mailing.Service.Tests", "..\tests\mailing\Mailing.Service.Tests\Mailing.Service.Tests.csproj", "{1EAF34DA-6D16-4F5E-86F4-344185F53942}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -1340,6 +1344,30 @@ Global
{A5BEDD89-7280-466E-8D14-EC5E177AAD07}.Release|x64.Build.0 = Release|Any CPU
{A5BEDD89-7280-466E-8D14-EC5E177AAD07}.Release|x86.ActiveCfg = Release|Any CPU
{A5BEDD89-7280-466E-8D14-EC5E177AAD07}.Release|x86.Build.0 = Release|Any CPU
{6113B579-C995-47F8-9AC1-4CC6EFDDD883}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6113B579-C995-47F8-9AC1-4CC6EFDDD883}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6113B579-C995-47F8-9AC1-4CC6EFDDD883}.Debug|x64.ActiveCfg = Debug|Any CPU
{6113B579-C995-47F8-9AC1-4CC6EFDDD883}.Debug|x64.Build.0 = Debug|Any CPU
{6113B579-C995-47F8-9AC1-4CC6EFDDD883}.Debug|x86.ActiveCfg = Debug|Any CPU
{6113B579-C995-47F8-9AC1-4CC6EFDDD883}.Debug|x86.Build.0 = Debug|Any CPU
{6113B579-C995-47F8-9AC1-4CC6EFDDD883}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6113B579-C995-47F8-9AC1-4CC6EFDDD883}.Release|Any CPU.Build.0 = Release|Any CPU
{6113B579-C995-47F8-9AC1-4CC6EFDDD883}.Release|x64.ActiveCfg = Release|Any CPU
{6113B579-C995-47F8-9AC1-4CC6EFDDD883}.Release|x64.Build.0 = Release|Any CPU
{6113B579-C995-47F8-9AC1-4CC6EFDDD883}.Release|x86.ActiveCfg = Release|Any CPU
{6113B579-C995-47F8-9AC1-4CC6EFDDD883}.Release|x86.Build.0 = Release|Any CPU
{1EAF34DA-6D16-4F5E-86F4-344185F53942}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1EAF34DA-6D16-4F5E-86F4-344185F53942}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1EAF34DA-6D16-4F5E-86F4-344185F53942}.Debug|x64.ActiveCfg = Debug|Any CPU
{1EAF34DA-6D16-4F5E-86F4-344185F53942}.Debug|x64.Build.0 = Debug|Any CPU
{1EAF34DA-6D16-4F5E-86F4-344185F53942}.Debug|x86.ActiveCfg = Debug|Any CPU
{1EAF34DA-6D16-4F5E-86F4-344185F53942}.Debug|x86.Build.0 = Debug|Any CPU
{1EAF34DA-6D16-4F5E-86F4-344185F53942}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1EAF34DA-6D16-4F5E-86F4-344185F53942}.Release|Any CPU.Build.0 = Release|Any CPU
{1EAF34DA-6D16-4F5E-86F4-344185F53942}.Release|x64.ActiveCfg = Release|Any CPU
{1EAF34DA-6D16-4F5E-86F4-344185F53942}.Release|x64.Build.0 = Release|Any CPU
{1EAF34DA-6D16-4F5E-86F4-344185F53942}.Release|x86.ActiveCfg = Release|Any CPU
{1EAF34DA-6D16-4F5E-86F4-344185F53942}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -1348,6 +1376,7 @@ Global
SolutionGuid = {2EB6265F-323A-4BF3-969E-003D64A14B64}
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{1EAF34DA-6D16-4F5E-86F4-344185F53942} = {323C198D-A8C6-4EB0-8B79-72624275E35F}
{A5BEDD89-7280-466E-8D14-EC5E177AAD07} = {323C198D-A8C6-4EB0-8B79-72624275E35F}
{EA9BA26E-83F6-47C4-BA3B-880AF1AD6A82} = {323C198D-A8C6-4EB0-8B79-72624275E35F}
{4B40193E-2C67-4DC4-8EF4-3286DAA01D8B} = {323C198D-A8C6-4EB0-8B79-72624275E35F}
Expand Down Expand Up @@ -1441,5 +1470,6 @@ Global
{47E089E3-E875-4045-9E58-C1223BE899E9} = {23500169-FC01-4D2B-A997-E7FAE2169FC0}
{9D574E57-75A6-4965-AF23-ACE0BB9CD0B3} = {323C198D-A8C6-4EB0-8B79-72624275E35F}
{E1D41A07-F468-4D13-8185-35F127230B17} = {46383371-8252-4598-9350-A97692851408}
{6113B579-C995-47F8-9AC1-4CC6EFDDD883} = {68D43DB1-DFC5-4F15-A2B4-6BA18B875F9E}
EndGlobalSection
EndGlobal
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using Microsoft.Extensions.DependencyInjection;
using Org.Eclipse.TractusX.Portal.Backend.Mailing.Service;

namespace Org.Eclipse.TractusX.Portal.Backend.Mailing.Service.DependencyInjection;

public static class MailingServiceExtensions
{
public static IServiceCollection AddMailingService(this IServiceCollection services)
{
return services
.AddTransient<IRoleBaseMailService, RoleBaseMailService>();
}
}
28 changes: 28 additions & 0 deletions src/mailing/Mailing.Service/IRoleBaseMailService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/********************************************************************************
* Copyright (c) 2021, 2023 BMW Group AG
* Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* SPDX-License-Identifier: Apache-2.0
********************************************************************************/

using Org.Eclipse.TractusX.Portal.Backend.Framework.Models.Configuration;

namespace Org.Eclipse.TractusX.Portal.Backend.Mailing.Service;

public interface IRoleBaseMailService
{
Task RoleBaseSendMail(IEnumerable<UserRoleConfig> receiverRoles, IEnumerable<(string ParameterName, string ParameterValue)> parameters, (string ParameterName, string ParameterValue)? userNameParameter, IEnumerable<string> template, Guid companyId);
}
33 changes: 33 additions & 0 deletions src/mailing/Mailing.Service/Mailing.Service.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<!--
- Copyright (c) 2021, 2023 BMW Group AG
- Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation
-
- See the NOTICE file(s) distributed with this work for additional
- information regarding copyright ownership.
-
- This program and the accompanying materials are made available under the
- terms of the Apache License, Version 2.0 which is available at
- https://www.apache.org/licenses/LICENSE-2.0.
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- License for the specific language governing permissions and limitations
- under the License.
-
- SPDX-License-Identifier: Apache-2.0
-->
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\..\portalbackend\PortalBackend.DBAccess\PortalBackend.DBAccess.csproj" />
<ProjectReference Include="..\..\portalbackend\PortalBackend.PortalEntities\PortalBackend.PortalEntities.csproj" />
<ProjectReference Include="..\..\framework\Framework.Models\Framework.Models.csproj" />
<ProjectReference Include="..\Mailing.SendMail\Mailing.SendMail.csproj" />
</ItemGroup>
<PropertyGroup>
<AssemblyName>Org.Eclipse.TractusX.Portal.Backend.Mailing.Service</AssemblyName>
<TargetFramework>net7.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
</Project>
76 changes: 76 additions & 0 deletions src/mailing/Mailing.Service/RoleBaseMailService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/********************************************************************************
* Copyright (c) 2021, 2023 BMW Group AG
* Copyright (c) 2021, 2023 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Apache License, Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* SPDX-License-Identifier: Apache-2.0
********************************************************************************/

using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling;
using Org.Eclipse.TractusX.Portal.Backend.Framework.Models.Configuration;
using Org.Eclipse.TractusX.Portal.Backend.Mailing.SendMail;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess.Repositories;
using System.Collections.Immutable;

namespace Org.Eclipse.TractusX.Portal.Backend.Mailing.Service;

public class RoleBaseMailService : IRoleBaseMailService
{

private readonly IPortalRepositories _portalRepositories;
private readonly IMailingService _mailingService;

public RoleBaseMailService(IPortalRepositories portalRepositories, IMailingService mailingService)
{
_portalRepositories = portalRepositories;
_mailingService = mailingService;
}
public async Task RoleBaseSendMail(IEnumerable<UserRoleConfig> receiverRoles, IEnumerable<(string ParameterName, string ParameterValue)> parameters, (string ParameterName, string ParameterValue)? userNameParameter, IEnumerable<string> template, Guid companyId)
{
var receiverUserRoles = receiverRoles;
var userRolesRepository = _portalRepositories.GetInstance<IUserRolesRepository>();
var roleData = await userRolesRepository
.GetUserRoleIdsUntrackedAsync(receiverUserRoles)
.ToListAsync()
.ConfigureAwait(false);
if (roleData.Count < receiverUserRoles.Sum(clientRoles => clientRoles.UserRoleNames.Count()))
{
throw new ConfigurationException(
$"invalid configuration, at least one of the configured roles does not exist in the database: {string.Join(", ", receiverUserRoles.Select(clientRoles => $"client: {clientRoles.ClientId}, roles: [{string.Join(", ", clientRoles.UserRoleNames)}]"))}");
}

var companyUserWithRoleIdForCompany = _portalRepositories.GetInstance<IUserRepository>()
.GetCompanyUserEmailForCompanyAndRoleId(roleData, companyId);

await foreach (var (receiver, firstName, lastName) in companyUserWithRoleIdForCompany)
{
IEnumerable<(string ParameterName, string ParameterValue)> ParametersWithUserName()
{
if (userNameParameter.HasValue)
{
var userName = string.Join(" ", new[] { firstName, lastName }.Where(item => !string.IsNullOrWhiteSpace(item)));
return parameters.Append(
string.IsNullOrWhiteSpace(userName)
? userNameParameter.Value
: new(userNameParameter.Value.ParameterName, userName));
}
return parameters;
}

await _mailingService.SendMails(receiver, ParametersWithUserName().ToImmutableDictionary(x => x.ParameterName, x => x.ParameterValue), template).ConfigureAwait(false);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ public async Task AddFavouriteAppForUserAsync(Guid appId, Guid userId)

/// <inheritdoc/>
public Task<Guid> AddOwnCompanyAppSubscriptionAsync(Guid appId, IEnumerable<OfferAgreementConsentData> offerAgreementConsentData, (Guid UserId, Guid CompanyId) identity) =>
_offerSubscriptionService.AddOfferSubscriptionAsync(appId, offerAgreementConsentData, identity, OfferTypeId.APP, _settings.BasePortalAddress);
_offerSubscriptionService.AddOfferSubscriptionAsync(appId, offerAgreementConsentData, identity, OfferTypeId.APP, _settings.BasePortalAddress, _settings.SubscriptionManagerRoles);

/// <inheritdoc/>
public async Task ActivateOwnCompanyProvidedAppSubscriptionAsync(Guid subscriptionId, (Guid UserId, Guid CompanyId) identity)
Expand Down
7 changes: 7 additions & 0 deletions src/marketplace/Apps.Service/BusinessLogic/AppsSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,13 @@ public class AppsSettings
[Required]
[DistinctValues("x => x.ClientId")]
public IEnumerable<UserRoleConfig> CompanyAdminRoles { get; set; } = null!;

/// <summary>
/// Roles to notify when a new subscription was created
/// </summary>
[Required]
[DistinctValues("x => x.ClientId")]
public IEnumerable<UserRoleConfig> SubscriptionManagerRoles { get; set; } = null!;
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

using Microsoft.Extensions.DependencyInjection;
using Org.Eclipse.TractusX.Portal.Backend.Framework.Logging;
using Org.Eclipse.TractusX.Portal.Backend.Mailing.Service;
using Org.Eclipse.TractusX.Portal.Backend.Offers.Library.Service;
using Org.Eclipse.TractusX.Portal.Backend.Processes.OfferSubscription.Library.DependencyInjection;

Expand All @@ -35,6 +36,7 @@ public static IServiceCollection AddOfferServices(this IServiceCollection servic
return services
.AddTransient<IOfferService, OfferService>()
.AddTransient<IOfferSetupService, OfferSetupService>()
.AddTransient<IRoleBaseMailService, RoleBaseMailService>()
.AddTransient<IOfferSubscriptionService, OfferSubscriptionService>()
.AddOfferSubscriptionProcess();
}
Expand Down
1 change: 1 addition & 0 deletions src/marketplace/Offers.Library/Offers.Library.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
<ProjectReference Include="..\..\notifications\Notifications.Library\Notifications.Library.csproj" />
<ProjectReference Include="..\..\processes\OfferSubscription.Library\OfferSubscription.Library.csproj" />
<ProjectReference Include="..\..\provisioning\Provisioning.Library\Provisioning.Library.csproj" />
<ProjectReference Include="..\..\mailing\Mailing.Service\Mailing.Service.csproj" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
* SPDX-License-Identifier: Apache-2.0
********************************************************************************/

using Org.Eclipse.TractusX.Portal.Backend.Framework.Models.Configuration;
using Org.Eclipse.TractusX.Portal.Backend.Offers.Library.Models;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.PortalEntities.Enums;

Expand All @@ -27,5 +28,5 @@ public interface IOfferSubscriptionService
{
Task<Guid> AddOfferSubscriptionAsync(Guid offerId,
IEnumerable<OfferAgreementConsentData> offerAgreementConsentData, (Guid UserId, Guid CompanyId) identity,
OfferTypeId offerTypeId, string basePortalAddress);
OfferTypeId offerTypeId, string basePortalAddress, IEnumerable<UserRoleConfig> notificationRecipients);
}
59 changes: 22 additions & 37 deletions src/marketplace/Offers.Library/Service/OfferService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
using Org.Eclipse.TractusX.Portal.Backend.Framework.ErrorHandling;
using Org.Eclipse.TractusX.Portal.Backend.Framework.Models;
using Org.Eclipse.TractusX.Portal.Backend.Framework.Models.Configuration;
using Org.Eclipse.TractusX.Portal.Backend.Mailing.SendMail;
using Org.Eclipse.TractusX.Portal.Backend.Mailing.Service;
using Org.Eclipse.TractusX.Portal.Backend.Notifications.Library;
using Org.Eclipse.TractusX.Portal.Backend.Offers.Library.Models;
using Org.Eclipse.TractusX.Portal.Backend.PortalBackend.DBAccess;
Expand All @@ -40,7 +40,7 @@ public class OfferService : IOfferService
{
private readonly IPortalRepositories _portalRepositories;
private readonly INotificationService _notificationService;
private readonly IMailingService _mailingService;
private readonly IRoleBaseMailService _roleBaseMailService;
private readonly IOfferSetupService _offerSetupService;

/// <summary>
Expand All @@ -52,12 +52,12 @@ public class OfferService : IOfferService
/// <param name="offerSetupService">The offer Setup Service</param>
public OfferService(IPortalRepositories portalRepositories,
INotificationService notificationService,
IMailingService mailingService,
IRoleBaseMailService roleBaseMailService,
IOfferSetupService offerSetupService)
{
_portalRepositories = portalRepositories;
_notificationService = notificationService;
_mailingService = mailingService;
_roleBaseMailService = roleBaseMailService;
_offerSetupService = offerSetupService;
}

Expand Down Expand Up @@ -559,45 +559,30 @@ public async Task DeclineOfferAsync(Guid offerId, Guid userId, OfferDeclineReque
DeclineMessage = data.Message
};

var serializeNotificationContent = JsonSerializer.Serialize(notificationContent);
var content = Enumerable.Repeat(notificationTypeId, 1).Select(typeId => new ValueTuple<string?, NotificationTypeId>(serializeNotificationContent, typeId));
var content = new (string?, NotificationTypeId)[]
{
(JsonSerializer.Serialize(notificationContent), notificationTypeId)
};

await _notificationService.CreateNotifications(notificationRecipients, userId, content, declineData.CompanyId.Value).AwaitAll().ConfigureAwait(false);
await _notificationService.SetNotificationsForOfferToDone(catenaAdminRoles, submitOfferNotificationTypeIds, offerId).ConfigureAwait(false);

await _portalRepositories.SaveAsync().ConfigureAwait(false);

await SendMail(notificationRecipients, declineData.OfferName, basePortalAddress, data.Message, declineData.CompanyId.Value);
}

private async Task SendMail(IEnumerable<UserRoleConfig> receiverRoles, string offerName, string basePortalAddress, string message, Guid companyId)
{
var receiverUserRoles = receiverRoles;
var userRolesRepository = _portalRepositories.GetInstance<IUserRolesRepository>();
var roleData = await userRolesRepository
.GetUserRoleIdsUntrackedAsync(receiverUserRoles)
.ToListAsync()
.ConfigureAwait(false);
if (roleData.Count < receiverUserRoles.Sum(clientRoles => clientRoles.UserRoleNames.Count()))
{
throw new ConfigurationException(
$"invalid configuration, at least one of the configured roles does not exist in the database: {string.Join(", ", receiverUserRoles.Select(clientRoles => $"client: {clientRoles.ClientId}, roles: [{string.Join(", ", clientRoles.UserRoleNames)}]"))}");
}

var companyUserWithRoleIdForCompany = _portalRepositories.GetInstance<IUserRepository>()
.GetCompanyUserEmailForCompanyAndRoleId(roleData, companyId);
await foreach (var (receiver, firstName, lastName) in companyUserWithRoleIdForCompany)
{
var userName = string.Join(" ", new[] { firstName, lastName }.Where(item => !string.IsNullOrWhiteSpace(item)));

var mailParams = new Dictionary<string, string>
await _roleBaseMailService.RoleBaseSendMail(
notificationRecipients,
new[]
{
{ "offerName", offerName },
{ "url", basePortalAddress },
{ "declineMessage", message },
{ "offerProviderName", !string.IsNullOrWhiteSpace(userName) ? userName : "Service Manager"},
};
await _mailingService.SendMails(receiver, mailParams, new List<string> { "offer-request-decline" }).ConfigureAwait(false);
}
("offerName", declineData.OfferName),
("url", basePortalAddress),
("declineMessage", data.Message),
},
("offerProviderName", "Service Manager"),
new[]
{
"offer-request-decline"
},
declineData.CompanyId.Value).ConfigureAwait(false);
}

private async Task CheckLanguageCodesExist(IEnumerable<string> languageCodes)
Expand Down
Loading