Skip to content

Commit

Permalink
Merge pull request #299 from NielsPilgaard/feature/blazor-server
Browse files Browse the repository at this point in the history
Migrate to InteractiveServer + Blazor Web App Built-in Authentication
  • Loading branch information
NielsPilgaard authored Feb 24, 2024
2 parents e02bb1e + c2d0798 commit fd834ea
Show file tree
Hide file tree
Showing 297 changed files with 9,153 additions and 7,156 deletions.
15 changes: 4 additions & 11 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -159,11 +159,9 @@ csharp_style_prefer_not_pattern = true:suggestion
csharp_style_prefer_extended_property_pattern = true:suggestion
dotnet_diagnostic.xunit2019.severity = warning
dotnet_diagnostic.xunit2001.severity = warning

[*.{c,c++,cc,cginc,compute,cp,cpp,cppm,cu,cuh,cxx,fx,fxh,h,hh,hlsl,hlsli,hlslinc,hpp,hxx,inc,inl,ino,ipp,ixx,mpp,mq4,mq5,mqh,tpp,usf,ush}]
indent_style = tab
indent_size = tab
tab_width = 4
csharp_using_directive_placement = outside_namespace:warning
csharp_prefer_braces = true:warning
csharp_style_namespace_declarations = file_scoped:warning

[*.{asax,ascx,aspx,axaml,cs,cshtml,htm,html,master,paml,razor,skin,vb,xaml,xamlx,xoml}]
indent_style = tab
Expand Down Expand Up @@ -205,11 +203,6 @@ dotnet_style_qualification_for_method = false:suggestion
dotnet_style_qualification_for_event = false:suggestion

[*.{appxmanifest,axml,build,config,csproj,dbml,discomap,dtd,jsproj,lsproj,njsproj,nuspec,proj,props,resw,resx,StyleCop,targets,tasks,vbproj,xml,xsd}]
indent_style = space
indent_size = 2
tab_width = 2

[*.{c,c++,cc,cginc,compute,cp,cpp,cppm,cs,cu,cuh,cxx,fx,fxh,h,hh,hlsl,hlsli,hlslinc,hpp,hxx,inc,inl,ino,ipp,ixx,mpp,mq4,mq5,mqh,tpp,usf,ush}]
indent_style = tab
indent_size = tab
indent_size = 4
tab_width = 4
2 changes: 1 addition & 1 deletion .github/workflows/website_frontend_ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
playwright:
runs-on: ubuntu-latest
container:
image: mcr.microsoft.com/playwright/dotnet:v1.40.0-jammy
image: mcr.microsoft.com/playwright/dotnet:v1.41.2-jammy
options: --user 1001
steps:
- name: Checkout
Expand Down
8 changes: 1 addition & 7 deletions Jordnaer.sln
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
README.md = README.md
.github\workflows\website_backend_ci.yml = .github\workflows\website_backend_ci.yml
.github\workflows\website_cd.yml = .github\workflows\website_cd.yml
.github\workflows\website_frontend_ci.yml = .github\workflows\website_frontend_ci.yml
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{3F3B23F8-EA95-44B5-B907-5E772A2660E2}"
Expand Down Expand Up @@ -55,8 +56,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Jordnaer.Load.Tests", "test
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Jordnaer", "src\web\Jordnaer\Jordnaer.csproj", "{06B65FD2-ABF3-4D58-9655-375C0C57B3C3}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Jordnaer.Client", "src\web\Jordnaer.Client\Jordnaer.Client.csproj", "{728773D3-66FD-4476-B585-FE5692CD8F2F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Jordnaer.Tests", "tests\web\Jordnaer.Tests\Jordnaer.Tests.csproj", "{26821232-1D4D-4CA8-AA41-7605C42C373A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Jordnaer.Benchmarks", "benchmarks\Jordnaer.Benchmarks\Jordnaer.Benchmarks.csproj", "{3C1DA78A-722B-485E-9D60-CC19ACFDA892}"
Expand Down Expand Up @@ -95,10 +94,6 @@ Global
{06B65FD2-ABF3-4D58-9655-375C0C57B3C3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{06B65FD2-ABF3-4D58-9655-375C0C57B3C3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{06B65FD2-ABF3-4D58-9655-375C0C57B3C3}.Release|Any CPU.Build.0 = Release|Any CPU
{728773D3-66FD-4476-B585-FE5692CD8F2F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{728773D3-66FD-4476-B585-FE5692CD8F2F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{728773D3-66FD-4476-B585-FE5692CD8F2F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{728773D3-66FD-4476-B585-FE5692CD8F2F}.Release|Any CPU.Build.0 = Release|Any CPU
{26821232-1D4D-4CA8-AA41-7605C42C373A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{26821232-1D4D-4CA8-AA41-7605C42C373A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{26821232-1D4D-4CA8-AA41-7605C42C373A}.Release|Any CPU.ActiveCfg = Release|Any CPU
Expand All @@ -124,7 +119,6 @@ Global
{D17408FE-1231-4CEC-8C7F-773915B70242} = {B4EAF579-8327-4B92-8357-8FF12C21755F}
{3F6E02C2-D7D6-43C4-9FEA-0E76FCA3F656} = {B4EAF579-8327-4B92-8357-8FF12C21755F}
{06B65FD2-ABF3-4D58-9655-375C0C57B3C3} = {7326F14D-ADB6-4CB0-9AE4-2717133CED27}
{728773D3-66FD-4476-B585-FE5692CD8F2F} = {7326F14D-ADB6-4CB0-9AE4-2717133CED27}
{26821232-1D4D-4CA8-AA41-7605C42C373A} = {B4EAF579-8327-4B92-8357-8FF12C21755F}
{3C1DA78A-722B-485E-9D60-CC19ACFDA892} = {B7172579-75AE-4D50-9328-3B0D80252384}
EndGlobalSection
Expand Down
30 changes: 15 additions & 15 deletions benchmarks/Jordnaer.Benchmarks/BenchmarkWebApplicationFactory.cs
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
using Jordnaer.Server.Database;
using Jordnaer.Database;
using Microsoft.AspNetCore.Mvc.Testing;

namespace Jordnaer.Server.Benchmarks;
namespace Jordnaer.Benchmarks;

public class BenchmarkWebApplicationFactory : WebApplicationFactory<Program>
{
public BenchmarkWebApplicationFactory()
{
Environment.SetEnvironmentVariable($"ConnectionStrings_{nameof(JordnaerDbContext)}",
"Server=localhost;" +
"Initial Catalog=jordnaer;" +
"User Id=sa;" +
"Password=6efe173b-3e33-4d6c-8f50-3e5f7cadd54c;" +
"Persist Security Info=True;" +
"MultipleActiveResultSets=False;" +
"Encrypt=False;" +
"TrustServerCertificate=True;" +
"Connection Timeout=30;");
}
public BenchmarkWebApplicationFactory()
{
Environment.SetEnvironmentVariable($"ConnectionStrings_{nameof(JordnaerDbContext)}",
"Server=localhost;" +
"Initial Catalog=jordnaer;" +
"User Id=sa;" +
"Password=6efe173b-3e33-4d6c-8f50-3e5f7cadd54c;" +
"Persist Security Info=True;" +
"MultipleActiveResultSets=False;" +
"Encrypt=False;" +
"TrustServerCertificate=True;" +
"Connection Timeout=30;");
}
}
2 changes: 1 addition & 1 deletion benchmarks/Jordnaer.Benchmarks/Jordnaer.Benchmarks.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.13.12" />
<PackageReference Include="Bogus" Version="35.4.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.2" />
</ItemGroup>

<ItemGroup>
Expand Down
40 changes: 20 additions & 20 deletions benchmarks/Jordnaer.Benchmarks/RenderProfileBenchmark.cs
Original file line number Diff line number Diff line change
@@ -1,39 +1,39 @@
using BenchmarkDotNet.Attributes;
using Jordnaer.Server.Database;
using Jordnaer.Database;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;

namespace Jordnaer.Server.Benchmarks;
namespace Jordnaer.Benchmarks;

[MemoryDiagnoser]
public class RenderProfileBenchmark
{
private string _userName = null!;
private HttpClient _client = null!;
private string _userName = null!;
private HttpClient _client = null!;

[GlobalSetup]
public async Task GlobalSetupAsync()
{
var factory = new BenchmarkWebApplicationFactory();
[GlobalSetup]
public async Task GlobalSetupAsync()
{
var factory = new BenchmarkWebApplicationFactory();

using var scope = factory.Services.CreateScope();
using var scope = factory.Services.CreateScope();

await using var context = scope.ServiceProvider.GetRequiredService<JordnaerDbContext>();
await using var context = scope.ServiceProvider.GetRequiredService<JordnaerDbContext>();

await context.Database.MigrateAsync();
await context.Database.MigrateAsync();

var categories = await context.InsertCategoriesAsync();
var categories = await context.InsertCategoriesAsync();

await context.InsertFakeUsersAsync(categories, 100);
await context.InsertFakeUsersAsync(categories, 100);

await context.SaveChangesAsync();
await context.SaveChangesAsync();

var user = await context.UserProfiles.FirstOrDefaultAsync();
_userName = user!.UserName!;
var user = await context.UserProfiles.FirstOrDefaultAsync();
_userName = user!.UserName!;

_client = factory.CreateClient();
}
_client = factory.CreateClient();
}

[Benchmark]
public async Task RenderProfileAsync() => await _client.GetAsync($"/{_userName}");
[Benchmark]
public async Task RenderProfileAsync() => await _client.GetAsync($"/{_userName}");
}
4 changes: 2 additions & 2 deletions benchmarks/Jordnaer.Benchmarks/StartBenchmark.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
using System.Reflection;
using BenchmarkDotNet.Running;

namespace Jordnaer.Server.Benchmarks;
namespace Jordnaer.Benchmarks;

public class StartBenchmark
{
public static void Main() => BenchmarkRunner.Run(Assembly.GetExecutingAssembly());
public static void Main() => BenchmarkRunner.Run(Assembly.GetExecutingAssembly());
}
172 changes: 85 additions & 87 deletions benchmarks/Jordnaer.Benchmarks/UserSearchBenchmark.cs
Original file line number Diff line number Diff line change
@@ -1,97 +1,95 @@
using BenchmarkDotNet.Attributes;
using Jordnaer.Client.Features.UserSearch;
using Jordnaer.Server.Database;
using Jordnaer.Database;
using Jordnaer.Features.UserSearch;
using Jordnaer.Shared;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Refit;

namespace Jordnaer.Server.Benchmarks;
namespace Jordnaer.Benchmarks;

//TODO: This fails because the search endpoint requires auth and has rate limiting
[MemoryDiagnoser]
public class UserSearchBenchmark
{
private IUserSearchClient _client = null!;
private JordnaerDbContext _context = null!;
private UserProfile _randomUser = null!;
private List<Category> _categories = new();

[GlobalSetup]
public async Task GlobalSetupAsync()
{
var factory = new BenchmarkWebApplicationFactory();
factory.ClientOptions.AllowAutoRedirect = false;

using var scope = factory.Services.CreateScope();

_context = scope.ServiceProvider.GetRequiredService<JordnaerDbContext>();

await _context.Database.MigrateAsync();

_categories = await _context.InsertCategoriesAsync();

await _context.InsertFakeUsersAsync(_categories);

await _context.SaveChangesAsync();

var httpClient = factory.CreateClient();

_randomUser = (await _context.UserProfiles
.Order()
.Skip(Random.Shared.Next(0, 10000))
.Take(1)
.FirstOrDefaultAsync())!;

_client = RestService.For<IUserSearchClient>(httpClient);
}

[Benchmark]
public async Task UserSearch_No_Filter() =>
await _client.GetUsers(new UserSearchFilter());

[Benchmark]
public async Task UserSearch_Filter_By_FirstName() =>
await _client.GetUsers(new UserSearchFilter { Name = _randomUser.FirstName });

[Benchmark]
public async Task UserSearch_Filter_By_LastName() =>
await _client.GetUsers(new UserSearchFilter { Name = _randomUser.LastName });

[Benchmark]
public async Task UserSearch_Filter_By_UserName() =>
await _client.GetUsers(new UserSearchFilter { Name = _randomUser.UserName });

[Benchmark]
public async Task UserSearch_Filter_By_Age_Of_Children()
{
int minimumAge = Random.Shared.Next(0, 14);
int maximumAge = Random.Shared.Next(minimumAge, 14);
await _client.GetUsers(new UserSearchFilter { MinimumChildAge = minimumAge, MaximumChildAge = maximumAge });
}

[Benchmark]
public async Task UserSearch_Filter_By_Category() =>
await _client.GetUsers(new UserSearchFilter
{
Categories = _categories
.Select(category => category.Name)
.Skip(Random.Shared.Next(0, _categories.Count))
.ToArray()
});

[Benchmark]
public async Task UserSearch_Filter_By_Gender_Of_Children()
{
var genders = Enum.GetValues<Gender>();
await _client.GetUsers(new UserSearchFilter { ChildGender = genders[Random.Shared.Next(0, genders.Length)] });
}

[Benchmark]
public async Task UserSearch_Filter_By_Address_Within_20_Kilometers() =>
await _client.GetUsers(new UserSearchFilter
{
Location = $"{_randomUser.Address}, {_randomUser.ZipCode} {_randomUser.City}",
WithinRadiusKilometers = 20
});
private IUserSearchService _service = null!;
private JordnaerDbContext _context = null!;
private UserProfile _randomUser = null!;
private List<Category> _categories = [];

[GlobalSetup]
public async Task GlobalSetupAsync()
{
var factory = new BenchmarkWebApplicationFactory();
factory.ClientOptions.AllowAutoRedirect = false;

const int userCount = 10000;

using var scope = factory.Services.CreateScope();

_context = scope.ServiceProvider.GetRequiredService<JordnaerDbContext>();

await _context.Database.MigrateAsync();

_categories = await _context.InsertCategoriesAsync();

await _context.InsertFakeUsersAsync(_categories, userCount);

await _context.SaveChangesAsync();

_randomUser = (await _context.UserProfiles
.OrderBy(x => x.Id)
.Skip(Random.Shared.Next(userCount))
.Take(1)
.FirstOrDefaultAsync())!;

_service = scope.ServiceProvider.GetRequiredService<IUserSearchService>();
}

[Benchmark]
public async Task UserSearch_No_Filter() =>
await _service.GetUsersAsync(new UserSearchFilter());

[Benchmark]
public async Task UserSearch_Filter_By_FirstName() =>
await _service.GetUsersAsync(new UserSearchFilter { Name = _randomUser.FirstName });

[Benchmark]
public async Task UserSearch_Filter_By_LastName() =>
await _service.GetUsersAsync(new UserSearchFilter { Name = _randomUser.LastName });

[Benchmark]
public async Task UserSearch_Filter_By_UserName() =>
await _service.GetUsersAsync(new UserSearchFilter { Name = _randomUser.UserName });

[Benchmark]
public async Task UserSearch_Filter_By_Age_Of_Children()
{
var minimumAge = Random.Shared.Next(0, 14);
var maximumAge = Random.Shared.Next(minimumAge, 14);
await _service.GetUsersAsync(new UserSearchFilter { MinimumChildAge = minimumAge, MaximumChildAge = maximumAge });
}

[Benchmark]
public async Task UserSearch_Filter_By_Category() =>
await _service.GetUsersAsync(new UserSearchFilter
{
Categories = _categories
.Select(category => category.Name)
.Skip(Random.Shared.Next(0, _categories.Count))
.ToArray()
});

[Benchmark]
public async Task UserSearch_Filter_By_Gender_Of_Children()
{
var genders = Enum.GetValues<Gender>();
await _service.GetUsersAsync(new UserSearchFilter { ChildGender = genders[Random.Shared.Next(0, genders.Length)] });
}

[Benchmark]
public async Task UserSearch_Filter_By_Address_Within_20_Kilometers() =>
await _service.GetUsersAsync(new UserSearchFilter
{
Location = $"{_randomUser.Address}, {_randomUser.ZipCode} {_randomUser.City}",
WithinRadiusKilometers = 20
});
}
2 changes: 0 additions & 2 deletions robots.txt

This file was deleted.

4 changes: 2 additions & 2 deletions src/container_apps/Jordnaer.Chat/Jordnaer.Chat.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@

<PackageReference Include="Microsoft.Azure.AppConfiguration.AspNetCore" Version="7.0.0" />

<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.1">
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.2">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
Expand Down
Loading

0 comments on commit fd834ea

Please sign in to comment.