using MessengerApi.Configuration.Model; using MessengerApi.Contracts.Factories; using MessengerApi.Db; using MessengerApi.Models; using System.Text; namespace MessengerApi.Handlers { // TODO: This needs to be redone, because at every run, it wipes users and creates new ones. This makes // all existing DB messages unassignable. public class UserSetupHandler { private readonly MessengerConfiguration configuration; private readonly ILogger logger; private readonly IDbContextFactory dbContextFactory; public UserSetupHandler( MessengerConfiguration configuration, ILogger logger, IDbContextFactory dbContextFactory) { this.configuration = configuration; this.logger = logger; this.dbContextFactory = dbContextFactory; } public async Task UpdateFromFile(FileInfo file) { if(file.Exists) { var lines = await File.ReadAllLinesAsync(file.FullName, Encoding.UTF8); var items = await this.ReadLines(lines); await this.SynchronizeUsers(items); } } private async Task ReadLines(string[] lines) { var items = new List(); foreach (var line in lines) { var values = line.Split(';', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); var item = new UserSetupItem { UserName = values[0], ApiKey = values[1], }; if(values.Length > 2) { item.CanSendToUserNames = values[2].Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); } items.Add(item); } if (items.GroupBy(x => x.UserName).Any(x => x.Count() > 1)) { throw new InvalidOperationException("Usernames are not unique. One username per line."); } else if(items.GroupBy(x=>x.ApiKey).Any(x=>x.Count() > 1)) { throw new InvalidOperationException("API keys are not unique. One API key per line."); } return items.ToArray(); } private Task SynchronizeUsers(IEnumerable users) { using var db = this.dbContextFactory.CreateDbContext(); db.RemoveRange(db.Users); db.RemoveRange(db.UserRoutes); var dbUsers = users.Select(x => new Db.Entities.User { Id = new Guid(), Name = x.UserName, ApiKey = Guid.Parse(x.ApiKey), IsEnabled = true }); var dbRoutes = users.SelectMany(x => x.CanSendToUserNames.Select(cs => new Db.Entities.UserRoute { Id = new Guid(), From = dbUsers.Single(dbu => dbu.Name == x.UserName), To = dbUsers.Single(dbu => dbu.Name == x.UserName) })); db.AddRange(dbUsers); db.AddRange(dbRoutes); db.SaveChanges(); return Task.CompletedTask; } } }