mirror of
https://github.com/jellyfin/jellyfin.git
synced 2025-04-24 14:08:44 -04:00
revise endpoint attributes
This commit is contained in:
parent
15a56fa069
commit
a4b75934e5
59 changed files with 714 additions and 494 deletions
|
@ -84,7 +84,6 @@ namespace MediaBrowser.Api
|
|||
/// Gets the session.
|
||||
/// </summary>
|
||||
/// <returns>SessionInfo.</returns>
|
||||
/// <exception cref="System.ArgumentException">Session not found.</exception>
|
||||
protected SessionInfo GetSession()
|
||||
{
|
||||
var session = SessionContext.GetSession(Request);
|
||||
|
|
|
@ -9,7 +9,6 @@ using MediaBrowser.Model.Serialization;
|
|||
using ServiceStack;
|
||||
using ServiceStack.Text.Controller;
|
||||
using ServiceStack.Web;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
@ -38,13 +37,13 @@ namespace MediaBrowser.Api
|
|||
/// Class UpdateConfiguration
|
||||
/// </summary>
|
||||
[Route("/System/Configuration", "POST", Summary = "Updates application configuration")]
|
||||
[Authenticated]
|
||||
[Authenticated(Roles = "Admin")]
|
||||
public class UpdateConfiguration : ServerConfiguration, IReturnVoid
|
||||
{
|
||||
}
|
||||
|
||||
[Route("/System/Configuration/{Key}", "POST", Summary = "Updates named configuration")]
|
||||
[Authenticated]
|
||||
[Authenticated(Roles = "Admin")]
|
||||
public class UpdateNamedConfiguration : IReturnVoid, IRequiresRequestStream
|
||||
{
|
||||
[ApiMember(Name = "Key", Description = "Key", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
|
||||
|
@ -54,21 +53,21 @@ namespace MediaBrowser.Api
|
|||
}
|
||||
|
||||
[Route("/System/Configuration/MetadataOptions/Default", "GET", Summary = "Gets a default MetadataOptions object")]
|
||||
[Authenticated]
|
||||
[Authenticated(Roles = "Admin")]
|
||||
public class GetDefaultMetadataOptions : IReturn<MetadataOptions>
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
[Route("/System/Configuration/MetadataPlugins", "GET", Summary = "Gets all available metadata plugins")]
|
||||
[Authenticated]
|
||||
[Authenticated(Roles = "Admin")]
|
||||
public class GetMetadataPlugins : IReturn<List<MetadataPluginSummary>>
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
[Route("/System/Configuration/MetadataPlugins/Autoset", "POST")]
|
||||
[Authenticated]
|
||||
[Authenticated(Roles = "Admin", AllowBeforeStartupWizard = true)]
|
||||
public class AutoSetMetadataOptions : IReturnVoid
|
||||
{
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ using System.Threading.Tasks;
|
|||
namespace MediaBrowser.Api.Devices
|
||||
{
|
||||
[Route("/Devices", "GET", Summary = "Gets all devices")]
|
||||
[Authenticated(Roles = "Admin")]
|
||||
public class GetDevices : IReturn<List<DeviceInfo>>
|
||||
{
|
||||
[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")]
|
||||
[Authenticated]
|
||||
public class GetCameraUploads : IReturn<ContentUploadHistory>
|
||||
{
|
||||
[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")]
|
||||
[Authenticated]
|
||||
public class PostCameraUpload : IRequiresRequestStream, IReturnVoid
|
||||
{
|
||||
[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")]
|
||||
[Authenticated]
|
||||
public class GetDeviceInfo : IReturn<DeviceInfo>
|
||||
{
|
||||
[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")]
|
||||
[Authenticated]
|
||||
public class GetDeviceCapabilities : IReturn<ClientCapabilities>
|
||||
{
|
||||
[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")]
|
||||
[Authenticated(Roles = "Admin")]
|
||||
public class PostDeviceOptions : DeviceOptions, IReturnVoid
|
||||
{
|
||||
[ApiMember(Name = "Id", Description = "Device Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "DELETE")]
|
||||
public string Id { get; set; }
|
||||
}
|
||||
|
||||
[Authenticated]
|
||||
public class DeviceService : BaseApiService
|
||||
{
|
||||
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")]
|
||||
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")]
|
||||
|
|
|
@ -43,7 +43,7 @@ namespace MediaBrowser.Api.Dlna
|
|||
{
|
||||
}
|
||||
|
||||
[Authenticated]
|
||||
[Authenticated(Roles = "Admin")]
|
||||
public class DlnaService : BaseApiService
|
||||
{
|
||||
private readonly IDlnaManager _dlnaManager;
|
||||
|
|
|
@ -87,7 +87,7 @@ namespace MediaBrowser.Api
|
|||
/// <summary>
|
||||
/// Class EnvironmentService
|
||||
/// </summary>
|
||||
[Authenticated]
|
||||
[Authenticated(Roles = "Admin")]
|
||||
public class EnvironmentService : BaseApiService
|
||||
{
|
||||
const char UncSeparator = '\\';
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
using MediaBrowser.Common.IO;
|
||||
using MediaBrowser.Controller;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Net;
|
||||
using MediaBrowser.Model.Dto;
|
||||
using ServiceStack;
|
||||
using System;
|
||||
|
@ -14,8 +15,7 @@ namespace MediaBrowser.Api.Images
|
|||
/// <summary>
|
||||
/// Class GetGeneralImage
|
||||
/// </summary>
|
||||
[Route("/Images/General/{Name}/{Type}", "GET")]
|
||||
[Api(Description = "Gets a general image by name")]
|
||||
[Route("/Images/General/{Name}/{Type}", "GET", Summary = "Gets a general image by name")]
|
||||
public class GetGeneralImage
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -32,8 +32,7 @@ namespace MediaBrowser.Api.Images
|
|||
/// <summary>
|
||||
/// Class GetRatingImage
|
||||
/// </summary>
|
||||
[Route("/Images/Ratings/{Theme}/{Name}", "GET")]
|
||||
[Api(Description = "Gets a rating image by name")]
|
||||
[Route("/Images/Ratings/{Theme}/{Name}", "GET", Summary = "Gets a rating image by name")]
|
||||
public class GetRatingImage
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -54,8 +53,7 @@ namespace MediaBrowser.Api.Images
|
|||
/// <summary>
|
||||
/// Class GetMediaInfoImage
|
||||
/// </summary>
|
||||
[Route("/Images/MediaInfo/{Theme}/{Name}", "GET")]
|
||||
[Api(Description = "Gets a media info image by name")]
|
||||
[Route("/Images/MediaInfo/{Theme}/{Name}", "GET", Summary = "Gets a media info image by name")]
|
||||
public class GetMediaInfoImage
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -73,20 +71,20 @@ namespace MediaBrowser.Api.Images
|
|||
public string Theme { get; set; }
|
||||
}
|
||||
|
||||
[Route("/Images/MediaInfo", "GET")]
|
||||
[Api(Description = "Gets all media info image by name")]
|
||||
[Route("/Images/MediaInfo", "GET", Summary = "Gets all media info image by name")]
|
||||
[Authenticated]
|
||||
public class GetMediaInfoImages : IReturn<List<ImageByNameInfo>>
|
||||
{
|
||||
}
|
||||
|
||||
[Route("/Images/Ratings", "GET")]
|
||||
[Api(Description = "Gets all rating images by name")]
|
||||
[Route("/Images/Ratings", "GET", Summary = "Gets all rating images by name")]
|
||||
[Authenticated]
|
||||
public class GetRatingImages : IReturn<List<ImageByNameInfo>>
|
||||
{
|
||||
}
|
||||
|
||||
[Route("/Images/General", "GET")]
|
||||
[Api(Description = "Gets all general images by name")]
|
||||
[Route("/Images/General", "GET", Summary = "Gets all general images by name")]
|
||||
[Authenticated]
|
||||
public class GetGeneralImages : IReturn<List<ImageByNameInfo>>
|
||||
{
|
||||
}
|
||||
|
|
|
@ -24,8 +24,7 @@ namespace MediaBrowser.Api.Images
|
|||
/// <summary>
|
||||
/// Class GetItemImage
|
||||
/// </summary>
|
||||
[Route("/Items/{Id}/Images", "GET")]
|
||||
[Api(Description = "Gets information about an item's images")]
|
||||
[Route("/Items/{Id}/Images", "GET", Summary = "Gets information about an item's images")]
|
||||
[Authenticated]
|
||||
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}/{Tag}/{Format}/{MaxWidth}/{MaxHeight}/{PercentPlayed}", "GET")]
|
||||
[Route("/Items/{Id}/Images/{Type}/{Index}/{Tag}/{Format}/{MaxWidth}/{MaxHeight}/{PercentPlayed}", "HEAD")]
|
||||
[Api(Description = "Gets an item image")]
|
||||
public class GetItemImage : ImageRequest
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -57,8 +55,7 @@ namespace MediaBrowser.Api.Images
|
|||
/// <summary>
|
||||
/// Class UpdateItemImageIndex
|
||||
/// </summary>
|
||||
[Route("/Items/{Id}/Images/{Type}/{Index}/Index", "POST")]
|
||||
[Api(Description = "Updates the index for an item image")]
|
||||
[Route("/Items/{Id}/Images/{Type}/{Index}/Index", "POST", Summary = "Updates the index for an item image")]
|
||||
[Authenticated]
|
||||
public class UpdateItemImageIndex : IReturnVoid
|
||||
{
|
||||
|
@ -122,7 +119,6 @@ namespace MediaBrowser.Api.Images
|
|||
[Route("/Studios/{Name}/Images/{Type}/{Index}", "HEAD")]
|
||||
[Route("/Years/{Year}/Images/{Type}", "HEAD")]
|
||||
[Route("/Years/{Year}/Images/{Type}/{Index}", "HEAD")]
|
||||
[Api(Description = "Gets an item by name image")]
|
||||
public class GetItemByNameImage : ImageRequest
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -140,7 +136,6 @@ namespace MediaBrowser.Api.Images
|
|||
[Route("/Users/{Id}/Images/{Type}/{Index}", "GET")]
|
||||
[Route("/Users/{Id}/Images/{Type}", "HEAD")]
|
||||
[Route("/Users/{Id}/Images/{Type}/{Index}", "HEAD")]
|
||||
[Api(Description = "Gets a user image")]
|
||||
public class GetUserImage : ImageRequest
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -156,7 +151,6 @@ namespace MediaBrowser.Api.Images
|
|||
/// </summary>
|
||||
[Route("/Items/{Id}/Images/{Type}", "DELETE")]
|
||||
[Route("/Items/{Id}/Images/{Type}/{Index}", "DELETE")]
|
||||
[Api(Description = "Deletes an item image")]
|
||||
[Authenticated]
|
||||
public class DeleteItemImage : DeleteImageRequest, IReturnVoid
|
||||
{
|
||||
|
@ -173,7 +167,6 @@ namespace MediaBrowser.Api.Images
|
|||
/// </summary>
|
||||
[Route("/Users/{Id}/Images/{Type}", "DELETE")]
|
||||
[Route("/Users/{Id}/Images/{Type}/{Index}", "DELETE")]
|
||||
[Api(Description = "Deletes a user image")]
|
||||
[Authenticated]
|
||||
public class DeleteUserImage : DeleteImageRequest, IReturnVoid
|
||||
{
|
||||
|
@ -190,7 +183,6 @@ namespace MediaBrowser.Api.Images
|
|||
/// </summary>
|
||||
[Route("/Users/{Id}/Images/{Type}", "POST")]
|
||||
[Route("/Users/{Id}/Images/{Type}/{Index}", "POST")]
|
||||
[Api(Description = "Posts a user image")]
|
||||
[Authenticated]
|
||||
public class PostUserImage : DeleteImageRequest, IRequiresRequestStream, IReturnVoid
|
||||
{
|
||||
|
|
|
@ -5,11 +5,11 @@ using MediaBrowser.Controller;
|
|||
using MediaBrowser.Controller.Dto;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Net;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Providers;
|
||||
using ServiceStack;
|
||||
using ServiceStack.Text.Controller;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
@ -45,8 +45,8 @@ namespace MediaBrowser.Api.Images
|
|||
public bool IncludeAllLanguages { get; set; }
|
||||
}
|
||||
|
||||
[Route("/Items/{Id}/RemoteImages", "GET")]
|
||||
[Api(Description = "Gets available remote images for an item")]
|
||||
[Route("/Items/{Id}/RemoteImages", "GET", Summary = "Gets available remote images for an item")]
|
||||
[Authenticated]
|
||||
public class GetRemoteImages : BaseRemoteImageRequest
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -57,25 +57,8 @@ namespace MediaBrowser.Api.Images
|
|||
public string Id { get; set; }
|
||||
}
|
||||
|
||||
[Route("/Artists/{Name}/RemoteImages", "GET")]
|
||||
[Route("/Genres/{Name}/RemoteImages", "GET")]
|
||||
[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")]
|
||||
[Route("/Items/{Id}/RemoteImages/Providers", "GET", Summary = "Gets available remote image providers for an item")]
|
||||
[Authenticated]
|
||||
public class GetRemoteImageProviders : IReturn<List<ImageProviderInfo>>
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -86,23 +69,6 @@ namespace MediaBrowser.Api.Images
|
|||
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
|
||||
{
|
||||
[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; }
|
||||
}
|
||||
|
||||
[Route("/Items/{Id}/RemoteImages/Download", "POST")]
|
||||
[Api(Description = "Downloads a remote image for an item")]
|
||||
[Route("/Items/{Id}/RemoteImages/Download", "POST", Summary = "Downloads a remote image for an item")]
|
||||
[Authenticated(Roles="Admin")]
|
||||
public class DownloadRemoteImage : BaseDownloadRemoteImage
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -127,25 +93,7 @@ namespace MediaBrowser.Api.Images
|
|||
public string Id { get; set; }
|
||||
}
|
||||
|
||||
[Route("/Artists/{Name}/RemoteImages/Download", "POST")]
|
||||
[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")]
|
||||
[Route("/Images/Remote", "GET", Summary = "Gets a remote image")]
|
||||
public class GetRemoteImage
|
||||
{
|
||||
[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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
return _providerManager.GetRemoteImageProviderInfo(item).ToList();
|
||||
|
@ -206,16 +142,6 @@ namespace MediaBrowser.Api.Images
|
|||
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)
|
||||
{
|
||||
var images = await _providerManager.GetAvailableRemoteImages(item, new RemoteImageQuery
|
||||
|
@ -274,18 +200,6 @@ namespace MediaBrowser.Api.Images
|
|||
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>
|
||||
/// Downloads the remote image.
|
||||
/// </summary>
|
||||
|
|
|
@ -8,7 +8,6 @@ using MediaBrowser.Controller.Entities.TV;
|
|||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Net;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Providers;
|
||||
using ServiceStack;
|
||||
using System;
|
||||
|
@ -20,9 +19,8 @@ using System.Threading.Tasks;
|
|||
|
||||
namespace MediaBrowser.Api
|
||||
{
|
||||
[Route("/Items/{Id}/ExternalIdInfos", "GET")]
|
||||
[Api(Description = "Gets external id infos for an item")]
|
||||
[Authenticated]
|
||||
[Route("/Items/{Id}/ExternalIdInfos", "GET", Summary = "Gets external id infos for an item")]
|
||||
[Authenticated(Roles = "Admin")]
|
||||
public class GetExternalIdInfos : IReturn<List<ExternalIdInfo>>
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -34,70 +32,60 @@ namespace MediaBrowser.Api
|
|||
}
|
||||
|
||||
[Route("/Items/RemoteSearch/Movie", "POST")]
|
||||
[Api(Description = "Gets external id infos for an item")]
|
||||
[Authenticated]
|
||||
public class GetMovieRemoteSearchResults : RemoteSearchQuery<MovieInfo>, IReturn<List<RemoteSearchResult>>
|
||||
{
|
||||
}
|
||||
|
||||
[Route("/Items/RemoteSearch/Trailer", "POST")]
|
||||
[Api(Description = "Gets external id infos for an item")]
|
||||
[Authenticated]
|
||||
public class GetTrailerRemoteSearchResults : RemoteSearchQuery<TrailerInfo>, IReturn<List<RemoteSearchResult>>
|
||||
{
|
||||
}
|
||||
|
||||
[Route("/Items/RemoteSearch/AdultVideo", "POST")]
|
||||
[Api(Description = "Gets external id infos for an item")]
|
||||
[Authenticated]
|
||||
public class GetAdultVideoRemoteSearchResults : RemoteSearchQuery<ItemLookupInfo>, IReturn<List<RemoteSearchResult>>
|
||||
{
|
||||
}
|
||||
|
||||
[Route("/Items/RemoteSearch/Series", "POST")]
|
||||
[Api(Description = "Gets external id infos for an item")]
|
||||
[Authenticated]
|
||||
public class GetSeriesRemoteSearchResults : RemoteSearchQuery<SeriesInfo>, IReturn<List<RemoteSearchResult>>
|
||||
{
|
||||
}
|
||||
|
||||
[Route("/Items/RemoteSearch/Game", "POST")]
|
||||
[Api(Description = "Gets external id infos for an item")]
|
||||
[Authenticated]
|
||||
public class GetGameRemoteSearchResults : RemoteSearchQuery<GameInfo>, IReturn<List<RemoteSearchResult>>
|
||||
{
|
||||
}
|
||||
|
||||
[Route("/Items/RemoteSearch/BoxSet", "POST")]
|
||||
[Api(Description = "Gets external id infos for an item")]
|
||||
[Authenticated]
|
||||
public class GetBoxSetRemoteSearchResults : RemoteSearchQuery<BoxSetInfo>, IReturn<List<RemoteSearchResult>>
|
||||
{
|
||||
}
|
||||
|
||||
[Route("/Items/RemoteSearch/MusicArtist", "POST")]
|
||||
[Api(Description = "Gets external id infos for an item")]
|
||||
[Authenticated]
|
||||
public class GetMusicArtistRemoteSearchResults : RemoteSearchQuery<ArtistInfo>, IReturn<List<RemoteSearchResult>>
|
||||
{
|
||||
}
|
||||
|
||||
[Route("/Items/RemoteSearch/MusicAlbum", "POST")]
|
||||
[Api(Description = "Gets external id infos for an item")]
|
||||
[Authenticated]
|
||||
public class GetMusicAlbumRemoteSearchResults : RemoteSearchQuery<AlbumInfo>, IReturn<List<RemoteSearchResult>>
|
||||
{
|
||||
}
|
||||
|
||||
[Route("/Items/RemoteSearch/Person", "POST")]
|
||||
[Api(Description = "Gets external id infos for an item")]
|
||||
[Authenticated]
|
||||
[Authenticated(Roles = "Admin")]
|
||||
public class GetPersonRemoteSearchResults : RemoteSearchQuery<PersonLookupInfo>, IReturn<List<RemoteSearchResult>>
|
||||
{
|
||||
}
|
||||
|
||||
[Route("/Items/RemoteSearch/Image", "GET")]
|
||||
[Api(Description = "Gets a remote image")]
|
||||
[Route("/Items/RemoteSearch/Image", "GET", Summary = "Gets a remote image")]
|
||||
public class GetRemoteSearchImage
|
||||
{
|
||||
[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; }
|
||||
}
|
||||
|
||||
[Route("/Items/RemoteSearch/Apply/{Id}", "POST")]
|
||||
[Api(Description = "Applies search criteria to an item and refreshes metadata")]
|
||||
[Authenticated]
|
||||
[Route("/Items/RemoteSearch/Apply/{Id}", "POST", Summary = "Applies search criteria to an item and refreshes metadata")]
|
||||
[Authenticated(Roles = "Admin")]
|
||||
public class ApplySearchCriteria : RemoteSearchResult, IReturnVoid
|
||||
{
|
||||
[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; }
|
||||
}
|
||||
|
||||
[Route("/Items/{Id}/Refresh", "POST")]
|
||||
[Api(Description = "Refreshes metadata for an item")]
|
||||
[Route("/Items/{Id}/Refresh", "POST", Summary = "Refreshes metadata for an item")]
|
||||
public class RefreshItem : BaseRefreshRequest
|
||||
{
|
||||
[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
|
||||
{
|
||||
[Route("/Library/FileOrganization", "GET")]
|
||||
[Api(Description = "Gets file organization results")]
|
||||
[Route("/Library/FileOrganization", "GET", Summary = "Gets file organization results")]
|
||||
public class GetFileOrganizationActivity : IReturn<QueryResult<FileOrganizationResult>>
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -26,14 +25,12 @@ namespace MediaBrowser.Api.Library
|
|||
public int? Limit { get; set; }
|
||||
}
|
||||
|
||||
[Route("/Library/FileOrganizations", "DELETE")]
|
||||
[Api(Description = "Clears the activity log")]
|
||||
[Route("/Library/FileOrganizations", "DELETE", Summary = "Clears the activity log")]
|
||||
public class ClearOrganizationLog : IReturnVoid
|
||||
{
|
||||
}
|
||||
|
||||
[Route("/Library/FileOrganizations/{Id}/File", "DELETE")]
|
||||
[Api(Description = "Deletes the original file of a organizer result")]
|
||||
[Route("/Library/FileOrganizations/{Id}/File", "DELETE", Summary = "Deletes the original file of a organizer result")]
|
||||
public class DeleteOriginalFile : IReturnVoid
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -44,8 +41,7 @@ namespace MediaBrowser.Api.Library
|
|||
public string Id { get; set; }
|
||||
}
|
||||
|
||||
[Route("/Library/FileOrganizations/{Id}/Organize", "POST")]
|
||||
[Api(Description = "Performs an organization")]
|
||||
[Route("/Library/FileOrganizations/{Id}/Organize", "POST", Summary = "Performs an organization")]
|
||||
public class PerformOrganization : IReturn<QueryResult<FileOrganizationResult>>
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -56,8 +52,7 @@ namespace MediaBrowser.Api.Library
|
|||
public string Id { get; set; }
|
||||
}
|
||||
|
||||
[Route("/Library/FileOrganizations/{Id}/Episode/Organize", "POST")]
|
||||
[Api(Description = "Performs an organization")]
|
||||
[Route("/Library/FileOrganizations/{Id}/Episode/Organize", "POST", Summary = "Performs an organization")]
|
||||
public class OrganizeEpisode
|
||||
{
|
||||
[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; }
|
||||
}
|
||||
|
||||
[Authenticated]
|
||||
[Authenticated(Roles = "Admin")]
|
||||
public class FileOrganizationService : BaseApiService
|
||||
{
|
||||
private readonly IFileOrganizationService _iFileOrganizationService;
|
||||
|
|
|
@ -23,8 +23,8 @@ using System.Threading.Tasks;
|
|||
|
||||
namespace MediaBrowser.Api.Library
|
||||
{
|
||||
[Route("/Items/{Id}/File", "GET")]
|
||||
[Api(Description = "Gets the original file of an item")]
|
||||
[Route("/Items/{Id}/File", "GET", Summary = "Gets the original file of an item")]
|
||||
[Authenticated]
|
||||
public class GetFile
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -38,8 +38,8 @@ namespace MediaBrowser.Api.Library
|
|||
/// <summary>
|
||||
/// Class GetCriticReviews
|
||||
/// </summary>
|
||||
[Route("/Items/{Id}/CriticReviews", "GET")]
|
||||
[Api(Description = "Gets critic reviews for an item")]
|
||||
[Route("/Items/{Id}/CriticReviews", "GET", Summary = "Gets critic reviews for an item")]
|
||||
[Authenticated]
|
||||
public class GetCriticReviews : IReturn<QueryResult<ItemReview>>
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -67,8 +67,8 @@ namespace MediaBrowser.Api.Library
|
|||
/// <summary>
|
||||
/// Class GetThemeSongs
|
||||
/// </summary>
|
||||
[Route("/Items/{Id}/ThemeSongs", "GET")]
|
||||
[Api(Description = "Gets theme songs for an item")]
|
||||
[Route("/Items/{Id}/ThemeSongs", "GET", Summary = "Gets theme songs for an item")]
|
||||
[Authenticated]
|
||||
public class GetThemeSongs : IReturn<ThemeMediaResult>
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -92,8 +92,8 @@ namespace MediaBrowser.Api.Library
|
|||
/// <summary>
|
||||
/// Class GetThemeVideos
|
||||
/// </summary>
|
||||
[Route("/Items/{Id}/ThemeVideos", "GET")]
|
||||
[Api(Description = "Gets theme videos for an item")]
|
||||
[Route("/Items/{Id}/ThemeVideos", "GET", Summary = "Gets theme videos for an item")]
|
||||
[Authenticated]
|
||||
public class GetThemeVideos : IReturn<ThemeMediaResult>
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -117,8 +117,8 @@ namespace MediaBrowser.Api.Library
|
|||
/// <summary>
|
||||
/// Class GetThemeVideos
|
||||
/// </summary>
|
||||
[Route("/Items/{Id}/ThemeMedia", "GET")]
|
||||
[Api(Description = "Gets theme videos and songs for an item")]
|
||||
[Route("/Items/{Id}/ThemeMedia", "GET", Summary = "Gets theme videos and songs for an item")]
|
||||
[Authenticated]
|
||||
public class GetThemeMedia : IReturn<AllThemeMediaResult>
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -139,14 +139,14 @@ namespace MediaBrowser.Api.Library
|
|||
public bool InheritFromParent { get; set; }
|
||||
}
|
||||
|
||||
[Route("/Library/Refresh", "POST")]
|
||||
[Api(Description = "Starts a library scan")]
|
||||
[Route("/Library/Refresh", "POST", Summary = "Starts a library scan")]
|
||||
[Authenticated(Roles = "Admin")]
|
||||
public class RefreshLibrary : IReturnVoid
|
||||
{
|
||||
}
|
||||
|
||||
[Route("/Items/{Id}", "DELETE")]
|
||||
[Api(Description = "Deletes an item from the library and file system")]
|
||||
[Route("/Items/{Id}", "DELETE", Summary = "Deletes an item from the library and file system")]
|
||||
[Authenticated(Roles = "Delete")]
|
||||
public class DeleteItem : IReturnVoid
|
||||
{
|
||||
[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")]
|
||||
[Api(Description = "Gets counts of various item types")]
|
||||
[Authenticated]
|
||||
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")]
|
||||
|
@ -164,8 +164,8 @@ namespace MediaBrowser.Api.Library
|
|||
public bool? IsFavorite { get; set; }
|
||||
}
|
||||
|
||||
[Route("/Items/{Id}/Ancestors", "GET")]
|
||||
[Api(Description = "Gets all parents of an item")]
|
||||
[Route("/Items/{Id}/Ancestors", "GET", Summary = "Gets all parents of an item")]
|
||||
[Authenticated]
|
||||
public class GetAncestors : IReturn<BaseItemDto[]>
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -183,8 +183,8 @@ namespace MediaBrowser.Api.Library
|
|||
public string Id { get; set; }
|
||||
}
|
||||
|
||||
[Route("/Items/YearIndex", "GET")]
|
||||
[Api(Description = "Gets a year index based on an item query.")]
|
||||
[Route("/Items/YearIndex", "GET", Summary = "Gets a year index based on an item query.")]
|
||||
[Authenticated]
|
||||
public class GetYearIndex : IReturn<List<ItemIndex>>
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -201,23 +201,23 @@ namespace MediaBrowser.Api.Library
|
|||
/// <summary>
|
||||
/// Class GetPhyscialPaths
|
||||
/// </summary>
|
||||
[Route("/Library/PhysicalPaths", "GET")]
|
||||
[Api(Description = "Gets a list of physical paths from virtual folders")]
|
||||
[Route("/Library/PhysicalPaths", "GET", Summary = "Gets a list of physical paths from virtual folders")]
|
||||
[Authenticated(Roles = "Admin")]
|
||||
public class GetPhyscialPaths : IReturn<List<string>>
|
||||
{
|
||||
}
|
||||
|
||||
[Route("/Library/MediaFolders", "GET")]
|
||||
[Api(Description = "Gets all user media folders.")]
|
||||
[Route("/Library/MediaFolders", "GET", Summary = "Gets all user media folders.")]
|
||||
[Authenticated]
|
||||
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")]
|
||||
public bool? IsHidden { get; set; }
|
||||
}
|
||||
|
||||
[Route("/Library/Series/Added", "POST")]
|
||||
[Route("/Library/Series/Updated", "POST")]
|
||||
[Api(Description = "Reports that new episodes of a series have been added by an external source")]
|
||||
[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", Summary = "Reports that new episodes of a series have been added by an external source")]
|
||||
[Authenticated]
|
||||
public class PostUpdatedSeries : IReturnVoid
|
||||
{
|
||||
[ApiMember(Name = "TvdbId", Description = "Tvdb Id", IsRequired = false, DataType = "string", ParameterType = "path", Verb = "GET")]
|
||||
|
@ -227,7 +227,6 @@ namespace MediaBrowser.Api.Library
|
|||
/// <summary>
|
||||
/// Class LibraryService
|
||||
/// </summary>
|
||||
[Authenticated]
|
||||
public class LibraryService : BaseApiService
|
||||
{
|
||||
/// <summary>
|
||||
|
|
|
@ -135,7 +135,7 @@ namespace MediaBrowser.Api.Library
|
|||
/// <summary>
|
||||
/// Class LibraryStructureService
|
||||
/// </summary>
|
||||
[Authenticated]
|
||||
[Authenticated(Roles = "Admin", AllowBeforeStartupWizard = true)]
|
||||
public class LibraryStructureService : BaseApiService
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -164,7 +164,6 @@ namespace MediaBrowser.Api.Library
|
|||
/// <param name="appPaths">The app paths.</param>
|
||||
/// <param name="userManager">The user 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)
|
||||
{
|
||||
if (appPaths == null)
|
||||
|
|
|
@ -18,6 +18,7 @@ namespace MediaBrowser.Api.LiveTv
|
|||
/// This is insecure right now to avoid windows phone refactoring
|
||||
/// </summary>
|
||||
[Route("/LiveTv/Info", "GET", Summary = "Gets available live tv services.")]
|
||||
[Authenticated]
|
||||
public class GetLiveTvInfo : IReturn<LiveTvInfo>
|
||||
{
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ namespace MediaBrowser.Api
|
|||
/// <summary>
|
||||
/// Class CulturesService
|
||||
/// </summary>
|
||||
[Authenticated]
|
||||
[Authenticated(AllowBeforeStartupWizard = true)]
|
||||
public class LocalizationService : BaseApiService
|
||||
{
|
||||
/// <summary>
|
||||
|
|
|
@ -69,6 +69,7 @@
|
|||
<Compile Include="..\SharedVersion.cs">
|
||||
<Link>Properties\SharedVersion.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="AppThemeService.cs" />
|
||||
<Compile Include="BrandingService.cs" />
|
||||
<Compile Include="ChannelService.cs" />
|
||||
<Compile Include="ConnectService.cs" />
|
||||
|
@ -79,10 +80,10 @@
|
|||
<Compile Include="Library\ChapterService.cs" />
|
||||
<Compile Include="Playback\Hls\MpegDashService.cs" />
|
||||
<Compile Include="PlaylistService.cs" />
|
||||
<Compile Include="StartupWizardService.cs" />
|
||||
<Compile Include="Subtitles\SubtitleService.cs" />
|
||||
<Compile Include="Movies\CollectionService.cs" />
|
||||
<Compile Include="Music\AlbumsService.cs" />
|
||||
<Compile Include="AppThemeService.cs" />
|
||||
<Compile Include="BaseApiService.cs" />
|
||||
<Compile Include="ConfigurationService.cs" />
|
||||
<Compile Include="DisplayPreferencesService.cs" />
|
||||
|
|
|
@ -122,7 +122,7 @@ namespace MediaBrowser.Api
|
|||
/// <summary>
|
||||
/// Class PackageService
|
||||
/// </summary>
|
||||
[Authenticated]
|
||||
[Authenticated(Roles = "Admin")]
|
||||
public class PackageService : BaseApiService
|
||||
{
|
||||
private readonly IInstallationManager _installationManager;
|
||||
|
|
|
@ -6,7 +6,6 @@ using MediaBrowser.Model.Dto;
|
|||
using MediaBrowser.Model.Playlists;
|
||||
using MediaBrowser.Model.Querying;
|
||||
using ServiceStack;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ namespace MediaBrowser.Api
|
|||
/// Class Plugins
|
||||
/// </summary>
|
||||
[Route("/Plugins", "GET", Summary = "Gets a list of currently installed plugins")]
|
||||
[Authenticated]
|
||||
public class GetPlugins : IReturn<List<PluginInfo>>
|
||||
{
|
||||
}
|
||||
|
@ -28,6 +29,7 @@ namespace MediaBrowser.Api
|
|||
/// Class UninstallPlugin
|
||||
/// </summary>
|
||||
[Route("/Plugins/{Id}", "DELETE", Summary = "Uninstalls a plugin")]
|
||||
[Authenticated(Roles = "Admin")]
|
||||
public class UninstallPlugin : IReturnVoid
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -42,6 +44,7 @@ namespace MediaBrowser.Api
|
|||
/// Class GetPluginConfiguration
|
||||
/// </summary>
|
||||
[Route("/Plugins/{Id}/Configuration", "GET", Summary = "Gets a plugin's configuration")]
|
||||
[Authenticated]
|
||||
public class GetPluginConfiguration
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -56,6 +59,7 @@ namespace MediaBrowser.Api
|
|||
/// Class UpdatePluginConfiguration
|
||||
/// </summary>
|
||||
[Route("/Plugins/{Id}/Configuration", "POST", Summary = "Updates a plugin's configuration")]
|
||||
[Authenticated]
|
||||
public class UpdatePluginConfiguration : IRequiresRequestStream, IReturnVoid
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -76,6 +80,7 @@ namespace MediaBrowser.Api
|
|||
/// Class GetPluginSecurityInfo
|
||||
/// </summary>
|
||||
[Route("/Plugins/SecurityInfo", "GET", Summary = "Gets plugin registration information")]
|
||||
[Authenticated]
|
||||
public class GetPluginSecurityInfo : IReturn<PluginSecurityInfo>
|
||||
{
|
||||
}
|
||||
|
@ -84,11 +89,13 @@ namespace MediaBrowser.Api
|
|||
/// Class UpdatePluginSecurityInfo
|
||||
/// </summary>
|
||||
[Route("/Plugins/SecurityInfo", "POST", Summary = "Updates plugin registration information")]
|
||||
[Authenticated(Roles = "Admin")]
|
||||
public class UpdatePluginSecurityInfo : PluginSecurityInfo, IReturnVoid
|
||||
{
|
||||
}
|
||||
|
||||
[Route("/Plugins/RegistrationRecords/{Name}", "GET", Summary = "Gets registration status for a feature")]
|
||||
[Authenticated]
|
||||
public class GetRegistrationStatus
|
||||
{
|
||||
[ApiMember(Name = "Name", Description = "Feature Name", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
|
||||
|
@ -101,7 +108,6 @@ namespace MediaBrowser.Api
|
|||
/// <summary>
|
||||
/// Class PluginsService
|
||||
/// </summary>
|
||||
[Authenticated]
|
||||
public class PluginService : BaseApiService
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -118,14 +124,6 @@ namespace MediaBrowser.Api
|
|||
|
||||
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)
|
||||
: base()
|
||||
{
|
||||
|
|
|
@ -79,7 +79,7 @@ namespace MediaBrowser.Api.ScheduledTasks
|
|||
/// <summary>
|
||||
/// Class ScheduledTasksService
|
||||
/// </summary>
|
||||
[Authenticated]
|
||||
[Authenticated(Roles = "Admin")]
|
||||
public class ScheduledTaskService : BaseApiService
|
||||
{
|
||||
/// <summary>
|
||||
|
|
|
@ -241,16 +241,19 @@ namespace MediaBrowser.Api.Session
|
|||
}
|
||||
|
||||
[Route("/Sessions/Logout", "POST", Summary = "Reports that a session has ended")]
|
||||
[Authenticated]
|
||||
public class ReportSessionEnded : IReturnVoid
|
||||
{
|
||||
}
|
||||
|
||||
[Route("/Auth/Keys", "GET")]
|
||||
[Authenticated(Roles = "Admin")]
|
||||
public class GetApiKeys
|
||||
{
|
||||
}
|
||||
|
||||
[Route("/Auth/Keys/{Key}", "DELETE")]
|
||||
[Authenticated(Roles = "Admin")]
|
||||
public class RevokeKey
|
||||
{
|
||||
[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")]
|
||||
[Authenticated(Roles = "Admin")]
|
||||
public class CreateKey
|
||||
{
|
||||
[ApiMember(Name = "App", Description = "App", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
|
||||
|
|
163
MediaBrowser.Api/StartupWizardService.cs
Normal file
163
MediaBrowser.Api/StartupWizardService.cs
Normal file
|
@ -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
|
||||
{
|
||||
[Route("/Videos/{Id}/Subtitles/{Index}", "DELETE", Summary = "Deletes an external subtitle file")]
|
||||
[Authenticated]
|
||||
[Authenticated(Roles = "Admin")]
|
||||
public class DeleteSubtitle
|
||||
{
|
||||
/// <summary>
|
||||
|
|
|
@ -29,7 +29,7 @@ namespace MediaBrowser.Api.System
|
|||
public string MinDate { get; set; }
|
||||
}
|
||||
|
||||
[Authenticated]
|
||||
[Authenticated(Roles = "Admin")]
|
||||
public class ActivityLogService : BaseApiService
|
||||
{
|
||||
private readonly IActivityManager _activityManager;
|
||||
|
|
|
@ -35,7 +35,7 @@ namespace MediaBrowser.Api.System
|
|||
/// Class RestartApplication
|
||||
/// </summary>
|
||||
[Route("/System/Restart", "POST", Summary = "Restarts the application, if needed")]
|
||||
[Authenticated]
|
||||
[Authenticated(Roles = "Admin")]
|
||||
public class RestartApplication
|
||||
{
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ namespace MediaBrowser.Api.System
|
|||
}
|
||||
|
||||
[Route("/System/Logs", "GET", Summary = "Gets a list of available server log files")]
|
||||
[Authenticated]
|
||||
[Authenticated(Roles = "Admin")]
|
||||
public class GetServerLogs : IReturn<List<LogFile>>
|
||||
{
|
||||
}
|
||||
|
@ -64,6 +64,7 @@ namespace MediaBrowser.Api.System
|
|||
}
|
||||
|
||||
[Route("/System/Logs/Log", "GET", Summary = "Gets a log file")]
|
||||
[Authenticated(Roles = "Admin")]
|
||||
public class GetLogFile
|
||||
{
|
||||
[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.Entities;
|
||||
using MediaBrowser.Controller.Entities.TV;
|
||||
|
|
|
@ -13,8 +13,7 @@ using System.Linq;
|
|||
|
||||
namespace MediaBrowser.Api.UserLibrary
|
||||
{
|
||||
[Route("/GameGenres", "GET")]
|
||||
[Api(Description = "Gets all Game genres from a given item, folder, or the entire library")]
|
||||
[Route("/GameGenres", "GET", Summary = "Gets all Game genres from a given item, folder, or the entire library")]
|
||||
public class GetGameGenres : GetItemsByName
|
||||
{
|
||||
public GetGameGenres()
|
||||
|
@ -23,8 +22,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
}
|
||||
}
|
||||
|
||||
[Route("/GameGenres/{Name}", "GET")]
|
||||
[Api(Description = "Gets a Game genre, by name")]
|
||||
[Route("/GameGenres/{Name}", "GET", Summary = "Gets a Game genre, by name")]
|
||||
public class GetGameGenre : IReturn<BaseItemDto>
|
||||
{
|
||||
/// <summary>
|
||||
|
|
|
@ -16,8 +16,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
/// <summary>
|
||||
/// Class GetGenres
|
||||
/// </summary>
|
||||
[Route("/Genres", "GET")]
|
||||
[Api(Description = "Gets all genres from a given item, folder, or the entire library")]
|
||||
[Route("/Genres", "GET", Summary = "Gets all genres from a given item, folder, or the entire library")]
|
||||
public class GetGenres : GetItemsByName
|
||||
{
|
||||
}
|
||||
|
@ -25,8 +24,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
/// <summary>
|
||||
/// Class GetGenre
|
||||
/// </summary>
|
||||
[Route("/Genres/{Name}", "GET")]
|
||||
[Api(Description = "Gets a genre, by name")]
|
||||
[Route("/Genres/{Name}", "GET", Summary = "Gets a genre, by name")]
|
||||
public class GetGenre : IReturn<BaseItemDto>
|
||||
{
|
||||
/// <summary>
|
||||
|
|
|
@ -13,8 +13,7 @@ using System.Linq;
|
|||
|
||||
namespace MediaBrowser.Api.UserLibrary
|
||||
{
|
||||
[Route("/MusicGenres", "GET")]
|
||||
[Api(Description = "Gets all music genres from a given item, folder, or the entire library")]
|
||||
[Route("/MusicGenres", "GET", Summary = "Gets all music genres from a given item, folder, or the entire library")]
|
||||
public class GetMusicGenres : GetItemsByName
|
||||
{
|
||||
public GetMusicGenres()
|
||||
|
@ -23,8 +22,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
}
|
||||
}
|
||||
|
||||
[Route("/MusicGenres/{Name}", "GET")]
|
||||
[Api(Description = "Gets a music genre, by name")]
|
||||
[Route("/MusicGenres/{Name}", "GET", Summary = "Gets a music genre, by name")]
|
||||
public class GetMusicGenre : IReturn<BaseItemDto>
|
||||
{
|
||||
/// <summary>
|
||||
|
|
|
@ -15,8 +15,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
/// <summary>
|
||||
/// Class GetPersons
|
||||
/// </summary>
|
||||
[Route("/Persons", "GET")]
|
||||
[Api(Description = "Gets all persons from a given item, folder, or the entire library")]
|
||||
[Route("/Persons", "GET", Summary = "Gets all persons from a given item, folder, or the entire library")]
|
||||
public class GetPersons : GetItemsByName
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -30,8 +29,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
/// <summary>
|
||||
/// Class GetPerson
|
||||
/// </summary>
|
||||
[Route("/Persons/{Name}", "GET")]
|
||||
[Api(Description = "Gets a person, by name")]
|
||||
[Route("/Persons/{Name}", "GET", Summary = "Gets a person, by name")]
|
||||
public class GetPerson : IReturn<BaseItemDto>
|
||||
{
|
||||
/// <summary>
|
||||
|
|
|
@ -15,8 +15,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
/// <summary>
|
||||
/// Class MarkPlayedItem
|
||||
/// </summary>
|
||||
[Route("/Users/{UserId}/PlayedItems/{Id}", "POST")]
|
||||
[Api(Description = "Marks an item as played")]
|
||||
[Route("/Users/{UserId}/PlayedItems/{Id}", "POST", Summary = "Marks an item as played")]
|
||||
public class MarkPlayedItem : IReturn<UserItemDataDto>
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -40,8 +39,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
/// <summary>
|
||||
/// Class MarkUnplayedItem
|
||||
/// </summary>
|
||||
[Route("/Users/{UserId}/PlayedItems/{Id}", "DELETE")]
|
||||
[Api(Description = "Marks an item as unplayed")]
|
||||
[Route("/Users/{UserId}/PlayedItems/{Id}", "DELETE", Summary = "Marks an item as unplayed")]
|
||||
public class MarkUnplayedItem : IReturn<UserItemDataDto>
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -59,20 +57,17 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
public string Id { get; set; }
|
||||
}
|
||||
|
||||
[Route("/Sessions/Playing", "POST")]
|
||||
[Api(Description = "Reports playback has started within a session")]
|
||||
[Route("/Sessions/Playing", "POST", Summary = "Reports playback has started within a session")]
|
||||
public class ReportPlaybackStart : PlaybackStartInfo, IReturnVoid
|
||||
{
|
||||
}
|
||||
|
||||
[Route("/Sessions/Playing/Progress", "POST")]
|
||||
[Api(Description = "Reports playback progress within a session")]
|
||||
[Route("/Sessions/Playing/Progress", "POST", Summary = "Reports playback progress within a session")]
|
||||
public class ReportPlaybackProgress : PlaybackProgressInfo, IReturnVoid
|
||||
{
|
||||
}
|
||||
|
||||
[Route("/Sessions/Playing/Stopped", "POST")]
|
||||
[Api(Description = "Reports playback has stopped within a session")]
|
||||
[Route("/Sessions/Playing/Stopped", "POST", Summary = "Reports playback has stopped within a session")]
|
||||
public class ReportPlaybackStopped : PlaybackStopInfo, IReturnVoid
|
||||
{
|
||||
}
|
||||
|
@ -80,8 +75,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
/// <summary>
|
||||
/// Class OnPlaybackStart
|
||||
/// </summary>
|
||||
[Route("/Users/{UserId}/PlayingItems/{Id}", "POST")]
|
||||
[Api(Description = "Reports that a user has begun playing an item")]
|
||||
[Route("/Users/{UserId}/PlayingItems/{Id}", "POST", Summary = "Reports that a user has begun playing an item")]
|
||||
public class OnPlaybackStart : IReturnVoid
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -125,8 +119,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
/// <summary>
|
||||
/// Class OnPlaybackProgress
|
||||
/// </summary>
|
||||
[Route("/Users/{UserId}/PlayingItems/{Id}/Progress", "POST")]
|
||||
[Api(Description = "Reports a user's playback progress")]
|
||||
[Route("/Users/{UserId}/PlayingItems/{Id}/Progress", "POST", Summary = "Reports a user's playback progress")]
|
||||
public class OnPlaybackProgress : IReturnVoid
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -172,8 +165,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
/// <summary>
|
||||
/// Class OnPlaybackStopped
|
||||
/// </summary>
|
||||
[Route("/Users/{UserId}/PlayingItems/{Id}", "DELETE")]
|
||||
[Api(Description = "Reports that a user has stopped playing an item")]
|
||||
[Route("/Users/{UserId}/PlayingItems/{Id}", "DELETE", Summary = "Reports that a user has stopped playing an item")]
|
||||
public class OnPlaybackStopped : IReturnVoid
|
||||
{
|
||||
/// <summary>
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
using MediaBrowser.Controller.Dto;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Entities.Movies;
|
||||
using MediaBrowser.Controller.Entities.TV;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Net;
|
||||
|
@ -21,8 +20,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
/// <summary>
|
||||
/// Class GetItem
|
||||
/// </summary>
|
||||
[Route("/Users/{UserId}/Items/{Id}", "GET")]
|
||||
[Api(Description = "Gets an item from a user's library")]
|
||||
[Route("/Users/{UserId}/Items/{Id}", "GET", Summary = "Gets an item from a user's library")]
|
||||
public class GetItem : IReturn<BaseItemDto>
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -57,8 +55,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
/// <summary>
|
||||
/// Class GetItem
|
||||
/// </summary>
|
||||
[Route("/Users/{UserId}/Items/Root", "GET")]
|
||||
[Api(Description = "Gets the root folder from a user's library")]
|
||||
[Route("/Users/{UserId}/Items/Root", "GET", Summary = "Gets the root folder from a user's library")]
|
||||
public class GetRootFolder : IReturn<BaseItemDto>
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -72,8 +69,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
/// <summary>
|
||||
/// Class GetIntros
|
||||
/// </summary>
|
||||
[Route("/Users/{UserId}/Items/{Id}/Intros", "GET")]
|
||||
[Api(("Gets intros to play before the main media item plays"))]
|
||||
[Route("/Users/{UserId}/Items/{Id}/Intros", "GET", Summary = "Gets intros to play before the main media item plays")]
|
||||
public class GetIntros : IReturn<ItemsResult>
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -94,8 +90,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
/// <summary>
|
||||
/// Class MarkFavoriteItem
|
||||
/// </summary>
|
||||
[Route("/Users/{UserId}/FavoriteItems/{Id}", "POST")]
|
||||
[Api(Description = "Marks an item as a favorite")]
|
||||
[Route("/Users/{UserId}/FavoriteItems/{Id}", "POST", Summary = "Marks an item as a favorite")]
|
||||
public class MarkFavoriteItem : IReturn<UserItemDataDto>
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -116,8 +111,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
/// <summary>
|
||||
/// Class UnmarkFavoriteItem
|
||||
/// </summary>
|
||||
[Route("/Users/{UserId}/FavoriteItems/{Id}", "DELETE")]
|
||||
[Api(Description = "Unmarks an item as a favorite")]
|
||||
[Route("/Users/{UserId}/FavoriteItems/{Id}", "DELETE", Summary = "Unmarks an item as a favorite")]
|
||||
public class UnmarkFavoriteItem : IReturn<UserItemDataDto>
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -138,8 +132,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
/// <summary>
|
||||
/// Class ClearUserItemRating
|
||||
/// </summary>
|
||||
[Route("/Users/{UserId}/Items/{Id}/Rating", "DELETE")]
|
||||
[Api(Description = "Deletes a user's saved personal rating for an item")]
|
||||
[Route("/Users/{UserId}/Items/{Id}/Rating", "DELETE", Summary = "Deletes a user's saved personal rating for an item")]
|
||||
public class DeleteUserItemRating : IReturn<UserItemDataDto>
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -160,8 +153,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
/// <summary>
|
||||
/// Class UpdateUserItemRating
|
||||
/// </summary>
|
||||
[Route("/Users/{UserId}/Items/{Id}/Rating", "POST")]
|
||||
[Api(Description = "Updates a user's rating for an item")]
|
||||
[Route("/Users/{UserId}/Items/{Id}/Rating", "POST", Summary = "Updates a user's rating for an item")]
|
||||
public class UpdateUserItemRating : IReturn<UserItemDataDto>
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -189,8 +181,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
/// <summary>
|
||||
/// Class GetLocalTrailers
|
||||
/// </summary>
|
||||
[Route("/Users/{UserId}/Items/{Id}/LocalTrailers", "GET")]
|
||||
[Api(Description = "Gets local trailers for an item")]
|
||||
[Route("/Users/{UserId}/Items/{Id}/LocalTrailers", "GET", Summary = "Gets local trailers for an item")]
|
||||
public class GetLocalTrailers : IReturn<List<BaseItemDto>>
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -211,8 +202,7 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
/// <summary>
|
||||
/// Class GetSpecialFeatures
|
||||
/// </summary>
|
||||
[Route("/Users/{UserId}/Items/{Id}/SpecialFeatures", "GET")]
|
||||
[Api(Description = "Gets special features for an item")]
|
||||
[Route("/Users/{UserId}/Items/{Id}/SpecialFeatures", "GET", Summary = "Gets special features for an item")]
|
||||
public class GetSpecialFeatures : IReturn<List<BaseItemDto>>
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -280,15 +270,6 @@ namespace MediaBrowser.Api.UserLibrary
|
|||
private readonly IDtoService _dtoService;
|
||||
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)
|
||||
{
|
||||
_userManager = userManager;
|
||||
|
|
|
@ -12,7 +12,6 @@ using ServiceStack;
|
|||
using ServiceStack.Text.Controller;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
@ -59,7 +58,7 @@ namespace MediaBrowser.Api
|
|||
/// Class DeleteUser
|
||||
/// </summary>
|
||||
[Route("/Users/{Id}", "DELETE", Summary = "Deletes a user")]
|
||||
[Authenticated]
|
||||
[Authenticated(Roles = "Admin")]
|
||||
public class DeleteUser : IReturnVoid
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -151,25 +150,16 @@ namespace MediaBrowser.Api
|
|||
/// Class UpdateUser
|
||||
/// </summary>
|
||||
[Route("/Users/{Id}", "POST", Summary = "Updates a user")]
|
||||
[Authenticated]
|
||||
[Authenticated(Roles = "Admin")]
|
||||
public class UpdateUser : UserDto, IReturnVoid
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Class CreateUser
|
||||
/// </summary>
|
||||
[Route("/Users", "POST", Summary = "Creates a user")]
|
||||
[Authenticated]
|
||||
public class CreateUser : UserDto, IReturn<UserDto>
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Class CreateUser
|
||||
/// </summary>
|
||||
[Route("/Users/New", "POST", Summary = "Creates a user")]
|
||||
[Authenticated]
|
||||
[Authenticated(Roles = "Admin")]
|
||||
public class CreateUserByName : IReturn<UserDto>
|
||||
{
|
||||
[ApiMember(Name = "Name", IsRequired = true, DataType = "string", ParameterType = "body", Verb = "POST")]
|
||||
|
@ -473,24 +463,6 @@ namespace MediaBrowser.Api
|
|||
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>
|
||||
/// Posts the specified request.
|
||||
/// </summary>
|
||||
|
|
|
@ -15,6 +15,7 @@ using System.Threading.Tasks;
|
|||
namespace MediaBrowser.Api
|
||||
{
|
||||
[Route("/Videos/{Id}/AdditionalParts", "GET", Summary = "Gets additional parts for a video.")]
|
||||
[Authenticated]
|
||||
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")]
|
||||
|
@ -29,6 +30,7 @@ namespace MediaBrowser.Api
|
|||
}
|
||||
|
||||
[Route("/Videos/{Id}/AlternateSources", "DELETE", Summary = "Removes alternate video sources.")]
|
||||
[Authenticated(Roles = "Admin")]
|
||||
public class DeleteAlternateSources : IReturnVoid
|
||||
{
|
||||
[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")]
|
||||
[Authenticated(Roles = "Admin")]
|
||||
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)]
|
||||
public string Ids { get; set; }
|
||||
}
|
||||
|
||||
[Authenticated]
|
||||
public class VideosService : BaseApiService
|
||||
{
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
|
|
|
@ -1618,7 +1618,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
|
||||
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.LiveTvRecordingGroups, user, string.Empty, parent).ConfigureAwait(false));
|
||||
|
||||
|
|
|
@ -220,8 +220,11 @@
|
|||
<Compile Include="Net\IHttpResultFactory.cs" />
|
||||
<Compile Include="Net\IHttpServer.cs" />
|
||||
<Compile Include="Net\IRestfulService.cs" />
|
||||
<Compile Include="Net\IServiceRequest.cs" />
|
||||
<Compile Include="Net\ISessionContext.cs" />
|
||||
<Compile Include="Net\LoggedAttribute.cs" />
|
||||
<Compile Include="Net\SecurityException.cs" />
|
||||
<Compile Include="Net\ServiceStackServiceRequest.cs" />
|
||||
<Compile Include="Net\StaticResultOptions.cs" />
|
||||
<Compile Include="News\INewsService.cs" />
|
||||
<Compile Include="Notifications\INotificationManager.cs" />
|
||||
|
|
|
@ -5,7 +5,7 @@ using System.Linq;
|
|||
|
||||
namespace MediaBrowser.Controller.Net
|
||||
{
|
||||
public class AuthenticatedAttribute : Attribute, IHasRequestFilter, IAuthenticated
|
||||
public class AuthenticatedAttribute : Attribute, IHasRequestFilter, IAuthenticationAttributes
|
||||
{
|
||||
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>
|
||||
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>
|
||||
/// The request filter is executed before the service.
|
||||
/// </summary>
|
||||
|
@ -29,7 +35,9 @@ namespace MediaBrowser.Controller.Net
|
|||
/// <param name="requestDto">The request DTO</param>
|
||||
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>
|
||||
|
@ -60,9 +68,10 @@ namespace MediaBrowser.Controller.Net
|
|||
}
|
||||
}
|
||||
|
||||
public interface IAuthenticated
|
||||
public interface IAuthenticationAttributes
|
||||
{
|
||||
bool EscapeParentalControl { get; }
|
||||
bool AllowBeforeStartupWizard { get; }
|
||||
|
||||
IEnumerable<string> GetRoles();
|
||||
}
|
||||
|
|
|
@ -1,12 +1,9 @@
|
|||
using ServiceStack.Web;
|
||||
|
||||
|
||||
namespace MediaBrowser.Controller.Net
|
||||
{
|
||||
public interface IAuthService
|
||||
{
|
||||
void Authenticate(IRequest request,
|
||||
IResponse response,
|
||||
object requestDto,
|
||||
IAuthenticated authAttribtues);
|
||||
void Authenticate(IServiceRequest request,
|
||||
IAuthenticationAttributes authAttribtues);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using ServiceStack.Web;
|
||||
|
||||
|
||||
namespace MediaBrowser.Controller.Net
|
||||
{
|
||||
public interface IAuthorizationContext
|
||||
|
@ -9,6 +8,13 @@ namespace MediaBrowser.Controller.Net
|
|||
/// </summary>
|
||||
/// <param name="requestContext">The request context.</param>
|
||||
/// <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);
|
||||
}
|
||||
}
|
||||
|
|
15
MediaBrowser.Controller/Net/IServiceRequest.cs
Normal file
15
MediaBrowser.Controller/Net/IServiceRequest.cs
Normal file
|
@ -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.Session;
|
||||
using ServiceStack.Web;
|
||||
|
||||
namespace MediaBrowser.Controller.Net
|
||||
{
|
||||
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>
|
||||
public void RequestFilter(IRequest request, IResponse response, object requestDto)
|
||||
{
|
||||
var serviceRequest = new ServiceStackServiceRequest(request);
|
||||
|
||||
//This code is executed before the service
|
||||
var auth = AuthorizationContext.GetAuthorizationInfo(request);
|
||||
var auth = AuthorizationContext.GetAuthorizationInfo(serviceRequest);
|
||||
|
||||
if (auth != null)
|
||||
{
|
||||
|
|
21
MediaBrowser.Controller/Net/SecurityException.cs
Normal file
21
MediaBrowser.Controller/Net/SecurityException.cs
Normal file
|
@ -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
|
||||
}
|
||||
}
|
62
MediaBrowser.Controller/Net/ServiceStackServiceRequest.cs
Normal file
62
MediaBrowser.Controller/Net/ServiceStackServiceRequest.cs
Normal file
|
@ -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>
|
||||
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>
|
||||
/// Logouts the specified access token.
|
||||
/// </summary>
|
||||
|
|
|
@ -170,7 +170,7 @@ namespace MediaBrowser.Model.Configuration
|
|||
public PeopleMetadataOptions PeopleMetadataOptions { get; set; }
|
||||
public bool FindInternetTrailers { get; set; }
|
||||
|
||||
public string[] InsecureApps6 { get; set; }
|
||||
public string[] InsecureApps7 { get; set; }
|
||||
|
||||
public bool SaveMetadataHidden { get; set; }
|
||||
|
||||
|
@ -222,19 +222,16 @@ namespace MediaBrowser.Model.Configuration
|
|||
|
||||
PeopleMetadataOptions = new PeopleMetadataOptions();
|
||||
|
||||
InsecureApps6 = new[]
|
||||
InsecureApps7 = new[]
|
||||
{
|
||||
"Roku",
|
||||
"Chromecast",
|
||||
"iOS",
|
||||
"Windows Phone",
|
||||
"Windows RT",
|
||||
"Xbmc",
|
||||
"Unknown app",
|
||||
"MediaPortal",
|
||||
"Media Portal",
|
||||
"iPad",
|
||||
"iPhone"
|
||||
"iPhone",
|
||||
"Roku"
|
||||
};
|
||||
|
||||
MetadataOptions = new[]
|
||||
|
|
|
@ -91,7 +91,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer
|
|||
{typeof (ResourceNotFoundException), 404},
|
||||
{typeof (FileNotFoundException), 404},
|
||||
{typeof (DirectoryNotFoundException), 404},
|
||||
{typeof (Implementations.Security.AuthenticationException), 401},
|
||||
{typeof (SecurityException), 401},
|
||||
{typeof (UnauthorizedAccessException), 401}
|
||||
};
|
||||
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.Connect;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Net;
|
||||
using MediaBrowser.Controller.Session;
|
||||
using ServiceStack;
|
||||
using ServiceStack.Auth;
|
||||
using ServiceStack.Web;
|
||||
using MediaBrowser.Controller.Security;
|
||||
using System;
|
||||
using System.Collections.Specialized;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace MediaBrowser.Server.Implementations.HttpServer.Security
|
||||
|
@ -16,61 +14,43 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security
|
|||
{
|
||||
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;
|
||||
_config = config;
|
||||
ConnectManager = connectManager;
|
||||
SessionManager = sessionManager;
|
||||
UserManager = userManager;
|
||||
}
|
||||
|
||||
public IUserManager UserManager { get; private set; }
|
||||
public ISessionManager SessionManager { get; private set; }
|
||||
public IAuthorizationContext AuthorizationContext { 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>
|
||||
/// Redirect the client to a specific URL if authentication failed.
|
||||
/// If this property is null, simply `401 Unauthorized` is returned.
|
||||
/// </summary>
|
||||
public string HtmlRedirect { get; set; }
|
||||
|
||||
public void Authenticate(IRequest request,
|
||||
IResponse response,
|
||||
object requestDto,
|
||||
IAuthenticated authAttribtues)
|
||||
public void Authenticate(IServiceRequest request,
|
||||
IAuthenticationAttributes authAttribtues)
|
||||
{
|
||||
if (HostContext.HasValidAuthSecret(request))
|
||||
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);
|
||||
ValidateUser(request, authAttribtues);
|
||||
}
|
||||
|
||||
private void ValidateUser(IRequest req, IResponse response, IAuthenticated authAttribtues)
|
||||
private void ValidateUser(IServiceRequest request,
|
||||
IAuthenticationAttributes authAttribtues)
|
||||
{
|
||||
// This code is executed before the service
|
||||
var auth = AuthorizationContext.GetAuthorizationInfo(req);
|
||||
var auth = AuthorizationContext.GetAuthorizationInfo(request);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(auth.Token) ||
|
||||
!_config.Configuration.InsecureApps6.Contains(auth.Client ?? string.Empty, StringComparer.OrdinalIgnoreCase))
|
||||
if (!IsExemptFromAuthenticationToken(auth, authAttribtues))
|
||||
{
|
||||
var valid = IsValidConnectKey(auth.Token);
|
||||
|
||||
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))
|
||||
{
|
||||
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.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 &&
|
||||
!authAttribtues.EscapeParentalControl &&
|
||||
!user.IsParentalScheduleAllowed())
|
||||
{
|
||||
response.AddHeader("X-Application-Error-Code", "ParentalControl");
|
||||
throw new AuthenticationException("This user account is not allowed access at this time.");
|
||||
request.AddResponseHeader("X-Application-Error-Code", "ParentalControl");
|
||||
throw new SecurityException("This user account is not allowed access at this time.")
|
||||
{
|
||||
SecurityExceptionType = SecurityExceptionType.ParentalControl
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
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 (user == null || !user.Configuration.IsAdministrator)
|
||||
{
|
||||
throw new ArgumentException("Administrative access is required for this request.");
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(auth.DeviceId) &&
|
||||
!string.IsNullOrWhiteSpace(auth.Client) &&
|
||||
!string.IsNullOrWhiteSpace(auth.Device))
|
||||
throw new SecurityException("User does not have admin access.")
|
||||
{
|
||||
SessionManager.LogSessionActivity(auth.Client,
|
||||
auth.Version,
|
||||
auth.DeviceId,
|
||||
auth.Device,
|
||||
req.RemoteIp,
|
||||
user);
|
||||
SecurityExceptionType = SecurityExceptionType.Unauthenticated
|
||||
};
|
||||
}
|
||||
}
|
||||
if (roles.Contains("delete", StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
if (user == null || !user.Configuration.EnableContentDeletion)
|
||||
{
|
||||
throw new SecurityException("User does not have delete access.")
|
||||
{
|
||||
SecurityExceptionType = SecurityExceptionType.Unauthenticated
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -132,40 +150,34 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security
|
|||
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 (htmlRedirect != null && req.ResponseContentType.MatchesContentType(MimeTypes.Html))
|
||||
if (string.IsNullOrWhiteSpace(token))
|
||||
{
|
||||
DoHtmlRedirect(htmlRedirect, req, res, includeRedirectParam);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
throw new SecurityException("Access token is invalid or expired.");
|
||||
}
|
||||
|
||||
public static void DoHtmlRedirect(string redirectUrl, IRequest req, IResponse res, bool includeRedirectParam)
|
||||
var info = (AuthenticationInfo)request.Items["OriginalAuthenticationInfo"];
|
||||
|
||||
if (info == null)
|
||||
{
|
||||
var url = req.ResolveAbsoluteUrl(redirectUrl);
|
||||
if (includeRedirectParam)
|
||||
{
|
||||
var absoluteRequestPath = req.ResolveAbsoluteUrl("~" + req.PathInfo + ToQueryString(req.QueryString));
|
||||
url = url.AddQueryParam(HostContext.ResolveLocalizedString(LocalizedStrings.Redirect), absoluteRequestPath);
|
||||
throw new SecurityException("Access token is invalid or expired.");
|
||||
}
|
||||
|
||||
res.RedirectToUrl(url);
|
||||
if (!info.IsActive)
|
||||
{
|
||||
throw new SecurityException("Access token has expired.");
|
||||
}
|
||||
|
||||
private static string ToQueryString(INameValueCollection queryStringCollection)
|
||||
{
|
||||
return ToQueryString((NameValueCollection)queryStringCollection.Original);
|
||||
}
|
||||
//if (!string.IsNullOrWhiteSpace(info.UserId))
|
||||
//{
|
||||
// var user = _userManager.GetUserById(info.UserId);
|
||||
|
||||
private static string ToQueryString(NameValueCollection queryStringCollection)
|
||||
{
|
||||
if (queryStringCollection == null || queryStringCollection.Count == 0)
|
||||
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 System.Collections.Generic;
|
||||
using MediaBrowser.Controller.Net;
|
||||
using MediaBrowser.Controller.Net;
|
||||
using MediaBrowser.Controller.Security;
|
||||
using ServiceStack.Web;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace MediaBrowser.Server.Implementations.HttpServer.Security
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -17,7 +38,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security
|
|||
/// </summary>
|
||||
/// <param name="httpReq">The HTTP req.</param>
|
||||
/// <returns>Dictionary{System.StringSystem.String}.</returns>
|
||||
private AuthorizationInfo GetAuthorization(IRequest httpReq)
|
||||
private AuthorizationInfo GetAuthorization(IServiceRequest httpReq)
|
||||
{
|
||||
var auth = GetAuthorizationDictionary(httpReq);
|
||||
|
||||
|
@ -29,7 +50,9 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security
|
|||
|
||||
if (auth != null)
|
||||
{
|
||||
// TODO: Remove this
|
||||
auth.TryGetValue("UserId", out userId);
|
||||
|
||||
auth.TryGetValue("DeviceId", out deviceId);
|
||||
auth.TryGetValue("Device", out device);
|
||||
auth.TryGetValue("Client", out client);
|
||||
|
@ -84,7 +107,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security
|
|||
}
|
||||
}
|
||||
|
||||
return new AuthorizationInfo
|
||||
var info = new AuthorizationInfo
|
||||
{
|
||||
Client = client,
|
||||
Device = device,
|
||||
|
@ -93,6 +116,26 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security
|
|||
Version = version,
|
||||
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>
|
||||
|
@ -100,7 +143,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security
|
|||
/// </summary>
|
||||
/// <param name="httpReq">The HTTP req.</param>
|
||||
/// <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"];
|
||||
|
||||
|
|
|
@ -19,18 +19,30 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security
|
|||
_sessionManager = sessionManager;
|
||||
}
|
||||
|
||||
public SessionInfo GetSession(IRequest requestContext)
|
||||
public SessionInfo GetSession(IServiceRequest requestContext)
|
||||
{
|
||||
var authorization = _authContext.GetAuthorizationInfo(requestContext);
|
||||
|
||||
return _sessionManager.GetSession(authorization.DeviceId, authorization.Client, authorization.Version);
|
||||
}
|
||||
|
||||
public User GetUser(IRequest requestContext)
|
||||
public User GetUser(IServiceRequest requestContext)
|
||||
{
|
||||
var session = GetSession(requestContext);
|
||||
|
||||
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.Entities;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Net;
|
||||
using MediaBrowser.Controller.Persistence;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.Model.Configuration;
|
||||
|
@ -180,12 +181,12 @@ namespace MediaBrowser.Server.Implementations.Library
|
|||
|
||||
if (user == null)
|
||||
{
|
||||
throw new AuthenticationException("Invalid username or password entered.");
|
||||
throw new SecurityException("Invalid username or password entered.");
|
||||
}
|
||||
|
||||
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;
|
||||
|
|
|
@ -247,7 +247,6 @@
|
|||
<Compile Include="ScheduledTasks\RefreshIntrosTask.cs" />
|
||||
<Compile Include="ScheduledTasks\RefreshMediaLibraryTask.cs" />
|
||||
<Compile Include="ScheduledTasks\SystemUpdateTask.cs" />
|
||||
<Compile Include="Security\AuthenticationException.cs" />
|
||||
<Compile Include="Security\AuthenticationRepository.cs" />
|
||||
<Compile Include="Security\EncryptionManager.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.Library;
|
||||
using MediaBrowser.Controller.LiveTv;
|
||||
using MediaBrowser.Controller.Net;
|
||||
using MediaBrowser.Controller.Persistence;
|
||||
using MediaBrowser.Controller.Security;
|
||||
using MediaBrowser.Controller.Session;
|
||||
using MediaBrowser.Model.Connect;
|
||||
using MediaBrowser.Model.Devices;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Events;
|
||||
|
@ -23,7 +23,6 @@ using MediaBrowser.Model.Logging;
|
|||
using MediaBrowser.Model.Serialization;
|
||||
using MediaBrowser.Model.Session;
|
||||
using MediaBrowser.Model.Users;
|
||||
using MediaBrowser.Server.Implementations.Security;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
|
@ -253,11 +252,6 @@ namespace MediaBrowser.Server.Implementations.Session
|
|||
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 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>
|
||||
/// Authenticates the new session.
|
||||
/// </summary>
|
||||
/// <param name="request">The request.</param>
|
||||
/// <returns>Task{SessionInfo}.</returns>
|
||||
/// <exception cref="AuthenticationException">Invalid user or password entered.</exception>
|
||||
/// <exception cref="System.UnauthorizedAccessException">Invalid user or password entered.</exception>
|
||||
/// <exception cref="UnauthorizedAccessException">Invalid user or password entered.</exception>
|
||||
public async Task<AuthenticationResult> AuthenticateNewSession(AuthenticationRequest request)
|
||||
{
|
||||
var user = _userManager.Users
|
||||
|
@ -1315,7 +1271,7 @@ namespace MediaBrowser.Server.Implementations.Session
|
|||
{
|
||||
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);
|
||||
|
|
|
@ -496,10 +496,10 @@ namespace MediaBrowser.Server.Startup.Common
|
|||
RegisterSingleInstance(activityLogRepo);
|
||||
RegisterSingleInstance<IActivityManager>(new ActivityManager(LogManager.GetLogger("ActivityManager"), activityLogRepo, UserManager));
|
||||
|
||||
var authContext = new AuthorizationContext();
|
||||
var authContext = new AuthorizationContext(AuthenticationRepository);
|
||||
RegisterSingleInstance<IAuthorizationContext>(authContext);
|
||||
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));
|
||||
|
||||
|
@ -534,6 +534,8 @@ namespace MediaBrowser.Server.Startup.Common
|
|||
var info = await new FFMpegDownloader(Logger, ApplicationPaths, HttpClient, ZipClient, FileSystemManager)
|
||||
.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);
|
||||
RegisterSingleInstance(MediaEncoder);
|
||||
}
|
||||
|
|
116
MediaBrowser.Server.Startup.Common/FFMpeg/FFmpegValidator.cs
Normal file
116
MediaBrowser.Server.Startup.Common/FFMpeg/FFmpegValidator.cs
Normal file
|
@ -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\FFMpegDownloadInfo.cs" />
|
||||
<Compile Include="FFMpeg\FFMpegInfo.cs" />
|
||||
<Compile Include="FFMpeg\FFmpegValidator.cs" />
|
||||
<Compile Include="INativeApp.cs" />
|
||||
<Compile Include="Migrations\DeprecatePlugins.cs" />
|
||||
<Compile Include="Migrations\IVersionMigration.cs" />
|
||||
|
|
|
@ -195,8 +195,7 @@ namespace MediaBrowser.ServerApplication
|
|||
/// <param name="appPaths">The app paths.</param>
|
||||
private static void BeginLog(ILogger logger, IApplicationPaths appPaths)
|
||||
{
|
||||
logger.Info("Media Browser Server started");
|
||||
ApplicationHost.LogEnvironmentInfo(logger, appPaths);
|
||||
ApplicationHost.LogEnvironmentInfo(logger, appPaths, true);
|
||||
}
|
||||
|
||||
private static readonly TaskCompletionSource<bool> ApplicationTaskCompletionSource = new TaskCompletionSource<bool>();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue