diff --git a/Kyoo.Abstractions/Controllers/ILibraryManager.cs b/Kyoo.Abstractions/Controllers/ILibraryManager.cs
index 2257af97..8b63bdb9 100644
--- a/Kyoo.Abstractions/Controllers/ILibraryManager.cs
+++ b/Kyoo.Abstractions/Controllers/ILibraryManager.cs
@@ -10,7 +10,7 @@ using Kyoo.Abstractions.Models.Exceptions;
namespace Kyoo.Abstractions.Controllers
{
///
- /// An interface to interract with the database. Every repository is mapped through here.
+ /// An interface to interact with the database. Every repository is mapped through here.
///
public interface ILibraryManager
{
@@ -20,7 +20,8 @@ namespace Kyoo.Abstractions.Controllers
/// The type you want
/// If the item is not found
/// The repository corresponding
- IRepository GetRepository() where T : class, IResource;
+ IRepository GetRepository()
+ where T : class, IResource;
///
/// The repository that handle libraries.
@@ -28,7 +29,7 @@ namespace Kyoo.Abstractions.Controllers
ILibraryRepository LibraryRepository { get; }
///
- /// The repository that handle libraries's items (a wrapper arround shows & collections).
+ /// The repository that handle libraries items (a wrapper around shows & collections).
///
ILibraryItemRepository LibraryItemRepository { get; }
@@ -90,7 +91,8 @@ namespace Kyoo.Abstractions.Controllers
/// If the item is not found
/// The resource found
[ItemNotNull]
- Task Get(int id) where T : class, IResource;
+ Task Get(int id)
+ where T : class, IResource;
///
/// Get the resource by it's slug
@@ -100,7 +102,8 @@ namespace Kyoo.Abstractions.Controllers
/// If the item is not found
/// The resource found
[ItemNotNull]
- Task Get(string slug) where T : class, IResource;
+ Task Get(string slug)
+ where T : class, IResource;
///
/// Get the resource by a filter function.
@@ -110,7 +113,8 @@ namespace Kyoo.Abstractions.Controllers
/// If the item is not found
/// The first resource found that match the where function
[ItemNotNull]
- Task Get(Expression> where) where T : class, IResource;
+ Task Get(Expression> where)
+ where T : class, IResource;
///
/// Get a season from it's showID and it's seasonNumber
@@ -161,7 +165,8 @@ namespace Kyoo.Abstractions.Controllers
/// The type of the resource
/// The resource found
[ItemCanBeNull]
- Task GetOrDefault(int id) where T : class, IResource;
+ Task GetOrDefault(int id)
+ where T : class, IResource;
///
/// Get the resource by it's slug or null if it is not found.
@@ -170,7 +175,8 @@ namespace Kyoo.Abstractions.Controllers
/// The type of the resource
/// The resource found
[ItemCanBeNull]
- Task GetOrDefault(string slug) where T : class, IResource;
+ Task GetOrDefault(string slug)
+ where T : class, IResource;
///
/// Get the resource by a filter function or null if it is not found.
@@ -179,7 +185,8 @@ namespace Kyoo.Abstractions.Controllers
/// The type of the resource
/// The first resource found that match the where function
[ItemCanBeNull]
- Task GetOrDefault(Expression> where) where T : class, IResource;
+ Task GetOrDefault(Expression> where)
+ where T : class, IResource;
///
/// Get a season from it's showID and it's seasonNumber or null if it is not found.
@@ -219,20 +226,19 @@ namespace Kyoo.Abstractions.Controllers
[ItemCanBeNull]
Task GetOrDefault(string showSlug, int seasonNumber, int episodeNumber);
-
///
/// Load a related resource
///
/// The source object.
/// A getter function for the member to load
///
- /// true if you want to load the relation even if it is not null, false otherwise.
+ /// true if you want to load the relation even if it is not null, false otherwise.
///
/// The type of the source object
/// The related resource's type
/// The param
///
- ///
+ ///
///
Task Load([NotNull] T obj, Expression> member, bool force = false)
where T : class, IResource
@@ -244,13 +250,13 @@ namespace Kyoo.Abstractions.Controllers
/// The source object.
/// A getter function for the member to load
///
- /// true if you want to load the relation even if it is not null, false otherwise.
+ /// true if you want to load the relation even if it is not null, false otherwise.
///
/// The type of the source object
/// The related resource's type
/// The param
///
- ///
+ ///
///
Task Load([NotNull] T obj, Expression>> member, bool force = false)
where T : class, IResource
@@ -262,7 +268,7 @@ namespace Kyoo.Abstractions.Controllers
/// The source object.
/// The name of the resource to load (case sensitive)
///
- /// true if you want to load the relation even if it is not null, false otherwise.
+ /// true if you want to load the relation even if it is not null, false otherwise.
///
/// The type of the source object
/// The param
@@ -273,24 +279,25 @@ namespace Kyoo.Abstractions.Controllers
where T : class, IResource;
///
- /// Load a related resource without specifing it's type.
+ /// Load a related resource without specifying it's type.
///
/// The source object.
/// The name of the resource to load (case sensitive)
///
- /// true if you want to load the relation even if it is not null, false otherwise.
+ /// true if you want to load the relation even if it is not null, false otherwise.
///
///
///
- ///
+ ///
+ /// A representing the asynchronous operation.
Task Load([NotNull] IResource obj, string memberName, bool force = false);
///
- /// Get items (A wrapper arround shows or collections) from a library.
+ /// Get items (A wrapper around shows or collections) from a library.
///
/// The ID of the library
/// A filter function
- /// Sort informations (sort order & sort by)
+ /// Sort information (sort order & sort by)
/// How many items to return and where to start
/// A list of items that match every filters
Task> GetItemsFromLibrary(int id,
@@ -299,7 +306,7 @@ namespace Kyoo.Abstractions.Controllers
Pagination limit = default);
///
- /// Get items (A wrapper arround shows or collections) from a library.
+ /// Get items (A wrapper around shows or collections) from a library.
///
/// The ID of the library
/// A filter function
@@ -313,11 +320,11 @@ namespace Kyoo.Abstractions.Controllers
) => GetItemsFromLibrary(id, where, new Sort(sort), limit);
///
- /// Get items (A wrapper arround shows or collections) from a library.
+ /// Get items (A wrapper around shows or collections) from a library.
///
/// The slug of the library
/// A filter function
- /// Sort informations (sort order & sort by)
+ /// Sort information (sort order & sort by)
/// How many items to return and where to start
/// A list of items that match every filters
Task> GetItemsFromLibrary(string slug,
@@ -326,7 +333,7 @@ namespace Kyoo.Abstractions.Controllers
Pagination limit = default);
///
- /// Get items (A wrapper arround shows or collections) from a library.
+ /// Get items (A wrapper around shows or collections) from a library.
///
/// The slug of the library
/// A filter function
@@ -339,13 +346,12 @@ namespace Kyoo.Abstractions.Controllers
Pagination limit = default
) => GetItemsFromLibrary(slug, where, new Sort(sort), limit);
-
///
/// Get people's roles from a show.
///
/// The ID of the show
/// A filter function
- /// Sort informations (sort order & sort by)
+ /// Sort information (sort order & sort by)
/// How many items to return and where to start
/// A list of items that match every filters
Task> GetPeopleFromShow(int showID,
@@ -372,7 +378,7 @@ namespace Kyoo.Abstractions.Controllers
///
/// The slug of the show
/// A filter function
- /// Sort informations (sort order & sort by)
+ /// Sort information (sort order & sort by)
/// How many items to return and where to start
/// A list of items that match every filters
Task> GetPeopleFromShow(string showSlug,
@@ -394,13 +400,12 @@ namespace Kyoo.Abstractions.Controllers
Pagination limit = default
) => GetPeopleFromShow(showSlug, where, new Sort(sort), limit);
-
///
/// Get people's roles from a person.
///
/// The id of the person
/// A filter function
- /// Sort informations (sort order & sort by)
+ /// Sort information (sort order & sort by)
/// How many items to return and where to start
/// A list of items that match every filters
Task> GetRolesFromPeople(int id,
@@ -427,7 +432,7 @@ namespace Kyoo.Abstractions.Controllers
///
/// The slug of the person
/// A filter function
- /// Sort informations (sort order & sort by)
+ /// Sort information (sort order & sort by)
/// How many items to return and where to start
/// A list of items that match every filters
Task> GetRolesFromPeople(string slug,
@@ -449,13 +454,13 @@ namespace Kyoo.Abstractions.Controllers
Pagination limit = default
) => GetRolesFromPeople(slug, where, new Sort(sort), limit);
-
///
/// Setup relations between a show, a library and a collection
///
/// The show's ID to setup relations with
/// The library's ID to setup relations with (optional)
/// The collection's ID to setup relations with (optional)
+ /// A representing the asynchronous operation.
Task AddShowLink(int showID, int? libraryID, int? collectionID);
///
@@ -464,19 +469,21 @@ namespace Kyoo.Abstractions.Controllers
/// The show to setup relations with
/// The library to setup relations with (optional)
/// The collection to setup relations with (optional)
+ /// A representing the asynchronous operation.
Task AddShowLink([NotNull] Show show, Library library, Collection collection);
///
/// Get all resources with filters
///
/// A filter function
- /// Sort informations (sort order & sort by)
+ /// Sort information (sort order & sort by)
/// How many items to return and where to start
/// The type of resources to load
/// A list of resources that match every filters
Task> GetAll(Expression> where = null,
Sort sort = default,
- Pagination limit = default) where T : class, IResource;
+ Pagination limit = default)
+ where T : class, IResource;
///
/// Get all resources with filters
@@ -488,7 +495,8 @@ namespace Kyoo.Abstractions.Controllers
/// A list of resources that match every filters
Task> GetAll([Optional] Expression> where,
Expression> sort,
- Pagination limit = default) where T : class, IResource
+ Pagination limit = default)
+ where T : class, IResource
{
return GetAll(where, new Sort(sort), limit);
}
@@ -499,7 +507,8 @@ namespace Kyoo.Abstractions.Controllers
/// A filter function
/// The type of resources to load
/// A list of resources that match every filters
- Task GetCount(Expression> where = null) where T : class, IResource;
+ Task GetCount(Expression> where = null)
+ where T : class, IResource;
///
/// Search for a resource
@@ -507,15 +516,17 @@ namespace Kyoo.Abstractions.Controllers
/// The search query
/// The type of resources
/// A list of 20 items that match the search query
- Task> Search(string query) where T : class, IResource;
+ Task> Search(string query)
+ where T : class, IResource;
///
/// Create a new resource.
///
/// The item to register
/// The type of resource
- /// The resource registers and completed by database's informations (related items & so on)
- Task Create([NotNull] T item) where T : class, IResource;
+ /// The resource registers and completed by database's information (related items & so on)
+ Task Create([NotNull] T item)
+ where T : class, IResource;
///
/// Create a new resource if it does not exist already. If it does, the existing value is returned instead.
@@ -523,17 +534,19 @@ namespace Kyoo.Abstractions.Controllers
/// The item to register
/// The type of resource
/// The newly created item or the existing value if it existed.
- Task CreateIfNotExists([NotNull] T item) where T : class, IResource;
+ Task CreateIfNotExists([NotNull] T item)
+ where T : class, IResource;
///
/// Edit a resource
///
- /// The resourcce to edit, it's ID can't change.
+ /// The resource to edit, it's ID can't change.
/// Should old properties of the resource be discarded or should null values considered as not changed?
/// The type of resources
/// If the item is not found
- /// The resource edited and completed by database's informations (related items & so on)
- Task Edit(T item, bool resetOld) where T : class, IResource;
+ /// The resource edited and completed by database's information (related items & so on)
+ Task Edit(T item, bool resetOld)
+ where T : class, IResource;
///
/// Delete a resource.
@@ -541,7 +554,9 @@ namespace Kyoo.Abstractions.Controllers
/// The resource to delete
/// The type of resource to delete
/// If the item is not found
- Task Delete(T item) where T : class, IResource;
+ /// A representing the asynchronous operation.
+ Task Delete(T item)
+ where T : class, IResource;
///
/// Delete a resource by it's ID.
@@ -549,7 +564,9 @@ namespace Kyoo.Abstractions.Controllers
/// The id of the resource to delete
/// The type of resource to delete
/// If the item is not found
- Task Delete(int id) where T : class, IResource;
+ /// A representing the asynchronous operation.
+ Task Delete(int id)
+ where T : class, IResource;
///
/// Delete a resource by it's slug.
@@ -557,6 +574,8 @@ namespace Kyoo.Abstractions.Controllers
/// The slug of the resource to delete
/// The type of resource to delete
/// If the item is not found
- Task Delete(string slug) where T : class, IResource;
+ /// A representing the asynchronous operation.
+ Task Delete(string slug)
+ where T : class, IResource;
}
}
diff --git a/Kyoo.Abstractions/Controllers/IMetadataProvider.cs b/Kyoo.Abstractions/Controllers/IMetadataProvider.cs
index c04ac906..73c0a974 100644
--- a/Kyoo.Abstractions/Controllers/IMetadataProvider.cs
+++ b/Kyoo.Abstractions/Controllers/IMetadataProvider.cs
@@ -1,7 +1,7 @@
-using Kyoo.Abstractions.Models;
-using System.Collections.Generic;
+using System.Collections.Generic;
using System.Threading.Tasks;
using JetBrains.Annotations;
+using Kyoo.Abstractions.Models;
namespace Kyoo.Abstractions.Controllers
{
@@ -30,6 +30,7 @@ namespace Kyoo.Abstractions.Controllers
/// Merging metadata is the job of Kyoo, a complex is given
/// to make a precise search and give you every available properties, not to discard properties.
///
+ /// The type of resource to retrieve metadata for.
/// A new containing metadata from your provider or null
[ItemCanBeNull]
Task Get([NotNull] T item)
@@ -39,6 +40,7 @@ namespace Kyoo.Abstractions.Controllers
/// Search for a specific type of items with a given query.
///
/// The search query to use.
+ /// The type of resource to search metadata for.
/// The list of items that could be found on this specific provider.
[ItemNotNull]
Task> Search(string query)
@@ -62,7 +64,7 @@ namespace Kyoo.Abstractions.Controllers
///
/// Since this is a composite and not a real provider, no metadata is available.
- /// It is not meant to be stored or selected. This class will handle merge based on what is required.
+ /// It is not meant to be stored or selected. This class will handle merge based on what is required.
///
public Provider Provider => null;
diff --git a/Kyoo.Abstractions/Controllers/IPermissionValidator.cs b/Kyoo.Abstractions/Controllers/IPermissionValidator.cs
new file mode 100644
index 00000000..53bd8b83
--- /dev/null
+++ b/Kyoo.Abstractions/Controllers/IPermissionValidator.cs
@@ -0,0 +1,29 @@
+using Kyoo.Abstractions.Models.Permissions;
+using Microsoft.AspNetCore.Mvc.Filters;
+
+namespace Kyoo.Abstractions.Controllers
+{
+ ///
+ /// A service to validate permissions.
+ ///
+ public interface IPermissionValidator
+ {
+ ///
+ /// Create an IAuthorizationFilter that will be used to validate permissions.
+ /// This can registered with any lifetime.
+ ///
+ /// The permission attribute to validate.
+ /// An authorization filter used to validate the permission.
+ IFilterMetadata Create(PermissionAttribute attribute);
+
+ ///
+ /// Create an IAuthorizationFilter that will be used to validate permissions.
+ /// This can registered with any lifetime.
+ ///
+ ///
+ /// A partial attribute to validate. See .
+ ///
+ /// An authorization filter used to validate the permission.
+ IFilterMetadata Create(PartialPermissionAttribute attribute);
+ }
+}
diff --git a/Kyoo.Abstractions/Controllers/IPlugin.cs b/Kyoo.Abstractions/Controllers/IPlugin.cs
index 507fbb39..6ea00db3 100644
--- a/Kyoo.Abstractions/Controllers/IPlugin.cs
+++ b/Kyoo.Abstractions/Controllers/IPlugin.cs
@@ -35,7 +35,7 @@ namespace Kyoo.Abstractions.Controllers
/// true if the plugin should be enabled, false otherwise.
/// If a plugin is not enabled, no configure method will be called.
/// This allow one to enable a plugin if a specific configuration value is set or if the environment contains
- /// the right settings.
+ /// the right settings.
///
///
/// By default, a plugin is always enabled. This method can be overriden to change this behavior.
diff --git a/Kyoo.Abstractions/Controllers/IRepository.cs b/Kyoo.Abstractions/Controllers/IRepository.cs
index 5cc6c9a3..2898e9a9 100644
--- a/Kyoo.Abstractions/Controllers/IRepository.cs
+++ b/Kyoo.Abstractions/Controllers/IRepository.cs
@@ -19,8 +19,9 @@ namespace Kyoo.Abstractions.Controllers
/// The count of items to return.
///
public int Count { get; }
+
///
- /// Where to start? Using the given sort
+ /// Where to start? Using the given sort.
///
public int AfterID { get; }
@@ -53,6 +54,7 @@ namespace Kyoo.Abstractions.Controllers
/// The sort key. This member will be used to sort the results.
///
public Expression> Key { get; }
+
///
/// If this is set to true, items will be sorted in descend order else, they will be sorted in ascendant order.
///
@@ -121,7 +123,8 @@ namespace Kyoo.Abstractions.Controllers
/// A common repository for every resources.
///
/// The resource's type that this repository manage.
- public interface IRepository : IBaseRepository where T : class, IResource
+ public interface IRepository : IBaseRepository
+ where T : class, IResource
{
///
/// Get a resource from it's ID.
diff --git a/Kyoo.Abstractions/Models/Attributes/Permission/PartialPermissionAttribute.cs b/Kyoo.Abstractions/Models/Attributes/Permission/PartialPermissionAttribute.cs
new file mode 100644
index 00000000..5cab9ad8
--- /dev/null
+++ b/Kyoo.Abstractions/Models/Attributes/Permission/PartialPermissionAttribute.cs
@@ -0,0 +1,70 @@
+using System;
+using Kyoo.Abstractions.Controllers;
+using Microsoft.AspNetCore.Mvc.Filters;
+using Microsoft.Extensions.DependencyInjection;
+
+namespace Kyoo.Abstractions.Models.Permissions
+{
+ ///
+ /// Specify one part of a permissions needed for the API (the kind or the type).
+ ///
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
+ public class PartialPermissionAttribute : Attribute, IFilterFactory
+ {
+ ///
+ /// The needed permission type.
+ ///
+ public string Type { get; }
+
+ ///
+ /// The needed permission kind.
+ ///
+ public Kind Kind { get; }
+
+ ///
+ /// Ask a permission to run an action.
+ ///
+ ///
+ /// With this attribute, you can only specify a type or a kind.
+ /// To have a valid permission attribute, you must specify the kind and the permission using two attributes.
+ /// Those attributes can be dispatched at different places (one on the class, one on the method for example).
+ /// If you don't put exactly two of those attributes, the permission attribute will be ill-formed and will
+ /// lead to unspecified behaviors.
+ ///
+ ///
+ /// The type of the action
+ /// (if the type ends with api, it will be removed. This allow you to use nameof(YourApi)).
+ ///
+ public PartialPermissionAttribute(string type)
+ {
+ if (type.EndsWith("API", StringComparison.OrdinalIgnoreCase))
+ type = type[..^3];
+ Type = type.ToLower();
+ }
+
+ ///
+ /// Ask a permission to run an action.
+ ///
+ ///
+ /// With this attribute, you can only specify a type or a kind.
+ /// To have a valid permission attribute, you must specify the kind and the permission using two attributes.
+ /// Those attributes can be dispatched at different places (one on the class, one on the method for example).
+ /// If you don't put exactly two of those attributes, the permission attribute will be ill-formed and will
+ /// lead to unspecified behaviors.
+ ///
+ /// The kind of permission needed.
+ public PartialPermissionAttribute(Kind permission)
+ {
+ Kind = permission;
+ }
+
+ ///
+ public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
+ {
+ return serviceProvider.GetRequiredService().Create(this);
+ }
+
+ ///
+ public bool IsReusable => true;
+ }
+}
diff --git a/Kyoo.Abstractions/Models/Attributes/Permission/PermissionAttribute.cs b/Kyoo.Abstractions/Models/Attributes/Permission/PermissionAttribute.cs
new file mode 100644
index 00000000..382170d6
--- /dev/null
+++ b/Kyoo.Abstractions/Models/Attributes/Permission/PermissionAttribute.cs
@@ -0,0 +1,110 @@
+using System;
+using Kyoo.Abstractions.Controllers;
+using Microsoft.AspNetCore.Mvc.Filters;
+using Microsoft.Extensions.DependencyInjection;
+
+namespace Kyoo.Abstractions.Models.Permissions
+{
+ ///
+ /// The kind of permission needed.
+ ///
+ public enum Kind
+ {
+ ///
+ /// Allow the user to read for this kind of data.
+ ///
+ Read,
+
+ ///
+ /// Allow the user to write for this kind of data.
+ ///
+ Write,
+
+ ///
+ /// Allow the user to create this kind of data.
+ ///
+ Create,
+
+ ///
+ /// Allow the user to delete this kind od data.
+ ///
+ Delete
+ }
+
+ ///
+ /// The group of the permission.
+ ///
+ public enum Group
+ {
+ ///
+ /// Allow all operations on basic items types.
+ ///
+ Overall,
+
+ ///
+ /// Allow operation on sensitive items like libraries path, configurations and so on.
+ ///
+ Admin
+ }
+
+ ///
+ /// Specify permissions needed for the API.
+ ///
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
+ public class PermissionAttribute : Attribute, IFilterFactory
+ {
+ ///
+ /// The needed permission as string.
+ ///
+ public string Type { get; }
+
+ ///
+ /// The needed permission kind.
+ ///
+ public Kind Kind { get; }
+
+ ///
+ /// The group of this permission.
+ ///
+ public Group Group { get; }
+
+ ///
+ /// Ask a permission to run an action.
+ ///
+ ///
+ /// The type of the action
+ /// (if the type ends with api, it will be removed. This allow you to use nameof(YourApi)).
+ ///
+ /// The kind of permission needed.
+ ///
+ /// The group of this permission (allow grouped permission like overall.read
+ /// for all read permissions of this group).
+ ///
+ public PermissionAttribute(string type, Kind permission, Group group = Group.Overall)
+ {
+ if (type.EndsWith("API", StringComparison.OrdinalIgnoreCase))
+ type = type[..^3];
+ Type = type.ToLower();
+ Kind = permission;
+ Group = group;
+ }
+
+ ///
+ public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
+ {
+ return serviceProvider.GetRequiredService().Create(this);
+ }
+
+ ///
+ public bool IsReusable => true;
+
+ ///
+ /// Return this permission attribute as a string.
+ ///
+ /// The string representation.
+ public string AsPermissionString()
+ {
+ return Type;
+ }
+ }
+}
diff --git a/Kyoo.Abstractions/Models/Attributes/PermissionAttribute.cs b/Kyoo.Abstractions/Models/Attributes/PermissionAttribute.cs
deleted file mode 100644
index 19bd1961..00000000
--- a/Kyoo.Abstractions/Models/Attributes/PermissionAttribute.cs
+++ /dev/null
@@ -1,172 +0,0 @@
-using System;
-using Microsoft.AspNetCore.Mvc.Filters;
-using Microsoft.Extensions.DependencyInjection;
-
-namespace Kyoo.Abstractions.Models.Permissions
-{
- ///
- /// The kind of permission needed.
- ///
- public enum Kind
- {
- Read,
- Write,
- Create,
- Delete
- }
-
- ///
- /// The group of the permission.
- ///
- public enum Group
- {
- Overall,
- Admin
- }
-
- ///
- /// Specify permissions needed for the API.
- ///
- [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
- public class PermissionAttribute : Attribute, IFilterFactory
- {
- ///
- /// The needed permission as string.
- ///
- public string Type { get; }
- ///
- /// The needed permission kind.
- ///
- public Kind Kind { get; }
- ///
- /// The group of this permission
- ///
- public Group Group { get; }
-
- ///
- /// Ask a permission to run an action.
- ///
- ///
- /// The type of the action
- /// (if the type ends with api, it will be removed. This allow you to use nameof(YourApi)).
- ///
- /// The kind of permission needed
- ///
- /// The group of this permission (allow grouped permission like overall.read
- /// for all read permissions of this group)
- ///
- public PermissionAttribute(string type, Kind permission, Group group = Group.Overall)
- {
- if (type.EndsWith("API", StringComparison.OrdinalIgnoreCase))
- type = type[..^3];
- Type = type.ToLower();
- Kind = permission;
- Group = group;
- }
-
- ///
- public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
- {
- return serviceProvider.GetRequiredService().Create(this);
- }
-
- ///
- public bool IsReusable => true;
-
- ///
- /// Return this permission attribute as a string
- ///
- /// The string representation.
- public string AsPermissionString()
- {
- return Type;
- }
- }
-
- ///
- /// Specify one part of a permissions needed for the API (the kind or the type).
- ///
- [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
- public class PartialPermissionAttribute : Attribute, IFilterFactory
- {
- ///
- /// The needed permission type.
- ///
- public string Type { get; }
- ///
- /// The needed permission kind.
- ///
- public Kind Kind { get; }
-
- ///
- /// Ask a permission to run an action.
- ///
- ///
- /// With this attribute, you can only specify a type or a kind.
- /// To have a valid permission attribute, you must specify the kind and the permission using two attributes.
- /// Those attributes can be dispatched at different places (one on the class, one on the method for example).
- /// If you don't put exactly two of those attributes, the permission attribute will be ill-formed and will
- /// lead to unspecified behaviors.
- ///
- ///
- /// The type of the action
- /// (if the type ends with api, it will be removed. This allow you to use nameof(YourApi)).
- ///
- public PartialPermissionAttribute(string type)
- {
- if (type.EndsWith("API", StringComparison.OrdinalIgnoreCase))
- type = type[..^3];
- Type = type.ToLower();
- }
-
- ///
- /// Ask a permission to run an action.
- ///
- ///
- /// With this attribute, you can only specify a type or a kind.
- /// To have a valid permission attribute, you must specify the kind and the permission using two attributes.
- /// Those attributes can be dispatched at different places (one on the class, one on the method for example).
- /// If you don't put exactly two of those attributes, the permission attribute will be ill-formed and will
- /// lead to unspecified behaviors.
- ///
- /// The kind of permission needed
- public PartialPermissionAttribute(Kind permission)
- {
- Kind = permission;
- }
-
- ///
- public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
- {
- return serviceProvider.GetRequiredService().Create(this);
- }
-
- ///
- public bool IsReusable => true;
- }
-
-
- ///
- /// A service to validate permissions
- ///
- public interface IPermissionValidator
- {
- ///
- /// Create an IAuthorizationFilter that will be used to validate permissions.
- /// This can registered with any lifetime.
- ///
- /// The permission attribute to validate
- /// An authorization filter used to validate the permission
- IFilterMetadata Create(PermissionAttribute attribute);
-
- ///
- /// Create an IAuthorizationFilter that will be used to validate permissions.
- /// This can registered with any lifetime.
- ///
- ///
- /// A partial attribute to validate. See .
- ///
- /// An authorization filter used to validate the permission
- IFilterMetadata Create(PartialPermissionAttribute attribute);
- }
-}
\ No newline at end of file
diff --git a/Kyoo.Abstractions/Models/Resources/Show.cs b/Kyoo.Abstractions/Models/Resources/Show.cs
index 1a4b87c9..a46fa8fb 100644
--- a/Kyoo.Abstractions/Models/Resources/Show.cs
+++ b/Kyoo.Abstractions/Models/Resources/Show.cs
@@ -50,7 +50,7 @@ namespace Kyoo.Abstractions.Models
public string TrailerUrl => Images?.GetValueOrDefault(Models.Images.Trailer);
///
- /// The date this show started airing. It can be null if this is unknown.
+ /// The date this show started airing. It can be null if this is unknown.
///
public DateTime? StartAir { get; set; }
@@ -103,6 +103,7 @@ namespace Kyoo.Abstractions.Models
/// The ID of the Studio that made this show.
///
[SerializeIgnore] public int? StudioID { get; set; }
+
///
/// The Studio that made this show.
/// This must be explicitly loaded via a call to .
@@ -145,19 +146,48 @@ namespace Kyoo.Abstractions.Models
public void OnMerge(object merged)
{
if (People != null)
+ {
foreach (PeopleRole link in People)
link.Show = this;
+ }
+
if (Seasons != null)
+ {
foreach (Season season in Seasons)
season.Show = this;
+ }
+
if (Episodes != null)
+ {
foreach (Episode episode in Episodes)
episode.Show = this;
+ }
}
}
///
/// The enum containing show's status.
///
- public enum Status { Unknown, Finished, Airing, Planned }
+ public enum Status
+ {
+ ///
+ /// The status of the show is not known.
+ ///
+ Unknown,
+
+ ///
+ /// The show has finished airing.
+ ///
+ Finished,
+
+ ///
+ /// The show is still actively airing.
+ ///
+ Airing,
+
+ ///
+ /// This show has not aired yet but has been announced.
+ ///
+ Planned
+ }
}
diff --git a/Kyoo.Authentication/AuthenticationModule.cs b/Kyoo.Authentication/AuthenticationModule.cs
index 054b0268..f05c10ac 100644
--- a/Kyoo.Authentication/AuthenticationModule.cs
+++ b/Kyoo.Authentication/AuthenticationModule.cs
@@ -85,7 +85,7 @@ namespace Kyoo.Authentication
///
public void Configure(ContainerBuilder builder)
{
- builder.RegisterType().As().SingleInstance();
+ builder.RegisterType().As().SingleInstance();
DefaultCorsPolicyService cors = new(_logger)
{
diff --git a/Kyoo.Authentication/Controllers/PremissionValidator.cs b/Kyoo.Authentication/Controllers/PermissionValidator.cs
similarity index 77%
rename from Kyoo.Authentication/Controllers/PremissionValidator.cs
rename to Kyoo.Authentication/Controllers/PermissionValidator.cs
index 05ef1a16..e4bdf0b3 100644
--- a/Kyoo.Authentication/Controllers/PremissionValidator.cs
+++ b/Kyoo.Authentication/Controllers/PermissionValidator.cs
@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
+using Kyoo.Abstractions.Controllers;
using Kyoo.Abstractions.Models.Permissions;
using Kyoo.Authentication.Models;
using Microsoft.AspNetCore.Authentication;
@@ -17,7 +18,7 @@ namespace Kyoo.Authentication
/// A permission validator to validate permission with user Permission array
/// or the default array from the configurations if the user is not logged.
///
- public class PermissionValidatorFactory : IPermissionValidator
+ public class PermissionValidator : IPermissionValidator
{
///
/// The permissions options to retrieve default permissions.
@@ -25,10 +26,10 @@ namespace Kyoo.Authentication
private readonly IOptionsMonitor _options;
///
- /// Create a new factory with the given options
+ /// Create a new factory with the given options.
///
/// The option containing default values.
- public PermissionValidatorFactory(IOptionsMonitor options)
+ public PermissionValidator(IOptionsMonitor options)
{
_options = options;
}
@@ -36,46 +37,49 @@ namespace Kyoo.Authentication
///
public IFilterMetadata Create(PermissionAttribute attribute)
{
- return new PermissionValidator(attribute.Type, attribute.Kind, attribute.Group, _options);
+ return new PermissionValidatorFilter(attribute.Type, attribute.Kind, attribute.Group, _options);
}
///
public IFilterMetadata Create(PartialPermissionAttribute attribute)
{
- return new PermissionValidator((object)attribute.Type ?? attribute.Kind, _options);
+ return new PermissionValidatorFilter((object)attribute.Type ?? attribute.Kind, _options);
}
///
- /// The authorization filter used by
+ /// The authorization filter used by .
///
- private class PermissionValidator : IAsyncAuthorizationFilter
+ private class PermissionValidatorFilter : IAsyncAuthorizationFilter
{
///
- /// The permission to validate
+ /// The permission to validate.
///
private readonly string _permission;
+
///
- /// The kind of permission needed
+ /// The kind of permission needed.
///
private readonly Kind? _kind;
///
- /// The group of he permission
+ /// The group of he permission.
///
private readonly Group _group = Group.Overall;
+
///
/// The permissions options to retrieve default permissions.
///
private readonly IOptionsMonitor _options;
///
- /// Create a new permission validator with the given options
+ /// Create a new permission validator with the given options.
///
- /// The permission to validate
- /// The kind of permission needed
- /// The group of the permission
+ /// The permission to validate.
+ /// The kind of permission needed.
+ /// The group of the permission.
/// The option containing default values.
- public PermissionValidator(string permission, Kind kind, Group group, IOptionsMonitor options)
+ public PermissionValidatorFilter(string permission, Kind kind, Group group,
+ IOptionsMonitor options)
{
_permission = permission;
_kind = kind;
@@ -84,11 +88,11 @@ namespace Kyoo.Authentication
}
///
- /// Create a new permission validator with the given options
+ /// Create a new permission validator with the given options.
///
- /// The partial permission to validate
+ /// The partial permission to validate.
/// The option containing default values.
- public PermissionValidator(object partialInfo, IOptionsMonitor options)
+ public PermissionValidatorFilter(object partialInfo, IOptionsMonitor options)
{
if (partialInfo is Kind kind)
_kind = kind;
@@ -99,7 +103,6 @@ namespace Kyoo.Authentication
_options = options;
}
-
///
public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
{
@@ -127,8 +130,10 @@ namespace Kyoo.Authentication
"are not supported.");
}
if (permission == null || kind == null)
+ {
throw new ArgumentException("The permission type or kind is still missing after two partial " +
"permission attributes, this is unsupported.");
+ }
}
string permStr = $"{permission.ToLower()}.{kind.ToString()!.ToLower()}";
diff --git a/Kyoo.Core/Controllers/PassthroughPermissionValidator.cs b/Kyoo.Core/Controllers/PassthroughPermissionValidator.cs
index ff9b07aa..a17d587a 100644
--- a/Kyoo.Core/Controllers/PassthroughPermissionValidator.cs
+++ b/Kyoo.Core/Controllers/PassthroughPermissionValidator.cs
@@ -1,3 +1,5 @@
+using System.Diagnostics.CodeAnalysis;
+using Kyoo.Abstractions.Controllers;
using Kyoo.Abstractions.Models.Permissions;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;
@@ -9,7 +11,8 @@ namespace Kyoo.Core.Controllers
///
public class PassthroughPermissionValidator : IPermissionValidator
{
- // ReSharper disable once SuggestBaseTypeForParameter
+ [SuppressMessage("ReSharper", "SuggestBaseTypeForParameterInConstructor",
+ Justification = "ILogger should include the typeparam for context.")]
public PassthroughPermissionValidator(ILogger logger)
{
logger.LogWarning("No permission validator has been enabled, all users will have all permissions");
@@ -28,8 +31,8 @@ namespace Kyoo.Core.Controllers
}
///
- /// An useless filter that does nothing.
+ /// An useless filter that does nothing.
///
private class PassthroughValidator : IFilterMetadata { }
}
-}
\ No newline at end of file
+}
diff --git a/Kyoo.Core/Views/VideoApi.cs b/Kyoo.Core/Views/VideoApi.cs
index 8a21a560..fbaf605e 100644
--- a/Kyoo.Core/Views/VideoApi.cs
+++ b/Kyoo.Core/Views/VideoApi.cs
@@ -41,9 +41,9 @@ namespace Kyoo.Core.Api
}
+ // TODO enable the following line, this is disabled since the web app can't use bearers. [Permission("video", Kind.Read)]
[HttpGet("{slug}")]
[HttpGet("direct/{slug}")]
- // TODO enable the following line, this is disabled since the web app can't use bearers. [Permission("video", Kind.Read)]
public async Task Direct(string slug)
{
try
@@ -114,4 +114,4 @@ namespace Kyoo.Core.Api
return PhysicalFile(path, "video/MP2T");
}
}
-}
\ No newline at end of file
+}
diff --git a/Kyoo.Database/DatabaseContext.cs b/Kyoo.Database/DatabaseContext.cs
index 50d5ebeb..8819d1e6 100644
--- a/Kyoo.Database/DatabaseContext.cs
+++ b/Kyoo.Database/DatabaseContext.cs
@@ -26,38 +26,47 @@ namespace Kyoo.Database
/// All libraries of Kyoo. See .
///
public DbSet Libraries { get; set; }
+
///
/// All collections of Kyoo. See .
///
public DbSet Collections { get; set; }
+
///
/// All shows of Kyoo. See .
///
public DbSet Shows { get; set; }
+
///
/// All seasons of Kyoo. See .
///
public DbSet Seasons { get; set; }
+
///
/// All episodes of Kyoo. See .
///
public DbSet Episodes { get; set; }
+
///
/// All tracks of Kyoo. See .
///
public DbSet
/// A to observe while waiting for the task to complete
/// The number of state entries written to the database or -1 if a duplicate exist.
- public async Task SaveIfNoDuplicates(CancellationToken cancellationToken = new())
+ public async Task SaveIfNoDuplicates(CancellationToken cancellationToken = default)
{
try
{
@@ -507,7 +516,7 @@ namespace Kyoo.Database
///
/// Return the first resource with the given slug that is currently tracked by this context.
/// This allow one to limit redundant calls to during the
- /// same transaction and prevent fails from EF when two same entities are being tracked.
+ /// same transaction and prevent fails from EF when two same entities are being tracked.
///
/// The slug of the resource to check
/// The type of entity to check
@@ -548,4 +557,4 @@ namespace Kyoo.Database
/// An expression representing the like query. It can directly be passed to a where call.
public abstract Expression> Like(Expression> query, string format);
}
-}
\ No newline at end of file
+}
diff --git a/Kyoo.TheMovieDb/ProviderTmdb.cs b/Kyoo.TheMovieDb/TheMovieDbProvider.cs
similarity index 91%
rename from Kyoo.TheMovieDb/ProviderTmdb.cs
rename to Kyoo.TheMovieDb/TheMovieDbProvider.cs
index 826e348b..87f9f2f5 100644
--- a/Kyoo.TheMovieDb/ProviderTmdb.cs
+++ b/Kyoo.TheMovieDb/TheMovieDbProvider.cs
@@ -23,6 +23,7 @@ namespace Kyoo.TheMovieDb
/// The API key used to authenticate with TheMovieDb API.
///
private readonly IOptions _apiKey;
+
///
/// The logger to use in ase of issue.
///
@@ -43,7 +44,7 @@ namespace Kyoo.TheMovieDb
///
/// Create a new using the given api key.
///
- /// The api key
+ /// The api key.
/// The logger to use in case of issue.
public TheMovieDbProvider(IOptions apiKey, ILogger logger)
{
@@ -51,7 +52,6 @@ namespace Kyoo.TheMovieDb
_logger = logger;
}
-
///
public Task Get(T item)
where T : class, IResource
@@ -71,8 +71,8 @@ namespace Kyoo.TheMovieDb
///
/// Get a collection using it's id, if the id is not present in the collection, fallback to a name search.
///
- /// The collection to search for
- /// A collection containing metadata from TheMovieDb
+ /// The collection to search for.
+ /// A collection containing metadata from TheMovieDb.
private async Task _GetCollection(Collection collection)
{
if (!collection.TryGetID(Provider.Slug, out int id))
@@ -89,8 +89,8 @@ namespace Kyoo.TheMovieDb
///
/// Get a show using it's id, if the id is not present in the show, fallback to a title search.
///
- /// The show to search for
- /// A show containing metadata from TheMovieDb
+ /// The show to search for.
+ /// A show containing metadata from TheMovieDb.
private async Task _GetShow(Show show)
{
if (!show.TryGetID(Provider.Slug, out int id))
@@ -119,7 +119,7 @@ namespace Kyoo.TheMovieDb
/// Get a season using it's show and it's season number.
///
/// The season to retrieve metadata for.
- /// A season containing metadata from TheMovieDb
+ /// A season containing metadata from TheMovieDb.
private async Task _GetSeason(Season season)
{
if (season.Show == null)
@@ -139,10 +139,10 @@ namespace Kyoo.TheMovieDb
///
/// Get an episode using it's show, it's season number and it's episode number.
- /// Absolute numbering is not supported.
+ /// Absolute numbering is not supported.
///
/// The episode to retrieve metadata for.
- /// An episode containing metadata from TheMovieDb
+ /// An episode containing metadata from TheMovieDb.
private async Task _GetEpisode(Episode episode)
{
if (episode.Show == null)
@@ -163,8 +163,8 @@ namespace Kyoo.TheMovieDb
///
/// Get a person using it's id, if the id is not present in the person, fallback to a name search.
///
- /// The person to search for
- /// A person containing metadata from TheMovieDb
+ /// The person to search for.
+ /// A person containing metadata from TheMovieDb.
private async Task _GetPerson(People person)
{
if (!person.TryGetID(Provider.Slug, out int id))
@@ -181,8 +181,8 @@ namespace Kyoo.TheMovieDb
///
/// Get a studio using it's id, if the id is not present in the studio, fallback to a name search.
///
- /// The studio to search for
- /// A studio containing metadata from TheMovieDb
+ /// The studio to search for.
+ /// A studio containing metadata from TheMovieDb.
private async Task _GetStudio(Studio studio)
{
if (!studio.TryGetID(Provider.Slug, out int id))
@@ -277,4 +277,4 @@ namespace Kyoo.TheMovieDb
.ToArray();
}
}
-}
\ No newline at end of file
+}
diff --git a/Kyoo.ruleset b/Kyoo.ruleset
index 0ef4692c..a4415374 100644
--- a/Kyoo.ruleset
+++ b/Kyoo.ruleset
@@ -3,6 +3,10 @@
+
+
+
+
@@ -11,13 +15,20 @@
+
+
+
+
+
+
+
@@ -27,5 +38,6 @@
+