178 lines
6.2 KiB
C#
178 lines
6.2 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.DAL.Cache.Services.Base;
|
|
using PARR.DAL.InfluxDbServices;
|
|
using PARR.DAL.Services.Interfaces;
|
|
using PARR.DAL.Services.Interfaces.Unit;
|
|
using PARR.DAL.Settings;
|
|
using PARR.Domain.Common.Roles;
|
|
|
|
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<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}";
|
|
}
|
|
|
|
private string GetAllowKey(string ipAddress)
|
|
{
|
|
// a - allow
|
|
return $"a_{ipAddress}";
|
|
}
|
|
|
|
|
|
}
|
|
}
|