mirror of
				https://github.com/zoriya/Kyoo.git
				synced 2025-10-31 10:37:13 -04:00 
			
		
		
		
	Switch to file scopped namespaces (#349)
This commit is contained in:
		
						commit
						5fedce71a0
					
				| @ -1,2 +1,3 @@ | ||||
| 7e6e56a366babe17e7891a5897180efbf93c00c5 | ||||
| a5638203a6ecb9f372a5a61e1c8fd443bf3a17fe | ||||
| 18e301f26acd7f2e97eac26c5f48377fa13956f5 | ||||
|  | ||||
| @ -16,6 +16,8 @@ dotnet_diagnostic.IDE0055.severity = none | ||||
| dotnet_diagnostic.IDE0058.severity = none | ||||
| dotnet_diagnostic.IDE0130.severity = none | ||||
| 
 | ||||
| # Convert to file-scoped namespace | ||||
| csharp_style_namespace_declarations = file_scoped:warning | ||||
| # Sort using and Import directives with System.* appearing first | ||||
| dotnet_sort_system_directives_first = true | ||||
| csharp_using_directive_placement = outside_namespace:warning | ||||
|  | ||||
| @ -18,13 +18,13 @@ | ||||
| 
 | ||||
| using Kyoo.Abstractions.Models; | ||||
| 
 | ||||
| namespace Kyoo.Abstractions.Controllers | ||||
| namespace Kyoo.Abstractions.Controllers; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// An interface to interact with the database. Every repository is mapped through here. | ||||
| /// </summary> | ||||
| public interface ILibraryManager | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// An interface to interact with the database. Every repository is mapped through here. | ||||
| 	/// </summary> | ||||
| 	public interface ILibraryManager | ||||
| 	{ | ||||
| 	IRepository<T> Repository<T>() | ||||
| 		where T : IResource, IQuery; | ||||
| 
 | ||||
| @ -77,5 +77,4 @@ namespace Kyoo.Abstractions.Controllers | ||||
| 	/// The repository that handle users. | ||||
| 	/// </summary> | ||||
| 	IRepository<User> Users { get; } | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -19,13 +19,13 @@ | ||||
| using Kyoo.Abstractions.Models.Permissions; | ||||
| using Microsoft.AspNetCore.Mvc.Filters; | ||||
| 
 | ||||
| namespace Kyoo.Abstractions.Controllers | ||||
| namespace Kyoo.Abstractions.Controllers; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// A service to validate permissions. | ||||
| /// </summary> | ||||
| public interface IPermissionValidator | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// A service to validate permissions. | ||||
| 	/// </summary> | ||||
| 	public interface IPermissionValidator | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// Create an IAuthorizationFilter that will be used to validate permissions. | ||||
| 	/// This can registered with any lifetime. | ||||
| @ -43,5 +43,4 @@ namespace Kyoo.Abstractions.Controllers | ||||
| 	/// </param> | ||||
| 	/// <returns>An authorization filter used to validate the permission.</returns> | ||||
| 	IFilterMetadata Create(PartialPermissionAttribute attribute); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -21,17 +21,17 @@ using System.Collections.Generic; | ||||
| using Autofac; | ||||
| using Microsoft.Extensions.DependencyInjection; | ||||
| 
 | ||||
| namespace Kyoo.Abstractions.Controllers | ||||
| namespace Kyoo.Abstractions.Controllers; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// A common interface used to discord plugins | ||||
| /// </summary> | ||||
| /// <remarks> | ||||
| /// You can inject services in the IPlugin constructor. | ||||
| /// You should only inject well known services like an ILogger, IConfiguration or IWebHostEnvironment. | ||||
| /// </remarks> | ||||
| public interface IPlugin | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// A common interface used to discord plugins | ||||
| 	/// </summary> | ||||
| 	/// <remarks> | ||||
| 	/// You can inject services in the IPlugin constructor. | ||||
| 	/// You should only inject well known services like an ILogger, IConfiguration or IWebHostEnvironment. | ||||
| 	/// </remarks> | ||||
| 	public interface IPlugin | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// The name of the plugin | ||||
| 	/// </summary> | ||||
| @ -62,5 +62,4 @@ namespace Kyoo.Abstractions.Controllers | ||||
| 	{ | ||||
| 		// Skipped | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -20,13 +20,13 @@ using System; | ||||
| using System.Collections.Generic; | ||||
| using Kyoo.Abstractions.Models.Exceptions; | ||||
| 
 | ||||
| namespace Kyoo.Abstractions.Controllers | ||||
| namespace Kyoo.Abstractions.Controllers; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// A manager to load plugins and retrieve information from them. | ||||
| /// </summary> | ||||
| public interface IPluginManager | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// A manager to load plugins and retrieve information from them. | ||||
| 	/// </summary> | ||||
| 	public interface IPluginManager | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// Get a single plugin that match the type and name given. | ||||
| 	/// </summary> | ||||
| @ -66,5 +66,4 @@ namespace Kyoo.Abstractions.Controllers | ||||
| 	/// You should not try to put plugins from the plugins directory here as they will get automatically loaded. | ||||
| 	/// </param> | ||||
| 	public void LoadPlugins(params Type[] plugins); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -23,15 +23,15 @@ using Kyoo.Abstractions.Models; | ||||
| using Kyoo.Abstractions.Models.Exceptions; | ||||
| using Kyoo.Abstractions.Models.Utils; | ||||
| 
 | ||||
| namespace Kyoo.Abstractions.Controllers | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// A common repository for every resources. | ||||
| 	/// </summary> | ||||
| 	/// <typeparam name="T">The resource's type that this repository manage.</typeparam> | ||||
| 	public interface IRepository<T> : IBaseRepository | ||||
| namespace Kyoo.Abstractions.Controllers; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// A common repository for every resources. | ||||
| /// </summary> | ||||
| /// <typeparam name="T">The resource's type that this repository manage.</typeparam> | ||||
| public interface IRepository<T> : IBaseRepository | ||||
| 	where T : IResource, IQuery | ||||
| 	{ | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// The event handler type for all events of this repository. | ||||
| 	/// </summary> | ||||
| @ -170,8 +170,7 @@ namespace Kyoo.Abstractions.Controllers | ||||
| 	/// </summary> | ||||
| 	/// <param name="obj">The resource newly created.</param> | ||||
| 	/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns> | ||||
| 		protected static Task OnResourceCreated(T obj) => | ||||
| 			OnCreated?.Invoke(obj) ?? Task.CompletedTask; | ||||
| 	protected static Task OnResourceCreated(T obj) => OnCreated?.Invoke(obj) ?? Task.CompletedTask; | ||||
| 
 | ||||
| 	/// <summary> | ||||
| 	/// Edit a resource and replace every property | ||||
| @ -203,8 +202,7 @@ namespace Kyoo.Abstractions.Controllers | ||||
| 	/// </summary> | ||||
| 	/// <param name="obj">The resource newly edited.</param> | ||||
| 	/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns> | ||||
| 		protected static Task OnResourceEdited(T obj) => | ||||
| 			OnEdited?.Invoke(obj) ?? Task.CompletedTask; | ||||
| 	protected static Task OnResourceEdited(T obj) => OnEdited?.Invoke(obj) ?? Task.CompletedTask; | ||||
| 
 | ||||
| 	/// <summary> | ||||
| 	/// Delete a resource by it's ID | ||||
| @ -247,25 +245,23 @@ namespace Kyoo.Abstractions.Controllers | ||||
| 	/// </summary> | ||||
| 	/// <param name="obj">The resource newly deleted.</param> | ||||
| 	/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns> | ||||
| 		protected static Task OnResourceDeleted(T obj) => | ||||
| 			OnDeleted?.Invoke(obj) ?? Task.CompletedTask; | ||||
| 	} | ||||
| 	protected static Task OnResourceDeleted(T obj) => OnDeleted?.Invoke(obj) ?? Task.CompletedTask; | ||||
| } | ||||
| 
 | ||||
| 	/// <summary> | ||||
| 	/// A base class for repositories. Every service implementing this will be handled by the <see cref="ILibraryManager"/>. | ||||
| 	/// </summary> | ||||
| 	public interface IBaseRepository | ||||
| 	{ | ||||
| /// <summary> | ||||
| /// A base class for repositories. Every service implementing this will be handled by the <see cref="ILibraryManager"/>. | ||||
| /// </summary> | ||||
| public interface IBaseRepository | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// The type for witch this repository is responsible or null if non applicable. | ||||
| 	/// </summary> | ||||
| 	Type RepositoryType { get; } | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| 	public interface IUserRepository : IRepository<User> | ||||
| 	{ | ||||
| public interface IUserRepository : IRepository<User> | ||||
| { | ||||
| 	Task<User?> GetByExternalId(string provider, string id); | ||||
| 	Task<User> AddExternalToken(Guid userId, string provider, ExternalToken token); | ||||
| 	Task<User> DeleteExternalToken(Guid userId, string provider); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -21,13 +21,13 @@ using System.IO; | ||||
| using System.Threading.Tasks; | ||||
| using Kyoo.Abstractions.Models; | ||||
| 
 | ||||
| namespace Kyoo.Abstractions.Controllers | ||||
| namespace Kyoo.Abstractions.Controllers; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// Download images and retrieve the path of those images for a resource. | ||||
| /// </summary> | ||||
| public interface IThumbnailsManager | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// Download images and retrieve the path of those images for a resource. | ||||
| 	/// </summary> | ||||
| 	public interface IThumbnailsManager | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// Download images of a specified item. | ||||
| 	/// If no images is available to download, do nothing and silently return. | ||||
| @ -75,5 +75,4 @@ namespace Kyoo.Abstractions.Controllers | ||||
| 	/// <param name="userId">The id of the user. </param> | ||||
| 	/// <param name="image">The byte stream of the image. Null to delete the image.</param> | ||||
| 	Task SetUserImage(Guid userId, Stream? image); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -19,14 +19,14 @@ | ||||
| using System; | ||||
| using Microsoft.Extensions.DependencyInjection; | ||||
| 
 | ||||
| namespace Kyoo.Abstractions.Controllers | ||||
| namespace Kyoo.Abstractions.Controllers; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// A list of constant priorities used for <see cref="IStartupAction"/>'s <see cref="IStartupAction.Priority"/>. | ||||
| /// It also contains helper methods for creating new <see cref="StartupAction"/>. | ||||
| /// </summary> | ||||
| public static class SA | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// A list of constant priorities used for <see cref="IStartupAction"/>'s <see cref="IStartupAction.Priority"/>. | ||||
| 	/// It also contains helper methods for creating new <see cref="StartupAction"/>. | ||||
| 	/// </summary> | ||||
| 	public static class SA | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// The highest predefined priority existing for <see cref="StartupAction"/>. | ||||
| 	/// </summary> | ||||
| @ -102,10 +102,7 @@ namespace Kyoo.Abstractions.Controllers | ||||
| 	/// <typeparam name="T2">A second dependency that this action will use.</typeparam> | ||||
| 	/// <typeparam name="T3">A third dependency that this action will use.</typeparam> | ||||
| 	/// <returns>A new <see cref="StartupAction"/></returns> | ||||
| 		public static StartupAction<T, T2, T3> New<T, T2, T3>( | ||||
| 			Action<T, T2, T3> action, | ||||
| 			int priority | ||||
| 		) | ||||
| 	public static StartupAction<T, T2, T3> New<T, T2, T3>(Action<T, T2, T3> action, int priority) | ||||
| 		where T : notnull | ||||
| 		where T2 : notnull | ||||
| 		where T3 : notnull => new(action, priority); | ||||
| @ -249,16 +246,16 @@ namespace Kyoo.Abstractions.Controllers | ||||
| 			); | ||||
| 		} | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| 	/// <summary> | ||||
| 	/// An action executed on kyoo's startup to initialize the asp-net container. | ||||
| 	/// </summary> | ||||
| 	/// <remarks> | ||||
| 	/// This is the base interface, see <see cref="SA.StartupAction"/> for a simpler use of this. | ||||
| 	/// </remarks> | ||||
| 	public interface IStartupAction | ||||
| 	{ | ||||
| /// <summary> | ||||
| /// An action executed on kyoo's startup to initialize the asp-net container. | ||||
| /// </summary> | ||||
| /// <remarks> | ||||
| /// This is the base interface, see <see cref="SA.StartupAction"/> for a simpler use of this. | ||||
| /// </remarks> | ||||
| public interface IStartupAction | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// The priority of this action. The actions will be executed on descending priority order. | ||||
| 	/// If two actions have the same priority, their order is undefined. | ||||
| @ -270,5 +267,4 @@ namespace Kyoo.Abstractions.Controllers | ||||
| 	/// </summary> | ||||
| 	/// <param name="provider">The service provider containing all services can be used.</param> | ||||
| 	void Run(IServiceProvider provider); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -23,13 +23,13 @@ using System.Security.Claims; | ||||
| using Kyoo.Abstractions.Models.Exceptions; | ||||
| using Kyoo.Authentication.Models; | ||||
| 
 | ||||
| namespace Kyoo.Authentication | ||||
| namespace Kyoo.Authentication; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// Extension methods. | ||||
| /// </summary> | ||||
| public static class Extensions | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// Extension methods. | ||||
| 	/// </summary> | ||||
| 	public static class Extensions | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// Get the permissions of an user. | ||||
| 	/// </summary> | ||||
| @ -61,5 +61,4 @@ namespace Kyoo.Authentication | ||||
| 			throw new UnauthorizedException(); | ||||
| 		return ret.Value; | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -18,16 +18,16 @@ | ||||
| 
 | ||||
| using System; | ||||
| 
 | ||||
| namespace Kyoo.Abstractions.Models.Attributes | ||||
| namespace Kyoo.Abstractions.Models.Attributes; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// An attribute to specify on apis to specify it's documentation's name and category. | ||||
| /// If this is applied on a method, the specified method will be exploded from the controller's page and be | ||||
| /// included on the specified tag page. | ||||
| /// </summary> | ||||
| [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] | ||||
| public class ApiDefinitionAttribute : Attribute | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// An attribute to specify on apis to specify it's documentation's name and category. | ||||
| 	/// If this is applied on a method, the specified method will be exploded from the controller's page and be | ||||
| 	/// included on the specified tag page. | ||||
| 	/// </summary> | ||||
| 	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] | ||||
| 	public class ApiDefinitionAttribute : Attribute | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// The public name of this api. | ||||
| 	/// </summary> | ||||
| @ -48,5 +48,4 @@ namespace Kyoo.Abstractions.Models.Attributes | ||||
| 	{ | ||||
| 		Name = name; | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -18,11 +18,10 @@ | ||||
| 
 | ||||
| using System; | ||||
| 
 | ||||
| namespace Kyoo.Abstractions.Models.Attributes | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// An attribute to inform that the property is computed automatically and can't be assigned manually. | ||||
| 	/// </summary> | ||||
| 	[AttributeUsage(AttributeTargets.Property)] | ||||
| 	public class ComputedAttribute : NotMergeableAttribute { } | ||||
| } | ||||
| namespace Kyoo.Abstractions.Models.Attributes; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// An attribute to inform that the property is computed automatically and can't be assigned manually. | ||||
| /// </summary> | ||||
| [AttributeUsage(AttributeTargets.Property)] | ||||
| public class ComputedAttribute : NotMergeableAttribute { } | ||||
|  | ||||
| @ -18,14 +18,14 @@ | ||||
| 
 | ||||
| using System; | ||||
| 
 | ||||
| namespace Kyoo.Abstractions.Models.Attributes | ||||
| namespace Kyoo.Abstractions.Models.Attributes; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// The targeted relation can be loaded. | ||||
| /// </summary> | ||||
| [AttributeUsage(AttributeTargets.Property)] | ||||
| public class LoadableRelationAttribute : Attribute | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// The targeted relation can be loaded. | ||||
| 	/// </summary> | ||||
| 	[AttributeUsage(AttributeTargets.Property)] | ||||
| 	public class LoadableRelationAttribute : Attribute | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// The name of the field containing the related resource's ID. | ||||
| 	/// </summary> | ||||
| @ -50,5 +50,4 @@ namespace Kyoo.Abstractions.Models.Attributes | ||||
| 	{ | ||||
| 		RelationID = relationID; | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -18,23 +18,22 @@ | ||||
| 
 | ||||
| using System; | ||||
| 
 | ||||
| namespace Kyoo.Abstractions.Models.Attributes | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// Specify that a property can't be merged. | ||||
| 	/// </summary> | ||||
| 	[AttributeUsage(AttributeTargets.Property)] | ||||
| 	public class NotMergeableAttribute : Attribute { } | ||||
| namespace Kyoo.Abstractions.Models.Attributes; | ||||
| 
 | ||||
| 	/// <summary> | ||||
| 	/// An interface with a method called when this object is merged. | ||||
| 	/// </summary> | ||||
| 	public interface IOnMerge | ||||
| 	{ | ||||
| /// <summary> | ||||
| /// Specify that a property can't be merged. | ||||
| /// </summary> | ||||
| [AttributeUsage(AttributeTargets.Property)] | ||||
| public class NotMergeableAttribute : Attribute { } | ||||
| 
 | ||||
| /// <summary> | ||||
| /// An interface with a method called when this object is merged. | ||||
| /// </summary> | ||||
| public interface IOnMerge | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// This function is called after the object has been merged. | ||||
| 	/// </summary> | ||||
| 	/// <param name="merged">The object that has been merged with this.</param> | ||||
| 	void OnMerge(object merged); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -21,14 +21,14 @@ using Kyoo.Abstractions.Controllers; | ||||
| using Microsoft.AspNetCore.Mvc.Filters; | ||||
| using Microsoft.Extensions.DependencyInjection; | ||||
| 
 | ||||
| namespace Kyoo.Abstractions.Models.Permissions | ||||
| namespace Kyoo.Abstractions.Models.Permissions; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// Specify one part of a permissions needed for the API (the kind or the type). | ||||
| /// </summary> | ||||
| [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)] | ||||
| public class PartialPermissionAttribute : Attribute, IFilterFactory | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// Specify one part of a permissions needed for the API (the kind or the type). | ||||
| 	/// </summary> | ||||
| 	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)] | ||||
| 	public class PartialPermissionAttribute : Attribute, IFilterFactory | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// The needed permission type. | ||||
| 	/// </summary> | ||||
| @ -84,5 +84,4 @@ namespace Kyoo.Abstractions.Models.Permissions | ||||
| 
 | ||||
| 	/// <inheritdoc /> | ||||
| 	public bool IsReusable => true; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -21,13 +21,13 @@ using Kyoo.Abstractions.Controllers; | ||||
| using Microsoft.AspNetCore.Mvc.Filters; | ||||
| using Microsoft.Extensions.DependencyInjection; | ||||
| 
 | ||||
| namespace Kyoo.Abstractions.Models.Permissions | ||||
| namespace Kyoo.Abstractions.Models.Permissions; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// The kind of permission needed. | ||||
| /// </summary> | ||||
| public enum Kind | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// The kind of permission needed. | ||||
| 	/// </summary> | ||||
| 	public enum Kind | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// Allow the user to read for this kind of data. | ||||
| 	/// </summary> | ||||
| @ -52,13 +52,13 @@ namespace Kyoo.Abstractions.Models.Permissions | ||||
| 	/// Allow the user to play this file. | ||||
| 	/// </summary> | ||||
| 	Play, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| 	/// <summary> | ||||
| 	/// The group of the permission. | ||||
| 	/// </summary> | ||||
| 	public enum Group | ||||
| 	{ | ||||
| /// <summary> | ||||
| /// The group of the permission. | ||||
| /// </summary> | ||||
| public enum Group | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// Default group indicating no value. | ||||
| 	/// </summary> | ||||
| @ -73,14 +73,14 @@ namespace Kyoo.Abstractions.Models.Permissions | ||||
| 	/// Allow operation on sensitive items like libraries path, configurations and so on. | ||||
| 	/// </summary> | ||||
| 	Admin | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| 	/// <summary> | ||||
| 	/// Specify permissions needed for the API. | ||||
| 	/// </summary> | ||||
| 	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)] | ||||
| 	public class PermissionAttribute : Attribute, IFilterFactory | ||||
| 	{ | ||||
| /// <summary> | ||||
| /// Specify permissions needed for the API. | ||||
| /// </summary> | ||||
| [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)] | ||||
| public class PermissionAttribute : Attribute, IFilterFactory | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// The needed permission as string. | ||||
| 	/// </summary> | ||||
| @ -133,5 +133,4 @@ namespace Kyoo.Abstractions.Models.Permissions | ||||
| 	{ | ||||
| 		return Type; | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -18,14 +18,13 @@ | ||||
| 
 | ||||
| using System; | ||||
| 
 | ||||
| namespace Kyoo.Abstractions.Models.Permissions | ||||
| namespace Kyoo.Abstractions.Models.Permissions; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// The annotated route can only be accessed by a logged in user. | ||||
| /// </summary> | ||||
| [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)] | ||||
| public class UserOnlyAttribute : Attribute | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// The annotated route can only be accessed by a logged in user. | ||||
| 	/// </summary> | ||||
| 	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)] | ||||
| 	public class UserOnlyAttribute : Attribute | ||||
| 	{ | ||||
| 	// TODO: Implement a Filter Attribute to make this work. For now, this attribute is only useful as documentation. | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -19,14 +19,14 @@ | ||||
| using System; | ||||
| using System.Runtime.Serialization; | ||||
| 
 | ||||
| namespace Kyoo.Abstractions.Models.Exceptions | ||||
| namespace Kyoo.Abstractions.Models.Exceptions; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// An exception raised when an item already exists in the database. | ||||
| /// </summary> | ||||
| [Serializable] | ||||
| public class DuplicatedItemException : Exception | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// An exception raised when an item already exists in the database. | ||||
| 	/// </summary> | ||||
| 	[Serializable] | ||||
| 	public class DuplicatedItemException : Exception | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// The existing object. | ||||
| 	/// </summary> | ||||
| @ -49,5 +49,4 @@ namespace Kyoo.Abstractions.Models.Exceptions | ||||
| 	/// <param name="context">The serialization context</param> | ||||
| 	protected DuplicatedItemException(SerializationInfo info, StreamingContext context) | ||||
| 		: base(info, context) { } | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -19,14 +19,14 @@ | ||||
| using System; | ||||
| using System.Runtime.Serialization; | ||||
| 
 | ||||
| namespace Kyoo.Abstractions.Models.Exceptions | ||||
| namespace Kyoo.Abstractions.Models.Exceptions; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// An exception raised when an item could not be found. | ||||
| /// </summary> | ||||
| [Serializable] | ||||
| public class ItemNotFoundException : Exception | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// An exception raised when an item could not be found. | ||||
| 	/// </summary> | ||||
| 	[Serializable] | ||||
| 	public class ItemNotFoundException : Exception | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// Create a default <see cref="ItemNotFoundException"/> with no message. | ||||
| 	/// </summary> | ||||
| @ -47,5 +47,4 @@ namespace Kyoo.Abstractions.Models.Exceptions | ||||
| 	/// <param name="context">The serialization context</param> | ||||
| 	protected ItemNotFoundException(SerializationInfo info, StreamingContext context) | ||||
| 		: base(info, context) { } | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -19,11 +19,11 @@ | ||||
| using System; | ||||
| using System.Runtime.Serialization; | ||||
| 
 | ||||
| namespace Kyoo.Abstractions.Models.Exceptions | ||||
| namespace Kyoo.Abstractions.Models.Exceptions; | ||||
| 
 | ||||
| [Serializable] | ||||
| public class UnauthorizedException : Exception | ||||
| { | ||||
| 	[Serializable] | ||||
| 	public class UnauthorizedException : Exception | ||||
| 	{ | ||||
| 	public UnauthorizedException() | ||||
| 		: base("User not authenticated or token invalid.") { } | ||||
| 
 | ||||
| @ -32,5 +32,4 @@ namespace Kyoo.Abstractions.Models.Exceptions | ||||
| 
 | ||||
| 	protected UnauthorizedException(SerializationInfo info, StreamingContext context) | ||||
| 		: base(info, context) { } | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -16,13 +16,13 @@ | ||||
| // You should have received a copy of the GNU General Public License | ||||
| // along with Kyoo. If not, see <https://www.gnu.org/licenses/>. | ||||
| 
 | ||||
| namespace Kyoo.Abstractions.Models | ||||
| namespace Kyoo.Abstractions.Models; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// A genre that allow one to specify categories for shows. | ||||
| /// </summary> | ||||
| public enum Genre | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// A genre that allow one to specify categories for shows. | ||||
| 	/// </summary> | ||||
| 	public enum Genre | ||||
| 	{ | ||||
| 	Action, | ||||
| 	Adventure, | ||||
| 	Animation, | ||||
| @ -41,5 +41,4 @@ namespace Kyoo.Abstractions.Models | ||||
| 	Thriller, | ||||
| 	War, | ||||
| 	Western, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -16,13 +16,13 @@ | ||||
| // You should have received a copy of the GNU General Public License | ||||
| // along with Kyoo. If not, see <https://www.gnu.org/licenses/>. | ||||
| 
 | ||||
| namespace Kyoo.Abstractions.Models | ||||
| namespace Kyoo.Abstractions.Models; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// ID and link of an item on an external provider. | ||||
| /// </summary> | ||||
| public class MetadataId | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// ID and link of an item on an external provider. | ||||
| 	/// </summary> | ||||
| 	public class MetadataId | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// The ID of the resource on the external provider. | ||||
| 	/// </summary> | ||||
| @ -32,5 +32,4 @@ namespace Kyoo.Abstractions.Models | ||||
| 	/// The URL of the resource on the external provider. | ||||
| 	/// </summary> | ||||
| 	public string? Link { get; set; } | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -20,15 +20,15 @@ using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using Kyoo.Utils; | ||||
| 
 | ||||
| namespace Kyoo.Abstractions.Models | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// A page of resource that contains information about the pagination of resources. | ||||
| 	/// </summary> | ||||
| 	/// <typeparam name="T">The type of resource contained in this page.</typeparam> | ||||
| 	public class Page<T> | ||||
| namespace Kyoo.Abstractions.Models; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// A page of resource that contains information about the pagination of resources. | ||||
| /// </summary> | ||||
| /// <typeparam name="T">The type of resource contained in this page.</typeparam> | ||||
| public class Page<T> | ||||
| 	where T : IResource | ||||
| 	{ | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// The link of the current page. | ||||
| 	/// </summary> | ||||
| @ -67,13 +67,7 @@ namespace Kyoo.Abstractions.Models | ||||
| 	/// <param name="previous">The link of the previous page.</param> | ||||
| 	/// <param name="next">The link of the next page.</param> | ||||
| 	/// <param name="first">The link of the first page.</param> | ||||
| 		public Page( | ||||
| 			ICollection<T> items, | ||||
| 			string @this, | ||||
| 			string? previous, | ||||
| 			string? next, | ||||
| 			string first | ||||
| 		) | ||||
| 	public Page(ICollection<T> items, string @this, string? previous, string? next, string first) | ||||
| 	{ | ||||
| 		Items = items; | ||||
| 		This = @this; | ||||
| @ -108,5 +102,4 @@ namespace Kyoo.Abstractions.Models | ||||
| 		query.Remove("afterID"); | ||||
| 		First = url + query.ToQueryString(); | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -23,13 +23,13 @@ using System.Text.Json.Serialization; | ||||
| using Kyoo.Abstractions.Controllers; | ||||
| using Kyoo.Utils; | ||||
| 
 | ||||
| namespace Kyoo.Abstractions.Models | ||||
| namespace Kyoo.Abstractions.Models; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// A class representing collections of <see cref="Show"/>. | ||||
| /// </summary> | ||||
| public class Collection : IQuery, IResource, IMetadata, IThumbnails, IAddedDate, ILibraryItem | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// A class representing collections of <see cref="Show"/>. | ||||
| 	/// </summary> | ||||
| 	public class Collection : IQuery, IResource, IMetadata, IThumbnails, IAddedDate, ILibraryItem | ||||
| 	{ | ||||
| 	public static Sort DefaultSort => new Sort<Collection>.By(nameof(Collection.Name)); | ||||
| 
 | ||||
| 	/// <inheritdoc /> | ||||
| @ -87,5 +87,4 @@ namespace Kyoo.Abstractions.Models | ||||
| 			Name = name; | ||||
| 		} | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -26,13 +26,13 @@ using EntityFrameworkCore.Projectables; | ||||
| using Kyoo.Abstractions.Controllers; | ||||
| using Kyoo.Abstractions.Models.Attributes; | ||||
| 
 | ||||
| namespace Kyoo.Abstractions.Models | ||||
| namespace Kyoo.Abstractions.Models; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// A class to represent a single show's episode. | ||||
| /// </summary> | ||||
| public class Episode : IQuery, IResource, IMetadata, IThumbnails, IAddedDate, INews | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// A class to represent a single show's episode. | ||||
| 	/// </summary> | ||||
| 	public class Episode : IQuery, IResource, IMetadata, IThumbnails, IAddedDate, INews | ||||
| 	{ | ||||
| 	// Use absolute numbers by default and fallback to season/episodes if it does not exists. | ||||
| 	public static Sort DefaultSort => | ||||
| 		new Sort<Episode>.Conglomerate( | ||||
| @ -52,12 +52,7 @@ namespace Kyoo.Abstractions.Models | ||||
| 		get | ||||
| 		{ | ||||
| 			if (ShowSlug != null || Show?.Slug != null) | ||||
| 					return GetSlug( | ||||
| 						ShowSlug ?? Show!.Slug, | ||||
| 						SeasonNumber, | ||||
| 						EpisodeNumber, | ||||
| 						AbsoluteNumber | ||||
| 					); | ||||
| 				return GetSlug(ShowSlug ?? Show!.Slug, SeasonNumber, EpisodeNumber, AbsoluteNumber); | ||||
| 			return GetSlug(ShowId.ToString(), SeasonNumber, EpisodeNumber, AbsoluteNumber); | ||||
| 		} | ||||
| 		private set | ||||
| @ -301,5 +296,4 @@ namespace Kyoo.Abstractions.Models | ||||
| 			_ => $"{showSlug}-s{seasonNumber}e{episodeNumber}" | ||||
| 		}; | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -18,16 +18,15 @@ | ||||
| 
 | ||||
| using System; | ||||
| 
 | ||||
| namespace Kyoo.Abstractions.Models | ||||
| namespace Kyoo.Abstractions.Models; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// An interface applied to resources. | ||||
| /// </summary> | ||||
| public interface IAddedDate | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// An interface applied to resources. | ||||
| 	/// </summary> | ||||
| 	public interface IAddedDate | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// The date at which this resource was added to kyoo. | ||||
| 	/// </summary> | ||||
| 	public DateTime AddedDate { get; set; } | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -18,16 +18,15 @@ | ||||
| 
 | ||||
| using System.Collections.Generic; | ||||
| 
 | ||||
| namespace Kyoo.Abstractions.Models | ||||
| namespace Kyoo.Abstractions.Models; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// An interface applied to resources containing external metadata. | ||||
| /// </summary> | ||||
| public interface IMetadata | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// An interface applied to resources containing external metadata. | ||||
| 	/// </summary> | ||||
| 	public interface IMetadata | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// The link to metadata providers that this show has. See <see cref="MetadataId"/> for more information. | ||||
| 	/// </summary> | ||||
| 	public Dictionary<string, MetadataId> ExternalId { get; set; } | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -20,13 +20,13 @@ using System; | ||||
| using System.ComponentModel.DataAnnotations; | ||||
| using Kyoo.Abstractions.Controllers; | ||||
| 
 | ||||
| namespace Kyoo.Abstractions.Models | ||||
| namespace Kyoo.Abstractions.Models; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// An interface to represent a resource that can be retrieved from the database. | ||||
| /// </summary> | ||||
| public interface IResource : IQuery | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// An interface to represent a resource that can be retrieved from the database. | ||||
| 	/// </summary> | ||||
| 	public interface IResource : IQuery | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// A unique ID for this type of resource. This can't be changed and duplicates are not allowed. | ||||
| 	/// </summary> | ||||
| @ -46,5 +46,4 @@ namespace Kyoo.Abstractions.Models | ||||
| 	/// </remarks> | ||||
| 	[MaxLength(256)] | ||||
| 	public string Slug { get; } | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -23,13 +23,13 @@ using System.Globalization; | ||||
| using System.Text.Json.Serialization; | ||||
| using Kyoo.Abstractions.Models.Attributes; | ||||
| 
 | ||||
| namespace Kyoo.Abstractions.Models | ||||
| namespace Kyoo.Abstractions.Models; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// An interface representing items that contains images (like posters, thumbnails, logo, banners...) | ||||
| /// </summary> | ||||
| public interface IThumbnails | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// An interface representing items that contains images (like posters, thumbnails, logo, banners...) | ||||
| 	/// </summary> | ||||
| 	public interface IThumbnails | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// A poster is a 2/3 format image with the cover of the resource. | ||||
| 	/// </summary> | ||||
| @ -45,12 +45,12 @@ namespace Kyoo.Abstractions.Models | ||||
| 	/// A logo is a small image representing the resource. | ||||
| 	/// </summary> | ||||
| 	public Image? Logo { get; set; } | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| 	[TypeConverter(typeof(ImageConvertor))] | ||||
| 	[SqlFirstColumn(nameof(Source))] | ||||
| 	public class Image | ||||
| 	{ | ||||
| [TypeConverter(typeof(ImageConvertor))] | ||||
| [SqlFirstColumn(nameof(Source))] | ||||
| public class Image | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// The original image from another server. | ||||
| 	/// </summary> | ||||
| @ -94,21 +94,18 @@ namespace Kyoo.Abstractions.Models | ||||
| 		} | ||||
| 
 | ||||
| 		/// <inheritdoc /> | ||||
| 			public override bool CanConvertTo( | ||||
| 				ITypeDescriptorContext? context, | ||||
| 				Type? destinationType | ||||
| 			) | ||||
| 		public override bool CanConvertTo(ITypeDescriptorContext? context, Type? destinationType) | ||||
| 		{ | ||||
| 			return false; | ||||
| 		} | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| 	/// <summary> | ||||
| 	/// The quality of an image | ||||
| 	/// </summary> | ||||
| 	public enum ImageQuality | ||||
| 	{ | ||||
| /// <summary> | ||||
| /// The quality of an image | ||||
| /// </summary> | ||||
| public enum ImageQuality | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// Small | ||||
| 	/// </summary> | ||||
| @ -123,5 +120,4 @@ namespace Kyoo.Abstractions.Models | ||||
| 	/// Large | ||||
| 	/// </summary> | ||||
| 	High, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -27,12 +27,12 @@ using Kyoo.Abstractions.Controllers; | ||||
| using Kyoo.Abstractions.Models.Attributes; | ||||
| using Kyoo.Utils; | ||||
| 
 | ||||
| namespace Kyoo.Abstractions.Models | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// A series or a movie. | ||||
| 	/// </summary> | ||||
| 	public class Movie | ||||
| namespace Kyoo.Abstractions.Models; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// A series or a movie. | ||||
| /// </summary> | ||||
| public class Movie | ||||
| 	: IQuery, | ||||
| 		IResource, | ||||
| 		IMetadata, | ||||
| @ -41,7 +41,7 @@ namespace Kyoo.Abstractions.Models | ||||
| 		ILibraryItem, | ||||
| 		INews, | ||||
| 		IWatchlist | ||||
| 	{ | ||||
| { | ||||
| 	public static Sort DefaultSort => new Sort<Movie>.By(x => x.Name); | ||||
| 
 | ||||
| 	/// <inheritdoc /> | ||||
| @ -185,5 +185,4 @@ namespace Kyoo.Abstractions.Models | ||||
| 			Name = name; | ||||
| 		} | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -26,13 +26,13 @@ using EntityFrameworkCore.Projectables; | ||||
| using Kyoo.Abstractions.Controllers; | ||||
| using Kyoo.Abstractions.Models.Attributes; | ||||
| 
 | ||||
| namespace Kyoo.Abstractions.Models | ||||
| namespace Kyoo.Abstractions.Models; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// A season of a <see cref="Show"/>. | ||||
| /// </summary> | ||||
| public class Season : IQuery, IResource, IMetadata, IThumbnails, IAddedDate | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// A season of a <see cref="Show"/>. | ||||
| 	/// </summary> | ||||
| 	public class Season : IQuery, IResource, IMetadata, IThumbnails, IAddedDate | ||||
| 	{ | ||||
| 	public static Sort DefaultSort => new Sort<Season>.By(x => x.SeasonNumber); | ||||
| 
 | ||||
| 	/// <inheritdoc /> | ||||
| @ -145,5 +145,4 @@ namespace Kyoo.Abstractions.Models | ||||
| 	public int EpisodesCount { get; set; } | ||||
| 
 | ||||
| 	private int _EpisodesCount => Episodes!.Count; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -27,12 +27,12 @@ using Kyoo.Abstractions.Controllers; | ||||
| using Kyoo.Abstractions.Models.Attributes; | ||||
| using Kyoo.Utils; | ||||
| 
 | ||||
| namespace Kyoo.Abstractions.Models | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// A series or a movie. | ||||
| 	/// </summary> | ||||
| 	public class Show | ||||
| namespace Kyoo.Abstractions.Models; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// A series or a movie. | ||||
| /// </summary> | ||||
| public class Show | ||||
| 	: IQuery, | ||||
| 		IResource, | ||||
| 		IMetadata, | ||||
| @ -41,7 +41,7 @@ namespace Kyoo.Abstractions.Models | ||||
| 		IAddedDate, | ||||
| 		ILibraryItem, | ||||
| 		IWatchlist | ||||
| 	{ | ||||
| { | ||||
| 	public static Sort DefaultSort => new Sort<Show>.By(x => x.Name); | ||||
| 
 | ||||
| 	/// <inheritdoc /> | ||||
| @ -250,13 +250,13 @@ namespace Kyoo.Abstractions.Models | ||||
| 			Name = name; | ||||
| 		} | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| 	/// <summary> | ||||
| 	/// The enum containing show's status. | ||||
| 	/// </summary> | ||||
| 	public enum Status | ||||
| 	{ | ||||
| /// <summary> | ||||
| /// The enum containing show's status. | ||||
| /// </summary> | ||||
| public enum Status | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// The status of the show is not known. | ||||
| 	/// </summary> | ||||
| @ -276,5 +276,4 @@ namespace Kyoo.Abstractions.Models | ||||
| 	/// This show has not aired yet but has been announced. | ||||
| 	/// </summary> | ||||
| 	Planned | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -23,13 +23,13 @@ using System.Text.Json.Serialization; | ||||
| using Kyoo.Abstractions.Controllers; | ||||
| using Kyoo.Utils; | ||||
| 
 | ||||
| namespace Kyoo.Abstractions.Models | ||||
| namespace Kyoo.Abstractions.Models; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// A studio that make shows. | ||||
| /// </summary> | ||||
| public class Studio : IQuery, IResource, IMetadata | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// A studio that make shows. | ||||
| 	/// </summary> | ||||
| 	public class Studio : IQuery, IResource, IMetadata | ||||
| 	{ | ||||
| 	public static Sort DefaultSort => new Sort<Studio>.By(x => x.Name); | ||||
| 
 | ||||
| 	/// <inheritdoc /> | ||||
| @ -77,5 +77,4 @@ namespace Kyoo.Abstractions.Models | ||||
| 			Name = name; | ||||
| 		} | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -23,13 +23,13 @@ using System.Text.Json.Serialization; | ||||
| using Kyoo.Abstractions.Controllers; | ||||
| using Kyoo.Utils; | ||||
| 
 | ||||
| namespace Kyoo.Abstractions.Models | ||||
| namespace Kyoo.Abstractions.Models; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// A single user of the app. | ||||
| /// </summary> | ||||
| public class User : IQuery, IResource, IAddedDate | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// A single user of the app. | ||||
| 	/// </summary> | ||||
| 	public class User : IQuery, IResource, IAddedDate | ||||
| 	{ | ||||
| 	public static Sort DefaultSort => new Sort<User>.By(x => x.Username); | ||||
| 
 | ||||
| 	/// <inheritdoc /> | ||||
| @ -89,10 +89,10 @@ namespace Kyoo.Abstractions.Models | ||||
| 			Username = username; | ||||
| 		} | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| 	public class ExternalToken | ||||
| 	{ | ||||
| public class ExternalToken | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// The id of this user on the external service. | ||||
| 	/// </summary> | ||||
| @ -113,5 +113,4 @@ namespace Kyoo.Abstractions.Models | ||||
| 	/// Do not forget to refresh it when using it if necessary. | ||||
| 	/// </summary> | ||||
| 	public JwtToken Token { get; set; } | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -20,13 +20,13 @@ using System; | ||||
| using System.Text.Json.Serialization; | ||||
| using Kyoo.Abstractions.Models.Attributes; | ||||
| 
 | ||||
| namespace Kyoo.Abstractions.Models | ||||
| namespace Kyoo.Abstractions.Models; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// Has the user started watching, is it planned? | ||||
| /// </summary> | ||||
| public enum WatchStatus | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// Has the user started watching, is it planned? | ||||
| 	/// </summary> | ||||
| 	public enum WatchStatus | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// The user has already watched this. | ||||
| 	/// </summary> | ||||
| @ -46,14 +46,14 @@ namespace Kyoo.Abstractions.Models | ||||
| 	/// The user has not started watching this but plans to. | ||||
| 	/// </summary> | ||||
| 	Planned, | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| 	/// <summary> | ||||
| 	/// Metadata of what an user as started/planned to watch. | ||||
| 	/// </summary> | ||||
| 	[SqlFirstColumn(nameof(UserId))] | ||||
| 	public class MovieWatchStatus : IAddedDate | ||||
| 	{ | ||||
| /// <summary> | ||||
| /// Metadata of what an user as started/planned to watch. | ||||
| /// </summary> | ||||
| [SqlFirstColumn(nameof(UserId))] | ||||
| public class MovieWatchStatus : IAddedDate | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// The ID of the user that started watching this episode. | ||||
| 	/// </summary> | ||||
| @ -104,11 +104,11 @@ namespace Kyoo.Abstractions.Models | ||||
| 	/// Null if the status is not Watching. | ||||
| 	/// </remarks> | ||||
| 	public int? WatchedPercent { get; set; } | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| 	[SqlFirstColumn(nameof(UserId))] | ||||
| 	public class EpisodeWatchStatus : IAddedDate | ||||
| 	{ | ||||
| [SqlFirstColumn(nameof(UserId))] | ||||
| public class EpisodeWatchStatus : IAddedDate | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// The ID of the user that started watching this episode. | ||||
| 	/// </summary> | ||||
| @ -159,11 +159,11 @@ namespace Kyoo.Abstractions.Models | ||||
| 	/// Null if the status is not Watching or if the next episode is not started. | ||||
| 	/// </remarks> | ||||
| 	public int? WatchedPercent { get; set; } | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| 	[SqlFirstColumn(nameof(UserId))] | ||||
| 	public class ShowWatchStatus : IAddedDate | ||||
| 	{ | ||||
| [SqlFirstColumn(nameof(UserId))] | ||||
| public class ShowWatchStatus : IAddedDate | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// The ID of the user that started watching this episode. | ||||
| 	/// </summary> | ||||
| @ -229,5 +229,4 @@ namespace Kyoo.Abstractions.Models | ||||
| 	/// Null if the status is not Watching or if the next episode is not started. | ||||
| 	/// </remarks> | ||||
| 	public int? WatchedPercent { get; set; } | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -18,15 +18,15 @@ | ||||
| 
 | ||||
| using System.Collections.Generic; | ||||
| 
 | ||||
| namespace Kyoo.Abstractions.Models | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// Results of a search request. | ||||
| 	/// </summary> | ||||
| 	/// <typeparam name="T">The search item's type.</typeparam> | ||||
| 	public class SearchPage<T> : Page<T> | ||||
| namespace Kyoo.Abstractions.Models; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// Results of a search request. | ||||
| /// </summary> | ||||
| /// <typeparam name="T">The search item's type.</typeparam> | ||||
| public class SearchPage<T> : Page<T> | ||||
| 	where T : IResource | ||||
| 	{ | ||||
| { | ||||
| 	public SearchPage( | ||||
| 		SearchResult result, | ||||
| 		string @this, | ||||
| @ -50,5 +50,4 @@ namespace Kyoo.Abstractions.Models | ||||
| 
 | ||||
| 		public ICollection<T> Items { get; set; } | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -16,13 +16,13 @@ | ||||
| // You should have received a copy of the GNU General Public License | ||||
| // along with Kyoo. If not, see <https://www.gnu.org/licenses/>. | ||||
| 
 | ||||
| namespace Kyoo.Authentication.Models | ||||
| namespace Kyoo.Authentication.Models; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// List of well known claims of kyoo | ||||
| /// </summary> | ||||
| public static class Claims | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// List of well known claims of kyoo | ||||
| 	/// </summary> | ||||
| 	public static class Claims | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// The id of the user | ||||
| 	/// </summary> | ||||
| @ -52,5 +52,4 @@ namespace Kyoo.Authentication.Models | ||||
| 	/// A guid used to identify a specific refresh token. This is only useful for the server to revokate tokens. | ||||
| 	/// </summary> | ||||
| 	public static string Guid => "guid"; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -18,13 +18,13 @@ | ||||
| 
 | ||||
| using Kyoo.Abstractions.Models.Attributes; | ||||
| 
 | ||||
| namespace Kyoo.Abstractions.Models.Utils | ||||
| namespace Kyoo.Abstractions.Models.Utils; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// A class containing constant numbers. | ||||
| /// </summary> | ||||
| public static class Constants | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// A class containing constant numbers. | ||||
| 	/// </summary> | ||||
| 	public static class Constants | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// A property to use on a Microsoft.AspNet.MVC.Route.Order property to mark it as an alternative route | ||||
| 	/// that won't be included on the swagger. | ||||
| @ -56,5 +56,4 @@ namespace Kyoo.Abstractions.Models.Utils | ||||
| 	/// A group name for <see cref="ApiDefinitionAttribute"/>. It should be used for endpoints used by admins. | ||||
| 	/// </summary> | ||||
| 	public const string AdminGroup = "4:Admin"; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -24,16 +24,16 @@ using System.Linq; | ||||
| using System.Linq.Expressions; | ||||
| using System.Reflection; | ||||
| 
 | ||||
| namespace Kyoo.Abstractions.Models.Utils | ||||
| namespace Kyoo.Abstractions.Models.Utils; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// A class that represent a resource. It is made to be used as a parameter in a query and not used somewhere else | ||||
| /// on the application. | ||||
| /// This class allow routes to be used via ether IDs or Slugs, this is suitable for every <see cref="IResource"/>. | ||||
| /// </summary> | ||||
| [TypeConverter(typeof(IdentifierConvertor))] | ||||
| public class Identifier | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// A class that represent a resource. It is made to be used as a parameter in a query and not used somewhere else | ||||
| 	/// on the application. | ||||
| 	/// This class allow routes to be used via ether IDs or Slugs, this is suitable for every <see cref="IResource"/>. | ||||
| 	/// </summary> | ||||
| 	[TypeConverter(typeof(IdentifierConvertor))] | ||||
| 	public class Identifier | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// The ID of the resource or null if the slug is specified. | ||||
| 	/// </summary> | ||||
| @ -162,9 +162,7 @@ namespace Kyoo.Abstractions.Models.Utils | ||||
| 	public Filter<T> IsSame<T>() | ||||
| 		where T : IResource | ||||
| 	{ | ||||
| 			return _id.HasValue | ||||
| 				? new Filter<T>.Eq("Id", _id.Value) | ||||
| 				: new Filter<T>.Eq("Slug", _slug!); | ||||
| 		return _id.HasValue ? new Filter<T>.Eq("Id", _id.Value) : new Filter<T>.Eq("Slug", _slug!); | ||||
| 	} | ||||
| 
 | ||||
| 	public bool Is(Guid uid) | ||||
| @ -244,5 +242,4 @@ namespace Kyoo.Abstractions.Models.Utils | ||||
| 			return Guid.TryParse(slug, out id) ? new Identifier(id) : new Identifier(slug); | ||||
| 		} | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -18,13 +18,13 @@ | ||||
| 
 | ||||
| using System; | ||||
| 
 | ||||
| namespace Kyoo.Abstractions.Controllers | ||||
| namespace Kyoo.Abstractions.Controllers; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// Information about the pagination. How many items should be displayed and where to start. | ||||
| /// </summary> | ||||
| public class Pagination | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// Information about the pagination. How many items should be displayed and where to start. | ||||
| 	/// </summary> | ||||
| 	public class Pagination | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// The count of items to return. | ||||
| 	/// </summary> | ||||
| @ -69,5 +69,4 @@ namespace Kyoo.Abstractions.Controllers | ||||
| 	/// <param name="limit">Set the <see cref="Limit"/> value</param> | ||||
| 	/// <returns>A new <see cref="Pagination"/> instance</returns> | ||||
| 	public static implicit operator Pagination(int limit) => new(limit); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -19,13 +19,13 @@ | ||||
| using System; | ||||
| using System.Linq; | ||||
| 
 | ||||
| namespace Kyoo.Abstractions.Models.Utils | ||||
| namespace Kyoo.Abstractions.Models.Utils; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// The list of errors that where made in the request. | ||||
| /// </summary> | ||||
| public class RequestError | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// The list of errors that where made in the request. | ||||
| 	/// </summary> | ||||
| 	public class RequestError | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// The list of errors that where made in the request. | ||||
| 	/// </summary> | ||||
| @ -50,11 +50,7 @@ namespace Kyoo.Abstractions.Models.Utils | ||||
| 	public RequestError(string[] errors) | ||||
| 	{ | ||||
| 		if (errors == null || !errors.Any()) | ||||
| 				throw new ArgumentException( | ||||
| 					"Errors must be non null and not empty", | ||||
| 					nameof(errors) | ||||
| 				); | ||||
| 			throw new ArgumentException("Errors must be non null and not empty", nameof(errors)); | ||||
| 		Errors = errors; | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -16,13 +16,13 @@ | ||||
| // You should have received a copy of the GNU General Public License | ||||
| // along with Kyoo. If not, see <https://www.gnu.org/licenses/>. | ||||
| 
 | ||||
| namespace Kyoo.Abstractions.Controllers | ||||
| namespace Kyoo.Abstractions.Controllers; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// Information about the pagination. How many items should be displayed and where to start. | ||||
| /// </summary> | ||||
| public class SearchPagination | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// Information about the pagination. How many items should be displayed and where to start. | ||||
| 	/// </summary> | ||||
| 	public class SearchPagination | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// The count of items to return. | ||||
| 	/// </summary> | ||||
| @ -32,5 +32,4 @@ namespace Kyoo.Abstractions.Controllers | ||||
| 	/// Where to start? How many items to skip? | ||||
| 	/// </summary> | ||||
| 	public int? Skip { get; set; } | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -25,17 +25,17 @@ using Kyoo.Abstractions.Models; | ||||
| using Kyoo.Abstractions.Models.Attributes; | ||||
| using Kyoo.Utils; | ||||
| 
 | ||||
| namespace Kyoo.Abstractions.Controllers | ||||
| { | ||||
| 	public record Sort; | ||||
| namespace Kyoo.Abstractions.Controllers; | ||||
| 
 | ||||
| 	/// <summary> | ||||
| 	/// Information about how a query should be sorted. What factor should decide the sort and in which order. | ||||
| 	/// </summary> | ||||
| 	/// <typeparam name="T">For witch type this sort applies</typeparam> | ||||
| 	public record Sort<T> : Sort | ||||
| public record Sort; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// Information about how a query should be sorted. What factor should decide the sort and in which order. | ||||
| /// </summary> | ||||
| /// <typeparam name="T">For witch type this sort applies</typeparam> | ||||
| public record Sort<T> : Sort | ||||
| 	where T : IQuery | ||||
| 	{ | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// Sort by a specific key | ||||
| 	/// </summary> | ||||
| @ -117,8 +117,7 @@ namespace Kyoo.Abstractions.Controllers | ||||
| 				) | ||||
| 		}; | ||||
| 
 | ||||
| 			Type[] types = | ||||
| 				typeof(T).GetCustomAttribute<OneOfAttribute>()?.Types ?? new[] { typeof(T) }; | ||||
| 		Type[] types = typeof(T).GetCustomAttribute<OneOfAttribute>()?.Types ?? new[] { typeof(T) }; | ||||
| 		PropertyInfo? property = types | ||||
| 			.Select(x => | ||||
| 				x.GetProperty( | ||||
| @ -131,5 +130,4 @@ namespace Kyoo.Abstractions.Controllers | ||||
| 			throw new ValidationException("The given sort key is not valid."); | ||||
| 		return new By(property.Name, desendant); | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -16,13 +16,13 @@ | ||||
| // You should have received a copy of the GNU General Public License | ||||
| // along with Kyoo. If not, see <https://www.gnu.org/licenses/>. | ||||
| 
 | ||||
| namespace Kyoo.Abstractions.Models | ||||
| namespace Kyoo.Abstractions.Models; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// The links to see a movie or an episode. | ||||
| /// </summary> | ||||
| public class VideoLinks | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// The links to see a movie or an episode. | ||||
| 	/// </summary> | ||||
| 	public class VideoLinks | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// The direct link to the unprocessed video (pristine quality). | ||||
| 	/// </summary> | ||||
| @ -32,5 +32,4 @@ namespace Kyoo.Abstractions.Models | ||||
| 	/// The link to an HLS master playlist containing all qualities available for this video. | ||||
| 	/// </summary> | ||||
| 	public string Hls { get; set; } | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -21,13 +21,13 @@ using Autofac.Builder; | ||||
| using Kyoo.Abstractions.Controllers; | ||||
| using Kyoo.Utils; | ||||
| 
 | ||||
| namespace Kyoo.Abstractions | ||||
| namespace Kyoo.Abstractions; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// A static class with helper functions to setup external modules | ||||
| /// </summary> | ||||
| public static class Module | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// A static class with helper functions to setup external modules | ||||
| 	/// </summary> | ||||
| 	public static class Module | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// Register a new repository to the container. | ||||
| 	/// </summary> | ||||
| @ -72,5 +72,4 @@ namespace Kyoo.Abstractions | ||||
| 	{ | ||||
| 		return builder.RegisterRepository<T2>().AsSelf().As<T>(); | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -19,13 +19,13 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| 
 | ||||
| namespace Kyoo.Utils | ||||
| namespace Kyoo.Utils; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// A set of extensions class for enumerable. | ||||
| /// </summary> | ||||
| public static class EnumerableExtensions | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// A set of extensions class for enumerable. | ||||
| 	/// </summary> | ||||
| 	public static class EnumerableExtensions | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// If the enumerable is empty, execute an action. | ||||
| 	/// </summary> | ||||
| @ -67,5 +67,4 @@ namespace Kyoo.Utils | ||||
| 		foreach (T i in self) | ||||
| 			action(i); | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -22,13 +22,13 @@ using System.Linq; | ||||
| using System.Reflection; | ||||
| using Kyoo.Abstractions.Models.Attributes; | ||||
| 
 | ||||
| namespace Kyoo.Utils | ||||
| namespace Kyoo.Utils; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// A class containing helper methods to merge objects. | ||||
| /// </summary> | ||||
| public static class Merger | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// A class containing helper methods to merge objects. | ||||
| 	/// </summary> | ||||
| 	public static class Merger | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// Merge two dictionary, if the same key is found on both dictionary, the values of the second one is kept. | ||||
| 	/// </summary> | ||||
| @ -130,5 +130,4 @@ namespace Kyoo.Utils | ||||
| 			merge.OnMerge(second); | ||||
| 		return first; | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -25,13 +25,13 @@ using System.Reflection; | ||||
| using System.Text; | ||||
| using System.Text.RegularExpressions; | ||||
| 
 | ||||
| namespace Kyoo.Utils | ||||
| namespace Kyoo.Utils; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// A set of utility functions that can be used everywhere. | ||||
| /// </summary> | ||||
| public static class Utility | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// A set of utility functions that can be used everywhere. | ||||
| 	/// </summary> | ||||
| 	public static class Utility | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// Convert a string to snake case. Stollen from | ||||
| 	/// https://github.com/efcore/EFCore.NamingConventions/blob/main/EFCore.NamingConventions/Internal/SnakeCaseNameRewriter.cs | ||||
| @ -204,9 +204,7 @@ namespace Kyoo.Utils | ||||
| 			: type.GetInheritanceTree(); | ||||
| 		return types | ||||
| 			.Prepend(type) | ||||
| 				.FirstOrDefault(x => | ||||
| 					x.IsGenericType && x.GetGenericTypeDefinition() == genericType | ||||
| 				); | ||||
| 			.FirstOrDefault(x => x.IsGenericType && x.GetGenericTypeDefinition() == genericType); | ||||
| 	} | ||||
| 
 | ||||
| 	/// <summary> | ||||
| @ -361,5 +359,4 @@ namespace Kyoo.Utils | ||||
| 			return string.Empty; | ||||
| 		return "?" + string.Join('&', query.Select(x => $"{x.Key}={x.Value}")); | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -32,19 +32,19 @@ using Microsoft.Extensions.Logging; | ||||
| using Microsoft.Extensions.Primitives; | ||||
| using Microsoft.IdentityModel.Tokens; | ||||
| 
 | ||||
| namespace Kyoo.Authentication | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// A module that enable OpenID authentication for Kyoo. | ||||
| 	/// </summary> | ||||
| 	/// <remarks> | ||||
| 	/// Create a new authentication module instance and use the given configuration. | ||||
| 	/// </remarks> | ||||
| 	public class AuthenticationModule( | ||||
| namespace Kyoo.Authentication; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// A module that enable OpenID authentication for Kyoo. | ||||
| /// </summary> | ||||
| /// <remarks> | ||||
| /// Create a new authentication module instance and use the given configuration. | ||||
| /// </remarks> | ||||
| public class AuthenticationModule( | ||||
| 	IConfiguration configuration, | ||||
| 	ILogger<AuthenticationModule> logger | ||||
| 	) : IPlugin | ||||
| 	{ | ||||
| ) : IPlugin | ||||
| { | ||||
| 	/// <inheritdoc /> | ||||
| 	public string Name => "Authentication"; | ||||
| 
 | ||||
| @ -78,10 +78,7 @@ namespace Kyoo.Authentication | ||||
| 				NewUser = _configuration | ||||
| 					.GetValue("DEFAULT_PERMISSIONS", "overall.read,overall.play")! | ||||
| 					.Split(','), | ||||
| 					RequireVerification = _configuration.GetValue( | ||||
| 						"REQUIRE_ACCOUNT_VERIFICATION", | ||||
| 						true | ||||
| 					), | ||||
| 				RequireVerification = _configuration.GetValue("REQUIRE_ACCOUNT_VERIFICATION", true), | ||||
| 				PublicUrl = | ||||
| 					_configuration.GetValue<string?>("PUBLIC_URL") ?? "http://localhost:8901", | ||||
| 				ApiKeys = _configuration.GetValue("KYOO_APIKEYS", string.Empty)!.Split(','), | ||||
| @ -154,10 +151,7 @@ namespace Kyoo.Authentication | ||||
| 					{ | ||||
| 						string prefix = "Bearer "; | ||||
| 						if ( | ||||
| 								ctx.Request.Headers.TryGetValue( | ||||
| 									"Authorization", | ||||
| 									out StringValues val | ||||
| 								) | ||||
| 							ctx.Request.Headers.TryGetValue("Authorization", out StringValues val) | ||||
| 							&& val.ToString() is string auth | ||||
| 							&& auth.StartsWith(prefix) | ||||
| 						) | ||||
| @ -185,5 +179,4 @@ namespace Kyoo.Authentication | ||||
| 		{ | ||||
| 			SA.New<IApplicationBuilder>(app => app.UseAuthentication(), SA.Authentication), | ||||
| 		}; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -21,13 +21,13 @@ using System.Threading.Tasks; | ||||
| using Kyoo.Abstractions.Models; | ||||
| using Microsoft.IdentityModel.Tokens; | ||||
| 
 | ||||
| namespace Kyoo.Authentication | ||||
| namespace Kyoo.Authentication; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// The service that controls jwt creation and validation. | ||||
| /// </summary> | ||||
| public interface ITokenController | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// The service that controls jwt creation and validation. | ||||
| 	/// </summary> | ||||
| 	public interface ITokenController | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// Create a new access token for the given user. | ||||
| 	/// </summary> | ||||
| @ -50,5 +50,4 @@ namespace Kyoo.Authentication | ||||
| 	/// <exception cref="SecurityTokenException">The given refresh token is not valid.</exception> | ||||
| 	/// <returns>The id of the token's user.</returns> | ||||
| 	Guid GetRefreshTokenUserID(string refreshToken); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -32,14 +32,14 @@ using Microsoft.AspNetCore.Mvc; | ||||
| using Microsoft.AspNetCore.Mvc.Filters; | ||||
| using Microsoft.Extensions.Primitives; | ||||
| 
 | ||||
| namespace Kyoo.Authentication | ||||
| namespace Kyoo.Authentication; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// A permission validator to validate permission with user Permission array | ||||
| /// or the default array from the configurations if the user is not logged. | ||||
| /// </summary> | ||||
| public class PermissionValidator : IPermissionValidator | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// A permission validator to validate permission with user Permission array | ||||
| 	/// or the default array from the configurations if the user is not logged. | ||||
| 	/// </summary> | ||||
| 	public class PermissionValidator : IPermissionValidator | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// The permissions options to retrieve default permissions. | ||||
| 	/// </summary> | ||||
| @ -126,11 +126,7 @@ namespace Kyoo.Authentication | ||||
| 		/// <param name="partialInfo">The partial permission to validate.</param> | ||||
| 		/// <param name="group">The group of the permission.</param> | ||||
| 		/// <param name="options">The option containing default values.</param> | ||||
| 			public PermissionValidatorFilter( | ||||
| 				object partialInfo, | ||||
| 				Group? group, | ||||
| 				PermissionOption options | ||||
| 			) | ||||
| 		public PermissionValidatorFilter(object partialInfo, Group? group, PermissionOption options) | ||||
| 		{ | ||||
| 			switch (partialInfo) | ||||
| 			{ | ||||
| @ -159,11 +155,7 @@ namespace Kyoo.Authentication | ||||
| 
 | ||||
| 			if (permission == null || kind == null) | ||||
| 			{ | ||||
| 					if ( | ||||
| 						context.HttpContext.Items["PermissionGroup"] | ||||
| 						is Group group | ||||
| 							and not Group.None | ||||
| 					) | ||||
| 				if (context.HttpContext.Items["PermissionGroup"] is Group group and not Group.None) | ||||
| 					_group = group; | ||||
| 				else if (_group == Group.None) | ||||
| 					_group = Group.Overall; | ||||
| @ -226,10 +218,7 @@ namespace Kyoo.Authentication | ||||
| 				} | ||||
| 			} | ||||
| 			else if (res.Failure != null) | ||||
| 					context.Result = _ErrorResult( | ||||
| 						res.Failure.Message, | ||||
| 						StatusCodes.Status403Forbidden | ||||
| 					); | ||||
| 				context.Result = _ErrorResult(res.Failure.Message, StatusCodes.Status403Forbidden); | ||||
| 			else | ||||
| 				context.Result = _ErrorResult( | ||||
| 					"Authentication panic", | ||||
| @ -277,9 +266,7 @@ namespace Kyoo.Authentication | ||||
| 			); | ||||
| 			// Change the failure message to make the API nice to use. | ||||
| 			if (ret.Failure != null) | ||||
| 					return AuthenticateResult.Fail( | ||||
| 						"Invalid JWT token. The token may have expired." | ||||
| 					); | ||||
| 				return AuthenticateResult.Fail("Invalid JWT token. The token may have expired."); | ||||
| 			return ret; | ||||
| 		} | ||||
| 	} | ||||
| @ -294,5 +281,4 @@ namespace Kyoo.Authentication | ||||
| 	{ | ||||
| 		return new ObjectResult(new RequestError(error)) { StatusCode = code }; | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -27,13 +27,13 @@ using Kyoo.Abstractions.Models; | ||||
| using Kyoo.Authentication.Models; | ||||
| using Microsoft.IdentityModel.Tokens; | ||||
| 
 | ||||
| namespace Kyoo.Authentication | ||||
| namespace Kyoo.Authentication; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// The service that controls jwt creation and validation. | ||||
| /// </summary> | ||||
| public class TokenController : ITokenController | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// The service that controls jwt creation and validation. | ||||
| 	/// </summary> | ||||
| 	public class TokenController : ITokenController | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// The options that this controller will use. | ||||
| 	/// </summary> | ||||
| @ -131,5 +131,4 @@ namespace Kyoo.Authentication | ||||
| 			return id; | ||||
| 		throw new SecurityTokenException("Token not associated to any user."); | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -16,13 +16,13 @@ | ||||
| // You should have received a copy of the GNU General Public License | ||||
| // along with Kyoo. If not, see <https://www.gnu.org/licenses/>. | ||||
| 
 | ||||
| namespace Kyoo.Authentication.Models.DTO | ||||
| namespace Kyoo.Authentication.Models.DTO; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// A model only used on login requests. | ||||
| /// </summary> | ||||
| public class LoginRequest | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// A model only used on login requests. | ||||
| 	/// </summary> | ||||
| 	public class LoginRequest | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// The user's username. | ||||
| 	/// </summary> | ||||
| @ -43,5 +43,4 @@ namespace Kyoo.Authentication.Models.DTO | ||||
| 		Username = username; | ||||
| 		Password = password; | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -21,13 +21,13 @@ using Kyoo.Abstractions.Models; | ||||
| using Kyoo.Utils; | ||||
| using BCryptNet = BCrypt.Net.BCrypt; | ||||
| 
 | ||||
| namespace Kyoo.Authentication.Models.DTO | ||||
| namespace Kyoo.Authentication.Models.DTO; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// A model only used on register requests. | ||||
| /// </summary> | ||||
| public class RegisterRequest | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// A model only used on register requests. | ||||
| 	/// </summary> | ||||
| 	public class RegisterRequest | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// The user email address | ||||
| 	/// </summary> | ||||
| @ -73,5 +73,4 @@ namespace Kyoo.Authentication.Models.DTO | ||||
| 			Email = Email, | ||||
| 		}; | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -16,13 +16,13 @@ | ||||
| // You should have received a copy of the GNU General Public License | ||||
| // along with Kyoo. If not, see <https://www.gnu.org/licenses/>. | ||||
| 
 | ||||
| namespace Kyoo.Authentication.Models | ||||
| namespace Kyoo.Authentication.Models; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// The main authentication options. | ||||
| /// </summary> | ||||
| public class AuthenticationOption | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// The main authentication options. | ||||
| 	/// </summary> | ||||
| 	public class AuthenticationOption | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// The path to get this option from the root configuration. | ||||
| 	/// </summary> | ||||
| @ -42,5 +42,4 @@ namespace Kyoo.Authentication.Models | ||||
| 	/// Options for permissions | ||||
| 	/// </summary> | ||||
| 	public PermissionOption Permissions { get; set; } = new(); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -35,22 +35,22 @@ using Microsoft.IdentityModel.Tokens; | ||||
| using static Kyoo.Abstractions.Models.Utils.Constants; | ||||
| using BCryptNet = BCrypt.Net.BCrypt; | ||||
| 
 | ||||
| namespace Kyoo.Authentication.Views | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// Sign in, Sign up or refresh tokens. | ||||
| 	/// </summary> | ||||
| 	[ApiController] | ||||
| 	[Route("auth")] | ||||
| 	[ApiDefinition("Authentication", Group = UsersGroup)] | ||||
| 	public class AuthApi( | ||||
| namespace Kyoo.Authentication.Views; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// Sign in, Sign up or refresh tokens. | ||||
| /// </summary> | ||||
| [ApiController] | ||||
| [Route("auth")] | ||||
| [ApiDefinition("Authentication", Group = UsersGroup)] | ||||
| public class AuthApi( | ||||
| 	IUserRepository users, | ||||
| 	OidcController oidc, | ||||
| 	ITokenController tokenController, | ||||
| 	IThumbnailsManager thumbs, | ||||
| 	PermissionOption options | ||||
| 	) : ControllerBase | ||||
| 	{ | ||||
| ) : ControllerBase | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// Create a new Forbidden result from an object. | ||||
| 	/// </summary> | ||||
| @ -127,12 +127,7 @@ namespace Kyoo.Authentication.Views | ||||
| 	/// <response code="403">The provider gave an error.</response> | ||||
| 	[HttpGet("logged/{provider}")] | ||||
| 	[ProducesResponseType(StatusCodes.Status302Found)] | ||||
| 		public ActionResult OauthCodeRedirect( | ||||
| 			string provider, | ||||
| 			string code, | ||||
| 			string state, | ||||
| 			string? error | ||||
| 		) | ||||
| 	public ActionResult OauthCodeRedirect(string provider, string code, string state, string? error) | ||||
| 	{ | ||||
| 		return Redirect( | ||||
| 			_BuildUrl( | ||||
| @ -494,5 +489,4 @@ namespace Kyoo.Authentication.Views | ||||
| 		await thumbs.SetUserImage(User.GetIdOrThrow(), null); | ||||
| 		return NoContent(); | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -20,13 +20,13 @@ using Kyoo.Abstractions.Models.Utils; | ||||
| using Microsoft.AspNetCore.Http; | ||||
| using Microsoft.AspNetCore.Routing; | ||||
| 
 | ||||
| namespace Kyoo.Core.Controllers | ||||
| namespace Kyoo.Core.Controllers; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// The route constraint that goes with the <see cref="Identifier"/>. | ||||
| /// </summary> | ||||
| public class IdentifierRouteConstraint : IRouteConstraint | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// The route constraint that goes with the <see cref="Identifier"/>. | ||||
| 	/// </summary> | ||||
| 	public class IdentifierRouteConstraint : IRouteConstraint | ||||
| 	{ | ||||
| 	/// <inheritdoc /> | ||||
| 	public bool Match( | ||||
| 		HttpContext? httpContext, | ||||
| @ -38,5 +38,4 @@ namespace Kyoo.Core.Controllers | ||||
| 	{ | ||||
| 		return values.ContainsKey(routeKey); | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -20,13 +20,13 @@ using System.Linq; | ||||
| using Kyoo.Abstractions.Controllers; | ||||
| using Kyoo.Abstractions.Models; | ||||
| 
 | ||||
| namespace Kyoo.Core.Controllers | ||||
| namespace Kyoo.Core.Controllers; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// An class to interact with the database. Every repository is mapped through here. | ||||
| /// </summary> | ||||
| public class LibraryManager : ILibraryManager | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// An class to interact with the database. Every repository is mapped through here. | ||||
| 	/// </summary> | ||||
| 	public class LibraryManager : ILibraryManager | ||||
| 	{ | ||||
| 	private readonly IBaseRepository[] _repositories; | ||||
| 
 | ||||
| 	public LibraryManager( | ||||
| @ -102,5 +102,4 @@ namespace Kyoo.Core.Controllers | ||||
| 	{ | ||||
| 		return (IRepository<T>)_repositories.First(x => x.RepositoryType == typeof(T)); | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -26,13 +26,13 @@ using Kyoo.Abstractions.Models.Utils; | ||||
| using Kyoo.Postgresql; | ||||
| using Microsoft.EntityFrameworkCore; | ||||
| 
 | ||||
| namespace Kyoo.Core.Controllers | ||||
| namespace Kyoo.Core.Controllers; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// A local repository to handle collections | ||||
| /// </summary> | ||||
| public class CollectionRepository : LocalRepository<Collection> | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// A local repository to handle collections | ||||
| 	/// </summary> | ||||
| 	public class CollectionRepository : LocalRepository<Collection> | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// The database handle | ||||
| 	/// </summary> | ||||
| @ -99,5 +99,4 @@ namespace Kyoo.Core.Controllers | ||||
| 		await _database.SaveChangesAsync(); | ||||
| 		await base.Delete(obj); | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -27,13 +27,13 @@ using Kyoo.Postgresql; | ||||
| using Microsoft.EntityFrameworkCore; | ||||
| using Microsoft.Extensions.DependencyInjection; | ||||
| 
 | ||||
| namespace Kyoo.Core.Controllers | ||||
| namespace Kyoo.Core.Controllers; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// A local repository to handle episodes. | ||||
| /// </summary> | ||||
| public class EpisodeRepository : LocalRepository<Episode> | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// A local repository to handle episodes. | ||||
| 	/// </summary> | ||||
| 	public class EpisodeRepository : LocalRepository<Episode> | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// The database handle | ||||
| 	/// </summary> | ||||
| @ -47,8 +47,7 @@ namespace Kyoo.Core.Controllers | ||||
| 		IRepository<Show>.OnEdited += async (show) => | ||||
| 		{ | ||||
| 			await using AsyncServiceScope scope = CoreModule.Services.CreateAsyncScope(); | ||||
| 				DatabaseContext database = | ||||
| 					scope.ServiceProvider.GetRequiredService<DatabaseContext>(); | ||||
| 			DatabaseContext database = scope.ServiceProvider.GetRequiredService<DatabaseContext>(); | ||||
| 			List<Episode> episodes = await database | ||||
| 				.Episodes.AsTracking() | ||||
| 				.Where(x => x.ShowId == show.Id) | ||||
| @ -152,5 +151,4 @@ namespace Kyoo.Core.Controllers | ||||
| 		if (epCount == 1) | ||||
| 			await _shows.Delete(obj.ShowId); | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -25,13 +25,13 @@ using Kyoo.Abstractions.Controllers; | ||||
| using Kyoo.Abstractions.Models; | ||||
| using Kyoo.Abstractions.Models.Utils; | ||||
| 
 | ||||
| namespace Kyoo.Core.Controllers | ||||
| namespace Kyoo.Core.Controllers; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// A local repository to handle library items. | ||||
| /// </summary> | ||||
| public class LibraryItemRepository : DapperRepository<ILibraryItem> | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// A local repository to handle library items. | ||||
| 	/// </summary> | ||||
| 	public class LibraryItemRepository : DapperRepository<ILibraryItem> | ||||
| 	{ | ||||
| 	// language=PostgreSQL | ||||
| 	protected override FormattableString Sql => | ||||
| 		$"""
 | ||||
| @ -123,5 +123,4 @@ namespace Kyoo.Core.Controllers | ||||
| 			limit ?? new() | ||||
| 		); | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -32,15 +32,15 @@ using Kyoo.Postgresql; | ||||
| using Kyoo.Utils; | ||||
| using Microsoft.EntityFrameworkCore; | ||||
| 
 | ||||
| namespace Kyoo.Core.Controllers | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// A base class to create repositories using Entity Framework. | ||||
| 	/// </summary> | ||||
| 	/// <typeparam name="T">The type of this repository</typeparam> | ||||
| 	public abstract class LocalRepository<T> : IRepository<T> | ||||
| namespace Kyoo.Core.Controllers; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// A base class to create repositories using Entity Framework. | ||||
| /// </summary> | ||||
| /// <typeparam name="T">The type of this repository</typeparam> | ||||
| public abstract class LocalRepository<T> : IRepository<T> | ||||
| 	where T : class, IResource, IQuery | ||||
| 	{ | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// The Entity Framework's Database handle. | ||||
| 	/// </summary> | ||||
| @ -170,9 +170,7 @@ namespace Kyoo.Core.Controllers | ||||
| 	{ | ||||
| 		T? ret = await GetOrDefault(filter, include, sortBy, reverse, afterId); | ||||
| 		if (ret == null) | ||||
| 				throw new ItemNotFoundException( | ||||
| 					$"No {typeof(T).Name} found with the given predicate." | ||||
| 				); | ||||
| 			throw new ItemNotFoundException($"No {typeof(T).Name} found with the given predicate."); | ||||
| 		return ret; | ||||
| 	} | ||||
| 
 | ||||
| @ -244,13 +242,7 @@ namespace Kyoo.Core.Controllers | ||||
| 		Pagination? limit = default | ||||
| 	) | ||||
| 	{ | ||||
| 			IQueryable<T> query = await ApplyFilters( | ||||
| 				Database.Set<T>(), | ||||
| 				filter, | ||||
| 				sort, | ||||
| 				limit, | ||||
| 				include | ||||
| 			); | ||||
| 		IQueryable<T> query = await ApplyFilters(Database.Set<T>(), filter, sort, limit, include); | ||||
| 		return await query.ToListAsync(); | ||||
| 	} | ||||
| 
 | ||||
| @ -435,9 +427,8 @@ namespace Kyoo.Core.Controllers | ||||
| 	protected virtual Task Validate(T resource) | ||||
| 	{ | ||||
| 		if ( | ||||
| 				typeof(T) | ||||
| 					.GetProperty(nameof(resource.Slug))! | ||||
| 					.GetCustomAttribute<ComputedAttribute>() != null | ||||
| 			typeof(T).GetProperty(nameof(resource.Slug))!.GetCustomAttribute<ComputedAttribute>() | ||||
| 			!= null | ||||
| 		) | ||||
| 			return Task.CompletedTask; | ||||
| 		if (string.IsNullOrEmpty(resource.Slug)) | ||||
| @ -446,9 +437,7 @@ namespace Kyoo.Core.Controllers | ||||
| 		{ | ||||
| 			try | ||||
| 			{ | ||||
| 					MethodInfo? setter = typeof(T) | ||||
| 						.GetProperty(nameof(resource.Slug))! | ||||
| 						.GetSetMethod(); | ||||
| 				MethodInfo? setter = typeof(T).GetProperty(nameof(resource.Slug))!.GetSetMethod(); | ||||
| 				if (setter != null) | ||||
| 					setter.Invoke(resource, new object[] { resource.Slug + '!' }); | ||||
| 				else | ||||
| @ -495,5 +484,4 @@ namespace Kyoo.Core.Controllers | ||||
| 		foreach (T resource in await GetAll(filter)) | ||||
| 			await Delete(resource); | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -25,13 +25,13 @@ using Kyoo.Abstractions.Models.Utils; | ||||
| using Kyoo.Postgresql; | ||||
| using Microsoft.EntityFrameworkCore; | ||||
| 
 | ||||
| namespace Kyoo.Core.Controllers | ||||
| namespace Kyoo.Core.Controllers; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// A local repository to handle shows | ||||
| /// </summary> | ||||
| public class MovieRepository : LocalRepository<Movie> | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// A local repository to handle shows | ||||
| 	/// </summary> | ||||
| 	public class MovieRepository : LocalRepository<Movie> | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// The database handle | ||||
| 	/// </summary> | ||||
| @ -105,5 +105,4 @@ namespace Kyoo.Core.Controllers | ||||
| 		await _database.SaveChangesAsync(); | ||||
| 		await base.Delete(obj); | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -22,13 +22,13 @@ using System.Data.Common; | ||||
| using System.IO; | ||||
| using Kyoo.Abstractions.Models; | ||||
| 
 | ||||
| namespace Kyoo.Core.Controllers | ||||
| namespace Kyoo.Core.Controllers; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// A local repository to handle shows | ||||
| /// </summary> | ||||
| public class NewsRepository : DapperRepository<INews> | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// A local repository to handle shows | ||||
| 	/// </summary> | ||||
| 	public class NewsRepository : DapperRepository<INews> | ||||
| 	{ | ||||
| 	// language=PostgreSQL | ||||
| 	protected override FormattableString Sql => | ||||
| 		$"""
 | ||||
| @ -60,5 +60,4 @@ namespace Kyoo.Core.Controllers | ||||
| 
 | ||||
| 	public NewsRepository(DbConnection database, SqlVariableContext context) | ||||
| 		: base(database, context) { } | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -29,13 +29,13 @@ using Kyoo.Postgresql; | ||||
| using Microsoft.EntityFrameworkCore; | ||||
| using Microsoft.Extensions.DependencyInjection; | ||||
| 
 | ||||
| namespace Kyoo.Core.Controllers | ||||
| namespace Kyoo.Core.Controllers; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// A local repository to handle seasons. | ||||
| /// </summary> | ||||
| public class SeasonRepository : LocalRepository<Season> | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// A local repository to handle seasons. | ||||
| 	/// </summary> | ||||
| 	public class SeasonRepository : LocalRepository<Season> | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// The database handle | ||||
| 	/// </summary> | ||||
| @ -47,8 +47,7 @@ namespace Kyoo.Core.Controllers | ||||
| 		IRepository<Show>.OnEdited += async (show) => | ||||
| 		{ | ||||
| 			await using AsyncServiceScope scope = CoreModule.Services.CreateAsyncScope(); | ||||
| 				DatabaseContext database = | ||||
| 					scope.ServiceProvider.GetRequiredService<DatabaseContext>(); | ||||
| 			DatabaseContext database = scope.ServiceProvider.GetRequiredService<DatabaseContext>(); | ||||
| 			List<Season> seasons = await database | ||||
| 				.Seasons.AsTracking() | ||||
| 				.Where(x => x.ShowId == show.Id) | ||||
| @ -129,5 +128,4 @@ namespace Kyoo.Core.Controllers | ||||
| 		await _database.SaveChangesAsync(); | ||||
| 		await base.Delete(obj); | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -26,13 +26,13 @@ using Kyoo.Postgresql; | ||||
| using Kyoo.Utils; | ||||
| using Microsoft.EntityFrameworkCore; | ||||
| 
 | ||||
| namespace Kyoo.Core.Controllers | ||||
| namespace Kyoo.Core.Controllers; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// A local repository to handle shows | ||||
| /// </summary> | ||||
| public class ShowRepository : LocalRepository<Show> | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// A local repository to handle shows | ||||
| 	/// </summary> | ||||
| 	public class ShowRepository : LocalRepository<Show> | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// The database handle | ||||
| 	/// </summary> | ||||
| @ -106,5 +106,4 @@ namespace Kyoo.Core.Controllers | ||||
| 		await _database.SaveChangesAsync(); | ||||
| 		await base.Delete(obj); | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -26,13 +26,13 @@ using Kyoo.Postgresql; | ||||
| using Kyoo.Utils; | ||||
| using Microsoft.EntityFrameworkCore; | ||||
| 
 | ||||
| namespace Kyoo.Core.Controllers | ||||
| namespace Kyoo.Core.Controllers; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// A local repository to handle studios | ||||
| /// </summary> | ||||
| public class StudioRepository : LocalRepository<Studio> | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// A local repository to handle studios | ||||
| 	/// </summary> | ||||
| 	public class StudioRepository : LocalRepository<Studio> | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// The database handle | ||||
| 	/// </summary> | ||||
| @ -78,5 +78,4 @@ namespace Kyoo.Core.Controllers | ||||
| 		await _database.SaveChangesAsync(); | ||||
| 		await base.Delete(obj); | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -31,19 +31,18 @@ using Kyoo.Abstractions.Models.Exceptions; | ||||
| using Microsoft.Extensions.Logging; | ||||
| using SkiaSharp; | ||||
| 
 | ||||
| namespace Kyoo.Core.Controllers | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// Download images and retrieve the path of those images for a resource. | ||||
| 	/// </summary> | ||||
| 	public class ThumbnailsManager( | ||||
| namespace Kyoo.Core.Controllers; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// Download images and retrieve the path of those images for a resource. | ||||
| /// </summary> | ||||
| public class ThumbnailsManager( | ||||
| 	IHttpClientFactory clientFactory, | ||||
| 	ILogger<ThumbnailsManager> logger, | ||||
| 	Lazy<IRepository<User>> users | ||||
| 	) : IThumbnailsManager | ||||
| 	{ | ||||
| 		private static readonly Dictionary<string, TaskCompletionSource<object>> _downloading = | ||||
| 			new(); | ||||
| ) : IThumbnailsManager | ||||
| { | ||||
| 	private static readonly Dictionary<string, TaskCompletionSource<object>> _downloading = new(); | ||||
| 
 | ||||
| 	private static async Task _WriteTo(SKBitmap bitmap, string path, int quality) | ||||
| 	{ | ||||
| @ -264,5 +263,4 @@ namespace Kyoo.Core.Controllers | ||||
| 		Directory.CreateDirectory("/metadata/user"); | ||||
| 		await _WriteTo(ret, $"/metadata/user/{userId}.webp", 75); | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -33,13 +33,13 @@ using Microsoft.AspNetCore.Mvc; | ||||
| using Microsoft.AspNetCore.Routing; | ||||
| using Microsoft.Extensions.DependencyInjection; | ||||
| 
 | ||||
| namespace Kyoo.Core | ||||
| namespace Kyoo.Core; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// The core module containing default implementations | ||||
| /// </summary> | ||||
| public class CoreModule : IPlugin | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// The core module containing default implementations | ||||
| 	/// </summary> | ||||
| 	public class CoreModule : IPlugin | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// A service provider to access services in static context (in events for example). | ||||
| 	/// </summary> | ||||
| @ -144,5 +144,4 @@ namespace Kyoo.Core | ||||
| 				SA.Endpoint | ||||
| 			) | ||||
| 		}; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -25,17 +25,17 @@ using Microsoft.AspNetCore.Mvc; | ||||
| using Microsoft.AspNetCore.Mvc.Filters; | ||||
| using Microsoft.Extensions.Logging; | ||||
| 
 | ||||
| namespace Kyoo.Core | ||||
| namespace Kyoo.Core; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// A middleware to handle errors globally. | ||||
| /// </summary> | ||||
| /// <remarks> | ||||
| /// Initializes a new instance of the <see cref="ExceptionFilter"/> class. | ||||
| /// </remarks> | ||||
| /// <param name="logger">The logger used to log errors.</param> | ||||
| public class ExceptionFilter(ILogger<ExceptionFilter> logger) : IExceptionFilter | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// A middleware to handle errors globally. | ||||
| 	/// </summary> | ||||
| 	/// <remarks> | ||||
| 	/// Initializes a new instance of the <see cref="ExceptionFilter"/> class. | ||||
| 	/// </remarks> | ||||
| 	/// <param name="logger">The logger used to log errors.</param> | ||||
| 	public class ExceptionFilter(ILogger<ExceptionFilter> logger) : IExceptionFilter | ||||
| 	{ | ||||
| 	/// <inheritdoc/> | ||||
| 	public void OnException(ExceptionContext context) | ||||
| 	{ | ||||
| @ -79,5 +79,4 @@ namespace Kyoo.Core | ||||
| 			StatusCode = StatusCodes.Status500InternalServerError; | ||||
| 		} | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -22,16 +22,16 @@ using Microsoft.AspNetCore.Http; | ||||
| using Microsoft.AspNetCore.Mvc; | ||||
| using Microsoft.Extensions.Diagnostics.HealthChecks; | ||||
| 
 | ||||
| namespace Kyoo.Core.Api | ||||
| namespace Kyoo.Core.Api; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// An API endpoint to check the health. | ||||
| /// </summary> | ||||
| [Route("health")] | ||||
| [ApiController] | ||||
| [ApiDefinition("Health")] | ||||
| public class Health : BaseApi | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// An API endpoint to check the health. | ||||
| 	/// </summary> | ||||
| 	[Route("health")] | ||||
| 	[ApiController] | ||||
| 	[ApiDefinition("Health")] | ||||
| 	public class Health : BaseApi | ||||
| 	{ | ||||
| 	private readonly HealthCheckService _healthCheckService; | ||||
| 
 | ||||
| 	/// <summary> | ||||
| @ -71,5 +71,4 @@ namespace Kyoo.Core.Api | ||||
| 	/// The result of a health operation. | ||||
| 	/// </summary> | ||||
| 	public record HealthResult(string Status); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -25,13 +25,13 @@ using Kyoo.Abstractions.Models; | ||||
| using Kyoo.Utils; | ||||
| using Microsoft.AspNetCore.Mvc; | ||||
| 
 | ||||
| namespace Kyoo.Core.Api | ||||
| namespace Kyoo.Core.Api; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// A common API containing custom methods to help inheritors. | ||||
| /// </summary> | ||||
| public abstract class BaseApi : ControllerBase | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// A common API containing custom methods to help inheritors. | ||||
| 	/// </summary> | ||||
| 	public abstract class BaseApi : ControllerBase | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// Construct and return a page from an api. | ||||
| 	/// </summary> | ||||
| @ -96,5 +96,4 @@ namespace Kyoo.Core.Api | ||||
| 
 | ||||
| 		return new SearchPage<TResult>(result, self, previous, next, first); | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -27,16 +27,16 @@ using Kyoo.Models; | ||||
| using Microsoft.AspNetCore.Http; | ||||
| using Microsoft.AspNetCore.Mvc; | ||||
| 
 | ||||
| namespace Kyoo.Core.Api | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// A base class to handle CRUD operations on a specific resource type <typeparamref name="T"/>. | ||||
| 	/// </summary> | ||||
| 	/// <typeparam name="T">The type of resource to make CRUD apis for.</typeparam> | ||||
| 	[ApiController] | ||||
| 	public class CrudApi<T> : BaseApi | ||||
| namespace Kyoo.Core.Api; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// A base class to handle CRUD operations on a specific resource type <typeparamref name="T"/>. | ||||
| /// </summary> | ||||
| /// <typeparam name="T">The type of resource to make CRUD apis for.</typeparam> | ||||
| [ApiController] | ||||
| public class CrudApi<T> : BaseApi | ||||
| 	where T : class, IResource, IQuery | ||||
| 	{ | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// The repository of the resource, used to retrieve, save and do operations on the baking store. | ||||
| 	/// </summary> | ||||
| @ -67,10 +67,7 @@ namespace Kyoo.Core.Api | ||||
| 	[PartialPermission(Kind.Read)] | ||||
| 	[ProducesResponseType(StatusCodes.Status200OK)] | ||||
| 	[ProducesResponseType(StatusCodes.Status404NotFound)] | ||||
| 		public async Task<ActionResult<T>> Get( | ||||
| 			Identifier identifier, | ||||
| 			[FromQuery] Include<T>? fields | ||||
| 		) | ||||
| 	public async Task<ActionResult<T>> Get(Identifier identifier, [FromQuery] Include<T>? fields) | ||||
| 	{ | ||||
| 		T? ret = await identifier.Match( | ||||
| 			id => Repository.GetOrDefault(id, fields), | ||||
| @ -272,5 +269,4 @@ namespace Kyoo.Core.Api | ||||
| 		await Repository.DeleteAll(filter); | ||||
| 		return NoContent(); | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -26,17 +26,17 @@ using Microsoft.AspNetCore.Http; | ||||
| using Microsoft.AspNetCore.Mvc; | ||||
| using static Kyoo.Abstractions.Models.Utils.Constants; | ||||
| 
 | ||||
| namespace Kyoo.Core.Api | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// A base class to handle CRUD operations and services thumbnails for | ||||
| 	/// a specific resource type <typeparamref name="T"/>. | ||||
| 	/// </summary> | ||||
| 	/// <typeparam name="T">The type of resource to make CRUD and thumbnails apis for.</typeparam> | ||||
| 	[ApiController] | ||||
| 	public class CrudThumbsApi<T> : CrudApi<T> | ||||
| namespace Kyoo.Core.Api; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// A base class to handle CRUD operations and services thumbnails for | ||||
| /// a specific resource type <typeparamref name="T"/>. | ||||
| /// </summary> | ||||
| /// <typeparam name="T">The type of resource to make CRUD and thumbnails apis for.</typeparam> | ||||
| [ApiController] | ||||
| public class CrudThumbsApi<T> : CrudApi<T> | ||||
| 	where T : class, IResource, IThumbnails, IQuery | ||||
| 	{ | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// The thumbnail manager used to retrieve images paths. | ||||
| 	/// </summary> | ||||
| @ -97,10 +97,7 @@ namespace Kyoo.Core.Api | ||||
| 	[PartialPermission(Kind.Read)] | ||||
| 	[ProducesResponseType(StatusCodes.Status200OK)] | ||||
| 	[ProducesResponseType(StatusCodes.Status404NotFound)] | ||||
| 		public Task<IActionResult> GetPoster( | ||||
| 			Identifier identifier, | ||||
| 			[FromQuery] ImageQuality? quality | ||||
| 		) | ||||
| 	public Task<IActionResult> GetPoster(Identifier identifier, [FromQuery] ImageQuality? quality) | ||||
| 	{ | ||||
| 		return _GetImage(identifier, "poster", quality); | ||||
| 	} | ||||
| @ -140,12 +137,8 @@ namespace Kyoo.Core.Api | ||||
| 	/// </response> | ||||
| 	[HttpGet("{identifier:id}/thumbnail")] | ||||
| 	[HttpGet("{identifier:id}/backdrop", Order = AlternativeRoute)] | ||||
| 		public Task<IActionResult> GetBackdrop( | ||||
| 			Identifier identifier, | ||||
| 			[FromQuery] ImageQuality? quality | ||||
| 		) | ||||
| 	public Task<IActionResult> GetBackdrop(Identifier identifier, [FromQuery] ImageQuality? quality) | ||||
| 	{ | ||||
| 		return _GetImage(identifier, "thumbnail", quality); | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -28,18 +28,18 @@ using Microsoft.AspNetCore.Http; | ||||
| using Microsoft.AspNetCore.Mvc; | ||||
| using static Kyoo.Abstractions.Models.Utils.Constants; | ||||
| 
 | ||||
| namespace Kyoo.Core.Api | ||||
| namespace Kyoo.Core.Api; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// Information about one or multiple <see cref="Studio"/>. | ||||
| /// </summary> | ||||
| [Route("studios")] | ||||
| [Route("studio", Order = AlternativeRoute)] | ||||
| [ApiController] | ||||
| [PartialPermission(nameof(Show))] | ||||
| [ApiDefinition("Studios", Group = MetadataGroup)] | ||||
| public class StudioApi : CrudApi<Studio> | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// Information about one or multiple <see cref="Studio"/>. | ||||
| 	/// </summary> | ||||
| 	[Route("studios")] | ||||
| 	[Route("studio", Order = AlternativeRoute)] | ||||
| 	[ApiController] | ||||
| 	[PartialPermission(nameof(Show))] | ||||
| 	[ApiDefinition("Studios", Group = MetadataGroup)] | ||||
| 	public class StudioApi : CrudApi<Studio> | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// The library manager used to modify or retrieve information in the data store. | ||||
| 	/// </summary> | ||||
| @ -99,5 +99,4 @@ namespace Kyoo.Core.Api | ||||
| 			return NotFound(); | ||||
| 		return Page(resources, pagination.Limit); | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -30,18 +30,18 @@ using Microsoft.AspNetCore.Http; | ||||
| using Microsoft.AspNetCore.Mvc; | ||||
| using static Kyoo.Abstractions.Models.Utils.Constants; | ||||
| 
 | ||||
| namespace Kyoo.Core.Api | ||||
| namespace Kyoo.Core.Api; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// Information about one or multiple <see cref="Collection"/>. | ||||
| /// </summary> | ||||
| [Route("collections")] | ||||
| [Route("collection", Order = AlternativeRoute)] | ||||
| [ApiController] | ||||
| [PartialPermission(nameof(Collection))] | ||||
| [ApiDefinition("Collections", Group = ResourcesGroup)] | ||||
| public class CollectionApi : CrudThumbsApi<Collection> | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// Information about one or multiple <see cref="Collection"/>. | ||||
| 	/// </summary> | ||||
| 	[Route("collections")] | ||||
| 	[Route("collection", Order = AlternativeRoute)] | ||||
| 	[ApiController] | ||||
| 	[PartialPermission(nameof(Collection))] | ||||
| 	[ApiDefinition("Collections", Group = ResourcesGroup)] | ||||
| 	public class CollectionApi : CrudThumbsApi<Collection> | ||||
| 	{ | ||||
| 	private readonly ILibraryManager _libraryManager; | ||||
| 	private readonly CollectionRepository _collections; | ||||
| 	private readonly LibraryItemRepository _items; | ||||
| @ -259,5 +259,4 @@ namespace Kyoo.Core.Api | ||||
| 			return NotFound(); | ||||
| 		return Page(resources, pagination.Limit); | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -28,19 +28,19 @@ using Microsoft.AspNetCore.Http; | ||||
| using Microsoft.AspNetCore.Mvc; | ||||
| using static Kyoo.Abstractions.Models.Utils.Constants; | ||||
| 
 | ||||
| namespace Kyoo.Core.Api | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// Information about one or multiple <see cref="Episode"/>. | ||||
| 	/// </summary> | ||||
| 	[Route("episodes")] | ||||
| 	[Route("episode", Order = AlternativeRoute)] | ||||
| 	[ApiController] | ||||
| 	[PartialPermission(nameof(Episode))] | ||||
| 	[ApiDefinition("Episodes", Group = ResourcesGroup)] | ||||
| 	public class EpisodeApi(ILibraryManager libraryManager, IThumbnailsManager thumbnails) | ||||
| namespace Kyoo.Core.Api; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// Information about one or multiple <see cref="Episode"/>. | ||||
| /// </summary> | ||||
| [Route("episodes")] | ||||
| [Route("episode", Order = AlternativeRoute)] | ||||
| [ApiController] | ||||
| [PartialPermission(nameof(Episode))] | ||||
| [ApiDefinition("Episodes", Group = ResourcesGroup)] | ||||
| public class EpisodeApi(ILibraryManager libraryManager, IThumbnailsManager thumbnails) | ||||
| 	: TranscoderApi<Episode>(libraryManager.Episodes, thumbnails) | ||||
| 	{ | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// Get episode's show | ||||
| 	/// </summary> | ||||
| @ -195,5 +195,4 @@ namespace Kyoo.Core.Api | ||||
| 		); | ||||
| 		return (path, $"/episodes/{identifier}"); | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -23,19 +23,19 @@ using Kyoo.Abstractions.Models.Permissions; | ||||
| using Microsoft.AspNetCore.Mvc; | ||||
| using static Kyoo.Abstractions.Models.Utils.Constants; | ||||
| 
 | ||||
| namespace Kyoo.Core.Api | ||||
| namespace Kyoo.Core.Api; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// Endpoint for items that are not part of a specific library. | ||||
| /// An item can ether represent a collection or a show. | ||||
| /// </summary> | ||||
| [Route("items")] | ||||
| [Route("item", Order = AlternativeRoute)] | ||||
| [ApiController] | ||||
| [PartialPermission("LibraryItem")] | ||||
| [ApiDefinition("Items", Group = ResourcesGroup)] | ||||
| public class LibraryItemApi : CrudThumbsApi<ILibraryItem> | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// Endpoint for items that are not part of a specific library. | ||||
| 	/// An item can ether represent a collection or a show. | ||||
| 	/// </summary> | ||||
| 	[Route("items")] | ||||
| 	[Route("item", Order = AlternativeRoute)] | ||||
| 	[ApiController] | ||||
| 	[PartialPermission("LibraryItem")] | ||||
| 	[ApiDefinition("Items", Group = ResourcesGroup)] | ||||
| 	public class LibraryItemApi : CrudThumbsApi<ILibraryItem> | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// The library item repository used to modify or retrieve information in the data store. | ||||
| 	/// </summary> | ||||
| @ -53,5 +53,4 @@ namespace Kyoo.Core.Api | ||||
| 	{ | ||||
| 		_libraryItems = libraryItems; | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -30,19 +30,19 @@ using Microsoft.AspNetCore.Http; | ||||
| using Microsoft.AspNetCore.Mvc; | ||||
| using static Kyoo.Abstractions.Models.Utils.Constants; | ||||
| 
 | ||||
| namespace Kyoo.Core.Api | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// Information about one or multiple <see cref="Movie"/>. | ||||
| 	/// </summary> | ||||
| 	[Route("movies")] | ||||
| 	[Route("movie", Order = AlternativeRoute)] | ||||
| 	[ApiController] | ||||
| 	[PartialPermission(nameof(Show))] | ||||
| 	[ApiDefinition("Shows", Group = ResourcesGroup)] | ||||
| 	public class MovieApi(ILibraryManager libraryManager, IThumbnailsManager thumbs) | ||||
| namespace Kyoo.Core.Api; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// Information about one or multiple <see cref="Movie"/>. | ||||
| /// </summary> | ||||
| [Route("movies")] | ||||
| [Route("movie", Order = AlternativeRoute)] | ||||
| [ApiController] | ||||
| [PartialPermission(nameof(Show))] | ||||
| [ApiDefinition("Shows", Group = ResourcesGroup)] | ||||
| public class MovieApi(ILibraryManager libraryManager, IThumbnailsManager thumbs) | ||||
| 	: TranscoderApi<Movie>(libraryManager.Movies, thumbs) | ||||
| 	{ | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// Get studio that made the show | ||||
| 	/// </summary> | ||||
| @ -207,5 +207,4 @@ namespace Kyoo.Core.Api | ||||
| 		); | ||||
| 		return (path, $"/movies/{identifier}"); | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -23,19 +23,18 @@ using Kyoo.Abstractions.Models.Permissions; | ||||
| using Microsoft.AspNetCore.Mvc; | ||||
| using static Kyoo.Abstractions.Models.Utils.Constants; | ||||
| 
 | ||||
| namespace Kyoo.Core.Api | ||||
| namespace Kyoo.Core.Api; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// List new items added to kyoo. | ||||
| /// </summary> | ||||
| [Route("news")] | ||||
| [Route("new", Order = AlternativeRoute)] | ||||
| [ApiController] | ||||
| [PartialPermission("LibraryItem")] | ||||
| [ApiDefinition("News", Group = ResourcesGroup)] | ||||
| public class NewsApi : CrudThumbsApi<INews> | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// List new items added to kyoo. | ||||
| 	/// </summary> | ||||
| 	[Route("news")] | ||||
| 	[Route("new", Order = AlternativeRoute)] | ||||
| 	[ApiController] | ||||
| 	[PartialPermission("LibraryItem")] | ||||
| 	[ApiDefinition("News", Group = ResourcesGroup)] | ||||
| 	public class NewsApi : CrudThumbsApi<INews> | ||||
| 	{ | ||||
| 	public NewsApi(IRepository<INews> news, IThumbnailsManager thumbs) | ||||
| 		: base(news, thumbs) { } | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -26,17 +26,17 @@ using Microsoft.AspNetCore.Http; | ||||
| using Microsoft.AspNetCore.Mvc; | ||||
| using static Kyoo.Abstractions.Models.Utils.Constants; | ||||
| 
 | ||||
| namespace Kyoo.Core.Api | ||||
| namespace Kyoo.Core.Api; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// An endpoint to search for every resources of kyoo. Searching for only a specific type of resource | ||||
| /// is available on the said endpoint. | ||||
| /// </summary> | ||||
| [Route("search")] | ||||
| [ApiController] | ||||
| [ApiDefinition("Search", Group = ResourcesGroup)] | ||||
| public class SearchApi : BaseApi | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// An endpoint to search for every resources of kyoo. Searching for only a specific type of resource | ||||
| 	/// is available on the said endpoint. | ||||
| 	/// </summary> | ||||
| 	[Route("search")] | ||||
| 	[ApiController] | ||||
| 	[ApiDefinition("Search", Group = ResourcesGroup)] | ||||
| 	public class SearchApi : BaseApi | ||||
| 	{ | ||||
| 	private readonly ISearchManager _searchManager; | ||||
| 
 | ||||
| 	public SearchApi(ISearchManager searchManager) | ||||
| @ -69,9 +69,7 @@ namespace Kyoo.Core.Api | ||||
| 		[FromQuery] Include<Collection> fields | ||||
| 	) | ||||
| 	{ | ||||
| 			return SearchPage( | ||||
| 				await _searchManager.SearchCollections(q, sortBy, pagination, fields) | ||||
| 			); | ||||
| 		return SearchPage(await _searchManager.SearchCollections(q, sortBy, pagination, fields)); | ||||
| 	} | ||||
| 
 | ||||
| 	/// <summary> | ||||
| @ -203,5 +201,4 @@ namespace Kyoo.Core.Api | ||||
| 	{ | ||||
| 		return SearchPage(await _searchManager.SearchStudios(q, sortBy, pagination, fields)); | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -28,18 +28,18 @@ using Microsoft.AspNetCore.Http; | ||||
| using Microsoft.AspNetCore.Mvc; | ||||
| using static Kyoo.Abstractions.Models.Utils.Constants; | ||||
| 
 | ||||
| namespace Kyoo.Core.Api | ||||
| namespace Kyoo.Core.Api; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// Information about one or multiple <see cref="Season"/>. | ||||
| /// </summary> | ||||
| [Route("seasons")] | ||||
| [Route("season", Order = AlternativeRoute)] | ||||
| [ApiController] | ||||
| [PartialPermission(nameof(Season))] | ||||
| [ApiDefinition("Seasons", Group = ResourcesGroup)] | ||||
| public class SeasonApi : CrudThumbsApi<Season> | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// Information about one or multiple <see cref="Season"/>. | ||||
| 	/// </summary> | ||||
| 	[Route("seasons")] | ||||
| 	[Route("season", Order = AlternativeRoute)] | ||||
| 	[ApiController] | ||||
| 	[PartialPermission(nameof(Season))] | ||||
| 	[ApiDefinition("Seasons", Group = ResourcesGroup)] | ||||
| 	public class SeasonApi : CrudThumbsApi<Season> | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// The library manager used to modify or retrieve information in the data store. | ||||
| 	/// </summary> | ||||
| @ -87,10 +87,7 @@ namespace Kyoo.Core.Api | ||||
| 	) | ||||
| 	{ | ||||
| 		ICollection<Episode> resources = await _libraryManager.Episodes.GetAll( | ||||
| 				Filter.And( | ||||
| 					filter, | ||||
| 					identifier.Matcher<Episode>(x => x.SeasonId, x => x.Season!.Slug) | ||||
| 				), | ||||
| 			Filter.And(filter, identifier.Matcher<Episode>(x => x.SeasonId, x => x.Season!.Slug)), | ||||
| 			sortBy, | ||||
| 			fields, | ||||
| 			pagination | ||||
| @ -131,5 +128,4 @@ namespace Kyoo.Core.Api | ||||
| 			return NotFound(); | ||||
| 		return ret; | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -30,18 +30,18 @@ using Microsoft.AspNetCore.Http; | ||||
| using Microsoft.AspNetCore.Mvc; | ||||
| using static Kyoo.Abstractions.Models.Utils.Constants; | ||||
| 
 | ||||
| namespace Kyoo.Core.Api | ||||
| namespace Kyoo.Core.Api; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// Information about one or multiple <see cref="Show"/>. | ||||
| /// </summary> | ||||
| [Route("shows")] | ||||
| [Route("show", Order = AlternativeRoute)] | ||||
| [ApiController] | ||||
| [PartialPermission(nameof(Show))] | ||||
| [ApiDefinition("Shows", Group = ResourcesGroup)] | ||||
| public class ShowApi : CrudThumbsApi<Show> | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// Information about one or multiple <see cref="Show"/>. | ||||
| 	/// </summary> | ||||
| 	[Route("shows")] | ||||
| 	[Route("show", Order = AlternativeRoute)] | ||||
| 	[ApiController] | ||||
| 	[PartialPermission(nameof(Show))] | ||||
| 	[ApiDefinition("Shows", Group = ResourcesGroup)] | ||||
| 	public class ShowApi : CrudThumbsApi<Show> | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// The library manager used to modify or retrieve information in the data store. | ||||
| 	/// </summary> | ||||
| @ -256,10 +256,7 @@ namespace Kyoo.Core.Api | ||||
| 	[ProducesResponseType(StatusCodes.Status204NoContent)] | ||||
| 	[ProducesResponseType(StatusCodes.Status400BadRequest)] | ||||
| 	[ProducesResponseType(StatusCodes.Status404NotFound)] | ||||
| 		public async Task<ShowWatchStatus?> SetWatchStatus( | ||||
| 			Identifier identifier, | ||||
| 			WatchStatus status | ||||
| 		) | ||||
| 	public async Task<ShowWatchStatus?> SetWatchStatus(Identifier identifier, WatchStatus status) | ||||
| 	{ | ||||
| 		Guid id = await identifier.Match( | ||||
| 			id => Task.FromResult(id), | ||||
| @ -290,5 +287,4 @@ namespace Kyoo.Core.Api | ||||
| 		); | ||||
| 		await _libraryManager.WatchStatus.DeleteShowStatus(id, User.GetIdOrThrow()); | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -29,18 +29,18 @@ using Microsoft.AspNetCore.Http; | ||||
| using Microsoft.AspNetCore.Mvc; | ||||
| using static Kyoo.Abstractions.Models.Utils.Constants; | ||||
| 
 | ||||
| namespace Kyoo.Core.Api | ||||
| namespace Kyoo.Core.Api; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// List new items added to kyoo. | ||||
| /// </summary> | ||||
| [Route("watchlist")] | ||||
| [ApiController] | ||||
| [PartialPermission("LibraryItem")] | ||||
| [ApiDefinition("News", Group = ResourcesGroup)] | ||||
| [UserOnly] | ||||
| public class WatchlistApi(IWatchStatusRepository repository) : BaseApi | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// List new items added to kyoo. | ||||
| 	/// </summary> | ||||
| 	[Route("watchlist")] | ||||
| 	[ApiController] | ||||
| 	[PartialPermission("LibraryItem")] | ||||
| 	[ApiDefinition("News", Group = ResourcesGroup)] | ||||
| 	[UserOnly] | ||||
| 	public class WatchlistApi(IWatchStatusRepository repository) : BaseApi | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// Get all | ||||
| 	/// </summary> | ||||
| @ -68,5 +68,4 @@ namespace Kyoo.Core.Api | ||||
| 
 | ||||
| 		return Page(resources, pagination.Limit); | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -28,15 +28,15 @@ using Kyoo.Utils; | ||||
| using Microsoft.AspNetCore.Http; | ||||
| using Microsoft.AspNetCore.Mvc; | ||||
| 
 | ||||
| namespace Kyoo.Core.Api | ||||
| namespace Kyoo.Core.Api; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// Proxy to other services | ||||
| /// </summary> | ||||
| [ApiController] | ||||
| [Obsolete("Use /episode/id/master.m3u8 or routes like that")] | ||||
| public class ProxyApi(ILibraryManager library) : Controller | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// Proxy to other services | ||||
| 	/// </summary> | ||||
| 	[ApiController] | ||||
| 	[Obsolete("Use /episode/id/master.m3u8 or routes like that")] | ||||
| 	public class ProxyApi(ILibraryManager library) : Controller | ||||
| 	{ | ||||
| 	private Task _Proxy(string route, (string path, string route) info) | ||||
| 	{ | ||||
| 		HttpProxyOptions proxyOptions = HttpProxyOptionsBuilder | ||||
| @ -92,5 +92,4 @@ namespace Kyoo.Core.Api | ||||
| 		); | ||||
| 		await _Proxy(rest + query.ToQueryString(), (path, $"{type}/{id}")); | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -37,14 +37,14 @@ using Serilog.Templates; | ||||
| using Serilog.Templates.Themes; | ||||
| using ILogger = Serilog.ILogger; | ||||
| 
 | ||||
| namespace Kyoo.Host | ||||
| namespace Kyoo.Host; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// Hosts of kyoo (main functions) generally only create a new <see cref="Application"/> | ||||
| /// and return <see cref="Start(string[])"/>. | ||||
| /// </summary> | ||||
| public class Application | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// Hosts of kyoo (main functions) generally only create a new <see cref="Application"/> | ||||
| 	/// and return <see cref="Start(string[])"/>. | ||||
| 	/// </summary> | ||||
| 	public class Application | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// The environment in witch Kyoo will run (ether "Production" or "Development"). | ||||
| 	/// </summary> | ||||
| @ -124,10 +124,7 @@ namespace Kyoo.Host | ||||
| 				"Version: {Version}", | ||||
| 				Assembly.GetExecutingAssembly().GetName().Version.ToString(3) | ||||
| 			); | ||||
| 				_logger.Information( | ||||
| 					"Data directory: {DataDirectory}", | ||||
| 					Environment.CurrentDirectory | ||||
| 				); | ||||
| 			_logger.Information("Data directory: {DataDirectory}", Environment.CurrentDirectory); | ||||
| 			await host.RunAsync(cancellationToken); | ||||
| 		} | ||||
| 		catch (Exception ex) | ||||
| @ -157,9 +154,7 @@ namespace Kyoo.Host | ||||
| 					}) | ||||
| 					.UseIIS() | ||||
| 					.UseIISIntegration() | ||||
| 						.UseUrls( | ||||
| 							Environment.GetEnvironmentVariable("KYOO_BIND_URL") ?? "http://*:5000" | ||||
| 						) | ||||
| 					.UseUrls(Environment.GetEnvironmentVariable("KYOO_BIND_URL") ?? "http://*:5000") | ||||
| 					.UseStartup(host => | ||||
| 						PluginsStartup.FromWebHost(host, new LoggerFactory().AddSerilog()) | ||||
| 					) | ||||
| @ -198,5 +193,4 @@ namespace Kyoo.Host | ||||
| 			.Enrich.WithThreadId() | ||||
| 			.Enrich.FromLogContext(); | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -23,14 +23,14 @@ using Kyoo.Abstractions.Controllers; | ||||
| using Microsoft.Extensions.DependencyInjection; | ||||
| using Microsoft.Extensions.Logging; | ||||
| 
 | ||||
| namespace Kyoo.Host.Controllers | ||||
| namespace Kyoo.Host.Controllers; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// An implementation of <see cref="IPluginManager"/>. | ||||
| /// This is used to load plugins and retrieve information from them. | ||||
| /// </summary> | ||||
| public class PluginManager : IPluginManager | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// An implementation of <see cref="IPluginManager"/>. | ||||
| 	/// This is used to load plugins and retrieve information from them. | ||||
| 	/// </summary> | ||||
| 	public class PluginManager : IPluginManager | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// The service provider. It allow plugin's activation. | ||||
| 	/// </summary> | ||||
| @ -86,10 +86,7 @@ namespace Kyoo.Host.Controllers | ||||
| 	public void LoadPlugins(params Type[] plugins) | ||||
| 	{ | ||||
| 		LoadPlugins( | ||||
| 				plugins | ||||
| 					.Select(x => (IPlugin)ActivatorUtilities.CreateInstance(_provider, x)) | ||||
| 					.ToArray() | ||||
| 			plugins.Select(x => (IPlugin)ActivatorUtilities.CreateInstance(_provider, x)).ToArray() | ||||
| 		); | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -23,13 +23,13 @@ using Kyoo.Abstractions.Controllers; | ||||
| using Microsoft.AspNetCore.Builder; | ||||
| using Serilog; | ||||
| 
 | ||||
| namespace Kyoo.Host | ||||
| namespace Kyoo.Host; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// A module that registers host controllers and other needed things. | ||||
| /// </summary> | ||||
| public class HostModule : IPlugin | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// A module that registers host controllers and other needed things. | ||||
| 	/// </summary> | ||||
| 	public class HostModule : IPlugin | ||||
| 	{ | ||||
| 	/// <inheritdoc /> | ||||
| 	public string Name => "Host"; | ||||
| 
 | ||||
| @ -57,5 +57,4 @@ namespace Kyoo.Host | ||||
| 	/// <inheritdoc /> | ||||
| 	public IEnumerable<IStartupAction> ConfigureSteps => | ||||
| 		new[] { SA.New<IApplicationBuilder>(app => app.UseSerilogRequestLogging(), SA.Before) }; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -36,13 +36,13 @@ using Microsoft.Extensions.DependencyInjection; | ||||
| using Microsoft.Extensions.Hosting; | ||||
| using Microsoft.Extensions.Logging; | ||||
| 
 | ||||
| namespace Kyoo.Host | ||||
| namespace Kyoo.Host; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// The Startup class is used to configure the AspNet's webhost. | ||||
| /// </summary> | ||||
| public class PluginsStartup | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// The Startup class is used to configure the AspNet's webhost. | ||||
| 	/// </summary> | ||||
| 	public class PluginsStartup | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// A plugin manager used to load plugins and allow them to configure services / asp net. | ||||
| 	/// </summary> | ||||
| @ -81,8 +81,7 @@ namespace Kyoo.Host | ||||
| 	/// <returns>A new <see cref="PluginsStartup"/>.</returns> | ||||
| 	public static PluginsStartup FromWebHost(WebHostBuilderContext host, ILoggerFactory logger) | ||||
| 	{ | ||||
| 			HostServiceProvider hostProvider = | ||||
| 				new(host.HostingEnvironment, host.Configuration, logger); | ||||
| 		HostServiceProvider hostProvider = new(host.HostingEnvironment, host.Configuration, logger); | ||||
| 		PluginManager plugins = new(hostProvider, logger.CreateLogger<PluginManager>()); | ||||
| 		return new PluginsStartup(plugins); | ||||
| 	} | ||||
| @ -93,9 +92,7 @@ namespace Kyoo.Host | ||||
| 	/// <param name="services">The service collection to fill.</param> | ||||
| 	public void ConfigureServices(IServiceCollection services) | ||||
| 	{ | ||||
| 			foreach ( | ||||
| 				Assembly assembly in _plugins.GetAllPlugins().Select(x => x.GetType().Assembly) | ||||
| 			) | ||||
| 		foreach (Assembly assembly in _plugins.GetAllPlugins().Select(x => x.GetType().Assembly)) | ||||
| 			services.AddMvcCore().AddApplicationPart(assembly); | ||||
| 
 | ||||
| 		_hostModule.Configure(services); | ||||
| @ -198,5 +195,4 @@ namespace Kyoo.Host | ||||
| 			return null; | ||||
| 		} | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -19,13 +19,13 @@ | ||||
| using System.Threading.Tasks; | ||||
| using Microsoft.AspNetCore.Hosting; | ||||
| 
 | ||||
| namespace Kyoo.Host | ||||
| namespace Kyoo.Host; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// Program entrypoint. | ||||
| /// </summary> | ||||
| public static class Program | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// Program entrypoint. | ||||
| 	/// </summary> | ||||
| 	public static class Program | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// The string representation of the environment used in <see cref="IWebHostEnvironment"/>. | ||||
| 	/// </summary> | ||||
| @ -45,5 +45,4 @@ namespace Kyoo.Host | ||||
| 		Application application = new(Environment); | ||||
| 		return application.Start(args); | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -24,10 +24,10 @@ using Microsoft.Extensions.Configuration; | ||||
| using Microsoft.Extensions.DependencyInjection; | ||||
| using static System.Text.Json.JsonNamingPolicy; | ||||
| 
 | ||||
| namespace Kyoo.Meiliseach | ||||
| namespace Kyoo.Meiliseach; | ||||
| 
 | ||||
| public class MeilisearchModule : IPlugin | ||||
| { | ||||
| 	public class MeilisearchModule : IPlugin | ||||
| 	{ | ||||
| 	/// <inheritdoc /> | ||||
| 	public string Name => "Meilisearch"; | ||||
| 
 | ||||
| @ -64,11 +64,7 @@ namespace Kyoo.Meiliseach | ||||
| 						CamelCase.ConvertName(nameof(Movie.Rating)), | ||||
| 						CamelCase.ConvertName(nameof(Movie.Runtime)), | ||||
| 					}, | ||||
| 						DisplayedAttributes = new[] | ||||
| 						{ | ||||
| 							CamelCase.ConvertName(nameof(Movie.Id)), | ||||
| 							"kind" | ||||
| 						}, | ||||
| 					DisplayedAttributes = new[] { CamelCase.ConvertName(nameof(Movie.Id)), "kind" }, | ||||
| 					RankingRules = new[] | ||||
| 					{ | ||||
| 						"words", | ||||
| @ -190,5 +186,4 @@ namespace Kyoo.Meiliseach | ||||
| 		builder.RegisterType<MeiliSync>().AsSelf().SingleInstance().AutoActivate(); | ||||
| 		builder.RegisterType<SearchManager>().As<ISearchManager>().InstancePerLifetimeScope(); | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -31,17 +31,17 @@ using Microsoft.AspNetCore.Http; | ||||
| using Microsoft.EntityFrameworkCore; | ||||
| using Microsoft.EntityFrameworkCore.ChangeTracking; | ||||
| 
 | ||||
| namespace Kyoo.Postgresql | ||||
| namespace Kyoo.Postgresql; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// The database handle used for all local repositories. | ||||
| /// This is an abstract class. It is meant to be implemented by plugins. This allow the core to be database agnostic. | ||||
| /// </summary> | ||||
| /// <remarks> | ||||
| /// It should not be used directly, to access the database use a <see cref="ILibraryManager"/> or repositories. | ||||
| /// </remarks> | ||||
| public abstract class DatabaseContext : DbContext | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// The database handle used for all local repositories. | ||||
| 	/// This is an abstract class. It is meant to be implemented by plugins. This allow the core to be database agnostic. | ||||
| 	/// </summary> | ||||
| 	/// <remarks> | ||||
| 	/// It should not be used directly, to access the database use a <see cref="ILibraryManager"/> or repositories. | ||||
| 	/// </remarks> | ||||
| 	public abstract class DatabaseContext : DbContext | ||||
| 	{ | ||||
| 	private readonly IHttpContextAccessor _accessor; | ||||
| 
 | ||||
| 	/// <summary> | ||||
| @ -260,10 +260,7 @@ namespace Kyoo.Postgresql | ||||
| 		base.OnModelCreating(modelBuilder); | ||||
| 
 | ||||
| 		modelBuilder.Entity<Show>().Ignore(x => x.FirstEpisode).Ignore(x => x.AirDate); | ||||
| 			modelBuilder | ||||
| 				.Entity<Episode>() | ||||
| 				.Ignore(x => x.PreviousEpisode) | ||||
| 				.Ignore(x => x.NextEpisode); | ||||
| 		modelBuilder.Entity<Episode>().Ignore(x => x.PreviousEpisode).Ignore(x => x.NextEpisode); | ||||
| 
 | ||||
| 		modelBuilder | ||||
| 			.Entity<Show>() | ||||
| @ -353,9 +350,7 @@ namespace Kyoo.Postgresql | ||||
| 
 | ||||
| 		modelBuilder.Entity<MovieWatchStatus>().HasQueryFilter(x => x.UserId == CurrentUserId); | ||||
| 		modelBuilder.Entity<ShowWatchStatus>().HasQueryFilter(x => x.UserId == CurrentUserId); | ||||
| 			modelBuilder | ||||
| 				.Entity<EpisodeWatchStatus>() | ||||
| 				.HasQueryFilter(x => x.UserId == CurrentUserId); | ||||
| 		modelBuilder.Entity<EpisodeWatchStatus>().HasQueryFilter(x => x.UserId == CurrentUserId); | ||||
| 
 | ||||
| 		modelBuilder.Entity<ShowWatchStatus>().Navigation(x => x.NextEpisode).AutoInclude(); | ||||
| 
 | ||||
| @ -543,9 +538,7 @@ namespace Kyoo.Postgresql | ||||
| 	/// <param name="cancellationToken">A <see cref="CancellationToken"/> to observe while waiting for the task to complete</param> | ||||
| 	/// <exception cref="DuplicatedItemException">A duplicated item has been found.</exception> | ||||
| 	/// <returns>The number of state entries written to the database.</returns> | ||||
| 		public override async Task<int> SaveChangesAsync( | ||||
| 			CancellationToken cancellationToken = default | ||||
| 		) | ||||
| 	public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default) | ||||
| 	{ | ||||
| 		try | ||||
| 		{ | ||||
| @ -635,13 +628,10 @@ namespace Kyoo.Postgresql | ||||
| 	public void DiscardChanges() | ||||
| 	{ | ||||
| 		foreach ( | ||||
| 				EntityEntry entry in ChangeTracker | ||||
| 					.Entries() | ||||
| 					.Where(x => x.State != EntityState.Detached) | ||||
| 			EntityEntry entry in ChangeTracker.Entries().Where(x => x.State != EntityState.Detached) | ||||
| 		) | ||||
| 		{ | ||||
| 			entry.State = EntityState.Detached; | ||||
| 		} | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -25,13 +25,13 @@ using Microsoft.EntityFrameworkCore; | ||||
| using Microsoft.EntityFrameworkCore.Query.SqlExpressions; | ||||
| using Npgsql; | ||||
| 
 | ||||
| namespace Kyoo.Postgresql | ||||
| namespace Kyoo.Postgresql; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// A postgresql implementation of <see cref="DatabaseContext"/>. | ||||
| /// </summary> | ||||
| public class PostgresContext : DatabaseContext | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// A postgresql implementation of <see cref="DatabaseContext"/>. | ||||
| 	/// </summary> | ||||
| 	public class PostgresContext : DatabaseContext | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// Is this instance in debug mode? | ||||
| 	/// </summary> | ||||
| @ -134,5 +134,4 @@ namespace Kyoo.Postgresql | ||||
| 					or PostgresErrorCodes.ForeignKeyViolation | ||||
| 			}; | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -33,13 +33,13 @@ using Microsoft.Extensions.DependencyInjection; | ||||
| using Microsoft.Extensions.Hosting; | ||||
| using Npgsql; | ||||
| 
 | ||||
| namespace Kyoo.Postgresql | ||||
| namespace Kyoo.Postgresql; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// A module to add postgresql capacity to the app. | ||||
| /// </summary> | ||||
| public class PostgresModule : IPlugin | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// A module to add postgresql capacity to the app. | ||||
| 	/// </summary> | ||||
| 	public class PostgresModule : IPlugin | ||||
| 	{ | ||||
| 	/// <inheritdoc /> | ||||
| 	public string Name => "Postgresql"; | ||||
| 
 | ||||
| @ -137,11 +137,8 @@ namespace Kyoo.Postgresql | ||||
| 			}, | ||||
| 			ServiceLifetime.Transient | ||||
| 		); | ||||
| 			services.AddTransient<DbConnection>( | ||||
| 				(_) => new NpgsqlConnection(builder.ConnectionString) | ||||
| 			); | ||||
| 		services.AddTransient<DbConnection>((_) => new NpgsqlConnection(builder.ConnectionString)); | ||||
| 
 | ||||
| 		services.AddHealthChecks().AddDbContextCheck<DatabaseContext>(); | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -22,13 +22,13 @@ using Kyoo.Swagger.Models; | ||||
| using NSwag; | ||||
| using NSwag.Generation.AspNetCore; | ||||
| 
 | ||||
| namespace Kyoo.Swagger | ||||
| namespace Kyoo.Swagger; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// A class to sort apis. | ||||
| /// </summary> | ||||
| public static class ApiSorter | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// A class to sort apis. | ||||
| 	/// </summary> | ||||
| 	public static class ApiSorter | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// Sort apis by alphabetical orders. | ||||
| 	/// </summary> | ||||
| @ -62,5 +62,4 @@ namespace Kyoo.Swagger | ||||
| 				.ToList(); | ||||
| 		}; | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -26,15 +26,15 @@ using NSwag; | ||||
| using NSwag.Generation.AspNetCore; | ||||
| using NSwag.Generation.Processors.Contexts; | ||||
| 
 | ||||
| namespace Kyoo.Swagger | ||||
| namespace Kyoo.Swagger; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// A class to handle Api Groups (OpenApi tags and x-tagGroups). | ||||
| /// Tags should be specified via <see cref="ApiDefinitionAttribute"/> and this filter will map this to the | ||||
| /// <see cref="OpenApiDocument"/>. | ||||
| /// </summary> | ||||
| public static class ApiTagsFilter | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// A class to handle Api Groups (OpenApi tags and x-tagGroups). | ||||
| 	/// Tags should be specified via <see cref="ApiDefinitionAttribute"/> and this filter will map this to the | ||||
| 	/// <see cref="OpenApiDocument"/>. | ||||
| 	/// </summary> | ||||
| 	public static class ApiTagsFilter | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// The main operation filter that will map every <see cref="ApiDefinitionAttribute"/>. | ||||
| 	/// </summary> | ||||
| @ -120,5 +120,4 @@ namespace Kyoo.Swagger | ||||
| 		options.AddOperationFilter(OperationFilter); | ||||
| 		options.PostProcess += x => x.AddLeftoversToOthersGroup(); | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -24,19 +24,19 @@ using Kyoo.Utils; | ||||
| using Microsoft.AspNetCore.Mvc; | ||||
| using Microsoft.AspNetCore.Mvc.ApplicationModels; | ||||
| 
 | ||||
| namespace Kyoo.Swagger | ||||
| namespace Kyoo.Swagger; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// A filter that change <see cref="ProducesResponseTypeAttribute"/>'s | ||||
| /// <see cref="ProducesResponseTypeAttribute.Type"/> that where set to <see cref="ActionResult{T}"/> to the | ||||
| /// return type of the method. | ||||
| /// </summary> | ||||
| /// <remarks> | ||||
| /// This is only useful when the return type of the method is a generics type and that can't be specified in the | ||||
| /// attribute directly (since attributes don't support generics). This should not be used otherwise. | ||||
| /// </remarks> | ||||
| public class GenericResponseProvider : IApplicationModelProvider | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// A filter that change <see cref="ProducesResponseTypeAttribute"/>'s | ||||
| 	/// <see cref="ProducesResponseTypeAttribute.Type"/> that where set to <see cref="ActionResult{T}"/> to the | ||||
| 	/// return type of the method. | ||||
| 	/// </summary> | ||||
| 	/// <remarks> | ||||
| 	/// This is only useful when the return type of the method is a generics type and that can't be specified in the | ||||
| 	/// attribute directly (since attributes don't support generics). This should not be used otherwise. | ||||
| 	/// </remarks> | ||||
| 	public class GenericResponseProvider : IApplicationModelProvider | ||||
| 	{ | ||||
| 	/// <inheritdoc /> | ||||
| 	public int Order => -1; | ||||
| 
 | ||||
| @ -65,5 +65,4 @@ namespace Kyoo.Swagger | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -20,13 +20,13 @@ using System.Collections.Generic; | ||||
| using Newtonsoft.Json; | ||||
| using NSwag; | ||||
| 
 | ||||
| namespace Kyoo.Swagger.Models | ||||
| namespace Kyoo.Swagger.Models; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// A class representing a group of tags in the <see cref="OpenApiDocument"/> | ||||
| /// </summary> | ||||
| public class TagGroups | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// A class representing a group of tags in the <see cref="OpenApiDocument"/> | ||||
| 	/// </summary> | ||||
| 	public class TagGroups | ||||
| 	{ | ||||
| 	/// <summary> | ||||
| 	/// The name of the tag group. | ||||
| 	/// </summary> | ||||
| @ -38,5 +38,4 @@ namespace Kyoo.Swagger.Models | ||||
| 	/// </summary> | ||||
| 	[JsonProperty(PropertyName = "tags")] | ||||
| 	public List<string> Tags { get; set; } | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -25,19 +25,18 @@ using NSwag; | ||||
| using NSwag.Generation.Processors; | ||||
| using NSwag.Generation.Processors.Contexts; | ||||
| 
 | ||||
| namespace Kyoo.Swagger | ||||
| namespace Kyoo.Swagger; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// An operation processor that adds permissions information from the <see cref="PermissionAttribute"/> and the | ||||
| /// <see cref="PartialPermissionAttribute"/>. | ||||
| /// </summary> | ||||
| public class OperationPermissionProcessor : IOperationProcessor | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// An operation processor that adds permissions information from the <see cref="PermissionAttribute"/> and the | ||||
| 	/// <see cref="PartialPermissionAttribute"/>. | ||||
| 	/// </summary> | ||||
| 	public class OperationPermissionProcessor : IOperationProcessor | ||||
| 	{ | ||||
| 	/// <inheritdoc /> | ||||
| 	public bool Process(OperationProcessorContext context) | ||||
| 	{ | ||||
| 			context.OperationDescription.Operation.Security ??= | ||||
| 				new List<OpenApiSecurityRequirement>(); | ||||
| 		context.OperationDescription.Operation.Security ??= new List<OpenApiSecurityRequirement>(); | ||||
| 		OpenApiSecurityRequirement perms = context | ||||
| 			.MethodInfo.GetCustomAttributes<UserOnlyAttribute>() | ||||
| 			.Aggregate( | ||||
| @ -100,5 +99,4 @@ namespace Kyoo.Swagger | ||||
| 			? perms.ToList() | ||||
| 			: new List<string>(); | ||||
| 	} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -29,13 +29,13 @@ using NSwag; | ||||
| using NSwag.Generation.AspNetCore; | ||||
| using static Kyoo.Abstractions.Models.Utils.Constants; | ||||
| 
 | ||||
| namespace Kyoo.Swagger | ||||
| namespace Kyoo.Swagger; | ||||
| 
 | ||||
| /// <summary> | ||||
| /// A module to enable a swagger interface and an OpenAPI endpoint to document Kyoo. | ||||
| /// </summary> | ||||
| public class SwaggerModule : IPlugin | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// A module to enable a swagger interface and an OpenAPI endpoint to document Kyoo. | ||||
| 	/// </summary> | ||||
| 	public class SwaggerModule : IPlugin | ||||
| 	{ | ||||
| 	/// <inheritdoc /> | ||||
| 	public string Name => "Swagger"; | ||||
| 
 | ||||
| @ -127,5 +127,4 @@ namespace Kyoo.Swagger | ||||
| 				SA.Before | ||||
| 			) | ||||
| 		}; | ||||
| 	} | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user