Skip to content

Commit

Permalink
Merge pull request #248 from bcgov/yj
Browse files Browse the repository at this point in the history
Yj
  • Loading branch information
ychung-mot authored May 1, 2024
2 parents eee8ef6 + 363ae84 commit 8e2bda9
Show file tree
Hide file tree
Showing 8 changed files with 181 additions and 23 deletions.
4 changes: 2 additions & 2 deletions helm/main/values-prod.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ route:

frontend:
enabled: true
replicaCount: 2
replicaCount: 3
nameOverride: strdss-prod-frontend
fullnameOverride: strdss-prod-frontend
secretName: strdss-secrets-prod
Expand All @@ -57,7 +57,7 @@ frontend:
backend:
enabled: true
replicaCount: 2
replicaCount: 3
nameOverride: strdss-prod-backend
fullnameOverride: strdss-prod-backend
secretName: strdss-secrets-prod
Expand Down
4 changes: 2 additions & 2 deletions helm/main/values-uat.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ route:

frontend:
enabled: true
replicaCount: 2
replicaCount: 3
nameOverride: strdss-uat-frontend
fullnameOverride: strdss-uat-frontend
secretName: strdss-secrets-uat
Expand All @@ -57,7 +57,7 @@ frontend:
backend:
enabled: true
replicaCount: 2
replicaCount: 3
nameOverride: strdss-uat-backend
fullnameOverride: strdss-uat-backend
secretName: strdss-secrets-uat
Expand Down
8 changes: 8 additions & 0 deletions server/StrDss.Api/BatchTakedownRequestCreateDto.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace StrDss.Model.DelistingDtos
{
public class BatchTakedownRequestCreateDto
{
public long PlatformId { get; set; }
public IFormFile File { get; set; } = null!;
}
}
43 changes: 39 additions & 4 deletions server/StrDss.Api/Controllers/DelistingController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
using StrDss.Model;
using StrDss.Model.DelistingDtos;
using StrDss.Service;
using StrDss.Service.HttpClients;

namespace StrDss.Api.Controllers
{
Expand All @@ -15,15 +14,13 @@ namespace StrDss.Api.Controllers
[ApiController]
public class DelistingController : BaseApiController
{
private IChesTokenApi _chesTokenApi;
private IDelistingService _delistingService { get; }
private IEmailMessageService _emailService;

public DelistingController(ICurrentUser currentUser, IMapper mapper, IConfiguration config, IChesTokenApi chesTokenApi, ILogger<StrDssLogger> logger,
public DelistingController(ICurrentUser currentUser, IMapper mapper, IConfiguration config, ILogger<StrDssLogger> logger,
IDelistingService delistingService, IEmailMessageService emailService)
: base(currentUser, mapper, config, logger)
{
_chesTokenApi = chesTokenApi;
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_delistingService = delistingService;
_emailService = emailService;
Expand Down Expand Up @@ -87,5 +84,43 @@ public async Task<ActionResult<EmailPreview>> GetTakedownRequestPreview(Takedown

return preview;
}

//[ApiAuthorize(Permissions.TakedownAction)]
//[HttpPost("batchtakedownrequest", Name = "SendBatchTakedownRequest")]
//public async Task<ActionResult> SendBatchTakedownRequest([FromForm] BatchTakedownRequestCreateDto dto)
//{
// Dictionary<string, List<string>> errors = new Dictionary<string, List<string>>();

// if (dto.File == null || dto.File.Length == 0)
// {
// errors.AddItem("File", $"File is null or empty.");
// return ValidationUtils.GetValidationErrorResult(errors, ControllerContext);
// }

// var maxSizeInMb = _config.GetValue<int>("RENTAL_LISTING_REPORT_MAX_SIZE");
// var maxSizeInB = (maxSizeInMb == 0 ? 2 : maxSizeInMb) * 1024 * 1024;

// if (dto.File.Length > maxSizeInB)
// {
// errors.AddItem("File", $"The file size exceeds the maximum size {maxSizeInMb}MB.");
// return ValidationUtils.GetValidationErrorResult(errors, ControllerContext);
// }

// if (!CommonUtils.IsTextFile(dto.File.ContentType))
// {
// errors.AddItem("File", $"Uploaded file is not a text file.");
// return ValidationUtils.GetValidationErrorResult(errors, ControllerContext);
// }

// using var stream = dto.File.OpenReadStream();

// errors = await _delistingService.SendBatchTakedownRequestAsync(dto.PlatformId, stream);
// if (errors.Count > 0)
// {
// return ValidationUtils.GetValidationErrorResult(errors, ControllerContext);
// }

// return NoContent();
//}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Asp.Versioning;
using AutoMapper;
using Hangfire.PostgreSql.Utils;
using Microsoft.AspNetCore.Mvc;
using StrDss.Api.Authorization;
using StrDss.Common;
Expand Down Expand Up @@ -44,7 +45,7 @@ public async Task<ActionResult> CreateRentalLisingReport([FromForm] RentalListin
return ValidationUtils.GetValidationErrorResult(errors, ControllerContext);
}

if (!IsTextFile(dto.File.ContentType))
if (!CommonUtils.IsTextFile(dto.File.ContentType))
{
errors.AddItem("File", $"Uploaded file is not a text file.");
return ValidationUtils.GetValidationErrorResult(errors, ControllerContext);
Expand All @@ -62,11 +63,5 @@ public async Task<ActionResult> CreateRentalLisingReport([FromForm] RentalListin
return Ok();
}

private bool IsTextFile(string contentType)
{
return contentType == "text/plain" ||
contentType == "text/csv" ||
contentType == "application/octet-stream";
}
}
}
15 changes: 15 additions & 0 deletions server/StrDss.Common/CommonUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,20 @@ public static T CloneObject<T>(T obj)

return newObj;
}

public static bool IsTextFile(string contentType)
{
return contentType == "text/plain" ||
contentType == "text/csv" ||
contentType == "application/octet-stream";
}

public static string StreamToBase64(Stream stream)
{
using var memoryStream = new MemoryStream();

stream.CopyTo(memoryStream);
return Convert.ToBase64String(memoryStream.ToArray());
}
}
}
108 changes: 103 additions & 5 deletions server/StrDss.Service/DelistingService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,6 @@
using StrDss.Model.OrganizationDtos;
using StrDss.Service.CsvHelpers;
using StrDss.Service.EmailTemplates;
using System;
using System.Collections.Generic;
using System.Net.Mail;
using System.Text.RegularExpressions;

namespace StrDss.Service
Expand All @@ -25,6 +22,7 @@ public interface IDelistingService
Task<Dictionary<string, List<string>>> CreateTakedownRequestAsync(TakedownRequestCreateDto dto);
Task<(Dictionary<string, List<string>> errors, EmailPreview preview)> GetTakedownRequestPreviewAsync(TakedownRequestCreateDto dto);
Task ProcessTakedownRequestBatchEmailsAsync();
Task<Dictionary<string, List<string>>> SendBatchTakedownRequestAsync(long platformId, Stream stream);
}
public class DelistingService : ServiceBase, IDelistingService
{
Expand Down Expand Up @@ -202,9 +200,12 @@ private TakedownNotice GetTakedownNoticeTemplate(TakedownNoticeCreateDto dto, Or

// BCC: [sender], [platform], [Additional CCs] (optional)
dto.CcList.Add(_currentUser.EmailAddress);
dto.CcList.Add(platform!.ContactPeople

var platformEmail = platform!.ContactPeople
.FirstOrDefault(x => x.IsPrimary && x.EmailAddressDsc.IsNotEmpty() && x.EmailMessageType == EmailMessageTypes.NoticeOfTakedown)!
.EmailAddressDsc);
.EmailAddressDsc;

dto.CcList.Add(platformEmail);

var template = new TakedownNotice(_emailService)
{
Expand All @@ -213,6 +214,7 @@ private TakedownNotice GetTakedownNoticeTemplate(TakedownNoticeCreateDto dto, Or
LgName = lg!.OrganizationNm,
To = dto.ToList,
Bcc = dto.CcList,
EmailsToHide = new List<string> { platformEmail! },
Info = dto.ListingUrl,
Comment = dto.Comment,
Preview = preview
Expand Down Expand Up @@ -479,5 +481,101 @@ private async Task ProcessTakedownRequestBatchEmailAsync(OrganizationDto platfor

_unitOfWork.CommitTransaction(transaction);
}

public async Task<Dictionary<string, List<string>>> SendBatchTakedownRequestAsync(long platformId, Stream stream)
{
var platform = await _orgService.GetOrganizationByIdAsync(platformId);

var errors = await ValidateBatchTakedownRequestAsync(platform, stream);
if (errors.Count > 0)
{
return errors;
}

//the existence of the contact email has been validated above
var contact = platform.ContactPeople.First(x => x.IsPrimary && x.EmailAddressDsc.IsNotEmpty() && x.EmailMessageType == EmailMessageTypes.BatchTakedownRequest);

var content = CommonUtils.StreamToBase64(stream);
var date = DateUtils.ConvertUtcToPacificTime(DateTime.UtcNow).ToString("yyyy-MM-dd-HH-mm");
var fileName = $"{platform.OrganizationNm} - {date}.csv";
var adminEmail = _config.GetValue<string>("ADMIN_EMAIL") ?? throw new Exception($"There's no admin eamil.");

var template = new BatchTakedownRequest(_emailService)
{
To = new string[] { contact!.EmailAddressDsc },
Bcc = new string[] { adminEmail! },
Info = $"{EmailMessageTypes.BatchTakedownRequest} for {platform.OrganizationNm}",
Attachments = new EmailAttachment[] { new EmailAttachment {
Content = content,
ContentType = "text/csv",
Encoding = "base64",
Filename = fileName
}},
};

var emailEntity = new DssEmailMessage
{
EmailMessageType = template.EmailMessageType,
MessageDeliveryDtm = DateTime.UtcNow,
MessageTemplateDsc = template.GetContent() + $" Attachement: {fileName}",
IsHostContactedExternally = false,
IsSubmitterCcRequired = false,
MessageReasonId = null,
LgPhoneNo = null,
UnreportedListingNo = null,
HostEmailAddressDsc = null,
LgEmailAddressDsc = null,
CcEmailAddressDsc = null,
UnreportedListingUrl = null,
LgStrBylawUrl = null,
InitiatingUserIdentityId = _currentUser.Id,
AffectedByUserIdentityId = null,
InvolvedInOrganizationId = platform.OrganizationId,
RequestingOrganizationId = null
};

await _emailRepo.AddEmailMessage(emailEntity);

emailEntity.ExternalMessageNo = await template.SendEmail();

using var transaction = _unitOfWork.BeginTransaction();

_unitOfWork.Commit();

emailEntity.BatchingEmailMessageId = emailEntity.EmailMessageId;

_unitOfWork.Commit();

_unitOfWork.CommitTransaction(transaction);

return errors;
}

private async Task<Dictionary<string, List<string>>> ValidateBatchTakedownRequestAsync(OrganizationDto? platform, Stream stream)
{
await Task.CompletedTask;

var errors = new Dictionary<string, List<string>>();

if (platform == null)
{
errors.AddItem("platformId", $"Platform ID ({platform!.OrganizationId}) does not exist.");
}
else
{
if (platform.OrganizationType != OrganizationTypes.Platform)
{
errors.AddItem("platformId", $"Organization ({platform!.OrganizationId}) is not a platform");
}

if (platform.ContactPeople == null ||
!platform.ContactPeople.Any(x => x.IsPrimary && x.EmailAddressDsc.IsNotEmpty() && x.EmailMessageType == EmailMessageTypes.BatchTakedownRequest))
{
errors.AddItem("platformId", $"Platform ({platform!.OrganizationId}) does not have the primary '{EmailMessageTypes.BatchTakedownRequest}' contact info");
}
}

return errors;
}
}
}
13 changes: 10 additions & 3 deletions server/StrDss.Service/EmailTemplates/EmailTemplateBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,22 @@ public EmailTemplateBase(IEmailMessageService emailService)
public bool Preview { get; set; } = false;
public string EmailMessageType { get; set; } = "";
public IEnumerable<EmailAttachment> Attachments { get; set; } = Enumerable.Empty<EmailAttachment>();
public List<string> EmailsToHide { get; set; } = new List<string>();

public string GetPreviewContent()
{
return $@"To: {string.Join(";", To)}"
+ (Bcc.Count() > 0 ? $"<br/>Bcc: {string.Join(";", Bcc)}<br/><br/>" : "")
+ (Cc.Count() > 0 ? $"<br/>Cc: {string.Join(";", Cc)}<br/><br/>" : "")
return $@"To: {GetRecipentsForPreview(To)}"
+ (Bcc.Count() > 0 ? $"<br/>Bcc: {GetRecipentsForPreview(Bcc)}<br/><br/>" : "")
+ (Cc.Count() > 0 ? $"<br/>Cc: {GetRecipentsForPreview(Cc)}<br/><br/>" : "")
;
}

public string GetRecipentsForPreview(IEnumerable<string> list)
{
var filteredList = list.Except(EmailsToHide);
return string.Join(", ", filteredList);
}

public virtual string GetContent()
{
return "";
Expand Down

0 comments on commit 8e2bda9

Please sign in to comment.