AuditTrail: used file-scope namespaces

This commit is contained in:
Maksim Chegulov 2022-02-03 14:16:34 +03:00
parent 0cc387a4b8
commit fdc4652edb
20 changed files with 520 additions and 539 deletions

View File

@ -1,17 +1,16 @@
using System;
namespace ASC.AuditTrail.Attributes
{
[AttributeUsage(AttributeTargets.Property)]
public class EventAttribute : Attribute
{
public string Resource { get; private set; }
public int Order { get; private set; }
namespace ASC.AuditTrail.Attributes;
public EventAttribute(string resource, int order = 0)
{
Resource = resource;
Order = order;
}
[AttributeUsage(AttributeTargets.Property)]
public class EventAttribute : Attribute
{
public string Resource { get; private set; }
public int Order { get; private set; }
public EventAttribute(string resource, int order = 0)
{
Resource = resource;
Order = order;
}
}
}

View File

@ -43,58 +43,57 @@ using CsvHelper;
using Microsoft.Extensions.Options;
namespace ASC.AuditTrail
namespace ASC.AuditTrail;
[Scope]
public class AuditReportCreator
{
[Scope]
public class AuditReportCreator
{
private readonly GlobalFolderHelper _globalFolderHelper;
private readonly FileUploader _fileUploader;
private readonly FilesLinkUtility _filesLinkUtility;
private readonly CommonLinkUtility _commonLinkUtility;
private readonly ILog _logger;
public AuditReportCreator(
GlobalFolderHelper globalFolderHelper,
IOptionsMonitor<ILog> options,
FileUploader fileUploader,
FilesLinkUtility filesLinkUtility,
CommonLinkUtility commonLinkUtility)
{
_globalFolderHelper = globalFolderHelper;
_logger = options.CurrentValue;
_fileUploader = fileUploader;
_filesLinkUtility = filesLinkUtility;
_commonLinkUtility = commonLinkUtility;
}
public string CreateCsvReport<TEvent>(IEnumerable<TEvent> events, string reportName) where TEvent : BaseEvent
{
try
{
using var stream = new MemoryStream();
using var writer = new StreamWriter(stream, Encoding.UTF8);
using var csv = new CsvWriter(writer, CultureInfo.CurrentCulture);
private readonly GlobalFolderHelper _globalFolderHelper;
private readonly FileUploader _fileUploader;
private readonly FilesLinkUtility _filesLinkUtility;
private readonly CommonLinkUtility _commonLinkUtility;
private readonly ILog _logger;
csv.Configuration.RegisterClassMap(new BaseEventMap<TEvent>());
public AuditReportCreator(
GlobalFolderHelper globalFolderHelper,
IOptionsMonitor<ILog> options,
FileUploader fileUploader,
FilesLinkUtility filesLinkUtility,
CommonLinkUtility commonLinkUtility)
{
_globalFolderHelper = globalFolderHelper;
_logger = options.CurrentValue;
_fileUploader = fileUploader;
_filesLinkUtility = filesLinkUtility;
_commonLinkUtility = commonLinkUtility;
}
csv.WriteHeader<TEvent>();
csv.NextRecord();
csv.WriteRecords(events);
writer.Flush();
public string CreateCsvReport<TEvent>(IEnumerable<TEvent> events, string reportName) where TEvent : BaseEvent
{
try
{
using var stream = new MemoryStream();
using var writer = new StreamWriter(stream, Encoding.UTF8);
using var csv = new CsvWriter(writer, CultureInfo.CurrentCulture);
var file = _fileUploader.Exec(_globalFolderHelper.FolderMy, reportName, stream.Length, stream, true);
var fileUrl = _commonLinkUtility.GetFullAbsolutePath(_filesLinkUtility.GetFileWebEditorUrl(file.ID));
csv.Configuration.RegisterClassMap(new BaseEventMap<TEvent>());
fileUrl += string.Format("&options={{\"codePage\":{0}}}", Encoding.UTF8.CodePage);
csv.WriteHeader<TEvent>();
csv.NextRecord();
csv.WriteRecords(events);
writer.Flush();
return fileUrl;
}
catch (Exception ex)
{
_logger.Error("Error while generating login report: " + ex);
throw;
}
}
}
var file = _fileUploader.Exec(_globalFolderHelper.FolderMy, reportName, stream.Length, stream, true);
var fileUrl = _commonLinkUtility.GetFullAbsolutePath(_filesLinkUtility.GetFileWebEditorUrl(file.ID));
fileUrl += string.Format("&options={{\"codePage\":{0}}}", Encoding.UTF8.CodePage);
return fileUrl;
}
catch (Exception ex)
{
_logger.Error("Error while generating login report: " + ex);
throw;
}
}
}

View File

@ -35,120 +35,119 @@ using ASC.MessagingSystem;
using Microsoft.Extensions.Options;
namespace ASC.AuditTrail.Mappers
namespace ASC.AuditTrail.Mappers;
[Singletone]
public class AuditActionMapper
{
[Singletone]
public class AuditActionMapper
{
private readonly Dictionary<MessageAction, MessageMaps> _actions;
private readonly ILog _logger;
public AuditActionMapper(IOptionsMonitor<ILog> options)
{
_actions = new Dictionary<MessageAction, MessageMaps>();
_logger = options.CurrentValue;
_actions = _actions
.Union(LoginActionsMapper.GetMaps())
.Union(ProjectsActionsMapper.GetMaps())
.Union(CrmActionMapper.GetMaps())
.Union(PeopleActionMapper.GetMaps())
.Union(DocumentsActionMapper.GetMaps())
.Union(SettingsActionsMapper.GetMaps())
.Union(OthersActionsMapper.GetMaps())
.ToDictionary(x => x.Key, x => x.Value);
}
public string GetActionText(AuditEvent evt)
{
var action = (MessageAction)evt.Action;
if (!_actions.ContainsKey(action))
{
_logger.Error(string.Format("There is no action text for \"{0}\" type of event", action));
return string.Empty;
}
try
{
var actionText = _actions[(MessageAction)evt.Action].GetActionText();
if (evt.Description == null || !evt.Description.Any()) return actionText;
var description = evt.Description
.Select(t => t.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
.Select(split => string.Join(", ", split.Select(ToLimitedText))).ToArray();
return string.Format(actionText, description);
}
catch
{
//log.Error(string.Format("Error while building action text for \"{0}\" type of event", action));
return string.Empty;
}
}
public string GetActionText(LoginEvent evt)
{
var action = (MessageAction)evt.Action;
if (!_actions.ContainsKey(action))
{
//log.Error(string.Format("There is no action text for \"{0}\" type of event", action));
return string.Empty;
}
try
{
var actionText = _actions[(MessageAction)evt.Action].GetActionText();
if (evt.Description == null || !evt.Description.Any()) return actionText;
var description = evt.Description
.Select(t => t.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
.Select(split => string.Join(", ", split.Select(ToLimitedText))).ToArray();
return string.Format(actionText, description);
}
catch
{
//log.Error(string.Format("Error while building action text for \"{0}\" type of event", action));
return string.Empty;
}
}
public string GetActionTypeText(AuditEvent evt)
{
var action = (MessageAction)evt.Action;
return !_actions.ContainsKey(action)
? string.Empty
: _actions[(MessageAction)evt.Action].GetActionTypeText();
}
public string GetProductText(AuditEvent evt)
{
var action = (MessageAction)evt.Action;
return !_actions.ContainsKey(action)
? string.Empty
: _actions[(MessageAction)evt.Action].GetProduct();
}
public string GetModuleText(AuditEvent evt)
{
var action = (MessageAction)evt.Action;
return !_actions.ContainsKey(action)
? string.Empty
: _actions[(MessageAction)evt.Action].GetModule();
}
private string ToLimitedText(string text)
{
if (text == null) return null;
return text.Length < 50 ? text : string.Format("{0}...", text.Substring(0, 47));
}
}
private readonly Dictionary<MessageAction, MessageMaps> _actions;
private readonly ILog _logger;
public AuditActionMapper(IOptionsMonitor<ILog> options)
{
_actions = new Dictionary<MessageAction, MessageMaps>();
_logger = options.CurrentValue;
_actions = _actions
.Union(LoginActionsMapper.GetMaps())
.Union(ProjectsActionsMapper.GetMaps())
.Union(CrmActionMapper.GetMaps())
.Union(PeopleActionMapper.GetMaps())
.Union(DocumentsActionMapper.GetMaps())
.Union(SettingsActionsMapper.GetMaps())
.Union(OthersActionsMapper.GetMaps())
.ToDictionary(x => x.Key, x => x.Value);
}
public string GetActionText(AuditEventDto evt)
{
var action = (MessageAction)evt.Action;
if (!_actions.ContainsKey(action))
{
_logger.Error(string.Format("There is no action text for \"{0}\" type of event", action));
return string.Empty;
}
try
{
var actionText = _actions[(MessageAction)evt.Action].GetActionText();
if (evt.Description == null || !evt.Description.Any()) return actionText;
var description = evt.Description
.Select(t => t.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
.Select(split => string.Join(", ", split.Select(ToLimitedText))).ToArray();
return string.Format(actionText, description);
}
catch
{
//log.Error(string.Format("Error while building action text for \"{0}\" type of event", action));
return string.Empty;
}
}
public string GetActionText(LoginEventDTO evt)
{
var action = (MessageAction)evt.Action;
if (!_actions.ContainsKey(action))
{
//log.Error(string.Format("There is no action text for \"{0}\" type of event", action));
return string.Empty;
}
try
{
var actionText = _actions[(MessageAction)evt.Action].GetActionText();
if (evt.Description == null || !evt.Description.Any()) return actionText;
var description = evt.Description
.Select(t => t.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
.Select(split => string.Join(", ", split.Select(ToLimitedText))).ToArray();
return string.Format(actionText, description);
}
catch
{
//log.Error(string.Format("Error while building action text for \"{0}\" type of event", action));
return string.Empty;
}
}
public string GetActionTypeText(AuditEventDto evt)
{
var action = (MessageAction)evt.Action;
return !_actions.ContainsKey(action)
? string.Empty
: _actions[(MessageAction)evt.Action].GetActionTypeText();
}
public string GetProductText(AuditEventDto evt)
{
var action = (MessageAction)evt.Action;
return !_actions.ContainsKey(action)
? string.Empty
: _actions[(MessageAction)evt.Action].GetProduct();
}
public string GetModuleText(AuditEventDto evt)
{
var action = (MessageAction)evt.Action;
return !_actions.ContainsKey(action)
? string.Empty
: _actions[(MessageAction)evt.Action].GetModule();
}
private string ToLimitedText(string text)
{
if (text == null) return null;
return text.Length < 50 ? text : string.Format("{0}...", text.Substring(0, 47));
}
}

View File

@ -30,13 +30,13 @@ using System.Collections.Generic;
using ASC.MessagingSystem;
namespace ASC.AuditTrail.Mappers
{
internal class CrmActionMapper
{
public static Dictionary<MessageAction, MessageMaps> GetMaps() =>
new Dictionary<MessageAction, MessageMaps>
{
namespace ASC.AuditTrail.Mappers;
internal class CrmActionMapper
{
public static Dictionary<MessageAction, MessageMaps> GetMaps() =>
new Dictionary<MessageAction, MessageMaps>
{
#region companies
{
@ -1618,9 +1618,8 @@ namespace ASC.AuditTrail.Mappers
ProductResourceName = "CrmProduct",
ModuleResourceName = "CasesModule"
}
},
#endregion
};
}
},
#endregion
};
}

View File

@ -29,13 +29,13 @@ using System.Collections.Generic;
using ASC.MessagingSystem;
namespace ASC.AuditTrail.Mappers
{
internal class DocumentsActionMapper
{
public static Dictionary<MessageAction, MessageMaps> GetMaps() =>
new Dictionary<MessageAction, MessageMaps>
{
namespace ASC.AuditTrail.Mappers;
internal class DocumentsActionMapper
{
public static Dictionary<MessageAction, MessageMaps> GetMaps() =>
new Dictionary<MessageAction, MessageMaps>
{
{
MessageAction.FileRenamed, new MessageMaps
{
@ -413,7 +413,6 @@ namespace ASC.AuditTrail.Mappers
ProductResourceName = "DocumentsProduct",
ModuleResourceName = "FilesModule"
}
},
};
}
},
};
}

View File

@ -30,13 +30,13 @@ using System.Collections.Generic;
using ASC.MessagingSystem;
namespace ASC.AuditTrail.Mappers
{
internal class LoginActionsMapper
{
public static Dictionary<MessageAction, MessageMaps> GetMaps() =>
new Dictionary<MessageAction, MessageMaps>
{
namespace ASC.AuditTrail.Mappers;
internal class LoginActionsMapper
{
public static Dictionary<MessageAction, MessageMaps> GetMaps() =>
new Dictionary<MessageAction, MessageMaps>
{
{ MessageAction.LoginSuccess, new MessageMaps { ActionTextResourceName = "LoginSuccess"} },
{ MessageAction.LoginSuccessViaSocialAccount, new MessageMaps { ActionTextResourceName = "LoginSuccessSocialAccount"} },
{ MessageAction.LoginSuccessViaSocialApp, new MessageMaps { ActionTextResourceName = "LoginSuccessSocialApp"} },
@ -63,7 +63,6 @@ namespace ASC.AuditTrail.Mappers
{ MessageAction.LoginFailRecaptcha, new MessageMaps { ActionTextResourceName = "LoginFailRecaptcha" } },
{ MessageAction.Logout, new MessageMaps { ActionTextResourceName = "Logout" } },
{ MessageAction.SessionStarted, new MessageMaps { ActionTextResourceName = "SessionStarted" } },
{ MessageAction.SessionCompleted, new MessageMaps { ActionTextResourceName = "SessionCompleted" } }
};
}
{ MessageAction.SessionCompleted, new MessageMaps { ActionTextResourceName = "SessionCompleted" } }
};
}

View File

@ -28,61 +28,60 @@
namespace ASC.AuditTrail.Mappers
namespace ASC.AuditTrail.Mappers;
internal class MessageMaps
{
internal class MessageMaps
public string ActionTypeTextResourceName { get; set; }
public string ActionTextResourceName { get; set; }
public string ProductResourceName { get; set; }
public string ModuleResourceName { get; set; }
public string GetActionTypeText()
{
public string ActionTypeTextResourceName { get; set; }
public string ActionTextResourceName { get; set; }
public string ProductResourceName { get; set; }
public string ModuleResourceName { get; set; }
public string GetActionTypeText()
try
{
try
{
return AuditReportResource.ResourceManager.GetString(ActionTypeTextResourceName);
}
catch
{
return null;
}
return AuditReportResource.ResourceManager.GetString(ActionTypeTextResourceName);
}
public string GetActionText()
catch
{
try
{
return AuditReportResource.ResourceManager.GetString(ActionTextResourceName);
}
catch
{
return null;
}
return null;
}
}
public string GetProduct()
public string GetActionText()
{
try
{
try
{
return AuditReportResource.ResourceManager.GetString(ProductResourceName);
}
catch
{
return null;
}
return AuditReportResource.ResourceManager.GetString(ActionTextResourceName);
}
public string GetModule()
catch
{
try
{
return AuditReportResource.ResourceManager.GetString(ModuleResourceName);
}
catch
{
return null;
}
return null;
}
}
public string GetProduct()
{
try
{
return AuditReportResource.ResourceManager.GetString(ProductResourceName);
}
catch
{
return null;
}
}
public string GetModule()
{
try
{
return AuditReportResource.ResourceManager.GetString(ModuleResourceName);
}
catch
{
return null;
}
}
}

View File

@ -30,13 +30,13 @@ using System.Collections.Generic;
using ASC.MessagingSystem;
namespace ASC.AuditTrail.Mappers
{
internal class OthersActionsMapper
{
public static Dictionary<MessageAction, MessageMaps> GetMaps() =>
new Dictionary<MessageAction, MessageMaps>
{
namespace ASC.AuditTrail.Mappers;
internal class OthersActionsMapper
{
public static Dictionary<MessageAction, MessageMaps> GetMaps() =>
new Dictionary<MessageAction, MessageMaps>
{
{
MessageAction.ContactAdminMailSent, new MessageMaps
{
@ -44,7 +44,6 @@ namespace ASC.AuditTrail.Mappers
ActionTextResourceName = "ContactAdminMailSent",
ProductResourceName = "OthersProduct"
}
}
};
}
}
};
}

View File

@ -30,13 +30,13 @@ using System.Collections.Generic;
using ASC.MessagingSystem;
namespace ASC.AuditTrail.Mappers
{
internal class PeopleActionMapper
{
public static Dictionary<MessageAction, MessageMaps> GetMaps() =>
new Dictionary<MessageAction, MessageMaps>
{
namespace ASC.AuditTrail.Mappers;
internal class PeopleActionMapper
{
public static Dictionary<MessageAction, MessageMaps> GetMaps() =>
new Dictionary<MessageAction, MessageMaps>
{
{
MessageAction.UserCreated, new MessageMaps
{
@ -351,7 +351,6 @@ namespace ASC.AuditTrail.Mappers
ProductResourceName = "PeopleProduct",
ModuleResourceName = "UsersModule"
}
}
};
}
}
};
}

View File

@ -29,13 +29,13 @@ using System.Collections.Generic;
using ASC.MessagingSystem;
namespace ASC.AuditTrail.Mappers
{
internal class ProjectsActionsMapper
{
public static Dictionary<MessageAction, MessageMaps> GetMaps() =>
new Dictionary<MessageAction, MessageMaps>
{
namespace ASC.AuditTrail.Mappers;
internal class ProjectsActionsMapper
{
public static Dictionary<MessageAction, MessageMaps> GetMaps() =>
new Dictionary<MessageAction, MessageMaps>
{
#region projects
{
@ -604,9 +604,8 @@ namespace ASC.AuditTrail.Mappers
ProductResourceName = "ProjectsProduct",
ModuleResourceName = "ProjectsModule"
}
},
#endregion
};
}
},
#endregion
};
}

View File

@ -29,13 +29,13 @@ using System.Collections.Generic;
using ASC.MessagingSystem;
namespace ASC.AuditTrail.Mappers
{
internal class SettingsActionsMapper
{
public static Dictionary<MessageAction, MessageMaps> GetMaps() =>
new Dictionary<MessageAction, MessageMaps>
{
namespace ASC.AuditTrail.Mappers;
internal class SettingsActionsMapper
{
public static Dictionary<MessageAction, MessageMaps> GetMaps() =>
new Dictionary<MessageAction, MessageMaps>
{
{
MessageAction.LanguageSettingsUpdated, new MessageMaps
{
@ -476,7 +476,6 @@ namespace ASC.AuditTrail.Mappers
ProductResourceName = "SettingsProduct",
ModuleResourceName = "ProductsModule"
}
}
};
}
}
};
}

View File

@ -32,38 +32,37 @@ using ASC.Core.Common.EF;
using ASC.AuditTrail.Models.Mapping.Actions;
using ASC.Core.Common.EF.Model;
namespace ASC.AuditTrail.Models
namespace ASC.AuditTrail.Models;
public class AuditEventDto : BaseEvent, IMapFrom<AuditEventQuery>
{
public class AuditEventDto : BaseEvent, IMapFrom<AuditEventQuery>
public string Initiator { get; set; }
[Event("ActionIdCol", 33)]
public int Action { get; set; }
[Event("ActionTypeCol", 30)]
public string ActionTypeText { get; set; }
[Event("ProductCol", 31)]
public string Product { get; set; }
[Event("ModuleCol", 32)]
public string Module { get; set; }
[Event("TargetIdCol", 34)]
public MessageTarget Target { get; set; }
public void Mapping(Profile profile)
{
public string Initiator { get; set; }
profile.CreateMap<AuditEvent, AuditEventDto>()
.ForMember(src => src.Description, opt => opt.Ignore());
[Event("ActionIdCol", 33)]
public int Action { get; set; }
profile.CreateMap<User, AuditEventDto>()
.ForMember(src => src.Id, opt => opt.Ignore());
[Event("ActionTypeCol", 30)]
public string ActionTypeText { get; set; }
[Event("ProductCol", 31)]
public string Product { get; set; }
[Event("ModuleCol", 32)]
public string Module { get; set; }
[Event("TargetIdCol", 34)]
public MessageTarget Target { get; set; }
public void Mapping(Profile profile)
{
profile.CreateMap<AuditEvent, AuditEventDto>()
.ForMember(src => src.Description, opt => opt.Ignore());
profile.CreateMap<User, AuditEventDto>()
.ForMember(src => src.Id, opt => opt.Ignore());
profile.CreateMap<AuditEventQuery, AuditEventDto>()
.IncludeMembers(src => src.AuditEvent, src => src.User)
.AfterMap<AuditEventMappingAction>();
}
profile.CreateMap<AuditEventQuery, AuditEventDto>()
.IncludeMembers(src => src.AuditEvent, src => src.User)
.AfterMap<AuditEventMappingAction>();
}
}

View File

@ -1,10 +1,10 @@
using ASC.Core.Common.EF;
using ASC.Core.Common.EF.Model;
namespace ASC.AuditTrail.Models
namespace ASC.AuditTrail.Models;
public class AuditEventQuery
{
public class AuditEventQuery
{
public Core.Common.EF.Model.AuditEvent AuditEvent { get; set; }
public User User { get; set; }
}
public AuditEvent AuditEvent { get; set; }
public User User { get; set; }
}

View File

@ -35,53 +35,52 @@ using ASC.AuditTrail.Attributes;
using CsvHelper.Configuration;
namespace ASC.AuditTrail.Models
namespace ASC.AuditTrail.Models;
public class BaseEvent
{
public class BaseEvent
public int Id { get; set; }
public int TenantId { get; set; }
public Guid UserId { get; set; }
public bool Mobile { get; set; }
public IList<string> Description { get; set; }
[Event("IpCol")]
public string Ip { get; set; }
[Event("BrowserCol")]
public string Browser { get; set; }
[Event("PlatformCol")]
public string Platform { get; set; }
[Event("DateCol")]
public DateTime Date { get; set; }
[Event("UserCol")]
public string UserName { get; set; }
[Event("PageCol")]
public string Page { get; set; }
[Event("ActionCol")]
public string ActionText { get; set; }
}
internal class BaseEventMap<T> : ClassMap<T> where T : BaseEvent
{
public BaseEventMap()
{
public int Id { get; set; }
public int TenantId { get; set; }
public Guid UserId { get; set; }
public bool Mobile { get; set; }
public IList<string> Description { get; set; }
var eventType = typeof(T);
var eventProps = eventType
.GetProperties()
.Where(r => r.GetCustomAttribute<EventAttribute>() != null)
.OrderBy(r => r.GetCustomAttribute<EventAttribute>().Order);
[Event("IpCol")]
public string Ip { get; set; }
[Event("BrowserCol")]
public string Browser { get; set; }
[Event("PlatformCol")]
public string Platform { get; set; }
[Event("DateCol")]
public DateTime Date { get; set; }
[Event("UserCol")]
public string UserName { get; set; }
[Event("PageCol")]
public string Page { get; set; }
[Event("ActionCol")]
public string ActionText { get; set; }
}
internal class BaseEventMap<T> : ClassMap<T> where T : BaseEvent
{
public BaseEventMap()
foreach (var prop in eventProps)
{
var eventType = typeof(T);
var eventProps = eventType
.GetProperties()
.Where(r => r.GetCustomAttribute<EventAttribute>() != null)
.OrderBy(r=> r.GetCustomAttribute<EventAttribute>().Order);
foreach (var prop in eventProps)
{
var attr = prop.GetCustomAttribute<EventAttribute>().Resource;
Map(eventType, prop).Name(AuditReportResource.ResourceManager.GetString(attr));
}
var attr = prop.GetCustomAttribute<EventAttribute>().Resource;
Map(eventType, prop).Name(AuditReportResource.ResourceManager.GetString(attr));
}
}
}
}

View File

@ -33,24 +33,23 @@ using ASC.Core.Common.EF.Model;
using AutoMapper;
namespace ASC.AuditTrail.Models
namespace ASC.AuditTrail.Models;
public class LoginEventDTO : BaseEvent, IMapFrom<LoginEventQuery>
{
public class LoginEventDTO : BaseEvent, IMapFrom<LoginEventQuery>
public string Login { get; set; }
public int Action { get; set; }
public void Mapping(Profile profile)
{
public string Login { get; set; }
public int Action { get; set; }
profile.CreateMap<LoginEvent, LoginEventDTO>()
.ForMember(src => src.Description, opt => opt.Ignore());
public void Mapping(Profile profile)
{
profile.CreateMap<LoginEvents, LoginEventDTO>()
.ForMember(src => src.Description, opt => opt.Ignore());
profile.CreateMap<User, LoginEventDTO>()
.ForMember(src => src.Id, opt => opt.Ignore());
profile.CreateMap<User, LoginEventDTO>()
.ForMember(src => src.Id, opt => opt.Ignore());
profile.CreateMap<LoginEventQuery, LoginEventDTO>()
.IncludeMembers(src => src.LoginEvents, src => src.User)
.AfterMap<LoginEventMappingAction>();
}
profile.CreateMap<LoginEventQuery, LoginEventDTO>()
.IncludeMembers(src => src.LoginEvents, src => src.User)
.AfterMap<LoginEventMappingAction>();
}
}

View File

@ -1,11 +1,10 @@
using ASC.Core.Common.EF;
using ASC.Core.Common.EF.Model;
namespace ASC.AuditTrail.Models
namespace ASC.AuditTrail.Models;
public class LoginEventQuery
{
public class LoginEventQuery
{
public LoginEvents LoginEvents { get; set; }
public User User { get; set; }
}
}
public LoginEvent LoginEvents { get; set; }
public User User { get; set; }
}

View File

@ -8,42 +8,41 @@ using ASC.MessagingSystem;
using ASC.Core.Users;
using ASC.AuditTrail.Mappers;
namespace ASC.AuditTrail.Models.Mapping.Actions
namespace ASC.AuditTrail.Models.Mapping.Actions;
public class AuditEventMappingAction : IMappingAction<AuditEventQuery, AuditEventDto>
{
public class AuditEventMappingAction : IMappingAction<AuditEventQuery, AuditEventDto>
private MessageTarget _messageTarget;
private UserFormatter _userFormatter;
private AuditActionMapper _auditActionMapper;
public AuditEventMappingAction(
MessageTarget messageTarget,
UserFormatter userFormatter,
AuditActionMapper auditActionMapper)
{
private MessageTarget _messageTarget;
private UserFormatter _userFormatter;
private AuditActionMapper _auditActionMapper;
_messageTarget = messageTarget;
_userFormatter = userFormatter;
_auditActionMapper = auditActionMapper;
}
public AuditEventMappingAction(
MessageTarget messageTarget,
UserFormatter userFormatter,
AuditActionMapper auditActionMapper)
{
_messageTarget = messageTarget;
_userFormatter = userFormatter;
_auditActionMapper = auditActionMapper;
}
public void Process(AuditEventQuery source, AuditEventDto destination, ResolutionContext context)
{
if (source.AuditEvent.Description != null)
destination.Description = JsonConvert.DeserializeObject<IList<string>>(
Convert.ToString(source.AuditEvent.Description),
new JsonSerializerSettings { DateTimeZoneHandling = DateTimeZoneHandling.Utc });
public void Process(AuditEventQuery source, AuditEventDto destination, ResolutionContext context)
{
if (source.AuditEvent.Description != null)
destination.Description = JsonConvert.DeserializeObject<IList<string>>(
Convert.ToString(source.AuditEvent.Description),
new JsonSerializerSettings { DateTimeZoneHandling = DateTimeZoneHandling.Utc });
destination.Target = _messageTarget.Parse(source.AuditEvent.Target);
destination.Target = _messageTarget.Parse(source.AuditEvent.Target);
destination.UserName = (source.User.FirstName != null && source.User.LastName != null) ? _userFormatter.GetUserName(source.User.FirstName, source.User.LastName) :
source.AuditEvent.UserId == Core.Configuration.Constants.CoreSystem.ID ? AuditReportResource.SystemAccount :
source.AuditEvent.UserId == Core.Configuration.Constants.Guest.ID ? AuditReportResource.GuestAccount :
source.AuditEvent.Initiator ?? AuditReportResource.UnknownAccount;
destination.UserName = (source.User.FirstName != null && source.User.LastName != null) ? _userFormatter.GetUserName(source.User.FirstName, source.User.LastName) :
source.AuditEvent.UserId == Core.Configuration.Constants.CoreSystem.ID ? AuditReportResource.SystemAccount :
source.AuditEvent.UserId == Core.Configuration.Constants.Guest.ID ? AuditReportResource.GuestAccount :
source.AuditEvent.Initiator ?? AuditReportResource.UnknownAccount;
destination.ActionText = _auditActionMapper.GetActionText(destination);
destination.ActionTypeText = _auditActionMapper.GetActionTypeText(destination);
destination.Product = _auditActionMapper.GetProductText(destination);
destination.Module = _auditActionMapper.GetModuleText(destination);
}
destination.ActionText = _auditActionMapper.GetActionText(destination);
destination.ActionTypeText = _auditActionMapper.GetActionTypeText(destination);
destination.Product = _auditActionMapper.GetProductText(destination);
destination.Module = _auditActionMapper.GetModuleText(destination);
}
}

View File

@ -7,38 +7,37 @@ using AutoMapper;
using Newtonsoft.Json;
namespace ASC.AuditTrail.Models.Mapping.Actions
namespace ASC.AuditTrail.Models.Mapping.Actions;
public class LoginEventMappingAction : IMappingAction<LoginEventQuery, LoginEventDTO>
{
public class LoginEventMappingAction : IMappingAction<LoginEventQuery, LoginEventDTO>
private readonly UserFormatter _userFormatter;
private readonly AuditActionMapper _auditActionMapper;
public LoginEventMappingAction(UserFormatter userFormatter, AuditActionMapper auditActionMapper)
{
private readonly UserFormatter _userFormatter;
private readonly AuditActionMapper _auditActionMapper;
_userFormatter = userFormatter;
_auditActionMapper = auditActionMapper;
}
public LoginEventMappingAction(UserFormatter userFormatter, AuditActionMapper auditActionMapper)
{
_userFormatter = userFormatter;
_auditActionMapper = auditActionMapper;
}
public void Process(LoginEventQuery source, LoginEventDTO destination, ResolutionContext context)
{
if (source.LoginEvents.Description != null)
destination.Description = JsonConvert.DeserializeObject<IList<string>>(
source.LoginEvents.Description,
new JsonSerializerSettings
{
DateTimeZoneHandling = DateTimeZoneHandling.Utc
});
public void Process(LoginEventQuery source, LoginEventDTO destination, ResolutionContext context)
{
if (source.LoginEvents.Description != null)
destination.Description = JsonConvert.DeserializeObject<IList<string>>(
source.LoginEvents.Description,
new JsonSerializerSettings
{
DateTimeZoneHandling = DateTimeZoneHandling.Utc
});
destination.UserName = (!string.IsNullOrEmpty(source.User?.FirstName) && !string.IsNullOrEmpty(source.User?.LastName))
? _userFormatter.GetUserName(source.User.FirstName, source.User.LastName)
: !string.IsNullOrWhiteSpace(source.LoginEvents.Login)
? source.LoginEvents.Login
: source.LoginEvents.UserId == Core.Configuration.Constants.Guest.ID
? AuditReportResource.GuestAccount
: AuditReportResource.UnknownAccount;
destination.UserName = (!string.IsNullOrEmpty(source.User?.FirstName) && !string.IsNullOrEmpty(source.User?.LastName))
? _userFormatter.GetUserName(source.User.FirstName, source.User.LastName)
: !string.IsNullOrWhiteSpace(source.LoginEvents.Login)
? source.LoginEvents.Login
: source.LoginEvents.UserId == Core.Configuration.Constants.Guest.ID
? AuditReportResource.GuestAccount
: AuditReportResource.UnknownAccount;
destination.ActionText = _auditActionMapper.GetActionText(destination);
}
destination.ActionText = _auditActionMapper.GetActionText(destination);
}
}

View File

@ -35,55 +35,54 @@ using ASC.Core.Common.EF.Context;
using AutoMapper;
namespace ASC.AuditTrail.Repositories
namespace ASC.AuditTrail.Repositories;
[Scope]
public class AuditEventsRepository
{
[Scope]
public class AuditEventsRepository
private AuditTrailContext AuditTrailContext => _lazyAuditTrailContext.Value;
private readonly Lazy<AuditTrailContext> _lazyAuditTrailContext;
private readonly IMapper _mapper;
public AuditEventsRepository(
DbContextManager<AuditTrailContext> dbContextManager,
IMapper mapper)
{
private AuditTrailContext AuditTrailContext => _lazyAuditTrailContext.Value;
_lazyAuditTrailContext = new Lazy<AuditTrailContext>(() => dbContextManager.Value);
_mapper = mapper;
}
private readonly Lazy<AuditTrailContext> _lazyAuditTrailContext;
private readonly IMapper _mapper;
public IEnumerable<AuditEventDto> GetLast(int tenant, int chunk) => Get(tenant, null, null, chunk);
public AuditEventsRepository(
DbContextManager<AuditTrailContext> dbContextManager,
IMapper mapper)
{
_lazyAuditTrailContext = new Lazy<AuditTrailContext>(() => dbContextManager.Value);
_mapper = mapper;
}
public IEnumerable<AuditEventDto> Get(int tenant, DateTime from, DateTime to) => Get(tenant, from, to, null);
public IEnumerable<AuditEvent> GetLast(int tenant, int chunk) => Get(tenant, null, null, chunk);
public int GetCount(int tenant, DateTime? from = null, DateTime? to = null)
{
IQueryable<Core.Common.EF.Model.AuditEvent> query = AuditTrailContext.AuditEvents
.Where(a => a.TenantId == tenant)
.OrderByDescending(a => a.Date);
public IEnumerable<AuditEvent> Get(int tenant, DateTime from, DateTime to) => Get(tenant, from, to, null);
if (from.HasValue && to.HasValue)
query = query.Where(a => a.Date >= from & a.Date <= to);
private IEnumerable<AuditEvent> Get(int tenant, DateTime? fromDate, DateTime? to, int? limit)
{
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 { AuditEvent = q, User = p };
return query.Count();
}
if (fromDate.HasValue && to.HasValue)
query = query.Where(q => q.AuditEvent.Date >= fromDate & q.AuditEvent.Date <= to);
private IEnumerable<AuditEventDto> Get(int tenant, DateTime? fromDate, DateTime? to, int? limit)
{
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 { AuditEvent = q, User = p };
if (limit.HasValue) query = query.Take((int)limit);
if (fromDate.HasValue && to.HasValue)
query = query.Where(q => q.AuditEvent.Date >= fromDate & q.AuditEvent.Date <= to);
return query.AsEnumerable().Select(_mapper.Map<AuditEvent>).ToList();
}
if (limit.HasValue) query = query.Take((int)limit);
public int GetCount(int tenant, DateTime? from = null, DateTime? to = null)
{
IQueryable<Core.Common.EF.Model.AuditEvent> query = AuditTrailContext.AuditEvents
.Where(a => a.TenantId == tenant)
.OrderByDescending(a => a.Date);
if (from.HasValue && to.HasValue)
query = query.Where(a => a.Date >= from & a.Date <= to);
return query.Count();
}
return query.AsEnumerable().Select(_mapper.Map<AuditEventDto>).ToList();
}
}

View File

@ -36,59 +36,58 @@ using ASC.Core.Common.EF.Context;
using AutoMapper;
namespace ASC.AuditTrail.Data.Repositories
namespace ASC.AuditTrail.Data.Repositories;
[Scope]
public class LoginEventsRepository
{
[Scope]
public class LoginEventsRepository
private MessagesContext MessagesContext => _lazyMessagesContext.Value;
private readonly Lazy<MessagesContext> _lazyMessagesContext;
private readonly IMapper _mapper;
public LoginEventsRepository(
DbContextManager<MessagesContext> dbMessagesContext,
IMapper mapper)
{
private MessagesContext MessagesContext => _lazyMessagesContext.Value;
_lazyMessagesContext = new Lazy<MessagesContext>(() => dbMessagesContext.Value);
_mapper = mapper;
}
private readonly Lazy<MessagesContext> _lazyMessagesContext;
private readonly IMapper _mapper;
public IEnumerable<LoginEventDTO> GetLast(int tenant, int chunk)
{
var query =
(from b in MessagesContext.LoginEvents
from p in MessagesContext.Users.Where(p => b.UserId == p.Id).DefaultIfEmpty()
where b.TenantId == tenant
orderby b.Date descending
select new LoginEventQuery { LoginEvents = b, User = p })
.Take(chunk);
public LoginEventsRepository(
DbContextManager<MessagesContext> dbMessagesContext,
IMapper mapper)
{
_lazyMessagesContext = new Lazy<MessagesContext>(() => dbMessagesContext.Value);
_mapper = mapper;
}
return query.AsEnumerable().Select(_mapper.Map<LoginEventDTO>).ToList();
}
public IEnumerable<LoginEvent> GetLast(int tenant, int chunk)
{
var query =
(from b in MessagesContext.LoginEvents
from p in MessagesContext.Users.Where(p => b.UserId == p.Id).DefaultIfEmpty()
where b.TenantId == tenant
orderby b.Date descending
select new LoginEventQuery { LoginEvents = b, User = p })
.Take(chunk);
public IEnumerable<LoginEventDTO> Get(int tenant, DateTime fromDate, DateTime to)
{
var query =
from q in MessagesContext.LoginEvents
from p in MessagesContext.Users.Where(p => q.UserId == p.Id).DefaultIfEmpty()
where q.TenantId == tenant
where q.Date >= fromDate
where q.Date <= to
orderby q.Date descending
select new LoginEventQuery { LoginEvents = q, User = p };
return query.AsEnumerable().Select(_mapper.Map<LoginEvent>).ToList();
}
return query.AsEnumerable().Select(_mapper.Map<LoginEventDTO>).ToList();
}
public IEnumerable<LoginEvent> Get(int tenant, DateTime fromDate, DateTime to)
{
var query =
from q in MessagesContext.LoginEvents
from p in MessagesContext.Users.Where(p => q.UserId == p.Id).DefaultIfEmpty()
where q.TenantId == tenant
where q.Date >= fromDate
where q.Date <= to
orderby q.Date descending
select new LoginEventQuery { LoginEvents = q, User = p };
public int GetCount(int tenant, DateTime? from = null, DateTime? to = null)
{
var query = MessagesContext.LoginEvents
.Where(l => l.TenantId == tenant);
return query.AsEnumerable().Select(_mapper.Map<LoginEvent>).ToList();
}
if (from.HasValue && to.HasValue) query = query.Where(l => l.Date >= from & l.Date <= to);
public int GetCount(int tenant, DateTime? from = null, DateTime? to = null)
{
var query = MessagesContext.LoginEvents
.Where(l => l.TenantId == tenant);
if (from.HasValue && to.HasValue) query = query.Where(l => l.Date >= from & l.Date <= to);
return query.Count();
}
return query.Count();
}
}