using System; using System.Collections.Generic; using System.Linq; using System.Text.Json; using System.Threading; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Knot.Shared.Infrastructure.Persistence; using Knot.Shared.Infrastructure.Persistence.Entities; using Knot.Shared.Kernel.Security; using Knot.Contracts.Settings.Application.Abstractions; using Knot.Contracts.Settings.Application.DTOs; namespace Knot.Modules.Settings.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(); } 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 GetSettingsAsync(CancellationToken cancellationToken = default) { using var scope = _serviceProvider.CreateScope(); var db = scope.ServiceProvider.GetRequiredService(); 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(json); if (dto != null) { _current = dto; return dto; } } catch { // Fail safe } return new SystemSettingsDto(); } public async Task UpdateSettingsAsync(SystemSettingsDto settings, CancellationToken cancellationToken = default) { using var scope = _serviceProvider.CreateScope(); var db = scope.ServiceProvider.GetRequiredService(); 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; } public void Initialize() { _current = GetSettingsAsync().GetAwaiter().GetResult(); } }