using Microsoft.EntityFrameworkCore; using PARR.API.Authentication.Models; using PARR.API.Domain.InfluxDbModels; using PARR.API.Services.Interfaces; using PARR.API.Settings; using PARR.Core.Common.Interfaces; using PARR.DAL.Services.Interfaces; using PARR.DAL.Services.Interfaces.Unit; using PARR.Domain.Common.Roles; using PARR.Domain.Settings; namespace PARR.API.Services.Implementations { public class AuthService : IAuthService { private readonly IRedisCacheService cacheService; private readonly IUserService userService; private readonly UserCacheSettings userCacheSettings; private readonly IClientService clientService; private readonly IInfluxDbService influxDbService; private readonly InfluxDbSettings influxDbSettings; private readonly IUnitService unitService; public AuthService( IRedisCacheService cacheService, IUserService userService, UserCacheSettings userCacheSettings, IClientService clientService, IInfluxDbService influxDbService, InfluxDbSettings influxDbSettings, IUnitService unitService ) { this.cacheService = cacheService; this.userService = userService; this.userCacheSettings = userCacheSettings; this.clientService = clientService; this.influxDbService = influxDbService; this.influxDbSettings = influxDbSettings; this.unitService = unitService; } public async Task UserIsBlockedAsync(string ipAddress) { //пользователь есть в списке блокировки? var existUserInBlockList = await cacheService.GetCachedDataAsync(GetBlockKey(ipAddress)); return existUserInBlockList != null; } public async Task GetCurrentUserAsync() { var userIp = clientService.GetClientIp()?.ToString(); if (userIp == null) return null; return await GetUserAsync(userIp); } public async Task GetUserAsync(string ipAddress) { // смотрим, есть ли в кэше var userInCache = await cacheService.GetCachedDataAsync(GetAllowKey(ipAddress)); if (userInCache != null) return userInCache; // нет в кэше var roles = new List(); var user = await userService.GetByIpWithRolesAsync(ipAddress); if (user != null) { user.Roles.ToList().ForEach(t => { if (t.Role != null) roles.Add(new UserRoleInCache { Name = t.Role.Name, Description = t.Role.Description }); }); // сохраняем время входа user.LastLogon = DateTimeOffset.UtcNow; await userService.CommitAsync(); } var unit = await unitService.Get() .Include(t => t.UnitValues).ThenInclude(t => t.Value) .FirstOrDefaultAsync(t => t.UnitValues.FirstOrDefault(v => v.Value!.Value == ipAddress) != null); if (unit != null) { roles.Add(new UserRoleInCache { Name = ParrRoles.Agent.Role, Description = ParrRoles.Agent.Description }); // сохраняем время входа unit.LastLogon = DateTimeOffset.UtcNow; await unitService.CommitAsync(); } if (user == null && unit == null) { // если это не пользователь и не хост, добавляем в кэш на блокировку await cacheService.SetCachedDataAsync(GetBlockKey(ipAddress), DateTimeOffset.UtcNow, userCacheSettings.UserBlockTtl); return null; } // пользователь есть, добавляем в КЭШ и возвращаем роли var cacheData = new UserCache { UserIp = ipAddress, Roles = roles }; if (unit != null) { cacheData.Name = unit.Name; cacheData.UnitId = unit.Id; cacheData.LastLogon = unit.LastLogon; } if (user != null) { cacheData.Name = user.Name + (unit != null ? $", {unit.Name}" : string.Empty); cacheData.Description = user.Description ?? string.Empty; cacheData.UserId = user.Id; cacheData.LastLogon = user.LastLogon; } await cacheService.SetCachedDataAsync(GetAllowKey(ipAddress), cacheData, userCacheSettings.UserCacheTtl); //тут записать в статистику входов в influxdb WriteLogonStatistic(cacheData); return cacheData; } private void WriteLogonStatistic(UserCache cacheData) { influxDbService.Write(write => { var data = new LogonDbModel { UnitId = cacheData.UnitId, Ip = cacheData.UserIp, UserId = cacheData.UserId }; write.WriteMeasurement(data, InfluxDB.Client.Api.Domain.WritePrecision.Ns, bucket: influxDbSettings.Logons!.Bucket, org: influxDbSettings.Organization); }, influxDbSettings.Logons!.Token); } public async Task UnlockUserAsync(string ipAddress) { await cacheService.DeleteCachedDataAsync(GetBlockKey(ipAddress)); } public async Task RemoveCacheUserAsync(string ipAddress) { await cacheService.DeleteCachedDataAsync(GetAllowKey(ipAddress)); await cacheService.DeleteCachedDataAsync(GetBlockKey(ipAddress)); } private string GetBlockKey(string ipAddress) { // d - deny return $"d_{ipAddress}"; } private string GetAllowKey(string ipAddress) { // a - allow return $"a_{ipAddress}"; } } }