DocSpace-buildtools/common/services/ASC.AuditTrail/Repositories/AuditEventsRepository.cs

267 lines
9.5 KiB
C#
Raw Normal View History

2022-03-15 18:00:53 +00:00
// (c) Copyright Ascensio System SIA 2010-2022
//
// This program is a free software product.
// You can redistribute it and/or modify it under the terms
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
// any third-party rights.
//
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
//
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
//
// The interactive user interfaces in modified source and object code versions of the Program must
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
//
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
// trademark law for use of our trademarks.
//
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
2022-02-03 11:16:34 +00:00
namespace ASC.AuditTrail.Repositories;
2022-03-18 10:31:02 +00:00
[Scope(Additional = typeof(AuditEventsRepositoryExtensions))]
2022-02-03 11:16:34 +00:00
public class AuditEventsRepository
2022-02-01 09:11:19 +00:00
{
2022-02-21 15:35:57 +00:00
private MessagesContext AuditTrailContext => _lazyAuditTrailContext.Value;
2022-02-01 09:11:19 +00:00
2022-06-08 09:02:40 +00:00
private readonly Lazy<MessagesContext> _lazyAuditTrailContext;
private readonly AuditActionMapper _auditActionMapper;
private readonly TenantManager _tenantManager;
2022-02-03 11:16:34 +00:00
private readonly IMapper _mapper;
2022-02-01 09:11:19 +00:00
2022-06-08 09:02:40 +00:00
public AuditEventsRepository(
AuditActionMapper auditActionMapper,
TenantManager tenantManager,
2022-02-21 15:35:57 +00:00
DbContextManager<MessagesContext> dbContextManager,
2022-02-03 11:16:34 +00:00
IMapper mapper)
{
2022-06-08 09:02:40 +00:00
_lazyAuditTrailContext = new Lazy<MessagesContext>(() => dbContextManager.Value);
_auditActionMapper = auditActionMapper;
_tenantManager = tenantManager;
2022-02-03 11:16:34 +00:00
_mapper = mapper;
2022-06-08 09:02:40 +00:00
}
private IEnumerable<AuditEventDto> Get(int tenant, DateTime? fromDate, DateTime? to, int? limit)
2022-02-08 00:11:22 +00:00
{
2022-06-08 09:02:40 +00:00
var query =
(from q in AuditTrailContext.AuditEvents
from p in AuditTrailContext.Users.Where(p => q.UserId == p.Id).DefaultIfEmpty()
where q.TenantId == tenant
orderby q.Date descending
select new AuditEventQuery
{
Event = q,
FirstName = p.FirstName,
LastName = p.LastName,
UserName = p.UserName
});
2022-02-01 09:11:19 +00:00
2022-06-08 09:02:40 +00:00
if (fromDate.HasValue && to.HasValue)
2022-02-08 00:11:22 +00:00
{
2022-06-08 09:02:40 +00:00
query = query.Where(q => q.Event.Date >= fromDate & q.Event.Date <= to);
2022-02-08 00:11:22 +00:00
}
2022-02-01 09:11:19 +00:00
2022-06-08 09:02:40 +00:00
if (limit.HasValue)
{
query = query.Take((int)limit);
}
2022-02-01 09:11:19 +00:00
2022-06-08 09:02:40 +00:00
return _mapper.Map<List<AuditEventQuery>, IEnumerable<AuditEventDto>>(query.ToList());
}
public IEnumerable<AuditEventDto> GetByFilter(
Guid? userId = null,
ProductType? productType = null,
ModuleType? moduleType = null,
ActionType? actionType = null,
MessageAction? action = null,
EntryType? entry = null,
string target = null,
DateTime? from = null,
DateTime? to = null,
int startIndex = 0,
int limit = 0)
{
var tenant = _tenantManager.GetCurrentTenant().Id;
var query =
(from q in AuditTrailContext.AuditEvents
from p in AuditTrailContext.Users.Where(p => q.UserId == p.Id).DefaultIfEmpty()
where q.TenantId == tenant
orderby q.Date descending
2022-04-14 19:42:15 +00:00
select new AuditEventQuery
{
Event = q,
FirstName = p.FirstName,
LastName = p.LastName,
UserName = p.UserName
2022-06-08 09:02:40 +00:00
});
if (startIndex > 0)
{
query = query.Skip(startIndex);
}
if (limit > 0)
{
query = query.Take(limit);
}
if (userId.HasValue && userId.Value != Guid.Empty)
{
query = query.Where(r => r.Event.UserId == userId.Value);
}
var isNeedFindEntry = entry.HasValue && entry.Value != EntryType.None && target != null;
if (action.HasValue && action.Value != MessageAction.None)
{
query = query.Where(r => r.Event.Action == (int)action);
}
else
{
IEnumerable<KeyValuePair<MessageAction, MessageMaps>> actions = new List<KeyValuePair<MessageAction, MessageMaps>>();
var isFindActionType = actionType.HasValue && actionType.Value != ActionType.None;
if (productType.HasValue && productType.Value != ProductType.None)
{
var productMapper = _auditActionMapper.Mappers.FirstOrDefault(m => m.Product == productType.Value);
if (productMapper != null)
{
if (moduleType.HasValue && moduleType.Value != ModuleType.None)
{
var moduleMapper = productMapper.Mappers.FirstOrDefault(m => m.Module == moduleType.Value);
if (moduleMapper != null)
{
actions = moduleMapper.Actions;
}
}
else
{
actions = productMapper.Mappers.SelectMany(r => r.Actions);
}
}
}
else
{
actions = _auditActionMapper.Mappers
.SelectMany(r => r.Mappers)
.SelectMany(r => r.Actions);
}
if (isFindActionType || isNeedFindEntry)
{
actions = actions
.Where(a => (!isFindActionType || a.Value.ActionType == actionType.Value) && (!isNeedFindEntry || (entry.Value == a.Value.EntryType1) || entry.Value == a.Value.EntryType2))
.ToList();
}
if (isNeedFindEntry)
{
2022-06-16 08:13:53 +00:00
FindByEntry(query, entry.Value, target, actions);
2022-06-08 09:02:40 +00:00
}
else
{
var keys = actions.Select(x => (int)x.Key).ToList();
Merge branch 'develop' into feature/migrations-fix # Conflicts: # common/ASC.Core.Common/EF/Model/Core/Acl.cs # common/ASC.Core.Common/GlobalUsings.cs # common/ASC.Core.Common/Messaging/EventMessage.cs # common/ASC.Core.Common/Messaging/LoginEvent.cs # common/ASC.Core.Common/Messaging/MessageTarget.cs # common/ASC.Core.Common/Migrations/MySql/CoreDbContextMySql/20211012145320_CoreDbContextMySql.cs # common/ASC.Core.Common/Migrations/MySql/FilesDbContextMySql/20220708104408_FilesDbContextMySql.Designer.cs # common/ASC.Core.Common/Migrations/MySql/FilesDbContextMySql/20220708104408_FilesDbContextMySql.cs # common/ASC.Core.Common/Migrations/MySql/FilesDbContextMySql/MySqlFilesDbContextModelSnapshot.cs # common/ASC.Core.Common/Migrations/MySql/MessagesContextMySql/20211012145334_MessagesContextMySql.Designer.cs # common/ASC.Core.Common/Migrations/MySql/MessagesContextMySql/20211012145334_MessagesContextMySql.cs # common/ASC.Core.Common/Migrations/MySql/MessagesContextMySql/20220708104428_MessagesContextMySql.Designer.cs # common/ASC.Core.Common/Migrations/MySql/MessagesContextMySql/20220708104428_MessagesContextMySql.cs # common/ASC.Core.Common/Migrations/MySql/UserDbContextMySql/20211012145322_UserDbContextMySql.cs # common/ASC.Core.Common/Migrations/MySql/UserDbContextMySql/20220708104402_UserDbContextMySql.Designer.cs # common/ASC.Core.Common/Migrations/MySql/UserDbContextMySql/MySqlUserDbContextModelSnapshot.cs # common/ASC.Core.Common/Migrations/PostgreSql/CoreDbContextPostgreSql/20211012145321_CoreDbContextPostgreSql.cs # common/ASC.Core.Common/Migrations/PostgreSql/FilesDbContextPostgreSql/20220708104409_FilesDbContextPostgreSql.Designer.cs # common/ASC.Core.Common/Migrations/PostgreSql/FilesDbContextPostgreSql/20220708104409_FilesDbContextPostgreSql.cs # common/ASC.Core.Common/Migrations/PostgreSql/FilesDbContextPostgreSql/PostgreSqlFilesDbContextModelSnapshot.cs # common/ASC.Core.Common/Migrations/PostgreSql/MessagesContextPostgreSql/20211012145335_MessagesContextPostgreSql.Designer.cs # common/ASC.Core.Common/Migrations/PostgreSql/MessagesContextPostgreSql/20211012145335_MessagesContextPostgreSql.cs # common/ASC.Core.Common/Migrations/PostgreSql/MessagesContextPostgreSql/20220708104429_MessagesContextPostgreSql.Designer.cs # common/ASC.Core.Common/Migrations/PostgreSql/MessagesContextPostgreSql/20220708104429_MessagesContextPostgreSql.cs # common/ASC.Core.Common/Migrations/PostgreSql/TenantDbContextPostgreSql/20211012145343_TenantDbContextPostgreSql.cs # common/ASC.Core.Common/Migrations/PostgreSql/UserDbContextPostgreSql/20211012145323_UserDbContextPostgreSql.cs # common/ASC.Core.Common/Migrations/PostgreSql/UserDbContextPostgreSql/20220708104403_UserDbContextPostgreSql.Designer.cs # common/ASC.Core.Common/Migrations/PostgreSql/UserDbContextPostgreSql/PostgreSqlUserDbContextModelSnapshot.cs # common/ASC.Data.Backup.Core/Migrations/MySql/BackupsContextMySql/20220708104422_BackupsContextMySql.Designer.cs # common/ASC.Data.Backup.Core/Migrations/PostgreSql/BackupsContextPostgreSql/20220708104423_BackupsContextPostgreSql.Designer.cs # common/ASC.MessagingSystem/Migrations/MySql/MessagesContextMySql/20211012145334_MessagesContextMySql.Designer.cs # common/ASC.MessagingSystem/Migrations/PostgreSql/MessagesContextPostgreSql/20211012145335_MessagesContextPostgreSql.Designer.cs # common/ASC.Resource.Manager/ResourceData.cs # common/services/ASC.AuditTrail/GlobalUsings.cs # products/ASC.Files/Core/Core/EF/DbFilesThirdpartyAccount.cs # products/ASC.Files/Core/Migrations/MySql/FilesDbContextMySql/20211022170840_FilesDbContextMySql.cs # products/ASC.Files/Core/Migrations/MySql/FilesDbContextMySql/MySqlFilesDbContextModelSnapshot.cs # products/ASC.Files/Core/Migrations/PostgreSql/FilesDbContextPostgreSql/20211022170841_FilesDbContextPostgreSql.cs # products/ASC.Files/Core/Migrations/PostgreSql/FilesDbContextPostgreSql/PostgreSqlFilesDbContextModelSnapshot.cs # web/ASC.Web.Api/GlobalUsings.cs
2022-07-11 10:28:49 +00:00
query = query.Where(r => keys.Contains(r.Event.Action ?? 0));
2022-06-08 09:02:40 +00:00
}
}
var hasFromFilter = (from.HasValue && from.Value != DateTime.MinValue);
var hasToFilter = (to.HasValue && to.Value != DateTime.MinValue);
if (hasFromFilter || hasToFilter)
{
if (hasFromFilter)
{
if (hasToFilter)
{
query = query.Where(q => q.Event.Date >= from.Value & q.Event.Date <= to.Value);
}
else
{
query = query.Where(q => q.Event.Date >= from.Value);
}
}
else if (hasToFilter)
{
query = query.Where(q => q.Event.Date <= to.Value);
}
}
return _mapper.Map<List<AuditEventQuery>, IEnumerable<AuditEventDto>>(query.ToList());
}
private static void FindByEntry(IQueryable<AuditEventQuery> q, EntryType entry, string target, IEnumerable<KeyValuePair<MessageAction, MessageMaps>> actions)
{
2022-06-16 08:13:53 +00:00
Expression<Func<AuditEventQuery, bool>> a = r => false;
2022-06-08 09:02:40 +00:00
foreach (var action in actions)
{
2022-06-16 08:13:53 +00:00
if (action.Value.EntryType1 == entry || action.Value.EntryType2 == entry)
2022-06-08 09:02:40 +00:00
{
2022-06-16 08:13:53 +00:00
a = a.Or(r => r.Event.Action == (int)action.Key && r.Event.Target.Split(',', StringSplitOptions.TrimEntries).Contains(target));
2022-06-08 09:02:40 +00:00
}
}
2022-06-16 08:13:53 +00:00
q = q.Where(a);
2022-02-08 00:11:22 +00:00
}
2022-02-01 09:11:19 +00:00
2022-02-03 11:16:34 +00:00
public int GetCount(int tenant, DateTime? from = null, DateTime? to = null)
{
2022-06-08 09:02:40 +00:00
var query = AuditTrailContext.AuditEvents
.Where(a => a.TenantId == tenant);
2022-02-01 09:11:19 +00:00
2022-02-03 11:16:34 +00:00
if (from.HasValue && to.HasValue)
2022-02-08 00:11:22 +00:00
{
2022-02-03 11:16:34 +00:00
query = query.Where(a => a.Date >= from & a.Date <= to);
2022-02-08 00:11:22 +00:00
}
2022-02-01 09:11:19 +00:00
2022-02-03 11:16:34 +00:00
return query.Count();
}
2022-06-16 08:13:53 +00:00
}
2022-02-01 09:11:19 +00:00
2022-06-16 08:13:53 +00:00
internal static class PredicateBuilder
{
internal static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> a, Expression<Func<T, bool>> b)
2022-02-03 11:16:34 +00:00
{
2022-06-16 08:13:53 +00:00
var p = a.Parameters[0];
2022-02-01 09:11:19 +00:00
2022-06-16 08:13:53 +00:00
var visitor = new SubstExpressionVisitor();
visitor.Subst[b.Parameters[0]] = p;
2022-02-01 09:11:19 +00:00
2022-06-16 08:13:53 +00:00
Expression body = Expression.OrElse(a.Body, visitor.Visit(b.Body));
return Expression.Lambda<Func<T, bool>>(body, p);
}
2022-03-18 10:31:02 +00:00
}
2022-06-16 08:13:53 +00:00
internal class SubstExpressionVisitor : System.Linq.Expressions.ExpressionVisitor
{
internal Dictionary<Expression, Expression> Subst = new Dictionary<Expression, Expression>();
protected override Expression VisitParameter(ParameterExpression node)
{
if (Subst.TryGetValue(node, out var newValue))
2022-02-08 00:11:22 +00:00
{
2022-06-16 08:13:53 +00:00
return newValue;
2022-02-08 00:11:22 +00:00
}
2022-06-16 08:13:53 +00:00
return node;
2022-02-01 09:11:19 +00:00
}
2022-06-16 08:13:53 +00:00
}
2022-03-18 10:31:02 +00:00
public static class AuditEventsRepositoryExtensions
{
public static void Register(DIHelper services)
{
services.TryAdd<EventTypeConverter>();
}
2020-10-06 07:06:05 +00:00
}