Skip to content

Commit

Permalink
Update/mail (#390)
Browse files Browse the repository at this point in the history
* xxx

* xyz

* ehehe
  • Loading branch information
ChienNQuang authored Jul 30, 2023
1 parent 72f287f commit 1cf9b1f
Show file tree
Hide file tree
Showing 14 changed files with 277 additions and 13 deletions.
6 changes: 5 additions & 1 deletion src/Api/appsettings.Development.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@
"Token": "745f040659edff0ce87b545567da72d2",
"SenderName": "ProFile",
"SenderEmail": "[email protected]",
"TemplateUuid": "9d6a8f25-65e9-4819-be7d-106ce077acf1"
"TemplateUuids": {
"ResetPassword": "9d6a8f25-65e9-4819-be7d-106ce077acf1",
"ShareEntry": "ad69df89-885a-48fb-b8f6-6d06af1a54e3",
"Request": "bce7e60c-d848-4f80-af96-cccd264dcc32"
}
},
"Seed": true,
"Serilog" : {
Expand Down
3 changes: 3 additions & 0 deletions src/Application/Borrows/Commands/BorrowDocument.cs
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,10 @@ is BorrowRequestStatus.Approved
entity.Status = BorrowRequestStatus.Approved;
}


var result = await _context.Borrows.AddAsync(entity, cancellationToken);
entity.AddDomainEvent(new RequestCreated($"{user.FirstName} {user.LastName}", "borrow request", "borrow",
document.Title, entity.Id, request.BorrowReason, document.Id));
await _context.SaveChangesAsync(cancellationToken);
using (Logging.PushProperties("Request", document.Id, user.Id))
{
Expand Down
4 changes: 3 additions & 1 deletion src/Application/Common/Interfaces/IMailService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,7 @@ namespace Application.Common.Interfaces;

public interface IMailService
{
bool SendResetPasswordHtmlMail(string userEmail, string temporaryPassword);
bool SendResetPasswordHtmlMail(string userEmail, string temporaryPassword, string tokenHash);
bool SendShareEntryHtmlMail(bool isDirectory, string name, string sharerName, string operation, string ownerName, string email, string path);
bool SendCreateRequestHtmlMail(string userName, string requestType, string operation, string documentName, string reason, Guid documentId, string email);
}
42 changes: 38 additions & 4 deletions src/Application/Common/Models/HtmlMailData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public class HtmlMailData
[JsonPropertyName("template_uuid")]
public string TemplateUuid { get; set; }
[JsonPropertyName("template_variables")]
public TemplateVariables TemplateVariables { get; set; }
public object TemplateVariables { get; set; }
}

public class From
Expand All @@ -28,12 +28,46 @@ public class To
public string Email { get; set; }
}

public class TemplateVariables
public class ResetPasswordTemplateVariables
{
[JsonPropertyName("user_email")]
public string UserEmail { get; set; }
[JsonPropertyName("reset_password_token_hash")]
public string ResetPasswordTokenHash { get; set; }
[JsonPropertyName("token_hash")]
public string TokenHash { get; set; }
[JsonPropertyName("user_password")]
public string UserPassword { get; set; }
}

public class ShareEntryTemplateVariables
{
[JsonPropertyName("entry_type")]
public string EntryType { get; set; }
[JsonPropertyName("entry_name")]
public string EntryName { get; set; }
[JsonPropertyName("sharer_name")]
public string SharerName { get; set; }
[JsonPropertyName("operation")]
public string Operation { get; set; }
[JsonPropertyName("owner_name")]
public string OwnerName { get; set; }
[JsonPropertyName("path")]
public string Path { get; set; }
}

public class CreateRequestTemplateVariables
{
[JsonPropertyName("user_name")]
public string UserName { get; set; }
[JsonPropertyName("request_type")]
public string RequestType { get; set; }
[JsonPropertyName("operation")]
public string Operation { get; set; }
[JsonPropertyName("document_name")]
public string DocumentName { get; set; }
[JsonPropertyName("reason")]
public string Reason { get; set; }
[JsonPropertyName("path")]
public string Path { get; set; }
[JsonPropertyName("id")]
public string Id { get; set; }
}
37 changes: 37 additions & 0 deletions src/Application/Documents/EventHandlers/RequestCreatedHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using Application.Common.Interfaces;
using Domain.Events;
using MediatR;
using Microsoft.EntityFrameworkCore;

namespace Application.Documents.EventHandlers;

public class RequestCreatedHandler : INotificationHandler<RequestCreated>
{
private readonly IApplicationDbContext _context;
private readonly IMailService _mailService;

public RequestCreatedHandler(IMailService mailService, IApplicationDbContext context)
{
_mailService = mailService;
_context = context;
}

public async Task Handle(RequestCreated notification, CancellationToken cancellationToken)
{
var document = await _context.Documents
.Include(x => x.Department)
.FirstOrDefaultAsync(x => x.Id == notification.DocumentId, cancellationToken);

var departmentId = document!.Department!.Id;

var staff = await _context.Staffs
.Include(x => x.User)
.FirstOrDefaultAsync(x => x.Room!.DepartmentId == departmentId, cancellationToken);

if (staff is not null)
{
_mailService.SendCreateRequestHtmlMail(notification.UserName, notification.RequestType, notification.Operation,
notification.DocumentTitle, notification.Reason, notification.RequestId, staff.User.Email);
}
}
}
10 changes: 10 additions & 0 deletions src/Application/Entries/Commands/ShareEntry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using AutoMapper;
using Domain.Entities;
using Domain.Entities.Digital;
using Domain.Events;
using MediatR;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
Expand Down Expand Up @@ -103,6 +104,15 @@ public async Task<EntryPermissionDto> Handle(Command request, CancellationToken
await GrantOrRevokePermission(childEntry, user, childAllowOperations, request.ExpiryDate, false, cancellationToken);
}
}

if (request.CanView)
{
var p = "view";
if (request.CanEdit) p = "edit";
entry.AddDomainEvent(new ShareEntryEvent(entry.Name,
request.CurrentUser.FirstName + request.CurrentUser.LastName,
entry.Owner.FirstName + entry.Owner.LastName, user.Email, entry.IsDirectory, p, entry.Id.ToString()));
}
await _context.SaveChangesAsync(cancellationToken);
using (Logging.PushProperties(nameof(Entry), entry.Id, request.CurrentUser.Id))
{
Expand Down
21 changes: 21 additions & 0 deletions src/Application/Entries/EventHandlers/ShareEntryEventHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using Application.Common.Interfaces;
using Domain.Events;
using MediatR;

namespace Application.Entries.EventHandlers;

public class ShareEntryEventHandler : INotificationHandler<ShareEntryEvent>
{
private readonly IMailService _mailService;

public ShareEntryEventHandler(IMailService mailService)
{
_mailService = mailService;
}

public async Task Handle(ShareEntryEvent notification, CancellationToken cancellationToken)
{
_mailService.SendShareEntryHtmlMail(notification.IsDirectory, notification.EntryName, notification.SharerName,
notification.Operation, notification.OwnerName, notification.SharedUserEmail, notification.Path);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,6 @@ public async Task Handle(UserCreatedEvent notification, CancellationToken cancel
await _authDbContext.ResetPasswordTokens.AddAsync(resetPasswordToken, cancellationToken);
await _authDbContext.SaveChangesAsync(cancellationToken);

_mailService.SendResetPasswordHtmlMail(notification.User.Email, notification.Password);
_mailService.SendResetPasswordHtmlMail(notification.User.Email, notification.Password, resetPasswordToken.TokenHash);
}
}
24 changes: 24 additions & 0 deletions src/Domain/Events/RequestCreated.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using Domain.Common;

namespace Domain.Events;

public class RequestCreated : BaseEvent
{
public RequestCreated(string userName, string requestType, string operation, string documentTitle, Guid requestId, string reason, Guid documentId)
{
UserName = userName;
RequestType = requestType;
Operation = operation;
DocumentTitle = documentTitle;
RequestId = requestId;
Reason = reason;
DocumentId = documentId;
}
public string UserName { get; }
public string RequestType { get; }
public string Operation { get; }
public string DocumentTitle { get; }
public string Reason { get; }
public Guid DocumentId { get; }
public Guid RequestId { get; }
}
25 changes: 25 additions & 0 deletions src/Domain/Events/ShareEntryEvent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using Domain.Common;

namespace Domain.Events;

public class ShareEntryEvent : BaseEvent
{
public ShareEntryEvent(string entryName, string sharerName, string ownerName, string sharedUserEmail, bool isDirectory, string operation, string path)
{
EntryName = entryName;
SharerName = sharerName;
OwnerName = ownerName;
SharedUserEmail = sharedUserEmail;
IsDirectory = isDirectory;
Operation = operation;
Path = path;
}

public string EntryName { get; }
public string SharerName { get; }
public string OwnerName { get; }
public string SharedUserEmail { get; }
public bool IsDirectory { get; }
public string Operation { get; }
public string Path { get; }
}
2 changes: 1 addition & 1 deletion src/Infrastructure/ConfigureServices.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ private static IServiceCollection AddMailService(this IServiceCollection service
options.Token = mailSettings!.Token;
options.SenderEmail = mailSettings!.SenderEmail;
options.SenderName = mailSettings!.SenderName;
options.TemplateUuid = mailSettings!.TemplateUuid;
options.TemplateUuids = mailSettings!.TemplateUuids;
});

services.AddTransient<IMailService, MailService>();
Expand Down
90 changes: 87 additions & 3 deletions src/Infrastructure/Services/MailService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public MailService(IOptions<MailSettings> mailSettingsOptions)
_mailSettings = mailSettingsOptions.Value;
}

public bool SendResetPasswordHtmlMail(string userEmail, string temporaryPassword)
public bool SendResetPasswordHtmlMail(string userEmail, string temporaryPassword, string tokenHash)
{
var data = new HtmlMailData()
{
Expand All @@ -30,11 +30,95 @@ public bool SendResetPasswordHtmlMail(string userEmail, string temporaryPassword
{
new (){ Email = userEmail },
},
TemplateUuid = _mailSettings.TemplateUuid,
TemplateVariables = new TemplateVariables()
TemplateUuid = _mailSettings.TemplateUuids.ResetPassword,
TemplateVariables = new ResetPasswordTemplateVariables()
{
UserEmail = userEmail,
UserPassword = temporaryPassword,
TokenHash = tokenHash
},
};

var json = JsonSerializer.Serialize(data, new JsonSerializerOptions(JsonSerializerDefaults.Web));

var client = new RestClient(_mailSettings.ClientUrl);
var request = new RestRequest
{
Method = Method.Post
};

request.AddHeader("Authorization", $"{JwtBearerDefaults.AuthenticationScheme} {_mailSettings.Token}");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", json, ParameterType.RequestBody);
var response = client.Execute(request);
return response.IsSuccessStatusCode;
}

public bool SendShareEntryHtmlMail(bool isDirectory, string name, string sharerName, string operation, string ownerName,
string email, string path)
{
var data = new HtmlMailData()
{
From = new From()
{
Email = _mailSettings.SenderEmail,
Name = _mailSettings.SenderName,
},
To = new To[]
{
new (){ Email = email },
},
TemplateUuid = _mailSettings.TemplateUuids.ShareEntry,
TemplateVariables = new ShareEntryTemplateVariables()
{
EntryName = name,
Operation = operation,
EntryType = isDirectory ? "Folder" : "File",
OwnerName = ownerName,
SharerName = sharerName,
Path = path
},
};

var json = JsonSerializer.Serialize(data, new JsonSerializerOptions(JsonSerializerDefaults.Web));

var client = new RestClient(_mailSettings.ClientUrl);
var request = new RestRequest
{
Method = Method.Post
};

request.AddHeader("Authorization", $"{JwtBearerDefaults.AuthenticationScheme} {_mailSettings.Token}");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", json, ParameterType.RequestBody);
var response = client.Execute(request);
return response.IsSuccessStatusCode;
}

public bool SendCreateRequestHtmlMail(string userName, string requestType, string operation, string documentName,
string reason, Guid documentId, string email)
{
var data = new HtmlMailData()
{
From = new From()
{
Email = _mailSettings.SenderEmail,
Name = _mailSettings.SenderName,
},
To = new To[]
{
new (){ Email = email },
},
TemplateUuid = _mailSettings.TemplateUuids.Request,
TemplateVariables = new CreateRequestTemplateVariables()
{
Operation = operation,
Reason = reason,
DocumentName = documentName,
UserName = userName,
Id = documentId.ToString(),
RequestType = requestType,
Path = !requestType.Equals("borrow request") ? "import/manage" : "requests"
},
};

Expand Down
10 changes: 9 additions & 1 deletion src/Infrastructure/Shared/MailSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,13 @@ public class MailSettings
public string Token { get; set; }
public string SenderName { get; set; }
public string SenderEmail { get; set; }
public string TemplateUuid { get; set; }

public Template TemplateUuids { get; set; }
}

public class Template
{
public string ResetPassword { get; set; }
public string ShareEntry { get; set; }
public string Request { get; set; }
}
14 changes: 13 additions & 1 deletion tests/Application.Tests.Integration/CustomMailService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,19 @@ namespace Application.Tests.Integration;

public class CustomMailService : IMailService
{
public bool SendResetPasswordHtmlMail(string userEmail, string temporaryPassword)
public bool SendResetPasswordHtmlMail(string userEmail, string temporaryPassword, string tokenHash)
{
return true;
}

public bool SendShareEntryHtmlMail(bool isDirectory, string name, string sharerName, string operation, string ownerName,
string email, string path)
{
return true;
}

public bool SendCreateRequestHtmlMail(string userName, string requestType, string operation, string documentName,
string reason, Guid documentId, string email)
{
return true;
}
Expand Down

0 comments on commit 1cf9b1f

Please sign in to comment.