diff --git a/Jellyfin.Api/Auth/CustomAuthenticationHandler.cs b/Jellyfin.Api/Auth/CustomAuthenticationHandler.cs
index bb6192b03d..a753d60838 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
{
+ ///
+ /// Custom authentication handler wrapping the legacy authentication.
+ ///
public class CustomAuthenticationHandler : AuthenticationHandler
{
private readonly IAuthService _authService;
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The jellyfin authentication service.
+ /// Options monitor.
+ /// The logger.
+ /// The url encoder.
+ /// The system clock.
public CustomAuthenticationHandler(
IAuthService authService,
IOptionsMonitor options,
@@ -22,6 +34,7 @@ namespace Jellyfin.Api.Auth
_authService = authService;
}
+ ///
protected override Task 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 73925cd616..f07e568dea 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
{
+ ///
+ /// Authorization handler for requiring first time setup or elevated privileges.
+ ///
public class FirstTimeSetupOrElevatedHandler : AuthorizationHandler
{
private readonly IConfigurationManager _configurationManager;
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The jellyfin configuration manager.
public FirstTimeSetupOrElevatedHandler(IConfigurationManager configurationManager)
{
_configurationManager = configurationManager;
}
- protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, FirstTimeSetupOrElevatedRequirement firstTimeSetupOrElevatedRequirement)
+ ///
+ 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 42436c870d..a590155420 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
{
+ ///
+ /// The authorization requirement, requiring first time setup or elevated privileges, for the authorization handler.
+ ///
public class FirstTimeSetupOrElevatedRequirement : IAuthorizationRequirement
{
}
diff --git a/Jellyfin.Api/Auth/RequiresElevationPolicy/RequiresElevationHandler.cs b/Jellyfin.Api/Auth/RequiresElevationPolicy/RequiresElevationHandler.cs
index 6948274582..8674f3e262 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
{
+ ///
+ /// Authorization handler for requiring elevated privileges.
+ ///
public class RequiresElevationHandler : AuthorizationHandler
{
+ ///
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 dd51cd3c20..cfff1cc0c5 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
{
+ ///
+ /// The authorization requirement for requiring elevated privileges in the authorization handler.
+ ///
public class RequiresElevationRequirement : IAuthorizationRequirement
{
-
}
}
diff --git a/Jellyfin.Api/BaseJellyfinApiController.cs b/Jellyfin.Api/BaseJellyfinApiController.cs
index 796a8039af..1f4508e6cb 100644
--- a/Jellyfin.Api/BaseJellyfinApiController.cs
+++ b/Jellyfin.Api/BaseJellyfinApiController.cs
@@ -2,10 +2,12 @@ using Microsoft.AspNetCore.Mvc;
namespace Jellyfin.Api
{
+ ///
+ /// Base api controller for the API setting a default route.
+ ///
[ApiController]
[Route("[controller]")]
public class BaseJellyfinApiController : ControllerBase
{
-
}
}
diff --git a/Jellyfin.Api/Controllers/StartupController.cs b/Jellyfin.Api/Controllers/StartupController.cs
index 271745e057..0e7d17a27f 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
{
+ ///
+ /// The startup wizard controller.
+ ///
[Authorize(Policy = "FirstTimeSetupOrElevated")]
public class StartupController : BaseJellyfinApiController
{
private readonly IServerConfigurationManager _config;
private readonly IUserManager _userManager;
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The server configuration manager.
+ /// The user manager.
public StartupController(IServerConfigurationManager config, IUserManager userManager)
{
_config = config;
_userManager = userManager;
}
+ ///
+ /// Api endpoint for completing the startup wizard.
+ ///
[HttpPost("Complete")]
public void CompleteWizard()
{
@@ -28,6 +39,10 @@ namespace Jellyfin.Api.Controllers
_config.SaveConfiguration();
}
+ ///
+ /// Endpoint for getting the initial startup wizard configuration.
+ ///
+ /// The initial startup wizard configuration.
[HttpGet("Configuration")]
public StartupConfigurationDto GetStartupConfiguration()
{
@@ -41,6 +56,12 @@ namespace Jellyfin.Api.Controllers
return result;
}
+ ///
+ /// Endpoint for updating the initial startup wizard configuration.
+ ///
+ /// The UI language culture.
+ /// The metadata country code.
+ /// The preferred language for metadata.
[HttpPost("Configuration")]
public void UpdateInitialConfiguration(
[FromForm] string uiCulture,
@@ -53,6 +74,11 @@ namespace Jellyfin.Api.Controllers
_config.SaveConfiguration();
}
+ ///
+ /// Endpoint for (dis)allowing remote access and UPnP.
+ ///
+ /// Enable remote access.
+ /// Enable UPnP.
[HttpPost("RemoteAccess")]
public void SetRemoteAccess([FromForm] bool enableRemoteAccess, [FromForm] bool enableAutomaticPortMapping)
{
@@ -61,8 +87,12 @@ namespace Jellyfin.Api.Controllers
_config.SaveConfiguration();
}
+ ///
+ /// Endpoint for returning the first user.
+ ///
+ /// The first user.
[HttpGet("User")]
- public StartupUserDto GetUser()
+ public StartupUserDto GetFirstUser()
{
var user = _userManager.Users.First();
@@ -73,6 +103,11 @@ namespace Jellyfin.Api.Controllers
};
}
+ ///
+ /// Endpoint for updating the user name and password.
+ ///
+ /// The DTO containing username and password.
+ /// The async task.
[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 0000000000..05826d9f41
--- /dev/null
+++ b/Jellyfin.Api/Enums/UserRole.cs
@@ -0,0 +1,23 @@
+namespace Jellyfin.Api.Enums
+{
+ ///
+ /// Enum for user roles used in the authentication and authorization for the API.
+ ///
+ public enum UserRole
+ {
+ ///
+ /// Guest user.
+ ///
+ Guest = 0,
+
+ ///
+ /// Regular user with no special privileges.
+ ///
+ User = 1,
+
+ ///
+ /// Administrator user with elevated privileges.
+ ///
+ Administrator = 2
+ }
+}
diff --git a/Jellyfin.Api/Extensions/ApiApplicationBuilderExtensions.cs b/Jellyfin.Api/Extensions/ApiApplicationBuilderExtensions.cs
index 18442bf272..f70466ebec 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
{
+ ///
+ /// Extensions for adding API specific functionality to the application pipeline.
+ ///
public static class ApiApplicationBuilderExtensions
{
+ ///
+ /// Adds swagger and swagger UI to the application pipeline.
+ ///
+ /// The application builder.
+ /// The updated application builder.
public static IApplicationBuilder UseJellyfinApiSwagger(this IApplicationBuilder applicationBuilder)
{
applicationBuilder.UseSwagger();
diff --git a/Jellyfin.Api/Extensions/ApiServiceCollectionExtensions.cs b/Jellyfin.Api/Extensions/ApiServiceCollectionExtensions.cs
index 1c682f8e43..38f5f6d390 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
{
+ ///
+ /// API specific extensions for the service collection.
+ ///
public static class ApiServiceCollectionExtensions
{
+ ///
+ /// Adds jellyfin API authorization policies to the DI container.
+ ///
+ /// The service collection.
+ /// The updated service collection.
public static IServiceCollection AddJellyfinApiAuthorization(this IServiceCollection serviceCollection)
{
serviceCollection.AddSingleton();
@@ -37,12 +44,23 @@ namespace Jellyfin.Api.Extensions
});
}
+ ///
+ /// Adds custom legacy authentication to the service collection.
+ ///
+ /// The service collection.
+ /// The updated service collection.
public static AuthenticationBuilder AddCustomAuthentication(this IServiceCollection serviceCollection)
{
return serviceCollection.AddAuthentication("CustomAuthentication")
.AddScheme("CustomAuthentication", null);
}
+ ///
+ /// Extension method for adding the jellyfin API to the service collection.
+ ///
+ /// The service collection.
+ /// The base url for the API.
+ /// The MVC builder.
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();
}
+ ///
+ /// Adds Swagger to the service collection.
+ ///
+ /// The service collection.
+ /// The updated service collection.
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 d77861cc4a..1cc23c07b4 100644
--- a/Jellyfin.Api/Jellyfin.Api.csproj
+++ b/Jellyfin.Api/Jellyfin.Api.csproj
@@ -2,6 +2,8 @@
netstandard2.1
+ true
+ true
@@ -15,4 +17,16 @@
+
+
+
+
+
+
+
+
+
+ ../jellyfin.ruleset
+
+
diff --git a/Jellyfin.Api/Models/Startup/StartupConfigurationDto.cs b/Jellyfin.Api/Models/Startup/StartupConfigurationDto.cs
index 769d2e1bb6..dac15e412c 100644
--- a/Jellyfin.Api/Models/Startup/StartupConfigurationDto.cs
+++ b/Jellyfin.Api/Models/Startup/StartupConfigurationDto.cs
@@ -1,9 +1,23 @@
namespace Jellyfin.Api.Models.Startup
{
+ ///
+ /// The startup configuration DTO.
+ ///
public class StartupConfigurationDto
{
+ ///
+ /// Gets or sets UI language culture.
+ ///
public string UICulture { get; set; }
+
+ ///
+ /// Gets or sets the metadata country code.
+ ///
public string MetadataCountryCode { get; set; }
+
+ ///
+ /// Gets or sets the preferred language for the metadata.
+ ///
public string PreferredMetadataLanguage { get; set; }
}
}
diff --git a/Jellyfin.Api/Models/Startup/StartupUserDto.cs b/Jellyfin.Api/Models/Startup/StartupUserDto.cs
index c7c2e8cb04..7e890d76a0 100644
--- a/Jellyfin.Api/Models/Startup/StartupUserDto.cs
+++ b/Jellyfin.Api/Models/Startup/StartupUserDto.cs
@@ -1,8 +1,18 @@
namespace Jellyfin.Api.Models.Startup
{
+ ///
+ /// The startup user DTO.
+ ///
public class StartupUserDto
{
+ ///
+ /// Gets or sets the username.
+ ///
public string Name { get; set; }
+
+ ///
+ /// Gets or sets the user's password.
+ ///
public string Password { get; set; }
}
}
diff --git a/Jellyfin.Api/MvcRoutePrefix.cs b/Jellyfin.Api/MvcRoutePrefix.cs
index 974a2a8852..e009730947 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
{
+ ///
+ /// Route prefixing for ASP.NET MVC.
+ ///
public static class MvcRoutePrefix
{
+ ///
+ /// Adds route prefixes to the MVC conventions.
+ ///
+ /// The MVC options.
+ /// The list of prefixes.
public static void UseGeneralRoutePrefix(this MvcOptions opts, params string[] prefixes)
{
opts.Conventions.Insert(0, new RoutePrefixConvention(prefixes));