mirror of
https://github.com/fiodarsazanavets/aspire-13-examples.git
synced 2026-06-20 12:23:14 +00:00
Add MailDev components
This commit is contained in:
@@ -0,0 +1,52 @@
|
|||||||
|
using Microsoft.AspNetCore.Authentication;
|
||||||
|
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||||
|
using Microsoft.IdentityModel.Tokens;
|
||||||
|
|
||||||
|
namespace OnlineShop.ApiService
|
||||||
|
{
|
||||||
|
public static class AuthExtensions
|
||||||
|
{
|
||||||
|
public static void ConfigureApiJwt(this AuthenticationBuilder authentication)
|
||||||
|
{
|
||||||
|
// Named options
|
||||||
|
authentication.Services
|
||||||
|
.AddOptions<JwtBearerOptions>(
|
||||||
|
JwtBearerDefaults.AuthenticationScheme)
|
||||||
|
.Configure<
|
||||||
|
IConfiguration,
|
||||||
|
IHttpClientFactory,
|
||||||
|
IHostEnvironment>(Configure);
|
||||||
|
|
||||||
|
// Unnamed options
|
||||||
|
authentication.Services.AddOptions<JwtBearerOptions>()
|
||||||
|
.Configure<
|
||||||
|
IConfiguration,
|
||||||
|
IHttpClientFactory,
|
||||||
|
IHostEnvironment>(Configure);
|
||||||
|
|
||||||
|
static void Configure(
|
||||||
|
JwtBearerOptions options,
|
||||||
|
IConfiguration configuration,
|
||||||
|
IHttpClientFactory httpClientFactory,
|
||||||
|
IHostEnvironment hostEnvironment)
|
||||||
|
{
|
||||||
|
var backchannelHttpClient =
|
||||||
|
httpClientFactory.CreateClient(
|
||||||
|
"OidcBackchannel");
|
||||||
|
|
||||||
|
options.Backchannel = backchannelHttpClient;
|
||||||
|
options.Authority =
|
||||||
|
backchannelHttpClient
|
||||||
|
.GetIdpAuthorityUri().ToString();
|
||||||
|
options.RequireHttpsMetadata =
|
||||||
|
!hostEnvironment.IsDevelopment();
|
||||||
|
options.MapInboundClaims = false;
|
||||||
|
options.TokenValidationParameters =
|
||||||
|
new TokenValidationParameters
|
||||||
|
{
|
||||||
|
ValidateAudience = false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,6 +11,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="10.0.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.0" />
|
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,31 @@
|
|||||||
|
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||||
|
using OnlineShop.ApiService;
|
||||||
|
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
// Add service defaults & Aspire client integrations.
|
|
||||||
builder.AddServiceDefaults();
|
builder.AddServiceDefaults();
|
||||||
|
|
||||||
// Add services to the container.
|
|
||||||
builder.Services.AddProblemDetails();
|
builder.Services.AddProblemDetails();
|
||||||
|
|
||||||
// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi
|
|
||||||
builder.Services.AddOpenApi();
|
builder.Services.AddOpenApi();
|
||||||
|
|
||||||
|
builder.Services.AddHttpClient(
|
||||||
|
"OidcBackchannel", o => o.BaseAddress = new("http://idp"));
|
||||||
|
|
||||||
|
builder.Services.AddAuthentication(options =>
|
||||||
|
{
|
||||||
|
options.DefaultAuthenticateScheme =
|
||||||
|
JwtBearerDefaults.AuthenticationScheme;
|
||||||
|
options.DefaultChallengeScheme =
|
||||||
|
JwtBearerDefaults.AuthenticationScheme;
|
||||||
|
|
||||||
|
})
|
||||||
|
.AddJwtBearer()
|
||||||
|
.ConfigureApiJwt();
|
||||||
|
|
||||||
|
|
||||||
var app = builder.Build();
|
var app = builder.Build();
|
||||||
|
|
||||||
// Configure the HTTP request pipeline.
|
|
||||||
app.UseExceptionHandler();
|
app.UseExceptionHandler();
|
||||||
|
|
||||||
if (app.Environment.IsDevelopment())
|
if (app.Environment.IsDevelopment())
|
||||||
|
|||||||
@@ -1,13 +1,17 @@
|
|||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using OnlineShop.AppHost.Extensions;
|
using OnlineShop.AppHost.Extensions;
|
||||||
|
using OnlineShop.MailDev.Hosting;
|
||||||
|
|
||||||
var builder = DistributedApplication.CreateBuilder(args);
|
var builder = DistributedApplication.CreateBuilder(args);
|
||||||
|
|
||||||
|
var maildev = builder.AddMailDev("maildev");
|
||||||
|
|
||||||
var idp = builder.AddKeycloakContainer(
|
var idp = builder.AddKeycloakContainer(
|
||||||
"idp", tag: "23.0")
|
"idp", tag: "23.0")
|
||||||
.ImportRealms("Keycloak")
|
.ImportRealms("Keycloak")
|
||||||
.WithExternalHttpEndpoints();
|
.WithExternalHttpEndpoints();
|
||||||
|
|
||||||
|
var cache = builder.AddRedis("cache");
|
||||||
|
|
||||||
var apiService = builder.AddProject<Projects.OnlineShop_ApiService>("apiservice")
|
var apiService = builder.AddProject<Projects.OnlineShop_ApiService>("apiservice")
|
||||||
.WithHttpHealthCheck("/health")
|
.WithHttpHealthCheck("/health")
|
||||||
@@ -21,7 +25,9 @@ var webFrontend = builder
|
|||||||
.WithHttpHealthCheck("/health")
|
.WithHttpHealthCheck("/health")
|
||||||
.WithReference(apiService)
|
.WithReference(apiService)
|
||||||
.WithReference(idp, env: "Identity__ClientSecret")
|
.WithReference(idp, env: "Identity__ClientSecret")
|
||||||
.WaitFor(idp);
|
.WaitFor(idp)
|
||||||
|
.WithReference(cache)
|
||||||
|
.WaitFor(cache);
|
||||||
|
|
||||||
if (builder.Environment.IsDevelopment())
|
if (builder.Environment.IsDevelopment())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<Project Sdk="Aspire.AppHost.Sdk/13.0.1">
|
<Project Sdk="Aspire.AppHost.Sdk/13.0.1">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
@@ -8,11 +8,20 @@
|
|||||||
<UserSecretsId>2f2ef062-99af-422f-b6a5-1094759553e7</UserSecretsId>
|
<UserSecretsId>2f2ef062-99af-422f-b6a5-1094759553e7</UserSecretsId>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Aspire.Hosting.Redis" Version="13.0.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\OnlineShop.ApiService\OnlineShop.ApiService.csproj" />
|
<ProjectReference Include="..\OnlineShop.ApiService\OnlineShop.ApiService.csproj" />
|
||||||
<ProjectReference Include="..\OnlineShop.Web\OnlineShop.Web.csproj" />
|
<ProjectReference Include="..\OnlineShop.Web\OnlineShop.Web.csproj" />
|
||||||
|
<ProjectReference
|
||||||
|
Include="..\OnlineShop.MailDev.Hosting\OnlineShop.MailDev.Hosting.csproj"
|
||||||
|
IsAspireProjectResource="false" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Update="Keycloak\import.json">
|
<None Update="Keycloak\import.json">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
|||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
namespace OnlineShop.MailDev.Hosting;
|
||||||
|
|
||||||
|
internal static class MailDevContainerImageTags
|
||||||
|
{
|
||||||
|
internal const string Registry = "docker.io";
|
||||||
|
|
||||||
|
internal const string Image = "maildev/maildev";
|
||||||
|
|
||||||
|
internal const string Tag = "2.1.0";
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
using Aspire.Hosting.ApplicationModel;
|
||||||
|
|
||||||
|
namespace OnlineShop.MailDev.Hosting;
|
||||||
|
|
||||||
|
public sealed class MailDevResource(string name) :
|
||||||
|
ContainerResource(name), IResourceWithConnectionString
|
||||||
|
{
|
||||||
|
internal const string SmtpEndpointName = "smtp";
|
||||||
|
internal const string HttpEndpointName = "http";
|
||||||
|
|
||||||
|
private EndpointReference? _smtpReference;
|
||||||
|
|
||||||
|
public EndpointReference SmtpEndpoint =>
|
||||||
|
_smtpReference ??= new(this, SmtpEndpointName);
|
||||||
|
|
||||||
|
public ReferenceExpression ConnectionStringExpression =>
|
||||||
|
ReferenceExpression.Create(
|
||||||
|
$"smtp://{SmtpEndpoint.Property(EndpointProperty.Host)}:{SmtpEndpoint.Property(EndpointProperty.Port)}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
+31
@@ -0,0 +1,31 @@
|
|||||||
|
using Aspire.Hosting;
|
||||||
|
using Aspire.Hosting.ApplicationModel;
|
||||||
|
|
||||||
|
namespace OnlineShop.MailDev.Hosting;
|
||||||
|
|
||||||
|
public static class MailDevResourceBuilderExtensions
|
||||||
|
{
|
||||||
|
public static IResourceBuilder<MailDevResource> AddMailDev(
|
||||||
|
this IDistributedApplicationBuilder builder,
|
||||||
|
string name,
|
||||||
|
int? httpPort = null,
|
||||||
|
int? smtpPort = null)
|
||||||
|
{
|
||||||
|
MailDevResource resource = new(name);
|
||||||
|
|
||||||
|
return builder.AddResource(resource)
|
||||||
|
.WithImage(MailDevContainerImageTags.Image)
|
||||||
|
.WithImageRegistry(MailDevContainerImageTags.Registry)
|
||||||
|
.WithImageTag(MailDevContainerImageTags.Tag)
|
||||||
|
.WithHttpEndpoint(
|
||||||
|
targetPort: 1080,
|
||||||
|
port: httpPort,
|
||||||
|
name: MailDevResource.HttpEndpointName)
|
||||||
|
.WithEndpoint(
|
||||||
|
targetPort: 1025,
|
||||||
|
port: smtpPort,
|
||||||
|
name: MailDevResource.SmtpEndpointName);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Aspire.Hosting" Version="13.0.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
using Microsoft.AspNetCore.Authentication;
|
||||||
|
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
|
||||||
|
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
|
||||||
|
|
||||||
|
namespace OnlineShop.Web;
|
||||||
|
|
||||||
|
public static class AuthExtensions
|
||||||
|
{
|
||||||
|
public static void ConfigureWebAppOpenIdConnect(this AuthenticationBuilder authentication)
|
||||||
|
{
|
||||||
|
// Named options
|
||||||
|
authentication.Services
|
||||||
|
.AddOptions<OpenIdConnectOptions>(
|
||||||
|
OpenIdConnectDefaults.AuthenticationScheme)
|
||||||
|
.Configure<
|
||||||
|
IConfiguration,
|
||||||
|
IHttpClientFactory,
|
||||||
|
IHostEnvironment>(Configure);
|
||||||
|
|
||||||
|
// Unnamed options
|
||||||
|
authentication.Services.AddOptions<OpenIdConnectOptions>()
|
||||||
|
.Configure<
|
||||||
|
IConfiguration,
|
||||||
|
IHttpClientFactory,
|
||||||
|
IHostEnvironment>(Configure);
|
||||||
|
|
||||||
|
static void Configure(
|
||||||
|
OpenIdConnectOptions options,
|
||||||
|
IConfiguration configuration,
|
||||||
|
IHttpClientFactory httpClientFactory,
|
||||||
|
IHostEnvironment hostEnvironment)
|
||||||
|
{
|
||||||
|
var backchannelHttpClient =
|
||||||
|
httpClientFactory.CreateClient(
|
||||||
|
"OidcBackchannel");
|
||||||
|
|
||||||
|
options.Backchannel = backchannelHttpClient;
|
||||||
|
options.Authority =
|
||||||
|
backchannelHttpClient
|
||||||
|
.GetIdpAuthorityUri().ToString();
|
||||||
|
options.ClientId = "webapp";
|
||||||
|
options.ClientSecret =
|
||||||
|
Environment
|
||||||
|
.GetEnvironmentVariable(
|
||||||
|
"Identity__ClientSecret");
|
||||||
|
options.ResponseType =
|
||||||
|
OpenIdConnectResponseType.Code;
|
||||||
|
options.SaveTokens = true;
|
||||||
|
options.RequireHttpsMetadata =
|
||||||
|
!hostEnvironment.IsDevelopment();
|
||||||
|
options.MapInboundClaims = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -6,6 +6,11 @@
|
|||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Aspire.StackExchange.Redis.OutputCaching" Version="13.0.1" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="10.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\OnlineShop.ServiceDefaults\OnlineShop.ServiceDefaults.csproj" />
|
<ProjectReference Include="..\OnlineShop.ServiceDefaults\OnlineShop.ServiceDefaults.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -1,30 +1,45 @@
|
|||||||
|
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||||
|
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
|
||||||
using OnlineShop.Web;
|
using OnlineShop.Web;
|
||||||
using OnlineShop.Web.Components;
|
using OnlineShop.Web.Components;
|
||||||
|
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
// Add service defaults & Aspire client integrations.
|
builder.AddRedisOutputCache("cache");
|
||||||
|
|
||||||
builder.AddServiceDefaults();
|
builder.AddServiceDefaults();
|
||||||
|
|
||||||
// Add services to the container.
|
|
||||||
builder.Services.AddRazorComponents()
|
builder.Services.AddRazorComponents()
|
||||||
.AddInteractiveServerComponents();
|
.AddInteractiveServerComponents();
|
||||||
|
|
||||||
builder.Services.AddOutputCache();
|
builder.Services.AddOutputCache();
|
||||||
|
|
||||||
|
builder.Services.AddHttpClient(
|
||||||
|
"OidcBackchannel", o => o.BaseAddress = new("http://idp"));
|
||||||
|
|
||||||
builder.Services.AddHttpClient<WeatherApiClient>(client =>
|
builder.Services.AddHttpClient<WeatherApiClient>(client =>
|
||||||
{
|
{
|
||||||
// This URL uses "https+http://" to indicate HTTPS is preferred over HTTP.
|
|
||||||
// Learn more about service discovery scheme resolution at https://aka.ms/dotnet/sdschemes.
|
|
||||||
client.BaseAddress = new("https+http://apiservice");
|
client.BaseAddress = new("https+http://apiservice");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
builder.Services.AddAuthentication(options =>
|
||||||
|
{
|
||||||
|
options.DefaultScheme =
|
||||||
|
CookieAuthenticationDefaults.AuthenticationScheme;
|
||||||
|
options.DefaultChallengeScheme =
|
||||||
|
OpenIdConnectDefaults.AuthenticationScheme;
|
||||||
|
})
|
||||||
|
.AddCookie(
|
||||||
|
CookieAuthenticationDefaults.AuthenticationScheme)
|
||||||
|
.AddOpenIdConnect()
|
||||||
|
.ConfigureWebAppOpenIdConnect();
|
||||||
|
|
||||||
|
|
||||||
var app = builder.Build();
|
var app = builder.Build();
|
||||||
|
|
||||||
if (!app.Environment.IsDevelopment())
|
if (!app.Environment.IsDevelopment())
|
||||||
{
|
{
|
||||||
app.UseExceptionHandler("/Error", createScopeForErrors: true);
|
app.UseExceptionHandler("/Error", createScopeForErrors: true);
|
||||||
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
|
|
||||||
app.UseHsts();
|
app.UseHsts();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<Solution>
|
<Solution>
|
||||||
<Project Path="OnlineShop.ApiService/OnlineShop.ApiService.csproj" />
|
<Project Path="OnlineShop.ApiService/OnlineShop.ApiService.csproj" />
|
||||||
<Project Path="OnlineShop.AppHost/OnlineShop.AppHost.csproj" />
|
<Project Path="OnlineShop.AppHost/OnlineShop.AppHost.csproj" />
|
||||||
|
<Project Path="OnlineShop.MailDev.Hosting/OnlineShop.MailDev.Hosting.csproj" Id="bcd7a762-a5a4-4043-9990-a00cca6b4a91" />
|
||||||
<Project Path="OnlineShop.ServiceDefaults/OnlineShop.ServiceDefaults.csproj" />
|
<Project Path="OnlineShop.ServiceDefaults/OnlineShop.ServiceDefaults.csproj" />
|
||||||
<Project Path="OnlineShop.Web/OnlineShop.Web.csproj" />
|
<Project Path="OnlineShop.Web/OnlineShop.Web.csproj" />
|
||||||
</Solution>
|
</Solution>
|
||||||
|
|||||||
Reference in New Issue
Block a user