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(emailNotification): Add Multiple Users | Invite email didnt receive by User(s) #922

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
Original file line number Diff line number Diff line change
Expand Up @@ -158,38 +158,38 @@ public async Task<Guid> CreateOwnCompanyIdpUserAsync(Guid identityProviderId, Us
userCreationInfo.UserId,
UserStatusId.ACTIVE,
true
), 1).ToAsyncEnumerable())
), 1).ToAsyncEnumerable(),
creationData =>
{
var mailParameters = ImmutableDictionary.CreateBuilder<string, string>();
mailParameters.AddRange([
new("companyName", displayName),
new("nameCreatedBy", nameCreatedBy),
new("url", _settings.Portal.BasePortalAddress),
new("idpAlias", displayName),
]);
IEnumerable<string> mailTemplates = companyNameIdpAliasData.IsSharedIdp
? ["NewUserTemplate", "NewUserPasswordTemplate"]
: ["NewUserExternalIdpTemplate"];
if (companyNameIdpAliasData.IsSharedIdp)
{
mailParameters.Add(new("password", creationData.Password ?? throw new UnexpectedConditionException("password should never be null here")));
}
foreach (var template in mailTemplates)
{
mailingProcessCreation.CreateMailProcess(creationData.UserCreationInfo.Email, template, mailParameters.ToImmutable());
}
})
.FirstAsync()
.ConfigureAwait(false);

if (result.Error != null)
{
throw result.Error;
}

var mailParameters = new Dictionary<string, string>
{
{ "companyName", displayName },
{ "nameCreatedBy", nameCreatedBy },
{ "url", _settings.Portal.BasePortalAddress },
{ "idpAlias", displayName },
};

var mailTemplates = companyNameIdpAliasData.IsSharedIdp
? new[] { "NewUserTemplate", "NewUserPasswordTemplate" }
: new[] { "NewUserExternalIdpTemplate" };

if (companyNameIdpAliasData.IsSharedIdp)
{
mailParameters["password"] = result.Password;
}

foreach (var template in mailTemplates)
{
mailingProcessCreation.CreateMailProcess(userCreationInfo.Email, template, mailParameters.ToImmutableDictionary());
}

await portalRepositories.SaveAsync().ConfigureAwait(ConfigureAwaitOptions.None);
return result.CompanyUserId;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
using Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library.Models;
using Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library.Service;
using System.Collections.Immutable;
using System.Runtime.CompilerServices;

namespace Org.Eclipse.TractusX.Portal.Backend.Administration.Service.BusinessLogic;

Expand Down Expand Up @@ -78,6 +77,10 @@ private async ValueTask<UserCreationStats> UploadOwnCompanyIdpUsersInternalAsync

var validRoleData = new List<UserRoleData>();

var displayName = companyNameIdpAliasData.IsSharedIdp
? null
: await _userProvisioningService.GetIdentityProviderDisplayName(companyNameIdpAliasData.IdpAlias).ConfigureAwait(ConfigureAwaitOptions.None) ?? companyNameIdpAliasData.IdpAlias;

var (numCreated, numLines, errors) = await CsvParser.ProcessCsvAsync(
stream,
line =>
Expand All @@ -99,17 +102,23 @@ await GetUserRoleDatas(parsed.Roles, validRoleData, _identityData.CompanyId).Con
UserStatusId.ACTIVE,
true);
},
lines => (companyNameIdpAliasData.IsSharedIdp
? _userProvisioningService
lines =>
_userProvisioningService
.CreateOwnCompanyIdpUsersAsync(
companyNameIdpAliasData,
lines,
creationData =>
{
if (companyNameIdpAliasData.IsSharedIdp)
return;
var mailParameters = ImmutableDictionary.CreateRange<string, string>([
new("nameCreatedBy", nameCreatedBy),
new("url", _settings.Portal.BasePortalAddress),
new("idpAlias", displayName ?? throw new UnexpectedConditionException("displayname should never be null here"))
]);
_mailingProcessCreation.CreateMailProcess(creationData.UserCreationInfo.Email, "NewUserExternalIdpTemplate", mailParameters);
},
cancellationToken)
: CreateOwnCompanyIdpUsersWithEmailAsync(
nameCreatedBy,
companyNameIdpAliasData,
lines,
cancellationToken))
.Select(x => (x.CompanyUserId != Guid.Empty, x.Error)),
cancellationToken).ConfigureAwait(false);

Expand All @@ -120,53 +129,6 @@ await GetUserRoleDatas(parsed.Roles, validRoleData, _identityData.CompanyId).Con
errors.Select(error => CreateUserCreationError(error.Line, error.Error)));
}

private async IAsyncEnumerable<(Guid CompanyUserId, string UserName, string? Password, Exception? Error)> CreateOwnCompanyIdpUsersWithEmailAsync(string nameCreatedBy, CompanyNameIdpAliasData companyNameIdpAliasData, IAsyncEnumerable<UserCreationRoleDataIdpInfo> userCreationInfos, [EnumeratorCancellation] CancellationToken cancellationToken)
{
if (companyNameIdpAliasData.IsSharedIdp)
{
throw new UnexpectedConditionException($"unexpected call to {nameof(CreateOwnCompanyIdpUsersWithEmailAsync)} for shared-idp");
}

UserCreationRoleDataIdpInfo? userCreationInfo = null;

var displayName = await _userProvisioningService.GetIdentityProviderDisplayName(companyNameIdpAliasData.IdpAlias).ConfigureAwait(ConfigureAwaitOptions.None) ?? companyNameIdpAliasData.IdpAlias;

await foreach (var result in
_userProvisioningService
.CreateOwnCompanyIdpUsersAsync(
companyNameIdpAliasData,
userCreationInfos
.Select(info =>
{
userCreationInfo = info;
return info;
}),
cancellationToken)
.WithCancellation(cancellationToken)
.ConfigureAwait(false))
{
if (userCreationInfo == null)
{
throw new UnexpectedConditionException("userCreationInfo should never be null here");
}
if (result.Error != null || result.CompanyUserId == Guid.Empty || string.IsNullOrEmpty(userCreationInfo.Email))
{
yield return result;
continue;
}

var mailParameters = ImmutableDictionary.CreateRange(new[]
{
KeyValuePair.Create("nameCreatedBy", nameCreatedBy),
KeyValuePair.Create("url", _settings.Portal.BasePortalAddress),
KeyValuePair.Create("idpAlias", displayName)
});
_mailingProcessCreation.CreateMailProcess(userCreationInfo.Email, "NewUserExternalIdpTemplate", mailParameters);

yield return (result.CompanyUserId, result.UserName, result.Password, null);
}
}

private static void ValidateUserCreationRoles(IEnumerable<string> roles)
{
if (!roles.Any())
Expand Down Expand Up @@ -199,7 +161,8 @@ private async ValueTask<UserCreationStats> UploadOwnCompanySharedIdpUsersInterna
{
using var stream = document.OpenReadStream();

var (companyNameIdpAliasData, _) = await _userProvisioningService.GetCompanyNameSharedIdpAliasData(_identityData.IdentityId).ConfigureAwait(ConfigureAwaitOptions.None);
var (companyNameIdpAliasData, nameCreatedBy) = await _userProvisioningService.GetCompanyNameSharedIdpAliasData(_identityData.IdentityId).ConfigureAwait(ConfigureAwaitOptions.None);
var displayName = await _userProvisioningService.GetIdentityProviderDisplayName(companyNameIdpAliasData.IdpAlias).ConfigureAwait(ConfigureAwaitOptions.None) ?? companyNameIdpAliasData.IdpAlias;

var validRoleData = new List<UserRoleData>();

Expand Down Expand Up @@ -229,6 +192,18 @@ await GetUserRoleDatas(parsed.Roles, validRoleData, _identityData.CompanyId).Con
.CreateOwnCompanyIdpUsersAsync(
companyNameIdpAliasData,
lines,
creationData =>
{
var mailParameters = ImmutableDictionary.CreateRange<string, string>([
new("password", creationData.Password ?? ""),
new("companyName", displayName),
new("nameCreatedBy", nameCreatedBy),
new("url", _settings.Portal.BasePortalAddress),
new("passwordResendUrl", _settings.Portal.PasswordResendAddress),
]);
_mailingProcessCreation.CreateMailProcess(creationData.UserCreationInfo.Email, "NewUserTemplate", mailParameters);
_mailingProcessCreation.CreateMailProcess(creationData.UserCreationInfo.Email, "NewUserPasswordTemplate", mailParameters);
},
cancellationToken)
.Select(x => (x.CompanyUserId != Guid.Empty, x.Error)),
cancellationToken).ConfigureAwait(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ await _idpManagement
true
)}.ToAsyncEnumerable();

var (companyUserId, _, password, error) = await _userProvisioningService.CreateOwnCompanyIdpUsersAsync(companyNameIdpAliasData, userCreationInfoIdps, cancellationToken).SingleAsync(cancellationToken).ConfigureAwait(false);
var (companyUserId, _, password, error) = await _userProvisioningService.CreateOwnCompanyIdpUsersAsync(companyNameIdpAliasData, userCreationInfoIdps, cancellationToken: cancellationToken).SingleAsync(cancellationToken).ConfigureAwait(false);

if (error is not null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,8 @@ public record UserCreationRoleDataIdpInfo(
UserStatusId UserStatusId,
bool Enabled
);

public record UserCreationCallbackData(
UserCreationRoleDataIdpInfo UserCreationInfo,
string? Password
);
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ namespace Org.Eclipse.TractusX.Portal.Backend.Provisioning.Library.Service;

public interface IUserProvisioningService
{
IAsyncEnumerable<(Guid CompanyUserId, string UserName, string? Password, Exception? Error)> CreateOwnCompanyIdpUsersAsync(CompanyNameIdpAliasData companyNameIdpAliasData, IAsyncEnumerable<UserCreationRoleDataIdpInfo> userCreationInfos, CancellationToken cancellationToken = default);
IAsyncEnumerable<(Guid CompanyUserId, string UserName, string? Password, Exception? Error)> CreateOwnCompanyIdpUsersAsync(CompanyNameIdpAliasData companyNameIdpAliasData, IAsyncEnumerable<UserCreationRoleDataIdpInfo> userCreationInfos, Action<UserCreationCallbackData>? onSuccessfulCreation = null, CancellationToken cancellationToken = default);
Task HandleCentralKeycloakCreation(UserCreationRoleDataIdpInfo user, Guid companyUserId, string companyName, string? businessPartnerNumber, Identity? identity, IEnumerable<IdentityProviderLink> identityProviderLinks, IUserRepository userRepository, IUserRolesRepository userRolesRepository);
Task<(CompanyNameIdpAliasData IdpAliasData, string NameCreatedBy)> GetCompanyNameIdpAliasData(Guid identityProviderId, Guid companyUserId);
Task<(CompanyNameIdpAliasData IdpAliasData, string NameCreatedBy)> GetCompanyNameSharedIdpAliasData(Guid companyUserId, Guid? applicationId = null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ public UserProvisioningService(IProvisioningManager provisioningManager, IPortal
public async IAsyncEnumerable<(Guid CompanyUserId, string UserName, string? Password, Exception? Error)> CreateOwnCompanyIdpUsersAsync(
CompanyNameIdpAliasData companyNameIdpAliasData,
IAsyncEnumerable<UserCreationRoleDataIdpInfo> userCreationInfos,
Action<UserCreationCallbackData>? onSuccessfulCreation = null,
[EnumeratorCancellation] CancellationToken cancellationToken = default)
{
var userRepository = _portalRepositories.GetInstance<IUserRepository>();
Expand All @@ -76,6 +77,7 @@ public UserProvisioningService(IProvisioningManager provisioningManager, IPortal

var providerUserId = await CreateSharedIdpUserOrReturnUserId(user, alias, nextPassword, isSharedIdp).ConfigureAwait(ConfigureAwaitOptions.None);
await HandleCentralKeycloakCreation(user, companyUserId, companyName, businessPartnerNumber, identity, Enumerable.Repeat(new IdentityProviderLink(alias, providerUserId, user.UserName), 1), userRepository, userRolesRepository).ConfigureAwait(ConfigureAwaitOptions.None);
onSuccessfulCreation?.Invoke(new(user, nextPassword));
}
catch (Exception e) when (e is not OperationCanceledException)
{
Expand Down
Loading
Loading