Files
2026-05-28 15:50:14 +10:00

180 lines
6.4 KiB
C#

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.Core.Repositories.Interfaces;
using PARR.Core.Repositories.Interfaces.Unit;
using PARR.Domain.Cache;
using PARR.Domain.Common.Roles;
using PARR.Domain.Settings;
namespace PARR.API.Services.Implementations
{
public class AuthService : IAuthService
{
private readonly IRedisCacheService cacheService;
private readonly IUserRepository userService;
private readonly UserCacheSettings userCacheSettings;
private readonly IClientService clientService;
private readonly IInfluxDbService influxDbService;
private readonly InfluxDbSettings influxDbSettings;
private readonly IUnitRepository unitService;
public AuthService(
IRedisCacheService cacheService,
IUserRepository userService,
UserCacheSettings userCacheSettings,
IClientService clientService,
IInfluxDbService influxDbService,
InfluxDbSettings influxDbSettings,
IUnitRepository 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<bool> UserIsBlockedAsync(string ipAddress)
{
//пользователь есть в списке блокировки?
var existUserInBlockList = await cacheService.GetCachedDataAsync<DateTimeOffset?>(GetBlockKey(ipAddress));
return existUserInBlockList != null;
}
public async Task<UserCache?> GetCurrentUserAsync()
{
var userIp = clientService.GetClientIp()?.ToString();
if (userIp == null)
return null;
return await GetUserAsync(userIp);
}
public async Task<UserCache?> GetUserAsync(string ipAddress)
{
// смотрим, есть ли в кэше
var userInCache = await cacheService.GetCachedDataAsync<UserCache>(GetAllowKey(ipAddress));
if (userInCache != null)
return userInCache;
// нет в кэше
var roles = new List<UserRoleInCache>();
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}";
return cacheService.GetKey(CacheKeys.UserAuth.Banned(ipAddress));
}
private string GetAllowKey(string ipAddress)
{
// a - allow
//return $"a_{ipAddress}";
return cacheService.GetKey(CacheKeys.UserAuth.Session(ipAddress));
}
}
}