diff --git a/StandManager.MailProcessor/Mail/Email.cs b/StandManager.MailProcessor/Mail/Email.cs new file mode 100644 index 0000000..0338ca2 --- /dev/null +++ b/StandManager.MailProcessor/Mail/Email.cs @@ -0,0 +1,17 @@ +namespace StandManager.MailProcessor.Mail; + +public class Email +{ + public string From { get; set; } + public List To { get; set; } + public List? Cc { get; set; } + public string Subject { get; set; } + public string Body { get; set; } +} + +public class EmailConfig +{ + public string From { get; set; } + public string ServerAddress { get; set; } + public string MailSplitChar { get; set; } +} \ No newline at end of file diff --git a/StandManager.MailProcessor/MailProcessor.cs b/StandManager.MailProcessor/MailProcessor.cs index 48e8236..2ab3448 100644 --- a/StandManager.MailProcessor/MailProcessor.cs +++ b/StandManager.MailProcessor/MailProcessor.cs @@ -1,18 +1,77 @@ +using System.Net.Http.Headers; +using System.Net.Http.Json; +using System.Text; +using System.Text.Json; +using StandManager.MailProcessor.Mail; using StandManager.Service.Interfaces; public class MailProcessor { private readonly IManagerService _managerService; + private readonly EmailConfig _config; - public MailProcessor(IManagerService managerService) + public MailProcessor(IManagerService managerService, EmailConfig config) { _managerService = managerService; + _config = config; } public async Task Process() { var list = await _managerService.MailQueueService.RicercaQueryable(x => - x.Eliminato == false && x.Sent == false); + x.Eliminato == false && x.Sent == false && string.IsNullOrEmpty(x.Error), solaLettura:false); + + using var httpClient = new HttpClient(); + foreach (var mailQueue in list) + { + var email = new Email() + { + From = _config.From, + Body = string.IsNullOrEmpty(mailQueue.Args) ? mailQueue.Body : string.Format(mailQueue.Body, mailQueue.Args?.Split(_config.MailSplitChar) ?? [""]), + Cc = null, + Subject = mailQueue.Subject, + To = new(){"g.vitari@oaservice.it"} // mailQueue.ToList.Split(";").ToList() + }; + var messageJson = JsonSerializer.Serialize(email); + + // multipart + using var form = new MultipartFormDataContent(); + form.Add( + new StringContent(messageJson, Encoding.UTF8, "application/json"), + "messageJson" + ); + + //Attachments + /*var filePath = @"C:\temp\test.pdf"; + var fileBytes = await File.ReadAllBytesAsync(filePath); + + var fileContent = new ByteArrayContent(fileBytes); + fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse("application/pdf"); + + form.Add( + fileContent, + "attachments", + Path.GetFileName(filePath) + );*/ + try + { + var response = await httpClient.PostAsync( + _config.ServerAddress, + form + ); + response.EnsureSuccessStatusCode(); + mailQueue.Sent = true; + await _managerService.MailQueueService.Salva(mailQueue); + } + catch (Exception e) + { + mailQueue.Sent = false; + mailQueue.Error = e.Message; + await _managerService.MailQueueService.Salva(mailQueue); + } + + } + var a = list; } } \ No newline at end of file diff --git a/StandManager.MailProcessor/Program.cs b/StandManager.MailProcessor/Program.cs index d9d1e2f..6736eea 100644 --- a/StandManager.MailProcessor/Program.cs +++ b/StandManager.MailProcessor/Program.cs @@ -4,6 +4,7 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using StandManager.Infrastructure.DAL.Context; +using StandManager.MailProcessor.Mail; using StandManager.Service; using StandManager.Service.Interfaces; using StandManager.Service.Repository; @@ -19,7 +20,11 @@ var host = Host.CreateDefaultBuilder(args) var impl = allProviderTypes.FirstOrDefault(c => c.IsClass && intfc.Name[1..] == c.Name); if (impl != null) services.AddScoped(intfc, impl); } -//Database + + var emailConfigSection = context.Configuration.GetSection("EmailConfig"); + services.Configure(emailConfigSection); + + //Database var connectionString = context.Configuration.GetConnectionString("ConnectionString"); services.AddDbContext(options => options.UseSqlServer(connectionString) diff --git a/StandManager.MailProcessor/appsettings.json b/StandManager.MailProcessor/appsettings.json index 30d3494..e5edbd4 100644 --- a/StandManager.MailProcessor/appsettings.json +++ b/StandManager.MailProcessor/appsettings.json @@ -8,5 +8,10 @@ "Microsoft.AspNetCore": "Warning" } }, - "AllowedHosts": "*" + "AllowedHosts": "*", + "EmailConfig": { + "From": "", + "ServerAddress": "", + "MailSplitChar": "#" + } } diff --git a/StandManager.Service/Interfaces/IMailQueueService.cs b/StandManager.Service/Interfaces/IMailQueueService.cs index f9a14e3..88e0673 100644 --- a/StandManager.Service/Interfaces/IMailQueueService.cs +++ b/StandManager.Service/Interfaces/IMailQueueService.cs @@ -5,4 +5,5 @@ namespace StandManager.Service.Interfaces; public interface IMailQueueService : ITService { + Task Salva(MailQueue entity); } \ No newline at end of file diff --git a/StandManager.Service/MailQueueService.cs b/StandManager.Service/MailQueueService.cs index 59b7237..f692b3f 100644 --- a/StandManager.Service/MailQueueService.cs +++ b/StandManager.Service/MailQueueService.cs @@ -13,4 +13,12 @@ public class MailQueueService : TService, IMailQueueService { _unitOfWork = unitOfWork; } + + public async Task Salva(MailQueue entity) + { + _unitOfWork.MailQueueRepository.Update(entity); + await _unitOfWork.Salva(); + + return entity; + } } \ No newline at end of file diff --git a/StandManager.Service/Repository/IStandManagerUnitOfWork.cs b/StandManager.Service/Repository/IStandManagerUnitOfWork.cs index 62b5de5..f5f1e72 100644 --- a/StandManager.Service/Repository/IStandManagerUnitOfWork.cs +++ b/StandManager.Service/Repository/IStandManagerUnitOfWork.cs @@ -6,4 +6,5 @@ namespace StandManager.Service.Repository; public interface IStandManagerUnitOfWork : IUnitOfWork { public IStandManagerGenericRepository UtenteRepository { get; } + public IStandManagerGenericRepository MailQueueRepository { get; } } \ No newline at end of file diff --git a/StandManager.Service/Repository/StandManagerUnitOfWork.cs b/StandManager.Service/Repository/StandManagerUnitOfWork.cs index e22a055..f48b843 100644 --- a/StandManager.Service/Repository/StandManagerUnitOfWork.cs +++ b/StandManager.Service/Repository/StandManagerUnitOfWork.cs @@ -24,4 +24,7 @@ public class StandManagerUnitOfWork : UnitOfWork, IStandManagerUnitOfWork private IStandManagerGenericRepository _utenteRepository; public new IStandManagerGenericRepository UtenteRepository => _utenteRepository ??= new StandManagerGenericRepository(_context); + + private IStandManagerGenericRepository _mailQueueRepository; + public new IStandManagerGenericRepository MailQueueRepository => _mailQueueRepository ??= new StandManagerGenericRepository(_context); } \ No newline at end of file diff --git a/StandManager/Components/Pages/Management/Clienti.razor b/StandManager/Components/Pages/Management/Clienti.razor index 08e7783..02c0da9 100644 --- a/StandManager/Components/Pages/Management/Clienti.razor +++ b/StandManager/Components/Pages/Management/Clienti.razor @@ -1,9 +1,7 @@ @attribute [Authorize] @page "/management/Clienti" -@using ClosedXML.Excel @using Microsoft.EntityFrameworkCore @using StandManager.Model -@using System.Threading.Tasks @rendermode InteractiveServer diff --git a/StandManager/Components/Pages/Management/Profile.razor b/StandManager/Components/Pages/Management/Profile.razor new file mode 100644 index 0000000..94aaea5 --- /dev/null +++ b/StandManager/Components/Pages/Management/Profile.razor @@ -0,0 +1,108 @@ +@page "/management/profile" +@using Microsoft.AspNetCore.Identity +@using StandManager.Model + +@attribute [Authorize] +@rendermode InteractiveServer + +
+ +
+
+
+
+
+ +
 
+

Profilo

+
+
+ +
+
+
+ Nome + +
+
+ Cognome + +
+
+ Email + +
+
+ + +
+
+ Password + +
+
+ Conferma Password + +
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+
+
+@code{ + [SupplyParameterFromForm] + private ProfiloViewModel profilo { get; set; } = new(); + private Guid userId = new(); + + protected override async Task OnInitializedAsync() + { + await base.OnInitializedAsync(); + userId = await MembershipUtils.GetUserId(_auth); + + profilo = await _managerService.UtenteService + .RicercaPer(x => x.Id == userId); + } + + private async Task onProfiloSave() + { + try + { + profilo.Validate(); + var user = await _managerService.UtenteService.RicercaPer(x => x.Id == userId, solaLettura: false); + user = profilo.Map(user); + if (!string.IsNullOrEmpty(profilo.Password)) + { + var hasher = new PasswordHasher(); + user.Password = hasher.HashPassword(user, profilo.Password); + } + await _managerService.UtenteService.Salva(user, userId); + } + catch (Exception ex) + { + await _dialogService.Alert(ex.Message, "Errore"); + } + } + + /// + /// Torna alla pagina di elenco clienti senza salvare altre modifiche. + /// + private void backToHome() + { + _navManager.NavigateTo("/management"); + } +} \ No newline at end of file diff --git a/StandManager/Model/ProfiloViewModel.cs b/StandManager/Model/ProfiloViewModel.cs new file mode 100644 index 0000000..44a7ae7 --- /dev/null +++ b/StandManager/Model/ProfiloViewModel.cs @@ -0,0 +1,47 @@ +using System.ComponentModel.DataAnnotations; +using OAService.Domain.Entita; +using StandManager.Domain.Entita; + +namespace StandManager.Model; + +public class ProfiloViewModel +{ + public Guid Id { get; set; } + public string Username { get; set; } + public string Email { get; set; } + public string Password { get; set; } + public string ConfirmPassword { get; set; } + public string Nome { get; set; } + public string Cognome { get; set; } + + public static implicit operator ProfiloViewModel(Utente model) + { + return model == null + ? null + : new ProfiloViewModel() + { + Cognome = model.Cognome, + Nome = model.Nome, + Email = model.Email, + Username = model.Username, + Id = model.Id + }; + } + + public Utente Map(Utente user) + { + user.Nome = Nome; + user.Cognome = Cognome; + + return user; + } + + public void Validate() + { + if (string.IsNullOrEmpty(Nome)) throw new ValidationException("Il nome inserito non è valido"); + if (string.IsNullOrEmpty(Cognome)) throw new ValidationException("Il cognome inserito non è valido"); + if (!string.IsNullOrEmpty(Password) && string.IsNullOrEmpty(ConfirmPassword)) throw new Exception("E' necessario inserire la password di conferma"); + if (!string.IsNullOrEmpty(Password) && !string.IsNullOrEmpty(ConfirmPassword) && Password != ConfirmPassword) + throw new ValidationException("Le due password non corrispondono"); + } +} \ No newline at end of file diff --git a/StandManager/Model/UtenteViewModel.cs b/StandManager/Model/UtenteViewModel.cs index 712decb..81043cc 100644 --- a/StandManager/Model/UtenteViewModel.cs +++ b/StandManager/Model/UtenteViewModel.cs @@ -1,49 +1,47 @@ using StandManager.Domain.Entita; using System.ComponentModel.DataAnnotations; -using System.ComponentModel.DataAnnotations.Schema; -namespace StandManager.Model +namespace StandManager.Model; + +public class UtenteViewModel { - public class UtenteViewModel + public Guid Id { get; set; } + public string Username { get; set; } + [Required] + [EmailAddress(ErrorMessage = "Email non valida")] + public string Email { get; set; } + public string Password { get; set; } + [Required(ErrorMessage = "Il nome è obbligatorio")] + public string Nome { get; set; } + [Required(ErrorMessage = "Il cognome è obbligatorio")] + public string Cognome { get; set; } + public Guid RuoloId { get; set; } + public Guid CapoareaId { get; set; } + public bool IsCapoarea { get; set; } + public string Info => $"{Nome} {Cognome}"; + + public static implicit operator UtenteViewModel(Utente? model) { - public Guid Id { get; set; } - public string Username { get; set; } - [Required] - [EmailAddress(ErrorMessage = "Email non valida")] - public string Email { get; set; } - public string Password { get; set; } - [Required(ErrorMessage = "Il nome è obbligatorio")] - public string Nome { get; set; } - [Required(ErrorMessage = "Il cognome è obbligatorio")] - public string Cognome { get; set; } - public Guid RuoloId { get; set; } - public Guid CapoareaId { get; set; } - public bool IsCapoarea { get; set; } - public string Info => $"{Nome} {Cognome}"; - - public static implicit operator UtenteViewModel(Utente? model) + return model == null ? null : new UtenteViewModel { - return model == null ? null : new UtenteViewModel - { - Id = model.Id, - Username = model.Username, - Email = model.Email, - Nome = model.Nome, - Cognome = model.Cognome, - RuoloId = model.Ruolo?.Id ?? Guid.Empty, - CapoareaId = model.Capoarea?.Id ?? Guid.Empty, - IsCapoarea = model.IsCapoarea - }; - } + Id = model.Id, + Username = model.Username, + Email = model.Email, + Nome = model.Nome, + Cognome = model.Cognome, + RuoloId = model.Ruolo?.Id ?? Guid.Empty, + CapoareaId = model.Capoarea?.Id ?? Guid.Empty, + IsCapoarea = model.IsCapoarea + }; + } - public Utente Map(Utente model) - { - model.Nome = Nome; - model.Cognome = Cognome; - model.Email = Email; - model.IsCapoarea = IsCapoarea; + public Utente Map(Utente model) + { + model.Nome = Nome; + model.Cognome = Cognome; + model.Email = Email; + model.IsCapoarea = IsCapoarea; - return model; - } + return model; } } \ No newline at end of file