Сборка бэк

This commit is contained in:
Халимов Рустам
2026-03-27 15:45:34 +03:00
parent 16978c423c
commit 11f2b232a3
135 changed files with 2162 additions and 725 deletions

View File

@@ -1,98 +0,0 @@
using System.Text.Json;
using Knot.Shared.Infrastructure.Persistence;
using Knot.Shared.Infrastructure.Persistence.Entities;
using Knot.Shared.Kernel.Configuration;
using Knot.Shared.Kernel.Security;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
namespace Knot.Shared.Infrastructure.Configuration;
public class SettingsService : ISettingsService,
ISystemSettings,
IStoriesSettings,
IChatsSettings,
IMessagesSettings,
IWebRtcSettings,
IKlipySettings,
IImportSettings,
IFederationSettings
{
private readonly IServiceProvider _serviceProvider;
private readonly IEncryptionService _encryptionService;
private SystemSettingsDto _current;
public SettingsService(IServiceProvider serviceProvider, IEncryptionService encryptionService)
{
_serviceProvider = serviceProvider;
_encryptionService = encryptionService;
_current = new SystemSettingsDto(); // Default
}
public SystemSettingsDto Current => _current;
SystemConfig ISystemSettings.Current => _current.System;
StoriesConfig IStoriesSettings.Current => _current.Stories;
ChatsConfig IChatsSettings.Current => _current.Chats;
MessagesConfig IMessagesSettings.Current => _current.Messages;
WebRtcConfig IWebRtcSettings.Current => _current.WebRtc;
KlipyConfig IKlipySettings.Current => _current.Klipy;
ImportConfig IImportSettings.Current => _current.Import;
FederationConfig IFederationSettings.Current => _current.Federation;
public async Task<SystemSettingsDto> GetSettingsAsync(CancellationToken cancellationToken = default)
{
using var scope = _serviceProvider.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<SystemDbContext>();
var setting = await db.Settings.FirstOrDefaultAsync(s => s.Key == "Global", cancellationToken);
if (setting == null)
{
return new SystemSettingsDto();
}
try
{
var json = _encryptionService.DecryptMessage(setting.EncryptedValue);
var dto = JsonSerializer.Deserialize<SystemSettingsDto>(json);
if (dto != null)
{
_current = dto;
return dto;
}
}
catch
{
// If decryption fails or JSON is invalid, return default
}
return new SystemSettingsDto();
}
public async Task UpdateSettingsAsync(SystemSettingsDto settings, CancellationToken cancellationToken = default)
{
using var scope = _serviceProvider.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<SystemDbContext>();
var json = JsonSerializer.Serialize(settings);
var encrypted = _encryptionService.EncryptMessage(json);
var setting = await db.Settings.FirstOrDefaultAsync(s => s.Key == "Global", cancellationToken);
if (setting == null)
{
db.Settings.Add(new SystemSetting { Key = "Global", EncryptedValue = encrypted });
}
else
{
setting.EncryptedValue = encrypted;
}
await db.SaveChangesAsync(cancellationToken);
_current = settings; // Update in-memory reference
}
public void Initialize()
{
_current = GetSettingsAsync().GetAwaiter().GetResult();
}
}

View File

@@ -4,9 +4,7 @@ using Knot.Shared.Kernel;
using Knot.Shared.Kernel.Security;
using Knot.Shared.Kernel.Storage;
using Knot.Shared.Infrastructure.Persistence;
using Knot.Shared.Infrastructure.Configuration;
using Knot.Shared.Infrastructure.Statistics;
using Knot.Shared.Kernel.Configuration;
using Microsoft.EntityFrameworkCore;
using Minio;
using System;
@@ -38,17 +36,6 @@ public static class DependencyInjection
services.AddMemoryCache();
services.AddSingleton<SettingsService>();
services.AddSingleton<ISettingsService>(sp => sp.GetRequiredService<SettingsService>());
services.AddSingleton<ISystemSettings>(sp => sp.GetRequiredService<SettingsService>());
services.AddSingleton<IStoriesSettings>(sp => sp.GetRequiredService<SettingsService>());
services.AddSingleton<IChatsSettings>(sp => sp.GetRequiredService<SettingsService>());
services.AddSingleton<IMessagesSettings>(sp => sp.GetRequiredService<SettingsService>());
services.AddSingleton<IWebRtcSettings>(sp => sp.GetRequiredService<SettingsService>());
services.AddSingleton<IKlipySettings>(sp => sp.GetRequiredService<SettingsService>());
services.AddSingleton<IImportSettings>(sp => sp.GetRequiredService<SettingsService>());
services.AddSingleton<IFederationSettings>(sp => sp.GetRequiredService<SettingsService>());
services.AddScoped<Knot.Shared.Kernel.Services.IStatisticsService, StatisticsService>();
services.AddHostedService<StatisticsWorker>();

View File

@@ -28,3 +28,5 @@
</ItemGroup>
</Project>

View File

@@ -1,51 +0,0 @@
using System.Threading;
using System.Threading.Tasks;
namespace Knot.Shared.Kernel.Configuration;
public interface ISettingsService
{
Task<SystemSettingsDto> GetSettingsAsync(CancellationToken cancellationToken = default);
Task UpdateSettingsAsync(SystemSettingsDto settings, CancellationToken cancellationToken = default);
SystemSettingsDto Current { get; }
}
public interface ISystemSettings
{
SystemConfig Current { get; }
}
public interface IStoriesSettings
{
StoriesConfig Current { get; }
}
public interface IChatsSettings
{
ChatsConfig Current { get; }
}
public interface IMessagesSettings
{
MessagesConfig Current { get; }
}
public interface IWebRtcSettings
{
WebRtcConfig Current { get; }
}
public interface IKlipySettings
{
KlipyConfig Current { get; }
}
public interface IImportSettings
{
ImportConfig Current { get; }
}
public interface IFederationSettings
{
FederationConfig Current { get; }
}

View File

@@ -1,118 +0,0 @@
using System.Collections.Generic;
namespace Knot.Shared.Kernel.Configuration;
public class SystemConfig
{
public string ServerTimezone { get; set; } = "UTC";
public string DomainUrl { get; set; } = "https://example.com";
public string AdminRoute { get; set; } = "admin";
public bool EnableRegistration { get; set; } = true;
}
public class StoriesConfig
{
public bool Enabled { get; set; } = true;
public int MaxStoriesPerPeriod { get; set; } = 5; // 1 to 10
public int StoryLifetimeHours { get; set; } = 24; // 4 to 48
// Text Stories
public bool TextStoriesEnabled { get; set; } = true;
public int TextStoryDurationSeconds { get; set; } = 15; // 5 to 30
// Media Stories
public int MediaStoryMaxDurationSeconds { get; set; } = 30; // 5 to 60
public int MaxMediaSizeBytes { get; set; } = 15 * 1024 * 1024; // 15MB
}
public class ChatsConfig
{
public bool SupportGroups { get; set; } = true;
public int MaxGroupParticipants { get; set; } = 200000; // 5 to 1,000,000
public bool AutoCleanChats { get; set; } = false;
public bool AllowChatToGroupConversion { get; set; } = true;
public bool EnableFolders { get; set; } = true;
}
public class MessagesConfig
{
public int DailyMessageLimitPerUser { get; set; } = 0; // 0 = unlimited
public int ChatMessageLimit { get; set; } = 0; // 0 = unlimited
public bool AllowMedia { get; set; } = true;
public int MaxMediaSizeBytes { get; set; } = 50 * 1024 * 1024; // 50MB
public List<string> AllowedMediaTypes { get; set; } = new() { "image/jpeg", "image/png", "video/mp4", "image/gif" };
public bool AllowVoiceMessages { get; set; } = true;
public bool AllowForwarding { get; set; } = true;
public bool AllowReactions { get; set; } = true;
public bool AllowReplies { get; set; } = true;
public bool AllowQuoting { get; set; } = true;
public bool AllowMessageDeletion { get; set; } = true;
public bool ForbidCopying { get; set; } = false;
public bool AllowLinks { get; set; } = true;
public bool AllowPolls { get; set; } = true;
public bool AllowPinning { get; set; } = true;
}
public class WebRtcConfig
{
public bool Enabled { get; set; } = false;
public bool EnableVoiceCalls { get; set; } = true;
public bool EnableVideoCalls { get; set; } = true;
public bool EnableScreenSharing { get; set; } = true;
public string TurnHost { get; set; } = string.Empty;
public int TurnPort { get; set; } = 3478;
public string TurnUser { get; set; } = string.Empty;
public string TurnSecret { get; set; } = string.Empty;
}
public class KlipyConfig
{
public bool Enabled { get; set; } = false;
public string ApiKey { get; set; } = string.Empty;
public string AppName { get; set; } = string.Empty;
}
public class ImportConfig
{
public bool EnableTelegramImport { get; set; } = false;
}
public class FederationDomainConfig
{
public string Domain { get; set; } = string.Empty;
public bool IsEnabled { get; set; } = true;
public string? PublicKey { get; set; }
public RemoteCapabilities? Capabilities { get; set; }
}
public class RemoteCapabilities
{
public bool AllowMedia { get; set; }
public bool AllowPolls { get; set; }
public bool AllowVoiceMessages { get; set; }
public bool AllowVideoCalls { get; set; }
public bool AllowScreenSharing { get; set; }
}
public class FederationConfig
{
public bool Enabled { get; set; } = false;
public string ServerDescription { get; set; } = string.Empty; // 20 to 120 chars
public string? PrivateKey { get; set; } // RSA PEM
public string? PublicKey { get; set; } // RSA PEM
public List<FederationDomainConfig> AllowedDomains { get; set; } = new();
}
public class SystemSettingsDto
{
public SystemConfig System { get; set; } = new();
public StoriesConfig Stories { get; set; } = new();
public ChatsConfig Chats { get; set; } = new();
public MessagesConfig Messages { get; set; } = new();
public WebRtcConfig WebRtc { get; set; } = new();
public KlipyConfig Klipy { get; set; } = new();
public ImportConfig Import { get; set; } = new();
public FederationConfig Federation { get; set; } = new();
}

View File

@@ -0,0 +1,15 @@
using System;
using Knot.Shared.Kernel;
using MediatR;
namespace Knot.Shared.Kernel.Events;
/// <summary>
/// Domain event published when a new user is registered in the Identity system.
/// Handled by other modules to initialize their own data (e.g. Profiles, Notifications).
/// </summary>
public sealed record UserRegisteredDomainEvent(
Guid UserId,
string Username,
string DisplayName,
string? Bio) : IDomainEvent;

View File

@@ -11,3 +11,4 @@
</ItemGroup>
</Project>