aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MediaBrowser.Api/BaseApiService.cs1
-rw-r--r--MediaBrowser.Api/ConfigurationService.cs17
-rw-r--r--MediaBrowser.Api/Devices/DeviceService.cs9
-rw-r--r--MediaBrowser.Api/DisplayPreferencesService.cs3
-rw-r--r--MediaBrowser.Api/Dlna/DlnaService.cs2
-rw-r--r--MediaBrowser.Api/EnvironmentService.cs2
-rw-r--r--MediaBrowser.Api/Images/ImageByNameService.cs22
-rw-r--r--MediaBrowser.Api/Images/ImageService.cs12
-rw-r--r--MediaBrowser.Api/Images/RemoteImageService.cs102
-rw-r--r--MediaBrowser.Api/ItemLookupService.cs25
-rw-r--r--MediaBrowser.Api/ItemRefreshService.cs3
-rw-r--r--MediaBrowser.Api/Library/FileOrganizationService.cs17
-rw-r--r--MediaBrowser.Api/Library/LibraryService.cs53
-rw-r--r--MediaBrowser.Api/Library/LibraryStructureService.cs5
-rw-r--r--MediaBrowser.Api/LiveTv/LiveTvService.cs1
-rw-r--r--MediaBrowser.Api/LocalizationService.cs2
-rw-r--r--MediaBrowser.Api/MediaBrowser.Api.csproj3
-rw-r--r--MediaBrowser.Api/PackageService.cs2
-rw-r--r--MediaBrowser.Api/PlaylistService.cs1
-rw-r--r--MediaBrowser.Api/PluginService.cs20
-rw-r--r--MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs2
-rw-r--r--MediaBrowser.Api/Session/SessionsService.cs4
-rw-r--r--MediaBrowser.Api/StartupWizardService.cs163
-rw-r--r--MediaBrowser.Api/Subtitles/SubtitleService.cs2
-rw-r--r--MediaBrowser.Api/System/ActivityLogService.cs2
-rw-r--r--MediaBrowser.Api/System/SystemService.cs5
-rw-r--r--MediaBrowser.Api/TvShowsService.cs3
-rw-r--r--MediaBrowser.Api/UserLibrary/GameGenresService.cs6
-rw-r--r--MediaBrowser.Api/UserLibrary/GenresService.cs6
-rw-r--r--MediaBrowser.Api/UserLibrary/MusicGenresService.cs6
-rw-r--r--MediaBrowser.Api/UserLibrary/PersonsService.cs6
-rw-r--r--MediaBrowser.Api/UserLibrary/PlaystateService.cs24
-rw-r--r--MediaBrowser.Api/UserLibrary/UserLibraryService.cs37
-rw-r--r--MediaBrowser.Api/UserService.cs34
-rw-r--r--MediaBrowser.Api/VideosService.cs4
-rw-r--r--MediaBrowser.Controller/Entities/UserViewBuilder.cs2
-rw-r--r--MediaBrowser.Controller/MediaBrowser.Controller.csproj3
-rw-r--r--MediaBrowser.Controller/Net/AuthenticatedAttribute.cs15
-rw-r--r--MediaBrowser.Controller/Net/IAuthService.cs9
-rw-r--r--MediaBrowser.Controller/Net/IAuthorizationContext.cs12
-rw-r--r--MediaBrowser.Controller/Net/IServiceRequest.cs15
-rw-r--r--MediaBrowser.Controller/Net/ISessionContext.cs9
-rw-r--r--MediaBrowser.Controller/Net/LoggedAttribute.cs4
-rw-r--r--MediaBrowser.Controller/Net/SecurityException.cs21
-rw-r--r--MediaBrowser.Controller/Net/ServiceStackServiceRequest.cs62
-rw-r--r--MediaBrowser.Controller/Session/ISessionManager.cs6
-rw-r--r--MediaBrowser.Model/Configuration/ServerConfiguration.cs11
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs2
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs158
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/Security/AuthorizationContext.cs57
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/Security/SessionContext.cs16
-rw-r--r--MediaBrowser.Server.Implementations/Library/UserManager.cs5
-rw-r--r--MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj1
-rw-r--r--MediaBrowser.Server.Implementations/Security/AuthenticationException.cs16
-rw-r--r--MediaBrowser.Server.Implementations/Session/SessionManager.cs48
-rw-r--r--MediaBrowser.Server.Startup.Common/ApplicationHost.cs6
-rw-r--r--MediaBrowser.Server.Startup.Common/FFMpeg/FFmpegValidator.cs116
-rw-r--r--MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj1
-rw-r--r--MediaBrowser.ServerApplication/MainStartup.cs3
59 files changed, 712 insertions, 492 deletions
diff --git a/MediaBrowser.Api/BaseApiService.cs b/MediaBrowser.Api/BaseApiService.cs
index f8379a810..297a13155 100644
--- a/MediaBrowser.Api/BaseApiService.cs
+++ b/MediaBrowser.Api/BaseApiService.cs
@@ -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);
diff --git a/MediaBrowser.Api/ConfigurationService.cs b/MediaBrowser.Api/ConfigurationService.cs
index f6edea86e..5fe606e16 100644
--- a/MediaBrowser.Api/ConfigurationService.cs
+++ b/MediaBrowser.Api/ConfigurationService.cs
@@ -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;
@@ -33,18 +32,18 @@ namespace MediaBrowser.Api
[ApiMember(Name = "Key", Description = "Key", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
public string Key { get; set; }
}
-
+
/// <summary>
/// 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")]
@@ -52,23 +51,23 @@ namespace MediaBrowser.Api
public Stream RequestStream { get; set; }
}
-
+
[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
{
@@ -149,7 +148,7 @@ namespace MediaBrowser.Api
var configurationType = _configurationManager.GetConfigurationType(key);
var configuration = _jsonSerializer.DeserializeFromStream(request.RequestStream, configurationType);
-
+
_configurationManager.SaveConfiguration(key, configuration);
}
diff --git a/MediaBrowser.Api/Devices/DeviceService.cs b/MediaBrowser.Api/Devices/DeviceService.cs
index b873c6a71..0d86d6a5c 100644
--- a/MediaBrowser.Api/Devices/DeviceService.cs
+++ b/MediaBrowser.Api/Devices/DeviceService.cs
@@ -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;
diff --git a/MediaBrowser.Api/DisplayPreferencesService.cs b/MediaBrowser.Api/DisplayPreferencesService.cs
index 9f3a6134e..72b12020d 100644
--- a/MediaBrowser.Api/DisplayPreferencesService.cs
+++ b/MediaBrowser.Api/DisplayPreferencesService.cs
@@ -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")]
diff --git a/MediaBrowser.Api/Dlna/DlnaService.cs b/MediaBrowser.Api/Dlna/DlnaService.cs
index fec6d698a..b6c4f5dfb 100644
--- a/MediaBrowser.Api/Dlna/DlnaService.cs
+++ b/MediaBrowser.Api/Dlna/DlnaService.cs
@@ -43,7 +43,7 @@ namespace MediaBrowser.Api.Dlna
{
}
- [Authenticated]
+ [Authenticated(Roles = "Admin")]
public class DlnaService : BaseApiService
{
private readonly IDlnaManager _dlnaManager;
diff --git a/MediaBrowser.Api/EnvironmentService.cs b/MediaBrowser.Api/EnvironmentService.cs
index 590deff5a..4265d0f9f 100644
--- a/MediaBrowser.Api/EnvironmentService.cs
+++ b/MediaBrowser.Api/EnvironmentService.cs
@@ -87,7 +87,7 @@ namespace MediaBrowser.Api
/// <summary>
/// Class EnvironmentService
/// </summary>
- [Authenticated]
+ [Authenticated(Roles = "Admin")]
public class EnvironmentService : BaseApiService
{
const char UncSeparator = '\\';
diff --git a/MediaBrowser.Api/Images/ImageByNameService.cs b/MediaBrowser.Api/Images/ImageByNameService.cs
index 99d2f144b..b4d5a9949 100644
--- a/MediaBrowser.Api/Images/ImageByNameService.cs
+++ b/MediaBrowser.Api/Images/ImageByNameService.cs
@@ -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>>
{
}
diff --git a/MediaBrowser.Api/Images/ImageService.cs b/MediaBrowser.Api/Images/ImageService.cs
index 326253795..561ce4a5c 100644
--- a/MediaBrowser.Api/Images/ImageService.cs
+++ b/MediaBrowser.Api/Images/ImageService.cs
@@ -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
{
diff --git a/MediaBrowser.Api/Images/RemoteImageService.cs b/MediaBrowser.Api/Images/RemoteImageService.cs
index 235f18296..6d2579ea9 100644
--- a/MediaBrowser.Api/Images/RemoteImageService.cs
+++ b/MediaBrowser.Api/Images/RemoteImageService.cs
@@ -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>
diff --git a/MediaBrowser.Api/ItemLookupService.cs b/MediaBrowser.Api/ItemLookupService.cs
index 846d71802..b19d6c654 100644
--- a/MediaBrowser.Api/ItemLookupService.cs
+++ b/MediaBrowser.Api/ItemLookupService.cs
@@ -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")]
diff --git a/MediaBrowser.Api/ItemRefreshService.cs b/MediaBrowser.Api/ItemRefreshService.cs
index 34e0726f1..152a64c24 100644
--- a/MediaBrowser.Api/ItemRefreshService.cs
+++ b/MediaBrowser.Api/ItemRefreshService.cs
@@ -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")]
diff --git a/MediaBrowser.Api/Library/FileOrganizationService.cs b/MediaBrowser.Api/Library/FileOrganizationService.cs
index adf6a522b..29a982629 100644
--- a/MediaBrowser.Api/Library/FileOrganizationService.cs
+++ b/MediaBrowser.Api/Library/FileOrganizationService.cs
@@ -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;
diff --git a/MediaBrowser.Api/Library/LibraryService.cs b/MediaBrowser.Api/Library/LibraryService.cs
index 231f5e9a6..ec7b1f0b3 100644
--- a/MediaBrowser.Api/Library/LibraryService.cs
+++ b/MediaBrowser.Api/Library/LibraryService.cs
@@ -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>
diff --git a/MediaBrowser.Api/Library/LibraryStructureService.cs b/MediaBrowser.Api/Library/LibraryStructureService.cs
index f56daca1e..ee80d4b73 100644
--- a/MediaBrowser.Api/Library/LibraryStructureService.cs
+++ b/MediaBrowser.Api/Library/LibraryStructureService.cs
@@ -131,11 +131,11 @@ namespace MediaBrowser.Api.Library
/// <value><c>true</c> if [refresh library]; otherwise, <c>false</c>.</value>
public bool RefreshLibrary { get; set; }
}
-
+
/// <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)
diff --git a/MediaBrowser.Api/LiveTv/LiveTvService.cs b/MediaBrowser.Api/LiveTv/LiveTvService.cs
index 906c0d830..3afe72866 100644
--- a/MediaBrowser.Api/LiveTv/LiveTvService.cs
+++ b/MediaBrowser.Api/LiveTv/LiveTvService.cs
@@ -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>
{
}
diff --git a/MediaBrowser.Api/LocalizationService.cs b/MediaBrowser.Api/LocalizationService.cs
index 5696d8df7..a8bb61b73 100644
--- a/MediaBrowser.Api/LocalizationService.cs
+++ b/MediaBrowser.Api/LocalizationService.cs
@@ -43,7 +43,7 @@ namespace MediaBrowser.Api
/// <summary>
/// Class CulturesService
/// </summary>
- [Authenticated]
+ [Authenticated(AllowBeforeStartupWizard = true)]
public class LocalizationService : BaseApiService
{
/// <summary>
diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj
index 5a6e6f545..bc6cba5b9 100644
--- a/MediaBrowser.Api/MediaBrowser.Api.csproj
+++ b/MediaBrowser.Api/MediaBrowser.Api.csproj
@@ -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" />
diff --git a/MediaBrowser.Api/PackageService.cs b/MediaBrowser.Api/PackageService.cs
index 84b42baa3..eebdafc5c 100644
--- a/MediaBrowser.Api/PackageService.cs
+++ b/MediaBrowser.Api/PackageService.cs
@@ -122,7 +122,7 @@ namespace MediaBrowser.Api
/// <summary>
/// Class PackageService
/// </summary>
- [Authenticated]
+ [Authenticated(Roles = "Admin")]
public class PackageService : BaseApiService
{
private readonly IInstallationManager _installationManager;
diff --git a/MediaBrowser.Api/PlaylistService.cs b/MediaBrowser.Api/PlaylistService.cs
index 1318b322a..5325e9c44 100644
--- a/MediaBrowser.Api/PlaylistService.cs
+++ b/MediaBrowser.Api/PlaylistService.cs
@@ -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;
diff --git a/MediaBrowser.Api/PluginService.cs b/MediaBrowser.Api/PluginService.cs
index d6c854734..b4e12184a 100644
--- a/MediaBrowser.Api/PluginService.cs
+++ b/MediaBrowser.Api/PluginService.cs
@@ -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")]
@@ -97,11 +104,10 @@ namespace MediaBrowser.Api
[ApiMember(Name = "Mb2Equivalent", Description = "Optional. The equivalent feature name in MB2", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
public string Mb2Equivalent { get; set; }
}
-
+
/// <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()
{
@@ -151,7 +149,7 @@ namespace MediaBrowser.Api
return ToOptimizedResult(result);
}
-
+
/// <summary>
/// Gets the specified request.
/// </summary>
diff --git a/MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs b/MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs
index 483133c10..a05be024e 100644
--- a/MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs
+++ b/MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs
@@ -79,7 +79,7 @@ namespace MediaBrowser.Api.ScheduledTasks
/// <summary>
/// Class ScheduledTasksService
/// </summary>
- [Authenticated]
+ [Authenticated(Roles = "Admin")]
public class ScheduledTaskService : BaseApiService
{
/// <summary>
diff --git a/MediaBrowser.Api/Session/SessionsService.cs b/MediaBrowser.Api/Session/SessionsService.cs
index 74dccb7af..4d68cbf39 100644
--- a/MediaBrowser.Api/Session/SessionsService.cs
+++ b/MediaBrowser.Api/Session/SessionsService.cs
@@ -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")]
diff --git a/MediaBrowser.Api/StartupWizardService.cs b/MediaBrowser.Api/StartupWizardService.cs
new file mode 100644
index 000000000..fd5019126
--- /dev/null
+++ b/MediaBrowser.Api/StartupWizardService.cs
@@ -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; }
+ }
+}
diff --git a/MediaBrowser.Api/Subtitles/SubtitleService.cs b/MediaBrowser.Api/Subtitles/SubtitleService.cs
index 1d62374bd..a2a93d50e 100644
--- a/MediaBrowser.Api/Subtitles/SubtitleService.cs
+++ b/MediaBrowser.Api/Subtitles/SubtitleService.cs
@@ -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>
diff --git a/MediaBrowser.Api/System/ActivityLogService.cs b/MediaBrowser.Api/System/ActivityLogService.cs
index 8dc3079c7..d24bc99cb 100644
--- a/MediaBrowser.Api/System/ActivityLogService.cs
+++ b/MediaBrowser.Api/System/ActivityLogService.cs
@@ -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;
diff --git a/MediaBrowser.Api/System/SystemService.cs b/MediaBrowser.Api/System/SystemService.cs
index 3b8eb7b6f..0a49cf47c 100644
--- a/MediaBrowser.Api/System/SystemService.cs
+++ b/MediaBrowser.Api/System/SystemService.cs
@@ -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)]
diff --git a/MediaBrowser.Api/TvShowsService.cs b/MediaBrowser.Api/TvShowsService.cs
index f4ea7ef94..2f9bbca47 100644
--- a/MediaBrowser.Api/TvShowsService.cs
+++ b/MediaBrowser.Api/TvShowsService.cs
@@ -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;
diff --git a/MediaBrowser.Api/UserLibrary/GameGenresService.cs b/MediaBrowser.Api/UserLibrary/GameGenresService.cs
index 49e979e55..adc21c362 100644
--- a/MediaBrowser.Api/UserLibrary/GameGenresService.cs
+++ b/MediaBrowser.Api/UserLibrary/GameGenresService.cs
@@ -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>
diff --git a/MediaBrowser.Api/UserLibrary/GenresService.cs b/MediaBrowser.Api/UserLibrary/GenresService.cs
index c8c45c1bb..7b6b18c9c 100644
--- a/MediaBrowser.Api/UserLibrary/GenresService.cs
+++ b/MediaBrowser.Api/UserLibrary/GenresService.cs
@@ -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>
diff --git a/MediaBrowser.Api/UserLibrary/MusicGenresService.cs b/MediaBrowser.Api/UserLibrary/MusicGenresService.cs
index f50f0a0bd..1088ada02 100644
--- a/MediaBrowser.Api/UserLibrary/MusicGenresService.cs
+++ b/MediaBrowser.Api/UserLibrary/MusicGenresService.cs
@@ -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>
diff --git a/MediaBrowser.Api/UserLibrary/PersonsService.cs b/MediaBrowser.Api/UserLibrary/PersonsService.cs
index 5651f2c73..dd80801ee 100644
--- a/MediaBrowser.Api/UserLibrary/PersonsService.cs
+++ b/MediaBrowser.Api/UserLibrary/PersonsService.cs
@@ -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>
diff --git a/MediaBrowser.Api/UserLibrary/PlaystateService.cs b/MediaBrowser.Api/UserLibrary/PlaystateService.cs
index 932ce77d3..fae83e369 100644
--- a/MediaBrowser.Api/UserLibrary/PlaystateService.cs
+++ b/MediaBrowser.Api/UserLibrary/PlaystateService.cs
@@ -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>
diff --git a/MediaBrowser.Api/UserLibrary/UserLibraryService.cs b/MediaBrowser.Api/UserLibrary/UserLibraryService.cs
index 4722df641..fd0e79a21 100644
--- a/MediaBrowser.Api/UserLibrary/UserLibraryService.cs
+++ b/MediaBrowser.Api/UserLibrary/UserLibraryService.cs
@@ -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;
diff --git a/MediaBrowser.Api/UserService.cs b/MediaBrowser.Api/UserService.cs
index 9bd85426d..a8a288b7e 100644
--- a/MediaBrowser.Api/UserService.cs
+++ b/MediaBrowser.Api/UserService.cs
@@ -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,7 +150,7 @@ namespace MediaBrowser.Api
/// Class UpdateUser
/// </summary>
[Route("/Users/{Id}", "POST", Summary = "Updates a user")]
- [Authenticated]
+ [Authenticated(Roles = "Admin")]
public class UpdateUser : UserDto, IReturnVoid
{
}
@@ -159,17 +158,8 @@ namespace MediaBrowser.Api
/// <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")]
@@ -478,24 +468,6 @@ namespace MediaBrowser.Api
/// </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>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
public object Post(CreateUserByName request)
{
var dtoUser = request;
diff --git a/MediaBrowser.Api/VideosService.cs b/MediaBrowser.Api/VideosService.cs
index c964ab458..fbf9cec2e 100644
--- a/MediaBrowser.Api/VideosService.cs
+++ b/MediaBrowser.Api/VideosService.cs
@@ -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;
diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs
index a76a28469..71e26b23c 100644
--- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs
+++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs
@@ -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));
diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
index 69edabfb9..72a8f6016 100644
--- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj
+++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
@@ -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" />
diff --git a/MediaBrowser.Controller/Net/AuthenticatedAttribute.cs b/MediaBrowser.Controller/Net/AuthenticatedAttribute.cs
index 17c91c977..b1bab79c5 100644
--- a/MediaBrowser.Controller/Net/AuthenticatedAttribute.cs
+++ b/MediaBrowser.Controller/Net/AuthenticatedAttribute.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; }
@@ -22,6 +22,12 @@ namespace MediaBrowser.Controller.Net
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>
/// <param name="request">The http request wrapper</param>
@@ -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();
}
diff --git a/MediaBrowser.Controller/Net/IAuthService.cs b/MediaBrowser.Controller/Net/IAuthService.cs
index 9d335566f..dc298c8d9 100644
--- a/MediaBrowser.Controller/Net/IAuthService.cs
+++ b/MediaBrowser.Controller/Net/IAuthService.cs
@@ -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);
}
}
diff --git a/MediaBrowser.Controller/Net/IAuthorizationContext.cs b/MediaBrowser.Controller/Net/IAuthorizationContext.cs
index 9cf562370..bdaed6046 100644
--- a/MediaBrowser.Controller/Net/IAuthorizationContext.cs
+++ b/MediaBrowser.Controller/Net/IAuthorizationContext.cs
@@ -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);
}
}
diff --git a/MediaBrowser.Controller/Net/IServiceRequest.cs b/MediaBrowser.Controller/Net/IServiceRequest.cs
new file mode 100644
index 000000000..e48247362
--- /dev/null
+++ b/MediaBrowser.Controller/Net/IServiceRequest.cs
@@ -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);
+ }
+}
diff --git a/MediaBrowser.Controller/Net/ISessionContext.cs b/MediaBrowser.Controller/Net/ISessionContext.cs
index 31ccd5373..be8d28acc 100644
--- a/MediaBrowser.Controller/Net/ISessionContext.cs
+++ b/MediaBrowser.Controller/Net/ISessionContext.cs
@@ -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);
-
- User GetUser(IRequest requestContext);
+ SessionInfo GetSession(object requestContext);
+ User GetUser(object requestContext);
+
+ SessionInfo GetSession(IServiceRequest requestContext);
+ User GetUser(IServiceRequest requestContext);
}
}
diff --git a/MediaBrowser.Controller/Net/LoggedAttribute.cs b/MediaBrowser.Controller/Net/LoggedAttribute.cs
index ea07b1c7f..d56a015a8 100644
--- a/MediaBrowser.Controller/Net/LoggedAttribute.cs
+++ b/MediaBrowser.Controller/Net/LoggedAttribute.cs
@@ -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)
{
diff --git a/MediaBrowser.Controller/Net/SecurityException.cs b/MediaBrowser.Controller/Net/SecurityException.cs
new file mode 100644
index 000000000..b251ab9a9
--- /dev/null
+++ b/MediaBrowser.Controller/Net/SecurityException.cs
@@ -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
+ }
+}
diff --git a/MediaBrowser.Controller/Net/ServiceStackServiceRequest.cs b/MediaBrowser.Controller/Net/ServiceStackServiceRequest.cs
new file mode 100644
index 000000000..a33e9c1c6
--- /dev/null
+++ b/MediaBrowser.Controller/Net/ServiceStackServiceRequest.cs
@@ -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);
+ }
+ }
+}
diff --git a/MediaBrowser.Controller/Session/ISessionManager.cs b/MediaBrowser.Controller/Session/ISessionManager.cs
index 8bc516887..f0272b335 100644
--- a/MediaBrowser.Controller/Session/ISessionManager.cs
+++ b/MediaBrowser.Controller/Session/ISessionManager.cs
@@ -256,12 +256,6 @@ namespace MediaBrowser.Controller.Session
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>
/// <param name="accessToken">The access token.</param>
diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs
index 5b2208333..c9df615e1 100644
--- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs
+++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs
@@ -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[]
diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs
index a750dd82e..56e2e5247 100644
--- a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs
+++ b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs
@@ -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}
};
diff --git a/MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs b/MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs
index dde61079b..e9a8cc752 100644
--- a/MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs
+++ b/MediaBrowser.Server.Implementations/HttpServer/Security/AuthService.cs
@@ -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
+ };
}
}
- var roles = authAttribtues.GetRoles().ToList();
+ if (!IsExemptFromRoles(auth, authAttribtues))
+ {
+ var roles = authAttribtues.GetRoles().ToList();
+
+ ValidateRoles(roles, user);
+ }
+ }
+
+ private bool IsExemptFromAuthenticationToken(AuthorizationInfo auth, IAuthenticationAttributes authAttribtues)
+ {
+ if (!_config.Configuration.IsStartupWizardCompleted &&
+ authAttribtues.AllowBeforeStartupWizard)
+ {
+ return true;
+ }
+
+ return _config.Configuration.InsecureApps7.Contains(auth.Client ?? string.Empty,
+ StringComparer.OrdinalIgnoreCase);
+ }
+
+ private bool IsExemptFromRoles(AuthorizationInfo auth, IAuthenticationAttributes authAttribtues)
+ {
+ if (!_config.Configuration.IsStartupWizardCompleted &&
+ authAttribtues.AllowBeforeStartupWizard)
+ {
+ return true;
+ }
+
+ return false;
+ }
+ private void ValidateRoles(List<string> roles, User user)
+ {
if (roles.Contains("admin", StringComparer.OrdinalIgnoreCase))
{
if (user == null || !user.Configuration.IsAdministrator)
{
- throw new ArgumentException("Administrative access is required for this request.");
+ throw new SecurityException("User does not have admin access.")
+ {
+ SecurityExceptionType = SecurityExceptionType.Unauthenticated
+ };
}
}
-
- if (!string.IsNullOrWhiteSpace(auth.DeviceId) &&
- !string.IsNullOrWhiteSpace(auth.Client) &&
- !string.IsNullOrWhiteSpace(auth.Device))
+ if (roles.Contains("delete", StringComparer.OrdinalIgnoreCase))
{
- SessionManager.LogSessionActivity(auth.Client,
- auth.Version,
- auth.DeviceId,
- auth.Device,
- req.RemoteIp,
- user);
+ 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;
+ throw new SecurityException("Access token is invalid or expired.");
}
- return false;
- }
- public static void DoHtmlRedirect(string redirectUrl, IRequest req, IResponse res, bool includeRedirectParam)
- {
- var url = req.ResolveAbsoluteUrl(redirectUrl);
- if (includeRedirectParam)
+ var info = (AuthenticationInfo)request.Items["OriginalAuthenticationInfo"];
+
+ if (info == null)
{
- 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);
- }
-
- private static string ToQueryString(INameValueCollection queryStringCollection)
- {
- return ToQueryString((NameValueCollection)queryStringCollection.Original);
- }
+ if (!info.IsActive)
+ {
+ throw new SecurityException("Access token has expired.");
+ }
- private static string ToQueryString(NameValueCollection queryStringCollection)
- {
- if (queryStringCollection == null || queryStringCollection.Count == 0)
- return String.Empty;
+ //if (!string.IsNullOrWhiteSpace(info.UserId))
+ //{
+ // var user = _userManager.GetUserById(info.UserId);
- return "?" + queryStringCollection.ToFormUrlEncoded();
+ // if (user == null || user.Configuration.IsDisabled)
+ // {
+ // throw new SecurityException("User account has been disabled.");
+ // }
+ //}
}
}
}
diff --git a/MediaBrowser.Server.Implementations/HttpServer/Security/AuthorizationContext.cs b/MediaBrowser.Server.Implementations/HttpServer/Security/AuthorizationContext.cs
index 3cc703bbf..4e9899301 100644
--- a/MediaBrowser.Server.Implementations/HttpServer/Security/AuthorizationContext.cs
+++ b/MediaBrowser.Server.Implementations/HttpServer/Security/AuthorizationContext.cs
@@ -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"];
diff --git a/MediaBrowser.Server.Implementations/HttpServer/Security/SessionContext.cs b/MediaBrowser.Server.Implementations/HttpServer/Security/SessionContext.cs
index f67c643c8..9d1ddb7fc 100644
--- a/MediaBrowser.Server.Implementations/HttpServer/Security/SessionContext.cs
+++ b/MediaBrowser.Server.Implementations/HttpServer/Security/SessionContext.cs
@@ -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);
+ }
}
}
diff --git a/MediaBrowser.Server.Implementations/Library/UserManager.cs b/MediaBrowser.Server.Implementations/Library/UserManager.cs
index fa34a2c1f..803fbd454 100644
--- a/MediaBrowser.Server.Implementations/Library/UserManager.cs
+++ b/MediaBrowser.Server.Implementations/Library/UserManager.cs
@@ -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;
diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
index 591dfba49..644b041f9 100644
--- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
+++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
@@ -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" />
diff --git a/MediaBrowser.Server.Implementations/Security/AuthenticationException.cs b/MediaBrowser.Server.Implementations/Security/AuthenticationException.cs
deleted file mode 100644
index f4ba2fb63..000000000
--- a/MediaBrowser.Server.Implementations/Security/AuthenticationException.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-using System;
-
-namespace MediaBrowser.Server.Implementations.Security
-{
- public class AuthenticationException : Exception
- {
- public AuthenticationException(string message)
- : base(message)
- {
- }
-
- public AuthenticationException()
- {
- }
- }
-}
diff --git a/MediaBrowser.Server.Implementations/Session/SessionManager.cs b/MediaBrowser.Server.Implementations/Session/SessionManager.cs
index d6db836cc..1f294c325 100644
--- a/MediaBrowser.Server.Implementations/Session/SessionManager.cs
+++ b/MediaBrowser.Server.Implementations/Session/SessionManager.cs
@@ -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);
diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs
index c4a3562ea..4389dd98c 100644
--- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs
+++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs
@@ -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);
}
diff --git a/MediaBrowser.Server.Startup.Common/FFMpeg/FFmpegValidator.cs b/MediaBrowser.Server.Startup.Common/FFMpeg/FFmpegValidator.cs
new file mode 100644
index 000000000..a2abea13c
--- /dev/null
+++ b/MediaBrowser.Server.Startup.Common/FFMpeg/FFmpegValidator.cs
@@ -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;
+ }
+ }
+ }
+ }
+}
diff --git a/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj b/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj
index 4667fe194..474dadfe2 100644
--- a/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj
+++ b/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj
@@ -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" />
diff --git a/MediaBrowser.ServerApplication/MainStartup.cs b/MediaBrowser.ServerApplication/MainStartup.cs
index 294752efc..ab96f1da1 100644
--- a/MediaBrowser.ServerApplication/MainStartup.cs
+++ b/MediaBrowser.ServerApplication/MainStartup.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>();