revise endpoint attributes

pull/702/head
Luke Pulverenti 10 years ago
parent 15a56fa069
commit a4b75934e5

@ -84,7 +84,6 @@ namespace MediaBrowser.Api
/// Gets the session. /// Gets the session.
/// </summary> /// </summary>
/// <returns>SessionInfo.</returns> /// <returns>SessionInfo.</returns>
/// <exception cref="System.ArgumentException">Session not found.</exception>
protected SessionInfo GetSession() protected SessionInfo GetSession()
{ {
var session = SessionContext.GetSession(Request); var session = SessionContext.GetSession(Request);

@ -9,7 +9,6 @@ using MediaBrowser.Model.Serialization;
using ServiceStack; using ServiceStack;
using ServiceStack.Text.Controller; using ServiceStack.Text.Controller;
using ServiceStack.Web; using ServiceStack.Web;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@ -33,18 +32,18 @@ namespace MediaBrowser.Api
[ApiMember(Name = "Key", Description = "Key", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] [ApiMember(Name = "Key", Description = "Key", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
public string Key { get; set; } public string Key { get; set; }
} }
/// <summary> /// <summary>
/// Class UpdateConfiguration /// Class UpdateConfiguration
/// </summary> /// </summary>
[Route("/System/Configuration", "POST", Summary = "Updates application configuration")] [Route("/System/Configuration", "POST", Summary = "Updates application configuration")]
[Authenticated] [Authenticated(Roles = "Admin")]
public class UpdateConfiguration : ServerConfiguration, IReturnVoid public class UpdateConfiguration : ServerConfiguration, IReturnVoid
{ {
} }
[Route("/System/Configuration/{Key}", "POST", Summary = "Updates named configuration")] [Route("/System/Configuration/{Key}", "POST", Summary = "Updates named configuration")]
[Authenticated] [Authenticated(Roles = "Admin")]
public class UpdateNamedConfiguration : IReturnVoid, IRequiresRequestStream public class UpdateNamedConfiguration : IReturnVoid, IRequiresRequestStream
{ {
[ApiMember(Name = "Key", Description = "Key", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] [ApiMember(Name = "Key", Description = "Key", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
@ -52,23 +51,23 @@ namespace MediaBrowser.Api
public Stream RequestStream { get; set; } public Stream RequestStream { get; set; }
} }
[Route("/System/Configuration/MetadataOptions/Default", "GET", Summary = "Gets a default MetadataOptions object")] [Route("/System/Configuration/MetadataOptions/Default", "GET", Summary = "Gets a default MetadataOptions object")]
[Authenticated] [Authenticated(Roles = "Admin")]
public class GetDefaultMetadataOptions : IReturn<MetadataOptions> public class GetDefaultMetadataOptions : IReturn<MetadataOptions>
{ {
} }
[Route("/System/Configuration/MetadataPlugins", "GET", Summary = "Gets all available metadata plugins")] [Route("/System/Configuration/MetadataPlugins", "GET", Summary = "Gets all available metadata plugins")]
[Authenticated] [Authenticated(Roles = "Admin")]
public class GetMetadataPlugins : IReturn<List<MetadataPluginSummary>> public class GetMetadataPlugins : IReturn<List<MetadataPluginSummary>>
{ {
} }
[Route("/System/Configuration/MetadataPlugins/Autoset", "POST")] [Route("/System/Configuration/MetadataPlugins/Autoset", "POST")]
[Authenticated] [Authenticated(Roles = "Admin", AllowBeforeStartupWizard = true)]
public class AutoSetMetadataOptions : IReturnVoid public class AutoSetMetadataOptions : IReturnVoid
{ {
@ -149,7 +148,7 @@ namespace MediaBrowser.Api
var configurationType = _configurationManager.GetConfigurationType(key); var configurationType = _configurationManager.GetConfigurationType(key);
var configuration = _jsonSerializer.DeserializeFromStream(request.RequestStream, configurationType); var configuration = _jsonSerializer.DeserializeFromStream(request.RequestStream, configurationType);
_configurationManager.SaveConfiguration(key, configuration); _configurationManager.SaveConfiguration(key, configuration);
} }

@ -12,6 +12,7 @@ using System.Threading.Tasks;
namespace MediaBrowser.Api.Devices namespace MediaBrowser.Api.Devices
{ {
[Route("/Devices", "GET", Summary = "Gets all devices")] [Route("/Devices", "GET", Summary = "Gets all devices")]
[Authenticated(Roles = "Admin")]
public class GetDevices : IReturn<List<DeviceInfo>> public class GetDevices : IReturn<List<DeviceInfo>>
{ {
[ApiMember(Name = "SupportsContentUploading", Description = "SupportsContentUploading", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] [ApiMember(Name = "SupportsContentUploading", Description = "SupportsContentUploading", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
@ -26,6 +27,7 @@ namespace MediaBrowser.Api.Devices
} }
[Route("/Devices/CameraUploads", "GET", Summary = "Gets camera upload history for a device")] [Route("/Devices/CameraUploads", "GET", Summary = "Gets camera upload history for a device")]
[Authenticated]
public class GetCameraUploads : IReturn<ContentUploadHistory> public class GetCameraUploads : IReturn<ContentUploadHistory>
{ {
[ApiMember(Name = "Id", Description = "Device Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] [ApiMember(Name = "Id", Description = "Device Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
@ -33,6 +35,7 @@ namespace MediaBrowser.Api.Devices
} }
[Route("/Devices/CameraUploads", "POST", Summary = "Uploads content")] [Route("/Devices/CameraUploads", "POST", Summary = "Uploads content")]
[Authenticated]
public class PostCameraUpload : IRequiresRequestStream, IReturnVoid public class PostCameraUpload : IRequiresRequestStream, IReturnVoid
{ {
[ApiMember(Name = "DeviceId", Description = "Device Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] [ApiMember(Name = "DeviceId", Description = "Device Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
@ -51,6 +54,7 @@ namespace MediaBrowser.Api.Devices
} }
[Route("/Devices/Info", "GET", Summary = "Gets device info")] [Route("/Devices/Info", "GET", Summary = "Gets device info")]
[Authenticated]
public class GetDeviceInfo : IReturn<DeviceInfo> public class GetDeviceInfo : IReturn<DeviceInfo>
{ {
[ApiMember(Name = "Id", Description = "Device Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "DELETE")] [ApiMember(Name = "Id", Description = "Device Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "DELETE")]
@ -58,6 +62,7 @@ namespace MediaBrowser.Api.Devices
} }
[Route("/Devices/Capabilities", "GET", Summary = "Gets device capabilities")] [Route("/Devices/Capabilities", "GET", Summary = "Gets device capabilities")]
[Authenticated]
public class GetDeviceCapabilities : IReturn<ClientCapabilities> public class GetDeviceCapabilities : IReturn<ClientCapabilities>
{ {
[ApiMember(Name = "Id", Description = "Device Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "DELETE")] [ApiMember(Name = "Id", Description = "Device Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "DELETE")]
@ -65,13 +70,13 @@ namespace MediaBrowser.Api.Devices
} }
[Route("/Devices/Options", "POST", Summary = "Updates device options")] [Route("/Devices/Options", "POST", Summary = "Updates device options")]
[Authenticated(Roles = "Admin")]
public class PostDeviceOptions : DeviceOptions, IReturnVoid public class PostDeviceOptions : DeviceOptions, IReturnVoid
{ {
[ApiMember(Name = "Id", Description = "Device Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "DELETE")] [ApiMember(Name = "Id", Description = "Device Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "DELETE")]
public string Id { get; set; } public string Id { get; set; }
} }
[Authenticated]
public class DeviceService : BaseApiService public class DeviceService : BaseApiService
{ {
private readonly IDeviceManager _deviceManager; private readonly IDeviceManager _deviceManager;

@ -24,9 +24,6 @@ namespace MediaBrowser.Api
[ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")] [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
public Guid UserId { get; set; } public Guid UserId { get; set; }
[ApiMember(Name = "Client", Description = "Client", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
public string Client { get; set; }
} }
[Route("/DisplayPreferences/{Id}", "GET", Summary = "Gets a user's display preferences for an item")] [Route("/DisplayPreferences/{Id}", "GET", Summary = "Gets a user's display preferences for an item")]

@ -43,7 +43,7 @@ namespace MediaBrowser.Api.Dlna
{ {
} }
[Authenticated] [Authenticated(Roles = "Admin")]
public class DlnaService : BaseApiService public class DlnaService : BaseApiService
{ {
private readonly IDlnaManager _dlnaManager; private readonly IDlnaManager _dlnaManager;

@ -87,7 +87,7 @@ namespace MediaBrowser.Api
/// <summary> /// <summary>
/// Class EnvironmentService /// Class EnvironmentService
/// </summary> /// </summary>
[Authenticated] [Authenticated(Roles = "Admin")]
public class EnvironmentService : BaseApiService public class EnvironmentService : BaseApiService
{ {
const char UncSeparator = '\\'; const char UncSeparator = '\\';

@ -2,6 +2,7 @@
using MediaBrowser.Common.IO; using MediaBrowser.Common.IO;
using MediaBrowser.Controller; using MediaBrowser.Controller;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Dto; using MediaBrowser.Model.Dto;
using ServiceStack; using ServiceStack;
using System; using System;
@ -14,8 +15,7 @@ namespace MediaBrowser.Api.Images
/// <summary> /// <summary>
/// Class GetGeneralImage /// Class GetGeneralImage
/// </summary> /// </summary>
[Route("/Images/General/{Name}/{Type}", "GET")] [Route("/Images/General/{Name}/{Type}", "GET", Summary = "Gets a general image by name")]
[Api(Description = "Gets a general image by name")]
public class GetGeneralImage public class GetGeneralImage
{ {
/// <summary> /// <summary>
@ -32,8 +32,7 @@ namespace MediaBrowser.Api.Images
/// <summary> /// <summary>
/// Class GetRatingImage /// Class GetRatingImage
/// </summary> /// </summary>
[Route("/Images/Ratings/{Theme}/{Name}", "GET")] [Route("/Images/Ratings/{Theme}/{Name}", "GET", Summary = "Gets a rating image by name")]
[Api(Description = "Gets a rating image by name")]
public class GetRatingImage public class GetRatingImage
{ {
/// <summary> /// <summary>
@ -54,8 +53,7 @@ namespace MediaBrowser.Api.Images
/// <summary> /// <summary>
/// Class GetMediaInfoImage /// Class GetMediaInfoImage
/// </summary> /// </summary>
[Route("/Images/MediaInfo/{Theme}/{Name}", "GET")] [Route("/Images/MediaInfo/{Theme}/{Name}", "GET", Summary = "Gets a media info image by name")]
[Api(Description = "Gets a media info image by name")]
public class GetMediaInfoImage public class GetMediaInfoImage
{ {
/// <summary> /// <summary>
@ -73,20 +71,20 @@ namespace MediaBrowser.Api.Images
public string Theme { get; set; } public string Theme { get; set; }
} }
[Route("/Images/MediaInfo", "GET")] [Route("/Images/MediaInfo", "GET", Summary = "Gets all media info image by name")]
[Api(Description = "Gets all media info image by name")] [Authenticated]
public class GetMediaInfoImages : IReturn<List<ImageByNameInfo>> public class GetMediaInfoImages : IReturn<List<ImageByNameInfo>>
{ {
} }
[Route("/Images/Ratings", "GET")] [Route("/Images/Ratings", "GET", Summary = "Gets all rating images by name")]
[Api(Description = "Gets all rating images by name")] [Authenticated]
public class GetRatingImages : IReturn<List<ImageByNameInfo>> public class GetRatingImages : IReturn<List<ImageByNameInfo>>
{ {
} }
[Route("/Images/General", "GET")] [Route("/Images/General", "GET", Summary = "Gets all general images by name")]
[Api(Description = "Gets all general images by name")] [Authenticated]
public class GetGeneralImages : IReturn<List<ImageByNameInfo>> public class GetGeneralImages : IReturn<List<ImageByNameInfo>>
{ {
} }

@ -24,8 +24,7 @@ namespace MediaBrowser.Api.Images
/// <summary> /// <summary>
/// Class GetItemImage /// Class GetItemImage
/// </summary> /// </summary>
[Route("/Items/{Id}/Images", "GET")] [Route("/Items/{Id}/Images", "GET", Summary = "Gets information about an item's images")]
[Api(Description = "Gets information about an item's images")]
[Authenticated] [Authenticated]
public class GetItemImageInfos : IReturn<List<ImageInfo>> public class GetItemImageInfos : IReturn<List<ImageInfo>>
{ {
@ -43,7 +42,6 @@ namespace MediaBrowser.Api.Images
[Route("/Items/{Id}/Images/{Type}/{Index}", "HEAD")] [Route("/Items/{Id}/Images/{Type}/{Index}", "HEAD")]
[Route("/Items/{Id}/Images/{Type}/{Index}/{Tag}/{Format}/{MaxWidth}/{MaxHeight}/{PercentPlayed}", "GET")] [Route("/Items/{Id}/Images/{Type}/{Index}/{Tag}/{Format}/{MaxWidth}/{MaxHeight}/{PercentPlayed}", "GET")]
[Route("/Items/{Id}/Images/{Type}/{Index}/{Tag}/{Format}/{MaxWidth}/{MaxHeight}/{PercentPlayed}", "HEAD")] [Route("/Items/{Id}/Images/{Type}/{Index}/{Tag}/{Format}/{MaxWidth}/{MaxHeight}/{PercentPlayed}", "HEAD")]
[Api(Description = "Gets an item image")]
public class GetItemImage : ImageRequest public class GetItemImage : ImageRequest
{ {
/// <summary> /// <summary>
@ -57,8 +55,7 @@ namespace MediaBrowser.Api.Images
/// <summary> /// <summary>
/// Class UpdateItemImageIndex /// Class UpdateItemImageIndex
/// </summary> /// </summary>
[Route("/Items/{Id}/Images/{Type}/{Index}/Index", "POST")] [Route("/Items/{Id}/Images/{Type}/{Index}/Index", "POST", Summary = "Updates the index for an item image")]
[Api(Description = "Updates the index for an item image")]
[Authenticated] [Authenticated]
public class UpdateItemImageIndex : IReturnVoid public class UpdateItemImageIndex : IReturnVoid
{ {
@ -122,7 +119,6 @@ namespace MediaBrowser.Api.Images
[Route("/Studios/{Name}/Images/{Type}/{Index}", "HEAD")] [Route("/Studios/{Name}/Images/{Type}/{Index}", "HEAD")]
[Route("/Years/{Year}/Images/{Type}", "HEAD")] [Route("/Years/{Year}/Images/{Type}", "HEAD")]
[Route("/Years/{Year}/Images/{Type}/{Index}", "HEAD")] [Route("/Years/{Year}/Images/{Type}/{Index}", "HEAD")]
[Api(Description = "Gets an item by name image")]
public class GetItemByNameImage : ImageRequest public class GetItemByNameImage : ImageRequest
{ {
/// <summary> /// <summary>
@ -140,7 +136,6 @@ namespace MediaBrowser.Api.Images
[Route("/Users/{Id}/Images/{Type}/{Index}", "GET")] [Route("/Users/{Id}/Images/{Type}/{Index}", "GET")]
[Route("/Users/{Id}/Images/{Type}", "HEAD")] [Route("/Users/{Id}/Images/{Type}", "HEAD")]
[Route("/Users/{Id}/Images/{Type}/{Index}", "HEAD")] [Route("/Users/{Id}/Images/{Type}/{Index}", "HEAD")]
[Api(Description = "Gets a user image")]
public class GetUserImage : ImageRequest public class GetUserImage : ImageRequest
{ {
/// <summary> /// <summary>
@ -156,7 +151,6 @@ namespace MediaBrowser.Api.Images
/// </summary> /// </summary>
[Route("/Items/{Id}/Images/{Type}", "DELETE")] [Route("/Items/{Id}/Images/{Type}", "DELETE")]
[Route("/Items/{Id}/Images/{Type}/{Index}", "DELETE")] [Route("/Items/{Id}/Images/{Type}/{Index}", "DELETE")]
[Api(Description = "Deletes an item image")]
[Authenticated] [Authenticated]
public class DeleteItemImage : DeleteImageRequest, IReturnVoid public class DeleteItemImage : DeleteImageRequest, IReturnVoid
{ {
@ -173,7 +167,6 @@ namespace MediaBrowser.Api.Images
/// </summary> /// </summary>
[Route("/Users/{Id}/Images/{Type}", "DELETE")] [Route("/Users/{Id}/Images/{Type}", "DELETE")]
[Route("/Users/{Id}/Images/{Type}/{Index}", "DELETE")] [Route("/Users/{Id}/Images/{Type}/{Index}", "DELETE")]
[Api(Description = "Deletes a user image")]
[Authenticated] [Authenticated]
public class DeleteUserImage : DeleteImageRequest, IReturnVoid public class DeleteUserImage : DeleteImageRequest, IReturnVoid
{ {
@ -190,7 +183,6 @@ namespace MediaBrowser.Api.Images
/// </summary> /// </summary>
[Route("/Users/{Id}/Images/{Type}", "POST")] [Route("/Users/{Id}/Images/{Type}", "POST")]
[Route("/Users/{Id}/Images/{Type}/{Index}", "POST")] [Route("/Users/{Id}/Images/{Type}/{Index}", "POST")]
[Api(Description = "Posts a user image")]
[Authenticated] [Authenticated]
public class PostUserImage : DeleteImageRequest, IRequiresRequestStream, IReturnVoid public class PostUserImage : DeleteImageRequest, IRequiresRequestStream, IReturnVoid
{ {

@ -5,11 +5,11 @@ using MediaBrowser.Controller;
using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities; using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers; using MediaBrowser.Model.Providers;
using ServiceStack; using ServiceStack;
using ServiceStack.Text.Controller;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
@ -45,8 +45,8 @@ namespace MediaBrowser.Api.Images
public bool IncludeAllLanguages { get; set; } public bool IncludeAllLanguages { get; set; }
} }
[Route("/Items/{Id}/RemoteImages", "GET")] [Route("/Items/{Id}/RemoteImages", "GET", Summary = "Gets available remote images for an item")]
[Api(Description = "Gets available remote images for an item")] [Authenticated]
public class GetRemoteImages : BaseRemoteImageRequest public class GetRemoteImages : BaseRemoteImageRequest
{ {
/// <summary> /// <summary>
@ -57,25 +57,8 @@ namespace MediaBrowser.Api.Images
public string Id { get; set; } public string Id { get; set; }
} }
[Route("/Artists/{Name}/RemoteImages", "GET")] [Route("/Items/{Id}/RemoteImages/Providers", "GET", Summary = "Gets available remote image providers for an item")]
[Route("/Genres/{Name}/RemoteImages", "GET")] [Authenticated]
[Route("/GameGenres/{Name}/RemoteImages", "GET")]
[Route("/MusicGenres/{Name}/RemoteImages", "GET")]
[Route("/Persons/{Name}/RemoteImages", "GET")]
[Route("/Studios/{Name}/RemoteImages", "GET")]
[Api(Description = "Gets available remote images for an item")]
public class GetItemByNameRemoteImages : BaseRemoteImageRequest
{
/// <summary>
/// Gets or sets the id.
/// </summary>
/// <value>The id.</value>
[ApiMember(Name = "Name", Description = "Name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
public string Name { get; set; }
}
[Route("/Items/{Id}/RemoteImages/Providers", "GET")]
[Api(Description = "Gets available remote image providers for an item")]
public class GetRemoteImageProviders : IReturn<List<ImageProviderInfo>> public class GetRemoteImageProviders : IReturn<List<ImageProviderInfo>>
{ {
/// <summary> /// <summary>
@ -86,23 +69,6 @@ namespace MediaBrowser.Api.Images
public string Id { get; set; } public string Id { get; set; }
} }
[Route("/Artists/{Name}/RemoteImages/Providers", "GET")]
[Route("/Genres/{Name}/RemoteImages/Providers", "GET")]
[Route("/GameGenres/{Name}/RemoteImages/Providers", "GET")]
[Route("/MusicGenres/{Name}/RemoteImages/Providers", "GET")]
[Route("/Persons/{Name}/RemoteImages/Providers", "GET")]
[Route("/Studios/{Name}/RemoteImages/Providers", "GET")]
[Api(Description = "Gets available remote image providers for an item")]
public class GetItemByNameRemoteImageProviders : IReturn<List<ImageProviderInfo>>
{
/// <summary>
/// Gets or sets the id.
/// </summary>
/// <value>The id.</value>
[ApiMember(Name = "Name", Description = "Name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
public string Name { get; set; }
}
public class BaseDownloadRemoteImage : IReturnVoid public class BaseDownloadRemoteImage : IReturnVoid
{ {
[ApiMember(Name = "Type", Description = "The image type", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] [ApiMember(Name = "Type", Description = "The image type", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
@ -115,8 +81,8 @@ namespace MediaBrowser.Api.Images
public string ImageUrl { get; set; } public string ImageUrl { get; set; }
} }
[Route("/Items/{Id}/RemoteImages/Download", "POST")] [Route("/Items/{Id}/RemoteImages/Download", "POST", Summary = "Downloads a remote image for an item")]
[Api(Description = "Downloads a remote image for an item")] [Authenticated(Roles="Admin")]
public class DownloadRemoteImage : BaseDownloadRemoteImage public class DownloadRemoteImage : BaseDownloadRemoteImage
{ {
/// <summary> /// <summary>
@ -127,25 +93,7 @@ namespace MediaBrowser.Api.Images
public string Id { get; set; } public string Id { get; set; }
} }
[Route("/Artists/{Name}/RemoteImages/Download", "POST")] [Route("/Images/Remote", "GET", Summary = "Gets a remote image")]
[Route("/Genres/{Name}/RemoteImages/Download", "POST")]
[Route("/GameGenres/{Name}/RemoteImages/Download", "POST")]
[Route("/MusicGenres/{Name}/RemoteImages/Download", "POST")]
[Route("/Persons/{Name}/RemoteImages/Download", "POST")]
[Route("/Studios/{Name}/RemoteImages/Download", "POST")]
[Api(Description = "Downloads a remote image for an item")]
public class DownloadItemByNameRemoteImage : BaseDownloadRemoteImage
{
/// <summary>
/// Gets or sets the id.
/// </summary>
/// <value>The id.</value>
[ApiMember(Name = "Name", Description = "Name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
public string Name { get; set; }
}
[Route("/Images/Remote", "GET")]
[Api(Description = "Gets a remote image")]
public class GetRemoteImage public class GetRemoteImage
{ {
[ApiMember(Name = "ImageUrl", Description = "The image url", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] [ApiMember(Name = "ImageUrl", Description = "The image url", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
@ -182,18 +130,6 @@ namespace MediaBrowser.Api.Images
return ToOptimizedSerializedResultUsingCache(result); return ToOptimizedSerializedResultUsingCache(result);
} }
public object Get(GetItemByNameRemoteImageProviders request)
{
var pathInfo = PathInfo.Parse(Request.PathInfo);
var type = pathInfo.GetArgumentValue<string>(0);
var item = GetItemByName(request.Name, type, _libraryManager);
var result = GetImageProviders(item);
return ToOptimizedSerializedResultUsingCache(result);
}
private List<ImageProviderInfo> GetImageProviders(BaseItem item) private List<ImageProviderInfo> GetImageProviders(BaseItem item)
{ {
return _providerManager.GetRemoteImageProviderInfo(item).ToList(); return _providerManager.GetRemoteImageProviderInfo(item).ToList();
@ -206,16 +142,6 @@ namespace MediaBrowser.Api.Images
return await GetRemoteImageResult(item, request).ConfigureAwait(false); return await GetRemoteImageResult(item, request).ConfigureAwait(false);
} }
public async Task<object> Get(GetItemByNameRemoteImages request)
{
var pathInfo = PathInfo.Parse(Request.PathInfo);
var type = pathInfo.GetArgumentValue<string>(0);
var item = GetItemByName(request.Name, type, _libraryManager);
return await GetRemoteImageResult(item, request).ConfigureAwait(false);
}
private async Task<RemoteImageResult> GetRemoteImageResult(BaseItem item, BaseRemoteImageRequest request) private async Task<RemoteImageResult> GetRemoteImageResult(BaseItem item, BaseRemoteImageRequest request)
{ {
var images = await _providerManager.GetAvailableRemoteImages(item, new RemoteImageQuery var images = await _providerManager.GetAvailableRemoteImages(item, new RemoteImageQuery
@ -274,18 +200,6 @@ namespace MediaBrowser.Api.Images
Task.WaitAll(task); Task.WaitAll(task);
} }
public void Post(DownloadItemByNameRemoteImage request)
{
var pathInfo = PathInfo.Parse(Request.PathInfo);
var type = pathInfo.GetArgumentValue<string>(0);
var item = GetItemByName(request.Name, type, _libraryManager);
var task = DownloadRemoteImage(item, request);
Task.WaitAll(task);
}
/// <summary> /// <summary>
/// Downloads the remote image. /// Downloads the remote image.
/// </summary> /// </summary>

@ -8,7 +8,6 @@ using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers; using MediaBrowser.Model.Providers;
using ServiceStack; using ServiceStack;
using System; using System;
@ -20,9 +19,8 @@ using System.Threading.Tasks;
namespace MediaBrowser.Api namespace MediaBrowser.Api
{ {
[Route("/Items/{Id}/ExternalIdInfos", "GET")] [Route("/Items/{Id}/ExternalIdInfos", "GET", Summary = "Gets external id infos for an item")]
[Api(Description = "Gets external id infos for an item")] [Authenticated(Roles = "Admin")]
[Authenticated]
public class GetExternalIdInfos : IReturn<List<ExternalIdInfo>> public class GetExternalIdInfos : IReturn<List<ExternalIdInfo>>
{ {
/// <summary> /// <summary>
@ -34,70 +32,60 @@ namespace MediaBrowser.Api
} }
[Route("/Items/RemoteSearch/Movie", "POST")] [Route("/Items/RemoteSearch/Movie", "POST")]
[Api(Description = "Gets external id infos for an item")]
[Authenticated] [Authenticated]
public class GetMovieRemoteSearchResults : RemoteSearchQuery<MovieInfo>, IReturn<List<RemoteSearchResult>> public class GetMovieRemoteSearchResults : RemoteSearchQuery<MovieInfo>, IReturn<List<RemoteSearchResult>>
{ {
} }
[Route("/Items/RemoteSearch/Trailer", "POST")] [Route("/Items/RemoteSearch/Trailer", "POST")]
[Api(Description = "Gets external id infos for an item")]
[Authenticated] [Authenticated]
public class GetTrailerRemoteSearchResults : RemoteSearchQuery<TrailerInfo>, IReturn<List<RemoteSearchResult>> public class GetTrailerRemoteSearchResults : RemoteSearchQuery<TrailerInfo>, IReturn<List<RemoteSearchResult>>
{ {
} }
[Route("/Items/RemoteSearch/AdultVideo", "POST")] [Route("/Items/RemoteSearch/AdultVideo", "POST")]
[Api(Description = "Gets external id infos for an item")]
[Authenticated] [Authenticated]
public class GetAdultVideoRemoteSearchResults : RemoteSearchQuery<ItemLookupInfo>, IReturn<List<RemoteSearchResult>> public class GetAdultVideoRemoteSearchResults : RemoteSearchQuery<ItemLookupInfo>, IReturn<List<RemoteSearchResult>>
{ {
} }
[Route("/Items/RemoteSearch/Series", "POST")] [Route("/Items/RemoteSearch/Series", "POST")]
[Api(Description = "Gets external id infos for an item")]
[Authenticated] [Authenticated]
public class GetSeriesRemoteSearchResults : RemoteSearchQuery<SeriesInfo>, IReturn<List<RemoteSearchResult>> public class GetSeriesRemoteSearchResults : RemoteSearchQuery<SeriesInfo>, IReturn<List<RemoteSearchResult>>
{ {
} }
[Route("/Items/RemoteSearch/Game", "POST")] [Route("/Items/RemoteSearch/Game", "POST")]
[Api(Description = "Gets external id infos for an item")]
[Authenticated] [Authenticated]
public class GetGameRemoteSearchResults : RemoteSearchQuery<GameInfo>, IReturn<List<RemoteSearchResult>> public class GetGameRemoteSearchResults : RemoteSearchQuery<GameInfo>, IReturn<List<RemoteSearchResult>>
{ {
} }
[Route("/Items/RemoteSearch/BoxSet", "POST")] [Route("/Items/RemoteSearch/BoxSet", "POST")]
[Api(Description = "Gets external id infos for an item")]
[Authenticated] [Authenticated]
public class GetBoxSetRemoteSearchResults : RemoteSearchQuery<BoxSetInfo>, IReturn<List<RemoteSearchResult>> public class GetBoxSetRemoteSearchResults : RemoteSearchQuery<BoxSetInfo>, IReturn<List<RemoteSearchResult>>
{ {
} }
[Route("/Items/RemoteSearch/MusicArtist", "POST")] [Route("/Items/RemoteSearch/MusicArtist", "POST")]
[Api(Description = "Gets external id infos for an item")]
[Authenticated] [Authenticated]
public class GetMusicArtistRemoteSearchResults : RemoteSearchQuery<ArtistInfo>, IReturn<List<RemoteSearchResult>> public class GetMusicArtistRemoteSearchResults : RemoteSearchQuery<ArtistInfo>, IReturn<List<RemoteSearchResult>>
{ {
} }
[Route("/Items/RemoteSearch/MusicAlbum", "POST")] [Route("/Items/RemoteSearch/MusicAlbum", "POST")]
[Api(Description = "Gets external id infos for an item")]
[Authenticated] [Authenticated]
public class GetMusicAlbumRemoteSearchResults : RemoteSearchQuery<AlbumInfo>, IReturn<List<RemoteSearchResult>> public class GetMusicAlbumRemoteSearchResults : RemoteSearchQuery<AlbumInfo>, IReturn<List<RemoteSearchResult>>
{ {
} }
[Route("/Items/RemoteSearch/Person", "POST")] [Route("/Items/RemoteSearch/Person", "POST")]
[Api(Description = "Gets external id infos for an item")] [Authenticated(Roles = "Admin")]
[Authenticated]
public class GetPersonRemoteSearchResults : RemoteSearchQuery<PersonLookupInfo>, IReturn<List<RemoteSearchResult>> public class GetPersonRemoteSearchResults : RemoteSearchQuery<PersonLookupInfo>, IReturn<List<RemoteSearchResult>>
{ {
} }
[Route("/Items/RemoteSearch/Image", "GET")] [Route("/Items/RemoteSearch/Image", "GET", Summary = "Gets a remote image")]
[Api(Description = "Gets a remote image")]
public class GetRemoteSearchImage public class GetRemoteSearchImage
{ {
[ApiMember(Name = "ImageUrl", Description = "The image url", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] [ApiMember(Name = "ImageUrl", Description = "The image url", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
@ -107,9 +95,8 @@ namespace MediaBrowser.Api
public string ProviderName { get; set; } public string ProviderName { get; set; }
} }
[Route("/Items/RemoteSearch/Apply/{Id}", "POST")] [Route("/Items/RemoteSearch/Apply/{Id}", "POST", Summary = "Applies search criteria to an item and refreshes metadata")]
[Api(Description = "Applies search criteria to an item and refreshes metadata")] [Authenticated(Roles = "Admin")]
[Authenticated]
public class ApplySearchCriteria : RemoteSearchResult, IReturnVoid public class ApplySearchCriteria : RemoteSearchResult, IReturnVoid
{ {
[ApiMember(Name = "Id", Description = "The item id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")] [ApiMember(Name = "Id", Description = "The item id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]

@ -26,8 +26,7 @@ namespace MediaBrowser.Api
public bool ReplaceAllImages { get; set; } public bool ReplaceAllImages { get; set; }
} }
[Route("/Items/{Id}/Refresh", "POST")] [Route("/Items/{Id}/Refresh", "POST", Summary = "Refreshes metadata for an item")]
[Api(Description = "Refreshes metadata for an item")]
public class RefreshItem : BaseRefreshRequest public class RefreshItem : BaseRefreshRequest
{ {
[ApiMember(Name = "Recursive", Description = "Indicates if the refresh should occur recursively.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "POST")] [ApiMember(Name = "Recursive", Description = "Indicates if the refresh should occur recursively.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "POST")]

@ -7,8 +7,7 @@ using System.Threading.Tasks;
namespace MediaBrowser.Api.Library namespace MediaBrowser.Api.Library
{ {
[Route("/Library/FileOrganization", "GET")] [Route("/Library/FileOrganization", "GET", Summary = "Gets file organization results")]
[Api(Description = "Gets file organization results")]
public class GetFileOrganizationActivity : IReturn<QueryResult<FileOrganizationResult>> public class GetFileOrganizationActivity : IReturn<QueryResult<FileOrganizationResult>>
{ {
/// <summary> /// <summary>
@ -26,14 +25,12 @@ namespace MediaBrowser.Api.Library
public int? Limit { get; set; } public int? Limit { get; set; }
} }
[Route("/Library/FileOrganizations", "DELETE")] [Route("/Library/FileOrganizations", "DELETE", Summary = "Clears the activity log")]
[Api(Description = "Clears the activity log")]
public class ClearOrganizationLog : IReturnVoid public class ClearOrganizationLog : IReturnVoid
{ {
} }
[Route("/Library/FileOrganizations/{Id}/File", "DELETE")] [Route("/Library/FileOrganizations/{Id}/File", "DELETE", Summary = "Deletes the original file of a organizer result")]
[Api(Description = "Deletes the original file of a organizer result")]
public class DeleteOriginalFile : IReturnVoid public class DeleteOriginalFile : IReturnVoid
{ {
/// <summary> /// <summary>
@ -44,8 +41,7 @@ namespace MediaBrowser.Api.Library
public string Id { get; set; } public string Id { get; set; }
} }
[Route("/Library/FileOrganizations/{Id}/Organize", "POST")] [Route("/Library/FileOrganizations/{Id}/Organize", "POST", Summary = "Performs an organization")]
[Api(Description = "Performs an organization")]
public class PerformOrganization : IReturn<QueryResult<FileOrganizationResult>> public class PerformOrganization : IReturn<QueryResult<FileOrganizationResult>>
{ {
/// <summary> /// <summary>
@ -56,8 +52,7 @@ namespace MediaBrowser.Api.Library
public string Id { get; set; } public string Id { get; set; }
} }
[Route("/Library/FileOrganizations/{Id}/Episode/Organize", "POST")] [Route("/Library/FileOrganizations/{Id}/Episode/Organize", "POST", Summary = "Performs an organization")]
[Api(Description = "Performs an organization")]
public class OrganizeEpisode public class OrganizeEpisode
{ {
[ApiMember(Name = "Id", Description = "Result Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] [ApiMember(Name = "Id", Description = "Result Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
@ -79,7 +74,7 @@ namespace MediaBrowser.Api.Library
public bool RememberCorrection { get; set; } public bool RememberCorrection { get; set; }
} }
[Authenticated] [Authenticated(Roles = "Admin")]
public class FileOrganizationService : BaseApiService public class FileOrganizationService : BaseApiService
{ {
private readonly IFileOrganizationService _iFileOrganizationService; private readonly IFileOrganizationService _iFileOrganizationService;

@ -23,8 +23,8 @@ using System.Threading.Tasks;
namespace MediaBrowser.Api.Library namespace MediaBrowser.Api.Library
{ {
[Route("/Items/{Id}/File", "GET")] [Route("/Items/{Id}/File", "GET", Summary = "Gets the original file of an item")]
[Api(Description = "Gets the original file of an item")] [Authenticated]
public class GetFile public class GetFile
{ {
/// <summary> /// <summary>
@ -38,8 +38,8 @@ namespace MediaBrowser.Api.Library
/// <summary> /// <summary>
/// Class GetCriticReviews /// Class GetCriticReviews
/// </summary> /// </summary>
[Route("/Items/{Id}/CriticReviews", "GET")] [Route("/Items/{Id}/CriticReviews", "GET", Summary = "Gets critic reviews for an item")]
[Api(Description = "Gets critic reviews for an item")] [Authenticated]
public class GetCriticReviews : IReturn<QueryResult<ItemReview>> public class GetCriticReviews : IReturn<QueryResult<ItemReview>>
{ {
/// <summary> /// <summary>
@ -67,8 +67,8 @@ namespace MediaBrowser.Api.Library
/// <summary> /// <summary>
/// Class GetThemeSongs /// Class GetThemeSongs
/// </summary> /// </summary>
[Route("/Items/{Id}/ThemeSongs", "GET")] [Route("/Items/{Id}/ThemeSongs", "GET", Summary = "Gets theme songs for an item")]
[Api(Description = "Gets theme songs for an item")] [Authenticated]
public class GetThemeSongs : IReturn<ThemeMediaResult> public class GetThemeSongs : IReturn<ThemeMediaResult>
{ {
/// <summary> /// <summary>
@ -92,8 +92,8 @@ namespace MediaBrowser.Api.Library
/// <summary> /// <summary>
/// Class GetThemeVideos /// Class GetThemeVideos
/// </summary> /// </summary>
[Route("/Items/{Id}/ThemeVideos", "GET")] [Route("/Items/{Id}/ThemeVideos", "GET", Summary = "Gets theme videos for an item")]
[Api(Description = "Gets theme videos for an item")] [Authenticated]
public class GetThemeVideos : IReturn<ThemeMediaResult> public class GetThemeVideos : IReturn<ThemeMediaResult>
{ {
/// <summary> /// <summary>
@ -117,8 +117,8 @@ namespace MediaBrowser.Api.Library
/// <summary> /// <summary>
/// Class GetThemeVideos /// Class GetThemeVideos
/// </summary> /// </summary>
[Route("/Items/{Id}/ThemeMedia", "GET")] [Route("/Items/{Id}/ThemeMedia", "GET", Summary = "Gets theme videos and songs for an item")]
[Api(Description = "Gets theme videos and songs for an item")] [Authenticated]
public class GetThemeMedia : IReturn<AllThemeMediaResult> public class GetThemeMedia : IReturn<AllThemeMediaResult>
{ {
/// <summary> /// <summary>
@ -139,14 +139,14 @@ namespace MediaBrowser.Api.Library
public bool InheritFromParent { get; set; } public bool InheritFromParent { get; set; }
} }
[Route("/Library/Refresh", "POST")] [Route("/Library/Refresh", "POST", Summary = "Starts a library scan")]
[Api(Description = "Starts a library scan")] [Authenticated(Roles = "Admin")]
public class RefreshLibrary : IReturnVoid public class RefreshLibrary : IReturnVoid
{ {
} }
[Route("/Items/{Id}", "DELETE")] [Route("/Items/{Id}", "DELETE", Summary = "Deletes an item from the library and file system")]
[Api(Description = "Deletes an item from the library and file system")] [Authenticated(Roles = "Delete")]
public class DeleteItem : IReturnVoid public class DeleteItem : IReturnVoid
{ {
[ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")] [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
@ -154,7 +154,7 @@ namespace MediaBrowser.Api.Library
} }
[Route("/Items/Counts", "GET")] [Route("/Items/Counts", "GET")]
[Api(Description = "Gets counts of various item types")] [Authenticated]
public class GetItemCounts : IReturn<ItemCounts> public class GetItemCounts : IReturn<ItemCounts>
{ {
[ApiMember(Name = "UserId", Description = "Optional. Get counts from a specific user's library.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] [ApiMember(Name = "UserId", Description = "Optional. Get counts from a specific user's library.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
@ -164,8 +164,8 @@ namespace MediaBrowser.Api.Library
public bool? IsFavorite { get; set; } public bool? IsFavorite { get; set; }
} }
[Route("/Items/{Id}/Ancestors", "GET")] [Route("/Items/{Id}/Ancestors", "GET", Summary = "Gets all parents of an item")]
[Api(Description = "Gets all parents of an item")] [Authenticated]
public class GetAncestors : IReturn<BaseItemDto[]> public class GetAncestors : IReturn<BaseItemDto[]>
{ {
/// <summary> /// <summary>
@ -183,8 +183,8 @@ namespace MediaBrowser.Api.Library
public string Id { get; set; } public string Id { get; set; }
} }
[Route("/Items/YearIndex", "GET")] [Route("/Items/YearIndex", "GET", Summary = "Gets a year index based on an item query.")]
[Api(Description = "Gets a year index based on an item query.")] [Authenticated]
public class GetYearIndex : IReturn<List<ItemIndex>> public class GetYearIndex : IReturn<List<ItemIndex>>
{ {
/// <summary> /// <summary>
@ -201,23 +201,23 @@ namespace MediaBrowser.Api.Library
/// <summary> /// <summary>
/// Class GetPhyscialPaths /// Class GetPhyscialPaths
/// </summary> /// </summary>
[Route("/Library/PhysicalPaths", "GET")] [Route("/Library/PhysicalPaths", "GET", Summary = "Gets a list of physical paths from virtual folders")]
[Api(Description = "Gets a list of physical paths from virtual folders")] [Authenticated(Roles = "Admin")]
public class GetPhyscialPaths : IReturn<List<string>> public class GetPhyscialPaths : IReturn<List<string>>
{ {
} }
[Route("/Library/MediaFolders", "GET")] [Route("/Library/MediaFolders", "GET", Summary = "Gets all user media folders.")]
[Api(Description = "Gets all user media folders.")] [Authenticated]
public class GetMediaFolders : IReturn<ItemsResult> public class GetMediaFolders : IReturn<ItemsResult>
{ {
[ApiMember(Name = "IsHidden", Description = "Optional. Filter by folders that are marked hidden, or not.", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")] [ApiMember(Name = "IsHidden", Description = "Optional. Filter by folders that are marked hidden, or not.", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
public bool? IsHidden { get; set; } public bool? IsHidden { get; set; }
} }
[Route("/Library/Series/Added", "POST")] [Route("/Library/Series/Added", "POST", Summary = "Reports that new episodes of a series have been added by an external source")]
[Route("/Library/Series/Updated", "POST")] [Route("/Library/Series/Updated", "POST", Summary = "Reports that new episodes of a series have been added by an external source")]
[Api(Description = "Reports that new episodes of a series have been added by an external source")] [Authenticated]
public class PostUpdatedSeries : IReturnVoid public class PostUpdatedSeries : IReturnVoid
{ {
[ApiMember(Name = "TvdbId", Description = "Tvdb Id", IsRequired = false, DataType = "string", ParameterType = "path", Verb = "GET")] [ApiMember(Name = "TvdbId", Description = "Tvdb Id", IsRequired = false, DataType = "string", ParameterType = "path", Verb = "GET")]
@ -227,7 +227,6 @@ namespace MediaBrowser.Api.Library
/// <summary> /// <summary>
/// Class LibraryService /// Class LibraryService
/// </summary> /// </summary>
[Authenticated]
public class LibraryService : BaseApiService public class LibraryService : BaseApiService
{ {
/// <summary> /// <summary>

@ -131,11 +131,11 @@ namespace MediaBrowser.Api.Library
/// <value><c>true</c> if [refresh library]; otherwise, <c>false</c>.</value> /// <value><c>true</c> if [refresh library]; otherwise, <c>false</c>.</value>
public bool RefreshLibrary { get; set; } public bool RefreshLibrary { get; set; }
} }
/// <summary> /// <summary>
/// Class LibraryStructureService /// Class LibraryStructureService
/// </summary> /// </summary>
[Authenticated] [Authenticated(Roles = "Admin", AllowBeforeStartupWizard = true)]
public class LibraryStructureService : BaseApiService public class LibraryStructureService : BaseApiService
{ {
/// <summary> /// <summary>
@ -164,7 +164,6 @@ namespace MediaBrowser.Api.Library
/// <param name="appPaths">The app paths.</param> /// <param name="appPaths">The app paths.</param>
/// <param name="userManager">The user manager.</param> /// <param name="userManager">The user manager.</param>
/// <param name="libraryManager">The library manager.</param> /// <param name="libraryManager">The library manager.</param>
/// <exception cref="System.ArgumentNullException">appPaths</exception>
public LibraryStructureService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager, ILibraryMonitor libraryMonitor, IFileSystem fileSystem, ILogger logger) public LibraryStructureService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager, ILibraryMonitor libraryMonitor, IFileSystem fileSystem, ILogger logger)
{ {
if (appPaths == null) if (appPaths == null)

@ -18,6 +18,7 @@ namespace MediaBrowser.Api.LiveTv
/// This is insecure right now to avoid windows phone refactoring /// This is insecure right now to avoid windows phone refactoring
/// </summary> /// </summary>
[Route("/LiveTv/Info", "GET", Summary = "Gets available live tv services.")] [Route("/LiveTv/Info", "GET", Summary = "Gets available live tv services.")]
[Authenticated]
public class GetLiveTvInfo : IReturn<LiveTvInfo> public class GetLiveTvInfo : IReturn<LiveTvInfo>
{ {
} }

@ -43,7 +43,7 @@ namespace MediaBrowser.Api
/// <summary> /// <summary>
/// Class CulturesService /// Class CulturesService
/// </summary> /// </summary>
[Authenticated] [Authenticated(AllowBeforeStartupWizard = true)]
public class LocalizationService : BaseApiService public class LocalizationService : BaseApiService
{ {
/// <summary> /// <summary>

@ -69,6 +69,7 @@
<Compile Include="..\SharedVersion.cs"> <Compile Include="..\SharedVersion.cs">
<Link>Properties\SharedVersion.cs</Link> <Link>Properties\SharedVersion.cs</Link>
</Compile> </Compile>
<Compile Include="AppThemeService.cs" />
<Compile Include="BrandingService.cs" /> <Compile Include="BrandingService.cs" />
<Compile Include="ChannelService.cs" /> <Compile Include="ChannelService.cs" />
<Compile Include="ConnectService.cs" /> <Compile Include="ConnectService.cs" />
@ -79,10 +80,10 @@
<Compile Include="Library\ChapterService.cs" /> <Compile Include="Library\ChapterService.cs" />
<Compile Include="Playback\Hls\MpegDashService.cs" /> <Compile Include="Playback\Hls\MpegDashService.cs" />
<Compile Include="PlaylistService.cs" /> <Compile Include="PlaylistService.cs" />
<Compile Include="StartupWizardService.cs" />
<Compile Include="Subtitles\SubtitleService.cs" /> <Compile Include="Subtitles\SubtitleService.cs" />
<Compile Include="Movies\CollectionService.cs" /> <Compile Include="Movies\CollectionService.cs" />
<Compile Include="Music\AlbumsService.cs" /> <Compile Include="Music\AlbumsService.cs" />
<Compile Include="AppThemeService.cs" />
<Compile Include="BaseApiService.cs" /> <Compile Include="BaseApiService.cs" />
<Compile Include="ConfigurationService.cs" /> <Compile Include="ConfigurationService.cs" />
<Compile Include="DisplayPreferencesService.cs" /> <Compile Include="DisplayPreferencesService.cs" />

@ -122,7 +122,7 @@ namespace MediaBrowser.Api
/// <summary> /// <summary>
/// Class PackageService /// Class PackageService
/// </summary> /// </summary>
[Authenticated] [Authenticated(Roles = "Admin")]
public class PackageService : BaseApiService public class PackageService : BaseApiService
{ {
private readonly IInstallationManager _installationManager; private readonly IInstallationManager _installationManager;

@ -6,7 +6,6 @@ using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Playlists; using MediaBrowser.Model.Playlists;
using MediaBrowser.Model.Querying; using MediaBrowser.Model.Querying;
using ServiceStack; using ServiceStack;
using System;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;

@ -20,6 +20,7 @@ namespace MediaBrowser.Api
/// Class Plugins /// Class Plugins
/// </summary> /// </summary>
[Route("/Plugins", "GET", Summary = "Gets a list of currently installed plugins")] [Route("/Plugins", "GET", Summary = "Gets a list of currently installed plugins")]
[Authenticated]
public class GetPlugins : IReturn<List<PluginInfo>> public class GetPlugins : IReturn<List<PluginInfo>>
{ {
} }
@ -28,6 +29,7 @@ namespace MediaBrowser.Api
/// Class UninstallPlugin /// Class UninstallPlugin
/// </summary> /// </summary>
[Route("/Plugins/{Id}", "DELETE", Summary = "Uninstalls a plugin")] [Route("/Plugins/{Id}", "DELETE", Summary = "Uninstalls a plugin")]
[Authenticated(Roles = "Admin")]
public class UninstallPlugin : IReturnVoid public class UninstallPlugin : IReturnVoid
{ {
/// <summary> /// <summary>
@ -42,6 +44,7 @@ namespace MediaBrowser.Api
/// Class GetPluginConfiguration /// Class GetPluginConfiguration
/// </summary> /// </summary>
[Route("/Plugins/{Id}/Configuration", "GET", Summary = "Gets a plugin's configuration")] [Route("/Plugins/{Id}/Configuration", "GET", Summary = "Gets a plugin's configuration")]
[Authenticated]
public class GetPluginConfiguration public class GetPluginConfiguration
{ {
/// <summary> /// <summary>
@ -56,6 +59,7 @@ namespace MediaBrowser.Api
/// Class UpdatePluginConfiguration /// Class UpdatePluginConfiguration
/// </summary> /// </summary>
[Route("/Plugins/{Id}/Configuration", "POST", Summary = "Updates a plugin's configuration")] [Route("/Plugins/{Id}/Configuration", "POST", Summary = "Updates a plugin's configuration")]
[Authenticated]
public class UpdatePluginConfiguration : IRequiresRequestStream, IReturnVoid public class UpdatePluginConfiguration : IRequiresRequestStream, IReturnVoid
{ {
/// <summary> /// <summary>
@ -76,6 +80,7 @@ namespace MediaBrowser.Api
/// Class GetPluginSecurityInfo /// Class GetPluginSecurityInfo
/// </summary> /// </summary>
[Route("/Plugins/SecurityInfo", "GET", Summary = "Gets plugin registration information")] [Route("/Plugins/SecurityInfo", "GET", Summary = "Gets plugin registration information")]
[Authenticated]
public class GetPluginSecurityInfo : IReturn<PluginSecurityInfo> public class GetPluginSecurityInfo : IReturn<PluginSecurityInfo>
{ {
} }
@ -84,11 +89,13 @@ namespace MediaBrowser.Api
/// Class UpdatePluginSecurityInfo /// Class UpdatePluginSecurityInfo
/// </summary> /// </summary>
[Route("/Plugins/SecurityInfo", "POST", Summary = "Updates plugin registration information")] [Route("/Plugins/SecurityInfo", "POST", Summary = "Updates plugin registration information")]
[Authenticated(Roles = "Admin")]
public class UpdatePluginSecurityInfo : PluginSecurityInfo, IReturnVoid public class UpdatePluginSecurityInfo : PluginSecurityInfo, IReturnVoid
{ {
} }
[Route("/Plugins/RegistrationRecords/{Name}", "GET", Summary = "Gets registration status for a feature")] [Route("/Plugins/RegistrationRecords/{Name}", "GET", Summary = "Gets registration status for a feature")]
[Authenticated]
public class GetRegistrationStatus public class GetRegistrationStatus
{ {
[ApiMember(Name = "Name", Description = "Feature Name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] [ApiMember(Name = "Name", Description = "Feature Name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
@ -97,11 +104,10 @@ namespace MediaBrowser.Api
[ApiMember(Name = "Mb2Equivalent", Description = "Optional. The equivalent feature name in MB2", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] [ApiMember(Name = "Mb2Equivalent", Description = "Optional. The equivalent feature name in MB2", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
public string Mb2Equivalent { get; set; } public string Mb2Equivalent { get; set; }
} }
/// <summary> /// <summary>
/// Class PluginsService /// Class PluginsService
/// </summary> /// </summary>
[Authenticated]
public class PluginService : BaseApiService public class PluginService : BaseApiService
{ {
/// <summary> /// <summary>
@ -118,14 +124,6 @@ namespace MediaBrowser.Api
private readonly IInstallationManager _installationManager; private readonly IInstallationManager _installationManager;
/// <summary>
/// Initializes a new instance of the <see cref="PluginService" /> class.
/// </summary>
/// <param name="jsonSerializer">The json serializer.</param>
/// <param name="appHost">The app host.</param>
/// <param name="securityManager">The security manager.</param>
/// <param name="installationManager">The installation manager.</param>
/// <exception cref="System.ArgumentNullException">jsonSerializer</exception>
public PluginService(IJsonSerializer jsonSerializer, IApplicationHost appHost, ISecurityManager securityManager, IInstallationManager installationManager) public PluginService(IJsonSerializer jsonSerializer, IApplicationHost appHost, ISecurityManager securityManager, IInstallationManager installationManager)
: base() : base()
{ {
@ -151,7 +149,7 @@ namespace MediaBrowser.Api
return ToOptimizedResult(result); return ToOptimizedResult(result);
} }
/// <summary> /// <summary>
/// Gets the specified request. /// Gets the specified request.
/// </summary> /// </summary>

@ -79,7 +79,7 @@ namespace MediaBrowser.Api.ScheduledTasks
/// <summary> /// <summary>
/// Class ScheduledTasksService /// Class ScheduledTasksService
/// </summary> /// </summary>
[Authenticated] [Authenticated(Roles = "Admin")]
public class ScheduledTaskService : BaseApiService public class ScheduledTaskService : BaseApiService
{ {
/// <summary> /// <summary>

@ -241,16 +241,19 @@ namespace MediaBrowser.Api.Session
} }
[Route("/Sessions/Logout", "POST", Summary = "Reports that a session has ended")] [Route("/Sessions/Logout", "POST", Summary = "Reports that a session has ended")]
[Authenticated]
public class ReportSessionEnded : IReturnVoid public class ReportSessionEnded : IReturnVoid
{ {
} }
[Route("/Auth/Keys", "GET")] [Route("/Auth/Keys", "GET")]
[Authenticated(Roles = "Admin")]
public class GetApiKeys public class GetApiKeys
{ {
} }
[Route("/Auth/Keys/{Key}", "DELETE")] [Route("/Auth/Keys/{Key}", "DELETE")]
[Authenticated(Roles = "Admin")]
public class RevokeKey public class RevokeKey
{ {
[ApiMember(Name = "Key", Description = "Auth Key", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] [ApiMember(Name = "Key", Description = "Auth Key", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
@ -258,6 +261,7 @@ namespace MediaBrowser.Api.Session
} }
[Route("/Auth/Keys", "POST")] [Route("/Auth/Keys", "POST")]
[Authenticated(Roles = "Admin")]
public class CreateKey public class CreateKey
{ {
[ApiMember(Name = "App", Description = "App", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")] [ApiMember(Name = "App", Description = "App", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]

@ -0,0 +1,163 @@
using MediaBrowser.Common.Configuration;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Connect;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Configuration;
using ServiceStack;
using System;
using System.Linq;
using System.Threading.Tasks;
namespace MediaBrowser.Api
{
[Route("/Startup/Complete", "POST", Summary = "Reports that the startup wizard has been completed")]
public class ReportStartupWizardComplete : IReturnVoid
{
}
[Route("/Startup/Info", "GET", Summary = "Gets initial server info")]
public class GetStartupInfo : IReturn<StartupInfo>
{
}
[Route("/Startup/Configuration", "GET", Summary = "Gets initial server configuration")]
public class GetStartupConfiguration : IReturn<StartupConfiguration>
{
}
[Route("/Startup/Configuration", "POST", Summary = "Updates initial server configuration")]
public class UpdateStartupConfiguration : StartupConfiguration, IReturnVoid
{
}
[Route("/Startup/User", "GET", Summary = "Gets initial user info")]
public class GetStartupUser : IReturn<StartupUser>
{
}
[Route("/Startup/User", "POST", Summary = "Updates initial user info")]
public class UpdateStartupUser : StartupUser, IReturn<UpdateStartupUserResult>
{
}
[Authenticated(AllowBeforeStartupWizard = true, Roles = "Admin")]
public class StartupWizardService : BaseApiService
{
private readonly IServerConfigurationManager _config;
private readonly IServerApplicationHost _appHost;
private readonly IUserManager _userManager;
private readonly IConnectManager _connectManager;
public StartupWizardService(IServerConfigurationManager config, IServerApplicationHost appHost, IUserManager userManager, IConnectManager connectManager)
{
_config = config;
_appHost = appHost;
_userManager = userManager;
_connectManager = connectManager;
}
public void Post(ReportStartupWizardComplete request)
{
_config.Configuration.IsStartupWizardCompleted = true;
_config.SaveConfiguration();
}
public object Get(GetStartupInfo request)
{
var info = _appHost.GetSystemInfo();
return new StartupInfo
{
SupportsRunningAsService = info.SupportsRunningAsService
};
}
public object Get(GetStartupConfiguration request)
{
return new StartupConfiguration
{
UICulture = _config.Configuration.UICulture,
EnableInternetProviders = _config.Configuration.EnableInternetProviders,
SaveLocalMeta = _config.Configuration.SaveLocalMeta,
MetadataCountryCode = _config.Configuration.MetadataCountryCode,
PreferredMetadataLanguage = _config.Configuration.PreferredMetadataLanguage
};
}
public void Post(UpdateStartupConfiguration request)
{
_config.Configuration.UICulture = request.UICulture;
_config.Configuration.EnableInternetProviders = request.EnableInternetProviders;
_config.Configuration.SaveLocalMeta = request.SaveLocalMeta;
_config.Configuration.MetadataCountryCode = request.MetadataCountryCode;
_config.Configuration.PreferredMetadataLanguage = request.PreferredMetadataLanguage;
_config.SaveConfiguration();
}
public object Get(GetStartupUser request)
{
var user = _userManager.Users.First();
return new StartupUser
{
Name = user.Name,
ConnectUserName = user.ConnectUserName
};
}
public async Task<object> Post(UpdateStartupUser request)
{
var user = _userManager.Users.First();
// TODO: This should be handled internally by xbmc metadata
const string metadataKey = "xbmcmetadata";
var metadata = _config.GetConfiguration<XbmcMetadataOptions>(metadataKey);
metadata.UserId = user.Id.ToString("N");
_config.SaveConfiguration(metadataKey, metadata);
user.Name = request.Name;
await _userManager.UpdateUser(user).ConfigureAwait(false);
var result = new UpdateStartupUserResult();
if (!string.IsNullOrWhiteSpace(user.ConnectUserName) &&
string.IsNullOrWhiteSpace(request.ConnectUserName))
{
await _connectManager.RemoveConnect(user.Id.ToString("N")).ConfigureAwait(false);
}
else if (!string.Equals(user.ConnectUserName, request.ConnectUserName, StringComparison.OrdinalIgnoreCase))
{
result.UserLinkResult = await _connectManager.LinkUser(user.Id.ToString("N"), request.ConnectUserName).ConfigureAwait(false);
}
return result;
}
}
public class StartupConfiguration
{
public string UICulture { get; set; }
public bool EnableInternetProviders { get; set; }
public bool SaveLocalMeta { get; set; }
public string MetadataCountryCode { get; set; }
public string PreferredMetadataLanguage { get; set; }
}
public class StartupInfo
{
public bool SupportsRunningAsService { get; set; }
}
public class StartupUser
{
public string Name { get; set; }
public string ConnectUserName { get; set; }
}
public class UpdateStartupUserResult
{
public UserLinkResult UserLinkResult { get; set; }
}
}

@ -19,7 +19,7 @@ using System.Threading.Tasks;
namespace MediaBrowser.Api.Subtitles namespace MediaBrowser.Api.Subtitles
{ {
[Route("/Videos/{Id}/Subtitles/{Index}", "DELETE", Summary = "Deletes an external subtitle file")] [Route("/Videos/{Id}/Subtitles/{Index}", "DELETE", Summary = "Deletes an external subtitle file")]
[Authenticated] [Authenticated(Roles = "Admin")]
public class DeleteSubtitle public class DeleteSubtitle
{ {
/// <summary> /// <summary>

@ -29,7 +29,7 @@ namespace MediaBrowser.Api.System
public string MinDate { get; set; } public string MinDate { get; set; }
} }
[Authenticated] [Authenticated(Roles = "Admin")]
public class ActivityLogService : BaseApiService public class ActivityLogService : BaseApiService
{ {
private readonly IActivityManager _activityManager; private readonly IActivityManager _activityManager;

@ -35,7 +35,7 @@ namespace MediaBrowser.Api.System
/// Class RestartApplication /// Class RestartApplication
/// </summary> /// </summary>
[Route("/System/Restart", "POST", Summary = "Restarts the application, if needed")] [Route("/System/Restart", "POST", Summary = "Restarts the application, if needed")]
[Authenticated] [Authenticated(Roles = "Admin")]
public class RestartApplication public class RestartApplication
{ {
} }
@ -51,7 +51,7 @@ namespace MediaBrowser.Api.System
} }
[Route("/System/Logs", "GET", Summary = "Gets a list of available server log files")] [Route("/System/Logs", "GET", Summary = "Gets a list of available server log files")]
[Authenticated] [Authenticated(Roles = "Admin")]
public class GetServerLogs : IReturn<List<LogFile>> public class GetServerLogs : IReturn<List<LogFile>>
{ {
} }
@ -64,6 +64,7 @@ namespace MediaBrowser.Api.System
} }
[Route("/System/Logs/Log", "GET", Summary = "Gets a log file")] [Route("/System/Logs/Log", "GET", Summary = "Gets a log file")]
[Authenticated(Roles = "Admin")]
public class GetLogFile public class GetLogFile
{ {
[ApiMember(Name = "Name", Description = "The log file name.", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] [ApiMember(Name = "Name", Description = "The log file name.", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]

@ -1,5 +1,4 @@
using MediaBrowser.Api.UserLibrary; using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Entities.TV;

@ -13,8 +13,7 @@ using System.Linq;
namespace MediaBrowser.Api.UserLibrary namespace MediaBrowser.Api.UserLibrary
{ {
[Route("/GameGenres", "GET")] [Route("/GameGenres", "GET", Summary = "Gets all Game genres from a given item, folder, or the entire library")]
[Api(Description = "Gets all Game genres from a given item, folder, or the entire library")]
public class GetGameGenres : GetItemsByName public class GetGameGenres : GetItemsByName
{ {
public GetGameGenres() public GetGameGenres()
@ -23,8 +22,7 @@ namespace MediaBrowser.Api.UserLibrary
} }
} }
[Route("/GameGenres/{Name}", "GET")] [Route("/GameGenres/{Name}", "GET", Summary = "Gets a Game genre, by name")]
[Api(Description = "Gets a Game genre, by name")]
public class GetGameGenre : IReturn<BaseItemDto> public class GetGameGenre : IReturn<BaseItemDto>
{ {
/// <summary> /// <summary>

@ -16,8 +16,7 @@ namespace MediaBrowser.Api.UserLibrary
/// <summary> /// <summary>
/// Class GetGenres /// Class GetGenres
/// </summary> /// </summary>
[Route("/Genres", "GET")] [Route("/Genres", "GET", Summary = "Gets all genres from a given item, folder, or the entire library")]
[Api(Description = "Gets all genres from a given item, folder, or the entire library")]
public class GetGenres : GetItemsByName public class GetGenres : GetItemsByName
{ {
} }
@ -25,8 +24,7 @@ namespace MediaBrowser.Api.UserLibrary
/// <summary> /// <summary>
/// Class GetGenre /// Class GetGenre
/// </summary> /// </summary>
[Route("/Genres/{Name}", "GET")] [Route("/Genres/{Name}", "GET", Summary = "Gets a genre, by name")]
[Api(Description = "Gets a genre, by name")]
public class GetGenre : IReturn<BaseItemDto> public class GetGenre : IReturn<BaseItemDto>
{ {
/// <summary> /// <summary>

@ -13,8 +13,7 @@ using System.Linq;
namespace MediaBrowser.Api.UserLibrary namespace MediaBrowser.Api.UserLibrary
{ {
[Route("/MusicGenres", "GET")] [Route("/MusicGenres", "GET", Summary = "Gets all music genres from a given item, folder, or the entire library")]
[Api(Description = "Gets all music genres from a given item, folder, or the entire library")]
public class GetMusicGenres : GetItemsByName public class GetMusicGenres : GetItemsByName
{ {
public GetMusicGenres() public GetMusicGenres()
@ -23,8 +22,7 @@ namespace MediaBrowser.Api.UserLibrary
} }
} }
[Route("/MusicGenres/{Name}", "GET")] [Route("/MusicGenres/{Name}", "GET", Summary = "Gets a music genre, by name")]
[Api(Description = "Gets a music genre, by name")]
public class GetMusicGenre : IReturn<BaseItemDto> public class GetMusicGenre : IReturn<BaseItemDto>
{ {
/// <summary> /// <summary>

@ -15,8 +15,7 @@ namespace MediaBrowser.Api.UserLibrary
/// <summary> /// <summary>
/// Class GetPersons /// Class GetPersons
/// </summary> /// </summary>
[Route("/Persons", "GET")] [Route("/Persons", "GET", Summary = "Gets all persons from a given item, folder, or the entire library")]
[Api(Description = "Gets all persons from a given item, folder, or the entire library")]
public class GetPersons : GetItemsByName public class GetPersons : GetItemsByName
{ {
/// <summary> /// <summary>
@ -30,8 +29,7 @@ namespace MediaBrowser.Api.UserLibrary
/// <summary> /// <summary>
/// Class GetPerson /// Class GetPerson
/// </summary> /// </summary>
[Route("/Persons/{Name}", "GET")] [Route("/Persons/{Name}", "GET", Summary = "Gets a person, by name")]
[Api(Description = "Gets a person, by name")]
public class GetPerson : IReturn<BaseItemDto> public class GetPerson : IReturn<BaseItemDto>
{ {
/// <summary> /// <summary>

@ -15,8 +15,7 @@ namespace MediaBrowser.Api.UserLibrary
/// <summary> /// <summary>
/// Class MarkPlayedItem /// Class MarkPlayedItem
/// </summary> /// </summary>
[Route("/Users/{UserId}/PlayedItems/{Id}", "POST")] [Route("/Users/{UserId}/PlayedItems/{Id}", "POST", Summary = "Marks an item as played")]
[Api(Description = "Marks an item as played")]
public class MarkPlayedItem : IReturn<UserItemDataDto> public class MarkPlayedItem : IReturn<UserItemDataDto>
{ {
/// <summary> /// <summary>
@ -40,8 +39,7 @@ namespace MediaBrowser.Api.UserLibrary
/// <summary> /// <summary>
/// Class MarkUnplayedItem /// Class MarkUnplayedItem
/// </summary> /// </summary>
[Route("/Users/{UserId}/PlayedItems/{Id}", "DELETE")] [Route("/Users/{UserId}/PlayedItems/{Id}", "DELETE", Summary = "Marks an item as unplayed")]
[Api(Description = "Marks an item as unplayed")]
public class MarkUnplayedItem : IReturn<UserItemDataDto> public class MarkUnplayedItem : IReturn<UserItemDataDto>
{ {
/// <summary> /// <summary>
@ -59,20 +57,17 @@ namespace MediaBrowser.Api.UserLibrary
public string Id { get; set; } public string Id { get; set; }
} }
[Route("/Sessions/Playing", "POST")] [Route("/Sessions/Playing", "POST", Summary = "Reports playback has started within a session")]
[Api(Description = "Reports playback has started within a session")]
public class ReportPlaybackStart : PlaybackStartInfo, IReturnVoid public class ReportPlaybackStart : PlaybackStartInfo, IReturnVoid
{ {
} }
[Route("/Sessions/Playing/Progress", "POST")] [Route("/Sessions/Playing/Progress", "POST", Summary = "Reports playback progress within a session")]
[Api(Description = "Reports playback progress within a session")]
public class ReportPlaybackProgress : PlaybackProgressInfo, IReturnVoid public class ReportPlaybackProgress : PlaybackProgressInfo, IReturnVoid
{ {
} }
[Route("/Sessions/Playing/Stopped", "POST")] [Route("/Sessions/Playing/Stopped", "POST", Summary = "Reports playback has stopped within a session")]
[Api(Description = "Reports playback has stopped within a session")]
public class ReportPlaybackStopped : PlaybackStopInfo, IReturnVoid public class ReportPlaybackStopped : PlaybackStopInfo, IReturnVoid
{ {
} }
@ -80,8 +75,7 @@ namespace MediaBrowser.Api.UserLibrary
/// <summary> /// <summary>
/// Class OnPlaybackStart /// Class OnPlaybackStart
/// </summary> /// </summary>
[Route("/Users/{UserId}/PlayingItems/{Id}", "POST")] [Route("/Users/{UserId}/PlayingItems/{Id}", "POST", Summary = "Reports that a user has begun playing an item")]
[Api(Description = "Reports that a user has begun playing an item")]
public class OnPlaybackStart : IReturnVoid public class OnPlaybackStart : IReturnVoid
{ {
/// <summary> /// <summary>
@ -125,8 +119,7 @@ namespace MediaBrowser.Api.UserLibrary
/// <summary> /// <summary>
/// Class OnPlaybackProgress /// Class OnPlaybackProgress
/// </summary> /// </summary>
[Route("/Users/{UserId}/PlayingItems/{Id}/Progress", "POST")] [Route("/Users/{UserId}/PlayingItems/{Id}/Progress", "POST", Summary = "Reports a user's playback progress")]
[Api(Description = "Reports a user's playback progress")]
public class OnPlaybackProgress : IReturnVoid public class OnPlaybackProgress : IReturnVoid
{ {
/// <summary> /// <summary>
@ -172,8 +165,7 @@ namespace MediaBrowser.Api.UserLibrary
/// <summary> /// <summary>
/// Class OnPlaybackStopped /// Class OnPlaybackStopped
/// </summary> /// </summary>
[Route("/Users/{UserId}/PlayingItems/{Id}", "DELETE")] [Route("/Users/{UserId}/PlayingItems/{Id}", "DELETE", Summary = "Reports that a user has stopped playing an item")]
[Api(Description = "Reports that a user has stopped playing an item")]
public class OnPlaybackStopped : IReturnVoid public class OnPlaybackStopped : IReturnVoid
{ {
/// <summary> /// <summary>

@ -1,6 +1,5 @@
using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Net;
@ -21,8 +20,7 @@ namespace MediaBrowser.Api.UserLibrary
/// <summary> /// <summary>
/// Class GetItem /// Class GetItem
/// </summary> /// </summary>
[Route("/Users/{UserId}/Items/{Id}", "GET")] [Route("/Users/{UserId}/Items/{Id}", "GET", Summary = "Gets an item from a user's library")]
[Api(Description = "Gets an item from a user's library")]
public class GetItem : IReturn<BaseItemDto> public class GetItem : IReturn<BaseItemDto>
{ {
/// <summary> /// <summary>
@ -57,8 +55,7 @@ namespace MediaBrowser.Api.UserLibrary
/// <summary> /// <summary>
/// Class GetItem /// Class GetItem
/// </summary> /// </summary>
[Route("/Users/{UserId}/Items/Root", "GET")] [Route("/Users/{UserId}/Items/Root", "GET", Summary = "Gets the root folder from a user's library")]
[Api(Description = "Gets the root folder from a user's library")]
public class GetRootFolder : IReturn<BaseItemDto> public class GetRootFolder : IReturn<BaseItemDto>
{ {
/// <summary> /// <summary>
@ -72,8 +69,7 @@ namespace MediaBrowser.Api.UserLibrary
/// <summary> /// <summary>
/// Class GetIntros /// Class GetIntros
/// </summary> /// </summary>
[Route("/Users/{UserId}/Items/{Id}/Intros", "GET")] [Route("/Users/{UserId}/Items/{Id}/Intros", "GET", Summary = "Gets intros to play before the main media item plays")]
[Api(("Gets intros to play before the main media item plays"))]
public class GetIntros : IReturn<ItemsResult> public class GetIntros : IReturn<ItemsResult>
{ {
/// <summary> /// <summary>
@ -94,8 +90,7 @@ namespace MediaBrowser.Api.UserLibrary
/// <summary> /// <summary>
/// Class MarkFavoriteItem /// Class MarkFavoriteItem
/// </summary> /// </summary>
[Route("/Users/{UserId}/FavoriteItems/{Id}", "POST")] [Route("/Users/{UserId}/FavoriteItems/{Id}", "POST", Summary = "Marks an item as a favorite")]
[Api(Description = "Marks an item as a favorite")]
public class MarkFavoriteItem : IReturn<UserItemDataDto> public class MarkFavoriteItem : IReturn<UserItemDataDto>
{ {
/// <summary> /// <summary>
@ -116,8 +111,7 @@ namespace MediaBrowser.Api.UserLibrary
/// <summary> /// <summary>
/// Class UnmarkFavoriteItem /// Class UnmarkFavoriteItem
/// </summary> /// </summary>
[Route("/Users/{UserId}/FavoriteItems/{Id}", "DELETE")] [Route("/Users/{UserId}/FavoriteItems/{Id}", "DELETE", Summary = "Unmarks an item as a favorite")]
[Api(Description = "Unmarks an item as a favorite")]
public class UnmarkFavoriteItem : IReturn<UserItemDataDto> public class UnmarkFavoriteItem : IReturn<UserItemDataDto>
{ {
/// <summary> /// <summary>
@ -138,8 +132,7 @@ namespace MediaBrowser.Api.UserLibrary
/// <summary> /// <summary>
/// Class ClearUserItemRating /// Class ClearUserItemRating
/// </summary> /// </summary>
[Route("/Users/{UserId}/Items/{Id}/Rating", "DELETE")] [Route("/Users/{UserId}/Items/{Id}/Rating", "DELETE", Summary = "Deletes a user's saved personal rating for an item")]
[Api(Description = "Deletes a user's saved personal rating for an item")]
public class DeleteUserItemRating : IReturn<UserItemDataDto> public class DeleteUserItemRating : IReturn<UserItemDataDto>
{ {
/// <summary> /// <summary>
@ -160,8 +153,7 @@ namespace MediaBrowser.Api.UserLibrary
/// <summary> /// <summary>
/// Class UpdateUserItemRating /// Class UpdateUserItemRating
/// </summary> /// </summary>
[Route("/Users/{UserId}/Items/{Id}/Rating", "POST")] [Route("/Users/{UserId}/Items/{Id}/Rating", "POST", Summary = "Updates a user's rating for an item")]
[Api(Description = "Updates a user's rating for an item")]
public class UpdateUserItemRating : IReturn<UserItemDataDto> public class UpdateUserItemRating : IReturn<UserItemDataDto>
{ {
/// <summary> /// <summary>
@ -189,8 +181,7 @@ namespace MediaBrowser.Api.UserLibrary
/// <summary> /// <summary>
/// Class GetLocalTrailers /// Class GetLocalTrailers
/// </summary> /// </summary>
[Route("/Users/{UserId}/Items/{Id}/LocalTrailers", "GET")] [Route("/Users/{UserId}/Items/{Id}/LocalTrailers", "GET", Summary = "Gets local trailers for an item")]
[Api(Description = "Gets local trailers for an item")]
public class GetLocalTrailers : IReturn<List<BaseItemDto>> public class GetLocalTrailers : IReturn<List<BaseItemDto>>
{ {
/// <summary> /// <summary>
@ -211,8 +202,7 @@ namespace MediaBrowser.Api.UserLibrary
/// <summary> /// <summary>
/// Class GetSpecialFeatures /// Class GetSpecialFeatures
/// </summary> /// </summary>
[Route("/Users/{UserId}/Items/{Id}/SpecialFeatures", "GET")] [Route("/Users/{UserId}/Items/{Id}/SpecialFeatures", "GET", Summary = "Gets special features for an item")]
[Api(Description = "Gets special features for an item")]
public class GetSpecialFeatures : IReturn<List<BaseItemDto>> public class GetSpecialFeatures : IReturn<List<BaseItemDto>>
{ {
/// <summary> /// <summary>
@ -280,15 +270,6 @@ namespace MediaBrowser.Api.UserLibrary
private readonly IDtoService _dtoService; private readonly IDtoService _dtoService;
private readonly IUserViewManager _userViewManager; private readonly IUserViewManager _userViewManager;
/// <summary>
/// Initializes a new instance of the <see cref="UserLibraryService" /> class.
/// </summary>
/// <param name="userManager">The user manager.</param>
/// <param name="libraryManager">The library manager.</param>
/// <param name="userDataRepository">The user data repository.</param>
/// <param name="dtoService">The dto service.</param>
/// <param name="userViewManager">The user view manager.</param>
/// <exception cref="System.ArgumentNullException">jsonSerializer</exception>
public UserLibraryService(IUserManager userManager, ILibraryManager libraryManager, IUserDataManager userDataRepository, IDtoService dtoService, IUserViewManager userViewManager) public UserLibraryService(IUserManager userManager, ILibraryManager libraryManager, IUserDataManager userDataRepository, IDtoService dtoService, IUserViewManager userViewManager)
{ {
_userManager = userManager; _userManager = userManager;

@ -12,7 +12,6 @@ using ServiceStack;
using ServiceStack.Text.Controller; using ServiceStack.Text.Controller;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -59,7 +58,7 @@ namespace MediaBrowser.Api
/// Class DeleteUser /// Class DeleteUser
/// </summary> /// </summary>
[Route("/Users/{Id}", "DELETE", Summary = "Deletes a user")] [Route("/Users/{Id}", "DELETE", Summary = "Deletes a user")]
[Authenticated] [Authenticated(Roles = "Admin")]
public class DeleteUser : IReturnVoid public class DeleteUser : IReturnVoid
{ {
/// <summary> /// <summary>
@ -151,25 +150,16 @@ namespace MediaBrowser.Api
/// Class UpdateUser /// Class UpdateUser
/// </summary> /// </summary>
[Route("/Users/{Id}", "POST", Summary = "Updates a user")] [Route("/Users/{Id}", "POST", Summary = "Updates a user")]
[Authenticated] [Authenticated(Roles = "Admin")]
public class UpdateUser : UserDto, IReturnVoid public class UpdateUser : UserDto, IReturnVoid
{ {
} }
/// <summary>
/// Class CreateUser
/// </summary>
[Route("/Users", "POST", Summary = "Creates a user")]
[Authenticated]
public class CreateUser : UserDto, IReturn<UserDto>
{
}
/// <summary> /// <summary>
/// Class CreateUser /// Class CreateUser
/// </summary> /// </summary>
[Route("/Users/New", "POST", Summary = "Creates a user")] [Route("/Users/New", "POST", Summary = "Creates a user")]
[Authenticated] [Authenticated(Roles = "Admin")]
public class CreateUserByName : IReturn<UserDto> public class CreateUserByName : IReturn<UserDto>
{ {
[ApiMember(Name = "Name", IsRequired = true, DataType = "string", ParameterType = "body", Verb = "POST")] [ApiMember(Name = "Name", IsRequired = true, DataType = "string", ParameterType = "body", Verb = "POST")]
@ -473,24 +463,6 @@ namespace MediaBrowser.Api
user.UpdateConfiguration(dtoUser.Configuration); user.UpdateConfiguration(dtoUser.Configuration);
} }
/// <summary>
/// Posts the specified request.
/// </summary>
/// <param name="request">The request.</param>
/// <returns>System.Object.</returns>
public object Post(CreateUser request)
{
var dtoUser = request;
var newUser = _userManager.CreateUser(dtoUser.Name).Result;
newUser.UpdateConfiguration(dtoUser.Configuration);
var result = _userManager.GetUserDto(newUser, Request.RemoteIp);
return ToOptimizedResult(result);
}
/// <summary> /// <summary>
/// Posts the specified request. /// Posts the specified request.
/// </summary> /// </summary>

@ -15,6 +15,7 @@ using System.Threading.Tasks;
namespace MediaBrowser.Api namespace MediaBrowser.Api
{ {
[Route("/Videos/{Id}/AdditionalParts", "GET", Summary = "Gets additional parts for a video.")] [Route("/Videos/{Id}/AdditionalParts", "GET", Summary = "Gets additional parts for a video.")]
[Authenticated]
public class GetAdditionalParts : IReturn<ItemsResult> public class GetAdditionalParts : IReturn<ItemsResult>
{ {
[ApiMember(Name = "UserId", Description = "Optional. Filter by user id, and attach user data", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] [ApiMember(Name = "UserId", Description = "Optional. Filter by user id, and attach user data", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
@ -29,6 +30,7 @@ namespace MediaBrowser.Api
} }
[Route("/Videos/{Id}/AlternateSources", "DELETE", Summary = "Removes alternate video sources.")] [Route("/Videos/{Id}/AlternateSources", "DELETE", Summary = "Removes alternate video sources.")]
[Authenticated(Roles = "Admin")]
public class DeleteAlternateSources : IReturnVoid public class DeleteAlternateSources : IReturnVoid
{ {
[ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")] [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
@ -36,13 +38,13 @@ namespace MediaBrowser.Api
} }
[Route("/Videos/MergeVersions", "POST", Summary = "Merges videos into a single record")] [Route("/Videos/MergeVersions", "POST", Summary = "Merges videos into a single record")]
[Authenticated(Roles = "Admin")]
public class MergeVersions : IReturnVoid public class MergeVersions : IReturnVoid
{ {
[ApiMember(Name = "Ids", Description = "Item id list. This allows multiple, comma delimited.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST", AllowMultiple = true)] [ApiMember(Name = "Ids", Description = "Item id list. This allows multiple, comma delimited.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST", AllowMultiple = true)]
public string Ids { get; set; } public string Ids { get; set; }
} }
[Authenticated]
public class VideosService : BaseApiService public class VideosService : BaseApiService
{ {
private readonly ILibraryManager _libraryManager; private readonly ILibraryManager _libraryManager;

@ -1618,7 +1618,7 @@ namespace MediaBrowser.Controller.Entities
var parent = user.RootFolder; var parent = user.RootFolder;
list.Add(await GetUserView(SpecialFolder.LiveTvNowPlaying, user, "0", parent).ConfigureAwait(false)); //list.Add(await GetUserView(SpecialFolder.LiveTvNowPlaying, user, "0", parent).ConfigureAwait(false));
list.Add(await GetUserView(SpecialFolder.LiveTvChannels, user, string.Empty, parent).ConfigureAwait(false)); list.Add(await GetUserView(SpecialFolder.LiveTvChannels, user, string.Empty, parent).ConfigureAwait(false));
list.Add(await GetUserView(SpecialFolder.LiveTvRecordingGroups, user, string.Empty, parent).ConfigureAwait(false)); list.Add(await GetUserView(SpecialFolder.LiveTvRecordingGroups, user, string.Empty, parent).ConfigureAwait(false));

@ -220,8 +220,11 @@
<Compile Include="Net\IHttpResultFactory.cs" /> <Compile Include="Net\IHttpResultFactory.cs" />
<Compile Include="Net\IHttpServer.cs" /> <Compile Include="Net\IHttpServer.cs" />
<Compile Include="Net\IRestfulService.cs" /> <Compile Include="Net\IRestfulService.cs" />
<Compile Include="Net\IServiceRequest.cs" />
<Compile Include="Net\ISessionContext.cs" /> <Compile Include="Net\ISessionContext.cs" />
<Compile Include="Net\LoggedAttribute.cs" /> <Compile Include="Net\LoggedAttribute.cs" />
<Compile Include="Net\SecurityException.cs" />
<Compile Include="Net\ServiceStackServiceRequest.cs" />
<Compile Include="Net\StaticResultOptions.cs" /> <Compile Include="Net\StaticResultOptions.cs" />
<Compile Include="News\INewsService.cs" /> <Compile Include="News\INewsService.cs" />
<Compile Include="Notifications\INotificationManager.cs" /> <Compile Include="Notifications\INotificationManager.cs" />

@ -5,7 +5,7 @@ using System.Linq;
namespace MediaBrowser.Controller.Net namespace MediaBrowser.Controller.Net
{ {
public class AuthenticatedAttribute : Attribute, IHasRequestFilter, IAuthenticated public class AuthenticatedAttribute : Attribute, IHasRequestFilter, IAuthenticationAttributes
{ {
public IAuthService AuthService { get; set; } public IAuthService AuthService { get; set; }
@ -21,6 +21,12 @@ namespace MediaBrowser.Controller.Net
/// <value><c>true</c> if [escape parental control]; otherwise, <c>false</c>.</value> /// <value><c>true</c> if [escape parental control]; otherwise, <c>false</c>.</value>
public bool EscapeParentalControl { get; set; } public bool EscapeParentalControl { get; set; }
/// <summary>
/// Gets or sets a value indicating whether [allow before startup wizard].
/// </summary>
/// <value><c>true</c> if [allow before startup wizard]; otherwise, <c>false</c>.</value>
public bool AllowBeforeStartupWizard { get; set; }
/// <summary> /// <summary>
/// The request filter is executed before the service. /// The request filter is executed before the service.
/// </summary> /// </summary>
@ -29,7 +35,9 @@ namespace MediaBrowser.Controller.Net
/// <param name="requestDto">The request DTO</param> /// <param name="requestDto">The request DTO</param>
public void RequestFilter(IRequest request, IResponse response, object requestDto) public void RequestFilter(IRequest request, IResponse response, object requestDto)
{ {
AuthService.Authenticate(request, response, requestDto, this); var serviceRequest = new ServiceStackServiceRequest(request);
AuthService.Authenticate(serviceRequest, this);
} }
/// <summary> /// <summary>
@ -60,9 +68,10 @@ namespace MediaBrowser.Controller.Net
} }
} }
public interface IAuthenticated public interface IAuthenticationAttributes
{ {
bool EscapeParentalControl { get; } bool EscapeParentalControl { get; }
bool AllowBeforeStartupWizard { get; }
IEnumerable<string> GetRoles(); IEnumerable<string> GetRoles();
} }

@ -1,12 +1,9 @@
using ServiceStack.Web; 
namespace MediaBrowser.Controller.Net namespace MediaBrowser.Controller.Net
{ {
public interface IAuthService public interface IAuthService
{ {
void Authenticate(IRequest request, void Authenticate(IServiceRequest request,
IResponse response, IAuthenticationAttributes authAttribtues);
object requestDto,
IAuthenticated authAttribtues);
} }
} }

@ -1,5 +1,4 @@
using ServiceStack.Web; 
namespace MediaBrowser.Controller.Net namespace MediaBrowser.Controller.Net
{ {
public interface IAuthorizationContext public interface IAuthorizationContext
@ -9,6 +8,13 @@ namespace MediaBrowser.Controller.Net
/// </summary> /// </summary>
/// <param name="requestContext">The request context.</param> /// <param name="requestContext">The request context.</param>
/// <returns>AuthorizationInfo.</returns> /// <returns>AuthorizationInfo.</returns>
AuthorizationInfo GetAuthorizationInfo(IRequest requestContext); AuthorizationInfo GetAuthorizationInfo(object requestContext);
/// <summary>
/// Gets the authorization information.
/// </summary>
/// <param name="requestContext">The request context.</param>
/// <returns>AuthorizationInfo.</returns>
AuthorizationInfo GetAuthorizationInfo(IServiceRequest requestContext);
} }
} }

@ -0,0 +1,15 @@
using System.Collections.Generic;
using System.Collections.Specialized;
namespace MediaBrowser.Controller.Net
{
public interface IServiceRequest
{
object OriginalRequest { get; }
string RemoteIp { get; }
NameValueCollection Headers { get; }
NameValueCollection QueryString { get; }
IDictionary<string,object> Items { get; }
void AddResponseHeader(string name, string value);
}
}

@ -1,13 +1,14 @@
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Session; using MediaBrowser.Controller.Session;
using ServiceStack.Web;
namespace MediaBrowser.Controller.Net namespace MediaBrowser.Controller.Net
{ {
public interface ISessionContext public interface ISessionContext
{ {
SessionInfo GetSession(IRequest requestContext); SessionInfo GetSession(object requestContext);
User GetUser(object requestContext);
User GetUser(IRequest requestContext);
SessionInfo GetSession(IServiceRequest requestContext);
User GetUser(IServiceRequest requestContext);
} }
} }

@ -22,8 +22,10 @@ namespace MediaBrowser.Controller.Net
/// <param name="requestDto">The request DTO</param> /// <param name="requestDto">The request DTO</param>
public void RequestFilter(IRequest request, IResponse response, object requestDto) public void RequestFilter(IRequest request, IResponse response, object requestDto)
{ {
var serviceRequest = new ServiceStackServiceRequest(request);
//This code is executed before the service //This code is executed before the service
var auth = AuthorizationContext.GetAuthorizationInfo(request); var auth = AuthorizationContext.GetAuthorizationInfo(serviceRequest);
if (auth != null) if (auth != null)
{ {

@ -0,0 +1,21 @@
using System;
namespace MediaBrowser.Controller.Net
{
public class SecurityException : Exception
{
public SecurityException(string message)
: base(message)
{
}
public SecurityExceptionType SecurityExceptionType { get; set; }
}
public enum SecurityExceptionType
{
Unauthenticated = 0,
ParentalControl = 1
}
}

@ -0,0 +1,62 @@
using ServiceStack.Web;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
namespace MediaBrowser.Controller.Net
{
public class ServiceStackServiceRequest : IServiceRequest
{
private readonly IRequest _request;
public ServiceStackServiceRequest(IRequest request)
{
_request = request;
}
public object OriginalRequest
{
get { return _request; }
}
public string RemoteIp
{
get { return _request.RemoteIp; }
}
private NameValueCollection _headers;
public NameValueCollection Headers
{
get { return _headers ?? (_headers = Get(_request.Headers)); }
}
private NameValueCollection _query;
public NameValueCollection QueryString
{
get { return _query ?? (_query = Get(_request.QueryString)); }
}
private NameValueCollection Get(INameValueCollection coll)
{
var nv = new NameValueCollection(StringComparer.OrdinalIgnoreCase);
foreach (var key in coll.AllKeys)
{
nv[key] = coll[key];
}
return nv;
//return coll.ToNameValueCollection();
}
public IDictionary<string, object> Items
{
get { return _request.Items; }
}
public void AddResponseHeader(string name, string value)
{
_request.Response.AddHeader(name, value);
}
}
}

@ -255,12 +255,6 @@ namespace MediaBrowser.Controller.Session
/// <returns>SessionInfo.</returns> /// <returns>SessionInfo.</returns>
SessionInfo GetSession(string deviceId, string client, string version); SessionInfo GetSession(string deviceId, string client, string version);
/// <summary>
/// Validates the security token.
/// </summary>
/// <param name="accessToken">The access token.</param>
void ValidateSecurityToken(string accessToken);
/// <summary> /// <summary>
/// Logouts the specified access token. /// Logouts the specified access token.
/// </summary> /// </summary>

@ -170,7 +170,7 @@ namespace MediaBrowser.Model.Configuration
public PeopleMetadataOptions PeopleMetadataOptions { get; set; } public PeopleMetadataOptions PeopleMetadataOptions { get; set; }
public bool FindInternetTrailers { get; set; } public bool FindInternetTrailers { get; set; }
public string[] InsecureApps6 { get; set; } public string[] InsecureApps7 { get; set; }
public bool SaveMetadataHidden { get; set; } public bool SaveMetadataHidden { get; set; }
@ -222,19 +222,16 @@ namespace MediaBrowser.Model.Configuration
PeopleMetadataOptions = new PeopleMetadataOptions(); PeopleMetadataOptions = new PeopleMetadataOptions();
InsecureApps6 = new[] InsecureApps7 = new[]
{ {
"Roku",
"Chromecast", "Chromecast",
"iOS", "iOS",
"Windows Phone",
"Windows RT",
"Xbmc",
"Unknown app", "Unknown app",
"MediaPortal", "MediaPortal",
"Media Portal", "Media Portal",
"iPad", "iPad",
"iPhone" "iPhone",
"Roku"
}; };
MetadataOptions = new[] MetadataOptions = new[]

@ -91,7 +91,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer
{typeof (ResourceNotFoundException), 404}, {typeof (ResourceNotFoundException), 404},
{typeof (FileNotFoundException), 404}, {typeof (FileNotFoundException), 404},
{typeof (DirectoryNotFoundException), 404}, {typeof (DirectoryNotFoundException), 404},
{typeof (Implementations.Security.AuthenticationException), 401}, {typeof (SecurityException), 401},
{typeof (UnauthorizedAccessException), 401} {typeof (UnauthorizedAccessException), 401}
}; };

@ -1,13 +1,11 @@
using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Connect; using MediaBrowser.Controller.Connect;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Session; using MediaBrowser.Controller.Security;
using ServiceStack;
using ServiceStack.Auth;
using ServiceStack.Web;
using System; using System;
using System.Collections.Specialized; using System.Collections.Generic;
using System.Linq; using System.Linq;
namespace MediaBrowser.Server.Implementations.HttpServer.Security namespace MediaBrowser.Server.Implementations.HttpServer.Security
@ -16,61 +14,43 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security
{ {
private readonly IServerConfigurationManager _config; private readonly IServerConfigurationManager _config;
public AuthService(IUserManager userManager, ISessionManager sessionManager, IAuthorizationContext authorizationContext, IServerConfigurationManager config, IConnectManager connectManager) public AuthService(IUserManager userManager, IAuthorizationContext authorizationContext, IServerConfigurationManager config, IConnectManager connectManager)
{ {
AuthorizationContext = authorizationContext; AuthorizationContext = authorizationContext;
_config = config; _config = config;
ConnectManager = connectManager; ConnectManager = connectManager;
SessionManager = sessionManager;
UserManager = userManager; UserManager = userManager;
} }
public IUserManager UserManager { get; private set; } public IUserManager UserManager { get; private set; }
public ISessionManager SessionManager { get; private set; }
public IAuthorizationContext AuthorizationContext { get; private set; } public IAuthorizationContext AuthorizationContext { get; private set; }
public IConnectManager ConnectManager { get; private set; } public IConnectManager ConnectManager { get; private set; }
/// <summary>
/// Restrict authentication to a specific <see cref="IAuthProvider"/>.
/// For example, if this attribute should only permit access
/// if the user is authenticated with <see cref="BasicAuthProvider"/>,
/// you should set this property to <see cref="BasicAuthProvider.Name"/>.
/// </summary>
public string Provider { get; set; }
/// <summary> /// <summary>
/// Redirect the client to a specific URL if authentication failed. /// Redirect the client to a specific URL if authentication failed.
/// If this property is null, simply `401 Unauthorized` is returned. /// If this property is null, simply `401 Unauthorized` is returned.
/// </summary> /// </summary>
public string HtmlRedirect { get; set; } public string HtmlRedirect { get; set; }
public void Authenticate(IRequest request, public void Authenticate(IServiceRequest request,
IResponse response, IAuthenticationAttributes authAttribtues)
object requestDto,
IAuthenticated authAttribtues)
{ {
if (HostContext.HasValidAuthSecret(request)) ValidateUser(request, authAttribtues);
return;
//ExecuteBasic(req, res, requestDto); //first check if session is authenticated
//if (res.IsClosed) return; //AuthenticateAttribute already closed the request (ie auth failed)
ValidateUser(request, response, authAttribtues);
} }
private void ValidateUser(IRequest req, IResponse response, IAuthenticated authAttribtues) private void ValidateUser(IServiceRequest request,
IAuthenticationAttributes authAttribtues)
{ {
// This code is executed before the service // This code is executed before the service
var auth = AuthorizationContext.GetAuthorizationInfo(req); var auth = AuthorizationContext.GetAuthorizationInfo(request);
if (!string.IsNullOrWhiteSpace(auth.Token) || if (!IsExemptFromAuthenticationToken(auth, authAttribtues))
!_config.Configuration.InsecureApps6.Contains(auth.Client ?? string.Empty, StringComparer.OrdinalIgnoreCase))
{ {
var valid = IsValidConnectKey(auth.Token); var valid = IsValidConnectKey(auth.Token);
if (!valid) if (!valid)
{ {
SessionManager.ValidateSecurityToken(auth.Token); ValidateSecurityToken(request, auth.Token);
} }
} }
@ -80,45 +60,83 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security
if (user == null & !string.IsNullOrWhiteSpace(auth.UserId)) if (user == null & !string.IsNullOrWhiteSpace(auth.UserId))
{ {
throw new ArgumentException("User with Id " + auth.UserId + " not found"); throw new SecurityException("User with Id " + auth.UserId + " not found");
} }
if (user != null) if (user != null)
{ {
if (user.Configuration.IsDisabled) if (user.Configuration.IsDisabled)
{ {
throw new AuthenticationException("User account has been disabled."); throw new SecurityException("User account has been disabled.")
{
SecurityExceptionType = SecurityExceptionType.Unauthenticated
};
} }
if (!user.Configuration.IsAdministrator && if (!user.Configuration.IsAdministrator &&
!authAttribtues.EscapeParentalControl && !authAttribtues.EscapeParentalControl &&
!user.IsParentalScheduleAllowed()) !user.IsParentalScheduleAllowed())
{ {
response.AddHeader("X-Application-Error-Code", "ParentalControl"); request.AddResponseHeader("X-Application-Error-Code", "ParentalControl");
throw new AuthenticationException("This user account is not allowed access at this time."); throw new SecurityException("This user account is not allowed access at this time.")
{
SecurityExceptionType = SecurityExceptionType.ParentalControl
};
} }
} }
var roles = authAttribtues.GetRoles().ToList(); if (!IsExemptFromRoles(auth, authAttribtues))
{
var roles = authAttribtues.GetRoles().ToList();
ValidateRoles(roles, user);
}
}
private bool IsExemptFromAuthenticationToken(AuthorizationInfo auth, IAuthenticationAttributes authAttribtues)
{
if (!_config.Configuration.IsStartupWizardCompleted &&
authAttribtues.AllowBeforeStartupWizard)
{
return true;
}
return _config.Configuration.InsecureApps7.Contains(auth.Client ?? string.Empty,
StringComparer.OrdinalIgnoreCase);
}
private bool IsExemptFromRoles(AuthorizationInfo auth, IAuthenticationAttributes authAttribtues)
{
if (!_config.Configuration.IsStartupWizardCompleted &&
authAttribtues.AllowBeforeStartupWizard)
{
return true;
}
return false;
}
private void ValidateRoles(List<string> roles, User user)
{
if (roles.Contains("admin", StringComparer.OrdinalIgnoreCase)) if (roles.Contains("admin", StringComparer.OrdinalIgnoreCase))
{ {
if (user == null || !user.Configuration.IsAdministrator) if (user == null || !user.Configuration.IsAdministrator)
{ {
throw new ArgumentException("Administrative access is required for this request."); throw new SecurityException("User does not have admin access.")
{
SecurityExceptionType = SecurityExceptionType.Unauthenticated
};
} }
} }
if (roles.Contains("delete", StringComparer.OrdinalIgnoreCase))
if (!string.IsNullOrWhiteSpace(auth.DeviceId) &&
!string.IsNullOrWhiteSpace(auth.Client) &&
!string.IsNullOrWhiteSpace(auth.Device))
{ {
SessionManager.LogSessionActivity(auth.Client, if (user == null || !user.Configuration.EnableContentDeletion)
auth.Version, {
auth.DeviceId, throw new SecurityException("User does not have delete access.")
auth.Device, {
req.RemoteIp, SecurityExceptionType = SecurityExceptionType.Unauthenticated
user); };
}
} }
} }
@ -132,40 +150,34 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security
return ConnectManager.IsAuthorizationTokenValid(token); return ConnectManager.IsAuthorizationTokenValid(token);
} }
protected bool DoHtmlRedirectIfConfigured(IRequest req, IResponse res, bool includeRedirectParam = false) private void ValidateSecurityToken(IServiceRequest request, string token)
{ {
var htmlRedirect = this.HtmlRedirect ?? AuthenticateService.HtmlRedirect; if (string.IsNullOrWhiteSpace(token))
if (htmlRedirect != null && req.ResponseContentType.MatchesContentType(MimeTypes.Html))
{ {
DoHtmlRedirect(htmlRedirect, req, res, includeRedirectParam); throw new SecurityException("Access token is invalid or expired.");
return true;
} }
return false;
}
public static void DoHtmlRedirect(string redirectUrl, IRequest req, IResponse res, bool includeRedirectParam) var info = (AuthenticationInfo)request.Items["OriginalAuthenticationInfo"];
{
var url = req.ResolveAbsoluteUrl(redirectUrl); if (info == null)
if (includeRedirectParam)
{ {
var absoluteRequestPath = req.ResolveAbsoluteUrl("~" + req.PathInfo + ToQueryString(req.QueryString)); throw new SecurityException("Access token is invalid or expired.");
url = url.AddQueryParam(HostContext.ResolveLocalizedString(LocalizedStrings.Redirect), absoluteRequestPath);
} }
res.RedirectToUrl(url); if (!info.IsActive)
} {
throw new SecurityException("Access token has expired.");
private static string ToQueryString(INameValueCollection queryStringCollection) }
{
return ToQueryString((NameValueCollection)queryStringCollection.Original);
}
private static string ToQueryString(NameValueCollection queryStringCollection) //if (!string.IsNullOrWhiteSpace(info.UserId))
{ //{
if (queryStringCollection == null || queryStringCollection.Count == 0) // var user = _userManager.GetUserById(info.UserId);
return String.Empty;
return "?" + queryStringCollection.ToFormUrlEncoded(); // if (user == null || user.Configuration.IsDisabled)
// {
// throw new SecurityException("User account has been disabled.");
// }
//}
} }
} }
} }

@ -1,14 +1,35 @@
using System; using MediaBrowser.Controller.Net;
using System.Collections.Generic; using MediaBrowser.Controller.Security;
using MediaBrowser.Controller.Net;
using ServiceStack.Web; using ServiceStack.Web;
using System;
using System.Collections.Generic;
using System.Linq;
namespace MediaBrowser.Server.Implementations.HttpServer.Security namespace MediaBrowser.Server.Implementations.HttpServer.Security
{ {
public class AuthorizationContext : IAuthorizationContext public class AuthorizationContext : IAuthorizationContext
{ {
public AuthorizationInfo GetAuthorizationInfo(IRequest requestContext) private readonly IAuthenticationRepository _authRepo;
public AuthorizationContext(IAuthenticationRepository authRepo)
{
_authRepo = authRepo;
}
public AuthorizationInfo GetAuthorizationInfo(object requestContext)
{ {
var req = new ServiceStackServiceRequest((IRequest)requestContext);
return GetAuthorizationInfo(req);
}
public AuthorizationInfo GetAuthorizationInfo(IServiceRequest requestContext)
{
object cached;
if (requestContext.Items.TryGetValue("AuthorizationInfo", out cached))
{
return (AuthorizationInfo)cached;
}
return GetAuthorization(requestContext); return GetAuthorization(requestContext);
} }
@ -17,7 +38,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security
/// </summary> /// </summary>
/// <param name="httpReq">The HTTP req.</param> /// <param name="httpReq">The HTTP req.</param>
/// <returns>Dictionary{System.StringSystem.String}.</returns> /// <returns>Dictionary{System.StringSystem.String}.</returns>
private AuthorizationInfo GetAuthorization(IRequest httpReq) private AuthorizationInfo GetAuthorization(IServiceRequest httpReq)
{ {
var auth = GetAuthorizationDictionary(httpReq); var auth = GetAuthorizationDictionary(httpReq);
@ -29,7 +50,9 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security
if (auth != null) if (auth != null)
{ {
// TODO: Remove this
auth.TryGetValue("UserId", out userId); auth.TryGetValue("UserId", out userId);
auth.TryGetValue("DeviceId", out deviceId); auth.TryGetValue("DeviceId", out deviceId);
auth.TryGetValue("Device", out device); auth.TryGetValue("Device", out device);
auth.TryGetValue("Client", out client); auth.TryGetValue("Client", out client);
@ -84,7 +107,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security
} }
} }
return new AuthorizationInfo var info = new AuthorizationInfo
{ {
Client = client, Client = client,
Device = device, Device = device,
@ -93,6 +116,26 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security
Version = version, Version = version,
Token = token Token = token
}; };
if (!string.IsNullOrWhiteSpace(token))
{
var result = _authRepo.Get(new AuthenticationInfoQuery
{
AccessToken = token
});
var tokenInfo = result.Items.FirstOrDefault();
if (tokenInfo != null)
{
info.UserId = tokenInfo.UserId;
}
httpReq.Items["OriginalAuthenticationInfo"] = tokenInfo;
}
httpReq.Items["AuthorizationInfo"] = info;
return info;
} }
/// <summary> /// <summary>
@ -100,7 +143,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security
/// </summary> /// </summary>
/// <param name="httpReq">The HTTP req.</param> /// <param name="httpReq">The HTTP req.</param>
/// <returns>Dictionary{System.StringSystem.String}.</returns> /// <returns>Dictionary{System.StringSystem.String}.</returns>
private Dictionary<string, string> GetAuthorizationDictionary(IRequest httpReq) private Dictionary<string, string> GetAuthorizationDictionary(IServiceRequest httpReq)
{ {
var auth = httpReq.Headers["Authorization"]; var auth = httpReq.Headers["Authorization"];

@ -19,18 +19,30 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security
_sessionManager = sessionManager; _sessionManager = sessionManager;
} }
public SessionInfo GetSession(IRequest requestContext) public SessionInfo GetSession(IServiceRequest requestContext)
{ {
var authorization = _authContext.GetAuthorizationInfo(requestContext); var authorization = _authContext.GetAuthorizationInfo(requestContext);
return _sessionManager.GetSession(authorization.DeviceId, authorization.Client, authorization.Version); return _sessionManager.GetSession(authorization.DeviceId, authorization.Client, authorization.Version);
} }
public User GetUser(IRequest requestContext) public User GetUser(IServiceRequest requestContext)
{ {
var session = GetSession(requestContext); var session = GetSession(requestContext);
return session == null || !session.UserId.HasValue ? null : _userManager.GetUserById(session.UserId.Value); return session == null || !session.UserId.HasValue ? null : _userManager.GetUserById(session.UserId.Value);
} }
public SessionInfo GetSession(object requestContext)
{
var req = new ServiceStackServiceRequest((IRequest)requestContext);
return GetSession(req);
}
public User GetUser(object requestContext)
{
var req = new ServiceStackServiceRequest((IRequest)requestContext);
return GetUser(req);
}
} }
} }

@ -8,6 +8,7 @@ using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Configuration;
@ -180,12 +181,12 @@ namespace MediaBrowser.Server.Implementations.Library
if (user == null) if (user == null)
{ {
throw new AuthenticationException("Invalid username or password entered."); throw new SecurityException("Invalid username or password entered.");
} }
if (user.Configuration.IsDisabled) if (user.Configuration.IsDisabled)
{ {
throw new AuthenticationException(string.Format("The {0} account is currently disabled. Please consult with your administrator.", user.Name)); throw new SecurityException(string.Format("The {0} account is currently disabled. Please consult with your administrator.", user.Name));
} }
var success = false; var success = false;

@ -247,7 +247,6 @@
<Compile Include="ScheduledTasks\RefreshIntrosTask.cs" /> <Compile Include="ScheduledTasks\RefreshIntrosTask.cs" />
<Compile Include="ScheduledTasks\RefreshMediaLibraryTask.cs" /> <Compile Include="ScheduledTasks\RefreshMediaLibraryTask.cs" />
<Compile Include="ScheduledTasks\SystemUpdateTask.cs" /> <Compile Include="ScheduledTasks\SystemUpdateTask.cs" />
<Compile Include="Security\AuthenticationException.cs" />
<Compile Include="Security\AuthenticationRepository.cs" /> <Compile Include="Security\AuthenticationRepository.cs" />
<Compile Include="Security\EncryptionManager.cs" /> <Compile Include="Security\EncryptionManager.cs" />
<Compile Include="ServerApplicationPaths.cs" /> <Compile Include="ServerApplicationPaths.cs" />

@ -1,16 +0,0 @@
using System;
namespace MediaBrowser.Server.Implementations.Security
{
public class AuthenticationException : Exception
{
public AuthenticationException(string message)
: base(message)
{
}
public AuthenticationException()
{
}
}
}

@ -11,10 +11,10 @@ using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Security; using MediaBrowser.Controller.Security;
using MediaBrowser.Controller.Session; using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Connect;
using MediaBrowser.Model.Devices; using MediaBrowser.Model.Devices;
using MediaBrowser.Model.Entities; using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Events; using MediaBrowser.Model.Events;
@ -23,7 +23,6 @@ using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Serialization; using MediaBrowser.Model.Serialization;
using MediaBrowser.Model.Session; using MediaBrowser.Model.Session;
using MediaBrowser.Model.Users; using MediaBrowser.Model.Users;
using MediaBrowser.Server.Implementations.Security;
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
@ -253,11 +252,6 @@ namespace MediaBrowser.Server.Implementations.Session
throw new ArgumentNullException("deviceName"); throw new ArgumentNullException("deviceName");
} }
if (user != null && user.Configuration.IsDisabled)
{
throw new AuthenticationException(string.Format("The {0} account is currently disabled. Please consult with your administrator.", user.Name));
}
var activityDate = DateTime.UtcNow; var activityDate = DateTime.UtcNow;
var userId = user == null ? (Guid?)null : user.Id; var userId = user == null ? (Guid?)null : user.Id;
@ -1261,49 +1255,11 @@ namespace MediaBrowser.Server.Implementations.Session
} }
} }
public void ValidateSecurityToken(string token)
{
if (string.IsNullOrWhiteSpace(token))
{
throw new AuthenticationException();
}
var result = _authRepo.Get(new AuthenticationInfoQuery
{
AccessToken = token
});
var info = result.Items.FirstOrDefault();
if (info == null)
{
throw new AuthenticationException();
}
if (!info.IsActive)
{
throw new AuthenticationException("Access token has expired.");
}
if (!string.IsNullOrWhiteSpace(info.UserId))
{
var user = _userManager.GetUserById(info.UserId);
if (user == null || user.Configuration.IsDisabled)
{
throw new AuthenticationException("User account has been disabled.");
}
}
}
/// <summary> /// <summary>
/// Authenticates the new session. /// Authenticates the new session.
/// </summary> /// </summary>
/// <param name="request">The request.</param> /// <param name="request">The request.</param>
/// <returns>Task{SessionInfo}.</returns> /// <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(AuthenticationRequest request) public async Task<AuthenticationResult> AuthenticateNewSession(AuthenticationRequest request)
{ {
var user = _userManager.Users var user = _userManager.Users
@ -1315,7 +1271,7 @@ namespace MediaBrowser.Server.Implementations.Session
{ {
EventHelper.FireEventIfNotNull(AuthenticationFailed, this, new GenericEventArgs<AuthenticationRequest>(request), _logger); EventHelper.FireEventIfNotNull(AuthenticationFailed, this, new GenericEventArgs<AuthenticationRequest>(request), _logger);
throw new AuthenticationException("Invalid user or password entered."); throw new UnauthorizedAccessException("Invalid user or password entered.");
} }
var token = await GetAuthorizationToken(user.Id.ToString("N"), request.DeviceId, request.App, request.DeviceName).ConfigureAwait(false); var token = await GetAuthorizationToken(user.Id.ToString("N"), request.DeviceId, request.App, request.DeviceName).ConfigureAwait(false);

@ -496,10 +496,10 @@ namespace MediaBrowser.Server.Startup.Common
RegisterSingleInstance(activityLogRepo); RegisterSingleInstance(activityLogRepo);
RegisterSingleInstance<IActivityManager>(new ActivityManager(LogManager.GetLogger("ActivityManager"), activityLogRepo, UserManager)); RegisterSingleInstance<IActivityManager>(new ActivityManager(LogManager.GetLogger("ActivityManager"), activityLogRepo, UserManager));
var authContext = new AuthorizationContext(); var authContext = new AuthorizationContext(AuthenticationRepository);
RegisterSingleInstance<IAuthorizationContext>(authContext); RegisterSingleInstance<IAuthorizationContext>(authContext);
RegisterSingleInstance<ISessionContext>(new SessionContext(UserManager, authContext, SessionManager)); RegisterSingleInstance<ISessionContext>(new SessionContext(UserManager, authContext, SessionManager));
RegisterSingleInstance<IAuthService>(new AuthService(UserManager, SessionManager, authContext, ServerConfigurationManager, ConnectManager)); RegisterSingleInstance<IAuthService>(new AuthService(UserManager, authContext, ServerConfigurationManager, ConnectManager));
RegisterSingleInstance<ISubtitleEncoder>(new SubtitleEncoder(LibraryManager, LogManager.GetLogger("SubtitleEncoder"), ApplicationPaths, FileSystemManager, MediaEncoder, JsonSerializer)); RegisterSingleInstance<ISubtitleEncoder>(new SubtitleEncoder(LibraryManager, LogManager.GetLogger("SubtitleEncoder"), ApplicationPaths, FileSystemManager, MediaEncoder, JsonSerializer));
@ -534,6 +534,8 @@ namespace MediaBrowser.Server.Startup.Common
var info = await new FFMpegDownloader(Logger, ApplicationPaths, HttpClient, ZipClient, FileSystemManager) var info = await new FFMpegDownloader(Logger, ApplicationPaths, HttpClient, ZipClient, FileSystemManager)
.GetFFMpegInfo(NativeApp.Environment, _startupOptions, progress).ConfigureAwait(false); .GetFFMpegInfo(NativeApp.Environment, _startupOptions, progress).ConfigureAwait(false);
new FFmpegValidator(Logger, ApplicationPaths).Validate(info);
MediaEncoder = new MediaEncoder(LogManager.GetLogger("MediaEncoder"), JsonSerializer, info.EncoderPath, info.ProbePath, info.Version); MediaEncoder = new MediaEncoder(LogManager.GetLogger("MediaEncoder"), JsonSerializer, info.EncoderPath, info.ProbePath, info.Version);
RegisterSingleInstance(MediaEncoder); RegisterSingleInstance(MediaEncoder);
} }

@ -0,0 +1,116 @@
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Model.Logging;
using System;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Text;
namespace MediaBrowser.Server.Startup.Common.FFMpeg
{
public class FFmpegValidator
{
private readonly ILogger _logger;
private readonly IApplicationPaths _appPaths;
public FFmpegValidator(ILogger logger, IApplicationPaths appPaths)
{
_logger = logger;
_appPaths = appPaths;
}
public void Validate(FFMpegInfo info)
{
_logger.Info("FFMpeg: {0}", info.EncoderPath);
_logger.Info("FFProbe: {0}", info.ProbePath);
var fileInfo = new FileInfo(info.EncoderPath);
var cachePath = Path.Combine(_appPaths.CachePath, fileInfo.Length.ToString(CultureInfo.InvariantCulture).GetMD5().ToString("N"));
if (!File.Exists(cachePath))
{
ValidateCodecs(info.EncoderPath);
Directory.CreateDirectory(Path.GetDirectoryName(cachePath));
File.WriteAllText(cachePath, string.Empty, Encoding.UTF8);
}
}
private void ValidateCodecs(string path)
{
var output = GetOutput(path, "-encoders");
var required = new[]
{
"libx264",
"mpeg4",
"msmpeg4",
"libvpx",
//"libvpx-vp9",
"aac",
"ac3",
"libmp3lame",
"libvorbis",
"srt"
};
foreach (var encoder in required)
{
var srch = " " + encoder + " ";
if (output.IndexOf(srch, StringComparison.OrdinalIgnoreCase) == -1)
{
throw new ArgumentException("ffmpeg is missing encoder " + encoder);
}
}
}
private string GetOutput(string path, string arguments)
{
var process = new Process
{
StartInfo = new ProcessStartInfo
{
CreateNoWindow = true,
UseShellExecute = false,
FileName = path,
Arguments = arguments,
WindowStyle = ProcessWindowStyle.Hidden,
ErrorDialog = false,
RedirectStandardOutput = true,
RedirectStandardError = true
}
};
using (process)
{
process.Start();
try
{
process.BeginErrorReadLine();
using (var reader = new StreamReader(process.StandardOutput.BaseStream))
{
return reader.ReadToEnd();
}
}
catch
{
// Hate having to do this
try
{
process.Kill();
}
catch (Exception ex1)
{
_logger.ErrorException("Error killing ffmpeg", ex1);
}
throw;
}
}
}
}
}

@ -59,6 +59,7 @@
<Compile Include="FFMpeg\FFMpegDownloader.cs" /> <Compile Include="FFMpeg\FFMpegDownloader.cs" />
<Compile Include="FFMpeg\FFMpegDownloadInfo.cs" /> <Compile Include="FFMpeg\FFMpegDownloadInfo.cs" />
<Compile Include="FFMpeg\FFMpegInfo.cs" /> <Compile Include="FFMpeg\FFMpegInfo.cs" />
<Compile Include="FFMpeg\FFmpegValidator.cs" />
<Compile Include="INativeApp.cs" /> <Compile Include="INativeApp.cs" />
<Compile Include="Migrations\DeprecatePlugins.cs" /> <Compile Include="Migrations\DeprecatePlugins.cs" />
<Compile Include="Migrations\IVersionMigration.cs" /> <Compile Include="Migrations\IVersionMigration.cs" />

@ -195,8 +195,7 @@ namespace MediaBrowser.ServerApplication
/// <param name="appPaths">The app paths.</param> /// <param name="appPaths">The app paths.</param>
private static void BeginLog(ILogger logger, IApplicationPaths appPaths) private static void BeginLog(ILogger logger, IApplicationPaths appPaths)
{ {
logger.Info("Media Browser Server started"); ApplicationHost.LogEnvironmentInfo(logger, appPaths, true);
ApplicationHost.LogEnvironmentInfo(logger, appPaths);
} }
private static readonly TaskCompletionSource<bool> ApplicationTaskCompletionSource = new TaskCompletionSource<bool>(); private static readonly TaskCompletionSource<bool> ApplicationTaskCompletionSource = new TaskCompletionSource<bool>();

Loading…
Cancel
Save