aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Api
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.Api')
-rw-r--r--MediaBrowser.Api/BrandingService.cs44
-rw-r--r--MediaBrowser.Api/DisplayPreferencesService.cs101
-rw-r--r--MediaBrowser.Api/ItemLookupService.cs336
-rw-r--r--MediaBrowser.Api/ItemUpdateService.cs396
-rw-r--r--MediaBrowser.Api/PlaylistService.cs217
-rw-r--r--MediaBrowser.Api/Sessions/SessionService.cs499
-rw-r--r--MediaBrowser.Api/SuggestionsService.cs98
-rw-r--r--MediaBrowser.Api/TestService.cs26
-rw-r--r--MediaBrowser.Api/UserService.cs605
-rw-r--r--MediaBrowser.Api/VideosService.cs193
10 files changed, 26 insertions, 2489 deletions
diff --git a/MediaBrowser.Api/BrandingService.cs b/MediaBrowser.Api/BrandingService.cs
deleted file mode 100644
index f4724e774..000000000
--- a/MediaBrowser.Api/BrandingService.cs
+++ /dev/null
@@ -1,44 +0,0 @@
-using MediaBrowser.Common.Configuration;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Model.Branding;
-using MediaBrowser.Model.Services;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api
-{
- [Route("/Branding/Configuration", "GET", Summary = "Gets branding configuration")]
- public class GetBrandingOptions : IReturn<BrandingOptions>
- {
- }
-
- [Route("/Branding/Css", "GET", Summary = "Gets custom css")]
- [Route("/Branding/Css.css", "GET", Summary = "Gets custom css")]
- public class GetBrandingCss
- {
- }
-
- public class BrandingService : BaseApiService
- {
- public BrandingService(
- ILogger<BrandingService> logger,
- IServerConfigurationManager serverConfigurationManager,
- IHttpResultFactory httpResultFactory)
- : base(logger, serverConfigurationManager, httpResultFactory)
- {
- }
-
- public object Get(GetBrandingOptions request)
- {
- return ServerConfigurationManager.GetConfiguration<BrandingOptions>("branding");
- }
-
- public object Get(GetBrandingCss request)
- {
- var result = ServerConfigurationManager.GetConfiguration<BrandingOptions>("branding");
-
- // When null this throws a 405 error under Mono OSX, so default to empty string
- return ResultFactory.GetResult(Request, result.CustomCss ?? string.Empty, "text/css");
- }
- }
-}
diff --git a/MediaBrowser.Api/DisplayPreferencesService.cs b/MediaBrowser.Api/DisplayPreferencesService.cs
deleted file mode 100644
index 62c4ff43f..000000000
--- a/MediaBrowser.Api/DisplayPreferencesService.cs
+++ /dev/null
@@ -1,101 +0,0 @@
-using System.Threading;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Controller.Persistence;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Serialization;
-using MediaBrowser.Model.Services;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api
-{
- /// <summary>
- /// Class UpdateDisplayPreferences
- /// </summary>
- [Route("/DisplayPreferences/{DisplayPreferencesId}", "POST", Summary = "Updates a user's display preferences for an item")]
- public class UpdateDisplayPreferences : DisplayPreferences, IReturnVoid
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "DisplayPreferencesId", Description = "DisplayPreferences Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string DisplayPreferencesId { get; set; }
-
- [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string UserId { get; set; }
- }
-
- [Route("/DisplayPreferences/{Id}", "GET", Summary = "Gets a user's display preferences for an item")]
- public class GetDisplayPreferences : IReturn<DisplayPreferences>
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string Id { get; set; }
-
- [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string UserId { get; set; }
-
- [ApiMember(Name = "Client", Description = "Client", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string Client { get; set; }
- }
-
- /// <summary>
- /// Class DisplayPreferencesService
- /// </summary>
- [Authenticated]
- public class DisplayPreferencesService : BaseApiService
- {
- /// <summary>
- /// The _display preferences manager
- /// </summary>
- private readonly IDisplayPreferencesRepository _displayPreferencesManager;
- /// <summary>
- /// The _json serializer
- /// </summary>
- private readonly IJsonSerializer _jsonSerializer;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="DisplayPreferencesService" /> class.
- /// </summary>
- /// <param name="jsonSerializer">The json serializer.</param>
- /// <param name="displayPreferencesManager">The display preferences manager.</param>
- public DisplayPreferencesService(
- ILogger<DisplayPreferencesService> logger,
- IServerConfigurationManager serverConfigurationManager,
- IHttpResultFactory httpResultFactory,
- IJsonSerializer jsonSerializer,
- IDisplayPreferencesRepository displayPreferencesManager)
- : base(logger, serverConfigurationManager, httpResultFactory)
- {
- _jsonSerializer = jsonSerializer;
- _displayPreferencesManager = displayPreferencesManager;
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- public object Get(GetDisplayPreferences request)
- {
- var result = _displayPreferencesManager.GetDisplayPreferences(request.Id, request.UserId, request.Client);
-
- return ToOptimizedResult(result);
- }
-
- /// <summary>
- /// Posts the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- public void Post(UpdateDisplayPreferences request)
- {
- // Serialize to json and then back so that the core doesn't see the request dto type
- var displayPreferences = _jsonSerializer.DeserializeFromString<DisplayPreferences>(_jsonSerializer.SerializeToString(request));
-
- _displayPreferencesManager.SaveDisplayPreferences(displayPreferences, request.UserId, request.Client, CancellationToken.None);
- }
- }
-}
diff --git a/MediaBrowser.Api/ItemLookupService.cs b/MediaBrowser.Api/ItemLookupService.cs
deleted file mode 100644
index 68e3dfa59..000000000
--- a/MediaBrowser.Api/ItemLookupService.cs
+++ /dev/null
@@ -1,336 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using MediaBrowser.Common.Extensions;
-using MediaBrowser.Controller;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.Audio;
-using MediaBrowser.Controller.Entities.Movies;
-using MediaBrowser.Controller.Entities.TV;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.IO;
-using MediaBrowser.Model.Providers;
-using MediaBrowser.Model.Serialization;
-using MediaBrowser.Model.Services;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api
-{
- [Route("/Items/{Id}/ExternalIdInfos", "GET", Summary = "Gets external id infos for an item")]
- [Authenticated(Roles = "Admin")]
- public class GetExternalIdInfos : IReturn<List<ExternalIdInfo>>
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public Guid Id { get; set; }
- }
-
- [Route("/Items/RemoteSearch/Movie", "POST")]
- [Authenticated]
- public class GetMovieRemoteSearchResults : RemoteSearchQuery<MovieInfo>, IReturn<List<RemoteSearchResult>>
- {
- }
-
- [Route("/Items/RemoteSearch/Trailer", "POST")]
- [Authenticated]
- public class GetTrailerRemoteSearchResults : RemoteSearchQuery<TrailerInfo>, IReturn<List<RemoteSearchResult>>
- {
- }
-
- [Route("/Items/RemoteSearch/MusicVideo", "POST")]
- [Authenticated]
- public class GetMusicVideoRemoteSearchResults : RemoteSearchQuery<MusicVideoInfo>, IReturn<List<RemoteSearchResult>>
- {
- }
-
- [Route("/Items/RemoteSearch/Series", "POST")]
- [Authenticated]
- public class GetSeriesRemoteSearchResults : RemoteSearchQuery<SeriesInfo>, IReturn<List<RemoteSearchResult>>
- {
- }
-
- [Route("/Items/RemoteSearch/BoxSet", "POST")]
- [Authenticated]
- public class GetBoxSetRemoteSearchResults : RemoteSearchQuery<BoxSetInfo>, IReturn<List<RemoteSearchResult>>
- {
- }
-
- [Route("/Items/RemoteSearch/MusicArtist", "POST")]
- [Authenticated]
- public class GetMusicArtistRemoteSearchResults : RemoteSearchQuery<ArtistInfo>, IReturn<List<RemoteSearchResult>>
- {
- }
-
- [Route("/Items/RemoteSearch/MusicAlbum", "POST")]
- [Authenticated]
- public class GetMusicAlbumRemoteSearchResults : RemoteSearchQuery<AlbumInfo>, IReturn<List<RemoteSearchResult>>
- {
- }
-
- [Route("/Items/RemoteSearch/Person", "POST")]
- [Authenticated(Roles = "Admin")]
- public class GetPersonRemoteSearchResults : RemoteSearchQuery<PersonLookupInfo>, IReturn<List<RemoteSearchResult>>
- {
- }
-
- [Route("/Items/RemoteSearch/Book", "POST")]
- [Authenticated]
- public class GetBookRemoteSearchResults : RemoteSearchQuery<BookInfo>, IReturn<List<RemoteSearchResult>>
- {
- }
-
- [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")]
- public string ImageUrl { get; set; }
-
- [ApiMember(Name = "ProviderName", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string ProviderName { get; set; }
- }
-
- [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 = "POST")]
- public string Id { get; set; }
-
- [ApiMember(Name = "ReplaceAllImages", Description = "Whether or not to replace all images", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "POST")]
- public bool ReplaceAllImages { get; set; }
-
- public ApplySearchCriteria()
- {
- ReplaceAllImages = true;
- }
- }
-
- public class ItemLookupService : BaseApiService
- {
- private readonly IProviderManager _providerManager;
- private readonly IServerApplicationPaths _appPaths;
- private readonly IFileSystem _fileSystem;
- private readonly ILibraryManager _libraryManager;
- private readonly IJsonSerializer _json;
-
- public ItemLookupService(
- ILogger<ItemLookupService> logger,
- IServerConfigurationManager serverConfigurationManager,
- IHttpResultFactory httpResultFactory,
- IProviderManager providerManager,
- IFileSystem fileSystem,
- ILibraryManager libraryManager,
- IJsonSerializer json)
- : base(logger, serverConfigurationManager, httpResultFactory)
- {
- _providerManager = providerManager;
- _appPaths = serverConfigurationManager.ApplicationPaths;
- _fileSystem = fileSystem;
- _libraryManager = libraryManager;
- _json = json;
- }
-
- public object Get(GetExternalIdInfos request)
- {
- var item = _libraryManager.GetItemById(request.Id);
-
- var infos = _providerManager.GetExternalIdInfos(item).ToList();
-
- return ToOptimizedResult(infos);
- }
-
- public async Task<object> Post(GetTrailerRemoteSearchResults request)
- {
- var result = await _providerManager.GetRemoteSearchResults<Trailer, TrailerInfo>(request, CancellationToken.None).ConfigureAwait(false);
-
- return ToOptimizedResult(result);
- }
-
- public async Task<object> Post(GetBookRemoteSearchResults request)
- {
- var result = await _providerManager.GetRemoteSearchResults<Book, BookInfo>(request, CancellationToken.None).ConfigureAwait(false);
-
- return ToOptimizedResult(result);
- }
-
- public async Task<object> Post(GetMovieRemoteSearchResults request)
- {
- var result = await _providerManager.GetRemoteSearchResults<Movie, MovieInfo>(request, CancellationToken.None).ConfigureAwait(false);
-
- return ToOptimizedResult(result);
- }
-
- public async Task<object> Post(GetSeriesRemoteSearchResults request)
- {
- var result = await _providerManager.GetRemoteSearchResults<Series, SeriesInfo>(request, CancellationToken.None).ConfigureAwait(false);
-
- return ToOptimizedResult(result);
- }
-
- public async Task<object> Post(GetBoxSetRemoteSearchResults request)
- {
- var result = await _providerManager.GetRemoteSearchResults<BoxSet, BoxSetInfo>(request, CancellationToken.None).ConfigureAwait(false);
-
- return ToOptimizedResult(result);
- }
-
- public async Task<object> Post(GetMusicVideoRemoteSearchResults request)
- {
- var result = await _providerManager.GetRemoteSearchResults<MusicVideo, MusicVideoInfo>(request, CancellationToken.None).ConfigureAwait(false);
-
- return ToOptimizedResult(result);
- }
-
- public async Task<object> Post(GetPersonRemoteSearchResults request)
- {
- var result = await _providerManager.GetRemoteSearchResults<Person, PersonLookupInfo>(request, CancellationToken.None).ConfigureAwait(false);
-
- return ToOptimizedResult(result);
- }
-
- public async Task<object> Post(GetMusicAlbumRemoteSearchResults request)
- {
- var result = await _providerManager.GetRemoteSearchResults<MusicAlbum, AlbumInfo>(request, CancellationToken.None).ConfigureAwait(false);
-
- return ToOptimizedResult(result);
- }
-
- public async Task<object> Post(GetMusicArtistRemoteSearchResults request)
- {
- var result = await _providerManager.GetRemoteSearchResults<MusicArtist, ArtistInfo>(request, CancellationToken.None).ConfigureAwait(false);
-
- return ToOptimizedResult(result);
- }
-
- public Task<object> Get(GetRemoteSearchImage request)
- {
- return GetRemoteImage(request);
- }
-
- public Task Post(ApplySearchCriteria request)
- {
- var item = _libraryManager.GetItemById(new Guid(request.Id));
-
- //foreach (var key in request.ProviderIds)
- //{
- // var value = key.Value;
-
- // if (!string.IsNullOrWhiteSpace(value))
- // {
- // item.SetProviderId(key.Key, value);
- // }
- //}
- Logger.LogInformation("Setting provider id's to item {0}-{1}: {2}", item.Id, item.Name, _json.SerializeToString(request.ProviderIds));
-
- // Since the refresh process won't erase provider Ids, we need to set this explicitly now.
- item.ProviderIds = request.ProviderIds;
- //item.ProductionYear = request.ProductionYear;
- //item.Name = request.Name;
-
- return _providerManager.RefreshFullItem(
- item,
- new MetadataRefreshOptions(new DirectoryService(_fileSystem))
- {
- MetadataRefreshMode = MetadataRefreshMode.FullRefresh,
- ImageRefreshMode = MetadataRefreshMode.FullRefresh,
- ReplaceAllMetadata = true,
- ReplaceAllImages = request.ReplaceAllImages,
- SearchResult = request
- },
- CancellationToken.None);
- }
-
- /// <summary>
- /// Gets the remote image.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>Task{System.Object}.</returns>
- private async Task<object> GetRemoteImage(GetRemoteSearchImage request)
- {
- var urlHash = request.ImageUrl.GetMD5();
- var pointerCachePath = GetFullCachePath(urlHash.ToString());
-
- string contentPath;
-
- try
- {
- contentPath = File.ReadAllText(pointerCachePath);
-
- if (File.Exists(contentPath))
- {
- return await ResultFactory.GetStaticFileResult(Request, contentPath).ConfigureAwait(false);
- }
- }
- catch (FileNotFoundException)
- {
- // Means the file isn't cached yet
- }
- catch (IOException)
- {
- // Means the file isn't cached yet
- }
-
- await DownloadImage(request.ProviderName, request.ImageUrl, urlHash, pointerCachePath).ConfigureAwait(false);
-
- // Read the pointer file again
- contentPath = File.ReadAllText(pointerCachePath);
-
- return await ResultFactory.GetStaticFileResult(Request, contentPath).ConfigureAwait(false);
- }
-
- /// <summary>
- /// Downloads the image.
- /// </summary>
- /// <param name="providerName">Name of the provider.</param>
- /// <param name="url">The URL.</param>
- /// <param name="urlHash">The URL hash.</param>
- /// <param name="pointerCachePath">The pointer cache path.</param>
- /// <returns>Task.</returns>
- private async Task DownloadImage(string providerName, string url, Guid urlHash, string pointerCachePath)
- {
- var result = await _providerManager.GetSearchImage(providerName, url, CancellationToken.None).ConfigureAwait(false);
-
- var ext = result.ContentType.Split('/')[^1];
-
- var fullCachePath = GetFullCachePath(urlHash + "." + ext);
-
- Directory.CreateDirectory(Path.GetDirectoryName(fullCachePath));
- var stream = result.Content;
-
- await using (stream.ConfigureAwait(false))
- {
- var fileStream = new FileStream(
- fullCachePath,
- FileMode.Create,
- FileAccess.Write,
- FileShare.Read,
- IODefaults.FileStreamBufferSize,
- true);
- await using (fileStream.ConfigureAwait(false))
- {
- await stream.CopyToAsync(fileStream).ConfigureAwait(false);
- }
- }
-
- Directory.CreateDirectory(Path.GetDirectoryName(pointerCachePath));
- File.WriteAllText(pointerCachePath, fullCachePath);
- }
-
- /// <summary>
- /// Gets the full cache path.
- /// </summary>
- /// <param name="filename">The filename.</param>
- /// <returns>System.String.</returns>
- private string GetFullCachePath(string filename)
- => Path.Combine(_appPaths.CachePath, "remote-images", filename.Substring(0, 1), filename);
- }
-}
diff --git a/MediaBrowser.Api/ItemUpdateService.cs b/MediaBrowser.Api/ItemUpdateService.cs
deleted file mode 100644
index 2db6d717a..000000000
--- a/MediaBrowser.Api/ItemUpdateService.cs
+++ /dev/null
@@ -1,396 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Entities;
-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.Providers;
-using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Globalization;
-using MediaBrowser.Model.IO;
-using MediaBrowser.Model.Services;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api
-{
- [Route("/Items/{ItemId}", "POST", Summary = "Updates an item")]
- public class UpdateItem : BaseItemDto, IReturnVoid
- {
- [ApiMember(Name = "ItemId", Description = "The id of the item", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string ItemId { get; set; }
- }
-
- [Route("/Items/{ItemId}/MetadataEditor", "GET", Summary = "Gets metadata editor info for an item")]
- public class GetMetadataEditorInfo : IReturn<MetadataEditorInfo>
- {
- [ApiMember(Name = "ItemId", Description = "The id of the item", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string ItemId { get; set; }
- }
-
- [Route("/Items/{ItemId}/ContentType", "POST", Summary = "Updates an item's content type")]
- public class UpdateItemContentType : IReturnVoid
- {
- [ApiMember(Name = "ItemId", Description = "The id of the item", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public Guid ItemId { get; set; }
-
- [ApiMember(Name = "ContentType", Description = "The content type of the item", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string ContentType { get; set; }
- }
-
- [Authenticated(Roles = "admin")]
- public class ItemUpdateService : BaseApiService
- {
- private readonly ILibraryManager _libraryManager;
- private readonly IProviderManager _providerManager;
- private readonly ILocalizationManager _localizationManager;
- private readonly IFileSystem _fileSystem;
-
- public ItemUpdateService(
- ILogger<ItemUpdateService> logger,
- IServerConfigurationManager serverConfigurationManager,
- IHttpResultFactory httpResultFactory,
- IFileSystem fileSystem,
- ILibraryManager libraryManager,
- IProviderManager providerManager,
- ILocalizationManager localizationManager)
- : base(logger, serverConfigurationManager, httpResultFactory)
- {
- _libraryManager = libraryManager;
- _providerManager = providerManager;
- _localizationManager = localizationManager;
- _fileSystem = fileSystem;
- }
-
- public object Get(GetMetadataEditorInfo request)
- {
- var item = _libraryManager.GetItemById(request.ItemId);
-
- var info = new MetadataEditorInfo
- {
- ParentalRatingOptions = _localizationManager.GetParentalRatings().ToArray(),
- ExternalIdInfos = _providerManager.GetExternalIdInfos(item).ToArray(),
- Countries = _localizationManager.GetCountries().ToArray(),
- Cultures = _localizationManager.GetCultures().ToArray()
- };
-
- if (!item.IsVirtualItem && !(item is ICollectionFolder) && !(item is UserView) && !(item is AggregateFolder) && !(item is LiveTvChannel) && !(item is IItemByName) &&
- item.SourceType == SourceType.Library)
- {
- var inheritedContentType = _libraryManager.GetInheritedContentType(item);
- var configuredContentType = _libraryManager.GetConfiguredContentType(item);
-
- if (string.IsNullOrWhiteSpace(inheritedContentType) || !string.IsNullOrWhiteSpace(configuredContentType))
- {
- info.ContentTypeOptions = GetContentTypeOptions(true).ToArray();
- info.ContentType = configuredContentType;
-
- if (string.IsNullOrWhiteSpace(inheritedContentType) || string.Equals(inheritedContentType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase))
- {
- info.ContentTypeOptions = info.ContentTypeOptions
- .Where(i => string.IsNullOrWhiteSpace(i.Value) || string.Equals(i.Value, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase))
- .ToArray();
- }
- }
- }
-
- return ToOptimizedResult(info);
- }
-
- public void Post(UpdateItemContentType request)
- {
- var item = _libraryManager.GetItemById(request.ItemId);
- var path = item.ContainingFolderPath;
-
- var types = ServerConfigurationManager.Configuration.ContentTypes
- .Where(i => !string.IsNullOrWhiteSpace(i.Name))
- .Where(i => !string.Equals(i.Name, path, StringComparison.OrdinalIgnoreCase))
- .ToList();
-
- if (!string.IsNullOrWhiteSpace(request.ContentType))
- {
- types.Add(new NameValuePair
- {
- Name = path,
- Value = request.ContentType
- });
- }
-
- ServerConfigurationManager.Configuration.ContentTypes = types.ToArray();
- ServerConfigurationManager.SaveConfiguration();
- }
-
- private List<NameValuePair> GetContentTypeOptions(bool isForItem)
- {
- var list = new List<NameValuePair>();
-
- if (isForItem)
- {
- list.Add(new NameValuePair
- {
- Name = "Inherit",
- Value = ""
- });
- }
-
- list.Add(new NameValuePair
- {
- Name = "Movies",
- Value = "movies"
- });
- list.Add(new NameValuePair
- {
- Name = "Music",
- Value = "music"
- });
- list.Add(new NameValuePair
- {
- Name = "Shows",
- Value = "tvshows"
- });
-
- if (!isForItem)
- {
- list.Add(new NameValuePair
- {
- Name = "Books",
- Value = "books"
- });
- }
-
- list.Add(new NameValuePair
- {
- Name = "HomeVideos",
- Value = "homevideos"
- });
- list.Add(new NameValuePair
- {
- Name = "MusicVideos",
- Value = "musicvideos"
- });
- list.Add(new NameValuePair
- {
- Name = "Photos",
- Value = "photos"
- });
-
- if (!isForItem)
- {
- list.Add(new NameValuePair
- {
- Name = "MixedContent",
- Value = ""
- });
- }
-
- foreach (var val in list)
- {
- val.Name = _localizationManager.GetLocalizedString(val.Name);
- }
-
- return list;
- }
-
- public void Post(UpdateItem request)
- {
- var item = _libraryManager.GetItemById(request.ItemId);
-
- var newLockData = request.LockData ?? false;
- var isLockedChanged = item.IsLocked != newLockData;
-
- var series = item as Series;
- var displayOrderChanged = series != null && !string.Equals(series.DisplayOrder ?? string.Empty, request.DisplayOrder ?? string.Empty, StringComparison.OrdinalIgnoreCase);
-
- // Do this first so that metadata savers can pull the updates from the database.
- if (request.People != null)
- {
- _libraryManager.UpdatePeople(item, request.People.Select(x => new PersonInfo { Name = x.Name, Role = x.Role, Type = x.Type }).ToList());
- }
-
- UpdateItem(request, item);
-
- item.OnMetadataChanged();
-
- item.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None);
-
- if (isLockedChanged && item.IsFolder)
- {
- var folder = (Folder)item;
-
- foreach (var child in folder.GetRecursiveChildren())
- {
- child.IsLocked = newLockData;
- child.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None);
- }
- }
-
- if (displayOrderChanged)
- {
- _providerManager.QueueRefresh(
- series.Id,
- new MetadataRefreshOptions(new DirectoryService(_fileSystem))
- {
- MetadataRefreshMode = MetadataRefreshMode.FullRefresh,
- ImageRefreshMode = MetadataRefreshMode.FullRefresh,
- ReplaceAllMetadata = true
- },
- RefreshPriority.High);
- }
- }
-
- private DateTime NormalizeDateTime(DateTime val)
- {
- return DateTime.SpecifyKind(val, DateTimeKind.Utc);
- }
-
- private void UpdateItem(BaseItemDto request, BaseItem item)
- {
- item.Name = request.Name;
- item.ForcedSortName = request.ForcedSortName;
-
- item.OriginalTitle = string.IsNullOrWhiteSpace(request.OriginalTitle) ? null : request.OriginalTitle;
-
- item.CriticRating = request.CriticRating;
-
- item.CommunityRating = request.CommunityRating;
- item.IndexNumber = request.IndexNumber;
- item.ParentIndexNumber = request.ParentIndexNumber;
- item.Overview = request.Overview;
- item.Genres = request.Genres;
-
- if (item is Episode episode)
- {
- episode.AirsAfterSeasonNumber = request.AirsAfterSeasonNumber;
- episode.AirsBeforeEpisodeNumber = request.AirsBeforeEpisodeNumber;
- episode.AirsBeforeSeasonNumber = request.AirsBeforeSeasonNumber;
- }
-
- item.Tags = request.Tags;
-
- if (request.Taglines != null)
- {
- item.Tagline = request.Taglines.FirstOrDefault();
- }
-
- if (request.Studios != null)
- {
- item.Studios = request.Studios.Select(x => x.Name).ToArray();
- }
-
- if (request.DateCreated.HasValue)
- {
- item.DateCreated = NormalizeDateTime(request.DateCreated.Value);
- }
-
- item.EndDate = request.EndDate.HasValue ? NormalizeDateTime(request.EndDate.Value) : (DateTime?)null;
- item.PremiereDate = request.PremiereDate.HasValue ? NormalizeDateTime(request.PremiereDate.Value) : (DateTime?)null;
- item.ProductionYear = request.ProductionYear;
- item.OfficialRating = string.IsNullOrWhiteSpace(request.OfficialRating) ? null : request.OfficialRating;
- item.CustomRating = request.CustomRating;
-
- if (request.ProductionLocations != null)
- {
- item.ProductionLocations = request.ProductionLocations;
- }
-
- item.PreferredMetadataCountryCode = request.PreferredMetadataCountryCode;
- item.PreferredMetadataLanguage = request.PreferredMetadataLanguage;
-
- if (item is IHasDisplayOrder hasDisplayOrder)
- {
- hasDisplayOrder.DisplayOrder = request.DisplayOrder;
- }
-
- if (item is IHasAspectRatio hasAspectRatio)
- {
- hasAspectRatio.AspectRatio = request.AspectRatio;
- }
-
- item.IsLocked = request.LockData ?? false;
-
- if (request.LockedFields != null)
- {
- item.LockedFields = request.LockedFields;
- }
-
- // Only allow this for series. Runtimes for media comes from ffprobe.
- if (item is Series)
- {
- item.RunTimeTicks = request.RunTimeTicks;
- }
-
- foreach (var pair in request.ProviderIds.ToList())
- {
- if (string.IsNullOrEmpty(pair.Value))
- {
- request.ProviderIds.Remove(pair.Key);
- }
- }
-
- item.ProviderIds = request.ProviderIds;
-
- if (item is Video video)
- {
- video.Video3DFormat = request.Video3DFormat;
- }
-
- if (request.AlbumArtists != null)
- {
- if (item is IHasAlbumArtist hasAlbumArtists)
- {
- hasAlbumArtists.AlbumArtists = request
- .AlbumArtists
- .Select(i => i.Name)
- .ToArray();
- }
- }
-
- if (request.ArtistItems != null)
- {
- if (item is IHasArtist hasArtists)
- {
- hasArtists.Artists = request
- .ArtistItems
- .Select(i => i.Name)
- .ToArray();
- }
- }
-
- if (item is Audio song)
- {
- song.Album = request.Album;
- }
-
- if (item is MusicVideo musicVideo)
- {
- musicVideo.Album = request.Album;
- }
-
- if (item is Series series)
- {
- series.Status = GetSeriesStatus(request);
-
- if (request.AirDays != null)
- {
- series.AirDays = request.AirDays;
- series.AirTime = request.AirTime;
- }
- }
- }
-
- private SeriesStatus? GetSeriesStatus(BaseItemDto item)
- {
- if (string.IsNullOrEmpty(item.Status))
- {
- return null;
- }
-
- return (SeriesStatus)Enum.Parse(typeof(SeriesStatus), item.Status, true);
- }
- }
-}
diff --git a/MediaBrowser.Api/PlaylistService.cs b/MediaBrowser.Api/PlaylistService.cs
deleted file mode 100644
index 953b00e35..000000000
--- a/MediaBrowser.Api/PlaylistService.cs
+++ /dev/null
@@ -1,217 +0,0 @@
-using System;
-using System.Linq;
-using System.Threading.Tasks;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Dto;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Controller.Playlists;
-using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.Playlists;
-using MediaBrowser.Model.Querying;
-using MediaBrowser.Model.Services;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api
-{
- [Route("/Playlists", "POST", Summary = "Creates a new playlist")]
- public class CreatePlaylist : IReturn<PlaylistCreationResult>
- {
- [ApiMember(Name = "Name", Description = "The name of the new playlist.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string Name { get; set; }
-
- [ApiMember(Name = "Ids", Description = "Item Ids to add to the playlist", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST", AllowMultiple = true)]
- public string Ids { get; set; }
-
- [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public Guid UserId { get; set; }
-
- [ApiMember(Name = "MediaType", Description = "The playlist media type", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string MediaType { get; set; }
- }
-
- [Route("/Playlists/{Id}/Items", "POST", Summary = "Adds items to a playlist")]
- public class AddToPlaylist : IReturnVoid
- {
- [ApiMember(Name = "Ids", Description = "Item id, comma delimited", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string Ids { get; set; }
-
- [ApiMember(Name = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string Id { get; set; }
-
- /// <summary>
- /// Gets or sets the user id.
- /// </summary>
- /// <value>The user id.</value>
- [ApiMember(Name = "UserId", Description = "User Id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
- public Guid UserId { get; set; }
- }
-
- [Route("/Playlists/{Id}/Items/{ItemId}/Move/{NewIndex}", "POST", Summary = "Moves a playlist item")]
- public class MoveItem : IReturnVoid
- {
- [ApiMember(Name = "ItemId", Description = "ItemId", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string ItemId { get; set; }
-
- [ApiMember(Name = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string Id { get; set; }
-
- /// <summary>
- /// Gets or sets the user id.
- /// </summary>
- /// <value>The user id.</value>
- [ApiMember(Name = "NewIndex", Description = "NewIndex", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
- public int NewIndex { get; set; }
- }
-
- [Route("/Playlists/{Id}/Items", "DELETE", Summary = "Removes items from a playlist")]
- public class RemoveFromPlaylist : IReturnVoid
- {
- [ApiMember(Name = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
- public string Id { get; set; }
-
- [ApiMember(Name = "EntryIds", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "DELETE")]
- public string EntryIds { get; set; }
- }
-
- [Route("/Playlists/{Id}/Items", "GET", Summary = "Gets the original items of a playlist")]
- public class GetPlaylistItems : IReturn<QueryResult<BaseItemDto>>, IHasDtoOptions
- {
- [ApiMember(Name = "Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
- public Guid Id { get; set; }
-
- /// <summary>
- /// Gets or sets the user id.
- /// </summary>
- /// <value>The user id.</value>
- [ApiMember(Name = "UserId", Description = "User Id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public Guid UserId { get; set; }
-
- /// <summary>
- /// Skips over a given number of items within the results. Use for paging.
- /// </summary>
- /// <value>The start index.</value>
- [ApiMember(Name = "StartIndex", Description = "Optional. The record index to start at. All items with a lower index will be dropped from the results.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int? StartIndex { get; set; }
-
- /// <summary>
- /// The maximum number of items to return
- /// </summary>
- /// <value>The limit.</value>
- [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int? Limit { get; set; }
-
- /// <summary>
- /// Fields to return within the items, in addition to basic information
- /// </summary>
- /// <value>The fields.</value>
- [ApiMember(Name = "Fields", Description = "Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)]
- public string Fields { get; set; }
-
- [ApiMember(Name = "EnableImages", Description = "Optional, include image information in output", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
- public bool? EnableImages { get; set; }
-
- [ApiMember(Name = "EnableUserData", Description = "Optional, include user data", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
- public bool? EnableUserData { get; set; }
-
- [ApiMember(Name = "ImageTypeLimit", Description = "Optional, the max number of images to return, per image type", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
- public int? ImageTypeLimit { get; set; }
-
- [ApiMember(Name = "EnableImageTypes", Description = "Optional. The image types to include in the output.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string EnableImageTypes { get; set; }
- }
-
- [Authenticated]
- public class PlaylistService : BaseApiService
- {
- private readonly IPlaylistManager _playlistManager;
- private readonly IDtoService _dtoService;
- private readonly IUserManager _userManager;
- private readonly ILibraryManager _libraryManager;
- private readonly IAuthorizationContext _authContext;
-
- public PlaylistService(
- ILogger<PlaylistService> logger,
- IServerConfigurationManager serverConfigurationManager,
- IHttpResultFactory httpResultFactory,
- IDtoService dtoService,
- IPlaylistManager playlistManager,
- IUserManager userManager,
- ILibraryManager libraryManager,
- IAuthorizationContext authContext)
- : base(logger, serverConfigurationManager, httpResultFactory)
- {
- _dtoService = dtoService;
- _playlistManager = playlistManager;
- _userManager = userManager;
- _libraryManager = libraryManager;
- _authContext = authContext;
- }
-
- public void Post(MoveItem request)
- {
- _playlistManager.MoveItem(request.Id, request.ItemId, request.NewIndex);
- }
-
- public async Task<object> Post(CreatePlaylist request)
- {
- var result = await _playlistManager.CreatePlaylist(new PlaylistCreationRequest
- {
- Name = request.Name,
- ItemIdList = GetGuids(request.Ids),
- UserId = request.UserId,
- MediaType = request.MediaType
-
- }).ConfigureAwait(false);
-
- return ToOptimizedResult(result);
- }
-
- public void Post(AddToPlaylist request)
- {
- _playlistManager.AddToPlaylist(request.Id, GetGuids(request.Ids), request.UserId);
- }
-
- public void Delete(RemoveFromPlaylist request)
- {
- _playlistManager.RemoveFromPlaylist(request.Id, request.EntryIds.Split(','));
- }
-
- public object Get(GetPlaylistItems request)
- {
- var playlist = (Playlist)_libraryManager.GetItemById(request.Id);
- var user = !request.UserId.Equals(Guid.Empty) ? _userManager.GetUserById(request.UserId) : null;
-
- var items = playlist.GetManageableItems().ToArray();
-
- var count = items.Length;
-
- if (request.StartIndex.HasValue)
- {
- items = items.Skip(request.StartIndex.Value).ToArray();
- }
-
- if (request.Limit.HasValue)
- {
- items = items.Take(request.Limit.Value).ToArray();
- }
-
- var dtoOptions = GetDtoOptions(_authContext, request);
-
- var dtos = _dtoService.GetBaseItemDtos(items.Select(i => i.Item2).ToList(), dtoOptions, user);
-
- for (int index = 0; index < dtos.Count; index++)
- {
- dtos[index].PlaylistItemId = items[index].Item1.Id;
- }
-
- var result = new QueryResult<BaseItemDto>
- {
- Items = dtos,
- TotalRecordCount = count
- };
-
- return ToOptimizedResult(result);
- }
- }
-}
diff --git a/MediaBrowser.Api/Sessions/SessionService.cs b/MediaBrowser.Api/Sessions/SessionService.cs
deleted file mode 100644
index d986eea65..000000000
--- a/MediaBrowser.Api/Sessions/SessionService.cs
+++ /dev/null
@@ -1,499 +0,0 @@
-using System;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using Jellyfin.Data.Enums;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Devices;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Controller.Session;
-using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.Services;
-using MediaBrowser.Model.Session;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api.Sessions
-{
- /// <summary>
- /// Class GetSessions.
- /// </summary>
- [Route("/Sessions", "GET", Summary = "Gets a list of sessions")]
- [Authenticated]
- public class GetSessions : IReturn<SessionInfo[]>
- {
- [ApiMember(Name = "ControllableByUserId", Description = "Filter by sessions that a given user is allowed to remote control.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public Guid ControllableByUserId { get; set; }
-
- [ApiMember(Name = "DeviceId", Description = "Filter by device Id.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public string DeviceId { get; set; }
-
- public int? ActiveWithinSeconds { get; set; }
- }
-
- /// <summary>
- /// Class DisplayContent.
- /// </summary>
- [Route("/Sessions/{Id}/Viewing", "POST", Summary = "Instructs a session to browse to an item or view")]
- [Authenticated]
- public class DisplayContent : IReturnVoid
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string Id { get; set; }
-
- /// <summary>
- /// Artist, Genre, Studio, Person, or any kind of BaseItem
- /// </summary>
- /// <value>The type of the item.</value>
- [ApiMember(Name = "ItemType", Description = "The type of item to browse to.", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string ItemType { get; set; }
-
- /// <summary>
- /// Artist name, genre name, item Id, etc
- /// </summary>
- /// <value>The item identifier.</value>
- [ApiMember(Name = "ItemId", Description = "The Id of the item.", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string ItemId { get; set; }
-
- /// <summary>
- /// Gets or sets the name of the item.
- /// </summary>
- /// <value>The name of the item.</value>
- [ApiMember(Name = "ItemName", Description = "The name of the item.", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string ItemName { get; set; }
- }
-
- [Route("/Sessions/{Id}/Playing", "POST", Summary = "Instructs a session to play an item")]
- [Authenticated]
- public class Play : PlayRequest
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string Id { get; set; }
- }
-
- [Route("/Sessions/{Id}/Playing/{Command}", "POST", Summary = "Issues a playstate command to a client")]
- [Authenticated]
- public class SendPlaystateCommand : PlaystateRequest, IReturnVoid
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string Id { get; set; }
- }
-
- [Route("/Sessions/{Id}/System/{Command}", "POST", Summary = "Issues a system command to a client")]
- [Authenticated]
- public class SendSystemCommand : IReturnVoid
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string Id { get; set; }
-
- /// <summary>
- /// Gets or sets the command.
- /// </summary>
- /// <value>The play command.</value>
- [ApiMember(Name = "Command", Description = "The command to send.", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string Command { get; set; }
- }
-
- [Route("/Sessions/{Id}/Command/{Command}", "POST", Summary = "Issues a system command to a client")]
- [Authenticated]
- public class SendGeneralCommand : IReturnVoid
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string Id { get; set; }
-
- /// <summary>
- /// Gets or sets the command.
- /// </summary>
- /// <value>The play command.</value>
- [ApiMember(Name = "Command", Description = "The command to send.", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string Command { get; set; }
- }
-
- [Route("/Sessions/{Id}/Command", "POST", Summary = "Issues a system command to a client")]
- [Authenticated]
- public class SendFullGeneralCommand : GeneralCommand, IReturnVoid
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string Id { get; set; }
- }
-
- [Route("/Sessions/{Id}/Message", "POST", Summary = "Issues a command to a client to display a message to the user")]
- [Authenticated]
- public class SendMessageCommand : IReturnVoid
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string Id { get; set; }
-
- [ApiMember(Name = "Text", Description = "The message text.", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string Text { get; set; }
-
- [ApiMember(Name = "Header", Description = "The message header.", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string Header { get; set; }
-
- [ApiMember(Name = "TimeoutMs", Description = "The message timeout. If omitted the user will have to confirm viewing the message.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
- public long? TimeoutMs { get; set; }
- }
-
- [Route("/Sessions/{Id}/Users/{UserId}", "POST", Summary = "Adds an additional user to a session")]
- [Authenticated]
- public class AddUserToSession : IReturnVoid
- {
- [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string Id { get; set; }
-
- [ApiMember(Name = "UserId", Description = "UserId Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string UserId { get; set; }
- }
-
- [Route("/Sessions/{Id}/Users/{UserId}", "DELETE", Summary = "Removes an additional user from a session")]
- [Authenticated]
- public class RemoveUserFromSession : IReturnVoid
- {
- [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string Id { get; set; }
-
- [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string UserId { get; set; }
- }
-
- [Route("/Sessions/Capabilities", "POST", Summary = "Updates capabilities for a device")]
- [Authenticated]
- public class PostCapabilities : IReturnVoid
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string Id { get; set; }
-
- [ApiMember(Name = "PlayableMediaTypes", Description = "A list of playable media types, comma delimited. Audio, Video, Book, Photo.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string PlayableMediaTypes { get; set; }
-
- [ApiMember(Name = "SupportedCommands", Description = "A list of supported remote control commands, comma delimited", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string SupportedCommands { get; set; }
-
- [ApiMember(Name = "SupportsMediaControl", Description = "Determines whether media can be played remotely.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "POST")]
- public bool SupportsMediaControl { get; set; }
-
- [ApiMember(Name = "SupportsSync", Description = "Determines whether sync is supported.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "POST")]
- public bool SupportsSync { get; set; }
-
- [ApiMember(Name = "SupportsPersistentIdentifier", Description = "Determines whether the device supports a unique identifier.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "POST")]
- public bool SupportsPersistentIdentifier { get; set; }
-
- public PostCapabilities()
- {
- SupportsPersistentIdentifier = true;
- }
- }
-
- [Route("/Sessions/Capabilities/Full", "POST", Summary = "Updates capabilities for a device")]
- [Authenticated]
- public class PostFullCapabilities : ClientCapabilities, IReturnVoid
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string Id { get; set; }
- }
-
- [Route("/Sessions/Viewing", "POST", Summary = "Reports that a session is viewing an item")]
- [Authenticated]
- public class ReportViewing : IReturnVoid
- {
- [ApiMember(Name = "SessionId", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string SessionId { get; set; }
-
- [ApiMember(Name = "ItemId", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string ItemId { get; set; }
- }
-
- [Route("/Sessions/Logout", "POST", Summary = "Reports that a session has ended")]
- [Authenticated]
- public class ReportSessionEnded : IReturnVoid
- {
- }
-
- [Route("/Auth/Providers", "GET")]
- [Authenticated(Roles = "Admin")]
- public class GetAuthProviders : IReturn<NameIdPair[]>
- {
- }
-
- [Route("/Auth/PasswordResetProviders", "GET")]
- [Authenticated(Roles = "Admin")]
- public class GetPasswordResetProviders : IReturn<NameIdPair[]>
- {
- }
-
- /// <summary>
- /// Class SessionsService.
- /// </summary>
- public class SessionService : BaseApiService
- {
- /// <summary>
- /// The session manager.
- /// </summary>
- private readonly ISessionManager _sessionManager;
-
- private readonly IUserManager _userManager;
- private readonly IAuthorizationContext _authContext;
- private readonly IDeviceManager _deviceManager;
- private readonly ISessionContext _sessionContext;
-
- public SessionService(
- ILogger<SessionService> logger,
- IServerConfigurationManager serverConfigurationManager,
- IHttpResultFactory httpResultFactory,
- ISessionManager sessionManager,
- IUserManager userManager,
- IAuthorizationContext authContext,
- IDeviceManager deviceManager,
- ISessionContext sessionContext)
- : base(logger, serverConfigurationManager, httpResultFactory)
- {
- _sessionManager = sessionManager;
- _userManager = userManager;
- _authContext = authContext;
- _deviceManager = deviceManager;
- _sessionContext = sessionContext;
- }
-
- public object Get(GetAuthProviders request)
- {
- return _userManager.GetAuthenticationProviders();
- }
-
- public object Get(GetPasswordResetProviders request)
- {
- return _userManager.GetPasswordResetProviders();
- }
-
- public void Post(ReportSessionEnded request)
- {
- var auth = _authContext.GetAuthorizationInfo(Request);
-
- _sessionManager.Logout(auth.Token);
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
- public object Get(GetSessions request)
- {
- var result = _sessionManager.Sessions;
-
- if (!string.IsNullOrEmpty(request.DeviceId))
- {
- result = result.Where(i => string.Equals(i.DeviceId, request.DeviceId, StringComparison.OrdinalIgnoreCase));
- }
-
- if (!request.ControllableByUserId.Equals(Guid.Empty))
- {
- result = result.Where(i => i.SupportsRemoteControl);
-
- var user = _userManager.GetUserById(request.ControllableByUserId);
-
- if (!user.HasPermission(PermissionKind.EnableRemoteControlOfOtherUsers))
- {
- result = result.Where(i => i.UserId.Equals(Guid.Empty) || i.ContainsUser(request.ControllableByUserId));
- }
-
- if (!user.HasPermission(PermissionKind.EnableSharedDeviceControl))
- {
- result = result.Where(i => !i.UserId.Equals(Guid.Empty));
- }
-
- if (request.ActiveWithinSeconds.HasValue && request.ActiveWithinSeconds.Value > 0)
- {
- var minActiveDate = DateTime.UtcNow.AddSeconds(0 - request.ActiveWithinSeconds.Value);
- result = result.Where(i => i.LastActivityDate >= minActiveDate);
- }
-
- result = result.Where(i =>
- {
- var deviceId = i.DeviceId;
-
- if (!string.IsNullOrWhiteSpace(deviceId))
- {
- if (!_deviceManager.CanAccessDevice(user, deviceId))
- {
- return false;
- }
- }
-
- return true;
- });
- }
-
- return ToOptimizedResult(result.ToArray());
- }
-
- public Task Post(SendPlaystateCommand request)
- {
- return _sessionManager.SendPlaystateCommand(GetSession(_sessionContext).Id, request.Id, request, CancellationToken.None);
- }
-
- /// <summary>
- /// Posts the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- public Task Post(DisplayContent request)
- {
- var command = new BrowseRequest
- {
- ItemId = request.ItemId,
- ItemName = request.ItemName,
- ItemType = request.ItemType
- };
-
- return _sessionManager.SendBrowseCommand(GetSession(_sessionContext).Id, request.Id, command, CancellationToken.None);
- }
-
- /// <summary>
- /// Posts the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- public Task Post(SendSystemCommand request)
- {
- var name = request.Command;
- if (Enum.TryParse(name, true, out GeneralCommandType commandType))
- {
- name = commandType.ToString();
- }
-
- var currentSession = GetSession(_sessionContext);
- var command = new GeneralCommand
- {
- Name = name,
- ControllingUserId = currentSession.UserId
- };
-
- return _sessionManager.SendGeneralCommand(currentSession.Id, request.Id, command, CancellationToken.None);
- }
-
- /// <summary>
- /// Posts the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- public Task Post(SendMessageCommand request)
- {
- var command = new MessageCommand
- {
- Header = string.IsNullOrEmpty(request.Header) ? "Message from Server" : request.Header,
- TimeoutMs = request.TimeoutMs,
- Text = request.Text
- };
-
- return _sessionManager.SendMessageCommand(GetSession(_sessionContext).Id, request.Id, command, CancellationToken.None);
- }
-
- /// <summary>
- /// Posts the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- public Task Post(Play request)
- {
- return _sessionManager.SendPlayCommand(GetSession(_sessionContext).Id, request.Id, request, CancellationToken.None);
- }
-
- public Task Post(SendGeneralCommand request)
- {
- var currentSession = GetSession(_sessionContext);
-
- var command = new GeneralCommand
- {
- Name = request.Command,
- ControllingUserId = currentSession.UserId
- };
-
- return _sessionManager.SendGeneralCommand(currentSession.Id, request.Id, command, CancellationToken.None);
- }
-
- public Task Post(SendFullGeneralCommand request)
- {
- var currentSession = GetSession(_sessionContext);
-
- request.ControllingUserId = currentSession.UserId;
-
- return _sessionManager.SendGeneralCommand(currentSession.Id, request.Id, request, CancellationToken.None);
- }
-
- public void Post(AddUserToSession request)
- {
- _sessionManager.AddAdditionalUser(request.Id, new Guid(request.UserId));
- }
-
- public void Delete(RemoveUserFromSession request)
- {
- _sessionManager.RemoveAdditionalUser(request.Id, new Guid(request.UserId));
- }
-
- public void Post(PostCapabilities request)
- {
- if (string.IsNullOrWhiteSpace(request.Id))
- {
- request.Id = GetSession(_sessionContext).Id;
- }
-
- _sessionManager.ReportCapabilities(request.Id, new ClientCapabilities
- {
- PlayableMediaTypes = SplitValue(request.PlayableMediaTypes, ','),
- SupportedCommands = SplitValue(request.SupportedCommands, ','),
- SupportsMediaControl = request.SupportsMediaControl,
- SupportsSync = request.SupportsSync,
- SupportsPersistentIdentifier = request.SupportsPersistentIdentifier
- });
- }
-
- public void Post(PostFullCapabilities request)
- {
- if (string.IsNullOrWhiteSpace(request.Id))
- {
- request.Id = GetSession(_sessionContext).Id;
- }
-
- _sessionManager.ReportCapabilities(request.Id, request);
- }
-
- public void Post(ReportViewing request)
- {
- request.SessionId = GetSession(_sessionContext).Id;
-
- _sessionManager.ReportNowViewingItem(request.SessionId, request.ItemId);
- }
- }
-}
diff --git a/MediaBrowser.Api/SuggestionsService.cs b/MediaBrowser.Api/SuggestionsService.cs
deleted file mode 100644
index 32d3bde5c..000000000
--- a/MediaBrowser.Api/SuggestionsService.cs
+++ /dev/null
@@ -1,98 +0,0 @@
-using System;
-using System.Linq;
-using Jellyfin.Data.Entities;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Dto;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Querying;
-using MediaBrowser.Model.Services;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api
-{
- [Route("/Users/{UserId}/Suggestions", "GET", Summary = "Gets items based on a query.")]
- public class GetSuggestedItems : IReturn<QueryResult<BaseItemDto>>
- {
- public string MediaType { get; set; }
- public string Type { get; set; }
- public Guid UserId { get; set; }
- public bool EnableTotalRecordCount { get; set; }
- public int? StartIndex { get; set; }
- public int? Limit { get; set; }
-
- public string[] GetMediaTypes()
- {
- return (MediaType ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
- }
-
- public string[] GetIncludeItemTypes()
- {
- return (Type ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
- }
- }
-
- public class SuggestionsService : BaseApiService
- {
- private readonly IDtoService _dtoService;
- private readonly IAuthorizationContext _authContext;
- private readonly IUserManager _userManager;
- private readonly ILibraryManager _libraryManager;
-
- public SuggestionsService(
- ILogger<SuggestionsService> logger,
- IServerConfigurationManager serverConfigurationManager,
- IHttpResultFactory httpResultFactory,
- IDtoService dtoService,
- IAuthorizationContext authContext,
- IUserManager userManager,
- ILibraryManager libraryManager)
- : base(logger, serverConfigurationManager, httpResultFactory)
- {
- _dtoService = dtoService;
- _authContext = authContext;
- _userManager = userManager;
- _libraryManager = libraryManager;
- }
-
- public object Get(GetSuggestedItems request)
- {
- return GetResultItems(request);
- }
-
- private QueryResult<BaseItemDto> GetResultItems(GetSuggestedItems request)
- {
- var user = !request.UserId.Equals(Guid.Empty) ? _userManager.GetUserById(request.UserId) : null;
-
- var dtoOptions = GetDtoOptions(_authContext, request);
- var result = GetItems(request, user, dtoOptions);
-
- var dtoList = _dtoService.GetBaseItemDtos(result.Items, dtoOptions, user);
-
- return new QueryResult<BaseItemDto>
- {
- TotalRecordCount = result.TotalRecordCount,
- Items = dtoList
- };
- }
-
- private QueryResult<BaseItem> GetItems(GetSuggestedItems request, User user, DtoOptions dtoOptions)
- {
- return _libraryManager.GetItemsResult(new InternalItemsQuery(user)
- {
- OrderBy = new[] { ItemSortBy.Random }.Select(i => new ValueTuple<string, SortOrder>(i, SortOrder.Descending)).ToArray(),
- MediaTypes = request.GetMediaTypes(),
- IncludeItemTypes = request.GetIncludeItemTypes(),
- IsVirtualItem = false,
- StartIndex = request.StartIndex,
- Limit = request.Limit,
- DtoOptions = dtoOptions,
- EnableTotalRecordCount = request.EnableTotalRecordCount,
- Recursive = true
- });
- }
- }
-}
diff --git a/MediaBrowser.Api/TestService.cs b/MediaBrowser.Api/TestService.cs
new file mode 100644
index 000000000..6c999e08d
--- /dev/null
+++ b/MediaBrowser.Api/TestService.cs
@@ -0,0 +1,26 @@
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Net;
+using Microsoft.Extensions.Logging;
+
+namespace MediaBrowser.Api
+{
+ /// <summary>
+ /// Service for testing path value.
+ /// </summary>
+ public class TestService : BaseApiService
+ {
+ /// <summary>
+ /// Test service.
+ /// </summary>
+ /// <param name="logger">Instance of the <see cref="ILogger{TestService}"/> interface.</param>
+ /// <param name="serverConfigurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</param>
+ /// <param name="httpResultFactory">Instance of the <see cref="IHttpResultFactory"/> interface.</param>
+ public TestService(
+ ILogger<TestService> logger,
+ IServerConfigurationManager serverConfigurationManager,
+ IHttpResultFactory httpResultFactory)
+ : base(logger, serverConfigurationManager, httpResultFactory)
+ {
+ }
+ }
+}
diff --git a/MediaBrowser.Api/UserService.cs b/MediaBrowser.Api/UserService.cs
deleted file mode 100644
index 9cb9baf63..000000000
--- a/MediaBrowser.Api/UserService.cs
+++ /dev/null
@@ -1,605 +0,0 @@
-using System;
-using System.Linq;
-using System.Threading.Tasks;
-using Jellyfin.Data.Enums;
-using MediaBrowser.Common.Extensions;
-using MediaBrowser.Common.Net;
-using MediaBrowser.Controller.Authentication;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Devices;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Controller.Session;
-using MediaBrowser.Model.Configuration;
-using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.Services;
-using MediaBrowser.Model.Users;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api
-{
- /// <summary>
- /// Class GetUsers
- /// </summary>
- [Route("/Users", "GET", Summary = "Gets a list of users")]
- [Authenticated]
- public class GetUsers : IReturn<UserDto[]>
- {
- [ApiMember(Name = "IsHidden", Description = "Optional filter by IsHidden=true or false", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
- public bool? IsHidden { get; set; }
-
- [ApiMember(Name = "IsDisabled", Description = "Optional filter by IsDisabled=true or false", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
- public bool? IsDisabled { get; set; }
-
- [ApiMember(Name = "IsGuest", Description = "Optional filter by IsGuest=true or false", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
- public bool? IsGuest { get; set; }
- }
-
- [Route("/Users/Public", "GET", Summary = "Gets a list of publicly visible users for display on a login screen.")]
- public class GetPublicUsers : IReturn<UserDto[]>
- {
- }
-
- /// <summary>
- /// Class GetUser
- /// </summary>
- [Route("/Users/{Id}", "GET", Summary = "Gets a user by Id")]
- [Authenticated(EscapeParentalControl = true)]
- public class GetUser : IReturn<UserDto>
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public Guid Id { get; set; }
- }
-
- /// <summary>
- /// Class DeleteUser
- /// </summary>
- [Route("/Users/{Id}", "DELETE", Summary = "Deletes a user")]
- [Authenticated(Roles = "Admin")]
- public class DeleteUser : IReturnVoid
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
- public Guid Id { get; set; }
- }
-
- /// <summary>
- /// Class AuthenticateUser
- /// </summary>
- [Route("/Users/{Id}/Authenticate", "POST", Summary = "Authenticates a user")]
- public class AuthenticateUser : IReturn<AuthenticationResult>
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public Guid Id { get; set; }
-
- [ApiMember(Name = "Pw", IsRequired = true, DataType = "string", ParameterType = "body", Verb = "POST")]
- public string Pw { get; set; }
-
- /// <summary>
- /// Gets or sets the password.
- /// </summary>
- /// <value>The password.</value>
- [ApiMember(Name = "Password", IsRequired = true, DataType = "string", ParameterType = "body", Verb = "POST")]
- public string Password { get; set; }
- }
-
- /// <summary>
- /// Class AuthenticateUser
- /// </summary>
- [Route("/Users/AuthenticateByName", "POST", Summary = "Authenticates a user")]
- public class AuthenticateUserByName : IReturn<AuthenticationResult>
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Username", IsRequired = true, DataType = "string", ParameterType = "body", Verb = "POST")]
- public string Username { get; set; }
-
- /// <summary>
- /// Gets or sets the password.
- /// </summary>
- /// <value>The password.</value>
- [ApiMember(Name = "Password", IsRequired = true, DataType = "string", ParameterType = "body", Verb = "POST")]
- public string Password { get; set; }
-
- [ApiMember(Name = "Pw", IsRequired = true, DataType = "string", ParameterType = "body", Verb = "POST")]
- public string Pw { get; set; }
- }
-
- /// <summary>
- /// Class UpdateUserPassword
- /// </summary>
- [Route("/Users/{Id}/Password", "POST", Summary = "Updates a user's password")]
- [Authenticated]
- public class UpdateUserPassword : IReturnVoid
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- public Guid Id { get; set; }
-
- /// <summary>
- /// Gets or sets the password.
- /// </summary>
- /// <value>The password.</value>
- public string CurrentPassword { get; set; }
-
- public string CurrentPw { get; set; }
-
- public string NewPw { get; set; }
-
- /// <summary>
- /// Gets or sets a value indicating whether [reset password].
- /// </summary>
- /// <value><c>true</c> if [reset password]; otherwise, <c>false</c>.</value>
- public bool ResetPassword { get; set; }
- }
-
- /// <summary>
- /// Class UpdateUserEasyPassword
- /// </summary>
- [Route("/Users/{Id}/EasyPassword", "POST", Summary = "Updates a user's easy password")]
- [Authenticated]
- public class UpdateUserEasyPassword : IReturnVoid
- {
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- public Guid Id { get; set; }
-
- /// <summary>
- /// Gets or sets the new password.
- /// </summary>
- /// <value>The new password.</value>
- public string NewPassword { get; set; }
-
- public string NewPw { get; set; }
-
- /// <summary>
- /// Gets or sets a value indicating whether [reset password].
- /// </summary>
- /// <value><c>true</c> if [reset password]; otherwise, <c>false</c>.</value>
- public bool ResetPassword { get; set; }
- }
-
- /// <summary>
- /// Class UpdateUser
- /// </summary>
- [Route("/Users/{Id}", "POST", Summary = "Updates a user")]
- [Authenticated]
- public class UpdateUser : UserDto, IReturnVoid
- {
- }
-
- /// <summary>
- /// Class UpdateUser
- /// </summary>
- [Route("/Users/{Id}/Policy", "POST", Summary = "Updates a user policy")]
- [Authenticated(Roles = "admin")]
- public class UpdateUserPolicy : UserPolicy, IReturnVoid
- {
- [ApiMember(Name = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public Guid Id { get; set; }
- }
-
- /// <summary>
- /// Class UpdateUser
- /// </summary>
- [Route("/Users/{Id}/Configuration", "POST", Summary = "Updates a user configuration")]
- [Authenticated]
- public class UpdateUserConfiguration : UserConfiguration, IReturnVoid
- {
- [ApiMember(Name = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public Guid Id { get; set; }
- }
-
- /// <summary>
- /// Class CreateUser
- /// </summary>
- [Route("/Users/New", "POST", Summary = "Creates a user")]
- [Authenticated(Roles = "Admin")]
- public class CreateUserByName : IReturn<UserDto>
- {
- [ApiMember(Name = "Name", IsRequired = true, DataType = "string", ParameterType = "body", Verb = "POST")]
- public string Name { get; set; }
-
- [ApiMember(Name = "Password", IsRequired = false, DataType = "string", ParameterType = "body", Verb = "POST")]
- public string Password { get; set; }
- }
-
- [Route("/Users/ForgotPassword", "POST", Summary = "Initiates the forgot password process for a local user")]
- public class ForgotPassword : IReturn<ForgotPasswordResult>
- {
- [ApiMember(Name = "EnteredUsername", IsRequired = false, DataType = "string", ParameterType = "body", Verb = "POST")]
- public string EnteredUsername { get; set; }
- }
-
- [Route("/Users/ForgotPassword/Pin", "POST", Summary = "Redeems a forgot password pin")]
- public class ForgotPasswordPin : IReturn<PinRedeemResult>
- {
- [ApiMember(Name = "Pin", IsRequired = false, DataType = "string", ParameterType = "body", Verb = "POST")]
- public string Pin { get; set; }
- }
-
- /// <summary>
- /// Class UsersService
- /// </summary>
- public class UserService : BaseApiService
- {
- /// <summary>
- /// The user manager.
- /// </summary>
- private readonly IUserManager _userManager;
- private readonly ISessionManager _sessionMananger;
- private readonly INetworkManager _networkManager;
- private readonly IDeviceManager _deviceManager;
- private readonly IAuthorizationContext _authContext;
-
- public UserService(
- ILogger<UserService> logger,
- IServerConfigurationManager serverConfigurationManager,
- IHttpResultFactory httpResultFactory,
- IUserManager userManager,
- ISessionManager sessionMananger,
- INetworkManager networkManager,
- IDeviceManager deviceManager,
- IAuthorizationContext authContext)
- : base(logger, serverConfigurationManager, httpResultFactory)
- {
- _userManager = userManager;
- _sessionMananger = sessionMananger;
- _networkManager = networkManager;
- _deviceManager = deviceManager;
- _authContext = authContext;
- }
-
- public object Get(GetPublicUsers request)
- {
- // If the startup wizard hasn't been completed then just return all users
- if (!ServerConfigurationManager.Configuration.IsStartupWizardCompleted)
- {
- return Get(new GetUsers
- {
- IsDisabled = false
- });
- }
-
- return Get(new GetUsers
- {
- IsHidden = false,
- IsDisabled = false
- }, true, true);
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
- public object Get(GetUsers request)
- {
- return Get(request, false, false);
- }
-
- private object Get(GetUsers request, bool filterByDevice, bool filterByNetwork)
- {
- var users = _userManager.Users;
-
- if (request.IsDisabled.HasValue)
- {
- users = users.Where(i => i.HasPermission(PermissionKind.IsDisabled) == request.IsDisabled.Value);
- }
-
- if (request.IsHidden.HasValue)
- {
- users = users.Where(i => i.HasPermission(PermissionKind.IsHidden) == request.IsHidden.Value);
- }
-
- if (filterByDevice)
- {
- var deviceId = _authContext.GetAuthorizationInfo(Request).DeviceId;
-
- if (!string.IsNullOrWhiteSpace(deviceId))
- {
- users = users.Where(i => _deviceManager.CanAccessDevice(i, deviceId));
- }
- }
-
- if (filterByNetwork)
- {
- if (!_networkManager.IsInLocalNetwork(Request.RemoteIp))
- {
- users = users.Where(i => i.HasPermission(PermissionKind.EnableRemoteAccess));
- }
- }
-
- var result = users
- .OrderBy(u => u.Username)
- .Select(i => _userManager.GetUserDto(i, Request.RemoteIp))
- .ToArray();
-
- return ToOptimizedResult(result);
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
- public object Get(GetUser request)
- {
- var user = _userManager.GetUserById(request.Id);
-
- if (user == null)
- {
- throw new ResourceNotFoundException("User not found");
- }
-
- var result = _userManager.GetUserDto(user, Request.RemoteIp);
-
- return ToOptimizedResult(result);
- }
-
- /// <summary>
- /// Deletes the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- public Task Delete(DeleteUser request)
- {
- return DeleteAsync(request);
- }
-
- public Task DeleteAsync(DeleteUser request)
- {
- var user = _userManager.GetUserById(request.Id);
-
- if (user == null)
- {
- throw new ResourceNotFoundException("User not found");
- }
-
- _sessionMananger.RevokeUserTokens(user.Id, null);
- _userManager.DeleteUser(user);
- return Task.CompletedTask;
- }
-
- /// <summary>
- /// Posts the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- public object Post(AuthenticateUser request)
- {
- var user = _userManager.GetUserById(request.Id);
-
- if (user == null)
- {
- throw new ResourceNotFoundException("User not found");
- }
-
- if (!string.IsNullOrEmpty(request.Password) && string.IsNullOrEmpty(request.Pw))
- {
- throw new MethodNotAllowedException("Hashed-only passwords are not valid for this API.");
- }
-
- // Password should always be null
- return Post(new AuthenticateUserByName
- {
- Username = user.Username,
- Password = null,
- Pw = request.Pw
- });
- }
-
- public async Task<object> Post(AuthenticateUserByName request)
- {
- var auth = _authContext.GetAuthorizationInfo(Request);
-
- try
- {
- var result = await _sessionMananger.AuthenticateNewSession(new AuthenticationRequest
- {
- App = auth.Client,
- AppVersion = auth.Version,
- DeviceId = auth.DeviceId,
- DeviceName = auth.Device,
- Password = request.Pw,
- PasswordSha1 = request.Password,
- RemoteEndPoint = Request.RemoteIp,
- Username = request.Username
- }).ConfigureAwait(false);
-
- return ToOptimizedResult(result);
- }
- catch (SecurityException e)
- {
- // rethrow adding IP address to message
- throw new SecurityException($"[{Request.RemoteIp}] {e.Message}", e);
- }
- }
-
- /// <summary>
- /// Posts the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- public Task Post(UpdateUserPassword request)
- {
- return PostAsync(request);
- }
-
- public async Task PostAsync(UpdateUserPassword request)
- {
- AssertCanUpdateUser(_authContext, _userManager, request.Id, true);
-
- var user = _userManager.GetUserById(request.Id);
-
- if (user == null)
- {
- throw new ResourceNotFoundException("User not found");
- }
-
- if (request.ResetPassword)
- {
- await _userManager.ResetPassword(user).ConfigureAwait(false);
- }
- else
- {
- var success = await _userManager.AuthenticateUser(
- user.Username,
- request.CurrentPw,
- request.CurrentPassword,
- Request.RemoteIp,
- false).ConfigureAwait(false);
-
- if (success == null)
- {
- throw new ArgumentException("Invalid user or password entered.");
- }
-
- await _userManager.ChangePassword(user, request.NewPw).ConfigureAwait(false);
-
- var currentToken = _authContext.GetAuthorizationInfo(Request).Token;
-
- _sessionMananger.RevokeUserTokens(user.Id, currentToken);
- }
- }
-
- public void Post(UpdateUserEasyPassword request)
- {
- AssertCanUpdateUser(_authContext, _userManager, request.Id, true);
-
- var user = _userManager.GetUserById(request.Id);
-
- if (user == null)
- {
- throw new ResourceNotFoundException("User not found");
- }
-
- if (request.ResetPassword)
- {
- _userManager.ResetEasyPassword(user);
- }
- else
- {
- _userManager.ChangeEasyPassword(user, request.NewPw, request.NewPassword);
- }
- }
-
- /// <summary>
- /// Posts the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- public async Task Post(UpdateUser request)
- {
- var id = Guid.Parse(GetPathValue(1));
-
- AssertCanUpdateUser(_authContext, _userManager, id, false);
-
- var dtoUser = request;
-
- var user = _userManager.GetUserById(id);
-
- if (string.Equals(user.Username, dtoUser.Name, StringComparison.Ordinal))
- {
- await _userManager.UpdateUserAsync(user);
- _userManager.UpdateConfiguration(user.Id, dtoUser.Configuration);
- }
- else
- {
- await _userManager.RenameUser(user, dtoUser.Name).ConfigureAwait(false);
-
- _userManager.UpdateConfiguration(dtoUser.Id, dtoUser.Configuration);
- }
- }
-
- /// <summary>
- /// Posts the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
- public async Task<object> Post(CreateUserByName request)
- {
- var newUser = _userManager.CreateUser(request.Name);
-
- // no need to authenticate password for new user
- if (request.Password != null)
- {
- await _userManager.ChangePassword(newUser, request.Password).ConfigureAwait(false);
- }
-
- var result = _userManager.GetUserDto(newUser, Request.RemoteIp);
-
- return ToOptimizedResult(result);
- }
-
- public async Task<object> Post(ForgotPassword request)
- {
- var isLocal = Request.IsLocal || _networkManager.IsInLocalNetwork(Request.RemoteIp);
-
- var result = await _userManager.StartForgotPasswordProcess(request.EnteredUsername, isLocal).ConfigureAwait(false);
-
- return result;
- }
-
- public async Task<object> Post(ForgotPasswordPin request)
- {
- var result = await _userManager.RedeemPasswordResetPin(request.Pin).ConfigureAwait(false);
-
- return result;
- }
-
- public void Post(UpdateUserConfiguration request)
- {
- AssertCanUpdateUser(_authContext, _userManager, request.Id, false);
-
- _userManager.UpdateConfiguration(request.Id, request);
- }
-
- public void Post(UpdateUserPolicy request)
- {
- var user = _userManager.GetUserById(request.Id);
-
- // If removing admin access
- if (!request.IsAdministrator && user.HasPermission(PermissionKind.IsAdministrator))
- {
- if (_userManager.Users.Count(i => i.HasPermission(PermissionKind.IsAdministrator)) == 1)
- {
- throw new ArgumentException("There must be at least one user in the system with administrative access.");
- }
- }
-
- // If disabling
- if (request.IsDisabled && user.HasPermission(PermissionKind.IsAdministrator))
- {
- throw new ArgumentException("Administrators cannot be disabled.");
- }
-
- // If disabling
- if (request.IsDisabled && !user.HasPermission(PermissionKind.IsDisabled))
- {
- if (_userManager.Users.Count(i => !i.HasPermission(PermissionKind.IsDisabled)) == 1)
- {
- throw new ArgumentException("There must be at least one enabled user in the system.");
- }
-
- var currentToken = _authContext.GetAuthorizationInfo(Request).Token;
- _sessionMananger.RevokeUserTokens(user.Id, currentToken);
- }
-
- _userManager.UpdatePolicy(request.Id, request);
- }
- }
-}
diff --git a/MediaBrowser.Api/VideosService.cs b/MediaBrowser.Api/VideosService.cs
deleted file mode 100644
index 957a279f8..000000000
--- a/MediaBrowser.Api/VideosService.cs
+++ /dev/null
@@ -1,193 +0,0 @@
-using System;
-using System.Globalization;
-using System.Linq;
-using System.Threading;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Dto;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Net;
-using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.Querying;
-using MediaBrowser.Model.Services;
-using Microsoft.Extensions.Logging;
-
-namespace MediaBrowser.Api
-{
- [Route("/Videos/{Id}/AdditionalParts", "GET", Summary = "Gets additional parts for a video.")]
- [Authenticated]
- public class GetAdditionalParts : IReturn<QueryResult<BaseItemDto>>
- {
- [ApiMember(Name = "UserId", Description = "Optional. Filter by user id, and attach user data", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
- public Guid UserId { get; set; }
-
- /// <summary>
- /// Gets or sets the id.
- /// </summary>
- /// <value>The id.</value>
- [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string Id { get; set; }
- }
-
- [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")]
- public string Id { get; set; }
- }
-
- [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; }
- }
-
- public class VideosService : BaseApiService
- {
- private readonly ILibraryManager _libraryManager;
- private readonly IUserManager _userManager;
- private readonly IDtoService _dtoService;
- private readonly IAuthorizationContext _authContext;
-
- public VideosService(
- ILogger<VideosService> logger,
- IServerConfigurationManager serverConfigurationManager,
- IHttpResultFactory httpResultFactory,
- ILibraryManager libraryManager,
- IUserManager userManager,
- IDtoService dtoService,
- IAuthorizationContext authContext)
- : base(logger, serverConfigurationManager, httpResultFactory)
- {
- _libraryManager = libraryManager;
- _userManager = userManager;
- _dtoService = dtoService;
- _authContext = authContext;
- }
-
- /// <summary>
- /// Gets the specified request.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns>System.Object.</returns>
- public object Get(GetAdditionalParts request)
- {
- var user = !request.UserId.Equals(Guid.Empty) ? _userManager.GetUserById(request.UserId) : null;
-
- var item = string.IsNullOrEmpty(request.Id)
- ? (!request.UserId.Equals(Guid.Empty)
- ? _libraryManager.GetUserRootFolder()
- : _libraryManager.RootFolder)
- : _libraryManager.GetItemById(request.Id);
-
- var dtoOptions = GetDtoOptions(_authContext, request);
-
- BaseItemDto[] items;
- if (item is Video video)
- {
- items = video.GetAdditionalParts()
- .Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, video))
- .ToArray();
- }
- else
- {
- items = Array.Empty<BaseItemDto>();
- }
-
- var result = new QueryResult<BaseItemDto>
- {
- Items = items,
- TotalRecordCount = items.Length
- };
-
- return ToOptimizedResult(result);
- }
-
- public void Delete(DeleteAlternateSources request)
- {
- var video = (Video)_libraryManager.GetItemById(request.Id);
-
- foreach (var link in video.GetLinkedAlternateVersions())
- {
- link.SetPrimaryVersionId(null);
- link.LinkedAlternateVersions = Array.Empty<LinkedChild>();
-
- link.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None);
- }
-
- video.LinkedAlternateVersions = Array.Empty<LinkedChild>();
- video.SetPrimaryVersionId(null);
- video.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None);
- }
-
- public void Post(MergeVersions request)
- {
- var items = request.Ids.Split(',')
- .Select(i => _libraryManager.GetItemById(i))
- .OfType<Video>()
- .OrderBy(i => i.Id)
- .ToList();
-
- if (items.Count < 2)
- {
- throw new ArgumentException("Please supply at least two videos to merge.");
- }
-
- var videosWithVersions = items.Where(i => i.MediaSourceCount > 1)
- .ToList();
-
- var primaryVersion = videosWithVersions.FirstOrDefault();
- if (primaryVersion == null)
- {
- primaryVersion = items.OrderBy(i =>
- {
- if (i.Video3DFormat.HasValue || i.VideoType != Model.Entities.VideoType.VideoFile)
- {
- return 1;
- }
-
- return 0;
- })
- .ThenByDescending(i =>
- {
- return i.GetDefaultVideoStream()?.Width ?? 0;
- }).First();
- }
-
- var list = primaryVersion.LinkedAlternateVersions.ToList();
-
- foreach (var item in items.Where(i => i.Id != primaryVersion.Id))
- {
- item.SetPrimaryVersionId(primaryVersion.Id.ToString("N", CultureInfo.InvariantCulture));
-
- item.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None);
-
- list.Add(new LinkedChild
- {
- Path = item.Path,
- ItemId = item.Id
- });
-
- foreach (var linkedItem in item.LinkedAlternateVersions)
- {
- if (!list.Any(i => string.Equals(i.Path, linkedItem.Path, StringComparison.OrdinalIgnoreCase)))
- {
- list.Add(linkedItem);
- }
- }
-
- if (item.LinkedAlternateVersions.Length > 0)
- {
- item.LinkedAlternateVersions = Array.Empty<LinkedChild>();
- item.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None);
- }
- }
-
- primaryVersion.LinkedAlternateVersions = list.ToArray();
- primaryVersion.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None);
- }
- }
-}