This commit is contained in:
Loretta 2024-08-09 19:04:02 +02:00
commit 82b198702b
22 changed files with 777 additions and 111 deletions

View File

@ -13,10 +13,51 @@ public static class TiamConstClient
Guid.Parse("4cbaed43-2465-4d99-84f1-c8bc6b7025f7"),
Guid.Parse("540271f6-c604-4c16-8160-d5a7cafedf00")
};
public static string SystemEmailAddress = "system@touriam.com";
public static Dictionary<string, Guid> SysAccounts = new Dictionary<string, Guid>
{
{ "SystemEmailSender", Guid.Parse("5e13e051-4fd6-4a30-a371-75cc785cfb84")},
};
public static string WelcomeEmailTemplateName = "WelcomeEmailTemplate";
public static string NewTransferEmailTemplateName = "NewTransferEmailTemplate";
public static string TransferModifiedEmailTemplateName = "TramsferModifiedEmailTemplate";
public static string ForgotPasswordEmailTemplateName = "ForgotPasswordEmailTemplate";
public static List<string> WelcomeEmailParameters = new List<string>()
{
"UserName",
"ActivationCode"
};
public static List<string> ForgotPasswordEmailParameters = new List<string>()
{
//string userName, string settingBaseUrl, string userId, string token
"UserName",
"SettingBaseUrl",
"UserId",
"Token"
};
public static List<string> NewTransferEmailParameters = new List<string>()
{
//string userName, string fromAddress, string toAddress, string appointment,
//string fullname,string passengerCount, string luggageCount, string settingBaseUrl, string transferId
"UserName",
"FromAddress",
"ToAddress",
"Appointment",
"FullName",
"PassengerCount",
"LuggageCount",
"SettingBaseUrl",
"TransferId"
};
#if RELEASE
public static string SystemEmailAddress = "system@touriam.com";
public static LogLevel DefaultLogLevelClient = LogLevel.Debug;
#else
public static string SystemEmailAddress = "system@anataworld.com";
public static LogLevel DefaultLogLevelClient = LogLevel.Detail;
#endif
}

View File

@ -0,0 +1,106 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using TIAM.Core.Consts;
namespace TIAM.Services.Server
{
public static class EmailTemplateHelper
{
public static string GetTemplate(string templateName)
{
var assembly = Assembly.GetExecutingAssembly();
var resourceName = $"TIAM.Services.Server.EmbeddedResources.EmailTemplates.{templateName}.html";
Console.WriteLine(resourceName);
if (assembly.GetManifestResourceStream(resourceName) != null)
{
using (Stream stream = assembly.GetManifestResourceStream(resourceName))
{
if (stream != null)
{
using (StreamReader reader = new StreamReader(stream))
{
return reader.ReadToEnd();
}
}
else
{
return "File not found";
}
}
}
else
{
return "Error";
}
}
public static string ReplacePlaceholders(string template, IDictionary<string, string> placeholders)
{
foreach (var placeholder in placeholders)
{
template = template.Replace($"{{{{{placeholder.Key}}}}}", placeholder.Value);
}
return template;
}
public static string GenerateForgotPasswordEmail(string userName, string settingBaseUrl, string userId, string token)
{
string template = EmailTemplateHelper.GetTemplate(TiamConstClient.ForgotPasswordEmailTemplateName);
var placeholders = new Dictionary<string, string>
{
{ TiamConstClient.ForgotPasswordEmailParameters[0], userName },
{ TiamConstClient.ForgotPasswordEmailParameters[1], settingBaseUrl },
{ TiamConstClient.ForgotPasswordEmailParameters[2], userId },
{ TiamConstClient.ForgotPasswordEmailParameters[3], token }
};
return EmailTemplateHelper.ReplacePlaceholders(template, placeholders);
}
public static string GenerateNewTransferEmail(string userName, string fromAddress, string toAddress, string appointment, string fullName, string passengerCount, string luggageCount, string settingBaseUrl, string transferId)
{
string template = EmailTemplateHelper.GetTemplate(TiamConstClient.ForgotPasswordEmailTemplateName);
var placeholders = new Dictionary<string, string>
{
{ TiamConstClient.NewTransferEmailParameters[0], userName },
{ TiamConstClient.NewTransferEmailParameters[1], fromAddress },
{ TiamConstClient.NewTransferEmailParameters[2], toAddress },
{ TiamConstClient.NewTransferEmailParameters[3], appointment },
{ TiamConstClient.NewTransferEmailParameters[4], fullName },
{ TiamConstClient.NewTransferEmailParameters[5], passengerCount },
{ TiamConstClient.NewTransferEmailParameters[6], luggageCount },
{ TiamConstClient.NewTransferEmailParameters[7], settingBaseUrl },
{ TiamConstClient.NewTransferEmailParameters[7], transferId }
};
return EmailTemplateHelper.ReplacePlaceholders(template, placeholders);
}
public static string GenerateTransferModifiedEmail(string userName, string fromAddress, string toAddress, string appointment, string fullName, string passengerCount, string luggageCount, string settingBaseUrl, string transferId)
{
string template = EmailTemplateHelper.GetTemplate(TiamConstClient.ForgotPasswordEmailTemplateName);
var placeholders = new Dictionary<string, string>
{
{ TiamConstClient.NewTransferEmailParameters[0], userName },
{ TiamConstClient.NewTransferEmailParameters[1], fromAddress },
{ TiamConstClient.NewTransferEmailParameters[2], toAddress },
{ TiamConstClient.NewTransferEmailParameters[3], appointment },
{ TiamConstClient.NewTransferEmailParameters[4], fullName },
{ TiamConstClient.NewTransferEmailParameters[5], passengerCount },
{ TiamConstClient.NewTransferEmailParameters[6], luggageCount },
{ TiamConstClient.NewTransferEmailParameters[7], settingBaseUrl },
{ TiamConstClient.NewTransferEmailParameters[7], transferId }
};
return EmailTemplateHelper.ReplacePlaceholders(template, placeholders);
}
}
}

View File

@ -0,0 +1,14 @@
<!DOCTYPE html>
<html>
<head>
<title>Forgot password</title>
</head>
<body>
<p>Dear {{UserName}},</p>
<p>Please follow the link below to renew your password:</p>
<p>
<p><a href="{{SettingBaseUrl}}/renewpassword/{{UserId}}/{{Token}}">Confirm Transfer</a></p>
<p>If you did not request this, please disregard this email.</p>
<p>Thank you,<br />Tour I Am team</p>
</body>
</html>

View File

@ -0,0 +1,16 @@
<!DOCTYPE html>
<html>
<body>
<p>Dear {{UserName}},</p>
<p>We are pleased to inform you that a transfer order has been placed. Below are the details of the transfer:</p>
<p>{{FromAddress}} - {{ToAddress}}</p>
<p>{{Appointment}}</p>
<p>{{FullName}}</p>
<p>{{PassengerCount}}</p>
<p>{{LuggageCount}}</p>
<p>Please confirm the transfer by clicking on the following link:</p>
<p><a href="{{SettingBaseUrl}}/mytransfers/{{TransferId}}">Confirm Transfer</a></p>
<p>If you did not request this transfer, please disregard this email.</p>
<p>Thank you,<br />Tour I Am team</p>
</body>
</html>

View File

@ -0,0 +1,11 @@
<!DOCTYPE html>
<html>
<head>
<title>Transfer modified</title>
</head>
<body>
<h1>Hello, {{UserName}}!</h1>
<p>Your transfer has been modified.</p>
<p>You can check the details here: {{TransferUrl}}</p>
</body>
</html>

View File

@ -0,0 +1,11 @@
<!DOCTYPE html>
<html>
<head>
<title>Welcome</title>
</head>
<body>
<h1>Hello, {{UserName}}!</h1>
<p>Thank you for joining us.</p>
<p>Your activation code is: {{ActivationCode}}</p>
</body>
</html>

View File

@ -4,8 +4,10 @@ using AyCode.Models.Enums;
using Microsoft.Extensions.Configuration;
using SendGrid;
using SendGrid.Helpers.Mail;
using TIAM.Core.Consts;
using TIAM.Database.DataLayers.Admins;
using TIAM.Entities.Emails;
using TIAM.Entities.Users;
namespace TIAM.Services.Server
{
@ -46,24 +48,41 @@ namespace TIAM.Services.Server
Console.WriteLine($@"Message: {message.Text}");
//resolve user!!!
if (!message.SenderId.HasValue) return HttpStatusCode.BadRequest;
var senderUser = adminDal.GetUserById(message.SenderId.Value);
if (senderUser == null) return HttpStatusCode.BadRequest;
User senderUser;
var apiKey = configuration["SendGrid:Key"];
var client = new SendGridClient(apiKey);
EmailAddress from;
if (message.SenderId == Guid.Empty)
if (!message.SenderId.HasValue)
{
message.EmailAddress = "noreply@anataworld.com";
from = new EmailAddress("noreply@anataworld.com", "TourIAm mailservice");
//SYSTEM MAIL
message.SenderId = TiamConstClient.SysAccounts.FirstOrDefault(x => x.Key == "SystemEmailSender").Value;
senderUser = null; //TODO get user from DB soon
}
else
{
from = new EmailAddress(message.EmailAddress, senderUser.Profile.Name);
//USER sent message
senderUser = adminDal.GetUserById(message.SenderId.Value);
}
if (senderUser == null)
{
if (message.SenderId == Guid.Empty)
{
message.EmailAddress = TiamConstClient.SystemEmailAddress;
from = new EmailAddress(TiamConstClient.SystemEmailAddress, "TourIAm mailservice");
}
else
{
//user not valid, don't send message
return HttpStatusCode.BadRequest;
}
}
else
{
from = new EmailAddress(TiamConstClient.SystemEmailAddress, senderUser.Profile.Name);
}
Response[] responses = [];
@ -139,5 +158,20 @@ namespace TIAM.Services.Server
}
public string GenerateWelcomeEmail(string userName, string activationCode)
{
string template = EmailTemplateHelper.GetTemplate(TiamConstClient.WelcomeEmailTemplateName);
var placeholders = new Dictionary<string, string>
{
{ "UserName", userName },
{ "ActivationCode", activationCode }
};
return EmailTemplateHelper.ReplacePlaceholders(template, placeholders);
}
}
}

View File

@ -6,6 +6,25 @@
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<None Remove="EmbeddedResources\EmailTemplates\ForgotPasswordEmailTemplate.html" />
<None Remove="EmbeddedResources\EmailTemplates\NewTransferEmailTemplate.html" />
<None Remove="EmbeddedResources\EmailTemplates\TransferModifiedEmailTemplate.html" />
<None Remove="EmbeddedResources\EmailTemplates\WelcomeEmailTemplate.html" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="EmbeddedResources\EmailTemplates\ForgotPasswordEmailTemplate.html">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</EmbeddedResource>
<EmbeddedResource Include="EmbeddedResources\EmailTemplates\NewTransferEmailTemplate.html">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</EmbeddedResource>
<EmbeddedResource Include="EmbeddedResources\EmailTemplates\TransferModifiedEmailTemplate.html">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="8.0.7" />
<PackageReference Include="SendGrid" Version="9.29.3" />
@ -64,4 +83,10 @@
<Folder Include="Interfaces\" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="EmbeddedResources\EmailTemplates\WelcomeEmailTemplate.html">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</EmbeddedResource>
</ItemGroup>
</Project>

View File

@ -114,5 +114,8 @@ public class SignalRTags : AcSignalRTags
public const int UserChangePassword = 139;
public const int UserForgotPassword = 140;
public const int GuestUpdateTransfer = 150;
public const int DriverUpdateTransfer = 151;
public const int GetAllLogItemsByFilterText = 1000;
}

View File

@ -324,6 +324,39 @@ namespace TIAMMobileApp.Services
return result;
}
public async Task<bool> SendForgottenPasswordMail(string emailAddress)
{
_logger.Info("SendForgottenPasswordMail() called");
var url = $"{Setting.ApiBaseUrl}/{APIUrls.SendForgottenPasswordMail}";
var response = await http.PostAsJsonAsync(url, emailAddress);
var success = await response.Content.ReadFromJsonAsync<bool>();
_logger.Detail($"SendForgottenPasswordMail(): {success.ToString()}");
return success;
}
public async Task<string> ValidateForgotPasswordToken(Guid userId, string token)
{
_logger.Info("SendForgottenPasswordMail() called");
string[] parameters = new string[2];
parameters[0] = userId.ToString();
parameters[1] = token.ToString();
var url = $"{Setting.ApiBaseUrl}/{APIUrls.SendForgottenPasswordMail}";
var response = await http.PostAsJsonAsync(url, parameters);
var success = await response.Content.ReadFromJsonAsync<string>();
if (success == "Success")
{
_logger.Detail($"SendForgottenPasswordMail(): {success}");
}
return success;
}
//public Task<Dictionary<int, string>> GetUserRolesAsync(UserModel userModel)
//{
// //TODO Finish this

View File

@ -1,4 +1,6 @@
@using TIAMWebApp.Shared.Application.Models.PageModels;
@using AyCode.Core.Consts
@using TIAM.Core.Consts
@using TIAMWebApp.Shared.Application.Models.PageModels;
<EditForm Model="@LoginModel" OnValidSubmit="GoToNextStep">
@* <DataAnnotationsValidator /> *@
@ -44,7 +46,7 @@
IEnumerable<char> PredefinedPlaceholders { get; set; } = new List<char>() { '_', '#' };
string EmailMask { get; set; } = @"(\w|[.-])+@(\w|-)+\.(\w|-){2,4}";
string EmailMask { get; set; } = AcRegExpression.EmailMask;
MaskAutoCompleteMode AutoCompleteMode { get; set; } = MaskAutoCompleteMode.Strong;
char Placeholder { get; set; } = '_';
bool PlaceholderVisible { get; set; } = false;

View File

@ -0,0 +1,93 @@
@page "/forgotpassword"
@inherits BasePageComponent
@using AyCode.Core.Consts
@using AyCode.Core.Helpers
@using TIAM.Models.Dtos.Users
@using TIAMSharedUI.Shared.Components.BaseComponents
@using BlazorAnimation
@using TIAMWebApp.Shared.Application.Interfaces
@using TIAMWebApp.Shared.Application.Models.PageModels;
@using TIAMSharedUI.Pages.Components;
@using TIAMSharedUI.Pages.User.CardComponents
@using TIAMWebApp.Shared.Application.Services
@inject AdminSignalRClient AdminSignalRClient
@inject IUserDataService UserDataService
<PageTitle>Forgot password</PageTitle>
<div class="text-center m-5">
<h1>Renew password</h1>
<h2 style="font-size:small">Good to see you again!</h2>
</div>
<div class="container mt-3">
<div class="row d-flex justify-content-center align-items-center h-100">
<div class="col-12 col-sm-6 px-5">
<Animation Effect="@Effect.FadeIn" Speed="@Speed.Slow" Delay="@TimeSpan.FromMilliseconds(250)">
<div class="card glass inputwizardwrapper my-5">
<div class="wrapper">
<div class="my-logo">
<img src="_content/TIAMSharedUI/images/png-logo-0.png" alt="">
</div>
<div class="text-center mt-4 name">
@_localizer["LoginTitleText"]
</div>
<div class="form-field">
<DxMaskedInput @bind-Value="@emailAddress"
Id="Email"
CssClass="form-control"
Mask="@EmailMask"
MaskMode="MaskMode.RegEx">
<DxRegExMaskProperties MaskAutoCompleteMode="@((MaskAutoCompleteMode)AutoCompleteMode)"
Placeholder="Placeholder"
PlaceholdersVisible="PlaceholderVisible" />
</DxMaskedInput>
</div>
<DxButton CssClass="btn btn-primary mt-3" Click="() => SendMail(emailAddress)">Send</DxButton>
<div class="text-center fs-6">
No account yet? <a href="register">Sign up here!</a>
</div>
<div class="text-center fs-6">
Figured it out? <a href="login">Back to login!</a>
</div>
</div>
</div>
</Animation>
</div>
<div class="col-12 col-sm-6 px-5">
<Animation Effect="@Effect.FadeIn" Speed="@Speed.Fast" Delay="@TimeSpan.FromMilliseconds(250)">
<p>
@msg;
</p>
</Animation>
</div>
</div>
</div>
@code {
private string emailAddress { get; set; }
string EmailMask { get; set; } = AcRegExpression.EmailMask;
MaskAutoCompleteMode AutoCompleteMode { get; set; } = MaskAutoCompleteMode.Strong;
char Placeholder { get; set; } = '_';
bool PlaceholderVisible { get; set; } = false;
private bool sendResult = false;
private string msg = "Welcome back to TourIam! We're delighted to have you return to our platform. Let's figure out your password issue! Please fill in the email address you have used for registration.";
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
}
private void SendMail(string email)
{
var sendResult = UserDataService.SendForgottenPasswordMail(emailAddress).Forget;
}
}

View File

@ -61,7 +61,7 @@
No account yet? <a href="register">Sign up here!</a>
</div>
<div class="text-center fs-6">
Forgot your password? <a href="renewpassword">Click here!</a>
Forgot your password? <a href="forgotpassword">Click here!</a>
</div>
</div>
</div>

View File

@ -1,13 +1,18 @@
@page "/renewpassword"
@page "/renewpassword/{userId}/{renewToken}"
@inherits BasePageComponent
@using TIAM.Models.Dtos.Users
@using TIAM.Services
@using TIAMSharedUI.Shared.Components.BaseComponents
@using BlazorAnimation
@using TIAMWebApp.Shared.Application.Interfaces
@using TIAMWebApp.Shared.Application.Models.PageModels;
@using TIAMSharedUI.Pages.Components;
@using TIAMSharedUI.Pages.User.CardComponents
@using TIAMWebApp.Shared.Application.Services
@inject IUserDataService UserDataService
@inject AdminSignalRClient AdminSignalRClient
<PageTitle>Forgot password</PageTitle>
<PageTitle>Renew password</PageTitle>
<div class="text-center m-5">
<h1>Renew password</h1>
@ -20,7 +25,9 @@
<div class="col-12 col-sm-6 px-5">
<Animation Effect="@Effect.FadeIn" Speed="@Speed.Slow" Delay="@TimeSpan.FromMilliseconds(250)">
<div class="card glass inputwizardwrapper my-5">
@{
if (!isFormHidden)
{
<div class="wrapper">
<div class="my-logo">
<img src="_content/TIAMSharedUI/images/png-logo-0.png" alt="">
@ -28,7 +35,7 @@
<div class="text-center mt-4 name">
@_localizer["LoginTitleText"]
</div>
<UserCardComponent Context="user" IsForgotten="true" />
<UserCardComponent DataChanged="SendForm" Context="user" IsForgotten="true" />
<div class="text-center fs-6">
No account yet? <a href="register">Sign up here!</a>
</div>
@ -36,6 +43,29 @@
Figured it out? <a href="login">Back to login!</a>
</div>
</div>
}
else
{
<div class="wrapper">
<div class="my-logo">
<img src="_content/TIAMSharedUI/images/png-logo-0.png" alt="">
</div>
<div class="text-center mt-4 name">
@_localizer["LoginTitleText"]
</div>
<p>@resultMsg</p>
<div class="text-center fs-6">
No account yet? <a href="register">Sign up here!</a>
</div>
<div class="text-center fs-6">
Figured it out? <a href="login">Back to login!</a>
</div>
</div>
}
}
</div>
</Animation>
</div>
@ -52,13 +82,54 @@
</div>
@code {
[Parameter] public string? userId { get; set; } = "";
[Parameter] public string? renewToken { get; set; } = "";
[Parameter] public string renewToken { get; set; }
[Parameter] public string emailAddress { get; set; }
private bool isFormHidden = true;
string resultMsg = "";
private UserModelDtoDetail? user = new UserModelDtoDetail();
private UserModelDtoDetail user;
protected override Task OnInitializedAsync()
protected override async Task OnInitializedAsync()
{
return base.OnInitializedAsync();
if (userId != null && renewToken != null)
{
string msg = await UserDataService.ValidateForgotPasswordToken(Guid.Parse(userId), renewToken);
if (msg == "Success")
{
user = await UserDataService.GetUserDetailByIdAsync(Guid.Parse(userId));
isFormHidden = false;
}
else
{
isFormHidden = true;
resultMsg = msg;
}
}
await base.OnInitializedAsync();
}
protected override async Task OnParametersSetAsync()
{
//validate Token
await base.OnParametersSetAsync();
}
private void SendForm(bool isSuccess)
{
if (isSuccess)
{
resultMsg = "Successful, now you can go to the login page and log in with your new password!";
}
else
{
resultMsg = "Password wasn't saved. Please try again sending the forgotten password email. ";
}
}
}

View File

@ -14,23 +14,20 @@
@using TIAMWebApp.Shared.Application.Models.PageModels
@using TIAMWebApp.Shared.Application.Services
@inject IServiceProviderDataService ServiceProviderDataService
@inject IUserDataService UserDataService;
@inject AdminSignalRClient AdminSignalRClient;
@inject IJSRuntime JsRuntime;
@inject NavigationManager NavManager;
@inject IUserDataService UserDataService
@inject AdminSignalRClient AdminSignalRClient
@inject IJSRuntime JsRuntime
@inject NavigationManager NavManager
<div class="e-card cw-480">
<div class="e-main d-flex align-items-center">
@* <div class="flex-shrink-0">
<img class="e-photo" src="_content/TIAMSharedUI/images/defaultavatar_60.png" alt="" />
</div> *@
<div class="flex-shrink-0">
<a href="api/pictures/1" download="data:image/png;base64,@ImageSource" target="_top">
<img class="align-self-center img-fluid"
src="data:image/png;base64,@ImageSource" width="128" />
<img class="align-self-center img-fluid" src="data:image/png;base64,@ImageSource" width="128" />
</a>
<br />
<DxButton Context="ButtonContext" CssClass="btn-primary" Click="DownloadImage"><i class="fa-solid fa-download"></i> Download QR</DxButton>
</div>
<div class="e-info flex-grow-1 ms-3">
@ -45,7 +42,6 @@
<div class="row">
<div class="col-12 col-md-3">
<h4>Information</h4>
@RenderDetailsItem("fa-solid fa-user", "Contact Name", productProfile.FullName)
@RenderDetailsItem("fa-solid fa-circle-info", "Description", Context.Description)
</div>
@ -59,17 +55,11 @@
<p>Use this link to send it in an email to the client</p>
<a href="@_url" target="_blank">@_url</a>
<DxButton Context="ButtonContext" CssClass="btn-primary" Click="() => CopyUrl(_url)"><i class="fa-solid fa-copy"></i></DxButton>
// <DxButton CssClass="btn btn-primary" Click="() => CopyUrl(_url)">Copy referral url</DxButton>
}
}
</div>
<div class="col-12 col-md-6">
</div>
<div class="col-12 col-md-6"></div>
<div class="col-12">
<div class="row py-3">
@ -89,15 +79,11 @@
</div>
<div class="col-4">
@{
if (!isAddressTransferDestination)
{
// <p>Address:</p>
// <p>@(((Product)context.DataItem).Profile.Address.AddressText)</p>
<DxButton Click="() => SaveAsDestination(productProfile.Address, Context)" Text="Save as destination" RenderStyle="ButtonRenderStyle.Primary" />
}
}
</div>
<div class="col-4"></div>
</div>
@ -114,6 +100,15 @@
alert('Could not copy text: ' + err);
});
}
function downloadImage(base64String, filename) {
const link = document.createElement('a');
link.href = base64String;
link.download = filename;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
</script>
@code {
@ -126,17 +121,21 @@
AccordionExpandCollapseAction ExpandCollapseAction { get; set; } = AccordionExpandCollapseAction.HeaderClick;
private Profile productProfile = new Profile();
private List<TransferDestination> destinations = [];
private List<TransferDestination> destinations = new List<TransferDestination>();
string msg;
private bool isSaveActive = false;
private bool isAddressTransferDestination = false;
private async Task CopyUrl(string url)
{
await JsRuntime.InvokeVoidAsync("copyToClipboard", url);
}
private async Task DownloadImage()
{
await JsRuntime.InvokeVoidAsync("downloadImage", $"data:image/png;base64,{ImageSource}", "QRCode.jpg");
}
protected override async Task OnInitializedAsync()
{
var productOwner = await AdminSignalRClient.GetByIdAsync<List<Company>>(SignalRTags.GetCompaniesById, Context.ServiceProviderId);
@ -158,7 +157,6 @@
protected override async Task OnParametersSetAsync()
{
await base.OnParametersSetAsync();
}
@ -177,8 +175,6 @@
private bool CheckDestinations(Guid addressId)
{
if (destinations != null)
{
if (destinations.Any(d => d.AddressId == addressId))
@ -194,7 +190,6 @@
{
return false;
}
}
private async Task SaveAsDestination(Address address, Product product)

View File

@ -14,6 +14,10 @@
@inject AdminSignalRClient AdminSignalRClient;
<div class="e-card cw-480">
@{
if(!IsForgotten)
{
<div class="e-main d-flex align-items-center">
<div class="flex-shrink-0">
<img class="e-photo" src="_content/TIAMSharedUI/images/defaultavatar_60.png" alt="" />
@ -26,6 +30,9 @@
</div>
<hr class="hr" />
}
}
<div class="row">
<div class="col-12 col-md-6">
@ -33,10 +40,16 @@
</div>
<div class="col-9 col-md-4">
<DxTextBox hidden="@IsForgotten" @bind-Text="@OldPassword"
@{
if(!IsForgotten)
{
<DxTextBox @bind-Text="@OldPassword"
NullText="Old password"
Password="true"
CssClass="form-field" />
}
}
<DxTextBox @bind-Text="@NewPassword"
NullText="New password"
BindValueMode="BindValueMode.OnDelayedInput"
@ -62,7 +75,7 @@
@code {
[Parameter] public UserModelDtoDetail Context { get; set; }
[Parameter] public EventCallback<string> DataChanged { get; set; }
[Parameter] public EventCallback<bool> DataChanged { get; set; }
[Parameter] public bool IsForgotten { get; set; } = false;
@ -126,9 +139,9 @@
protected async Task SetPassword()
{
bool isSuccess = false;
if (!IsForgotten)
{
isSaveActive = false;
var changePasswordDto = new ChangePasswordDto(Context.Id, OldPassword, NewPassword);
@ -148,26 +161,25 @@
else
{
isSaveActive = false;
var forgotPasswordDto = new ForgotPasswordDto(Context.UserDto.EmailAddress, NewPassword);
//var changePasswordDto = new ChangePasswordDto(Context.Id, "Asdasd123456", NewPassword);
var result = await AdminSignalRClient.PostDataAsync<ForgotPasswordDto, UserModelDtoDetail>(SignalRTags.UserForgotPassword, forgotPasswordDto);
if (result != null)
{
isSuccess = true;
msg = $"Password saved";
StateHasChanged();
}
else
{
isSuccess = false;
msg = "Some error occured during saving, please try again later";
}
}
await DataChanged.InvokeAsync(msg);
await DataChanged.InvokeAsync(isSuccess);
}
protected override async Task OnInitializedAsync()
{

View File

@ -30,9 +30,7 @@ namespace TIAMSharedUI.Shared.Components.BaseComponents
{
base.OnInitialized();
_logger = new LoggerClient<UserBasePageComponent>(_logWriters.ToArray());
var currentUrl = _navManager.ToBaseRelativePath(_navManager.Uri);
_pageState.AddPageToHistory(currentUrl);
_logger.Debug(_pageState.GetGoBackPage());
}
}
}

View File

@ -331,6 +331,34 @@ namespace TIAMWebApp.Client.Services
return result;
}
public async Task<bool> SendForgottenPasswordMail(string emailAddress)
{
_logger.Info("SendForgottenPasswordMail() called");
var url = $"{Setting.ApiBaseUrl}/{APIUrls.SendForgottenPasswordMail}";
var response = await http.PostAsJsonAsync(url, emailAddress);
var success = await response.Content.ReadFromJsonAsync<bool>();
_logger.Detail($"SendForgottenPasswordMail(): {success.ToString()}");
return success;
}
public async Task<string> ValidateForgotPasswordToken(Guid userId, string token)
{
string? result = "";
_logger.Info("ValidateForgotPasswordToken() called");
var url = $"{Setting.ApiBaseUrl}/{APIUrls.ValidateForgottenPasswordToken}";
var parameters = new[] { userId.ToString(), token };
var response = await http.PostAsJsonAsync(url, parameters);
result = await response.Content.ReadAsStringAsync();
_logger.Detail($"ValidateForgotPasswordToken(): {result}");
return result;
}
/*public Task<Dictionary<int, string>> GetUserRolesAsync(UserModel userModel)
{
//TODO: finish this

View File

@ -43,8 +43,9 @@ namespace TIAMWebApp.Server.Controllers
private readonly TransferBackendService _transferBackendService;
private readonly IMessageSenderService _messageSenderService;
private readonly AuthService _authService;
private readonly UserAPIController _userApiController;
public TransferDataAPIController(AdminDal adminDal, TransferBackendService transferBackendService, IMessageSenderService messageSenderService, IEnumerable<IAcLogWriterBase> logWriters, AuthService authService)
public TransferDataAPIController(AdminDal adminDal, TransferBackendService transferBackendService, IMessageSenderService messageSenderService, IEnumerable<IAcLogWriterBase> logWriters, AuthService authService, UserAPIController userApiController)
{
_adminDal = adminDal;
_transferBackendService = transferBackendService;
@ -52,6 +53,7 @@ namespace TIAMWebApp.Server.Controllers
_logger = new TIAM.Core.Loggers.Logger<TransferDataAPIController>(logWriters.ToArray());
_messageSenderService = messageSenderService;
_authService = authService;
_userApiController = userApiController;
}
@ -745,6 +747,29 @@ namespace TIAMWebApp.Server.Controllers
return await _adminDal.UpdateTransferAsync(transfer);
}
[AllowAnonymous]
[HttpPost]
[Route(APIUrls.GuestUpdateTransferRouteName)]
[SignalR(SignalRTags.GuestUpdateTransfer)]
public async Task<Transfer?> GuestUpdateTransfer(Transfer transfer)
{
_logger.Info($"UpdateTransfer called! transferId: {transfer.Id}");
return await _adminDal.UpdateTransferAsync(transfer);
}
[AllowAnonymous]
[HttpPost]
[Route(APIUrls.DriverUpdateTransferRouteName)]
[SignalR(SignalRTags.DriverUpdateTransfer)]
public async Task<Transfer?> DriverUpdateTransfer(Transfer transfer)
{
_logger.Info($"UpdateTransfer called! transferId: {transfer.Id}");
return await _adminDal.UpdateTransferAsync(transfer);
}
[NonAction]
[SignalR(SignalRTags.RemoveTransfer)]
public async Task<Transfer?> RemoveTransfer(Transfer transfer)

View File

@ -24,13 +24,19 @@ using TIAM.Services;
using TIAM.Services.Interfaces;
using TIAMWebApp.Shared.Application.Services;
using GoogleApi.Entities.Search.Video.Common;
using TIAM.Database.DataLayers.Admins;
using TIAM.Entities.Emails;
using TIAMWebApp.Shared.Application.Models.ClientSide.Messages;
using TIAMWebApp.Shared.Application.Models.ClientSide;
using System.Net;
using TIAM.Services.Server;
namespace TIAMWebApp.Server.Controllers
{
[Authorize]
[ApiController]
[Route("api/v1/[controller]")]
public class UserAPIController(IConfiguration configuration, UserDal userDal, IEnumerable<IAcLogWriterBase> logWriters) : ControllerBase, IUserApiControllerCommon
public class UserAPIController(IConfiguration configuration, AdminDal adminDal, UserDal userDal, IMessageSenderService messageSenderService, IEnumerable<IAcLogWriterBase> logWriters) : ControllerBase, IUserApiControllerCommon
{
private readonly TIAM.Core.Loggers.Logger<UserAPIController> _logger = new(logWriters.ToArray());
@ -428,7 +434,7 @@ namespace TIAMWebApp.Server.Controllers
[AllowAnonymous]
[HttpPost]
[Route("GetUserById")]
[Route(APIUrls.GetUserByIdRouteName)]
public async Task<UserModelDto?> GetUserById([FromBody] Guid id)
{
_logger.Info($"GetUserById called with id: {id}");
@ -441,8 +447,131 @@ namespace TIAMWebApp.Server.Controllers
public async Task<UserModelDtoDetail?> GetUserDetailById([FromBody] Guid id)
{
_logger.Info($"GetUserDetailById called with id: {id}");
var result = await userDal.GetUserModelDtoByIdAsync<UserModelDtoDetail>(id, true);
var result = await userDal.GetUserModelDtoByIdAsync<UserModelDtoDetail>(id, false);
return result;
}
[AllowAnonymous]
[HttpPost]
[Route(APIUrls.SendForgottenPasswordMailRouteName)]
public async Task<bool> SendForgottenPasswordMail([FromBody] string email)
{
User user;
_logger.Info($"SendForgottenPasswordMail called with id: {email}");
user = await userDal.GetUserByEmailAsync(email, false);
if (user == null)
{
return false;
}
else
{
//create new token for the user
//user.ConfirmToken = Guid.NewGuid().ToString("N");
user.ConfirmToken = AcCharsGenerator.NewToken();
_logger.Debug($"Generated token for user: {user.ConfirmToken}");
var result = await adminDal.UpdateUserAsync(user);
_logger.Debug($"Saved token for user: {result.ConfirmToken}");
//send email
_logger.Info($"Created transfer, send emailMessage!!!");
var message = new MessageSenderModel<EmailMessage>();
message.Message = new EmailMessage();
message.Message.EmailAddress = email;
message.Message.Id = Guid.NewGuid();
message.MessageType = AyCode.Models.Enums.MessageTypesEnum.email;
message.Message.Subject = "[Tour I Am] New transfer in Budapest";
message.Message.ContextId = user.Id;
message.Message.SenderId = Guid.Empty;
message.Message.Recipients.Add(new EmailRecipient(Guid.NewGuid(), user.Id, Guid.NewGuid(), email));
message.Message.Text = EmailTemplateHelper.GenerateForgotPasswordEmail(user.FullName, Setting.BaseUrl, user.Id.ToString(), user.ConfirmToken);
_logger.Info(message.Message.Text);
var messageElement = message.Message;
Console.WriteLine(message.Message);
var mailResult = await messageSenderService.SendMessageAsync(messageElement, (int)message.MessageType);
await adminDal.AddEmailMessageAsync(messageElement);
_logger.Info("SendEmail result: " + mailResult);
//-----------------
if (mailResult == HttpStatusCode.OK.ToString())
{
await adminDal.AddEmailMessageAsync(messageElement);
return true;
}
else
{
return false;
}
}
}
[AllowAnonymous]
[HttpPost]
[Route(APIUrls.ValidateForgottenPasswordTokenRouteName)]
public async Task<string> ValidateForgottenPasswordToken([FromBody] string[] parameters)
{
User? user;
_logger.Info($"ValidateForgottenPasswordToken called with id: {parameters[0]}");
if (parameters != null && parameters[0] != null && parameters[1] != null)
{
user = await userDal.GetUserByIdAsync(Guid.Parse(parameters[0]), false);
if (user == null)
{
return "User not found";
}
else
{
if (parameters[1] == user.ConfirmToken)
{
_logger.Debug($"Generated token for user: {user.ConfirmToken}");
//if user is not email validated, set email valid
if (!user.EmailConfirmed)
await SetEmailConfirmedMethod(user);
return "Success";
}
else
{
_logger.Debug($"Generated token for user: {user.ConfirmToken}");
return "Invalid token";
}
}
}
else
{
return "Invalid request";
}
}
[AllowAnonymous]
[HttpPost]
[Route(APIUrls.SetEmailConfirmedRouteName)]
public async Task<bool> SetEmailConfirmed([FromBody] Guid userId)
{
_logger.Info($"SetEmailConfirmed called with id: {userId}");
if(User!= null)
{
var user = await userDal.GetUserByIdAsync(userId, false);
return await SetEmailConfirmedMethod(user);
}
return false;
}
[NonAction]
private async Task<bool> SetEmailConfirmedMethod(User user)
{
user.EmailConfirmed = true;
var result = await adminDal.UpdateUserAsync(user);
if (result != null)
{
return true;
}
return false;
}
}
}

View File

@ -26,5 +26,9 @@ namespace TIAMWebApp.Shared.Application.Interfaces
Task<bool> RefreshToken();
public Task<bool> Logout(string refreshToken);
public Task<bool> SendForgottenPasswordMail(string emailAddress);
public Task<string> ValidateForgotPasswordToken(Guid userId, string token);
}
}

View File

@ -66,6 +66,15 @@ namespace TIAMWebApp.Shared.Application.Models
public const string RefreshTokenRouteName = "RefreshToken";
public const string RefreshToken = UserAPI + RefreshTokenRouteName;
public const string SendForgottenPasswordMailRouteName = "SendForgottenPasswordMail";
public const string SendForgottenPasswordMail = UserAPI + SendForgottenPasswordMailRouteName;
public const string ValidateForgottenPasswordTokenRouteName = "ValidateForgottenPasswordToken";
public const string ValidateForgottenPasswordToken = UserAPI + ValidateForgottenPasswordTokenRouteName;
public const string SetEmailConfirmedRouteName = "SetEmailConfirmed";
public const string SetEmailConfirmed = UserAPI + SetEmailConfirmedRouteName;
//Weatherdata
//public const string WeatherForecast = "api/WeatherForecastAPI";
public const string WeatherForecast = WeatherForecastAPI;
@ -129,6 +138,12 @@ namespace TIAMWebApp.Shared.Application.Models
public const string UpdateTransferRouteName = "UpdateTransfer";
public const string UpdateTransfer = TransferDataAPI + UpdateTransferRouteName;
public const string GuestUpdateTransferRouteName = "GuestUpdateTransfer";
public const string GuestUpdateTransfer = TransferDataAPI + GuestUpdateTransferRouteName;
public const string DriverUpdateTransferRouteName = "DriverUpdateTransfer";
public const string DriverUpdateTransfer = TransferDataAPI + DriverUpdateTransferRouteName;
public const string UpdateTransferDestinationRouteName = "UpdateTransferDestintion";
public const string UpdateTransferDestination = TransferDataAPI + UpdateTransferDestinationRouteName;