Generator Changes at 9/27/2025 8:46:36 AM

This commit is contained in:
generator
2025-09-27 08:46:36 +03:30
parent fd82e3edcf
commit fd8614f72e
261 changed files with 6333 additions and 0 deletions

View File

@@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="7.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="7.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\CMSMicroservice.Application\CMSMicroservice.Application.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,24 @@
using CMSMicroservice.Domain.Common;
using Microsoft.EntityFrameworkCore;
namespace MediatR;
public static class MediatorExtensions
{
public static async Task DispatchDomainEvents(this IMediator mediator, DbContext context)
{
var entities = context.ChangeTracker
.Entries<BaseEntity>()
.Where(e => e.Entity.DomainEvents.Any())
.Select(e => e.Entity);
var domainEvents = entities
.SelectMany(e => e.DomainEvents)
.ToList();
entities.ToList().ForEach(e => e.ClearDomainEvents());
foreach (var domainEvent in domainEvents)
await mediator.Publish(domainEvent);
}
}

View File

@@ -0,0 +1,92 @@
using CMSMicroservice.Application.Common.Interfaces;
using CMSMicroservice.Infrastructure.Persistence;
using CMSMicroservice.Infrastructure.Persistence.Interceptors;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Http;
using System.Diagnostics;
using Microsoft.Extensions.Configuration;
namespace Microsoft.Extensions.DependencyInjection;
public static class ConfigureServices
{
public static IServiceCollection AddInfrastructureServices(this IServiceCollection services, IConfiguration configuration)
{
services.AddScoped<AuditableEntitySaveChangesInterceptor>();
services.AddScoped<ApplicationDbContextInitialiser>();
services.AddScoped<IApplicationDbContext>(p => p.GetRequiredService<ApplicationDbContext>());
if (configuration.GetValue<bool>("UseInMemoryDatabase"))
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseInMemoryDatabase("MyMemoryDb"));
}
else
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(configuration.GetConnectionString("DefaultConnection"),
builder => builder.MigrationsAssembly(typeof(ApplicationDbContext).Assembly.FullName)));
}
#region AddAuthentication
var message = "";
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(jwtBearerOptions =>
{
jwtBearerOptions.Authority = configuration["Authentication:Authority"];
jwtBearerOptions.Audience = configuration["Authentication:Audience"];
jwtBearerOptions.TokenValidationParameters.ValidateAudience = false;
jwtBearerOptions.TokenValidationParameters.ValidateIssuer = true;
jwtBearerOptions.TokenValidationParameters.ValidateIssuerSigningKey = false;
try
{
jwtBearerOptions.Events = new JwtBearerEvents
{
OnAuthenticationFailed = ctx =>
{
ctx.Response.StatusCode = StatusCodes.Status401Unauthorized;
message += "From OnAuthenticationFailed:\n";
message += ctx.Exception.Message;
return Task.CompletedTask;
},
OnChallenge = ctx =>
{
message += "From OnChallenge:\n";
ctx.Response.StatusCode = StatusCodes.Status401Unauthorized;
ctx.Response.ContentType = "text/plain";
return ctx.Response.WriteAsync(message);
},
OnMessageReceived = ctx =>
{
message = "From OnMessageReceived:\n";
ctx.Request.Headers.TryGetValue("Authorization", out var BearerToken);
if (BearerToken.Count == 0)
BearerToken = "no Bearer token sent\n";
message += "Authorization Header sent: " + BearerToken + "\n";
return Task.CompletedTask;
},
OnTokenValidated = ctx =>
{
Debug.WriteLine("token: " + ctx.SecurityToken.ToString());
return Task.CompletedTask;
}
};
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
});
services.AddAuthorization();
#endregion
return services;
}
}

View File

@@ -0,0 +1,4 @@
global using System.Threading;
global using System.Threading.Tasks;
global using System;
global using System.Linq;

View File

@@ -0,0 +1,49 @@
using System.Reflection;
using CMSMicroservice.Application.Common.Interfaces;
using CMSMicroservice.Domain.Entities;
using CMSMicroservice.Infrastructure.Persistence.Interceptors;
using MediatR;
using Microsoft.EntityFrameworkCore;
namespace CMSMicroservice.Infrastructure.Persistence;
public class ApplicationDbContext : DbContext, IApplicationDbContext
{
private readonly IMediator _mediator;
private readonly AuditableEntitySaveChangesInterceptor _auditableEntitySaveChangesInterceptor;
public ApplicationDbContext(
DbContextOptions<ApplicationDbContext> options,
IMediator mediator,
AuditableEntitySaveChangesInterceptor auditableEntitySaveChangesInterceptor)
: base(options)
{
_mediator = mediator;
_auditableEntitySaveChangesInterceptor = auditableEntitySaveChangesInterceptor;
}
protected override void OnModelCreating(ModelBuilder builder)
{
builder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly());
builder.HasDefaultSchema("CMS");
base.OnModelCreating(builder);
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.AddInterceptors(_auditableEntitySaveChangesInterceptor);
}
public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
{
await _mediator.DispatchDomainEvents(this);
return await base.SaveChangesAsync(cancellationToken);
}
public DbSet<User> Users => Set<User>();
public DbSet<UserAddress> UserAddresss => Set<UserAddress>();
public DbSet<Package> Packages => Set<Package>();
public DbSet<UserOrder> UserOrders => Set<UserOrder>();
public DbSet<Role> Roles => Set<Role>();
public DbSet<UserRole> UserRoles => Set<UserRole>();
}

View File

@@ -0,0 +1,49 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
namespace CMSMicroservice.Infrastructure.Persistence;
public class ApplicationDbContextInitialiser
{
private readonly ApplicationDbContext _context;
private readonly ILogger<ApplicationDbContextInitialiser> _logger;
public ApplicationDbContextInitialiser(ApplicationDbContext context, ILogger<ApplicationDbContextInitialiser> logger)
{
_context = context;
_logger = logger;
}
public async Task InitialiseAsync()
{
try
{
if (_context.Database.IsSqlServer())
{
await _context.Database.MigrateAsync();
}
}
catch (Exception ex)
{
_logger.LogError(ex, "An error occurred while initialising the database.");
throw;
}
}
public async Task SeedAsync()
{
try
{
await TrySeedAsync();
}
catch (Exception ex)
{
_logger.LogError(ex, "An error occurred while seeding the database.");
throw;
}
}
public async Task TrySeedAsync()
{
}
}

View File

@@ -0,0 +1,20 @@
using CMSMicroservice.Domain.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace CMSMicroservice.Infrastructure.Persistence.Configurations;
public class PackageConfiguration : IEntityTypeConfiguration<Package>
{
public void Configure(EntityTypeBuilder<Package> builder)
{
builder.HasQueryFilter(p => !p.IsDeleted);
builder.Ignore(entity => entity.DomainEvents);
builder.HasKey(entity => entity.Id);
builder.Property(entity => entity.Id).UseIdentityColumn();
builder.Property(entity => entity.Title).IsRequired(true);
builder.Property(entity => entity.Description).IsRequired(true);
builder.Property(entity => entity.ImagePath).IsRequired(true);
builder.Property(entity => entity.Price).IsRequired(true);
}
}

View File

@@ -0,0 +1,18 @@
using CMSMicroservice.Domain.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace CMSMicroservice.Infrastructure.Persistence.Configurations;
public class RoleConfiguration : IEntityTypeConfiguration<Role>
{
public void Configure(EntityTypeBuilder<Role> builder)
{
builder.HasQueryFilter(p => !p.IsDeleted);
builder.Ignore(entity => entity.DomainEvents);
builder.HasKey(entity => entity.Id);
builder.Property(entity => entity.Id).UseIdentityColumn();
builder.Property(entity => entity.Name).IsRequired(true);
builder.Property(entity => entity.Title).IsRequired(true);
}
}

View File

@@ -0,0 +1,26 @@
using CMSMicroservice.Domain.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace CMSMicroservice.Infrastructure.Persistence.Configurations;
public class UserAddressConfiguration : IEntityTypeConfiguration<UserAddress>
{
public void Configure(EntityTypeBuilder<UserAddress> builder)
{
builder.HasQueryFilter(p => !p.IsDeleted);
builder.Ignore(entity => entity.DomainEvents);
builder.HasKey(entity => entity.Id);
builder.Property(entity => entity.Id).UseIdentityColumn();
builder
.HasOne(entity => entity.User)
.WithMany(entity => entity.UserAddresss)
.HasForeignKey(entity => entity.UserId)
.IsRequired(true);
builder.Property(entity => entity.Title).IsRequired(true);
builder.Property(entity => entity.Address).IsRequired(true);
builder.Property(entity => entity.PostalCode).IsRequired(true);
builder.Property(entity => entity.IsDefault).IsRequired(true);
builder.Property(entity => entity.CityId).IsRequired(true);
}
}

View File

@@ -0,0 +1,26 @@
using CMSMicroservice.Domain.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace CMSMicroservice.Infrastructure.Persistence.Configurations;
public class UserConfiguration : IEntityTypeConfiguration<User>
{
public void Configure(EntityTypeBuilder<User> builder)
{
builder.HasQueryFilter(p => !p.IsDeleted);
builder.Ignore(entity => entity.DomainEvents);
builder.HasKey(entity => entity.Id);
builder.Property(entity => entity.Id).UseIdentityColumn();
builder.Property(entity => entity.FirstName).IsRequired(false);
builder.Property(entity => entity.LastName).IsRequired(false);
builder.Property(entity => entity.Mobile).IsRequired(true);
builder.Property(entity => entity.NationalCode).IsRequired(false);
builder.Property(entity => entity.AvatarPath).IsRequired(false);
builder
.HasOne(entity => entity.Parent)
.WithMany(entity => entity.Users)
.HasForeignKey(entity => entity.ParentId)
.IsRequired(false);
}
}

View File

@@ -0,0 +1,30 @@
using CMSMicroservice.Domain.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace CMSMicroservice.Infrastructure.Persistence.Configurations;
public class UserOrderConfiguration : IEntityTypeConfiguration<UserOrder>
{
public void Configure(EntityTypeBuilder<UserOrder> builder)
{
builder.HasQueryFilter(p => !p.IsDeleted);
builder.Ignore(entity => entity.DomainEvents);
builder.HasKey(entity => entity.Id);
builder.Property(entity => entity.Id).UseIdentityColumn();
builder.Property(entity => entity.Price).IsRequired(true);
builder
.HasOne(entity => entity.Package)
.WithMany(entity => entity.UserOrders)
.HasForeignKey(entity => entity.PackageId)
.IsRequired(true);
builder.Property(entity => entity.TransactionId).IsRequired(false);
builder.Property(entity => entity.PaymentStatus).IsRequired(true);
builder.Property(entity => entity.PaymentDate).IsRequired(false);
builder
.HasOne(entity => entity.User)
.WithMany(entity => entity.UserOrders)
.HasForeignKey(entity => entity.UserId)
.IsRequired(true);
}
}

View File

@@ -0,0 +1,26 @@
using CMSMicroservice.Domain.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace CMSMicroservice.Infrastructure.Persistence.Configurations;
public class UserRoleConfiguration : IEntityTypeConfiguration<UserRole>
{
public void Configure(EntityTypeBuilder<UserRole> builder)
{
builder.HasQueryFilter(p => !p.IsDeleted);
builder.Ignore(entity => entity.DomainEvents);
builder.HasKey(entity => entity.Id);
builder.Property(entity => entity.Id).UseIdentityColumn();
builder
.HasOne(entity => entity.Role)
.WithMany(entity => entity.UserRoles)
.HasForeignKey(entity => entity.RoleId)
.IsRequired(true);
builder
.HasOne(entity => entity.User)
.WithMany(entity => entity.UserRoles)
.HasForeignKey(entity => entity.UserId)
.IsRequired(true);
}
}

View File

@@ -0,0 +1,58 @@
using CMSMicroservice.Application.Common.Interfaces;
using CMSMicroservice.Domain.Common;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.EntityFrameworkCore.Diagnostics;
namespace CMSMicroservice.Infrastructure.Persistence.Interceptors;
public class AuditableEntitySaveChangesInterceptor : SaveChangesInterceptor
{
private readonly ICurrentUserService _currentUserService;
public AuditableEntitySaveChangesInterceptor(
ICurrentUserService currentUserService)
{
_currentUserService = currentUserService;
}
public override InterceptionResult<int> SavingChanges(DbContextEventData eventData, InterceptionResult<int> result)
{
UpdateEntities(eventData.Context);
return base.SavingChanges(eventData, result);
}
public override ValueTask<InterceptionResult<int>> SavingChangesAsync(DbContextEventData eventData, InterceptionResult<int> result, CancellationToken cancellationToken = default)
{
UpdateEntities(eventData.Context);
return base.SavingChangesAsync(eventData, result, cancellationToken);
}
public void UpdateEntities(DbContext? context)
{
if (context == null) return;
foreach (var entry in context.ChangeTracker.Entries<BaseAuditableEntity>())
{
if (entry.State == EntityState.Added)
{
entry.Entity.CreatedBy = _currentUserService.UserId;
entry.Entity.Created = DateTime.Now;
}
if (entry.State == EntityState.Added || entry.State == EntityState.Modified || entry.HasChangedOwnedEntities())
{
entry.Entity.LastModifiedBy = _currentUserService.UserId;
entry.Entity.LastModified = DateTime.Now;
}
}
}
}
public static class Extensions
{
public static bool HasChangedOwnedEntities(this EntityEntry entry) =>
entry.References.Any(r =>
r.TargetEntry != null &&
r.TargetEntry.Metadata.IsOwned() &&
(r.TargetEntry.State == EntityState.Added || r.TargetEntry.State == EntityState.Modified));
}