completed auth database

pull/702/head
Luke Pulverenti 10 years ago
parent 379fa00228
commit c02e917f56

@ -37,7 +37,7 @@ namespace MediaBrowser.Api
private readonly ISessionManager _sessionManager;
public readonly SemaphoreSlim TranscodingStartLock = new SemaphoreSlim(1,1);
public readonly SemaphoreSlim TranscodingStartLock = new SemaphoreSlim(1, 1);
/// <summary>
/// Initializes a new instance of the <see cref="ApiEntryPoint" /> class.
@ -102,7 +102,7 @@ namespace MediaBrowser.Api
{
var jobCount = _activeTranscodingJobs.Count;
Parallel.ForEach(_activeTranscodingJobs.ToList(), j => KillTranscodingJob(j, FileDeleteMode.All));
Parallel.ForEach(_activeTranscodingJobs.ToList(), j => KillTranscodingJob(j, path => true));
// Try to allow for some time to kill the ffmpeg processes and delete the partial stream files
if (jobCount > 0)
@ -295,17 +295,18 @@ namespace MediaBrowser.Api
{
var job = (TranscodingJob)state;
KillTranscodingJob(job, FileDeleteMode.All);
KillTranscodingJob(job, path => true);
}
/// <summary>
/// Kills the single transcoding job.
/// </summary>
/// <param name="deviceId">The device id.</param>
/// <param name="deleteMode">The delete mode.</param>
/// <param name="delete">The delete.</param>
/// <param name="acquireLock">if set to <c>true</c> [acquire lock].</param>
/// <returns>Task.</returns>
/// <exception cref="System.ArgumentNullException">sourcePath</exception>
internal async Task KillTranscodingJobs(string deviceId, FileDeleteMode deleteMode, bool acquireLock)
internal async Task KillTranscodingJobs(string deviceId, Func<string, bool> delete, bool acquireLock)
{
if (string.IsNullOrEmpty(deviceId))
{
@ -330,12 +331,12 @@ namespace MediaBrowser.Api
{
await TranscodingStartLock.WaitAsync(CancellationToken.None).ConfigureAwait(false);
}
try
{
foreach (var job in jobs)
{
KillTranscodingJob(job, deleteMode);
KillTranscodingJob(job, delete);
}
}
finally
@ -352,10 +353,11 @@ namespace MediaBrowser.Api
/// </summary>
/// <param name="deviceId">The device identifier.</param>
/// <param name="type">The type.</param>
/// <param name="deleteMode">The delete mode.</param>
/// <param name="delete">The delete.</param>
/// <param name="acquireLock">if set to <c>true</c> [acquire lock].</param>
/// <returns>Task.</returns>
/// <exception cref="System.ArgumentNullException">deviceId</exception>
internal async Task KillTranscodingJobs(string deviceId, TranscodingJobType type, FileDeleteMode deleteMode, bool acquireLock)
internal async Task KillTranscodingJobs(string deviceId, TranscodingJobType type, Func<string, bool> delete, bool acquireLock)
{
if (string.IsNullOrEmpty(deviceId))
{
@ -385,7 +387,7 @@ namespace MediaBrowser.Api
{
foreach (var job in jobs)
{
KillTranscodingJob(job, deleteMode);
KillTranscodingJob(job, delete);
}
}
finally
@ -401,8 +403,8 @@ namespace MediaBrowser.Api
/// Kills the transcoding job.
/// </summary>
/// <param name="job">The job.</param>
/// <param name="deleteMode">The delete mode.</param>
private void KillTranscodingJob(TranscodingJob job, FileDeleteMode deleteMode)
/// <param name="delete">The delete.</param>
private void KillTranscodingJob(TranscodingJob job, Func<string, bool> delete)
{
lock (_activeTranscodingJobs)
{
@ -454,7 +456,7 @@ namespace MediaBrowser.Api
}
}
if (deleteMode == FileDeleteMode.All)
if (delete(job.Path))
{
DeletePartialStreamFiles(job.Path, job.Type, 0, 1500);
}
@ -593,10 +595,4 @@ namespace MediaBrowser.Api
/// </summary>
Hls
}
public enum FileDeleteMode
{
None,
All
}
}

@ -18,6 +18,7 @@ namespace MediaBrowser.Api
/// Class GetConfiguration
/// </summary>
[Route("/System/Configuration", "GET", Summary = "Gets application configuration")]
[Authenticated]
public class GetConfiguration : IReturn<ServerConfiguration>
{

@ -22,7 +22,8 @@ namespace MediaBrowser.Api.Playback.Hls
/// </summary>
public abstract class BaseHlsService : BaseStreamingService
{
protected BaseHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, IChannelManager channelManager, ISubtitleEncoder subtitleEncoder) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, liveTvManager, dlnaManager, channelManager, subtitleEncoder)
protected BaseHlsService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, ILiveTvManager liveTvManager, IDlnaManager dlnaManager, IChannelManager channelManager, ISubtitleEncoder subtitleEncoder)
: base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, liveTvManager, dlnaManager, channelManager, subtitleEncoder)
{
}
@ -103,8 +104,8 @@ namespace MediaBrowser.Api.Playback.Hls
}
else
{
await ApiEntryPoint.Instance.KillTranscodingJobs(state.Request.DeviceId, TranscodingJobType.Hls, FileDeleteMode.All, false).ConfigureAwait(false);
await ApiEntryPoint.Instance.KillTranscodingJobs(state.Request.DeviceId, TranscodingJobType.Hls, p => true, false).ConfigureAwait(false);
// If the playlist doesn't already exist, startup ffmpeg
try
{
@ -252,7 +253,7 @@ namespace MediaBrowser.Api.Playback.Hls
protected override string GetCommandLineArguments(string outputPath, StreamState state, bool isEncoding)
{
var hlsVideoRequest = state.VideoRequest as GetHlsVideoStream;
var itsOffsetMs = hlsVideoRequest == null
? 0
: hlsVideoRequest.TimeStampOffsetMs;

@ -127,8 +127,7 @@ namespace MediaBrowser.Api.Playback.Hls
// If the playlist doesn't already exist, startup ffmpeg
try
{
// TODO: Delete files from other jobs, but not this one
await ApiEntryPoint.Instance.KillTranscodingJobs(state.Request.DeviceId, TranscodingJobType.Hls, FileDeleteMode.None, false).ConfigureAwait(false);
await ApiEntryPoint.Instance.KillTranscodingJobs(state.Request.DeviceId, TranscodingJobType.Hls, p => !string.Equals(p, playlistPath, StringComparison.OrdinalIgnoreCase), false).ConfigureAwait(false);
if (currentTranscodingIndex.HasValue)
{

@ -74,7 +74,7 @@ namespace MediaBrowser.Api.Playback.Hls
public void Delete(StopEncodingProcess request)
{
var task = ApiEntryPoint.Instance.KillTranscodingJobs(request.DeviceId, FileDeleteMode.All, true);
var task = ApiEntryPoint.Instance.KillTranscodingJobs(request.DeviceId, path => true, true);
Task.WaitAll(task);
}

@ -213,6 +213,7 @@ namespace MediaBrowser.Api
}
[Route("/Sessions/Capabilities", "POST", Summary = "Updates capabilities for a device")]
[Authenticated]
public class PostCapabilities : IReturnVoid
{
/// <summary>
@ -235,6 +236,11 @@ namespace MediaBrowser.Api
public bool SupportsMediaControl { get; set; }
}
[Route("/Sessions/Logout", "POST", Summary = "Reports that a session has ended")]
public class ReportSessionEnded : IReturnVoid
{
}
/// <summary>
/// Class SessionsService
/// </summary>
@ -246,16 +252,26 @@ namespace MediaBrowser.Api
private readonly ISessionManager _sessionManager;
private readonly IUserManager _userManager;
private readonly IAuthorizationContext _authContext;
/// <summary>
/// Initializes a new instance of the <see cref="SessionsService" /> class.
/// </summary>
/// <param name="sessionManager">The session manager.</param>
/// <param name="userManager">The user manager.</param>
public SessionsService(ISessionManager sessionManager, IUserManager userManager)
public SessionsService(ISessionManager sessionManager, IUserManager userManager, IAuthorizationContext authContext)
{
_sessionManager = sessionManager;
_userManager = userManager;
_authContext = authContext;
}
public void Post(ReportSessionEnded request)
{
var auth = _authContext.GetAuthorizationInfo(Request);
_sessionManager.Logout(auth.Token);
}
/// <summary>

@ -15,6 +15,7 @@ namespace MediaBrowser.Api
/// Class GetSystemInfo
/// </summary>
[Route("/System/Info", "GET", Summary = "Gets information about the server")]
[Authenticated]
public class GetSystemInfo : IReturn<SystemInfo>
{

@ -4,7 +4,6 @@ using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Serialization;
using MediaBrowser.Model.Users;
using ServiceStack;
using ServiceStack.Text.Controller;
@ -19,6 +18,7 @@ namespace MediaBrowser.Api
/// Class GetUsers
/// </summary>
[Route("/Users", "GET", Summary = "Gets a list of users")]
[Authenticated]
public class GetUsers : IReturn<List<UserDto>>
{
[ApiMember(Name = "IsHidden", Description = "Optional filter by IsHidden=true or false", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
@ -37,6 +37,7 @@ namespace MediaBrowser.Api
/// Class GetUser
/// </summary>
[Route("/Users/{Id}", "GET", Summary = "Gets a user by Id")]
[Authenticated]
public class GetUser : IReturn<UserDto>
{
/// <summary>
@ -159,11 +160,6 @@ namespace MediaBrowser.Api
/// </summary>
public class UserService : BaseApiService, IHasAuthorization
{
/// <summary>
/// The _XML serializer
/// </summary>
private readonly IXmlSerializer _xmlSerializer;
/// <summary>
/// The _user manager
/// </summary>
@ -176,19 +172,12 @@ namespace MediaBrowser.Api
/// <summary>
/// Initializes a new instance of the <see cref="UserService" /> class.
/// </summary>
/// <param name="xmlSerializer">The XML serializer.</param>
/// <param name="userManager">The user manager.</param>
/// <param name="dtoService">The dto service.</param>
/// <param name="sessionMananger">The session mananger.</param>
/// <exception cref="System.ArgumentNullException">xmlSerializer</exception>
public UserService(IXmlSerializer xmlSerializer, IUserManager userManager, IDtoService dtoService, ISessionManager sessionMananger)
: base()
public UserService(IUserManager userManager, IDtoService dtoService, ISessionManager sessionMananger)
{
if (xmlSerializer == null)
{
throw new ArgumentNullException("xmlSerializer");
}
_xmlSerializer = xmlSerializer;
_userManager = userManager;
_dtoService = dtoService;
_sessionMananger = sessionMananger;
@ -196,6 +185,11 @@ namespace MediaBrowser.Api
public object Get(GetPublicUsers request)
{
if (!Request.IsLocal && !_sessionMananger.IsLocal(Request.RemoteIp))
{
return ToOptimizedResult(new List<UserDto>());
}
return Get(new GetUsers
{
IsHidden = false,
@ -368,9 +362,15 @@ namespace MediaBrowser.Api
{
throw new ArgumentException("There must be at least one enabled user in the system.");
}
var revokeTask = _sessionMananger.RevokeUserTokens(user.Id.ToString("N"));
Task.WaitAll(revokeTask);
}
var task = user.Name.Equals(dtoUser.Name, StringComparison.Ordinal) ? _userManager.UpdateUser(user) : _userManager.RenameUser(user, dtoUser.Name);
var task = user.Name.Equals(dtoUser.Name, StringComparison.Ordinal) ?
_userManager.UpdateUser(user) :
_userManager.RenameUser(user, dtoUser.Name);
Task.WaitAll(task);

@ -10,6 +10,8 @@ namespace MediaBrowser.Controller.Channels
{
public string Name { get; set; }
public string SeriesName { get; set; }
public string Id { get; set; }
public ChannelItemType Type { get; set; }
@ -28,8 +30,6 @@ namespace MediaBrowser.Controller.Channels
public long? RunTimeTicks { get; set; }
public bool IsInfiniteStream { get; set; }
public string ImageUrl { get; set; }
public ChannelMediaType MediaType { get; set; }
@ -43,9 +43,14 @@ namespace MediaBrowser.Controller.Channels
public int? ProductionYear { get; set; }
public DateTime? DateCreated { get; set; }
public int? IndexNumber { get; set; }
public int? ParentIndexNumber { get; set; }
public List<ChannelMediaInfo> MediaSources { get; set; }
public bool IsInfiniteStream { get; set; }
public ChannelItemInfo()
{
MediaSources = new List<ChannelMediaInfo>();

@ -0,0 +1,37 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
using System;
using System.Collections.Generic;
namespace MediaBrowser.Controller.Collections
{
public class CollectionCreatedEventArgs : EventArgs
{
/// <summary>
/// Gets or sets the collection.
/// </summary>
/// <value>The collection.</value>
public BoxSet Collection { get; set; }
/// <summary>
/// Gets or sets the options.
/// </summary>
/// <value>The options.</value>
public CollectionCreationOptions Options { get; set; }
}
public class CollectionModifiedEventArgs : EventArgs
{
/// <summary>
/// Gets or sets the collection.
/// </summary>
/// <value>The collection.</value>
public BoxSet Collection { get; set; }
/// <summary>
/// Gets or sets the items changed.
/// </summary>
/// <value>The items changed.</value>
public List<BaseItem> ItemsChanged { get; set; }
}
}

@ -8,6 +8,21 @@ namespace MediaBrowser.Controller.Collections
{
public interface ICollectionManager
{
/// <summary>
/// Occurs when [collection created].
/// </summary>
event EventHandler<CollectionCreatedEventArgs> CollectionCreated;
/// <summary>
/// Occurs when [items added to collection].
/// </summary>
event EventHandler<CollectionModifiedEventArgs> ItemsAddedToCollection;
/// <summary>
/// Occurs when [items removed from collection].
/// </summary>
event EventHandler<CollectionModifiedEventArgs> ItemsRemovedFromCollection;
/// <summary>
/// Creates the collection.
/// </summary>

@ -50,6 +50,13 @@ namespace MediaBrowser.Controller.Dto
/// <returns>ChapterInfoDto.</returns>
ChapterInfoDto GetChapterInfoDto(ChapterInfo chapterInfo, BaseItem item);
/// <summary>
/// Gets the user item data dto.
/// </summary>
/// <param name="data">The data.</param>
/// <returns>UserItemDataDto.</returns>
UserItemDataDto GetUserItemDataDto(UserItemData data);
/// <summary>
/// Gets the item by name dto.
/// </summary>

@ -95,6 +95,7 @@
<Compile Include="Chapters\IChapterProvider.cs" />
<Compile Include="Chapters\ChapterResponse.cs" />
<Compile Include="Collections\CollectionCreationOptions.cs" />
<Compile Include="Collections\CollectionEvents.cs" />
<Compile Include="Collections\ICollectionManager.cs" />
<Compile Include="Dlna\ControlRequest.cs" />
<Compile Include="Dlna\ControlResponse.cs" />
@ -233,6 +234,9 @@
<Compile Include="Providers\IRemoteMetadataProvider.cs" />
<Compile Include="Providers\VideoContentType.cs" />
<Compile Include="RelatedMedia\IRelatedMediaProvider.cs" />
<Compile Include="Security\AuthenticationInfo.cs" />
<Compile Include="Security\AuthenticationInfoQuery.cs" />
<Compile Include="Security\IAuthenticationRepository.cs" />
<Compile Include="Security\IEncryptionManager.cs" />
<Compile Include="Subtitles\ISubtitleManager.cs" />
<Compile Include="Subtitles\ISubtitleProvider.cs" />

@ -1,4 +1,5 @@
using MediaBrowser.Controller.Entities;
using System.Collections.Generic;
namespace MediaBrowser.Controller.Providers
{

@ -0,0 +1,61 @@
using System;
namespace MediaBrowser.Controller.Security
{
public class AuthenticationInfo
{
/// <summary>
/// Gets or sets the identifier.
/// </summary>
/// <value>The identifier.</value>
public string Id { get; set; }
/// <summary>
/// Gets or sets the access token.
/// </summary>
/// <value>The access token.</value>
public string AccessToken { get; set; }
/// <summary>
/// Gets or sets the device identifier.
/// </summary>
/// <value>The device identifier.</value>
public string DeviceId { get; set; }
/// <summary>
/// Gets or sets the name of the application.
/// </summary>
/// <value>The name of the application.</value>
public string AppName { get; set; }
/// <summary>
/// Gets or sets the name of the device.
/// </summary>
/// <value>The name of the device.</value>
public string DeviceName { get; set; }
/// <summary>
/// Gets or sets the user identifier.
/// </summary>
/// <value>The user identifier.</value>
public string UserId { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this instance is active.
/// </summary>
/// <value><c>true</c> if this instance is active; otherwise, <c>false</c>.</value>
public bool IsActive { get; set; }
/// <summary>
/// Gets or sets the date created.
/// </summary>
/// <value>The date created.</value>
public DateTime DateCreated { get; set; }
/// <summary>
/// Gets or sets the date revoked.
/// </summary>
/// <value>The date revoked.</value>
public DateTime? DateRevoked { get; set; }
}
}

@ -0,0 +1,42 @@

namespace MediaBrowser.Controller.Security
{
public class AuthenticationInfoQuery
{
/// <summary>
/// Gets or sets the device identifier.
/// </summary>
/// <value>The device identifier.</value>
public string DeviceId { get; set; }
/// <summary>
/// Gets or sets the user identifier.
/// </summary>
/// <value>The user identifier.</value>
public string UserId { get; set; }
/// <summary>
/// Gets or sets the access token.
/// </summary>
/// <value>The access token.</value>
public string AccessToken { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this instance is active.
/// </summary>
/// <value><c>null</c> if [is active] contains no value, <c>true</c> if [is active]; otherwise, <c>false</c>.</value>
public bool? IsActive { get; set; }
/// <summary>
/// Gets or sets the start index.
/// </summary>
/// <value>The start index.</value>
public int? StartIndex { get; set; }
/// <summary>
/// Gets or sets the limit.
/// </summary>
/// <value>The limit.</value>
public int? Limit { get; set; }
}
}

@ -0,0 +1,39 @@
using MediaBrowser.Model.Querying;
using System.Threading;
using System.Threading.Tasks;
namespace MediaBrowser.Controller.Security
{
public interface IAuthenticationRepository
{
/// <summary>
/// Creates the specified information.
/// </summary>
/// <param name="info">The information.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
Task Create(AuthenticationInfo info, CancellationToken cancellationToken);
/// <summary>
/// Updates the specified information.
/// </summary>
/// <param name="info">The information.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
Task Update(AuthenticationInfo info, CancellationToken cancellationToken);
/// <summary>
/// Gets the specified query.
/// </summary>
/// <param name="query">The query.</param>
/// <returns>QueryResult{AuthenticationInfo}.</returns>
QueryResult<AuthenticationInfo> Get(AuthenticationInfoQuery query);
/// <summary>
/// Gets the specified identifier.
/// </summary>
/// <param name="id">The identifier.</param>
/// <returns>AuthenticationInfo.</returns>
AuthenticationInfo Get(string id);
}
}

@ -259,7 +259,28 @@ namespace MediaBrowser.Controller.Session
/// <summary>
/// Validates the security token.
/// </summary>
/// <param name="token">The token.</param>
void ValidateSecurityToken(string token);
/// <param name="accessToken">The access token.</param>
void ValidateSecurityToken(string accessToken);
/// <summary>
/// Logouts the specified access token.
/// </summary>
/// <param name="accessToken">The access token.</param>
/// <returns>Task.</returns>
Task Logout(string accessToken);
/// <summary>
/// Revokes the user tokens.
/// </summary>
/// <param name="userId">The user identifier.</param>
/// <returns>Task.</returns>
Task RevokeUserTokens(string userId);
/// <summary>
/// Determines whether the specified remote endpoint is local.
/// </summary>
/// <param name="remoteEndpoint">The remote endpoint.</param>
/// <returns><c>true</c> if the specified remote endpoint is local; otherwise, <c>false</c>.</returns>
bool IsLocal(string remoteEndpoint);
}
}

@ -123,7 +123,7 @@ namespace MediaBrowser.Controller.Session
public List<string> SupportedCommands { get; set; }
public TranscodingInfo TranscodingInfo { get; set; }
/// <summary>
/// Gets a value indicating whether this instance is active.
/// </summary>

@ -1,11 +1,11 @@
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Common.IO;
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Logging;
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace MediaBrowser.LocalMetadata
{

@ -246,7 +246,7 @@ namespace MediaBrowser.Model.ApiClient
/// Gets the client session asynchronous.
/// </summary>
/// <returns>Task{SessionInfoDto}.</returns>
Task<SessionInfoDto> GetCurrentSessionAsync();
Task<SessionInfoDto> GetCurrentSessionAsync(CancellationToken cancellationToken);
/// <summary>
/// Gets the item counts async.
@ -644,6 +644,13 @@ namespace MediaBrowser.Model.ApiClient
/// <returns>Task.</returns>
Task SetVolume(string sessionId, int volume);
/// <summary>
/// Stops the transcoding processes.
/// </summary>
/// <param name="deviceId">The device identifier.</param>
/// <returns>Task.</returns>
Task StopTranscodingProcesses(string deviceId);
/// <summary>
/// Sets the index of the audio stream.
/// </summary>
@ -984,7 +991,7 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="query">The query.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{LiveTvInfo}.</returns>
Task<QueryResult<ChannelInfoDto>> GetLiveTvChannelsAsync(ChannelQuery query, CancellationToken cancellationToken);
Task<QueryResult<ChannelInfoDto>> GetLiveTvChannelsAsync(LiveTvChannelQuery query, CancellationToken cancellationToken);
/// <summary>
/// Gets the live tv channel asynchronous.
@ -1187,5 +1194,13 @@ namespace MediaBrowser.Model.ApiClient
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{QueryResult{BaseItemDto}}.</returns>
Task<QueryResult<BaseItemDto>> GetChannels(ChannelQuery query, CancellationToken cancellationToken);
/// <summary>
/// Gets the latest channel items.
/// </summary>
/// <param name="query">The query.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{QueryResult{BaseItemDto}}.</returns>
Task<QueryResult<BaseItemDto>> GetLatestChannelItems(AllChannelMediaQuery query, CancellationToken cancellationToken);
}
}

@ -210,6 +210,8 @@ namespace MediaBrowser.Model.Configuration
public bool DefaultMetadataSettingsApplied { get; set; }
public bool EnableTokenAuthentication { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="ServerConfiguration" /> class.
/// </summary>

@ -21,6 +21,6 @@ namespace MediaBrowser.Model.Users
/// Gets or sets the authentication token.
/// </summary>
/// <value>The authentication token.</value>
public string AuthenticationToken { get; set; }
public string AccessToken { get; set; }
}
}

@ -8,7 +8,6 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

@ -170,7 +170,7 @@ namespace MediaBrowser.Providers.Manager
var key = id.Key;
// Don't replace existing Id's.
if (!target.ProviderIds.ContainsKey(key))
if (replaceData || !target.ProviderIds.ContainsKey(key))
{
target.ProviderIds[key] = id.Value;
}

@ -19,7 +19,7 @@ using System.Threading.Tasks;
namespace MediaBrowser.Providers.TV
{
public class MovieDbEpisodeImageProvider : IRemoteImageProvider, IHasOrder
public class MovieDbEpisodeImageProvider/* : IRemoteImageProvider, IHasOrder*/
{
private const string GetTvInfo3 = @"http://api.themoviedb.org/3/tv/{0}/season/{1}/episode/{2}?api_key={3}&append_to_response=images,external_ids,credits,videos";
private readonly IHttpClient _httpClient;

@ -1133,6 +1133,8 @@ namespace MediaBrowser.Server.Implementations.Channels
item.CommunityRating = info.CommunityRating;
item.OfficialRating = info.OfficialRating;
item.Overview = info.Overview;
item.IndexNumber = info.IndexNumber;
item.ParentIndexNumber = info.ParentIndexNumber;
item.People = info.People;
item.PremiereDate = info.PremiereDate;
item.ProductionYear = info.ProductionYear;
@ -1159,7 +1161,6 @@ namespace MediaBrowser.Server.Implementations.Channels
if (channelMediaItem != null)
{
channelMediaItem.IsInfiniteStream = info.IsInfiniteStream;
channelMediaItem.ContentType = info.ContentType;
channelMediaItem.ChannelMediaSources = info.MediaSources;

@ -1,9 +1,11 @@
using MediaBrowser.Common.IO;
using MediaBrowser.Common.Events;
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Collections;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Logging;
using MoreLinq;
using System;
using System.Collections.Generic;
@ -19,12 +21,18 @@ namespace MediaBrowser.Server.Implementations.Collections
private readonly ILibraryManager _libraryManager;
private readonly IFileSystem _fileSystem;
private readonly ILibraryMonitor _iLibraryMonitor;
private readonly ILogger _logger;
public CollectionManager(ILibraryManager libraryManager, IFileSystem fileSystem, ILibraryMonitor iLibraryMonitor)
public event EventHandler<CollectionCreatedEventArgs> CollectionCreated;
public event EventHandler<CollectionModifiedEventArgs> ItemsAddedToCollection;
public event EventHandler<CollectionModifiedEventArgs> ItemsRemovedFromCollection;
public CollectionManager(ILibraryManager libraryManager, IFileSystem fileSystem, ILibraryMonitor iLibraryMonitor, ILogger logger)
{
_libraryManager = libraryManager;
_fileSystem = fileSystem;
_iLibraryMonitor = iLibraryMonitor;
_logger = logger;
}
public Folder GetCollectionsFolder(string userId)
@ -74,9 +82,16 @@ namespace MediaBrowser.Server.Implementations.Collections
if (options.ItemIdList.Count > 0)
{
await AddToCollection(collection.Id, options.ItemIdList);
await AddToCollection(collection.Id, options.ItemIdList, false);
}
EventHelper.FireEventIfNotNull(CollectionCreated, this, new CollectionCreatedEventArgs
{
Collection = collection,
Options = options
}, _logger);
return collection;
}
finally
@ -113,7 +128,12 @@ namespace MediaBrowser.Server.Implementations.Collections
return GetCollectionsFolder(string.Empty);
}
public async Task AddToCollection(Guid collectionId, IEnumerable<Guid> ids)
public Task AddToCollection(Guid collectionId, IEnumerable<Guid> ids)
{
return AddToCollection(collectionId, ids, true);
}
private async Task AddToCollection(Guid collectionId, IEnumerable<Guid> ids, bool fireEvent)
{
var collection = _libraryManager.GetItemById(collectionId) as BoxSet;
@ -123,6 +143,7 @@ namespace MediaBrowser.Server.Implementations.Collections
}
var list = new List<LinkedChild>();
var itemList = new List<BaseItem>();
var currentLinkedChildren = collection.GetLinkedChildren().ToList();
foreach (var itemId in ids)
@ -134,6 +155,8 @@ namespace MediaBrowser.Server.Implementations.Collections
throw new ArgumentException("No item exists with the supplied Id");
}
itemList.Add(item);
if (currentLinkedChildren.Any(i => i.Id == itemId))
{
throw new ArgumentException("Item already exists in collection");
@ -165,6 +188,16 @@ namespace MediaBrowser.Server.Implementations.Collections
await collection.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
await collection.RefreshMetadata(CancellationToken.None).ConfigureAwait(false);
if (fireEvent)
{
EventHelper.FireEventIfNotNull(ItemsRemovedFromCollection, this, new CollectionModifiedEventArgs
{
Collection = collection,
ItemsChanged = itemList
}, _logger);
}
}
public async Task RemoveFromCollection(Guid collectionId, IEnumerable<Guid> itemIds)
@ -177,6 +210,7 @@ namespace MediaBrowser.Server.Implementations.Collections
}
var list = new List<LinkedChild>();
var itemList = new List<BaseItem>();
foreach (var itemId in itemIds)
{
@ -190,6 +224,12 @@ namespace MediaBrowser.Server.Implementations.Collections
list.Add(child);
var childItem = _libraryManager.GetItemById(itemId);
if (childItem != null)
{
itemList.Add(childItem);
}
var supportsGrouping = childItem as ISupportsBoxSetGrouping;
if (supportsGrouping != null)
@ -221,7 +261,7 @@ namespace MediaBrowser.Server.Implementations.Collections
{
File.Delete(file);
}
foreach (var child in list)
{
collection.LinkedChildren.Remove(child);
@ -238,6 +278,13 @@ namespace MediaBrowser.Server.Implementations.Collections
await collection.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
await collection.RefreshMetadata(CancellationToken.None).ConfigureAwait(false);
EventHelper.FireEventIfNotNull(ItemsRemovedFromCollection, this, new CollectionModifiedEventArgs
{
Collection = collection,
ItemsChanged = itemList
}, _logger);
}
public IEnumerable<BaseItem> CollapseItemsWithinBoxSets(IEnumerable<BaseItem> items, User user)

@ -1,4 +1,4 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Session;
@ -13,9 +13,12 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security
{
public class AuthService : IAuthService
{
public AuthService(IUserManager userManager, ISessionManager sessionManager, IAuthorizationContext authorizationContext)
private readonly IServerConfigurationManager _config;
public AuthService(IUserManager userManager, ISessionManager sessionManager, IAuthorizationContext authorizationContext, IServerConfigurationManager config)
{
AuthorizationContext = authorizationContext;
_config = config;
SessionManager = sessionManager;
UserManager = userManager;
}
@ -54,28 +57,30 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security
//This code is executed before the service
var auth = AuthorizationContext.GetAuthorizationInfo(req);
if (string.IsNullOrWhiteSpace(auth.Token))
if (!string.IsNullOrWhiteSpace(auth.Token) || _config.Configuration.EnableTokenAuthentication)
{
// Legacy
// TODO: Deprecate this in Oct 2014
User user = null;
if (!string.IsNullOrWhiteSpace(auth.UserId))
{
var userId = auth.UserId;
SessionManager.ValidateSecurityToken(auth.Token);
}
user = UserManager.GetUserById(new Guid(userId));
}
var user = string.IsNullOrWhiteSpace(auth.UserId)
? null
: UserManager.GetUserById(new Guid(auth.UserId));
if (user == null || user.Configuration.IsDisabled)
{
throw new UnauthorizedAccessException("Unauthorized access.");
}
if (user != null && user.Configuration.IsDisabled)
{
throw new UnauthorizedAccessException("User account has been disabled.");
}
else
if (!string.IsNullOrWhiteSpace(auth.DeviceId) &&
!string.IsNullOrWhiteSpace(auth.Client) &&
!string.IsNullOrWhiteSpace(auth.Device))
{
SessionManager.ValidateSecurityToken(auth.Token);
SessionManager.LogSessionActivity(auth.Client,
auth.Version,
auth.DeviceId,
auth.Device,
req.RemoteIp,
user);
}
}
@ -108,11 +113,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security
}
}
private void LogRequest()
{
}
protected bool DoHtmlRedirectIfConfigured(IRequest req, IResponse res, bool includeRedirectParam = false)
{
var htmlRedirect = this.HtmlRedirect ?? AuthenticateService.HtmlRedirect;

@ -216,6 +216,7 @@
<Compile Include="ScheduledTasks\ChapterImagesTask.cs" />
<Compile Include="ScheduledTasks\RefreshIntrosTask.cs" />
<Compile Include="ScheduledTasks\RefreshMediaLibraryTask.cs" />
<Compile Include="Security\AuthenticationRepository.cs" />
<Compile Include="Security\EncryptionManager.cs" />
<Compile Include="ServerApplicationPaths.cs" />
<Compile Include="ServerManager\ServerManager.cs" />

@ -14,7 +14,7 @@ using System.Threading.Tasks;
namespace MediaBrowser.Server.Implementations.Persistence
{
public class SqliteFileOrganizationRepository : IFileOrganizationRepository
public class SqliteFileOrganizationRepository : IFileOrganizationRepository, IDisposable
{
private IDbConnection _connection;

@ -0,0 +1,338 @@
using MediaBrowser.Controller;
using MediaBrowser.Controller.Security;
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.Security
{
public class AuthenticationRepository : IAuthenticationRepository
{
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 _saveInfoCommand;
public AuthenticationRepository(ILogger logger, IServerApplicationPaths appPaths)
{
_logger = logger;
_appPaths = appPaths;
}
public async Task Initialize()
{
var dbFile = Path.Combine(_appPaths.DataPath, "authentication.db");
_connection = await SqliteExtensions.ConnectToDb(dbFile, _logger).ConfigureAwait(false);
string[] queries = {
"create table if not exists AccessTokens (Id GUID PRIMARY KEY, AccessToken TEXT NOT NULL, DeviceId TEXT, AppName TEXT, DeviceName TEXT, UserId TEXT, IsActive BIT, DateCreated DATETIME NOT NULL, DateRevoked DATETIME)",
"create index if not exists idx_AccessTokens on AccessTokens(Id)",
//pragmas
"pragma temp_store = memory",
"pragma shrink_memory"
};
_connection.RunQueries(queries, _logger);
PrepareStatements();
}
private void PrepareStatements()
{
_saveInfoCommand = _connection.CreateCommand();
_saveInfoCommand.CommandText = "replace into AccessTokens (Id, AccessToken, DeviceId, AppName, DeviceName, UserId, IsActive, DateCreated, DateRevoked) values (@Id, @AccessToken, @DeviceId, @AppName, @DeviceName, @UserId, @IsActive, @DateCreated, @DateRevoked)";
_saveInfoCommand.Parameters.Add(_saveInfoCommand, "@Id");
_saveInfoCommand.Parameters.Add(_saveInfoCommand, "@AccessToken");
_saveInfoCommand.Parameters.Add(_saveInfoCommand, "@DeviceId");
_saveInfoCommand.Parameters.Add(_saveInfoCommand, "@AppName");
_saveInfoCommand.Parameters.Add(_saveInfoCommand, "@DeviceName");
_saveInfoCommand.Parameters.Add(_saveInfoCommand, "@UserId");
_saveInfoCommand.Parameters.Add(_saveInfoCommand, "@IsActive");
_saveInfoCommand.Parameters.Add(_saveInfoCommand, "@DateCreated");
_saveInfoCommand.Parameters.Add(_saveInfoCommand, "@DateRevoked");
}
public Task Create(AuthenticationInfo info, CancellationToken cancellationToken)
{
info.Id = Guid.NewGuid().ToString("N");
return Update(info, cancellationToken);
}
public async Task Update(AuthenticationInfo info, CancellationToken cancellationToken)
{
if (info == null)
{
throw new ArgumentNullException("info");
}
cancellationToken.ThrowIfCancellationRequested();
await _writeLock.WaitAsync(cancellationToken).ConfigureAwait(false);
IDbTransaction transaction = null;
try
{
transaction = _connection.BeginTransaction();
var index = 0;
_saveInfoCommand.GetParameter(index++).Value = new Guid(info.Id);
_saveInfoCommand.GetParameter(index++).Value = info.AccessToken;
_saveInfoCommand.GetParameter(index++).Value = info.DeviceId;
_saveInfoCommand.GetParameter(index++).Value = info.AppName;
_saveInfoCommand.GetParameter(index++).Value = info.DeviceName;
_saveInfoCommand.GetParameter(index++).Value = info.UserId;
_saveInfoCommand.GetParameter(index++).Value = info.IsActive;
_saveInfoCommand.GetParameter(index++).Value = info.DateCreated;
_saveInfoCommand.GetParameter(index++).Value = info.DateRevoked;
_saveInfoCommand.Transaction = transaction;
_saveInfoCommand.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();
}
}
private const string BaseSelectText = "select Id, AccessToken, DeviceId, AppName, DeviceName, UserId, IsActive, DateCreated, DateRevoked from AccessTokens";
public QueryResult<AuthenticationInfo> Get(AuthenticationInfoQuery query)
{
if (query == null)
{
throw new ArgumentNullException("query");
}
using (var cmd = _connection.CreateCommand())
{
cmd.CommandText = BaseSelectText;
var whereClauses = new List<string>();
var startIndex = query.StartIndex ?? 0;
if (startIndex > 0)
{
whereClauses.Add(string.Format("Id NOT IN (SELECT Id FROM AccessTokens ORDER BY DateCreated LIMIT {0})",
startIndex.ToString(_usCulture)));
}
if (!string.IsNullOrWhiteSpace(query.AccessToken))
{
whereClauses.Add("AccessToken=@AccessToken");
cmd.Parameters.Add(cmd, "@AccessToken", DbType.String).Value = query.AccessToken;
}
if (!string.IsNullOrWhiteSpace(query.UserId))
{
whereClauses.Add("UserId=@UserId");
cmd.Parameters.Add(cmd, "@UserId", DbType.String).Value = query.UserId;
}
if (!string.IsNullOrWhiteSpace(query.DeviceId))
{
whereClauses.Add("DeviceId=@DeviceId");
cmd.Parameters.Add(cmd, "@DeviceId", DbType.String).Value = query.DeviceId;
}
if (query.IsActive.HasValue)
{
whereClauses.Add("IsActive=@IsActive");
cmd.Parameters.Add(cmd, "@IsActive", DbType.Boolean).Value = query.IsActive.Value;
}
if (whereClauses.Count > 0)
{
cmd.CommandText += " where " + string.Join(" AND ", whereClauses.ToArray());
}
cmd.CommandText += " ORDER BY DateCreated";
if (query.Limit.HasValue)
{
cmd.CommandText += " LIMIT " + query.Limit.Value.ToString(_usCulture);
}
cmd.CommandText += "; select count (Id) from AccessTokens";
var list = new List<AuthenticationInfo>();
var count = 0;
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess))
{
while (reader.Read())
{
list.Add(Get(reader));
}
if (reader.NextResult() && reader.Read())
{
count = reader.GetInt32(0);
}
}
return new QueryResult<AuthenticationInfo>()
{
Items = list.ToArray(),
TotalRecordCount = count
};
}
}
public AuthenticationInfo Get(string id)
{
if (string.IsNullOrEmpty(id))
{
throw new ArgumentNullException("id");
}
var guid = new Guid(id);
using (var cmd = _connection.CreateCommand())
{
cmd.CommandText = BaseSelectText + " where Id=@Id";
cmd.Parameters.Add(cmd, "@Id", DbType.Guid).Value = guid;
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow))
{
if (reader.Read())
{
return Get(reader);
}
}
}
return null;
}
private AuthenticationInfo Get(IDataReader reader)
{
var s = "select Id, AccessToken, DeviceId, AppName, DeviceName, UserId, IsActive, DateCreated, DateRevoked from AccessTokens";
var info = new AuthenticationInfo
{
Id = reader.GetGuid(0).ToString("N"),
AccessToken = reader.GetString(1)
};
if (!reader.IsDBNull(2))
{
info.DeviceId = reader.GetString(2);
}
if (!reader.IsDBNull(3))
{
info.AppName = reader.GetString(3);
}
if (!reader.IsDBNull(4))
{
info.DeviceName = reader.GetString(4);
}
if (!reader.IsDBNull(5))
{
info.UserId = reader.GetString(5);
}
info.IsActive = reader.GetBoolean(6);
info.DateCreated = reader.GetDateTime(7);
if (!reader.IsDBNull(8))
{
info.DateRevoked = reader.GetDateTime(8);
}
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);
}
}
}
}
}

@ -1,6 +1,4 @@
using System.Security.Cryptography;
using System.Text;
using MediaBrowser.Common.Events;
using MediaBrowser.Common.Events;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller;
@ -13,12 +11,14 @@ using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Security;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Library;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Serialization;
using MediaBrowser.Model.Session;
using MediaBrowser.Model.Users;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
@ -27,7 +27,6 @@ using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Model.Users;
namespace MediaBrowser.Server.Implementations.Session
{
@ -62,6 +61,8 @@ namespace MediaBrowser.Server.Implementations.Session
private readonly IJsonSerializer _jsonSerializer;
private readonly IServerApplicationHost _appHost;
private readonly IAuthenticationRepository _authRepo;
/// <summary>
/// Gets or sets the configuration manager.
/// </summary>
@ -104,7 +105,7 @@ namespace MediaBrowser.Server.Implementations.Session
/// <param name="logger">The logger.</param>
/// <param name="userRepository">The user repository.</param>
/// <param name="libraryManager">The library manager.</param>
public SessionManager(IUserDataManager userDataRepository, IServerConfigurationManager configurationManager, ILogger logger, IUserRepository userRepository, ILibraryManager libraryManager, IUserManager userManager, IMusicManager musicManager, IDtoService dtoService, IImageProcessor imageProcessor, IItemRepository itemRepo, IJsonSerializer jsonSerializer, IServerApplicationHost appHost, IHttpClient httpClient)
public SessionManager(IUserDataManager userDataRepository, IServerConfigurationManager configurationManager, ILogger logger, IUserRepository userRepository, ILibraryManager libraryManager, IUserManager userManager, IMusicManager musicManager, IDtoService dtoService, IImageProcessor imageProcessor, IItemRepository itemRepo, IJsonSerializer jsonSerializer, IServerApplicationHost appHost, IHttpClient httpClient, IAuthenticationRepository authRepo)
{
_userDataRepository = userDataRepository;
_configurationManager = configurationManager;
@ -119,6 +120,7 @@ namespace MediaBrowser.Server.Implementations.Session
_jsonSerializer = jsonSerializer;
_appHost = appHost;
_httpClient = httpClient;
_authRepo = authRepo;
}
/// <summary>
@ -204,7 +206,12 @@ namespace MediaBrowser.Server.Implementations.Session
/// <returns>Task.</returns>
/// <exception cref="System.ArgumentNullException">user</exception>
/// <exception cref="System.UnauthorizedAccessException"></exception>
public async Task<SessionInfo> LogSessionActivity(string clientType, string appVersion, string deviceId, string deviceName, string remoteEndPoint, User user)
public async Task<SessionInfo> LogSessionActivity(string clientType,
string appVersion,
string deviceId,
string deviceName,
string remoteEndPoint,
User user)
{
if (string.IsNullOrEmpty(clientType))
{
@ -1157,7 +1164,37 @@ namespace MediaBrowser.Server.Implementations.Session
public void ValidateSecurityToken(string token)
{
if (string.IsNullOrWhiteSpace(token))
{
throw new UnauthorizedAccessException();
}
var result = _authRepo.Get(new AuthenticationInfoQuery
{
AccessToken = token
});
var info = result.Items.FirstOrDefault();
if (info == null)
{
throw new UnauthorizedAccessException();
}
if (!info.IsActive)
{
throw new UnauthorizedAccessException("Access token has expired.");
}
if (!string.IsNullOrWhiteSpace(info.UserId))
{
var user = _userManager.GetUserById(new Guid(info.UserId));
if (user == null || user.Configuration.IsDisabled)
{
throw new UnauthorizedAccessException("User account has been disabled.");
}
}
}
/// <summary>
@ -1175,7 +1212,7 @@ namespace MediaBrowser.Server.Implementations.Session
/// <exception cref="UnauthorizedAccessException"></exception>
public async Task<AuthenticationResult> AuthenticateNewSession(string username, string password, string clientType, string appVersion, string deviceId, string deviceName, string remoteEndPoint)
{
var result = await _userManager.AuthenticateUser(username, password).ConfigureAwait(false);
var result = IsLocalhost(remoteEndPoint) || await _userManager.AuthenticateUser(username, password).ConfigureAwait(false);
if (!result)
{
@ -1185,6 +1222,8 @@ namespace MediaBrowser.Server.Implementations.Session
var user = _userManager.Users
.First(i => string.Equals(username, i.Name, StringComparison.OrdinalIgnoreCase));
var token = await GetAuthorizationToken(user.Id.ToString("N"), deviceId, clientType, deviceName).ConfigureAwait(false);
var session = await LogSessionActivity(clientType,
appVersion,
deviceId,
@ -1197,11 +1236,108 @@ namespace MediaBrowser.Server.Implementations.Session
{
User = _dtoService.GetUserDto(user),
SessionInfo = GetSessionInfoDto(session),
AuthenticationToken = Guid.NewGuid().ToString("N")
AccessToken = token
};
}
private bool IsLocal(string remoteEndpoint)
private async Task<string> GetAuthorizationToken(string userId, string deviceId, string app, string deviceName)
{
var existing = _authRepo.Get(new AuthenticationInfoQuery
{
DeviceId = deviceId,
IsActive = true,
UserId = userId,
Limit = 1
});
if (existing.Items.Length > 0)
{
_logger.Debug("Reissuing access token");
return existing.Items[0].AccessToken;
}
var newToken = new AuthenticationInfo
{
AppName = app,
DateCreated = DateTime.UtcNow,
DeviceId = deviceId,
DeviceName = deviceName,
UserId = userId,
IsActive = true,
AccessToken = Guid.NewGuid().ToString("N")
};
_logger.Debug("Creating new access token for user {0}", userId);
await _authRepo.Create(newToken, CancellationToken.None).ConfigureAwait(false);
return newToken.AccessToken;
}
public async Task Logout(string accessToken)
{
if (string.IsNullOrWhiteSpace(accessToken))
{
throw new ArgumentNullException("accessToken");
}
var existing = _authRepo.Get(new AuthenticationInfoQuery
{
Limit = 1,
AccessToken = accessToken
}).Items.FirstOrDefault();
if (existing != null)
{
existing.IsActive = false;
await _authRepo.Update(existing, CancellationToken.None).ConfigureAwait(false);
var sessions = Sessions
.Where(i => string.Equals(i.DeviceId, existing.DeviceId, StringComparison.OrdinalIgnoreCase))
.ToList();
foreach (var session in sessions)
{
try
{
ReportSessionEnded(session.Id);
}
catch (Exception ex)
{
_logger.ErrorException("Error reporting session ended", ex);
}
}
}
}
public async Task RevokeUserTokens(string userId)
{
var existing = _authRepo.Get(new AuthenticationInfoQuery
{
IsActive = true,
UserId = userId
});
foreach (var info in existing.Items)
{
await Logout(info.AccessToken).ConfigureAwait(false);
}
}
private bool IsLocalhost(string remoteEndpoint)
{
if (string.IsNullOrWhiteSpace(remoteEndpoint))
{
throw new ArgumentNullException("remoteEndpoint");
}
return remoteEndpoint.IndexOf("localhost", StringComparison.OrdinalIgnoreCase) != -1 ||
remoteEndpoint.StartsWith("127.", StringComparison.OrdinalIgnoreCase) ||
remoteEndpoint.StartsWith("::", StringComparison.OrdinalIgnoreCase);
}
public bool IsLocal(string remoteEndpoint)
{
if (string.IsNullOrWhiteSpace(remoteEndpoint))
{
@ -1211,12 +1347,11 @@ namespace MediaBrowser.Server.Implementations.Session
// Private address space:
// http://en.wikipedia.org/wiki/Private_network
return remoteEndpoint.IndexOf("localhost", StringComparison.OrdinalIgnoreCase) != -1 ||
return IsLocalhost(remoteEndpoint) ||
remoteEndpoint.StartsWith("10.", StringComparison.OrdinalIgnoreCase) ||
remoteEndpoint.StartsWith("192.", StringComparison.OrdinalIgnoreCase) ||
remoteEndpoint.StartsWith("172.", StringComparison.OrdinalIgnoreCase) ||
remoteEndpoint.StartsWith("127.", StringComparison.OrdinalIgnoreCase) ||
remoteEndpoint.StartsWith("::", StringComparison.OrdinalIgnoreCase);
remoteEndpoint.StartsWith("169.", StringComparison.OrdinalIgnoreCase);
}
/// <summary>

@ -210,6 +210,8 @@ namespace MediaBrowser.ServerApplication
private IUserViewManager UserViewManager { get; set; }
private IAuthenticationRepository AuthenticationRepository { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="ApplicationHost"/> class.
/// </summary>
@ -586,6 +588,9 @@ namespace MediaBrowser.ServerApplication
FileOrganizationRepository = await GetFileOrganizationRepository().ConfigureAwait(false);
RegisterSingleInstance(FileOrganizationRepository);
AuthenticationRepository = await GetAuthenticationRepository().ConfigureAwait(false);
RegisterSingleInstance(AuthenticationRepository);
UserManager = new UserManager(LogManager.GetLogger("UserManager"), ServerConfigurationManager, UserRepository, XmlSerializer);
RegisterSingleInstance(UserManager);
@ -625,7 +630,7 @@ namespace MediaBrowser.ServerApplication
DtoService = new DtoService(Logger, LibraryManager, UserDataManager, ItemRepository, ImageProcessor, ServerConfigurationManager, FileSystemManager, ProviderManager, () => ChannelManager);
RegisterSingleInstance(DtoService);
SessionManager = new SessionManager(UserDataManager, ServerConfigurationManager, Logger, UserRepository, LibraryManager, UserManager, musicManager, DtoService, ImageProcessor, ItemRepository, JsonSerializer, this, HttpClient);
SessionManager = new SessionManager(UserDataManager, ServerConfigurationManager, Logger, UserRepository, LibraryManager, UserManager, musicManager, DtoService, ImageProcessor, ItemRepository, JsonSerializer, this, HttpClient, AuthenticationRepository);
RegisterSingleInstance(SessionManager);
var newsService = new Server.Implementations.News.NewsService(ApplicationPaths, JsonSerializer);
@ -651,7 +656,7 @@ namespace MediaBrowser.ServerApplication
var connectionManager = new ConnectionManager(dlnaManager, ServerConfigurationManager, LogManager.GetLogger("UpnpConnectionManager"), HttpClient);
RegisterSingleInstance<IConnectionManager>(connectionManager);
var collectionManager = new CollectionManager(LibraryManager, FileSystemManager, LibraryMonitor);
var collectionManager = new CollectionManager(LibraryManager, FileSystemManager, LibraryMonitor, LogManager.GetLogger("CollectionManager"));
RegisterSingleInstance<ICollectionManager>(collectionManager);
LiveTvManager = new LiveTvManager(ServerConfigurationManager, FileSystemManager, Logger, ItemRepository, ImageProcessor, UserDataManager, DtoService, UserManager, LibraryManager, TaskManager, LocalizationManager);
@ -678,7 +683,7 @@ namespace MediaBrowser.ServerApplication
var authContext = new AuthorizationContext();
RegisterSingleInstance<IAuthorizationContext>(authContext);
RegisterSingleInstance<ISessionContext>(new SessionContext(UserManager, authContext, SessionManager));
RegisterSingleInstance<IAuthService>(new AuthService(UserManager, SessionManager, authContext));
RegisterSingleInstance<IAuthService>(new AuthService(UserManager, SessionManager, authContext, ServerConfigurationManager));
RegisterSingleInstance<ISubtitleEncoder>(new SubtitleEncoder(LibraryManager, LogManager.GetLogger("SubtitleEncoder"), ApplicationPaths, FileSystemManager, MediaEncoder));
@ -755,6 +760,15 @@ namespace MediaBrowser.ServerApplication
return repo;
}
private async Task<IAuthenticationRepository> GetAuthenticationRepository()
{
var repo = new AuthenticationRepository(LogManager.GetLogger("AuthenticationRepository"), ServerConfigurationManager.ApplicationPaths);
await repo.Initialize().ConfigureAwait(false);
return repo;
}
/// <summary>
/// Configures the repositories.
/// </summary>

@ -77,7 +77,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers
/// <param name="cancellationToken">The cancellation token.</param>
private void Fetch(T item, string metadataFile, XmlReaderSettings settings, Encoding encoding, CancellationToken cancellationToken)
{
using (var streamReader = new StreamReader(metadataFile, encoding))
using (var streamReader = new StreamReader(metadataFile))
{
// Use XmlReader for best performance
using (var reader = XmlReader.Create(streamReader, settings))

@ -27,7 +27,7 @@ namespace MediaBrowser.XbmcMetadata.Providers
var path = file.FullName;
await XmlProviderUtils.XmlParsingResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false);
//await XmlProviderUtils.XmlParsingResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false);
try
{
@ -44,10 +44,10 @@ namespace MediaBrowser.XbmcMetadata.Providers
{
result.HasMetadata = false;
}
finally
{
XmlProviderUtils.XmlParsingResourcePool.Release();
}
//finally
//{
// XmlProviderUtils.XmlParsingResourcePool.Release();
//}
return result;
}

@ -1,15 +1,14 @@
using System.Collections.Generic;
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Security;
using System.Text;
using System.Threading;
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Entities;
namespace MediaBrowser.XbmcMetadata.Savers
{

@ -1,12 +1,4 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Security;
using System.Text;
using System.Xml;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
@ -18,6 +10,14 @@ using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities;
using MediaBrowser.XbmcMetadata.Configuration;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Security;
using System.Text;
using System.Xml;
namespace MediaBrowser.XbmcMetadata.Savers
{
@ -392,9 +392,9 @@ namespace MediaBrowser.XbmcMetadata.Savers
builder.Append("<writer>" + SecurityElement.Escape(person) + "</writer>");
}
if (writers.Count > 0)
foreach (var person in writers)
{
builder.Append("<credits>" + SecurityElement.Escape(string.Join(" / ", writers.ToArray())) + "</credits>");
builder.Append("<credits>" + SecurityElement.Escape(person) + "</credits>");
}
var hasTrailer = item as IHasTrailers;

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>MediaBrowser.Common.Internal</id>
<version>3.0.412</version>
<version>3.0.414</version>
<title>MediaBrowser.Common.Internal</title>
<authors>Luke</authors>
<owners>ebr,Luke,scottisafool</owners>
@ -12,7 +12,7 @@
<description>Contains common components shared by Media Browser Theater and Media Browser Server. Not intended for plugin developer consumption.</description>
<copyright>Copyright © Media Browser 2013</copyright>
<dependencies>
<dependency id="MediaBrowser.Common" version="3.0.412" />
<dependency id="MediaBrowser.Common" version="3.0.414" />
<dependency id="NLog" version="2.1.0" />
<dependency id="SimpleInjector" version="2.5.0" />
<dependency id="sharpcompress" version="0.10.2" />

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>MediaBrowser.Common</id>
<version>3.0.412</version>
<version>3.0.414</version>
<title>MediaBrowser.Common</title>
<authors>Media Browser Team</authors>
<owners>ebr,Luke,scottisafool</owners>

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>MediaBrowser.Server.Core</id>
<version>3.0.412</version>
<version>3.0.414</version>
<title>Media Browser.Server.Core</title>
<authors>Media Browser Team</authors>
<owners>ebr,Luke,scottisafool</owners>
@ -12,7 +12,7 @@
<description>Contains core components required to build plugins for Media Browser Server.</description>
<copyright>Copyright © Media Browser 2013</copyright>
<dependencies>
<dependency id="MediaBrowser.Common" version="3.0.412" />
<dependency id="MediaBrowser.Common" version="3.0.414" />
</dependencies>
</metadata>
<files>

Loading…
Cancel
Save