fixes #1001 - Support downloading

pull/702/head
Luke Pulverenti 10 years ago
parent 4ae6b5f675
commit b6d59c7688

@ -226,6 +226,18 @@ namespace MediaBrowser.Api.Library
public string TvdbId { get; set; } public string TvdbId { get; set; }
} }
[Route("/Items/{Id}/Download", "GET", Summary = "Downloads item media")]
[Authenticated(Roles = "download")]
public class GetDownload
{
/// <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; }
}
/// <summary> /// <summary>
/// Class LibraryService /// Class LibraryService
/// </summary> /// </summary>
@ -289,6 +301,28 @@ namespace MediaBrowser.Api.Library
Task.Run(() => _libraryManager.ValidateMediaLibrary(new Progress<double>(), CancellationToken.None)); Task.Run(() => _libraryManager.ValidateMediaLibrary(new Progress<double>(), CancellationToken.None));
} }
public object Get(GetDownload request)
{
var item = _libraryManager.GetItemById(request.Id);
if (!item.CanDelete())
{
throw new ArgumentException("Item does not support downloading");
}
var headers = new Dictionary<string, string>();
// Quotes are valid in linux. They'll possibly cause issues here
var filename = Path.GetFileName(item.Path).Replace("\"", string.Empty);
headers["Content-Disposition"] = string.Format("inline; filename=\"{0}\"", filename);
return ResultFactory.GetStaticFileResult(Request, new StaticFileResultOptions
{
Path = item.Path,
ResponseHeaders = headers
});
}
public object Get(GetFile request) public object Get(GetFile request)
{ {
var item = _libraryManager.GetItemById(request.Id); var item = _libraryManager.GetItemById(request.Id);
@ -458,24 +492,10 @@ namespace MediaBrowser.Api.Library
var auth = _authContext.GetAuthorizationInfo(Request); var auth = _authContext.GetAuthorizationInfo(Request);
var user = _userManager.GetUserById(auth.UserId); var user = _userManager.GetUserById(auth.UserId);
if (item is Playlist || item is BoxSet) if (!item.CanDelete(user))
{
// For now this is allowed if user can see the playlist
}
else if (item is ILiveTvRecording)
{
if (!user.Policy.EnableLiveTvManagement)
{ {
throw new UnauthorizedAccessException(); throw new UnauthorizedAccessException();
} }
}
else
{
if (!user.Policy.EnableContentDeletion)
{
throw new UnauthorizedAccessException();
}
}
var task = _libraryManager.DeleteItem(item); var task = _libraryManager.DeleteItem(item);

@ -323,13 +323,13 @@ namespace MediaBrowser.Api.Playback
switch (qualitySetting) switch (qualitySetting)
{ {
case EncodingQuality.HighSpeed: case EncodingQuality.HighSpeed:
param += " -crf 23"; param += " -subq 0 -crf 23";
break; break;
case EncodingQuality.HighQuality: case EncodingQuality.HighQuality:
param += " -crf 20"; param += " -subq 3 -crf 20";
break; break;
case EncodingQuality.MaxQuality: case EncodingQuality.MaxQuality:
param += " -crf 18"; param += " -subq 6 -crf 18";
break; break;
} }
} }
@ -507,7 +507,7 @@ namespace MediaBrowser.Api.Playback
} }
} }
return param; return "-pix_fmt yuv420p " + param;
} }
protected string GetAudioFilterParam(StreamState state, bool isHls) protected string GetAudioFilterParam(StreamState state, bool isHls)

@ -97,6 +97,7 @@ namespace MediaBrowser.Api.Playback.Progressive
if (string.Equals(Path.GetExtension(outputPath), ".mp4", StringComparison.OrdinalIgnoreCase)) if (string.Equals(Path.GetExtension(outputPath), ".mp4", StringComparison.OrdinalIgnoreCase))
{ {
// Comparison: https://github.com/jansmolders86/mediacenterjs/blob/master/lib/transcoding/desktop.js
format = " -f mp4 -movflags frag_keyframe+empty_moov"; format = " -f mp4 -movflags frag_keyframe+empty_moov";
} }

@ -67,5 +67,10 @@ namespace MediaBrowser.Controller.Channels
{ {
return System.IO.Path.Combine(basePath, "channels", id.ToString("N"), "metadata"); return System.IO.Path.Combine(basePath, "channels", id.ToString("N"), "metadata");
} }
public override bool CanDelete()
{
return false;
}
} }
} }

@ -3,10 +3,10 @@ using MediaBrowser.Model.Channels;
using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Dto; using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities; using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Users;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using MediaBrowser.Model.Users;
namespace MediaBrowser.Controller.Channels namespace MediaBrowser.Controller.Channels
{ {
@ -89,5 +89,10 @@ namespace MediaBrowser.Controller.Channels
return list; return list;
} }
public override bool CanDelete()
{
return false;
}
} }
} }

@ -1,11 +1,10 @@
using System; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Channels; using MediaBrowser.Model.Channels;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Querying; using MediaBrowser.Model.Querying;
using MediaBrowser.Model.Users;
using System;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using MediaBrowser.Model.Users;
namespace MediaBrowser.Controller.Channels namespace MediaBrowser.Controller.Channels
{ {
@ -76,5 +75,10 @@ namespace MediaBrowser.Controller.Channels
{ {
return System.IO.Path.Combine(basePath, "channels", ChannelId, Id.ToString("N")); return System.IO.Path.Combine(basePath, "channels", ChannelId, Id.ToString("N"));
} }
public override bool CanDelete()
{
return false;
}
} }
} }

@ -4,11 +4,11 @@ using MediaBrowser.Model.Channels;
using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Dto; using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities; using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Users;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using MediaBrowser.Model.Users;
namespace MediaBrowser.Controller.Channels namespace MediaBrowser.Controller.Channels
{ {
@ -119,5 +119,10 @@ namespace MediaBrowser.Controller.Channels
{ {
return System.IO.Path.Combine(basePath, "channels", ChannelId, Id.ToString("N")); return System.IO.Path.Combine(basePath, "channels", ChannelId, Id.ToString("N"));
} }
public override bool CanDelete()
{
return false;
}
} }
} }

@ -32,6 +32,11 @@ namespace MediaBrowser.Controller.Entities
} }
} }
public override bool CanDelete()
{
return false;
}
/// <summary> /// <summary>
/// The _virtual children /// The _virtual children
/// </summary> /// </summary>

@ -113,6 +113,13 @@ namespace MediaBrowser.Controller.Entities.Audio
} }
} }
public override bool CanDownload()
{
var locationType = LocationType;
return locationType != LocationType.Remote &&
locationType != LocationType.Virtual;
}
/// <summary> /// <summary>
/// Gets or sets the artist. /// Gets or sets the artist.
/// </summary> /// </summary>

@ -1,14 +1,13 @@
using System.Runtime.Serialization; using MediaBrowser.Controller.Providers;
using MediaBrowser.Common.Progress;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities; using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Users;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Runtime.Serialization;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using MediaBrowser.Model.Users;
namespace MediaBrowser.Controller.Entities.Audio namespace MediaBrowser.Controller.Entities.Audio
{ {
@ -35,6 +34,11 @@ namespace MediaBrowser.Controller.Entities.Audio
get { return true; } get { return true; }
} }
public override bool CanDelete()
{
return !IsAccessedByName;
}
protected override IEnumerable<BaseItem> ActualChildren protected override IEnumerable<BaseItem> ActualChildren
{ {
get get

@ -39,6 +39,11 @@ namespace MediaBrowser.Controller.Entities.Audio
} }
} }
public override bool CanDelete()
{
return false;
}
/// <summary> /// <summary>
/// Gets a value indicating whether this instance is owned item. /// Gets a value indicating whether this instance is owned item.
/// </summary> /// </summary>

@ -239,6 +239,38 @@ namespace MediaBrowser.Controller.Entities
get { return this.GetImagePath(ImageType.Primary); } get { return this.GetImagePath(ImageType.Primary); }
} }
public virtual bool CanDelete()
{
var locationType = LocationType;
return locationType != LocationType.Remote &&
locationType != LocationType.Virtual;
}
public virtual bool IsAuthorizedToDelete(User user)
{
return user.Policy.EnableContentDeletion;
}
public bool CanDelete(User user)
{
return CanDelete() && IsAuthorizedToDelete(user);
}
public virtual bool CanDownload()
{
return false;
}
public virtual bool IsAuthorizedToDownload(User user)
{
return user.Policy.EnableContentDownloading;
}
public bool CanDownload(User user)
{
return CanDownload() && IsAuthorizedToDownload(user);
}
/// <summary> /// <summary>
/// Gets or sets the date created. /// Gets or sets the date created.
/// </summary> /// </summary>

@ -11,5 +11,10 @@ namespace MediaBrowser.Controller.Entities
{ {
get { return null; } get { return null; }
} }
public override bool CanDelete()
{
return false;
}
} }
} }

@ -2,6 +2,7 @@
using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Configuration;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Users; using MediaBrowser.Model.Users;
namespace MediaBrowser.Controller.Entities namespace MediaBrowser.Controller.Entities
@ -37,6 +38,13 @@ namespace MediaBrowser.Controller.Entities
Tags = new List<string>(); Tags = new List<string>();
} }
public override bool CanDownload()
{
var locationType = LocationType;
return locationType != LocationType.Remote &&
locationType != LocationType.Virtual;
}
protected override bool GetBlockUnratedValue(UserPolicy config) protected override bool GetBlockUnratedValue(UserPolicy config)
{ {
return config.BlockUnratedItems.Contains(UnratedItem.Book); return config.BlockUnratedItems.Contains(UnratedItem.Book);

@ -35,6 +35,11 @@ namespace MediaBrowser.Controller.Entities
} }
} }
public override bool CanDelete()
{
return false;
}
public string CollectionType { get; set; } public string CollectionType { get; set; }
/// <summary> /// <summary>

@ -1,10 +1,10 @@
using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities; using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Users;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using MediaBrowser.Model.Users;
namespace MediaBrowser.Controller.Entities namespace MediaBrowser.Controller.Entities
{ {
@ -38,6 +38,13 @@ namespace MediaBrowser.Controller.Entities
public List<Guid> LocalTrailerIds { get; set; } public List<Guid> LocalTrailerIds { get; set; }
public List<Guid> RemoteTrailerIds { get; set; } public List<Guid> RemoteTrailerIds { get; set; }
public override bool CanDownload()
{
var locationType = LocationType;
return locationType != LocationType.Remote &&
locationType != LocationType.Virtual;
}
/// <summary> /// <summary>
/// Gets or sets the tags. /// Gets or sets the tags.
/// </summary> /// </summary>

@ -43,6 +43,11 @@ namespace MediaBrowser.Controller.Entities
} }
} }
public override bool CanDelete()
{
return false;
}
public IEnumerable<BaseItem> GetTaggedItems(IEnumerable<BaseItem> inputItems) public IEnumerable<BaseItem> GetTaggedItems(IEnumerable<BaseItem> inputItems)
{ {
return inputItems.Where(GetItemFilter()); return inputItems.Where(GetItemFilter());

@ -34,6 +34,11 @@ namespace MediaBrowser.Controller.Entities
} }
} }
public override bool CanDelete()
{
return false;
}
/// <summary> /// <summary>
/// Gets a value indicating whether this instance is owned item. /// Gets a value indicating whether this instance is owned item.
/// </summary> /// </summary>

@ -15,6 +15,10 @@ namespace MediaBrowser.Controller.Entities
/// <returns>IEnumerable{BaseItem}.</returns> /// <returns>IEnumerable{BaseItem}.</returns>
IEnumerable<BaseItem> GetTaggedItems(IEnumerable<BaseItem> inputItems); IEnumerable<BaseItem> GetTaggedItems(IEnumerable<BaseItem> inputItems);
/// <summary>
/// Gets the item filter.
/// </summary>
/// <returns>Func&lt;BaseItem, System.Boolean&gt;.</returns>
Func<BaseItem, bool> GetItemFilter(); Func<BaseItem, bool> GetItemFilter();
} }

@ -74,6 +74,11 @@ namespace MediaBrowser.Controller.Entities.Movies
} }
} }
public override bool IsAuthorizedToDelete(User user)
{
return true;
}
/// <summary> /// <summary>
/// Gets the trailer ids. /// Gets the trailer ids.
/// </summary> /// </summary>

@ -45,6 +45,11 @@ namespace MediaBrowser.Controller.Entities
} }
} }
public override bool CanDelete()
{
return false;
}
/// <summary> /// <summary>
/// Gets a value indicating whether this instance is owned item. /// Gets a value indicating whether this instance is owned item.
/// </summary> /// </summary>

@ -40,6 +40,11 @@ namespace MediaBrowser.Controller.Entities
} }
} }
public override bool CanDelete()
{
return false;
}
/// <summary> /// <summary>
/// Gets a value indicating whether this instance is owned item. /// Gets a value indicating whether this instance is owned item.
/// </summary> /// </summary>

@ -40,6 +40,11 @@ namespace MediaBrowser.Controller.Entities
return result.Items; return result.Items;
} }
public override bool CanDelete()
{
return false;
}
public override IEnumerable<BaseItem> GetRecursiveChildren(User user, Func<BaseItem, bool> filter) public override IEnumerable<BaseItem> GetRecursiveChildren(User user, Func<BaseItem, bool> filter)
{ {
var result = GetItems(new InternalItemsQuery var result = GetItems(new InternalItemsQuery

@ -64,6 +64,19 @@ namespace MediaBrowser.Controller.Entities
LinkedAlternateVersions = new List<LinkedChild>(); LinkedAlternateVersions = new List<LinkedChild>();
} }
public override bool CanDownload()
{
if (VideoType == VideoType.HdDvd || VideoType == VideoType.Dvd ||
VideoType == VideoType.BluRay)
{
return false;
}
var locationType = LocationType;
return locationType != LocationType.Remote &&
locationType != LocationType.Virtual;
}
[IgnoreDataMember] [IgnoreDataMember]
public override bool SupportsAddingToPlaylist public override bool SupportsAddingToPlaylist
{ {

@ -34,6 +34,11 @@ namespace MediaBrowser.Controller.Entities
} }
} }
public override bool CanDelete()
{
return false;
}
/// <summary> /// <summary>
/// Gets a value indicating whether this instance is owned item. /// Gets a value indicating whether this instance is owned item.
/// </summary> /// </summary>

@ -25,5 +25,9 @@ namespace MediaBrowser.Controller.LiveTv
Task RefreshMetadata(MetadataRefreshOptions options, CancellationToken cancellationToken); Task RefreshMetadata(MetadataRefreshOptions options, CancellationToken cancellationToken);
PlayAccess GetPlayAccess(User user); PlayAccess GetPlayAccess(User user);
bool CanDelete();
bool CanDelete(User user);
} }
} }

@ -1,4 +1,5 @@
using System.Runtime.Serialization; using System.Runtime.Serialization;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities; using MediaBrowser.Model.Entities;
@ -93,5 +94,10 @@ namespace MediaBrowser.Controller.LiveTv
{ {
return System.IO.Path.Combine(basePath, "livetv", Id.ToString("N")); return System.IO.Path.Combine(basePath, "livetv", Id.ToString("N"));
} }
public override bool IsAuthorizedToDelete(User user)
{
return user.Policy.EnableLiveTvManagement;
}
} }
} }

@ -1,5 +1,4 @@
using System.Runtime.Serialization; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Dto; using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities; using MediaBrowser.Model.Entities;
@ -8,6 +7,7 @@ using MediaBrowser.Model.MediaInfo;
using MediaBrowser.Model.Users; using MediaBrowser.Model.Users;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Runtime.Serialization;
namespace MediaBrowser.Controller.LiveTv namespace MediaBrowser.Controller.LiveTv
{ {
@ -135,5 +135,10 @@ namespace MediaBrowser.Controller.LiveTv
{ {
return System.IO.Path.Combine(basePath, "livetv", Id.ToString("N"), "metadata"); return System.IO.Path.Combine(basePath, "livetv", Id.ToString("N"), "metadata");
} }
public override bool CanDelete()
{
return false;
}
} }
} }

@ -1,13 +1,13 @@
using System.Runtime.Serialization; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.LiveTv; using MediaBrowser.Model.LiveTv;
using MediaBrowser.Model.Users;
using System; using System;
using System.Linq;
using System.Runtime.Serialization;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Linq;
using MediaBrowser.Model.Users;
namespace MediaBrowser.Controller.LiveTv namespace MediaBrowser.Controller.LiveTv
{ {
@ -215,5 +215,10 @@ namespace MediaBrowser.Controller.LiveTv
{ {
return System.IO.Path.Combine(basePath, "livetv", Id.ToString("N")); return System.IO.Path.Combine(basePath, "livetv", Id.ToString("N"));
} }
public override bool CanDelete()
{
return false;
}
} }
} }

@ -92,5 +92,10 @@ namespace MediaBrowser.Controller.LiveTv
{ {
return System.IO.Path.Combine(basePath, "livetv", Id.ToString("N")); return System.IO.Path.Combine(basePath, "livetv", Id.ToString("N"));
} }
public override bool IsAuthorizedToDelete(User user)
{
return user.Policy.EnableLiveTvManagement;
}
} }
} }

@ -1,7 +1,5 @@
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Model.Entities; using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Querying; using MediaBrowser.Model.Querying;
using System; using System;
@ -40,6 +38,11 @@ namespace MediaBrowser.Controller.Playlists
} }
} }
public override bool IsAuthorizedToDelete(User user)
{
return true;
}
public override bool IsSaveLocalMetadataEnabled() public override bool IsSaveLocalMetadataEnabled()
{ {
return true; return true;

@ -631,13 +631,13 @@ namespace MediaBrowser.MediaEncoding.Encoder
switch (qualitySetting) switch (qualitySetting)
{ {
case EncodingQuality.HighSpeed: case EncodingQuality.HighSpeed:
param += " -crf 23"; param += " -subq 0 -crf 23";
break; break;
case EncodingQuality.HighQuality: case EncodingQuality.HighQuality:
param += " -crf 20"; param += " -subq 3 -crf 20";
break; break;
case EncodingQuality.MaxQuality: case EncodingQuality.MaxQuality:
param += " -crf 18"; param += " -subq 6 -crf 18";
break; break;
} }
} }
@ -740,7 +740,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
param += " -level " + state.Options.Level.Value.ToString(UsCulture); param += " -level " + state.Options.Level.Value.ToString(UsCulture);
} }
return param; return "-pix_fmt yuv420p " + param;
} }
protected string GetVideoBitrateParam(EncodingJob state, string videoCodec, bool isHls) protected string GetVideoBitrateParam(EncodingJob state, string videoCodec, bool isHls)

@ -56,6 +56,8 @@ namespace MediaBrowser.Model.Dto
public int? AirsBeforeEpisodeNumber { get; set; } public int? AirsBeforeEpisodeNumber { get; set; }
public int? AbsoluteEpisodeNumber { get; set; } public int? AbsoluteEpisodeNumber { get; set; }
public bool? DisplaySpecialsWithSeasons { get; set; } public bool? DisplaySpecialsWithSeasons { get; set; }
public bool? CanDelete { get; set; }
public bool? CanDownload { get; set; }
public string PreferredMetadataLanguage { get; set; } public string PreferredMetadataLanguage { get; set; }
public string PreferredMetadataCountryCode { get; set; } public string PreferredMetadataCountryCode { get; set; }

@ -99,6 +99,12 @@ namespace MediaBrowser.Model.LiveTv
/// <value>The path.</value> /// <value>The path.</value>
public string Path { get; set; } public string Path { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this instance can delete.
/// </summary>
/// <value><c>null</c> if [can delete] contains no value, <c>true</c> if [can delete]; otherwise, <c>false</c>.</value>
public bool? CanDelete { get; set; }
/// <summary> /// <summary>
/// Overview of the recording. /// Overview of the recording.
/// </summary> /// </summary>

@ -1,5 +1,4 @@
 namespace MediaBrowser.Model.Querying
namespace MediaBrowser.Model.Querying
{ {
/// <summary> /// <summary>
/// Used to control the data that gets attached to DtoBaseItems /// Used to control the data that gets attached to DtoBaseItems
@ -26,6 +25,16 @@ namespace MediaBrowser.Model.Querying
/// </summary> /// </summary>
Budget, Budget,
/// <summary>
/// The can delete
/// </summary>
CanDelete,
/// <summary>
/// The can download
/// </summary>
CanDownload,
/// <summary> /// <summary>
/// The chapters /// The chapters
/// </summary> /// </summary>

@ -42,6 +42,7 @@ namespace MediaBrowser.Model.Users
public bool EnableMediaPlayback { get; set; } public bool EnableMediaPlayback { get; set; }
public bool EnableContentDeletion { get; set; } public bool EnableContentDeletion { get; set; }
public bool EnableContentDownloading { get; set; }
/// <summary> /// <summary>
/// Gets or sets a value indicating whether [enable synchronize]. /// Gets or sets a value indicating whether [enable synchronize].
@ -80,6 +81,8 @@ namespace MediaBrowser.Model.Users
EnabledDevices = new string[] { }; EnabledDevices = new string[] { };
EnableAllDevices = true; EnableAllDevices = true;
EnableContentDownloading = true;
} }
} }
} }

@ -284,6 +284,20 @@ namespace MediaBrowser.Server.Implementations.Dto
AttachLinkedChildImages(dto, playlist, user, options); AttachLinkedChildImages(dto, playlist, user, options);
} }
if (fields.Contains(ItemFields.CanDelete))
{
dto.CanDelete = user == null
? item.CanDelete()
: item.CanDelete(user);
}
if (fields.Contains(ItemFields.CanDownload))
{
dto.CanDownload = user == null
? item.CanDownload()
: item.CanDownload(user);
}
return dto; return dto;
} }

@ -74,7 +74,9 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security
ValidateUserAccess(user, request, authAttribtues, auth); ValidateUserAccess(user, request, authAttribtues, auth);
} }
if (!IsExemptFromRoles(auth, authAttribtues)) var info = (AuthenticationInfo)request.Items["OriginalAuthenticationInfo"];
if (!IsExemptFromRoles(auth, authAttribtues, info))
{ {
var roles = authAttribtues.GetRoles().ToList(); var roles = authAttribtues.GetRoles().ToList();
@ -142,7 +144,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security
StringComparer.OrdinalIgnoreCase); StringComparer.OrdinalIgnoreCase);
} }
private bool IsExemptFromRoles(AuthorizationInfo auth, IAuthenticationAttributes authAttribtues) private bool IsExemptFromRoles(AuthorizationInfo auth, IAuthenticationAttributes authAttribtues, AuthenticationInfo tokenInfo)
{ {
if (!_config.Configuration.IsStartupWizardCompleted && if (!_config.Configuration.IsStartupWizardCompleted &&
authAttribtues.AllowBeforeStartupWizard) authAttribtues.AllowBeforeStartupWizard)
@ -150,6 +152,16 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security
return true; return true;
} }
if (string.IsNullOrWhiteSpace(auth.Token))
{
return true;
}
if (tokenInfo != null && string.IsNullOrWhiteSpace(tokenInfo.UserId))
{
return true;
}
return false; return false;
} }
@ -175,6 +187,16 @@ namespace MediaBrowser.Server.Implementations.HttpServer.Security
}; };
} }
} }
if (roles.Contains("download", StringComparer.OrdinalIgnoreCase))
{
if (user == null || !user.Policy.EnableContentDownloading)
{
throw new SecurityException("User does not have download access.")
{
SecurityExceptionType = SecurityExceptionType.Unauthenticated
};
}
}
} }
private bool IsValidConnectKey(string token) private bool IsValidConnectKey(string token)

@ -229,6 +229,10 @@ namespace MediaBrowser.Server.Implementations.LiveTv
ServerId = _appHost.SystemId ServerId = _appHost.SystemId
}; };
dto.CanDelete = user == null
? recording.CanDelete()
: recording.CanDelete(user);
dto.MediaStreams = dto.MediaSources.SelectMany(i => i.MediaStreams).ToList(); dto.MediaStreams = dto.MediaSources.SelectMany(i => i.MediaStreams).ToList();
if (info.Status == RecordingStatus.InProgress) if (info.Status == RecordingStatus.InProgress)

@ -48,6 +48,7 @@
"LabelFailed": "(failed)", "LabelFailed": "(failed)",
"ButtonHelp": "Help", "ButtonHelp": "Help",
"ButtonSave": "Save", "ButtonSave": "Save",
"ButtonDownload": "Download",
"SyncJobStatusQueued": "Queued", "SyncJobStatusQueued": "Queued",
"SyncJobStatusConverting": "Converting", "SyncJobStatusConverting": "Converting",
"SyncJobStatusFailed": "Failed", "SyncJobStatusFailed": "Failed",
@ -56,6 +57,7 @@
"SyncJobStatusReadyToTransfer": "Ready to Transfer", "SyncJobStatusReadyToTransfer": "Ready to Transfer",
"SyncJobStatusTransferring": "Transferring", "SyncJobStatusTransferring": "Transferring",
"SyncJobStatusCompletedWithError": "Synced with errors", "SyncJobStatusCompletedWithError": "Synced with errors",
"SyncJobItemStatusReadyToTransfer": "Ready to Transfer",
"LabelCollection": "Collection", "LabelCollection": "Collection",
"HeaderAddToCollection": "Add to Collection", "HeaderAddToCollection": "Add to Collection",
"NewCollectionNameExample": "Example: Star Wars Collection", "NewCollectionNameExample": "Example: Star Wars Collection",

@ -285,10 +285,10 @@
"ButtonHelp": "Help", "ButtonHelp": "Help",
"OptionAllowUserToManageServer": "Allow this user to manage the server", "OptionAllowUserToManageServer": "Allow this user to manage the server",
"HeaderFeatureAccess": "Feature Access", "HeaderFeatureAccess": "Feature Access",
"OptionAllowMediaPlayback": "Allow media playback", "OptionAllowMediaPlayback": "Media playback",
"OptionAllowBrowsingLiveTv": "Allow browsing of live tv", "OptionAllowBrowsingLiveTv": "Live TV",
"OptionAllowDeleteLibraryContent": "Allow deletion of library content", "OptionAllowDeleteLibraryContent": "Media deletion",
"OptionAllowManageLiveTv": "Allow management of live tv recordings", "OptionAllowManageLiveTv": "Live TV recording management",
"OptionAllowRemoteControlOthers": "Allow remote control of other users", "OptionAllowRemoteControlOthers": "Allow remote control of other users",
"OptionAllowRemoteSharedDevices": "Allow remote control of shared devices", "OptionAllowRemoteSharedDevices": "Allow remote control of shared devices",
"OptionAllowRemoteSharedDevicesHelp": "Dlna devices are considered shared until a user begins controlling it.", "OptionAllowRemoteSharedDevicesHelp": "Dlna devices are considered shared until a user begins controlling it.",
@ -1362,7 +1362,8 @@
"LabelEnableSingleImageInDidlLimitHelp": "Some devices will not render properly if multiple images are embedded within Didl.", "LabelEnableSingleImageInDidlLimitHelp": "Some devices will not render properly if multiple images are embedded within Didl.",
"TabActivity": "Activity", "TabActivity": "Activity",
"TitleSync": "Sync", "TitleSync": "Sync",
"OptionAllowSyncContent": "Allow syncing media to devices", "OptionAllowSyncContent": "Sync",
"OptionAllowContentDownloading": "Media downloading",
"NameSeasonUnknown": "Season Unknown", "NameSeasonUnknown": "Season Unknown",
"NameSeasonNumber": "Season {0}", "NameSeasonNumber": "Season {0}",
"LabelNewUserNameHelp": "Usernames can contain letters (a-z), numbers (0-9), dashes (-), underscores (_), apostrophes ('), and periods (.)", "LabelNewUserNameHelp": "Usernames can contain letters (a-z), numbers (0-9), dashes (-), underscores (_), apostrophes ('), and periods (.)",

@ -311,8 +311,10 @@ namespace MediaBrowser.Server.Implementations.Sync
var itemByName = item as IItemByName; var itemByName = item as IItemByName;
if (itemByName != null) if (itemByName != null)
{ {
var itemByNameFilter = itemByName.GetItemFilter();
return user.RootFolder return user.RootFolder
.GetRecursiveChildren(user, itemByName.GetItemFilter()); .GetRecursiveChildren(user, i => !i.IsFolder && itemByNameFilter(i));
} }
if (item.IsFolder) if (item.IsFolder)

@ -414,7 +414,6 @@ namespace MediaBrowser.WebDashboard.Api
"indexpage.js", "indexpage.js",
"itembynamedetailpage.js", "itembynamedetailpage.js",
"itemdetailpage.js", "itemdetailpage.js",
"itemgallery.js",
"itemlistpage.js", "itemlistpage.js",
"librarypathmapping.js", "librarypathmapping.js",
"reports.js", "reports.js",

@ -1656,9 +1656,6 @@
</Content> </Content>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Content Include="dashboard-ui\itemgallery.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\librarysettings.html"> <Content Include="dashboard-ui\librarysettings.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
@ -1707,9 +1704,6 @@
<Content Include="dashboard-ui\scripts\edititemmetadata.js"> <Content Include="dashboard-ui\scripts\edititemmetadata.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<Content Include="dashboard-ui\scripts\itemgallery.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\scripts\librarysettings.js"> <Content Include="dashboard-ui\scripts\librarysettings.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>

Loading…
Cancel
Save