Skip to content

Commit

Permalink
Hosting extensions (#16)
Browse files Browse the repository at this point in the history
* Hosting extensions

* Packaging

* Documentation

* Merge into single new project

* Test project

* Self-hosted attribute with tests

* Hyphens

* Move to new attributes folder
  • Loading branch information
withinfocus authored Sep 25, 2024
1 parent 053b659 commit 0e2fa35
Show file tree
Hide file tree
Showing 13 changed files with 554 additions and 1 deletion.
19 changes: 18 additions & 1 deletion bitwarden-dotnet.sln
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@


Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
Expand All @@ -23,6 +23,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MinimalApis", "extensions\B
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bitwarden.Core.Microbenchmarks", "extensions\Bitwarden.Core\perf\Bitwarden.Core.Microbenchmarks.csproj", "{6DBBD50B-4FA1-4043-A0F0-D4D4A5BBC1BD}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bitwarden.Extensions.Hosting", "extensions\Bitwarden.Extensions.Hosting\src\Bitwarden.Extensions.Hosting.csproj", "{F5B1A2C7-2B1D-4164-9A8E-41FD9E0FF6F0}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Bitwarden.Extensions.Hosting", "Bitwarden.Extensions.Hosting", "{A1C893A6-887B-44FE-9DA3-B85E6ACADC55}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bitwarden.Extensions.Hosting.Tests", "extensions\Bitwarden.Extensions.Hosting\tests\Bitwarden.Extensions.Hosting.Tests.csproj", "{2EABE7A5-6B68-4DAC-9D37-F312059C3C27}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -56,6 +62,14 @@ Global
{6DBBD50B-4FA1-4043-A0F0-D4D4A5BBC1BD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6DBBD50B-4FA1-4043-A0F0-D4D4A5BBC1BD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6DBBD50B-4FA1-4043-A0F0-D4D4A5BBC1BD}.Release|Any CPU.Build.0 = Release|Any CPU
{F5B1A2C7-2B1D-4164-9A8E-41FD9E0FF6F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F5B1A2C7-2B1D-4164-9A8E-41FD9E0FF6F0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F5B1A2C7-2B1D-4164-9A8E-41FD9E0FF6F0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F5B1A2C7-2B1D-4164-9A8E-41FD9E0FF6F0}.Release|Any CPU.Build.0 = Release|Any CPU
{2EABE7A5-6B68-4DAC-9D37-F312059C3C27}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2EABE7A5-6B68-4DAC-9D37-F312059C3C27}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2EABE7A5-6B68-4DAC-9D37-F312059C3C27}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2EABE7A5-6B68-4DAC-9D37-F312059C3C27}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{5EC8B943-2E9E-437D-9FFC-D18B5DB4D7D0} = {695C76EF-1102-4805-970F-7C995EE54930}
Expand All @@ -67,5 +81,8 @@ Global
{8308DD08-D336-4A13-ACD1-4FA367C3C2D4} = {0008B44C-95E9-4A33-92EF-66741AC8AE47}
{1BD7DE1A-F62C-4E6F-8BC5-6574E2C2E258} = {8308DD08-D336-4A13-ACD1-4FA367C3C2D4}
{6DBBD50B-4FA1-4043-A0F0-D4D4A5BBC1BD} = {5EC8B943-2E9E-437D-9FFC-D18B5DB4D7D0}
{A1C893A6-887B-44FE-9DA3-B85E6ACADC55} = {695C76EF-1102-4805-970F-7C995EE54930}
{F5B1A2C7-2B1D-4164-9A8E-41FD9E0FF6F0} = {A1C893A6-887B-44FE-9DA3-B85E6ACADC55}
{2EABE7A5-6B68-4DAC-9D37-F312059C3C27} = {A1C893A6-887B-44FE-9DA3-B85E6ACADC55}
EndGlobalSection
EndGlobal
60 changes: 60 additions & 0 deletions extensions/Bitwarden.Extensions.Hosting/src/AssemblyHelpers.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
using System.Reflection;

namespace Bitwarden.Extensions.Hosting;

/// <summary>
/// Helper class for working with assembly attributes.
/// </summary>
public static class AssemblyHelpers
{
private const string _gitHashAssemblyKey = "GitHash";

private static readonly IEnumerable<AssemblyMetadataAttribute> _assemblyMetadataAttributes;
private static readonly AssemblyInformationalVersionAttribute? _assemblyInformationalVersionAttributes;
private static string? _version;
private static string? _gitHash;

static AssemblyHelpers()
{
_assemblyMetadataAttributes = Assembly.GetEntryAssembly()!
.GetCustomAttributes<AssemblyMetadataAttribute>();
_assemblyInformationalVersionAttributes = Assembly.GetEntryAssembly()!
.GetCustomAttribute<AssemblyInformationalVersionAttribute>();
}

/// <summary>
/// Gets the version of the entry assembly.
/// </summary>
/// <returns></returns>
public static string? GetVersion()
{
if (string.IsNullOrWhiteSpace(_version))
{
_version = _assemblyInformationalVersionAttributes?.InformationalVersion;
}

return _version;
}

/// <summary>
/// Gets the Git hash of the entry assembly.
/// </summary>
/// <returns></returns>
public static string? GetGitHash()
{
if (string.IsNullOrWhiteSpace(_gitHash))
{
try
{
_gitHash = _assemblyMetadataAttributes.First(i =>
i.Key == _gitHashAssemblyKey).Value;
}
catch (Exception)
{
// suppress
}
}

return _gitHash;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using Bitwarden.Extensions.Hosting.Exceptions;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.DependencyInjection;

namespace Bitwarden.Extensions.Hosting.Attributes;

/// <summary>
/// Attribute to indicate that an instance is self-hosted.
/// </summary>
public class SelfHostedAttribute : ActionFilterAttribute
{
/// <summary>
/// Gets or sets a value indicating whether the attribute is only allowed when self-hosted.
/// </summary>
public bool SelfHostedOnly { get; init; }
/// <summary>
/// Gets or sets a value indicating whether the attribute is only allowed when not self-hosted.
/// </summary>
public bool NotSelfHostedOnly { get; init; }

/// <summary>
/// Initializes a new instance of the <see cref="SelfHostedAttribute"/> class.
/// </summary>
/// <param name="context">Action context.</param>
/// <exception cref="BadRequestException"></exception>
public override void OnActionExecuting(ActionExecutingContext context)
{
var globalSettings = context.HttpContext.RequestServices.GetRequiredService<GlobalSettingsBase>();
if (SelfHostedOnly && !globalSettings.IsSelfHosted)
{
throw new BadRequestException("Only allowed when self-hosted.");
}
else if (NotSelfHostedOnly && globalSettings.IsSelfHosted)
{
throw new BadRequestException("Only allowed when not self-hosted.");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<IsPackable>true</IsPackable>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<PropertyGroup>
<Authors>Bitwarden</Authors>
<Description>.NET hosting extensions library</Description>
<PackageProjectUrl>https://github.com/bitwarden/dotnet-extensions</PackageProjectUrl>
<PackageReleaseNotes>https://github.com/bitwarden/dotnet-extensions/releases</PackageReleaseNotes>
<PackageLicenseExpression>GPL-3.0-only</PackageLicenseExpression>
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
<PackageReadmeFile>README.md</PackageReadmeFile>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<DebugType>embedded</DebugType>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.8.1" />
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.8.1" />
<PackageReference Include="Serilog.Extensions.Hosting" Version="8.0.0" />
<PackageReference Include="Serilog.Formatting.Compact" Version="2.0.0" />
<PackageReference Include="Serilog.Settings.Configuration" Version="8.0.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="5.0.1" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
</ItemGroup>

<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Serilog.AspNetCore" Version="8.0.1" />
</ItemGroup>

<ItemGroup>
<None Include=".\README.md" Pack="true" PackagePath="\" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
namespace Bitwarden.Extensions.Hosting;

/// <summary>
/// Options for configuring the Bitwarden host.
/// </summary>
public class BitwardenHostOptions
{
/// <summary>
/// Gets or sets a value indicating whether to include request logging.
/// </summary>
public bool IncludeLogging { get; set; } = true;
/// <summary>
/// Gets or sets a value indicating whether to include metrics.
/// </summary>
public bool IncludeMetrics { get; set; } = true;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using Bitwarden.Extensions.Hosting;

namespace Bitwarden.Extensions.WebHosting;

/// <summary>
/// Options for configuring the web host.
/// </summary>
public class BitwardenWebHostOptions : BitwardenHostOptions
{
/// <summary>
/// Gets or sets a value indicating whether to include request logging.
/// </summary>
public bool IncludeRequestLogging { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace Bitwarden.Extensions.Hosting.Exceptions;

/// <summary>
/// Exception for when a request is invalid.
/// </summary>
public class BadRequestException : Exception
{
/// <summary>
/// Initializes a new instance of the <see cref="BadRequestException"/> class.
/// </summary>
/// <param name="message">Error message.</param>
public BadRequestException(string message)
: base(message)
{ }
}
12 changes: 12 additions & 0 deletions extensions/Bitwarden.Extensions.Hosting/src/GlobalSettingsBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace Bitwarden.Extensions.Hosting;

/// <summary>
/// Global settings.
/// </summary>
public class GlobalSettingsBase
{
/// <summary>
/// Gets or sets a value indicating whether the application is self-hosted.
/// </summary>
public bool IsSelfHosted { get; set; }
}
Loading

0 comments on commit 0e2fa35

Please sign in to comment.