.net10 сервер с рабочими звонками и файлами

This commit is contained in:
Халимов Рустам
2026-03-12 01:48:58 +03:00
parent 50d4d75c04
commit d025c98e61
741 changed files with 35231 additions and 1863 deletions

View File

@@ -7,3 +7,7 @@ apps/server/dist
apps/server/uploads
.vscode
.env
bin/
obj/
**/bin/
**/obj/

23
Dockerfile.server-net Normal file
View File

@@ -0,0 +1,23 @@
FROM mcr.microsoft.com/dotnet/sdk:10.0-preview AS build
WORKDIR /app
# Copy everything and restore as distinct layers
COPY . .
RUN dotnet restore apps/server-net/Vortex.sln
# Build and publish a release
RUN dotnet publish apps/server-net/src/Vortex.Host/Vortex.Host.csproj -c Release -o out
# Build runtime image
FROM mcr.microsoft.com/dotnet/aspnet:10.0-preview
WORKDIR /app
# Install native dependencies for Npgsql/GSSAPI
RUN apt-get update && apt-get install -y libgssapi-krb5-2 && rm -rf /var/lib/apt/lists/*
COPY --from=build /app/out .
EXPOSE 8080
ENV ASPNETCORE_URLS=http://+:8080
ENTRYPOINT ["dotnet", "Vortex.Host.dll"]

View File

@@ -5,7 +5,6 @@ WORKDIR /app
# ROOT package.json
COPY package*.json ./
COPY apps/server/package*.json ./apps/server/
COPY apps/web/package*.json ./apps/web/
RUN npm install

128
apps/server-net/Vortex.sln Normal file
View File

@@ -0,0 +1,128 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{827E0CD3-B72D-47B6-A68D-7590B98EB39B}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{C8E42992-5E42-0C2B-DBFE-AA848D06431C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Vortex.Shared.Kernel", "src\Shared\Vortex.Shared.Kernel\Vortex.Shared.Kernel.csproj", "{C829F859-FF48-4025-BF22-8E63672D113C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Vortex.Shared.Infrastructure", "src\Shared\Vortex.Shared.Infrastructure\Vortex.Shared.Infrastructure.csproj", "{6C13E9A4-234C-4BF1-A145-F1BBA2AC56CB}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Modules", "Modules", "{EC447DCF-ABFA-6E24-52A5-D7FD48A5C558}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Identity", "Identity", "{0EC62A1A-9858-3A60-8A0C-FC9AACFA2EC7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Vortex.Modules.Identity", "src\Modules\Identity\Vortex.Modules.Identity.csproj", "{5BB2F421-C4C4-40A1-8D6E-FEBB79AE7C98}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Chats", "Chats", "{B4154CE3-9153-E2B0-0515-138FFCE32938}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Vortex.Modules.Chats", "src\Modules\Chats\Vortex.Modules.Chats.csproj", "{695CC919-E321-4DC0-8D70-C631C51624E1}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{0AB3BF05-4346-4AA6-1389-037BE0695223}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Vortex.Modules.Identity.UnitTests", "tests\Vortex.Modules.Identity.UnitTests\Vortex.Modules.Identity.UnitTests.csproj", "{AB2F334E-DD7C-4314-93B9-941AFC6B2ACD}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Vortex.Modules.Chats.UnitTests", "tests\Vortex.Modules.Chats.UnitTests\Vortex.Modules.Chats.UnitTests.csproj", "{F48A3E3A-EEBB-43AA-81AB-7DD7FE5F29B4}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{C829F859-FF48-4025-BF22-8E63672D113C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C829F859-FF48-4025-BF22-8E63672D113C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C829F859-FF48-4025-BF22-8E63672D113C}.Debug|x64.ActiveCfg = Debug|Any CPU
{C829F859-FF48-4025-BF22-8E63672D113C}.Debug|x64.Build.0 = Debug|Any CPU
{C829F859-FF48-4025-BF22-8E63672D113C}.Debug|x86.ActiveCfg = Debug|Any CPU
{C829F859-FF48-4025-BF22-8E63672D113C}.Debug|x86.Build.0 = Debug|Any CPU
{C829F859-FF48-4025-BF22-8E63672D113C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C829F859-FF48-4025-BF22-8E63672D113C}.Release|Any CPU.Build.0 = Release|Any CPU
{C829F859-FF48-4025-BF22-8E63672D113C}.Release|x64.ActiveCfg = Release|Any CPU
{C829F859-FF48-4025-BF22-8E63672D113C}.Release|x64.Build.0 = Release|Any CPU
{C829F859-FF48-4025-BF22-8E63672D113C}.Release|x86.ActiveCfg = Release|Any CPU
{C829F859-FF48-4025-BF22-8E63672D113C}.Release|x86.Build.0 = Release|Any CPU
{6C13E9A4-234C-4BF1-A145-F1BBA2AC56CB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6C13E9A4-234C-4BF1-A145-F1BBA2AC56CB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6C13E9A4-234C-4BF1-A145-F1BBA2AC56CB}.Debug|x64.ActiveCfg = Debug|Any CPU
{6C13E9A4-234C-4BF1-A145-F1BBA2AC56CB}.Debug|x64.Build.0 = Debug|Any CPU
{6C13E9A4-234C-4BF1-A145-F1BBA2AC56CB}.Debug|x86.ActiveCfg = Debug|Any CPU
{6C13E9A4-234C-4BF1-A145-F1BBA2AC56CB}.Debug|x86.Build.0 = Debug|Any CPU
{6C13E9A4-234C-4BF1-A145-F1BBA2AC56CB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6C13E9A4-234C-4BF1-A145-F1BBA2AC56CB}.Release|Any CPU.Build.0 = Release|Any CPU
{6C13E9A4-234C-4BF1-A145-F1BBA2AC56CB}.Release|x64.ActiveCfg = Release|Any CPU
{6C13E9A4-234C-4BF1-A145-F1BBA2AC56CB}.Release|x64.Build.0 = Release|Any CPU
{6C13E9A4-234C-4BF1-A145-F1BBA2AC56CB}.Release|x86.ActiveCfg = Release|Any CPU
{6C13E9A4-234C-4BF1-A145-F1BBA2AC56CB}.Release|x86.Build.0 = Release|Any CPU
{5BB2F421-C4C4-40A1-8D6E-FEBB79AE7C98}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5BB2F421-C4C4-40A1-8D6E-FEBB79AE7C98}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5BB2F421-C4C4-40A1-8D6E-FEBB79AE7C98}.Debug|x64.ActiveCfg = Debug|Any CPU
{5BB2F421-C4C4-40A1-8D6E-FEBB79AE7C98}.Debug|x64.Build.0 = Debug|Any CPU
{5BB2F421-C4C4-40A1-8D6E-FEBB79AE7C98}.Debug|x86.ActiveCfg = Debug|Any CPU
{5BB2F421-C4C4-40A1-8D6E-FEBB79AE7C98}.Debug|x86.Build.0 = Debug|Any CPU
{5BB2F421-C4C4-40A1-8D6E-FEBB79AE7C98}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5BB2F421-C4C4-40A1-8D6E-FEBB79AE7C98}.Release|Any CPU.Build.0 = Release|Any CPU
{5BB2F421-C4C4-40A1-8D6E-FEBB79AE7C98}.Release|x64.ActiveCfg = Release|Any CPU
{5BB2F421-C4C4-40A1-8D6E-FEBB79AE7C98}.Release|x64.Build.0 = Release|Any CPU
{5BB2F421-C4C4-40A1-8D6E-FEBB79AE7C98}.Release|x86.ActiveCfg = Release|Any CPU
{5BB2F421-C4C4-40A1-8D6E-FEBB79AE7C98}.Release|x86.Build.0 = Release|Any CPU
{695CC919-E321-4DC0-8D70-C631C51624E1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{695CC919-E321-4DC0-8D70-C631C51624E1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{695CC919-E321-4DC0-8D70-C631C51624E1}.Debug|x64.ActiveCfg = Debug|Any CPU
{695CC919-E321-4DC0-8D70-C631C51624E1}.Debug|x64.Build.0 = Debug|Any CPU
{695CC919-E321-4DC0-8D70-C631C51624E1}.Debug|x86.ActiveCfg = Debug|Any CPU
{695CC919-E321-4DC0-8D70-C631C51624E1}.Debug|x86.Build.0 = Debug|Any CPU
{695CC919-E321-4DC0-8D70-C631C51624E1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{695CC919-E321-4DC0-8D70-C631C51624E1}.Release|Any CPU.Build.0 = Release|Any CPU
{695CC919-E321-4DC0-8D70-C631C51624E1}.Release|x64.ActiveCfg = Release|Any CPU
{695CC919-E321-4DC0-8D70-C631C51624E1}.Release|x64.Build.0 = Release|Any CPU
{695CC919-E321-4DC0-8D70-C631C51624E1}.Release|x86.ActiveCfg = Release|Any CPU
{695CC919-E321-4DC0-8D70-C631C51624E1}.Release|x86.Build.0 = Release|Any CPU
{AB2F334E-DD7C-4314-93B9-941AFC6B2ACD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AB2F334E-DD7C-4314-93B9-941AFC6B2ACD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AB2F334E-DD7C-4314-93B9-941AFC6B2ACD}.Debug|x64.ActiveCfg = Debug|Any CPU
{AB2F334E-DD7C-4314-93B9-941AFC6B2ACD}.Debug|x64.Build.0 = Debug|Any CPU
{AB2F334E-DD7C-4314-93B9-941AFC6B2ACD}.Debug|x86.ActiveCfg = Debug|Any CPU
{AB2F334E-DD7C-4314-93B9-941AFC6B2ACD}.Debug|x86.Build.0 = Debug|Any CPU
{AB2F334E-DD7C-4314-93B9-941AFC6B2ACD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AB2F334E-DD7C-4314-93B9-941AFC6B2ACD}.Release|Any CPU.Build.0 = Release|Any CPU
{AB2F334E-DD7C-4314-93B9-941AFC6B2ACD}.Release|x64.ActiveCfg = Release|Any CPU
{AB2F334E-DD7C-4314-93B9-941AFC6B2ACD}.Release|x64.Build.0 = Release|Any CPU
{AB2F334E-DD7C-4314-93B9-941AFC6B2ACD}.Release|x86.ActiveCfg = Release|Any CPU
{AB2F334E-DD7C-4314-93B9-941AFC6B2ACD}.Release|x86.Build.0 = Release|Any CPU
{F48A3E3A-EEBB-43AA-81AB-7DD7FE5F29B4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F48A3E3A-EEBB-43AA-81AB-7DD7FE5F29B4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F48A3E3A-EEBB-43AA-81AB-7DD7FE5F29B4}.Debug|x64.ActiveCfg = Debug|Any CPU
{F48A3E3A-EEBB-43AA-81AB-7DD7FE5F29B4}.Debug|x64.Build.0 = Debug|Any CPU
{F48A3E3A-EEBB-43AA-81AB-7DD7FE5F29B4}.Debug|x86.ActiveCfg = Debug|Any CPU
{F48A3E3A-EEBB-43AA-81AB-7DD7FE5F29B4}.Debug|x86.Build.0 = Debug|Any CPU
{F48A3E3A-EEBB-43AA-81AB-7DD7FE5F29B4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F48A3E3A-EEBB-43AA-81AB-7DD7FE5F29B4}.Release|Any CPU.Build.0 = Release|Any CPU
{F48A3E3A-EEBB-43AA-81AB-7DD7FE5F29B4}.Release|x64.ActiveCfg = Release|Any CPU
{F48A3E3A-EEBB-43AA-81AB-7DD7FE5F29B4}.Release|x64.Build.0 = Release|Any CPU
{F48A3E3A-EEBB-43AA-81AB-7DD7FE5F29B4}.Release|x86.ActiveCfg = Release|Any CPU
{F48A3E3A-EEBB-43AA-81AB-7DD7FE5F29B4}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{C8E42992-5E42-0C2B-DBFE-AA848D06431C} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
{C829F859-FF48-4025-BF22-8E63672D113C} = {C8E42992-5E42-0C2B-DBFE-AA848D06431C}
{6C13E9A4-234C-4BF1-A145-F1BBA2AC56CB} = {C8E42992-5E42-0C2B-DBFE-AA848D06431C}
{EC447DCF-ABFA-6E24-52A5-D7FD48A5C558} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
{0EC62A1A-9858-3A60-8A0C-FC9AACFA2EC7} = {EC447DCF-ABFA-6E24-52A5-D7FD48A5C558}
{5BB2F421-C4C4-40A1-8D6E-FEBB79AE7C98} = {0EC62A1A-9858-3A60-8A0C-FC9AACFA2EC7}
{B4154CE3-9153-E2B0-0515-138FFCE32938} = {EC447DCF-ABFA-6E24-52A5-D7FD48A5C558}
{695CC919-E321-4DC0-8D70-C631C51624E1} = {B4154CE3-9153-E2B0-0515-138FFCE32938}
{AB2F334E-DD7C-4314-93B9-941AFC6B2ACD} = {0AB3BF05-4346-4AA6-1389-037BE0695223}
{F48A3E3A-EEBB-43AA-81AB-7DD7FE5F29B4} = {0AB3BF05-4346-4AA6-1389-037BE0695223}
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,10 @@
using Vortex.Shared.Kernel;
namespace Vortex.Modules.Chats.Application.Abstractions;
/// <summary>
/// Unit of Work специфичный для модуля Chats.
/// </summary>
public interface IChatsUnitOfWork : IUnitOfWork
{
}

View File

@@ -0,0 +1,41 @@
using Vortex.Modules.Chats.Domain;
using Vortex.Shared.Kernel;
using Vortex.Modules.Chats.Application.Abstractions;
namespace Vortex.Modules.Chats.Application.Chats.Create;
/// <summary>
/// Команда для создания чата.
/// </summary>
public sealed record CreateChatCommand(
string Name,
ChatType Type,
List<Guid> MemberIds) : ICommand<Guid>;
public sealed class CreateChatCommandHandler : ICommandHandler<CreateChatCommand, Guid>
{
private readonly IChatRepository _chatRepository;
private readonly IChatsUnitOfWork _unitOfWork;
public CreateChatCommandHandler(IChatRepository chatRepository, IChatsUnitOfWork unitOfWork)
{
_chatRepository = chatRepository;
_unitOfWork = unitOfWork;
}
public async Task<Result<Guid>> Handle(CreateChatCommand request, CancellationToken cancellationToken)
{
var chat = Chat.Create(request.Name, request.Type);
foreach (var userId in request.MemberIds)
{
chat.AddMember(userId, ChatRole.Member);
}
_chatRepository.Add(chat);
await _unitOfWork.SaveChangesAsync(cancellationToken);
return Result.Success(chat.Id);
}
}

View File

@@ -0,0 +1,38 @@
using Vortex.Modules.Chats.Domain;
using Vortex.Shared.Kernel;
using Vortex.Modules.Chats.Application.Abstractions;
namespace Vortex.Modules.Chats.Application.Chats.GetOrCreateFavorites;
public sealed record GetOrCreateFavoritesCommand(Guid UserId) : ICommand<Guid>;
public sealed class GetOrCreateFavoritesCommandHandler : ICommandHandler<GetOrCreateFavoritesCommand, Guid>
{
private readonly IChatRepository _chatRepository;
private readonly IChatsUnitOfWork _unitOfWork;
public GetOrCreateFavoritesCommandHandler(IChatRepository chatRepository, IChatsUnitOfWork unitOfWork)
{
_chatRepository = chatRepository;
_unitOfWork = unitOfWork;
}
public async Task<Result<Guid>> Handle(GetOrCreateFavoritesCommand request, CancellationToken cancellationToken)
{
var favorites = await _chatRepository.GetFavoritesAsync(request.UserId, cancellationToken);
if (favorites != null)
{
return Result.Success(favorites.Id);
}
// Create new favorites chat
var chat = Chat.Create("Избранное", ChatType.Favorites);
chat.AddMember(request.UserId, ChatRole.Owner);
_chatRepository.Add(chat);
await _unitOfWork.SaveChangesAsync(cancellationToken);
return Result.Success(chat.Id);
}
}

View File

@@ -0,0 +1,34 @@
using MediatR;
using Vortex.Modules.Chats.Domain;
using Vortex.Shared.Kernel;
using Vortex.Modules.Chats.Application.Abstractions;
namespace Vortex.Modules.Chats.Application.Messages.Read;
public sealed record ReadMessagesCommand(Guid ChatId, Guid UserId, List<Guid> MessageIds) : ICommand;
public sealed class ReadMessagesCommandHandler : ICommandHandler<ReadMessagesCommand>
{
private readonly IMessageRepository _messageRepository;
private readonly IChatsUnitOfWork _unitOfWork;
public ReadMessagesCommandHandler(IMessageRepository messageRepository, IChatsUnitOfWork unitOfWork)
{
_messageRepository = messageRepository;
_unitOfWork = unitOfWork;
}
public async Task<Result> Handle(ReadMessagesCommand request, CancellationToken cancellationToken)
{
if (request.MessageIds == null || !request.MessageIds.Any())
{
return Result.Success();
}
await _messageRepository.AddReadReceiptsAsync(request.UserId, request.MessageIds, cancellationToken);
await _unitOfWork.SaveChangesAsync(cancellationToken);
return Result.Success();
}
}

View File

@@ -0,0 +1,66 @@
using Vortex.Modules.Chats.Domain;
using Vortex.Shared.Kernel;
using Vortex.Modules.Chats.Application.Abstractions;
namespace Vortex.Modules.Chats.Application.Messages.Send;
/// <summary>
/// Команда для отправки сообщения в чат.
/// </summary>
public sealed record SendMessageCommand(
Guid ChatId,
Guid SenderId,
string? Content,
string Type,
string? MediaUrl = null,
string? MediaType = null,
string? FileName = null,
long? FileSize = null) : ICommand<Guid>;
public sealed class SendMessageCommandHandler : ICommandHandler<SendMessageCommand, Guid>
{
private readonly IChatRepository _chatRepository;
private readonly IMessageRepository _messageRepository;
private readonly IChatsUnitOfWork _unitOfWork;
public SendMessageCommandHandler(
IChatRepository chatRepository,
IMessageRepository messageRepository,
IChatsUnitOfWork unitOfWork)
{
_chatRepository = chatRepository;
_messageRepository = messageRepository;
_unitOfWork = unitOfWork;
}
public async Task<Result<Guid>> Handle(SendMessageCommand request, CancellationToken cancellationToken)
{
// 1. Проверяем существование чата
var chat = await _chatRepository.GetByIdAsync(request.ChatId, cancellationToken);
if (chat is null)
{
return Result.Failure<Guid>(new Error("Chats.NotFound", "Чат не найден."));
}
// 2. Проверяем, является ли отправитель участником (в будущем)
// if (!chat.Members.Any(m => m.UserId == request.SenderId)) ...
// 3. Создаем сообщение
var message = Message.Create(
request.ChatId,
request.SenderId,
request.Content,
request.Type);
if (!string.IsNullOrEmpty(request.MediaUrl) && !string.IsNullOrEmpty(request.MediaType))
{
message.AddMedia(request.MediaType, request.MediaUrl, request.FileName, request.FileSize);
}
// 4. Сохраняем
_messageRepository.Add(message);
await _unitOfWork.SaveChangesAsync(cancellationToken);
return Result.Success(message.Id);
}
}

View File

@@ -0,0 +1,6 @@
namespace Vortex.Modules.Chats;
public class Class1
{
}

View File

@@ -0,0 +1,38 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
using Microsoft.EntityFrameworkCore;
using Vortex.Modules.Chats.Infrastructure.Persistence;
using Vortex.Modules.Chats.Domain;
using Vortex.Shared.Kernel;
using Vortex.Modules.Chats.Application.Abstractions;
namespace Vortex.Modules.Chats;
public static class DependencyInjection
{
/// <summary>
/// Регистрация сервисов модуля Chats.
/// </summary>
public static IServiceCollection AddChatsModule(
this IServiceCollection services,
IConfiguration configuration)
{
// Настройка базы данных
string connectionString = configuration.GetConnectionString("Database")!;
services.AddDbContext<ChatsDbContext>(options =>
options.UseNpgsql(connectionString));
// Регистрация Unit of Work и Репозиториев
services.AddScoped<IChatsUnitOfWork>(sp => sp.GetRequiredService<ChatsDbContext>());
services.AddScoped<IChatRepository, ChatRepository>();
services.AddScoped<IMessageRepository, MessageRepository>();
// Регистрация MediatR для этого модуля
services.AddMediatR(config =>
config.RegisterServicesFromAssembly(typeof(DependencyInjection).Assembly));
return services;
}
}

View File

@@ -0,0 +1,108 @@
using Vortex.Shared.Kernel;
namespace Vortex.Modules.Chats.Domain;
/// <summary>
/// Тип чата: личный или групповой.
/// </summary>
public enum ChatType
{
Personal,
Group,
Favorites
}
/// <summary>
/// Роль участника в чате.
/// </summary>
public static class ChatRole
{
public const string Owner = "owner";
public const string Admin = "admin";
public const string Member = "member";
}
/// <summary>
/// Сущность чата (Агрегат).
/// </summary>
public sealed class Chat : AggregateRoot<Guid>
{
public ChatType Type { get; private set; }
public string? Name { get; private set; }
public string? Avatar { get; private set; }
public DateTime CreatedAt { get; private set; }
private readonly List<ChatMember> _members = new();
public IReadOnlyCollection<ChatMember> Members => _members.AsReadOnly();
private Chat(Guid id, ChatType type, string? name, string? avatar) : base(id)
{
Type = type;
Name = name;
Avatar = avatar;
CreatedAt = DateTime.UtcNow;
}
/// <summary>
/// Создает личный чат между двумя пользователями.
/// </summary>
public static Chat CreatePersonal()
{
return new Chat(Guid.NewGuid(), ChatType.Personal, null, null);
}
/// <summary>
/// Создает групповой чат.
/// </summary>
public static Chat CreateGroup(string name, string? avatar = null)
{
return new Chat(Guid.NewGuid(), ChatType.Group, name, avatar);
}
/// <summary>
/// Фабричный метод для создания чата.
/// </summary>
public static Chat Create(string? name, ChatType type, string? avatar = null)
{
return new Chat(Guid.NewGuid(), type, name, avatar);
}
public void AddMember(Guid userId, string role = "member")
{
if (_members.Any(m => m.UserId == userId)) return;
_members.Add(new ChatMember(Id, userId, role));
}
public void RemoveMember(Guid userId)
{
var member = _members.FirstOrDefault(m => m.UserId == userId);
if (member != null) _members.Remove(member);
}
public void UpdateName(string name) => Name = name;
public void UpdateAvatar(string? avatarUrl) => Avatar = avatarUrl;
}
/// <summary>
/// Участник чата.
/// </summary>
public sealed class ChatMember : Entity<Guid>
{
public Guid ChatId { get; private set; }
public Guid UserId { get; private set; }
public string Role { get; private set; }
public DateTime JoinedAt { get; private set; }
public bool IsMuted { get; private set; }
// For EF Core
private ChatMember() : base(Guid.Empty) { Role = "member"; }
internal ChatMember(Guid chatId, Guid userId, string role) : base(Guid.NewGuid())
{
ChatId = chatId;
UserId = userId;
Role = role;
JoinedAt = DateTime.UtcNow;
}
}

View File

@@ -0,0 +1,13 @@
using Vortex.Modules.Chats.Domain;
namespace Vortex.Modules.Chats.Domain;
public interface IChatRepository
{
void Add(Chat chat);
void Update(Chat chat);
void Remove(Chat chat);
Task<Chat?> GetByIdAsync(Guid id, CancellationToken cancellationToken);
Task<Chat?> GetFavoritesAsync(Guid userId, CancellationToken cancellationToken);
Task<List<Chat>> GetUserChatsAsync(Guid userId, CancellationToken cancellationToken);
}

View File

@@ -0,0 +1,12 @@
using Vortex.Modules.Chats.Domain;
namespace Vortex.Modules.Chats.Domain;
public interface IMessageRepository
{
void Add(Message message);
Task<Message?> GetByIdAsync(Guid id, CancellationToken cancellationToken);
Task<List<Message>> GetChatMessagesAsync(Guid chatId, int limit, int offset, CancellationToken cancellationToken);
Task<List<Message>> SearchMessagesAsync(string query, Guid? chatId, CancellationToken cancellationToken);
Task AddReadReceiptsAsync(Guid userId, List<Guid> messageIds, CancellationToken cancellationToken);
}

View File

@@ -0,0 +1,84 @@
using Vortex.Shared.Kernel;
namespace Vortex.Modules.Chats.Domain;
/// <summary>
/// Доменное событие: сообщение отправлено.
/// </summary>
public sealed record MessageSentDomainEvent(Guid MessageId, Guid ChatId, Guid SenderId, string? Content) : IDomainEvent;
/// <summary>
/// Сущность сообщения (Агрегат).
/// </summary>
public sealed class Message : AggregateRoot<Guid>
{
public Guid ChatId { get; private set; }
public Guid SenderId { get; private set; }
public string? Content { get; private set; }
public string Type { get; private set; } // text, image, video, voice, file
public Guid? ReplyToId { get; private set; }
public string? Quote { get; private set; }
public bool IsEdited { get; private set; }
public bool IsDeleted { get; private set; }
public DateTime CreatedAt { get; private set; }
private readonly List<Media> _media = new();
public IReadOnlyCollection<Media> Media => _media.AsReadOnly();
private readonly List<ReadReceipt> _readBy = new();
public IReadOnlyCollection<ReadReceipt> ReadBy => _readBy.AsReadOnly();
private Message(Guid id, Guid chatId, Guid senderId, string? content, string type) : base(id)
{
ChatId = chatId;
SenderId = senderId;
Content = content;
Type = type;
CreatedAt = DateTime.UtcNow;
RaiseDomainEvent(new MessageSentDomainEvent(Id, ChatId, SenderId, Content));
}
public static Message Create(Guid chatId, Guid senderId, string? content, string type)
{
return new Message(Guid.NewGuid(), chatId, senderId, content, type);
}
public void AddMedia(string type, string url, string? filename, long? size)
{
_media.Add(new Media(Id, type, url, filename, size));
}
public void Edit(string newContent)
{
Content = newContent;
IsEdited = true;
}
public void Delete()
{
Content = null;
IsDeleted = true;
}
}
/// <summary>
/// Медиа-файл, прикрепленный к сообщению.
/// </summary>
public sealed class Media : Entity<Guid>
{
public Guid MessageId { get; private set; }
public string Type { get; private set; }
public string Url { get; private set; }
public string? Filename { get; private set; }
public long? Size { get; private set; }
internal Media(Guid messageId, string type, string url, string? filename, long? size) : base(Guid.NewGuid())
{
MessageId = messageId;
Type = type;
Url = url;
Filename = filename;
Size = size;
}
}

View File

@@ -0,0 +1,20 @@
using Vortex.Shared.Kernel;
namespace Vortex.Modules.Chats.Domain;
public sealed class ReadReceipt : Entity<Guid>
{
public Guid MessageId { get; private set; }
public Guid UserId { get; private set; }
public DateTime ReadAt { get; private set; }
// Для EF Core
private ReadReceipt() : base(Guid.Empty) { }
public ReadReceipt(Guid messageId, Guid userId) : base(Guid.NewGuid())
{
MessageId = messageId;
UserId = userId;
ReadAt = DateTime.UtcNow;
}
}

View File

@@ -0,0 +1,55 @@
using MediatR;
using Microsoft.AspNetCore.SignalR;
using Vortex.Modules.Chats.Domain;
using Vortex.Modules.Chats.Infrastructure.SignalR;
using Vortex.Shared.Kernel;
namespace Vortex.Modules.Chats.Infrastructure.Handlers;
/// <summary>
/// Обработчик доменного события отправки сообщения.
/// Отправляет уведомление через SignalR всем участникам чата.
/// </summary>
public sealed class MessageSentDomainEventHandler : INotificationHandler<MessageSentDomainEvent>
{
private readonly IHubContext<ChatHub> _hubContext;
private readonly IMessageRepository _messageRepository;
private readonly IUserDisplayNameProvider _displayNameProvider;
public MessageSentDomainEventHandler(
IHubContext<ChatHub> hubContext,
IMessageRepository messageRepository,
IUserDisplayNameProvider displayNameProvider)
{
_hubContext = hubContext;
_messageRepository = messageRepository;
_displayNameProvider = displayNameProvider;
}
public async Task Handle(MessageSentDomainEvent notification, CancellationToken cancellationToken)
{
var message = await _messageRepository.GetByIdAsync(notification.MessageId, cancellationToken);
if (message is null) return;
var userInfo = await _displayNameProvider.GetUserInfoAsync(message.SenderId, cancellationToken);
var senderObj = userInfo != null
? new { Id = userInfo.Id, Username = userInfo.Username, DisplayName = userInfo.DisplayName, Avatar = userInfo.Avatar }
: new { Id = message.SenderId, Username = "unknown", DisplayName = "Unknown", Avatar = (string?)null };
// Отправляем сообщение в "комнату" чата.
await _hubContext.Clients.Group(notification.ChatId.ToString())
.SendAsync("new_message", new
{
message.Id,
message.ChatId,
message.SenderId,
message.Content,
message.Type,
message.CreatedAt,
Media = message.Media.ToList(),
Sender = senderObj,
Reactions = new List<object>(),
ReadBy = new List<object>()
}, cancellationToken);
}
}

View File

@@ -0,0 +1,55 @@
using Microsoft.EntityFrameworkCore;
using Vortex.Modules.Chats.Domain;
namespace Vortex.Modules.Chats.Infrastructure.Persistence;
public sealed class ChatRepository : IChatRepository
{
private readonly ChatsDbContext _dbContext;
public ChatRepository(ChatsDbContext dbContext)
{
_dbContext = dbContext;
}
public void Add(Chat chat)
{
_dbContext.Chats.Add(chat);
}
public void Update(Chat chat)
{
_dbContext.Chats.Update(chat);
}
public void Remove(Chat chat)
{
_dbContext.Chats.Remove(chat);
}
public async Task<Chat?> GetByIdAsync(Guid id, CancellationToken cancellationToken)
{
return await _dbContext.Chats
.Include(c => c.Members)
.FirstOrDefaultAsync(c => c.Id == id, cancellationToken);
}
public async Task<Chat?> GetFavoritesAsync(Guid userId, CancellationToken cancellationToken)
{
return await _dbContext.Chats
.Include(c => c.Members)
.FirstOrDefaultAsync(c =>
c.Type == ChatType.Favorites &&
c.Members.Any(m => m.UserId == userId),
cancellationToken);
}
public async Task<List<Chat>> GetUserChatsAsync(Guid userId, CancellationToken cancellationToken)
{
return await _dbContext.Chats
.Include(c => c.Members)
.Where(c => c.Members.Any(m => m.UserId == userId))
.OrderByDescending(c => c.CreatedAt)
.ToListAsync(cancellationToken);
}
}

View File

@@ -0,0 +1,95 @@
using Microsoft.EntityFrameworkCore;
using MediatR;
using Vortex.Modules.Chats.Domain;
using Vortex.Shared.Kernel;
using Vortex.Modules.Chats.Application.Abstractions;
namespace Vortex.Modules.Chats.Infrastructure.Persistence;
/// <summary>
/// Контекст базы данных для модуля чатов.
/// </summary>
public sealed class ChatsDbContext : DbContext, IChatsUnitOfWork
{
private readonly IMediator _mediator;
public ChatsDbContext(DbContextOptions<ChatsDbContext> options, IMediator mediator)
: base(options)
{
_mediator = mediator;
}
public DbSet<Chat> Chats => Set<Chat>();
public DbSet<Message> Messages => Set<Message>();
public DbSet<ReadReceipt> ReadReceipts => Set<ReadReceipt>();
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.HasDefaultSchema("chats");
modelBuilder.Entity<Chat>(builder =>
{
builder.ToTable("Chats");
builder.HasKey(c => c.Id);
builder.Property(c => c.Type).HasConversion<string>();
builder.OwnsMany(c => c.Members, mb =>
{
mb.ToTable("ChatMembers");
mb.HasKey(m => m.Id);
mb.WithOwner().HasForeignKey(m => m.ChatId);
mb.HasIndex(m => new { m.ChatId, m.UserId }).IsUnique();
});
});
modelBuilder.Entity<Message>(builder =>
{
builder.ToTable("Messages");
builder.HasKey(m => m.Id);
builder.OwnsMany(m => m.Media, mb =>
{
mb.ToTable("MessageMedia");
mb.HasKey(x => x.Id);
mb.WithOwner().HasForeignKey(x => x.MessageId);
});
});
modelBuilder.Entity<ReadReceipt>(builder =>
{
builder.ToTable("ReadReceipts");
builder.HasKey(r => r.Id);
builder.HasIndex(r => new { r.MessageId, r.UserId }).IsUnique();
});
}
public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
{
// 1. Получаем все события из агрегатов
var domainEvents = ChangeTracker
.Entries<IAggregateRoot>()
.SelectMany(x =>
{
if (x.Entity is AggregateRoot<Guid> root)
{
var events = root.GetDomainEvents().ToList();
root.ClearDomainEvents();
return events;
}
return Enumerable.Empty<IDomainEvent>();
})
.ToList();
// 2. Сохраняем изменения
int result = await base.SaveChangesAsync(cancellationToken);
// 3. Публикуем события через MediatR
foreach (var domainEvent in domainEvents)
{
await _mediator.Publish(domainEvent, cancellationToken);
}
return result;
}
}

View File

@@ -0,0 +1,71 @@
using Microsoft.EntityFrameworkCore;
using Vortex.Modules.Chats.Domain;
namespace Vortex.Modules.Chats.Infrastructure.Persistence;
public sealed class MessageRepository : IMessageRepository
{
private readonly ChatsDbContext _dbContext;
public MessageRepository(ChatsDbContext dbContext)
{
_dbContext = dbContext;
}
public void Add(Message message)
{
_dbContext.Messages.Add(message);
}
public async Task<Message?> GetByIdAsync(Guid id, CancellationToken cancellationToken)
{
return await _dbContext.Messages
.Include(m => m.Media)
.Include(m => m.ReadBy)
.FirstOrDefaultAsync(m => m.Id == id, cancellationToken);
}
public async Task<List<Message>> GetChatMessagesAsync(Guid chatId, int limit, int offset, CancellationToken cancellationToken)
{
return await _dbContext.Messages
.Where(m => m.ChatId == chatId)
.OrderByDescending(m => m.CreatedAt)
.Skip(offset)
.Take(limit)
.Include(m => m.Media)
.Include(m => m.ReadBy)
.ToListAsync(cancellationToken);
}
public async Task<List<Message>> SearchMessagesAsync(string query, Guid? chatId, CancellationToken cancellationToken)
{
var q = _dbContext.Messages.AsQueryable();
if (chatId.HasValue)
{
q = q.Where(m => m.ChatId == chatId.Value);
}
return await q.Where(m => m.Content != null && m.Content.Contains(query))
.OrderByDescending(m => m.CreatedAt)
.Take(50)
.Include(m => m.Media)
.Include(m => m.ReadBy)
.ToListAsync(cancellationToken);
}
public async Task AddReadReceiptsAsync(Guid userId, List<Guid> messageIds, CancellationToken cancellationToken)
{
var existingReceipts = await _dbContext.ReadReceipts
.Where(r => r.UserId == userId && messageIds.Contains(r.MessageId))
.Select(r => r.MessageId)
.ToListAsync(cancellationToken);
var newReceipts = messageIds
.Except(existingReceipts)
.Select(id => new ReadReceipt(id, userId));
_dbContext.ReadReceipts.AddRange(newReceipts);
// SaveChangesAsync будет вызван в handlers или через UnitOfWork, но если мы здесь
await _dbContext.SaveChangesAsync(cancellationToken);
}
}

View File

@@ -0,0 +1,170 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using Vortex.Modules.Chats.Infrastructure.Persistence;
#nullable disable
namespace Vortex.Modules.Chats.Infrastructure.Persistence.Migrations
{
[DbContext(typeof(ChatsDbContext))]
[Migration("20260311180825_InitialChats")]
partial class InitialChats
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasDefaultSchema("chats")
.HasAnnotation("ProductVersion", "10.0.4")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("Vortex.Modules.Chats.Domain.Chat", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("Avatar")
.HasColumnType("text");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("Name")
.HasColumnType("text");
b.Property<string>("Type")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Chats", "chats");
});
modelBuilder.Entity("Vortex.Modules.Chats.Domain.Message", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<Guid>("ChatId")
.HasColumnType("uuid");
b.Property<string>("Content")
.HasColumnType("text");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<bool>("IsDeleted")
.HasColumnType("boolean");
b.Property<bool>("IsEdited")
.HasColumnType("boolean");
b.Property<string>("Quote")
.HasColumnType("text");
b.Property<Guid?>("ReplyToId")
.HasColumnType("uuid");
b.Property<Guid>("SenderId")
.HasColumnType("uuid");
b.Property<string>("Type")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Messages", "chats");
});
modelBuilder.Entity("Vortex.Modules.Chats.Domain.Chat", b =>
{
b.OwnsMany("Vortex.Modules.Chats.Domain.ChatMember", "Members", b1 =>
{
b1.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b1.Property<Guid>("ChatId")
.HasColumnType("uuid");
b1.Property<bool>("IsMuted")
.HasColumnType("boolean");
b1.Property<DateTime>("JoinedAt")
.HasColumnType("timestamp with time zone");
b1.Property<string>("Role")
.IsRequired()
.HasColumnType("text");
b1.Property<Guid>("UserId")
.HasColumnType("uuid");
b1.HasKey("Id");
b1.HasIndex("ChatId", "UserId")
.IsUnique();
b1.ToTable("ChatMembers", "chats");
b1.WithOwner()
.HasForeignKey("ChatId");
});
b.Navigation("Members");
});
modelBuilder.Entity("Vortex.Modules.Chats.Domain.Message", b =>
{
b.OwnsMany("Vortex.Modules.Chats.Domain.Media", "Media", b1 =>
{
b1.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b1.Property<string>("Filename")
.HasColumnType("text");
b1.Property<Guid>("MessageId")
.HasColumnType("uuid");
b1.Property<long?>("Size")
.HasColumnType("bigint");
b1.Property<string>("Type")
.IsRequired()
.HasColumnType("text");
b1.Property<string>("Url")
.IsRequired()
.HasColumnType("text");
b1.HasKey("Id");
b1.HasIndex("MessageId");
b1.ToTable("MessageMedia", "chats");
b1.WithOwner()
.HasForeignKey("MessageId");
});
b.Navigation("Media");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,136 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Vortex.Modules.Chats.Infrastructure.Persistence.Migrations
{
/// <inheritdoc />
public partial class InitialChats : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.EnsureSchema(
name: "chats");
migrationBuilder.CreateTable(
name: "Chats",
schema: "chats",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
Type = table.Column<string>(type: "text", nullable: false),
Name = table.Column<string>(type: "text", nullable: true),
Avatar = table.Column<string>(type: "text", nullable: true),
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Chats", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Messages",
schema: "chats",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
ChatId = table.Column<Guid>(type: "uuid", nullable: false),
SenderId = table.Column<Guid>(type: "uuid", nullable: false),
Content = table.Column<string>(type: "text", nullable: true),
Type = table.Column<string>(type: "text", nullable: false),
ReplyToId = table.Column<Guid>(type: "uuid", nullable: true),
Quote = table.Column<string>(type: "text", nullable: true),
IsEdited = table.Column<bool>(type: "boolean", nullable: false),
IsDeleted = table.Column<bool>(type: "boolean", nullable: false),
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Messages", x => x.Id);
});
migrationBuilder.CreateTable(
name: "ChatMembers",
schema: "chats",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
ChatId = table.Column<Guid>(type: "uuid", nullable: false),
UserId = table.Column<Guid>(type: "uuid", nullable: false),
Role = table.Column<string>(type: "text", nullable: false),
JoinedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
IsMuted = table.Column<bool>(type: "boolean", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ChatMembers", x => x.Id);
table.ForeignKey(
name: "FK_ChatMembers_Chats_ChatId",
column: x => x.ChatId,
principalSchema: "chats",
principalTable: "Chats",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "MessageMedia",
schema: "chats",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
MessageId = table.Column<Guid>(type: "uuid", nullable: false),
Type = table.Column<string>(type: "text", nullable: false),
Url = table.Column<string>(type: "text", nullable: false),
Filename = table.Column<string>(type: "text", nullable: true),
Size = table.Column<long>(type: "bigint", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_MessageMedia", x => x.Id);
table.ForeignKey(
name: "FK_MessageMedia_Messages_MessageId",
column: x => x.MessageId,
principalSchema: "chats",
principalTable: "Messages",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_ChatMembers_ChatId_UserId",
schema: "chats",
table: "ChatMembers",
columns: new[] { "ChatId", "UserId" },
unique: true);
migrationBuilder.CreateIndex(
name: "IX_MessageMedia_MessageId",
schema: "chats",
table: "MessageMedia",
column: "MessageId");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "ChatMembers",
schema: "chats");
migrationBuilder.DropTable(
name: "MessageMedia",
schema: "chats");
migrationBuilder.DropTable(
name: "Chats",
schema: "chats");
migrationBuilder.DropTable(
name: "Messages",
schema: "chats");
}
}
}

View File

@@ -0,0 +1,207 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using Vortex.Modules.Chats.Infrastructure.Persistence;
#nullable disable
namespace Vortex.Modules.Chats.Infrastructure.Persistence.Migrations
{
[DbContext(typeof(ChatsDbContext))]
[Migration("20260311215929_UpdateChatModel")]
partial class UpdateChatModel
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasDefaultSchema("chats")
.HasAnnotation("ProductVersion", "10.0.4")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("Vortex.Modules.Chats.Domain.Chat", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("Avatar")
.HasColumnType("text");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("Name")
.HasColumnType("text");
b.Property<string>("Type")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Chats", "chats");
});
modelBuilder.Entity("Vortex.Modules.Chats.Domain.Message", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<Guid>("ChatId")
.HasColumnType("uuid");
b.Property<string>("Content")
.HasColumnType("text");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<bool>("IsDeleted")
.HasColumnType("boolean");
b.Property<bool>("IsEdited")
.HasColumnType("boolean");
b.Property<string>("Quote")
.HasColumnType("text");
b.Property<Guid?>("ReplyToId")
.HasColumnType("uuid");
b.Property<Guid>("SenderId")
.HasColumnType("uuid");
b.Property<string>("Type")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Messages", "chats");
});
modelBuilder.Entity("Vortex.Modules.Chats.Domain.ReadReceipt", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<Guid>("MessageId")
.HasColumnType("uuid");
b.Property<DateTime>("ReadAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid>("UserId")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("MessageId", "UserId")
.IsUnique();
b.ToTable("ReadReceipts", "chats");
});
modelBuilder.Entity("Vortex.Modules.Chats.Domain.Chat", b =>
{
b.OwnsMany("Vortex.Modules.Chats.Domain.ChatMember", "Members", b1 =>
{
b1.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b1.Property<Guid>("ChatId")
.HasColumnType("uuid");
b1.Property<bool>("IsMuted")
.HasColumnType("boolean");
b1.Property<DateTime>("JoinedAt")
.HasColumnType("timestamp with time zone");
b1.Property<string>("Role")
.IsRequired()
.HasColumnType("text");
b1.Property<Guid>("UserId")
.HasColumnType("uuid");
b1.HasKey("Id");
b1.HasIndex("ChatId", "UserId")
.IsUnique();
b1.ToTable("ChatMembers", "chats");
b1.WithOwner()
.HasForeignKey("ChatId");
});
b.Navigation("Members");
});
modelBuilder.Entity("Vortex.Modules.Chats.Domain.Message", b =>
{
b.OwnsMany("Vortex.Modules.Chats.Domain.Media", "Media", b1 =>
{
b1.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b1.Property<string>("Filename")
.HasColumnType("text");
b1.Property<Guid>("MessageId")
.HasColumnType("uuid");
b1.Property<long?>("Size")
.HasColumnType("bigint");
b1.Property<string>("Type")
.IsRequired()
.HasColumnType("text");
b1.Property<string>("Url")
.IsRequired()
.HasColumnType("text");
b1.HasKey("Id");
b1.HasIndex("MessageId");
b1.ToTable("MessageMedia", "chats");
b1.WithOwner()
.HasForeignKey("MessageId");
});
b.Navigation("Media");
});
modelBuilder.Entity("Vortex.Modules.Chats.Domain.ReadReceipt", b =>
{
b.HasOne("Vortex.Modules.Chats.Domain.Message", null)
.WithMany("ReadBy")
.HasForeignKey("MessageId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Vortex.Modules.Chats.Domain.Message", b =>
{
b.Navigation("ReadBy");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,52 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Vortex.Modules.Chats.Infrastructure.Persistence.Migrations
{
/// <inheritdoc />
public partial class UpdateChatModel : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "ReadReceipts",
schema: "chats",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
MessageId = table.Column<Guid>(type: "uuid", nullable: false),
UserId = table.Column<Guid>(type: "uuid", nullable: false),
ReadAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ReadReceipts", x => x.Id);
table.ForeignKey(
name: "FK_ReadReceipts_Messages_MessageId",
column: x => x.MessageId,
principalSchema: "chats",
principalTable: "Messages",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_ReadReceipts_MessageId_UserId",
schema: "chats",
table: "ReadReceipts",
columns: new[] { "MessageId", "UserId" },
unique: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "ReadReceipts",
schema: "chats");
}
}
}

View File

@@ -0,0 +1,204 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using Vortex.Modules.Chats.Infrastructure.Persistence;
#nullable disable
namespace Vortex.Modules.Chats.Infrastructure.Persistence.Migrations
{
[DbContext(typeof(ChatsDbContext))]
partial class ChatsDbContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasDefaultSchema("chats")
.HasAnnotation("ProductVersion", "10.0.4")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("Vortex.Modules.Chats.Domain.Chat", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("Avatar")
.HasColumnType("text");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("Name")
.HasColumnType("text");
b.Property<string>("Type")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Chats", "chats");
});
modelBuilder.Entity("Vortex.Modules.Chats.Domain.Message", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<Guid>("ChatId")
.HasColumnType("uuid");
b.Property<string>("Content")
.HasColumnType("text");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<bool>("IsDeleted")
.HasColumnType("boolean");
b.Property<bool>("IsEdited")
.HasColumnType("boolean");
b.Property<string>("Quote")
.HasColumnType("text");
b.Property<Guid?>("ReplyToId")
.HasColumnType("uuid");
b.Property<Guid>("SenderId")
.HasColumnType("uuid");
b.Property<string>("Type")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Messages", "chats");
});
modelBuilder.Entity("Vortex.Modules.Chats.Domain.ReadReceipt", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<Guid>("MessageId")
.HasColumnType("uuid");
b.Property<DateTime>("ReadAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid>("UserId")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("MessageId", "UserId")
.IsUnique();
b.ToTable("ReadReceipts", "chats");
});
modelBuilder.Entity("Vortex.Modules.Chats.Domain.Chat", b =>
{
b.OwnsMany("Vortex.Modules.Chats.Domain.ChatMember", "Members", b1 =>
{
b1.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b1.Property<Guid>("ChatId")
.HasColumnType("uuid");
b1.Property<bool>("IsMuted")
.HasColumnType("boolean");
b1.Property<DateTime>("JoinedAt")
.HasColumnType("timestamp with time zone");
b1.Property<string>("Role")
.IsRequired()
.HasColumnType("text");
b1.Property<Guid>("UserId")
.HasColumnType("uuid");
b1.HasKey("Id");
b1.HasIndex("ChatId", "UserId")
.IsUnique();
b1.ToTable("ChatMembers", "chats");
b1.WithOwner()
.HasForeignKey("ChatId");
});
b.Navigation("Members");
});
modelBuilder.Entity("Vortex.Modules.Chats.Domain.Message", b =>
{
b.OwnsMany("Vortex.Modules.Chats.Domain.Media", "Media", b1 =>
{
b1.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b1.Property<string>("Filename")
.HasColumnType("text");
b1.Property<Guid>("MessageId")
.HasColumnType("uuid");
b1.Property<long?>("Size")
.HasColumnType("bigint");
b1.Property<string>("Type")
.IsRequired()
.HasColumnType("text");
b1.Property<string>("Url")
.IsRequired()
.HasColumnType("text");
b1.HasKey("Id");
b1.HasIndex("MessageId");
b1.ToTable("MessageMedia", "chats");
b1.WithOwner()
.HasForeignKey("MessageId");
});
b.Navigation("Media");
});
modelBuilder.Entity("Vortex.Modules.Chats.Domain.ReadReceipt", b =>
{
b.HasOne("Vortex.Modules.Chats.Domain.Message", null)
.WithMany("ReadBy")
.HasForeignKey("MessageId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Vortex.Modules.Chats.Domain.Message", b =>
{
b.Navigation("ReadBy");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,252 @@
using Microsoft.AspNetCore.SignalR;
using MediatR;
using Vortex.Modules.Chats.Application.Messages.Send;
using Vortex.Modules.Chats.Domain;
using Vortex.Shared.Kernel;
using Microsoft.AspNetCore.Authorization;
using System.Collections.Concurrent;
using System.Security.Claims;
namespace Vortex.Modules.Chats.Infrastructure.SignalR;
/// <summary>
/// Хаб SignalR для обработки сообщений и WebRTC сигналинга в реальном времени.
/// </summary>
[Authorize]
public sealed class ChatHub : Hub
{
// Маппинг userId → список connectionId
private static readonly ConcurrentDictionary<string, HashSet<string>> _userConnections = new();
private readonly ISender _sender;
private readonly IUserContext _userContext;
private readonly IChatRepository _chatRepository;
public ChatHub(ISender sender, IUserContext userContext, IChatRepository chatRepository)
{
_sender = sender;
_userContext = userContext;
_chatRepository = chatRepository;
}
public override async Task OnConnectedAsync()
{
if (_userContext.IsAuthenticated)
{
var userId = _userContext.UserId.ToString();
_userConnections.AddOrUpdate(
userId,
_ => new HashSet<string> { Context.ConnectionId },
(_, set) => { lock (set) { set.Add(Context.ConnectionId); } return set; }
);
var userChats = await _chatRepository.GetUserChatsAsync(_userContext.UserId, Context.ConnectionAborted);
foreach (var chat in userChats)
{
await Groups.AddToGroupAsync(Context.ConnectionId, chat.Id.ToString());
}
await Clients.Others.SendAsync("user_online", new { userId });
}
await base.OnConnectedAsync();
}
public override async Task OnDisconnectedAsync(Exception? exception)
{
if (_userContext.IsAuthenticated)
{
var userId = _userContext.UserId.ToString();
if (_userConnections.TryGetValue(userId, out var set))
{
lock (set) { set.Remove(Context.ConnectionId); }
if (set.Count == 0)
{
_userConnections.TryRemove(userId, out _);
await Clients.Others.SendAsync("user_offline", new { userId, lastSeen = DateTime.UtcNow });
}
}
}
await base.OnDisconnectedAsync(exception);
}
// ────────────────────────────────────────────────────────────────
// Chat methods
// ────────────────────────────────────────────────────────────────
[HubMethodName("send_message")]
public async Task SendMessage(SendMessageHubRequest request)
{
var command = new SendMessageCommand(
request.ChatId,
_userContext.UserId,
request.Content,
request.Type,
request.MediaUrl,
request.MediaType,
request.FileName,
request.FileSize);
await _sender.Send(command);
}
[HubMethodName("read_messages")]
public async Task ReadMessages(ReadMessagesRequest request)
{
if (request.MessageIds != null && request.MessageIds.Any())
{
var parsedIds = request.MessageIds
.Select(id => Guid.TryParse(id, out var parsed) ? parsed : Guid.Empty)
.Where(id => id != Guid.Empty)
.ToList();
if (parsedIds.Any())
{
var command = new Vortex.Modules.Chats.Application.Messages.Read.ReadMessagesCommand(
request.ChatId, _userContext.UserId, parsedIds);
await _sender.Send(command);
}
}
await Clients.Group(request.ChatId.ToString()).SendAsync("messages_read", new
{
ChatId = request.ChatId.ToString(),
UserId = _userContext.UserId,
MessageIds = request.MessageIds ?? new List<string>()
});
}
[HubMethodName("typing_start")]
public async Task TypingStart(string chatId)
{
await Clients.Group(chatId).SendAsync("user_typing", new { ChatId = chatId, UserId = _userContext.UserId });
}
[HubMethodName("typing_stop")]
public async Task TypingStop(string chatId)
{
await Clients.Group(chatId).SendAsync("user_stopped_typing", new { ChatId = chatId, UserId = _userContext.UserId });
}
// ────────────────────────────────────────────────────────────────
// WebRTC signaling
// ────────────────────────────────────────────────────────────────
private async Task SendToUserAsync(string targetUserId, string method, object payload)
{
if (_userConnections.TryGetValue(targetUserId, out var connectionIds))
{
string[] ids;
lock (connectionIds) { ids = connectionIds.ToArray(); }
foreach (var connId in ids)
{
await Clients.Client(connId).SendAsync(method, payload);
}
}
}
[HubMethodName("call_offer")]
public async Task CallOffer(CallOfferRequest request)
{
// Try to get caller info from current user's claims
var displayName = Context.User?.FindFirstValue("name") ?? Context.User?.FindFirstValue(ClaimTypes.Name) ?? "User";
var avatar = Context.User?.FindFirstValue("avatar");
var username = Context.User?.FindFirstValue("unique_name") ?? Context.User?.Identity?.Name;
await SendToUserAsync(request.TargetUserId, "call_incoming", new
{
from = _userContext.UserId.ToString(),
offer = request.Offer,
callType = request.CallType,
chatId = request.ChatId,
callerInfo = new
{
id = _userContext.UserId.ToString(),
displayName = displayName,
avatar = avatar,
username = username
}
});
}
[HubMethodName("call_answer")]
public async Task CallAnswer(CallAnswerRequest request)
{
await SendToUserAsync(request.TargetUserId, "call_answered", new
{
from = _userContext.UserId.ToString(),
answer = request.Answer,
});
}
[HubMethodName("call_decline")]
public async Task CallDecline(TargetUserRequest request)
{
await SendToUserAsync(request.TargetUserId, "call_declined", new
{
from = _userContext.UserId.ToString(),
});
}
[HubMethodName("call_end")]
public async Task CallEnd(TargetUserRequest request)
{
await SendToUserAsync(request.TargetUserId, "call_ended", new
{
from = _userContext.UserId.ToString(),
});
}
[HubMethodName("ice_candidate")]
public async Task IceCandidate(IceCandidateRequest request)
{
await SendToUserAsync(request.TargetUserId, "ice_candidate", new
{
from = _userContext.UserId.ToString(),
candidate = request.Candidate,
});
}
[HubMethodName("renegotiate")]
public async Task Renegotiate(RenegotiateRequest request)
{
await SendToUserAsync(request.TargetUserId, "renegotiate", new
{
from = _userContext.UserId.ToString(),
offer = request.Offer,
});
}
[HubMethodName("renegotiate_answer")]
public async Task RenegotiateAnswer(RenegotiateAnswerRequest request)
{
await SendToUserAsync(request.TargetUserId, "renegotiate_answer", new
{
from = _userContext.UserId.ToString(),
answer = request.Answer,
});
}
[HubMethodName("call_type_changed")]
public async Task CallTypeChanged(CallTypeChangedRequest request)
{
await SendToUserAsync(request.TargetUserId, "call_type_changed", new
{
from = _userContext.UserId.ToString(),
callType = request.CallType,
});
}
// ────────────────────────────────────────────────────────────────
// Records
// ────────────────────────────────────────────────────────────────
public record SendMessageHubRequest(Guid ChatId, string? Content, string Type, string? MediaUrl, string? MediaType, string? FileName, long? FileSize);
public record ReadMessagesRequest(Guid ChatId, List<string>? MessageIds);
public record CallOfferRequest(string TargetUserId, object Offer, string CallType, string? ChatId);
public record CallAnswerRequest(string TargetUserId, object Answer);
public record TargetUserRequest(string TargetUserId);
public record IceCandidateRequest(string TargetUserId, object Candidate);
public record RenegotiateRequest(string TargetUserId, object Offer);
public record RenegotiateAnswerRequest(string TargetUserId, object Answer);
public record CallTypeChangedRequest(string TargetUserId, string CallType);
}

View File

@@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\..\Shared\Vortex.Shared.Kernel\Vortex.Shared.Kernel.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="MediatR" Version="12.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="10.0.4" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="10.0.4" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.4" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="10.0.0" />
</ItemGroup>
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,338 @@
{
"runtimeTarget": {
"name": ".NETCoreApp,Version=v10.0",
"signature": ""
},
"compilationOptions": {},
"targets": {
".NETCoreApp,Version=v10.0": {
"Vortex.Modules.Chats/1.0.0": {
"dependencies": {
"MediatR": "12.0.1",
"Microsoft.EntityFrameworkCore": "10.0.4",
"Microsoft.EntityFrameworkCore.Relational": "10.0.4",
"Microsoft.Extensions.Configuration.Abstractions": "10.0.4",
"Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.4",
"Npgsql.EntityFrameworkCore.PostgreSQL": "10.0.0",
"Vortex.Shared.Kernel": "1.0.0"
},
"runtime": {
"Vortex.Modules.Chats.dll": {}
}
},
"MediatR/12.0.1": {
"dependencies": {
"MediatR.Contracts": "2.0.1"
},
"runtime": {
"lib/net6.0/MediatR.dll": {
"assemblyVersion": "12.0.0.0",
"fileVersion": "12.0.1.0"
}
}
},
"MediatR.Contracts/2.0.1": {
"runtime": {
"lib/netstandard2.0/MediatR.Contracts.dll": {
"assemblyVersion": "2.0.1.0",
"fileVersion": "2.0.1.0"
}
}
},
"Microsoft.EntityFrameworkCore/10.0.4": {
"dependencies": {
"Microsoft.EntityFrameworkCore.Abstractions": "10.0.4",
"Microsoft.Extensions.Caching.Memory": "10.0.4",
"Microsoft.Extensions.Logging": "10.0.4"
},
"runtime": {
"lib/net10.0/Microsoft.EntityFrameworkCore.dll": {
"assemblyVersion": "10.0.4.0",
"fileVersion": "10.0.426.12010"
}
}
},
"Microsoft.EntityFrameworkCore.Abstractions/10.0.4": {
"runtime": {
"lib/net10.0/Microsoft.EntityFrameworkCore.Abstractions.dll": {
"assemblyVersion": "10.0.4.0",
"fileVersion": "10.0.426.12010"
}
}
},
"Microsoft.EntityFrameworkCore.Relational/10.0.4": {
"dependencies": {
"Microsoft.EntityFrameworkCore": "10.0.4",
"Microsoft.Extensions.Caching.Memory": "10.0.4",
"Microsoft.Extensions.Configuration.Abstractions": "10.0.4",
"Microsoft.Extensions.Logging": "10.0.4"
},
"runtime": {
"lib/net10.0/Microsoft.EntityFrameworkCore.Relational.dll": {
"assemblyVersion": "10.0.4.0",
"fileVersion": "10.0.426.12010"
}
}
},
"Microsoft.Extensions.Caching.Abstractions/10.0.4": {
"dependencies": {
"Microsoft.Extensions.Primitives": "10.0.4"
},
"runtime": {
"lib/net10.0/Microsoft.Extensions.Caching.Abstractions.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.426.12010"
}
}
},
"Microsoft.Extensions.Caching.Memory/10.0.4": {
"dependencies": {
"Microsoft.Extensions.Caching.Abstractions": "10.0.4",
"Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.4",
"Microsoft.Extensions.Logging.Abstractions": "10.0.4",
"Microsoft.Extensions.Options": "10.0.4",
"Microsoft.Extensions.Primitives": "10.0.4"
},
"runtime": {
"lib/net10.0/Microsoft.Extensions.Caching.Memory.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.426.12010"
}
}
},
"Microsoft.Extensions.Configuration.Abstractions/10.0.4": {
"dependencies": {
"Microsoft.Extensions.Primitives": "10.0.4"
},
"runtime": {
"lib/net10.0/Microsoft.Extensions.Configuration.Abstractions.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.426.12010"
}
}
},
"Microsoft.Extensions.DependencyInjection/10.0.4": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.4"
},
"runtime": {
"lib/net10.0/Microsoft.Extensions.DependencyInjection.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.426.12010"
}
}
},
"Microsoft.Extensions.DependencyInjection.Abstractions/10.0.4": {
"runtime": {
"lib/net10.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.426.12010"
}
}
},
"Microsoft.Extensions.Logging/10.0.4": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "10.0.4",
"Microsoft.Extensions.Logging.Abstractions": "10.0.4",
"Microsoft.Extensions.Options": "10.0.4"
},
"runtime": {
"lib/net10.0/Microsoft.Extensions.Logging.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.426.12010"
}
}
},
"Microsoft.Extensions.Logging.Abstractions/10.0.4": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.4"
},
"runtime": {
"lib/net10.0/Microsoft.Extensions.Logging.Abstractions.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.426.12010"
}
}
},
"Microsoft.Extensions.Options/10.0.4": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.4",
"Microsoft.Extensions.Primitives": "10.0.4"
},
"runtime": {
"lib/net10.0/Microsoft.Extensions.Options.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.426.12010"
}
}
},
"Microsoft.Extensions.Primitives/10.0.4": {
"runtime": {
"lib/net10.0/Microsoft.Extensions.Primitives.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.426.12010"
}
}
},
"Npgsql/10.0.0": {
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "10.0.4"
},
"runtime": {
"lib/net10.0/Npgsql.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.0.0"
}
}
},
"Npgsql.EntityFrameworkCore.PostgreSQL/10.0.0": {
"dependencies": {
"Microsoft.EntityFrameworkCore": "10.0.4",
"Microsoft.EntityFrameworkCore.Relational": "10.0.4",
"Npgsql": "10.0.0"
},
"runtime": {
"lib/net10.0/Npgsql.EntityFrameworkCore.PostgreSQL.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.0.0"
}
}
},
"Vortex.Shared.Kernel/1.0.0": {
"dependencies": {
"MediatR": "12.0.1"
},
"runtime": {
"Vortex.Shared.Kernel.dll": {
"assemblyVersion": "1.0.0.0",
"fileVersion": "1.0.0.0"
}
}
}
}
},
"libraries": {
"Vortex.Modules.Chats/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"MediatR/12.0.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-vfxplMielft+g5jxGO31xjjQpI6yqe4r2YGt0Q8x23phwbpJNmUQGY+cCNNFMKKViXRM67ajUlAiwirMeuJWTQ==",
"path": "mediatr/12.0.1",
"hashPath": "mediatr.12.0.1.nupkg.sha512"
},
"MediatR.Contracts/2.0.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-FYv95bNT4UwcNA+G/J1oX5OpRiSUxteXaUt2BJbRSdRNiIUNbggJF69wy6mnk2wYToaanpdXZdCwVylt96MpwQ==",
"path": "mediatr.contracts/2.0.1",
"hashPath": "mediatr.contracts.2.0.1.nupkg.sha512"
},
"Microsoft.EntityFrameworkCore/10.0.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-kzTsfFK2GCytp6DDTfQOmxPU4gbGdrIlP7PxrxF3ESNLtfXrC8BoUVZENBN2WORlZPAD7CVX6AYIglgkpXQooA==",
"path": "microsoft.entityframeworkcore/10.0.4",
"hashPath": "microsoft.entityframeworkcore.10.0.4.nupkg.sha512"
},
"Microsoft.EntityFrameworkCore.Abstractions/10.0.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-qDcJqCfN1XYyX0ID/Hd9/kQTRvlia8S+Yuwyl9uFhBIKnOCbl9WMdGQCzbZUKbkpkfvf3P9CDdXsnxHyE3O0Aw==",
"path": "microsoft.entityframeworkcore.abstractions/10.0.4",
"hashPath": "microsoft.entityframeworkcore.abstractions.10.0.4.nupkg.sha512"
},
"Microsoft.EntityFrameworkCore.Relational/10.0.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-DOTjTHy93W3TwpMLM4SCm0n57Sc0Jj3+m2S6LSTstKyBB34eT1UouaMS19mpWwvtj42+sRiEjA3+rOTNoNzXFQ==",
"path": "microsoft.entityframeworkcore.relational/10.0.4",
"hashPath": "microsoft.entityframeworkcore.relational.10.0.4.nupkg.sha512"
},
"Microsoft.Extensions.Caching.Abstractions/10.0.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-uDRooaV6N3WZ0kdlNPMB68/MdGn/in1Fs7Db7DnIm85RBTPy4P321WO+daAImiYpH5dekjNggDqy1N44WaIlMA==",
"path": "microsoft.extensions.caching.abstractions/10.0.4",
"hashPath": "microsoft.extensions.caching.abstractions.10.0.4.nupkg.sha512"
},
"Microsoft.Extensions.Caching.Memory/10.0.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-CLLussNUMdSbyJOu4VBF7sqskHGB/5N1EcFzrqG/HsPATN8fCRUcfp0qns1VwkxKHwxrtYCh5FKe+kM81Q1PHA==",
"path": "microsoft.extensions.caching.memory/10.0.4",
"hashPath": "microsoft.extensions.caching.memory.10.0.4.nupkg.sha512"
},
"Microsoft.Extensions.Configuration.Abstractions/10.0.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-3x9X9SMAMdAoEwWxHfsT2a9dTBqEtfYfbEOFw+UPtBshEH2gHWJeazxrZ1FK1O18MoCbe1NxINg5qciB01pEcg==",
"path": "microsoft.extensions.configuration.abstractions/10.0.4",
"hashPath": "microsoft.extensions.configuration.abstractions.10.0.4.nupkg.sha512"
},
"Microsoft.Extensions.DependencyInjection/10.0.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-NkvJ8aSr3AG30yabjv7ZWwTG/wq5OElNTlNq39Ok2HSEF3TIwAc1f1xnTJlR/GuoJmEgkfT7WBO9YbSXRk41+g==",
"path": "microsoft.extensions.dependencyinjection/10.0.4",
"hashPath": "microsoft.extensions.dependencyinjection.10.0.4.nupkg.sha512"
},
"Microsoft.Extensions.DependencyInjection.Abstractions/10.0.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-SIe9zlVQJecnk/DTmevIcl6+aEDYhoVLc2eG2AKwVeNEC8CSyxHAbh4lf0xtHq9JUum0vVTEByGNTK+b6oihTQ==",
"path": "microsoft.extensions.dependencyinjection.abstractions/10.0.4",
"hashPath": "microsoft.extensions.dependencyinjection.abstractions.10.0.4.nupkg.sha512"
},
"Microsoft.Extensions.Logging/10.0.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-S8+6fCuMOhJZGk8sGFtOy3VsF9mk9x4UOL59GM91REiA/fmCDjunKKIw4RmStG87qyXPfxelDJf2pXIbTuaBdw==",
"path": "microsoft.extensions.logging/10.0.4",
"hashPath": "microsoft.extensions.logging.10.0.4.nupkg.sha512"
},
"Microsoft.Extensions.Logging.Abstractions/10.0.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-PDMMt7fvBatv6hcxxyJtXIzSwn7Dy00W6I2vDAOTYrQqNM2dF5A2L9n0uMzdPz2IPoNZWkAmYjoOCEdDLq0i4w==",
"path": "microsoft.extensions.logging.abstractions/10.0.4",
"hashPath": "microsoft.extensions.logging.abstractions.10.0.4.nupkg.sha512"
},
"Microsoft.Extensions.Options/10.0.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-kRxa2Zjzhg/ohh7EklpqQpBIcyQnC3meWxCcpZBn+0QWy/fY1DmDd45JiW8Vyrpj2J1RDtau5yRHiLZS/AoxUw==",
"path": "microsoft.extensions.options/10.0.4",
"hashPath": "microsoft.extensions.options.10.0.4.nupkg.sha512"
},
"Microsoft.Extensions.Primitives/10.0.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-lABYqiRH9HgYJsjzO3W7+cucUwWXhEkiyrRylANdIubnzcESlkIsLowXpQ4E+sc7kjMLbk1hk5oxw4qTKowTEg==",
"path": "microsoft.extensions.primitives/10.0.4",
"hashPath": "microsoft.extensions.primitives.10.0.4.nupkg.sha512"
},
"Npgsql/10.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-xZAYhPOU2rUIFpV48xsqhCx9vXs6Y+0jX2LCoSEfDFYMw9jtAOUk3iQsCnDLrFIv9NT3JGMihn7nnuZsPKqJmA==",
"path": "npgsql/10.0.0",
"hashPath": "npgsql.10.0.0.nupkg.sha512"
},
"Npgsql.EntityFrameworkCore.PostgreSQL/10.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-E2+uSWxSB8LdsUVwPaqRWOcGOP92biry2JEwc0KJMdLJF+aZdczeIdEXVwEyv4nSVMQJH0o8tLhyAMiR6VF0lw==",
"path": "npgsql.entityframeworkcore.postgresql/10.0.0",
"hashPath": "npgsql.entityframeworkcore.postgresql.10.0.0.nupkg.sha512"
},
"Vortex.Shared.Kernel/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
}
}
}

View File

@@ -0,0 +1,4 @@
// <autogenerated />
using System;
using System.Reflection;
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v10.0", FrameworkDisplayName = ".NET 10.0")]

View File

@@ -0,0 +1,22 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("Vortex.Modules.Chats")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+50d4d75c04b5524c8439d9168f3a5a578f26d47c")]
[assembly: System.Reflection.AssemblyProductAttribute("Vortex.Modules.Chats")]
[assembly: System.Reflection.AssemblyTitleAttribute("Vortex.Modules.Chats")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
// Создано классом WriteCodeFragment MSBuild.

View File

@@ -0,0 +1 @@
7ea02b337752b6c3ee9972270dd51a0230d3bf7881178b777a5efe217aceafb1

View File

@@ -0,0 +1,17 @@
is_global = true
build_property.TargetFramework = net10.0
build_property.TargetFrameworkIdentifier = .NETCoreApp
build_property.TargetFrameworkVersion = v10.0
build_property.TargetPlatformMinVersion =
build_property.UsingMicrosoftNETSdkWeb =
build_property.ProjectTypeGuids =
build_property.InvariantGlobalization =
build_property.PlatformNeutralAssembly =
build_property.EnforceExtendedAnalyzerRules =
build_property._SupportedPlatformList = Linux,macOS,Windows
build_property.RootNamespace = Vortex.Modules.Chats
build_property.ProjectDir = E:\GIT\forkmessager\apps\server-net\src\Modules\Chats\
build_property.EnableComHosting =
build_property.EnableGeneratedComInterfaceComImportInterop =
build_property.EffectiveAnalysisLevelStyle = 10.0
build_property.EnableCodeStyleSeverity =

View File

@@ -0,0 +1,8 @@
// <auto-generated/>
global using System;
global using System.Collections.Generic;
global using System.IO;
global using System.Linq;
global using System.Net.Http;
global using System.Threading;
global using System.Threading.Tasks;

View File

@@ -0,0 +1 @@
c39010166c2f8abf3397d023e78ad2aa480bef5668aa8c99f0daac981b2cf801

View File

@@ -0,0 +1,15 @@
E:\GIT\forkmessager\apps\server-net\src\Modules\Chats\obj\Debug\net10.0\Vortex.Modules.Chats.csproj.AssemblyReference.cache
E:\GIT\forkmessager\apps\server-net\src\Modules\Chats\obj\Debug\net10.0\Vortex.Modules.Chats.GeneratedMSBuildEditorConfig.editorconfig
E:\GIT\forkmessager\apps\server-net\src\Modules\Chats\obj\Debug\net10.0\Vortex.Modules.Chats.AssemblyInfoInputs.cache
E:\GIT\forkmessager\apps\server-net\src\Modules\Chats\obj\Debug\net10.0\Vortex.Modules.Chats.AssemblyInfo.cs
E:\GIT\forkmessager\apps\server-net\src\Modules\Chats\obj\Debug\net10.0\Vortex.Modules.Chats.csproj.CoreCompileInputs.cache
E:\GIT\forkmessager\apps\server-net\src\Modules\Chats\bin\Debug\net10.0\Vortex.Modules.Chats.deps.json
E:\GIT\forkmessager\apps\server-net\src\Modules\Chats\bin\Debug\net10.0\Vortex.Modules.Chats.dll
E:\GIT\forkmessager\apps\server-net\src\Modules\Chats\bin\Debug\net10.0\Vortex.Modules.Chats.pdb
E:\GIT\forkmessager\apps\server-net\src\Modules\Chats\bin\Debug\net10.0\Vortex.Shared.Kernel.dll
E:\GIT\forkmessager\apps\server-net\src\Modules\Chats\bin\Debug\net10.0\Vortex.Shared.Kernel.pdb
E:\GIT\forkmessager\apps\server-net\src\Modules\Chats\obj\Debug\net10.0\Vortex.M.639B64A4.Up2Date
E:\GIT\forkmessager\apps\server-net\src\Modules\Chats\obj\Debug\net10.0\Vortex.Modules.Chats.dll
E:\GIT\forkmessager\apps\server-net\src\Modules\Chats\obj\Debug\net10.0\refint\Vortex.Modules.Chats.dll
E:\GIT\forkmessager\apps\server-net\src\Modules\Chats\obj\Debug\net10.0\Vortex.Modules.Chats.pdb
E:\GIT\forkmessager\apps\server-net\src\Modules\Chats\obj\Debug\net10.0\ref\Vortex.Modules.Chats.dll

View File

@@ -0,0 +1,4 @@
// <autogenerated />
using System;
using System.Reflection;
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v10.0", FrameworkDisplayName = ".NET 10.0")]

View File

@@ -0,0 +1,22 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("Vortex.Modules.Chats")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Release")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+50d4d75c04b5524c8439d9168f3a5a578f26d47c")]
[assembly: System.Reflection.AssemblyProductAttribute("Vortex.Modules.Chats")]
[assembly: System.Reflection.AssemblyTitleAttribute("Vortex.Modules.Chats")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
// Создано классом WriteCodeFragment MSBuild.

View File

@@ -0,0 +1 @@
502c80adbbed16d300408e4f330e018209bcd47b2fbedfbab86312811987ae88

View File

@@ -0,0 +1,17 @@
is_global = true
build_property.TargetFramework = net10.0
build_property.TargetFrameworkIdentifier = .NETCoreApp
build_property.TargetFrameworkVersion = v10.0
build_property.TargetPlatformMinVersion =
build_property.UsingMicrosoftNETSdkWeb =
build_property.ProjectTypeGuids =
build_property.InvariantGlobalization =
build_property.PlatformNeutralAssembly =
build_property.EnforceExtendedAnalyzerRules =
build_property._SupportedPlatformList = Linux,macOS,Windows
build_property.RootNamespace = Vortex.Modules.Chats
build_property.ProjectDir = E:\GIT\forkmessager\apps\server-net\src\Modules\Chats\
build_property.EnableComHosting =
build_property.EnableGeneratedComInterfaceComImportInterop =
build_property.EffectiveAnalysisLevelStyle = 10.0
build_property.EnableCodeStyleSeverity =

View File

@@ -0,0 +1,8 @@
// <auto-generated/>
global using System;
global using System.Collections.Generic;
global using System.IO;
global using System.Linq;
global using System.Net.Http;
global using System.Threading;
global using System.Threading.Tasks;

View File

@@ -0,0 +1 @@
6bc2815f955344103df2c21eeb6c589717e719c8f8f4f966b83b146f84113a5b

View File

@@ -0,0 +1,5 @@
E:\GIT\forkmessager\apps\server-net\src\Modules\Chats\obj\Release\net10.0\Vortex.Modules.Chats.csproj.AssemblyReference.cache
E:\GIT\forkmessager\apps\server-net\src\Modules\Chats\obj\Release\net10.0\Vortex.Modules.Chats.GeneratedMSBuildEditorConfig.editorconfig
E:\GIT\forkmessager\apps\server-net\src\Modules\Chats\obj\Release\net10.0\Vortex.Modules.Chats.AssemblyInfoInputs.cache
E:\GIT\forkmessager\apps\server-net\src\Modules\Chats\obj\Release\net10.0\Vortex.Modules.Chats.AssemblyInfo.cs
E:\GIT\forkmessager\apps\server-net\src\Modules\Chats\obj\Release\net10.0\Vortex.Modules.Chats.csproj.CoreCompileInputs.cache

View File

@@ -0,0 +1,867 @@
{
"format": 1,
"restore": {
"E:\\GIT\\forkmessager\\apps\\server-net\\src\\Modules\\Chats\\Vortex.Modules.Chats.csproj": {}
},
"projects": {
"E:\\GIT\\forkmessager\\apps\\server-net\\src\\Modules\\Chats\\Vortex.Modules.Chats.csproj": {
"version": "1.0.0",
"restore": {
"projectUniqueName": "E:\\GIT\\forkmessager\\apps\\server-net\\src\\Modules\\Chats\\Vortex.Modules.Chats.csproj",
"projectName": "Vortex.Modules.Chats",
"projectPath": "E:\\GIT\\forkmessager\\apps\\server-net\\src\\Modules\\Chats\\Vortex.Modules.Chats.csproj",
"packagesPath": "C:\\Users\\HomePC\\.nuget\\packages\\",
"outputPath": "E:\\GIT\\forkmessager\\apps\\server-net\\src\\Modules\\Chats\\obj\\",
"projectStyle": "PackageReference",
"fallbackFolders": [
"C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages"
],
"configFilePaths": [
"C:\\Users\\HomePC\\AppData\\Roaming\\NuGet\\NuGet.Config",
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config",
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config"
],
"originalTargetFrameworks": [
"net10.0"
],
"sources": {
"C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {},
"C:\\Program Files\\dotnet\\library-packs": {},
"https://api.nuget.org/v3/index.json": {}
},
"frameworks": {
"net10.0": {
"targetAlias": "net10.0",
"projectReferences": {
"E:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj": {
"projectPath": "E:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj"
}
}
}
},
"warningProperties": {
"warnAsError": [
"NU1605"
]
},
"restoreAuditProperties": {
"enableAudit": "true",
"auditLevel": "low",
"auditMode": "all"
},
"SdkAnalysisLevel": "10.0.100"
},
"frameworks": {
"net10.0": {
"targetAlias": "net10.0",
"dependencies": {
"MediatR": {
"target": "Package",
"version": "[12.0.1, )"
},
"Microsoft.EntityFrameworkCore": {
"target": "Package",
"version": "[10.0.4, )"
},
"Microsoft.EntityFrameworkCore.Relational": {
"target": "Package",
"version": "[10.0.4, )"
},
"Microsoft.Extensions.Configuration.Abstractions": {
"target": "Package",
"version": "[10.0.4, )"
},
"Microsoft.Extensions.DependencyInjection.Abstractions": {
"target": "Package",
"version": "[10.0.4, )"
},
"Npgsql.EntityFrameworkCore.PostgreSQL": {
"target": "Package",
"version": "[10.0.0, )"
}
},
"imports": [
"net461",
"net462",
"net47",
"net471",
"net472",
"net48",
"net481"
],
"assetTargetFallback": true,
"warn": true,
"frameworkReferences": {
"Microsoft.AspNetCore.App": {
"privateAssets": "none"
},
"Microsoft.NETCore.App": {
"privateAssets": "all"
}
},
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\10.0.100-preview.6.25358.103/PortableRuntimeIdentifierGraph.json",
"packagesToPrune": {
"Microsoft.AspNetCore": "(,10.0.32767]",
"Microsoft.AspNetCore.Antiforgery": "(,10.0.32767]",
"Microsoft.AspNetCore.App": "(,10.0.32767]",
"Microsoft.AspNetCore.Authentication": "(,10.0.32767]",
"Microsoft.AspNetCore.Authentication.Abstractions": "(,10.0.32767]",
"Microsoft.AspNetCore.Authentication.BearerToken": "(,10.0.32767]",
"Microsoft.AspNetCore.Authentication.Cookies": "(,10.0.32767]",
"Microsoft.AspNetCore.Authentication.Core": "(,10.0.32767]",
"Microsoft.AspNetCore.Authentication.OAuth": "(,10.0.32767]",
"Microsoft.AspNetCore.Authorization": "(,10.0.32767]",
"Microsoft.AspNetCore.Authorization.Policy": "(,10.0.32767]",
"Microsoft.AspNetCore.Components": "(,10.0.32767]",
"Microsoft.AspNetCore.Components.Authorization": "(,10.0.32767]",
"Microsoft.AspNetCore.Components.Endpoints": "(,10.0.32767]",
"Microsoft.AspNetCore.Components.Forms": "(,10.0.32767]",
"Microsoft.AspNetCore.Components.Server": "(,10.0.32767]",
"Microsoft.AspNetCore.Components.Web": "(,10.0.32767]",
"Microsoft.AspNetCore.Connections.Abstractions": "(,10.0.32767]",
"Microsoft.AspNetCore.CookiePolicy": "(,10.0.32767]",
"Microsoft.AspNetCore.Cors": "(,10.0.32767]",
"Microsoft.AspNetCore.Cryptography.Internal": "(,10.0.32767]",
"Microsoft.AspNetCore.Cryptography.KeyDerivation": "(,10.0.32767]",
"Microsoft.AspNetCore.DataProtection": "(,10.0.32767]",
"Microsoft.AspNetCore.DataProtection.Abstractions": "(,10.0.32767]",
"Microsoft.AspNetCore.DataProtection.Extensions": "(,10.0.32767]",
"Microsoft.AspNetCore.Diagnostics": "(,10.0.32767]",
"Microsoft.AspNetCore.Diagnostics.Abstractions": "(,10.0.32767]",
"Microsoft.AspNetCore.Diagnostics.HealthChecks": "(,10.0.32767]",
"Microsoft.AspNetCore.HostFiltering": "(,10.0.32767]",
"Microsoft.AspNetCore.Hosting": "(,10.0.32767]",
"Microsoft.AspNetCore.Hosting.Abstractions": "(,10.0.32767]",
"Microsoft.AspNetCore.Hosting.Server.Abstractions": "(,10.0.32767]",
"Microsoft.AspNetCore.Html.Abstractions": "(,10.0.32767]",
"Microsoft.AspNetCore.Http": "(,10.0.32767]",
"Microsoft.AspNetCore.Http.Abstractions": "(,10.0.32767]",
"Microsoft.AspNetCore.Http.Connections": "(,10.0.32767]",
"Microsoft.AspNetCore.Http.Connections.Common": "(,10.0.32767]",
"Microsoft.AspNetCore.Http.Extensions": "(,10.0.32767]",
"Microsoft.AspNetCore.Http.Features": "(,10.0.32767]",
"Microsoft.AspNetCore.Http.Results": "(,10.0.32767]",
"Microsoft.AspNetCore.HttpLogging": "(,10.0.32767]",
"Microsoft.AspNetCore.HttpOverrides": "(,10.0.32767]",
"Microsoft.AspNetCore.HttpsPolicy": "(,10.0.32767]",
"Microsoft.AspNetCore.Identity": "(,10.0.32767]",
"Microsoft.AspNetCore.Localization": "(,10.0.32767]",
"Microsoft.AspNetCore.Localization.Routing": "(,10.0.32767]",
"Microsoft.AspNetCore.Metadata": "(,10.0.32767]",
"Microsoft.AspNetCore.Mvc": "(,10.0.32767]",
"Microsoft.AspNetCore.Mvc.Abstractions": "(,10.0.32767]",
"Microsoft.AspNetCore.Mvc.ApiExplorer": "(,10.0.32767]",
"Microsoft.AspNetCore.Mvc.Core": "(,10.0.32767]",
"Microsoft.AspNetCore.Mvc.Cors": "(,10.0.32767]",
"Microsoft.AspNetCore.Mvc.DataAnnotations": "(,10.0.32767]",
"Microsoft.AspNetCore.Mvc.Formatters.Json": "(,10.0.32767]",
"Microsoft.AspNetCore.Mvc.Formatters.Xml": "(,10.0.32767]",
"Microsoft.AspNetCore.Mvc.Localization": "(,10.0.32767]",
"Microsoft.AspNetCore.Mvc.Razor": "(,10.0.32767]",
"Microsoft.AspNetCore.Mvc.RazorPages": "(,10.0.32767]",
"Microsoft.AspNetCore.Mvc.TagHelpers": "(,10.0.32767]",
"Microsoft.AspNetCore.Mvc.ViewFeatures": "(,10.0.32767]",
"Microsoft.AspNetCore.OutputCaching": "(,10.0.32767]",
"Microsoft.AspNetCore.RateLimiting": "(,10.0.32767]",
"Microsoft.AspNetCore.Razor": "(,10.0.32767]",
"Microsoft.AspNetCore.Razor.Runtime": "(,10.0.32767]",
"Microsoft.AspNetCore.RequestDecompression": "(,10.0.32767]",
"Microsoft.AspNetCore.ResponseCaching": "(,10.0.32767]",
"Microsoft.AspNetCore.ResponseCaching.Abstractions": "(,10.0.32767]",
"Microsoft.AspNetCore.ResponseCompression": "(,10.0.32767]",
"Microsoft.AspNetCore.Rewrite": "(,10.0.32767]",
"Microsoft.AspNetCore.Routing": "(,10.0.32767]",
"Microsoft.AspNetCore.Routing.Abstractions": "(,10.0.32767]",
"Microsoft.AspNetCore.Server.HttpSys": "(,10.0.32767]",
"Microsoft.AspNetCore.Server.IIS": "(,10.0.32767]",
"Microsoft.AspNetCore.Server.IISIntegration": "(,10.0.32767]",
"Microsoft.AspNetCore.Server.Kestrel": "(,10.0.32767]",
"Microsoft.AspNetCore.Server.Kestrel.Core": "(,10.0.32767]",
"Microsoft.AspNetCore.Server.Kestrel.Transport.NamedPipes": "(,10.0.32767]",
"Microsoft.AspNetCore.Server.Kestrel.Transport.Quic": "(,10.0.32767]",
"Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets": "(,10.0.32767]",
"Microsoft.AspNetCore.Session": "(,10.0.32767]",
"Microsoft.AspNetCore.SignalR": "(,10.0.32767]",
"Microsoft.AspNetCore.SignalR.Common": "(,10.0.32767]",
"Microsoft.AspNetCore.SignalR.Core": "(,10.0.32767]",
"Microsoft.AspNetCore.SignalR.Protocols.Json": "(,10.0.32767]",
"Microsoft.AspNetCore.StaticAssets": "(,10.0.32767]",
"Microsoft.AspNetCore.StaticFiles": "(,10.0.32767]",
"Microsoft.AspNetCore.WebSockets": "(,10.0.32767]",
"Microsoft.AspNetCore.WebUtilities": "(,10.0.32767]",
"Microsoft.CSharp": "(,4.7.32767]",
"Microsoft.Extensions.Caching.Abstractions": "(,10.0.0-preview.6.25358.103]",
"Microsoft.Extensions.Caching.Memory": "(,10.0.0-preview.6.25358.103]",
"Microsoft.Extensions.Configuration": "(,10.0.0-preview.6.25358.103]",
"Microsoft.Extensions.Configuration.Abstractions": "(,10.0.0-preview.6.25358.103]",
"Microsoft.Extensions.Configuration.Binder": "(,10.0.0-preview.6.25358.103]",
"Microsoft.Extensions.Configuration.CommandLine": "(,10.0.0-preview.6.25358.103]",
"Microsoft.Extensions.Configuration.EnvironmentVariables": "(,10.0.0-preview.6.25358.103]",
"Microsoft.Extensions.Configuration.FileExtensions": "(,10.0.0-preview.6.25358.103]",
"Microsoft.Extensions.Configuration.Ini": "(,10.0.0-preview.6.25358.103]",
"Microsoft.Extensions.Configuration.Json": "(,10.0.0-preview.6.25358.103]",
"Microsoft.Extensions.Configuration.KeyPerFile": "(,10.0.32767]",
"Microsoft.Extensions.Configuration.UserSecrets": "(,10.0.0-preview.6.25358.103]",
"Microsoft.Extensions.Configuration.Xml": "(,10.0.0-preview.6.25358.103]",
"Microsoft.Extensions.DependencyInjection": "(,10.0.0-preview.6.25358.103]",
"Microsoft.Extensions.DependencyInjection.Abstractions": "(,10.0.0-preview.6.25358.103]",
"Microsoft.Extensions.Diagnostics": "(,10.0.0-preview.6.25358.103]",
"Microsoft.Extensions.Diagnostics.Abstractions": "(,10.0.0-preview.6.25358.103]",
"Microsoft.Extensions.Diagnostics.HealthChecks": "(,10.0.32767]",
"Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions": "(,10.0.32767]",
"Microsoft.Extensions.Features": "(,10.0.32767]",
"Microsoft.Extensions.FileProviders.Abstractions": "(,10.0.0-preview.6.25358.103]",
"Microsoft.Extensions.FileProviders.Composite": "(,10.0.0-preview.6.25358.103]",
"Microsoft.Extensions.FileProviders.Embedded": "(,10.0.32767]",
"Microsoft.Extensions.FileProviders.Physical": "(,10.0.0-preview.6.25358.103]",
"Microsoft.Extensions.FileSystemGlobbing": "(,10.0.0-preview.6.25358.103]",
"Microsoft.Extensions.Hosting": "(,10.0.0-preview.6.25358.103]",
"Microsoft.Extensions.Hosting.Abstractions": "(,10.0.0-preview.6.25358.103]",
"Microsoft.Extensions.Http": "(,10.0.0-preview.6.25358.103]",
"Microsoft.Extensions.Identity.Core": "(,10.0.32767]",
"Microsoft.Extensions.Identity.Stores": "(,10.0.32767]",
"Microsoft.Extensions.Localization": "(,10.0.32767]",
"Microsoft.Extensions.Localization.Abstractions": "(,10.0.32767]",
"Microsoft.Extensions.Logging": "(,10.0.0-preview.6.25358.103]",
"Microsoft.Extensions.Logging.Abstractions": "(,10.0.0-preview.6.25358.103]",
"Microsoft.Extensions.Logging.Configuration": "(,10.0.0-preview.6.25358.103]",
"Microsoft.Extensions.Logging.Console": "(,10.0.0-preview.6.25358.103]",
"Microsoft.Extensions.Logging.Debug": "(,10.0.0-preview.6.25358.103]",
"Microsoft.Extensions.Logging.EventLog": "(,10.0.0-preview.6.25358.103]",
"Microsoft.Extensions.Logging.EventSource": "(,10.0.0-preview.6.25358.103]",
"Microsoft.Extensions.Logging.TraceSource": "(,10.0.0-preview.6.25358.103]",
"Microsoft.Extensions.ObjectPool": "(,10.0.32767]",
"Microsoft.Extensions.Options": "(,10.0.0-preview.6.25358.103]",
"Microsoft.Extensions.Options.ConfigurationExtensions": "(,10.0.0-preview.6.25358.103]",
"Microsoft.Extensions.Options.DataAnnotations": "(,10.0.0-preview.6.25358.103]",
"Microsoft.Extensions.Primitives": "(,10.0.0-preview.6.25358.103]",
"Microsoft.Extensions.Validation": "(,10.0.32767]",
"Microsoft.Extensions.WebEncoders": "(,10.0.32767]",
"Microsoft.JSInterop": "(,10.0.32767]",
"Microsoft.Net.Http.Headers": "(,10.0.32767]",
"Microsoft.VisualBasic": "(,10.4.32767]",
"Microsoft.Win32.Primitives": "(,4.3.32767]",
"Microsoft.Win32.Registry": "(,5.0.32767]",
"runtime.any.System.Collections": "(,4.3.32767]",
"runtime.any.System.Diagnostics.Tools": "(,4.3.32767]",
"runtime.any.System.Diagnostics.Tracing": "(,4.3.32767]",
"runtime.any.System.Globalization": "(,4.3.32767]",
"runtime.any.System.Globalization.Calendars": "(,4.3.32767]",
"runtime.any.System.IO": "(,4.3.32767]",
"runtime.any.System.Reflection": "(,4.3.32767]",
"runtime.any.System.Reflection.Extensions": "(,4.3.32767]",
"runtime.any.System.Reflection.Primitives": "(,4.3.32767]",
"runtime.any.System.Resources.ResourceManager": "(,4.3.32767]",
"runtime.any.System.Runtime": "(,4.3.32767]",
"runtime.any.System.Runtime.Handles": "(,4.3.32767]",
"runtime.any.System.Runtime.InteropServices": "(,4.3.32767]",
"runtime.any.System.Text.Encoding": "(,4.3.32767]",
"runtime.any.System.Text.Encoding.Extensions": "(,4.3.32767]",
"runtime.any.System.Threading.Tasks": "(,4.3.32767]",
"runtime.any.System.Threading.Timer": "(,4.3.32767]",
"runtime.aot.System.Collections": "(,4.3.32767]",
"runtime.aot.System.Diagnostics.Tools": "(,4.3.32767]",
"runtime.aot.System.Diagnostics.Tracing": "(,4.3.32767]",
"runtime.aot.System.Globalization": "(,4.3.32767]",
"runtime.aot.System.Globalization.Calendars": "(,4.3.32767]",
"runtime.aot.System.IO": "(,4.3.32767]",
"runtime.aot.System.Reflection": "(,4.3.32767]",
"runtime.aot.System.Reflection.Extensions": "(,4.3.32767]",
"runtime.aot.System.Reflection.Primitives": "(,4.3.32767]",
"runtime.aot.System.Resources.ResourceManager": "(,4.3.32767]",
"runtime.aot.System.Runtime": "(,4.3.32767]",
"runtime.aot.System.Runtime.Handles": "(,4.3.32767]",
"runtime.aot.System.Runtime.InteropServices": "(,4.3.32767]",
"runtime.aot.System.Text.Encoding": "(,4.3.32767]",
"runtime.aot.System.Text.Encoding.Extensions": "(,4.3.32767]",
"runtime.aot.System.Threading.Tasks": "(,4.3.32767]",
"runtime.aot.System.Threading.Timer": "(,4.3.32767]",
"runtime.debian.8-x64.runtime.native.System": "(,4.3.32767]",
"runtime.debian.8-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
"runtime.debian.8-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
"runtime.debian.8-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
"runtime.debian.8-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
"runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
"runtime.debian.9-x64.runtime.native.System": "(,4.3.32767]",
"runtime.debian.9-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
"runtime.debian.9-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
"runtime.debian.9-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
"runtime.fedora.23-x64.runtime.native.System": "(,4.3.32767]",
"runtime.fedora.23-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
"runtime.fedora.23-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
"runtime.fedora.23-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
"runtime.fedora.23-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
"runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
"runtime.fedora.24-x64.runtime.native.System": "(,4.3.32767]",
"runtime.fedora.24-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
"runtime.fedora.24-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
"runtime.fedora.24-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
"runtime.fedora.24-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
"runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
"runtime.fedora.27-x64.runtime.native.System": "(,4.3.32767]",
"runtime.fedora.27-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
"runtime.fedora.27-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
"runtime.fedora.27-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
"runtime.fedora.28-x64.runtime.native.System": "(,4.3.32767]",
"runtime.fedora.28-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
"runtime.fedora.28-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
"runtime.fedora.28-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
"runtime.opensuse.13.2-x64.runtime.native.System": "(,4.3.32767]",
"runtime.opensuse.13.2-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
"runtime.opensuse.13.2-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
"runtime.opensuse.13.2-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
"runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
"runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
"runtime.opensuse.42.1-x64.runtime.native.System": "(,4.3.32767]",
"runtime.opensuse.42.1-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
"runtime.opensuse.42.1-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
"runtime.opensuse.42.1-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
"runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
"runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
"runtime.opensuse.42.3-x64.runtime.native.System": "(,4.3.32767]",
"runtime.opensuse.42.3-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
"runtime.opensuse.42.3-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
"runtime.opensuse.42.3-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
"runtime.osx.10.10-x64.runtime.native.System": "(,4.3.32767]",
"runtime.osx.10.10-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
"runtime.osx.10.10-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
"runtime.osx.10.10-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
"runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
"runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": "(,4.3.32767]",
"runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
"runtime.rhel.7-x64.runtime.native.System": "(,4.3.32767]",
"runtime.rhel.7-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
"runtime.rhel.7-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
"runtime.rhel.7-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
"runtime.rhel.7-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
"runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
"runtime.ubuntu.14.04-x64.runtime.native.System": "(,4.3.32767]",
"runtime.ubuntu.14.04-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
"runtime.ubuntu.14.04-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
"runtime.ubuntu.14.04-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
"runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
"runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
"runtime.ubuntu.16.04-x64.runtime.native.System": "(,4.3.32767]",
"runtime.ubuntu.16.04-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
"runtime.ubuntu.16.04-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
"runtime.ubuntu.16.04-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
"runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
"runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
"runtime.ubuntu.16.10-x64.runtime.native.System": "(,4.3.32767]",
"runtime.ubuntu.16.10-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
"runtime.ubuntu.16.10-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
"runtime.ubuntu.16.10-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
"runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
"runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
"runtime.ubuntu.18.04-x64.runtime.native.System": "(,4.3.32767]",
"runtime.ubuntu.18.04-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
"runtime.ubuntu.18.04-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
"runtime.ubuntu.18.04-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
"runtime.unix.Microsoft.Win32.Primitives": "(,4.3.32767]",
"runtime.unix.System.Console": "(,4.3.32767]",
"runtime.unix.System.Diagnostics.Debug": "(,4.3.32767]",
"runtime.unix.System.IO.FileSystem": "(,4.3.32767]",
"runtime.unix.System.Net.Primitives": "(,4.3.32767]",
"runtime.unix.System.Net.Sockets": "(,4.3.32767]",
"runtime.unix.System.Private.Uri": "(,4.3.32767]",
"runtime.unix.System.Runtime.Extensions": "(,4.3.32767]",
"runtime.win.Microsoft.Win32.Primitives": "(,4.3.32767]",
"runtime.win.System.Console": "(,4.3.32767]",
"runtime.win.System.Diagnostics.Debug": "(,4.3.32767]",
"runtime.win.System.IO.FileSystem": "(,4.3.32767]",
"runtime.win.System.Net.Primitives": "(,4.3.32767]",
"runtime.win.System.Net.Sockets": "(,4.3.32767]",
"runtime.win.System.Runtime.Extensions": "(,4.3.32767]",
"runtime.win10-arm-aot.runtime.native.System.IO.Compression": "(,4.0.32767]",
"runtime.win10-arm64.runtime.native.System.IO.Compression": "(,4.3.32767]",
"runtime.win10-x64-aot.runtime.native.System.IO.Compression": "(,4.0.32767]",
"runtime.win10-x86-aot.runtime.native.System.IO.Compression": "(,4.0.32767]",
"runtime.win7-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
"runtime.win7-x86.runtime.native.System.IO.Compression": "(,4.3.32767]",
"runtime.win7.System.Private.Uri": "(,4.3.32767]",
"runtime.win8-arm.runtime.native.System.IO.Compression": "(,4.3.32767]",
"System.AppContext": "(,4.3.32767]",
"System.Buffers": "(,5.0.32767]",
"System.Collections": "(,4.3.32767]",
"System.Collections.Concurrent": "(,4.3.32767]",
"System.Collections.Immutable": "(,10.0.0-preview.6.25358.103]",
"System.Collections.NonGeneric": "(,4.3.32767]",
"System.Collections.Specialized": "(,4.3.32767]",
"System.ComponentModel": "(,4.3.32767]",
"System.ComponentModel.Annotations": "(,4.3.32767]",
"System.ComponentModel.EventBasedAsync": "(,4.3.32767]",
"System.ComponentModel.Primitives": "(,4.3.32767]",
"System.ComponentModel.TypeConverter": "(,4.3.32767]",
"System.Console": "(,4.3.32767]",
"System.Data.Common": "(,4.3.32767]",
"System.Data.DataSetExtensions": "(,4.4.32767]",
"System.Diagnostics.Contracts": "(,4.3.32767]",
"System.Diagnostics.Debug": "(,4.3.32767]",
"System.Diagnostics.DiagnosticSource": "(,10.0.0-preview.6.25358.103]",
"System.Diagnostics.EventLog": "(,10.0.0-preview.6.25358.103]",
"System.Diagnostics.FileVersionInfo": "(,4.3.32767]",
"System.Diagnostics.Process": "(,4.3.32767]",
"System.Diagnostics.StackTrace": "(,4.3.32767]",
"System.Diagnostics.TextWriterTraceListener": "(,4.3.32767]",
"System.Diagnostics.Tools": "(,4.3.32767]",
"System.Diagnostics.TraceSource": "(,4.3.32767]",
"System.Diagnostics.Tracing": "(,4.3.32767]",
"System.Drawing.Primitives": "(,4.3.32767]",
"System.Dynamic.Runtime": "(,4.3.32767]",
"System.Formats.Asn1": "(,10.0.0-preview.6.25358.103]",
"System.Formats.Cbor": "(,10.0.0-preview.6.25358.103]",
"System.Formats.Tar": "(,10.0.0-preview.6.25358.103]",
"System.Globalization": "(,4.3.32767]",
"System.Globalization.Calendars": "(,4.3.32767]",
"System.Globalization.Extensions": "(,4.3.32767]",
"System.IO": "(,4.3.32767]",
"System.IO.Compression": "(,4.3.32767]",
"System.IO.Compression.ZipFile": "(,4.3.32767]",
"System.IO.FileSystem": "(,4.3.32767]",
"System.IO.FileSystem.AccessControl": "(,4.4.32767]",
"System.IO.FileSystem.DriveInfo": "(,4.3.32767]",
"System.IO.FileSystem.Primitives": "(,4.3.32767]",
"System.IO.FileSystem.Watcher": "(,4.3.32767]",
"System.IO.IsolatedStorage": "(,4.3.32767]",
"System.IO.MemoryMappedFiles": "(,4.3.32767]",
"System.IO.Pipelines": "(,10.0.0-preview.6.25358.103]",
"System.IO.Pipes": "(,4.3.32767]",
"System.IO.Pipes.AccessControl": "(,5.0.32767]",
"System.IO.UnmanagedMemoryStream": "(,4.3.32767]",
"System.Linq": "(,4.3.32767]",
"System.Linq.AsyncEnumerable": "(,10.0.0-preview.6.25358.103]",
"System.Linq.Expressions": "(,4.3.32767]",
"System.Linq.Parallel": "(,4.3.32767]",
"System.Linq.Queryable": "(,4.3.32767]",
"System.Memory": "(,5.0.32767]",
"System.Net.Http": "(,4.3.32767]",
"System.Net.Http.Json": "(,10.0.0-preview.6.25358.103]",
"System.Net.NameResolution": "(,4.3.32767]",
"System.Net.NetworkInformation": "(,4.3.32767]",
"System.Net.Ping": "(,4.3.32767]",
"System.Net.Primitives": "(,4.3.32767]",
"System.Net.Requests": "(,4.3.32767]",
"System.Net.Security": "(,4.3.32767]",
"System.Net.ServerSentEvents": "(,10.0.0-preview.6.25358.103]",
"System.Net.Sockets": "(,4.3.32767]",
"System.Net.WebHeaderCollection": "(,4.3.32767]",
"System.Net.WebSockets": "(,4.3.32767]",
"System.Net.WebSockets.Client": "(,4.3.32767]",
"System.Numerics.Vectors": "(,5.0.32767]",
"System.ObjectModel": "(,4.3.32767]",
"System.Private.DataContractSerialization": "(,4.3.32767]",
"System.Private.Uri": "(,4.3.32767]",
"System.Reflection": "(,4.3.32767]",
"System.Reflection.DispatchProxy": "(,6.0.32767]",
"System.Reflection.Emit": "(,4.7.32767]",
"System.Reflection.Emit.ILGeneration": "(,4.7.32767]",
"System.Reflection.Emit.Lightweight": "(,4.7.32767]",
"System.Reflection.Extensions": "(,4.3.32767]",
"System.Reflection.Metadata": "(,10.0.0-preview.6.25358.103]",
"System.Reflection.Primitives": "(,4.3.32767]",
"System.Reflection.TypeExtensions": "(,4.3.32767]",
"System.Resources.Reader": "(,4.3.32767]",
"System.Resources.ResourceManager": "(,4.3.32767]",
"System.Resources.Writer": "(,4.3.32767]",
"System.Runtime": "(,4.3.32767]",
"System.Runtime.CompilerServices.Unsafe": "(,7.0.32767]",
"System.Runtime.CompilerServices.VisualC": "(,4.3.32767]",
"System.Runtime.Extensions": "(,4.3.32767]",
"System.Runtime.Handles": "(,4.3.32767]",
"System.Runtime.InteropServices": "(,4.3.32767]",
"System.Runtime.InteropServices.RuntimeInformation": "(,4.3.32767]",
"System.Runtime.Loader": "(,4.3.32767]",
"System.Runtime.Numerics": "(,4.3.32767]",
"System.Runtime.Serialization.Formatters": "(,4.3.32767]",
"System.Runtime.Serialization.Json": "(,4.3.32767]",
"System.Runtime.Serialization.Primitives": "(,4.3.32767]",
"System.Runtime.Serialization.Xml": "(,4.3.32767]",
"System.Security.AccessControl": "(,6.0.32767]",
"System.Security.Claims": "(,4.3.32767]",
"System.Security.Cryptography.Algorithms": "(,4.3.32767]",
"System.Security.Cryptography.Cng": "(,5.0.32767]",
"System.Security.Cryptography.Csp": "(,4.3.32767]",
"System.Security.Cryptography.Encoding": "(,4.3.32767]",
"System.Security.Cryptography.OpenSsl": "(,5.0.32767]",
"System.Security.Cryptography.Primitives": "(,4.3.32767]",
"System.Security.Cryptography.X509Certificates": "(,4.3.32767]",
"System.Security.Cryptography.Xml": "(,10.0.0-preview.6.25358.103]",
"System.Security.Principal": "(,4.3.32767]",
"System.Security.Principal.Windows": "(,5.0.32767]",
"System.Security.SecureString": "(,4.3.32767]",
"System.Text.Encoding": "(,4.3.32767]",
"System.Text.Encoding.CodePages": "(,10.0.0-preview.6.25358.103]",
"System.Text.Encoding.Extensions": "(,4.3.32767]",
"System.Text.Encodings.Web": "(,10.0.0-preview.6.25358.103]",
"System.Text.Json": "(,10.0.0-preview.6.25358.103]",
"System.Text.RegularExpressions": "(,4.3.32767]",
"System.Threading": "(,4.3.32767]",
"System.Threading.AccessControl": "(,10.0.0-preview.6.25358.103]",
"System.Threading.Channels": "(,10.0.0-preview.6.25358.103]",
"System.Threading.Overlapped": "(,4.3.32767]",
"System.Threading.RateLimiting": "(,10.0.0-preview.6.25358.103]",
"System.Threading.Tasks": "(,4.3.32767]",
"System.Threading.Tasks.Dataflow": "(,10.0.0-preview.6.25358.103]",
"System.Threading.Tasks.Extensions": "(,5.0.32767]",
"System.Threading.Tasks.Parallel": "(,4.3.32767]",
"System.Threading.Thread": "(,4.3.32767]",
"System.Threading.ThreadPool": "(,4.3.32767]",
"System.Threading.Timer": "(,4.3.32767]",
"System.ValueTuple": "(,4.5.32767]",
"System.Xml.ReaderWriter": "(,4.3.32767]",
"System.Xml.XDocument": "(,4.3.32767]",
"System.Xml.XmlDocument": "(,4.3.32767]",
"System.Xml.XmlSerializer": "(,4.3.32767]",
"System.Xml.XPath": "(,4.3.32767]",
"System.Xml.XPath.XDocument": "(,5.0.32767]"
}
}
}
},
"E:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj": {
"version": "1.0.0",
"restore": {
"projectUniqueName": "E:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj",
"projectName": "Vortex.Shared.Kernel",
"projectPath": "E:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\Vortex.Shared.Kernel.csproj",
"packagesPath": "C:\\Users\\HomePC\\.nuget\\packages\\",
"outputPath": "E:\\GIT\\forkmessager\\apps\\server-net\\src\\Shared\\Vortex.Shared.Kernel\\obj\\",
"projectStyle": "PackageReference",
"fallbackFolders": [
"C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages"
],
"configFilePaths": [
"C:\\Users\\HomePC\\AppData\\Roaming\\NuGet\\NuGet.Config",
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config",
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config"
],
"originalTargetFrameworks": [
"net10.0"
],
"sources": {
"C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {},
"C:\\Program Files\\dotnet\\library-packs": {},
"https://api.nuget.org/v3/index.json": {}
},
"frameworks": {
"net10.0": {
"targetAlias": "net10.0",
"projectReferences": {}
}
},
"warningProperties": {
"warnAsError": [
"NU1605"
]
},
"restoreAuditProperties": {
"enableAudit": "true",
"auditLevel": "low",
"auditMode": "all"
},
"SdkAnalysisLevel": "10.0.100"
},
"frameworks": {
"net10.0": {
"targetAlias": "net10.0",
"dependencies": {
"MediatR": {
"target": "Package",
"version": "[12.0.1, )"
}
},
"imports": [
"net461",
"net462",
"net47",
"net471",
"net472",
"net48",
"net481"
],
"assetTargetFallback": true,
"warn": true,
"frameworkReferences": {
"Microsoft.NETCore.App": {
"privateAssets": "all"
}
},
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\10.0.100-preview.6.25358.103/PortableRuntimeIdentifierGraph.json",
"packagesToPrune": {
"Microsoft.CSharp": "(,4.7.32767]",
"Microsoft.VisualBasic": "(,10.4.32767]",
"Microsoft.Win32.Primitives": "(,4.3.32767]",
"Microsoft.Win32.Registry": "(,5.0.32767]",
"runtime.any.System.Collections": "(,4.3.32767]",
"runtime.any.System.Diagnostics.Tools": "(,4.3.32767]",
"runtime.any.System.Diagnostics.Tracing": "(,4.3.32767]",
"runtime.any.System.Globalization": "(,4.3.32767]",
"runtime.any.System.Globalization.Calendars": "(,4.3.32767]",
"runtime.any.System.IO": "(,4.3.32767]",
"runtime.any.System.Reflection": "(,4.3.32767]",
"runtime.any.System.Reflection.Extensions": "(,4.3.32767]",
"runtime.any.System.Reflection.Primitives": "(,4.3.32767]",
"runtime.any.System.Resources.ResourceManager": "(,4.3.32767]",
"runtime.any.System.Runtime": "(,4.3.32767]",
"runtime.any.System.Runtime.Handles": "(,4.3.32767]",
"runtime.any.System.Runtime.InteropServices": "(,4.3.32767]",
"runtime.any.System.Text.Encoding": "(,4.3.32767]",
"runtime.any.System.Text.Encoding.Extensions": "(,4.3.32767]",
"runtime.any.System.Threading.Tasks": "(,4.3.32767]",
"runtime.any.System.Threading.Timer": "(,4.3.32767]",
"runtime.aot.System.Collections": "(,4.3.32767]",
"runtime.aot.System.Diagnostics.Tools": "(,4.3.32767]",
"runtime.aot.System.Diagnostics.Tracing": "(,4.3.32767]",
"runtime.aot.System.Globalization": "(,4.3.32767]",
"runtime.aot.System.Globalization.Calendars": "(,4.3.32767]",
"runtime.aot.System.IO": "(,4.3.32767]",
"runtime.aot.System.Reflection": "(,4.3.32767]",
"runtime.aot.System.Reflection.Extensions": "(,4.3.32767]",
"runtime.aot.System.Reflection.Primitives": "(,4.3.32767]",
"runtime.aot.System.Resources.ResourceManager": "(,4.3.32767]",
"runtime.aot.System.Runtime": "(,4.3.32767]",
"runtime.aot.System.Runtime.Handles": "(,4.3.32767]",
"runtime.aot.System.Runtime.InteropServices": "(,4.3.32767]",
"runtime.aot.System.Text.Encoding": "(,4.3.32767]",
"runtime.aot.System.Text.Encoding.Extensions": "(,4.3.32767]",
"runtime.aot.System.Threading.Tasks": "(,4.3.32767]",
"runtime.aot.System.Threading.Timer": "(,4.3.32767]",
"runtime.debian.8-x64.runtime.native.System": "(,4.3.32767]",
"runtime.debian.8-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
"runtime.debian.8-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
"runtime.debian.8-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
"runtime.debian.8-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
"runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
"runtime.debian.9-x64.runtime.native.System": "(,4.3.32767]",
"runtime.debian.9-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
"runtime.debian.9-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
"runtime.debian.9-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
"runtime.fedora.23-x64.runtime.native.System": "(,4.3.32767]",
"runtime.fedora.23-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
"runtime.fedora.23-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
"runtime.fedora.23-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
"runtime.fedora.23-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
"runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
"runtime.fedora.24-x64.runtime.native.System": "(,4.3.32767]",
"runtime.fedora.24-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
"runtime.fedora.24-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
"runtime.fedora.24-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
"runtime.fedora.24-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
"runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
"runtime.fedora.27-x64.runtime.native.System": "(,4.3.32767]",
"runtime.fedora.27-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
"runtime.fedora.27-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
"runtime.fedora.27-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
"runtime.fedora.28-x64.runtime.native.System": "(,4.3.32767]",
"runtime.fedora.28-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
"runtime.fedora.28-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
"runtime.fedora.28-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
"runtime.opensuse.13.2-x64.runtime.native.System": "(,4.3.32767]",
"runtime.opensuse.13.2-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
"runtime.opensuse.13.2-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
"runtime.opensuse.13.2-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
"runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
"runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
"runtime.opensuse.42.1-x64.runtime.native.System": "(,4.3.32767]",
"runtime.opensuse.42.1-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
"runtime.opensuse.42.1-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
"runtime.opensuse.42.1-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
"runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
"runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
"runtime.opensuse.42.3-x64.runtime.native.System": "(,4.3.32767]",
"runtime.opensuse.42.3-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
"runtime.opensuse.42.3-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
"runtime.opensuse.42.3-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
"runtime.osx.10.10-x64.runtime.native.System": "(,4.3.32767]",
"runtime.osx.10.10-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
"runtime.osx.10.10-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
"runtime.osx.10.10-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
"runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
"runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": "(,4.3.32767]",
"runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
"runtime.rhel.7-x64.runtime.native.System": "(,4.3.32767]",
"runtime.rhel.7-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
"runtime.rhel.7-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
"runtime.rhel.7-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
"runtime.rhel.7-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
"runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
"runtime.ubuntu.14.04-x64.runtime.native.System": "(,4.3.32767]",
"runtime.ubuntu.14.04-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
"runtime.ubuntu.14.04-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
"runtime.ubuntu.14.04-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
"runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
"runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
"runtime.ubuntu.16.04-x64.runtime.native.System": "(,4.3.32767]",
"runtime.ubuntu.16.04-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
"runtime.ubuntu.16.04-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
"runtime.ubuntu.16.04-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
"runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
"runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
"runtime.ubuntu.16.10-x64.runtime.native.System": "(,4.3.32767]",
"runtime.ubuntu.16.10-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
"runtime.ubuntu.16.10-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
"runtime.ubuntu.16.10-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
"runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
"runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
"runtime.ubuntu.18.04-x64.runtime.native.System": "(,4.3.32767]",
"runtime.ubuntu.18.04-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
"runtime.ubuntu.18.04-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
"runtime.ubuntu.18.04-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
"runtime.unix.Microsoft.Win32.Primitives": "(,4.3.32767]",
"runtime.unix.System.Console": "(,4.3.32767]",
"runtime.unix.System.Diagnostics.Debug": "(,4.3.32767]",
"runtime.unix.System.IO.FileSystem": "(,4.3.32767]",
"runtime.unix.System.Net.Primitives": "(,4.3.32767]",
"runtime.unix.System.Net.Sockets": "(,4.3.32767]",
"runtime.unix.System.Private.Uri": "(,4.3.32767]",
"runtime.unix.System.Runtime.Extensions": "(,4.3.32767]",
"runtime.win.Microsoft.Win32.Primitives": "(,4.3.32767]",
"runtime.win.System.Console": "(,4.3.32767]",
"runtime.win.System.Diagnostics.Debug": "(,4.3.32767]",
"runtime.win.System.IO.FileSystem": "(,4.3.32767]",
"runtime.win.System.Net.Primitives": "(,4.3.32767]",
"runtime.win.System.Net.Sockets": "(,4.3.32767]",
"runtime.win.System.Runtime.Extensions": "(,4.3.32767]",
"runtime.win10-arm-aot.runtime.native.System.IO.Compression": "(,4.0.32767]",
"runtime.win10-arm64.runtime.native.System.IO.Compression": "(,4.3.32767]",
"runtime.win10-x64-aot.runtime.native.System.IO.Compression": "(,4.0.32767]",
"runtime.win10-x86-aot.runtime.native.System.IO.Compression": "(,4.0.32767]",
"runtime.win7-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
"runtime.win7-x86.runtime.native.System.IO.Compression": "(,4.3.32767]",
"runtime.win7.System.Private.Uri": "(,4.3.32767]",
"runtime.win8-arm.runtime.native.System.IO.Compression": "(,4.3.32767]",
"System.AppContext": "(,4.3.32767]",
"System.Buffers": "(,5.0.32767]",
"System.Collections": "(,4.3.32767]",
"System.Collections.Concurrent": "(,4.3.32767]",
"System.Collections.Immutable": "(,10.0.0-preview.6.25358.103]",
"System.Collections.NonGeneric": "(,4.3.32767]",
"System.Collections.Specialized": "(,4.3.32767]",
"System.ComponentModel": "(,4.3.32767]",
"System.ComponentModel.Annotations": "(,4.3.32767]",
"System.ComponentModel.EventBasedAsync": "(,4.3.32767]",
"System.ComponentModel.Primitives": "(,4.3.32767]",
"System.ComponentModel.TypeConverter": "(,4.3.32767]",
"System.Console": "(,4.3.32767]",
"System.Data.Common": "(,4.3.32767]",
"System.Data.DataSetExtensions": "(,4.4.32767]",
"System.Diagnostics.Contracts": "(,4.3.32767]",
"System.Diagnostics.Debug": "(,4.3.32767]",
"System.Diagnostics.DiagnosticSource": "(,10.0.0-preview.6.25358.103]",
"System.Diagnostics.FileVersionInfo": "(,4.3.32767]",
"System.Diagnostics.Process": "(,4.3.32767]",
"System.Diagnostics.StackTrace": "(,4.3.32767]",
"System.Diagnostics.TextWriterTraceListener": "(,4.3.32767]",
"System.Diagnostics.Tools": "(,4.3.32767]",
"System.Diagnostics.TraceSource": "(,4.3.32767]",
"System.Diagnostics.Tracing": "(,4.3.32767]",
"System.Drawing.Primitives": "(,4.3.32767]",
"System.Dynamic.Runtime": "(,4.3.32767]",
"System.Formats.Asn1": "(,10.0.0-preview.6.25358.103]",
"System.Formats.Tar": "(,10.0.0-preview.6.25358.103]",
"System.Globalization": "(,4.3.32767]",
"System.Globalization.Calendars": "(,4.3.32767]",
"System.Globalization.Extensions": "(,4.3.32767]",
"System.IO": "(,4.3.32767]",
"System.IO.Compression": "(,4.3.32767]",
"System.IO.Compression.ZipFile": "(,4.3.32767]",
"System.IO.FileSystem": "(,4.3.32767]",
"System.IO.FileSystem.AccessControl": "(,4.4.32767]",
"System.IO.FileSystem.DriveInfo": "(,4.3.32767]",
"System.IO.FileSystem.Primitives": "(,4.3.32767]",
"System.IO.FileSystem.Watcher": "(,4.3.32767]",
"System.IO.IsolatedStorage": "(,4.3.32767]",
"System.IO.MemoryMappedFiles": "(,4.3.32767]",
"System.IO.Pipelines": "(,10.0.0-preview.6.25358.103]",
"System.IO.Pipes": "(,4.3.32767]",
"System.IO.Pipes.AccessControl": "(,5.0.32767]",
"System.IO.UnmanagedMemoryStream": "(,4.3.32767]",
"System.Linq": "(,4.3.32767]",
"System.Linq.AsyncEnumerable": "(,10.0.0-preview.6.25358.103]",
"System.Linq.Expressions": "(,4.3.32767]",
"System.Linq.Parallel": "(,4.3.32767]",
"System.Linq.Queryable": "(,4.3.32767]",
"System.Memory": "(,5.0.32767]",
"System.Net.Http": "(,4.3.32767]",
"System.Net.Http.Json": "(,10.0.0-preview.6.25358.103]",
"System.Net.NameResolution": "(,4.3.32767]",
"System.Net.NetworkInformation": "(,4.3.32767]",
"System.Net.Ping": "(,4.3.32767]",
"System.Net.Primitives": "(,4.3.32767]",
"System.Net.Requests": "(,4.3.32767]",
"System.Net.Security": "(,4.3.32767]",
"System.Net.ServerSentEvents": "(,10.0.0-preview.6.25358.103]",
"System.Net.Sockets": "(,4.3.32767]",
"System.Net.WebHeaderCollection": "(,4.3.32767]",
"System.Net.WebSockets": "(,4.3.32767]",
"System.Net.WebSockets.Client": "(,4.3.32767]",
"System.Numerics.Vectors": "(,5.0.32767]",
"System.ObjectModel": "(,4.3.32767]",
"System.Private.DataContractSerialization": "(,4.3.32767]",
"System.Private.Uri": "(,4.3.32767]",
"System.Reflection": "(,4.3.32767]",
"System.Reflection.DispatchProxy": "(,6.0.32767]",
"System.Reflection.Emit": "(,4.7.32767]",
"System.Reflection.Emit.ILGeneration": "(,4.7.32767]",
"System.Reflection.Emit.Lightweight": "(,4.7.32767]",
"System.Reflection.Extensions": "(,4.3.32767]",
"System.Reflection.Metadata": "(,10.0.0-preview.6.25358.103]",
"System.Reflection.Primitives": "(,4.3.32767]",
"System.Reflection.TypeExtensions": "(,4.3.32767]",
"System.Resources.Reader": "(,4.3.32767]",
"System.Resources.ResourceManager": "(,4.3.32767]",
"System.Resources.Writer": "(,4.3.32767]",
"System.Runtime": "(,4.3.32767]",
"System.Runtime.CompilerServices.Unsafe": "(,7.0.32767]",
"System.Runtime.CompilerServices.VisualC": "(,4.3.32767]",
"System.Runtime.Extensions": "(,4.3.32767]",
"System.Runtime.Handles": "(,4.3.32767]",
"System.Runtime.InteropServices": "(,4.3.32767]",
"System.Runtime.InteropServices.RuntimeInformation": "(,4.3.32767]",
"System.Runtime.Loader": "(,4.3.32767]",
"System.Runtime.Numerics": "(,4.3.32767]",
"System.Runtime.Serialization.Formatters": "(,4.3.32767]",
"System.Runtime.Serialization.Json": "(,4.3.32767]",
"System.Runtime.Serialization.Primitives": "(,4.3.32767]",
"System.Runtime.Serialization.Xml": "(,4.3.32767]",
"System.Security.AccessControl": "(,6.0.32767]",
"System.Security.Claims": "(,4.3.32767]",
"System.Security.Cryptography.Algorithms": "(,4.3.32767]",
"System.Security.Cryptography.Cng": "(,5.0.32767]",
"System.Security.Cryptography.Csp": "(,4.3.32767]",
"System.Security.Cryptography.Encoding": "(,4.3.32767]",
"System.Security.Cryptography.OpenSsl": "(,5.0.32767]",
"System.Security.Cryptography.Primitives": "(,4.3.32767]",
"System.Security.Cryptography.X509Certificates": "(,4.3.32767]",
"System.Security.Principal": "(,4.3.32767]",
"System.Security.Principal.Windows": "(,5.0.32767]",
"System.Security.SecureString": "(,4.3.32767]",
"System.Text.Encoding": "(,4.3.32767]",
"System.Text.Encoding.CodePages": "(,10.0.0-preview.6.25358.103]",
"System.Text.Encoding.Extensions": "(,4.3.32767]",
"System.Text.Encodings.Web": "(,10.0.0-preview.6.25358.103]",
"System.Text.Json": "(,10.0.0-preview.6.25358.103]",
"System.Text.RegularExpressions": "(,4.3.32767]",
"System.Threading": "(,4.3.32767]",
"System.Threading.Channels": "(,10.0.0-preview.6.25358.103]",
"System.Threading.Overlapped": "(,4.3.32767]",
"System.Threading.Tasks": "(,4.3.32767]",
"System.Threading.Tasks.Dataflow": "(,10.0.0-preview.6.25358.103]",
"System.Threading.Tasks.Extensions": "(,5.0.32767]",
"System.Threading.Tasks.Parallel": "(,4.3.32767]",
"System.Threading.Thread": "(,4.3.32767]",
"System.Threading.ThreadPool": "(,4.3.32767]",
"System.Threading.Timer": "(,4.3.32767]",
"System.ValueTuple": "(,4.5.32767]",
"System.Xml.ReaderWriter": "(,4.3.32767]",
"System.Xml.XDocument": "(,4.3.32767]",
"System.Xml.XmlDocument": "(,4.3.32767]",
"System.Xml.XmlSerializer": "(,4.3.32767]",
"System.Xml.XPath": "(,4.3.32767]",
"System.Xml.XPath.XDocument": "(,5.0.32767]"
}
}
}
}
}
}

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<RestoreSuccess Condition=" '$(RestoreSuccess)' == '' ">True</RestoreSuccess>
<RestoreTool Condition=" '$(RestoreTool)' == '' ">NuGet</RestoreTool>
<ProjectAssetsFile Condition=" '$(ProjectAssetsFile)' == '' ">$(MSBuildThisFileDirectory)project.assets.json</ProjectAssetsFile>
<NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">$(UserProfile)\.nuget\packages\</NuGetPackageRoot>
<NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">C:\Users\HomePC\.nuget\packages\;C:\Program Files (x86)\Microsoft Visual Studio\Shared\NuGetPackages</NuGetPackageFolders>
<NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">PackageReference</NuGetProjectStyle>
<NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">6.15.0</NuGetToolVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<SourceRoot Include="C:\Users\HomePC\.nuget\packages\" />
<SourceRoot Include="C:\Program Files (x86)\Microsoft Visual Studio\Shared\NuGetPackages\" />
</ItemGroup>
<ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<Import Project="$(NuGetPackageRoot)microsoft.entityframeworkcore\10.0.4\buildTransitive\net10.0\Microsoft.EntityFrameworkCore.props" Condition="Exists('$(NuGetPackageRoot)microsoft.entityframeworkcore\10.0.4\buildTransitive\net10.0\Microsoft.EntityFrameworkCore.props')" />
</ImportGroup>
</Project>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<Import Project="$(NuGetPackageRoot)microsoft.extensions.logging.abstractions\10.0.4\buildTransitive\net8.0\Microsoft.Extensions.Logging.Abstractions.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.logging.abstractions\10.0.4\buildTransitive\net8.0\Microsoft.Extensions.Logging.Abstractions.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.extensions.options\10.0.4\buildTransitive\net8.0\Microsoft.Extensions.Options.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.options\10.0.4\buildTransitive\net8.0\Microsoft.Extensions.Options.targets')" />
</ImportGroup>
</Project>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,26 @@
{
"version": 2,
"dgSpecHash": "rWL1CDgJNu8=",
"success": true,
"projectFilePath": "E:\\GIT\\forkmessager\\apps\\server-net\\src\\Modules\\Chats\\Vortex.Modules.Chats.csproj",
"expectedPackageFiles": [
"C:\\Users\\HomePC\\.nuget\\packages\\mediatr\\12.0.1\\mediatr.12.0.1.nupkg.sha512",
"C:\\Users\\HomePC\\.nuget\\packages\\mediatr.contracts\\2.0.1\\mediatr.contracts.2.0.1.nupkg.sha512",
"C:\\Users\\HomePC\\.nuget\\packages\\microsoft.entityframeworkcore\\10.0.4\\microsoft.entityframeworkcore.10.0.4.nupkg.sha512",
"C:\\Users\\HomePC\\.nuget\\packages\\microsoft.entityframeworkcore.abstractions\\10.0.4\\microsoft.entityframeworkcore.abstractions.10.0.4.nupkg.sha512",
"C:\\Users\\HomePC\\.nuget\\packages\\microsoft.entityframeworkcore.analyzers\\10.0.4\\microsoft.entityframeworkcore.analyzers.10.0.4.nupkg.sha512",
"C:\\Users\\HomePC\\.nuget\\packages\\microsoft.entityframeworkcore.relational\\10.0.4\\microsoft.entityframeworkcore.relational.10.0.4.nupkg.sha512",
"C:\\Users\\HomePC\\.nuget\\packages\\microsoft.extensions.caching.abstractions\\10.0.4\\microsoft.extensions.caching.abstractions.10.0.4.nupkg.sha512",
"C:\\Users\\HomePC\\.nuget\\packages\\microsoft.extensions.caching.memory\\10.0.4\\microsoft.extensions.caching.memory.10.0.4.nupkg.sha512",
"C:\\Users\\HomePC\\.nuget\\packages\\microsoft.extensions.configuration.abstractions\\10.0.4\\microsoft.extensions.configuration.abstractions.10.0.4.nupkg.sha512",
"C:\\Users\\HomePC\\.nuget\\packages\\microsoft.extensions.dependencyinjection\\10.0.4\\microsoft.extensions.dependencyinjection.10.0.4.nupkg.sha512",
"C:\\Users\\HomePC\\.nuget\\packages\\microsoft.extensions.dependencyinjection.abstractions\\10.0.4\\microsoft.extensions.dependencyinjection.abstractions.10.0.4.nupkg.sha512",
"C:\\Users\\HomePC\\.nuget\\packages\\microsoft.extensions.logging\\10.0.4\\microsoft.extensions.logging.10.0.4.nupkg.sha512",
"C:\\Users\\HomePC\\.nuget\\packages\\microsoft.extensions.logging.abstractions\\10.0.4\\microsoft.extensions.logging.abstractions.10.0.4.nupkg.sha512",
"C:\\Users\\HomePC\\.nuget\\packages\\microsoft.extensions.options\\10.0.4\\microsoft.extensions.options.10.0.4.nupkg.sha512",
"C:\\Users\\HomePC\\.nuget\\packages\\microsoft.extensions.primitives\\10.0.4\\microsoft.extensions.primitives.10.0.4.nupkg.sha512",
"C:\\Users\\HomePC\\.nuget\\packages\\npgsql\\10.0.0\\npgsql.10.0.0.nupkg.sha512",
"C:\\Users\\HomePC\\.nuget\\packages\\npgsql.entityframeworkcore.postgresql\\10.0.0\\npgsql.entityframeworkcore.postgresql.10.0.0.nupkg.sha512"
],
"logs": []
}

View File

@@ -0,0 +1,10 @@
using Vortex.Shared.Kernel;
namespace Vortex.Modules.Identity.Application.Abstractions;
/// <summary>
/// Unit of Work специфичный для модуля Identity.
/// </summary>
public interface IIdentityUnitOfWork : IUnitOfWork
{
}

View File

@@ -0,0 +1,8 @@
using Vortex.Modules.Identity.Domain;
namespace Vortex.Modules.Identity.Application.Abstractions;
public interface IJwtTokenProvider
{
string Generate(User user);
}

View File

@@ -0,0 +1,37 @@
using Vortex.Modules.Identity.Application.Abstractions;
using Vortex.Modules.Identity.Domain;
using Vortex.Shared.Kernel;
using BCrypt.Net;
namespace Vortex.Modules.Identity.Application.Users.Login;
/// <summary>
/// Команда для входа пользователя. Возвращает JWT токен.
/// </summary>
public sealed record LoginUserCommand(string Username, string Password) : ICommand<string>;
public sealed class LoginUserCommandHandler : ICommandHandler<LoginUserCommand, string>
{
private readonly IUserRepository _userRepository;
private readonly IJwtTokenProvider _tokenProvider;
public LoginUserCommandHandler(IUserRepository userRepository, IJwtTokenProvider tokenProvider)
{
_userRepository = userRepository;
_tokenProvider = tokenProvider;
}
public async Task<Result<string>> Handle(LoginUserCommand request, CancellationToken cancellationToken)
{
var user = await _userRepository.GetByUsernameAsync(request.Username, cancellationToken);
if (user is null || !BCrypt.Net.BCrypt.Verify(request.Password, user.PasswordHash))
{
return Result.Failure<string>(new Error("Identity.InvalidCredentials", "Неверное имя пользователя или пароль."));
}
string token = _tokenProvider.Generate(user);
return Result.Success(token);
}
}

View File

@@ -0,0 +1,57 @@
using Vortex.Modules.Identity.Application.Abstractions;
using Vortex.Modules.Identity.Domain;
using Vortex.Shared.Kernel;
using BCrypt.Net;
namespace Vortex.Modules.Identity.Application.Users.Register;
/// <summary>
/// Команда для регистрации нового пользователя.
/// </summary>
public sealed record RegisterUserCommand(
string Username,
string Password,
string DisplayName,
string? Email,
string? Bio) : ICommand<Guid>;
/// <summary>
/// Обработчик команды регистрации.
/// </summary>
public sealed class RegisterUserCommandHandler : ICommandHandler<RegisterUserCommand, Guid>
{
private readonly IUserRepository _userRepository;
private readonly IIdentityUnitOfWork _unitOfWork;
public RegisterUserCommandHandler(IUserRepository userRepository, IIdentityUnitOfWork unitOfWork)
{
_userRepository = userRepository;
_unitOfWork = unitOfWork;
}
public async Task<Result<Guid>> Handle(RegisterUserCommand request, CancellationToken cancellationToken)
{
// 1. Проверка уникальности username
if (!await _userRepository.IsUsernameUniqueAsync(request.Username, cancellationToken))
{
return Result.Failure<Guid>(new Error("Identity.UsernameNotUnique", "Это имя пользователя уже занято."));
}
// 2. Хеширование пароля (здесь будет вызов сервиса, пока заглушка)
string passwordHash = BCrypt.Net.BCrypt.HashPassword(request.Password);
// 3. Создание сущности
var user = User.Create(
request.Username,
passwordHash,
request.DisplayName,
request.Email,
request.Bio);
// 4. Сохранение
_userRepository.Add(user);
await _unitOfWork.SaveChangesAsync(cancellationToken);
return Result.Success(user.Id);
}
}

View File

@@ -0,0 +1,6 @@
namespace Vortex.Modules.Identity;
public class Class1
{
}

View File

@@ -0,0 +1,39 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
using Microsoft.EntityFrameworkCore;
using Vortex.Modules.Identity.Infrastructure.Persistence;
using Vortex.Modules.Identity.Domain;
using Vortex.Modules.Identity.Application.Abstractions;
using Vortex.Modules.Identity.Infrastructure.Authentication;
using Vortex.Shared.Kernel;
namespace Vortex.Modules.Identity;
public static class DependencyInjection
{
/// <summary>
/// Регистрация сервисов модуля Identity.
/// </summary>
public static IServiceCollection AddIdentityModule(
this IServiceCollection services,
IConfiguration configuration)
{
// Настройка базы данных
string connectionString = configuration.GetConnectionString("Database")!;
services.AddDbContext<IdentityDbContext>(options =>
options.UseNpgsql(connectionString));
// Регистрация Unit of Work и Репозиториев
services.AddScoped<IIdentityUnitOfWork>(sp => sp.GetRequiredService<IdentityDbContext>());
services.AddScoped<IUserRepository, UserRepository>();
services.AddScoped<IJwtTokenProvider, JwtTokenProvider>();
services.AddScoped<IUserDisplayNameProvider, Vortex.Modules.Identity.Infrastructure.Services.UserDisplayNameProvider>();
// Регистрация MediatR для этого модуля
services.AddMediatR(config =>
config.RegisterServicesFromAssembly(typeof(DependencyInjection).Assembly));
return services;
}
}

View File

@@ -0,0 +1,34 @@
using Vortex.Shared.Kernel;
namespace Vortex.Modules.Identity.Domain;
public enum FriendshipStatus
{
Pending,
Accepted,
Declined
}
public sealed class Friendship : Entity<Guid>
{
public Guid UserId { get; private set; }
public Guid FriendId { get; private set; }
public FriendshipStatus Status { get; private set; }
public DateTime CreatedAt { get; private set; }
private Friendship(Guid id, Guid userId, Guid friendId, FriendshipStatus status) : base(id)
{
UserId = userId;
FriendId = friendId;
Status = status;
CreatedAt = DateTime.UtcNow;
}
public static Friendship Create(Guid userId, Guid friendId)
{
return new Friendship(Guid.NewGuid(), userId, friendId, FriendshipStatus.Pending);
}
public void Accept() => Status = FriendshipStatus.Accepted;
public void Decline() => Status = FriendshipStatus.Declined;
}

View File

@@ -0,0 +1,16 @@
using Vortex.Modules.Identity.Domain;
namespace Vortex.Modules.Identity.Domain;
/// <summary>
/// Интерфейс репозитория для работы с пользователями.
/// </summary>
public interface IUserRepository
{
Task<User?> GetByIdAsync(Guid id, CancellationToken cancellationToken = default);
Task<User?> GetByUsernameAsync(string username, CancellationToken cancellationToken = default);
Task<bool> IsUsernameUniqueAsync(string username, CancellationToken cancellationToken = default);
Task<List<User>> SearchUsersAsync(string query, CancellationToken cancellationToken = default);
void Add(User user);
void Update(User user);
}

View File

@@ -0,0 +1,30 @@
using Vortex.Shared.Kernel;
namespace Vortex.Modules.Identity.Domain;
public sealed class Story : Entity<Guid>
{
public Guid UserId { get; private set; }
public string Type { get; private set; } // text, image, video
public string? MediaUrl { get; private set; }
public string? Content { get; private set; }
public string? BgColor { get; private set; }
public DateTime CreatedAt { get; private set; }
public DateTime ExpiresAt { get; private set; }
private Story(Guid id, Guid userId, string type, string? mediaUrl, string? content, string? bgColor) : base(id)
{
UserId = userId;
Type = type;
MediaUrl = mediaUrl;
Content = content;
BgColor = bgColor;
CreatedAt = DateTime.UtcNow;
ExpiresAt = CreatedAt.AddDays(1);
}
public static Story Create(Guid userId, string type, string? mediaUrl, string? content, string? bgColor)
{
return new Story(Guid.NewGuid(), userId, type, mediaUrl, content, bgColor);
}
}

View File

@@ -0,0 +1,55 @@
using Vortex.Shared.Kernel;
namespace Vortex.Modules.Identity.Domain;
/// <summary>
/// Сущность пользователя в контексте идентификации (Identity).
/// </summary>
public sealed class User : AggregateRoot<Guid>
{
public string Username { get; private set; }
public string PasswordHash { get; private set; }
public string DisplayName { get; private set; }
public string? Email { get; private set; }
public string? Bio { get; private set; }
public string? Avatar { get; private set; }
public DateTime? Birthday { get; private set; }
public DateTime CreatedAt { get; private set; }
public bool HideStoryViews { get; private set; }
private User(Guid id, string username, string passwordHash, string displayName, string? email, string? bio = null)
: base(id)
{
Username = username;
PasswordHash = passwordHash;
DisplayName = displayName;
Email = email;
Bio = bio;
CreatedAt = DateTime.UtcNow;
}
/// <summary>
/// Фабричный метод для создания нового пользователя.
/// </summary>
public static User Create(string username, string passwordHash, string displayName, string? email = null, string? bio = null)
{
return new User(Guid.NewGuid(), username, passwordHash, displayName, email, bio);
}
public void UpdateProfile(string displayName, string? bio, DateTime? birthday)
{
DisplayName = displayName;
Bio = bio;
Birthday = birthday;
}
public void UpdateAvatar(string? avatarUrl)
{
Avatar = avatarUrl;
}
public void UpdateSettings(bool hideStoryViews)
{
HideStoryViews = hideStoryViews;
}
}

View File

@@ -0,0 +1,45 @@
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens;
using Vortex.Modules.Identity.Application.Abstractions;
using Vortex.Modules.Identity.Domain;
namespace Vortex.Modules.Identity.Infrastructure.Authentication;
public sealed class JwtTokenProvider : IJwtTokenProvider
{
private readonly IConfiguration _configuration;
public JwtTokenProvider(IConfiguration configuration)
{
_configuration = configuration;
}
public string Generate(User user)
{
var claims = new Claim[]
{
new(JwtRegisteredClaimNames.Sub, user.Id.ToString()),
new(JwtRegisteredClaimNames.UniqueName, user.Username),
new("name", user.DisplayName),
new(ClaimTypes.Name, user.DisplayName),
new("avatar", user.Avatar ?? string.Empty)
};
var secretKey = _configuration["Jwt:Secret"]!;
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secretKey));
var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken(
_configuration["Jwt:Issuer"],
_configuration["Jwt:Audience"],
claims,
null,
DateTime.UtcNow.AddMinutes(double.Parse(_configuration["Jwt:ExpiryInMinutes"] ?? "1440")),
credentials);
return new JwtSecurityTokenHandler().WriteToken(token);
}
}

View File

@@ -0,0 +1,87 @@
using MediatR;
using Microsoft.EntityFrameworkCore;
using Vortex.Shared.Kernel;
using Vortex.Modules.Identity.Domain;
using Vortex.Modules.Identity.Application.Abstractions;
namespace Vortex.Modules.Identity.Infrastructure.Persistence;
/// <summary>
/// Контекст базы данных для модуля Identity.
/// </summary>
public sealed class IdentityDbContext : DbContext, IIdentityUnitOfWork
{
private readonly IMediator _mediator;
public IdentityDbContext(DbContextOptions<IdentityDbContext> options, IMediator mediator)
: base(options)
{
_mediator = mediator;
}
public DbSet<User> Users => Set<User>();
public DbSet<Story> Stories => Set<Story>();
public DbSet<Friendship> Friendships => Set<Friendship>();
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.HasDefaultSchema("identity");
modelBuilder.Entity<Friendship>(builder =>
{
builder.ToTable("Friendships");
builder.HasKey(f => f.Id);
builder.HasIndex(f => new { f.UserId, f.FriendId }).IsUnique();
});
modelBuilder.Entity<Story>(builder =>
{
builder.ToTable("Stories");
builder.HasKey(s => s.Id);
builder.Property(s => s.Type).IsRequired();
});
modelBuilder.Entity<User>(builder =>
{
builder.ToTable("Users");
builder.HasKey(u => u.Id);
builder.Property(u => u.Username).IsRequired().HasMaxLength(50);
builder.HasIndex(u => u.Username).IsUnique();
builder.Property(u => u.PasswordHash).IsRequired();
builder.Property(u => u.DisplayName).HasMaxLength(100);
builder.Property(u => u.Email).HasMaxLength(255);
builder.Property(u => u.Bio).HasMaxLength(500);
builder.Property(u => u.Avatar).HasMaxLength(500);
builder.Property(u => u.Birthday);
builder.Property(u => u.CreatedAt).IsRequired();
builder.Property(u => u.HideStoryViews).HasDefaultValue(false);
});
}
public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
{
var domainEvents = ChangeTracker
.Entries<IAggregateRoot>()
.SelectMany(x =>
{
if (x.Entity is AggregateRoot<Guid> root)
{
var events = root.GetDomainEvents().ToList();
root.ClearDomainEvents();
return events;
}
return Enumerable.Empty<IDomainEvent>();
})
.ToList();
int result = await base.SaveChangesAsync(cancellationToken);
foreach (var domainEvent in domainEvents)
{
await _mediator.Publish(domainEvent, cancellationToken);
}
return result;
}
}

View File

@@ -0,0 +1,63 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using Vortex.Modules.Identity.Infrastructure.Persistence;
#nullable disable
namespace Vortex.Modules.Identity.Infrastructure.Persistence.Migrations
{
[DbContext(typeof(IdentityDbContext))]
[Migration("20260311180816_InitialIdentity")]
partial class InitialIdentity
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasDefaultSchema("identity")
.HasAnnotation("ProductVersion", "10.0.4")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("Vortex.Modules.Identity.Domain.User", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("DisplayName")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)");
b.Property<string>("Email")
.HasMaxLength(255)
.HasColumnType("character varying(255)");
b.Property<string>("PasswordHash")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Username")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.HasKey("Id");
b.HasIndex("Username")
.IsUnique();
b.ToTable("Users", "identity");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,49 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Vortex.Modules.Identity.Infrastructure.Persistence.Migrations
{
/// <inheritdoc />
public partial class InitialIdentity : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.EnsureSchema(
name: "identity");
migrationBuilder.CreateTable(
name: "Users",
schema: "identity",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
Username = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: false),
PasswordHash = table.Column<string>(type: "text", nullable: false),
DisplayName = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false),
Email = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Users", x => x.Id);
});
migrationBuilder.CreateIndex(
name: "IX_Users_Username",
schema: "identity",
table: "Users",
column: "Username",
unique: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Users",
schema: "identity");
}
}
}

View File

@@ -0,0 +1,136 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using Vortex.Modules.Identity.Infrastructure.Persistence;
#nullable disable
namespace Vortex.Modules.Identity.Infrastructure.Persistence.Migrations
{
[DbContext(typeof(IdentityDbContext))]
[Migration("20260311200839_UpdateIdentityWithNewFieldsAndTables")]
partial class UpdateIdentityWithNewFieldsAndTables
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasDefaultSchema("identity")
.HasAnnotation("ProductVersion", "10.0.4")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("Vortex.Modules.Identity.Domain.Friendship", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid>("FriendId")
.HasColumnType("uuid");
b.Property<int>("Status")
.HasColumnType("integer");
b.Property<Guid>("UserId")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("UserId", "FriendId")
.IsUnique();
b.ToTable("Friendships", "identity");
});
modelBuilder.Entity("Vortex.Modules.Identity.Domain.Story", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("BgColor")
.HasColumnType("text");
b.Property<string>("Content")
.HasColumnType("text");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<DateTime>("ExpiresAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("MediaUrl")
.HasColumnType("text");
b.Property<string>("Type")
.IsRequired()
.HasColumnType("text");
b.Property<Guid>("UserId")
.HasColumnType("uuid");
b.HasKey("Id");
b.ToTable("Stories", "identity");
});
modelBuilder.Entity("Vortex.Modules.Identity.Domain.User", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("Avatar")
.HasMaxLength(500)
.HasColumnType("character varying(500)");
b.Property<string>("Bio")
.HasMaxLength(500)
.HasColumnType("character varying(500)");
b.Property<DateTime?>("Birthday")
.HasColumnType("timestamp with time zone");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("DisplayName")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)");
b.Property<string>("Email")
.HasMaxLength(255)
.HasColumnType("character varying(255)");
b.Property<string>("PasswordHash")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Username")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.HasKey("Id");
b.HasIndex("Username")
.IsUnique();
b.ToTable("Users", "identity");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,120 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Vortex.Modules.Identity.Infrastructure.Persistence.Migrations
{
/// <inheritdoc />
public partial class UpdateIdentityWithNewFieldsAndTables : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "Avatar",
schema: "identity",
table: "Users",
type: "character varying(500)",
maxLength: 500,
nullable: true);
migrationBuilder.AddColumn<string>(
name: "Bio",
schema: "identity",
table: "Users",
type: "character varying(500)",
maxLength: 500,
nullable: true);
migrationBuilder.AddColumn<DateTime>(
name: "Birthday",
schema: "identity",
table: "Users",
type: "timestamp with time zone",
nullable: true);
migrationBuilder.AddColumn<DateTime>(
name: "CreatedAt",
schema: "identity",
table: "Users",
type: "timestamp with time zone",
nullable: false,
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
migrationBuilder.CreateTable(
name: "Friendships",
schema: "identity",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
UserId = table.Column<Guid>(type: "uuid", nullable: false),
FriendId = table.Column<Guid>(type: "uuid", nullable: false),
Status = table.Column<int>(type: "integer", nullable: false),
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Friendships", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Stories",
schema: "identity",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
UserId = table.Column<Guid>(type: "uuid", nullable: false),
Type = table.Column<string>(type: "text", nullable: false),
MediaUrl = table.Column<string>(type: "text", nullable: true),
Content = table.Column<string>(type: "text", nullable: true),
BgColor = table.Column<string>(type: "text", nullable: true),
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
ExpiresAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Stories", x => x.Id);
});
migrationBuilder.CreateIndex(
name: "IX_Friendships_UserId_FriendId",
schema: "identity",
table: "Friendships",
columns: new[] { "UserId", "FriendId" },
unique: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Friendships",
schema: "identity");
migrationBuilder.DropTable(
name: "Stories",
schema: "identity");
migrationBuilder.DropColumn(
name: "Avatar",
schema: "identity",
table: "Users");
migrationBuilder.DropColumn(
name: "Bio",
schema: "identity",
table: "Users");
migrationBuilder.DropColumn(
name: "Birthday",
schema: "identity",
table: "Users");
migrationBuilder.DropColumn(
name: "CreatedAt",
schema: "identity",
table: "Users");
}
}
}

View File

@@ -0,0 +1,141 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using Vortex.Modules.Identity.Infrastructure.Persistence;
#nullable disable
namespace Vortex.Modules.Identity.Infrastructure.Persistence.Migrations
{
[DbContext(typeof(IdentityDbContext))]
[Migration("20260311215347_AddHideStoryViewsToUser")]
partial class AddHideStoryViewsToUser
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasDefaultSchema("identity")
.HasAnnotation("ProductVersion", "10.0.4")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("Vortex.Modules.Identity.Domain.Friendship", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid>("FriendId")
.HasColumnType("uuid");
b.Property<int>("Status")
.HasColumnType("integer");
b.Property<Guid>("UserId")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("UserId", "FriendId")
.IsUnique();
b.ToTable("Friendships", "identity");
});
modelBuilder.Entity("Vortex.Modules.Identity.Domain.Story", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("BgColor")
.HasColumnType("text");
b.Property<string>("Content")
.HasColumnType("text");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<DateTime>("ExpiresAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("MediaUrl")
.HasColumnType("text");
b.Property<string>("Type")
.IsRequired()
.HasColumnType("text");
b.Property<Guid>("UserId")
.HasColumnType("uuid");
b.HasKey("Id");
b.ToTable("Stories", "identity");
});
modelBuilder.Entity("Vortex.Modules.Identity.Domain.User", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("Avatar")
.HasMaxLength(500)
.HasColumnType("character varying(500)");
b.Property<string>("Bio")
.HasMaxLength(500)
.HasColumnType("character varying(500)");
b.Property<DateTime?>("Birthday")
.HasColumnType("timestamp with time zone");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("DisplayName")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)");
b.Property<string>("Email")
.HasMaxLength(255)
.HasColumnType("character varying(255)");
b.Property<bool>("HideStoryViews")
.ValueGeneratedOnAdd()
.HasColumnType("boolean")
.HasDefaultValue(false);
b.Property<string>("PasswordHash")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Username")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.HasKey("Id");
b.HasIndex("Username")
.IsUnique();
b.ToTable("Users", "identity");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,31 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Vortex.Modules.Identity.Infrastructure.Persistence.Migrations
{
/// <inheritdoc />
public partial class AddHideStoryViewsToUser : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<bool>(
name: "HideStoryViews",
schema: "identity",
table: "Users",
type: "boolean",
nullable: false,
defaultValue: false);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "HideStoryViews",
schema: "identity",
table: "Users");
}
}
}

View File

@@ -0,0 +1,138 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using Vortex.Modules.Identity.Infrastructure.Persistence;
#nullable disable
namespace Vortex.Modules.Identity.Infrastructure.Persistence.Migrations
{
[DbContext(typeof(IdentityDbContext))]
partial class IdentityDbContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasDefaultSchema("identity")
.HasAnnotation("ProductVersion", "10.0.4")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("Vortex.Modules.Identity.Domain.Friendship", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<Guid>("FriendId")
.HasColumnType("uuid");
b.Property<int>("Status")
.HasColumnType("integer");
b.Property<Guid>("UserId")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("UserId", "FriendId")
.IsUnique();
b.ToTable("Friendships", "identity");
});
modelBuilder.Entity("Vortex.Modules.Identity.Domain.Story", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("BgColor")
.HasColumnType("text");
b.Property<string>("Content")
.HasColumnType("text");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<DateTime>("ExpiresAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("MediaUrl")
.HasColumnType("text");
b.Property<string>("Type")
.IsRequired()
.HasColumnType("text");
b.Property<Guid>("UserId")
.HasColumnType("uuid");
b.HasKey("Id");
b.ToTable("Stories", "identity");
});
modelBuilder.Entity("Vortex.Modules.Identity.Domain.User", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("Avatar")
.HasMaxLength(500)
.HasColumnType("character varying(500)");
b.Property<string>("Bio")
.HasMaxLength(500)
.HasColumnType("character varying(500)");
b.Property<DateTime?>("Birthday")
.HasColumnType("timestamp with time zone");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
b.Property<string>("DisplayName")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("character varying(100)");
b.Property<string>("Email")
.HasMaxLength(255)
.HasColumnType("character varying(255)");
b.Property<bool>("HideStoryViews")
.ValueGeneratedOnAdd()
.HasColumnType("boolean")
.HasDefaultValue(false);
b.Property<string>("PasswordHash")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Username")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)");
b.HasKey("Id");
b.HasIndex("Username")
.IsUnique();
b.ToTable("Users", "identity");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,51 @@
using Microsoft.EntityFrameworkCore;
using Vortex.Modules.Identity.Domain;
namespace Vortex.Modules.Identity.Infrastructure.Persistence;
/// <summary>
/// Реализация репозитория пользователей с использованием EF Core.
/// </summary>
public sealed class UserRepository : IUserRepository
{
private readonly IdentityDbContext _context;
public UserRepository(IdentityDbContext context)
{
_context = context;
}
public async Task<User?> GetByIdAsync(Guid id, CancellationToken cancellationToken = default)
{
return await _context.Users.FirstOrDefaultAsync(u => u.Id == id, cancellationToken);
}
public async Task<User?> GetByUsernameAsync(string username, CancellationToken cancellationToken = default)
{
return await _context.Users.FirstOrDefaultAsync(u => u.Username == username, cancellationToken);
}
public async Task<bool> IsUsernameUniqueAsync(string username, CancellationToken cancellationToken = default)
{
return !await _context.Users.AnyAsync(u => u.Username == username, cancellationToken);
}
public async Task<List<User>> SearchUsersAsync(string query, CancellationToken cancellationToken = default)
{
return await _context.Users
.Where(u => u.Username.ToLower().Contains(query.ToLower()) ||
(u.DisplayName != null && u.DisplayName.ToLower().Contains(query.ToLower())))
.Take(20)
.ToListAsync(cancellationToken);
}
public void Add(User user)
{
_context.Users.Add(user);
}
public void Update(User user)
{
_context.Users.Update(user);
}
}

View File

@@ -0,0 +1,27 @@
using Vortex.Shared.Kernel;
using Vortex.Modules.Identity.Domain;
namespace Vortex.Modules.Identity.Infrastructure.Services;
public sealed class UserDisplayNameProvider : IUserDisplayNameProvider
{
private readonly IUserRepository _userRepository;
public UserDisplayNameProvider(IUserRepository userRepository)
{
_userRepository = userRepository;
}
public async Task<string> GetDisplayNameAsync(Guid userId, CancellationToken ct = default)
{
var user = await _userRepository.GetByIdAsync(userId, ct);
return user?.DisplayName ?? "User";
}
public async Task<UserInfo?> GetUserInfoAsync(Guid userId, CancellationToken ct = default)
{
var user = await _userRepository.GetByIdAsync(userId, ct);
if (user == null) return null;
return new UserInfo(user.Id, user.Username, user.DisplayName, user.Avatar);
}
}

View File

@@ -0,0 +1,30 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Shared\Vortex.Shared.Kernel\Vortex.Shared.Kernel.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="BCrypt.Net-Next" Version="4.1.0" />
<PackageReference Include="MediatR" Version="12.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="10.0.4" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="10.0.4" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.4" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="10.0.4" />
<PackageReference Include="Microsoft.IdentityModel.Tokens" Version="8.16.0" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="10.0.0" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.16.0" />
</ItemGroup>
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,506 @@
{
"runtimeTarget": {
"name": ".NETCoreApp,Version=v10.0",
"signature": ""
},
"compilationOptions": {},
"targets": {
".NETCoreApp,Version=v10.0": {
"Vortex.Modules.Identity/1.0.0": {
"dependencies": {
"BCrypt.Net-Next": "4.1.0",
"MediatR": "12.0.1",
"Microsoft.EntityFrameworkCore": "10.0.4",
"Microsoft.EntityFrameworkCore.Relational": "10.0.4",
"Microsoft.Extensions.Configuration.Abstractions": "10.0.4",
"Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.4",
"Microsoft.Extensions.Options.ConfigurationExtensions": "10.0.4",
"Microsoft.IdentityModel.Tokens": "8.16.0",
"Npgsql.EntityFrameworkCore.PostgreSQL": "10.0.0",
"System.IdentityModel.Tokens.Jwt": "8.16.0",
"Vortex.Shared.Kernel": "1.0.0"
},
"runtime": {
"Vortex.Modules.Identity.dll": {}
}
},
"BCrypt.Net-Next/4.1.0": {
"runtime": {
"lib/net10.0/BCrypt.Net-Next.dll": {
"assemblyVersion": "4.1.0.0",
"fileVersion": "4.1.0.0"
}
}
},
"MediatR/12.0.1": {
"dependencies": {
"MediatR.Contracts": "2.0.1"
},
"runtime": {
"lib/net6.0/MediatR.dll": {
"assemblyVersion": "12.0.0.0",
"fileVersion": "12.0.1.0"
}
}
},
"MediatR.Contracts/2.0.1": {
"runtime": {
"lib/netstandard2.0/MediatR.Contracts.dll": {
"assemblyVersion": "2.0.1.0",
"fileVersion": "2.0.1.0"
}
}
},
"Microsoft.EntityFrameworkCore/10.0.4": {
"dependencies": {
"Microsoft.EntityFrameworkCore.Abstractions": "10.0.4",
"Microsoft.Extensions.Caching.Memory": "10.0.4",
"Microsoft.Extensions.Logging": "10.0.4"
},
"runtime": {
"lib/net10.0/Microsoft.EntityFrameworkCore.dll": {
"assemblyVersion": "10.0.4.0",
"fileVersion": "10.0.426.12010"
}
}
},
"Microsoft.EntityFrameworkCore.Abstractions/10.0.4": {
"runtime": {
"lib/net10.0/Microsoft.EntityFrameworkCore.Abstractions.dll": {
"assemblyVersion": "10.0.4.0",
"fileVersion": "10.0.426.12010"
}
}
},
"Microsoft.EntityFrameworkCore.Relational/10.0.4": {
"dependencies": {
"Microsoft.EntityFrameworkCore": "10.0.4",
"Microsoft.Extensions.Caching.Memory": "10.0.4",
"Microsoft.Extensions.Configuration.Abstractions": "10.0.4",
"Microsoft.Extensions.Logging": "10.0.4"
},
"runtime": {
"lib/net10.0/Microsoft.EntityFrameworkCore.Relational.dll": {
"assemblyVersion": "10.0.4.0",
"fileVersion": "10.0.426.12010"
}
}
},
"Microsoft.Extensions.Caching.Abstractions/10.0.4": {
"dependencies": {
"Microsoft.Extensions.Primitives": "10.0.4"
},
"runtime": {
"lib/net10.0/Microsoft.Extensions.Caching.Abstractions.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.426.12010"
}
}
},
"Microsoft.Extensions.Caching.Memory/10.0.4": {
"dependencies": {
"Microsoft.Extensions.Caching.Abstractions": "10.0.4",
"Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.4",
"Microsoft.Extensions.Logging.Abstractions": "10.0.4",
"Microsoft.Extensions.Options": "10.0.4",
"Microsoft.Extensions.Primitives": "10.0.4"
},
"runtime": {
"lib/net10.0/Microsoft.Extensions.Caching.Memory.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.426.12010"
}
}
},
"Microsoft.Extensions.Configuration/10.0.4": {
"dependencies": {
"Microsoft.Extensions.Configuration.Abstractions": "10.0.4",
"Microsoft.Extensions.Primitives": "10.0.4"
},
"runtime": {
"lib/net10.0/Microsoft.Extensions.Configuration.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.426.12010"
}
}
},
"Microsoft.Extensions.Configuration.Abstractions/10.0.4": {
"dependencies": {
"Microsoft.Extensions.Primitives": "10.0.4"
},
"runtime": {
"lib/net10.0/Microsoft.Extensions.Configuration.Abstractions.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.426.12010"
}
}
},
"Microsoft.Extensions.Configuration.Binder/10.0.4": {
"dependencies": {
"Microsoft.Extensions.Configuration": "10.0.4",
"Microsoft.Extensions.Configuration.Abstractions": "10.0.4"
},
"runtime": {
"lib/net10.0/Microsoft.Extensions.Configuration.Binder.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.426.12010"
}
}
},
"Microsoft.Extensions.DependencyInjection/10.0.4": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.4"
},
"runtime": {
"lib/net10.0/Microsoft.Extensions.DependencyInjection.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.426.12010"
}
}
},
"Microsoft.Extensions.DependencyInjection.Abstractions/10.0.4": {
"runtime": {
"lib/net10.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.426.12010"
}
}
},
"Microsoft.Extensions.Logging/10.0.4": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "10.0.4",
"Microsoft.Extensions.Logging.Abstractions": "10.0.4",
"Microsoft.Extensions.Options": "10.0.4"
},
"runtime": {
"lib/net10.0/Microsoft.Extensions.Logging.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.426.12010"
}
}
},
"Microsoft.Extensions.Logging.Abstractions/10.0.4": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.4"
},
"runtime": {
"lib/net10.0/Microsoft.Extensions.Logging.Abstractions.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.426.12010"
}
}
},
"Microsoft.Extensions.Options/10.0.4": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.4",
"Microsoft.Extensions.Primitives": "10.0.4"
},
"runtime": {
"lib/net10.0/Microsoft.Extensions.Options.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.426.12010"
}
}
},
"Microsoft.Extensions.Options.ConfigurationExtensions/10.0.4": {
"dependencies": {
"Microsoft.Extensions.Configuration.Abstractions": "10.0.4",
"Microsoft.Extensions.Configuration.Binder": "10.0.4",
"Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.4",
"Microsoft.Extensions.Options": "10.0.4",
"Microsoft.Extensions.Primitives": "10.0.4"
},
"runtime": {
"lib/net10.0/Microsoft.Extensions.Options.ConfigurationExtensions.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.426.12010"
}
}
},
"Microsoft.Extensions.Primitives/10.0.4": {
"runtime": {
"lib/net10.0/Microsoft.Extensions.Primitives.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.426.12010"
}
}
},
"Microsoft.IdentityModel.Abstractions/8.16.0": {
"runtime": {
"lib/net10.0/Microsoft.IdentityModel.Abstractions.dll": {
"assemblyVersion": "8.16.0.0",
"fileVersion": "8.16.0.26043"
}
}
},
"Microsoft.IdentityModel.JsonWebTokens/8.16.0": {
"dependencies": {
"Microsoft.IdentityModel.Tokens": "8.16.0"
},
"runtime": {
"lib/net10.0/Microsoft.IdentityModel.JsonWebTokens.dll": {
"assemblyVersion": "8.16.0.0",
"fileVersion": "8.16.0.26043"
}
}
},
"Microsoft.IdentityModel.Logging/8.16.0": {
"dependencies": {
"Microsoft.IdentityModel.Abstractions": "8.16.0"
},
"runtime": {
"lib/net10.0/Microsoft.IdentityModel.Logging.dll": {
"assemblyVersion": "8.16.0.0",
"fileVersion": "8.16.0.26043"
}
}
},
"Microsoft.IdentityModel.Tokens/8.16.0": {
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "10.0.4",
"Microsoft.IdentityModel.Logging": "8.16.0"
},
"runtime": {
"lib/net10.0/Microsoft.IdentityModel.Tokens.dll": {
"assemblyVersion": "8.16.0.0",
"fileVersion": "8.16.0.26043"
}
}
},
"Npgsql/10.0.0": {
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "10.0.4"
},
"runtime": {
"lib/net10.0/Npgsql.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.0.0"
}
}
},
"Npgsql.EntityFrameworkCore.PostgreSQL/10.0.0": {
"dependencies": {
"Microsoft.EntityFrameworkCore": "10.0.4",
"Microsoft.EntityFrameworkCore.Relational": "10.0.4",
"Npgsql": "10.0.0"
},
"runtime": {
"lib/net10.0/Npgsql.EntityFrameworkCore.PostgreSQL.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.0.0"
}
}
},
"System.IdentityModel.Tokens.Jwt/8.16.0": {
"dependencies": {
"Microsoft.IdentityModel.JsonWebTokens": "8.16.0",
"Microsoft.IdentityModel.Tokens": "8.16.0"
},
"runtime": {
"lib/net10.0/System.IdentityModel.Tokens.Jwt.dll": {
"assemblyVersion": "8.16.0.0",
"fileVersion": "8.16.0.26043"
}
}
},
"Vortex.Shared.Kernel/1.0.0": {
"dependencies": {
"MediatR": "12.0.1"
},
"runtime": {
"Vortex.Shared.Kernel.dll": {
"assemblyVersion": "1.0.0.0",
"fileVersion": "1.0.0.0"
}
}
}
}
},
"libraries": {
"Vortex.Modules.Identity/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"BCrypt.Net-Next/4.1.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-5YT3DKllmtkyW68PjURu/V1TOe4MKiByKwsRNVcfYE1S5KuFTeozdmKzyNzolKiQF391OXCaQtINvYT3j1ERzQ==",
"path": "bcrypt.net-next/4.1.0",
"hashPath": "bcrypt.net-next.4.1.0.nupkg.sha512"
},
"MediatR/12.0.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-vfxplMielft+g5jxGO31xjjQpI6yqe4r2YGt0Q8x23phwbpJNmUQGY+cCNNFMKKViXRM67ajUlAiwirMeuJWTQ==",
"path": "mediatr/12.0.1",
"hashPath": "mediatr.12.0.1.nupkg.sha512"
},
"MediatR.Contracts/2.0.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-FYv95bNT4UwcNA+G/J1oX5OpRiSUxteXaUt2BJbRSdRNiIUNbggJF69wy6mnk2wYToaanpdXZdCwVylt96MpwQ==",
"path": "mediatr.contracts/2.0.1",
"hashPath": "mediatr.contracts.2.0.1.nupkg.sha512"
},
"Microsoft.EntityFrameworkCore/10.0.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-kzTsfFK2GCytp6DDTfQOmxPU4gbGdrIlP7PxrxF3ESNLtfXrC8BoUVZENBN2WORlZPAD7CVX6AYIglgkpXQooA==",
"path": "microsoft.entityframeworkcore/10.0.4",
"hashPath": "microsoft.entityframeworkcore.10.0.4.nupkg.sha512"
},
"Microsoft.EntityFrameworkCore.Abstractions/10.0.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-qDcJqCfN1XYyX0ID/Hd9/kQTRvlia8S+Yuwyl9uFhBIKnOCbl9WMdGQCzbZUKbkpkfvf3P9CDdXsnxHyE3O0Aw==",
"path": "microsoft.entityframeworkcore.abstractions/10.0.4",
"hashPath": "microsoft.entityframeworkcore.abstractions.10.0.4.nupkg.sha512"
},
"Microsoft.EntityFrameworkCore.Relational/10.0.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-DOTjTHy93W3TwpMLM4SCm0n57Sc0Jj3+m2S6LSTstKyBB34eT1UouaMS19mpWwvtj42+sRiEjA3+rOTNoNzXFQ==",
"path": "microsoft.entityframeworkcore.relational/10.0.4",
"hashPath": "microsoft.entityframeworkcore.relational.10.0.4.nupkg.sha512"
},
"Microsoft.Extensions.Caching.Abstractions/10.0.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-uDRooaV6N3WZ0kdlNPMB68/MdGn/in1Fs7Db7DnIm85RBTPy4P321WO+daAImiYpH5dekjNggDqy1N44WaIlMA==",
"path": "microsoft.extensions.caching.abstractions/10.0.4",
"hashPath": "microsoft.extensions.caching.abstractions.10.0.4.nupkg.sha512"
},
"Microsoft.Extensions.Caching.Memory/10.0.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-CLLussNUMdSbyJOu4VBF7sqskHGB/5N1EcFzrqG/HsPATN8fCRUcfp0qns1VwkxKHwxrtYCh5FKe+kM81Q1PHA==",
"path": "microsoft.extensions.caching.memory/10.0.4",
"hashPath": "microsoft.extensions.caching.memory.10.0.4.nupkg.sha512"
},
"Microsoft.Extensions.Configuration/10.0.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-601B3ha6XvOsOcu9GVd2dVd1KEDuqr49r46GUWhNJkeZDhZ/NI9EYTyoeQjZQEi8ZUvnrv++FbTfGmC8F0vgtg==",
"path": "microsoft.extensions.configuration/10.0.4",
"hashPath": "microsoft.extensions.configuration.10.0.4.nupkg.sha512"
},
"Microsoft.Extensions.Configuration.Abstractions/10.0.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-3x9X9SMAMdAoEwWxHfsT2a9dTBqEtfYfbEOFw+UPtBshEH2gHWJeazxrZ1FK1O18MoCbe1NxINg5qciB01pEcg==",
"path": "microsoft.extensions.configuration.abstractions/10.0.4",
"hashPath": "microsoft.extensions.configuration.abstractions.10.0.4.nupkg.sha512"
},
"Microsoft.Extensions.Configuration.Binder/10.0.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-ilnL/kQn62Gx3OZCVT7SJrBNi0CRIhS8VEunmE6i/a9lp9l/eos+hpxMvCW4iX2aVc/NWeDhxuQusZL7zvmKIg==",
"path": "microsoft.extensions.configuration.binder/10.0.4",
"hashPath": "microsoft.extensions.configuration.binder.10.0.4.nupkg.sha512"
},
"Microsoft.Extensions.DependencyInjection/10.0.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-NkvJ8aSr3AG30yabjv7ZWwTG/wq5OElNTlNq39Ok2HSEF3TIwAc1f1xnTJlR/GuoJmEgkfT7WBO9YbSXRk41+g==",
"path": "microsoft.extensions.dependencyinjection/10.0.4",
"hashPath": "microsoft.extensions.dependencyinjection.10.0.4.nupkg.sha512"
},
"Microsoft.Extensions.DependencyInjection.Abstractions/10.0.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-SIe9zlVQJecnk/DTmevIcl6+aEDYhoVLc2eG2AKwVeNEC8CSyxHAbh4lf0xtHq9JUum0vVTEByGNTK+b6oihTQ==",
"path": "microsoft.extensions.dependencyinjection.abstractions/10.0.4",
"hashPath": "microsoft.extensions.dependencyinjection.abstractions.10.0.4.nupkg.sha512"
},
"Microsoft.Extensions.Logging/10.0.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-S8+6fCuMOhJZGk8sGFtOy3VsF9mk9x4UOL59GM91REiA/fmCDjunKKIw4RmStG87qyXPfxelDJf2pXIbTuaBdw==",
"path": "microsoft.extensions.logging/10.0.4",
"hashPath": "microsoft.extensions.logging.10.0.4.nupkg.sha512"
},
"Microsoft.Extensions.Logging.Abstractions/10.0.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-PDMMt7fvBatv6hcxxyJtXIzSwn7Dy00W6I2vDAOTYrQqNM2dF5A2L9n0uMzdPz2IPoNZWkAmYjoOCEdDLq0i4w==",
"path": "microsoft.extensions.logging.abstractions/10.0.4",
"hashPath": "microsoft.extensions.logging.abstractions.10.0.4.nupkg.sha512"
},
"Microsoft.Extensions.Options/10.0.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-kRxa2Zjzhg/ohh7EklpqQpBIcyQnC3meWxCcpZBn+0QWy/fY1DmDd45JiW8Vyrpj2J1RDtau5yRHiLZS/AoxUw==",
"path": "microsoft.extensions.options/10.0.4",
"hashPath": "microsoft.extensions.options.10.0.4.nupkg.sha512"
},
"Microsoft.Extensions.Options.ConfigurationExtensions/10.0.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-amQUITwSnkbMPxh/ngneNykz4UtytEOXo0M/pbwdBiQU57EAVvBV5PFI8r/dRastUj0yxHVwrH64N9ACR5SdGQ==",
"path": "microsoft.extensions.options.configurationextensions/10.0.4",
"hashPath": "microsoft.extensions.options.configurationextensions.10.0.4.nupkg.sha512"
},
"Microsoft.Extensions.Primitives/10.0.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-lABYqiRH9HgYJsjzO3W7+cucUwWXhEkiyrRylANdIubnzcESlkIsLowXpQ4E+sc7kjMLbk1hk5oxw4qTKowTEg==",
"path": "microsoft.extensions.primitives/10.0.4",
"hashPath": "microsoft.extensions.primitives.10.0.4.nupkg.sha512"
},
"Microsoft.IdentityModel.Abstractions/8.16.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-gSxKLWRZzBpIsEoeUPkxfywNCCvRvl7hkq146XHPk5vOQc9izSf1I+uL1vh4y2U19QPxd9Z8K/8AdWyxYz2lSg==",
"path": "microsoft.identitymodel.abstractions/8.16.0",
"hashPath": "microsoft.identitymodel.abstractions.8.16.0.nupkg.sha512"
},
"Microsoft.IdentityModel.JsonWebTokens/8.16.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-prBU72cIP4V8E9fhN+o/YdskTsLeIcnKPbhZf0X6mD7fdxoZqnS/NdEkSr+9Zp+2q7OZBOMfNBKGbTbhXODO4w==",
"path": "microsoft.identitymodel.jsonwebtokens/8.16.0",
"hashPath": "microsoft.identitymodel.jsonwebtokens.8.16.0.nupkg.sha512"
},
"Microsoft.IdentityModel.Logging/8.16.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-MTzXmETkNQPACR7/XCXM1OGM6oU9RkyibqeJRtO9Ndew2LnGjMf9Atqj2VSf4XC27X0FQycUAlzxxEgQMWn2xQ==",
"path": "microsoft.identitymodel.logging/8.16.0",
"hashPath": "microsoft.identitymodel.logging.8.16.0.nupkg.sha512"
},
"Microsoft.IdentityModel.Tokens/8.16.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-rtViGJcGsN7WcfUNErwNeQgjuU5cJNl6FDQsfi9TncwO+Epzn0FTfBsg3YuFW1Q0Ch/KPxaVdjLw3/+5Z5ceFQ==",
"path": "microsoft.identitymodel.tokens/8.16.0",
"hashPath": "microsoft.identitymodel.tokens.8.16.0.nupkg.sha512"
},
"Npgsql/10.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-xZAYhPOU2rUIFpV48xsqhCx9vXs6Y+0jX2LCoSEfDFYMw9jtAOUk3iQsCnDLrFIv9NT3JGMihn7nnuZsPKqJmA==",
"path": "npgsql/10.0.0",
"hashPath": "npgsql.10.0.0.nupkg.sha512"
},
"Npgsql.EntityFrameworkCore.PostgreSQL/10.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-E2+uSWxSB8LdsUVwPaqRWOcGOP92biry2JEwc0KJMdLJF+aZdczeIdEXVwEyv4nSVMQJH0o8tLhyAMiR6VF0lw==",
"path": "npgsql.entityframeworkcore.postgresql/10.0.0",
"hashPath": "npgsql.entityframeworkcore.postgresql.10.0.0.nupkg.sha512"
},
"System.IdentityModel.Tokens.Jwt/8.16.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-rrs2u7DRMXQG2yh0oVyF/vLwosfRv20Ld2iEpYcKwQWXHjfV+gFXNQsQ9p008kR9Ou4pxBs68Q6/9zC8Gi1wjg==",
"path": "system.identitymodel.tokens.jwt/8.16.0",
"hashPath": "system.identitymodel.tokens.jwt.8.16.0.nupkg.sha512"
},
"Vortex.Shared.Kernel/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
}
}
}

View File

@@ -0,0 +1,506 @@
{
"runtimeTarget": {
"name": ".NETCoreApp,Version=v10.0",
"signature": ""
},
"compilationOptions": {},
"targets": {
".NETCoreApp,Version=v10.0": {
"Vortex.Modules.Identity/1.0.0": {
"dependencies": {
"BCrypt.Net-Next": "4.1.0",
"MediatR": "12.0.1",
"Microsoft.EntityFrameworkCore": "10.0.4",
"Microsoft.EntityFrameworkCore.Relational": "10.0.4",
"Microsoft.Extensions.Configuration.Abstractions": "10.0.4",
"Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.4",
"Microsoft.Extensions.Options.ConfigurationExtensions": "10.0.4",
"Microsoft.IdentityModel.Tokens": "8.16.0",
"Npgsql.EntityFrameworkCore.PostgreSQL": "10.0.0",
"System.IdentityModel.Tokens.Jwt": "8.16.0",
"Vortex.Shared.Kernel": "1.0.0"
},
"runtime": {
"Vortex.Modules.Identity.dll": {}
}
},
"BCrypt.Net-Next/4.1.0": {
"runtime": {
"lib/net10.0/BCrypt.Net-Next.dll": {
"assemblyVersion": "4.1.0.0",
"fileVersion": "4.1.0.0"
}
}
},
"MediatR/12.0.1": {
"dependencies": {
"MediatR.Contracts": "2.0.1"
},
"runtime": {
"lib/net6.0/MediatR.dll": {
"assemblyVersion": "12.0.0.0",
"fileVersion": "12.0.1.0"
}
}
},
"MediatR.Contracts/2.0.1": {
"runtime": {
"lib/netstandard2.0/MediatR.Contracts.dll": {
"assemblyVersion": "2.0.1.0",
"fileVersion": "2.0.1.0"
}
}
},
"Microsoft.EntityFrameworkCore/10.0.4": {
"dependencies": {
"Microsoft.EntityFrameworkCore.Abstractions": "10.0.4",
"Microsoft.Extensions.Caching.Memory": "10.0.4",
"Microsoft.Extensions.Logging": "10.0.4"
},
"runtime": {
"lib/net10.0/Microsoft.EntityFrameworkCore.dll": {
"assemblyVersion": "10.0.4.0",
"fileVersion": "10.0.426.12010"
}
}
},
"Microsoft.EntityFrameworkCore.Abstractions/10.0.4": {
"runtime": {
"lib/net10.0/Microsoft.EntityFrameworkCore.Abstractions.dll": {
"assemblyVersion": "10.0.4.0",
"fileVersion": "10.0.426.12010"
}
}
},
"Microsoft.EntityFrameworkCore.Relational/10.0.4": {
"dependencies": {
"Microsoft.EntityFrameworkCore": "10.0.4",
"Microsoft.Extensions.Caching.Memory": "10.0.4",
"Microsoft.Extensions.Configuration.Abstractions": "10.0.4",
"Microsoft.Extensions.Logging": "10.0.4"
},
"runtime": {
"lib/net10.0/Microsoft.EntityFrameworkCore.Relational.dll": {
"assemblyVersion": "10.0.4.0",
"fileVersion": "10.0.426.12010"
}
}
},
"Microsoft.Extensions.Caching.Abstractions/10.0.4": {
"dependencies": {
"Microsoft.Extensions.Primitives": "10.0.4"
},
"runtime": {
"lib/net10.0/Microsoft.Extensions.Caching.Abstractions.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.426.12010"
}
}
},
"Microsoft.Extensions.Caching.Memory/10.0.4": {
"dependencies": {
"Microsoft.Extensions.Caching.Abstractions": "10.0.4",
"Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.4",
"Microsoft.Extensions.Logging.Abstractions": "10.0.4",
"Microsoft.Extensions.Options": "10.0.4",
"Microsoft.Extensions.Primitives": "10.0.4"
},
"runtime": {
"lib/net10.0/Microsoft.Extensions.Caching.Memory.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.426.12010"
}
}
},
"Microsoft.Extensions.Configuration/10.0.4": {
"dependencies": {
"Microsoft.Extensions.Configuration.Abstractions": "10.0.4",
"Microsoft.Extensions.Primitives": "10.0.4"
},
"runtime": {
"lib/net10.0/Microsoft.Extensions.Configuration.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.426.12010"
}
}
},
"Microsoft.Extensions.Configuration.Abstractions/10.0.4": {
"dependencies": {
"Microsoft.Extensions.Primitives": "10.0.4"
},
"runtime": {
"lib/net10.0/Microsoft.Extensions.Configuration.Abstractions.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.426.12010"
}
}
},
"Microsoft.Extensions.Configuration.Binder/10.0.4": {
"dependencies": {
"Microsoft.Extensions.Configuration": "10.0.4",
"Microsoft.Extensions.Configuration.Abstractions": "10.0.4"
},
"runtime": {
"lib/net10.0/Microsoft.Extensions.Configuration.Binder.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.426.12010"
}
}
},
"Microsoft.Extensions.DependencyInjection/10.0.4": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.4"
},
"runtime": {
"lib/net10.0/Microsoft.Extensions.DependencyInjection.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.426.12010"
}
}
},
"Microsoft.Extensions.DependencyInjection.Abstractions/10.0.4": {
"runtime": {
"lib/net10.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.426.12010"
}
}
},
"Microsoft.Extensions.Logging/10.0.4": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "10.0.4",
"Microsoft.Extensions.Logging.Abstractions": "10.0.4",
"Microsoft.Extensions.Options": "10.0.4"
},
"runtime": {
"lib/net10.0/Microsoft.Extensions.Logging.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.426.12010"
}
}
},
"Microsoft.Extensions.Logging.Abstractions/10.0.4": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.4"
},
"runtime": {
"lib/net10.0/Microsoft.Extensions.Logging.Abstractions.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.426.12010"
}
}
},
"Microsoft.Extensions.Options/10.0.4": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.4",
"Microsoft.Extensions.Primitives": "10.0.4"
},
"runtime": {
"lib/net10.0/Microsoft.Extensions.Options.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.426.12010"
}
}
},
"Microsoft.Extensions.Options.ConfigurationExtensions/10.0.4": {
"dependencies": {
"Microsoft.Extensions.Configuration.Abstractions": "10.0.4",
"Microsoft.Extensions.Configuration.Binder": "10.0.4",
"Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.4",
"Microsoft.Extensions.Options": "10.0.4",
"Microsoft.Extensions.Primitives": "10.0.4"
},
"runtime": {
"lib/net10.0/Microsoft.Extensions.Options.ConfigurationExtensions.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.426.12010"
}
}
},
"Microsoft.Extensions.Primitives/10.0.4": {
"runtime": {
"lib/net10.0/Microsoft.Extensions.Primitives.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.426.12010"
}
}
},
"Microsoft.IdentityModel.Abstractions/8.16.0": {
"runtime": {
"lib/net10.0/Microsoft.IdentityModel.Abstractions.dll": {
"assemblyVersion": "8.16.0.0",
"fileVersion": "8.16.0.26043"
}
}
},
"Microsoft.IdentityModel.JsonWebTokens/8.16.0": {
"dependencies": {
"Microsoft.IdentityModel.Tokens": "8.16.0"
},
"runtime": {
"lib/net10.0/Microsoft.IdentityModel.JsonWebTokens.dll": {
"assemblyVersion": "8.16.0.0",
"fileVersion": "8.16.0.26043"
}
}
},
"Microsoft.IdentityModel.Logging/8.16.0": {
"dependencies": {
"Microsoft.IdentityModel.Abstractions": "8.16.0"
},
"runtime": {
"lib/net10.0/Microsoft.IdentityModel.Logging.dll": {
"assemblyVersion": "8.16.0.0",
"fileVersion": "8.16.0.26043"
}
}
},
"Microsoft.IdentityModel.Tokens/8.16.0": {
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "10.0.4",
"Microsoft.IdentityModel.Logging": "8.16.0"
},
"runtime": {
"lib/net10.0/Microsoft.IdentityModel.Tokens.dll": {
"assemblyVersion": "8.16.0.0",
"fileVersion": "8.16.0.26043"
}
}
},
"Npgsql/10.0.0": {
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "10.0.4"
},
"runtime": {
"lib/net10.0/Npgsql.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.0.0"
}
}
},
"Npgsql.EntityFrameworkCore.PostgreSQL/10.0.0": {
"dependencies": {
"Microsoft.EntityFrameworkCore": "10.0.4",
"Microsoft.EntityFrameworkCore.Relational": "10.0.4",
"Npgsql": "10.0.0"
},
"runtime": {
"lib/net10.0/Npgsql.EntityFrameworkCore.PostgreSQL.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.0.0"
}
}
},
"System.IdentityModel.Tokens.Jwt/8.16.0": {
"dependencies": {
"Microsoft.IdentityModel.JsonWebTokens": "8.16.0",
"Microsoft.IdentityModel.Tokens": "8.16.0"
},
"runtime": {
"lib/net10.0/System.IdentityModel.Tokens.Jwt.dll": {
"assemblyVersion": "8.16.0.0",
"fileVersion": "8.16.0.26043"
}
}
},
"Vortex.Shared.Kernel/1.0.0": {
"dependencies": {
"MediatR": "12.0.1"
},
"runtime": {
"Vortex.Shared.Kernel.dll": {
"assemblyVersion": "1.0.0.0",
"fileVersion": "1.0.0.0"
}
}
}
}
},
"libraries": {
"Vortex.Modules.Identity/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"BCrypt.Net-Next/4.1.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-5YT3DKllmtkyW68PjURu/V1TOe4MKiByKwsRNVcfYE1S5KuFTeozdmKzyNzolKiQF391OXCaQtINvYT3j1ERzQ==",
"path": "bcrypt.net-next/4.1.0",
"hashPath": "bcrypt.net-next.4.1.0.nupkg.sha512"
},
"MediatR/12.0.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-vfxplMielft+g5jxGO31xjjQpI6yqe4r2YGt0Q8x23phwbpJNmUQGY+cCNNFMKKViXRM67ajUlAiwirMeuJWTQ==",
"path": "mediatr/12.0.1",
"hashPath": "mediatr.12.0.1.nupkg.sha512"
},
"MediatR.Contracts/2.0.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-FYv95bNT4UwcNA+G/J1oX5OpRiSUxteXaUt2BJbRSdRNiIUNbggJF69wy6mnk2wYToaanpdXZdCwVylt96MpwQ==",
"path": "mediatr.contracts/2.0.1",
"hashPath": "mediatr.contracts.2.0.1.nupkg.sha512"
},
"Microsoft.EntityFrameworkCore/10.0.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-kzTsfFK2GCytp6DDTfQOmxPU4gbGdrIlP7PxrxF3ESNLtfXrC8BoUVZENBN2WORlZPAD7CVX6AYIglgkpXQooA==",
"path": "microsoft.entityframeworkcore/10.0.4",
"hashPath": "microsoft.entityframeworkcore.10.0.4.nupkg.sha512"
},
"Microsoft.EntityFrameworkCore.Abstractions/10.0.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-qDcJqCfN1XYyX0ID/Hd9/kQTRvlia8S+Yuwyl9uFhBIKnOCbl9WMdGQCzbZUKbkpkfvf3P9CDdXsnxHyE3O0Aw==",
"path": "microsoft.entityframeworkcore.abstractions/10.0.4",
"hashPath": "microsoft.entityframeworkcore.abstractions.10.0.4.nupkg.sha512"
},
"Microsoft.EntityFrameworkCore.Relational/10.0.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-DOTjTHy93W3TwpMLM4SCm0n57Sc0Jj3+m2S6LSTstKyBB34eT1UouaMS19mpWwvtj42+sRiEjA3+rOTNoNzXFQ==",
"path": "microsoft.entityframeworkcore.relational/10.0.4",
"hashPath": "microsoft.entityframeworkcore.relational.10.0.4.nupkg.sha512"
},
"Microsoft.Extensions.Caching.Abstractions/10.0.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-uDRooaV6N3WZ0kdlNPMB68/MdGn/in1Fs7Db7DnIm85RBTPy4P321WO+daAImiYpH5dekjNggDqy1N44WaIlMA==",
"path": "microsoft.extensions.caching.abstractions/10.0.4",
"hashPath": "microsoft.extensions.caching.abstractions.10.0.4.nupkg.sha512"
},
"Microsoft.Extensions.Caching.Memory/10.0.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-CLLussNUMdSbyJOu4VBF7sqskHGB/5N1EcFzrqG/HsPATN8fCRUcfp0qns1VwkxKHwxrtYCh5FKe+kM81Q1PHA==",
"path": "microsoft.extensions.caching.memory/10.0.4",
"hashPath": "microsoft.extensions.caching.memory.10.0.4.nupkg.sha512"
},
"Microsoft.Extensions.Configuration/10.0.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-601B3ha6XvOsOcu9GVd2dVd1KEDuqr49r46GUWhNJkeZDhZ/NI9EYTyoeQjZQEi8ZUvnrv++FbTfGmC8F0vgtg==",
"path": "microsoft.extensions.configuration/10.0.4",
"hashPath": "microsoft.extensions.configuration.10.0.4.nupkg.sha512"
},
"Microsoft.Extensions.Configuration.Abstractions/10.0.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-3x9X9SMAMdAoEwWxHfsT2a9dTBqEtfYfbEOFw+UPtBshEH2gHWJeazxrZ1FK1O18MoCbe1NxINg5qciB01pEcg==",
"path": "microsoft.extensions.configuration.abstractions/10.0.4",
"hashPath": "microsoft.extensions.configuration.abstractions.10.0.4.nupkg.sha512"
},
"Microsoft.Extensions.Configuration.Binder/10.0.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-ilnL/kQn62Gx3OZCVT7SJrBNi0CRIhS8VEunmE6i/a9lp9l/eos+hpxMvCW4iX2aVc/NWeDhxuQusZL7zvmKIg==",
"path": "microsoft.extensions.configuration.binder/10.0.4",
"hashPath": "microsoft.extensions.configuration.binder.10.0.4.nupkg.sha512"
},
"Microsoft.Extensions.DependencyInjection/10.0.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-NkvJ8aSr3AG30yabjv7ZWwTG/wq5OElNTlNq39Ok2HSEF3TIwAc1f1xnTJlR/GuoJmEgkfT7WBO9YbSXRk41+g==",
"path": "microsoft.extensions.dependencyinjection/10.0.4",
"hashPath": "microsoft.extensions.dependencyinjection.10.0.4.nupkg.sha512"
},
"Microsoft.Extensions.DependencyInjection.Abstractions/10.0.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-SIe9zlVQJecnk/DTmevIcl6+aEDYhoVLc2eG2AKwVeNEC8CSyxHAbh4lf0xtHq9JUum0vVTEByGNTK+b6oihTQ==",
"path": "microsoft.extensions.dependencyinjection.abstractions/10.0.4",
"hashPath": "microsoft.extensions.dependencyinjection.abstractions.10.0.4.nupkg.sha512"
},
"Microsoft.Extensions.Logging/10.0.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-S8+6fCuMOhJZGk8sGFtOy3VsF9mk9x4UOL59GM91REiA/fmCDjunKKIw4RmStG87qyXPfxelDJf2pXIbTuaBdw==",
"path": "microsoft.extensions.logging/10.0.4",
"hashPath": "microsoft.extensions.logging.10.0.4.nupkg.sha512"
},
"Microsoft.Extensions.Logging.Abstractions/10.0.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-PDMMt7fvBatv6hcxxyJtXIzSwn7Dy00W6I2vDAOTYrQqNM2dF5A2L9n0uMzdPz2IPoNZWkAmYjoOCEdDLq0i4w==",
"path": "microsoft.extensions.logging.abstractions/10.0.4",
"hashPath": "microsoft.extensions.logging.abstractions.10.0.4.nupkg.sha512"
},
"Microsoft.Extensions.Options/10.0.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-kRxa2Zjzhg/ohh7EklpqQpBIcyQnC3meWxCcpZBn+0QWy/fY1DmDd45JiW8Vyrpj2J1RDtau5yRHiLZS/AoxUw==",
"path": "microsoft.extensions.options/10.0.4",
"hashPath": "microsoft.extensions.options.10.0.4.nupkg.sha512"
},
"Microsoft.Extensions.Options.ConfigurationExtensions/10.0.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-amQUITwSnkbMPxh/ngneNykz4UtytEOXo0M/pbwdBiQU57EAVvBV5PFI8r/dRastUj0yxHVwrH64N9ACR5SdGQ==",
"path": "microsoft.extensions.options.configurationextensions/10.0.4",
"hashPath": "microsoft.extensions.options.configurationextensions.10.0.4.nupkg.sha512"
},
"Microsoft.Extensions.Primitives/10.0.4": {
"type": "package",
"serviceable": true,
"sha512": "sha512-lABYqiRH9HgYJsjzO3W7+cucUwWXhEkiyrRylANdIubnzcESlkIsLowXpQ4E+sc7kjMLbk1hk5oxw4qTKowTEg==",
"path": "microsoft.extensions.primitives/10.0.4",
"hashPath": "microsoft.extensions.primitives.10.0.4.nupkg.sha512"
},
"Microsoft.IdentityModel.Abstractions/8.16.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-gSxKLWRZzBpIsEoeUPkxfywNCCvRvl7hkq146XHPk5vOQc9izSf1I+uL1vh4y2U19QPxd9Z8K/8AdWyxYz2lSg==",
"path": "microsoft.identitymodel.abstractions/8.16.0",
"hashPath": "microsoft.identitymodel.abstractions.8.16.0.nupkg.sha512"
},
"Microsoft.IdentityModel.JsonWebTokens/8.16.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-prBU72cIP4V8E9fhN+o/YdskTsLeIcnKPbhZf0X6mD7fdxoZqnS/NdEkSr+9Zp+2q7OZBOMfNBKGbTbhXODO4w==",
"path": "microsoft.identitymodel.jsonwebtokens/8.16.0",
"hashPath": "microsoft.identitymodel.jsonwebtokens.8.16.0.nupkg.sha512"
},
"Microsoft.IdentityModel.Logging/8.16.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-MTzXmETkNQPACR7/XCXM1OGM6oU9RkyibqeJRtO9Ndew2LnGjMf9Atqj2VSf4XC27X0FQycUAlzxxEgQMWn2xQ==",
"path": "microsoft.identitymodel.logging/8.16.0",
"hashPath": "microsoft.identitymodel.logging.8.16.0.nupkg.sha512"
},
"Microsoft.IdentityModel.Tokens/8.16.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-rtViGJcGsN7WcfUNErwNeQgjuU5cJNl6FDQsfi9TncwO+Epzn0FTfBsg3YuFW1Q0Ch/KPxaVdjLw3/+5Z5ceFQ==",
"path": "microsoft.identitymodel.tokens/8.16.0",
"hashPath": "microsoft.identitymodel.tokens.8.16.0.nupkg.sha512"
},
"Npgsql/10.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-xZAYhPOU2rUIFpV48xsqhCx9vXs6Y+0jX2LCoSEfDFYMw9jtAOUk3iQsCnDLrFIv9NT3JGMihn7nnuZsPKqJmA==",
"path": "npgsql/10.0.0",
"hashPath": "npgsql.10.0.0.nupkg.sha512"
},
"Npgsql.EntityFrameworkCore.PostgreSQL/10.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-E2+uSWxSB8LdsUVwPaqRWOcGOP92biry2JEwc0KJMdLJF+aZdczeIdEXVwEyv4nSVMQJH0o8tLhyAMiR6VF0lw==",
"path": "npgsql.entityframeworkcore.postgresql/10.0.0",
"hashPath": "npgsql.entityframeworkcore.postgresql.10.0.0.nupkg.sha512"
},
"System.IdentityModel.Tokens.Jwt/8.16.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-rrs2u7DRMXQG2yh0oVyF/vLwosfRv20Ld2iEpYcKwQWXHjfV+gFXNQsQ9p008kR9Ou4pxBs68Q6/9zC8Gi1wjg==",
"path": "system.identitymodel.tokens.jwt/8.16.0",
"hashPath": "system.identitymodel.tokens.jwt.8.16.0.nupkg.sha512"
},
"Vortex.Shared.Kernel/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
}
}
}

View File

@@ -0,0 +1,4 @@
// <autogenerated />
using System;
using System.Reflection;
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v10.0", FrameworkDisplayName = ".NET 10.0")]

View File

@@ -0,0 +1,22 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("Vortex.Modules.Identity")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+50d4d75c04b5524c8439d9168f3a5a578f26d47c")]
[assembly: System.Reflection.AssemblyProductAttribute("Vortex.Modules.Identity")]
[assembly: System.Reflection.AssemblyTitleAttribute("Vortex.Modules.Identity")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
// Создано классом WriteCodeFragment MSBuild.

View File

@@ -0,0 +1 @@
59b2bed890c47b7093a9de6a348a05d0adb9ad9b7fdd786efe67aaec3a83cae8

View File

@@ -0,0 +1,17 @@
is_global = true
build_property.TargetFramework = net10.0
build_property.TargetFrameworkIdentifier = .NETCoreApp
build_property.TargetFrameworkVersion = v10.0
build_property.TargetPlatformMinVersion =
build_property.UsingMicrosoftNETSdkWeb =
build_property.ProjectTypeGuids =
build_property.InvariantGlobalization =
build_property.PlatformNeutralAssembly =
build_property.EnforceExtendedAnalyzerRules =
build_property._SupportedPlatformList = Linux,macOS,Windows
build_property.RootNamespace = Vortex.Modules.Identity
build_property.ProjectDir = E:\GIT\forkmessager\apps\server-net\src\Modules\Identity\
build_property.EnableComHosting =
build_property.EnableGeneratedComInterfaceComImportInterop =
build_property.EffectiveAnalysisLevelStyle = 10.0
build_property.EnableCodeStyleSeverity =

View File

@@ -0,0 +1,8 @@
// <auto-generated/>
global using System;
global using System.Collections.Generic;
global using System.IO;
global using System.Linq;
global using System.Net.Http;
global using System.Threading;
global using System.Threading.Tasks;

Some files were not shown because too many files have changed in this diff Show More