New: Don't return API Keys and Passwords via the API
This commit is contained in:
parent
b154b00c61
commit
570be88215
|
@ -48,7 +48,11 @@ namespace Sonarr.Api.V3.CustomFormats
|
||||||
private static ICustomFormatSpecification MapSpecification(CustomFormatSpecificationSchema resource, List<ICustomFormatSpecification> specifications)
|
private static ICustomFormatSpecification MapSpecification(CustomFormatSpecificationSchema resource, List<ICustomFormatSpecification> specifications)
|
||||||
{
|
{
|
||||||
var type = specifications.SingleOrDefault(x => x.GetType().Name == resource.Implementation).GetType();
|
var type = specifications.SingleOrDefault(x => x.GetType().Name == resource.Implementation).GetType();
|
||||||
var spec = (ICustomFormatSpecification)SchemaBuilder.ReadFromSchema(resource.Fields, type);
|
|
||||||
|
// Finding the exact current specification isn't possible given the dynamic nature of them and the possibility that multiple
|
||||||
|
// of the same type exist within the same format. Passing in null is safe as long as there never exists a specification that
|
||||||
|
// relies on additional privacy.
|
||||||
|
var spec = (ICustomFormatSpecification)SchemaBuilder.ReadFromSchema(resource.Fields, type, null);
|
||||||
spec.Name = resource.Name;
|
spec.Name = resource.Name;
|
||||||
spec.Negate = resource.Negate;
|
spec.Negate = resource.Negate;
|
||||||
spec.Required = resource.Required;
|
spec.Required = resource.Required;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using NzbDrone.Core.Download;
|
using NzbDrone.Core.Download;
|
||||||
using NzbDrone.Core.Indexers;
|
using NzbDrone.Core.Indexers;
|
||||||
|
|
||||||
namespace Sonarr.Api.V3.DownloadClient
|
namespace Sonarr.Api.V3.DownloadClient
|
||||||
|
@ -32,14 +32,14 @@ namespace Sonarr.Api.V3.DownloadClient
|
||||||
return resource;
|
return resource;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override DownloadClientDefinition ToModel(DownloadClientResource resource)
|
public override DownloadClientDefinition ToModel(DownloadClientResource resource, DownloadClientDefinition existingDefinition)
|
||||||
{
|
{
|
||||||
if (resource == null)
|
if (resource == null)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var definition = base.ToModel(resource);
|
var definition = base.ToModel(resource, existingDefinition);
|
||||||
|
|
||||||
definition.Enable = resource.Enable;
|
definition.Enable = resource.Enable;
|
||||||
definition.Protocol = resource.Protocol;
|
definition.Protocol = resource.Protocol;
|
||||||
|
|
|
@ -40,14 +40,14 @@ namespace Sonarr.Api.V3.ImportLists
|
||||||
return resource;
|
return resource;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override ImportListDefinition ToModel(ImportListResource resource)
|
public override ImportListDefinition ToModel(ImportListResource resource, ImportListDefinition existingDefinition)
|
||||||
{
|
{
|
||||||
if (resource == null)
|
if (resource == null)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var definition = base.ToModel(resource);
|
var definition = base.ToModel(resource, existingDefinition);
|
||||||
|
|
||||||
definition.EnableAutomaticAdd = resource.EnableAutomaticAdd;
|
definition.EnableAutomaticAdd = resource.EnableAutomaticAdd;
|
||||||
definition.ShouldMonitor = resource.ShouldMonitor;
|
definition.ShouldMonitor = resource.ShouldMonitor;
|
||||||
|
|
|
@ -39,14 +39,14 @@ namespace Sonarr.Api.V3.Indexers
|
||||||
return resource;
|
return resource;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override IndexerDefinition ToModel(IndexerResource resource)
|
public override IndexerDefinition ToModel(IndexerResource resource, IndexerDefinition existingDefinition)
|
||||||
{
|
{
|
||||||
if (resource == null)
|
if (resource == null)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var definition = base.ToModel(resource);
|
var definition = base.ToModel(resource, existingDefinition);
|
||||||
|
|
||||||
definition.EnableRss = resource.EnableRss;
|
definition.EnableRss = resource.EnableRss;
|
||||||
definition.EnableAutomaticSearch = resource.EnableAutomaticSearch;
|
definition.EnableAutomaticSearch = resource.EnableAutomaticSearch;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using NzbDrone.Core.Extras.Metadata;
|
using NzbDrone.Core.Extras.Metadata;
|
||||||
|
|
||||||
namespace Sonarr.Api.V3.Metadata
|
namespace Sonarr.Api.V3.Metadata
|
||||||
{
|
{
|
||||||
|
@ -23,14 +23,14 @@ namespace Sonarr.Api.V3.Metadata
|
||||||
return resource;
|
return resource;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override MetadataDefinition ToModel(MetadataResource resource)
|
public override MetadataDefinition ToModel(MetadataResource resource, MetadataDefinition existingDefinition)
|
||||||
{
|
{
|
||||||
if (resource == null)
|
if (resource == null)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var definition = base.ToModel(resource);
|
var definition = base.ToModel(resource, existingDefinition);
|
||||||
|
|
||||||
definition.Enable = resource.Enable;
|
definition.Enable = resource.Enable;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using NzbDrone.Core.Notifications;
|
using NzbDrone.Core.Notifications;
|
||||||
|
|
||||||
namespace Sonarr.Api.V3.Notifications
|
namespace Sonarr.Api.V3.Notifications
|
||||||
{
|
{
|
||||||
|
@ -61,14 +61,14 @@ namespace Sonarr.Api.V3.Notifications
|
||||||
return resource;
|
return resource;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override NotificationDefinition ToModel(NotificationResource resource)
|
public override NotificationDefinition ToModel(NotificationResource resource, NotificationDefinition existingDefinition)
|
||||||
{
|
{
|
||||||
if (resource == null)
|
if (resource == null)
|
||||||
{
|
{
|
||||||
return default(NotificationDefinition);
|
return default(NotificationDefinition);
|
||||||
}
|
}
|
||||||
|
|
||||||
var definition = base.ToModel(resource);
|
var definition = base.ToModel(resource, existingDefinition);
|
||||||
|
|
||||||
definition.OnGrab = resource.OnGrab;
|
definition.OnGrab = resource.OnGrab;
|
||||||
definition.OnDownload = resource.OnDownload;
|
definition.OnDownload = resource.OnDownload;
|
||||||
|
|
|
@ -92,7 +92,8 @@ namespace Sonarr.Api.V3
|
||||||
|
|
||||||
private TProviderDefinition GetDefinition(TProviderResource providerResource, bool validate, bool includeWarnings, bool forceValidate)
|
private TProviderDefinition GetDefinition(TProviderResource providerResource, bool validate, bool includeWarnings, bool forceValidate)
|
||||||
{
|
{
|
||||||
var definition = _resourceMapper.ToModel(providerResource);
|
var existingDefinition = providerResource.Id > 0 ? _providerFactory.Find(providerResource.Id) : null;
|
||||||
|
var definition = _resourceMapper.ToModel(providerResource, existingDefinition);
|
||||||
|
|
||||||
if (validate && (definition.Enable || forceValidate))
|
if (validate && (definition.Enable || forceValidate))
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using NzbDrone.Common.Reflection;
|
using NzbDrone.Common.Reflection;
|
||||||
using NzbDrone.Core.ThingiProvider;
|
using NzbDrone.Core.ThingiProvider;
|
||||||
using Sonarr.Http.ClientSchema;
|
using Sonarr.Http.ClientSchema;
|
||||||
|
@ -42,7 +42,7 @@ namespace Sonarr.Api.V3
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual TProviderDefinition ToModel(TProviderResource resource)
|
public virtual TProviderDefinition ToModel(TProviderResource resource, TProviderDefinition existingDefinition)
|
||||||
{
|
{
|
||||||
if (resource == null)
|
if (resource == null)
|
||||||
{
|
{
|
||||||
|
@ -62,7 +62,7 @@ namespace Sonarr.Api.V3
|
||||||
};
|
};
|
||||||
|
|
||||||
var configContract = ReflectionExtensions.CoreAssembly.FindTypeByName(definition.ConfigContract);
|
var configContract = ReflectionExtensions.CoreAssembly.FindTypeByName(definition.ConfigContract);
|
||||||
definition.Settings = (IProviderConfig)SchemaBuilder.ReadFromSchema(resource.Fields, configContract);
|
definition.Settings = (IProviderConfig)SchemaBuilder.ReadFromSchema(resource.Fields, configContract, existingDefinition?.Settings);
|
||||||
|
|
||||||
return definition;
|
return definition;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ namespace Sonarr.Http.ClientSchema
|
||||||
public string SelectOptionsProviderAction { get; set; }
|
public string SelectOptionsProviderAction { get; set; }
|
||||||
public string Section { get; set; }
|
public string Section { get; set; }
|
||||||
public string Hidden { get; set; }
|
public string Hidden { get; set; }
|
||||||
|
public PrivacyLevel Privacy { get; set; }
|
||||||
public Field Clone()
|
public Field Clone()
|
||||||
{
|
{
|
||||||
return (Field)MemberwiseClone();
|
return (Field)MemberwiseClone();
|
||||||
|
|
|
@ -13,6 +13,7 @@ namespace Sonarr.Http.ClientSchema
|
||||||
{
|
{
|
||||||
public static class SchemaBuilder
|
public static class SchemaBuilder
|
||||||
{
|
{
|
||||||
|
private static readonly string PRIVATE_VALUE = "********";
|
||||||
private static Dictionary<Type, FieldMapping[]> _mappings = new Dictionary<Type, FieldMapping[]>();
|
private static Dictionary<Type, FieldMapping[]> _mappings = new Dictionary<Type, FieldMapping[]>();
|
||||||
|
|
||||||
public static List<Field> ToSchema(object model)
|
public static List<Field> ToSchema(object model)
|
||||||
|
@ -26,7 +27,15 @@ namespace Sonarr.Http.ClientSchema
|
||||||
foreach (var mapping in mappings)
|
foreach (var mapping in mappings)
|
||||||
{
|
{
|
||||||
var field = mapping.Field.Clone();
|
var field = mapping.Field.Clone();
|
||||||
field.Value = mapping.GetterFunc(model);
|
|
||||||
|
if (field.Privacy == PrivacyLevel.ApiKey || field.Privacy == PrivacyLevel.Password)
|
||||||
|
{
|
||||||
|
field.Value = PRIVATE_VALUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
field.Value = mapping.GetterFunc(model);
|
||||||
|
}
|
||||||
|
|
||||||
result.Add(field);
|
result.Add(field);
|
||||||
}
|
}
|
||||||
|
@ -34,7 +43,7 @@ namespace Sonarr.Http.ClientSchema
|
||||||
return result.OrderBy(r => r.Order).ToList();
|
return result.OrderBy(r => r.Order).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static object ReadFromSchema(List<Field> fields, Type targetType)
|
public static object ReadFromSchema(List<Field> fields, Type targetType, object model)
|
||||||
{
|
{
|
||||||
Ensure.That(targetType, () => targetType).IsNotNull();
|
Ensure.That(targetType, () => targetType).IsNotNull();
|
||||||
|
|
||||||
|
@ -49,18 +58,25 @@ namespace Sonarr.Http.ClientSchema
|
||||||
|
|
||||||
if (field != null)
|
if (field != null)
|
||||||
{
|
{
|
||||||
mapping.SetterFunc(target, field.Value);
|
// Use the Privacy property from the mapping's field as Privacy may not be set in the API request (nor is it required)
|
||||||
|
if ((mapping.Field.Privacy == PrivacyLevel.ApiKey || mapping.Field.Privacy == PrivacyLevel.Password) &&
|
||||||
|
(field.Value?.ToString()?.Equals(PRIVATE_VALUE) ?? false) &&
|
||||||
|
model != null)
|
||||||
|
{
|
||||||
|
var existingValue = mapping.GetterFunc(model);
|
||||||
|
|
||||||
|
mapping.SetterFunc(target, existingValue);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mapping.SetterFunc(target, field.Value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static T ReadFromSchema<T>(List<Field> fields)
|
|
||||||
{
|
|
||||||
return (T)ReadFromSchema(fields, typeof(T));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ideally this function should begin a System.Linq.Expression expression tree since it's faster.
|
// Ideally this function should begin a System.Linq.Expression expression tree since it's faster.
|
||||||
// But it's probably not needed till performance issues pop up.
|
// But it's probably not needed till performance issues pop up.
|
||||||
public static FieldMapping[] GetFieldMappings(Type type)
|
public static FieldMapping[] GetFieldMappings(Type type)
|
||||||
|
@ -104,7 +120,8 @@ namespace Sonarr.Http.ClientSchema
|
||||||
Order = fieldAttribute.Order,
|
Order = fieldAttribute.Order,
|
||||||
Advanced = fieldAttribute.Advanced,
|
Advanced = fieldAttribute.Advanced,
|
||||||
Type = fieldAttribute.Type.ToString().FirstCharToLower(),
|
Type = fieldAttribute.Type.ToString().FirstCharToLower(),
|
||||||
Section = fieldAttribute.Section
|
Section = fieldAttribute.Section,
|
||||||
|
Privacy = fieldAttribute.Privacy
|
||||||
};
|
};
|
||||||
|
|
||||||
if (fieldAttribute.Type == FieldType.Select || fieldAttribute.Type == FieldType.TagSelect)
|
if (fieldAttribute.Type == FieldType.Select || fieldAttribute.Type == FieldType.TagSelect)
|
||||||
|
@ -131,7 +148,7 @@ namespace Sonarr.Http.ClientSchema
|
||||||
Field = field,
|
Field = field,
|
||||||
PropertyType = propertyInfo.PropertyType,
|
PropertyType = propertyInfo.PropertyType,
|
||||||
GetterFunc = t => propertyInfo.GetValue(targetSelector(t), null),
|
GetterFunc = t => propertyInfo.GetValue(targetSelector(t), null),
|
||||||
SetterFunc = (t, v) => propertyInfo.SetValue(targetSelector(t), valueConverter(v), null)
|
SetterFunc = (t, v) => propertyInfo.SetValue(targetSelector(t), v?.GetType() == propertyInfo.PropertyType ? v : valueConverter(v), null)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
Loading…
Reference in New Issue