This commit is contained in:
2025-09-12 14:18:08 +04:30
parent ad4c92f4c0
commit 338895a1ad
48 changed files with 361 additions and 357 deletions
+1 -3
View File
@@ -7,12 +7,10 @@ namespace VizhTalk.Gateway.Web.BFF.Mappers
{
public static async Task<UploadFile> AsFile(this IFile file)
{
using MemoryStream stream = new MemoryStream();
await file.CopyToAsync(stream);
return new UploadFile()
{
ContentType = file.ContentType,
File = ByteString.FromStream(stream),
File = ByteString.FromStream(file.OpenReadStream()),
Name = file.Name,
};
}
@@ -1,4 +1,4 @@
namespace VizhTalk.Gateway.Web.BFF.Models;
public record CreateLanguageRequest(string Title,IFile Icon);
public record UpdateLanguageRequest(IdRequest Id, string Title,IFile Icon);
public record UpdateLanguageRequest(IdRequest Id, string Title, IFile? Icon);
@@ -20,11 +20,19 @@ public class LanguageMutation(LanguageGrpc.LanguageGrpcClient client)
[GraphQLName("UpdateLanguage")]
public async Task<LanguageDTO> UpdateLanguage(UpdateLanguageRequest request)
{
UploadFile file = null;
if(request.Icon != null)
{
file = await request.Icon.AsFile();
}
return await client.UpdateAsync(new UpdateLanguageCommand()
{
Id = new Id(request.Id.Value),
Id = new Id()
{
Value = request.Id.Value
},
Title = request.Title,
Icon = await request.Icon.AsFile()
Icon = file
});
}
}
+2 -1
View File
@@ -14,7 +14,8 @@ builder.Services.AddScoped<LanguageMutation>();
builder.AddGraphQL()
.AddQueryType<LanguageQuery>()
.AddMutationType<LanguageMutation>()
.AddType<UploadType>();
.AddType<UploadType>()
.AddMutationConventions();
var app = builder.Build();
@@ -51,12 +51,10 @@ public class CreateLanguageCommandHandler(IUnitOfWork unitOfWork,
MediaGroupId = fileGroup.MediaGroupId
}, cancellationToken: cancellationToken);
var language = Language.CreateNew(new LanguageTitle(title));
var media = Media.CreateNew(title, upload.ContentType, upload.Size, upload.MediaGroupMediaId, new EntityType(EntityTypeEnum.Language));
var language = Language.CreateNew(new LanguageTitle(title), media);
await unitOfWork.Language.AddAsync(language, cancellationToken);
await unitOfWork.SaveChangeAsync(cancellationToken);
var media = Media.CreateNew(title, upload.ContentType, upload.Size, new EntityType(language.Id.Value.ToString(), EntityTypeEnum.Language));
await unitOfWork.Media.AddAsync(media, cancellationToken);
language.SetIcon(media);
return language.Adapt<LanguageDTO>();
}
catch (Exception ex)
@@ -92,7 +90,7 @@ public class UpdateLanguageCommandHandler(IUnitOfWork unitOfWork, CDNGrpc.CDNGrp
MediaGroupId = fileGroup.MediaGroupId
}, cancellationToken: cancellationToken);
var media = Media.CreateNew(request.Title, upload.ContentType, upload.Size, new EntityType(language.Id.Value.ToString(), EntityTypeEnum.Language));
var media = Media.CreateNew(request.Title, upload.ContentType, upload.Size, upload.MediaGroupMediaId, new EntityType(EntityTypeEnum.Language));
language.SetIcon(media);
}
@@ -13,7 +13,7 @@ public class FileGroup : Entity<FileGroupId>
private FileGroup(FileGroupKey key,
FileGroupTitle title,
bool isSecure,
long mediaGroupId)
Guid mediaGroupId)
{
Title = title;
MediaGroupId = mediaGroupId;
@@ -22,12 +22,12 @@ public class FileGroup : Entity<FileGroupId>
}
public FileGroupTitle Title { get; set; }
public FileGroupKey Key { get; private set; }
public long MediaGroupId { get; private set; }
public Guid MediaGroupId { get; private set; }
public bool IsSecure { get; set; }
public static FileGroup CreateNew(FileGroupKey key,
FileGroupTitle title,
bool isSecure,
long mediaGroupId)
Guid mediaGroupId)
=> new(key,title, isSecure, mediaGroupId);
}
@@ -12,15 +12,16 @@ public class Language : Entity<LanguageId>, IAggregateRoot
{
// only EF
}
private Language(LanguageTitle title)
private Language(LanguageTitle title, Media icon)
{
Title = title;
Icon = icon;
}
public LanguageTitle Title { get; private set; }
public Media Icon { get; private set; }
public IReadOnlyList<Course> Courses => _courses;
public static Language CreateNew(LanguageTitle title)
=> new(title);
public static Language CreateNew(LanguageTitle title,Media icon)
=> new(title, icon);
public void SetTitle(LanguageTitle title)
=> Title = title;
+5 -1
View File
@@ -13,21 +13,25 @@ public class Media : Entity<MediaId>
private Media(string name,
string contentType,
int size,
Guid fileId,
EntityType type)
{
Name = name;
ContentType = contentType;
Size = size;
FileId = fileId;
EntityType = type;
}
public string Name { get; private set; }
public string ContentType { get; private set; }
public int Size { get; private set; }
public Guid FileId { get; set; }
public EntityType EntityType { get; private set; }
public static Media CreateNew(string name,
string contentType,
int size,
Guid fileId,
EntityType type)
=> new(name, contentType, size, type);
=> new(name, contentType, size, fileId, type);
}
+2 -2
View File
@@ -2,9 +2,9 @@
namespace VizhTalk.Learning.Domain.TypeIds;
public class MediaId : TypeIdValueBase<Guid>
public class MediaId : TypeIdValueBase<long>
{
public MediaId(Guid value) : base(value)
public MediaId(long value) : base(value)
{
}
}
@@ -4,12 +4,10 @@ namespace VizhTalk.Learning.Domain.ValueObjects;
public class EntityType : ValueObject
{
public EntityType(string entityId, EntityTypeEnum type)
public EntityType(EntityTypeEnum type)
{
EntityId = entityId;
Type = type;
}
public string EntityId { get; private set; }
public EntityTypeEnum Type { get; private set; }
}
public enum EntityTypeEnum
@@ -9,6 +9,7 @@ public class FileGroupTitle : ValueObject
{
Guard.NullOrEmpty(value, nameof(FileGroupTitle));
Guard.MaxLength(value, nameof(FileGroupTitle), 50);
Value = value;
}
public string Value { get; set; }
}
@@ -15,6 +15,7 @@ internal class FileGroupConfiguration : IEntityTypeConfiguration<FileGroup>
builder.Property(x => x.Id)
.ValueGeneratedOnAdd()
.HasConversion(x => x.Value, x => new Domain.TypeIds.FileGroupId(x));
builder.Property(x => x.Title)
.HasColumnName("Title")
.HasConversion(x => x.Value, x => new FileGroupTitle(x));
@@ -12,7 +12,8 @@ internal class MediaConfiguration : IEntityTypeConfiguration<Media>
builder.HasKey(x => x.Id);
builder.Property(x => x.Id)
.HasConversion(x => x.Value, x => new Domain.TypeIds.MediaId(x));
.HasConversion(x => x.Value, x => new Domain.TypeIds.MediaId(x))
.ValueGeneratedOnAdd();
builder.Property(x => x.Name)
.HasMaxLength(150);
@@ -24,10 +25,6 @@ internal class MediaConfiguration : IEntityTypeConfiguration<Media>
op.Property(x => x.Type)
.HasColumnName("EntityType")
.HasMaxLength(200);
op.Property(x => x.EntityId)
.HasColumnName("EntityId")
.HasMaxLength(50);
});
}
}
@@ -10,6 +10,7 @@ using VizhTalk.BuildingBlocks.Application.Outbox;
using VizhTalk.BuildingBlocks.Infrastructure;
using VizhTalk.BuildingBlocks.Infrastructure.DomainEventsDispatching;
using VizhTalk.Grpc.CDN;
using VizhTalk.Grpc.Learning.Language;
using VizhTalk.Learning.Application;
using VizhTalk.Learning.Application.Mappers;
using VizhTalk.Learning.Infrastructure.Configuration;
@@ -29,6 +30,10 @@ public static class LearningStartup
{
op.UseSqlServer(connectionString);
});
services.AddGrpcClient<CDNGrpc.CDNGrpcClient>(o =>
{
o.Address = new Uri("https://localhost:5001");
});
services.AddScoped<DbContext>(sp => sp.GetService<LearningDbContext>());
services.AddScoped<ILearningModule, LearningModule>();
services.AddScoped<IExecutor, LearningModule>();
@@ -1,183 +0,0 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using VizhTalk.Learning.Infrastructure.EF;
#nullable disable
namespace VizhTalk.Learning.Infrastructure.Migrations
{
[DbContext(typeof(LearningDbContext))]
[Migration("20250905153842_initial")]
partial class initial
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasDefaultSchema("Learning")
.HasAnnotation("ProductVersion", "8.0.19")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("VizhTalk.Learning.Domain.Entities.FileGroup", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Id"));
b.Property<DateTime>("CreateOn")
.HasColumnType("datetime2");
b.Property<bool>("IsActive")
.HasColumnType("bit");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<bool>("IsSecure")
.HasColumnType("bit");
b.Property<string>("Key")
.IsRequired()
.HasMaxLength(150)
.HasColumnType("nvarchar(150)")
.HasColumnName("Key");
b.Property<DateTime>("LastUpdate")
.HasColumnType("datetime2");
b.Property<long>("MediaGroupId")
.HasColumnType("bigint");
b.Property<string>("Title")
.IsRequired()
.HasColumnType("nvarchar(max)")
.HasColumnName("Title");
b.HasKey("Id");
b.ToTable("FileGroups", "Attachment");
});
modelBuilder.Entity("VizhTalk.Learning.Domain.Entities.Language", b =>
{
b.Property<short>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("smallint");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<short>("Id"));
b.Property<DateTime>("CreateOn")
.HasColumnType("datetime2");
b.Property<Guid>("IconId")
.HasColumnType("uniqueidentifier");
b.Property<bool>("IsActive")
.HasColumnType("bit");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<DateTime>("LastUpdate")
.HasColumnType("datetime2");
b.Property<string>("Title")
.IsRequired()
.HasMaxLength(60)
.HasColumnType("nvarchar(60)");
b.HasKey("Id");
b.HasIndex("IconId");
b.ToTable("Languages", "Learning");
});
modelBuilder.Entity("VizhTalk.Learning.Domain.Entities.Media", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uniqueidentifier");
b.Property<string>("ContentType")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<DateTime>("CreateOn")
.HasColumnType("datetime2");
b.Property<bool>("IsActive")
.HasColumnType("bit");
b.Property<bool>("IsDeleted")
.HasColumnType("bit");
b.Property<DateTime>("LastUpdate")
.HasColumnType("datetime2");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(150)
.HasColumnType("nvarchar(150)");
b.Property<int>("Size")
.HasColumnType("int");
b.HasKey("Id");
b.ToTable("Medias", "Learning");
});
modelBuilder.Entity("VizhTalk.Learning.Domain.Entities.Language", b =>
{
b.HasOne("VizhTalk.Learning.Domain.Entities.Media", "Icon")
.WithMany()
.HasForeignKey("IconId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Icon");
});
modelBuilder.Entity("VizhTalk.Learning.Domain.Entities.Media", b =>
{
b.OwnsOne("VizhTalk.Learning.Domain.ValueObjects.EntityType", "EntityType", b1 =>
{
b1.Property<Guid>("MediaId")
.HasColumnType("uniqueidentifier");
b1.Property<string>("EntityId")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("nvarchar(50)")
.HasColumnName("EntityId");
b1.Property<int>("Type")
.HasMaxLength(200)
.HasColumnType("int")
.HasColumnName("EntityType");
b1.HasKey("MediaId");
b1.ToTable("Medias", "Learning");
b1.WithOwner()
.HasForeignKey("MediaId");
});
b.Navigation("EntityType")
.IsRequired();
});
#pragma warning restore 612, 618
}
}
}
@@ -1,69 +0,0 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace VizhTalk.Learning.Infrastructure.Migrations
{
/// <inheritdoc />
public partial class Course : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Courses",
schema: "Learning",
columns: table => new
{
Id = table.Column<long>(type: "bigint", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
Title = table.Column<string>(type: "nvarchar(max)", nullable: false),
ImageId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
Order = table.Column<int>(type: "int", nullable: false),
LanguageId = table.Column<short>(type: "smallint", nullable: true),
IsDeleted = table.Column<bool>(type: "bit", nullable: false),
IsActive = table.Column<bool>(type: "bit", nullable: false),
CreateOn = table.Column<DateTime>(type: "datetime2", nullable: false),
LastUpdate = table.Column<DateTime>(type: "datetime2", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Courses", x => x.Id);
table.ForeignKey(
name: "FK_Courses_Languages_LanguageId",
column: x => x.LanguageId,
principalSchema: "Learning",
principalTable: "Languages",
principalColumn: "Id");
table.ForeignKey(
name: "FK_Courses_Medias_ImageId",
column: x => x.ImageId,
principalSchema: "Learning",
principalTable: "Medias",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_Courses_ImageId",
schema: "Learning",
table: "Courses",
column: "ImageId");
migrationBuilder.CreateIndex(
name: "IX_Courses_LanguageId",
schema: "Learning",
table: "Courses",
column: "LanguageId");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Courses",
schema: "Learning");
}
}
}
@@ -12,8 +12,8 @@ using VizhTalk.Learning.Infrastructure.EF;
namespace VizhTalk.Learning.Infrastructure.Migrations
{
[DbContext(typeof(LearningDbContext))]
[Migration("20250907192005_Course")]
partial class Course
[Migration("20250912083328_initial")]
partial class initial
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
@@ -37,8 +37,8 @@ namespace VizhTalk.Learning.Infrastructure.Migrations
b.Property<DateTime>("CreateOn")
.HasColumnType("datetime2");
b.Property<Guid>("ImageId")
.HasColumnType("uniqueidentifier");
b.Property<long>("ImageId")
.HasColumnType("bigint");
b.Property<bool>("IsActive")
.HasColumnType("bit");
@@ -97,8 +97,8 @@ namespace VizhTalk.Learning.Infrastructure.Migrations
b.Property<DateTime>("LastUpdate")
.HasColumnType("datetime2");
b.Property<long>("MediaGroupId")
.HasColumnType("bigint");
b.Property<Guid>("MediaGroupId")
.HasColumnType("uniqueidentifier");
b.Property<string>("Title")
.IsRequired()
@@ -121,8 +121,8 @@ namespace VizhTalk.Learning.Infrastructure.Migrations
b.Property<DateTime>("CreateOn")
.HasColumnType("datetime2");
b.Property<Guid>("IconId")
.HasColumnType("uniqueidentifier");
b.Property<long>("IconId")
.HasColumnType("bigint");
b.Property<bool>("IsActive")
.HasColumnType("bit");
@@ -147,8 +147,11 @@ namespace VizhTalk.Learning.Infrastructure.Migrations
modelBuilder.Entity("VizhTalk.Learning.Domain.Entities.Media", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uniqueidentifier");
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Id"));
b.Property<string>("ContentType")
.IsRequired()
@@ -157,6 +160,9 @@ namespace VizhTalk.Learning.Infrastructure.Migrations
b.Property<DateTime>("CreateOn")
.HasColumnType("datetime2");
b.Property<Guid>("FileId")
.HasColumnType("uniqueidentifier");
b.Property<bool>("IsActive")
.HasColumnType("bit");
@@ -209,14 +215,8 @@ namespace VizhTalk.Learning.Infrastructure.Migrations
{
b.OwnsOne("VizhTalk.Learning.Domain.ValueObjects.EntityType", "EntityType", b1 =>
{
b1.Property<Guid>("MediaId")
.HasColumnType("uniqueidentifier");
b1.Property<string>("EntityId")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("nvarchar(50)")
.HasColumnName("EntityId");
b1.Property<long>("MediaId")
.HasColumnType("bigint");
b1.Property<int>("Type")
.HasMaxLength(200)
@@ -12,10 +12,10 @@ namespace VizhTalk.Learning.Infrastructure.Migrations
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.EnsureSchema(
name: "Attachment");
name: "Learning");
migrationBuilder.EnsureSchema(
name: "Learning");
name: "Attachment");
migrationBuilder.CreateTable(
name: "FileGroups",
@@ -26,7 +26,7 @@ namespace VizhTalk.Learning.Infrastructure.Migrations
.Annotation("SqlServer:Identity", "1, 1"),
Title = table.Column<string>(type: "nvarchar(max)", nullable: false),
Key = table.Column<string>(type: "nvarchar(150)", maxLength: 150, nullable: false),
MediaGroupId = table.Column<long>(type: "bigint", nullable: false),
MediaGroupId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
IsSecure = table.Column<bool>(type: "bit", nullable: false),
IsDeleted = table.Column<bool>(type: "bit", nullable: false),
IsActive = table.Column<bool>(type: "bit", nullable: false),
@@ -43,11 +43,12 @@ namespace VizhTalk.Learning.Infrastructure.Migrations
schema: "Learning",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
Id = table.Column<long>(type: "bigint", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
Name = table.Column<string>(type: "nvarchar(150)", maxLength: 150, nullable: false),
ContentType = table.Column<string>(type: "nvarchar(max)", nullable: false),
Size = table.Column<int>(type: "int", nullable: false),
EntityId = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: false),
FileId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
EntityType = table.Column<int>(type: "int", maxLength: 200, nullable: false),
IsDeleted = table.Column<bool>(type: "bit", nullable: false),
IsActive = table.Column<bool>(type: "bit", nullable: false),
@@ -67,7 +68,7 @@ namespace VizhTalk.Learning.Infrastructure.Migrations
Id = table.Column<short>(type: "smallint", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
Title = table.Column<string>(type: "nvarchar(60)", maxLength: 60, nullable: false),
IconId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
IconId = table.Column<long>(type: "bigint", nullable: false),
IsDeleted = table.Column<bool>(type: "bit", nullable: false),
IsActive = table.Column<bool>(type: "bit", nullable: false),
CreateOn = table.Column<DateTime>(type: "datetime2", nullable: false),
@@ -85,6 +86,52 @@ namespace VizhTalk.Learning.Infrastructure.Migrations
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "Courses",
schema: "Learning",
columns: table => new
{
Id = table.Column<long>(type: "bigint", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
Title = table.Column<string>(type: "nvarchar(max)", nullable: false),
ImageId = table.Column<long>(type: "bigint", nullable: false),
Order = table.Column<int>(type: "int", nullable: false),
LanguageId = table.Column<short>(type: "smallint", nullable: true),
IsDeleted = table.Column<bool>(type: "bit", nullable: false),
IsActive = table.Column<bool>(type: "bit", nullable: false),
CreateOn = table.Column<DateTime>(type: "datetime2", nullable: false),
LastUpdate = table.Column<DateTime>(type: "datetime2", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Courses", x => x.Id);
table.ForeignKey(
name: "FK_Courses_Languages_LanguageId",
column: x => x.LanguageId,
principalSchema: "Learning",
principalTable: "Languages",
principalColumn: "Id");
table.ForeignKey(
name: "FK_Courses_Medias_ImageId",
column: x => x.ImageId,
principalSchema: "Learning",
principalTable: "Medias",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_Courses_ImageId",
schema: "Learning",
table: "Courses",
column: "ImageId");
migrationBuilder.CreateIndex(
name: "IX_Courses_LanguageId",
schema: "Learning",
table: "Courses",
column: "LanguageId");
migrationBuilder.CreateIndex(
name: "IX_Languages_IconId",
schema: "Learning",
@@ -95,6 +142,10 @@ namespace VizhTalk.Learning.Infrastructure.Migrations
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Courses",
schema: "Learning");
migrationBuilder.DropTable(
name: "FileGroups",
schema: "Attachment");
@@ -34,8 +34,8 @@ namespace VizhTalk.Learning.Infrastructure.Migrations
b.Property<DateTime>("CreateOn")
.HasColumnType("datetime2");
b.Property<Guid>("ImageId")
.HasColumnType("uniqueidentifier");
b.Property<long>("ImageId")
.HasColumnType("bigint");
b.Property<bool>("IsActive")
.HasColumnType("bit");
@@ -94,8 +94,8 @@ namespace VizhTalk.Learning.Infrastructure.Migrations
b.Property<DateTime>("LastUpdate")
.HasColumnType("datetime2");
b.Property<long>("MediaGroupId")
.HasColumnType("bigint");
b.Property<Guid>("MediaGroupId")
.HasColumnType("uniqueidentifier");
b.Property<string>("Title")
.IsRequired()
@@ -118,8 +118,8 @@ namespace VizhTalk.Learning.Infrastructure.Migrations
b.Property<DateTime>("CreateOn")
.HasColumnType("datetime2");
b.Property<Guid>("IconId")
.HasColumnType("uniqueidentifier");
b.Property<long>("IconId")
.HasColumnType("bigint");
b.Property<bool>("IsActive")
.HasColumnType("bit");
@@ -144,8 +144,11 @@ namespace VizhTalk.Learning.Infrastructure.Migrations
modelBuilder.Entity("VizhTalk.Learning.Domain.Entities.Media", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uniqueidentifier");
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Id"));
b.Property<string>("ContentType")
.IsRequired()
@@ -154,6 +157,9 @@ namespace VizhTalk.Learning.Infrastructure.Migrations
b.Property<DateTime>("CreateOn")
.HasColumnType("datetime2");
b.Property<Guid>("FileId")
.HasColumnType("uniqueidentifier");
b.Property<bool>("IsActive")
.HasColumnType("bit");
@@ -206,14 +212,8 @@ namespace VizhTalk.Learning.Infrastructure.Migrations
{
b.OwnsOne("VizhTalk.Learning.Domain.ValueObjects.EntityType", "EntityType", b1 =>
{
b1.Property<Guid>("MediaId")
.HasColumnType("uniqueidentifier");
b1.Property<string>("EntityId")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("nvarchar(50)")
.HasColumnName("EntityId");
b1.Property<long>("MediaId")
.HasColumnType("bigint");
b1.Property<int>("Type")
.HasMaxLength(200)
+5 -1
View File
@@ -5,7 +5,11 @@ var builder = WebApplication.CreateBuilder(args);
var connectionString = builder.Configuration.GetConnectionString("LearningDB")!;
// Add services to the container.
builder.Services.AddGrpc();
builder.Services.AddGrpc(op =>
{
op.MaxReceiveMessageSize = 200 * 1024 * 1024;
op.MaxSendMessageSize = 200 * 1024 * 1024;
});
builder.Services.Initialize(connectionString);
var app = builder.Build();
@@ -14,25 +14,24 @@ using VizhTalk.Grpc.CDN;
namespace Vizhtalk.CDN.Presentation.Application.CommandHandlers;
public class CreateMediaGroupCommandHandler(IUnitOfWork unitOfWork, CDNGrpc.CDNGrpcClient cdnClient) : ICommandHandler<CreateMediaGroupCommand, MediaGroupDTO>
public class CreateMediaGroupCommandHandler(IUnitOfWork unitOfWork) : ICommandHandler<CreateMediaGroupCommand, MediaGroupDTO>
{
public async Task<MediaGroupDTO> Handle(CreateMediaGroupCommand request, CancellationToken cancellationToken)
{
var title = request.Title.Trim();
if (await unitOfWork.MediaGroup.ExistsAsync(a => a.Key == request.Key))
throw new MediaGroupKeyAlreadyExistsException();
var mediaGroup = await unitOfWork.MediaGroup.GetAsync(a => a.Key == request.Key);
if (mediaGroup != null)
return mediaGroup.Adapt<MediaGroupDTO>();
var mediaGroup = MediaGroup.CreateNew(title, request.Key, request.IsSecure);
mediaGroup = MediaGroup.CreateNew(title, request.Key, request.IsSecure);
await unitOfWork.MediaGroup.AddAsync(mediaGroup, cancellationToken);
await unitOfWork.SaveChangeAsync(cancellationToken);
return mediaGroup.Adapt<MediaGroupDTO>();
}
}
public class UploadFileCommandHandler(IUnitOfWork unitOfWork, CDNGrpc.CDNGrpcClient cdnClient, IFileManagerService fileManager) : ICommandHandler<UploadFileCommand, UploadFileDTO>
public class UploadFileCommandHandler(IUnitOfWork unitOfWork, IFileManagerService fileManager) : ICommandHandler<UploadFileCommand, UploadFileDTO>
{
public async Task<UploadFileDTO> Handle(UploadFileCommand request, CancellationToken cancellationToken)
{
@@ -61,7 +60,7 @@ public class UploadFileCommandHandler(IUnitOfWork unitOfWork, CDNGrpc.CDNGrpcCli
if (!string.IsNullOrEmpty(request.ClientId))
mediaGroupMedia.AddMediaPermission(media, Client.CreateNew(new ClientId(request.ClientId)));
await unitOfWork.MediaGroup.AddAsync(mediaGroup, cancellationToken);
await unitOfWork.MediaGroup.UpdateAsync(mediaGroup, cancellationToken);
await unitOfWork.SaveChangeAsync(cancellationToken);
return new UploadFileDTO()
@@ -7,7 +7,7 @@ namespace Vizhtalk.CDN.Presentation.Application
{
IMediaRepository Media { get; }
IClientRepository Client { get; }
IMediaClientRepository MediaClient { get; }
IMediaPermissionRepository MediaClient { get; }
IMediaGroupRepository MediaGroup{ get; }
IMediaGroupMediaRepository MediaGroupMedia { get; }
@@ -7,10 +7,13 @@ namespace Vizhtalk.CDN.Presentation.Domain.Entities;
public class Media : Entity<MediaId>
{
private Media(ContentType contentType, int size , string hash , string path)
private Media()
{
}
private Media(ContentType contentType, int size , string hash , string path)
{
Id = new MediaId(Guid.NewGuid());
ContentType = contentType;
Size = size;
Hash = hash;
@@ -5,10 +5,14 @@ using VizhTalk.BuildingBlocks.Domain;
namespace Vizhtalk.CDN.Presentation.Domain.Entities;
public class MediaGroup : Entity<MediaGroupId>
{
private MediaGroup()
{
}
private MediaGroup(MediaGroupTitle title, string key, bool isSecure)
{
Id = new MediaGroupId(Guid.NewGuid());
Title = title;
Key = key;
IsSecure = isSecure;
@@ -7,11 +7,15 @@ namespace Vizhtalk.CDN.Presentation.Domain.Entities;
public class MediaGroupMedia : Entity<MediaGroupMediaId>
{
private List<MediaPermission> _mediaPermissions = new();
private MediaGroupMedia()
{
}
private MediaGroupMedia(FileName fileName,
Media media,
MediaGroup mediaGroup)
{
Id = new MediaGroupMediaId(Guid.NewGuid());
Name = fileName;
Media = media;
MediaGroup = mediaGroup;
@@ -3,7 +3,7 @@ using VizhTalk.BuildingBlocks.Domain;
namespace Vizhtalk.CDN.Presentation.Domain.Entities;
public class MediaPermission : Entity<MediaClientId>
public class MediaPermission : Entity<MediaPermissionId>
{
private MediaPermission()
{
@@ -11,6 +11,7 @@ public class MediaPermission : Entity<MediaClientId>
}
private MediaPermission(Media media, Client client, MediaGroupMedia mediaGroupMedia)
{
Id = new MediaPermissionId(Guid.NewGuid());
Media = media;
Client = client;
MediaGroupMedia = mediaGroupMedia;
@@ -4,4 +4,4 @@ using VizhTalk.BuildingBlocks.Domain;
namespace Vizhtalk.CDN.Presentation.Domain.Repositories;
public interface IMediaClientRepository : IRepositoryBase<MediaPermission, MediaClientId>;
public interface IMediaPermissionRepository : IRepositoryBase<MediaPermission, MediaPermissionId>;
@@ -2,9 +2,9 @@
namespace Vizhtalk.CDN.Presentation.Domain.TypeIds;
public class MediaId : TypeIdValueBase<long>
public class MediaId : TypeIdValueBase<Guid>
{
public MediaId(long value) : base(value)
public MediaId(Guid value) : base(value)
{
}
}
@@ -2,9 +2,9 @@
namespace Vizhtalk.CDN.Presentation.Domain.TypeIds;
public class MediaClientId : TypeIdValueBase<long>
public class MediaPermissionId : TypeIdValueBase<Guid>
{
public MediaClientId(long value) : base(value)
public MediaPermissionId(Guid value) : base(value)
{
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 MiB

@@ -1,6 +1,8 @@
using Microsoft.EntityFrameworkCore;
using MongoDB.Driver;
using Vizhtalk.CDN.Presentation.Application;
using Vizhtalk.CDN.Presentation.Application.Mappers;
using Vizhtalk.CDN.Presentation.FileManagerServices;
using Vizhtalk.CDN.Presentation.Infrastructure.Configuration;
using Vizhtalk.CDN.Presentation.Infrastructure.EF;
using VizhTalk.BuildingBlocks.Application;
@@ -18,6 +20,9 @@ public static class CDNStartup
{
public static void Initialize(this IServiceCollection services, string connectionString, string databaseName)
{
var domainNotificationsMap = new BiDictionary<string, Type>();
services.AddDbContext<CDNDbContext>(options =>
{
options.UseMongoDB(connectionString, databaseName);
@@ -25,6 +30,46 @@ public static class CDNStartup
services.AddScoped<DbContext>(sp => sp.GetService<CDNDbContext>());
services.Scan(scan => scan.
FromAssemblies(Assemblies.Application, Assemblies.Infrastructure)
.AddClasses(classes => classes.AssignableTo(typeof(ICommandHandler<>)), publicOnly: false)
.AsImplementedInterfaces()
.WithScopedLifetime()
.AddClasses(classes => classes.AssignableTo(typeof(ICommandHandler<,>)), publicOnly: false)
.AsImplementedInterfaces()
.WithScopedLifetime()
.AddClasses(classes => classes.AssignableTo(typeof(IQueryHandler<,>)), publicOnly: false)
.AsImplementedInterfaces()
.WithScopedLifetime()
.AddClasses(classes => classes.AssignableTo(typeof(ICommandHandler<>)), publicOnly: false)
.AsImplementedInterfaces()
.WithScopedLifetime());
services.AddScoped<IFileManagerService, FileManagerService>();
services.AddScoped<DbContext>(sp => sp.GetService<CDNDbContext>());
services.AddScoped<ICDNModule, CDNModule>();
services.AddScoped<IExecutor, CDNModule>();
services.AddScoped<IUnitOfWork, UnitOfWork>();
services.AddScoped<IDomainEventsAccessor, DomainEventsAccessor>();
services.AddScoped<IDomainEventsDispatcher, DomainEventsDispatcher>();
services.AddScoped<IDomainNotificationsMapper, DomainNotificationsMapper>();
services.AddScoped(sp => domainNotificationsMap);
MapperConfig.Process();
services.AddScoped(sa =>
{
var notifications = sa.GetServices<IDomainEventNotification>();
var notificationDic = new BiDictionary<string, Type>();
foreach (var notification in notifications)
notificationDic.Add(notification!.ToString()!, notification!.GetType());
return notificationDic;
});
services.AddScoped<IOutbox>(sa =>
{
return null; // ToDo
});
}
@@ -9,7 +9,7 @@ namespace Vizhtalk.CDN.Presentation.Infrastructure.EF
public CDNDbContext(DbContextOptions<CDNDbContext> options) : base(options)
{
Database.AutoTransactionBehavior = AutoTransactionBehavior.Never;
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
@@ -19,6 +19,5 @@ namespace Vizhtalk.CDN.Presentation.Infrastructure.EF
.ApplyConfigurationsFromAssembly(Assemblies.Infrastructure, x => x.FullName.Contains("EF.Configurations"))
.PluralizeEntities();
}
}
}
@@ -12,7 +12,7 @@ public class MediaClientConfiguration : IEntityTypeConfiguration<MediaPermission
builder.HasKey(x => x.Id);
builder.Property(x => x.Id)
.HasConversion(x => x.Value, x => new Domain.TypeIds.MediaClientId(x));
.HasConversion(x => x.Value, x => new Domain.TypeIds.MediaPermissionId(x));
builder.Property(x => x.ClientId)
@@ -0,0 +1,16 @@
using Microsoft.EntityFrameworkCore;
using Vizhtalk.CDN.Presentation.Domain.Entities;
using Vizhtalk.CDN.Presentation.Domain.Repositories;
using Vizhtalk.CDN.Presentation.Domain.TypeIds;
using Vizhtalk.CDN.Presentation.Infrastructure.EF;
using VizhTalk.BuildingBlocks.Infrastructure;
namespace Vizhtalk.CDN.Presentation.Infrastructure.Repositories
{
public class ClientRepository : RepositoryBase<Client, ClientId>, IClientRepository
{
public ClientRepository(CDNDbContext dbContext) : base(dbContext)
{
}
}
}
@@ -0,0 +1,16 @@
using Microsoft.EntityFrameworkCore;
using Vizhtalk.CDN.Presentation.Domain.Entities;
using Vizhtalk.CDN.Presentation.Domain.Repositories;
using Vizhtalk.CDN.Presentation.Domain.TypeIds;
using Vizhtalk.CDN.Presentation.Infrastructure.EF;
using VizhTalk.BuildingBlocks.Infrastructure;
namespace Vizhtalk.CDN.Presentation.Infrastructure.Repositories
{
public class MediaGroupMediaRepository : RepositoryBase<MediaGroupMedia, MediaGroupMediaId>, IMediaGroupMediaRepository
{
public MediaGroupMediaRepository(CDNDbContext dbContext) : base(dbContext)
{
}
}
}
@@ -0,0 +1,16 @@
using Microsoft.EntityFrameworkCore;
using Vizhtalk.CDN.Presentation.Domain.Entities;
using Vizhtalk.CDN.Presentation.Domain.Repositories;
using Vizhtalk.CDN.Presentation.Domain.TypeIds;
using Vizhtalk.CDN.Presentation.Infrastructure.EF;
using VizhTalk.BuildingBlocks.Infrastructure;
namespace Vizhtalk.CDN.Presentation.Infrastructure.Repositories
{
public class MediaGroupRepository : RepositoryBase<MediaGroup, MediaGroupId>, IMediaGroupRepository
{
public MediaGroupRepository(CDNDbContext dbContext) : base(dbContext)
{
}
}
}
@@ -0,0 +1,16 @@
using Microsoft.EntityFrameworkCore;
using Vizhtalk.CDN.Presentation.Domain.Entities;
using Vizhtalk.CDN.Presentation.Domain.Repositories;
using Vizhtalk.CDN.Presentation.Domain.TypeIds;
using Vizhtalk.CDN.Presentation.Infrastructure.EF;
using VizhTalk.BuildingBlocks.Infrastructure;
namespace Vizhtalk.CDN.Presentation.Infrastructure.Repositories
{
public class MediaPermissionRepository : RepositoryBase<MediaPermission, MediaPermissionId>, IMediaPermissionRepository
{
public MediaPermissionRepository(CDNDbContext dbContext) : base(dbContext)
{
}
}
}
@@ -0,0 +1,16 @@
using Microsoft.EntityFrameworkCore;
using Vizhtalk.CDN.Presentation.Domain.Entities;
using Vizhtalk.CDN.Presentation.Domain.Repositories;
using Vizhtalk.CDN.Presentation.Domain.TypeIds;
using Vizhtalk.CDN.Presentation.Infrastructure.EF;
using VizhTalk.BuildingBlocks.Infrastructure;
namespace Vizhtalk.CDN.Presentation.Infrastructure.Repositories
{
public class MediaRepository : RepositoryBase<Media, MediaId>, IMediaRepository
{
public MediaRepository(CDNDbContext dbContext) : base(dbContext)
{
}
}
}
@@ -3,21 +3,73 @@ using Vizhtalk.CDN.Presentation.Infrastructure.EF;
using Vizhtalk.CDN.Presentation.Domain.Repositories;
using VizhTalk.BuildingBlocks.Infrastructure;
using VizhTalk.BuildingBlocks.Infrastructure.DomainEventsDispatching;
using Vizhtalk.CDN.Presentation.Infrastructure.Repositories;
namespace Vizhtalk.CDN.Presentation.Infrastructure
{
public class UnitOfWork(CDNDbContext cdnDbContext, IDomainEventsDispatcher domainEventsDispatcher)
: UnitOfWorkBase(cdnDbContext, domainEventsDispatcher)
: UnitOfWorkBase(cdnDbContext, domainEventsDispatcher), IUnitOfWork
{
public IMediaRepository Media => throw new NotImplementedException();
public IClientRepository Client => throw new NotImplementedException();
public IMediaClientRepository MediaClient => throw new NotImplementedException();
public IMediaGroupRepository MediaGroup => throw new NotImplementedException();
public IMediaGroupMediaRepository MediaGroupMedia => throw new NotImplementedException();
private IMediaRepository _mediaRepository;
public IMediaRepository Media
{
get
{
if (_mediaRepository == null)
_mediaRepository = new MediaRepository(cdnDbContext);
return _mediaRepository;
}
}
private IClientRepository _clientRepository;
public IClientRepository Client
{
get
{
if(_clientRepository == null)
_clientRepository = new ClientRepository(cdnDbContext);
return _clientRepository;
}
}
private IMediaPermissionRepository _mediaPermissionRepository;
public IMediaPermissionRepository MediaClient
{
get
{
if( _mediaPermissionRepository == null)
_mediaPermissionRepository = new MediaPermissionRepository(cdnDbContext);
return _mediaPermissionRepository;
}
}
private IMediaGroupRepository _mediaGroupRepository;
public IMediaGroupRepository MediaGroup
{
get
{
if(_mediaGroupRepository == null)
_mediaGroupRepository = new MediaGroupRepository(cdnDbContext);
return _mediaGroupRepository;
}
}
private IMediaGroupMediaRepository _mediaGroupMediaRepository;
public IMediaGroupMediaRepository MediaGroupMedia
{
get
{
if(_mediaGroupMediaRepository == null)
_mediaGroupMediaRepository = new MediaGroupMediaRepository(cdnDbContext);
return _mediaGroupMediaRepository;
}
}
public async Task SaveChangeAsync(CancellationToken cancellationToken = default)
=> await cdnDbContext.SaveChangesAsync(cancellationToken);
}
}
+4 -2
View File
@@ -8,9 +8,11 @@ var builder = WebApplication.CreateBuilder(args);
var connectionString = builder.Configuration.GetConnectionString("VizhTalk.CDN")!;
var databaseName = builder.Configuration.GetConnectionString("VizhTalk.CDN.DatabaseName")!;
builder.Services.AddScoped<IFileManagerService, FileManagerService>();
builder.Services.Initialize(connectionString, databaseName);
builder.Services.AddGrpc();
builder.Services.AddGrpc(op =>
{
op.MaxReceiveMessageSize = 500 * 1024 * 1024;
});
var app = builder.Build();
+1 -1
View File
@@ -7,7 +7,7 @@
},
"ConnectionStrings": {
"VizhTalk.CDN": "mongodb://localhost:27017",
"VizhTalk.CDN.DatabaseName": "VizhTalk.CDN"
"VizhTalk.CDN.DatabaseName": "VizhTalk_CDN"
},
"AllowedHosts": "*"
}