add activity log feature

This commit is contained in:
Luke Pulverenti
2014-08-10 18:13:17 -04:00
parent 0f508dab47
commit e84ba17b9f
59 changed files with 1539 additions and 303 deletions

View File

@@ -0,0 +1,40 @@
using MediaBrowser.Common.Events;
using MediaBrowser.Controller.Activity;
using MediaBrowser.Model.Activity;
using MediaBrowser.Model.Events;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Querying;
using System;
using System.Threading.Tasks;
namespace MediaBrowser.Server.Implementations.Activity
{
public class ActivityManager : IActivityManager
{
public event EventHandler<GenericEventArgs<ActivityLogEntry>> EntryCreated;
private readonly IActivityRepository _repo;
private readonly ILogger _logger;
public ActivityManager(ILogger logger, IActivityRepository repo)
{
_logger = logger;
_repo = repo;
}
public async Task Create(ActivityLogEntry entry)
{
entry.Id = Guid.NewGuid().ToString("N");
entry.Date = DateTime.UtcNow;
await _repo.Create(entry).ConfigureAwait(false);
EventHelper.FireEventIfNotNull(EntryCreated, this, new GenericEventArgs<ActivityLogEntry>(entry), _logger);
}
public QueryResult<ActivityLogEntry> GetActivityLogEntries(int? startIndex, int? limit)
{
return _repo.GetActivityLogEntries(startIndex, limit);
}
}
}

View File

@@ -0,0 +1,293 @@
using MediaBrowser.Controller;
using MediaBrowser.Controller.Activity;
using MediaBrowser.Model.Activity;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Querying;
using MediaBrowser.Server.Implementations.Persistence;
using System;
using System.Collections.Generic;
using System.Data;
using System.Globalization;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace MediaBrowser.Server.Implementations.Activity
{
public class ActivityRepository : IActivityRepository, IDisposable
{
private IDbConnection _connection;
private readonly ILogger _logger;
private readonly SemaphoreSlim _writeLock = new SemaphoreSlim(1, 1);
private readonly IServerApplicationPaths _appPaths;
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
private IDbCommand _saveActivityCommand;
public ActivityRepository(ILogger logger, IServerApplicationPaths appPaths)
{
_logger = logger;
_appPaths = appPaths;
}
public async Task Initialize()
{
var dbFile = Path.Combine(_appPaths.DataPath, "activitylog.db");
_connection = await SqliteExtensions.ConnectToDb(dbFile, _logger).ConfigureAwait(false);
string[] queries = {
"create table if not exists ActivityLogEntries (Id GUID PRIMARY KEY, Name TEXT, Overview TEXT, ShortOverview TEXT, Type TEXT, ItemId TEXT, UserId TEXT, DateCreated DATETIME, LogSeverity TEXT)",
"create index if not exists idx_ActivityLogEntries on ActivityLogEntries(Id)",
//pragmas
"pragma temp_store = memory",
"pragma shrink_memory"
};
_connection.RunQueries(queries, _logger);
PrepareStatements();
}
private void PrepareStatements()
{
_saveActivityCommand = _connection.CreateCommand();
_saveActivityCommand.CommandText = "replace into ActivityLogEntries (Id, Name, Overview, ShortOverview, Type, ItemId, UserId, DateCreated, LogSeverity) values (@Id, @Name, @Overview, @ShortOverview, @Type, @ItemId, @UserId, @DateCreated, @LogSeverity)";
_saveActivityCommand.Parameters.Add(_saveActivityCommand, "@Id");
_saveActivityCommand.Parameters.Add(_saveActivityCommand, "@Name");
_saveActivityCommand.Parameters.Add(_saveActivityCommand, "@Overview");
_saveActivityCommand.Parameters.Add(_saveActivityCommand, "@ShortOverview");
_saveActivityCommand.Parameters.Add(_saveActivityCommand, "@Type");
_saveActivityCommand.Parameters.Add(_saveActivityCommand, "@ItemId");
_saveActivityCommand.Parameters.Add(_saveActivityCommand, "@UserId");
_saveActivityCommand.Parameters.Add(_saveActivityCommand, "@DateCreated");
_saveActivityCommand.Parameters.Add(_saveActivityCommand, "@LogSeverity");
}
private const string BaseActivitySelectText = "select Id, Name, Overview, ShortOverview, Type, ItemId, UserId, DateCreated, LogSeverity from ActivityLogEntries";
public Task Create(ActivityLogEntry entry)
{
return Update(entry);
}
public async Task Update(ActivityLogEntry entry)
{
if (entry == null)
{
throw new ArgumentNullException("entry");
}
await _writeLock.WaitAsync().ConfigureAwait(false);
IDbTransaction transaction = null;
try
{
transaction = _connection.BeginTransaction();
var index = 0;
_saveActivityCommand.GetParameter(index++).Value = new Guid(entry.Id);
_saveActivityCommand.GetParameter(index++).Value = entry.Name;
_saveActivityCommand.GetParameter(index++).Value = entry.Overview;
_saveActivityCommand.GetParameter(index++).Value = entry.ShortOverview;
_saveActivityCommand.GetParameter(index++).Value = entry.Type;
_saveActivityCommand.GetParameter(index++).Value = entry.ItemId;
_saveActivityCommand.GetParameter(index++).Value = entry.UserId;
_saveActivityCommand.GetParameter(index++).Value = entry.Date;
_saveActivityCommand.GetParameter(index++).Value = entry.Severity.ToString();
_saveActivityCommand.Transaction = transaction;
_saveActivityCommand.ExecuteNonQuery();
transaction.Commit();
}
catch (OperationCanceledException)
{
if (transaction != null)
{
transaction.Rollback();
}
throw;
}
catch (Exception e)
{
_logger.ErrorException("Failed to save record:", e);
if (transaction != null)
{
transaction.Rollback();
}
throw;
}
finally
{
if (transaction != null)
{
transaction.Dispose();
}
_writeLock.Release();
}
}
public QueryResult<ActivityLogEntry> GetActivityLogEntries(int? startIndex, int? limit)
{
using (var cmd = _connection.CreateCommand())
{
cmd.CommandText = BaseActivitySelectText;
var whereClauses = new List<string>();
if (startIndex.HasValue && startIndex.Value > 0)
{
whereClauses.Add(string.Format("Id NOT IN (SELECT Id FROM ActivityLogEntries ORDER BY DateCreated DESC LIMIT {0})",
startIndex.Value.ToString(_usCulture)));
}
if (whereClauses.Count > 0)
{
cmd.CommandText += " where " + string.Join(" AND ", whereClauses.ToArray());
}
cmd.CommandText += " ORDER BY DateCreated DESC";
if (limit.HasValue)
{
cmd.CommandText += " LIMIT " + limit.Value.ToString(_usCulture);
}
cmd.CommandText += "; select count (Id) from ActivityLogEntries";
var list = new List<ActivityLogEntry>();
var count = 0;
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess))
{
while (reader.Read())
{
list.Add(GetEntry(reader));
}
if (reader.NextResult() && reader.Read())
{
count = reader.GetInt32(0);
}
}
return new QueryResult<ActivityLogEntry>()
{
Items = list.ToArray(),
TotalRecordCount = count
};
}
}
private ActivityLogEntry GetEntry(IDataReader reader)
{
var index = 0;
var info = new ActivityLogEntry
{
Id = reader.GetGuid(index).ToString("N")
};
index++;
if (!reader.IsDBNull(index))
{
info.Name = reader.GetString(index);
}
index++;
if (!reader.IsDBNull(index))
{
info.Overview = reader.GetString(index);
}
index++;
if (!reader.IsDBNull(index))
{
info.ShortOverview = reader.GetString(index);
}
index++;
if (!reader.IsDBNull(index))
{
info.Type = reader.GetString(index);
}
index++;
if (!reader.IsDBNull(index))
{
info.ItemId = reader.GetString(index);
}
index++;
if (!reader.IsDBNull(index))
{
info.UserId = reader.GetString(index);
}
index++;
info.Date = reader.GetDateTime(index).ToUniversalTime();
index++;
if (!reader.IsDBNull(index))
{
info.Severity = (LogSeverity)Enum.Parse(typeof(LogSeverity), reader.GetString(index), true);
}
return info;
}
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private readonly object _disposeLock = new object();
/// <summary>
/// Releases unmanaged and - optionally - managed resources.
/// </summary>
/// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
protected virtual void Dispose(bool dispose)
{
if (dispose)
{
try
{
lock (_disposeLock)
{
if (_connection != null)
{
if (_connection.IsOpen())
{
_connection.Close();
}
_connection.Dispose();
_connection = null;
}
}
}
catch (Exception ex)
{
_logger.ErrorException("Error disposing database", ex);
}
}
}
}
}

View File

@@ -0,0 +1,543 @@
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Implementations.Logging;
using MediaBrowser.Common.Plugins;
using MediaBrowser.Common.ScheduledTasks;
using MediaBrowser.Common.Updates;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Activity;
using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.Localization;
using MediaBrowser.Controller.Plugins;
using MediaBrowser.Controller.Session;
using MediaBrowser.Controller.Subtitles;
using MediaBrowser.Model.Activity;
using MediaBrowser.Model.Events;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Tasks;
using MediaBrowser.Model.Updates;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MediaBrowser.Server.Implementations.EntryPoints
{
public class ActivityLogEntryPoint : IServerEntryPoint
{
private readonly IInstallationManager _installationManager;
//private readonly ILogManager _logManager;
private readonly ILogger _logger;
private readonly ISessionManager _sessionManager;
private readonly ITaskManager _taskManager;
private readonly IActivityManager _activityManager;
private readonly ILocalizationManager _localization;
private readonly ILibraryManager _libraryManager;
private readonly ISubtitleManager _subManager;
private readonly IUserManager _userManager;
private readonly IServerConfigurationManager _config;
private readonly IServerApplicationHost _appHost;
public ActivityLogEntryPoint(ISessionManager sessionManager, ITaskManager taskManager, IActivityManager activityManager, ILocalizationManager localization, IInstallationManager installationManager, ILibraryManager libraryManager, ISubtitleManager subManager, IUserManager userManager, IServerConfigurationManager config, IServerApplicationHost appHost)
{
//_logger = _logManager.GetLogger("ActivityLogEntryPoint");
_sessionManager = sessionManager;
_taskManager = taskManager;
_activityManager = activityManager;
_localization = localization;
_installationManager = installationManager;
_libraryManager = libraryManager;
_subManager = subManager;
_userManager = userManager;
_config = config;
//_logManager = logManager;
_appHost = appHost;
}
public void Run()
{
_taskManager.TaskExecuting += _taskManager_TaskExecuting;
_taskManager.TaskCompleted += _taskManager_TaskCompleted;
_installationManager.PluginInstalled += _installationManager_PluginInstalled;
_installationManager.PluginUninstalled += _installationManager_PluginUninstalled;
_installationManager.PluginUpdated += _installationManager_PluginUpdated;
_libraryManager.ItemAdded += _libraryManager_ItemAdded;
_libraryManager.ItemRemoved += _libraryManager_ItemRemoved;
_sessionManager.SessionStarted += _sessionManager_SessionStarted;
_sessionManager.AuthenticationFailed += _sessionManager_AuthenticationFailed;
_sessionManager.AuthenticationSucceeded += _sessionManager_AuthenticationSucceeded;
_sessionManager.SessionEnded += _sessionManager_SessionEnded;
_sessionManager.PlaybackStart += _sessionManager_PlaybackStart;
_sessionManager.PlaybackStopped += _sessionManager_PlaybackStopped;
_subManager.SubtitlesDownloaded += _subManager_SubtitlesDownloaded;
_subManager.SubtitleDownloadFailure += _subManager_SubtitleDownloadFailure;
_userManager.UserCreated += _userManager_UserCreated;
_userManager.UserPasswordChanged += _userManager_UserPasswordChanged;
_userManager.UserDeleted += _userManager_UserDeleted;
_userManager.UserConfigurationUpdated += _userManager_UserConfigurationUpdated;
_config.ConfigurationUpdated += _config_ConfigurationUpdated;
_config.NamedConfigurationUpdated += _config_NamedConfigurationUpdated;
//_logManager.LoggerLoaded += _logManager_LoggerLoaded;
_appHost.ApplicationUpdated += _appHost_ApplicationUpdated;
}
void _subManager_SubtitleDownloadFailure(object sender, SubtitleDownloadFailureEventArgs e)
{
CreateLogEntry(new ActivityLogEntry
{
Name = string.Format(_localization.GetLocalizedString("SubtitleDownloadFailureForItem"), Notifications.Notifications.GetItemName(e.Item)),
Type = "SubtitleDownloadFailure",
ItemId = e.Item.Id.ToString("N"),
ShortOverview = string.Format(_localization.GetLocalizedString("ProviderValue"), e.Provider),
Overview = LogHelper.GetLogMessage(e.Exception).ToString()
});
}
void _sessionManager_PlaybackStopped(object sender, PlaybackStopEventArgs e)
{
var item = e.MediaInfo;
if (item == null)
{
//_logger.Warn("PlaybackStopped reported with null media info.");
return;
}
if (e.Users.Count == 0)
{
return;
}
var username = e.Users.First().Name;
CreateLogEntry(new ActivityLogEntry
{
Name = string.Format(_localization.GetLocalizedString("UserStoppedPlayingItemWithValues"), username, item.Name),
Type = "PlaybackStopped",
ShortOverview = string.Format(_localization.GetLocalizedString("AppDeviceValues"), e.ClientName, e.DeviceName)
});
}
void _sessionManager_PlaybackStart(object sender, PlaybackProgressEventArgs e)
{
var item = e.MediaInfo;
if (item == null)
{
//_logger.Warn("PlaybackStart reported with null media info.");
return;
}
if (e.Users.Count == 0)
{
return;
}
var username = e.Users.First().Name;
CreateLogEntry(new ActivityLogEntry
{
Name = string.Format(_localization.GetLocalizedString("UserStartedPlayingItemWithValues"), username, item.Name),
Type = "PlaybackStart",
ShortOverview = string.Format(_localization.GetLocalizedString("AppDeviceValues"), e.ClientName, e.DeviceName)
});
}
void _sessionManager_SessionEnded(object sender, SessionEventArgs e)
{
string name;
var session = e.SessionInfo;
if (string.IsNullOrWhiteSpace(session.UserName))
{
name = string.Format(_localization.GetLocalizedString("DeviceOfflineWithName"), session.DeviceName);
}
else
{
name = string.Format(_localization.GetLocalizedString("UserOfflineFromDevice"), session.UserName, session.DeviceName);
}
CreateLogEntry(new ActivityLogEntry
{
Name = name,
Type = "SessionEnded",
ShortOverview = string.Format(_localization.GetLocalizedString("LabelIpAddressValue"), session.RemoteEndPoint)
});
}
void _sessionManager_AuthenticationSucceeded(object sender, GenericEventArgs<AuthenticationRequest> e)
{
CreateLogEntry(new ActivityLogEntry
{
Name = string.Format(_localization.GetLocalizedString("AuthenticationSucceededWithUserName"), e.Argument.Username),
Type = "AuthenticationSucceeded"
});
}
void _sessionManager_AuthenticationFailed(object sender, GenericEventArgs<AuthenticationRequest> e)
{
CreateLogEntry(new ActivityLogEntry
{
Name = string.Format(_localization.GetLocalizedString("FailedLoginAttemptWithUserName"), e.Argument.Username),
Type = "AuthenticationFailed"
});
}
void _appHost_ApplicationUpdated(object sender, GenericEventArgs<PackageVersionInfo> e)
{
CreateLogEntry(new ActivityLogEntry
{
Name = _localization.GetLocalizedString("MessageApplicationUpdated"),
Type = "ApplicationUpdated",
ShortOverview = string.Format(_localization.GetLocalizedString("VersionNumber"), e.Argument.versionStr),
Overview = e.Argument.description
});
}
void _logManager_LoggerLoaded(object sender, EventArgs e)
{
}
void _config_NamedConfigurationUpdated(object sender, ConfigurationUpdateEventArgs e)
{
CreateLogEntry(new ActivityLogEntry
{
Name = string.Format(_localization.GetLocalizedString("MessageNamedServerConfigurationUpdatedWithValue"), e.Key),
Type = "NamedConfigurationUpdated"
});
}
void _config_ConfigurationUpdated(object sender, EventArgs e)
{
CreateLogEntry(new ActivityLogEntry
{
Name = _localization.GetLocalizedString("MessageServerConfigurationUpdated"),
Type = "ServerConfigurationUpdated"
});
}
void _userManager_UserConfigurationUpdated(object sender, GenericEventArgs<User> e)
{
CreateLogEntry(new ActivityLogEntry
{
Name = string.Format(_localization.GetLocalizedString("UserConfigurationUpdatedWithName"), e.Argument.Name),
Type = "UserConfigurationUpdated"
});
}
void _userManager_UserDeleted(object sender, GenericEventArgs<User> e)
{
CreateLogEntry(new ActivityLogEntry
{
Name = string.Format(_localization.GetLocalizedString("UserDeletedWithName"), e.Argument.Name),
Type = "UserDeleted"
});
}
void _userManager_UserPasswordChanged(object sender, GenericEventArgs<User> e)
{
CreateLogEntry(new ActivityLogEntry
{
Name = string.Format(_localization.GetLocalizedString("UserPasswordChangedWithName"), e.Argument.Name),
Type = "UserPasswordChanged"
});
}
void _userManager_UserCreated(object sender, GenericEventArgs<User> e)
{
CreateLogEntry(new ActivityLogEntry
{
Name = string.Format(_localization.GetLocalizedString("UserCreatedWithName"), e.Argument.Name),
Type = "UserCreated"
});
}
void _subManager_SubtitlesDownloaded(object sender, SubtitleDownloadEventArgs e)
{
CreateLogEntry(new ActivityLogEntry
{
Name = string.Format(_localization.GetLocalizedString("SubtitlesDownloadedForItem"), Notifications.Notifications.GetItemName(e.Item)),
Type = "SubtitlesDownloaded",
ItemId = e.Item.Id.ToString("N"),
ShortOverview = string.Format(_localization.GetLocalizedString("ProviderValue"), e.Provider)
});
}
void _sessionManager_SessionStarted(object sender, SessionEventArgs e)
{
string name;
var session = e.SessionInfo;
if (string.IsNullOrWhiteSpace(session.UserName))
{
name = string.Format(_localization.GetLocalizedString("DeviceOnlineWithName"), session.DeviceName);
}
else
{
name = string.Format(_localization.GetLocalizedString("UserOnlineFromDevice"), session.UserName, session.DeviceName);
}
CreateLogEntry(new ActivityLogEntry
{
Name = name,
Type = "SessionStarted",
ShortOverview = string.Format(_localization.GetLocalizedString("LabelIpAddressValue"), session.RemoteEndPoint)
});
}
void _libraryManager_ItemRemoved(object sender, ItemChangeEventArgs e)
{
if (e.Item is LiveTvProgram || e.Item is IChannelItem)
{
return;
}
CreateLogEntry(new ActivityLogEntry
{
Name = string.Format(_localization.GetLocalizedString("ItemRemovedWithName"), Notifications.Notifications.GetItemName(e.Item)),
Type = "ItemRemoved"
});
}
void _libraryManager_ItemAdded(object sender, ItemChangeEventArgs e)
{
if (e.Item is LiveTvProgram || e.Item is IChannelItem)
{
return;
}
CreateLogEntry(new ActivityLogEntry
{
Name = string.Format(_localization.GetLocalizedString("ItemAddedWithName"), Notifications.Notifications.GetItemName(e.Item)),
Type = "ItemAdded",
ItemId = e.Item.Id.ToString("N")
});
}
void _installationManager_PluginUpdated(object sender, GenericEventArgs<Tuple<IPlugin, PackageVersionInfo>> e)
{
CreateLogEntry(new ActivityLogEntry
{
Name = string.Format(_localization.GetLocalizedString("PluginUpdatedWithName"), e.Argument.Item1.Name),
Type = "PluginUpdated",
ShortOverview = string.Format(_localization.GetLocalizedString("VersionNumber"), e.Argument.Item2.versionStr),
Overview = e.Argument.Item2.description
});
}
void _installationManager_PluginUninstalled(object sender, GenericEventArgs<IPlugin> e)
{
CreateLogEntry(new ActivityLogEntry
{
Name = string.Format(_localization.GetLocalizedString("PluginUninstalledWithName"), e.Argument.Name),
Type = "PluginUninstalled"
});
}
void _installationManager_PluginInstalled(object sender, GenericEventArgs<PackageVersionInfo> e)
{
CreateLogEntry(new ActivityLogEntry
{
Name = string.Format(_localization.GetLocalizedString("PluginInstalledWithName"), e.Argument.name),
Type = "PluginInstalled",
ShortOverview = string.Format(_localization.GetLocalizedString("VersionNumber"), e.Argument.versionStr)
});
}
void _taskManager_TaskExecuting(object sender, GenericEventArgs<IScheduledTaskWorker> e)
{
var task = e.Argument;
var activityTask = task.ScheduledTask as IScheduledTaskActivityLog;
if (activityTask != null && !activityTask.IsActivityLogged)
{
return;
}
CreateLogEntry(new ActivityLogEntry
{
Name = string.Format(_localization.GetLocalizedString("ScheduledTaskStartedWithName"), task.Name),
Type = "ScheduledTaskStarted"
});
}
void _taskManager_TaskCompleted(object sender, TaskCompletionEventArgs e)
{
var result = e.Result;
var task = e.Task;
var activityTask = task.ScheduledTask as IScheduledTaskActivityLog;
if (activityTask != null && !activityTask.IsActivityLogged)
{
return;
}
var time = result.EndTimeUtc - result.StartTimeUtc;
var runningTime = string.Format(_localization.GetLocalizedString("LabelRunningTimeValue"), ToUserFriendlyString(time));
if (result.Status == TaskCompletionStatus.Cancelled)
{
CreateLogEntry(new ActivityLogEntry
{
Name = string.Format(_localization.GetLocalizedString("ScheduledTaskCancelledWithName"), task.Name),
Type = "ScheduledTaskCancelled",
ShortOverview = runningTime
});
}
else if (result.Status == TaskCompletionStatus.Completed)
{
CreateLogEntry(new ActivityLogEntry
{
Name = string.Format(_localization.GetLocalizedString("ScheduledTaskCompletedWithName"), task.Name),
Type = "ScheduledTaskCompleted",
ShortOverview = runningTime
});
}
else if (result.Status == TaskCompletionStatus.Failed)
{
var vals = new List<string>();
if (!string.IsNullOrWhiteSpace(e.Result.ErrorMessage))
{
vals.Add(e.Result.ErrorMessage);
}
if (!string.IsNullOrWhiteSpace(e.Result.LongErrorMessage))
{
vals.Add(e.Result.LongErrorMessage);
}
CreateLogEntry(new ActivityLogEntry
{
Name = string.Format(_localization.GetLocalizedString("ScheduledTaskFailedWithName"), task.Name),
Type = "ScheduledTaskFailed",
Overview = string.Join(Environment.NewLine, vals.ToArray()),
ShortOverview = runningTime
});
}
}
private async void CreateLogEntry(ActivityLogEntry entry)
{
try
{
await _activityManager.Create(entry).ConfigureAwait(false);
}
catch
{
// Logged at lower levels
}
}
public void Dispose()
{
_taskManager.TaskExecuting -= _taskManager_TaskExecuting;
_taskManager.TaskCompleted -= _taskManager_TaskCompleted;
_installationManager.PluginInstalled -= _installationManager_PluginInstalled;
_installationManager.PluginUninstalled -= _installationManager_PluginUninstalled;
_installationManager.PluginUpdated -= _installationManager_PluginUpdated;
_libraryManager.ItemAdded -= _libraryManager_ItemAdded;
_libraryManager.ItemRemoved -= _libraryManager_ItemRemoved;
_sessionManager.SessionStarted -= _sessionManager_SessionStarted;
_sessionManager.AuthenticationFailed -= _sessionManager_AuthenticationFailed;
_sessionManager.AuthenticationSucceeded -= _sessionManager_AuthenticationSucceeded;
_sessionManager.SessionEnded -= _sessionManager_SessionEnded;
_sessionManager.PlaybackStart -= _sessionManager_PlaybackStart;
_sessionManager.PlaybackStopped -= _sessionManager_PlaybackStopped;
_subManager.SubtitlesDownloaded -= _subManager_SubtitlesDownloaded;
_subManager.SubtitleDownloadFailure -= _subManager_SubtitleDownloadFailure;
_userManager.UserCreated -= _userManager_UserCreated;
_userManager.UserPasswordChanged -= _userManager_UserPasswordChanged;
_userManager.UserDeleted -= _userManager_UserDeleted;
_userManager.UserConfigurationUpdated -= _userManager_UserConfigurationUpdated;
_config.ConfigurationUpdated -= _config_ConfigurationUpdated;
_config.NamedConfigurationUpdated -= _config_NamedConfigurationUpdated;
//_logManager.LoggerLoaded -= _logManager_LoggerLoaded;
_appHost.ApplicationUpdated -= _appHost_ApplicationUpdated;
}
/// <summary>
/// Constructs a user-friendly string for this TimeSpan instance.
/// </summary>
public static string ToUserFriendlyString(TimeSpan span)
{
const int DaysInYear = 365;
const int DaysInMonth = 30;
// Get each non-zero value from TimeSpan component
List<string> values = new List<string>();
// Number of years
int days = span.Days;
if (days >= DaysInYear)
{
int years = (days / DaysInYear);
values.Add(CreateValueString(years, "year"));
days = (days % DaysInYear);
}
// Number of months
if (days >= DaysInMonth)
{
int months = (days / DaysInMonth);
values.Add(CreateValueString(months, "month"));
days = (days % DaysInMonth);
}
// Number of days
if (days >= 1)
values.Add(CreateValueString(days, "day"));
// Number of hours
if (span.Hours >= 1)
values.Add(CreateValueString(span.Hours, "hour"));
// Number of minutes
if (span.Minutes >= 1)
values.Add(CreateValueString(span.Minutes, "minute"));
// Number of seconds (include when 0 if no other components included)
if (span.Seconds >= 1 || values.Count == 0)
values.Add(CreateValueString(span.Seconds, "second"));
// Combine values into string
StringBuilder builder = new StringBuilder();
for (int i = 0; i < values.Count; i++)
{
if (builder.Length > 0)
builder.Append((i == (values.Count - 1)) ? " and " : ", ");
builder.Append(values[i]);
}
// Return result
return builder.ToString();
}
/// <summary>
/// Constructs a string description of a time-span value.
/// </summary>
/// <param name="value">The value of this item</param>
/// <param name="description">The name of this item (singular form)</param>
private static string CreateValueString(int value, string description)
{
return String.Format("{0:#,##0} {1}",
value, (value == 1) ? description : String.Format("{0}s", description));
}
}
}

View File

@@ -2,14 +2,12 @@
using MediaBrowser.Common.ScheduledTasks;
using MediaBrowser.Common.Updates;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Notifications;
using MediaBrowser.Controller.Plugins;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Events;
using MediaBrowser.Model.Logging;
@@ -37,7 +35,6 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications
private readonly ITaskManager _taskManager;
private readonly INotificationManager _notificationManager;
private readonly IServerConfigurationManager _config;
private readonly ILibraryManager _libraryManager;
private readonly ISessionManager _sessionManager;
private readonly IServerApplicationHost _appHost;
@@ -45,14 +42,13 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications
private Timer LibraryUpdateTimer { get; set; }
private readonly object _libraryChangedSyncLock = new object();
public Notifications(IInstallationManager installationManager, IUserManager userManager, ILogger logger, ITaskManager taskManager, INotificationManager notificationManager, IServerConfigurationManager config, ILibraryManager libraryManager, ISessionManager sessionManager, IServerApplicationHost appHost)
public Notifications(IInstallationManager installationManager, IUserManager userManager, ILogger logger, ITaskManager taskManager, INotificationManager notificationManager, ILibraryManager libraryManager, ISessionManager sessionManager, IServerApplicationHost appHost)
{
_installationManager = installationManager;
_userManager = userManager;
_logger = logger;
_taskManager = taskManager;
_notificationManager = notificationManager;
_config = config;
_libraryManager = libraryManager;
_sessionManager = sessionManager;
_appHost = appHost;
@@ -317,7 +313,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications
}
}
private string GetItemName(BaseItem item)
public static string GetItemName(BaseItem item)
{
var name = item.Name;

View File

@@ -23,7 +23,6 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications
public void Run()
{
_notificationsRepo.NotificationAdded += _notificationsRepo_NotificationAdded;
_notificationsRepo.NotificationUpdated += _notificationsRepo_NotificationUpdated;
_notificationsRepo.NotificationsMarkedRead += _notificationsRepo_NotificationsMarkedRead;
}
@@ -40,13 +39,6 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications
_serverManager.SendWebSocketMessage("NotificationsMarkedRead", msg);
}
void _notificationsRepo_NotificationUpdated(object sender, NotificationUpdateEventArgs e)
{
var msg = e.Notification.UserId + "|" + e.Notification.Id;
_serverManager.SendWebSocketMessage("NotificationUpdated", msg);
}
void _notificationsRepo_NotificationAdded(object sender, NotificationUpdateEventArgs e)
{
var msg = e.Notification.UserId + "|" + e.Notification.Id;
@@ -57,7 +49,6 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications
public void Dispose()
{
_notificationsRepo.NotificationAdded -= _notificationsRepo_NotificationAdded;
_notificationsRepo.NotificationUpdated -= _notificationsRepo_NotificationUpdated;
}
}
}

View File

@@ -3,11 +3,13 @@ using MediaBrowser.Common.Plugins;
using MediaBrowser.Common.ScheduledTasks;
using MediaBrowser.Common.Updates;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Activity;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Plugins;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Activity;
using MediaBrowser.Model.Events;
using System;
using System.Threading;
@@ -47,6 +49,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
private readonly IDtoService _dtoService;
private readonly ISessionManager _sessionManager;
private readonly IActivityManager _activityManager;
/// <summary>
/// Initializes a new instance of the <see cref="ServerEventNotifier" /> class.
@@ -58,7 +61,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
/// <param name="taskManager">The task manager.</param>
/// <param name="dtoService">The dto service.</param>
/// <param name="sessionManager">The session manager.</param>
public ServerEventNotifier(IServerManager serverManager, IServerApplicationHost appHost, IUserManager userManager, IInstallationManager installationManager, ITaskManager taskManager, IDtoService dtoService, ISessionManager sessionManager)
public ServerEventNotifier(IServerManager serverManager, IServerApplicationHost appHost, IUserManager userManager, IInstallationManager installationManager, ITaskManager taskManager, IDtoService dtoService, ISessionManager sessionManager, IActivityManager activityManager)
{
_serverManager = serverManager;
_userManager = userManager;
@@ -67,6 +70,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
_taskManager = taskManager;
_dtoService = dtoService;
_sessionManager = sessionManager;
_activityManager = activityManager;
}
public void Run()
@@ -84,6 +88,13 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
_installationManager.PackageInstallationFailed += _installationManager_PackageInstallationFailed;
_taskManager.TaskCompleted += _taskManager_TaskCompleted;
_activityManager.EntryCreated += _activityManager_EntryCreated;
}
void _activityManager_EntryCreated(object sender, GenericEventArgs<ActivityLogEntry> e)
{
_serverManager.SendWebSocketMessage("ActivityLogEntryCreated", e.Argument);
}
void _userManager_UserConfigurationUpdated(object sender, GenericEventArgs<User> e)

View File

@@ -13,7 +13,7 @@ using System.Threading.Tasks;
namespace MediaBrowser.Server.Implementations.FileOrganization
{
public class OrganizerScheduledTask : IScheduledTask, IConfigurableScheduledTask
public class OrganizerScheduledTask : IScheduledTask, IConfigurableScheduledTask, IScheduledTaskActivityLog
{
private readonly ILibraryMonitor _libraryMonitor;
private readonly ILibraryManager _libraryManager;
@@ -77,5 +77,10 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
{
get { return GetTvOptions().IsEnabled; }
}
public bool IsActivityLogged
{
get { return false; }
}
}
}

View File

@@ -110,7 +110,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp
{
try
{
var webSocketContext = ctx.AcceptWebSocket(null, null);
var webSocketContext = ctx.AcceptWebSocket(null);
if (WebSocketHandler != null)
{

View File

@@ -48,6 +48,7 @@ namespace MediaBrowser.Server.Implementations.Library
/// </summary>
/// <value>The user repository.</value>
private IUserRepository UserRepository { get; set; }
public event EventHandler<GenericEventArgs<User>> UserPasswordChanged;
private readonly IXmlSerializer _xmlSerializer;
@@ -390,7 +391,7 @@ namespace MediaBrowser.Server.Implementations.Library
/// <param name="user">The user.</param>
/// <param name="newPassword">The new password.</param>
/// <returns>Task.</returns>
public Task ChangePassword(User user, string newPassword)
public async Task ChangePassword(User user, string newPassword)
{
if (user == null)
{
@@ -399,7 +400,9 @@ namespace MediaBrowser.Server.Implementations.Library
user.Password = string.IsNullOrEmpty(newPassword) ? string.Empty : GetSha1String(newPassword);
return UpdateUser(user);
await UpdateUser(user).ConfigureAwait(false);
EventHelper.FireEventIfNotNull(UserPasswordChanged, this, new GenericEventArgs<User>(user), _logger);
}
/// <summary>

View File

@@ -699,10 +699,10 @@
"HeaderProfileServerSettingsHelp": "These values control how Media Browser will present itself to the device.",
"LabelMaxBitrate": "Max bitrate:",
"LabelMaxBitrateHelp": "Specify a max bitrate in bandwidth constrained environments, or if the device imposes it's own limit.",
"LabelMaxStreamingBitrate": "Max streaming bitrate:",
"LabelMaxStreamingBitrateHelp": "Specify a max bitrate when streaming.",
"LabelMaxStaticBitrate": "Max sync bitrate:",
"LabelMaxStaticBitrateHelp": "Specify a max bitrate when syncing content at high quality.",
"LabelMaxStreamingBitrate": "Max streaming bitrate:",
"LabelMaxStreamingBitrateHelp": "Specify a max bitrate when streaming.",
"LabelMaxStaticBitrate": "Max sync bitrate:",
"LabelMaxStaticBitrateHelp": "Specify a max bitrate when syncing content at high quality.",
"OptionIgnoreTranscodeByteRangeRequests": "Ignore transcode byte range requests",
"OptionIgnoreTranscodeByteRangeRequestsHelp": "If enabled, these requests will be honored but will ignore the byte range header.",
"LabelFriendlyName": "Friendly name",
@@ -808,8 +808,8 @@
"TabNextUp": "Next Up",
"MessageNoMovieSuggestionsAvailable": "No movie suggestions are currently available. Start watching and rating your movies, and then come back to view your recommendations.",
"MessageNoCollectionsAvailable": "Collections allow you to enjoy personalized groupings of Movies, Series, Albums, Books and Games. Click the New button to start creating Collections.",
"MessageNoPlaylistsAvailable": "Playlists allow you to create lists of content to play consecutively at a time. To add items to playlists, right click or tap and hold, then select Add to Playlist.",
"MessageNoPlaylistItemsAvailable": "This playlist is currently empty.",
"MessageNoPlaylistsAvailable": "Playlists allow you to create lists of content to play consecutively at a time. To add items to playlists, right click or tap and hold, then select Add to Playlist.",
"MessageNoPlaylistItemsAvailable": "This playlist is currently empty.",
"HeaderWelcomeToMediaBrowserWebClient": "Welcome to the Media Browser Web Client",
"ButtonDismiss": "Dismiss",
"MessageLearnHowToCustomize": "Learn how to customize this page to your own personal tastes. Click your user icon in the top right corner of the screen to view and update your preferences.",
@@ -918,52 +918,84 @@
"LabelContext": "Context:",
"OptionContextStreaming": "Streaming",
"OptionContextStatic": "Sync",
"ButtonAddToPlaylist": "Add to playlist",
"TabPlaylists": "Playlists",
"ButtonClose": "Close",
"LabelAllLanguages": "All languages",
"HeaderBrowseOnlineImages": "Browse Online Images",
"LabelSource": "Source:",
"OptionAll": "All",
"LabelImage": "Image:",
"ButtonUpload": "Upload",
"ButtonBrowseImages": "Browse Images",
"HeaderImages": "Images",
"HeaderBackdrops": "Backdrops",
"HeaderScreenshots": "Screenshots",
"HeaderAddUpdateImage": "Add/Update Image",
"LabelDropImageHere": "Drop image here",
"LabelJpgPngOnly": "JPG/PNG only",
"LabelImageType": "Image type:",
"OptionPrimary": "Primary",
"OptionArt": "Art",
"OptionBackdrop": "Backdrop",
"OptionBox": "Box",
"OptionBoxRear": "Box rear",
"OptionDisc": "Disc",
"OptionLogo": "Logo",
"OptionMenu": "Menu",
"OptionScreenshot": "Screenshot",
"OptionLocked": "Locked",
"OptionUnidentified": "Unidentified",
"OptionMissingParentalRating": "Missing parental rating",
"OptionStub": "Stub",
"HeaderEpisodes": "Episodes:",
"OptionSeason0": "Season 0",
"LabelReport": "Report:",
"OptionReportSongs": "Songs",
"OptionReportSeries": "Series",
"OptionReportSeasons": "Seasons",
"OptionReportTrailers": "Trailers",
"OptionReportMusicVideos": "Music videos",
"OptionReportMovies": "Movies",
"OptionReportHomeVideos": "Home videos",
"OptionReportGames": "Games",
"OptionReportEpisodes": "Episodes",
"OptionReportCollections": "Collections",
"OptionReportBooks": "Books",
"OptionReportArtists": "Artists",
"OptionReportAlbums": "Albums",
"ButtonAddToPlaylist": "Add to playlist",
"TabPlaylists": "Playlists",
"ButtonClose": "Close",
"LabelAllLanguages": "All languages",
"HeaderBrowseOnlineImages": "Browse Online Images",
"LabelSource": "Source:",
"OptionAll": "All",
"LabelImage": "Image:",
"ButtonUpload": "Upload",
"ButtonBrowseImages": "Browse Images",
"HeaderImages": "Images",
"HeaderBackdrops": "Backdrops",
"HeaderScreenshots": "Screenshots",
"HeaderAddUpdateImage": "Add/Update Image",
"LabelDropImageHere": "Drop image here",
"LabelJpgPngOnly": "JPG/PNG only",
"LabelImageType": "Image type:",
"OptionPrimary": "Primary",
"OptionArt": "Art",
"OptionBackdrop": "Backdrop",
"OptionBox": "Box",
"OptionBoxRear": "Box rear",
"OptionDisc": "Disc",
"OptionLogo": "Logo",
"OptionMenu": "Menu",
"OptionScreenshot": "Screenshot",
"OptionLocked": "Locked",
"OptionUnidentified": "Unidentified",
"OptionMissingParentalRating": "Missing parental rating",
"OptionStub": "Stub",
"HeaderEpisodes": "Episodes:",
"OptionSeason0": "Season 0",
"LabelReport": "Report:",
"OptionReportSongs": "Songs",
"OptionReportSeries": "Series",
"OptionReportSeasons": "Seasons",
"OptionReportTrailers": "Trailers",
"OptionReportMusicVideos": "Music videos",
"OptionReportMovies": "Movies",
"OptionReportHomeVideos": "Home videos",
"OptionReportGames": "Games",
"OptionReportEpisodes": "Episodes",
"OptionReportCollections": "Collections",
"OptionReportBooks": "Books",
"OptionReportArtists": "Artists",
"OptionReportAlbums": "Albums",
"OptionReportAdultVideos": "Adult videos",
"ButtonMore": "More"
"ButtonMore": "More",
"HeaderActivity": "Activity",
"ScheduledTaskStartedWithName": "{0} started",
"ScheduledTaskCancelledWithName": "{0} was cancelled",
"ScheduledTaskCompletedWithName": "{0} completed",
"ScheduledTaskFailed": "Scheduled task completed",
"PluginInstalledWithName": "{0} was installed",
"PluginUpdatedWithName": "{0} was updated",
"PluginUninstalledWithName": "{0} was uninstalled",
"ScheduledTaskFailedWithName": "{0} failed",
"ItemAddedWithName": "{0} was added to the library",
"ItemRemovedWithName": "{0} was removed from the library",
"DeviceOnlineWithName": "{0} is connected",
"UserOnlineFromDevice": "{0} is online from {1}",
"DeviceOfflineWithName": "{0} has disconnected",
"UserOfflineFromDevice": "{0} has disconnected from {1}",
"SubtitlesDownloadedForItem": "Subtitles downloaded for {0}",
"SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
"LabelRunningTimeValue": "Running time: {0}",
"LabelIpAddressValue": "Ip address: {0}",
"UserConfigurationUpdatedWithName": "User configuration has been updated for {0}",
"UserCreatedWithName": "User {0} has been created",
"UserPasswordChangedWithName": "Password has been changed for user {0}",
"UserDeletedWithName": "User {0} has been deleted",
"MessageServerConfigurationUpdated": "Server configuration has been updated",
"MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated",
"MessageApplicationUpdated": "Media Browser Server has been updated",
"AuthenticationSucceededWithUserName": "{0} successfully authenticated",
"FailedLoginAttemptWithUserName": "Failed login attempt from {0}",
"UserStartedPlayingItemWithValues": "{0} has started playing {1}",
"UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}",
"AppDeviceValues": "App: {0}, Device: {1}",
"ProviderValue": "Provider: {0}"
}

View File

@@ -101,6 +101,8 @@
<Compile Include="..\SharedVersion.cs">
<Link>Properties\SharedVersion.cs</Link>
</Compile>
<Compile Include="Activity\ActivityManager.cs" />
<Compile Include="Activity\ActivityRepository.cs" />
<Compile Include="Branding\BrandingConfigurationFactory.cs" />
<Compile Include="Channels\ChannelConfigurations.cs" />
<Compile Include="Channels\ChannelDownloadScheduledTask.cs" />
@@ -117,6 +119,7 @@
<Compile Include="Drawing\PlayedIndicatorDrawer.cs" />
<Compile Include="Drawing\UnplayedCountIndicator.cs" />
<Compile Include="Dto\DtoService.cs" />
<Compile Include="EntryPoints\ActivityLogEntryPoint.cs" />
<Compile Include="EntryPoints\AutomaticRestartEntryPoint.cs" />
<Compile Include="EntryPoints\ExternalPortForwarding.cs" />
<Compile Include="EntryPoints\LibraryChangedNotifier.cs" />
@@ -492,4 +495,4 @@
<Target Name="AfterBuild">
</Target>
-->
</Project>
</Project>

View File

@@ -206,46 +206,6 @@ namespace MediaBrowser.Server.Implementations.Notifications
return notification;
}
/// <summary>
/// Gets the notification.
/// </summary>
/// <param name="id">The id.</param>
/// <param name="userId">The user id.</param>
/// <returns>Notification.</returns>
/// <exception cref="System.ArgumentNullException">
/// id
/// or
/// userId
/// </exception>
public Notification GetNotification(string id, string userId)
{
if (string.IsNullOrEmpty(id))
{
throw new ArgumentNullException("id");
}
if (string.IsNullOrEmpty(userId))
{
throw new ArgumentNullException("userId");
}
using (var cmd = _connection.CreateCommand())
{
cmd.CommandText = "select Id,UserId,Date,Name,Description,Url,Level,IsRead,Category,RelatedId where Id=@Id And UserId = @UserId";
cmd.Parameters.Add(cmd, "@Id", DbType.Guid).Value = new Guid(id);
cmd.Parameters.Add(cmd, "@UserId", DbType.Guid).Value = new Guid(userId);
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow))
{
if (reader.Read())
{
return GetNotification(reader);
}
}
return null;
}
}
/// <summary>
/// Gets the level.
/// </summary>
@@ -289,32 +249,6 @@ namespace MediaBrowser.Server.Implementations.Notifications
}
}
/// <summary>
/// Updates the notification.
/// </summary>
/// <param name="notification">The notification.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
public async Task UpdateNotification(Notification notification, CancellationToken cancellationToken)
{
await ReplaceNotification(notification, cancellationToken).ConfigureAwait(false);
if (NotificationUpdated != null)
{
try
{
NotificationUpdated(this, new NotificationUpdateEventArgs
{
Notification = notification
});
}
catch (Exception ex)
{
_logger.ErrorException("Error in NotificationUpdated event handler", ex);
}
}
}
/// <summary>
/// Replaces the notification.
/// </summary>

View File

@@ -153,6 +153,8 @@ namespace MediaBrowser.Server.Implementations.ServerManager
/// <param name="result">The result.</param>
private async void ProcessWebSocketMessageReceived(WebSocketMessageInfo result)
{
//_logger.Debug("Websocket message received: {0}", result.MessageType);
var tasks = _webSocketListeners.Select(i => Task.Run(async () =>
{
try

View File

@@ -14,11 +14,13 @@ using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Security;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Events;
using MediaBrowser.Model.Library;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Serialization;
using MediaBrowser.Model.Session;
using MediaBrowser.Model.Users;
using MediaBrowser.Server.Implementations.Security;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
@@ -27,7 +29,6 @@ using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Server.Implementations.Security;
namespace MediaBrowser.Server.Implementations.Session
{
@@ -76,6 +77,10 @@ namespace MediaBrowser.Server.Implementations.Session
private readonly ConcurrentDictionary<string, SessionInfo> _activeConnections =
new ConcurrentDictionary<string, SessionInfo>(StringComparer.OrdinalIgnoreCase);
public event EventHandler<GenericEventArgs<AuthenticationRequest>> AuthenticationFailed;
public event EventHandler<GenericEventArgs<AuthenticationRequest>> AuthenticationSucceeded;
/// <summary>
/// Occurs when [playback start].
/// </summary>
@@ -399,6 +404,11 @@ namespace MediaBrowser.Server.Implementations.Session
Id = Guid.NewGuid().ToString("N")
};
sessionInfo.DeviceName = deviceName;
sessionInfo.UserId = userId;
sessionInfo.UserName = username;
sessionInfo.RemoteEndPoint = remoteEndPoint;
OnSessionStarted(sessionInfo);
return sessionInfo;
@@ -1191,44 +1201,37 @@ namespace MediaBrowser.Server.Implementations.Session
/// <summary>
/// Authenticates the new session.
/// </summary>
/// <param name="username">The username.</param>
/// <param name="password">The password.</param>
/// <param name="clientType">Type of the client.</param>
/// <param name="appVersion">The application version.</param>
/// <param name="deviceId">The device identifier.</param>
/// <param name="deviceName">Name of the device.</param>
/// <param name="remoteEndPoint">The remote end point.</param>
/// <param name="request">The request.</param>
/// <param name="isLocal">if set to <c>true</c> [is local].</param>
/// <returns>Task{SessionInfo}.</returns>
/// <exception cref="AuthenticationException">Invalid user or password entered.</exception>
/// <exception cref="System.UnauthorizedAccessException">Invalid user or password entered.</exception>
/// <exception cref="UnauthorizedAccessException">Invalid user or password entered.</exception>
public async Task<AuthenticationResult> AuthenticateNewSession(string username,
string password,
string clientType,
string appVersion,
string deviceId,
string deviceName,
string remoteEndPoint,
public async Task<AuthenticationResult> AuthenticateNewSession(AuthenticationRequest request,
bool isLocal)
{
var result = (isLocal && string.Equals(clientType, "Dashboard", StringComparison.OrdinalIgnoreCase)) ||
await _userManager.AuthenticateUser(username, password).ConfigureAwait(false);
var result = (isLocal && string.Equals(request.App, "Dashboard", StringComparison.OrdinalIgnoreCase)) ||
await _userManager.AuthenticateUser(request.Username, request.Password).ConfigureAwait(false);
if (!result)
{
EventHelper.FireEventIfNotNull(AuthenticationFailed, this, new GenericEventArgs<AuthenticationRequest>(request), _logger);
throw new AuthenticationException("Invalid user or password entered.");
}
var user = _userManager.Users
.First(i => string.Equals(username, i.Name, StringComparison.OrdinalIgnoreCase));
.First(i => string.Equals(request.Username, i.Name, StringComparison.OrdinalIgnoreCase));
var token = await GetAuthorizationToken(user.Id.ToString("N"), deviceId, clientType, deviceName).ConfigureAwait(false);
var token = await GetAuthorizationToken(user.Id.ToString("N"), request.DeviceId, request.App, request.DeviceName).ConfigureAwait(false);
var session = await LogSessionActivity(clientType,
appVersion,
deviceId,
deviceName,
remoteEndPoint,
EventHelper.FireEventIfNotNull(AuthenticationSucceeded, this, new GenericEventArgs<AuthenticationRequest>(request), _logger);
var session = await LogSessionActivity(request.App,
request.AppVersion,
request.DeviceId,
request.DeviceName,
request.RemoteEndPoint,
user)
.ConfigureAwait(false);

View File

@@ -1,5 +1,4 @@
using MediaBrowser.Common.Net;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Serialization;

View File

@@ -15,7 +15,7 @@ using System.Threading.Tasks;
namespace MediaBrowser.Server.Implementations.Sync
{
public class SyncRepository : ISyncRepository
public class SyncRepository : ISyncRepository, IDisposable
{
private IDbConnection _connection;
private readonly ILogger _logger;
@@ -422,8 +422,50 @@ namespace MediaBrowser.Server.Implementations.Sync
}
info.TargetId = reader.GetString(5);
return info;
}
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private readonly object _disposeLock = new object();
/// <summary>
/// Releases unmanaged and - optionally - managed resources.
/// </summary>
/// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
protected virtual void Dispose(bool dispose)
{
if (dispose)
{
try
{
lock (_disposeLock)
{
if (_connection != null)
{
if (_connection.IsOpen())
{
_connection.Close();
}
_connection.Dispose();
_connection = null;
}
}
}
catch (Exception ex)
{
_logger.ErrorException("Error disposing database", ex);
}
}
}
}
}