feat(dal, api): в таблицу Units добавлено поле LastLogon. Переделана авторизация для хостов (ЭК), теперь берется ip из связанных Units. Переделаны запросы авторизации в кеш. Переделан запрос и модель в influxdb. Обновлена статистика по юнитам и полям.

This commit is contained in:
Mikhail Trubnikov
2025-08-26 14:04:49 +10:00
parent a6385ea39a
commit c7bc8f60ef
19 changed files with 3994 additions and 137 deletions

View File

@@ -39,7 +39,7 @@ namespace PARR.AIHITSyncer
{ {
var syncerService = scope.ServiceProvider.GetService<ISyncerService>(); var syncerService = scope.ServiceProvider.GetService<ISyncerService>();
if (syncerService == null) if (syncerService == null)
throw new Exception("Не смог получить серивс ISyncerService, scope.ServiceProvider.GetService<ISyncerService>()"); throw new Exception("Не смог получить сервис ISyncerService, scope.ServiceProvider.GetService<ISyncerService>()");
await syncerService.SyncAsync(msg); await syncerService.SyncAsync(msg);
//await Task.CompletedTask; //await Task.CompletedTask;

View File

@@ -4,7 +4,7 @@
{ {
public Guid? UserId { get; set; } public Guid? UserId { get; set; }
public Guid? HostId { get; set; } public Guid? UnitId { get; set; }
public required string UserIp { get; set; } public required string UserIp { get; set; }

View File

@@ -110,10 +110,10 @@
public const string Create = Base + "/generator-templates/"; public const string Create = Base + "/generator-templates/";
} }
public static class Host public static class Unit
{ {
public const string GetAll = Base + "/hosts/"; public const string GetAll = Base + "/units/";
public const string Get = Base + "/hosts/" + getParam; public const string Get = Base + "/units/" + getParam;
public const string getParam = "{id}"; public const string getParam = "{id}";
} }
@@ -227,17 +227,17 @@
public const string GetForPeriod = BaseStat + "/template-auto-controls/"; public const string GetForPeriod = BaseStat + "/template-auto-controls/";
} }
public static class StatHost public static class StatUnit
{ {
public const string Get = BaseStat + "/hosts/"; public const string Get = BaseStat + "/units/";
public const string GetWithTemplates = BaseStat + "/hosts/templates"; public const string GetWithTemplates = BaseStat + "/units/templates";
public const string GetForPeriod = BaseStat + "/hosts/period"; public const string GetForPeriod = BaseStat + "/units/period";
} }
public static class StatApplication public static class StatUnitFieldValues
{ {
public const string Get = BaseStat + "/applications/"; public const string Get = BaseStat + "/unit-field-values/";
public const string GetForPeriod = BaseStat + "/applications/period"; public const string GetForPeriod = BaseStat + "/unit-field-values/period";
} }
public static class StatOrder public static class StatOrder

View File

@@ -1,11 +0,0 @@
namespace PARR.API.Contracts.V1.Responses.Statistics
{
public class StatApplicationResponse
{
public int AllApplications { get; set; }
public int CreatedLastDay { get; set; }
public int UpdatedLastDay { get; set; }
}
}

View File

@@ -0,0 +1,11 @@
namespace PARR.API.Contracts.V1.Responses.Statistics
{
public class StatUnitFieldValuesResponse
{
public int AllValues { get; set; }
public int CreatedLastDay { get; set; }
//public int UpdatedLastDay { get; set; }
}
}

View File

@@ -1,9 +1,9 @@
namespace PARR.API.Contracts.V1.Responses.Statistics namespace PARR.API.Contracts.V1.Responses.Statistics
{ {
public class StatHostPeriodResponse public class StatUnitPeriodResponse
{ {
public DateOnly Date { get; set; } public DateOnly Date { get; set; }
public int CreatedHostsCount { get; set; } public int CreatedUnitsCount { get; set; }
} }
} }

View File

@@ -1,6 +1,6 @@
namespace PARR.API.Contracts.V1.Responses.Statistics namespace PARR.API.Contracts.V1.Responses.Statistics
{ {
public class StatHostResponse public class StatUnitResponse
{ {
public int AllHosts { get; set; } public int AllHosts { get; set; }

View File

@@ -1,8 +1,8 @@
namespace PARR.API.Contracts.V1.Responses.Statistics namespace PARR.API.Contracts.V1.Responses.Statistics
{ {
public class StatHostTemplateResponse public class StatUnitTemplateResponse
{ {
public int AllUnits { get; set; } public int AllUnits { get; set; }
public int HostsInTemplates { get; set; } public int UnitsInTemplates { get; set; }
} }
} }

View File

@@ -5,12 +5,13 @@
public Guid Id { get; set; } public Guid Id { get; set; }
public required string Name { get; set; } public required string Name { get; set; }
} }
public class UnitResponse : UnitBaseResponse public class UnitResponse : UnitBaseResponse
{ {
} }
@@ -19,6 +20,8 @@
/// </summary> /// </summary>
public class UnitWithAttributesResponse : UnitBaseResponse public class UnitWithAttributesResponse : UnitBaseResponse
{ {
public DateTimeOffset? LastLogon { get; set; }
public List<AttributeResponse>? Attributes { get; set; } public List<AttributeResponse>? Attributes { get; set; }
} }

View File

@@ -41,11 +41,17 @@ namespace PARR.API.Controllers.V1.Statistics
var result = await influxDbService.QueryAsync(async handler => var result = await influxDbService.QueryAsync(async handler =>
{ {
//var query = $"from(bucket: \"{influxDbSettings.Logons!.Bucket}\") " +
// $"|> range(start: {startAt}) " +
// $"|> filter(fn: (r) => r._measurement == \"logon\") " +
// $"|> drop(columns: [\"HostId\", \"UserId\"]) " +
// $"|> aggregateWindow(every: 5m, fn: count)";
var query = $"from(bucket: \"{influxDbSettings.Logons!.Bucket}\") " + var query = $"from(bucket: \"{influxDbSettings.Logons!.Bucket}\") " +
$"|> range(start: {startAt}) " + $"|> range(start: {startAt}) " +
$"|> filter(fn: (r) => r._measurement == \"logon\") " + $"|> filter(fn: (r) => r._measurement == \"logon\") " +
$"|> drop(columns: [\"HostId\", \"UserId\"]) " + $"|> drop(columns: [\"UnitId\", \"UserId\"]) " +
$"|> aggregateWindow(every: 5m, fn: count)"; $"|> aggregateWindow(every: 5m, fn: count)";
var tables = await handler.QueryAsync(query, influxDbSettings.Organization); var tables = await handler.QueryAsync(query, influxDbSettings.Organization);

View File

@@ -8,65 +8,65 @@ using PARR.API.Contracts.V1.Responses.Statistics;
using PARR.API.Controllers.V1.Base; using PARR.API.Controllers.V1.Base;
using PARR.BLL.Services.Interfaces; using PARR.BLL.Services.Interfaces;
using PARR.Constants; using PARR.Constants;
using PARR.DAL.Services.Interfaces;
using PARR.DAL.Services.Interfaces.Unit; using PARR.DAL.Services.Interfaces.Unit;
namespace PARR.API.Controllers.V1.Statistics namespace PARR.API.Controllers.V1.Statistics
{ {
/// <summary> /// <summary>
/// Статистика по хостам /// Статистика по юнитам (ЭК)
/// </summary> /// </summary>
[Authorize(Roles = ParrRoles.Administrator.Role)] [Authorize(Roles = ParrRoles.Administrator.Role)]
public class StatHostController : BaseApiController public class StatUnitController : BaseApiController
{ {
private readonly IHostService hostService;
private readonly IUnitService unitService; private readonly IUnitService unitService;
private readonly ICalendarService calendarService; private readonly ICalendarService calendarService;
public StatHostController( public StatUnitController(
IHostService hostService,
IUnitService unitService, IUnitService unitService,
ICalendarService calendarService ICalendarService calendarService
) )
{ {
this.hostService = hostService;
this.unitService = unitService; this.unitService = unitService;
this.calendarService = calendarService; this.calendarService = calendarService;
} }
/// <summary> /// <summary>
/// Статистика синхронизации хостов с АИХИТ за последние сутки /// Статистика синхронизации юнитов (ЭК) с АИХИТ за последние сутки
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
[HttpGet(ApiRoutes.StatHost.Get)] [HttpGet(ApiRoutes.StatUnit.Get)]
public async Task<IActionResult> Get() public async Task<IActionResult> Get()
{ {
var queryDate = DateTimeOffset.UtcNow.AddDays(-1); var queryDate = DateTimeOffset.UtcNow.AddDays(-1);
var response = new StatHostResponse var response = new StatUnitResponse
{ {
AllHosts = await hostService.Get().CountAsync(), AllHosts = await unitService.Get().CountAsync(),
CreatedLastDay = await hostService.Get().CountAsync(t => t.DateCreated >= queryDate), CreatedLastDay = await unitService.Get().CountAsync(t => t.DateCreated >= queryDate),
UpdatedLastDay = await hostService.Get().CountAsync(t => t.DateModified.HasValue && t.DateModified.Value >= queryDate) //UpdatedLastDay = await hostService.Get().CountAsync(t => t.DateModified.HasValue && t.DateModified.Value >= queryDate)
UpdatedLastDay = await unitService.Get()
.Include(t => t.UnitValues)
.Where(t => t.UnitValues.Any(v => v.DateModified.HasValue && v.DateModified.Value >= queryDate))
.CountAsync()
}; };
return Ok(new Response<StatHostResponse>(response, true)); return Ok(new Response<StatUnitResponse>(response, true));
} }
/// <summary> /// <summary>
/// Получить статистику за период /// Получить статистику созданных юнитов (ЭК) за период
/// </summary> /// </summary>
/// <param name="timeZoneQuery"></param> /// <param name="timeZoneQuery"></param>
/// <param name="startPeriodDays"></param> /// <param name="startPeriodDays"></param>
/// <returns></returns> /// <returns></returns>
[HttpGet(ApiRoutes.StatHost.GetForPeriod)] [HttpGet(ApiRoutes.StatUnit.GetForPeriod)]
public async Task<IActionResult> GetForPeriod([FromQuery] TimeZoneOffsetClient timeZoneQuery, [FromQuery] int startPeriodDays = 3) public async Task<IActionResult> GetForPeriod([FromQuery] TimeZoneOffsetClient timeZoneQuery, [FromQuery] int startPeriodDays = 3)
{ {
var endPeriod = calendarService.GetDateWithTimeZoneOffset(DateTimeOffset.UtcNow, timeZoneQuery.TimeZoneOffsetHours); var endPeriod = calendarService.GetDateWithTimeZoneOffset(DateTimeOffset.UtcNow, timeZoneQuery.TimeZoneOffsetHours);
var startPeriod = endPeriod.AddDays(-startPeriodDays); var startPeriod = endPeriod.AddDays(-startPeriodDays);
var query = hostService.Get() var query = unitService.Get()
.Where(t => .Where(t =>
t.DateCreated.DateTime.AddHours(timeZoneQuery.TimeZoneOffsetHours).Date >= startPeriod.Date t.DateCreated.DateTime.AddHours(timeZoneQuery.TimeZoneOffsetHours).Date >= startPeriod.Date
&& t.DateCreated.DateTime.AddHours(timeZoneQuery.TimeZoneOffsetHours).Date <= endPeriod.Date && t.DateCreated.DateTime.AddHours(timeZoneQuery.TimeZoneOffsetHours).Date <= endPeriod.Date
@@ -75,46 +75,46 @@ namespace PARR.API.Controllers.V1.Statistics
.Select(t => new .Select(t => new
{ {
Date = t.Key, Date = t.Key,
HostCount = t.Count() UnitCount = t.Count()
}); });
var result = await query.ToListAsync(); var result = await query.ToListAsync();
var daysList = calendarService.GetDatesForPeriod(startPeriod, endPeriod); var daysList = calendarService.GetDatesForPeriod(startPeriod, endPeriod);
var response = new List<StatHostPeriodResponse>(); var response = new List<StatUnitPeriodResponse>();
daysList.ForEach(date => daysList.ForEach(date =>
{ {
response.Add(new StatHostPeriodResponse response.Add(new StatUnitPeriodResponse
{ {
Date = date, Date = date,
CreatedHostsCount = result.FirstOrDefault(t => DateOnly.FromDateTime(t.Date) == date)?.HostCount ?? 0 CreatedUnitsCount = result.FirstOrDefault(t => DateOnly.FromDateTime(t.Date) == date)?.UnitCount ?? 0
}); });
}); });
response = response.OrderBy(t => t.Date).ToList(); response = response.OrderBy(t => t.Date).ToList();
return Ok(new Response<List<StatHostPeriodResponse>>(response, true)); return Ok(new Response<List<StatUnitPeriodResponse>>(response, true));
} }
/// <summary> /// <summary>
/// Количество хостов в шаблонах /// Количество юнитов (ЭК) в шаблонах
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
[HttpGet(ApiRoutes.StatHost.GetWithTemplates)] [HttpGet(ApiRoutes.StatUnit.GetWithTemplates)]
public async Task<IActionResult> GetWithTemplates() public async Task<IActionResult> GetWithTemplates()
{ {
//считаем именно хосты в шаблонах, т е один хост может быть в нескольких шаблонах //считаем именно хосты в шаблонах, т е один хост может быть в нескольких шаблонах
var response = new StatHostTemplateResponse var response = new StatUnitTemplateResponse
{ {
AllUnits = await unitService.Get().CountAsync(), AllUnits = await unitService.Get().CountAsync(),
HostsInTemplates = await unitService.Get().Include(t => t.Templates).CountAsync(t => t.Templates.Any()) UnitsInTemplates = await unitService.Get().Include(t => t.Templates).CountAsync(t => t.Templates.Any())
}; };
return Ok(new Response<StatHostTemplateResponse>(response, true)); return Ok(new Response<StatUnitTemplateResponse>(response, true));
} }
} }
} }

View File

@@ -9,41 +9,48 @@ using PARR.API.Controllers.V1.Base;
using PARR.BLL.Services.Interfaces; using PARR.BLL.Services.Interfaces;
using PARR.Constants; using PARR.Constants;
using PARR.DAL.Services.Interfaces; using PARR.DAL.Services.Interfaces;
using PARR.DAL.Services.Interfaces.Unit;
namespace PARR.API.Controllers.V1.Statistics namespace PARR.API.Controllers.V1.Statistics
{ {
/// <summary> /// <summary>
/// Статистика по приложениям /// Статистика по значениям unit.FieldValues полученных из АИХИТ
/// </summary> /// </summary>
[Authorize(Roles = ParrRoles.Administrator.Role)] [Authorize(Roles = ParrRoles.Administrator.Role)]
public class StatApplicationController : BaseApiController public class StatUnitFieldValuesController : BaseApiController
{ {
private readonly IApplicationService applicationService; private readonly IApplicationService applicationService;
private readonly IUnitFieldValueService unitFieldValueService;
private readonly ICalendarService calendarService; private readonly ICalendarService calendarService;
public StatApplicationController(IApplicationService applicationService, ICalendarService calendarService) public StatUnitFieldValuesController(
IApplicationService applicationService,
IUnitFieldValueService unitFieldValueService,
ICalendarService calendarService
)
{ {
this.applicationService = applicationService; this.applicationService = applicationService;
this.unitFieldValueService = unitFieldValueService;
this.calendarService = calendarService; this.calendarService = calendarService;
} }
/// <summary> /// <summary>
/// Статистика синхронизации приложений с АИХИТ за последние сутки /// Статистика синхронизации полей юнитов (ЭК) с АИХИТ за последние сутки
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
[HttpGet(ApiRoutes.StatApplication.Get)] [HttpGet(ApiRoutes.StatUnitFieldValues.Get)]
public async Task<IActionResult> Get() public async Task<IActionResult> Get()
{ {
var queryDate = DateTimeOffset.UtcNow.AddDays(-1); var queryDate = DateTimeOffset.UtcNow.AddDays(-1);
var response = new StatApplicationResponse var response = new StatUnitFieldValuesResponse
{ {
AllApplications = await applicationService.Get().CountAsync(), AllValues = await unitFieldValueService.Get().CountAsync(),
CreatedLastDay = await applicationService.Get().CountAsync(t => t.DateCreated >= queryDate), CreatedLastDay = await unitFieldValueService.Get().CountAsync(t => t.DateCreated >= queryDate),
UpdatedLastDay = await applicationService.Get().CountAsync(t => t.DateModified.HasValue && t.DateModified.Value >= queryDate), //UpdatedLastDay = await applicationService.Get().CountAsync(t => t.DateModified.HasValue && t.DateModified.Value >= queryDate),
}; };
return Ok(new Response<StatApplicationResponse>(response, true)); return Ok(new Response<StatUnitFieldValuesResponse>(response, true));
} }
@@ -53,13 +60,13 @@ namespace PARR.API.Controllers.V1.Statistics
/// <param name="timeZoneQuery"></param> /// <param name="timeZoneQuery"></param>
/// <param name="startPeriodDays"></param> /// <param name="startPeriodDays"></param>
/// <returns></returns> /// <returns></returns>
[HttpGet(ApiRoutes.StatApplication.GetForPeriod)] [HttpGet(ApiRoutes.StatUnitFieldValues.GetForPeriod)]
public async Task<IActionResult> GetForPeriod([FromQuery] TimeZoneOffsetClient timeZoneQuery, [FromQuery] int startPeriodDays = 3) public async Task<IActionResult> GetForPeriod([FromQuery] TimeZoneOffsetClient timeZoneQuery, [FromQuery] int startPeriodDays = 3)
{ {
var endPeriod = calendarService.GetDateWithTimeZoneOffset(DateTimeOffset.UtcNow, timeZoneQuery.TimeZoneOffsetHours); var endPeriod = calendarService.GetDateWithTimeZoneOffset(DateTimeOffset.UtcNow, timeZoneQuery.TimeZoneOffsetHours);
var startPeriod = endPeriod.AddDays(-startPeriodDays); var startPeriod = endPeriod.AddDays(-startPeriodDays);
var query = applicationService.Get() var query = unitFieldValueService.Get()
.Where(t => .Where(t =>
t.DateCreated.DateTime.AddHours(timeZoneQuery.TimeZoneOffsetHours).Date >= startPeriod.Date t.DateCreated.DateTime.AddHours(timeZoneQuery.TimeZoneOffsetHours).Date >= startPeriod.Date
&& t.DateCreated.DateTime.AddHours(timeZoneQuery.TimeZoneOffsetHours).Date <= endPeriod.Date && t.DateCreated.DateTime.AddHours(timeZoneQuery.TimeZoneOffsetHours).Date <= endPeriod.Date
@@ -68,7 +75,7 @@ namespace PARR.API.Controllers.V1.Statistics
.Select(t => new .Select(t => new
{ {
Date = t.Key, Date = t.Key,
ApplicationCount = t.Count() Count = t.Count()
}); });
var result = await query.ToListAsync(); var result = await query.ToListAsync();
@@ -82,7 +89,7 @@ namespace PARR.API.Controllers.V1.Statistics
response.Add(new StatApplicationPeriodResponse response.Add(new StatApplicationPeriodResponse
{ {
Date = date, Date = date,
CreatedApplicationsCount = result.FirstOrDefault(t => DateOnly.FromDateTime(t.Date) == date)?.ApplicationCount ?? 0 CreatedApplicationsCount = result.FirstOrDefault(t => DateOnly.FromDateTime(t.Date) == date)?.Count ?? 0
}); });
}); });

View File

@@ -12,58 +12,36 @@ using PARR.BLL.Helpers;
using PARR.Constants; using PARR.Constants;
using PARR.DAL.DomainModels; using PARR.DAL.DomainModels;
using PARR.DAL.Models.Unit; using PARR.DAL.Models.Unit;
using PARR.DAL.Services.Interfaces;
using PARR.DAL.Services.Interfaces.Unit; using PARR.DAL.Services.Interfaces.Unit;
namespace PARR.API.Controllers.V1 namespace PARR.API.Controllers.V1
{ {
[Authorize(Roles = ParrRoles.Administrator.Role)] [Authorize(Roles = ParrRoles.Administrator.Role)]
public class HostController : BaseApiController public class UnitController : BaseApiController
{ {
private readonly IMapper mapper; private readonly IMapper mapper;
private readonly IHostService hostService;
private readonly IUnitService unitService; private readonly IUnitService unitService;
public HostController( public UnitController(
IMapper mapper, IMapper mapper,
IHostService hostService,
IUnitService unitService IUnitService unitService
) )
{ {
this.mapper = mapper; this.mapper = mapper;
this.hostService = hostService;
this.unitService = unitService; this.unitService = unitService;
} }
/// <summary> /// <summary>
/// Получить список хостов постранично /// Получить список ЭК постранично
/// </summary> /// </summary>
/// <param name="paginationQuery"></param> /// <param name="paginationQuery"></param>
/// <returns></returns> /// <returns></returns>
[HttpGet(ApiRoutes.Host.GetAll)] [HttpGet(ApiRoutes.Unit.GetAll)]
public async Task<IActionResult> GetAll([FromQuery] PaginationQuery paginationQuery, [FromQuery] HostQuery request) public async Task<IActionResult> GetAll([FromQuery] PaginationQuery paginationQuery, [FromQuery] HostQuery request)
{ {
var paginationFilter = mapper.Map<PaginationFilter>(paginationQuery); var paginationFilter = mapper.Map<PaginationFilter>(paginationQuery);
//IQueryable<DAL.Models.Host> query = hostService.Get()
// .Include(t=>t.WorkGroup).ThenInclude(t=>t!.ResponseArea)
// .Include(s => s.EkStatus)
// .Include(s => s.ResponseArea)
// .Include(t => t.ApplicationsInHosts).ThenInclude(t => t.Application).ThenInclude(t => t!.ApplicationType)
// .OrderBy(t => t.Ek);
//if (!string.IsNullOrEmpty(request.Mask))
// query = query.Where(t => EF.Functions.Like(t.Ek.ToLower(), SqlHelpers.RegexToLike(request.Mask)));
//var hosts = await hostService.GetPage(query, paginationFilter).ToListAsync();
//if (!hosts.Any())
// return NoContent();
//var hostResponse = mapper.Map<List<HostWithApplicationsResponse>>(hosts);
//var paginationResponse = new PagedResponse<HostWithApplicationsResponse>(hostResponse, true).GetPaginatedProps(paginationFilter, query);
IQueryable<Unit> query = unitService.Get() IQueryable<Unit> query = unitService.Get()
.OrderBy(t => t.Name); .OrderBy(t => t.Name);
@@ -90,25 +68,13 @@ namespace PARR.API.Controllers.V1
/// <summary> /// <summary>
/// Получить хост по id /// Получить ЭК по id
/// </summary> /// </summary>
/// <param name="id"></param> /// <param name="id"></param>
/// <returns></returns> /// <returns></returns>
[HttpGet(ApiRoutes.Host.Get)] [HttpGet(ApiRoutes.Unit.Get)]
public async Task<IActionResult> GetById([FromRoute] Guid id) public async Task<IActionResult> GetById([FromRoute] Guid id)
{ {
//var host = await hostService.Get()
// .Include(t => t.WorkGroup).ThenInclude(t => t!.ResponseArea)
// .Include(s => s.EkStatus)
// .Include(s => s.ResponseArea)
// .Include(t => t.ApplicationsInHosts).ThenInclude(t => t.Application).ThenInclude(t => t!.ApplicationType)
// .FirstOrDefaultAsync(t => t.Id == id);
//if (host == null)
// return NotFound();
//var response = mapper.Map<HostWithApplicationsResponse>(host);
var unit = await unitService.Get() var unit = await unitService.Get()
.Include(t => t.UnitValues) .Include(t => t.UnitValues)
.ThenInclude(uv => uv.Value) .ThenInclude(uv => uv.Value)

View File

@@ -14,7 +14,7 @@ namespace PARR.API.Domain.InfluxDbModels
[Column(nameof(UserId), IsTag = true)] [Column(nameof(UserId), IsTag = true)]
public Guid? UserId { get; set; } public Guid? UserId { get; set; }
[Column(nameof(HostId), IsTag = true)] [Column(nameof(UnitId), IsTag = true)]
public Guid? HostId { get; set; } public Guid? UnitId { get; set; }
} }
} }

View File

@@ -1,4 +1,5 @@
using PARR.API.Authentication.Models; using Microsoft.EntityFrameworkCore;
using PARR.API.Authentication.Models;
using PARR.API.Domain.InfluxDbModels; using PARR.API.Domain.InfluxDbModels;
using PARR.API.Services.Interfaces; using PARR.API.Services.Interfaces;
using PARR.API.Settings; using PARR.API.Settings;
@@ -6,6 +7,7 @@ using PARR.Constants;
using PARR.DAL.CacheServices; using PARR.DAL.CacheServices;
using PARR.DAL.InfluxDbServices; using PARR.DAL.InfluxDbServices;
using PARR.DAL.Services.Interfaces; using PARR.DAL.Services.Interfaces;
using PARR.DAL.Services.Interfaces.Unit;
using PARR.DAL.Settings; using PARR.DAL.Settings;
namespace PARR.API.Services.Implementations namespace PARR.API.Services.Implementations
@@ -14,29 +16,29 @@ namespace PARR.API.Services.Implementations
{ {
private readonly IRedisCacheService cacheService; private readonly IRedisCacheService cacheService;
private readonly IUserService userService; private readonly IUserService userService;
private readonly IHostService hostService;
private readonly UserCacheSettings userCacheSettings; private readonly UserCacheSettings userCacheSettings;
private readonly IClientService clientService; private readonly IClientService clientService;
private readonly IInfluxDbService influxDbService; private readonly IInfluxDbService influxDbService;
private readonly InfluxDbSettings influxDbSettings; private readonly InfluxDbSettings influxDbSettings;
private readonly IUnitService unitService;
public AuthService( public AuthService(
IRedisCacheService cacheService, IRedisCacheService cacheService,
IUserService userService, IUserService userService,
IHostService hostService,
UserCacheSettings userCacheSettings, UserCacheSettings userCacheSettings,
IClientService clientService, IClientService clientService,
IInfluxDbService influxDbService, IInfluxDbService influxDbService,
InfluxDbSettings influxDbSettings InfluxDbSettings influxDbSettings,
IUnitService unitService
) )
{ {
this.cacheService = cacheService; this.cacheService = cacheService;
this.userService = userService; this.userService = userService;
this.hostService = hostService;
this.userCacheSettings = userCacheSettings; this.userCacheSettings = userCacheSettings;
this.clientService = clientService; this.clientService = clientService;
this.influxDbService = influxDbService; this.influxDbService = influxDbService;
this.influxDbSettings = influxDbSettings; this.influxDbSettings = influxDbSettings;
this.unitService = unitService;
} }
@@ -84,17 +86,19 @@ namespace PARR.API.Services.Implementations
await userService.CommitAsync(); await userService.CommitAsync();
} }
var host = await hostService.GetByIpAsync(ipAddress); var unit = await unitService.Get()
if (host != null) .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 }); roles.Add(new UserRoleInCache { Name = ParrRoles.Agent.Role, Description = ParrRoles.Agent.Description });
// сохраняем время входа // сохраняем время входа
host.LastLogon = DateTimeOffset.UtcNow; unit.LastLogon = DateTimeOffset.UtcNow;
await hostService.CommitAsync(); await unitService.CommitAsync();
} }
if (user == null && host == null) if (user == null && unit == null)
{ {
// если это не пользователь и не хост, добавляем в кэш на блокировку // если это не пользователь и не хост, добавляем в кэш на блокировку
await cacheService.SetCachedDataAsync(GetBlockKey(ipAddress), DateTimeOffset.UtcNow, userCacheSettings.UserBlockTtl); await cacheService.SetCachedDataAsync(GetBlockKey(ipAddress), DateTimeOffset.UtcNow, userCacheSettings.UserBlockTtl);
@@ -109,22 +113,21 @@ namespace PARR.API.Services.Implementations
Roles = roles Roles = roles
}; };
if (host != null) if (unit != null)
{ {
cacheData.Name = host.Ek; cacheData.Name = unit.Name;
cacheData.HostId = host.Id; cacheData.UnitId = unit.Id;
cacheData.LastLogon = host.LastLogon; cacheData.LastLogon = unit.LastLogon;
} }
if (user != null) if (user != null)
{ {
cacheData.Name = user.Name + (host != null ? $", {host.Ek}" : string.Empty); cacheData.Name = user.Name + (unit != null ? $", {unit.Name}" : string.Empty);
cacheData.Description = user.Description ?? string.Empty; cacheData.Description = user.Description ?? string.Empty;
cacheData.UserId = user.Id; cacheData.UserId = user.Id;
cacheData.LastLogon = user.LastLogon; cacheData.LastLogon = user.LastLogon;
} }
await cacheService.SetCachedDataAsync(GetAllowKey(ipAddress), cacheData, userCacheSettings.UserCacheTtl); await cacheService.SetCachedDataAsync(GetAllowKey(ipAddress), cacheData, userCacheSettings.UserCacheTtl);
//тут записать в статистику входов в influxdb //тут записать в статистику входов в influxdb
@@ -138,7 +141,7 @@ namespace PARR.API.Services.Implementations
{ {
influxDbService.Write(write => influxDbService.Write(write =>
{ {
var data = new LogonDbModel { HostId = cacheData.HostId, Ip = cacheData.UserIp, UserId = cacheData.UserId }; 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); write.WriteMeasurement(data, InfluxDB.Client.Api.Domain.WritePrecision.Ns, bucket: influxDbSettings.Logons!.Bucket, org: influxDbSettings.Organization);
}, influxDbSettings.Logons!.Token); }, influxDbSettings.Logons!.Token);
} }

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,31 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace PARR.DAL.Migrations
{
/// <inheritdoc />
public partial class tblUnitsAddLastLogon : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<DateTimeOffset>(
name: "LastLogon",
schema: "unit",
table: "Units",
type: "timestamp with time zone",
nullable: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "LastLogon",
schema: "unit",
table: "Units");
}
}
}

View File

@@ -2756,6 +2756,9 @@ namespace PARR.DAL.Migrations
b.Property<DateTimeOffset?>("DateModified") b.Property<DateTimeOffset?>("DateModified")
.HasColumnType("timestamp with time zone"); .HasColumnType("timestamp with time zone");
b.Property<DateTimeOffset?>("LastLogon")
.HasColumnType("timestamp with time zone");
b.Property<string>("Name") b.Property<string>("Name")
.IsRequired() .IsRequired()
.HasColumnType("text"); .HasColumnType("text");

View File

@@ -23,9 +23,7 @@ namespace PARR.DAL.Models.Unit
/// </summary> /// </summary>
public required string Name { get; set; } public required string Name { get; set; }
//статус ЭК public DateTimeOffset? LastLogon { get; set; }
// todo: добавить еще поля??? (которые есть у всех ЭК)
[NotMapped] [NotMapped]
@@ -42,7 +40,7 @@ namespace PARR.DAL.Models.Unit
result.ResponseArea = UnitValues.FirstOrDefault(t => t.Field?.AihitName == "ЗО_РГ")?.Value?.Value; result.ResponseArea = UnitValues.FirstOrDefault(t => t.Field?.AihitName == "ЗО_РГ")?.Value?.Value;
result.WorkGroup = UnitValues.FirstOrDefault(t => t.Field?.AihitName == "РАБОЧАЯ_ГР_ОТВ_ЗАК")?.Value?.Value; result.WorkGroup = UnitValues.FirstOrDefault(t => t.Field?.AihitName == "РАБОЧАЯ_ГР_ОТВ_ЗАК")?.Value?.Value;
result.Status = UnitValues.FirstOrDefault(t => t.Field?.AihitName == "СТАТУС")?.Value?.Value; result.Status = UnitValues.FirstOrDefault(t => t.Field?.AihitName == "СТАТУС")?.Value?.Value;
result.NotUnique = UnitValues.FirstOrDefault(t => t.Field?.AihitName == "НЕУНИКАЛЬНЫЙ_ЭК")?.Value?.Value; result.NotUnique = UnitValues.FirstOrDefault(t => t.Field?.AihitName == "НЕУНИКАЛЬНЫЙ_ЭК")?.Value?.Value;
return result; return result;
} }