533 lines
20 KiB
C#
533 lines
20 KiB
C#
using System;
|
||
using System.Data;
|
||
using System.Diagnostics;
|
||
using System.Threading;
|
||
|
||
using umbraco.DataLayer;
|
||
using System.Collections.Generic;
|
||
using System.Reflection;
|
||
using umbraco.BusinessLogic.Utils;
|
||
|
||
namespace umbraco.BusinessLogic
|
||
{
|
||
/// <summary>
|
||
/// Summary description for Log.
|
||
/// </summary>
|
||
public class Log
|
||
{
|
||
#region Statics
|
||
private Interfaces.ILog m_externalLogger = null;
|
||
private bool m_externalLoggerInitiated = false;
|
||
|
||
internal Interfaces.ILog ExternalLogger
|
||
{
|
||
get
|
||
{
|
||
if (!m_externalLoggerInitiated)
|
||
{
|
||
m_externalLoggerInitiated = true;
|
||
if (!String.IsNullOrEmpty(UmbracoSettings.ExternalLoggerAssembly)
|
||
&& !String.IsNullOrEmpty(UmbracoSettings.ExternalLoggerType))
|
||
{
|
||
try
|
||
{
|
||
string assemblyPath = IO.IOHelper.MapPath(UmbracoSettings.ExternalLoggerAssembly);
|
||
m_externalLogger = Assembly.LoadFrom(assemblyPath).CreateInstance(UmbracoSettings.ExternalLoggerType) as Interfaces.ILog;
|
||
}
|
||
catch (Exception ee)
|
||
{
|
||
Log.AddLocally(LogTypes.Error, User.GetUser(0), -1,
|
||
"Error loading external logger: " + ee.ToString());
|
||
}
|
||
}
|
||
}
|
||
|
||
return m_externalLogger;
|
||
}
|
||
}
|
||
|
||
|
||
#region Singleton
|
||
|
||
public static Log Instance
|
||
{
|
||
get { return Singleton<Log>.Instance; }
|
||
}
|
||
|
||
#endregion
|
||
|
||
private static ISqlHelper SqlHelper
|
||
{
|
||
get { return Application.SqlHelper; }
|
||
}
|
||
|
||
/// <summary>
|
||
/// Adds the specified log item to the log.
|
||
/// </summary>
|
||
/// <param name="type">The log type.</param>
|
||
/// <param name="user">The user adding the item.</param>
|
||
/// <param name="nodeId">The affected node id.</param>
|
||
/// <param name="comment">Comment.</param>
|
||
public static void Add(LogTypes type, User user, int nodeId, string comment)
|
||
{
|
||
if (Instance.ExternalLogger != null)
|
||
{
|
||
Instance.ExternalLogger.Add(type, user, nodeId, comment);
|
||
|
||
// Audit trail too?
|
||
if (!UmbracoSettings.ExternalLoggerLogAuditTrail && type.GetType().GetField(type.ToString()).GetCustomAttributes(typeof(AuditTrailLogItem), true) != null)
|
||
{
|
||
AddLocally(type, user, nodeId, comment);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (!UmbracoSettings.EnableLogging) return;
|
||
|
||
if (UmbracoSettings.DisabledLogTypes != null &&
|
||
UmbracoSettings.DisabledLogTypes.SelectSingleNode(String.Format("//logTypeAlias [. = '{0}']", type.ToString().ToLower())) == null)
|
||
{
|
||
|
||
if (comment.Length > 3999)
|
||
comment = comment.Substring(0, 3955) + "...";
|
||
|
||
if (UmbracoSettings.EnableAsyncLogging)
|
||
{
|
||
ThreadPool.QueueUserWorkItem(
|
||
delegate { AddSynced(type, user == null ? 0 : user.Id, nodeId, comment); });
|
||
return;
|
||
}
|
||
|
||
AddSynced(type, user == null ? 0 : user.Id, nodeId, comment);
|
||
}
|
||
}
|
||
}
|
||
|
||
public void AddException(Exception ee)
|
||
{
|
||
if (ExternalLogger != null)
|
||
{
|
||
ExternalLogger.Add(ee);
|
||
}
|
||
else
|
||
{
|
||
Exception ex2 = ee;
|
||
string error = String.Empty;
|
||
string errorMessage = string.Empty;
|
||
while (ex2 != null)
|
||
{
|
||
error += ex2.ToString();
|
||
ex2 = ex2.InnerException;
|
||
}
|
||
Add(LogTypes.Error, -1, error);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Adds the specified log item to the Umbraco log no matter if an external logger has been defined.
|
||
/// </summary>
|
||
/// <param name="type">The log type.</param>
|
||
/// <param name="user">The user adding the item.</param>
|
||
/// <param name="nodeId">The affected node id.</param>
|
||
/// <param name="comment">Comment.</param>
|
||
public static void AddLocally(LogTypes type, User user, int nodeId, string comment)
|
||
{
|
||
if (comment.Length > 3999)
|
||
comment = comment.Substring(0, 3955) + "...";
|
||
|
||
if (UmbracoSettings.EnableAsyncLogging)
|
||
{
|
||
ThreadPool.QueueUserWorkItem(
|
||
delegate { AddSynced(type, user == null ? 0 : user.Id, nodeId, comment); });
|
||
return;
|
||
}
|
||
|
||
AddSynced(type, user == null ? 0 : user.Id, nodeId, comment);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Adds the specified log item to the log without any user information attached.
|
||
/// </summary>
|
||
/// <param name="type">The log type.</param>
|
||
/// <param name="nodeId">The affected node id.</param>
|
||
/// <param name="comment">Comment.</param>
|
||
public static void Add(LogTypes type, int nodeId, string comment)
|
||
{
|
||
Add(type, null, nodeId, comment);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Adds a log item to the log immidiately instead of Queuing it as a work item.
|
||
/// </summary>
|
||
/// <param name="type">The type.</param>
|
||
/// <param name="userId">The user id.</param>
|
||
/// <param name="nodeId">The node id.</param>
|
||
/// <param name="comment">The comment.</param>
|
||
public static void AddSynced(LogTypes type, int userId, int nodeId, string comment)
|
||
{
|
||
try
|
||
{
|
||
SqlHelper.ExecuteNonQuery(
|
||
"insert into umbracoLog (userId, nodeId, logHeader, logComment) values (@userId, @nodeId, @logHeader, @comment)",
|
||
SqlHelper.CreateParameter("@userId", userId),
|
||
SqlHelper.CreateParameter("@nodeId", nodeId),
|
||
SqlHelper.CreateParameter("@logHeader", type.ToString()),
|
||
SqlHelper.CreateParameter("@comment", comment));
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Debug.WriteLine(e.ToString(), "Error");
|
||
Trace.WriteLine(e.ToString());
|
||
}
|
||
}
|
||
|
||
public List<LogItem> GetAuditLogItems(int NodeId)
|
||
{
|
||
if (UmbracoSettings.ExternalLoggerLogAuditTrail && ExternalLogger != null)
|
||
return ExternalLogger.GetAuditLogReader(NodeId);
|
||
else
|
||
return LogItem.ConvertIRecordsReader(SqlHelper.ExecuteReader(
|
||
"select userId, nodeId, logHeader, DateStamp, logComment from umbracoLog where nodeId = @id and logHeader not in ('open','system') order by DateStamp desc",
|
||
SqlHelper.CreateParameter("@id", NodeId)));
|
||
}
|
||
|
||
public List<LogItem> GetLogItems(LogTypes type, DateTime sinceDate)
|
||
{
|
||
if (ExternalLogger != null)
|
||
return ExternalLogger.GetLogItems(type, sinceDate);
|
||
else
|
||
return LogItem.ConvertIRecordsReader(SqlHelper.ExecuteReader(
|
||
"select userId, NodeId, DateStamp, logHeader, logComment from umbracoLog where logHeader = @logHeader and DateStamp >= @dateStamp order by dateStamp desc",
|
||
SqlHelper.CreateParameter("@logHeader", type),
|
||
SqlHelper.CreateParameter("@dateStamp", sinceDate)));
|
||
}
|
||
|
||
public List<LogItem> GetLogItems(int nodeId)
|
||
{
|
||
if (ExternalLogger != null)
|
||
return ExternalLogger.GetLogItems(nodeId);
|
||
else
|
||
return LogItem.ConvertIRecordsReader(SqlHelper.ExecuteReader(
|
||
"select userId, NodeId, DateStamp, logHeader, logComment from umbracoLog where id = @id order by dateStamp desc",
|
||
SqlHelper.CreateParameter("@id", nodeId)));
|
||
}
|
||
|
||
public List<LogItem> GetLogItems(User user, DateTime sinceDate)
|
||
{
|
||
if (ExternalLogger != null)
|
||
return ExternalLogger.GetLogItems(user, sinceDate);
|
||
else
|
||
return LogItem.ConvertIRecordsReader(SqlHelper.ExecuteReader(
|
||
"select userId, NodeId, DateStamp, logHeader, logComment from umbracoLog where UserId = @user and DateStamp >= @dateStamp order by dateStamp desc",
|
||
SqlHelper.CreateParameter("@user", user.Id),
|
||
SqlHelper.CreateParameter("@dateStamp", sinceDate)));
|
||
}
|
||
|
||
public List<LogItem> GetLogItems(User user, LogTypes type, DateTime sinceDate)
|
||
{
|
||
if (ExternalLogger != null)
|
||
return ExternalLogger.GetLogItems(user, type, sinceDate);
|
||
else
|
||
return LogItem.ConvertIRecordsReader(SqlHelper.ExecuteReader(
|
||
"select userId, NodeId, DateStamp, logHeader, logComment from umbracoLog where UserId = @user and logHeader = @logHeader and DateStamp >= @dateStamp order by dateStamp desc",
|
||
SqlHelper.CreateParameter("@logHeader", type),
|
||
SqlHelper.CreateParameter("@user", user.Id),
|
||
SqlHelper.CreateParameter("@dateStamp", sinceDate)));
|
||
}
|
||
|
||
public static void CleanLogs(int maximumAgeOfLogsInMinutes)
|
||
{
|
||
if (Instance.ExternalLogger != null)
|
||
Instance.ExternalLogger.CleanLogs(maximumAgeOfLogsInMinutes);
|
||
else
|
||
{
|
||
try
|
||
{
|
||
DateTime oldestPermittedLogEntry = DateTime.Now.Subtract(new TimeSpan(0, maximumAgeOfLogsInMinutes, 0));
|
||
SqlHelper.ExecuteNonQuery("delete from umbracoLog where datestamp < @oldestPermittedLogEntry and logHeader in ('open','system')",
|
||
SqlHelper.CreateParameter("@oldestPermittedLogEntry", oldestPermittedLogEntry));
|
||
Add(LogTypes.System, -1, "Log scrubbed. Removed all items older than " + oldestPermittedLogEntry);
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Debug.WriteLine(e.ToString(), "Error");
|
||
Trace.WriteLine(e.ToString());
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
#region New GetLog methods - DataLayer layer compatible
|
||
/// <summary>
|
||
/// Gets a reader for the audit log.
|
||
/// </summary>
|
||
/// <param name="NodeId">The node id.</param>
|
||
/// <returns>A reader for the audit log.</returns>
|
||
[Obsolete("Use the Instance.GetAuditLogItems method which return a list of LogItems instead")]
|
||
public static IRecordsReader GetAuditLogReader(int NodeId)
|
||
{
|
||
return SqlHelper.ExecuteReader(
|
||
"select u.userName as [User], logHeader as Action, DateStamp as Date, logComment as Comment from umbracoLog inner join umbracoUser u on u.id = userId where nodeId = @id and logHeader not in ('open','system') order by DateStamp desc",
|
||
SqlHelper.CreateParameter("@id", NodeId));
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets a reader for the log for the specified types.
|
||
/// </summary>
|
||
/// <param name="Type">The type of log message.</param>
|
||
/// <param name="SinceDate">The start date.</param>
|
||
/// <returns>A reader for the log.</returns>
|
||
[Obsolete("Use the Instance.GetLogItems method which return a list of LogItems instead")]
|
||
public static IRecordsReader GetLogReader(LogTypes Type, DateTime SinceDate)
|
||
{
|
||
return SqlHelper.ExecuteReader(
|
||
"select userId, NodeId, DateStamp, logHeader, logComment from umbracoLog where logHeader = @logHeader and DateStamp >= @dateStamp order by dateStamp desc",
|
||
SqlHelper.CreateParameter("@logHeader", Type.ToString()),
|
||
SqlHelper.CreateParameter("@dateStamp", SinceDate));
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets a reader for the log of the specified node.
|
||
/// </summary>
|
||
/// <param name="NodeId">The node id.</param>
|
||
/// <returns>A reader for the log.</returns>
|
||
[Obsolete("Use the Instance.GetLogItems method which return a list of LogItems instead")]
|
||
public static IRecordsReader GetLogReader(int NodeId)
|
||
{
|
||
return SqlHelper.ExecuteReader(
|
||
"select u.userName, DateStamp, logHeader, logComment from umbracoLog inner join umbracoUser u on u.id = userId where nodeId = @id",
|
||
SqlHelper.CreateParameter("@id", NodeId));
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets a reader for the log for the specified user.
|
||
/// </summary>
|
||
/// <param name="user">The user.</param>
|
||
/// <param name="SinceDate">The start date.</param>
|
||
/// <returns>A reader for the log.</returns>
|
||
[Obsolete("Use the Instance.GetLogItems method which return a list of LogItems instead")]
|
||
public static IRecordsReader GetLogReader(User user, DateTime SinceDate)
|
||
{
|
||
return SqlHelper.ExecuteReader(
|
||
"select userId, NodeId, DateStamp, logHeader, logComment from umbracoLog where UserId = @user and DateStamp >= @dateStamp order by dateStamp desc",
|
||
SqlHelper.CreateParameter("@user", user.Id),
|
||
SqlHelper.CreateParameter("@dateStamp", SinceDate));
|
||
}
|
||
|
||
/// <summary>
|
||
/// Gets a reader of specific for the log for specific types and a specified user.
|
||
/// </summary>
|
||
/// <param name="user">The user.</param>
|
||
/// <param name="Type">The type of log message.</param>
|
||
/// <param name="SinceDate">The since date.</param>
|
||
/// <returns>A reader for the log.</returns>
|
||
[Obsolete("Use the Instance.GetLogItems method which return a list of LogItems instead")]
|
||
public static IRecordsReader GetLogReader(User user, LogTypes Type, DateTime SinceDate)
|
||
{
|
||
return SqlHelper.ExecuteReader(
|
||
"select userId, NodeId, DateStamp, logHeader, logComment from umbracoLog where UserId = @user and logHeader = @logHeader and DateStamp >= @dateStamp order by dateStamp desc",
|
||
SqlHelper.CreateParameter("@logHeader", Type.ToString()),
|
||
SqlHelper.CreateParameter("@user", user.Id),
|
||
SqlHelper.CreateParameter("@dateStamp", SinceDate));
|
||
}
|
||
#endregion
|
||
|
||
#endregion
|
||
}
|
||
|
||
/// <summary>
|
||
/// The collection of available log types.
|
||
/// </summary>
|
||
public enum LogTypes
|
||
{
|
||
/// <summary>
|
||
/// Used when new nodes are added
|
||
/// </summary>
|
||
[AuditTrailLogItem]
|
||
New,
|
||
/// <summary>
|
||
/// Used when nodes are saved
|
||
/// </summary>
|
||
[AuditTrailLogItem]
|
||
Save,
|
||
/// <summary>
|
||
/// Used when nodes are opened
|
||
/// </summary>
|
||
[AuditTrailLogItem]
|
||
Open,
|
||
/// <summary>
|
||
/// Used when nodes are deleted
|
||
/// </summary>
|
||
[AuditTrailLogItem]
|
||
Delete,
|
||
/// <summary>
|
||
/// Used when nodes are published
|
||
/// </summary>
|
||
[AuditTrailLogItem]
|
||
Publish,
|
||
/// <summary>
|
||
/// Used when nodes are send to publishing
|
||
/// </summary>
|
||
[AuditTrailLogItem]
|
||
SendToPublish,
|
||
/// <summary>
|
||
/// Used when nodes are unpublished
|
||
/// </summary>
|
||
[AuditTrailLogItem]
|
||
UnPublish,
|
||
/// <summary>
|
||
/// Used when nodes are moved
|
||
/// </summary>
|
||
[AuditTrailLogItem]
|
||
Move,
|
||
/// <summary>
|
||
/// Used when nodes are copied
|
||
/// </summary>
|
||
[AuditTrailLogItem]
|
||
Copy,
|
||
/// <summary>
|
||
/// Used when nodes are ass<73>gned a domain
|
||
/// </summary>
|
||
[AuditTrailLogItem]
|
||
AssignDomain,
|
||
/// <summary>
|
||
/// Used when public access are changed for a node
|
||
/// </summary>
|
||
[AuditTrailLogItem]
|
||
PublicAccess,
|
||
/// <summary>
|
||
/// Used when nodes are sorted
|
||
/// </summary>
|
||
[AuditTrailLogItem]
|
||
Sort,
|
||
/// <summary>
|
||
/// Used when a notification are send to a user
|
||
/// </summary>
|
||
[AuditTrailLogItem]
|
||
Notify,
|
||
/// <summary>
|
||
/// Used when a user logs into the umbraco back-end
|
||
/// </summary>
|
||
Login,
|
||
/// <summary>
|
||
/// Used when a user logs out of the umbraco back-end
|
||
/// </summary>
|
||
Logout,
|
||
/// <summary>
|
||
/// Used when a user login fails
|
||
/// </summary>
|
||
LoginFailure,
|
||
/// <summary>
|
||
/// General system notification
|
||
/// </summary>
|
||
[AuditTrailLogItem]
|
||
System,
|
||
/// <summary>
|
||
/// System debugging notification
|
||
/// </summary>
|
||
Debug,
|
||
/// <summary>
|
||
/// System error notification
|
||
/// </summary>
|
||
Error,
|
||
/// <summary>
|
||
/// Notfound error notification
|
||
/// </summary>
|
||
NotFound,
|
||
/// <summary>
|
||
/// Used when a node's content is rolled back to a previous version
|
||
/// </summary>
|
||
[AuditTrailLogItem]
|
||
RollBack,
|
||
/// <summary>
|
||
/// Used when a package is installed
|
||
/// </summary>
|
||
[AuditTrailLogItem]
|
||
PackagerInstall,
|
||
/// <summary>
|
||
/// Used when a package is uninstalled
|
||
/// </summary>
|
||
[AuditTrailLogItem]
|
||
PackagerUninstall,
|
||
/// <summary>
|
||
/// Used when a ping is send to/from the system
|
||
/// </summary>
|
||
Ping,
|
||
/// <summary>
|
||
/// Used when a node is send to translation
|
||
/// </summary>
|
||
[AuditTrailLogItem]
|
||
SendToTranslate,
|
||
/// <summary>
|
||
/// Notification from a Scheduled task.
|
||
/// </summary>
|
||
ScheduledTask,
|
||
/// <summary>
|
||
/// Use this log action for custom log messages that should be shown in the audit trail
|
||
/// </summary>
|
||
[AuditTrailLogItem]
|
||
Custom
|
||
}
|
||
|
||
public class LogItem
|
||
{
|
||
public int UserId { get; set; }
|
||
public int NodeId { get; set; }
|
||
public DateTime Timestamp { get; set; }
|
||
public LogTypes LogType { get; set; }
|
||
public string Comment { get; set; }
|
||
|
||
public LogItem()
|
||
{
|
||
|
||
}
|
||
|
||
public LogItem(int userId, int nodeId, DateTime timestamp, LogTypes logType, string comment)
|
||
{
|
||
UserId = userId;
|
||
NodeId = nodeId;
|
||
Timestamp = timestamp;
|
||
LogType = logType;
|
||
Comment = comment;
|
||
}
|
||
|
||
public static List<LogItem> ConvertIRecordsReader(IRecordsReader reader)
|
||
{
|
||
List<LogItem> items = new List<LogItem>();
|
||
while (reader.Read())
|
||
{
|
||
items.Add(new LogItem(
|
||
reader.GetInt("userId"),
|
||
reader.GetInt("nodeId"),
|
||
reader.GetDateTime("DateStamp"),
|
||
convertLogHeader(reader.GetString("logHeader")),
|
||
reader.GetString("logComment")));
|
||
}
|
||
|
||
return items;
|
||
|
||
}
|
||
|
||
private static LogTypes convertLogHeader(string logHeader)
|
||
{
|
||
try
|
||
{
|
||
return (LogTypes)Enum.Parse(typeof(LogTypes), logHeader, true);
|
||
}
|
||
catch
|
||
{
|
||
return LogTypes.Custom;
|
||
}
|
||
}
|
||
}
|
||
|
||
public class AuditTrailLogItem : Attribute
|
||
{
|
||
public AuditTrailLogItem()
|
||
{
|
||
|
||
}
|
||
}
|
||
|
||
|
||
} |