diff options
| author | Claus Vium <clausvium@gmail.com> | 2019-11-23 20:31:17 +0100 |
|---|---|---|
| committer | Claus Vium <clausvium@gmail.com> | 2019-11-23 20:31:17 +0100 |
| commit | c2cdbc909ba8371261bb88b5dd313262be755fa3 (patch) | |
| tree | c8bc9baa34765d06c4bb09bb5d9752c9de9a9978 | |
| parent | c9669a0d21f37fe06a8838c001a6f93505ba549b (diff) | |
Add style rules and fix it all
14 files changed, 181 insertions, 10 deletions
diff --git a/Jellyfin.Api/Auth/CustomAuthenticationHandler.cs b/Jellyfin.Api/Auth/CustomAuthenticationHandler.cs index bb6192b03..a753d6083 100644 --- a/Jellyfin.Api/Auth/CustomAuthenticationHandler.cs +++ b/Jellyfin.Api/Auth/CustomAuthenticationHandler.cs @@ -1,6 +1,7 @@ using System.Security.Claims; using System.Text.Encodings.Web; using System.Threading.Tasks; +using Jellyfin.Api.Enums; using MediaBrowser.Controller.Net; using Microsoft.AspNetCore.Authentication; using Microsoft.Extensions.Logging; @@ -8,10 +9,21 @@ using Microsoft.Extensions.Options; namespace Jellyfin.Api.Auth { + /// <summary> + /// Custom authentication handler wrapping the legacy authentication. + /// </summary> public class CustomAuthenticationHandler : AuthenticationHandler<AuthenticationSchemeOptions> { private readonly IAuthService _authService; + /// <summary> + /// Initializes a new instance of the <see cref="CustomAuthenticationHandler" /> class. + /// </summary> + /// <param name="authService">The jellyfin authentication service.</param> + /// <param name="options">Options monitor.</param> + /// <param name="logger">The logger.</param> + /// <param name="encoder">The url encoder.</param> + /// <param name="clock">The system clock.</param> public CustomAuthenticationHandler( IAuthService authService, IOptionsMonitor<AuthenticationSchemeOptions> options, @@ -22,6 +34,7 @@ namespace Jellyfin.Api.Auth _authService = authService; } + /// <inheritdoc /> protected override Task<AuthenticateResult> HandleAuthenticateAsync() { var authenticatedAttribute = new AuthenticatedAttribute(); @@ -36,7 +49,9 @@ namespace Jellyfin.Api.Auth var claims = new[] { new Claim(ClaimTypes.Name, user.Name), - new Claim(ClaimTypes.Role, user.Policy.IsAdministrator ? "Administrator" : "User"), + new Claim( + ClaimTypes.Role, + value: user.Policy.IsAdministrator ? UserRole.Administrator.ToString() : UserRole.User.ToString()) }; var identity = new ClaimsIdentity(claims, Scheme.Name); var principal = new ClaimsPrincipal(identity); diff --git a/Jellyfin.Api/Auth/FirstTimeSetupOrElevatedPolicy/FirstTimeSetupOrElevatedHandler.cs b/Jellyfin.Api/Auth/FirstTimeSetupOrElevatedPolicy/FirstTimeSetupOrElevatedHandler.cs index 73925cd61..f07e568de 100644 --- a/Jellyfin.Api/Auth/FirstTimeSetupOrElevatedPolicy/FirstTimeSetupOrElevatedHandler.cs +++ b/Jellyfin.Api/Auth/FirstTimeSetupOrElevatedPolicy/FirstTimeSetupOrElevatedHandler.cs @@ -1,27 +1,35 @@ using System.Threading.Tasks; +using Jellyfin.Api.Enums; using MediaBrowser.Common.Configuration; using Microsoft.AspNetCore.Authorization; namespace Jellyfin.Api.Auth.FirstTimeSetupOrElevatedPolicy { + /// <summary> + /// Authorization handler for requiring first time setup or elevated privileges. + /// </summary> public class FirstTimeSetupOrElevatedHandler : AuthorizationHandler<FirstTimeSetupOrElevatedRequirement> { private readonly IConfigurationManager _configurationManager; + /// <summary> + /// Initializes a new instance of the <see cref="FirstTimeSetupOrElevatedHandler" /> class. + /// </summary> + /// <param name="configurationManager">The jellyfin configuration manager.</param> public FirstTimeSetupOrElevatedHandler(IConfigurationManager configurationManager) { _configurationManager = configurationManager; } - protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, FirstTimeSetupOrElevatedRequirement firstTimeSetupOrElevatedRequirement) + /// <inheritdoc /> + protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, FirstTimeSetupOrElevatedRequirement firstTimeSetupOrElevatedRequirement) { if (!_configurationManager.CommonConfiguration.IsStartupWizardCompleted) { context.Succeed(firstTimeSetupOrElevatedRequirement); } - else if (context.User.IsInRole("Administrator")) + else if (context.User.IsInRole(UserRole.Administrator.ToString())) { - // TODO user role enum context.Succeed(firstTimeSetupOrElevatedRequirement); } else diff --git a/Jellyfin.Api/Auth/FirstTimeSetupOrElevatedPolicy/FirstTimeSetupOrElevatedRequirement.cs b/Jellyfin.Api/Auth/FirstTimeSetupOrElevatedPolicy/FirstTimeSetupOrElevatedRequirement.cs index 42436c870..a59015542 100644 --- a/Jellyfin.Api/Auth/FirstTimeSetupOrElevatedPolicy/FirstTimeSetupOrElevatedRequirement.cs +++ b/Jellyfin.Api/Auth/FirstTimeSetupOrElevatedPolicy/FirstTimeSetupOrElevatedRequirement.cs @@ -2,6 +2,9 @@ using Microsoft.AspNetCore.Authorization; namespace Jellyfin.Api.Auth.FirstTimeSetupOrElevatedPolicy { + /// <summary> + /// The authorization requirement, requiring first time setup or elevated privileges, for the authorization handler. + /// </summary> public class FirstTimeSetupOrElevatedRequirement : IAuthorizationRequirement { } diff --git a/Jellyfin.Api/Auth/RequiresElevationPolicy/RequiresElevationHandler.cs b/Jellyfin.Api/Auth/RequiresElevationPolicy/RequiresElevationHandler.cs index 694827458..8674f3e26 100644 --- a/Jellyfin.Api/Auth/RequiresElevationPolicy/RequiresElevationHandler.cs +++ b/Jellyfin.Api/Auth/RequiresElevationPolicy/RequiresElevationHandler.cs @@ -1,13 +1,18 @@ using System.Threading.Tasks; +using Jellyfin.Api.Enums; using Microsoft.AspNetCore.Authorization; namespace Jellyfin.Api.Auth.RequiresElevationPolicy { + /// <summary> + /// Authorization handler for requiring elevated privileges. + /// </summary> public class RequiresElevationHandler : AuthorizationHandler<RequiresElevationRequirement> { + /// <inheritdoc /> protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, RequiresElevationRequirement requirement) { - if (context.User.IsInRole("Administrator")) + if (context.User.IsInRole(UserRole.Administrator.ToString())) { context.Succeed(requirement); } diff --git a/Jellyfin.Api/Auth/RequiresElevationPolicy/RequiresElevationRequirement.cs b/Jellyfin.Api/Auth/RequiresElevationPolicy/RequiresElevationRequirement.cs index dd51cd3c2..cfff1cc0c 100644 --- a/Jellyfin.Api/Auth/RequiresElevationPolicy/RequiresElevationRequirement.cs +++ b/Jellyfin.Api/Auth/RequiresElevationPolicy/RequiresElevationRequirement.cs @@ -2,8 +2,10 @@ using Microsoft.AspNetCore.Authorization; namespace Jellyfin.Api.Auth.RequiresElevationPolicy { + /// <summary> + /// The authorization requirement for requiring elevated privileges in the authorization handler. + /// </summary> public class RequiresElevationRequirement : IAuthorizationRequirement { - } } diff --git a/Jellyfin.Api/BaseJellyfinApiController.cs b/Jellyfin.Api/BaseJellyfinApiController.cs index 796a8039a..1f4508e6c 100644 --- a/Jellyfin.Api/BaseJellyfinApiController.cs +++ b/Jellyfin.Api/BaseJellyfinApiController.cs @@ -2,10 +2,12 @@ using Microsoft.AspNetCore.Mvc; namespace Jellyfin.Api { + /// <summary> + /// Base api controller for the API setting a default route. + /// </summary> [ApiController] [Route("[controller]")] public class BaseJellyfinApiController : ControllerBase { - } } diff --git a/Jellyfin.Api/Controllers/StartupController.cs b/Jellyfin.Api/Controllers/StartupController.cs index 271745e05..0e7d17a27 100644 --- a/Jellyfin.Api/Controllers/StartupController.cs +++ b/Jellyfin.Api/Controllers/StartupController.cs @@ -8,18 +8,29 @@ using Microsoft.AspNetCore.Mvc; namespace Jellyfin.Api.Controllers { + /// <summary> + /// The startup wizard controller. + /// </summary> [Authorize(Policy = "FirstTimeSetupOrElevated")] public class StartupController : BaseJellyfinApiController { private readonly IServerConfigurationManager _config; private readonly IUserManager _userManager; + /// <summary> + /// Initializes a new instance of the <see cref="StartupController" /> class. + /// </summary> + /// <param name="config">The server configuration manager.</param> + /// <param name="userManager">The user manager.</param> public StartupController(IServerConfigurationManager config, IUserManager userManager) { _config = config; _userManager = userManager; } + /// <summary> + /// Api endpoint for completing the startup wizard. + /// </summary> [HttpPost("Complete")] public void CompleteWizard() { @@ -28,6 +39,10 @@ namespace Jellyfin.Api.Controllers _config.SaveConfiguration(); } + /// <summary> + /// Endpoint for getting the initial startup wizard configuration. + /// </summary> + /// <returns>The initial startup wizard configuration.</returns> [HttpGet("Configuration")] public StartupConfigurationDto GetStartupConfiguration() { @@ -41,6 +56,12 @@ namespace Jellyfin.Api.Controllers return result; } + /// <summary> + /// Endpoint for updating the initial startup wizard configuration. + /// </summary> + /// <param name="uiCulture">The UI language culture.</param> + /// <param name="metadataCountryCode">The metadata country code.</param> + /// <param name="preferredMetadataLanguage">The preferred language for metadata.</param> [HttpPost("Configuration")] public void UpdateInitialConfiguration( [FromForm] string uiCulture, @@ -53,6 +74,11 @@ namespace Jellyfin.Api.Controllers _config.SaveConfiguration(); } + /// <summary> + /// Endpoint for (dis)allowing remote access and UPnP. + /// </summary> + /// <param name="enableRemoteAccess">Enable remote access.</param> + /// <param name="enableAutomaticPortMapping">Enable UPnP.</param> [HttpPost("RemoteAccess")] public void SetRemoteAccess([FromForm] bool enableRemoteAccess, [FromForm] bool enableAutomaticPortMapping) { @@ -61,8 +87,12 @@ namespace Jellyfin.Api.Controllers _config.SaveConfiguration(); } + /// <summary> + /// Endpoint for returning the first user. + /// </summary> + /// <returns>The first user.</returns> [HttpGet("User")] - public StartupUserDto GetUser() + public StartupUserDto GetFirstUser() { var user = _userManager.Users.First(); @@ -73,6 +103,11 @@ namespace Jellyfin.Api.Controllers }; } + /// <summary> + /// Endpoint for updating the user name and password. + /// </summary> + /// <param name="startupUserDto">The DTO containing username and password.</param> + /// <returns>The async task.</returns> [HttpPost("User")] public async Task UpdateUser([FromForm] StartupUserDto startupUserDto) { diff --git a/Jellyfin.Api/Enums/UserRole.cs b/Jellyfin.Api/Enums/UserRole.cs new file mode 100644 index 000000000..05826d9f4 --- /dev/null +++ b/Jellyfin.Api/Enums/UserRole.cs @@ -0,0 +1,23 @@ +namespace Jellyfin.Api.Enums +{ + /// <summary> + /// Enum for user roles used in the authentication and authorization for the API. + /// </summary> + public enum UserRole + { + /// <summary> + /// Guest user. + /// </summary> + Guest = 0, + + /// <summary> + /// Regular user with no special privileges. + /// </summary> + User = 1, + + /// <summary> + /// Administrator user with elevated privileges. + /// </summary> + Administrator = 2 + } +} diff --git a/Jellyfin.Api/Extensions/ApiApplicationBuilderExtensions.cs b/Jellyfin.Api/Extensions/ApiApplicationBuilderExtensions.cs index 18442bf27..f70466ebe 100644 --- a/Jellyfin.Api/Extensions/ApiApplicationBuilderExtensions.cs +++ b/Jellyfin.Api/Extensions/ApiApplicationBuilderExtensions.cs @@ -2,8 +2,16 @@ using Microsoft.AspNetCore.Builder; namespace Jellyfin.Api.Extensions { + /// <summary> + /// Extensions for adding API specific functionality to the application pipeline. + /// </summary> public static class ApiApplicationBuilderExtensions { + /// <summary> + /// Adds swagger and swagger UI to the application pipeline. + /// </summary> + /// <param name="applicationBuilder">The application builder.</param> + /// <returns>The updated application builder.</returns> public static IApplicationBuilder UseJellyfinApiSwagger(this IApplicationBuilder applicationBuilder) { applicationBuilder.UseSwagger(); diff --git a/Jellyfin.Api/Extensions/ApiServiceCollectionExtensions.cs b/Jellyfin.Api/Extensions/ApiServiceCollectionExtensions.cs index 1c682f8e4..38f5f6d39 100644 --- a/Jellyfin.Api/Extensions/ApiServiceCollectionExtensions.cs +++ b/Jellyfin.Api/Extensions/ApiServiceCollectionExtensions.cs @@ -1,4 +1,3 @@ -using Emby.Server.Implementations; using Jellyfin.Api.Auth; using Jellyfin.Api.Auth.FirstTimeSetupOrElevatedPolicy; using Jellyfin.Api.Auth.RequiresElevationPolicy; @@ -12,8 +11,16 @@ using Microsoft.OpenApi.Models; namespace Jellyfin.Api.Extensions { + /// <summary> + /// API specific extensions for the service collection. + /// </summary> public static class ApiServiceCollectionExtensions { + /// <summary> + /// Adds jellyfin API authorization policies to the DI container. + /// </summary> + /// <param name="serviceCollection">The service collection.</param> + /// <returns>The updated service collection.</returns> public static IServiceCollection AddJellyfinApiAuthorization(this IServiceCollection serviceCollection) { serviceCollection.AddSingleton<IAuthorizationHandler, FirstTimeSetupOrElevatedHandler>(); @@ -37,12 +44,23 @@ namespace Jellyfin.Api.Extensions }); } + /// <summary> + /// Adds custom legacy authentication to the service collection. + /// </summary> + /// <param name="serviceCollection">The service collection.</param> + /// <returns>The updated service collection.</returns> public static AuthenticationBuilder AddCustomAuthentication(this IServiceCollection serviceCollection) { return serviceCollection.AddAuthentication("CustomAuthentication") .AddScheme<AuthenticationSchemeOptions, CustomAuthenticationHandler>("CustomAuthentication", null); } + /// <summary> + /// Extension method for adding the jellyfin API to the service collection. + /// </summary> + /// <param name="serviceCollection">The service collection.</param> + /// <param name="baseUrl">The base url for the API.</param> + /// <returns>The MVC builder.</returns> public static IMvcBuilder AddJellyfinApi(this IServiceCollection serviceCollection, string baseUrl) { return serviceCollection.AddMvc(opts => @@ -55,12 +73,18 @@ namespace Jellyfin.Api.Extensions opts.UseGeneralRoutePrefix(baseUrl); }) .SetCompatibilityVersion(CompatibilityVersion.Version_2_2) + // Clear app parts to avoid other assemblies being picked up .ConfigureApplicationPartManager(a => a.ApplicationParts.Clear()) .AddApplicationPart(typeof(StartupController).Assembly) .AddControllersAsServices(); } + /// <summary> + /// Adds Swagger to the service collection. + /// </summary> + /// <param name="serviceCollection">The service collection.</param> + /// <returns>The updated service collection.</returns> public static IServiceCollection AddJellyfinApiSwagger(this IServiceCollection serviceCollection) { return serviceCollection.AddSwaggerGen(c => diff --git a/Jellyfin.Api/Jellyfin.Api.csproj b/Jellyfin.Api/Jellyfin.Api.csproj index d77861cc4..1cc23c07b 100644 --- a/Jellyfin.Api/Jellyfin.Api.csproj +++ b/Jellyfin.Api/Jellyfin.Api.csproj @@ -2,6 +2,8 @@ <PropertyGroup> <TargetFramework>netstandard2.1</TargetFramework> + <GenerateDocumentationFile>true</GenerateDocumentationFile> + <TreatWarningsAsErrors>true</TreatWarningsAsErrors> </PropertyGroup> <ItemGroup> @@ -15,4 +17,16 @@ <ProjectReference Include="..\MediaBrowser.Controller\MediaBrowser.Controller.csproj" /> </ItemGroup> + <!-- Code analysers--> + <ItemGroup Condition=" '$(Configuration)' == 'Debug' "> + <PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.4" /> + <PackageReference Include="SerilogAnalyzer" Version="0.15.0" /> + <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" /> + <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" /> + </ItemGroup> + + <PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> + <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet> + </PropertyGroup> + </Project> diff --git a/Jellyfin.Api/Models/Startup/StartupConfigurationDto.cs b/Jellyfin.Api/Models/Startup/StartupConfigurationDto.cs index 769d2e1bb..dac15e412 100644 --- a/Jellyfin.Api/Models/Startup/StartupConfigurationDto.cs +++ b/Jellyfin.Api/Models/Startup/StartupConfigurationDto.cs @@ -1,9 +1,23 @@ namespace Jellyfin.Api.Models.Startup { + /// <summary> + /// The startup configuration DTO. + /// </summary> public class StartupConfigurationDto { + /// <summary> + /// Gets or sets UI language culture. + /// </summary> public string UICulture { get; set; } + + /// <summary> + /// Gets or sets the metadata country code. + /// </summary> public string MetadataCountryCode { get; set; } + + /// <summary> + /// Gets or sets the preferred language for the metadata. + /// </summary> public string PreferredMetadataLanguage { get; set; } } } diff --git a/Jellyfin.Api/Models/Startup/StartupUserDto.cs b/Jellyfin.Api/Models/Startup/StartupUserDto.cs index c7c2e8cb0..7e890d76a 100644 --- a/Jellyfin.Api/Models/Startup/StartupUserDto.cs +++ b/Jellyfin.Api/Models/Startup/StartupUserDto.cs @@ -1,8 +1,18 @@ namespace Jellyfin.Api.Models.Startup { + /// <summary> + /// The startup user DTO. + /// </summary> public class StartupUserDto { + /// <summary> + /// Gets or sets the username. + /// </summary> public string Name { get; set; } + + /// <summary> + /// Gets or sets the user's password. + /// </summary> public string Password { get; set; } } } diff --git a/Jellyfin.Api/MvcRoutePrefix.cs b/Jellyfin.Api/MvcRoutePrefix.cs index 974a2a885..e00973094 100644 --- a/Jellyfin.Api/MvcRoutePrefix.cs +++ b/Jellyfin.Api/MvcRoutePrefix.cs @@ -3,10 +3,18 @@ using System.Linq; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.ApplicationModels; -namespace Emby.Server.Implementations +namespace Jellyfin.Api { + /// <summary> + /// Route prefixing for ASP.NET MVC. + /// </summary> public static class MvcRoutePrefix { + /// <summary> + /// Adds route prefixes to the MVC conventions. + /// </summary> + /// <param name="opts">The MVC options.</param> + /// <param name="prefixes">The list of prefixes.</param> public static void UseGeneralRoutePrefix(this MvcOptions opts, params string[] prefixes) { opts.Conventions.Insert(0, new RoutePrefixConvention(prefixes)); |
