├── .gitattributes ├── .github └── FUNDING.yml ├── .gitignore ├── Calabonga.Chat.API ├── .editorconfig ├── Calabonga.Chat.API.sln └── Calabonga.Chat.API │ ├── Calabonga.Chat.API.Data │ ├── ApplicationDbContext.cs │ ├── Base │ │ └── DbContextBase.cs │ ├── Calabonga.Chat.API.Data.csproj │ ├── DatabaseInitialization │ │ └── DatabaseInitializer.cs │ ├── IApplicaitonDbContext.cs │ └── ModelConfigurations │ │ ├── Base │ │ ├── AuditableModelConfigurationBase.cs │ │ └── IdentityModelConfigurationBase.cs │ │ └── LogModelConfiguration.cs │ ├── Calabonga.Chat.API.Entities │ ├── Calabonga.Chat.API.Entities.csproj │ ├── Core │ │ ├── AppData.Common.cs │ │ ├── AppData.Exceptions.cs │ │ ├── AppData.Messages.cs │ │ ├── EmailMessage.cs │ │ ├── IMailMessage.cs │ │ ├── SendEmailResult.cs │ │ └── StringExtensions.cs │ └── Log.cs │ └── Calabonga.Chat.API.Web │ ├── AppStart │ ├── ConfigureServices │ │ ├── ConfigureServicesAuthentication.cs │ │ ├── ConfigureServicesBase.cs │ │ ├── ConfigureServicesControllers.cs │ │ ├── ConfigureServicesCors.cs │ │ ├── ConfigureServicesMediator.cs │ │ ├── ConfigureServicesSignalR.cs │ │ ├── ConfigureServicesSwagger.cs │ │ └── ConfigureServicesValidators.cs │ ├── Configures │ │ ├── ConfigureCommon.cs │ │ └── ConfigureEndpoints.cs │ └── SwaggerFilters │ │ └── ApplySummariesOperationFilter.cs │ ├── Calabonga.Chat.API.Web.csproj │ ├── Controllers │ ├── LogsReadonly2Controller.cs │ ├── LogsReadonlyController.cs │ ├── LogsWritable2Controller.cs │ └── LogsWritableController.cs │ ├── Extensions │ ├── ApplicationBuilderExtensions.cs │ ├── AssemblyExtensions.cs │ ├── DateTimeExtensions.cs │ └── EntityValidatorExtensions.cs │ ├── Hubs │ ├── ChatConnection.cs │ ├── ChatManager.cs │ ├── ChatUser.cs │ ├── CommunicationHub.cs │ └── ICommunicationHub.cs │ ├── Infrastructure │ ├── Attributes │ │ ├── SwaggerFormAttribute.cs │ │ ├── SwaggerGroupAttribute.cs │ │ └── ValidateModelStateAttribute.cs │ ├── Auth │ │ ├── AuthorizationPolicyProvider.cs │ │ ├── IdentityHelper.cs │ │ ├── MicroservicePermissionHandler.cs │ │ └── PermissionRequirement.cs │ ├── DependencyInjection │ │ └── CommonRegistrations.cs │ ├── Engine │ │ ├── EntityManagers │ │ │ └── LogManager.cs │ │ ├── EntityValidators │ │ │ └── LogValidator.cs │ │ └── ViewModelFactories │ │ │ └── LogViewModelFactory.cs │ ├── EventLogs │ │ ├── EventNumbers.cs │ │ └── LoggerExtensions.cs │ ├── Factories │ │ └── Base │ │ │ ├── IViewModel.cs │ │ │ ├── IViewModelFactory.cs │ │ │ └── ViewModelFactory.cs │ ├── Helpers │ │ ├── AsyncHelper.cs │ │ ├── EmailHelper.cs │ │ ├── EnumHelper.cs │ │ ├── Utilites.cs │ │ └── ValidationContextHelper.cs │ ├── Mappers │ │ ├── Base │ │ │ ├── IAutoMapper.cs │ │ │ ├── MapperConfigurationBase.cs │ │ │ └── PagedListConverter.cs │ │ └── LogMapperConfiguration.cs │ ├── Services │ │ ├── CacheService.cs │ │ ├── ICacheService.cs │ │ ├── ILogService.cs │ │ └── LogService.cs │ ├── Settings │ │ ├── Base │ │ │ └── ServiceBase.cs │ │ └── CurrentAppSettings.cs │ └── Validations │ │ └── LogValidator.cs │ ├── Mediator │ ├── Behaviors │ │ └── ValidationBehavior.cs │ ├── LogsReadonly │ │ ├── GetRoles.cs │ │ ├── LogGetById.cs │ │ └── LogGetPaged.cs │ └── LogsWritable │ │ ├── LogDeleteItem.cs │ │ ├── LogPostItem.cs │ │ └── LogPutItem.cs │ ├── Middlewares │ ├── ETagMiddleware.cs │ └── ErrorHandle.cs │ ├── Program.cs │ ├── Startup.cs │ ├── ViewModels │ └── LogViewModels │ │ ├── LogCreateViewModel.cs │ │ ├── LogUpdateViewModel.cs │ │ └── LogViewModel.cs │ ├── appsettings.Development.json │ ├── appsettings.Production.json │ └── appsettings.json ├── Calabonga.Chat.AuthServer ├── Calabonga.Chat.AuthServer.sln └── Calabonga.Chat.AuthServer │ ├── Calabonga.Chat.AuthServer.Data │ ├── ApplicationDbContext.cs │ ├── ApplicationRole.cs │ ├── ApplicationUser.cs │ ├── ApplicationUserProfile.cs │ ├── ApplicationUserStore.cs │ ├── Base │ │ └── DbContextBase.cs │ ├── Calabonga.Chat.AuthServer.Data.csproj │ ├── DatabaseInitialization │ │ ├── DatabaseInitializer.cs │ │ └── UserHelper.cs │ ├── IApplicaitonDbContext.cs │ ├── MicroservicePermission.cs │ └── ModelConfigurations │ │ ├── ApplicationUserModelConfiguration.cs │ │ ├── ApplicationUserProfileModelConfiguration.cs │ │ ├── Base │ │ ├── AuditableModelConfigurationBase.cs │ │ └── IdentityModelConfigurationBase.cs │ │ ├── LogModelConfiguration.cs │ │ └── MicroservicePermissionModelConfiguration.cs │ ├── Calabonga.Chat.AuthServer.Entities │ ├── Calabonga.Chat.AuthServer.Entities.csproj │ ├── Core │ │ ├── AppData.Common.cs │ │ ├── AppData.Exceptions.cs │ │ └── AppData.Messages.cs │ └── Log.cs │ └── Calabonga.Chat.AuthServer.Web │ ├── AppStart │ ├── ConfigureServices │ │ ├── ConfigureServicesAuthentication.cs │ │ ├── ConfigureServicesBase.cs │ │ ├── ConfigureServicesControllers.cs │ │ ├── ConfigureServicesCors.cs │ │ ├── ConfigureServicesMediator.cs │ │ ├── ConfigureServicesSwagger.cs │ │ └── ConfigureServicesValidators.cs │ ├── Configures │ │ ├── ConfigureAuthentication.cs │ │ ├── ConfigureCommon.cs │ │ └── ConfigureEndpoints.cs │ ├── IdentityServerConfig.cs │ ├── MapperRegistration.cs │ └── SwaggerFilters │ │ └── ApplySummariesOperationFilter.cs │ ├── Calabonga.Chat.AuthServer.Web.csproj │ ├── Controllers │ ├── Account2Controller.cs │ ├── AccountController.cs │ ├── AuthenticationController.cs │ ├── LogsReadOnlyController.cs │ ├── LogsReadonly2Controller.cs │ ├── LogsWritable2Controller.cs │ └── LogsWritableController.cs │ ├── Extensions │ ├── ApplicationBuilderExtensions.cs │ ├── AssemblyExtensions.cs │ ├── DateTimeExtensions.cs │ ├── EntityValidatorExtensions.cs │ └── IdentityExtensions.cs │ ├── Infrastructure │ ├── Attributes │ │ ├── SwaggerFormAttribute.cs │ │ ├── SwaggerGroupAttribute.cs │ │ └── ValidateModelStateAttribute.cs │ ├── Auth │ │ ├── ApplicationClaimsPrincipalFactory.cs │ │ ├── AuthData.cs │ │ ├── AuthorizationPolicyExtensions.cs │ │ ├── AuthorizationPolicyProvider.cs │ │ ├── IdentityServerCorsPolicy.cs │ │ ├── MicroservicePermissionHandler.cs │ │ ├── PermissionRequirement.cs │ │ └── UserIdentity.cs │ ├── DependencyInjection │ │ └── CommonRegistrations.cs │ ├── Engine │ │ ├── EntityManagers │ │ │ └── LogManager.cs │ │ ├── EntityValidators │ │ │ └── LogValidator.cs │ │ └── ViewModelFactories │ │ │ └── LogViewModelFactory.cs │ ├── EventLogs │ │ ├── EventNumbers.cs │ │ └── LoggerExtensions.cs │ ├── Helpers │ │ └── ValidationContextHelper.cs │ ├── Mappers │ │ ├── ApplicationUserProfileMapperConfiguration.cs │ │ ├── Base │ │ │ ├── IAutoMapper.cs │ │ │ ├── MapperConfigurationBase.cs │ │ │ └── PagedListConverter.cs │ │ ├── LogMapperConfiguration.cs │ │ └── UserMapperConfiguration.cs │ ├── Services │ │ ├── AccountService.cs │ │ ├── CacheService.cs │ │ ├── IAccountService.cs │ │ ├── ICacheService.cs │ │ └── IdentityProfileService.cs │ └── Settings │ │ └── CurrentAppSettings.cs │ ├── Mediator │ ├── Account │ │ ├── Profile.cs │ │ └── Register.cs │ ├── Behaviors │ │ └── ValidatorBehavior.cs │ ├── LogsReadonly │ │ ├── GetRoles.cs │ │ ├── LogGetById.cs │ │ └── LogGetPaged.cs │ └── LogsWritable │ │ ├── LogDeleteItem.cs │ │ ├── LogPostItem.cs │ │ └── LogPutItem.cs │ ├── Middlewares │ ├── ETagMiddleware.cs │ └── ErrorHandle.cs │ ├── Program.cs │ ├── Startup.cs │ ├── ViewModels │ ├── AccountViewModels │ │ ├── LoginViewModel.cs │ │ ├── RegisterViewModel.cs │ │ ├── RegisterViewModelValidator.cs │ │ └── UserProfileViewModel.cs │ └── LogViewModels │ │ ├── LogCreateViewModel.cs │ │ ├── LogUpdateViewModel.cs │ │ └── LogViewModel.cs │ ├── Views │ ├── Authentication │ │ └── Login.cshtml │ ├── Shared │ │ └── _Layout.cshtml │ ├── _ViewImports.cshtml │ └── _ViewStart.cshtml │ ├── appsettings.Development.json │ ├── appsettings.Production.json │ ├── appsettings.json │ ├── tempkey.jwk │ └── tempkey.rsa ├── Calabonga.Chat.ConsoleClient ├── Calabonga.Chat.ConsoleClient.sln └── Calabonga.Chat.ConsoleClient │ ├── Calabonga.Chat.ConsoleClient.csproj │ ├── MessageHelper.cs │ ├── Program.cs │ └── TokenHelper │ ├── SecurityError.cs │ ├── SecurityToken.cs │ └── TokenLoader.cs ├── Calabonga.Chat.JavaScript ├── Calabonga.Chat.JavaScript.sln └── Calabonga.Chat.JavaScript │ ├── Calabonga.Chat.JavaScript.csproj │ ├── Program.cs │ ├── Startup.cs │ ├── appsettings.Development.json │ ├── appsettings.json │ ├── libman.json │ └── wwwroot │ ├── Index.html │ ├── app.js │ ├── bootstrap │ ├── css │ │ └── bootstrap.min.css │ └── js │ │ └── bootstrap.min.js │ └── microsoft-signalr │ ├── signalr.js │ └── signalr.min.js ├── Calabonga.Chat.WinFormClient ├── Calabonga.Chat.WinFormClient.sln └── Calabonga.Chat.WinFormClient │ ├── AppData.cs │ ├── Calabonga.Chat.WinFormClient.csproj │ ├── Form1.Designer.cs │ ├── Form1.cs │ ├── Form1.resx │ ├── Program.cs │ └── TokenHelper │ ├── SecurityError.cs │ ├── SecurityToken.cs │ └── TokenLoader.cs ├── Calabonga.Chat.WpfClient ├── Calabonga.Chat.WpfClient.sln └── Calabonga.Chat.WpfClient │ ├── App.xaml │ ├── App.xaml.cs │ ├── AssemblyInfo.cs │ ├── Calabonga.Chat.WpfClient.csproj │ ├── Converters │ └── BoolToVisibilityConverter.cs │ ├── TokenHelper │ ├── SecurityError.cs │ ├── SecurityToken.cs │ └── TokenLoader.cs │ ├── ViewModels │ └── ShellViewModel.cs │ └── Views │ ├── Shell.xaml │ └── Shell.xaml.cs ├── LICENSE ├── README.md ├── WpfClient.exe - Shortcut.lnk ├── start_AuthServer.cmd ├── start_ChatApiService_api.cmd ├── start_ConsoleClients_user1.cmd ├── start_ConsoleClients_user2.cmd └── start_ConsoleClients_user3.cmd /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | custom: https://www.calabonga.net/site/thanks 2 | -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Data/ApplicationDbContext.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.Chat.API.Data.Base; 2 | using Calabonga.Chat.API.Entities; 3 | using Microsoft.EntityFrameworkCore; 4 | 5 | namespace Calabonga.Chat.API.Data 6 | { 7 | /// 8 | /// Database for application 9 | /// 10 | public class ApplicationDbContext : DbContextBase, IApplicationDbContext 11 | { 12 | /// 13 | public ApplicationDbContext(DbContextOptions options) : base(options) 14 | { 15 | } 16 | 17 | #region System 18 | 19 | public DbSet Logs { get; set; } 20 | 21 | #endregion 22 | } 23 | } -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Data/Calabonga.Chat.API.Data.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net5.0 5 | enable 6 | 5.0 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | all 15 | runtime; build; native; contentfiles; analyzers; buildtransitive 16 | 17 | 18 | 19 | all 20 | runtime; build; native; contentfiles; analyzers; buildtransitive 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Data/DatabaseInitialization/DatabaseInitializer.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.DependencyInjection; 2 | using System; 3 | 4 | namespace Calabonga.Chat.API.Data.DatabaseInitialization 5 | { 6 | /// 7 | /// Database Initializer 8 | /// 9 | public static class DatabaseInitializer 10 | { 11 | public static async void Seed(IServiceProvider serviceProvider) 12 | { 13 | using var scope = serviceProvider.CreateScope(); 14 | await using var context = scope.ServiceProvider.GetService(); 15 | 16 | // Should be uncomment when using UseSqlServer() settings or any other provider. 17 | // This is should not be used when UseInMemoryDatabase() 18 | // context.Database.Migrate(); 19 | 20 | // TODO: Add your seed data here 21 | 22 | if (context.ChangeTracker.HasChanges()) 23 | { 24 | await context.SaveChangesAsync(); 25 | } 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Data/IApplicaitonDbContext.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.Chat.API.Entities; 2 | using Microsoft.EntityFrameworkCore; 3 | using Microsoft.EntityFrameworkCore.ChangeTracking; 4 | using Microsoft.EntityFrameworkCore.Infrastructure; 5 | 6 | namespace Calabonga.Chat.API.Data 7 | { 8 | /// 9 | /// Abstraction for Database (EntityFramework) 10 | /// 11 | public interface IApplicationDbContext 12 | { 13 | #region System 14 | 15 | DbSet Logs { get; set; } 16 | 17 | DatabaseFacade Database { get; } 18 | 19 | ChangeTracker ChangeTracker { get; } 20 | 21 | DbSet Set() where TEntity : class; 22 | 23 | int SaveChanges(); 24 | 25 | #endregion 26 | } 27 | } -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Data/ModelConfigurations/Base/AuditableModelConfigurationBase.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.EntityFrameworkCore.Entities.Base; 2 | using Microsoft.EntityFrameworkCore; 3 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 4 | using System; 5 | 6 | namespace Calabonga.Chat.API.Data.ModelConfigurations.Base 7 | { 8 | /// 9 | /// Audit-able Model Configuration base 10 | /// 11 | /// 12 | public abstract class AuditableModelConfigurationBase : IEntityTypeConfiguration where T : Auditable 13 | { 14 | public void Configure(EntityTypeBuilder builder) 15 | { 16 | builder.ToTable(TableName()); 17 | builder.HasKey(x => x.Id); 18 | builder.Property(x => x.Id).IsRequired(); 19 | 20 | // audit 21 | builder.Property(x => x.CreatedAt).IsRequired().HasConversion(v => v, v => DateTime.SpecifyKind(v, DateTimeKind.Utc)).IsRequired(); 22 | builder.Property(x => x.CreatedBy).HasMaxLength(256).IsRequired(); 23 | builder.Property(x => x.UpdatedAt).HasConversion(v => v.Value, v => DateTime.SpecifyKind(v, DateTimeKind.Utc)); 24 | builder.Property(x => x.UpdatedBy).HasMaxLength(256); 25 | 26 | AddBuilder(builder); 27 | } 28 | 29 | /// 30 | /// Add custom properties for your entity 31 | /// 32 | /// 33 | protected abstract void AddBuilder(EntityTypeBuilder builder); 34 | 35 | /// 36 | /// Table name 37 | /// 38 | /// 39 | protected abstract string TableName(); 40 | } 41 | } -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Data/ModelConfigurations/Base/IdentityModelConfigurationBase.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.EntityFrameworkCore.Entities.Base; 2 | using Microsoft.EntityFrameworkCore; 3 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 4 | 5 | namespace Calabonga.Chat.API.Data.ModelConfigurations.Base 6 | { 7 | /// 8 | /// Audit-able Model Configuration base 9 | /// 10 | /// 11 | public abstract class IdentityModelConfigurationBase : IEntityTypeConfiguration where T : Identity 12 | { 13 | public void Configure(EntityTypeBuilder builder) 14 | { 15 | builder.ToTable(TableName()); 16 | builder.HasKey(x => x.Id); 17 | builder.Property(x => x.Id).IsRequired(); 18 | 19 | AddBuilder(builder); 20 | } 21 | 22 | /// 23 | /// Add custom properties for your entity 24 | /// 25 | /// 26 | protected abstract void AddBuilder(EntityTypeBuilder builder); 27 | 28 | /// 29 | /// Table name 30 | /// 31 | /// 32 | protected abstract string TableName(); 33 | } 34 | } -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Data/ModelConfigurations/LogModelConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.Chat.API.Data.ModelConfigurations.Base; 2 | using Calabonga.Chat.API.Entities; 3 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 4 | using System; 5 | 6 | namespace Calabonga.Chat.API.Data.ModelConfigurations 7 | { 8 | /// 9 | /// Entity Type Configuration for Log entity 10 | /// 11 | public class LogModelConfiguration : IdentityModelConfigurationBase 12 | { 13 | protected override void AddBuilder(EntityTypeBuilder builder) 14 | { 15 | builder.Property(x => x.Logger).HasMaxLength(255).IsRequired(); 16 | builder.Property(x => x.Level).HasMaxLength(50).IsRequired(); 17 | builder.Property(x => x.Message).HasMaxLength(4000).IsRequired(); 18 | builder.Property(x => x.CreatedAt).HasConversion(v => v, v => DateTime.SpecifyKind(v, DateTimeKind.Utc)).IsRequired(); 19 | builder.Property(x => x.ThreadId).HasMaxLength(255); 20 | builder.Property(x => x.ExceptionMessage).HasMaxLength(2000); 21 | } 22 | 23 | protected override string TableName() 24 | { 25 | return "Logs"; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Entities/Calabonga.Chat.API.Entities.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net5.0 5 | enable 6 | 5.0 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Entities/Core/AppData.Common.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Calabonga.Chat.API.Entities.Core 4 | { 5 | /// 6 | /// Static data container 7 | /// 8 | public static partial class AppData 9 | { 10 | /// 11 | /// Current service name 12 | /// 13 | public const string ServiceName = "Module"; 14 | 15 | /// 16 | /// "SystemAdministrator" 17 | /// 18 | public const string SystemAdministratorRoleName = "Administrator"; 19 | 20 | /// 21 | /// "BusinessOwner" 22 | /// 23 | public const string ManagerRoleName = "Manager"; 24 | 25 | /// 26 | /// Roles 27 | /// 28 | public static IEnumerable Roles 29 | { 30 | get 31 | { 32 | yield return SystemAdministratorRoleName; 33 | yield return ManagerRoleName; 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Entities/Core/AppData.Messages.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace Calabonga.Chat.API.Entities.Core 3 | { 4 | public static partial class AppData 5 | { 6 | /// 7 | /// Common messages 8 | /// 9 | public static class Messages 10 | { 11 | 12 | /// 13 | /// "Entity successfully deleted" 14 | /// 15 | public static string EntitySuccessfullyDeleted => "Entity successfully deleted"; 16 | 17 | /// 18 | /// "Automatically generated by {0}" 19 | /// 20 | public static string ViewModelFactoryGenerationText => "Automatically generated by {0}"; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Entities/Core/EmailMessage.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace Calabonga.Chat.API.Entities.Core 3 | { 4 | /// 5 | /// Mail Message to send 6 | /// 7 | public class EmailMessage : IEmailMessage 8 | { 9 | 10 | /// 11 | public EmailMessage() 12 | { 13 | Result = new SendEmailResult(); 14 | } 15 | 16 | /// 17 | public string MailTo { get; set; } 18 | 19 | /// 20 | public string Subject { get; set; } 21 | 22 | /// 23 | public string Body { get; set; } 24 | 25 | /// 26 | /// Sent result info 27 | /// 28 | public SendEmailResult Result { get; } 29 | 30 | /// 31 | /// Use HTML in the Body 32 | /// 33 | public bool IsHtml { get; set; } 34 | 35 | /// 36 | public string MailFrom { get; set; } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Entities/Core/IMailMessage.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace Calabonga.Chat.API.Entities.Core 3 | { 4 | /// 5 | /// Mail message interface 6 | /// 7 | public interface IEmailMessage 8 | { 9 | /// 10 | /// Mail to 11 | /// 12 | string MailTo { get; set; } 13 | 14 | /// 15 | /// Mail from 16 | /// 17 | string MailFrom { get; set; } 18 | 19 | /// 20 | /// Subject or title of the message 21 | /// 22 | string Subject { get; set; } 23 | 24 | /// 25 | /// Message content 26 | /// 27 | string Body { get; set; } 28 | } 29 | } -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Entities/Core/SendEmailResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Calabonga.Chat.API.Entities.Core 4 | { 5 | /// 6 | /// MailKit send result 7 | /// 8 | public class SendEmailResult 9 | { 10 | /// 11 | /// Indicate mail sent 12 | /// 13 | public bool IsSent { get; set; } 14 | 15 | /// 16 | /// Indicate sending in process 17 | /// 18 | public bool IsInProcess { get; set; } 19 | 20 | /// 21 | /// Exception while sending 22 | /// 23 | public Exception Exception { get; set; } 24 | } 25 | } -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Entities/Log.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.EntityFrameworkCore.Entities.Base; 2 | using System; 3 | 4 | namespace Calabonga.Chat.API.Entities 5 | { 6 | /// 7 | /// Logs 8 | /// 9 | public class Log : Identity 10 | { 11 | public DateTime CreatedAt { get; set; } 12 | 13 | public string Logger { get; set; } 14 | 15 | public string Level { get; set; } 16 | 17 | public string Message { get; set; } 18 | 19 | public string ThreadId { get; set; } 20 | 21 | public string ExceptionMessage { get; set; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/AppStart/ConfigureServices/ConfigureServicesBase.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using Calabonga.Chat.API.Data; 3 | using Calabonga.Chat.API.Web.Extensions; 4 | using Calabonga.Chat.API.Web.Infrastructure.Settings; 5 | using Calabonga.UnitOfWork; 6 | using Microsoft.AspNetCore.Mvc; 7 | using Microsoft.EntityFrameworkCore; 8 | using Microsoft.Extensions.Configuration; 9 | using Microsoft.Extensions.DependencyInjection; 10 | 11 | namespace Calabonga.Chat.API.Web.AppStart.ConfigureServices 12 | { 13 | /// 14 | /// ASP.NET Core services registration and configurations 15 | /// 16 | public static class ConfigureServicesBase 17 | { 18 | /// 19 | /// ConfigureServices Services 20 | /// 21 | /// 22 | /// 23 | public static void ConfigureServices(IServiceCollection services, IConfiguration configuration) 24 | { 25 | services.AddDbContextPool(config => 26 | { 27 | // UseInMemoryDatabase - This for demo purposes only! 28 | // Should uninstall package "Microsoft.EntityFrameworkCore.InMemory" and install what you need. 29 | // For example: "Microsoft.EntityFrameworkCore.SqlServer" 30 | // uncomment line below to use UseSqlServer(). Don't forget setup connection string in appSettings.json 31 | config.UseInMemoryDatabase("DEMO_PURPOSES_ONLY"); 32 | // config.UseSqlServer(configuration.GetConnectionString(nameof(ApplicationDbContext))); 33 | }); 34 | 35 | services.AddAutoMapper(typeof(Startup)); 36 | services.AddControllers(); 37 | services.AddUnitOfWork(); 38 | services.AddMemoryCache(); 39 | services.AddRouting(); 40 | services.Configure(options => { options.SuppressModelStateInvalidFilter = true; }); 41 | services.AddOptions(); 42 | services.Configure(configuration.GetSection(nameof(CurrentAppSettings))); 43 | services.Configure(options => options.UseRouteSlugify()); 44 | services.AddLocalization(); 45 | services.AddHttpContextAccessor(); 46 | services.AddResponseCaching(); 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/AppStart/ConfigureServices/ConfigureServicesControllers.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.DependencyInjection; 2 | 3 | namespace Calabonga.Chat.API.Web.AppStart.ConfigureServices 4 | { 5 | /// 6 | /// Configure controllers 7 | /// 8 | public static class ConfigureServicesControllers 9 | { 10 | /// 11 | /// Configure services 12 | /// 13 | /// 14 | public static void ConfigureServices(IServiceCollection services) 15 | { 16 | services.AddControllers(); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/AppStart/ConfigureServices/ConfigureServicesCors.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Configuration; 2 | using Microsoft.Extensions.DependencyInjection; 3 | using System.Linq; 4 | 5 | namespace Calabonga.Chat.API.Web.AppStart.ConfigureServices 6 | { 7 | /// 8 | /// Cors configurations 9 | /// 10 | public class ConfigureServicesCors 11 | { 12 | /// 13 | /// ConfigureServices 14 | /// 15 | /// 16 | /// 17 | public static void ConfigureServices(IServiceCollection services, IConfiguration configuration) 18 | { 19 | var origins = configuration.GetSection("Cors")?.GetSection("Origins")?.Value?.Split(','); 20 | services.AddCors(options => 21 | { 22 | options.AddPolicy("CorsPolicy", builder => 23 | { 24 | builder.AllowAnyHeader(); 25 | builder.AllowAnyMethod(); 26 | if (origins != null && origins.Length > 0) 27 | { 28 | if (origins.Contains("*")) 29 | { 30 | builder.AllowAnyHeader(); 31 | builder.AllowAnyMethod(); 32 | builder.SetIsOriginAllowed(host => true); 33 | builder.AllowCredentials(); 34 | } 35 | else 36 | { 37 | foreach (var origin in origins) 38 | { 39 | builder.WithOrigins(origin); 40 | } 41 | } 42 | } 43 | }); 44 | }); 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/AppStart/ConfigureServices/ConfigureServicesMediator.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.AspNetCore.Controllers.Extensions; 2 | using Calabonga.Chat.API.Web.Mediator.Behaviors; 3 | using MediatR; 4 | using Microsoft.Extensions.DependencyInjection; 5 | 6 | namespace Calabonga.Chat.API.Web.AppStart.ConfigureServices 7 | { 8 | /// 9 | /// ASP.NET Core services registration and configurations 10 | /// 11 | public static class ConfigureServicesMediator 12 | { 13 | /// 14 | /// ConfigureServices Services 15 | /// 16 | /// 17 | public static void ConfigureServices(IServiceCollection services) 18 | { 19 | services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidatorBehavior<,>)); 20 | services.AddCommandAndQueries(typeof(Startup).Assembly); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/AppStart/ConfigureServices/ConfigureServicesSignalR.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.DependencyInjection; 2 | 3 | namespace Calabonga.Chat.API.Web.AppStart.ConfigureServices 4 | { 5 | /// 6 | /// ASP.NET Core services registration and configurations 7 | /// 8 | public static class ConfigureServicesSignalR 9 | { 10 | /// 11 | /// ConfigureServices Services 12 | /// 13 | /// 14 | public static void ConfigureServices(IServiceCollection services) 15 | { 16 | services.AddSignalR(); 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/AppStart/ConfigureServices/ConfigureServicesValidators.cs: -------------------------------------------------------------------------------- 1 | using FluentValidation; 2 | using Microsoft.Extensions.DependencyInjection; 3 | 4 | namespace Calabonga.Chat.API.Web.AppStart.ConfigureServices 5 | { 6 | /// 7 | /// ASP.NET Core services registration and configurations 8 | /// 9 | public static class ConfigureServicesValidators 10 | { 11 | /// 12 | /// ConfigureServices Services 13 | /// 14 | /// 15 | public static void ConfigureServices(IServiceCollection services) 16 | { 17 | services.AddValidatorsFromAssembly(typeof(Startup).Assembly); 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/AppStart/Configures/ConfigureCommon.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.Chat.API.Web.AppStart.ConfigureServices; 2 | using Calabonga.Chat.API.Web.Infrastructure.Auth; 3 | using Calabonga.Chat.API.Web.Middlewares; 4 | using Microsoft.AspNetCore.Builder; 5 | using Microsoft.AspNetCore.Hosting; 6 | using Microsoft.AspNetCore.Http; 7 | using Microsoft.Extensions.DependencyInjection; 8 | using Microsoft.Extensions.Hosting; 9 | 10 | namespace Calabonga.Chat.API.Web.AppStart.Configures 11 | { 12 | /// 13 | /// Pipeline configuration 14 | /// 15 | public static class ConfigureCommon 16 | { 17 | /// 18 | /// Configure pipeline 19 | /// 20 | /// 21 | /// 22 | /// 23 | public static void Configure(IApplicationBuilder app, IWebHostEnvironment env, AutoMapper.IConfigurationProvider mapper) 24 | { 25 | if (env.IsDevelopment()) 26 | { 27 | mapper.AssertConfigurationIsValid(); 28 | app.UseDeveloperExceptionPage(); 29 | } 30 | else 31 | { 32 | mapper.CompileMappings(); 33 | } 34 | 35 | app.UseDefaultFiles(); 36 | app.UseStaticFiles(new StaticFileOptions 37 | { 38 | OnPrepareResponse = ctx => 39 | { 40 | ctx.Context.Response.Headers.Append("Cache-Control", "public,max-age=600"); 41 | } 42 | }); 43 | 44 | app.UseResponseCaching(); 45 | app.UseETagger(); 46 | app.UseMiddleware(typeof(ErrorHandlingMiddleware)); 47 | app.UseSwagger(); 48 | app.UseSwaggerUI(ConfigureServicesSwagger.SwaggerSettings); 49 | 50 | // Singleton setup for User Identity 51 | IdentityHelper.Instance.Configure(app.ApplicationServices.GetService()!); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/AppStart/Configures/ConfigureEndpoints.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.Chat.API.Web.Hubs; 2 | using Microsoft.AspNetCore.Builder; 3 | 4 | namespace Calabonga.Chat.API.Web.AppStart.Configures 5 | { 6 | /// 7 | /// Configure pipeline 8 | /// 9 | public static class ConfigureEndpoints 10 | { 11 | /// 12 | /// Configure Routing 13 | /// 14 | /// 15 | public static void Configure(IApplicationBuilder app) 16 | { 17 | app.UseRouting(); 18 | app.UseCors("CorsPolicy"); 19 | app.UseAuthentication(); 20 | app.UseAuthorization(); 21 | app.UseEndpoints(endpoints => 22 | { 23 | endpoints.MapControllers(); 24 | endpoints.MapHub("/chat"); 25 | }); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/AppStart/SwaggerFilters/ApplySummariesOperationFilter.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc.Controllers; 2 | using Microsoft.OpenApi.Models; 3 | using Swashbuckle.AspNetCore.SwaggerGen; 4 | 5 | namespace Calabonga.Chat.API.Web.AppStart.SwaggerFilters 6 | { 7 | /// 8 | /// Swagger Method Info Generator from summary for 9 | /// 10 | public class ApplySummariesOperationFilter : IOperationFilter 11 | { 12 | /// 13 | public void Apply(OpenApiOperation operation, OperationFilterContext context) 14 | { 15 | var controllerActionDescriptor = context.ApiDescription.ActionDescriptor as ControllerActionDescriptor; 16 | if (controllerActionDescriptor == null) 17 | { 18 | return; 19 | } 20 | 21 | var actionName = controllerActionDescriptor.ActionName; 22 | if (actionName != "GetPaged") 23 | { 24 | return; 25 | } 26 | 27 | var resourceName = controllerActionDescriptor.ControllerName; 28 | operation.Summary = $"Returns paged list of the {resourceName} as IPagedList wrapped with OperationResult"; 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/Controllers/LogsReadonly2Controller.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using Calabonga.Chat.API.Data; 3 | using Calabonga.Chat.API.Entities; 4 | using Calabonga.Chat.API.Web.Infrastructure.Settings; 5 | using Calabonga.Chat.API.Web.ViewModels.LogViewModels; 6 | using Calabonga.Microservices.Core; 7 | using Calabonga.Microservices.Core.QueryParams; 8 | using Calabonga.Microservices.Core.Validators; 9 | using Calabonga.UnitOfWork; 10 | using Calabonga.UnitOfWork.Controllers.Controllers; 11 | using Microsoft.AspNetCore.Authorization; 12 | using Microsoft.AspNetCore.Mvc; 13 | using Microsoft.Extensions.Options; 14 | using System.Security.Claims; 15 | 16 | namespace Calabonga.Chat.API.Web.Controllers 17 | { 18 | /// 19 | /// ReadOnlyController Demo 20 | /// 21 | [Route("api/[controller]")] 22 | [Authorize] 23 | public class LogsReadonly2Controller : ReadOnlyController 24 | { 25 | private readonly CurrentAppSettings _appSettings; 26 | 27 | /// 28 | public LogsReadonly2Controller( 29 | IOptions appSettings, 30 | IUnitOfWork unitOfWork, 31 | IMapper mapper) 32 | : base(unitOfWork, mapper) 33 | { 34 | _appSettings = appSettings.Value; 35 | } 36 | 37 | [HttpGet("user-roles")] 38 | [Authorize(Policy = "Logs:UserRoles:View")] 39 | public IActionResult Get() 40 | { 41 | //Get Roles for current user 42 | var roles = ClaimsHelper.GetValues((ClaimsIdentity)User.Identity, "role"); 43 | return Ok($"Current user ({User.Identity.Name}) have following roles: {string.Join("|", roles)}"); 44 | } 45 | 46 | /// 47 | protected override PermissionValidationResult ValidateQueryParams(PagedListQueryParams queryParams) 48 | { 49 | if (queryParams.PageSize <= 0) 50 | { 51 | queryParams.PageSize = _appSettings.PageSize; 52 | } 53 | return new PermissionValidationResult(); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/Controllers/LogsReadonlyController.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.Chat.API.Entities.Core; 2 | using Calabonga.Chat.API.Web.Mediator.LogsReadonly; 3 | using Calabonga.Microservices.Core.QueryParams; 4 | using MediatR; 5 | using Microsoft.AspNetCore.Authorization; 6 | using Microsoft.AspNetCore.Mvc; 7 | using System; 8 | using System.Threading.Tasks; 9 | 10 | namespace Calabonga.Chat.API.Web.Controllers 11 | { 12 | /// 13 | /// ReadOnlyController Demo 14 | /// 15 | [Route("api/[controller]")] 16 | [Authorize] 17 | public class LogsReadonlyController : ControllerBase 18 | { 19 | private readonly IMediator _mediator; 20 | 21 | public LogsReadonlyController(IMediator mediator) 22 | { 23 | _mediator = mediator; 24 | } 25 | 26 | [HttpGet("[action]")] 27 | [Authorize(Policy = "Logs:UserRoles:View", Roles = AppData.SystemAdministratorRoleName)] 28 | public async Task GetRoles() 29 | { 30 | //Get Roles for current user 31 | return Ok(await _mediator.Send(new GetRolesRequest(), HttpContext.RequestAborted)); 32 | } 33 | 34 | [HttpGet("[action]/{id:guid}")] 35 | [ProducesResponseType(200)] 36 | public async Task GetById(Guid id) 37 | { 38 | return Ok(await _mediator.Send(new LogGetByIdRequest(id), HttpContext.RequestAborted)); 39 | } 40 | 41 | 42 | [HttpGet("[action]")] 43 | [ProducesResponseType(200)] 44 | public async Task GetPaged([FromQuery] PagedListQueryParams queryParams) 45 | { 46 | return Ok(await _mediator.Send(new LogGetPagedRequest(queryParams), HttpContext.RequestAborted)); 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/Controllers/LogsWritable2Controller.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using Calabonga.Chat.API.Data; 3 | using Calabonga.Chat.API.Entities; 4 | using Calabonga.Chat.API.Web.Infrastructure.Settings; 5 | using Calabonga.Chat.API.Web.ViewModels.LogViewModels; 6 | using Calabonga.Microservices.Core.QueryParams; 7 | using Calabonga.Microservices.Core.Validators; 8 | using Calabonga.OperationResults; 9 | using Calabonga.UnitOfWork; 10 | using Calabonga.UnitOfWork.Controllers.Controllers; 11 | using Calabonga.UnitOfWork.Controllers.Factories; 12 | using Microsoft.AspNetCore.Authorization; 13 | using Microsoft.AspNetCore.Mvc; 14 | using Microsoft.Extensions.Options; 15 | using System.Threading.Tasks; 16 | 17 | namespace Calabonga.Chat.API.Web.Controllers 18 | { 19 | /// 20 | /// WritableController Demo 21 | /// 22 | [Route("api/[controller]")] 23 | [Authorize] 24 | public class LogsWritable2Controller : WritableController 25 | { 26 | private readonly CurrentAppSettings _appSettings; 27 | 28 | /// 29 | public LogsWritable2Controller( 30 | IOptions appSettings, 31 | IEntityManagerFactory entityManagerFactory, 32 | IUnitOfWork unitOfWork, 33 | IMapper mapper) 34 | : base(entityManagerFactory, unitOfWork, mapper) 35 | { 36 | _appSettings = appSettings.Value; 37 | } 38 | 39 | /// 40 | [Authorize(Policy = "LogsWritable:GetCreateViewModelAsync:View")] 41 | public override Task>> GetViewmodelForCreation() 42 | { 43 | return base.GetViewmodelForCreation(); 44 | } 45 | 46 | /// 47 | protected override PermissionValidationResult ValidateQueryParams(PagedListQueryParams queryParams) 48 | { 49 | if (queryParams.PageSize <= 0) 50 | { 51 | queryParams.PageSize = _appSettings.PageSize; 52 | } 53 | return new PermissionValidationResult(); 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/Controllers/LogsWritableController.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.Chat.API.Web.Mediator.LogsReadonly; 2 | using Calabonga.Chat.API.Web.Mediator.LogsWritable; 3 | using Calabonga.Chat.API.Web.ViewModels.LogViewModels; 4 | using Calabonga.Microservices.Core.QueryParams; 5 | using MediatR; 6 | using Microsoft.AspNetCore.Authorization; 7 | using Microsoft.AspNetCore.Mvc; 8 | using System; 9 | using System.Threading.Tasks; 10 | 11 | namespace Calabonga.Chat.API.Web.Controllers 12 | { 13 | /// 14 | /// WritableController Demo 15 | /// 16 | [Route("api/[controller]")] 17 | [Authorize] 18 | public class LogsWritableController : ControllerBase 19 | { 20 | private readonly IMediator _mediator; 21 | 22 | public LogsWritableController(IMediator mediator) 23 | { 24 | _mediator = mediator; 25 | } 26 | 27 | 28 | [HttpGet("[action]/{id:guid}")] 29 | [ProducesResponseType(200)] 30 | public async Task GetById(Guid id) 31 | { 32 | return Ok(await _mediator.Send(new LogGetByIdRequest(id), HttpContext.RequestAborted)); 33 | } 34 | 35 | 36 | [HttpGet("[action]")] 37 | [ProducesResponseType(200)] 38 | public async Task GetPaged([FromQuery] PagedListQueryParams queryParams) 39 | { 40 | return Ok(await _mediator.Send(new LogGetPagedRequest(queryParams), HttpContext.RequestAborted)); 41 | } 42 | 43 | [HttpPost("[action]")] 44 | public async Task PostItem([FromBody] LogCreateViewModel model) 45 | { 46 | return Ok(await _mediator.Send(new LogPostItemRequest(model), HttpContext.RequestAborted)); 47 | } 48 | 49 | [HttpPut("[action]")] 50 | public async Task PutItem([FromBody] LogUpdateViewModel model) 51 | { 52 | return Ok(await _mediator.Send(new LogPutItemRequest(model), HttpContext.RequestAborted)); 53 | } 54 | 55 | [HttpDelete("[action]/{id:guid}")] 56 | public async Task DeleteItem(Guid id) 57 | { 58 | return Ok(await _mediator.Send(new LogDeleteItemRequest(id), HttpContext.RequestAborted)); 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/Extensions/ApplicationBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | using Microsoft.AspNetCore.Mvc.ApplicationModels; 3 | using Microsoft.AspNetCore.Routing; 4 | using Microsoft.Extensions.DependencyInjection; 5 | using System.Text.RegularExpressions; 6 | 7 | namespace Calabonga.Chat.API.Web.Extensions 8 | { 9 | /// 10 | /// Extensions for application class 11 | /// 12 | public static class ApplicationBuilderExtensions 13 | { 14 | /// 15 | /// Use special route slugify for Pegasus routing 16 | /// 17 | /// 18 | public static void UseRouteSlugify(this MvcOptions options) 19 | { 20 | options.Conventions.Add(new RouteTokenTransformerConvention(new SlugifyParameterTransformer())); 21 | } 22 | } 23 | 24 | /// 25 | /// Special route naming convention 26 | /// 27 | public class SlugifyParameterTransformer : IOutboundParameterTransformer 28 | { 29 | /// 30 | public string TransformOutbound(object value) 31 | { 32 | return value == null 33 | ? null 34 | : Regex.Replace(value.ToString(), "([a-z])([A-Z])", "$1-$2").ToLower(); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/Extensions/AssemblyExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Reflection; 4 | 5 | namespace Calabonga.Chat.API.Web.Extensions 6 | { 7 | /// 8 | /// Assembly helpers 9 | /// 10 | public static class AssemblyExtensions 11 | { 12 | /// 13 | /// Returns types 14 | /// 15 | /// 16 | /// 17 | /// 18 | public static List GetTypesAssignableFrom(this Assembly assembly) 19 | { 20 | return assembly.GetTypesAssignableFrom(typeof(T)); 21 | } 22 | 23 | private static List GetTypesAssignableFrom(this Assembly assembly, Type compareType) 24 | { 25 | var ret = new List(); 26 | foreach (var type in assembly.DefinedTypes) 27 | { 28 | if (compareType.IsAssignableFrom(type) && compareType != type && !type.IsAbstract) 29 | { 30 | ret.Add(type); 31 | } 32 | } 33 | return ret; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/Extensions/EntityValidatorExtensions.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.Microservices.Core.Validators; 2 | using System.Collections.Generic; 3 | 4 | namespace Calabonga.Chat.API.Web.Extensions 5 | { 6 | /// 7 | /// Entity Validator Extensions 8 | /// 9 | public static class EntityValidatorExtensions 10 | { 11 | /// 12 | /// Returns validator from validation results 13 | /// 14 | /// 15 | /// 16 | public static ValidationContext GetResult(this List source) 17 | { 18 | return new ValidationContext(source); 19 | } 20 | 21 | } 22 | } -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/Hubs/ChatConnection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Calabonga.Chat.API.Web.Hubs 4 | { 5 | /// 6 | /// User connection form one of the device (web) 7 | /// 8 | public class ChatConnection 9 | { 10 | /// 11 | /// Registered at time 12 | /// 13 | public DateTime ConnectedAt { get; set; } 14 | 15 | /// 16 | /// Connection Id from client 17 | /// 18 | public string ConnectionId { get; set; } = null!; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/Hubs/ICommunicationHub.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | 4 | namespace Calabonga.Chat.API.Web.Hubs 5 | { 6 | public interface ICommunicationHub 7 | { 8 | /// 9 | /// Send message 10 | /// 11 | /// 12 | /// 13 | /// 14 | Task SendMessageAsync(string userName, string message); 15 | 16 | /// 17 | /// Update user list 18 | /// 19 | /// 20 | Task UpdateUsersAsync(IEnumerable users); 21 | } 22 | } -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/Infrastructure/Attributes/SwaggerFormAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Calabonga.Chat.API.Web.Infrastructure.Attributes 4 | { 5 | /// 6 | /// Custom attribute for Swagger Upload Form 7 | /// 8 | [AttributeUsage(AttributeTargets.Method)] 9 | public sealed class SwaggerFormAttribute : Attribute 10 | { 11 | /// 12 | public SwaggerFormAttribute(string parameterName, string description, bool hasFileUpload = true) 13 | { 14 | ParameterName = parameterName; 15 | Description = description; 16 | HasFileUpload = hasFileUpload; 17 | } 18 | 19 | /// 20 | /// UploadFile enabled 21 | /// 22 | public bool HasFileUpload { get; } 23 | 24 | /// 25 | /// Name for the parameter 26 | /// 27 | public string ParameterName { get; } 28 | 29 | /// 30 | /// Small description 31 | /// 32 | public string Description { get; } 33 | } 34 | } -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/Infrastructure/Attributes/SwaggerGroupAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Calabonga.Chat.API.Web.Infrastructure.Attributes 4 | { 5 | /// 6 | /// Swagger controller group attribute 7 | /// 8 | /// 9 | [AttributeUsage(AttributeTargets.Class)] 10 | public class SwaggerGroupAttribute : Attribute 11 | { 12 | /// 13 | public SwaggerGroupAttribute(string groupName) 14 | { 15 | GroupName = groupName; 16 | } 17 | 18 | /// 19 | /// Group name 20 | /// 21 | public string GroupName { get; } 22 | } 23 | } -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/Infrastructure/Attributes/ValidateModelStateAttribute.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.OperationResults; 2 | using Microsoft.AspNetCore.Mvc; 3 | using Microsoft.AspNetCore.Mvc.Filters; 4 | using System.Linq; 5 | 6 | namespace Calabonga.Chat.API.Web.Infrastructure.Attributes 7 | { 8 | /// 9 | /// Custom validation handler for availability to whit OperationResult 10 | /// 11 | public class ValidateModelStateAttribute : ActionFilterAttribute 12 | { 13 | /// 14 | public override void OnActionExecuting(ActionExecutingContext context) 15 | { 16 | if (context.ModelState.IsValid) 17 | { 18 | return; 19 | } 20 | 21 | var operation = OperationResult.CreateResult(); 22 | var messages = context.ModelState.Values.SelectMany(x => x.Errors.Select(xx => xx.ErrorMessage)); 23 | var message = string.Join(" ", messages); 24 | operation.AddError(message); 25 | context.Result = new OkObjectResult(operation); 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/Infrastructure/Auth/AuthorizationPolicyProvider.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Authorization; 2 | using Microsoft.Extensions.Options; 3 | using System.Threading.Tasks; 4 | 5 | namespace Calabonga.Chat.API.Web.Infrastructure.Auth 6 | { 7 | /// 8 | /// Authorization policy provider 9 | /// 10 | public class AuthorizationPolicyProvider : DefaultAuthorizationPolicyProvider 11 | { 12 | private readonly AuthorizationOptions _options; 13 | 14 | /// 15 | public AuthorizationPolicyProvider(IOptions options) : base(options) 16 | { 17 | _options = options.Value; 18 | } 19 | 20 | /// 21 | public override async Task GetPolicyAsync(string policyName) 22 | { 23 | var policyExists = await base.GetPolicyAsync(policyName); 24 | if (policyExists != null) 25 | { 26 | return policyExists; 27 | } 28 | 29 | policyExists = new AuthorizationPolicyBuilder().AddRequirements(new PermissionRequirement(policyName)).Build(); 30 | _options.AddPolicy(policyName, policyExists); 31 | return policyExists; 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/Infrastructure/Auth/IdentityHelper.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.Microservices.Core.Exceptions; 2 | using Microsoft.AspNetCore.Http; 3 | using System; 4 | using System.Security.Principal; 5 | 6 | namespace Calabonga.Chat.API.Web.Infrastructure.Auth 7 | { 8 | /// 9 | /// Identity helper for Requests operations (Singleton) 10 | /// 11 | public sealed class IdentityHelper 12 | { 13 | private IdentityHelper() { } 14 | 15 | public static IdentityHelper Instance => Lazy.Value; 16 | 17 | public void Configure(IHttpContextAccessor httpContextAccessor) 18 | { 19 | ContextAccessor = httpContextAccessor ?? throw new MicroserviceArgumentNullException(nameof(IHttpContextAccessor)); 20 | IsInitialized = true; 21 | } 22 | 23 | public IIdentity? User 24 | { 25 | get 26 | { 27 | if (IsInitialized) 28 | { 29 | return ContextAccessor.HttpContext!.User.Identity != null 30 | && ContextAccessor.HttpContext != null 31 | && ContextAccessor.HttpContext.User.Identity.IsAuthenticated 32 | ? ContextAccessor.HttpContext.User.Identity 33 | : null; 34 | } 35 | throw new MicroserviceArgumentNullException($"{nameof(IdentityHelper)} has not been initialized. Please use {nameof(IdentityHelper)}.Instance.Configure(...) in Configure Application method in Startup.cs"); 36 | } 37 | } 38 | 39 | private static readonly Lazy Lazy = new Lazy(() => new IdentityHelper()); 40 | 41 | private bool IsInitialized { get; set; } 42 | 43 | private static IHttpContextAccessor ContextAccessor { get; set; } = null!; 44 | 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/Infrastructure/Auth/MicroservicePermissionHandler.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.Microservices.Core; 2 | using Microsoft.AspNetCore.Authorization; 3 | using System.Security.Claims; 4 | using System.Threading.Tasks; 5 | 6 | namespace Calabonga.Chat.API.Web.Infrastructure.Auth 7 | { 8 | /// 9 | /// Permission handler for custom authorization implementations 10 | /// 11 | public class MicroservicePermissionHandler : AuthorizationHandler 12 | { 13 | /// 14 | protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionRequirement requirement) 15 | { 16 | var identity = (ClaimsIdentity)context.User.Identity!; 17 | var claim = ClaimsHelper.GetValue(identity, requirement.PermissionName); 18 | if (claim == null) 19 | { 20 | return Task.CompletedTask; 21 | } 22 | 23 | context.Succeed(requirement); 24 | return Task.CompletedTask; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/Infrastructure/Auth/PermissionRequirement.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Authorization; 2 | 3 | namespace Calabonga.Chat.API.Web.Infrastructure.Auth 4 | { 5 | /// 6 | /// Permission requirement for user or service authorization 7 | /// 8 | public class PermissionRequirement : IAuthorizationRequirement 9 | { 10 | public PermissionRequirement(string permissionName) 11 | { 12 | PermissionName = permissionName; 13 | } 14 | 15 | /// 16 | /// Permission name 17 | /// 18 | public string PermissionName { get; } 19 | } 20 | } -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/Infrastructure/DependencyInjection/CommonRegistrations.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.Chat.API.Data; 2 | using Calabonga.Chat.API.Web.Hubs; 3 | using Calabonga.Chat.API.Web.Infrastructure.Services; 4 | using Microsoft.Extensions.DependencyInjection; 5 | 6 | namespace Calabonga.Chat.API.Web.Infrastructure.DependencyInjection 7 | { 8 | /// 9 | /// Registrations for both points: API and Scheduler 10 | /// 11 | public partial class DependencyContainer 12 | { 13 | /// 14 | /// Register 15 | /// 16 | /// 17 | public static void Common(IServiceCollection services) 18 | { 19 | services.AddTransient(); 20 | 21 | // services 22 | services.AddTransient(); 23 | services.AddTransient(); 24 | 25 | // chat 26 | services.AddSingleton(); 27 | } 28 | } 29 | 30 | 31 | } 32 | -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/Infrastructure/Engine/EntityManagers/LogManager.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using Calabonga.Chat.API.Entities; 3 | using Calabonga.Chat.API.Web.ViewModels.LogViewModels; 4 | using Calabonga.Microservices.Core.Validators; 5 | using Calabonga.UnitOfWork.Controllers.Factories; 6 | using Calabonga.UnitOfWork.Controllers.Managers; 7 | using System.Security.Principal; 8 | 9 | namespace Calabonga.Chat.API.Web.Infrastructure.Engine.EntityManagers 10 | { 11 | /// 12 | /// Entity manager for 13 | /// 14 | public class LogManager : EntityManager 15 | { 16 | /// 17 | public LogManager(IMapper mapper, IViewModelFactory viewModelFactory, IEntityValidator validator) 18 | : base(mapper, viewModelFactory, validator) 19 | { 20 | } 21 | 22 | protected override IIdentity? GetIdentity() 23 | { 24 | return null; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/Infrastructure/Engine/EntityValidators/LogValidator.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.Chat.API.Entities; 2 | using Calabonga.Microservices.Core.Validators; 3 | 4 | namespace Calabonga.Chat.API.Web.Infrastructure.Engine.EntityValidators 5 | { 6 | /// 7 | /// Entity Validator for 8 | /// 9 | public class LogValidator : EntityValidator 10 | { 11 | 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/Infrastructure/Engine/ViewModelFactories/LogViewModelFactory.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using Calabonga.Chat.API.Entities; 3 | using Calabonga.Chat.API.Web.ViewModels.LogViewModels; 4 | using Calabonga.OperationResults; 5 | using Calabonga.UnitOfWork; 6 | using Calabonga.UnitOfWork.Controllers.Factories; 7 | using Microsoft.Extensions.Logging; 8 | using System; 9 | using System.Threading.Tasks; 10 | 11 | namespace Calabonga.Chat.API.Web.Infrastructure.Engine.ViewModelFactories 12 | { 13 | /// 14 | /// ViewModel factory for 15 | /// 16 | public class LogViewModelFactory : ViewModelFactory 17 | { 18 | private readonly IUnitOfWork _context; 19 | private readonly IMapper _mapper; 20 | 21 | public LogViewModelFactory(IUnitOfWork context, IMapper mapper) 22 | { 23 | _context = context; 24 | _mapper = mapper; 25 | } 26 | 27 | /// 28 | public override Task> GenerateForCreateAsync() 29 | { 30 | var operation = OperationResult.CreateResult(); 31 | operation.Result = new LogCreateViewModel() 32 | { 33 | CreatedAt = DateTime.Now, 34 | Level = LogLevel.Information.ToString(), 35 | Logger = "Demo purposes only", 36 | Message = $"This is demo message {DateTime.Now}" 37 | }; 38 | return Task.FromResult(operation); 39 | } 40 | 41 | /// 42 | public override async Task> GenerateForUpdateAsync(Guid id) 43 | { 44 | var operation = OperationResult.CreateResult(); 45 | var entity = await _context.GetRepository().GetFirstOrDefaultAsync(predicate: x => x.Id == id); 46 | var mapped = _mapper.Map(entity); 47 | operation.Result = mapped; 48 | operation.AddSuccess("ViewModel generated for Log entity. Please see Additional information in DataObject").AddData(new { Identifier = id }); 49 | 50 | return operation; 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/Infrastructure/EventLogs/EventNumbers.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Logging; 2 | 3 | namespace Calabonga.Chat.API.Web.Infrastructure.EventLogs 4 | { 5 | /// 6 | /// The number identifiers for events in the microservices 7 | /// 8 | static class EventNumbers 9 | { 10 | internal static readonly EventId PostItemId = new EventId(9002, nameof(PostItemId)); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/Infrastructure/EventLogs/LoggerExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Logging; 2 | using System; 3 | 4 | namespace Calabonga.Chat.API.Web.Infrastructure.EventLogs 5 | { 6 | /// 7 | /// Event logging as ILogger extension. 8 | /// Please see the video as the manual https://youtu.be/09EVKgHgwnM 9 | /// 10 | internal static class LoggerExtensions 11 | { 12 | #region PostItem 13 | 14 | internal static void MicroservicePostItem(this ILogger source, string entityName, Exception? exception = null) 15 | { 16 | switch (exception) 17 | { 18 | case null: 19 | PostItemExecute(source, entityName, null); 20 | break; 21 | 22 | default: 23 | PostItemFailedExecute(source, entityName, exception); 24 | break; 25 | } 26 | } 27 | 28 | private static readonly Action PostItemExecute = 29 | LoggerMessage.Define(LogLevel.Information, EventNumbers.PostItemId, 30 | "The {entityName} successfully saved"); 31 | 32 | private static readonly Action PostItemFailedExecute = 33 | LoggerMessage.Define(LogLevel.Error, EventNumbers.PostItemId, 34 | "The {entityName} saving failed"); 35 | 36 | #endregion 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/Infrastructure/Factories/Base/IViewModel.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace Calabonga.Chat.API.Web.Infrastructure.Factories.Base 3 | { 4 | /// 5 | /// Just a stub for see 6 | /// 7 | public interface IViewModel { } 8 | } -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/Infrastructure/Factories/Base/IViewModelFactory.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.EntityFrameworkCore.Entities.Base; 2 | using System; 3 | 4 | namespace Calabonga.Chat.API.Web.Infrastructure.Factories.Base 5 | { 6 | /// 7 | /// ViewModel Factory 8 | /// 9 | /// 10 | /// 11 | /// 12 | public interface IViewModelFactory 13 | where TCreateViewModel : IViewModel, new() 14 | where TUpdateViewModel : IViewModel, new() 15 | where TEntity : class, IHaveId 16 | { 17 | /// 18 | /// Returns ViewModel for entity creation 19 | /// 20 | /// 21 | TCreateViewModel GenerateForCreate(); 22 | 23 | /// 24 | /// Returns ViewModel for entity editing 25 | /// 26 | /// 27 | /// 28 | TUpdateViewModel GenerateForUpdate(Guid id); 29 | } 30 | } -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/Infrastructure/Factories/Base/ViewModelFactory.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.EntityFrameworkCore.Entities.Base; 2 | using System; 3 | 4 | namespace Calabonga.Chat.API.Web.Infrastructure.Factories.Base 5 | { 6 | /// 7 | /// ViewModelFactory base class 8 | /// 9 | /// 10 | /// 11 | /// 12 | public abstract class ViewModelFactory : IViewModelFactory 13 | where TCreateViewModel : IViewModel, new() 14 | where TUpdateViewModel : IViewModel, new() 15 | where TEntity : class, IHaveId 16 | { 17 | 18 | /// 19 | public abstract TCreateViewModel GenerateForCreate(); 20 | 21 | /// 22 | public abstract TUpdateViewModel GenerateForUpdate(Guid id); 23 | } 24 | } -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/Infrastructure/Helpers/AsyncHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | 5 | namespace Calabonga.Chat.API.Web.Infrastructure.Helpers 6 | { 7 | /// 8 | /// Run Asynchronous methods as Synchronous. 9 | /// 10 | public static class AsyncHelper 11 | { 12 | private static readonly TaskFactory AppTaskFactory = new 13 | TaskFactory(CancellationToken.None, 14 | TaskCreationOptions.None, 15 | TaskContinuationOptions.None, 16 | TaskScheduler.Default); 17 | 18 | /// 19 | /// Run asynchronous method as synchronous 20 | /// 21 | /// 22 | /// 23 | /// 24 | public static TResult RunSync(Func> func) 25 | { 26 | return AppTaskFactory 27 | .StartNew(func) 28 | .Unwrap() 29 | .GetAwaiter() 30 | .GetResult(); 31 | } 32 | 33 | /// 34 | /// Run asynchronous method as synchronous 35 | /// 36 | /// 37 | public static void RunSync(Func func) 38 | { 39 | AppTaskFactory 40 | .StartNew(func) 41 | .Unwrap() 42 | .GetAwaiter() 43 | .GetResult(); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/Infrastructure/Helpers/EmailHelper.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.Chat.API.Entities.Core; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | 6 | namespace Calabonga.Chat.API.Web.Infrastructure.Helpers 7 | { 8 | /// 9 | /// Email validation helper 10 | /// 11 | public static class EmailHelper 12 | { 13 | /// 14 | /// Validates emails entries 15 | /// 16 | /// 17 | /// 18 | public static IEnumerable GetValidEmails(string emails) 19 | { 20 | if (string.IsNullOrWhiteSpace(emails)) 21 | { 22 | return null; 23 | } 24 | var split = emails.Split(new[] { ';', '|', ' ', ',' }, StringSplitOptions.RemoveEmptyEntries); 25 | return split.Where(x => x.IsEmail()); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/Infrastructure/Helpers/ValidationContextHelper.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.ObjectModel; 2 | using System.ComponentModel.DataAnnotations; 3 | 4 | namespace Calabonga.Chat.API.Web.Infrastructure.Helpers 5 | { 6 | /// 7 | /// ValidationContext Helper for validation operations 8 | /// 9 | public static class ValidationContextHelper 10 | { 11 | /// 12 | /// Returns validation results of IValidatableObject 13 | /// 14 | /// 15 | /// 16 | /// 17 | /// 18 | public static bool TryValidate(object obj, out Collection results, ValidationContext validationContext = null) 19 | { 20 | var context = validationContext ?? new ValidationContext(obj, serviceProvider: null, items: null); 21 | results = new Collection(); 22 | return Validator.TryValidateObject(obj, context, results, validateAllProperties: true); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/Infrastructure/Mappers/Base/IAutoMapper.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace Calabonga.Chat.API.Web.Infrastructure.Mappers.Base 3 | { 4 | /// 5 | /// The stub for reflection helper profiles registrations 6 | /// 7 | public interface IAutoMapper { } 8 | } -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/Infrastructure/Mappers/Base/MapperConfigurationBase.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | 3 | namespace Calabonga.Chat.API.Web.Infrastructure.Mappers.Base 4 | { 5 | /// 6 | /// Base class for mapper configuration. 7 | /// All ViewModel that will be mapped should implement IAutoMapper 8 | /// 9 | public abstract class MapperConfigurationBase : Profile, IAutoMapper { } 10 | } 11 | -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/Infrastructure/Mappers/Base/PagedListConverter.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using Calabonga.UnitOfWork; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | 6 | namespace Calabonga.Chat.API.Web.Infrastructure.Mappers.Base 7 | { 8 | /// 9 | /// Generic converter for IPagedList collections 10 | /// 11 | /// 12 | /// 13 | public class PagedListConverter : ITypeConverter, IPagedList> 14 | { 15 | 16 | /// Performs conversion from source to destination type 17 | /// Source object 18 | /// Destination object 19 | /// Resolution context 20 | /// Destination object 21 | public IPagedList Convert(IPagedList source, IPagedList destination, ResolutionContext context) 22 | { 23 | if (source == null) 24 | { 25 | return null; 26 | } 27 | 28 | var vm = source.Items.Select(m => context.Mapper.Map(m)).ToList(); 29 | 30 | 31 | var pagedList = PagedList.From(source, (con) => context.Mapper.Map>(con)); 32 | // var pagedList = vm.ToPagedList(source.PageIndex, source.PageSize); 33 | return pagedList; 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/Infrastructure/Mappers/LogMapperConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.Chat.API.Entities; 2 | using Calabonga.Chat.API.Web.Infrastructure.Mappers.Base; 3 | using Calabonga.Chat.API.Web.ViewModels.LogViewModels; 4 | using Calabonga.UnitOfWork; 5 | 6 | namespace Calabonga.Chat.API.Web.Infrastructure.Mappers 7 | { 8 | /// 9 | /// Mapper Configuration for entity Log 10 | /// 11 | public class LogMapperConfiguration : MapperConfigurationBase 12 | { 13 | /// 14 | public LogMapperConfiguration() 15 | { 16 | CreateMap() 17 | .ForMember(x => x.Id, o => o.Ignore()); 18 | 19 | CreateMap(); 20 | 21 | CreateMap, IPagedList>() 22 | .ConvertUsing>(); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/Infrastructure/Services/ICacheService.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Caching.Memory; 2 | using System; 3 | 4 | namespace Calabonga.Chat.API.Web.Infrastructure.Services 5 | { 6 | /// 7 | /// Cache service interface 8 | /// 9 | public interface ICacheService 10 | { 11 | /// 12 | /// Get the entry from the cache 13 | /// 14 | /// 15 | /// 16 | TEntry Get(object key); 17 | 18 | /// 19 | /// Sets entry cache for one minute sliding expiration 20 | /// 21 | /// 22 | /// 23 | /// 24 | void SetForMinute(object key, TEntry cacheEntry); 25 | 26 | /// 27 | /// Sets entry cache for 30 minutes sliding expiration 28 | /// 29 | /// 30 | /// 31 | /// 32 | void SetForThirtyMinutes(object key, TEntry cacheEntry); 33 | 34 | /// 35 | /// Sets entry cache for custom sliding expiration interval 36 | /// 37 | /// 38 | /// 39 | /// 40 | /// 41 | void SetWithSlidingExpiration(object key, TEntry cacheEntry, TimeSpan slidingExpiration); 42 | 43 | /// 44 | /// Returns already exist entry or first put it to the cache and then return entry 45 | /// 46 | /// 47 | /// 48 | /// 49 | /// 50 | /// 51 | TEntry GetOrCreate(TKey key, Func findIfNotFoundFunc); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/Infrastructure/Services/ILogService.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace Calabonga.Chat.API.Web.Infrastructure.Services 3 | { 4 | /// 5 | /// Interface for Business logic logger can save messages to database 6 | /// 7 | public interface ILogService 8 | { 9 | /// 10 | /// Log information message 11 | /// 12 | /// 13 | void LogInformation(string message); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/Infrastructure/Services/LogService.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.Chat.API.Data; 2 | using Calabonga.Chat.API.Entities; 3 | using Calabonga.Microservices.Core.Exceptions; 4 | using Calabonga.UnitOfWork; 5 | using Microsoft.Extensions.Logging; 6 | using System; 7 | 8 | namespace Calabonga.Chat.API.Web.Infrastructure.Services 9 | { 10 | /// 11 | /// Business logic logger can save messages to database 12 | /// 13 | public class LogService : ILogService 14 | { 15 | private readonly IUnitOfWork _unitOfWork; 16 | 17 | public LogService(IUnitOfWork unitOfWork) 18 | { 19 | _unitOfWork = unitOfWork; 20 | } 21 | 22 | /// 23 | /// Log information message 24 | /// 25 | /// 26 | public void LogInformation(string message) 27 | { 28 | Log(LogLevel.Information, message); 29 | } 30 | 31 | /// 32 | /// Allows to save data logs to the database Logs table 33 | /// 34 | private void Log(LogLevel level, string message, Exception exception = null) 35 | { 36 | var logs = _unitOfWork.GetRepository(); 37 | var log = new Log 38 | { 39 | CreatedAt = DateTime.UtcNow, 40 | Level = level.ToString(), 41 | Logger = GetType().Name, 42 | Message = message, 43 | ThreadId = "0", 44 | ExceptionMessage = exception?.Message 45 | }; 46 | logs.Insert(log); 47 | _unitOfWork.SaveChanges(); 48 | if (!_unitOfWork.LastSaveChangesResult.IsOk) 49 | { 50 | throw new MicroserviceInvalidOperationException(); 51 | } 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/Infrastructure/Settings/Base/ServiceBase.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace Calabonga.Chat.API.Web.Infrastructure.Settings.Base 3 | { 4 | /// 5 | /// Base service behavior 6 | /// 7 | public abstract class ServiceBase 8 | { 9 | /// 10 | /// Indicates that the processing available works is enabled 11 | /// 12 | public bool IsActive { get; set; } 13 | } 14 | } -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/Infrastructure/Settings/CurrentAppSettings.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace Calabonga.Chat.API.Web.Infrastructure.Settings 3 | { 4 | /// 5 | /// Represents configuration file with current application settings 6 | /// 7 | public class CurrentAppSettings 8 | { 9 | /// 10 | /// Default page size 11 | /// 12 | public int PageSize { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/Infrastructure/Validations/LogValidator.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.Chat.API.Entities; 2 | using Calabonga.Microservices.Core.Validators; 3 | 4 | namespace Calabonga.Chat.API.Web.Infrastructure.Validations 5 | { 6 | /// 7 | /// Validator for entity Log 8 | /// 9 | public class LogValidator : EntityValidator 10 | { 11 | 12 | } 13 | } -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/Mediator/LogsReadonly/GetRoles.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.AspNetCore.Controllers.Records; 2 | using Calabonga.Microservices.Core; 3 | using MediatR; 4 | using Microsoft.AspNetCore.Http; 5 | using System.Security.Claims; 6 | 7 | namespace Calabonga.Chat.API.Web.Mediator.LogsReadonly 8 | { 9 | /// 10 | /// Request: Returns user roles 11 | /// 12 | public record GetRolesRequest : RequestBase; 13 | 14 | public class GetRolesRequestHandler : RequestHandler 15 | { 16 | private readonly IHttpContextAccessor _httpContextAccessor; 17 | 18 | public GetRolesRequestHandler(IHttpContextAccessor httpContextAccessor) => _httpContextAccessor = httpContextAccessor; 19 | 20 | protected override string Handle(GetRolesRequest request) 21 | { 22 | var user = _httpContextAccessor.HttpContext!.User; 23 | var roles = ClaimsHelper.GetValues((ClaimsIdentity)user.Identity, "role"); 24 | return $"Current user ({user.Identity.Name}) have following roles: {string.Join("|", roles)}"; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/Mediator/LogsReadonly/LogGetById.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using Calabonga.AspNetCore.Controllers; 3 | using Calabonga.AspNetCore.Controllers.Records; 4 | using Calabonga.Chat.API.Entities; 5 | using Calabonga.Chat.API.Web.ViewModels.LogViewModels; 6 | using Calabonga.Microservices.Core.Exceptions; 7 | using Calabonga.OperationResults; 8 | using Calabonga.UnitOfWork; 9 | using System; 10 | using System.Threading; 11 | using System.Threading.Tasks; 12 | 13 | namespace Calabonga.Chat.API.Web.Mediator.LogsReadonly 14 | { 15 | /// 16 | /// Request for Log by Identifier 17 | /// 18 | public record LogGetByIdRequest(Guid Id) : OperationResultRequestBase; 19 | 20 | /// 21 | /// Response for Request for Log by Identifier 22 | /// 23 | public class LogGetByIdRequestHandler : OperationResultRequestHandlerBase 24 | { 25 | private readonly IUnitOfWork _unitOfWork; 26 | private readonly IMapper _mapper; 27 | 28 | public LogGetByIdRequestHandler(IUnitOfWork unitOfWork, IMapper mapper) 29 | { 30 | _unitOfWork = unitOfWork; 31 | _mapper = mapper; 32 | } 33 | 34 | public override async Task> Handle(LogGetByIdRequest request, CancellationToken cancellationToken) 35 | { 36 | var id = request.Id; 37 | var operation = OperationResult.CreateResult(); 38 | var repository = _unitOfWork.GetRepository(); 39 | var entityWithoutIncludes = await repository.GetFirstOrDefaultAsync(predicate: x => x.Id == id); 40 | if (entityWithoutIncludes == null) 41 | { 42 | operation.AddError(new MicroserviceNotFoundException($"Entity with identifier {id} not found")); 43 | return operation; 44 | } 45 | operation.Result = _mapper.Map(entityWithoutIncludes); 46 | return operation; 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/Mediator/LogsWritable/LogDeleteItem.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using Calabonga.AspNetCore.Controllers; 3 | using Calabonga.AspNetCore.Controllers.Records; 4 | using Calabonga.Chat.API.Entities; 5 | using Calabonga.Chat.API.Web.ViewModels.LogViewModels; 6 | using Calabonga.Microservices.Core.Exceptions; 7 | using Calabonga.OperationResults; 8 | using Calabonga.UnitOfWork; 9 | using System; 10 | using System.Threading; 11 | using System.Threading.Tasks; 12 | 13 | namespace Calabonga.Chat.API.Web.Mediator.LogsWritable 14 | { 15 | /// 16 | /// Request: Log delete 17 | /// 18 | public record LogDeleteItemRequest(Guid Id) : OperationResultRequestBase; 19 | 20 | /// 21 | /// Request: Log delete 22 | /// 23 | public class LogDeleteItemRequestHandler : OperationResultRequestHandlerBase 24 | { 25 | private readonly IUnitOfWork _unitOfWork; 26 | 27 | private readonly IMapper _mapper; 28 | 29 | public LogDeleteItemRequestHandler(IUnitOfWork unitOfWork, IMapper mapper) 30 | { 31 | _unitOfWork = unitOfWork; 32 | _mapper = mapper; 33 | } 34 | 35 | public override async Task> Handle(LogDeleteItemRequest request, CancellationToken cancellationToken) 36 | { 37 | var operation = OperationResult.CreateResult(); 38 | var repository = _unitOfWork.GetRepository(); 39 | var entity = await repository.FindAsync(request.Id); 40 | if (entity == null) 41 | { 42 | operation.AddError(new MicroserviceNotFoundException("Entity not found")); 43 | return operation; 44 | } 45 | repository.Delete(entity); 46 | await _unitOfWork.SaveChangesAsync(); 47 | if (_unitOfWork.LastSaveChangesResult.IsOk) 48 | { 49 | operation.Result = _mapper.Map(entity); 50 | return operation; 51 | } 52 | operation.AddError(_unitOfWork.LastSaveChangesResult.Exception); 53 | return operation; 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/Middlewares/ErrorHandle.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.UnitOfWork; 2 | using Microsoft.AspNetCore.Http; 3 | using Newtonsoft.Json; 4 | using System; 5 | using System.Threading.Tasks; 6 | 7 | namespace Calabonga.Chat.API.Web.Middlewares 8 | { 9 | /// 10 | /// Custom error handler. It allows to view error messages on UI 11 | /// 12 | public class ErrorHandlingMiddleware 13 | { 14 | private readonly RequestDelegate _next; 15 | 16 | /// 17 | public ErrorHandlingMiddleware(RequestDelegate next) 18 | { 19 | _next = next; 20 | } 21 | 22 | /// 23 | /// Invoke middle ware. Entry point 24 | /// 25 | /// 26 | /// 27 | public async Task Invoke(HttpContext context) 28 | { 29 | try 30 | { 31 | await _next(context); 32 | } 33 | catch (Exception ex) 34 | { 35 | await HandleExceptionAsync(context, ex); 36 | } 37 | } 38 | 39 | private static Task HandleExceptionAsync(HttpContext context, Exception exception) 40 | { 41 | try 42 | { 43 | var result = JsonConvert.SerializeObject(ExceptionHelper.GetMessages(exception), Formatting.Indented); 44 | if (result?.Length > 4000) 45 | { 46 | return context.Response.WriteAsync("Error message to long. Please use DEBUG in method HandleExceptionAsync to handle a whole of text of the exception"); 47 | } 48 | return context.Response.WriteAsync(result); 49 | } 50 | catch 51 | { 52 | return context.Response.WriteAsync($"{exception.Message} For more information please use DEBUG in method HandleExceptionAsync to handle a whole of text of the exception"); 53 | } 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/ViewModels/LogViewModels/LogCreateViewModel.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.EntityFrameworkCore.Entities.Base; 2 | using Microsoft.Extensions.Logging; 3 | using System; 4 | using System.ComponentModel.DataAnnotations; 5 | 6 | namespace Calabonga.Chat.API.Web.ViewModels.LogViewModels 7 | { 8 | /// 9 | /// Data Transfer Object for Log entity 10 | /// 11 | public class LogCreateViewModel : IViewModel 12 | { 13 | /// 14 | /// Log Created At 15 | /// 16 | [Required] 17 | public DateTime CreatedAt { get; set; } 18 | 19 | /// 20 | /// Service name or provider 21 | /// 22 | [Required] 23 | [StringLength(255)] 24 | public string Logger { get; set; } 25 | 26 | /// 27 | /// Log level for logging. See 28 | /// 29 | [Required] 30 | [StringLength(50)] 31 | public string Level { get; set; } 32 | 33 | /// 34 | /// Log Message 35 | /// 36 | [Required] 37 | [StringLength(4000)] 38 | public string Message { get; set; } 39 | 40 | /// 41 | /// Thread identifier 42 | /// 43 | public string ThreadId { get; set; } 44 | 45 | /// 46 | /// Exception message 47 | /// 48 | public string ExceptionMessage { get; set; } 49 | } 50 | } -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/ViewModels/LogViewModels/LogUpdateViewModel.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.EntityFrameworkCore.Entities.Base; 2 | 3 | namespace Calabonga.Chat.API.Web.ViewModels.LogViewModels 4 | { 5 | /// 6 | /// Log View model for Update operations 7 | /// 8 | public class LogUpdateViewModel : ViewModelBase 9 | { 10 | public string Logger { get; set; } 11 | 12 | public string Level { get; set; } 13 | 14 | public string Message { get; set; } 15 | } 16 | } -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/ViewModels/LogViewModels/LogViewModel.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.EntityFrameworkCore.Entities.Base; 2 | using System; 3 | 4 | namespace Calabonga.Chat.API.Web.ViewModels.LogViewModels 5 | { 6 | /// 7 | /// Log ViewModel 8 | /// 9 | public class LogViewModel : ViewModelBase 10 | { 11 | /// 12 | /// Created at 13 | /// 14 | public DateTime CreatedAt { get; set; } 15 | 16 | /// 17 | /// Logger name 18 | /// 19 | public string Logger { get; set; } 20 | 21 | /// 22 | /// Level 23 | /// 24 | public string Level { get; set; } 25 | 26 | /// 27 | /// Message text 28 | /// 29 | public string Message { get; set; } 30 | 31 | /// 32 | /// Thread ID 33 | /// 34 | public string ThreadId { get; set; } 35 | 36 | /// 37 | /// 38 | /// 39 | public string ExceptionMessage { get; set; } 40 | } 41 | } -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "ConnectionStrings": { 3 | "ApplicationDbContext": "Server=;Database=;User ID=;Password=" 4 | }, 5 | "Logging": { 6 | "Debug": { 7 | "LogLevel": { 8 | "Default": "Warning", 9 | "System": "Information", 10 | "Microsoft": "Information", 11 | "IdentityServer4": "Warning" 12 | } 13 | }, 14 | "Console": { 15 | "LogLevel": { 16 | "Default": "Warning", 17 | "System": "Information", 18 | "Microsoft": "Information", 19 | "IdentityServer4": "Warning" 20 | } 21 | } 22 | }, 23 | "Cors": { 24 | "Origins": "*" 25 | }, 26 | "IdentityServer": { 27 | "Url": "https://localhost:10001" 28 | }, 29 | "CurrentAppSettings": { 30 | "PageSize": 50 31 | } 32 | } -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/appsettings.Production.json: -------------------------------------------------------------------------------- 1 | { 2 | "ConnectionStrings": { 3 | "ApplicationDbContext": "Server=;Database=MicroserviceDb;Trusted_Connection=True;" 4 | }, 5 | "Logging": { 6 | "Debug": { 7 | "LogLevel": { 8 | "Default": "Information", 9 | "Microsoft": "Warning", 10 | "Microsoft.Hosting.Lifetime": "Information" 11 | } 12 | }, 13 | "Console": { 14 | "LogLevel": { 15 | "Default": "Information", 16 | "Microsoft": "Warning", 17 | "Microsoft.Hosting.Lifetime": "Error" 18 | } 19 | } 20 | }, 21 | "Cors": { 22 | "Origins": "*" 23 | }, 24 | "IdentityServer": { 25 | "Url": "https://localhost:10001" 26 | }, 27 | "CurrentAppSettings": { 28 | "PageSize": 50 29 | } 30 | } -------------------------------------------------------------------------------- /Calabonga.Chat.API/Calabonga.Chat.API/Calabonga.Chat.API.Web/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information", 7 | "IdentityServer4": "Warning" 8 | } 9 | }, 10 | "AllowedHosts": "*" 11 | } 12 | -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Data/ApplicationDbContext.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.Chat.AuthServer.Data.Base; 2 | using Calabonga.Chat.AuthServer.Entities; 3 | using Microsoft.EntityFrameworkCore; 4 | 5 | namespace Calabonga.Chat.AuthServer.Data 6 | { 7 | /// 8 | /// Database context for current application 9 | /// 10 | public class ApplicationDbContext : DbContextBase, IApplicationDbContext 11 | { 12 | public ApplicationDbContext(DbContextOptions options) 13 | : base(options) { } 14 | 15 | #region System 16 | 17 | public DbSet Logs { get; set; } 18 | 19 | public DbSet Profiles { get; set; } 20 | 21 | /// 22 | public DbSet Permissions { get; set; } 23 | 24 | #endregion 25 | } 26 | } -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Data/ApplicationRole.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Identity; 2 | using System; 3 | 4 | namespace Calabonga.Chat.AuthServer.Data 5 | { 6 | /// 7 | /// Application role 8 | /// 9 | public class ApplicationRole : IdentityRole 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Data/ApplicationUser.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Identity; 2 | using System; 3 | 4 | namespace Calabonga.Chat.AuthServer.Data 5 | { 6 | /// 7 | /// Default user for application. 8 | /// Add profile data for application users by adding properties to the ApplicationUser class 9 | /// 10 | public class ApplicationUser : IdentityUser 11 | { 12 | /// 13 | /// FirstName 14 | /// 15 | public string FirstName { get; set; } 16 | 17 | /// 18 | /// LastName 19 | /// 20 | public string LastName { get; set; } 21 | 22 | /// 23 | /// Profile identity 24 | /// 25 | public Guid? ApplicationUserProfileId { get; set; } 26 | 27 | /// 28 | /// User Profile 29 | /// 30 | public virtual ApplicationUserProfile ApplicationUserProfile { get; set; } 31 | } 32 | } -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Data/ApplicationUserProfile.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.EntityFrameworkCore.Entities.Base; 2 | using System.Collections.Generic; 3 | 4 | namespace Calabonga.Chat.AuthServer.Data 5 | { 6 | /// 7 | /// Represent person with login information (ApplicationUser) 8 | /// 9 | public class ApplicationUserProfile : Auditable 10 | { 11 | /// 12 | /// Account 13 | /// 14 | public virtual ApplicationUser ApplicationUser { get; set; } 15 | 16 | /// 17 | /// Microservice permission for policy-based authorization 18 | /// 19 | public ICollection Permissions { get; set; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Data/ApplicationUserStore.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Identity; 2 | using Microsoft.AspNetCore.Identity.EntityFrameworkCore; 3 | using Microsoft.EntityFrameworkCore; 4 | using System; 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | 8 | namespace Calabonga.Chat.AuthServer.Data 9 | { 10 | /// 11 | /// Application store for user 12 | /// 13 | public class ApplicationUserStore : UserStore 14 | { 15 | public ApplicationUserStore(ApplicationDbContext context, IdentityErrorDescriber describer = null) 16 | : base(context, describer) 17 | { 18 | 19 | } 20 | 21 | /// 22 | public override Task FindByIdAsync(string userId, CancellationToken cancellationToken = new CancellationToken()) 23 | { 24 | return Users 25 | .Include(x => x.ApplicationUserProfile) 26 | .ThenInclude(x => x.Permissions) 27 | .FirstOrDefaultAsync(u => u.Id.ToString() == userId, cancellationToken: cancellationToken); 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Data/Calabonga.Chat.AuthServer.Data.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net5.0 5 | enable 6 | 5.0 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | all 15 | runtime; build; native; contentfiles; analyzers; buildtransitive 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Data/DatabaseInitialization/DatabaseInitializer.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.Chat.AuthServer.Entities.Core; 2 | using Microsoft.AspNetCore.Identity; 3 | using Microsoft.Extensions.DependencyInjection; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | 8 | namespace Calabonga.Chat.AuthServer.Data.DatabaseInitialization 9 | { 10 | /// 11 | /// Database Initializer 12 | /// 13 | public static class DatabaseInitializer 14 | { 15 | public static async void Seed(IServiceProvider serviceProvider) 16 | { 17 | using var scope = serviceProvider.CreateScope(); 18 | await using var context = scope.ServiceProvider.GetService(); 19 | 20 | // Should be uncomment when using UseSqlServer() settings or any other provider. 21 | // This is should not be used when UseInMemoryDatabase() 22 | // context.Database.Migrate(); 23 | 24 | var roles = AppData.Roles.ToArray(); 25 | 26 | foreach (var role in roles) 27 | { 28 | var roleManager = scope.ServiceProvider.GetRequiredService>(); 29 | if (!context!.Roles.Any(r => r.Name == role)) 30 | { 31 | await roleManager.CreateAsync(new ApplicationRole { Name = role, NormalizedName = role.ToUpper() }); 32 | } 33 | } 34 | 35 | #region developer 36 | 37 | var user1 = UserHelper.GetUser("user1@yopmail.com"); 38 | await UserHelper.AddUserWithRoles(context!, scope, user1, roles); 39 | 40 | var user2 = UserHelper.GetUser("user2@yopmail.com"); 41 | await UserHelper.AddUserWithRoles(context!, scope, user2, roles); 42 | 43 | var user3 = UserHelper.GetUser("user3@yopmail.com"); 44 | await UserHelper.AddUserWithRoles(context!, scope, user3 , roles); 45 | 46 | #endregion 47 | 48 | await context!.SaveChangesAsync(); 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Data/IApplicaitonDbContext.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.Chat.AuthServer.Entities; 2 | using Microsoft.EntityFrameworkCore; 3 | using Microsoft.EntityFrameworkCore.ChangeTracking; 4 | using Microsoft.EntityFrameworkCore.Infrastructure; 5 | 6 | namespace Calabonga.Chat.AuthServer.Data 7 | { 8 | /// 9 | /// Abstraction for Database (EntityFramework) 10 | /// 11 | public interface IApplicationDbContext 12 | { 13 | #region System 14 | 15 | DbSet Logs { get; set; } 16 | 17 | DbSet Users { get; set; } 18 | 19 | DbSet Profiles { get; set; } 20 | 21 | DbSet Permissions { get; set; } 22 | 23 | DatabaseFacade Database { get; } 24 | 25 | ChangeTracker ChangeTracker { get; } 26 | 27 | DbSet Set() where TEntity : class; 28 | 29 | int SaveChanges(); 30 | 31 | #endregion 32 | } 33 | } -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Data/MicroservicePermission.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.EntityFrameworkCore.Entities.Base; 2 | using System; 3 | 4 | namespace Calabonga.Chat.AuthServer.Data 5 | { 6 | /// 7 | /// User permission for microservice 8 | /// 9 | public class MicroservicePermission : Auditable 10 | { 11 | /// 12 | /// Application User profile identifier 13 | /// 14 | public Guid ApplicationUserProfileId { get; set; } 15 | 16 | /// 17 | /// Application User Profile 18 | /// 19 | public virtual ApplicationUserProfile ApplicationUserProfile { get; set; } 20 | 21 | /// 22 | /// Authorize attribute policy name 23 | /// 24 | public string PolicyName { get; set; } 25 | 26 | /// 27 | /// Description for current permission 28 | /// 29 | public string Description { get; set; } 30 | } 31 | } -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Data/ModelConfigurations/ApplicationUserModelConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | 4 | namespace Calabonga.Chat.AuthServer.Data.ModelConfigurations 5 | { 6 | /// 7 | /// Entity Type Configuration for entity 8 | /// 9 | 10 | public class ApplicationUserModelConfiguration : IEntityTypeConfiguration 11 | { 12 | 13 | /// 14 | /// Configures the entity of type . 15 | /// 16 | /// The builder to be used to configure the entity type. 17 | public void Configure(EntityTypeBuilder builder) 18 | { 19 | builder.Property(x => x.LastName).HasMaxLength(128).IsRequired(); 20 | builder.Property(x => x.FirstName).HasMaxLength(128).IsRequired(); 21 | builder.Property(x => x.ApplicationUserProfileId).IsRequired(false); 22 | 23 | builder.HasOne(x => x.ApplicationUserProfile); 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Data/ModelConfigurations/ApplicationUserProfileModelConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.Chat.AuthServer.Data.ModelConfigurations.Base; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | 4 | namespace Calabonga.Chat.AuthServer.Data.ModelConfigurations 5 | { 6 | /// 7 | /// Entity Type Configuration for entity 8 | /// 9 | 10 | public class ApplicationUserProfileModelConfiguration : AuditableModelConfigurationBase 11 | { 12 | protected override void AddBuilder(EntityTypeBuilder builder) 13 | { 14 | builder.HasMany(x => x.Permissions); 15 | 16 | builder.HasOne(x => x.ApplicationUser) 17 | .WithOne(x => x.ApplicationUserProfile) 18 | .HasForeignKey(x => x.ApplicationUserProfileId); 19 | } 20 | 21 | protected override string TableName() 22 | { 23 | return "ApplicationUserProfiles"; 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Data/ModelConfigurations/Base/AuditableModelConfigurationBase.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.EntityFrameworkCore.Entities.Base; 2 | using Microsoft.EntityFrameworkCore; 3 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 4 | using System; 5 | 6 | namespace Calabonga.Chat.AuthServer.Data.ModelConfigurations.Base 7 | { 8 | /// 9 | /// Audit-able Model Configuration base 10 | /// 11 | /// 12 | public abstract class AuditableModelConfigurationBase : IEntityTypeConfiguration where T : Auditable 13 | { 14 | public void Configure(EntityTypeBuilder builder) 15 | { 16 | builder.ToTable(TableName()); 17 | builder.HasKey(x => x.Id); 18 | builder.Property(x => x.Id).IsRequired(); 19 | 20 | // audit 21 | builder.Property(x => x.CreatedAt).IsRequired().HasConversion(v => v, v => DateTime.SpecifyKind(v, DateTimeKind.Utc)).IsRequired(); 22 | builder.Property(x => x.CreatedBy).HasMaxLength(256).IsRequired(); 23 | builder.Property(x => x.UpdatedAt).HasConversion(v => v.Value, v => DateTime.SpecifyKind(v, DateTimeKind.Utc)); 24 | builder.Property(x => x.UpdatedBy).HasMaxLength(256); 25 | 26 | AddBuilder(builder); 27 | } 28 | 29 | /// 30 | /// Add custom properties for your entity 31 | /// 32 | /// 33 | protected abstract void AddBuilder(EntityTypeBuilder builder); 34 | 35 | /// 36 | /// Table name 37 | /// 38 | /// 39 | protected abstract string TableName(); 40 | } 41 | } -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Data/ModelConfigurations/Base/IdentityModelConfigurationBase.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.EntityFrameworkCore.Entities.Base; 2 | using Microsoft.EntityFrameworkCore; 3 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 4 | 5 | namespace Calabonga.Chat.AuthServer.Data.ModelConfigurations.Base 6 | { 7 | /// 8 | /// Audit-able Model Configuration base 9 | /// 10 | /// 11 | public abstract class IdentityModelConfigurationBase : IEntityTypeConfiguration where T : Identity 12 | { 13 | public void Configure(EntityTypeBuilder builder) 14 | { 15 | builder.ToTable(TableName()); 16 | builder.HasKey(x => x.Id); 17 | builder.Property(x => x.Id).IsRequired(); 18 | 19 | AddBuilder(builder); 20 | } 21 | 22 | /// 23 | /// Add custom properties for your entity 24 | /// 25 | /// 26 | protected abstract void AddBuilder(EntityTypeBuilder builder); 27 | 28 | /// 29 | /// Table name 30 | /// 31 | /// 32 | protected abstract string TableName(); 33 | } 34 | } -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Data/ModelConfigurations/LogModelConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.Chat.AuthServer.Data.ModelConfigurations.Base; 2 | using Calabonga.Chat.AuthServer.Entities; 3 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 4 | using System; 5 | 6 | namespace Calabonga.Chat.AuthServer.Data.ModelConfigurations 7 | { 8 | /// 9 | /// Entity Type Configuration for entity 10 | /// 11 | public class LogModelConfiguration : IdentityModelConfigurationBase 12 | { 13 | protected override void AddBuilder(EntityTypeBuilder builder) 14 | { 15 | builder.Property(x => x.Logger).HasMaxLength(255).IsRequired(); 16 | builder.Property(x => x.Level).HasMaxLength(50).IsRequired(); 17 | builder.Property(x => x.Message).HasMaxLength(4000).IsRequired(); 18 | builder.Property(x => x.CreatedAt).HasConversion(v => v, v => DateTime.SpecifyKind(v, DateTimeKind.Utc)).IsRequired(); 19 | builder.Property(x => x.ThreadId).HasMaxLength(255); 20 | builder.Property(x => x.ExceptionMessage).HasMaxLength(2000); 21 | } 22 | 23 | protected override string TableName() 24 | { 25 | return "Logs"; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Data/ModelConfigurations/MicroservicePermissionModelConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.Chat.AuthServer.Data.ModelConfigurations.Base; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | 4 | namespace Calabonga.Chat.AuthServer.Data.ModelConfigurations 5 | { 6 | /// 7 | /// Entity Type Configuration for entity 8 | /// 9 | 10 | public class MicroservicePermissionModelConfiguration : AuditableModelConfigurationBase 11 | { 12 | protected override void AddBuilder(EntityTypeBuilder builder) 13 | { 14 | builder.Property(x => x.PolicyName).HasMaxLength(64).IsRequired(); 15 | builder.Property(x => x.Description).HasMaxLength(1024); 16 | builder.Property(x => x.ApplicationUserProfileId).IsRequired(); 17 | 18 | builder.HasOne(x => x.ApplicationUserProfile).WithMany(x => x.Permissions); 19 | } 20 | 21 | protected override string TableName() 22 | { 23 | return "MicroservicePermissions"; 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Entities/Calabonga.Chat.AuthServer.Entities.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net5.0 5 | enable 6 | 5.0 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Entities/Core/AppData.Common.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Calabonga.Chat.AuthServer.Entities.Core 4 | { 5 | /// 6 | /// Static data container 7 | /// 8 | public static partial class AppData 9 | { 10 | /// 11 | /// Current service name 12 | /// 13 | public const string ServiceName = "IdentityModule"; 14 | 15 | /// 16 | /// "SystemAdministrator" 17 | /// 18 | public const string SystemAdministratorRoleName = "Administrator"; 19 | 20 | /// 21 | /// "BusinessOwner" 22 | /// 23 | public const string ManagerRoleName = "Manager"; 24 | 25 | /// 26 | /// Roles 27 | /// 28 | public static IEnumerable Roles 29 | { 30 | get 31 | { 32 | yield return SystemAdministratorRoleName; 33 | yield return ManagerRoleName; 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Entities/Core/AppData.Messages.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace Calabonga.Chat.AuthServer.Entities.Core 3 | { 4 | public static partial class AppData 5 | { 6 | /// 7 | /// Common messages 8 | /// 9 | public static class Messages 10 | { 11 | /// 12 | /// "User successfully registered" 13 | /// 14 | public static string UserSuccessfullyRegistered => "User successfully registered"; 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Entities/Log.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.EntityFrameworkCore.Entities.Base; 2 | using System; 3 | 4 | namespace Calabonga.Chat.AuthServer.Entities 5 | { 6 | /// 7 | /// Log entity for demo purposes only 8 | /// 9 | public class Log : Identity 10 | { 11 | public DateTime CreatedAt { get; set; } 12 | 13 | public string Logger { get; set; } 14 | 15 | public string Level { get; set; } 16 | 17 | public string Message { get; set; } 18 | 19 | public string ThreadId { get; set; } 20 | 21 | public string ExceptionMessage { get; set; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/AppStart/ConfigureServices/ConfigureServicesControllers.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.DependencyInjection; 2 | 3 | namespace Calabonga.Chat.AuthServer.Web.AppStart.ConfigureServices 4 | { 5 | /// 6 | /// Configure controllers 7 | /// 8 | public static class ConfigureServicesControllers 9 | { 10 | /// 11 | /// Configure services 12 | /// 13 | /// 14 | public static void ConfigureServices(IServiceCollection services) => services.AddControllersWithViews(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/AppStart/ConfigureServices/ConfigureServicesCors.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.Chat.AuthServer.Web.Infrastructure.Auth; 2 | using Microsoft.Extensions.Configuration; 3 | using Microsoft.Extensions.DependencyInjection; 4 | using System.Linq; 5 | 6 | namespace Calabonga.Chat.AuthServer.Web.AppStart.ConfigureServices 7 | { 8 | /// 9 | /// Cors configurations 10 | /// 11 | public class ConfigureServicesCors 12 | { 13 | /// 14 | /// ConfigureServices 15 | /// 16 | /// 17 | /// 18 | public static void ConfigureServices(IServiceCollection services, IConfiguration configuration) 19 | { 20 | var origins = configuration.GetSection("Cors")?.GetSection("Origins")?.Value?.Split(','); 21 | services.AddCors(options => 22 | { 23 | options.AddPolicy("CorsPolicy", builder => 24 | { 25 | builder.AllowAnyHeader(); 26 | builder.AllowAnyMethod(); 27 | if (origins != null && origins.Length > 0) 28 | { 29 | if (origins.Contains("*")) 30 | { 31 | builder.AllowAnyHeader(); 32 | builder.AllowAnyMethod(); 33 | builder.SetIsOriginAllowed(host => true); 34 | builder.AllowCredentials(); 35 | } 36 | else 37 | { 38 | foreach (var origin in origins) 39 | { 40 | builder.WithOrigins(origin); 41 | } 42 | } 43 | } 44 | }); 45 | }); 46 | 47 | services.UseMicroserviceAuthorizationPolicy(); 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/AppStart/ConfigureServices/ConfigureServicesMediator.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.AspNetCore.Controllers.Extensions; 2 | using Calabonga.Chat.AuthServer.Web.Mediator.Behaviors; 3 | using MediatR; 4 | using Microsoft.Extensions.DependencyInjection; 5 | 6 | namespace Calabonga.Chat.AuthServer.Web.AppStart.ConfigureServices 7 | { 8 | /// 9 | /// ASP.NET Core services registration and configurations 10 | /// 11 | public static class ConfigureServicesMediator 12 | { 13 | /// 14 | /// ConfigureServices Services 15 | /// 16 | /// 17 | public static void ConfigureServices(IServiceCollection services) 18 | { 19 | services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidatorBehavior<,>)); 20 | services.AddCommandAndQueries(typeof(Startup).Assembly); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/AppStart/ConfigureServices/ConfigureServicesValidators.cs: -------------------------------------------------------------------------------- 1 | using FluentValidation; 2 | using Microsoft.Extensions.DependencyInjection; 3 | 4 | namespace Calabonga.Chat.AuthServer.Web.AppStart.ConfigureServices 5 | { 6 | /// 7 | /// ASP.NET Core services registration and configurations 8 | /// 9 | public static class ConfigureServicesValidators 10 | { 11 | /// 12 | /// ConfigureServices Services 13 | /// 14 | /// 15 | public static void ConfigureServices(IServiceCollection services) => services.AddValidatorsFromAssembly(typeof(Startup).Assembly); 16 | } 17 | } -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/AppStart/Configures/ConfigureAuthentication.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | 3 | namespace Calabonga.Chat.AuthServer.Web.AppStart.Configures 4 | { 5 | /// 6 | /// Configure pipeline 7 | /// 8 | public static class ConfigureAuthentication 9 | { 10 | /// 11 | /// Configure Routing 12 | /// 13 | /// 14 | public static void Configure(IApplicationBuilder app) 15 | { 16 | app.UseRouting(); 17 | app.UseCors("CorsPolicy"); 18 | app.UseAuthentication(); 19 | app.UseAuthorization(); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/AppStart/Configures/ConfigureCommon.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.Chat.AuthServer.Web.AppStart.ConfigureServices; 2 | using Calabonga.Chat.AuthServer.Web.Infrastructure.Auth; 3 | using Calabonga.Chat.AuthServer.Web.Middlewares; 4 | using Microsoft.AspNetCore.Builder; 5 | using Microsoft.AspNetCore.Hosting; 6 | using Microsoft.AspNetCore.Http; 7 | using Microsoft.Extensions.DependencyInjection; 8 | using Microsoft.Extensions.Hosting; 9 | 10 | namespace Calabonga.Chat.AuthServer.Web.AppStart.Configures 11 | { 12 | /// 13 | /// Pipeline configuration 14 | /// 15 | public static class ConfigureCommon 16 | { 17 | /// 18 | /// Configure pipeline 19 | /// 20 | /// 21 | /// 22 | /// 23 | public static void Configure(IApplicationBuilder app, IWebHostEnvironment env, AutoMapper.IConfigurationProvider mapper) 24 | { 25 | if (env.IsDevelopment()) 26 | { 27 | mapper.AssertConfigurationIsValid(); 28 | app.UseDeveloperExceptionPage(); 29 | } 30 | else 31 | { 32 | mapper.CompileMappings(); 33 | } 34 | 35 | app.UseDefaultFiles(); 36 | app.UseStaticFiles(new StaticFileOptions 37 | { 38 | OnPrepareResponse = ctx => 39 | { 40 | ctx.Context.Response.Headers.Append("Cache-Control", "public,max-age=600"); 41 | } 42 | }); 43 | 44 | app.UseResponseCaching(); 45 | 46 | app.UseETagger(); 47 | 48 | app.UseIdentityServer(); 49 | 50 | app.UseMiddleware(typeof(ErrorHandlingMiddleware)); 51 | 52 | 53 | app.UseSwagger(); 54 | app.UseSwaggerUI(ConfigureServicesSwagger.SwaggerSettings); 55 | 56 | // Singleton setup for User Identity 57 | UserIdentity.Instance.Configure(app.ApplicationServices.GetService()!); 58 | 59 | 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/AppStart/Configures/ConfigureEndpoints.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | 3 | namespace Calabonga.Chat.AuthServer.Web.AppStart.Configures 4 | { 5 | /// 6 | /// Configure pipeline 7 | /// 8 | public static class ConfigureEndpoints 9 | { 10 | /// 11 | /// Configure Routing 12 | /// 13 | /// 14 | public static void Configure(IApplicationBuilder app) => app.UseEndpoints(endpoints => 15 | { 16 | endpoints.MapDefaultControllerRoute(); 17 | }); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/AppStart/MapperRegistration.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using Calabonga.Chat.AuthServer.Web.Infrastructure.Mappers.Base; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Reflection; 7 | 8 | namespace Calabonga.Chat.AuthServer.Web.AppStart 9 | { 10 | /// 11 | /// AutoMapper profiles registration 12 | /// 13 | public static class MapperRegistration 14 | { 15 | private static List GetProfiles() => (from t in typeof(Startup).GetTypeInfo().Assembly.GetTypes() 16 | where typeof(IAutoMapper).IsAssignableFrom(t) && !t.GetTypeInfo().IsAbstract 17 | select t).ToList(); 18 | 19 | /// 20 | /// Create and build mapper profiles 21 | /// 22 | /// 23 | public static MapperConfiguration GetMapperConfiguration() 24 | { 25 | var profiles = GetProfiles(); 26 | return new MapperConfiguration(cfg => 27 | { 28 | foreach (var item in profiles.Select(profile => (Profile)Activator.CreateInstance(profile))) 29 | { 30 | cfg.AddProfile(item); 31 | } 32 | }); 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/AppStart/SwaggerFilters/ApplySummariesOperationFilter.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc.Controllers; 2 | using Microsoft.OpenApi.Models; 3 | using Swashbuckle.AspNetCore.SwaggerGen; 4 | 5 | namespace Calabonga.Chat.AuthServer.Web.AppStart.SwaggerFilters 6 | { 7 | /// 8 | /// Swagger Method Info Generator from summary for 9 | /// 10 | public class ApplySummariesOperationFilter : IOperationFilter 11 | { 12 | /// 13 | public void Apply(OpenApiOperation operation, OperationFilterContext context) 14 | { 15 | var controllerActionDescriptor = context.ApiDescription.ActionDescriptor as ControllerActionDescriptor; 16 | if (controllerActionDescriptor == null) 17 | { 18 | return; 19 | } 20 | 21 | var actionName = controllerActionDescriptor.ActionName; 22 | if (actionName != "GetPaged") 23 | { 24 | return; 25 | } 26 | var resourceName = controllerActionDescriptor.ControllerName; 27 | operation.Summary = $"Returns paged list of the {resourceName} as IPagedList wrapped with OperationResult"; 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/Calabonga.Chat.AuthServer.Web.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net5.0 5 | enable 6 | 5.0 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | all 19 | runtime; build; native; contentfiles; analyzers; buildtransitive 20 | 21 | 22 | 23 | 24 | 25 | 26 | all 27 | runtime; build; native; contentfiles; analyzers; buildtransitive 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/Controllers/AccountController.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.Chat.AuthServer.Web.Infrastructure.Auth; 2 | using Calabonga.Chat.AuthServer.Web.Mediator.Account; 3 | using Calabonga.Chat.AuthServer.Web.ViewModels.AccountViewModels; 4 | using Calabonga.OperationResults; 5 | using MediatR; 6 | using Microsoft.AspNetCore.Authorization; 7 | using Microsoft.AspNetCore.Mvc; 8 | using System.Threading.Tasks; 9 | 10 | namespace Calabonga.Chat.AuthServer.Web.Controllers 11 | { 12 | /// 13 | /// Account Controller 14 | /// 15 | [Route("api/[controller]")] 16 | [Authorize(AuthenticationSchemes = AuthData.AuthSchemes)] 17 | public class AccountController : ControllerBase 18 | { 19 | private readonly IMediator _mediator; 20 | 21 | /// 22 | /// Register controller 23 | /// 24 | public AccountController(IMediator mediator) => _mediator = mediator; 25 | 26 | /// 27 | /// Register new user. Success registration returns UserProfile for new user. 28 | /// 29 | /// 30 | /// 31 | [HttpPost("[action]")] 32 | [AllowAnonymous] 33 | [ProducesResponseType(200, Type = typeof(OperationResult))] 34 | public async Task>> Register([FromBody] RegisterViewModel model) => 35 | Ok(await _mediator.Send(new RegisterRequest(model), HttpContext.RequestAborted)); 36 | 37 | /// 38 | /// Returns profile information for authenticated user 39 | /// 40 | /// 41 | [HttpGet("[action]")] 42 | [ProducesResponseType(200, Type = typeof(OperationResult))] 43 | public async Task>> Profile() => 44 | await _mediator.Send(new ProfileRequest(), HttpContext.RequestAborted); 45 | } 46 | } -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/Controllers/LogsReadOnlyController.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.Chat.AuthServer.Entities.Core; 2 | using Calabonga.Chat.AuthServer.Web.Infrastructure.Auth; 3 | using Calabonga.Chat.AuthServer.Web.Mediator.LogsReadonly; 4 | using Calabonga.Microservices.Core.QueryParams; 5 | using MediatR; 6 | using Microsoft.AspNetCore.Authorization; 7 | using Microsoft.AspNetCore.Mvc; 8 | using System; 9 | using System.Threading.Tasks; 10 | 11 | namespace Calabonga.Chat.AuthServer.Web.Controllers 12 | { 13 | /// 14 | /// ReadOnlyController Demo 15 | /// 16 | [Route("api/[controller]")] 17 | [Authorize(AuthenticationSchemes = AuthData.AuthSchemes)] 18 | public class LogsReadonlyController : ControllerBase 19 | { 20 | private readonly IMediator _mediator; 21 | 22 | public LogsReadonlyController(IMediator mediator) => _mediator = mediator; 23 | 24 | [HttpGet("[action]")] 25 | [Authorize(Policy = "Logs:UserRoles:View", Roles = AppData.SystemAdministratorRoleName)] 26 | public async Task GetRoles() => 27 | //Get Roles for current user 28 | Ok(await _mediator.Send(new GetRolesRequest(), HttpContext.RequestAborted)); 29 | 30 | [HttpGet("[action]/{id:guid}")] 31 | [ProducesResponseType(200)] 32 | public async Task GetById(Guid id) => Ok(await _mediator.Send(new LogGetByIdRequest(id), HttpContext.RequestAborted)); 33 | 34 | 35 | [HttpGet("[action]")] 36 | [ProducesResponseType(200)] 37 | public async Task GetPaged([FromQuery] PagedListQueryParams queryParams) => Ok(await _mediator.Send(new LogGetPagedRequest(queryParams), HttpContext.RequestAborted)); 38 | } 39 | } -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/Controllers/LogsReadonly2Controller.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using Calabonga.Chat.AuthServer.Data; 3 | using Calabonga.Chat.AuthServer.Entities; 4 | using Calabonga.Chat.AuthServer.Entities.Core; 5 | using Calabonga.Chat.AuthServer.Web.Infrastructure.Auth; 6 | using Calabonga.Chat.AuthServer.Web.Infrastructure.Settings; 7 | using Calabonga.Chat.AuthServer.Web.ViewModels.LogViewModels; 8 | using Calabonga.Microservices.Core; 9 | using Calabonga.Microservices.Core.QueryParams; 10 | using Calabonga.Microservices.Core.Validators; 11 | using Calabonga.UnitOfWork; 12 | using Calabonga.UnitOfWork.Controllers.Controllers; 13 | using Microsoft.AspNetCore.Authorization; 14 | using Microsoft.AspNetCore.Mvc; 15 | using Microsoft.Extensions.Options; 16 | using System.Security.Claims; 17 | 18 | namespace Calabonga.Chat.AuthServer.Web.Controllers 19 | { 20 | /// 21 | /// ReadOnlyController Demo 22 | /// 23 | [Route("api/[controller]")] 24 | [Authorize(AuthenticationSchemes = AuthData.AuthSchemes)] 25 | public class LogsReadonly2Controller : ReadOnlyController 26 | { 27 | private readonly CurrentAppSettings _appSettings; 28 | 29 | /// 30 | public LogsReadonly2Controller( 31 | IOptions appSettings, 32 | IUnitOfWork unitOfWork, 33 | IMapper mapper) 34 | : base(unitOfWork, mapper) 35 | => _appSettings = appSettings.Value; 36 | 37 | [HttpGet("[action]")] 38 | [Authorize(Policy = "Logs:UserRoles:View", Roles = AppData.SystemAdministratorRoleName)] 39 | public IActionResult GetRoles() 40 | { 41 | //Get Roles for current user 42 | var roles = ClaimsHelper.GetValues((ClaimsIdentity)User.Identity, "role"); 43 | return Ok($"Current user ({User.Identity.Name}) have following roles: {string.Join("|", roles)}"); 44 | } 45 | 46 | /// 47 | protected override PermissionValidationResult ValidateQueryParams(PagedListQueryParams queryParams) 48 | { 49 | if (queryParams.PageSize <= 0) 50 | { 51 | queryParams.PageSize = _appSettings.PageSize; 52 | } 53 | return new PermissionValidationResult(); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/Controllers/LogsWritable2Controller.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using Calabonga.Chat.AuthServer.Data; 3 | using Calabonga.Chat.AuthServer.Entities; 4 | using Calabonga.Chat.AuthServer.Web.Infrastructure.Auth; 5 | using Calabonga.Chat.AuthServer.Web.Infrastructure.Settings; 6 | using Calabonga.Chat.AuthServer.Web.ViewModels.LogViewModels; 7 | using Calabonga.Microservices.Core.QueryParams; 8 | using Calabonga.Microservices.Core.Validators; 9 | using Calabonga.UnitOfWork; 10 | using Calabonga.UnitOfWork.Controllers.Controllers; 11 | using Calabonga.UnitOfWork.Controllers.Factories; 12 | using Microsoft.AspNetCore.Authorization; 13 | using Microsoft.AspNetCore.Mvc; 14 | using Microsoft.Extensions.Options; 15 | 16 | namespace Calabonga.Chat.AuthServer.Web.Controllers 17 | { 18 | /// 19 | /// WritableController Demo 20 | /// 21 | [Route("api/[controller]")] 22 | [Authorize(AuthenticationSchemes = AuthData.AuthSchemes)] 23 | public class LogsWritable2Controller : WritableController 24 | { 25 | private readonly CurrentAppSettings _appSettings; 26 | 27 | /// 28 | public LogsWritable2Controller( 29 | IOptions appSettings, 30 | IEntityManagerFactory entityManagerFactory, 31 | IUnitOfWork unitOfWork, 32 | IMapper mapper) 33 | : base(entityManagerFactory, unitOfWork, mapper) 34 | => _appSettings = appSettings.Value; 35 | 36 | /// 37 | protected override PermissionValidationResult ValidateQueryParams(PagedListQueryParams queryParams) 38 | { 39 | if (queryParams.PageSize <= 0) 40 | { 41 | queryParams.PageSize = _appSettings.PageSize; 42 | } 43 | return new PermissionValidationResult(); 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/Controllers/LogsWritableController.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.Chat.AuthServer.Web.Infrastructure.Auth; 2 | using Calabonga.Chat.AuthServer.Web.Mediator.LogsReadonly; 3 | using Calabonga.Chat.AuthServer.Web.Mediator.LogsWritable; 4 | using Calabonga.Chat.AuthServer.Web.ViewModels.LogViewModels; 5 | using Calabonga.Microservices.Core.QueryParams; 6 | using MediatR; 7 | using Microsoft.AspNetCore.Authorization; 8 | using Microsoft.AspNetCore.Mvc; 9 | using System; 10 | using System.Threading.Tasks; 11 | 12 | namespace Calabonga.Chat.AuthServer.Web.Controllers 13 | { 14 | /// 15 | /// WritableController Demo 16 | /// 17 | [Route("api/[controller]")] 18 | [Authorize(AuthenticationSchemes = AuthData.AuthSchemes)] 19 | public class LogsWritableController : ControllerBase 20 | { 21 | private readonly IMediator _mediator; 22 | 23 | public LogsWritableController(IMediator mediator) => _mediator = mediator; 24 | 25 | 26 | [HttpGet("[action]/{id:guid}")] 27 | [ProducesResponseType(200)] 28 | public async Task GetById(Guid id) => Ok(await _mediator.Send(new LogGetByIdRequest(id), HttpContext.RequestAborted)); 29 | 30 | 31 | [HttpGet("[action]")] 32 | [ProducesResponseType(200)] 33 | public async Task GetPaged([FromQuery] PagedListQueryParams queryParams) => Ok(await _mediator.Send(new LogGetPagedRequest(queryParams), HttpContext.RequestAborted)); 34 | 35 | [HttpPost("[action]")] 36 | public async Task PostItem([FromBody] LogCreateViewModel model) => Ok(await _mediator.Send(new LogPostItemRequest(model), HttpContext.RequestAborted)); 37 | 38 | [HttpPut("[action]")] 39 | public async Task PutItem([FromBody] LogUpdateViewModel model) => Ok(await _mediator.Send(new LogPutItemRequest(model), HttpContext.RequestAborted)); 40 | 41 | [HttpDelete("[action]/{id:guid}")] 42 | public async Task DeleteItem(Guid id) => Ok(await _mediator.Send(new LogDeleteItemRequest(id), HttpContext.RequestAborted)); 43 | } 44 | } -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/Extensions/ApplicationBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | using Microsoft.AspNetCore.Mvc.ApplicationModels; 3 | using Microsoft.AspNetCore.Routing; 4 | using Microsoft.Extensions.DependencyInjection; 5 | using System.Text.RegularExpressions; 6 | 7 | namespace Calabonga.Chat.AuthServer.Web.Extensions 8 | { 9 | /// 10 | /// Extensions for application class 11 | /// 12 | public static class ApplicationBuilderExtensions 13 | { 14 | /// 15 | /// Use special route slugify for Pegasus routing 16 | /// 17 | /// 18 | public static void UseRouteSlugify(this MvcOptions options) => options.Conventions.Add(new RouteTokenTransformerConvention(new SlugifyParameterTransformer())); 19 | } 20 | 21 | /// 22 | /// Special route naming convention 23 | /// 24 | public class SlugifyParameterTransformer : IOutboundParameterTransformer 25 | { 26 | /// 27 | public string TransformOutbound(object value) => value == null 28 | ? null 29 | : Regex.Replace(value.ToString(), "([a-z])([A-Z])", "$1-$2").ToLower(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/Extensions/AssemblyExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Reflection; 4 | 5 | namespace Calabonga.Chat.AuthServer.Web.Extensions 6 | { 7 | /// 8 | /// Assembly helpers 9 | /// 10 | public static class AssemblyExtensions 11 | { 12 | /// 13 | /// Returns types 14 | /// 15 | /// 16 | /// 17 | /// 18 | public static List GetTypesAssignableFrom(this Assembly assembly) => assembly.GetTypesAssignableFrom(typeof(T)); 19 | 20 | private static List GetTypesAssignableFrom(this Assembly assembly, Type compareType) 21 | { 22 | var ret = new List(); 23 | foreach (var type in assembly.DefinedTypes) 24 | { 25 | if (compareType.IsAssignableFrom(type) && compareType != type && !type.IsAbstract) 26 | { 27 | ret.Add(type); 28 | } 29 | } 30 | return ret; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/Extensions/EntityValidatorExtensions.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.Microservices.Core.Validators; 2 | using System.Collections.Generic; 3 | 4 | namespace Calabonga.Chat.AuthServer.Web.Extensions 5 | { 6 | /// 7 | /// Entity Validator Extensions 8 | /// 9 | public static class EntityValidatorExtensions 10 | { 11 | /// 12 | /// Returns validator from validation results 13 | /// 14 | /// 15 | /// 16 | public static ValidationContext GetResult(this List source) => new ValidationContext(source); 17 | } 18 | } -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/Extensions/IdentityExtensions.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.Microservices.Core.Extensions; 2 | using IdentityServer4.Extensions; 3 | using System; 4 | using System.Security.Principal; 5 | 6 | namespace Calabonga.Chat.AuthServer.Web.Extensions 7 | { 8 | /// 9 | /// Extensions 10 | /// 11 | public static class IdentityExtensions 12 | { 13 | /// 14 | /// Returns true/false user is owner 15 | /// 16 | /// 17 | /// 18 | /// 19 | public static bool IsOwner(this IIdentity source, Guid userId) => source.GetSubjectId().ToGuid() == userId; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/Infrastructure/Attributes/SwaggerFormAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Calabonga.Chat.AuthServer.Web.Infrastructure.Attributes 4 | { 5 | /// 6 | /// Custom attribute for Swagger Upload Form 7 | /// 8 | [AttributeUsage(AttributeTargets.Method)] 9 | public sealed class SwaggerFormAttribute : Attribute 10 | { 11 | /// 12 | public SwaggerFormAttribute(string parameterName, string description, bool hasFileUpload = true) 13 | { 14 | ParameterName = parameterName; 15 | Description = description; 16 | HasFileUpload = hasFileUpload; 17 | } 18 | 19 | /// 20 | /// UploadFile enabled 21 | /// 22 | public bool HasFileUpload { get; } 23 | 24 | /// 25 | /// Name for the parameter 26 | /// 27 | public string ParameterName { get; } 28 | 29 | /// 30 | /// Small description 31 | /// 32 | public string Description { get; } 33 | } 34 | } -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/Infrastructure/Attributes/SwaggerGroupAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Calabonga.Chat.AuthServer.Web.Infrastructure.Attributes 4 | { 5 | /// 6 | /// Swagger controller group attribute 7 | /// 8 | /// 9 | [AttributeUsage(AttributeTargets.Class)] 10 | public class SwaggerGroupAttribute : Attribute 11 | { 12 | /// 13 | public SwaggerGroupAttribute(string groupName) => GroupName = groupName; 14 | 15 | /// 16 | /// Group name 17 | /// 18 | public string GroupName { get; } 19 | } 20 | } -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/Infrastructure/Attributes/ValidateModelStateAttribute.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.OperationResults; 2 | using Microsoft.AspNetCore.Mvc; 3 | using Microsoft.AspNetCore.Mvc.Filters; 4 | using System.Linq; 5 | 6 | namespace Calabonga.Chat.AuthServer.Web.Infrastructure.Attributes 7 | { 8 | /// 9 | /// Custom validation handler for availability to whit OperationResult 10 | /// 11 | public class ValidateModelStateAttribute : ActionFilterAttribute 12 | { 13 | /// 14 | public override void OnActionExecuting(ActionExecutingContext context) 15 | { 16 | if (context.ModelState.IsValid) 17 | { 18 | return; 19 | } 20 | var operation = OperationResult.CreateResult(); 21 | var messages = context.ModelState.Values.SelectMany(x => x.Errors.Select(xx => xx.ErrorMessage)); 22 | var message = string.Join(" ", messages); 23 | operation.AddError(message); 24 | context.Result = new OkObjectResult(operation); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/Infrastructure/Auth/AuthData.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Authentication.Cookies; 2 | using Microsoft.AspNetCore.Authentication.JwtBearer; 3 | 4 | namespace Calabonga.Chat.AuthServer.Web.Infrastructure.Auth 5 | { 6 | public static class AuthData 7 | { 8 | public const string AuthSchemes = CookieAuthenticationDefaults.AuthenticationScheme + "," + JwtBearerDefaults.AuthenticationScheme; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/Infrastructure/Auth/AuthorizationPolicyExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Authorization; 2 | using Microsoft.Extensions.DependencyInjection; 3 | 4 | namespace Calabonga.Chat.AuthServer.Web.Infrastructure.Auth 5 | { 6 | /// 7 | /// Authorization Policy registration 8 | /// 9 | public static class AuthorizationPolicyExtensions 10 | { 11 | /// 12 | /// Registers custom for able to use authorization by policy 13 | /// 14 | /// 15 | public static void UseMicroserviceAuthorizationPolicy(this IServiceCollection services) 16 | { 17 | services.AddSingleton(); 18 | services.AddSingleton(); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/Infrastructure/Auth/AuthorizationPolicyProvider.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Authorization; 2 | using Microsoft.Extensions.Options; 3 | using System.Threading.Tasks; 4 | 5 | namespace Calabonga.Chat.AuthServer.Web.Infrastructure.Auth 6 | { 7 | /// 8 | /// 9 | /// 10 | public class AuthorizationPolicyProvider : DefaultAuthorizationPolicyProvider 11 | { 12 | private readonly AuthorizationOptions _options; 13 | 14 | /// 15 | public AuthorizationPolicyProvider(IOptions options) : base(options) => _options = options.Value; 16 | 17 | /// 18 | public override async Task GetPolicyAsync(string policyName) 19 | { 20 | var policyExists = await base.GetPolicyAsync(policyName); 21 | if (policyExists != null) 22 | { 23 | return policyExists; 24 | } 25 | 26 | policyExists = new AuthorizationPolicyBuilder().AddRequirements(new PermissionRequirement(policyName)).Build(); 27 | _options.AddPolicy(policyName, policyExists); 28 | return policyExists; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/Infrastructure/Auth/IdentityServerCorsPolicy.cs: -------------------------------------------------------------------------------- 1 | using IdentityServer4.Services; 2 | using System.Threading.Tasks; 3 | 4 | namespace Calabonga.Chat.AuthServer.Web.Infrastructure.Auth 5 | { 6 | /// 7 | /// Customized CORS policy for IdentityServer4 8 | /// 9 | public class IdentityServerCorsPolicy : ICorsPolicyService 10 | { 11 | /// 12 | public Task IsOriginAllowedAsync(string origin) => Task.FromResult(true); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/Infrastructure/Auth/MicroservicePermissionHandler.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.Microservices.Core; 2 | using Microsoft.AspNetCore.Authorization; 3 | using System.Security.Claims; 4 | using System.Threading.Tasks; 5 | 6 | namespace Calabonga.Chat.AuthServer.Web.Infrastructure.Auth 7 | { 8 | /// 9 | /// Permission handler for custom authorization implementations 10 | /// 11 | public class MicroservicePermissionHandler : AuthorizationHandler 12 | { 13 | /// 14 | protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionRequirement requirement) 15 | { 16 | var identity = (ClaimsIdentity)context.User.Identity; 17 | var claim = ClaimsHelper.GetValue(identity, requirement.PermissionName); 18 | if (claim == null) 19 | { 20 | return Task.CompletedTask; 21 | } 22 | 23 | context.Succeed(requirement); 24 | return Task.CompletedTask; 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/Infrastructure/Auth/PermissionRequirement.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Authorization; 2 | 3 | namespace Calabonga.Chat.AuthServer.Web.Infrastructure.Auth 4 | { 5 | /// 6 | /// Permission requirement for user or service authorization 7 | /// 8 | public class PermissionRequirement : IAuthorizationRequirement 9 | { 10 | public PermissionRequirement(string permissionName) => PermissionName = permissionName; 11 | 12 | /// 13 | /// Permission name 14 | /// 15 | public string PermissionName { get; } 16 | } 17 | } -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/Infrastructure/Auth/UserIdentity.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.Microservices.Core.Exceptions; 2 | using Microsoft.AspNetCore.Http; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Security.Claims; 6 | using System.Security.Principal; 7 | 8 | namespace Calabonga.Chat.AuthServer.Web.Infrastructure.Auth 9 | { 10 | /// 11 | /// Identity helper for Requests operations 12 | /// 13 | public sealed class UserIdentity 14 | { 15 | private UserIdentity() { } 16 | 17 | public static UserIdentity Instance => Lazy.Value; 18 | 19 | public void Configure(IHttpContextAccessor httpContextAccessor) 20 | { 21 | ContextAccessor = httpContextAccessor ?? throw new MicroserviceArgumentNullException(nameof(IHttpContextAccessor)); 22 | IsInitialized = true; 23 | } 24 | 25 | public IIdentity? User 26 | { 27 | get 28 | { 29 | if (IsInitialized) 30 | { 31 | return ContextAccessor.HttpContext!.User.Identity != null 32 | && ContextAccessor.HttpContext != null 33 | && ContextAccessor.HttpContext.User.Identity.IsAuthenticated 34 | ? ContextAccessor.HttpContext.User.Identity 35 | : null; 36 | } 37 | throw new MicroserviceArgumentNullException($"{nameof(UserIdentity)} has not been initialized. Please use {nameof(UserIdentity)}.Instance.Configure(...) in Configure Application method in Startup.cs"); 38 | } 39 | } 40 | 41 | public IEnumerable Claims 42 | { 43 | get 44 | { 45 | if (User != null) 46 | { 47 | return ContextAccessor.HttpContext!.User.Claims; 48 | } 49 | return null; 50 | } 51 | } 52 | 53 | private static readonly Lazy Lazy = new Lazy(() => new UserIdentity()); 54 | 55 | private bool IsInitialized { get; set; } 56 | 57 | private static IHttpContextAccessor ContextAccessor { get; set; } = null!; 58 | 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/Infrastructure/DependencyInjection/CommonRegistrations.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.Chat.AuthServer.Data; 2 | using Calabonga.Chat.AuthServer.Web.Infrastructure.Auth; 3 | using Calabonga.Chat.AuthServer.Web.Infrastructure.Services; 4 | using IdentityServer4.Services; 5 | using Microsoft.Extensions.DependencyInjection; 6 | 7 | namespace Calabonga.Chat.AuthServer.Web.Infrastructure.DependencyInjection 8 | { 9 | /// 10 | /// Registrations for both points: API and Scheduler 11 | /// 12 | public partial class DependencyContainer 13 | { 14 | /// 15 | /// Register 16 | /// 17 | /// 18 | public static void Common(IServiceCollection services) 19 | { 20 | services.AddTransient(); 21 | services.AddTransient(); 22 | services.AddScoped(); 23 | 24 | // services 25 | services.AddTransient(); 26 | services.AddTransient(); 27 | services.AddTransient(); 28 | services.AddTransient(); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/Infrastructure/Engine/EntityManagers/LogManager.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using Calabonga.Chat.AuthServer.Entities; 3 | using Calabonga.Chat.AuthServer.Web.ViewModels.LogViewModels; 4 | using Calabonga.Microservices.Core.Validators; 5 | using Calabonga.UnitOfWork.Controllers.Factories; 6 | using Calabonga.UnitOfWork.Controllers.Managers; 7 | using System.Security.Principal; 8 | 9 | namespace Calabonga.Chat.AuthServer.Web.Infrastructure.Engine.EntityManagers 10 | { 11 | /// 12 | /// Entity manager for 13 | /// 14 | public class LogManager : EntityManager 15 | { 16 | /// 17 | public LogManager(IMapper mapper, IViewModelFactory viewModelFactory, IEntityValidator validator) 18 | : base(mapper, viewModelFactory, validator) 19 | { 20 | } 21 | 22 | protected override IIdentity? GetIdentity() => null; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/Infrastructure/Engine/EntityValidators/LogValidator.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.Chat.AuthServer.Entities; 2 | using Calabonga.Microservices.Core.Validators; 3 | 4 | namespace Calabonga.Chat.AuthServer.Web.Infrastructure.Engine.EntityValidators 5 | { 6 | /// 7 | /// Entity Validator for 8 | /// 9 | public class LogValidator : EntityValidator 10 | { 11 | 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/Infrastructure/EventLogs/EventNumbers.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Logging; 2 | 3 | namespace Calabonga.Chat.AuthServer.Web.Infrastructure.EventLogs 4 | { 5 | /// 6 | /// The number identifiers for events in the microservices 7 | /// 8 | static class EventNumbers 9 | { 10 | internal static readonly EventId UserRegistrationId = new EventId(9001, nameof(UserRegistrationId)); 11 | internal static readonly EventId PostItemId = new EventId(9002, nameof(PostItemId)); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/Infrastructure/Helpers/ValidationContextHelper.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.ObjectModel; 2 | using System.ComponentModel.DataAnnotations; 3 | 4 | namespace Calabonga.Chat.AuthServer.Web.Infrastructure.Helpers 5 | { 6 | /// 7 | /// ValidationContext Helper for validation operations 8 | /// 9 | public static class ValidationContextHelper 10 | { 11 | /// 12 | /// Returns validation results of IValidatableObject 13 | /// 14 | /// 15 | /// 16 | /// 17 | /// 18 | public static bool TryValidate(object obj, out Collection results, ValidationContext validationContext = null) 19 | { 20 | var context = validationContext ?? new ValidationContext(obj, serviceProvider: null, items: null); 21 | results = new Collection(); 22 | return Validator.TryValidateObject(obj, context, results, validateAllProperties: true); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/Infrastructure/Mappers/ApplicationUserProfileMapperConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.Chat.AuthServer.Data; 2 | using Calabonga.Chat.AuthServer.Web.Infrastructure.Mappers.Base; 3 | using Calabonga.Chat.AuthServer.Web.ViewModels.AccountViewModels; 4 | 5 | namespace Calabonga.Chat.AuthServer.Web.Infrastructure.Mappers 6 | { 7 | /// 8 | /// Mapper Configuration for entity Person 9 | /// 10 | public class ApplicationUserProfileMapperConfiguration : MapperConfigurationBase 11 | { 12 | /// 13 | public ApplicationUserProfileMapperConfiguration() => CreateMap() 14 | .ForAllOtherMembers(x => x.Ignore()); 15 | } 16 | } -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/Infrastructure/Mappers/Base/IAutoMapper.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace Calabonga.Chat.AuthServer.Web.Infrastructure.Mappers.Base 3 | { 4 | /// 5 | /// The stub for reflection helper profiles registrations 6 | /// 7 | public interface IAutoMapper { } 8 | } -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/Infrastructure/Mappers/Base/MapperConfigurationBase.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | 3 | namespace Calabonga.Chat.AuthServer.Web.Infrastructure.Mappers.Base 4 | { 5 | /// 6 | /// Base class for mapper configuration. 7 | /// All ViewModel that will be mapped should implement IAutoMapper 8 | /// 9 | public abstract class MapperConfigurationBase : Profile, IAutoMapper { } 10 | } 11 | -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/Infrastructure/Mappers/Base/PagedListConverter.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using Calabonga.UnitOfWork; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | 6 | namespace Calabonga.Chat.AuthServer.Web.Infrastructure.Mappers.Base 7 | { 8 | /// 9 | /// Generic converter for IPagedList collections 10 | /// 11 | /// 12 | /// 13 | public class PagedListConverter : ITypeConverter, IPagedList> 14 | { 15 | 16 | /// Performs conversion from source to destination type 17 | /// Source object 18 | /// Destination object 19 | /// Resolution context 20 | /// Destination object 21 | public IPagedList Convert(IPagedList source, IPagedList destination, ResolutionContext context) 22 | { 23 | if (source == null) 24 | { 25 | return null; 26 | } 27 | var vm = source.Items.Select(m => context.Mapper.Map(m)).ToList(); 28 | 29 | 30 | var pagedList = PagedList.From(source, (con) => context.Mapper.Map>(con)); 31 | // var pagedList = vm.ToPagedList(source.PageIndex, source.PageSize); 32 | return pagedList; 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/Infrastructure/Mappers/LogMapperConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.Chat.AuthServer.Entities; 2 | using Calabonga.Chat.AuthServer.Web.Infrastructure.Mappers.Base; 3 | using Calabonga.Chat.AuthServer.Web.ViewModels.LogViewModels; 4 | using Calabonga.UnitOfWork; 5 | 6 | namespace Calabonga.Chat.AuthServer.Web.Infrastructure.Mappers 7 | { 8 | /// 9 | /// Mapper Configuration for entity Log 10 | /// 11 | public class LogMapperConfiguration : MapperConfigurationBase 12 | { 13 | /// 14 | public LogMapperConfiguration() 15 | { 16 | CreateMap() 17 | .ForMember(x => x.Id, o => o.Ignore()); 18 | 19 | CreateMap(); 20 | 21 | CreateMap(); 22 | 23 | CreateMap() 24 | .ForMember(x => x.CreatedAt, o => o.Ignore()) 25 | .ForMember(x => x.ThreadId, o => o.Ignore()) 26 | .ForMember(x => x.ExceptionMessage, o => o.Ignore()); 27 | 28 | CreateMap, IPagedList>() 29 | .ConvertUsing>(); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/Infrastructure/Mappers/UserMapperConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.Chat.AuthServer.Data; 2 | using Calabonga.Chat.AuthServer.Web.Infrastructure.Mappers.Base; 3 | using Calabonga.Chat.AuthServer.Web.ViewModels.AccountViewModels; 4 | using Calabonga.Microservices.Core; 5 | using IdentityModel; 6 | using System; 7 | using System.Security.Claims; 8 | 9 | namespace Calabonga.Chat.AuthServer.Web.Infrastructure.Mappers 10 | { 11 | /// 12 | /// Mapper Configuration for entity ApplicationUser 13 | /// 14 | public class UserMapperConfiguration : MapperConfigurationBase 15 | { 16 | /// 17 | public UserMapperConfiguration() 18 | { 19 | CreateMap() 20 | .ForMember(x => x.UserName, o => o.MapFrom(p => p.Email)) 21 | .ForMember(x => x.Email, o => o.MapFrom(p => p.Email)) 22 | .ForMember(x => x.EmailConfirmed, o => o.MapFrom(src => true)) 23 | .ForMember(x => x.FirstName, o => o.MapFrom(p => p.FirstName)) 24 | .ForMember(x => x.LastName, o => o.MapFrom(p => p.LastName)) 25 | .ForMember(x => x.PhoneNumberConfirmed, o => o.MapFrom(src => true)) 26 | .ForAllOtherMembers(x => x.Ignore()); 27 | 28 | CreateMap() 29 | .ForMember(x => x.Id, o => o.MapFrom(claims => ClaimsHelper.GetValue(claims, JwtClaimTypes.Subject))) 30 | .ForMember(x => x.PositionName, o => o.MapFrom(claims => ClaimsHelper.GetValue(claims, ClaimTypes.Actor))) 31 | .ForMember(x => x.FirstName, o => o.MapFrom(claims => ClaimsHelper.GetValue(claims, JwtClaimTypes.GivenName))) 32 | .ForMember(x => x.LastName, o => o.MapFrom(claims => ClaimsHelper.GetValue(claims, ClaimTypes.Surname))) 33 | .ForMember(x => x.Roles, o => o.MapFrom(claims => ClaimsHelper.GetValues(claims, JwtClaimTypes.Role))) 34 | .ForMember(x => x.Email, o => o.MapFrom(claims => ClaimsHelper.GetValue(claims, JwtClaimTypes.Name))) 35 | .ForMember(x => x.PhoneNumber, o => o.MapFrom(claims => ClaimsHelper.GetValue(claims, JwtClaimTypes.PhoneNumber))) 36 | .ForAllOtherMembers(x => x.Ignore()); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/Infrastructure/Services/ICacheService.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Caching.Memory; 2 | using System; 3 | 4 | namespace Calabonga.Chat.AuthServer.Web.Infrastructure.Services 5 | { 6 | /// 7 | /// Cache service interface 8 | /// 9 | public interface ICacheService 10 | { 11 | /// 12 | /// Get the entry from the cache 13 | /// 14 | /// 15 | /// 16 | TEntry Get(object key); 17 | 18 | /// 19 | /// Sets entry cache for one minute sliding expiration 20 | /// 21 | /// 22 | /// 23 | /// 24 | void SetForMinute(object key, TEntry cacheEntry); 25 | 26 | /// 27 | /// Sets entry cache for 30 minutes sliding expiration 28 | /// 29 | /// 30 | /// 31 | /// 32 | void SetForThirtyMinutes(object key, TEntry cacheEntry); 33 | 34 | /// 35 | /// Sets entry cache for custom sliding expiration interval 36 | /// 37 | /// 38 | /// 39 | /// 40 | /// 41 | void SetWithSlidingExpiration(object key, TEntry cacheEntry, TimeSpan slidingExpiration); 42 | 43 | /// 44 | /// Returns already exist entry or first put it to the cache and then return entry 45 | /// 46 | /// 47 | /// 48 | /// 49 | /// 50 | /// 51 | TEntry GetOrCreate(TKey key, Func findIfNotFoundFunc); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/Infrastructure/Services/IdentityProfileService.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.Microservices.Core.Extensions; 2 | using IdentityServer4.Extensions; 3 | using IdentityServer4.Models; 4 | using IdentityServer4.Services; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | 8 | namespace Calabonga.Chat.AuthServer.Web.Infrastructure.Services 9 | { 10 | /// 11 | /// Custom implementation of the IProfileService 12 | /// 13 | public class IdentityProfileService : IProfileService 14 | { 15 | private readonly IAccountService _accountService; 16 | /// 17 | /// Identity Profile Service 18 | /// 19 | /// 20 | public IdentityProfileService(IAccountService accountService) => _accountService = accountService; 21 | 22 | /// 23 | /// This method is called whenever claims about the user are requested (e.g. during token creation or via the user info endpoint) 24 | /// 25 | /// The context. 26 | /// 27 | public async Task GetProfileDataAsync(ProfileDataRequestContext context) 28 | { 29 | var identifier = context.Subject.GetSubjectId(); 30 | var profile = await _accountService.GetUserClaimsAsync(identifier); 31 | context.IssuedClaims = profile.Claims.ToList(); 32 | } 33 | 34 | /// 35 | /// Returns IsActive (IdentityServer4) 36 | /// 37 | /// 38 | /// 39 | public async Task IsActiveAsync(IsActiveContext context) 40 | { 41 | var identifier = context.Subject.GetSubjectId(); 42 | var user = await _accountService.GetByIdAsync(identifier.ToGuid()); 43 | context.IsActive = user != null; 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/Infrastructure/Settings/CurrentAppSettings.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace Calabonga.Chat.AuthServer.Web.Infrastructure.Settings 3 | { 4 | /// 5 | /// Represents configuration file with current application settings 6 | /// 7 | public class CurrentAppSettings 8 | { 9 | /// 10 | /// Default page size 11 | /// 12 | public int PageSize { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/Mediator/Account/Profile.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.AspNetCore.Controllers; 2 | using Calabonga.AspNetCore.Controllers.Base; 3 | using Calabonga.Chat.AuthServer.Web.Infrastructure.Services; 4 | using Calabonga.Chat.AuthServer.Web.ViewModels.AccountViewModels; 5 | using Calabonga.OperationResults; 6 | using IdentityServer4.Extensions; 7 | using Microsoft.AspNetCore.Http; 8 | using System.Threading; 9 | using System.Threading.Tasks; 10 | 11 | namespace Calabonga.Chat.AuthServer.Web.Mediator.Account 12 | { 13 | /// 14 | /// Request: Profile 15 | /// 16 | public class ProfileRequest : RequestBase> 17 | { 18 | } 19 | 20 | /// 21 | /// Response: Profile 22 | /// 23 | public class ProfileRequestHandler : OperationResultRequestHandlerBase 24 | { 25 | private readonly IAccountService _accountService; 26 | private readonly IHttpContextAccessor _httpContextAccessor; 27 | 28 | public ProfileRequestHandler( 29 | IAccountService accountService, 30 | IHttpContextAccessor httpContextAccessor) 31 | { 32 | _accountService = accountService; 33 | _httpContextAccessor = httpContextAccessor; 34 | } 35 | 36 | public override async Task> Handle(ProfileRequest request, CancellationToken cancellationToken) 37 | { 38 | var user = _httpContextAccessor.HttpContext.User; 39 | if (user != null) 40 | { 41 | return await _accountService.GetProfileAsync(user.Identity.GetSubjectId()); 42 | } 43 | 44 | var operation = OperationResult.CreateResult(); 45 | operation.AddWarning("User not found"); 46 | return operation; 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/Mediator/Account/Register.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.AspNetCore.Controllers; 2 | using Calabonga.AspNetCore.Controllers.Base; 3 | using Calabonga.Chat.AuthServer.Web.Infrastructure.Services; 4 | using Calabonga.Chat.AuthServer.Web.ViewModels.AccountViewModels; 5 | using Calabonga.OperationResults; 6 | using System.Threading; 7 | using System.Threading.Tasks; 8 | 9 | namespace Calabonga.Chat.AuthServer.Web.Mediator.Account 10 | { 11 | /// 12 | /// Request: Register new account 13 | /// 14 | public class RegisterRequest : RequestBase> 15 | { 16 | public RegisterViewModel Model { get; } 17 | 18 | public RegisterRequest(RegisterViewModel model) => Model = model; 19 | } 20 | 21 | /// 22 | /// Response: Register new account 23 | /// 24 | public class RegisterRequestHandler : OperationResultRequestHandlerBase 25 | { 26 | private readonly IAccountService _accountService; 27 | 28 | public RegisterRequestHandler(IAccountService accountService) => _accountService = accountService; 29 | 30 | public override Task> Handle(RegisterRequest request, CancellationToken cancellationToken) => _accountService.RegisterAsync(request.Model); 31 | } 32 | } -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/Mediator/LogsReadonly/GetRoles.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.AspNetCore.Controllers.Records; 2 | using Calabonga.Microservices.Core; 3 | using MediatR; 4 | using Microsoft.AspNetCore.Http; 5 | using System.Security.Claims; 6 | 7 | namespace Calabonga.Chat.AuthServer.Web.Mediator.LogsReadonly 8 | { 9 | /// 10 | /// Request: Returns user roles 11 | /// 12 | public record GetRolesRequest : RequestBase; 13 | 14 | public class GetRolesRequestHandler : RequestHandler 15 | { 16 | private readonly IHttpContextAccessor _httpContextAccessor; 17 | 18 | public GetRolesRequestHandler(IHttpContextAccessor httpContextAccessor) => _httpContextAccessor = httpContextAccessor; 19 | 20 | protected override string Handle(GetRolesRequest request) 21 | { 22 | var user = _httpContextAccessor.HttpContext!.User; 23 | var roles = ClaimsHelper.GetValues((ClaimsIdentity)user.Identity, "role"); 24 | return $"Current user ({user.Identity.Name}) have following roles: {string.Join("|", roles)}"; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/Mediator/LogsReadonly/LogGetById.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using Calabonga.AspNetCore.Controllers; 3 | using Calabonga.AspNetCore.Controllers.Records; 4 | using Calabonga.Chat.AuthServer.Entities; 5 | using Calabonga.Chat.AuthServer.Web.ViewModels.LogViewModels; 6 | using Calabonga.Microservices.Core.Exceptions; 7 | using Calabonga.OperationResults; 8 | using Calabonga.UnitOfWork; 9 | using System; 10 | using System.Threading; 11 | using System.Threading.Tasks; 12 | 13 | namespace Calabonga.Chat.AuthServer.Web.Mediator.LogsReadonly 14 | { 15 | /// 16 | /// Request for Log by Identifier 17 | /// 18 | public record LogGetByIdRequest(Guid Id) : OperationResultRequestBase; 19 | 20 | /// 21 | /// Response for Request for Log by Identifier 22 | /// 23 | public class LogGetByIdRequestHandler : OperationResultRequestHandlerBase 24 | { 25 | private readonly IUnitOfWork _unitOfWork; 26 | private readonly IMapper _mapper; 27 | 28 | public LogGetByIdRequestHandler(IUnitOfWork unitOfWork, IMapper mapper) 29 | { 30 | _unitOfWork = unitOfWork; 31 | _mapper = mapper; 32 | } 33 | 34 | public override async Task> Handle(LogGetByIdRequest request, CancellationToken cancellationToken) 35 | { 36 | var id = request.Id; 37 | var operation = OperationResult.CreateResult(); 38 | var repository = _unitOfWork.GetRepository(); 39 | var entityWithoutIncludes = await repository.GetFirstOrDefaultAsync(predicate: x => x.Id == id); 40 | if (entityWithoutIncludes == null) 41 | { 42 | operation.AddError(new MicroserviceNotFoundException($"Entity with identifier {id} not found")); 43 | return operation; 44 | } 45 | operation.Result = _mapper.Map(entityWithoutIncludes); 46 | return operation; 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/Mediator/LogsWritable/LogDeleteItem.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using Calabonga.AspNetCore.Controllers; 3 | using Calabonga.AspNetCore.Controllers.Records; 4 | using Calabonga.Chat.AuthServer.Entities; 5 | using Calabonga.Chat.AuthServer.Web.ViewModels.LogViewModels; 6 | using Calabonga.Microservices.Core.Exceptions; 7 | using Calabonga.OperationResults; 8 | using Calabonga.UnitOfWork; 9 | using System; 10 | using System.Threading; 11 | using System.Threading.Tasks; 12 | 13 | namespace Calabonga.Chat.AuthServer.Web.Mediator.LogsWritable 14 | { 15 | /// 16 | /// Request: Log delete 17 | /// 18 | public record LogDeleteItemRequest(Guid Id) : OperationResultRequestBase; 19 | 20 | /// 21 | /// Request: Log delete 22 | /// 23 | public class LogDeleteItemRequestHandler : OperationResultRequestHandlerBase 24 | { 25 | private readonly IUnitOfWork _unitOfWork; 26 | 27 | private readonly IMapper _mapper; 28 | 29 | public LogDeleteItemRequestHandler(IUnitOfWork unitOfWork, IMapper mapper) 30 | { 31 | _unitOfWork = unitOfWork; 32 | _mapper = mapper; 33 | } 34 | 35 | public override async Task> Handle(LogDeleteItemRequest request, CancellationToken cancellationToken) 36 | { 37 | var operation = OperationResult.CreateResult(); 38 | var repository = _unitOfWork.GetRepository(); 39 | var entity = await repository.FindAsync(request.Id); 40 | if (entity == null) 41 | { 42 | operation.AddError(new MicroserviceNotFoundException("Entity not found")); 43 | return operation; 44 | } 45 | repository.Delete(entity); 46 | await _unitOfWork.SaveChangesAsync(); 47 | if (_unitOfWork.LastSaveChangesResult.IsOk) 48 | { 49 | operation.Result = _mapper.Map(entity); 50 | return operation; 51 | } 52 | operation.AddError(_unitOfWork.LastSaveChangesResult.Exception); 53 | return operation; 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/Middlewares/ErrorHandle.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.UnitOfWork; 2 | using Microsoft.AspNetCore.Http; 3 | using Newtonsoft.Json; 4 | using System; 5 | using System.Threading.Tasks; 6 | 7 | namespace Calabonga.Chat.AuthServer.Web.Middlewares 8 | { 9 | /// 10 | /// Custom error handler. It allows to view error messages on UI 11 | /// 12 | public class ErrorHandlingMiddleware 13 | { 14 | private readonly RequestDelegate _next; 15 | 16 | /// 17 | public ErrorHandlingMiddleware(RequestDelegate next) => _next = next; 18 | 19 | /// 20 | /// Invoke middle ware. Entry point 21 | /// 22 | /// 23 | /// 24 | public async Task Invoke(HttpContext context) 25 | { 26 | try 27 | { 28 | await _next(context); 29 | } 30 | catch (Exception ex) 31 | { 32 | await HandleExceptionAsync(context, ex); 33 | } 34 | } 35 | 36 | private static Task HandleExceptionAsync(HttpContext context, Exception exception) 37 | { 38 | try 39 | { 40 | var result = JsonConvert.SerializeObject(ExceptionHelper.GetMessages(exception), Formatting.Indented); 41 | if (result?.Length > 4000) 42 | { 43 | return context.Response.WriteAsync("Error message to long. Please use DEBUG in method HandleExceptionAsync to handle a whole of text of the exception"); 44 | } 45 | return context.Response.WriteAsync(result); 46 | } 47 | catch 48 | { 49 | return context.Response.WriteAsync($"{exception.Message} For more information please use DEBUG in method HandleExceptionAsync to handle a whole of text of the exception"); 50 | } 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/ViewModels/AccountViewModels/LoginViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace Calabonga.Chat.AuthServer.Web.ViewModels.AccountViewModels 4 | { 5 | public class LoginViewModel 6 | { 7 | [Required] 8 | public string UserName { get; set; } 9 | 10 | [Required] 11 | public string Password { get; set; } 12 | 13 | [Required] 14 | public string ReturnUrl { get; set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/ViewModels/AccountViewModels/RegisterViewModel.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace Calabonga.Chat.AuthServer.Web.ViewModels.AccountViewModels 4 | { 5 | /// 6 | /// Data transfer object for user registration 7 | /// 8 | public class RegisterViewModel 9 | { 10 | /// 11 | /// FirstName 12 | /// 13 | [Required] 14 | [StringLength(50, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 2)] 15 | [Display(Name = "First Name")] 16 | public string FirstName { get; set; } 17 | 18 | /// 19 | /// LastName 20 | /// 21 | [Required] 22 | [StringLength(50, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 2)] 23 | [Display(Name = "Last Name")] 24 | public string LastName { get; set; } 25 | 26 | /// 27 | /// Email 28 | /// 29 | [Required] 30 | [EmailAddress] 31 | [Display(Name = "Email")] 32 | public string Email { get; set; } 33 | 34 | /// 35 | /// Password 36 | /// 37 | [Required] 38 | [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)] 39 | [DataType(DataType.Password)] 40 | [Display(Name = "Password")] 41 | public string Password { get; set; } 42 | 43 | /// 44 | /// Password confirmation 45 | /// 46 | [DataType(DataType.Password)] 47 | [Display(Name = "Confirm password")] 48 | [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")] 49 | public string ConfirmPassword { get; set; } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/ViewModels/AccountViewModels/RegisterViewModelValidator.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.Chat.AuthServer.Web.Mediator.Account; 2 | using FluentValidation; 3 | 4 | namespace Calabonga.Chat.AuthServer.Web.ViewModels.AccountViewModels 5 | { 6 | /// 7 | /// RegisterViewModel Validator 8 | /// 9 | public class RegisterRequestValidator : AbstractValidator 10 | { 11 | public RegisterRequestValidator() => RuleSet("default", () => 12 | { 13 | RuleFor(x => x.Model.Email).NotNull().EmailAddress(); 14 | RuleFor(x => x.Model.FirstName).NotEmpty().NotNull().MaximumLength(50); 15 | RuleFor(x => x.Model.LastName).NotEmpty().NotNull().MaximumLength(50); 16 | RuleFor(x => x.Model.Password).NotNull().NotEmpty().MaximumLength(50); 17 | RuleFor(x => x.Model.ConfirmPassword).NotNull().MaximumLength(50).Equal(x => x.Model.Password).When(x => !string.IsNullOrEmpty(x.Model.Password)); 18 | }); 19 | } 20 | } -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/ViewModels/AccountViewModels/UserProfileViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Calabonga.Chat.AuthServer.Web.ViewModels.AccountViewModels 5 | { 6 | /// 7 | /// Application User Profile 8 | /// 9 | public class UserProfileViewModel 10 | { 11 | /// 12 | /// Identifier 13 | /// 14 | public Guid Id { get; set; } 15 | 16 | /// 17 | /// FirstName 18 | /// 19 | public string FirstName { get; set; } 20 | 21 | /// 22 | /// LastName 23 | /// 24 | public string LastName { get; set; } 25 | 26 | /// 27 | /// Email 28 | /// 29 | public string Email { get; set; } 30 | 31 | /// 32 | /// User Roles 33 | /// 34 | public List Roles { get; set; } 35 | 36 | /// 37 | /// User PhoneNumber 38 | /// 39 | public string PhoneNumber { get; set; } 40 | 41 | /// 42 | /// Position Name 43 | /// 44 | public string PositionName { get; set; } 45 | } 46 | } -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/ViewModels/LogViewModels/LogCreateViewModel.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.EntityFrameworkCore.Entities.Base; 2 | using Microsoft.Extensions.Logging; 3 | using System; 4 | using System.ComponentModel.DataAnnotations; 5 | 6 | namespace Calabonga.Chat.AuthServer.Web.ViewModels.LogViewModels 7 | { 8 | /// 9 | /// Data Transfer Object for Log entity 10 | /// 11 | public class LogCreateViewModel : IViewModel 12 | { 13 | /// 14 | /// Log Created At 15 | /// 16 | [Required] 17 | public DateTime CreatedAt { get; set; } 18 | 19 | /// 20 | /// Service name or provider 21 | /// 22 | [Required] 23 | [StringLength(255)] 24 | public string Logger { get; set; } 25 | 26 | /// 27 | /// Log level for logging. See 28 | /// 29 | [Required] 30 | [StringLength(50)] 31 | public string Level { get; set; } 32 | 33 | /// 34 | /// Log Message 35 | /// 36 | [Required] 37 | [StringLength(4000)] 38 | public string Message { get; set; } 39 | 40 | /// 41 | /// Thread identifier 42 | /// 43 | public string ThreadId { get; set; } 44 | 45 | /// 46 | /// Exception message 47 | /// 48 | public string ExceptionMessage { get; set; } 49 | } 50 | } -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/ViewModels/LogViewModels/LogUpdateViewModel.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.EntityFrameworkCore.Entities.Base; 2 | 3 | namespace Calabonga.Chat.AuthServer.Web.ViewModels.LogViewModels 4 | { 5 | /// 6 | /// Log View model for Update operations 7 | /// 8 | public class LogUpdateViewModel : ViewModelBase 9 | { 10 | public string Logger { get; set; } 11 | 12 | public string Level { get; set; } 13 | 14 | public string Message { get; set; } 15 | } 16 | } -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/ViewModels/LogViewModels/LogViewModel.cs: -------------------------------------------------------------------------------- 1 | using Calabonga.EntityFrameworkCore.Entities.Base; 2 | using System; 3 | 4 | namespace Calabonga.Chat.AuthServer.Web.ViewModels.LogViewModels 5 | { 6 | /// 7 | /// Log ViewModel 8 | /// 9 | public class LogViewModel : ViewModelBase 10 | { 11 | /// 12 | /// Created at 13 | /// 14 | public DateTime CreatedAt { get; set; } 15 | 16 | /// 17 | /// Logger name 18 | /// 19 | public string Logger { get; set; } 20 | 21 | /// 22 | /// Level 23 | /// 24 | public string Level { get; set; } 25 | 26 | /// 27 | /// Message text 28 | /// 29 | public string Message { get; set; } 30 | 31 | /// 32 | /// Thread ID 33 | /// 34 | public string ThreadId { get; set; } 35 | 36 | /// 37 | /// 38 | /// 39 | public string ExceptionMessage { get; set; } 40 | } 41 | } -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/Views/Authentication/Login.cshtml: -------------------------------------------------------------------------------- 1 | @model Calabonga.Chat.AuthServer.Web.ViewModels.AccountViewModels.LoginViewModel 2 | 3 |
4 | 5 |
6 | 7 |

Enter zone

8 | 9 |
10 | 11 | 12 | 13 |
14 | 15 | 16 |
17 | 18 |
19 | 20 | 21 |
22 |

23 | 24 |

25 | 26 |
27 |
28 |
-------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/Views/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | @ViewBag.Title 7 | 8 | 9 | 10 |
11 | @RenderBody() 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/Views/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @addTagHelper *,Microsoft.AspNetCore.Mvc.TagHelpers -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "_Layout"; 3 | } 4 | -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "ConnectionStrings": { 3 | "ApplicationDbContext": "Server=;Database=;User ID=;Password=" 4 | }, 5 | "Logging": { 6 | "IncludeScopes": false, 7 | "Debug": { 8 | "LogLevel": { 9 | "Default": "Warning", 10 | "System": "Information", 11 | "Microsoft": "Information", 12 | "IdentityServer4": "Warning" 13 | } 14 | }, 15 | "Console": { 16 | "LogLevel": { 17 | "Default": "Warning", 18 | "System": "Information", 19 | "Microsoft": "Information", 20 | "IdentityServer4": "Warning" 21 | } 22 | } 23 | }, 24 | "Cors": { 25 | "Origins": "*" 26 | }, 27 | "IdentityServer": { 28 | "Url": "https://localhost:10001" 29 | }, 30 | "CurrentAppSettings": { 31 | "PageSize": 50 32 | } 33 | } -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/appsettings.Production.json: -------------------------------------------------------------------------------- 1 | { 2 | "ConnectionStrings": { 3 | "ApplicationDbContext": "Server=;Database=;User ID=;Password=" 4 | }, 5 | "Logging": { 6 | "IncludeScopes": false, 7 | "Debug": { 8 | "LogLevel": { 9 | "Default": "Warning", 10 | "System": "Information", 11 | "Microsoft": "Information" 12 | } 13 | }, 14 | "Console": { 15 | "LogLevel": { 16 | "Default": "Warning", 17 | "System": "Information", 18 | "Microsoft": "Information" 19 | } 20 | } 21 | }, 22 | "Cors": { 23 | "Origins": "*" 24 | }, 25 | "IdentityServer": { 26 | "Url": "http://localhost:10001" 27 | }, 28 | "CurrentAppSettings": { 29 | "PageSize": 50 30 | } 31 | } -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/launchsettings.json", 3 | "Logging": { 4 | "LogLevel": { 5 | "Default": "Information", 6 | "Microsoft": "Warning", 7 | "Microsoft.Hosting.Lifetime": "Information", 8 | "IdentityServer4": "Warning" 9 | } 10 | }, 11 | "AllowedHosts": "*" 12 | } 13 | -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/tempkey.jwk: -------------------------------------------------------------------------------- 1 | {"alg":"RS256","d":"MR0gmrThHp6iHjLVL8ofRvz30UDV-L3B0QBLey15bVRo-nTDpTduvPaNDdh3WmbDCCTyoZ4dfWY3YREMtD7PeoG3otgBxnIL6ZBEwvT2QrutJnuPNQ0wU2LVQCFbNRYaA1GebDeTQt7qpUxlqx_Dm8zDoOWYw52cAjkq0UuesCq7maI0_ffGGIOyv-yyHpmVpu9c5aakmdHeP4vj9P3HrLEc8OI2RwYgH1FflIexHOs0tjmskK2TB1HwGLBlgD5YX36tAWsxLRtNxAuZdKvmQxwVqEpkffuCfm3X8LE_7J6qXxcsoVOB_oyQm_1TUocuOLwrHnFab6UITjlusPP00Q","dp":"LiHZEkcE9c_w6Wt29WfVrqd7Kr4s_q-ApWZAMqdndJqbfoGUQYQ6F0x6U8P_UkUmyJTRCtGWRjwajDZI0f6St297xjg-jSO_2rbcpqvmAdYOZEAA6OM-CDWyN7MxhHNaA_piOK7DByV3oFp7jaQ_1U5BqAPLr9vp4_nOIyhHDMM","dq":"8KFJso4RZE6hJALNTGdSHRhxC4ulQhd-jP0pPft_IGLBQe5GceX3lEGi3He2MpzxIAVQpAZ7kOkLpunMBqQ9t75ROL5jNIA8z0cIf390sdWz53A1599InL2imX8oce5IAbqBUSuIB80-CtA4HGqvttAXGQN9Au6FZWBH-E3gbZE","e":"AQAB","kid":"ED43460F57D930E62A56FC8BEEF8A283","kty":"RSA","n":"1Sne51c04wn7MwM-oyZvXs8V37s5DwzcPZyGMjLwYeM3ysuMEhdCdwlTJbsNizD8hd2Y5cS3BfZzizsHWI6-t4bIrD4ySsvj_GitY4NgoW53zBDqGzNKibeVt4zoTmp0H2RTyDj0lK-7tuEx1elUFSoaaHSImV51lm7CQz7dI8T-z2vHGN6mVCYpzR8h7Zuz0UixV5LWHI3ulYOI0IApk7obbH-2X3xHC6zEJMgPnFJ1cjXP474Y-FslF1u7Dx8h0v0zeD-fJ12P6L8Nsgo0NP_4OBAtrHFfThnugQC5WEA2mFXNMS0N_8SgLZlavv-NLNS74QXbzJC59SkGS60vZQ","p":"2rhU-K-zyaRzg9mPTeQEo5bEUIyZEGY3nQJrLDMUbXQaUZ5Np9E_pNsVPy1gEUTukV-cbjRucvpwpMSgPS2qJGBv0UGX1TmFxwvSiysbuCTlUYzdcJ9AMr1H5sPZ_ZvHdwjWcVKcmisg6A5LrKgwCELy1mAvxlvalnyajCp9Bz8","q":"-X8WBAyWajXfWbv2mbqXVJOtEdbrOMkl1IAjfeWdKQ9Ee3IeIjNtIqyIE4xW4Ftixzopk2u7Rm0MNwn1gP1DeZWyRCuHzdt0_3b5tVDK5mm3FhTrlnVsTOFg4BeYhAdc5MLOki4tHZp6o0s25-_6buATm2fN_7kCxRXsuUrZZFs","qi":"slbCpR9QO_FXiU2ciHEhtZCN4Vj4wXfTtQj2G0-WooOUSan_SFZsAXEfA-ihE0Fl1xQtcMwcMUsD9EGDDNjC_7ESlUojU_AOWRX_b8AcTJU28wqnXj4DP6gwptiywL-agwWrjnBWu8dMCogU8-hJFp3f8ruIx06hVecZXGzR-v8"} -------------------------------------------------------------------------------- /Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer/Calabonga.Chat.AuthServer.Web/tempkey.rsa: -------------------------------------------------------------------------------- 1 | {"KeyId":"YV6cLgCDMZMat6HrRL-K6g","Parameters":{"D":"KPGMhbGs2Nnl881go6X6QtFvN7x9KHAxOKIrt00GWhJ/7tZKbY/wrAimXxHWLNj/t3t0f7yY/zgTEwbXhTRY2Qz0LS2vTCc5SW/PrtKPfoAlgiaxcl3AUwzL0CG/84f1RwiarJQ139PrQLZylr5m7Chr7t8SOcx04RhliJ50afsUU2DoQ2ydNHVkNFHmD4LtKsUTe1HW2YZLhKlaaof7I/B5CYDJhOMktvssZnYn6tldaCPLFhlb2qKqJ5IIoLRbxSW49OgknBxvRPFhvuNgJy5U0G5Zj6hnGqVYkFAWpy8SvKr+y3x3utHas+5ad0Tl4Jni2oY5Hy5CsbjVJyq1XQ==","DP":"vb5xD/KvgM3vrWWvbrPHn/dkxn3v093fG3fTqusD1J8H3VSDlLAXFl1yLme3aGHFdfqU6Kh0fm2ljp1hcxzaSqIG6nm/eXtQKlPmUCfhVgaQd6kKpBTNR+fKi2GmJnYPq/j9YOtbRrvgfEOJjcr9pPnwvm462NXY/whBU20/1/U=","DQ":"KKF2T1Yjrx5x3DxY6uu5eDKCULwtOj1WcRt3sknVytVuXzdnHALQYPx3GlZGd69Os2783YTl27bA568NGdRTTDgH1WsbUEJ/L6HnmMjF2c9tFOuJTNkt9liepi1DE+vweNP47J7vC56RnB53cJxH9NrUJgwLOrduk0KOg51S9O0=","Exponent":"AQAB","InverseQ":"F/c6r8Lz5GFEvZ4pVoANwiLBJ6ygoU0epbNSJOctlh1WXSqK6vubx9kLaKXiPwvL1lKI3wLli90hS27IMQ0TGRbx2whCsQmYkQbZ/N8bQFbqLq17QGjlOtHTVyb1xVdpWBsbUsm2CyNcrcLwehNq1BQKZGhuMzRS2vjWdALWV8E=","Modulus":"ozV6PBtB42xupEMGErHRRM2BHbBie/73jtJeCiHwYkvcdQCwckO0owQZ98At0e26h8u+dyJIZsi+YteiI8eacAtqvXa0LuBV9hU5k0HSpKPuCTCfFoy1cZtNIwMRmXL41lif5lJoaye87kKZ47UpUXDX3OtC2+7Z/BCbuV7bph+fmr0HenPWy+s7kgKR0z6Zvb7DrQcbYxdm1L5Ocym3u/MjUifwNd7jpXUvzKSoKhRbY8aXa47JDzWAxZRReFQQsfsnq5bxtcFG8lyeAVsn6hLGLwtwnAx/abTTITAkKCY/DAHHg8uTr52WO9vwLbsXOP9VMMg3GaQDByzbFj1wjQ==","P":"xJrNIiraGxuADMd6GKuB1RwE8gweioaxwJzoRNVX1fupwkEBY5se9ONOUTL7De+fmvnutM/2LzvtG48HQ1m4lcW9TOVRssUmIBaae4lV2o2CHiKbVCj3K97SK/CPqwVgInyeJiE429IVMWMIJAY7E3+0Elrgyl/Vmkj38b9Ni6s=","Q":"1IPhc5uKlqkbT0bBbOkAsWwMptls8kgtFG3acWHdsIxtHVWSUImMmhEVBPjyg8Zu9I1jbWxk3BhI3aJcSMNsvqXmiCFbuNsCNY0ph6DYdSLqEHBqaY5hKPSeruMi4SEQumvUXx+pQuyIsnyJxH/T5G8qOm++GvEHsjjVlryB/Kc="}} -------------------------------------------------------------------------------- /Calabonga.Chat.ConsoleClient/Calabonga.Chat.ConsoleClient.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.31613.86 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Calabonga.Chat.ConsoleClient", "Calabonga.Chat.ConsoleClient\Calabonga.Chat.ConsoleClient.csproj", "{880BC958-789B-4EDC-9D18-25CE4D04BAE7}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {880BC958-789B-4EDC-9D18-25CE4D04BAE7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {880BC958-789B-4EDC-9D18-25CE4D04BAE7}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {880BC958-789B-4EDC-9D18-25CE4D04BAE7}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {880BC958-789B-4EDC-9D18-25CE4D04BAE7}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {D32D7FE6-DECF-4A8E-A614-CC6396671E3F} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /Calabonga.Chat.ConsoleClient/Calabonga.Chat.ConsoleClient/Calabonga.Chat.ConsoleClient.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net5.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /Calabonga.Chat.ConsoleClient/Calabonga.Chat.ConsoleClient/MessageHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Calabonga.Chat.ConsoleClient 4 | { 5 | public class MessageHelper 6 | { 7 | private readonly Random _random; 8 | private readonly string[] _messages = { 9 | "Hi there!", 10 | "Welcome!", 11 | "I'a chatting. Cool", 12 | "The weather is wonderful", 13 | "Is there anybody in chat?" }; 14 | 15 | public MessageHelper() 16 | { 17 | _random = new Random(); 18 | } 19 | 20 | internal string GetRandom() 21 | { 22 | var index = _random.Next(0, _messages.Length - 1); 23 | return _messages[index]; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Calabonga.Chat.ConsoleClient/Calabonga.Chat.ConsoleClient/TokenHelper/SecurityError.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace Calabonga.Chat.ConsoleClient.TokenHelper 4 | { 5 | /// 6 | /// Server authentication error 7 | /// 8 | public class SecurityError 9 | { 10 | [JsonPropertyName("error")] 11 | public string Error { get; set; } 12 | 13 | [JsonPropertyName("error_description")] 14 | public string Description { get; set; } 15 | } 16 | } -------------------------------------------------------------------------------- /Calabonga.Chat.ConsoleClient/Calabonga.Chat.ConsoleClient/TokenHelper/SecurityToken.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace Calabonga.Chat.ConsoleClient.TokenHelper 4 | { 5 | /// 6 | /// This is a Token for deserialization from 7 | /// 8 | public class SecurityToken 9 | { 10 | 11 | [JsonPropertyName("access_token")] 12 | public string AccessToken { get; set; } 13 | 14 | [JsonPropertyName("token_type")] 15 | public string TokenType { get; set; } 16 | 17 | [JsonPropertyName("expires_in")] 18 | public int ExpiresIn { get; set; } 19 | 20 | [JsonPropertyName("refresh_token")] 21 | public string RefreshToken { get; set; } 22 | } 23 | } -------------------------------------------------------------------------------- /Calabonga.Chat.JavaScript/Calabonga.Chat.JavaScript.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.31624.102 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Calabonga.Chat.JavaScript", "Calabonga.Chat.JavaScript\Calabonga.Chat.JavaScript.csproj", "{67A0AAA2-785F-4D52-A3B8-E30688A4CE36}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {67A0AAA2-785F-4D52-A3B8-E30688A4CE36}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {67A0AAA2-785F-4D52-A3B8-E30688A4CE36}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {67A0AAA2-785F-4D52-A3B8-E30688A4CE36}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {67A0AAA2-785F-4D52-A3B8-E30688A4CE36}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {04BFA349-87BD-4474-8AFB-5893E442572B} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /Calabonga.Chat.JavaScript/Calabonga.Chat.JavaScript/Calabonga.Chat.JavaScript.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net5.0 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Calabonga.Chat.JavaScript/Calabonga.Chat.JavaScript/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Hosting; 2 | using Microsoft.Extensions.Configuration; 3 | using Microsoft.Extensions.Hosting; 4 | using Microsoft.Extensions.Logging; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Threading.Tasks; 9 | 10 | namespace Calabonga.Chat.JavaScript 11 | { 12 | public class Program 13 | { 14 | public static void Main(string[] args) 15 | { 16 | CreateHostBuilder(args).Build().Run(); 17 | } 18 | 19 | public static IHostBuilder CreateHostBuilder(string[] args) => 20 | Host.CreateDefaultBuilder(args) 21 | .ConfigureWebHostDefaults(webBuilder => 22 | { 23 | webBuilder.UseStartup(); 24 | }); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Calabonga.Chat.JavaScript/Calabonga.Chat.JavaScript/Startup.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.Extensions.DependencyInjection; 4 | using Microsoft.Extensions.Hosting; 5 | 6 | namespace Calabonga.Chat.JavaScript 7 | { 8 | public class Startup 9 | { 10 | public void ConfigureServices(IServiceCollection services) 11 | { 12 | } 13 | 14 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 15 | { 16 | if (env.IsDevelopment()) 17 | { 18 | app.UseDeveloperExceptionPage(); 19 | } 20 | 21 | app.UseDefaultFiles(); 22 | 23 | app.UseStaticFiles(); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Calabonga.Chat.JavaScript/Calabonga.Chat.JavaScript/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Calabonga.Chat.JavaScript/Calabonga.Chat.JavaScript/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | }, 9 | "AllowedHosts": "*" 10 | } 11 | -------------------------------------------------------------------------------- /Calabonga.Chat.JavaScript/Calabonga.Chat.JavaScript/libman.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0", 3 | "defaultProvider": "cdnjs", 4 | "libraries": [ 5 | { 6 | "library": "bootstrap@5.1.0", 7 | "destination": "wwwroot/bootstrap/", 8 | "files": [ 9 | "js/bootstrap.min.js", 10 | "css/bootstrap.min.css" 11 | ] 12 | }, 13 | { 14 | "library": "microsoft-signalr@5.0.9", 15 | "destination": "wwwroot/microsoft-signalr/" 16 | } 17 | ] 18 | } -------------------------------------------------------------------------------- /Calabonga.Chat.WinFormClient/Calabonga.Chat.WinFormClient.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.31613.86 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Calabonga.Chat.WinFormClient", "Calabonga.Chat.WinFormClient\Calabonga.Chat.WinFormClient.csproj", "{C52981BB-5BEC-4741-9F3C-7A637796BDC8}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {C52981BB-5BEC-4741-9F3C-7A637796BDC8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {C52981BB-5BEC-4741-9F3C-7A637796BDC8}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {C52981BB-5BEC-4741-9F3C-7A637796BDC8}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {C52981BB-5BEC-4741-9F3C-7A637796BDC8}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {BBF3CE05-C7C0-4551-B11A-C8CFA305C618} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /Calabonga.Chat.WinFormClient/Calabonga.Chat.WinFormClient/AppData.cs: -------------------------------------------------------------------------------- 1 | namespace Calabonga.Chat.WinFormClient 2 | { 3 | public static class AppData 4 | { 5 | internal const string ServerTokenUrl = "https://localhost:10001/connect/token"; 6 | public static string ChatServerUrl = "https://localhost:20001/chat"; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /Calabonga.Chat.WinFormClient/Calabonga.Chat.WinFormClient/Calabonga.Chat.WinFormClient.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | WinExe 5 | net5.0-windows 6 | true 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /Calabonga.Chat.WinFormClient/Calabonga.Chat.WinFormClient/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using System.Windows.Forms; 6 | 7 | namespace Calabonga.Chat.WinFormClient 8 | { 9 | static class Program 10 | { 11 | /// 12 | /// The main entry point for the application. 13 | /// 14 | [STAThread] 15 | static void Main() 16 | { 17 | Application.SetHighDpiMode(HighDpiMode.SystemAware); 18 | Application.EnableVisualStyles(); 19 | Application.SetCompatibleTextRenderingDefault(false); 20 | Application.Run(new Form1()); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Calabonga.Chat.WinFormClient/Calabonga.Chat.WinFormClient/TokenHelper/SecurityError.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace Calabonga.Chat.WinFormClient.TokenHelper 4 | { 5 | /// 6 | /// Server authentication error 7 | /// 8 | public class SecurityError 9 | { 10 | [JsonPropertyName("error")] 11 | public string Error { get; set; } 12 | 13 | [JsonPropertyName("error_description")] 14 | public string Description { get; set; } 15 | } 16 | } -------------------------------------------------------------------------------- /Calabonga.Chat.WinFormClient/Calabonga.Chat.WinFormClient/TokenHelper/SecurityToken.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace Calabonga.Chat.WinFormClient.TokenHelper 4 | { 5 | /// 6 | /// This is a Token for deserialization from 7 | /// 8 | public class SecurityToken 9 | { 10 | 11 | [JsonPropertyName("access_token")] 12 | public string AccessToken { get; set; } 13 | 14 | [JsonPropertyName("token_type")] 15 | public string TokenType { get; set; } 16 | 17 | [JsonPropertyName("expires_in")] 18 | public int ExpiresIn { get; set; } 19 | 20 | [JsonPropertyName("refresh_token")] 21 | public string RefreshToken { get; set; } 22 | } 23 | } -------------------------------------------------------------------------------- /Calabonga.Chat.WpfClient/Calabonga.Chat.WpfClient.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.31613.86 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Calabonga.Chat.WpfClient", "Calabonga.Chat.WpfClient\Calabonga.Chat.WpfClient.csproj", "{91B076A0-83EA-4DB3-B3A0-94FE3819F504}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {91B076A0-83EA-4DB3-B3A0-94FE3819F504}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {91B076A0-83EA-4DB3-B3A0-94FE3819F504}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {91B076A0-83EA-4DB3-B3A0-94FE3819F504}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {91B076A0-83EA-4DB3-B3A0-94FE3819F504}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {72A8069C-0414-4006-97EB-E54DF3E503EB} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /Calabonga.Chat.WpfClient/Calabonga.Chat.WpfClient/App.xaml: -------------------------------------------------------------------------------- 1 |  6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Calabonga.Chat.WpfClient/Calabonga.Chat.WpfClient/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using Calabonga.Chat.WpfClient.Views; 3 | using Prism.Ioc; 4 | 5 | namespace Calabonga.Chat.WpfClient 6 | { 7 | /// 8 | /// Interaction logic for App.xaml 9 | /// 10 | public partial class App 11 | { 12 | /// 13 | /// Used to register types with the container that will be used by your application. 14 | /// 15 | protected override void RegisterTypes(IContainerRegistry containerRegistry) 16 | { 17 | 18 | } 19 | 20 | /// Creates the shell or main window of the application. 21 | /// The shell of the application. 22 | protected override Window CreateShell() 23 | { 24 | return Container.Resolve(); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Calabonga.Chat.WpfClient/Calabonga.Chat.WpfClient/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | 3 | [assembly: ThemeInfo( 4 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located 5 | //(used if a resource is not found in the page, 6 | // or application resource dictionaries) 7 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located 8 | //(used if a resource is not found in the page, 9 | // app, or any theme specific resource dictionaries) 10 | )] 11 | -------------------------------------------------------------------------------- /Calabonga.Chat.WpfClient/Calabonga.Chat.WpfClient/Calabonga.Chat.WpfClient.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | WinExe 5 | net5.0-windows 6 | true 7 | enable 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /Calabonga.Chat.WpfClient/Calabonga.Chat.WpfClient/TokenHelper/SecurityError.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace Calabonga.Chat.ConsoleClient.TokenHelper 4 | { 5 | /// 6 | /// Server authentication error 7 | /// 8 | public class SecurityError 9 | { 10 | [JsonPropertyName("error")] 11 | public string Error { get; set; } 12 | 13 | [JsonPropertyName("error_description")] 14 | public string Description { get; set; } 15 | } 16 | } -------------------------------------------------------------------------------- /Calabonga.Chat.WpfClient/Calabonga.Chat.WpfClient/TokenHelper/SecurityToken.cs: -------------------------------------------------------------------------------- 1 | using System.Text.Json.Serialization; 2 | 3 | namespace Calabonga.Chat.ConsoleClient.TokenHelper 4 | { 5 | /// 6 | /// This is a Token for deserialization from 7 | /// 8 | public class SecurityToken 9 | { 10 | 11 | [JsonPropertyName("access_token")] 12 | public string AccessToken { get; set; } 13 | 14 | [JsonPropertyName("token_type")] 15 | public string TokenType { get; set; } 16 | 17 | [JsonPropertyName("expires_in")] 18 | public int ExpiresIn { get; set; } 19 | 20 | [JsonPropertyName("refresh_token")] 21 | public string RefreshToken { get; set; } 22 | } 23 | } -------------------------------------------------------------------------------- /Calabonga.Chat.WpfClient/Calabonga.Chat.WpfClient/Views/Shell.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Shapes; 14 | 15 | namespace Calabonga.Chat.WpfClient.Views 16 | { 17 | /// 18 | /// Interaction logic for Shell.xaml 19 | /// 20 | public partial class Shell : Window 21 | { 22 | public Shell() 23 | { 24 | InitializeComponent(); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Calabonga 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SignalR в примерах 2 | 3 | Микросервисная система с сервисом авторизации (IdentityServer4) и сервисов чата для реализации обмена сообщениями в real-time. 4 | 5 | Видео материалы по данному репозиторию [Теоритическая часть + демонстрация ConsoleApp](https://youtu.be/TIG2oMgkbcg) с комментариями автора. 6 | 7 | Клиенты для чата реализованы (или почти реализованы) на разных платформах: 8 | 1. [x] [ConsoleApp](https://youtu.be/TIG2oMgkbcg?t=2293) 9 | 2. [x] [WPF](https://youtu.be/qxFF4wY2y9Q) 10 | 3. [x] [JavaScript (SPA)](https://youtu.be/vZnq7KHe1SQ) 11 | 4. [x] [WinForm](https://youtu.be/a92UbvvrbVY) 12 | 13 | ## Комментарии, пожелания, замечания 14 | 15 | Пишите комментарии к видео на сайте [www.calabonga.net](https://www.calabonga.net) 16 | 17 | # Автор 18 | 19 | Сергей Калабонга (Calabonga) 20 | 21 | ![Author](https://www.calabonga.net/images/Calabonga.gif) 22 | 23 | [Блог по программированию](https://www.calabonga.net) 24 | -------------------------------------------------------------------------------- /WpfClient.exe - Shortcut.lnk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Calabonga/SignalRChat/8ccd37197662c7dffd9f5be9cff59fe02e0341d8/WpfClient.exe - Shortcut.lnk -------------------------------------------------------------------------------- /start_AuthServer.cmd: -------------------------------------------------------------------------------- 1 | SET SOLUTION_NAME=Calabonga.Chat.AuthServer 2 | SET SOLUTION_PATH=%~dp0 3 | SET WEB_PATH=%SOLUTION_PATH%%SOLUTION_NAME%\%SOLUTION_NAME%\%SOLUTION_NAME%.Web 4 | 5 | dotnet run --project %WEB_PATH%\%SOLUTION_NAME%.Web.csproj -------------------------------------------------------------------------------- /start_ChatApiService_api.cmd: -------------------------------------------------------------------------------- 1 | SET SOLUTION_NAME=Calabonga.Chat.API 2 | SET SOLUTION_PATH=%~dp0 3 | SET WEB_PATH=%SOLUTION_PATH%%SOLUTION_NAME%\%SOLUTION_NAME%\%SOLUTION_NAME%.Web 4 | 5 | dotnet run --project %WEB_PATH%\%SOLUTION_NAME%.Web.csproj -------------------------------------------------------------------------------- /start_ConsoleClients_user1.cmd: -------------------------------------------------------------------------------- 1 | "D:\Projects\_YOUTUBE\ChatSignalR\Calabonga.Chat.ConsoleClient\Calabonga.Chat.ConsoleClient\bin\Debug\net5.0\Calabonga.Chat.ConsoleClient.exe" user1@yopmail.com -------------------------------------------------------------------------------- /start_ConsoleClients_user2.cmd: -------------------------------------------------------------------------------- 1 | "D:\Projects\_YOUTUBE\ChatSignalR\Calabonga.Chat.ConsoleClient\Calabonga.Chat.ConsoleClient\bin\Debug\net5.0\Calabonga.Chat.ConsoleClient.exe" user2@yopmail.com -------------------------------------------------------------------------------- /start_ConsoleClients_user3.cmd: -------------------------------------------------------------------------------- 1 | "D:\Projects\_YOUTUBE\ChatSignalR\Calabonga.Chat.ConsoleClient\Calabonga.Chat.ConsoleClient\bin\Debug\net5.0\Calabonga.Chat.ConsoleClient.exe" user3@yopmail.com --------------------------------------------------------------------------------