diff --git a/.github/workflows/integrate.yml b/.github/workflows/integrate.yml
index 82627e1..871f959 100644
--- a/.github/workflows/integrate.yml
+++ b/.github/workflows/integrate.yml
@@ -14,7 +14,7 @@ jobs:
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
- dotnet-version: '7.0.x'
+ dotnet-version: '8.0.x'
- name: Restore dependencies
run: dotnet restore -s ${MYGET_FEED} -s https://api.nuget.org/v3/index.json
env:
diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml
index 2a64596..6014382 100644
--- a/.github/workflows/pull_request.yml
+++ b/.github/workflows/pull_request.yml
@@ -26,7 +26,7 @@ jobs:
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
- dotnet-version: '7.0.x'
+ dotnet-version: '8.0.x'
- name: Restore dependencies
run: dotnet restore -s ${MYGET_FEED} -s https://api.nuget.org/v3/index.json
env:
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index a141787..b7260b0 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -14,7 +14,7 @@ jobs:
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
- dotnet-version: '7.0.x'
+ dotnet-version: '8.0.x'
- name: Extract version from tag
id: get_version
uses: battila7/get-version-action@v2
diff --git a/src/WopiHost.Abstractions/WopiAuthorizationRequirement.cs b/src/WopiHost.Abstractions/WopiAuthorizationRequirement.cs
index a0e88fa..7288318 100644
--- a/src/WopiHost.Abstractions/WopiAuthorizationRequirement.cs
+++ b/src/WopiHost.Abstractions/WopiAuthorizationRequirement.cs
@@ -5,19 +5,14 @@ namespace WopiHost.Abstractions;
///
/// Represents an authorization requirement for a given combination of resource, user, and action.
///
-public class WopiAuthorizationRequirement : IAuthorizationRequirement
+///
+/// Creates an instance of initialized with .
+///
+/// Permissions required for a given combination of resource, user, and action.
+public class WopiAuthorizationRequirement(Permission permission) : IAuthorizationRequirement
{
///
/// Gets a permissions required for a given combination of resource, user, and action.
///
- public Permission Permission { get; }
-
- ///
- /// Creates an instance of initialized with .
- ///
- /// Permissions required for a given combination of resource, user, and action.
- public WopiAuthorizationRequirement(Permission permission)
- {
- Permission = permission;
- }
+ public Permission Permission { get; } = permission;
}
diff --git a/src/WopiHost.Abstractions/WopiHost.Abstractions.csproj b/src/WopiHost.Abstractions/WopiHost.Abstractions.csproj
index 86c44a5..5d26204 100644
--- a/src/WopiHost.Abstractions/WopiHost.Abstractions.csproj
+++ b/src/WopiHost.Abstractions/WopiHost.Abstractions.csproj
@@ -3,7 +3,7 @@
WopiHost.Abstractions Class Library
Petr Svihlik
- net7.0
+ net8.0
WopiHost.Abstractions
WopiHost.Abstractions
LICENSE.txt
@@ -33,13 +33,13 @@
-
+
-
+
-
+
diff --git a/src/WopiHost.Cobalt/CobaltHostLockingStore.cs b/src/WopiHost.Cobalt/CobaltHostLockingStore.cs
index 2148029..2db9121 100644
--- a/src/WopiHost.Cobalt/CobaltHostLockingStore.cs
+++ b/src/WopiHost.Cobalt/CobaltHostLockingStore.cs
@@ -3,14 +3,9 @@
namespace WopiHost.Cobalt;
-public class CobaltHostLockingStore : HostLockingStore
+public class CobaltHostLockingStore(ClaimsPrincipal principal) : HostLockingStore
{
- private readonly ClaimsPrincipal _principal;
-
- public CobaltHostLockingStore(ClaimsPrincipal principal)
- {
- _principal = principal;
- }
+ private readonly ClaimsPrincipal _principal = principal;
public override WhoAmIRequest.OutputType HandleWhoAmI(WhoAmIRequest.InputType input)
{
@@ -180,10 +175,7 @@ public override GetCoauthoringStatusRequest.OutputType HandleGetCoauthoringStatu
return result;
}
- public override Dictionary QueryEditorsTable()
- {
- return new Dictionary();
- }
+ public override Dictionary QueryEditorsTable() => new Dictionary();
public override JoinEditingSessionRequest.OutputType HandleJoinEditingSession(JoinEditingSessionRequest.InputType input)
{
@@ -220,10 +212,7 @@ public override RemoveEditorMetadataRequest.OutputType HandleRemoveEditorMetadat
return result;
}
- public override ulong GetEditorsTableWaterline()
- {
- return 0;
- }
+ public override ulong GetEditorsTableWaterline() => 0;
public override AmIAloneRequest.OutputType HandleAmIAlone(AmIAloneRequest.InputType input)
{
diff --git a/src/WopiHost.Cobalt/WopiHost.Cobalt.csproj b/src/WopiHost.Cobalt/WopiHost.Cobalt.csproj
index 0606ff4..15f515c 100644
--- a/src/WopiHost.Cobalt/WopiHost.Cobalt.csproj
+++ b/src/WopiHost.Cobalt/WopiHost.Cobalt.csproj
@@ -3,7 +3,7 @@
WopiHost.Cobalt Class Library
Petr Svihlik
- net7.0
+ net8.0
WopiHost.Cobalt
WopiHost.Cobalt
LICENSE.txt
@@ -30,7 +30,7 @@
-
+
diff --git a/src/WopiHost.Core/Controllers/ContainersController.cs b/src/WopiHost.Core/Controllers/ContainersController.cs
index 7d0da8e..2b43fb7 100644
--- a/src/WopiHost.Core/Controllers/ContainersController.cs
+++ b/src/WopiHost.Core/Controllers/ContainersController.cs
@@ -10,18 +10,15 @@ namespace WopiHost.Core.Controllers;
///
/// Implementation of WOPI server protocol https://msdn.microsoft.com/en-us/library/hh659001.aspx
///
+///
+/// Creates an instance of .
+///
+/// Storage provider instance for retrieving files and folders.
+/// Security handler instance for performing security-related operations.
+/// WOPI Host configuration
[Route("wopi/[controller]")]
-public class ContainersController : WopiControllerBase
+public class ContainersController(IOptionsSnapshot wopiHostOptions, IWopiStorageProvider storageProvider, IWopiSecurityHandler securityHandler) : WopiControllerBase(storageProvider, securityHandler, wopiHostOptions)
{
- ///
- /// Creates an instance of .
- ///
- /// Storage provider instance for retrieving files and folders.
- /// Security handler instance for performing security-related operations.
- /// WOPI Host configuration
- public ContainersController(IOptionsSnapshot wopiHostOptions, IWopiStorageProvider storageProvider, IWopiSecurityHandler securityHandler) : base(storageProvider, securityHandler, wopiHostOptions)
- {
- }
///
/// Returns the metadata about a container specified by an identifier.
diff --git a/src/WopiHost.Core/Controllers/EcosystemController.cs b/src/WopiHost.Core/Controllers/EcosystemController.cs
index 9caa7f7..79f8875 100644
--- a/src/WopiHost.Core/Controllers/EcosystemController.cs
+++ b/src/WopiHost.Core/Controllers/EcosystemController.cs
@@ -9,27 +9,23 @@ namespace WopiHost.Core.Controllers;
///
/// Implementation of WOPI server protocol http://wopi.readthedocs.io/projects/wopirest/en/latest/ecosystem/CheckEcosystem.html
///
+///
+/// Creates an instance of .
+///
+/// Storage provider instance for retrieving files and folders.
+/// Security handler instance for performing security-related operations.
+/// WOPI Host configuration
[Route("wopi/[controller]")]
- public class EcosystemController : WopiControllerBase
+ public class EcosystemController(IWopiStorageProvider storageProvider, IWopiSecurityHandler securityHandler, IOptionsSnapshot wopiHostOptions) : WopiControllerBase(storageProvider, securityHandler, wopiHostOptions)
{
- ///
- /// Creates an instance of .
- ///
- /// Storage provider instance for retrieving files and folders.
- /// Security handler instance for performing security-related operations.
- /// WOPI Host configuration
- public EcosystemController(IWopiStorageProvider storageProvider, IWopiSecurityHandler securityHandler, IOptionsSnapshot wopiHostOptions)
- : base(storageProvider, securityHandler, wopiHostOptions)
- {
- }
- ///
- /// The GetRootContainer operation returns the root container. A WOPI client can use this operation to get a reference to the root container, from which the client can call EnumerateChildren (containers) to navigate a container hierarchy.
- /// Specification: http://wopi.readthedocs.io/projects/wopirest/en/latest/ecosystem/GetRootContainer.html
- /// Example URL: GET /wopi/ecosystem/root_container_pointer
- ///
- ///
- [HttpGet("root_container_pointer")]
+ ///
+ /// The GetRootContainer operation returns the root container. A WOPI client can use this operation to get a reference to the root container, from which the client can call EnumerateChildren (containers) to navigate a container hierarchy.
+ /// Specification: http://wopi.readthedocs.io/projects/wopirest/en/latest/ecosystem/GetRootContainer.html
+ /// Example URL: GET /wopi/ecosystem/root_container_pointer
+ ///
+ ///
+ [HttpGet("root_container_pointer")]
[Produces(MediaTypeNames.Application.Json)]
public RootContainerInfo GetRootContainer() //TODO: fix the path
{
diff --git a/src/WopiHost.Core/Controllers/FilesController.cs b/src/WopiHost.Core/Controllers/FilesController.cs
index 97eb33b..31425c2 100644
--- a/src/WopiHost.Core/Controllers/FilesController.cs
+++ b/src/WopiHost.Core/Controllers/FilesController.cs
@@ -155,13 +155,9 @@ public async Task PutFile(string id)
///
/// File identifier.
/// Returns if succeeded.
- [HttpPost("{id}"), WopiOverrideHeader(new[] { "PUT_RELATIVE" })]
+ [HttpPost("{id}"), WopiOverrideHeader(["PUT_RELATIVE"])]
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
- public async Task PutRelativeFile(string id)
-#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
- {
- throw new NotImplementedException($"{nameof(PutRelativeFile)} is not implemented yet.");
- }
+ public async Task PutRelativeFile(string id) => throw new NotImplementedException($"{nameof(PutRelativeFile)} is not implemented yet.");
///
/// Changes the contents of the file in accordance with [MS-FSSHTTP].
@@ -170,7 +166,7 @@ public async Task PutRelativeFile(string id)
/// Example URL path: /wopi/files/(file_id)
///
/// File identifier.
- [HttpPost("{id}"), WopiOverrideHeader(new[] { "COBALT" })]
+ [HttpPost("{id}"), WopiOverrideHeader(["COBALT"])]
public async Task ProcessCobalt(string id)
{
// Check permissions
@@ -189,8 +185,8 @@ public async Task ProcessCobalt(string id)
}
var responseAction = CobaltProcessor.ProcessCobalt(file, User, await HttpContext.Request.Body.ReadBytesAsync());
- HttpContext.Response.Headers.Add(WopiHeaders.CORRELATION_ID, HttpContext.Request.Headers[WopiHeaders.CORRELATION_ID]);
- HttpContext.Response.Headers.Add("request-id", HttpContext.Request.Headers[WopiHeaders.CORRELATION_ID]);
+ HttpContext.Response.Headers.Append(WopiHeaders.CORRELATION_ID, HttpContext.Request.Headers[WopiHeaders.CORRELATION_ID]);
+ HttpContext.Response.Headers.Append("request-id", HttpContext.Request.Headers[WopiHeaders.CORRELATION_ID]);
return new Results.FileResult(responseAction, "application/octet-stream");
}
@@ -202,7 +198,7 @@ public async Task ProcessCobalt(string id)
/// Example URL path: /wopi/files/(file_id)
///
/// File identifier.
- [HttpPost("{id}"), WopiOverrideHeader(new[] { "LOCK", "UNLOCK", "REFRESH_LOCK", "GET_LOCK" })]
+ [HttpPost("{id}"), WopiOverrideHeader(["LOCK", "UNLOCK", "REFRESH_LOCK", "GET_LOCK"])]
public IActionResult ProcessLock(string id)
{
string oldLock = Request.Headers[WopiHeaders.OLD_LOCK];
diff --git a/src/WopiHost.Core/Controllers/WopiBootstrapperController.cs b/src/WopiHost.Core/Controllers/WopiBootstrapperController.cs
index 6d842d6..2d3eaa4 100644
--- a/src/WopiHost.Core/Controllers/WopiBootstrapperController.cs
+++ b/src/WopiHost.Core/Controllers/WopiBootstrapperController.cs
@@ -1,4 +1,5 @@
using System.Net.Mime;
+using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.Primitives;
@@ -11,19 +12,15 @@ namespace WopiHost.Core.Controllers;
///
/// Controller containing the bootstrap operation.
///
+///
+/// Creates an instance of .
+///
+/// Storage provider instance for retrieving files and folders.
+/// Security handler instance for performing security-related operations.
+/// WOPI Host configuration
[Route("wopibootstrapper")]
-public class WopiBootstrapperController : WopiControllerBase
+public class WopiBootstrapperController(IWopiStorageProvider storageProvider, IWopiSecurityHandler securityHandler, IOptionsSnapshot wopiHostOptions) : WopiControllerBase(storageProvider, securityHandler, wopiHostOptions)
{
- ///
- /// Creates an instance of .
- ///
- /// Storage provider instance for retrieving files and folders.
- /// Security handler instance for performing security-related operations.
- /// WOPI Host configuration
- public WopiBootstrapperController(IWopiStorageProvider storageProvider, IWopiSecurityHandler securityHandler, IOptionsSnapshot wopiHostOptions)
- : base(storageProvider, securityHandler, wopiHostOptions)
- {
- }
///
/// Gets information about the root container.
@@ -33,7 +30,7 @@ public WopiBootstrapperController(IWopiStorageProvider storageProvider, IWopiSec
[Produces(MediaTypeNames.Application.Json)]
public IActionResult GetRootContainer() //TODO: fix the path
{
- var authorizationHeader = HttpContext.Request.Headers["Authorization"];
+ var authorizationHeader = HttpContext.Request.Headers.Authorization;
var ecosystemOperation = HttpContext.Request.Headers[WopiHeaders.ECOSYSTEM_OPERATION];
var wopiSrc = HttpContext.Request.Headers[WopiHeaders.WOPI_SRC].FirstOrDefault();
@@ -90,27 +87,25 @@ public IActionResult GetRootContainer() //TODO: fix the path
var tokenIssuanceUri = "https://contoso.com/api/oauth2/token";
var providerId = "tp_contoso";
var urlSchemes = Uri.EscapeDataString("{\"iOS\" : [\"contoso\",\"contoso - EMM\"], \"Android\" : [\"contoso\",\"contoso - EMM\"], \"UWP\": [\"contoso\",\"contoso - EMM\"]}");
- Response.Headers.Add("WWW-Authenticate", $"Bearer authorization_uri=\"{authorizationUri}\",tokenIssuance_uri=\"{tokenIssuanceUri}\",providerId=\"{providerId}\", UrlSchemes=\"{urlSchemes}\"");
+ Response.Headers.Append("WWW-Authenticate", $"Bearer authorization_uri=\"{authorizationUri}\",tokenIssuance_uri=\"{tokenIssuanceUri}\",providerId=\"{providerId}\", UrlSchemes=\"{urlSchemes}\"");
return new UnauthorizedResult();
}
}
private string GetIdFromUrl(string resourceUrl)
{
- var resourceId = resourceUrl[(resourceUrl.LastIndexOf("/", StringComparison.Ordinal) + 1)..];
- var queryIndex = resourceId.IndexOf("?", StringComparison.Ordinal);
+ var resourceId = resourceUrl[(resourceUrl.LastIndexOf('/') + 1)..];
+ var queryIndex = resourceId.IndexOf('?');
if (queryIndex > -1)
{
- resourceId = resourceId.Substring(0, queryIndex);
+ resourceId = resourceId[..queryIndex];
}
resourceId = Uri.UnescapeDataString(resourceId);
return resourceId;
}
- private bool ValidateAuthorizationHeader(StringValues authorizationHeader)
- {
+ private bool ValidateAuthorizationHeader(StringValues authorizationHeader) =>
//TODO: implement header validation http://wopi.readthedocs.io/projects/wopirest/en/latest/bootstrapper/GetRootContainer.html#sample-response
// http://stackoverflow.com/questions/31948426/oauth-bearer-token-authentication-is-not-passing-signature-validation
- return true;
- }
+ true;
}
diff --git a/src/WopiHost.Core/Controllers/WopiControllerBase.cs b/src/WopiHost.Core/Controllers/WopiControllerBase.cs
index 0ec8715..9a0f703 100644
--- a/src/WopiHost.Core/Controllers/WopiControllerBase.cs
+++ b/src/WopiHost.Core/Controllers/WopiControllerBase.cs
@@ -10,22 +10,28 @@ namespace WopiHost.Core.Controllers;
///
/// Extends the with some basic WOPI-related functionality.
///
-public abstract class WopiControllerBase : ControllerBase
+///
+/// Default constructor.
+///
+/// Object facilitating access to the storage of WOPI files.
+/// Object facilitating security-related actions.
+/// WOPI Host configuration object
+public abstract class WopiControllerBase(IWopiStorageProvider storageProvider, IWopiSecurityHandler securityHandler, IOptionsSnapshot wopiHostOptions) : ControllerBase
{
///
/// Provides access to the storage.
///
- protected IWopiStorageProvider StorageProvider { get; }
+ protected IWopiStorageProvider StorageProvider { get; } = storageProvider;
///
/// Provides security-related actions.
///
- protected IWopiSecurityHandler SecurityHandler { get; }
+ protected IWopiSecurityHandler SecurityHandler { get; } = securityHandler;
///
/// WOPI Host configuration object.
///
- protected IOptionsSnapshot WopiHostOptions { get; }
+ protected IOptionsSnapshot WopiHostOptions { get; } = wopiHostOptions;
///
/// WOPI Host base URL
@@ -45,19 +51,6 @@ protected string AccessToken
}
}
- ///
- /// Default constructor.
- ///
- /// Object facilitating access to the storage of WOPI files.
- /// Object facilitating security-related actions.
- /// WOPI Host configuration object
- protected WopiControllerBase(IWopiStorageProvider storageProvider, IWopiSecurityHandler securityHandler, IOptionsSnapshot wopiHostOptions)
- {
- StorageProvider = storageProvider;
- SecurityHandler = securityHandler;
- WopiHostOptions = wopiHostOptions;
- }
-
///
/// Creates a simple URL to access a WOPI object of choice.
///
diff --git a/src/WopiHost.Core/FileExtensions.cs b/src/WopiHost.Core/FileExtensions.cs
index 23a90ba..bf5892d 100644
--- a/src/WopiHost.Core/FileExtensions.cs
+++ b/src/WopiHost.Core/FileExtensions.cs
@@ -22,15 +22,9 @@ public static class FileExtensions
/// CheckFileInfo model
public static CheckFileInfo GetCheckFileInfo(this IWopiFile file, ClaimsPrincipal principal, HostCapabilities capabilities)
{
- if (file is null)
- {
- throw new ArgumentNullException(nameof(file));
- }
+ ArgumentNullException.ThrowIfNull(file);
- if (capabilities is null)
- {
- throw new ArgumentNullException(nameof(capabilities));
- }
+ ArgumentNullException.ThrowIfNull(capabilities);
var checkFileInfo = new CheckFileInfo();
if (principal is not null)
diff --git a/src/WopiHost.Core/HttpHeaderAttribute.cs b/src/WopiHost.Core/HttpHeaderAttribute.cs
index 330e937..a48aa47 100644
--- a/src/WopiHost.Core/HttpHeaderAttribute.cs
+++ b/src/WopiHost.Core/HttpHeaderAttribute.cs
@@ -5,29 +5,20 @@ namespace WopiHost.Core;
///
/// A header-based constraint for HTTP actions.
///
+///
+/// Creates an instance of a constraint based on a header name and allowed values.
+///
+/// Header name to check.
+/// Accepted header values.
[AttributeUsage(AttributeTargets.Method)]
-public class HttpHeaderAttribute : Attribute, IActionConstraint
+public class HttpHeaderAttribute(string header, params string[] values) : Attribute, IActionConstraint
{
- private string Header { get; set; }
+ private string Header { get; set; } = header;
- private string[] Values { get; set; }
-
- ///
- /// Creates an instance of a constraint based on a header name and allowed values.
- ///
- /// Header name to check.
- /// Accepted header values.
- public HttpHeaderAttribute(string header, params string[] values)
- {
- Header = header;
- Values = values;
- }
+ private string[] Values { get; set; } = values;
///
- public bool Accept(ActionConstraintContext context)
- {
- return (context is not null) && context.RouteContext.HttpContext.Request.Headers.TryGetValue(Header, out var value) && Values.Contains(value[0]);
- }
+ public bool Accept(ActionConstraintContext context) => (context is not null) && context.RouteContext.HttpContext.Request.Headers.TryGetValue(Header, out var value) && Values.Contains(value[0]);
///
public int Order => 0;
diff --git a/src/WopiHost.Core/Security/Authentication/AccessTokenHandler.cs b/src/WopiHost.Core/Security/Authentication/AccessTokenHandler.cs
index 4447dd9..6393a84 100644
--- a/src/WopiHost.Core/Security/Authentication/AccessTokenHandler.cs
+++ b/src/WopiHost.Core/Security/Authentication/AccessTokenHandler.cs
@@ -9,7 +9,13 @@ namespace WopiHost.Core.Security.Authentication;
///
/// Class facilitating authentication using an access token query parameter.
///
-public class AccessTokenHandler : AuthenticationHandler
+///
+/// Creates an instance of .
+///
+/// The monitor for the options instance.
+/// The Microsoft.Extensions.Logging.ILoggerFactory.
+/// The System.Text.Encodings.Web.UrlEncoder.
+public class AccessTokenHandler(IOptionsMonitor options, ILoggerFactory logger, UrlEncoder encoder) : AuthenticationHandler(options, logger, encoder)
{
///
/// Handles authentication using the access_token query parameter.
@@ -40,10 +46,10 @@ protected override Task HandleAuthenticateAsync()
if (Options.SaveToken)
{
- ticket.Properties.StoreTokens(new[]
- {
+ ticket.Properties.StoreTokens(
+ [
new AuthenticationToken { Name = AccessTokenDefaults.ACCESS_TOKEN_QUERY_NAME, Value = token }
- });
+ ]);
}
return Task.FromResult(AuthenticateResult.Success(ticket));
}
@@ -67,16 +73,4 @@ protected override Task HandleAuthenticateAsync()
return Task.FromResult(AuthenticateResult.Fail(ex));
}
}
-
- ///
- /// Creates an instance of .
- ///
- /// The monitor for the options instance.
- /// The Microsoft.Extensions.Logging.ILoggerFactory.
- /// The System.Text.Encodings.Web.UrlEncoder.
- /// The Microsoft.AspNetCore.Authentication.ISystemClock.
- public AccessTokenHandler(IOptionsMonitor options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock)
- {
- // Used by for Dependency Injection
- }
}
\ No newline at end of file
diff --git a/src/WopiHost.Core/Security/Authentication/AuthenticationBuilderExtensions.cs b/src/WopiHost.Core/Security/Authentication/AuthenticationBuilderExtensions.cs
index 6d8efd5..ec0f177 100644
--- a/src/WopiHost.Core/Security/Authentication/AuthenticationBuilderExtensions.cs
+++ b/src/WopiHost.Core/Security/Authentication/AuthenticationBuilderExtensions.cs
@@ -7,16 +7,13 @@ namespace WopiHost.Core.Security.Authentication;
///
public static class AuthenticationBuilderExtensions
{
- ///
- /// Adds to the .
- ///
- /// An instance of
- /// Schema name
- /// Schema display name
- /// A delegate for configuring
- ///
- public static AuthenticationBuilder AddTokenAuthentication(this AuthenticationBuilder builder, string authenticationScheme, string displayName, Action configureOptions)
- {
- return builder.AddScheme(authenticationScheme, displayName, configureOptions);
- }
+ ///
+ /// Adds to the .
+ ///
+ /// An instance of
+ /// Schema name
+ /// Schema display name
+ /// A delegate for configuring
+ ///
+ public static AuthenticationBuilder AddTokenAuthentication(this AuthenticationBuilder builder, string authenticationScheme, string displayName, Action configureOptions) => builder.AddScheme(authenticationScheme, displayName, configureOptions);
}
diff --git a/src/WopiHost.Core/Security/Authorization/WopiAuthorizationHandler.cs b/src/WopiHost.Core/Security/Authorization/WopiAuthorizationHandler.cs
index 70b91bd..f7005f5 100644
--- a/src/WopiHost.Core/Security/Authorization/WopiAuthorizationHandler.cs
+++ b/src/WopiHost.Core/Security/Authorization/WopiAuthorizationHandler.cs
@@ -6,21 +6,16 @@ namespace WopiHost.Core.Security.Authorization;
///
/// Performs resource-based authorization.
///
-public class WopiAuthorizationHandler : AuthorizationHandler
+///
+/// Creates an instance of .
+///
+/// AuthNZ handler.
+public class WopiAuthorizationHandler(IWopiSecurityHandler securityHandler) : AuthorizationHandler
{
///
/// Provides authentication and performs authorization operations for WOPI objects
///
- public IWopiSecurityHandler SecurityHandler { get; }
-
- ///
- /// Creates an instance of .
- ///
- /// AuthNZ handler.
- public WopiAuthorizationHandler(IWopiSecurityHandler securityHandler)
- {
- SecurityHandler = securityHandler;
- }
+ public IWopiSecurityHandler SecurityHandler { get; } = securityHandler;
///
/// Performs resource-based authorization check.
diff --git a/src/WopiHost.Core/Security/FileResource.cs b/src/WopiHost.Core/Security/FileResource.cs
index 3800be7..1496903 100644
--- a/src/WopiHost.Core/Security/FileResource.cs
+++ b/src/WopiHost.Core/Security/FileResource.cs
@@ -1,21 +1,16 @@
namespace WopiHost.Core.Security;
- ///
- /// Represents a resource for a resource-based authroization.
- ///
- public class FileResource
+///
+/// Represents a resource for a resource-based authroization.
+///
+///
+/// Creates an object representing a resource for a resource-based authroization.
+///
+/// Identifier of a resource.
+public class FileResource(string fileId)
{
- ///
- /// Identifier of a resource.
- ///
- public string FileId { get; }
-
- ///
- /// Creates an object representing a resource for a resource-based authroization.
- ///
- /// Identifier of a resource.
- public FileResource(string fileId)
- {
- FileId = fileId;
- }
+ ///
+ /// Identifier of a resource.
+ ///
+ public string FileId { get; } = fileId;
}
diff --git a/src/WopiHost.Core/WopiHost.Core.csproj b/src/WopiHost.Core/WopiHost.Core.csproj
index 00b6dfe..3ba0b0c 100644
--- a/src/WopiHost.Core/WopiHost.Core.csproj
+++ b/src/WopiHost.Core/WopiHost.Core.csproj
@@ -3,7 +3,7 @@
WopiHost.Core Class Library
Petr Svihlik
- net7.0
+ net8.0
WopiHost.Core
WopiHost.Core
LICENSE.txt
@@ -30,7 +30,7 @@
-
+
@@ -42,7 +42,7 @@
-
-
+
+
diff --git a/src/WopiHost.Core/WopiOverrideHeaderAttribute.cs b/src/WopiHost.Core/WopiOverrideHeaderAttribute.cs
index 72e9789..c67dc1b 100644
--- a/src/WopiHost.Core/WopiOverrideHeaderAttribute.cs
+++ b/src/WopiHost.Core/WopiOverrideHeaderAttribute.cs
@@ -3,14 +3,11 @@
///
/// An action constraint based on the X-WOPI-Override header.
///
+///
+/// Creates an instance of the header-based constraint based on allowed values.
+///
+/// Accepted header values.
[AttributeUsage(AttributeTargets.Method)]
-public class WopiOverrideHeaderAttribute : HttpHeaderAttribute
+public class WopiOverrideHeaderAttribute(string[] values) : HttpHeaderAttribute(WopiHeaders.WOPI_OVERRIDE, values)
{
- ///
- /// Creates an instance of the header-based constraint based on allowed values.
- ///
- /// Accepted header values.
- public WopiOverrideHeaderAttribute(string[] values) : base(WopiHeaders.WOPI_OVERRIDE, values)
- {
- }
}
diff --git a/src/WopiHost.Discovery/AsyncExpiringLazy{T}.cs b/src/WopiHost.Discovery/AsyncExpiringLazy{T}.cs
index 4404d12..658f260 100644
--- a/src/WopiHost.Discovery/AsyncExpiringLazy{T}.cs
+++ b/src/WopiHost.Discovery/AsyncExpiringLazy{T}.cs
@@ -6,23 +6,18 @@
/// https://www.strathweb.com/2016/11/lazy-async-initialization-for-expiring-objects/
///
/// Type of the temporary value.
-public class AsyncExpiringLazy
+///
+/// Creates a new instance of .
+///
+/// A delegate that facilitates the creation of the value.
+/// The must be initialized.
+public class AsyncExpiringLazy(Func, Task>> valueProvider)
{
private static readonly SemaphoreSlim SyncLock = new(initialCount: 1);
- private readonly Func, Task>> _valueProvider;
+ private readonly Func, Task>> _valueProvider = valueProvider ?? throw new ArgumentNullException(nameof(valueProvider));
private TemporaryValue _value;
private bool IsValueCreatedInternal => _value.Result != null && _value.ValidUntil > DateTimeOffset.UtcNow;
- ///
- /// Creates a new instance of .
- ///
- /// A delegate that facilitates the creation of the value.
- /// The must be initialized.
- public AsyncExpiringLazy(Func, Task>> valueProvider)
- {
- _valueProvider = valueProvider ?? throw new ArgumentNullException(nameof(valueProvider));
- }
-
///
/// Returns true if a value has been created and is still valid.
///
diff --git a/src/WopiHost.Discovery/FileSystemDiscoveryFileProvider.cs b/src/WopiHost.Discovery/FileSystemDiscoveryFileProvider.cs
index c18d59d..7b1d01c 100644
--- a/src/WopiHost.Discovery/FileSystemDiscoveryFileProvider.cs
+++ b/src/WopiHost.Discovery/FileSystemDiscoveryFileProvider.cs
@@ -5,22 +5,14 @@ namespace WopiHost.Discovery;
///
/// Loads the WOPI discovery XML file from the local file system.
///
-public class FileSystemDiscoveryFileProvider : IDiscoveryFileProvider
+///
+/// Initializes the provider using a local file-system path.
+///
+/// Path to a WOPI XML discovery file.
+public class FileSystemDiscoveryFileProvider(string filePath) : IDiscoveryFileProvider
{
- private readonly string _filePath;
+ private readonly string _filePath = filePath;
- ///
- /// Initializes the provider using a local file-system path.
- ///
- /// Path to a WOPI XML discovery file.
- public FileSystemDiscoveryFileProvider(string filePath)
- {
- _filePath = filePath;
- }
-
- ///
- public Task GetDiscoveryXmlAsync()
- {
- return Task.FromResult(XElement.Parse(File.ReadAllText(_filePath)));
- }
- }
\ No newline at end of file
+ ///
+ public Task GetDiscoveryXmlAsync() => Task.FromResult(XElement.Parse(File.ReadAllText(_filePath)));
+}
\ No newline at end of file
diff --git a/src/WopiHost.Discovery/HttpDiscoveryFileProvider.cs b/src/WopiHost.Discovery/HttpDiscoveryFileProvider.cs
index ec77f38..2a3168a 100644
--- a/src/WopiHost.Discovery/HttpDiscoveryFileProvider.cs
+++ b/src/WopiHost.Discovery/HttpDiscoveryFileProvider.cs
@@ -5,18 +5,13 @@ namespace WopiHost.Discovery;
///
/// A discovery file provider that loads the discovery file from a WOPI client over HTTP.
///
-public class HttpDiscoveryFileProvider : IDiscoveryFileProvider
+///
+/// Creates an instance of a discovery file provider that loads the discovery file from a WOPI client over HTTP.
+///
+/// An HTTP client with a configured to point to a WOPI client.
+public class HttpDiscoveryFileProvider(HttpClient httpClient) : IDiscoveryFileProvider
{
- private readonly HttpClient _httpClient;
-
- ///
- /// Creates an instance of a discovery file provider that loads the discovery file from a WOPI client over HTTP.
- ///
- /// An HTTP client with a configured to point to a WOPI client.
- public HttpDiscoveryFileProvider(HttpClient httpClient)
- {
- _httpClient = httpClient;
- }
+ private readonly HttpClient _httpClient = httpClient;
///
public async Task GetDiscoveryXmlAsync()
diff --git a/src/WopiHost.Discovery/WopiDiscoverer.cs b/src/WopiHost.Discovery/WopiDiscoverer.cs
index f058a57..2037ebd 100644
--- a/src/WopiHost.Discovery/WopiDiscoverer.cs
+++ b/src/WopiHost.Discovery/WopiDiscoverer.cs
@@ -4,7 +4,12 @@
namespace WopiHost.Discovery;
///
-public class WopiDiscoverer : IDiscoverer
+///
+/// Creates a new instance of the , a class for examining the capabilities of the WOPI client.
+///
+/// A service that provides the discovery file to examine.
+///
+public class WopiDiscoverer(IDiscoveryFileProvider discoveryFileProvider, DiscoveryOptions discoveryOptions) : IDiscoverer
{
private const string ElementNetZone = "net-zone";
private const string ElementApp = "app";
@@ -20,9 +25,9 @@ public class WopiDiscoverer : IDiscoverer
private AsyncExpiringLazy> _apps;
- private IDiscoveryFileProvider DiscoveryFileProvider { get; }
+ private IDiscoveryFileProvider DiscoveryFileProvider { get; } = discoveryFileProvider;
- private DiscoveryOptions DiscoveryOptions { get; }
+ private DiscoveryOptions DiscoveryOptions { get; } = discoveryOptions;
private AsyncExpiringLazy> Apps
{
@@ -43,21 +48,7 @@ private AsyncExpiringLazy> Apps
}
}
- ///
- /// Creates a new instance of the , a class for examining the capabilities of the WOPI client.
- ///
- /// A service that provides the discovery file to examine.
- ///
- public WopiDiscoverer(IDiscoveryFileProvider discoveryFileProvider, DiscoveryOptions discoveryOptions)
- {
- DiscoveryFileProvider = discoveryFileProvider;
- DiscoveryOptions = discoveryOptions;
- }
-
- internal async Task> GetAppsAsync()
- {
- return await Apps.Value();
- }
+ internal async Task> GetAppsAsync() => await Apps.Value();
private bool ValidateNetZone(XElement e)
{
@@ -80,7 +71,7 @@ public async Task SupportsActionAsync(string extension, WopiActionEnum act
{
var actionString = action.ToString().ToUpperInvariant();
- var query = (await GetAppsAsync()).Elements().Where(e => (string)e.Attribute(AttrActionExtension) == extension && e.Attribute(AttrActionName).Value.ToUpperInvariant() == actionString);
+ var query = (await GetAppsAsync()).Elements().Where(e => (string)e.Attribute(AttrActionExtension) == extension && e.Attribute(AttrActionName).Value.Equals(actionString, StringComparison.InvariantCultureIgnoreCase));
return query.Any();
}
@@ -90,7 +81,7 @@ public async Task> GetActionRequirementsAsync(string extensi
{
var actionString = action.ToString().ToUpperInvariant();
- var query = (await GetAppsAsync()).Elements().Where(e => (string)e.Attribute(AttrActionExtension) == extension && e.Attribute(AttrActionName).Value.ToUpperInvariant() == actionString).Select(e => e.Attribute(AttrActionRequires).Value.Split(','));
+ var query = (await GetAppsAsync()).Elements().Where(e => (string)e.Attribute(AttrActionExtension) == extension && e.Attribute(AttrActionName).Value.Equals(actionString, StringComparison.InvariantCultureIgnoreCase)).Select(e => e.Attribute(AttrActionRequires).Value.Split(','));
return query.FirstOrDefault();
}
@@ -106,7 +97,7 @@ public async Task RequiresCobaltAsync(string extension, WopiActionEnum act
public async Task GetUrlTemplateAsync(string extension, WopiActionEnum action)
{
var actionString = action.ToString().ToUpperInvariant();
- var query = (await GetAppsAsync()).Elements().Where(e => (string)e.Attribute(AttrActionExtension) == extension && e.Attribute(AttrActionName).Value.ToUpperInvariant() == actionString).Select(e => e.Attribute(AttrActionUrl).Value);
+ var query = (await GetAppsAsync()).Elements().Where(e => (string)e.Attribute(AttrActionExtension) == extension && e.Attribute(AttrActionName).Value.Equals(actionString, StringComparison.InvariantCultureIgnoreCase)).Select(e => e.Attribute(AttrActionUrl).Value);
return query.FirstOrDefault();
}
diff --git a/src/WopiHost.Discovery/WopiHost.Discovery.csproj b/src/WopiHost.Discovery/WopiHost.Discovery.csproj
index 90f68d7..26ac96e 100644
--- a/src/WopiHost.Discovery/WopiHost.Discovery.csproj
+++ b/src/WopiHost.Discovery/WopiHost.Discovery.csproj
@@ -3,7 +3,7 @@
WopiHost.Discovery Class Library
Petr Svihlik
- net7.0
+ net8.0
WopiHost.Discovery
WopiHost.Discovery
LICENSE.txt
@@ -33,7 +33,7 @@
-
+
diff --git a/src/WopiHost.FileSystemProvider/WopiFile.cs b/src/WopiHost.FileSystemProvider/WopiFile.cs
index f829558..4f8a9b5 100644
--- a/src/WopiHost.FileSystemProvider/WopiFile.cs
+++ b/src/WopiHost.FileSystemProvider/WopiFile.cs
@@ -7,20 +7,25 @@
namespace WopiHost.FileSystemProvider;
///
-public class WopiFile : IWopiFile
+///
+/// Creates an instance of .
+///
+/// Path on the file system the file is located in.
+/// Identifier of a file.
+public class WopiFile(string filePath, string fileIdentifier) : IWopiFile
{
private FileInfo _fileInfo;
private FileVersionInfo _fileVersionInfo;
- private string FilePath { get; set; }
+ private string FilePath { get; set; } = filePath;
private FileInfo FileInfo => _fileInfo ??= new FileInfo(FilePath);
private FileVersionInfo FileVersionInfo => _fileVersionInfo ??= FileVersionInfo.GetVersionInfo(FilePath);
///
- public string Identifier { get; }
+ public string Identifier { get; } = fileIdentifier;
///
public bool Exists => FileInfo.Exists;
@@ -31,7 +36,7 @@ public string Extension
get
{
var ext = FileInfo.Extension;
- if (ext.StartsWith(".", StringComparison.InvariantCulture))
+ if (ext.StartsWith('.'))
{
ext = ext[1..];
}
@@ -54,28 +59,11 @@ public string Extension
///
public DateTime LastWriteTimeUtc => FileInfo.LastWriteTimeUtc;
- ///
- /// Creates an instance of .
- ///
- /// Path on the file system the file is located in.
- /// Identifier of a file.
- public WopiFile(string filePath, string fileIdentifier)
- {
- FilePath = filePath;
- Identifier = fileIdentifier;
- }
-
///
- public Stream GetReadStream()
- {
- return FileInfo.OpenRead();
- }
+ public Stream GetReadStream() => FileInfo.OpenRead();
///
- public Stream GetWriteStream()
- {
- return FileInfo.Open(FileMode.Truncate);
- }
+ public Stream GetWriteStream() => FileInfo.Open(FileMode.Truncate);
///
/// A string that uniquely identifies the owner of the file.
diff --git a/src/WopiHost.FileSystemProvider/WopiFileSystemProvider.cs b/src/WopiHost.FileSystemProvider/WopiFileSystemProvider.cs
index 689000a..f561547 100644
--- a/src/WopiHost.FileSystemProvider/WopiFileSystemProvider.cs
+++ b/src/WopiHost.FileSystemProvider/WopiFileSystemProvider.cs
@@ -35,10 +35,7 @@ public class WopiFileSystemProvider : IWopiStorageProvider
/// Application configuration.
public WopiFileSystemProvider(IHostEnvironment env, IConfiguration configuration)
{
- if (configuration is null)
- {
- throw new ArgumentNullException(nameof(configuration));
- }
+ ArgumentNullException.ThrowIfNull(configuration);
HostEnvironment = env ?? throw new ArgumentNullException(nameof(env));
FileSystemProviderOptions = configuration.GetSection(WopiConfigurationSections.STORAGE_OPTIONS).Get(); //TODO: rework
diff --git a/src/WopiHost.FileSystemProvider/WopiFolder.cs b/src/WopiHost.FileSystemProvider/WopiFolder.cs
index 55dcd2c..e1441ff 100644
--- a/src/WopiHost.FileSystemProvider/WopiFolder.cs
+++ b/src/WopiHost.FileSystemProvider/WopiFolder.cs
@@ -3,30 +3,24 @@
namespace WopiHost.FileSystemProvider;
///
-public class WopiFolder : IWopiFolder
+///
+/// Creates an instance of .
+///
+/// Path on the file system the folder is located in.
+/// A unique identifier of a folder.
+public class WopiFolder(string path, string folderIdentifier) : IWopiFolder
{
private DirectoryInfo _folderInfo;
- ///
- protected string Path { get; set; }
+ ///
+ protected string Path { get; set; } = path;
- ///
- protected DirectoryInfo FolderInfo => _folderInfo ??= new DirectoryInfo(Path);
+ ///
+ protected DirectoryInfo FolderInfo => _folderInfo ??= new DirectoryInfo(Path);
///
public string Name => FolderInfo.Name;
- ///
- public string Identifier { get; }
-
- ///
- /// Creates an instance of .
- ///
- /// Path on the file system the folder is located in.
- /// A unique identifier of a folder.
- public WopiFolder(string path, string folderIdentifier)
- {
- Path = path;
- Identifier = folderIdentifier;
- }
- }
+ ///
+ public string Identifier { get; } = folderIdentifier;
+}
diff --git a/src/WopiHost.FileSystemProvider/WopiHost.FileSystemProvider.csproj b/src/WopiHost.FileSystemProvider/WopiHost.FileSystemProvider.csproj
index 082406f..7291f74 100644
--- a/src/WopiHost.FileSystemProvider/WopiHost.FileSystemProvider.csproj
+++ b/src/WopiHost.FileSystemProvider/WopiHost.FileSystemProvider.csproj
@@ -3,7 +3,7 @@
WopiHost.FileSystemProvider Class Library
Petr Svihlik
- net7.0
+ net8.0
WopiHost.FileSystemProvider
WopiHost.FileSystemProvider
LICENSE.txt
@@ -33,26 +33,22 @@
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
diff --git a/src/WopiHost.FileSystemProvider/WopiSecurityHandler.cs b/src/WopiHost.FileSystemProvider/WopiSecurityHandler.cs
index 69760b1..99698bd 100644
--- a/src/WopiHost.FileSystemProvider/WopiSecurityHandler.cs
+++ b/src/WopiHost.FileSystemProvider/WopiSecurityHandler.cs
@@ -8,9 +8,13 @@
namespace WopiHost.FileSystemProvider;
///
-public class WopiSecurityHandler : IWopiSecurityHandler
+///
+/// Creates a new instance of the .
+///
+/// An instance of a type used to configure the logging system and create instances of Microsoft.Extensions.Logging.ILogger from the registered Microsoft.Extensions.Logging.ILoggerProviders.
+public class WopiSecurityHandler(ILoggerFactory loggerFactory) : IWopiSecurityHandler
{
- private readonly ILogger _logger;
+ private readonly ILogger _logger = loggerFactory.CreateLogger();
private readonly JwtSecurityTokenHandler _tokenHandler = new();
private SymmetricSecurityKey _key = null;
@@ -50,15 +54,6 @@ private SymmetricSecurityKey Key
}
};
- ///
- /// Creates a new instance of the .
- ///
- /// An instance of a type used to configure the logging system and create instances of Microsoft.Extensions.Logging.ILogger from the registered Microsoft.Extensions.Logging.ILoggerProviders.
- public WopiSecurityHandler(ILoggerFactory loggerFactory)
- {
- _logger = loggerFactory.CreateLogger();
- }
-
///
public SecurityToken GenerateAccessToken(string userId, string resourceId)
{
@@ -102,17 +97,12 @@ public ClaimsPrincipal GetPrincipal(string tokenString)
}
///
- public bool IsAuthorized(ClaimsPrincipal principal, string resourceId, WopiAuthorizationRequirement operation)
- {
+ public bool IsAuthorized(ClaimsPrincipal principal, string resourceId, WopiAuthorizationRequirement operation) =>
//TODO: logic
- return true;
- }
+ true;
///
/// Converts the security token to a Base64 string.
///
- public string WriteToken(SecurityToken token)
- {
- return _tokenHandler.WriteToken(token);
- }
+ public string WriteToken(SecurityToken token) => _tokenHandler.WriteToken(token);
}
diff --git a/src/WopiHost.Url/WopiHost.Url.csproj b/src/WopiHost.Url/WopiHost.Url.csproj
index a36f45f..1264e49 100644
--- a/src/WopiHost.Url/WopiHost.Url.csproj
+++ b/src/WopiHost.Url/WopiHost.Url.csproj
@@ -3,7 +3,7 @@
WopiHost.Url Class Library
Petr Svihlik
- net7.0
+ net8.0
WopiHost.Url
WopiHost.Url
LICENSE.txt
@@ -33,7 +33,7 @@
-
+
diff --git a/src/WopiHost.Url/WopiUrlBuilder.cs b/src/WopiHost.Url/WopiUrlBuilder.cs
index 236c0c6..d0d4143 100644
--- a/src/WopiHost.Url/WopiUrlBuilder.cs
+++ b/src/WopiHost.Url/WopiUrlBuilder.cs
@@ -10,28 +10,22 @@ namespace WopiHost.Url;
/// WOPI v2 spec: http://wopi.readthedocs.io/en/latest/discovery.html
/// WOPI v1 spec: https://msdn.microsoft.com/en-us/library/hh695362(v=office.12).aspx
///
-public partial class WopiUrlBuilder
+///
+/// Creates a new instance of WOPI URL generator class.
+///
+/// Provider of WOPI discovery data.
+/// Additional settings influencing behavior of the WOPI client.
+public partial class WopiUrlBuilder(IDiscoverer discoverer, WopiUrlSettings urlSettings = null)
{
[GeneratedRegex("<(?\\w*)=(?\\w*)&*>")]
private static partial Regex UrlParamRegex();
- private readonly IDiscoverer _wopiDiscoverer;
+ private readonly IDiscoverer _wopiDiscoverer = discoverer;
///
/// Additional URL parameters influencing the behavior of the WOPI client.
///
- public WopiUrlSettings UrlSettings { get; }
-
- ///
- /// Creates a new instance of WOPI URL generator class.
- ///
- /// Provider of WOPI discovery data.
- /// Additional settings influencing behavior of the WOPI client.
- public WopiUrlBuilder(IDiscoverer discoverer, WopiUrlSettings urlSettings = null)
- {
- _wopiDiscoverer = discoverer;
- UrlSettings = urlSettings;
- }
+ public WopiUrlSettings UrlSettings { get; } = urlSettings;
///
/// Generates an URL for a given file and action.
diff --git a/src/WopiHost.Web/Controllers/HomeController.cs b/src/WopiHost.Web/Controllers/HomeController.cs
index d441daa..ab0ec79 100644
--- a/src/WopiHost.Web/Controllers/HomeController.cs
+++ b/src/WopiHost.Web/Controllers/HomeController.cs
@@ -10,27 +10,19 @@
namespace WopiHost.Web.Controllers;
-public class HomeController : Controller
+public class HomeController(IOptionsSnapshot wopiOptions, IWopiStorageProvider storageProvider, IDiscoverer discoverer, ILoggerFactory loggerFactory) : Controller
{
private WopiUrlBuilder _urlGenerator;
- private IOptionsSnapshot WopiOptions { get; }
- private IWopiStorageProvider StorageProvider { get; }
- private IDiscoverer Discoverer { get; }
- private ILoggerFactory LoggerFactory { get; }
+ private IOptionsSnapshot WopiOptions { get; } = wopiOptions;
+ private IWopiStorageProvider StorageProvider { get; } = storageProvider;
+ private IDiscoverer Discoverer { get; } = discoverer;
+ private ILoggerFactory LoggerFactory { get; } = loggerFactory;
//TODO: remove test culture value and load it from configuration SECTION
public WopiUrlBuilder UrlGenerator => _urlGenerator ??= new WopiUrlBuilder(Discoverer, new WopiUrlSettings { UiLlcc = new CultureInfo("en-US") });
- public HomeController(IOptionsSnapshot wopiOptions, IWopiStorageProvider storageProvider, IDiscoverer discoverer, ILoggerFactory loggerFactory)
- {
- WopiOptions = wopiOptions;
- StorageProvider = storageProvider;
- Discoverer = discoverer;
- LoggerFactory = loggerFactory;
- }
-
public async Task Index()
{
try
diff --git a/src/WopiHost.Web/Program.cs b/src/WopiHost.Web/Program.cs
index 9363623..af5981a 100644
--- a/src/WopiHost.Web/Program.cs
+++ b/src/WopiHost.Web/Program.cs
@@ -2,10 +2,7 @@
public class Program
{
- public static void Main(string[] args)
- {
- CreateHostBuilder(args).Build().Run();
- }
+ public static void Main(string[] args) => CreateHostBuilder(args).Build().Run();
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
diff --git a/src/WopiHost.Web/ServiceCollectionExtensions.cs b/src/WopiHost.Web/ServiceCollectionExtensions.cs
index 54ebfef..48779b0 100644
--- a/src/WopiHost.Web/ServiceCollectionExtensions.cs
+++ b/src/WopiHost.Web/ServiceCollectionExtensions.cs
@@ -4,8 +4,8 @@ public static class ServiceCollectionExtensions
{
public static TConfig Configure(this IServiceCollection services, IConfiguration configuration) where TConfig : class, new()
{
- if (services == null) throw new ArgumentNullException(nameof(services));
- if (configuration == null) throw new ArgumentNullException(nameof(configuration));
+ ArgumentNullException.ThrowIfNull(services);
+ ArgumentNullException.ThrowIfNull(configuration);
var config = new TConfig();
configuration.Bind(config);
@@ -15,9 +15,9 @@ public static class ServiceCollectionExtensions
public static TConfig Configure(this IServiceCollection services, IConfiguration configuration, Func pocoProvider) where TConfig : class
{
- if (services == null) throw new ArgumentNullException(nameof(services));
- if (configuration == null) throw new ArgumentNullException(nameof(configuration));
- if (pocoProvider == null) throw new ArgumentNullException(nameof(pocoProvider));
+ ArgumentNullException.ThrowIfNull(services);
+ ArgumentNullException.ThrowIfNull(configuration);
+ ArgumentNullException.ThrowIfNull(pocoProvider);
var config = pocoProvider();
configuration.Bind(config);
@@ -27,9 +27,9 @@ public static TConfig Configure(this IServiceCollection services, IConf
public static TConfig Configure(this IServiceCollection services, IConfiguration configuration, TConfig config) where TConfig : class
{
- if (services == null) throw new ArgumentNullException(nameof(services));
- if (configuration == null) throw new ArgumentNullException(nameof(configuration));
- if (config == null) throw new ArgumentNullException(nameof(config));
+ ArgumentNullException.ThrowIfNull(services);
+ ArgumentNullException.ThrowIfNull(configuration);
+ ArgumentNullException.ThrowIfNull(config);
configuration.Bind(config);
services.AddSingleton(config);
diff --git a/src/WopiHost.Web/Startup.cs b/src/WopiHost.Web/Startup.cs
index b0dcbf0..d3195ac 100644
--- a/src/WopiHost.Web/Startup.cs
+++ b/src/WopiHost.Web/Startup.cs
@@ -5,14 +5,9 @@
namespace WopiHost.Web;
-public class Startup
+public class Startup(IConfiguration configuration)
{
- public IConfiguration Configuration { get; }
-
- public Startup(IConfiguration configuration)
- {
- Configuration = configuration;
- }
+ public IConfiguration Configuration { get; } = configuration;
///
/// Sets up the DI container.
diff --git a/src/WopiHost.Web/Views/Home/Index.cshtml b/src/WopiHost.Web/Views/Home/Index.cshtml
index 0a84a11..8d25cd0 100644
--- a/src/WopiHost.Web/Views/Home/Index.cshtml
+++ b/src/WopiHost.Web/Views/Home/Index.cshtml
@@ -1,6 +1,6 @@
@using WopiHost.Discovery.Enumerations
-@model IEnumerable
+@model IEnumerable
@{
ViewData["Title"] = "List of WOPI files";
}
diff --git a/src/WopiHost.Web/WopiHost.Web.csproj b/src/WopiHost.Web/WopiHost.Web.csproj
index 045eb67..7df9991 100644
--- a/src/WopiHost.Web/WopiHost.Web.csproj
+++ b/src/WopiHost.Web/WopiHost.Web.csproj
@@ -1,7 +1,7 @@
- net7.0
+ net8.0
true
true
WopiHost.Web
@@ -13,7 +13,7 @@
-
+
diff --git a/src/WopiHost/LogHelper.cs b/src/WopiHost/LogHelper.cs
index bcc841a..16103c2 100644
--- a/src/WopiHost/LogHelper.cs
+++ b/src/WopiHost/LogHelper.cs
@@ -15,15 +15,9 @@ public static class LogHelper
/// HTTP context instance
public static void EnrichWithWopiDiagnostics(IDiagnosticContext diagnosticContext, HttpContext httpContext)
{
- if (diagnosticContext is null)
- {
- throw new System.ArgumentNullException(nameof(diagnosticContext));
- }
+ ArgumentNullException.ThrowIfNull(diagnosticContext);
- if (httpContext is null)
- {
- throw new System.ArgumentNullException(nameof(httpContext));
- }
+ ArgumentNullException.ThrowIfNull(httpContext);
var request = httpContext.Request;
diff --git a/src/WopiHost/Startup.cs b/src/WopiHost/Startup.cs
index bce0130..54425f6 100644
--- a/src/WopiHost/Startup.cs
+++ b/src/WopiHost/Startup.cs
@@ -7,14 +7,9 @@
namespace WopiHost;
-public class Startup
+public class Startup(IConfiguration configuration)
{
- public IConfiguration Configuration { get; set; }
-
- public Startup(IConfiguration configuration)
- {
- Configuration = configuration;
- }
+ public IConfiguration Configuration { get; set; } = configuration;
public void ConfigureContainer(ContainerBuilder builder)
{
diff --git a/src/WopiHost/WopiHost.csproj b/src/WopiHost/WopiHost.csproj
index 55bdb98..1b033d1 100644
--- a/src/WopiHost/WopiHost.csproj
+++ b/src/WopiHost/WopiHost.csproj
@@ -1,7 +1,7 @@
- net7.0
+ net8.0
WopiHost
Exe
true
@@ -23,19 +23,19 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/Directory.Build.props b/test/Directory.Build.props
index 0aab062..bf02000 100644
--- a/test/Directory.Build.props
+++ b/test/Directory.Build.props
@@ -1,7 +1,6 @@
Petr Svihlik
- net7.0
false
enable
enable
diff --git a/test/WopiHost.Core.Tests/WopiHost.Core.Tests.csproj b/test/WopiHost.Core.Tests/WopiHost.Core.Tests.csproj
index a0ef820..8e60abb 100644
--- a/test/WopiHost.Core.Tests/WopiHost.Core.Tests.csproj
+++ b/test/WopiHost.Core.Tests/WopiHost.Core.Tests.csproj
@@ -1,5 +1,29 @@
+
+ net8.0
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers
+
+
+ all
+ runtime; build; native; contentfiles; analyzers
+
+
diff --git a/test/WopiHost.Discovery.Tests/WopiDiscovererTests.cs b/test/WopiHost.Discovery.Tests/WopiDiscovererTests.cs
index 66f8476..6a48fc9 100644
--- a/test/WopiHost.Discovery.Tests/WopiDiscovererTests.cs
+++ b/test/WopiHost.Discovery.Tests/WopiDiscovererTests.cs
@@ -15,10 +15,7 @@ public WopiDiscovererTests()
{
}
- private void InitDiscoverer(string fileName, NetZoneEnum netZone)
- {
- _wopiDiscoverer = new WopiDiscoverer(new FileSystemDiscoveryFileProvider(Path.Combine(AppContext.BaseDirectory, fileName)), new DiscoveryOptions { NetZone = netZone });
- }
+ private void InitDiscoverer(string fileName, NetZoneEnum netZone) => _wopiDiscoverer = new WopiDiscoverer(new FileSystemDiscoveryFileProvider(Path.Combine(AppContext.BaseDirectory, fileName)), new DiscoveryOptions { NetZone = netZone });
[Theory]
[InlineData(NetZoneEnum.ExternalHttps, "xlsm", WopiActionEnum.LegacyWebService, "https://excel.officeapps.live.com/x/_vti_bin/excelserviceinternal.asmx?", XmlOo2019)]
@@ -145,7 +142,7 @@ public async void SupportedExtensionCobalt(NetZoneEnum netZone, string extension
[InlineData(NetZoneEnum.InternalHttp, "docx", WopiActionEnum.Edit, "http://owaserver/we/wordeditorframe.aspx?", XmlOwa2013)]
[InlineData(NetZoneEnum.InternalHttp, "html", WopiActionEnum.Edit, null, XmlOwa2013)]
[InlineData(NetZoneEnum.InternalHttp, "txt", WopiActionEnum.Edit, null, XmlOwa2013)]
- public async void UrlTemplateTests(NetZoneEnum netZone, string extension, WopiActionEnum action, string expectedValue, string fileName)
+ public async void UrlTemplateTests(NetZoneEnum netZone, string extension, WopiActionEnum action, string? expectedValue, string fileName)
{
// Arrange
InitDiscoverer(fileName, netZone);
@@ -162,7 +159,7 @@ public async void UrlTemplateTests(NetZoneEnum netZone, string extension, WopiAc
[InlineData(NetZoneEnum.InternalHttp, "docx", "Word", XmlOos2016)]
[InlineData(NetZoneEnum.InternalHttp, "html", null, XmlOos2016)]
[InlineData(NetZoneEnum.InternalHttp, "txt", null, XmlOos2016)]
- public async void AppNameTests(NetZoneEnum netZone, string extension, string expectedValue, string fileName)
+ public async void AppNameTests(NetZoneEnum netZone, string extension, string? expectedValue, string fileName)
{
// Arrange
InitDiscoverer(fileName, netZone);
@@ -179,7 +176,7 @@ public async void AppNameTests(NetZoneEnum netZone, string extension, string exp
[InlineData(NetZoneEnum.InternalHttp, "docx", "http://owaserver/wv/resources/1033/FavIcon_Word.ico", XmlOos2016)]
[InlineData(NetZoneEnum.InternalHttp, "html", null, XmlOos2016)]
[InlineData(NetZoneEnum.InternalHttp, "txt", null, XmlOos2016)]
- public async void FavIconTests(NetZoneEnum netZone, string extension, string expectedValue, string fileName)
+ public async void FavIconTests(NetZoneEnum netZone, string extension, string? expectedValue, string fileName)
{
// Arrange
InitDiscoverer(fileName, netZone);
diff --git a/test/WopiHost.Discovery.Tests/WopiHost.Discovery.Tests.csproj b/test/WopiHost.Discovery.Tests/WopiHost.Discovery.Tests.csproj
index ee521b4..9fcfa99 100644
--- a/test/WopiHost.Discovery.Tests/WopiHost.Discovery.Tests.csproj
+++ b/test/WopiHost.Discovery.Tests/WopiHost.Discovery.Tests.csproj
@@ -5,7 +5,33 @@
+
+ net8.0
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers
+
+
+ all
+ runtime; build; native; contentfiles; analyzers
+
+
diff --git a/test/WopiHost.FileSystemProvider.Tests/WopiHost.FileSystemProvider.Tests.csproj b/test/WopiHost.FileSystemProvider.Tests/WopiHost.FileSystemProvider.Tests.csproj
index cedd729..6efa1c4 100644
--- a/test/WopiHost.FileSystemProvider.Tests/WopiHost.FileSystemProvider.Tests.csproj
+++ b/test/WopiHost.FileSystemProvider.Tests/WopiHost.FileSystemProvider.Tests.csproj
@@ -1,5 +1,29 @@
+
+ net8.0
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers
+
+
+ all
+ runtime; build; native; contentfiles; analyzers
+
+
diff --git a/test/WopiHost.FileSystemProvider.Tests/WopiSecurityHandlerTests.cs b/test/WopiHost.FileSystemProvider.Tests/WopiSecurityHandlerTests.cs
index 9c51d97..7c54daf 100644
--- a/test/WopiHost.FileSystemProvider.Tests/WopiSecurityHandlerTests.cs
+++ b/test/WopiHost.FileSystemProvider.Tests/WopiSecurityHandlerTests.cs
@@ -3,8 +3,5 @@
public class WopiSecurityHandlerTests
{
[Fact]
- public void DummyTest()
- {
- Assert.True(true);
- }
+ public void DummyTest() => Assert.True(true);
}
diff --git a/test/WopiHost.Url.Tests/WopiHost.Url.Tests.csproj b/test/WopiHost.Url.Tests/WopiHost.Url.Tests.csproj
index 2d0d8a2..0c1a098 100644
--- a/test/WopiHost.Url.Tests/WopiHost.Url.Tests.csproj
+++ b/test/WopiHost.Url.Tests/WopiHost.Url.Tests.csproj
@@ -1,5 +1,29 @@
+
+ net8.0
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers
+
+
+ all
+ runtime; build; native; contentfiles; analyzers
+
+
diff --git a/test/WopiHost.Url.Tests/WopiUrlGeneratorTests.cs b/test/WopiHost.Url.Tests/WopiUrlGeneratorTests.cs
index 66401d2..651653d 100644
--- a/test/WopiHost.Url.Tests/WopiUrlGeneratorTests.cs
+++ b/test/WopiHost.Url.Tests/WopiUrlGeneratorTests.cs
@@ -49,7 +49,7 @@ public async void UrlWithAdditionalSettings(string extension, string wopiFileUrl
[Theory]
[InlineData("html", "http://wopihost:5000/wopi/files/test.xlsx", WopiActionEnum.Edit, null)]
- public async void NonExistentTemplate(string extension, string wopiFileUrl, WopiActionEnum action, string expectedValue)
+ public async void NonExistentTemplate(string extension, string wopiFileUrl, WopiActionEnum action, string? expectedValue)
{
// Arrange
var urlGenerator = new WopiUrlBuilder(_discoverer);