diff --git a/.gitignore b/.gitignore index 47c5ac07..7c31c0af 100644 --- a/.gitignore +++ b/.gitignore @@ -236,3 +236,4 @@ AppPackages/ /Registration/src/Application/Registration.API/appsettings.uat.json /Registration/src/Application/Registration.API/Migrations/20240319015849_InitialCreate.cs /Registration/src/Application/Registration.API/Migrations/DataContextModelSnapshot.cs +/Registration/docker-compose.uat.yml diff --git a/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/ConsumerChurchMonthWork.csproj b/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/ConsumerChurchMonthWork.csproj index e4d33872..e2103e78 100644 --- a/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/ConsumerChurchMonthWork.csproj +++ b/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/ConsumerChurchMonthWork.csproj @@ -14,6 +14,7 @@ + @@ -32,4 +33,8 @@ + + + + diff --git a/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/MessageBrocker/Config/RabbitMqConfiguration.cs b/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/MessageBrocker/Config/RabbitMqConfiguration.cs new file mode 100644 index 00000000..4f308285 --- /dev/null +++ b/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/MessageBrocker/Config/RabbitMqConfiguration.cs @@ -0,0 +1,11 @@ +namespace ConsumerChurchMonthWork.MessageBrocker.Config; +public class RabbitMQConfiguration +{ + public const string ConfigurationSection = "RabbitMQ"; + public string? Host { get; set; } + public string? VirtualHost { get; set; } + public int Port { get; set; } + public string? Username { get; set; } + public string? Password { get; set; } +} + diff --git a/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/MessageBrocker/Consumer/NewUserCreatedListerner.cs b/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/MessageBrocker/Consumer/NewUserCreatedListerner.cs new file mode 100644 index 00000000..5653d0c9 --- /dev/null +++ b/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/MessageBrocker/Consumer/NewUserCreatedListerner.cs @@ -0,0 +1,79 @@ +using ConsumerChurchMonthWork.Models; +using Microsoft.Extensions.Hosting; +using Serilog; +using RabbitMQ.Client; +using RabbitMQ.Client.Events; +using System.Text; +using System.Text.Json; +using RabbitMQ.Client.Exceptions; +using System.Security.Cryptography; +using ConsumerChurchMonthWork.Services; + +namespace ConsumerChurchMonthWork.MessageBrocker.Consumer; +public class NewUserCreatedListerner : BackgroundService +{ + private readonly IModel _channel; + private readonly ILogger _logger; + private readonly string _queueName = "user_created"; + public NewUserCreatedListerner(IModel channel, ILogger logger) + { + _channel = channel; + _logger = logger; + } + protected override async Task ExecuteAsync(CancellationToken stoppingToken) + { + try + { + await ExecuteConsume(stoppingToken); + } + catch(Exception ex) when (ex is BrokerUnreachableException || ex is OperationInterruptedException) + { + _logger.Error("An error with rabbitMq configs occurred before the connection: {0}", ex.Message); + } + catch (Exception ex) + { + _logger.Error("An error occurred before the connection: {0}", ex.Message); + } + } + + private async Task ExecuteConsume(CancellationToken stoppingToken) + { + var consumer = new EventingBasicConsumer(_channel); + consumer.Received += OnMessageReceived; + _channel.BasicConsume(_queueName, false, consumer); + + while (!stoppingToken.IsCancellationRequested) + await Task.Delay(1000, stoppingToken); + + _logger.Warning("Dispose connection"); + _channel.Dispose(); + } + + private async void OnMessageReceived(object? sender, BasicDeliverEventArgs eventsArgs) + { + try + { + byte[] rawMessage = eventsArgs.Body.ToArray(); + string message = Encoding.UTF8.GetString(rawMessage); + UserCreatedMessageDto? objMessage = JsonSerializer.Deserialize(message); + + if(objMessage is null || objMessage.EmailAddress is null) + throw new ArgumentNullException(); + + //await new SendEmailNewUser().SendEmailAsync(objMessage); + + _channel.BasicAck(eventsArgs.DeliveryTag, false); + _logger.Information($"Message newUserCreated processed successful - {objMessage.EmailAddress}"); + } + catch(Exception ex) when (ex is JsonException || ex is ArgumentNullException) + { + _logger.Error("There was an error deserializing the message: {0}", ex.Message); + _channel.BasicNack(eventsArgs.DeliveryTag, false, false); + } + catch (Exception ex) + { + _logger.Error("There was an error processing the message: {0}", ex.Message); + _channel.BasicNack(eventsArgs.DeliveryTag, false, false); + } + } +} diff --git a/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/MessageBrocker/RabbitMq.cs b/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/MessageBrocker/Consumer/RabbitMq.cs similarity index 70% rename from Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/MessageBrocker/RabbitMq.cs rename to Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/MessageBrocker/Consumer/RabbitMq.cs index 882844ae..8f6b28fb 100644 --- a/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/MessageBrocker/RabbitMq.cs +++ b/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/MessageBrocker/Consumer/RabbitMq.cs @@ -1,19 +1,20 @@ using ConsumerChurchMonthWork.Entitie; using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Hosting; using RabbitMQ.Client; using RabbitMQ.Client.Events; using Serilog; +using System.ComponentModel; using System.Text; using System.Text.Json; -using System.Threading.Channels; -namespace ConsumerChurchMonthWork.MessageBrocker; +namespace ConsumerChurchMonthWork.MessageBrocker.Consumer; -internal class RabbitMq : IMessageBrocker +internal class RabbitMq : BackgroundService { private readonly IConfiguration _configuration; private readonly ILogger _logger; - private ConnectionFactory _connectionFactory; + private ConnectionFactory _connectionFactory = null!; public RabbitMq(IConfiguration configuration, ILogger logger) { @@ -22,14 +23,14 @@ public RabbitMq(IConfiguration configuration, ILogger logger) LoadConfig(); } - public string Exchange { get; private set; } - public string Host { get; private set; } - public string VirtualHost { get; private set; } - public string Port { get; private set; } - public string UserName { get; private set; } - public string Password { get; private set; } - public string RoutingKey { get; private set; } - public string Queue { get; private set; } + public string Exchange { get; private set; } = null!; + public string Host { get; private set; } = null!; + public string VirtualHost { get; private set; } = null!; + public string Port { get; private set; } = null!; + public string UserName { get; private set; } = null!; + public string Password { get; private set; } = null!; + public string RoutingKey { get; private set; } = null!; + public string Queue { get; private set; } = null!; private void LoadConfig() @@ -46,7 +47,7 @@ private void LoadConfig() private ConnectionFactory CreateConnectionFromParameters() { - if (someValueIsEmptyOrNull()) + if (SomeValueIsEmptyOrNull()) throw new ArgumentNullException("Check the messageBroker properties"); _connectionFactory = new ConnectionFactory() @@ -60,10 +61,10 @@ private ConnectionFactory CreateConnectionFromParameters() return _connectionFactory; } - private bool someValueIsEmptyOrNull() => (string.IsNullOrEmpty(Host) | + private bool SomeValueIsEmptyOrNull() => string.IsNullOrEmpty(Host) | string.IsNullOrEmpty(UserName) | string.IsNullOrEmpty(Password) | - string.IsNullOrEmpty(Port)); + string.IsNullOrEmpty(Port); @@ -74,8 +75,8 @@ public void StartConsumer() _logger.Information("Consumindo monthly closing"); - using var connection = _connectionFactory.CreateConnection(); - using var channel = connection.CreateModel(); + using IConnection connection = _connectionFactory.CreateConnection(); + using IModel channel = connection.CreateModel(); channel.ExchangeDeclare(exchange: Exchange, type: ExchangeType.Topic); channel.QueueDeclare(queue: Queue, @@ -115,6 +116,11 @@ private static void ReadMessage(BasicDeliverEventArgs ea) var objBody = JsonSerializer.Deserialize(message); - Console.WriteLine($"Received message: {objBody.ChurcId}, {objBody.YearMonth}"); + Console.WriteLine($"Received message: {objBody!.ChurcId}, {objBody.YearMonth}"); + } + + protected override Task ExecuteAsync(CancellationToken stoppingToken) + { + throw new NotImplementedException(); } } diff --git a/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/MessageBrocker/IMessageBrocker.cs b/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/MessageBrocker/IMessageBrocker.cs deleted file mode 100644 index 4027ce46..00000000 --- a/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/MessageBrocker/IMessageBrocker.cs +++ /dev/null @@ -1,5 +0,0 @@ -namespace ConsumerChurchMonthWork.MessageBrocker; - -internal interface IMessageBrocker -{ -} diff --git a/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/Entitie/MonthlyClosing.cs b/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/Models/MonthlyClosing.cs similarity index 100% rename from Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/Entitie/MonthlyClosing.cs rename to Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/Models/MonthlyClosing.cs diff --git a/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/Entitie/ObjMessage.cs b/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/Models/ObjMessage.cs similarity index 68% rename from Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/Entitie/ObjMessage.cs rename to Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/Models/ObjMessage.cs index 29b64232..5e27ccf8 100644 --- a/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/Entitie/ObjMessage.cs +++ b/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/Models/ObjMessage.cs @@ -3,5 +3,5 @@ public class ObjMessage { public int ChurcId { get; set; } - public string YearMonth { get; set; } + public string YearMonth { get; set; } = null!; } diff --git a/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/Models/UserCreatedMessageDto.cs b/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/Models/UserCreatedMessageDto.cs new file mode 100644 index 00000000..36bd3e4b --- /dev/null +++ b/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/Models/UserCreatedMessageDto.cs @@ -0,0 +1,2 @@ +namespace ConsumerChurchMonthWork.Models; +public record UserCreatedMessageDto(short Id, string EmailAddress, DateTime OcurredOn, string Password); \ No newline at end of file diff --git a/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/Program.cs b/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/Program.cs index acf6a413..b668092a 100644 --- a/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/Program.cs +++ b/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/Program.cs @@ -1,41 +1,76 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Serilog; -using ConsumerChurchMonthWork.MessageBrocker; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Options; +using RabbitMQ.Client; +using ConsumerChurchMonthWork.MessageBrocker.Config; +using ConsumerChurchMonthWork.MessageBrocker.Consumer; IConfigurationRoot configuration; Serilog.ILogger logger; -ServiceCollection serviceCollection = new ServiceCollection(); -ConfigureServices(serviceCollection); +//ServiceCollection serviceCollection = new ServiceCollection(); +//ConfigureServices(serviceCollection); -//var churchId = 1; -//var competence = "05-2023"; +//void ConfigureServices(IServiceCollection serviceCollection) +//{ +logger = new LoggerConfiguration() +.WriteTo.Console() +.CreateLogger(); -//IDataBase dataBase = new MysqlDataBase(configuration); +configuration = new ConfigurationBuilder() + .SetBasePath(Directory.GetCurrentDirectory()) + .AddJsonFile("appsettings.json", false) + .Build(); -//var report = new Report(dataBase, churchId, competence); -//var listMonthleClosing = report.Generate(); +// serviceCollection.AddSingleton(configuration); +// serviceCollection.AddSingleton(logger); +// serviceCollection.AddHostedService(); +//} -//var jsonObj = JsonSerializer.Serialize(listMonthleClosing.Result); -//var returnList = JsonSerializer.Deserialize>(jsonObj); +var host = Host.CreateDefaultBuilder(args) + .ConfigureServices(services => + { + services.AddSingleton(configuration); + services.AddSingleton(logger); + services.Configure(configuration.GetSection("MessageBroker")); -void ConfigureServices(IServiceCollection serviceCollection) -{ - logger = new LoggerConfiguration() - .WriteTo.Console() - .CreateLogger(); + services.AddSingleton(serviceProvider => + { + RabbitMQConfiguration rabbitMQConfiguration = + serviceProvider.GetRequiredService>().Value; - configuration = new ConfigurationBuilder() - .SetBasePath(Directory.GetCurrentDirectory()) - .AddJsonFile("appsettings.json", false) - .Build(); + var factory = new ConnectionFactory + { + HostName = rabbitMQConfiguration.Host, + UserName = rabbitMQConfiguration.Username, + Password = rabbitMQConfiguration.Password, + Port = rabbitMQConfiguration.Port + }; - serviceCollection.AddSingleton(configuration); - serviceCollection.AddSingleton(logger); -} + IConnection connection = factory.CreateConnection(); + return connection; + }); + services.AddHostedService(serviceProvider => + { + var config = serviceProvider.GetRequiredService>(); + IConnection connection = serviceProvider.GetRequiredService(); -RabbitMq rabbit = new RabbitMq(configuration, logger); -rabbit.StartConsumer(); \ No newline at end of file + return new NewUserCreatedListerner( + connection.CreateModel(), + logger + ); + }); + + + + }) + .Build(); + +await host.RunAsync(); + +//RabbitMq rabbit = new RabbitMq(configuration, logger); +//rabbit.StartConsumer(); \ No newline at end of file diff --git a/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/Properties/launchSettings.json b/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/Properties/launchSettings.json new file mode 100644 index 00000000..1f216e94 --- /dev/null +++ b/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/Properties/launchSettings.json @@ -0,0 +1,11 @@ +{ + "profiles": { + "ConsumerChurchMonthWork": { + "commandName": "Project", + "environmentVariables": { + "PASSEMAIL": "#Sojesussalva", + "KEYUSERCREATED": "AAECAwQFBgcICQoLDA0ODw==" + } + } + } +} \ No newline at end of file diff --git a/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/Report.cs b/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/Report.cs index 682fdd91..8517b41e 100644 --- a/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/Report.cs +++ b/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/Report.cs @@ -1,4 +1,4 @@ -using ConsumerChurchMonthWork.Repository; +using ConsumerChurchMonthWork.Repository.Connections; namespace ConsumerChurchMonthWork; public class Report @@ -15,7 +15,7 @@ public Report(IDataBase repository, int churchId, string competence) public string Competence { get; private set; } - public async Task> Generate() + public async Task?> Generate() { if (ValidateProperties()) return null; diff --git a/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/Repository/IDataBase.cs b/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/Repository/Connections/IDataBase.cs similarity index 64% rename from Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/Repository/IDataBase.cs rename to Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/Repository/Connections/IDataBase.cs index a0817895..e0c09c65 100644 --- a/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/Repository/IDataBase.cs +++ b/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/Repository/Connections/IDataBase.cs @@ -1,7 +1,8 @@ using Entitie = ConsumerChurchMonthWork.Entitie; -namespace ConsumerChurchMonthWork.Repository; +namespace ConsumerChurchMonthWork.Repository.Connections; -public interface IDataBase { +public interface IDataBase +{ public Task> SelectReport(string churchId, string month, string year); } diff --git a/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/Repository/MysqlDataBase.cs b/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/Repository/Connections/MysqlDataBase.cs similarity index 68% rename from Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/Repository/MysqlDataBase.cs rename to Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/Repository/Connections/MysqlDataBase.cs index d17c669c..1c54b824 100644 --- a/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/Repository/MysqlDataBase.cs +++ b/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/Repository/Connections/MysqlDataBase.cs @@ -2,8 +2,9 @@ using Dapper; using Microsoft.Extensions.Configuration; using MySql.Data.MySqlClient; +using ConsumerChurchMonthWork.Repository.Queries; -namespace ConsumerChurchMonthWork.Repository; +namespace ConsumerChurchMonthWork.Repository.Connections; public class MysqlDataBase : IDataBase { @@ -21,7 +22,7 @@ public MysqlDataBase(IConfiguration configuration) private async Task> ExecuteQuery(string query) { - var obj = _mysqlConnection.Query(query); + var obj = await _mysqlConnection.QueryAsync(query); return obj; } @@ -32,12 +33,12 @@ public MysqlDataBase(IConfiguration configuration) public async Task> SelectReport(string churchId, string month, string year) { - var outFlow = await ExecuteQuery(ReadQueryMonthClosing(churchId, month, year, MonthlyClosing.ReadQueries.MonthlyClosingOutFlow)); - var tithes = await ExecuteQuery(ReadQueryMonthClosing(churchId, month, year, MonthlyClosing.ReadQueries.MonthlyClosingTithes)); - var offering = await ExecuteQuery(ReadQueryMonthClosing(churchId, month, year, MonthlyClosing.ReadQueries.MonthlyClosingOffering)); - var fruits = await ExecuteQuery(ReadQueryMonthClosing(churchId, month, year, MonthlyClosing.ReadQueries.MonthlyClosingFirstFruits)); + var outFlow = await ExecuteQuery(ReadQueryMonthClosing(churchId, month, year, ReadQueries.MonthlyClosingOutFlow)); + var tithes = await ExecuteQuery(ReadQueryMonthClosing(churchId, month, year, ReadQueries.MonthlyClosingTithes)); + var offering = await ExecuteQuery(ReadQueryMonthClosing(churchId, month, year, ReadQueries.MonthlyClosingOffering)); + var fruits = await ExecuteQuery(ReadQueryMonthClosing(churchId, month, year, ReadQueries.MonthlyClosingFirstFruits)); - List unionObjects = new[] {outFlow, tithes, offering, fruits }.SelectMany(x => x).ToList(); + List unionObjects = new[] { outFlow, tithes, offering, fruits }.SelectMany(x => x).ToList(); return unionObjects; } diff --git a/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/Repository/Queries/ReadQueries.cs b/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/Repository/Queries/ReadQueries.cs new file mode 100644 index 00000000..0db66a1b --- /dev/null +++ b/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/Repository/Queries/ReadQueries.cs @@ -0,0 +1,27 @@ +using MonthlyClosing; + +namespace ConsumerChurchMonthWork.Repository.Queries; + +public static class ReadQueries +{ + public static string MonthlyClosingOutFlow(string churchId, string month, string year) + { + var query = Scripts.MonthlyClosingOutFlow; + return string.Format(query, churchId, month, year); + } + public static string MonthlyClosingTithes(string churchId, string month, string year) + { + var query = Scripts.MonthlyClosingTithes; + return string.Format(query, churchId, month, year); + } + public static string MonthlyClosingOffering(string churchId, string month, string year) + { + var query = Scripts.MonthlyClosingOffering; + return string.Format(query, churchId, month, year); + } + public static string MonthlyClosingFirstFruits(string churchId, string month, string year) + { + var query = Scripts.MonthlyClosingFirstFruits; + return string.Format(query, churchId, month, year); + } +} diff --git a/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/Repository/Queries/Scripts.Designer.cs b/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/Repository/Queries/Scripts.Designer.cs new file mode 100644 index 00000000..b40bb1bc --- /dev/null +++ b/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/Repository/Queries/Scripts.Designer.cs @@ -0,0 +1,119 @@ +//------------------------------------------------------------------------------ +// +// O código foi gerado por uma ferramenta. +// Versão de Tempo de Execução:4.0.30319.42000 +// +// As alterações ao arquivo poderão causar comportamento incorreto e serão perdidas se +// o código for gerado novamente. +// +//------------------------------------------------------------------------------ + +namespace MonthlyClosing { + using System; + + + /// + /// Uma classe de recurso de tipo de alta segurança, para pesquisar cadeias de caracteres localizadas etc. + /// + // Essa classe foi gerada automaticamente pela classe StronglyTypedResourceBuilder + // através de uma ferramenta como ResGen ou Visual Studio. + // Para adicionar ou remover um associado, edite o arquivo .ResX e execute ResGen novamente + // com a opção /str, ou recrie o projeto do VS. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Scripts { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Scripts() { + } + + /// + /// Retorna a instância de ResourceManager armazenada em cache usada por essa classe. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MonthlyClosing.Scripts", typeof(Scripts).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Substitui a propriedade CurrentUICulture do thread atual para todas as + /// pesquisas de recursos que usam essa classe de recurso de tipo de alta segurança. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Consulta uma cadeia de caracteres localizada semelhante a SELECT o.Competence, o.Day, 0 as PreviousBalance, 0 as CurrentBalance, + ///k.Description as Title, o.Description, TotalAmount as AmountINputOperation, 0 as AmountOutPutOperation, 0 as TotalOperation, c.Name as Church + ///FROM Church c RIGHT JOIN FirstFruits o ON c.Id = o.ChurchId LEFT JOIN OfferingKind k ON o.OfferingKindId = k.Id + ///WHERE o.Active = true AND c.Id = {0} + ///AND EXTRACT(MONTH FROM o.Day) = {1} AND EXTRACT(YEAR FROM o.DAY) = {2} + ///ORDER BY Day Desc;. + /// + internal static string MonthlyClosingFirstFruits { + get { + return ResourceManager.GetString("MonthlyClosingFirstFruits", resourceCulture); + } + } + + /// + /// Consulta uma cadeia de caracteres localizada semelhante a SELECT o.Competence, o.Day, 0 as PreviousBalance, 0 as CurrentBalance, + ///k.Description as Title, o.Description, TotalAmount as AmountINputOperation, 0 as AmountOutPutOperation, 0 as TotalOperation, c.Name as Church + ///FROM Church c RIGHT JOIN Offering o ON c.Id = o.ChurchId LEFT JOIN OfferingKind k ON o.OfferingKindId = k.Id + ///WHERE o.Active = true AND c.Id = {0} + ///AND EXTRACT(MONTH FROM o.Day) = {1} AND EXTRACT(YEAR FROM o.DAY) = {2} + ///ORDER BY Day Desc;. + /// + internal static string MonthlyClosingOffering { + get { + return ResourceManager.GetString("MonthlyClosingOffering", resourceCulture); + } + } + + /// + /// Consulta uma cadeia de caracteres localizada semelhante a SELECT o.Competence, o.Day, 0 as PreviousBalance, 0 as CurrentBalance, + ///k.Description as Title, o.Description, 0 as AmountINputOperation, TotalAmount as AmountOutPutOperation, 0 as TotalOperation, c.Name as Church + ///FROM Church c RIGHT JOIN OutFlow o ON c.Id = o.ChurchId LEFT JOIN OutFlowKind k ON o.OutFlowKindId = k.Id + ///WHERE o.Authorized = true AND o.Active = true AND c.Id = {0} + ///AND EXTRACT(MONTH FROM o.Day) = {1} AND EXTRACT(YEAR FROM o.DAY) = {2} + ///ORDER BY Day Desc;. + /// + internal static string MonthlyClosingOutFlow { + get { + return ResourceManager.GetString("MonthlyClosingOutFlow", resourceCulture); + } + } + + /// + /// Consulta uma cadeia de caracteres localizada semelhante a SELECT o.Competence, o.Day, 0 as PreviousBalance, 0 as CurrentBalance, + ///k.Description as Title, o.Description, TotalAmount as AmountINputOperation, 0 as AmountOutPutOperation, 0 as TotalOperation, c.Name as Church + ///FROM Church c RIGHT JOIN Tithes o ON c.Id = o.ChurchId LEFT JOIN OfferingKind k ON o.OfferingKindId = k.Id + ///WHERE o.Active = true AND c.Id = {0} + ///AND EXTRACT(MONTH FROM o.Day) = {1} AND EXTRACT(YEAR FROM o.DAY) = {2} + ///ORDER BY Day Desc;. + /// + internal static string MonthlyClosingTithes { + get { + return ResourceManager.GetString("MonthlyClosingTithes", resourceCulture); + } + } + } +} diff --git a/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/Repository/Queries/Scripts.resx b/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/Repository/Queries/Scripts.resx new file mode 100644 index 00000000..cc7f8ee1 --- /dev/null +++ b/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/Repository/Queries/Scripts.resx @@ -0,0 +1,152 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + SELECT o.Competence, o.Day, 0 as PreviousBalance, 0 as CurrentBalance, +k.Description as Title, o.Description, TotalAmount as AmountINputOperation, 0 as AmountOutPutOperation, 0 as TotalOperation, c.Name as Church +FROM Church c RIGHT JOIN FirstFruits o ON c.Id = o.ChurchId LEFT JOIN OfferingKind k ON o.OfferingKindId = k.Id +WHERE o.Active = true AND c.Id = {0} +AND EXTRACT(MONTH FROM o.Day) = {1} AND EXTRACT(YEAR FROM o.DAY) = {2} +ORDER BY Day Desc; + + + SELECT o.Competence, o.Day, 0 as PreviousBalance, 0 as CurrentBalance, +k.Description as Title, o.Description, TotalAmount as AmountINputOperation, 0 as AmountOutPutOperation, 0 as TotalOperation, c.Name as Church +FROM Church c RIGHT JOIN Offering o ON c.Id = o.ChurchId LEFT JOIN OfferingKind k ON o.OfferingKindId = k.Id +WHERE o.Active = true AND c.Id = {0} +AND EXTRACT(MONTH FROM o.Day) = {1} AND EXTRACT(YEAR FROM o.DAY) = {2} +ORDER BY Day Desc; + + + SELECT o.Competence, o.Day, 0 as PreviousBalance, 0 as CurrentBalance, +k.Description as Title, o.Description, 0 as AmountINputOperation, TotalAmount as AmountOutPutOperation, 0 as TotalOperation, c.Name as Church +FROM Church c RIGHT JOIN OutFlow o ON c.Id = o.ChurchId LEFT JOIN OutFlowKind k ON o.OutFlowKindId = k.Id +WHERE o.Authorized = true AND o.Active = true AND c.Id = {0} +AND EXTRACT(MONTH FROM o.Day) = {1} AND EXTRACT(YEAR FROM o.DAY) = {2} +ORDER BY Day Desc; + + + SELECT o.Competence, o.Day, 0 as PreviousBalance, 0 as CurrentBalance, +k.Description as Title, o.Description, TotalAmount as AmountINputOperation, 0 as AmountOutPutOperation, 0 as TotalOperation, c.Name as Church +FROM Church c RIGHT JOIN Tithes o ON c.Id = o.ChurchId LEFT JOIN OfferingKind k ON o.OfferingKindId = k.Id +WHERE o.Active = true AND c.Id = {0} +AND EXTRACT(MONTH FROM o.Day) = {1} AND EXTRACT(YEAR FROM o.DAY) = {2} +ORDER BY Day Desc; + + \ No newline at end of file diff --git a/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/Services/SendEmailNewUser.cs b/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/Services/SendEmailNewUser.cs new file mode 100644 index 00000000..a8deb267 --- /dev/null +++ b/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/Services/SendEmailNewUser.cs @@ -0,0 +1,68 @@ +using ConsumerChurchMonthWork.Entitie; +using ConsumerChurchMonthWork.Models; +using System.Net; +using System.Net.Mail; +using System.Net.Mime; +using System.Security.Cryptography; +using System.Text; + +namespace ConsumerChurchMonthWork.Services; +public class SendEmailNewUser +{ + public async Task SendEmailAsync(UserCreatedMessageDto userCreated) + { + var pass = DescriptyPassword(userCreated.Password); + var body = @$"Ola! seu cadastro foi realizado com sucesso na plafaforma churchManager! + + Guarde sua senha para acessar a aplicação: + senha: {pass}"; + var message = PrepareteMessage(userCreated.EmailAddress, "Cadastro - ChurchManager", body); + + SendEmailBySmtp(message); + } + private string DescriptyPassword(string password) + { + byte[] ivv = new byte[16]; + byte[] buffer = Convert.FromBase64String(password); + + using (Aes aes = Aes.Create()) + { + aes.Key = Encoding.UTF8.GetBytes(Environment.GetEnvironmentVariable("KEYUSERCREATED")); + aes.IV = ivv; + ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV); + + using MemoryStream memoryStream = new(buffer); + using CryptoStream cryptoStream = new((Stream)memoryStream, decryptor, CryptoStreamMode.Read); + using (StreamReader streamReader = new((Stream)cryptoStream)) + { + var pass = streamReader.ReadToEnd(); + return pass; + } + } + } + + private MailMessage PrepareteMessage(string emailTo, string subject, string body) + { + var mail = new MailMessage(); + mail.From = new MailAddress(Environment.GetEnvironmentVariable("CHURCHMANAGEREMAIL")); + mail.To.Add(emailTo); + mail.Subject = subject; + mail.Body = body; + mail.IsBodyHtml = true; + + return mail; + } + + private void SendEmailBySmtp(MailMessage message) + { + SmtpClient smtpClient = new SmtpClient("smtp.office365.com"); + smtpClient.Host = "smtp.office365.com"; + smtpClient.Port = 587; + smtpClient.EnableSsl = true; + smtpClient.Timeout = 50000; + smtpClient.UseDefaultCredentials = false; + smtpClient.Credentials = new NetworkCredential(Environment.GetEnvironmentVariable("CHURCHMANAGEREMAIL"), Environment.GetEnvironmentVariable("PASSEMAIL")); + smtpClient.Send(message); + smtpClient.Dispose(); + } +} diff --git a/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/appsettings.json b/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/appsettings.json index ac41ff05..f03e72d4 100644 --- a/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/appsettings.json +++ b/Operations/Consumers/ChurchMonthWork/ConsumerChurchMonthWork/appsettings.json @@ -9,14 +9,11 @@ "ConnectionStrings": { "DataConnection": "server=localhost;port=3306;database=ChurchCashFlow;user=root;password=sinqia123" }, - "MonthlyClosing": { - "Exchange": "church_month_work", + "MessageBroker": { "Host": "localhost", "VirtualHost": "", "Port": "5672", "UserName": "sinqia", - "Password": "sinqia123", - "RoutingKey": "month_work", - "Queue": "church_month_work" + "Password": "sinqia123" } } \ No newline at end of file diff --git a/Registration/Dockerfile b/Registration/Dockerfile index faec0e0e..0c5c21a6 100644 --- a/Registration/Dockerfile +++ b/Registration/Dockerfile @@ -1,7 +1,7 @@ -FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base WORKDIR /app -FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build WORKDIR /src COPY ["src/Application/Registration.API/Registration.API.csproj", "src/Application/Registration.API/"] COPY ["src/Service/Registration.DependencyInjection/Registration.DependencyInjection.csproj", "src/Service/Registration.DependencyInjection/"] @@ -14,6 +14,7 @@ COPY ["src/Infrastructure/Registration.Resources/Registration.Resources.csproj", COPY ["src/Service/Registration.Mapper/Registration.Mapper.csproj", "src/Service/Registration.Mapper/"] COPY ["src/Service/MessageBroker/MessageBroker.csproj", "src/Service/MessageBroker/"] COPY ["src/Infrastructure/Registration.Infrastructure/Registration.Infrastructure.csproj", "src/Infrastructure/Registration.Infrastructure/"] +COPY ["src/Service/CloudServices/CloudServices.csproj", "src/Service/CloudServices/"] RUN dotnet restore "src/Application/Registration.API/Registration.API.csproj" COPY . . diff --git a/Registration/docker-compose.dev.yml b/Registration/docker-compose.dev.yml index 19c36f2b..f1598e91 100644 --- a/Registration/docker-compose.dev.yml +++ b/Registration/docker-compose.dev.yml @@ -8,7 +8,7 @@ services: dockerfile: Dockerfile command: dotnet run ports: - - 7070:70 + - 7171:8181 environment: - ASPNETCORE_ENVIRONMENT=Development diff --git a/Registration/docker-compose.uat.yml b/Registration/docker-compose.uat.yml deleted file mode 100644 index a7bd3726..00000000 --- a/Registration/docker-compose.uat.yml +++ /dev/null @@ -1,20 +0,0 @@ -version: '3.4' - -services: - churchmanager: - container_name: churchmanager-uat - build: - context: ./ - dockerfile: Dockerfile - command: dotnet run - ports: - - 8080:80 - environment: - - ASPNETCORE_ENVIRONMENT=uat - - networks: - - netchurchmanager - -networks: - netchurchmanager: - driver: bridge \ No newline at end of file diff --git a/Registration/src/Application/Registration.API/Program.cs b/Registration/src/Application/Registration.API/Program.cs index 32409335..cb66ef6d 100644 --- a/Registration/src/Application/Registration.API/Program.cs +++ b/Registration/src/Application/Registration.API/Program.cs @@ -22,14 +22,15 @@ builder.LoadContainers(); builder.LoadConfigAuth(); builder.AddPolicyPermission(); -//builder.LoadEndPoint(); + +builder.LoadEndPoint(); var app = builder.Build(); app.UseSwagger(); app.UseSwaggerUI(); -//app.UseHttpsRedirection(); +app.UseHttpsRedirection(); app.UseAuthorization(); @@ -41,4 +42,4 @@ InitialInformation.ShowInitial(); -app.Run(); \ No newline at end of file +app.Run("http://*:8181"); \ No newline at end of file diff --git a/Registration/src/Domain/Registration.DomainCore/Events/UserCreatedEvent.cs b/Registration/src/Domain/Registration.DomainCore/Events/UserCreatedEvent.cs index 5201b430..2518faae 100644 --- a/Registration/src/Domain/Registration.DomainCore/Events/UserCreatedEvent.cs +++ b/Registration/src/Domain/Registration.DomainCore/Events/UserCreatedEvent.cs @@ -1,12 +1,43 @@ -namespace Registration.DomainCore.Events; + +using Microsoft.AspNetCore.DataProtection.KeyManagement; +using System.Security.Cryptography; +using System.Text; + +namespace Registration.DomainCore.Events; public class UserCreatedEvent : DomainBaseEvents { public int Id { get; set; } public string EmailAddress { get; set; } = null!; + public string Password { get; set; } = null!; - public UserCreatedEvent(int id, string emailAddress) : base() + public UserCreatedEvent(int id, string emailAddress, string passwordNotEncrypt) : base() { Id = id; EmailAddress = emailAddress; + EncryptPassword(passwordNotEncrypt); + } + private void EncryptPassword(string passwordNotEncrypt) + { + byte[] iv = new byte[16]; + + using (Aes aes = Aes.Create()) + { + aes.Key = Encoding.UTF8.GetBytes(Environment.GetEnvironmentVariable("KEYUSERCREATED")); + aes.IV = iv; + + ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV); + + using (MemoryStream ms = new MemoryStream()) + { + using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write)) + { + using (StreamWriter sw = new StreamWriter(cs)) + { + sw.Write(passwordNotEncrypt); + } + } + Password = Convert.ToBase64String(ms.ToArray()); + } + } } } diff --git a/Registration/src/Repository/Registration.Repository/Mapping/UserMap.cs b/Registration/src/Repository/Registration.Repository/Mapping/UserMap.cs index 42d31aee..ced03f92 100644 --- a/Registration/src/Repository/Registration.Repository/Mapping/UserMap.cs +++ b/Registration/src/Repository/Registration.Repository/Mapping/UserMap.cs @@ -50,8 +50,10 @@ public void Configure(EntityTypeBuilder builder) .IsRequired() .HasColumnName("email") .HasColumnType("VARCHAR") - .IsRequired(false) .HasMaxLength(255); + + emailBuilder.HasIndex(e => e.Address) + .IsUnique(); }); builder.HasIndex(x => x.Code, "IX_User_Code") diff --git a/Registration/src/Service/MessageBroker/BaseMessageBrokerClient.cs b/Registration/src/Service/MessageBroker/BaseMessageBrokerClient.cs index af7700ce..0149a2d6 100644 --- a/Registration/src/Service/MessageBroker/BaseMessageBrokerClient.cs +++ b/Registration/src/Service/MessageBroker/BaseMessageBrokerClient.cs @@ -18,13 +18,16 @@ protected BaseMessageBrokerClient(IConfiguration configuration) } public string Exchange { get; protected set; } = string.Empty; + public string ExchangeDeadLeatter { get; protected set; } = string.Empty; public string Host { get; protected set; } = string.Empty; public string VirtualHost { get; protected set; } = string.Empty; public string Port { get; protected set; } = string.Empty; public string UserName { get; protected set; } = string.Empty; public string Password { get; protected set; } = string.Empty; public string Queue { get; protected set; } = string.Empty; + public string QueueDeadLeatter { get; protected set; } = string.Empty; public string RoutingKey { get; protected set; } = string.Empty; + public string RoutingKeyDeadLeatter { get; protected set; } = string.Empty; public byte[] BodyMessage { get; protected set; } = new byte[0]; protected abstract byte[] BuildMessage(); diff --git a/Registration/src/Service/MessageBroker/Messages/NewUserCreated.cs b/Registration/src/Service/MessageBroker/Messages/NewUserCreated.cs index 96f1a5bc..42d009e8 100644 --- a/Registration/src/Service/MessageBroker/Messages/NewUserCreated.cs +++ b/Registration/src/Service/MessageBroker/Messages/NewUserCreated.cs @@ -27,7 +27,8 @@ protected override byte[] BuildMessage() { _userCreated.Id, _userCreated.EmailAddress, - _userCreated.OcurredOn + _userCreated.OcurredOn, + _userCreated.Password }; var serialize = JsonSerializer.Serialize(objBody); @@ -43,8 +44,11 @@ protected override void LoadConfig() UserName = _configuration["MessageBroker:UserName"]!; Password = _configuration["MessageBroker:Password"]!; Exchange = _configuration["MessageBroker:UserCreated:Exchange"]!; + ExchangeDeadLeatter = $"{Exchange}_dead_leatter"; RoutingKey = _configuration["MessageBroker:UserCreated:RoutingKey"]!; + RoutingKeyDeadLeatter = $"{RoutingKey}_dead_leatter"; Queue = _configuration["MessageBroker:UserCreated:Queue"]!; + QueueDeadLeatter = $"{Queue}_dead_leatter"; BodyMessage = BuildMessage(); } diff --git a/Registration/src/Service/MessageBroker/RabbitMqClient.cs b/Registration/src/Service/MessageBroker/RabbitMqClient.cs index b78db4d1..a5296d4c 100644 --- a/Registration/src/Service/MessageBroker/RabbitMqClient.cs +++ b/Registration/src/Service/MessageBroker/RabbitMqClient.cs @@ -11,6 +11,7 @@ public class RabbitMqClient : IMessageBrokerClient where T : BaseMessageBroke private IConnection _connection; private IModel _channel; private string _queueName; + private string _queueNameDeadLeatter; public RabbitMqClient(T modelMessage) { @@ -21,8 +22,19 @@ public RabbitMqClient(T modelMessage) _connection = connFactory.CreateConnection(); _channel = _connection.CreateModel(); + _channel.ExchangeDeclare($"{ModelMessage.Exchange}_dead_leatter", ExchangeType.Topic, ModelMessage.Durable, ModelMessage.AutoDelete, null); + _queueNameDeadLeatter = _channel.QueueDeclare($"{ModelMessage.Queue}_dead_leatter", ModelMessage.Durable, ModelMessage.Exclusive, ModelMessage.AutoDelete, null); + _channel.QueueBind(_queueNameDeadLeatter, ModelMessage.ExchangeDeadLeatter, ModelMessage.RoutingKeyDeadLeatter, null); + + _channel.ExchangeDeclare(ModelMessage.Exchange, ExchangeType.Topic, ModelMessage.Durable, ModelMessage.AutoDelete, null); - _queueName = _channel.QueueDeclare(ModelMessage.Queue, ModelMessage.Durable, ModelMessage.Exclusive, ModelMessage.AutoDelete, null); + var args = new Dictionary + { + { "x-dead-letter-exchange", $"{ModelMessage.ExchangeDeadLeatter}" }, + { "x-dead-letter-routing-key", ModelMessage.RoutingKeyDeadLeatter } + }; + _queueName = _channel.QueueDeclare(ModelMessage.Queue, ModelMessage.Durable, ModelMessage.Exclusive, ModelMessage.AutoDelete, args); + _channel.QueueBind(_queueName, ModelMessage.Exchange, ModelMessage.RoutingKey, null); _connection.ConnectionShutdown += ConnectionShutDown; } @@ -51,7 +63,7 @@ private bool someValueIsEmptyOrNull() => (string.IsNullOrEmpty(ModelMessage.Host public void Publish() { - _channel.QueueBind(_queueName, ModelMessage.Exchange, ModelMessage.RoutingKey, null); + _channel.BasicPublish(ModelMessage.Exchange, ModelMessage.RoutingKey, null, ModelMessage.BodyMessage); } diff --git a/Registration/src/Service/Registration.Handlers/Handlers/Registrations/LoginHandler.cs b/Registration/src/Service/Registration.Handlers/Handlers/Registrations/LoginHandler.cs index fa909fcc..92f6dfa5 100644 --- a/Registration/src/Service/Registration.Handlers/Handlers/Registrations/LoginHandler.cs +++ b/Registration/src/Service/Registration.Handlers/Handlers/Registrations/LoginHandler.cs @@ -44,6 +44,8 @@ public async Task Login(EditUserLogin userLogin) _statusCode = (int)CodeLib.INTERNAL_SERVER_ERROR; _logger.Error("Fail in login attemp {error} - AC1101A", ex.Message); _viewModel!.SetErrors("Internal Error - AC1101A"); + + return _viewModel; } _logger.Information("Login successul"); diff --git a/Registration/src/Service/Registration.Handlers/Handlers/Registrations/UserHandler.cs b/Registration/src/Service/Registration.Handlers/Handlers/Registrations/UserHandler.cs index 8d1fe182..fcc7ccfa 100644 --- a/Registration/src/Service/Registration.Handlers/Handlers/Registrations/UserHandler.cs +++ b/Registration/src/Service/Registration.Handlers/Handlers/Registrations/UserHandler.cs @@ -31,9 +31,9 @@ public UserHandler(IUserRepository context, IMapper mapper, CViewModel viewModel _logger = logger; } - private void SendNewUserCreated(User user) + private void SendNewUserCreated(User user, string passwordNotEncrypt) { - var @event = new NewUserCreated(EnvironmentConfiguration.ConfigurationRoot, new UserCreatedEvent(user.Id, user.Email.Address)); + var @event = new NewUserCreated(EnvironmentConfiguration.ConfigurationRoot, new UserCreatedEvent(user.Id, user.Email.Address, passwordNotEncrypt)); @event.PreparePublish(); } @@ -123,7 +123,7 @@ public async Task Create(EditUserCreateDto dto) _viewModel.SetData(userReadDto); _logger.Information("The user {userName} was successfully created", user.Name); - SendNewUserCreated(user); + SendNewUserCreated(user, dto.PasswordHash); return _viewModel; } diff --git a/Registration/src/Service/Registration.Mapper/DTOs/Registration/User/ReadUserDto.cs b/Registration/src/Service/Registration.Mapper/DTOs/Registration/User/ReadUserDto.cs index 87bd0299..dc8339de 100644 --- a/Registration/src/Service/Registration.Mapper/DTOs/Registration/User/ReadUserDto.cs +++ b/Registration/src/Service/Registration.Mapper/DTOs/Registration/User/ReadUserDto.cs @@ -6,6 +6,7 @@ public class ReadUserDto : ModelDto public string Code { get; set; } = string.Empty; public string Name { get; set; } = string.Empty; public string Church { get; set; } = string.Empty; + public string Email { get; set; } = string.Empty; public int ChurchId { get; set; } public List UserRoles { get; set; } } diff --git a/Registration/src/Service/Registration.Mapper/Profiles/UsersProfile.cs b/Registration/src/Service/Registration.Mapper/Profiles/UsersProfile.cs index 151c86b9..e94bd37d 100644 --- a/Registration/src/Service/Registration.Mapper/Profiles/UsersProfile.cs +++ b/Registration/src/Service/Registration.Mapper/Profiles/UsersProfile.cs @@ -16,7 +16,9 @@ public UsersProfile() ) .ForMember(dest => dest.UserRoles, map => map.MapFrom(src => src.UserRoles.Select(x => x.Role).Select(r => r.Name)) - ); + ).ForMember(dest => dest.Email, map => + map.MapFrom(src => src.Email.Address) + ); CreateMap(); CreateMap();