From 3c3f0b37013ee5a5278cd91225f643f1fb42cb1e Mon Sep 17 00:00:00 2001 From: Ivan Kozelskikh Date: Sun, 2 Aug 2026 21:37:40 +0500 Subject: [PATCH 01/23] Migrate AppHost to Aspire v13 and .NET 10 Upgrade the AppHost to Aspire 13.4.6 and TargetFramework net10.0; rename Program.cs to AppHost.cs. Bump Aspire package refs and dotnet tools (dotnet-ef -> 10.0.10, add aspire.cli). Update RabbitMQ and Postgres images (postgis/postgis 18-3.6, pgAdmin 9.17) and switch Mailhog -> MailPit (v1.30) with new MailPit package. Add aspire.config.json and nuget.config, provide development parameter defaults, rename some data volumes, and remove legacy Docker Compose, Dockerfile, launchSettings and dockerignore artifacts. --- .dockerignore | 30 --------- CommentMap.AppHost/{Program.cs => AppHost.cs} | 38 ++++++------ CommentMap.AppHost/CommentMap.AppHost.csproj | 12 ++-- .../appsettings.Development.json | 6 ++ CommentMap.Mvc/.dockerignore | 10 --- CommentMap.Mvc/Dockerfile | 35 ----------- aspire.config.json | 5 ++ docker-compose.dcproj | 19 ------ docker-compose.override.yml | 14 ----- docker-compose.yml | 61 ------------------- .../dotnet-tools.json => dotnet-tools.json | 9 ++- launchSettings.json | 15 ----- nuget.config | 12 ++++ 13 files changed, 54 insertions(+), 212 deletions(-) delete mode 100644 .dockerignore rename CommentMap.AppHost/{Program.cs => AppHost.cs} (53%) delete mode 100644 CommentMap.Mvc/.dockerignore delete mode 100644 CommentMap.Mvc/Dockerfile create mode 100644 aspire.config.json delete mode 100644 docker-compose.dcproj delete mode 100644 docker-compose.override.yml delete mode 100644 docker-compose.yml rename .config/dotnet-tools.json => dotnet-tools.json (66%) delete mode 100644 launchSettings.json create mode 100644 nuget.config diff --git a/.dockerignore b/.dockerignore deleted file mode 100644 index fe1152b..0000000 --- a/.dockerignore +++ /dev/null @@ -1,30 +0,0 @@ -**/.classpath -**/.dockerignore -**/.env -**/.git -**/.gitignore -**/.project -**/.settings -**/.toolstarget -**/.vs -**/.vscode -**/*.*proj.user -**/*.dbmdl -**/*.jfm -**/azds.yaml -**/bin -**/charts -**/docker-compose* -**/Dockerfile* -**/node_modules -**/npm-debug.log -**/obj -**/secrets.dev.yaml -**/values.dev.yaml -LICENSE -README.md -!**/.gitignore -!.git/HEAD -!.git/config -!.git/packed-refs -!.git/refs/heads/** \ No newline at end of file diff --git a/CommentMap.AppHost/Program.cs b/CommentMap.AppHost/AppHost.cs similarity index 53% rename from CommentMap.AppHost/Program.cs rename to CommentMap.AppHost/AppHost.cs index 3d189a9..9d0f83a 100644 --- a/CommentMap.AppHost/Program.cs +++ b/CommentMap.AppHost/AppHost.cs @@ -1,37 +1,35 @@ var builder = DistributedApplication.CreateBuilder(args); -var rabbitUsername = builder.AddParameter("rabbit-username", secret: true); +var rabbitUsername = builder.AddParameter("rabbit-username"); var rabbitPassword = builder.AddParameter("rabbit-password", secret: true); var rabbitmq = builder.AddRabbitMQ("messaging", rabbitUsername, rabbitPassword) - .WithImageTag("4.0.7-alpine") + .WithImageTag("4.3.4") .WithManagementPlugin() - .WithDataVolume("messaging_data"); + .WithDataVolume("messaging-data"); -var mailpit = builder - .AddContainer("mailpit", "axllent/mailpit", "v1.23") - .WithEndpoint(port: 1025, targetPort: 1025, scheme: "smtp", name: "smtp") - .WithHttpEndpoint(8025, 8025) - .WithVolume("mailpit_data", "/data"); -var smtpEndpoint = mailpit.GetEndpoint("smtp"); +var pgUsername = builder.AddParameter("pg-username"); +var pgPassword = builder.AddParameter("pg-password", secret: true); +var postgres = builder.AddPostgres("postgres", pgUsername, pgPassword) + .WithImage("postgis/postgis", "18-3.6") + .WithPgAdmin(o => o.WithImageTag("9.17")) + .WithDataVolume("comment-map-data"); +var commentMapDb = postgres.AddDatabase("comment-map"); -builder.AddProject("email-sender") - .WithReference(rabbitmq) - .WaitFor(rabbitmq) - .WithReference(smtpEndpoint); +var mailpit = builder.AddMailPit("mailpit") + .WithImageTag("v1.30") + .WithDataVolume("mailpit-data"); -var pgUsername = builder.AddParameter("pg-username", secret: true); -var pgPassword = builder.AddParameter("pg-password", secret: true); -var postgres = builder.AddPostgres("postgres", pgUsername, pgPassword) - .WithImage("postgis/postgis", "17-3.5-alpine") - .WithPgAdmin(o => o.WithImageTag("9.1")) - .WithDataVolume("comment-map_data"); -var commentMapDb = postgres.AddDatabase("comment-map"); +builder.AddProject("email-sender") + .WithReference(rabbitmq) + .WaitFor(rabbitmq) + .WithReference(mailpit) + .WaitFor(mailpit); builder.AddProject("mvc") diff --git a/CommentMap.AppHost/CommentMap.AppHost.csproj b/CommentMap.AppHost/CommentMap.AppHost.csproj index 7008974..3e32e71 100644 --- a/CommentMap.AppHost/CommentMap.AppHost.csproj +++ b/CommentMap.AppHost/CommentMap.AppHost.csproj @@ -1,10 +1,8 @@ - - - + Exe - net9.0 + net10.0 enable enable true @@ -12,9 +10,9 @@ - - - + + + diff --git a/CommentMap.AppHost/appsettings.Development.json b/CommentMap.AppHost/appsettings.Development.json index 0c208ae..eddbcdc 100644 --- a/CommentMap.AppHost/appsettings.Development.json +++ b/CommentMap.AppHost/appsettings.Development.json @@ -4,5 +4,11 @@ "Default": "Information", "Microsoft.AspNetCore": "Warning" } + }, + "Parameters": { + "rabbit-username": "guest", + "rabbit-password": "guest", + "pg-username": "comment-map", + "pg-password": "P@ssw0rd" } } diff --git a/CommentMap.Mvc/.dockerignore b/CommentMap.Mvc/.dockerignore deleted file mode 100644 index bf7592f..0000000 --- a/CommentMap.Mvc/.dockerignore +++ /dev/null @@ -1,10 +0,0 @@ -**/.dockerignore -**/Dockerfile* -**/node_modules -**/*.*proj.user -**/bin -**/obj -**/wwwroot -**/Properties/ -**/appsettings.Development.json -**/eslint.config.js diff --git a/CommentMap.Mvc/Dockerfile b/CommentMap.Mvc/Dockerfile deleted file mode 100644 index 246d3bf..0000000 --- a/CommentMap.Mvc/Dockerfile +++ /dev/null @@ -1,35 +0,0 @@ -#See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging. - -FROM mcr.microsoft.com/dotnet/aspnet:8.0-jammy-chiseled-extra AS base -USER app -WORKDIR /app -EXPOSE 8080 - -FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build -ARG BUILD_CONFIGURATION=Release -WORKDIR /src -COPY ["CommentMap.Mvc.csproj", "libman.json", "CommentMap.Mvc/"] -RUN dotnet restore "./CommentMap.Mvc/CommentMap.Mvc.csproj" -WORKDIR "/src/CommentMap.Mvc" -COPY . . -RUN dotnet build --no-restore "./CommentMap.Mvc.csproj" -c $BUILD_CONFIGURATION -o /app/build - -FROM build AS publish -ARG BUILD_CONFIGURATION=Release -RUN dotnet publish "./CommentMap.Mvc.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false - -FROM node:20.14-alpine3.19 AS build-static -ENV NPM_CONFIG_UPDATE_NOTIFIER=false -ENV NPM_CONFIG_FUND=false -WORKDIR /src -COPY ["package.json", "package-lock.json", "tsconfig.json", "./"] -RUN npm ci --omit=dev -COPY "build" "./build" -COPY "Scripts" "./Scripts" -RUN npm run build - -FROM base AS final -WORKDIR /app -COPY --from=publish /app/publish . -COPY --from=build-static /src/wwwroot ./wwwroot -ENTRYPOINT ["dotnet", "CommentMap.Mvc.dll"] \ No newline at end of file diff --git a/aspire.config.json b/aspire.config.json new file mode 100644 index 0000000..c84104c --- /dev/null +++ b/aspire.config.json @@ -0,0 +1,5 @@ +{ + "appHost": { + "path": "CommentMap.AppHost/CommentMap.AppHost.csproj" + } +} \ No newline at end of file diff --git a/docker-compose.dcproj b/docker-compose.dcproj deleted file mode 100644 index 70c26c6..0000000 --- a/docker-compose.dcproj +++ /dev/null @@ -1,19 +0,0 @@ - - - - 2.1 - Linux - False - 50841206-e858-4315-aaaf-e75a509ca5e9 - LaunchBrowser - {Scheme}://localhost:{ServicePort} - commentmap.mvc - - - - - docker-compose.yml - - - - \ No newline at end of file diff --git a/docker-compose.override.yml b/docker-compose.override.yml deleted file mode 100644 index 874775b..0000000 --- a/docker-compose.override.yml +++ /dev/null @@ -1,14 +0,0 @@ -services: - commentmap-mvc: - environment: - ASPNETCORE_ENVIRONMENT: Development - Serilog__WriteTo__1__Name: Debug - volumes: - - ${APPDATA}/Microsoft/UserSecrets:/home/app/.microsoft/usersecrets:ro - - ${APPDATA}/ASP.NET/Https:/home/app/.aspnet/https:ro - - commentmap-emailsender: - environment: - - DOTNET_ENVIRONMENT=Development - volumes: - - ${APPDATA}/Microsoft/UserSecrets:/home/app/.microsoft/usersecrets:ro diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index 7a84b7c..0000000 --- a/docker-compose.yml +++ /dev/null @@ -1,61 +0,0 @@ -services: - commentmap-mvc: - image: ghcr.io/adedw/commentmap-mvc:master - build: - context: ./CommentMap.Mvc - depends_on: - - postgres - environment: - ConnectionStrings__DefaultConnection: "Host=postgres;Port=5432;Database=comment-map;Username=comment-map;Password=P@ssw0rd" - AllowedHosts: "*" - ASPNETCORE_HTTP_PORTS: 8080 - ASPNETCORE_ENVIRONMENT: Release - Serilog__MinimumLevel__Default: Information - Serilog__MinimumLevel__Override__Microsoft.AspNetCore: Warning - Serilog__MinimumLevel__Override__Microsoft.EntityFrameworkCore: Warning - Serilog__WriteTo__0__Name: Console - container_name: commentmap-mvc - ports: - - "127.0.0.1:8080:8080" - - postgres: - container_name: postgres - image: postgis/postgis:16-3.4-alpine - volumes: - - pg-data:/var/lib/postgresql/data - environment: - POSTGRES_DB: comment-map - POSTGRES_USER: comment-map - POSTGRES_PASSWORD: P@ssw0rd - ports: - - "127.0.0.1:5432:5432" - - mailhog: - image: mailhog/mailhog:v1.0.1 - container_name: mailhog - ports: - - "127.0.0.1:8025:8025" - - "127.0.0.1:1025:1025" - - commentmap-emailsender: - image: ${DOCKER_REGISTRY-}commentmap-emailsender - build: - context: . - dockerfile: CommentMap.EmailSender/Dockerfile - - rabbitmq: - container_name: rabbitmq - image: rabbitmq:4.0.4-management - ports: - - "127.0.0.1:15672:15672" - - "127.0.0.1:5672:5672" - environment: - RABBITMQ_DEFAULT_USER: commentmap - RABBITMQ_DEFAULT_PASS: P@ssw0rd - RABBITMQ_DEFAULT_VHOST: commentmap - volumes: - - rabbitmq-data:/var/lib/rabbitmq/mnesia - -volumes: - pg-data: - rabbitmq-data: diff --git a/.config/dotnet-tools.json b/dotnet-tools.json similarity index 66% rename from .config/dotnet-tools.json rename to dotnet-tools.json index 1613f09..ec72923 100644 --- a/.config/dotnet-tools.json +++ b/dotnet-tools.json @@ -10,11 +10,18 @@ "rollForward": false }, "dotnet-ef": { - "version": "9.0.0", + "version": "10.0.10", "commands": [ "dotnet-ef" ], "rollForward": false + }, + "aspire.cli": { + "version": "13.4.6", + "commands": [ + "aspire" + ], + "rollForward": false } } } \ No newline at end of file diff --git a/launchSettings.json b/launchSettings.json deleted file mode 100644 index 8d27d59..0000000 --- a/launchSettings.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "profiles": { - "My dependencies": { - "commandName": "DockerCompose", - "commandVersion": "1.0", - "serviceActions": { - "commentmap-mvc": "DoNotStart", - "postgres": "StartWithoutDebugging", - "mailhog": "StartWithoutDebugging", - "commentmap-emailsender": "DoNotStart", - "rabbitmq": "StartWithoutDebugging" - } - } - } -} \ No newline at end of file diff --git a/nuget.config b/nuget.config new file mode 100644 index 0000000..9e0277e --- /dev/null +++ b/nuget.config @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file From 92c155bda9289cce91c25b4f58041c65877c2741 Mon Sep 17 00:00:00 2001 From: Ivan Kozelskikh Date: Sun, 2 Aug 2026 21:44:04 +0500 Subject: [PATCH 02/23] Migrate projects to .NET 10 and add ServiceDefaults Upgrade projects to target .NET 10 (Mvc, EmailSender, Shared), refresh .gitattributes and .gitignore, and update several package versions. Add a new CommentMap.ServiceDefaults project with reusable Extensions (OpenTelemetry, health checks, service discovery, resilience) and wire project references to it. Replace the old .sln with a simple .slnx manifest, remove some Docker props from the MVC csproj, and add a clear.ps1 helper to remove bin/obj folders. --- .gitattributes | 162 +++++++++++------- .gitignore | 130 +++++++++++++- .../CommentMap.EmailSender.csproj | 16 +- CommentMap.Mvc/CommentMap.Mvc.csproj | 26 ++- .../CommentMap.ServiceDefaults.csproj | 23 +++ CommentMap.ServiceDefaults/Extensions.cs | 121 +++++++++++++ CommentMap.Shared/CommentMap.Shared.csproj | 2 +- CommentMap.sln | 55 ------ CommentMap.slnx | 10 ++ clear.ps1 | 1 + 10 files changed, 398 insertions(+), 148 deletions(-) create mode 100644 CommentMap.ServiceDefaults/CommentMap.ServiceDefaults.csproj create mode 100644 CommentMap.ServiceDefaults/Extensions.cs delete mode 100644 CommentMap.sln create mode 100644 CommentMap.slnx create mode 100644 clear.ps1 diff --git a/.gitattributes b/.gitattributes index 1ff0c42..8154320 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,63 +1,107 @@ -############################################################################### -# Set default behavior to automatically normalize line endings. -############################################################################### +## Set Git attributes for paths including line ending +## normalization, diff behavior, etc. +## +## Get latest from `dotnet new gitattributes` + +# Auto detect text files and perform LF normalization * text=auto -############################################################################### -# Set default behavior for command prompt diff. -# -# This is need for earlier builds of msysgit that does not have it on by -# default for csharp files. -# Note: This is only used by command line -############################################################################### -#*.cs diff=csharp - -############################################################################### -# Set the merge driver for project and solution files # -# Merging from the command prompt will add diff markers to the files if there -# are conflicts (Merging from VS is not affected by the settings below, in VS -# the diff markers are never inserted). Diff markers may cause the following -# file extensions to fail to load in VS. An alternative would be to treat -# these files as binary and thus will always conflict and require user -# intervention with every merge. To do so, just uncomment the entries below -############################################################################### -#*.sln merge=binary -#*.csproj merge=binary -#*.vbproj merge=binary -#*.vcxproj merge=binary -#*.vcproj merge=binary -#*.dbproj merge=binary -#*.fsproj merge=binary -#*.lsproj merge=binary -#*.wixproj merge=binary -#*.modelproj merge=binary -#*.sqlproj merge=binary -#*.wwaproj merge=binary - -############################################################################### -# behavior for image files +# The above will handle all files NOT found below # -# image files are treated as binary by default. -############################################################################### -#*.jpg binary -#*.png binary -#*.gif binary - -############################################################################### -# diff behavior for common document formats -# -# Convert binary document formats to text before diffing them. This feature -# is only available from the command line. Turn it on by uncommenting the -# entries below. -############################################################################### -#*.doc diff=astextplain -#*.DOC diff=astextplain -#*.docx diff=astextplain -#*.DOCX diff=astextplain -#*.dot diff=astextplain -#*.DOT diff=astextplain -#*.pdf diff=astextplain -#*.PDF diff=astextplain -#*.rtf diff=astextplain -#*.RTF diff=astextplain + +*.cs text diff=csharp +*.cshtml text diff=html +*.csx text diff=csharp +*.sln text eol=crlf + +# Content below from: https://github.com/gitattributes/gitattributes/blob/master/Common.gitattributes + +# Documents +*.bibtex text diff=bibtex +*.doc diff=astextplain +*.DOC diff=astextplain +*.docx diff=astextplain +*.DOCX diff=astextplain +*.dot diff=astextplain +*.DOT diff=astextplain +*.pdf diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain +*.md text diff=markdown +*.mdx text diff=markdown +*.tex text diff=tex +*.adoc text +*.textile text +*.mustache text +# Per RFC 4180, .csv should be CRLF +*.csv text eol=crlf +*.tab text +*.tsv text +*.txt text +*.sql text +*.epub diff=astextplain + +# Graphics +*.png binary +*.jpg binary +*.jpeg binary +*.gif binary +*.tif binary +*.tiff binary +*.ico binary +# SVG treated as text by default. +*.svg text +# If you want to treat it as binary, +# use the following line instead. +# *.svg binary +*.eps binary + +# Scripts +# Force Unix scripts to always use lf line endings so that if a repo is accessed +# in Unix via a file share from Windows, the scripts will work +*.bash text eol=lf +*.fish text eol=lf +*.ksh text eol=lf +*.sh text eol=lf +*.zsh text eol=lf +# Likewise, force cmd and batch scripts to always use crlf +*.bat text eol=crlf +*.cmd text eol=crlf + +# Serialization +*.json text +*.toml text +*.xml text +*.yaml text +*.yml text + +# Archives +*.7z binary +*.bz binary +*.bz2 binary +*.bzip2 binary +*.gz binary +*.lz binary +*.lzma binary +*.rar binary +*.tar binary +*.taz binary +*.tbz binary +*.tbz2 binary +*.tgz binary +*.tlz binary +*.txz binary +*.xz binary +*.Z binary +*.zip binary +*.zst binary + +# Text files where line endings should be preserved +*.patch -text + +# Exclude files from exporting +.gitattributes export-ignore +.gitignore export-ignore +.gitkeep export-ignore diff --git a/.gitignore b/.gitignore index 2cb1976..0808c4a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,10 @@ ## Ignore Visual Studio temporary files, build results, and ## files generated by popular Visual Studio add-ons. ## -## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore +## Get latest from `dotnet new gitignore` + +# dotenv files +.env # User-specific files *.rsuser @@ -29,15 +32,13 @@ x86/ bld/ [Bb]in/ [Oo]bj/ -[Oo]ut/ [Ll]og/ [Ll]ogs/ # Visual Studio 2015/2017 cache/options directory .vs/ # Uncomment if you have tasks that create the project's static files in wwwroot -/**/wwwroot/* -!/**/wwwroot/assets/ +#wwwroot/ # Visual Studio 2017 auto generated files Generated\ Files/ @@ -59,11 +60,14 @@ dlldata.c # Benchmark Results BenchmarkDotNet.Artifacts/ -# .NET Core +# .NET project.lock.json project.fragment.lock.json artifacts/ +# Tye +.tye/ + # ASP.NET Scaffolding ScaffoldingReadMe.txt @@ -84,6 +88,8 @@ StyleCopReport.xml *.pgc *.pgd *.rsp +# but not Directory.Build.rsp, as it configures directory-level build defaults +!Directory.Build.rsp *.sbr *.tlb *.tli @@ -92,6 +98,7 @@ StyleCopReport.xml *.tmp_proj *_wpftmp.csproj *.log +*.tlog *.vspscc *.vssscc .builds @@ -295,6 +302,17 @@ node_modules/ # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) *.vbw +# Visual Studio 6 auto-generated project file (contains which files were open etc.) +*.vbp + +# Visual Studio 6 workspace and project file (working project files containing files to include in project) +*.dsw +*.dsp + +# Visual Studio 6 technical files +*.ncb +*.aps + # Visual Studio LightSwitch build output **/*.HTMLClient/GeneratedArtifacts **/*.DesktopClient/GeneratedArtifacts @@ -351,6 +369,9 @@ ASALocalRun/ # Local History for Visual Studio .localhistory/ +# Visual Studio History (VSHistory) files +.vshistory/ + # BeatPulse healthcheck temp database healthchecksdb @@ -363,8 +384,99 @@ MigrationBackup/ # Fody - auto-generated XML schema FodyWeavers.xsd -# QGIS Projects -*.qgz +# VS Code files for those working on multiple tools +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.code-workspace -# Yarn internal files -.yarn/ +# Local History for Visual Studio Code +.history/ + +# Windows Installer files from build outputs +*.cab +*.msi +*.msix +*.msm +*.msp + +# JetBrains Rider +*.sln.iml +.idea/ + +## +## Visual studio for Mac +## + + +# globs +Makefile.in +*.userprefs +*.usertasks +config.make +config.status +aclocal.m4 +install-sh +autom4te.cache/ +*.tar.gz +tarballs/ +test-results/ + +# content below from: https://github.com/github/gitignore/blob/main/Global/macOS.gitignore +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +# content below from: https://github.com/github/gitignore/blob/main/Global/Windows.gitignore +# Windows thumbnail cache files +Thumbs.db +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# Vim temporary swap files +*.swp diff --git a/CommentMap.EmailSender/CommentMap.EmailSender.csproj b/CommentMap.EmailSender/CommentMap.EmailSender.csproj index 2d560cb..ead9227 100644 --- a/CommentMap.EmailSender/CommentMap.EmailSender.csproj +++ b/CommentMap.EmailSender/CommentMap.EmailSender.csproj @@ -1,23 +1,23 @@  - net9.0 + net10.0 enable enable dotnet-CommentMap.EmailSender-79f62d41-e375-4e59-9348-362f9f72db30 - - - - - - + + + + + + - + diff --git a/CommentMap.Mvc/CommentMap.Mvc.csproj b/CommentMap.Mvc/CommentMap.Mvc.csproj index a223bac..1732cbf 100644 --- a/CommentMap.Mvc/CommentMap.Mvc.csproj +++ b/CommentMap.Mvc/CommentMap.Mvc.csproj @@ -1,12 +1,10 @@  - net9.0 + net10.0 enable enable aspnet-CommentMap.Mvc-ee62d642-3c8e-45ac-9e81-917c8b6b333a - Linux - ..\docker-compose.dcproj false @@ -25,25 +23,21 @@ - - - - - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - + + + + + + - + diff --git a/CommentMap.ServiceDefaults/CommentMap.ServiceDefaults.csproj b/CommentMap.ServiceDefaults/CommentMap.ServiceDefaults.csproj new file mode 100644 index 0000000..333fa2f --- /dev/null +++ b/CommentMap.ServiceDefaults/CommentMap.ServiceDefaults.csproj @@ -0,0 +1,23 @@ + + + + net10.0 + enable + enable + true + 74acc6c3-ece8-4ca1-a163-2ad79be583e8 + + + + + + + + + + + + + + + diff --git a/CommentMap.ServiceDefaults/Extensions.cs b/CommentMap.ServiceDefaults/Extensions.cs new file mode 100644 index 0000000..a9c536d --- /dev/null +++ b/CommentMap.ServiceDefaults/Extensions.cs @@ -0,0 +1,121 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Diagnostics.HealthChecks; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Diagnostics.HealthChecks; +using Microsoft.Extensions.Logging; +using OpenTelemetry; +using OpenTelemetry.Metrics; +using OpenTelemetry.Trace; + +namespace Microsoft.Extensions.Hosting; + +// Adds common .NET Aspire services: service discovery, resilience, health checks, and OpenTelemetry. +// This project should be referenced by each service project in your solution. +// To learn more about using this project, see https://aka.ms/dotnet/aspire/service-defaults +public static class Extensions +{ + public static TBuilder AddServiceDefaults(this TBuilder builder) where TBuilder : IHostApplicationBuilder + { + builder.ConfigureOpenTelemetry(); + + builder.AddDefaultHealthChecks(); + + builder.Services.AddServiceDiscovery(); + + builder.Services.ConfigureHttpClientDefaults(http => + { + // Turn on resilience by default + http.AddStandardResilienceHandler(); + + // Turn on service discovery by default + http.AddServiceDiscovery(); + }); + + // Uncomment the following to restrict the allowed schemes for service discovery. + // builder.Services.Configure(options => + // { + // options.AllowedSchemes = ["https"]; + // }); + + return builder; + } + + public static TBuilder ConfigureOpenTelemetry(this TBuilder builder) where TBuilder : IHostApplicationBuilder + { + builder.Logging.AddOpenTelemetry(logging => + { + logging.IncludeFormattedMessage = true; + logging.IncludeScopes = true; + }); + + builder.Services.AddOpenTelemetry() + .WithMetrics(metrics => + { + metrics.AddAspNetCoreInstrumentation() + .AddHttpClientInstrumentation() + .AddRuntimeInstrumentation() + .AddMeter("Wolverine:CommentMap.EmailSender") + .AddMeter("Wolverine:CommentMap.Mvc"); + }) + .WithTracing(tracing => + { + tracing.AddSource(builder.Environment.ApplicationName) + .AddAspNetCoreInstrumentation() + // Uncomment the following line to enable gRPC instrumentation (requires the OpenTelemetry.Instrumentation.GrpcNetClient package) + //.AddGrpcClientInstrumentation() + .AddHttpClientInstrumentation() + .AddSource("Wolverine"); + }); + + builder.AddOpenTelemetryExporters(); + + return builder; + } + + private static TBuilder AddOpenTelemetryExporters(this TBuilder builder) where TBuilder : IHostApplicationBuilder + { + var useOtlpExporter = !string.IsNullOrWhiteSpace(builder.Configuration["OTEL_EXPORTER_OTLP_ENDPOINT"]); + + if (useOtlpExporter) + { + builder.Services.AddOpenTelemetry().UseOtlpExporter(); + } + + // Uncomment the following lines to enable the Azure Monitor exporter (requires the Azure.Monitor.OpenTelemetry.AspNetCore package) + //if (!string.IsNullOrEmpty(builder.Configuration["APPLICATIONINSIGHTS_CONNECTION_STRING"])) + //{ + // builder.Services.AddOpenTelemetry() + // .UseAzureMonitor(); + //} + + return builder; + } + + public static TBuilder AddDefaultHealthChecks(this TBuilder builder) where TBuilder : IHostApplicationBuilder + { + builder.Services.AddHealthChecks() + // Add a default liveness check to ensure app is responsive + .AddCheck("self", () => HealthCheckResult.Healthy(), ["live"]); + + return builder; + } + + public static WebApplication MapDefaultEndpoints(this WebApplication app) + { + // Adding health checks endpoints to applications in non-development environments has security implications. + // See https://aka.ms/dotnet/aspire/healthchecks for details before enabling these endpoints in non-development environments. + if (app.Environment.IsDevelopment()) + { + // All health checks must pass for app to be considered ready to accept traffic after starting + app.MapHealthChecks("/health"); + + // Only health checks tagged with the "live" tag must pass for app to be considered alive + app.MapHealthChecks("/alive", new HealthCheckOptions + { + Predicate = r => r.Tags.Contains("live") + }); + } + + return app; + } +} diff --git a/CommentMap.Shared/CommentMap.Shared.csproj b/CommentMap.Shared/CommentMap.Shared.csproj index 125f4c9..b760144 100644 --- a/CommentMap.Shared/CommentMap.Shared.csproj +++ b/CommentMap.Shared/CommentMap.Shared.csproj @@ -1,7 +1,7 @@  - net9.0 + net10.0 enable enable diff --git a/CommentMap.sln b/CommentMap.sln deleted file mode 100644 index 0af34db..0000000 --- a/CommentMap.sln +++ /dev/null @@ -1,55 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.9.34728.123 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CommentMap.Mvc", "CommentMap.Mvc\CommentMap.Mvc.csproj", "{0A8CE1C6-6A44-4C06-890E-1C1D133123B5}" -EndProject -Project("{E53339B2-1760-4266-BCC7-CA923CBCF16C}") = "docker-compose", "docker-compose.dcproj", "{50841206-E858-4315-AAAF-E75A509CA5E9}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommentMap.EmailSender", "CommentMap.EmailSender\CommentMap.EmailSender.csproj", "{2E6B5D50-ADF7-44BC-9364-2D60E162F61B}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommentMap.Shared", "CommentMap.Shared\CommentMap.Shared.csproj", "{9B1E3109-4300-4C8B-95E8-42C2AEF9226C}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommentMap.AppHost", "CommentMap.AppHost\CommentMap.AppHost.csproj", "{A2866720-D4DF-CCB4-7C4E-1D4514D4FF47}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommentMap.ServiceDefaults", "..\CommentMap.ServiceDefaults\CommentMap.ServiceDefaults.csproj", "{AFBB3F78-9D02-403C-A729-EC63BD60E7BF}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {0A8CE1C6-6A44-4C06-890E-1C1D133123B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0A8CE1C6-6A44-4C06-890E-1C1D133123B5}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0A8CE1C6-6A44-4C06-890E-1C1D133123B5}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0A8CE1C6-6A44-4C06-890E-1C1D133123B5}.Release|Any CPU.Build.0 = Release|Any CPU - {50841206-E858-4315-AAAF-E75A509CA5E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {50841206-E858-4315-AAAF-E75A509CA5E9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {50841206-E858-4315-AAAF-E75A509CA5E9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {50841206-E858-4315-AAAF-E75A509CA5E9}.Release|Any CPU.Build.0 = Release|Any CPU - {2E6B5D50-ADF7-44BC-9364-2D60E162F61B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2E6B5D50-ADF7-44BC-9364-2D60E162F61B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2E6B5D50-ADF7-44BC-9364-2D60E162F61B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2E6B5D50-ADF7-44BC-9364-2D60E162F61B}.Release|Any CPU.Build.0 = Release|Any CPU - {9B1E3109-4300-4C8B-95E8-42C2AEF9226C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9B1E3109-4300-4C8B-95E8-42C2AEF9226C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9B1E3109-4300-4C8B-95E8-42C2AEF9226C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9B1E3109-4300-4C8B-95E8-42C2AEF9226C}.Release|Any CPU.Build.0 = Release|Any CPU - {A2866720-D4DF-CCB4-7C4E-1D4514D4FF47}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A2866720-D4DF-CCB4-7C4E-1D4514D4FF47}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A2866720-D4DF-CCB4-7C4E-1D4514D4FF47}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A2866720-D4DF-CCB4-7C4E-1D4514D4FF47}.Release|Any CPU.Build.0 = Release|Any CPU - {AFBB3F78-9D02-403C-A729-EC63BD60E7BF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {AFBB3F78-9D02-403C-A729-EC63BD60E7BF}.Debug|Any CPU.Build.0 = Debug|Any CPU - {AFBB3F78-9D02-403C-A729-EC63BD60E7BF}.Release|Any CPU.ActiveCfg = Release|Any CPU - {AFBB3F78-9D02-403C-A729-EC63BD60E7BF}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {A03E777E-F4F1-4DAD-B906-746AD2767FA3} - EndGlobalSection -EndGlobal diff --git a/CommentMap.slnx b/CommentMap.slnx new file mode 100644 index 0000000..a3fa809 --- /dev/null +++ b/CommentMap.slnx @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/clear.ps1 b/clear.ps1 new file mode 100644 index 0000000..cf68bcf --- /dev/null +++ b/clear.ps1 @@ -0,0 +1 @@ +Get-ChildItem .\ -include bin,obj -Recurse | ForEach-Object ($_) { Remove-Item $_.FullName -Force -Recurse } From 882cca767d8478cdfa55f0beeeb305e21542f27a Mon Sep 17 00:00:00 2001 From: Ivan Kozelskikh Date: Sun, 2 Aug 2026 22:03:16 +0500 Subject: [PATCH 03/23] Replace MassTransit with Wolverine and refactor Migrate messaging from MassTransit to Wolverine (add Wolverine/Wolverine.RabbitMQ packages, enable static codegen and RunJasperFxCommands). Update EmailSender and Mvc programs to use Wolverine/RabbitMQ, publish/listen to Send*Email queues, and remove MassTransit consumers. Refactor email services: replace MailpitServiceOptions with MailpitClientSettings (config moved to Aspire:Mailpit), change DI extension signature, add ISmtpClientFactory, SmtpClientFactory, SmtpEmailSender (rename ISmtpEmailSender), MessageSenderHandler, SendMessageConsumer, and generated Wolverine handler registry/handlers. Remove legacy SmtpEmailSenderService, consumer and development appsettings. --- .../CommentMap.EmailSender.csproj | 4 ++ .../Extensions/ServiceCollectionExtensions.cs | 42 ++++++++++---- .../GeneratedHandlerRegistry.cs | 29 ++++++++++ .../SendChangeEmailHandler531316428.cs | 47 +++++++++++++++ .../SendConfirmEmailHandler111886888.cs | 47 +++++++++++++++ .../SendResetPasswordEmailHandler453035410.cs | 47 +++++++++++++++ .../Options/MailpitClientSettings.cs | 9 +++ .../Options/MailpitServiceOptions.cs | 24 -------- CommentMap.EmailSender/Program.cs | 42 ++++++-------- .../Services/ISmtpClientFactory.cs | 8 +++ ...ilSenderService.cs => ISmtpEmailSender.cs} | 2 +- .../Services/MessageSenderConsumer.cs | 40 ------------- .../Services/MessageSenderHandler.cs | 46 +++++++++++++++ .../Services/MessageSenderService.cs | 2 +- .../Services/SendMessageConsumer.cs | 35 ++++++++++++ .../Services/SmtpClientFactory.cs | 12 ++++ .../Services/SmtpEmailSender.cs | 57 +++++++++++++++++++ .../Services/SmtpEmailSenderService.cs | 48 ---------------- .../appsettings.Development.json | 8 --- CommentMap.EmailSender/appsettings.json | 6 ++ CommentMap.Mvc/Program.cs | 25 +++++++- 21 files changed, 419 insertions(+), 161 deletions(-) create mode 100644 CommentMap.EmailSender/Internal/Generated/WolverineHandlers/GeneratedHandlerRegistry.cs create mode 100644 CommentMap.EmailSender/Internal/Generated/WolverineHandlers/SendChangeEmailHandler531316428.cs create mode 100644 CommentMap.EmailSender/Internal/Generated/WolverineHandlers/SendConfirmEmailHandler111886888.cs create mode 100644 CommentMap.EmailSender/Internal/Generated/WolverineHandlers/SendResetPasswordEmailHandler453035410.cs create mode 100644 CommentMap.EmailSender/Options/MailpitClientSettings.cs delete mode 100644 CommentMap.EmailSender/Options/MailpitServiceOptions.cs create mode 100644 CommentMap.EmailSender/Services/ISmtpClientFactory.cs rename CommentMap.EmailSender/Services/{ISmtpEmailSenderService.cs => ISmtpEmailSender.cs} (79%) delete mode 100644 CommentMap.EmailSender/Services/MessageSenderConsumer.cs create mode 100644 CommentMap.EmailSender/Services/MessageSenderHandler.cs create mode 100644 CommentMap.EmailSender/Services/SendMessageConsumer.cs create mode 100644 CommentMap.EmailSender/Services/SmtpClientFactory.cs create mode 100644 CommentMap.EmailSender/Services/SmtpEmailSender.cs delete mode 100644 CommentMap.EmailSender/Services/SmtpEmailSenderService.cs delete mode 100644 CommentMap.EmailSender/appsettings.Development.json diff --git a/CommentMap.EmailSender/CommentMap.EmailSender.csproj b/CommentMap.EmailSender/CommentMap.EmailSender.csproj index ead9227..96f1e51 100644 --- a/CommentMap.EmailSender/CommentMap.EmailSender.csproj +++ b/CommentMap.EmailSender/CommentMap.EmailSender.csproj @@ -12,8 +12,12 @@ + + + + diff --git a/CommentMap.EmailSender/Extensions/ServiceCollectionExtensions.cs b/CommentMap.EmailSender/Extensions/ServiceCollectionExtensions.cs index e53e314..2bf24c2 100644 --- a/CommentMap.EmailSender/Extensions/ServiceCollectionExtensions.cs +++ b/CommentMap.EmailSender/Extensions/ServiceCollectionExtensions.cs @@ -6,20 +6,40 @@ namespace CommentMap.EmailSender.Extensions; public static class ServiceCollectionExtensions { - public static IServiceCollection AddSmtpEmailSenderServices( - this IServiceCollection services, - IConfiguration configuration) + private const string DefaultConfigSectionName = "Aspire:Mailpit"; + + public static IHostApplicationBuilder AddSmtpEmailSenderServices( + this IHostApplicationBuilder hostBuilder, + string connectionName, + Action? configureSettings = null) { - services.AddScoped(); + ArgumentNullException.ThrowIfNull(hostBuilder); + ArgumentException.ThrowIfNullOrEmpty(connectionName, nameof(connectionName)); + + MailpitClientSettings settings = new(); + + var configSection = hostBuilder.Configuration.GetSection(DefaultConfigSectionName); + configSection.Bind(settings); + + if (hostBuilder.Configuration.GetConnectionString(connectionName) is string connectionString) + { + var connectionBuilder = new DbConnectionStringBuilder + { + ConnectionString = connectionString, + }; + + var smtpEndpoint = new Uri((string)connectionBuilder["Endpoint"], UriKind.Absolute); + + settings.Host = smtpEndpoint.Host; + settings.Port = smtpEndpoint.Port; + } - var mailpitServiceConfiguration = configuration.GetSection(MailpitServiceOptions.SectionName); - services.AddOptions() - .Bind(mailpitServiceConfiguration) - .ValidateDataAnnotations() - .ValidateOnStart(); + configureSettings?.Invoke(settings); - services.AddScoped(); + hostBuilder.Services.AddSingleton(Microsoft.Extensions.Options.Options.Create(settings)); + hostBuilder.Services.AddSingleton(); + hostBuilder.Services.AddSingleton(); - return services; + return hostBuilder; } } diff --git a/CommentMap.EmailSender/Internal/Generated/WolverineHandlers/GeneratedHandlerRegistry.cs b/CommentMap.EmailSender/Internal/Generated/WolverineHandlers/GeneratedHandlerRegistry.cs new file mode 100644 index 0000000..36c2d27 --- /dev/null +++ b/CommentMap.EmailSender/Internal/Generated/WolverineHandlers/GeneratedHandlerRegistry.cs @@ -0,0 +1,29 @@ +// +#pragma warning disable + +namespace Internal.Generated.WolverineHandlers +{ + // START: GeneratedHandlerRegistry + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class GeneratedHandlerRegistry : Wolverine.Runtime.Handlers.HandlerRegistry + { + + + public override System.Type[] HandlerTypes() + { + return new System.Type[] { typeof(CommentMap.EmailSender.Services.MessageSenderHandler), typeof(CommentMap.EmailSender.Services.SendMessageConsumer) }; + } + + + public override System.Type[] MessageTypes() + { + return System.Array.Empty(); + } + + } + + // END: GeneratedHandlerRegistry + + +} + diff --git a/CommentMap.EmailSender/Internal/Generated/WolverineHandlers/SendChangeEmailHandler531316428.cs b/CommentMap.EmailSender/Internal/Generated/WolverineHandlers/SendChangeEmailHandler531316428.cs new file mode 100644 index 0000000..f9266e0 --- /dev/null +++ b/CommentMap.EmailSender/Internal/Generated/WolverineHandlers/SendChangeEmailHandler531316428.cs @@ -0,0 +1,47 @@ +// +#pragma warning disable +using CommentMap.EmailSender.Services; +using Microsoft.Extensions.Logging; + +namespace Internal.Generated.WolverineHandlers +{ + // START: SendChangeEmailHandler531316428 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class SendChangeEmailHandler531316428 : Wolverine.Runtime.Handlers.MessageHandler + { + private readonly CommentMap.EmailSender.Services.IMessageSenderService _messageSenderService; + private readonly Microsoft.Extensions.Logging.ILoggerFactory _loggerFactory; + private readonly Microsoft.Extensions.Logging.ILogger _loggerOfSendMessageConsumer; + + public SendChangeEmailHandler531316428(CommentMap.EmailSender.Services.IMessageSenderService messageSenderService, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory, Microsoft.Extensions.Logging.ILogger loggerOfSendMessageConsumer) + { + _messageSenderService = messageSenderService; + _loggerFactory = loggerFactory; + _loggerOfSendMessageConsumer = loggerOfSendMessageConsumer; + } + + + + public override async System.Threading.Tasks.Task HandleAsync(Wolverine.Runtime.MessageContext context, System.Threading.CancellationToken cancellation) + { + // The actual message body + var sendChangeEmail = (CommentMap.Shared.Messages.SendChangeEmail)context.Envelope.Message; + + var sendMessageConsumer = new CommentMap.EmailSender.Services.SendMessageConsumer(_messageSenderService, _loggerOfSendMessageConsumer); + + // The actual message execution + await CommentMap.EmailSender.Services.MessageSenderHandler.Handle(sendChangeEmail, _messageSenderService, _loggerFactory, cancellation).ConfigureAwait(false); + + + // The actual message execution + await sendMessageConsumer.ConsumeAsync(sendChangeEmail, cancellation).ConfigureAwait(false); + + } + + } + + // END: SendChangeEmailHandler531316428 + + +} + diff --git a/CommentMap.EmailSender/Internal/Generated/WolverineHandlers/SendConfirmEmailHandler111886888.cs b/CommentMap.EmailSender/Internal/Generated/WolverineHandlers/SendConfirmEmailHandler111886888.cs new file mode 100644 index 0000000..ce0a6c6 --- /dev/null +++ b/CommentMap.EmailSender/Internal/Generated/WolverineHandlers/SendConfirmEmailHandler111886888.cs @@ -0,0 +1,47 @@ +// +#pragma warning disable +using CommentMap.EmailSender.Services; +using Microsoft.Extensions.Logging; + +namespace Internal.Generated.WolverineHandlers +{ + // START: SendConfirmEmailHandler111886888 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class SendConfirmEmailHandler111886888 : Wolverine.Runtime.Handlers.MessageHandler + { + private readonly CommentMap.EmailSender.Services.IMessageSenderService _messageSenderService; + private readonly Microsoft.Extensions.Logging.ILoggerFactory _loggerFactory; + private readonly Microsoft.Extensions.Logging.ILogger _loggerOfSendMessageConsumer; + + public SendConfirmEmailHandler111886888(CommentMap.EmailSender.Services.IMessageSenderService messageSenderService, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory, Microsoft.Extensions.Logging.ILogger loggerOfSendMessageConsumer) + { + _messageSenderService = messageSenderService; + _loggerFactory = loggerFactory; + _loggerOfSendMessageConsumer = loggerOfSendMessageConsumer; + } + + + + public override async System.Threading.Tasks.Task HandleAsync(Wolverine.Runtime.MessageContext context, System.Threading.CancellationToken cancellation) + { + // The actual message body + var sendConfirmEmail = (CommentMap.Shared.Messages.SendConfirmEmail)context.Envelope.Message; + + var sendMessageConsumer = new CommentMap.EmailSender.Services.SendMessageConsumer(_messageSenderService, _loggerOfSendMessageConsumer); + + // The actual message execution + await CommentMap.EmailSender.Services.MessageSenderHandler.Handle(sendConfirmEmail, _messageSenderService, _loggerFactory, cancellation).ConfigureAwait(false); + + + // The actual message execution + await sendMessageConsumer.ConsumeAsync(sendConfirmEmail, cancellation).ConfigureAwait(false); + + } + + } + + // END: SendConfirmEmailHandler111886888 + + +} + diff --git a/CommentMap.EmailSender/Internal/Generated/WolverineHandlers/SendResetPasswordEmailHandler453035410.cs b/CommentMap.EmailSender/Internal/Generated/WolverineHandlers/SendResetPasswordEmailHandler453035410.cs new file mode 100644 index 0000000..b172168 --- /dev/null +++ b/CommentMap.EmailSender/Internal/Generated/WolverineHandlers/SendResetPasswordEmailHandler453035410.cs @@ -0,0 +1,47 @@ +// +#pragma warning disable +using CommentMap.EmailSender.Services; +using Microsoft.Extensions.Logging; + +namespace Internal.Generated.WolverineHandlers +{ + // START: SendResetPasswordEmailHandler453035410 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class SendResetPasswordEmailHandler453035410 : Wolverine.Runtime.Handlers.MessageHandler + { + private readonly CommentMap.EmailSender.Services.IMessageSenderService _messageSenderService; + private readonly Microsoft.Extensions.Logging.ILoggerFactory _loggerFactory; + private readonly Microsoft.Extensions.Logging.ILogger _loggerOfSendMessageConsumer; + + public SendResetPasswordEmailHandler453035410(CommentMap.EmailSender.Services.IMessageSenderService messageSenderService, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory, Microsoft.Extensions.Logging.ILogger loggerOfSendMessageConsumer) + { + _messageSenderService = messageSenderService; + _loggerFactory = loggerFactory; + _loggerOfSendMessageConsumer = loggerOfSendMessageConsumer; + } + + + + public override async System.Threading.Tasks.Task HandleAsync(Wolverine.Runtime.MessageContext context, System.Threading.CancellationToken cancellation) + { + // The actual message body + var sendResetPasswordEmail = (CommentMap.Shared.Messages.SendResetPasswordEmail)context.Envelope.Message; + + var sendMessageConsumer = new CommentMap.EmailSender.Services.SendMessageConsumer(_messageSenderService, _loggerOfSendMessageConsumer); + + // The actual message execution + await CommentMap.EmailSender.Services.MessageSenderHandler.Handle(sendResetPasswordEmail, _messageSenderService, _loggerFactory, cancellation).ConfigureAwait(false); + + + // The actual message execution + await sendMessageConsumer.ConsumeAsync(sendResetPasswordEmail, cancellation).ConfigureAwait(false); + + } + + } + + // END: SendResetPasswordEmailHandler453035410 + + +} + diff --git a/CommentMap.EmailSender/Options/MailpitClientSettings.cs b/CommentMap.EmailSender/Options/MailpitClientSettings.cs new file mode 100644 index 0000000..99dc671 --- /dev/null +++ b/CommentMap.EmailSender/Options/MailpitClientSettings.cs @@ -0,0 +1,9 @@ +namespace CommentMap.EmailSender.Options; + +public class MailpitClientSettings +{ + public string? Host { get; set; } + public int? Port { get; set; } + public string? FromName { get; set; } + public string? FromAddress { get; set; } +} diff --git a/CommentMap.EmailSender/Options/MailpitServiceOptions.cs b/CommentMap.EmailSender/Options/MailpitServiceOptions.cs deleted file mode 100644 index dd82ce3..0000000 --- a/CommentMap.EmailSender/Options/MailpitServiceOptions.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace CommentMap.EmailSender.Options; - -public class MailpitServiceOptions -{ - public const string SectionName = "services:mailpit"; - - [Required] - public required string[] Smtp { get; init; } - - [Required] - public required string FromName { get; init; } - - [Required] - public required string FromAddress { get; init; } - - public void Deconstruct(out string fromName, out string fromAddress, out string[] smtp) - { - fromName = FromName; - fromAddress = FromAddress; - smtp = Smtp; - } -} diff --git a/CommentMap.EmailSender/Program.cs b/CommentMap.EmailSender/Program.cs index 96ca98c..5582ebc 100644 --- a/CommentMap.EmailSender/Program.cs +++ b/CommentMap.EmailSender/Program.cs @@ -1,41 +1,31 @@ using CommentMap.EmailSender.Extensions; using CommentMap.EmailSender.Services; using CommentMap.Shared.Messages; -using MassTransit; +using JasperFx; +using JasperFx.CodeGeneration; using Mjml.Net; - +using Wolverine; +using Wolverine.RabbitMQ; var builder = Host.CreateApplicationBuilder(args); builder.AddServiceDefaults(); -builder.Services.AddSmtpEmailSenderServices(builder.Configuration); -builder.Services.AddScoped(_ => new MjmlRenderer()); -builder.Services.AddScoped(); +builder.AddSmtpEmailSenderServices(connectionName: "mailpit"); +builder.Services.AddSingleton(new MjmlRenderer()); +builder.Services.AddSingleton(); -builder.Services.AddMassTransit(x => +builder.UseWolverine(opts => { - x.AddConsumer(); + opts.CodeGeneration.TypeLoadMode = TypeLoadMode.Static; - x.UsingRabbitMq((context, cfg) => - { - var configuration = context.GetRequiredService(); - var host = configuration.GetConnectionString("messaging"); - cfg.Host(host); + opts.UseRabbitMqUsingNamedConnection("messaging") + .AutoProvision(); - cfg.ReceiveEndpoint(nameof(SendChangeEmail), endpoint => - { - endpoint.ConfigureConsumer(context); - }); - cfg.ReceiveEndpoint(nameof(SendConfirmEmail), endpoint => - { - endpoint.ConfigureConsumer(context); - }); - cfg.ReceiveEndpoint(nameof(SendResetPasswordEmail), endpoint => - { - endpoint.ConfigureConsumer(context); - }); - }); + opts.ListenToRabbitQueue(nameof(SendConfirmEmail)); + opts.ListenToRabbitQueue(nameof(SendResetPasswordEmail)); + opts.ListenToRabbitQueue(nameof(SendChangeEmail)); }); -builder.Build().Run(); +var host = builder.Build(); +return await host.RunJasperFxCommands(args); diff --git a/CommentMap.EmailSender/Services/ISmtpClientFactory.cs b/CommentMap.EmailSender/Services/ISmtpClientFactory.cs new file mode 100644 index 0000000..b0e4f50 --- /dev/null +++ b/CommentMap.EmailSender/Services/ISmtpClientFactory.cs @@ -0,0 +1,8 @@ +using MailKit.Net.Smtp; + +namespace CommentMap.EmailSender.Services; + +public interface ISmtpClientFactory +{ + ISmtpClient CreateClient(); +} diff --git a/CommentMap.EmailSender/Services/ISmtpEmailSenderService.cs b/CommentMap.EmailSender/Services/ISmtpEmailSender.cs similarity index 79% rename from CommentMap.EmailSender/Services/ISmtpEmailSenderService.cs rename to CommentMap.EmailSender/Services/ISmtpEmailSender.cs index 96b8bdd..8a220db 100644 --- a/CommentMap.EmailSender/Services/ISmtpEmailSenderService.cs +++ b/CommentMap.EmailSender/Services/ISmtpEmailSender.cs @@ -1,6 +1,6 @@ namespace CommentMap.EmailSender.Services; -public interface ISmtpEmailSenderService +public interface ISmtpEmailSender { Task SendHtmlEmailAsync(string to, string subject, string htmlBody, CancellationToken ct = default); } \ No newline at end of file diff --git a/CommentMap.EmailSender/Services/MessageSenderConsumer.cs b/CommentMap.EmailSender/Services/MessageSenderConsumer.cs deleted file mode 100644 index bbcd349..0000000 --- a/CommentMap.EmailSender/Services/MessageSenderConsumer.cs +++ /dev/null @@ -1,40 +0,0 @@ -using CommentMap.EmailSender.Logging; -using CommentMap.Shared.Messages; -using MassTransit; - -namespace CommentMap.EmailSender.Services; - -internal class MessageSenderConsumer( - IMessageSenderService emailMessageService, - ILogger logger) - : IConsumer - , IConsumer - , IConsumer -{ - public async Task Consume(ConsumeContext context) - { - var (email, callbackURL) = context.Message; - - await emailMessageService.SendConfirmationLinkAsync(email, callbackURL, context.CancellationToken); - - logger.LogConfirmationEmailSent(email); - } - - public async Task Consume(ConsumeContext context) - { - var (email, callbackURL) = context.Message; - - await emailMessageService.SendResetPasswordLinkAsync(email, callbackURL, context.CancellationToken); - - logger.LogResetPasswordEmailSent(email); - } - - public async Task Consume(ConsumeContext context) - { - var (email, callbackURL) = context.Message; - - await emailMessageService.SendEmailChangingLinkAsync(email, callbackURL, context.CancellationToken); - - logger.LogEmailChangingLinkSent(email); - } -} diff --git a/CommentMap.EmailSender/Services/MessageSenderHandler.cs b/CommentMap.EmailSender/Services/MessageSenderHandler.cs new file mode 100644 index 0000000..ec45319 --- /dev/null +++ b/CommentMap.EmailSender/Services/MessageSenderHandler.cs @@ -0,0 +1,46 @@ +using CommentMap.EmailSender.Logging; +using CommentMap.Shared.Messages; + +namespace CommentMap.EmailSender.Services; + +public static class MessageSenderHandler +{ + public static async Task Handle( + SendConfirmEmail message, + IMessageSenderService emailMessageService, + ILoggerFactory loggerFactory, + CancellationToken cancellationToken) + { + var (email, callbackURL) = message; + + await emailMessageService.SendConfirmationLinkAsync(email, callbackURL, cancellationToken); + + loggerFactory.CreateLogger("MessageSenderHandler").LogConfirmationEmailSent(email); + } + + public static async Task Handle( + SendResetPasswordEmail message, + IMessageSenderService emailMessageService, + ILoggerFactory loggerFactory, + CancellationToken cancellationToken) + { + var (email, callbackURL) = message; + + await emailMessageService.SendResetPasswordLinkAsync(email, callbackURL, cancellationToken); + + loggerFactory.CreateLogger("MessageSenderHandler").LogResetPasswordEmailSent(email); + } + + public static async Task Handle( + SendChangeEmail message, + IMessageSenderService emailMessageService, + ILoggerFactory loggerFactory, + CancellationToken cancellationToken) + { + var (email, callbackURL) = message; + + await emailMessageService.SendEmailChangingLinkAsync(email, callbackURL, cancellationToken); + + loggerFactory.CreateLogger("MessageSenderHandler").LogEmailChangingLinkSent(email); + } +} diff --git a/CommentMap.EmailSender/Services/MessageSenderService.cs b/CommentMap.EmailSender/Services/MessageSenderService.cs index 4c90c12..61bdbb3 100644 --- a/CommentMap.EmailSender/Services/MessageSenderService.cs +++ b/CommentMap.EmailSender/Services/MessageSenderService.cs @@ -4,7 +4,7 @@ namespace CommentMap.EmailSender.Services; -public class MessageSenderService(ISmtpEmailSenderService smtpEmailSenderService, IMjmlRenderer mjmlRenderer) +public class MessageSenderService(ISmtpEmailSender smtpEmailSenderService, IMjmlRenderer mjmlRenderer) : IMessageSenderService { public async Task SendConfirmationLinkAsync(string email, string callbackURL, CancellationToken ct = default) diff --git a/CommentMap.EmailSender/Services/SendMessageConsumer.cs b/CommentMap.EmailSender/Services/SendMessageConsumer.cs new file mode 100644 index 0000000..0028bae --- /dev/null +++ b/CommentMap.EmailSender/Services/SendMessageConsumer.cs @@ -0,0 +1,35 @@ +using CommentMap.EmailSender.Logging; +using CommentMap.Shared.Messages; +using Microsoft.Extensions.Logging; + +namespace CommentMap.EmailSender.Services; + +public class SendMessageConsumer(IMessageSenderService emailMessageService, ILogger logger) +{ + public async Task ConsumeAsync(SendConfirmEmail sendConfirmEmail, CancellationToken cancellationToken) + { + var (email, callbackURL) = sendConfirmEmail; + + await emailMessageService.SendConfirmationLinkAsync(email, callbackURL, cancellationToken); + + logger.LogConfirmationEmailSent(email); + } + + public async Task ConsumeAsync(SendResetPasswordEmail sendResetPasswordEmail, CancellationToken cancellationToken) + { + var (email, callbackURL) = sendResetPasswordEmail; + + await emailMessageService.SendResetPasswordLinkAsync(email, callbackURL, cancellationToken); + + logger.LogResetPasswordEmailSent(email); + } + + public async Task ConsumeAsync(SendChangeEmail sendChangeEmail, CancellationToken cancellationToken) + { + var (email, callbackURL) = sendChangeEmail; + + await emailMessageService.SendEmailChangingLinkAsync(email, callbackURL, cancellationToken); + + logger.LogEmailChangingLinkSent(email); + } +} diff --git a/CommentMap.EmailSender/Services/SmtpClientFactory.cs b/CommentMap.EmailSender/Services/SmtpClientFactory.cs new file mode 100644 index 0000000..dfb8972 --- /dev/null +++ b/CommentMap.EmailSender/Services/SmtpClientFactory.cs @@ -0,0 +1,12 @@ +using MailKit.Net.Smtp; + +namespace CommentMap.EmailSender.Services; + +public class SmtpClientFactory : ISmtpClientFactory +{ + public ISmtpClient CreateClient() + { + var client = new SmtpClient(); + return client; + } +} \ No newline at end of file diff --git a/CommentMap.EmailSender/Services/SmtpEmailSender.cs b/CommentMap.EmailSender/Services/SmtpEmailSender.cs new file mode 100644 index 0000000..7f5181a --- /dev/null +++ b/CommentMap.EmailSender/Services/SmtpEmailSender.cs @@ -0,0 +1,57 @@ +using CommentMap.EmailSender.Options; +using MailKit.Security; +using Microsoft.Extensions.Options; +using MimeKit; + +namespace CommentMap.EmailSender.Services; + +public class SmtpEmailSender : ISmtpEmailSender +{ + private readonly ISmtpClientFactory _smtpClientFactory; + private readonly MailboxAddress _fromAddress; + private readonly string _host; + private readonly int _port; + + public SmtpEmailSender(ISmtpClientFactory smtpClientFactory, IOptions options) + { + var value = options.Value; + if (string.IsNullOrEmpty(value.Host)) + { + throw new ArgumentException("Host must be provided.", nameof(options)); + } + if (!value.Port.HasValue || value.Port <= 0) + { + throw new ArgumentException("Port must be a positive integer.", nameof(options)); + } + if (string.IsNullOrEmpty(value.FromAddress)) + { + throw new ArgumentException("FromAddress must be provided.", nameof(options)); + } + + _smtpClientFactory = smtpClientFactory; + _host = value.Host; + _port = value.Port.Value; + _fromAddress = new MailboxAddress(value.FromName, value.FromAddress); + } + + public async Task SendHtmlEmailAsync(string to, string subject, string htmlBody, CancellationToken ct = default) + { + var message = new MimeMessage(); + message.From.Add(_fromAddress); + message.To.Add(new MailboxAddress(null, to)); + message.Subject = subject; + + var bodyBuilder = new BodyBuilder + { + HtmlBody = htmlBody + }; + + message.Body = bodyBuilder.ToMessageBody(); + + using var smtpClient = _smtpClientFactory.CreateClient(); + + await smtpClient.ConnectAsync(_host, _port, SecureSocketOptions.None, ct); + await smtpClient.SendAsync(message, ct); + await smtpClient.DisconnectAsync(quit: true, ct); + } +} \ No newline at end of file diff --git a/CommentMap.EmailSender/Services/SmtpEmailSenderService.cs b/CommentMap.EmailSender/Services/SmtpEmailSenderService.cs deleted file mode 100644 index 771ae9c..0000000 --- a/CommentMap.EmailSender/Services/SmtpEmailSenderService.cs +++ /dev/null @@ -1,48 +0,0 @@ -using CommentMap.EmailSender.Options; -using MailKit.Net.Smtp; -using MailKit.Security; -using Microsoft.Extensions.Options; -using MimeKit; - -namespace CommentMap.EmailSender.Services; - -public class SmtpEmailSenderService : ISmtpEmailSenderService -{ - private readonly ISmtpClient _smtpClient; - private readonly MailboxAddress _fromAddress; - private readonly string _host; - private readonly int _port; - - public SmtpEmailSenderService(ISmtpClient smtpClient, IOptions options) - { - _smtpClient = smtpClient; - - var (fromName, fromAddress, smtp) = options.Value; - _fromAddress = new MailboxAddress(fromName, fromAddress); - - var uri = new Uri(smtp[0]); - _host = uri.Host; - _port = uri.Port; - } - - public async Task SendHtmlEmailAsync(string to, string subject, string htmlBody, CancellationToken ct = default) - { - var message = new MimeMessage(); - message.From.Add(_fromAddress); - message.To.Add(new MailboxAddress(null, to)); - message.Subject = subject; - - var bodyBuilder = new BodyBuilder - { - HtmlBody = htmlBody - }; - - message.Body = bodyBuilder.ToMessageBody(); - - await _smtpClient.ConnectAsync(_host, _port, SecureSocketOptions.None, ct); - - await _smtpClient.SendAsync(message, ct); - - await _smtpClient.DisconnectAsync(quit: true, ct); - } -} \ No newline at end of file diff --git a/CommentMap.EmailSender/appsettings.Development.json b/CommentMap.EmailSender/appsettings.Development.json deleted file mode 100644 index 3d84dbc..0000000 --- a/CommentMap.EmailSender/appsettings.Development.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "services": { - "mailpit": { - "FromName": "CommentMap", - "FromAddress": "no-reply@commentmap.com" - } - } -} \ No newline at end of file diff --git a/CommentMap.EmailSender/appsettings.json b/CommentMap.EmailSender/appsettings.json index 0c208ae..a8df3e7 100644 --- a/CommentMap.EmailSender/appsettings.json +++ b/CommentMap.EmailSender/appsettings.json @@ -4,5 +4,11 @@ "Default": "Information", "Microsoft.AspNetCore": "Warning" } + }, + "Aspire": { + "Mailpit": { + "FromName": "CommentMap", + "FromAddress": "no-reply@commentmap.com" + } } } diff --git a/CommentMap.Mvc/Program.cs b/CommentMap.Mvc/Program.cs index cf3746c..d5846c1 100644 --- a/CommentMap.Mvc/Program.cs +++ b/CommentMap.Mvc/Program.cs @@ -4,13 +4,34 @@ using CommentMap.Mvc.Services; using MassTransit; using Microsoft.AspNetCore.Identity; +using CommentMap.Shared.Messages; +using JasperFx; +using JasperFx.CodeGeneration; +using JasperFx.CodeGeneration.Model; using QRCoder; +using Wolverine; +using Wolverine.RabbitMQ; var builder = WebApplication.CreateBuilder(args); builder.AddServiceDefaults(); builder.AddCommentMapDbContext(); +builder.Host.UseWolverine(opts => +{ + opts.CodeGeneration.TypeLoadMode = TypeLoadMode.Static; + opts.ServiceLocationPolicy = ServiceLocationPolicy.AlwaysAllowed; + opts.Discovery.IncludeAssembly(typeof(AddComment).Assembly); + + opts.UseRabbitMqUsingNamedConnection("messaging") + .AutoProvision(); + + opts.PublishMessage().ToRabbitQueue(nameof(SendConfirmEmail)); + opts.PublishMessage().ToRabbitQueue(nameof(SendResetPasswordEmail)); + opts.PublishMessage().ToRabbitQueue(nameof(SendChangeEmail)); +}); + +builder.AddInfrastructure(); builder.Services .AddIdentity(options => @@ -55,10 +76,10 @@ cfg.Host(host); }); }); +builder.Services.AddRazorPages(); var app = builder.Build(); -// Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseMigrationsEndPoint(); @@ -76,4 +97,4 @@ app.MapRazorPages(); -app.Run(); \ No newline at end of file +return await app.RunJasperFxCommands(args); From cd4ec30aac53e5a536e721c2fd73caa2ec20b8b9 Mon Sep 17 00:00:00 2001 From: Ivan Kozelskikh Date: Tue, 4 Aug 2026 23:16:33 +0500 Subject: [PATCH 04/23] Introduce Application & Infrastructure layers with Wolverine Restructure solution: add CommentMap.Application and CommentMap.Infrastructure projects and move entities, DTOs and the ICommentMapDbContext abstraction into the Application layer. Move EF DbContext, configurations and migrations into Infrastructure. Implement CQRS-like features (commands/queries) for comments, countries and Identity flows as message handlers/handlers results and add generated Wolverine handlers. Replace many in-MVC services with IMessageBus invocations and remove now-redundant service classes. Update DI via InfrastructureServiceCollectionExtensions and Program to use Wolverine and new projects, plus Identity mapping and new DTO models. --- .../Abstractions}/ICommentMapDbContext.cs | 4 +- .../CommentMap.Application.csproj | 23 ++ .../Entities/Comment.cs | 4 +- .../Entities/Country.cs | 4 +- CommentMap.Application/Entities/Role.cs | 7 + .../Entities/User.cs | 4 +- .../Features/Comments/AddComment.cs | 34 +++ .../Features/Comments/DeleteComment.cs | 16 + .../Features/Comments/GetCommentTitle.cs | 21 ++ .../Features/Comments/ListComments.cs | 41 +++ .../Features/Countries/GetCountry.cs | 26 ++ .../Features/Identity/ChangeEmail.cs | 44 +++ .../Features/Identity/ChangePassword.cs | 67 +++++ .../Features/Identity/ConfirmEmail.cs | 23 ++ .../Features/Identity/ConfirmEmailChange.cs | 34 +++ .../Features/Identity/DeleteProfile.cs | 53 ++++ .../Features/Identity/ExternalLogin.cs | 146 +++++++++ .../Features/Identity/ForgotPassword.cs | 24 ++ .../Features/Identity/IdentityMapping.cs | 13 + .../Features/Identity/LoginUser.cs | 30 ++ .../Features/Identity/LogoutUser.cs | 16 + .../Features/Identity/RegisterUser.cs | 47 +++ .../Identity/ResendEmailConfirmation.cs | 26 ++ .../Features/Identity/ResetPassword.cs | 23 ++ .../Features/Identity/TwoFactor.cs | 279 ++++++++++++++++++ .../Models/CommentCardDto.cs | 9 + CommentMap.Application/Models/CountryDto.cs | 8 + .../Models/IdentityResultDto.cs | 31 ++ .../Models/Order.cs | 4 +- .../Extensions/ServiceCollectionExtensions.cs | 2 +- .../CommentMap.Infrastructure.csproj | 30 ++ .../Data/CommentMapDbContext.cs | 10 +- .../Configurations/CommentConfiguration.cs | 5 +- .../Configurations/CountryConfiguration.cs | 5 +- ...0240523173725_InitialMigration.Designer.cs | 30 +- .../20240523173725_InitialMigration.cs | 4 +- ...525160654_AddCommentProperties.Designer.cs | 30 +- .../20240525160654_AddCommentProperties.cs | 4 +- .../20240623144537_AddIsDeleted.Designer.cs | 30 +- .../Migrations/20240623144537_AddIsDeleted.cs | 4 +- .../20240909164708_AddCountry.Designer.cs | 32 +- .../Migrations/20240909164708_AddCountry.cs | 4 +- ...39_AddISO3CountryCodeToComment.Designer.cs | 36 +-- ...40921074639_AddISO3CountryCodeToComment.cs | 4 +- .../CommentMapDbContextModelSnapshot.cs | 40 +-- ...frastructureServiceCollectionExtensions.cs | 37 +++ .../Pages/Account/ConfirmEmail.cshtml.cs | 23 +- .../Account/ConfirmEmailChange.cshtml.cs | 36 +-- .../Pages/Account/ExternalLogin.cshtml.cs | 139 ++------- .../Pages/Account/ForgotPassword.cshtml.cs | 54 +--- .../Identity/Pages/Account/Login.cshtml.cs | 110 ++----- .../Pages/Account/LoginWith2fa.cshtml.cs | 98 ++---- .../Account/LoginWithRecoveryCode.cshtml.cs | 87 ++---- .../Identity/Pages/Account/Logout.cshtml.cs | 28 +- .../Account/Manage/ChangePassword.cshtml.cs | 83 ++---- .../Account/Manage/DeleteProfile.cshtml.cs | 83 ++---- .../Pages/Account/Manage/Disable2fa.cshtml.cs | 56 +--- .../Manage/EnableAuthenticator.cshtml.cs | 144 +++------ .../Account/Manage/ExternalLogins.cshtml.cs | 127 +++----- .../Manage/GenerateRecoveryCodes.cshtml.cs | 68 ++--- .../Pages/Account/Manage/Index.cshtml.cs | 83 ++---- .../Manage/ResetAuthenticator.cshtml.cs | 51 +--- .../Account/Manage/SetPassword.cshtml.cs | 84 ++---- .../Manage/TwoFactorAuthentication.cshtml.cs | 72 ++--- .../Identity/Pages/Account/Register.cshtml.cs | 144 ++------- .../Account/ResendEmailConfirmation.cshtml.cs | 46 +-- .../Pages/Account/ResetPassword.cshtml.cs | 56 +--- CommentMap.Mvc/CommentMap.Mvc.csproj | 7 + CommentMap.Mvc/Data/Entities/Role.cs | 8 - .../ServiceCollectionExtensions.cs | 23 -- .../Extensions/QueriableExtensions.cs | 17 -- .../AddCommentHandler838741630.cs | 46 +++ .../ChangePasswordHandler702758377.cs | 95 ++++++ .../ConfirmEmailChangeHandler1497850754.cs | 92 ++++++ .../ConfirmEmailHandler55631218.cs | 56 ++++ .../CreateExternalUserHandler966620274.cs | 101 +++++++ .../DeleteCommentHandler107828254.cs | 46 +++ .../DeleteProfileHandler1834710062.cs | 95 ++++++ .../Disable2faHandler1923519541.cs | 59 ++++ .../EnableAuthenticatorHandler897587120.cs | 65 ++++ .../ExternalLoginSignInHandler1809594924.cs | 83 ++++++ .../ForgetTwoFactorClientHandler253588197.cs | 92 ++++++ .../ForgotPasswordHandler1306123444.cs | 56 ++++ .../GenerateRecoveryCodesHandler711237032.cs | 59 ++++ .../GeneratedHandlerRegistry.cs | 29 ++ .../GetAuthenticatorSetupHandler507613430.cs | 62 ++++ .../GetCommentTitleHandler595995119.cs | 50 ++++ .../GetCountryHandler1133281984.cs | 50 ++++ .../GetDeleteProfileInfoHandler900389426.cs | 56 ++++ .../GetExternalLoginsHandler199405825.cs | 98 ++++++ .../GetProfileEmailHandler1046567855.cs | 56 ++++ .../GetTwoFactorStatusHandler1213804985.cs | 92 ++++++ .../HasPasswordHandler1751871263.cs | 56 ++++ .../LinkExternalLoginHandler251495890.cs | 92 ++++++ .../ListCommentsHandler488515704.cs | 50 ++++ .../LoginUserHandler1789921628.cs | 83 ++++++ .../LoginWith2faHandler292869486.cs | 83 ++++++ .../LoginWithRecoveryCodeHandler277354287.cs | 83 ++++++ .../LogoutUserHandler132148485.cs | 79 +++++ .../RegisterUserHandler1265692392.cs | 62 ++++ .../RemoveExternalLoginHandler62493602.cs | 92 ++++++ .../RequestEmailChangeHandler172865511.cs | 56 ++++ .../ResendEmailConfirmationHandler19836290.cs | 56 ++++ .../ResetAuthenticatorHandler25524780.cs | 95 ++++++ .../ResetPasswordHandler433488700.cs | 56 ++++ .../SetPasswordHandler836449791.cs | 92 ++++++ ...ignInAfterRegistrationHandler2047984407.cs | 88 ++++++ CommentMap.Mvc/Models/AddNewCommentDto.cs | 3 - CommentMap.Mvc/Models/AddNewCommentInput.cs | 2 +- CommentMap.Mvc/Models/GetAllCommentsDto.cs | 3 - CommentMap.Mvc/Pages/Comments/Add.cshtml.cs | 14 +- .../Pages/Comments/ConfirmDelete.cshtml.cs | 11 +- CommentMap.Mvc/Pages/Comments/Index.cshtml | 1 - CommentMap.Mvc/Pages/Comments/Index.cshtml.cs | 21 +- .../Pages/Countries/Index.cshtml.cs | 21 +- CommentMap.Mvc/Pages/_ViewImports.cshtml | 3 +- CommentMap.Mvc/Program.cs | 37 +-- CommentMap.Mvc/Services/AddCommentService.cs | 17 -- CommentMap.Mvc/Services/CommentFactory.cs | 27 -- .../Services/ConfirmDeleteService.cs | 17 -- .../Services/DeleteCommentService.cs | 14 - .../Services/EnableAuthenticatorService.cs | 24 -- .../Services/GetCountryViewModelService.cs | 24 -- .../Services/GuessCountryService.cs | 16 - CommentMap.Mvc/Services/IAddCommentService.cs | 8 - CommentMap.Mvc/Services/ICommentFactory.cs | 9 - .../Services/IConfirmDeleteService.cs | 6 - .../Services/IDeleteCommentService.cs | 7 - .../Services/IEnableAuthenticatorService.cs | 7 - .../Services/IGetCountryViewModelService.cs | 8 - .../Services/IGuessCountryService.cs | 8 - .../Services/IListCommentsService.cs | 9 - .../Services/ListCommentsService.cs | 21 -- .../SignInPanelViewComponent.cs | 2 +- CommentMap.Mvc/ViewModels/CountryViewModel.cs | 1 - 135 files changed, 4263 insertions(+), 1734 deletions(-) rename {CommentMap.Mvc/Data => CommentMap.Application/Abstractions}/ICommentMapDbContext.cs (77%) create mode 100644 CommentMap.Application/CommentMap.Application.csproj rename {CommentMap.Mvc/Data => CommentMap.Application}/Entities/Comment.cs (91%) rename {CommentMap.Mvc/Data => CommentMap.Application}/Entities/Country.cs (85%) create mode 100644 CommentMap.Application/Entities/Role.cs rename {CommentMap.Mvc/Data => CommentMap.Application}/Entities/User.cs (54%) create mode 100644 CommentMap.Application/Features/Comments/AddComment.cs create mode 100644 CommentMap.Application/Features/Comments/DeleteComment.cs create mode 100644 CommentMap.Application/Features/Comments/GetCommentTitle.cs create mode 100644 CommentMap.Application/Features/Comments/ListComments.cs create mode 100644 CommentMap.Application/Features/Countries/GetCountry.cs create mode 100644 CommentMap.Application/Features/Identity/ChangeEmail.cs create mode 100644 CommentMap.Application/Features/Identity/ChangePassword.cs create mode 100644 CommentMap.Application/Features/Identity/ConfirmEmail.cs create mode 100644 CommentMap.Application/Features/Identity/ConfirmEmailChange.cs create mode 100644 CommentMap.Application/Features/Identity/DeleteProfile.cs create mode 100644 CommentMap.Application/Features/Identity/ExternalLogin.cs create mode 100644 CommentMap.Application/Features/Identity/ForgotPassword.cs create mode 100644 CommentMap.Application/Features/Identity/IdentityMapping.cs create mode 100644 CommentMap.Application/Features/Identity/LoginUser.cs create mode 100644 CommentMap.Application/Features/Identity/LogoutUser.cs create mode 100644 CommentMap.Application/Features/Identity/RegisterUser.cs create mode 100644 CommentMap.Application/Features/Identity/ResendEmailConfirmation.cs create mode 100644 CommentMap.Application/Features/Identity/ResetPassword.cs create mode 100644 CommentMap.Application/Features/Identity/TwoFactor.cs create mode 100644 CommentMap.Application/Models/CommentCardDto.cs create mode 100644 CommentMap.Application/Models/CountryDto.cs create mode 100644 CommentMap.Application/Models/IdentityResultDto.cs rename {CommentMap.Mvc => CommentMap.Application}/Models/Order.cs (57%) create mode 100644 CommentMap.Infrastructure/CommentMap.Infrastructure.csproj rename {CommentMap.Mvc => CommentMap.Infrastructure}/Data/CommentMapDbContext.cs (65%) rename {CommentMap.Mvc/Data/Entities => CommentMap.Infrastructure/Data}/Configurations/CommentConfiguration.cs (88%) rename {CommentMap.Mvc/Data/Entities => CommentMap.Infrastructure/Data}/Configurations/CountryConfiguration.cs (84%) rename {CommentMap.Mvc => CommentMap.Infrastructure}/Data/Migrations/20240523173725_InitialMigration.Designer.cs (91%) rename {CommentMap.Mvc => CommentMap.Infrastructure}/Data/Migrations/20240523173725_InitialMigration.cs (99%) rename {CommentMap.Mvc => CommentMap.Infrastructure}/Data/Migrations/20240525160654_AddCommentProperties.Designer.cs (91%) rename {CommentMap.Mvc => CommentMap.Infrastructure}/Data/Migrations/20240525160654_AddCommentProperties.cs (95%) rename {CommentMap.Mvc => CommentMap.Infrastructure}/Data/Migrations/20240623144537_AddIsDeleted.Designer.cs (91%) rename {CommentMap.Mvc => CommentMap.Infrastructure}/Data/Migrations/20240623144537_AddIsDeleted.cs (93%) rename {CommentMap.Mvc => CommentMap.Infrastructure}/Data/Migrations/20240909164708_AddCountry.Designer.cs (92%) rename {CommentMap.Mvc => CommentMap.Infrastructure}/Data/Migrations/20240909164708_AddCountry.cs (96%) rename {CommentMap.Mvc => CommentMap.Infrastructure}/Data/Migrations/20240921074639_AddISO3CountryCodeToComment.Designer.cs (91%) rename {CommentMap.Mvc => CommentMap.Infrastructure}/Data/Migrations/20240921074639_AddISO3CountryCodeToComment.cs (93%) rename {CommentMap.Mvc => CommentMap.Infrastructure}/Data/Migrations/CommentMapDbContextModelSnapshot.cs (90%) create mode 100644 CommentMap.Infrastructure/DependencyInjection/InfrastructureServiceCollectionExtensions.cs delete mode 100644 CommentMap.Mvc/Data/Entities/Role.cs delete mode 100644 CommentMap.Mvc/Extensions/DependencyInjection/ServiceCollectionExtensions.cs delete mode 100644 CommentMap.Mvc/Extensions/QueriableExtensions.cs create mode 100644 CommentMap.Mvc/Internal/Generated/WolverineHandlers/AddCommentHandler838741630.cs create mode 100644 CommentMap.Mvc/Internal/Generated/WolverineHandlers/ChangePasswordHandler702758377.cs create mode 100644 CommentMap.Mvc/Internal/Generated/WolverineHandlers/ConfirmEmailChangeHandler1497850754.cs create mode 100644 CommentMap.Mvc/Internal/Generated/WolverineHandlers/ConfirmEmailHandler55631218.cs create mode 100644 CommentMap.Mvc/Internal/Generated/WolverineHandlers/CreateExternalUserHandler966620274.cs create mode 100644 CommentMap.Mvc/Internal/Generated/WolverineHandlers/DeleteCommentHandler107828254.cs create mode 100644 CommentMap.Mvc/Internal/Generated/WolverineHandlers/DeleteProfileHandler1834710062.cs create mode 100644 CommentMap.Mvc/Internal/Generated/WolverineHandlers/Disable2faHandler1923519541.cs create mode 100644 CommentMap.Mvc/Internal/Generated/WolverineHandlers/EnableAuthenticatorHandler897587120.cs create mode 100644 CommentMap.Mvc/Internal/Generated/WolverineHandlers/ExternalLoginSignInHandler1809594924.cs create mode 100644 CommentMap.Mvc/Internal/Generated/WolverineHandlers/ForgetTwoFactorClientHandler253588197.cs create mode 100644 CommentMap.Mvc/Internal/Generated/WolverineHandlers/ForgotPasswordHandler1306123444.cs create mode 100644 CommentMap.Mvc/Internal/Generated/WolverineHandlers/GenerateRecoveryCodesHandler711237032.cs create mode 100644 CommentMap.Mvc/Internal/Generated/WolverineHandlers/GeneratedHandlerRegistry.cs create mode 100644 CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetAuthenticatorSetupHandler507613430.cs create mode 100644 CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetCommentTitleHandler595995119.cs create mode 100644 CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetCountryHandler1133281984.cs create mode 100644 CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetDeleteProfileInfoHandler900389426.cs create mode 100644 CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetExternalLoginsHandler199405825.cs create mode 100644 CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetProfileEmailHandler1046567855.cs create mode 100644 CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetTwoFactorStatusHandler1213804985.cs create mode 100644 CommentMap.Mvc/Internal/Generated/WolverineHandlers/HasPasswordHandler1751871263.cs create mode 100644 CommentMap.Mvc/Internal/Generated/WolverineHandlers/LinkExternalLoginHandler251495890.cs create mode 100644 CommentMap.Mvc/Internal/Generated/WolverineHandlers/ListCommentsHandler488515704.cs create mode 100644 CommentMap.Mvc/Internal/Generated/WolverineHandlers/LoginUserHandler1789921628.cs create mode 100644 CommentMap.Mvc/Internal/Generated/WolverineHandlers/LoginWith2faHandler292869486.cs create mode 100644 CommentMap.Mvc/Internal/Generated/WolverineHandlers/LoginWithRecoveryCodeHandler277354287.cs create mode 100644 CommentMap.Mvc/Internal/Generated/WolverineHandlers/LogoutUserHandler132148485.cs create mode 100644 CommentMap.Mvc/Internal/Generated/WolverineHandlers/RegisterUserHandler1265692392.cs create mode 100644 CommentMap.Mvc/Internal/Generated/WolverineHandlers/RemoveExternalLoginHandler62493602.cs create mode 100644 CommentMap.Mvc/Internal/Generated/WolverineHandlers/RequestEmailChangeHandler172865511.cs create mode 100644 CommentMap.Mvc/Internal/Generated/WolverineHandlers/ResendEmailConfirmationHandler19836290.cs create mode 100644 CommentMap.Mvc/Internal/Generated/WolverineHandlers/ResetAuthenticatorHandler25524780.cs create mode 100644 CommentMap.Mvc/Internal/Generated/WolverineHandlers/ResetPasswordHandler433488700.cs create mode 100644 CommentMap.Mvc/Internal/Generated/WolverineHandlers/SetPasswordHandler836449791.cs create mode 100644 CommentMap.Mvc/Internal/Generated/WolverineHandlers/SignInAfterRegistrationHandler2047984407.cs delete mode 100644 CommentMap.Mvc/Models/AddNewCommentDto.cs delete mode 100644 CommentMap.Mvc/Models/GetAllCommentsDto.cs delete mode 100644 CommentMap.Mvc/Services/AddCommentService.cs delete mode 100644 CommentMap.Mvc/Services/CommentFactory.cs delete mode 100644 CommentMap.Mvc/Services/ConfirmDeleteService.cs delete mode 100644 CommentMap.Mvc/Services/DeleteCommentService.cs delete mode 100644 CommentMap.Mvc/Services/EnableAuthenticatorService.cs delete mode 100644 CommentMap.Mvc/Services/GetCountryViewModelService.cs delete mode 100644 CommentMap.Mvc/Services/GuessCountryService.cs delete mode 100644 CommentMap.Mvc/Services/IAddCommentService.cs delete mode 100644 CommentMap.Mvc/Services/ICommentFactory.cs delete mode 100644 CommentMap.Mvc/Services/IConfirmDeleteService.cs delete mode 100644 CommentMap.Mvc/Services/IDeleteCommentService.cs delete mode 100644 CommentMap.Mvc/Services/IEnableAuthenticatorService.cs delete mode 100644 CommentMap.Mvc/Services/IGetCountryViewModelService.cs delete mode 100644 CommentMap.Mvc/Services/IGuessCountryService.cs delete mode 100644 CommentMap.Mvc/Services/IListCommentsService.cs delete mode 100644 CommentMap.Mvc/Services/ListCommentsService.cs diff --git a/CommentMap.Mvc/Data/ICommentMapDbContext.cs b/CommentMap.Application/Abstractions/ICommentMapDbContext.cs similarity index 77% rename from CommentMap.Mvc/Data/ICommentMapDbContext.cs rename to CommentMap.Application/Abstractions/ICommentMapDbContext.cs index 1b5fc71..56cdd7d 100644 --- a/CommentMap.Mvc/Data/ICommentMapDbContext.cs +++ b/CommentMap.Application/Abstractions/ICommentMapDbContext.cs @@ -1,7 +1,7 @@ -using CommentMap.Mvc.Data.Entities; +using CommentMap.Application.Entities; using Microsoft.EntityFrameworkCore; -namespace CommentMap.Mvc.Data; +namespace CommentMap.Application.Abstractions; public interface ICommentMapDbContext { diff --git a/CommentMap.Application/CommentMap.Application.csproj b/CommentMap.Application/CommentMap.Application.csproj new file mode 100644 index 0000000..e6e1433 --- /dev/null +++ b/CommentMap.Application/CommentMap.Application.csproj @@ -0,0 +1,23 @@ + + + + net10.0 + enable + enable + + + + + + + + + + + + + + + + + diff --git a/CommentMap.Mvc/Data/Entities/Comment.cs b/CommentMap.Application/Entities/Comment.cs similarity index 91% rename from CommentMap.Mvc/Data/Entities/Comment.cs rename to CommentMap.Application/Entities/Comment.cs index d0162d7..438b33b 100644 --- a/CommentMap.Mvc/Data/Entities/Comment.cs +++ b/CommentMap.Application/Entities/Comment.cs @@ -1,6 +1,6 @@ -using NetTopologySuite.Geometries; +using NetTopologySuite.Geometries; -namespace CommentMap.Mvc.Data.Entities; +namespace CommentMap.Application.Entities; public class Comment : IEquatable { diff --git a/CommentMap.Mvc/Data/Entities/Country.cs b/CommentMap.Application/Entities/Country.cs similarity index 85% rename from CommentMap.Mvc/Data/Entities/Country.cs rename to CommentMap.Application/Entities/Country.cs index 46b19d1..49bca30 100644 --- a/CommentMap.Mvc/Data/Entities/Country.cs +++ b/CommentMap.Application/Entities/Country.cs @@ -1,6 +1,6 @@ -using NetTopologySuite.Geometries; +using NetTopologySuite.Geometries; -namespace CommentMap.Mvc.Data.Entities; +namespace CommentMap.Application.Entities; public class Country { diff --git a/CommentMap.Application/Entities/Role.cs b/CommentMap.Application/Entities/Role.cs new file mode 100644 index 0000000..758256c --- /dev/null +++ b/CommentMap.Application/Entities/Role.cs @@ -0,0 +1,7 @@ +using Microsoft.AspNetCore.Identity; + +namespace CommentMap.Application.Entities; + +public class Role : IdentityRole +{ +} diff --git a/CommentMap.Mvc/Data/Entities/User.cs b/CommentMap.Application/Entities/User.cs similarity index 54% rename from CommentMap.Mvc/Data/Entities/User.cs rename to CommentMap.Application/Entities/User.cs index 04b39cf..de0c67b 100644 --- a/CommentMap.Mvc/Data/Entities/User.cs +++ b/CommentMap.Application/Entities/User.cs @@ -1,6 +1,6 @@ -using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Identity; -namespace CommentMap.Mvc.Data.Entities; +namespace CommentMap.Application.Entities; public class User : IdentityUser { diff --git a/CommentMap.Application/Features/Comments/AddComment.cs b/CommentMap.Application/Features/Comments/AddComment.cs new file mode 100644 index 0000000..736775b --- /dev/null +++ b/CommentMap.Application/Features/Comments/AddComment.cs @@ -0,0 +1,34 @@ +using CommentMap.Application.Abstractions; +using CommentMap.Application.Entities; +using Microsoft.EntityFrameworkCore; +using NetTopologySuite.Geometries; + +namespace CommentMap.Application.Features.Comments; + +public record AddComment(Guid UserId, string Title, string Text, double Longitude, double Latitude); + +public static class AddCommentHandler +{ + public static async Task Handle(AddComment command, ICommentMapDbContext db, CancellationToken cancellationToken) + { + var point = new Point(command.Longitude, command.Latitude) { SRID = 3857 }; + var iso3Code = await db.Countries + .Where(c => c.Boundaries.Intersects(point)) + .Select(c => c.ISO3Code) + .FirstOrDefaultAsync(cancellationToken); + + var comment = new Comment + { + Id = Guid.CreateVersion7(), + UserId = command.UserId, + Location = point, + Title = command.Title, + Text = command.Text, + CreatedAt = DateTime.UtcNow, + ISO3CodeCountry = iso3Code, + }; + + db.Comments.Add(comment); + await db.SaveChangesAsync(cancellationToken); + } +} diff --git a/CommentMap.Application/Features/Comments/DeleteComment.cs b/CommentMap.Application/Features/Comments/DeleteComment.cs new file mode 100644 index 0000000..5199249 --- /dev/null +++ b/CommentMap.Application/Features/Comments/DeleteComment.cs @@ -0,0 +1,16 @@ +using CommentMap.Application.Abstractions; +using Microsoft.EntityFrameworkCore; + +namespace CommentMap.Application.Features.Comments; + +public record DeleteComment(Guid Id); + +public static class DeleteCommentHandler +{ + public static Task Handle(DeleteComment command, ICommentMapDbContext db, CancellationToken cancellationToken) + { + return db.Comments + .Where(c => c.Id == command.Id) + .ExecuteUpdateAsync(setters => setters.SetProperty(q => q.IsDeleted, true), cancellationToken); + } +} diff --git a/CommentMap.Application/Features/Comments/GetCommentTitle.cs b/CommentMap.Application/Features/Comments/GetCommentTitle.cs new file mode 100644 index 0000000..9087a34 --- /dev/null +++ b/CommentMap.Application/Features/Comments/GetCommentTitle.cs @@ -0,0 +1,21 @@ +using CommentMap.Application.Abstractions; +using Microsoft.EntityFrameworkCore; + +namespace CommentMap.Application.Features.Comments; + +public record GetCommentTitle(Guid Id); + +public static class GetCommentTitleHandler +{ + public static Task Handle( + GetCommentTitle query, + ICommentMapDbContext db, + CancellationToken cancellationToken) + { + return db.Comments + .AsNoTracking() + .Where(c => c.Id == query.Id) + .Select(c => c.Title) + .FirstOrDefaultAsync(cancellationToken); + } +} diff --git a/CommentMap.Application/Features/Comments/ListComments.cs b/CommentMap.Application/Features/Comments/ListComments.cs new file mode 100644 index 0000000..0b75627 --- /dev/null +++ b/CommentMap.Application/Features/Comments/ListComments.cs @@ -0,0 +1,41 @@ +using CommentMap.Application.Abstractions; +using CommentMap.Application.Entities; +using CommentMap.Application.Models; +using Microsoft.EntityFrameworkCore; + +namespace CommentMap.Application.Features.Comments; + +public record ListComments(Guid UserId, Order Order); + +public static class ListCommentsHandler +{ + public static async Task> Handle( + ListComments query, + ICommentMapDbContext db, + CancellationToken cancellationToken) + { + var commentsQuery = db.Comments + .Where(c => c.UserId == query.UserId) + .Where(c => !c.IsDeleted); + + commentsQuery = OrderBy(commentsQuery, query.Order); + + return await commentsQuery + .Select(c => new CommentCardDto( + c.Id, + c.Location.X, + c.Location.Y, + c.Title, + c.Text, + c.CreatedAt)) + .ToListAsync(cancellationToken); + } + + private static IQueryable OrderBy(IQueryable queryable, Order order) => + order switch + { + Order.CreatedAt => queryable.OrderBy(c => c.Id), + Order.Title => queryable.OrderBy(c => c.Title), + _ => throw new ArgumentOutOfRangeException(nameof(order), order, "Unexpected order value."), + }; +} diff --git a/CommentMap.Application/Features/Countries/GetCountry.cs b/CommentMap.Application/Features/Countries/GetCountry.cs new file mode 100644 index 0000000..1ebb5c6 --- /dev/null +++ b/CommentMap.Application/Features/Countries/GetCountry.cs @@ -0,0 +1,26 @@ +using CommentMap.Application.Abstractions; +using CommentMap.Application.Models; +using Microsoft.EntityFrameworkCore; + +namespace CommentMap.Application.Features.Countries; + +public record GetCountry(string ISO3Code); + +public static class GetCountryHandler +{ + public static Task Handle( + GetCountry query, + ICommentMapDbContext db, + CancellationToken cancellationToken) + { + return db.Countries + .Where(c => c.ISO3Code.ToLower().Equals(query.ISO3Code.ToLower())) + .Select(c => new CountryDto( + c.ISO3Code, + c.ISO2Code, + c.Name, + c.RegionName, + c.SubregionName)) + .FirstOrDefaultAsync(cancellationToken); + } +} diff --git a/CommentMap.Application/Features/Identity/ChangeEmail.cs b/CommentMap.Application/Features/Identity/ChangeEmail.cs new file mode 100644 index 0000000..e7c87ee --- /dev/null +++ b/CommentMap.Application/Features/Identity/ChangeEmail.cs @@ -0,0 +1,44 @@ +using CommentMap.Application.Entities; +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.WebUtilities; +using System.Text; + +namespace CommentMap.Application.Features.Identity; + +public record GetProfileEmail(Guid UserId); +public record GetProfileEmailResult(bool Found, string? Email); + +public static class GetProfileEmailHandler +{ + public static async Task Handle(GetProfileEmail query, UserManager userManager) + { + var user = await userManager.FindByIdAsync(query.UserId.ToString()); + if (user is null) + return new GetProfileEmailResult(false, null); + + return new GetProfileEmailResult(true, await userManager.GetEmailAsync(user)); + } +} + +public record RequestEmailChange(Guid UserId, string NewEmail); +public record RequestEmailChangeResult(bool Found, bool Unchanged, string? EncodedCode); + +public static class RequestEmailChangeHandler +{ + public static async Task Handle( + RequestEmailChange command, + UserManager userManager) + { + var user = await userManager.FindByIdAsync(command.UserId.ToString()); + if (user is null) + return new RequestEmailChangeResult(false, false, null); + + var email = await userManager.GetEmailAsync(user); + if (command.NewEmail == email) + return new RequestEmailChangeResult(true, true, null); + + var code = await userManager.GenerateChangeEmailTokenAsync(user, command.NewEmail); + var encoded = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code)); + return new RequestEmailChangeResult(true, false, encoded); + } +} diff --git a/CommentMap.Application/Features/Identity/ChangePassword.cs b/CommentMap.Application/Features/Identity/ChangePassword.cs new file mode 100644 index 0000000..9738f2c --- /dev/null +++ b/CommentMap.Application/Features/Identity/ChangePassword.cs @@ -0,0 +1,67 @@ +using CommentMap.Application.Entities; +using CommentMap.Application.Models; +using Microsoft.AspNetCore.Identity; +using Microsoft.Extensions.Logging; + +namespace CommentMap.Application.Features.Identity; + +public record HasPassword(Guid UserId); +public record HasPasswordResult(bool Found, bool HasPassword); + +public static class HasPasswordHandler +{ + public static async Task Handle(HasPassword query, UserManager userManager) + { + var user = await userManager.FindByIdAsync(query.UserId.ToString()); + if (user is null) + return new HasPasswordResult(false, false); + + return new HasPasswordResult(true, await userManager.HasPasswordAsync(user)); + } +} + +public record ChangePassword(Guid UserId, string OldPassword, string NewPassword); + +public static class ChangePasswordHandler +{ + public static async Task Handle( + ChangePassword command, + UserManager userManager, + SignInManager signInManager, + ILogger logger) + { + var user = await userManager.FindByIdAsync(command.UserId.ToString()); + if (user is null) + return IdentityResultDto.Failed([new IdentityErrorDto("UserNotFound", "Unable to load user.")]); + + var result = await userManager.ChangePasswordAsync(user, command.OldPassword, command.NewPassword); + if (!result.Succeeded) + return result.ToDto(); + + await signInManager.RefreshSignInAsync(user); + logger.LogInformation("User changed their password successfully."); + return IdentityResultDto.Success(); + } +} + +public record SetPassword(Guid UserId, string NewPassword); + +public static class SetPasswordHandler +{ + public static async Task Handle( + SetPassword command, + UserManager userManager, + SignInManager signInManager) + { + var user = await userManager.FindByIdAsync(command.UserId.ToString()); + if (user is null) + return IdentityResultDto.Failed([new IdentityErrorDto("UserNotFound", "Unable to load user.")]); + + var result = await userManager.AddPasswordAsync(user, command.NewPassword); + if (!result.Succeeded) + return result.ToDto(); + + await signInManager.RefreshSignInAsync(user); + return IdentityResultDto.Success(); + } +} diff --git a/CommentMap.Application/Features/Identity/ConfirmEmail.cs b/CommentMap.Application/Features/Identity/ConfirmEmail.cs new file mode 100644 index 0000000..3dfbe07 --- /dev/null +++ b/CommentMap.Application/Features/Identity/ConfirmEmail.cs @@ -0,0 +1,23 @@ +using CommentMap.Application.Entities; +using CommentMap.Application.Models; +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.WebUtilities; +using System.Text; + +namespace CommentMap.Application.Features.Identity; + +public record ConfirmEmail(string UserId, string EncodedCode); + +public static class ConfirmEmailHandler +{ + public static async Task Handle(ConfirmEmail command, UserManager userManager) + { + var user = await userManager.FindByIdAsync(command.UserId); + if (user is null) + return IdentityResultDto.Failed([new IdentityErrorDto("UserNotFound", "Unable to load user.")]); + + var code = Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(command.EncodedCode)); + var result = await userManager.ConfirmEmailAsync(user, code); + return result.ToDto(); + } +} diff --git a/CommentMap.Application/Features/Identity/ConfirmEmailChange.cs b/CommentMap.Application/Features/Identity/ConfirmEmailChange.cs new file mode 100644 index 0000000..0551927 --- /dev/null +++ b/CommentMap.Application/Features/Identity/ConfirmEmailChange.cs @@ -0,0 +1,34 @@ +using CommentMap.Application.Entities; +using CommentMap.Application.Models; +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.WebUtilities; +using System.Text; + +namespace CommentMap.Application.Features.Identity; + +public record ConfirmEmailChange(string UserId, string Email, string EncodedCode); + +public static class ConfirmEmailChangeHandler +{ + public static async Task Handle( + ConfirmEmailChange command, + UserManager userManager, + SignInManager signInManager) + { + var user = await userManager.FindByIdAsync(command.UserId); + if (user is null) + return IdentityResultDto.Failed([new IdentityErrorDto("UserNotFound", "Unable to load user.")]); + + var code = Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(command.EncodedCode)); + var result = await userManager.ChangeEmailAsync(user, command.Email, code); + if (!result.Succeeded) + return result.ToDto(); + + var setUserNameResult = await userManager.SetUserNameAsync(user, command.Email); + if (!setUserNameResult.Succeeded) + return setUserNameResult.ToDto(); + + await signInManager.RefreshSignInAsync(user); + return IdentityResultDto.Success(); + } +} diff --git a/CommentMap.Application/Features/Identity/DeleteProfile.cs b/CommentMap.Application/Features/Identity/DeleteProfile.cs new file mode 100644 index 0000000..c0ff63f --- /dev/null +++ b/CommentMap.Application/Features/Identity/DeleteProfile.cs @@ -0,0 +1,53 @@ +using CommentMap.Application.Entities; +using CommentMap.Application.Models; +using Microsoft.AspNetCore.Identity; +using Microsoft.Extensions.Logging; + +namespace CommentMap.Application.Features.Identity; + +public record GetDeleteProfileInfo(Guid UserId); +public record GetDeleteProfileInfoResult(bool Found, bool RequirePassword); + +public static class GetDeleteProfileInfoHandler +{ + public static async Task Handle( + GetDeleteProfileInfo query, + UserManager userManager) + { + var user = await userManager.FindByIdAsync(query.UserId.ToString()); + if (user is null) + return new GetDeleteProfileInfoResult(false, false); + + return new GetDeleteProfileInfoResult(true, await userManager.HasPasswordAsync(user)); + } +} + +public record DeleteProfile(Guid UserId, string? Password); + +public static class DeleteProfileHandler +{ + public static async Task Handle( + DeleteProfile command, + UserManager userManager, + SignInManager signInManager, + ILogger logger) + { + var user = await userManager.FindByIdAsync(command.UserId.ToString()); + if (user is null) + return IdentityResultDto.Failed([new IdentityErrorDto("UserNotFound", "Unable to load user.")]); + + if (await userManager.HasPasswordAsync(user)) + { + if (command.Password is null || !await userManager.CheckPasswordAsync(user, command.Password)) + return IdentityResultDto.Failed([new IdentityErrorDto("Password", "Incorrect password.")]); + } + + var result = await userManager.DeleteAsync(user); + if (!result.Succeeded) + throw new InvalidOperationException("Unexpected error occurred deleting user."); + + await signInManager.SignOutAsync(); + logger.LogInformation("User with ID '{UserId}' deleted themselves.", user.Id); + return IdentityResultDto.Success(); + } +} diff --git a/CommentMap.Application/Features/Identity/ExternalLogin.cs b/CommentMap.Application/Features/Identity/ExternalLogin.cs new file mode 100644 index 0000000..9c6cbb5 --- /dev/null +++ b/CommentMap.Application/Features/Identity/ExternalLogin.cs @@ -0,0 +1,146 @@ +using CommentMap.Application.Entities; +using CommentMap.Application.Models; +using Microsoft.AspNetCore.Identity; +using Microsoft.Extensions.Logging; +using System.Security.Claims; + +namespace CommentMap.Application.Features.Identity; + +public record ExternalLoginSignIn(string LoginProvider, string ProviderKey); + +public static class ExternalLoginSignInHandler +{ + public static async Task Handle( + ExternalLoginSignIn command, + SignInManager signInManager, + ILogger logger) + { + var result = await signInManager.ExternalLoginSignInAsync( + command.LoginProvider, + command.ProviderKey, + isPersistent: false, + bypassTwoFactor: true); + + if (result.Succeeded) + logger.LogInformation("User logged in with {LoginProvider} provider.", command.LoginProvider); + + return result.ToDto(); + } +} + +public record CreateExternalUser(string UserName, ExternalLoginInfo LoginInfo); + +public static class CreateExternalUserHandler +{ + public static async Task Handle( + CreateExternalUser command, + UserManager userManager, + IUserStore userStore, + SignInManager signInManager, + ILogger logger, + CancellationToken cancellationToken) + { + var user = new User(); + await userStore.SetUserNameAsync(user, command.UserName, cancellationToken); + + var result = await userManager.CreateAsync(user); + if (!result.Succeeded) + return result.ToDto(); + + result = await userManager.AddLoginAsync(user, command.LoginInfo); + if (!result.Succeeded) + return result.ToDto(); + + logger.LogInformation("User created an account using {Name} provider.", command.LoginInfo.LoginProvider); + await signInManager.SignInAsync(user, isPersistent: false, command.LoginInfo.LoginProvider); + return IdentityResultDto.Success(); + } +} + +public record GetExternalLogins(Guid UserId); +public record ExternalLoginsDto( + bool Found, + IReadOnlyList CurrentLogins, + IReadOnlyList OtherLoginProviderNames, + bool ShowRemoveButton); + +public static class GetExternalLoginsHandler +{ + public static async Task Handle( + GetExternalLogins query, + UserManager userManager, + SignInManager signInManager, + IUserStore userStore, + CancellationToken cancellationToken) + { + var user = await userManager.FindByIdAsync(query.UserId.ToString()); + if (user is null) + return new ExternalLoginsDto(false, [], [], false); + + var currentLogins = await userManager.GetLoginsAsync(user); + var otherLogins = (await signInManager.GetExternalAuthenticationSchemesAsync()) + .Where(auth => currentLogins.All(ul => auth.Name != ul.LoginProvider)) + .Select(a => a.Name!) + .ToList(); + + string? passwordHash = null; + if (userStore is IUserPasswordStore userPasswordStore) + passwordHash = await userPasswordStore.GetPasswordHashAsync(user, cancellationToken); + + var showRemove = passwordHash != null || currentLogins.Count > 1; + return new ExternalLoginsDto(true, currentLogins.ToList(), otherLogins, showRemove); + } +} + +public record RemoveExternalLogin(Guid UserId, string LoginProvider, string ProviderKey); + +public static class RemoveExternalLoginHandler +{ + public static async Task Handle( + RemoveExternalLogin command, + UserManager userManager, + SignInManager signInManager) + { + var user = await userManager.FindByIdAsync(command.UserId.ToString()); + if (user is null) + return IdentityResultDto.Failed([new IdentityErrorDto("UserNotFound", "Unable to load user.")]); + + var result = await userManager.RemoveLoginAsync(user, command.LoginProvider, command.ProviderKey); + if (!result.Succeeded) + return result.ToDto(); + + await signInManager.RefreshSignInAsync(user); + return IdentityResultDto.Success(); + } +} + +public record LinkExternalLogin(Guid UserId); + +public static class LinkExternalLoginHandler +{ + public static async Task Handle( + LinkExternalLogin command, + UserManager userManager, + SignInManager signInManager) + { + var user = await userManager.FindByIdAsync(command.UserId.ToString()); + if (user is null) + return IdentityResultDto.Failed([new IdentityErrorDto("UserNotFound", "Unable to load user.")]); + + var userId = await userManager.GetUserIdAsync(user); + var info = await signInManager.GetExternalLoginInfoAsync(userId); + if (info is null) + throw new InvalidOperationException("Unexpected error occurred loading external login info."); + + var result = await userManager.AddLoginAsync(user, info); + return result.ToDto(); + } +} + +public static class ExternalLoginHelpers +{ + public static string? SuggestedUserName(ClaimsPrincipal principal) => + principal.HasClaim(c => c.Type == ClaimTypes.Name) + ? principal.FindFirstValue(ClaimTypes.Name) + : null; +} diff --git a/CommentMap.Application/Features/Identity/ForgotPassword.cs b/CommentMap.Application/Features/Identity/ForgotPassword.cs new file mode 100644 index 0000000..3dfe8e9 --- /dev/null +++ b/CommentMap.Application/Features/Identity/ForgotPassword.cs @@ -0,0 +1,24 @@ +using CommentMap.Application.Entities; +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.WebUtilities; +using System.Text; + +namespace CommentMap.Application.Features.Identity; + +public record ForgotPassword(string Email); + +public record ForgotPasswordResult(bool UserFound, Guid? UserId, string? EncodedResetCode); + +public static class ForgotPasswordHandler +{ + public static async Task Handle(ForgotPassword command, UserManager userManager) + { + var user = await userManager.FindByEmailAsync(command.Email); + if (user is null || !await userManager.IsEmailConfirmedAsync(user)) + return new ForgotPasswordResult(false, null, null); + + var code = await userManager.GeneratePasswordResetTokenAsync(user); + var encoded = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code)); + return new ForgotPasswordResult(true, user.Id, encoded); + } +} diff --git a/CommentMap.Application/Features/Identity/IdentityMapping.cs b/CommentMap.Application/Features/Identity/IdentityMapping.cs new file mode 100644 index 0000000..a94891c --- /dev/null +++ b/CommentMap.Application/Features/Identity/IdentityMapping.cs @@ -0,0 +1,13 @@ +using CommentMap.Application.Models; +using Microsoft.AspNetCore.Identity; + +namespace CommentMap.Application.Features.Identity; + +internal static class IdentityMapping +{ + public static IdentityResultDto ToDto(this IdentityResult result) => + new(result.Succeeded, result.Errors.Select(e => new IdentityErrorDto(e.Code, e.Description)).ToList()); + + public static LoginResultDto ToDto(this SignInResult result) => + new(result.Succeeded, result.RequiresTwoFactor, result.IsLockedOut, result.IsNotAllowed); +} diff --git a/CommentMap.Application/Features/Identity/LoginUser.cs b/CommentMap.Application/Features/Identity/LoginUser.cs new file mode 100644 index 0000000..978ea09 --- /dev/null +++ b/CommentMap.Application/Features/Identity/LoginUser.cs @@ -0,0 +1,30 @@ +using CommentMap.Application.Entities; +using CommentMap.Application.Models; +using Microsoft.AspNetCore.Identity; +using Microsoft.Extensions.Logging; + +namespace CommentMap.Application.Features.Identity; + +public record LoginUser(string Email, string Password, bool RememberMe); + +public static class LoginUserHandler +{ + public static async Task Handle( + LoginUser command, + SignInManager signInManager, + ILogger logger) + { + var result = await signInManager.PasswordSignInAsync( + command.Email, + command.Password, + command.RememberMe, + lockoutOnFailure: false); + + if (result.Succeeded) + logger.LogInformation("User logged in."); + else if (result.IsLockedOut) + logger.LogWarning("User account locked out."); + + return result.ToDto(); + } +} diff --git a/CommentMap.Application/Features/Identity/LogoutUser.cs b/CommentMap.Application/Features/Identity/LogoutUser.cs new file mode 100644 index 0000000..e71f9e1 --- /dev/null +++ b/CommentMap.Application/Features/Identity/LogoutUser.cs @@ -0,0 +1,16 @@ +using CommentMap.Application.Entities; +using Microsoft.AspNetCore.Identity; +using Microsoft.Extensions.Logging; + +namespace CommentMap.Application.Features.Identity; + +public record LogoutUser; + +public static class LogoutUserHandler +{ + public static async Task Handle(LogoutUser _, SignInManager signInManager, ILogger logger) + { + await signInManager.SignOutAsync(); + logger.LogInformation("User logged out."); + } +} diff --git a/CommentMap.Application/Features/Identity/RegisterUser.cs b/CommentMap.Application/Features/Identity/RegisterUser.cs new file mode 100644 index 0000000..5534ae3 --- /dev/null +++ b/CommentMap.Application/Features/Identity/RegisterUser.cs @@ -0,0 +1,47 @@ +using CommentMap.Application.Entities; +using CommentMap.Application.Models; +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.WebUtilities; +using System.Text; + +namespace CommentMap.Application.Features.Identity; + +public record RegisterUser(string Email, string Password); + +public record RegisterUserResult( + bool Succeeded, + Guid? UserId, + string? EncodedEmailConfirmationCode, + bool RequireConfirmedAccount, + IReadOnlyList Errors); + +public static class RegisterUserHandler +{ + public static async Task Handle( + RegisterUser command, + UserManager userManager, + IUserStore userStore, + CancellationToken cancellationToken) + { + var user = new User(); + await userStore.SetUserNameAsync(user, command.Email, cancellationToken); + var emailStore = (IUserEmailStore)userStore; + await emailStore.SetEmailAsync(user, command.Email, cancellationToken); + + var result = await userManager.CreateAsync(user, command.Password); + if (!result.Succeeded) + { + return new RegisterUserResult(false, null, null, false, result.ToDto().Errors); + } + + var code = await userManager.GenerateEmailConfirmationTokenAsync(user); + var encoded = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code)); + + return new RegisterUserResult( + true, + user.Id, + encoded, + userManager.Options.SignIn.RequireConfirmedAccount, + []); + } +} diff --git a/CommentMap.Application/Features/Identity/ResendEmailConfirmation.cs b/CommentMap.Application/Features/Identity/ResendEmailConfirmation.cs new file mode 100644 index 0000000..7af86ab --- /dev/null +++ b/CommentMap.Application/Features/Identity/ResendEmailConfirmation.cs @@ -0,0 +1,26 @@ +using CommentMap.Application.Entities; +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.WebUtilities; +using System.Text; + +namespace CommentMap.Application.Features.Identity; + +public record ResendEmailConfirmation(string Email); + +public record ResendEmailConfirmationResult(bool UserFound, Guid? UserId, string? EncodedCode); + +public static class ResendEmailConfirmationHandler +{ + public static async Task Handle( + ResendEmailConfirmation command, + UserManager userManager) + { + var user = await userManager.FindByEmailAsync(command.Email); + if (user is null) + return new ResendEmailConfirmationResult(false, null, null); + + var code = await userManager.GenerateEmailConfirmationTokenAsync(user); + var encoded = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code)); + return new ResendEmailConfirmationResult(true, user.Id, encoded); + } +} diff --git a/CommentMap.Application/Features/Identity/ResetPassword.cs b/CommentMap.Application/Features/Identity/ResetPassword.cs new file mode 100644 index 0000000..893eb73 --- /dev/null +++ b/CommentMap.Application/Features/Identity/ResetPassword.cs @@ -0,0 +1,23 @@ +using CommentMap.Application.Entities; +using CommentMap.Application.Models; +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.WebUtilities; +using System.Text; + +namespace CommentMap.Application.Features.Identity; + +public record ResetPassword(string UserId, string EncodedCode, string Password); + +public static class ResetPasswordHandler +{ + public static async Task Handle(ResetPassword command, UserManager userManager) + { + var user = await userManager.FindByIdAsync(command.UserId); + if (user is null) + return IdentityResultDto.Success(); + + var code = Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(command.EncodedCode)); + var result = await userManager.ResetPasswordAsync(user, code, command.Password); + return result.ToDto(); + } +} diff --git a/CommentMap.Application/Features/Identity/TwoFactor.cs b/CommentMap.Application/Features/Identity/TwoFactor.cs new file mode 100644 index 0000000..5878f0d --- /dev/null +++ b/CommentMap.Application/Features/Identity/TwoFactor.cs @@ -0,0 +1,279 @@ +using CommentMap.Application.Entities; +using CommentMap.Application.Models; +using Microsoft.AspNetCore.Identity; +using Microsoft.Extensions.Logging; +using QRCoder; +using System.Text; +using System.Text.Encodings.Web; + +namespace CommentMap.Application.Features.Identity; + +public record GetTwoFactorStatus(Guid UserId); +public record TwoFactorStatusDto( + bool Found, + bool HasAuthenticator, + bool Is2faEnabled, + bool IsMachineRemembered, + int RecoveryCodesLeft); + +public static class GetTwoFactorStatusHandler +{ + public static async Task Handle( + GetTwoFactorStatus query, + UserManager userManager, + SignInManager signInManager) + { + var user = await userManager.FindByIdAsync(query.UserId.ToString()); + if (user is null) + return new TwoFactorStatusDto(false, false, false, false, 0); + + return new TwoFactorStatusDto( + true, + await userManager.GetAuthenticatorKeyAsync(user) != null, + await userManager.GetTwoFactorEnabledAsync(user), + await signInManager.IsTwoFactorClientRememberedAsync(user), + await userManager.CountRecoveryCodesAsync(user)); + } +} + +public record ForgetTwoFactorClient(Guid UserId); + +public static class ForgetTwoFactorClientHandler +{ + public static async Task Handle( + ForgetTwoFactorClient command, + UserManager userManager, + SignInManager signInManager) + { + var user = await userManager.FindByIdAsync(command.UserId.ToString()); + if (user is null) + return false; + + await signInManager.ForgetTwoFactorClientAsync(); + return true; + } +} + +public record GetAuthenticatorSetup(Guid UserId, string AppName = "CommentMap"); + +public static class GetAuthenticatorSetupHandler +{ + public static async Task Handle( + GetAuthenticatorSetup query, + UserManager userManager, + UrlEncoder urlEncoder, + QRCodeGenerator qrCodeGenerator) + { + var user = await userManager.FindByIdAsync(query.UserId.ToString()); + if (user is null) + return null; + + var unformattedKey = await userManager.GetAuthenticatorKeyAsync(user); + if (string.IsNullOrEmpty(unformattedKey)) + { + await userManager.ResetAuthenticatorKeyAsync(user); + unformattedKey = await userManager.GetAuthenticatorKeyAsync(user); + } + + var sharedKey = FormatKey(unformattedKey!); + var uri = GetQrCodeUri(urlEncoder, query.AppName, user.UserName!, unformattedKey!); + var qr = GetEmbeddedSource(qrCodeGenerator, uri); + return new AuthenticatorSetupDto(sharedKey, uri, qr); + } + + internal static string FormatKey(string unformattedKey) + { + var result = new StringBuilder(); + var currentPosition = 0; + while (currentPosition + 4 < unformattedKey.Length) + { + result.Append(unformattedKey.AsSpan(currentPosition, 4)).Append(' '); + currentPosition += 4; + } + if (currentPosition < unformattedKey.Length) + result.Append(unformattedKey.AsSpan(currentPosition)); + + return result.ToString().ToLowerInvariant(); + } + + internal static string GetQrCodeUri(UrlEncoder urlEncoder, string appName, string userName, string key) + { + var encodedAppName = urlEncoder.Encode(appName); + var encodedUserName = urlEncoder.Encode(userName); + return $"otpauth://totp/{encodedAppName}:{encodedUserName}?secret={key}&issuer={encodedAppName}&digits=6"; + } + + internal static string GetEmbeddedSource(QRCodeGenerator qrCodeGenerator, string qrCodeUri, int pixelsPerModule = 6) + { + using var data = qrCodeGenerator.CreateQrCode(qrCodeUri, QRCodeGenerator.ECCLevel.Q); + using var base64 = new Base64QRCode(data); + return $"data:image/png;base64,{base64.GetGraphic(pixelsPerModule)}"; + } +} + +public record EnableAuthenticator(Guid UserId, string Code, string AppName = "CommentMap"); + +public static class EnableAuthenticatorHandler +{ + public static async Task Handle( + EnableAuthenticator command, + UserManager userManager, + ILogger logger, + UrlEncoder urlEncoder, + QRCodeGenerator qrCodeGenerator) + { + var user = await userManager.FindByIdAsync(command.UserId.ToString()); + if (user is null) + return new EnableAuthenticatorResultDto(false, false, false, null, null); + + var verificationCode = command.Code.Replace(" ", string.Empty).Replace("-", string.Empty); + var isValid = await userManager.VerifyTwoFactorTokenAsync( + user, userManager.Options.Tokens.AuthenticatorTokenProvider, verificationCode); + + if (!isValid) + { + var setup = await GetAuthenticatorSetupHandler.Handle( + new GetAuthenticatorSetup(command.UserId, command.AppName), + userManager, urlEncoder, qrCodeGenerator); + return new EnableAuthenticatorResultDto(false, true, false, null, setup); + } + + await userManager.SetTwoFactorEnabledAsync(user, true); + logger.LogInformation("User with ID '{UserId}' has enabled 2FA with an authenticator app.", user.Id); + + if (await userManager.CountRecoveryCodesAsync(user) == 0) + { + var recoveryCodes = await userManager.GenerateNewTwoFactorRecoveryCodesAsync(user, 10); + return new EnableAuthenticatorResultDto(true, false, true, recoveryCodes!.ToArray(), null); + } + + return new EnableAuthenticatorResultDto(true, false, false, null, null); + } +} + +public record Disable2fa(Guid UserId); + +public static class Disable2faHandler +{ + public static async Task Handle(Disable2fa command, UserManager userManager, ILogger logger) + { + var user = await userManager.FindByIdAsync(command.UserId.ToString()); + if (user is null) + return false; + + if (!await userManager.GetTwoFactorEnabledAsync(user)) + throw new InvalidOperationException("Cannot disable 2FA for user as it's not currently enabled."); + + var result = await userManager.SetTwoFactorEnabledAsync(user, false); + if (!result.Succeeded) + throw new InvalidOperationException("Unexpected error occurred disabling 2FA."); + + logger.LogInformation("User with ID '{UserId}' has disabled 2fa.", user.Id); + return true; + } +} + +public record ResetAuthenticator(Guid UserId); + +public static class ResetAuthenticatorHandler +{ + public static async Task Handle( + ResetAuthenticator command, + UserManager userManager, + SignInManager signInManager, + ILogger logger) + { + var user = await userManager.FindByIdAsync(command.UserId.ToString()); + if (user is null) + return false; + + await userManager.SetTwoFactorEnabledAsync(user, false); + await userManager.ResetAuthenticatorKeyAsync(user); + logger.LogInformation("User with ID '{UserId}' has reset their authentication app key.", user.Id); + await signInManager.RefreshSignInAsync(user); + return true; + } +} + +public record GenerateRecoveryCodes(Guid UserId); +public record GenerateRecoveryCodesResult(bool Found, bool TwoFactorEnabled, string[]? RecoveryCodes); + +public static class GenerateRecoveryCodesHandler +{ + public static async Task Handle( + GenerateRecoveryCodes command, + UserManager userManager, + ILogger logger) + { + var user = await userManager.FindByIdAsync(command.UserId.ToString()); + if (user is null) + return new GenerateRecoveryCodesResult(false, false, null); + + if (!await userManager.GetTwoFactorEnabledAsync(user)) + throw new InvalidOperationException("Cannot generate recovery codes for user because they do not have 2FA enabled."); + + var recoveryCodes = await userManager.GenerateNewTwoFactorRecoveryCodesAsync(user, 10); + logger.LogInformation("User with ID '{UserId}' has generated new 2FA recovery codes.", user.Id); + return new GenerateRecoveryCodesResult(true, true, recoveryCodes!.ToArray()); + } +} + +public record LoginWith2fa(string TwoFactorCode, bool RememberMe, bool RememberMachine); +public record LoginWithRecoveryCode(string RecoveryCode); + +public static class LoginWith2faHandler +{ + public static async Task Handle( + LoginWith2fa command, + SignInManager signInManager, + ILogger logger) + { + var user = await signInManager.GetTwoFactorAuthenticationUserAsync() + ?? throw new InvalidOperationException("Unable to load two-factor authentication user."); + + var authenticatorCode = command.TwoFactorCode.Replace(" ", string.Empty).Replace("-", string.Empty); + var result = await signInManager.TwoFactorAuthenticatorSignInAsync( + authenticatorCode, command.RememberMe, command.RememberMachine); + + if (result.Succeeded) + logger.LogInformation("User with ID '{UserId}' logged in with 2fa.", user.Id); + else if (result.IsLockedOut) + logger.LogWarning("User with ID '{UserId}' account locked out.", user.Id); + + return result.ToDto(); + } +} + +public static class LoginWithRecoveryCodeHandler +{ + public static async Task Handle( + LoginWithRecoveryCode command, + SignInManager signInManager, + ILogger logger) + { + var user = await signInManager.GetTwoFactorAuthenticationUserAsync() + ?? throw new InvalidOperationException("Unable to load two-factor authentication user."); + + var recoveryCode = command.RecoveryCode.Replace(" ", string.Empty); + var result = await signInManager.TwoFactorRecoveryCodeSignInAsync(recoveryCode); + + if (result.Succeeded) + logger.LogInformation("User with ID '{UserId}' logged in with a recovery code.", user.Id); + else if (result.IsLockedOut) + logger.LogWarning("User account locked out."); + + return result.ToDto(); + } +} + +public record SignInAfterRegistration(Guid UserId); + +public static class SignInAfterRegistrationHandler +{ + public static async Task Handle(SignInAfterRegistration command, UserManager userManager, SignInManager signInManager) + { + var user = await userManager.FindByIdAsync(command.UserId.ToString()) + ?? throw new InvalidOperationException("User not found."); + await signInManager.SignInAsync(user, isPersistent: false); + } +} diff --git a/CommentMap.Application/Models/CommentCardDto.cs b/CommentMap.Application/Models/CommentCardDto.cs new file mode 100644 index 0000000..fd38f3e --- /dev/null +++ b/CommentMap.Application/Models/CommentCardDto.cs @@ -0,0 +1,9 @@ +namespace CommentMap.Application.Models; + +public record CommentCardDto( + Guid Id, + double Longitude, + double Latitude, + string Title, + string Text, + DateTime CreatedAt); diff --git a/CommentMap.Application/Models/CountryDto.cs b/CommentMap.Application/Models/CountryDto.cs new file mode 100644 index 0000000..b85f842 --- /dev/null +++ b/CommentMap.Application/Models/CountryDto.cs @@ -0,0 +1,8 @@ +namespace CommentMap.Application.Models; + +public record CountryDto( + string ISO3Code, + string ISO2Code, + string Name, + string RegionName, + string SubregionName); diff --git a/CommentMap.Application/Models/IdentityResultDto.cs b/CommentMap.Application/Models/IdentityResultDto.cs new file mode 100644 index 0000000..ad6ea78 --- /dev/null +++ b/CommentMap.Application/Models/IdentityResultDto.cs @@ -0,0 +1,31 @@ +namespace CommentMap.Application.Models; + +public record IdentityErrorDto(string Code, string Description); + +public record IdentityResultDto(bool Succeeded, IReadOnlyList Errors) +{ + public static IdentityResultDto Success() => new(true, []); + + public static IdentityResultDto Failed(IEnumerable errors) => + new(false, [.. errors]); +} + +public record LoginResultDto( + bool Succeeded, + bool RequiresTwoFactor, + bool IsLockedOut, + bool IsNotAllowed); + +public record RegisterResultDto( + bool Succeeded, + bool RequireConfirmedAccount, + IReadOnlyList Errors); + +public record AuthenticatorSetupDto(string SharedKey, string AuthenticatorUri, string QrCodeEmbedded); + +public record EnableAuthenticatorResultDto( + bool Succeeded, + bool InvalidCode, + bool ShowRecoveryCodes, + string[]? RecoveryCodes, + AuthenticatorSetupDto? Setup); diff --git a/CommentMap.Mvc/Models/Order.cs b/CommentMap.Application/Models/Order.cs similarity index 57% rename from CommentMap.Mvc/Models/Order.cs rename to CommentMap.Application/Models/Order.cs index 821636b..c4f29d9 100644 --- a/CommentMap.Mvc/Models/Order.cs +++ b/CommentMap.Application/Models/Order.cs @@ -1,6 +1,6 @@ -using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations; -namespace CommentMap.Mvc.Models; +namespace CommentMap.Application.Models; public enum Order { diff --git a/CommentMap.EmailSender/Extensions/ServiceCollectionExtensions.cs b/CommentMap.EmailSender/Extensions/ServiceCollectionExtensions.cs index 2bf24c2..6ac54cf 100644 --- a/CommentMap.EmailSender/Extensions/ServiceCollectionExtensions.cs +++ b/CommentMap.EmailSender/Extensions/ServiceCollectionExtensions.cs @@ -1,6 +1,6 @@ using CommentMap.EmailSender.Options; using CommentMap.EmailSender.Services; -using MailKit.Net.Smtp; +using System.Data.Common; namespace CommentMap.EmailSender.Extensions; diff --git a/CommentMap.Infrastructure/CommentMap.Infrastructure.csproj b/CommentMap.Infrastructure/CommentMap.Infrastructure.csproj new file mode 100644 index 0000000..079061f --- /dev/null +++ b/CommentMap.Infrastructure/CommentMap.Infrastructure.csproj @@ -0,0 +1,30 @@ + + + + net10.0 + enable + enable + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + diff --git a/CommentMap.Mvc/Data/CommentMapDbContext.cs b/CommentMap.Infrastructure/Data/CommentMapDbContext.cs similarity index 65% rename from CommentMap.Mvc/Data/CommentMapDbContext.cs rename to CommentMap.Infrastructure/Data/CommentMapDbContext.cs index ee0b841..32c72b8 100644 --- a/CommentMap.Mvc/Data/CommentMapDbContext.cs +++ b/CommentMap.Infrastructure/Data/CommentMapDbContext.cs @@ -1,11 +1,13 @@ -using CommentMap.Mvc.Data.Entities; -using CommentMap.Mvc.Data.Entities.Configurations; +using CommentMap.Application.Abstractions; +using CommentMap.Application.Entities; +using CommentMap.Infrastructure.Data.Configurations; using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; -namespace CommentMap.Mvc.Data; +namespace CommentMap.Infrastructure.Data; -public class CommentMapDbContext(DbContextOptions options) : IdentityDbContext(options), ICommentMapDbContext +public class CommentMapDbContext(DbContextOptions options) + : IdentityDbContext(options), ICommentMapDbContext { public DbSet Comments => Set(); public DbSet Countries => Set(); diff --git a/CommentMap.Mvc/Data/Entities/Configurations/CommentConfiguration.cs b/CommentMap.Infrastructure/Data/Configurations/CommentConfiguration.cs similarity index 88% rename from CommentMap.Mvc/Data/Entities/Configurations/CommentConfiguration.cs rename to CommentMap.Infrastructure/Data/Configurations/CommentConfiguration.cs index 10ae548..e070804 100644 --- a/CommentMap.Mvc/Data/Entities/Configurations/CommentConfiguration.cs +++ b/CommentMap.Infrastructure/Data/Configurations/CommentConfiguration.cs @@ -1,7 +1,8 @@ -using Microsoft.EntityFrameworkCore; +using CommentMap.Application.Entities; +using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; -namespace CommentMap.Mvc.Data.Entities.Configurations; +namespace CommentMap.Infrastructure.Data.Configurations; public class CommentConfiguration : IEntityTypeConfiguration { diff --git a/CommentMap.Mvc/Data/Entities/Configurations/CountryConfiguration.cs b/CommentMap.Infrastructure/Data/Configurations/CountryConfiguration.cs similarity index 84% rename from CommentMap.Mvc/Data/Entities/Configurations/CountryConfiguration.cs rename to CommentMap.Infrastructure/Data/Configurations/CountryConfiguration.cs index 9f6a5ac..988a745 100644 --- a/CommentMap.Mvc/Data/Entities/Configurations/CountryConfiguration.cs +++ b/CommentMap.Infrastructure/Data/Configurations/CountryConfiguration.cs @@ -1,7 +1,8 @@ -using Microsoft.EntityFrameworkCore; +using CommentMap.Application.Entities; +using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; -namespace CommentMap.Mvc.Data.Entities.Configurations; +namespace CommentMap.Infrastructure.Data.Configurations; public class CountryConfiguration : IEntityTypeConfiguration { diff --git a/CommentMap.Mvc/Data/Migrations/20240523173725_InitialMigration.Designer.cs b/CommentMap.Infrastructure/Data/Migrations/20240523173725_InitialMigration.Designer.cs similarity index 91% rename from CommentMap.Mvc/Data/Migrations/20240523173725_InitialMigration.Designer.cs rename to CommentMap.Infrastructure/Data/Migrations/20240523173725_InitialMigration.Designer.cs index 9ded155..0342fb8 100644 --- a/CommentMap.Mvc/Data/Migrations/20240523173725_InitialMigration.Designer.cs +++ b/CommentMap.Infrastructure/Data/Migrations/20240523173725_InitialMigration.Designer.cs @@ -1,6 +1,6 @@ -// +// using System; -using CommentMap.Mvc.Data; +using CommentMap.Infrastructure.Data; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; @@ -10,7 +10,7 @@ #nullable disable -namespace CommentMap.Mvc.Data.Migrations +namespace CommentMap.Infrastructure.Data.Migrations { [DbContext(typeof(CommentMapDbContext))] [Migration("20240523173725_InitialMigration")] @@ -27,7 +27,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "postgis"); NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - modelBuilder.Entity("CommentMap.Mvc.Data.Entities.Comment", b => + modelBuilder.Entity("CommentMap.Application.Entities.Comment", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -52,7 +52,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("Comments"); }); - modelBuilder.Entity("CommentMap.Mvc.Data.Entities.Role", b => + modelBuilder.Entity("CommentMap.Application.Entities.Role", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -79,7 +79,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("AspNetRoles", (string)null); }); - modelBuilder.Entity("CommentMap.Mvc.Data.Entities.User", b => + modelBuilder.Entity("CommentMap.Application.Entities.User", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -251,9 +251,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("AspNetUserTokens", (string)null); }); - modelBuilder.Entity("CommentMap.Mvc.Data.Entities.Comment", b => + modelBuilder.Entity("CommentMap.Application.Entities.Comment", b => { - b.HasOne("CommentMap.Mvc.Data.Entities.User", "User") + b.HasOne("CommentMap.Application.Entities.User", "User") .WithMany("Comments") .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -264,7 +264,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => { - b.HasOne("CommentMap.Mvc.Data.Entities.Role", null) + b.HasOne("CommentMap.Application.Entities.Role", null) .WithMany() .HasForeignKey("RoleId") .OnDelete(DeleteBehavior.Cascade) @@ -273,7 +273,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => { - b.HasOne("CommentMap.Mvc.Data.Entities.User", null) + b.HasOne("CommentMap.Application.Entities.User", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -282,7 +282,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => { - b.HasOne("CommentMap.Mvc.Data.Entities.User", null) + b.HasOne("CommentMap.Application.Entities.User", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -291,13 +291,13 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => { - b.HasOne("CommentMap.Mvc.Data.Entities.Role", null) + b.HasOne("CommentMap.Application.Entities.Role", null) .WithMany() .HasForeignKey("RoleId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("CommentMap.Mvc.Data.Entities.User", null) + b.HasOne("CommentMap.Application.Entities.User", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -306,14 +306,14 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => { - b.HasOne("CommentMap.Mvc.Data.Entities.User", null) + b.HasOne("CommentMap.Application.Entities.User", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); }); - modelBuilder.Entity("CommentMap.Mvc.Data.Entities.User", b => + modelBuilder.Entity("CommentMap.Application.Entities.User", b => { b.Navigation("Comments"); }); diff --git a/CommentMap.Mvc/Data/Migrations/20240523173725_InitialMigration.cs b/CommentMap.Infrastructure/Data/Migrations/20240523173725_InitialMigration.cs similarity index 99% rename from CommentMap.Mvc/Data/Migrations/20240523173725_InitialMigration.cs rename to CommentMap.Infrastructure/Data/Migrations/20240523173725_InitialMigration.cs index 0a6fc37..c4b793f 100644 --- a/CommentMap.Mvc/Data/Migrations/20240523173725_InitialMigration.cs +++ b/CommentMap.Infrastructure/Data/Migrations/20240523173725_InitialMigration.cs @@ -1,11 +1,11 @@ -using System; +using System; using Microsoft.EntityFrameworkCore.Migrations; using NetTopologySuite.Geometries; using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; #nullable disable -namespace CommentMap.Mvc.Data.Migrations +namespace CommentMap.Infrastructure.Data.Migrations { /// public partial class InitialMigration : Migration diff --git a/CommentMap.Mvc/Data/Migrations/20240525160654_AddCommentProperties.Designer.cs b/CommentMap.Infrastructure/Data/Migrations/20240525160654_AddCommentProperties.Designer.cs similarity index 91% rename from CommentMap.Mvc/Data/Migrations/20240525160654_AddCommentProperties.Designer.cs rename to CommentMap.Infrastructure/Data/Migrations/20240525160654_AddCommentProperties.Designer.cs index 2359d79..cb021fa 100644 --- a/CommentMap.Mvc/Data/Migrations/20240525160654_AddCommentProperties.Designer.cs +++ b/CommentMap.Infrastructure/Data/Migrations/20240525160654_AddCommentProperties.Designer.cs @@ -1,6 +1,6 @@ -// +// using System; -using CommentMap.Mvc.Data; +using CommentMap.Infrastructure.Data; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; @@ -10,7 +10,7 @@ #nullable disable -namespace CommentMap.Mvc.Data.Migrations +namespace CommentMap.Infrastructure.Data.Migrations { [DbContext(typeof(CommentMapDbContext))] [Migration("20240525160654_AddCommentProperties")] @@ -27,7 +27,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "postgis"); NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - modelBuilder.Entity("CommentMap.Mvc.Data.Entities.Comment", b => + modelBuilder.Entity("CommentMap.Application.Entities.Comment", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -66,7 +66,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("Comments"); }); - modelBuilder.Entity("CommentMap.Mvc.Data.Entities.Role", b => + modelBuilder.Entity("CommentMap.Application.Entities.Role", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -93,7 +93,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("AspNetRoles", (string)null); }); - modelBuilder.Entity("CommentMap.Mvc.Data.Entities.User", b => + modelBuilder.Entity("CommentMap.Application.Entities.User", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -265,9 +265,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("AspNetUserTokens", (string)null); }); - modelBuilder.Entity("CommentMap.Mvc.Data.Entities.Comment", b => + modelBuilder.Entity("CommentMap.Application.Entities.Comment", b => { - b.HasOne("CommentMap.Mvc.Data.Entities.User", "User") + b.HasOne("CommentMap.Application.Entities.User", "User") .WithMany("Comments") .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -278,7 +278,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => { - b.HasOne("CommentMap.Mvc.Data.Entities.Role", null) + b.HasOne("CommentMap.Application.Entities.Role", null) .WithMany() .HasForeignKey("RoleId") .OnDelete(DeleteBehavior.Cascade) @@ -287,7 +287,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => { - b.HasOne("CommentMap.Mvc.Data.Entities.User", null) + b.HasOne("CommentMap.Application.Entities.User", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -296,7 +296,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => { - b.HasOne("CommentMap.Mvc.Data.Entities.User", null) + b.HasOne("CommentMap.Application.Entities.User", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -305,13 +305,13 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => { - b.HasOne("CommentMap.Mvc.Data.Entities.Role", null) + b.HasOne("CommentMap.Application.Entities.Role", null) .WithMany() .HasForeignKey("RoleId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("CommentMap.Mvc.Data.Entities.User", null) + b.HasOne("CommentMap.Application.Entities.User", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -320,14 +320,14 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => { - b.HasOne("CommentMap.Mvc.Data.Entities.User", null) + b.HasOne("CommentMap.Application.Entities.User", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); }); - modelBuilder.Entity("CommentMap.Mvc.Data.Entities.User", b => + modelBuilder.Entity("CommentMap.Application.Entities.User", b => { b.Navigation("Comments"); }); diff --git a/CommentMap.Mvc/Data/Migrations/20240525160654_AddCommentProperties.cs b/CommentMap.Infrastructure/Data/Migrations/20240525160654_AddCommentProperties.cs similarity index 95% rename from CommentMap.Mvc/Data/Migrations/20240525160654_AddCommentProperties.cs rename to CommentMap.Infrastructure/Data/Migrations/20240525160654_AddCommentProperties.cs index deb84bb..19d3b0b 100644 --- a/CommentMap.Mvc/Data/Migrations/20240525160654_AddCommentProperties.cs +++ b/CommentMap.Infrastructure/Data/Migrations/20240525160654_AddCommentProperties.cs @@ -1,9 +1,9 @@ -using System; +using System; using Microsoft.EntityFrameworkCore.Migrations; #nullable disable -namespace CommentMap.Mvc.Data.Migrations +namespace CommentMap.Infrastructure.Data.Migrations { /// public partial class AddCommentProperties : Migration diff --git a/CommentMap.Mvc/Data/Migrations/20240623144537_AddIsDeleted.Designer.cs b/CommentMap.Infrastructure/Data/Migrations/20240623144537_AddIsDeleted.Designer.cs similarity index 91% rename from CommentMap.Mvc/Data/Migrations/20240623144537_AddIsDeleted.Designer.cs rename to CommentMap.Infrastructure/Data/Migrations/20240623144537_AddIsDeleted.Designer.cs index 765eae4..f1367ad 100644 --- a/CommentMap.Mvc/Data/Migrations/20240623144537_AddIsDeleted.Designer.cs +++ b/CommentMap.Infrastructure/Data/Migrations/20240623144537_AddIsDeleted.Designer.cs @@ -1,6 +1,6 @@ -// +// using System; -using CommentMap.Mvc.Data; +using CommentMap.Infrastructure.Data; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; @@ -10,7 +10,7 @@ #nullable disable -namespace CommentMap.Mvc.Data.Migrations +namespace CommentMap.Infrastructure.Data.Migrations { [DbContext(typeof(CommentMapDbContext))] [Migration("20240623144537_AddIsDeleted")] @@ -27,7 +27,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "postgis"); NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - modelBuilder.Entity("CommentMap.Mvc.Data.Entities.Comment", b => + modelBuilder.Entity("CommentMap.Application.Entities.Comment", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -71,7 +71,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("Comments"); }); - modelBuilder.Entity("CommentMap.Mvc.Data.Entities.Role", b => + modelBuilder.Entity("CommentMap.Application.Entities.Role", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -98,7 +98,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("AspNetRoles", (string)null); }); - modelBuilder.Entity("CommentMap.Mvc.Data.Entities.User", b => + modelBuilder.Entity("CommentMap.Application.Entities.User", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -270,9 +270,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("AspNetUserTokens", (string)null); }); - modelBuilder.Entity("CommentMap.Mvc.Data.Entities.Comment", b => + modelBuilder.Entity("CommentMap.Application.Entities.Comment", b => { - b.HasOne("CommentMap.Mvc.Data.Entities.User", "User") + b.HasOne("CommentMap.Application.Entities.User", "User") .WithMany("Comments") .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -283,7 +283,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => { - b.HasOne("CommentMap.Mvc.Data.Entities.Role", null) + b.HasOne("CommentMap.Application.Entities.Role", null) .WithMany() .HasForeignKey("RoleId") .OnDelete(DeleteBehavior.Cascade) @@ -292,7 +292,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => { - b.HasOne("CommentMap.Mvc.Data.Entities.User", null) + b.HasOne("CommentMap.Application.Entities.User", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -301,7 +301,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => { - b.HasOne("CommentMap.Mvc.Data.Entities.User", null) + b.HasOne("CommentMap.Application.Entities.User", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -310,13 +310,13 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => { - b.HasOne("CommentMap.Mvc.Data.Entities.Role", null) + b.HasOne("CommentMap.Application.Entities.Role", null) .WithMany() .HasForeignKey("RoleId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("CommentMap.Mvc.Data.Entities.User", null) + b.HasOne("CommentMap.Application.Entities.User", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -325,14 +325,14 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => { - b.HasOne("CommentMap.Mvc.Data.Entities.User", null) + b.HasOne("CommentMap.Application.Entities.User", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); }); - modelBuilder.Entity("CommentMap.Mvc.Data.Entities.User", b => + modelBuilder.Entity("CommentMap.Application.Entities.User", b => { b.Navigation("Comments"); }); diff --git a/CommentMap.Mvc/Data/Migrations/20240623144537_AddIsDeleted.cs b/CommentMap.Infrastructure/Data/Migrations/20240623144537_AddIsDeleted.cs similarity index 93% rename from CommentMap.Mvc/Data/Migrations/20240623144537_AddIsDeleted.cs rename to CommentMap.Infrastructure/Data/Migrations/20240623144537_AddIsDeleted.cs index 4d52af6..57aab98 100644 --- a/CommentMap.Mvc/Data/Migrations/20240623144537_AddIsDeleted.cs +++ b/CommentMap.Infrastructure/Data/Migrations/20240623144537_AddIsDeleted.cs @@ -1,8 +1,8 @@ -using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Migrations; #nullable disable -namespace CommentMap.Mvc.Data.Migrations +namespace CommentMap.Infrastructure.Data.Migrations { /// public partial class AddIsDeleted : Migration diff --git a/CommentMap.Mvc/Data/Migrations/20240909164708_AddCountry.Designer.cs b/CommentMap.Infrastructure/Data/Migrations/20240909164708_AddCountry.Designer.cs similarity index 92% rename from CommentMap.Mvc/Data/Migrations/20240909164708_AddCountry.Designer.cs rename to CommentMap.Infrastructure/Data/Migrations/20240909164708_AddCountry.Designer.cs index 2714f07..97f3e30 100644 --- a/CommentMap.Mvc/Data/Migrations/20240909164708_AddCountry.Designer.cs +++ b/CommentMap.Infrastructure/Data/Migrations/20240909164708_AddCountry.Designer.cs @@ -1,6 +1,6 @@ -// +// using System; -using CommentMap.Mvc.Data; +using CommentMap.Infrastructure.Data; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; @@ -10,7 +10,7 @@ #nullable disable -namespace CommentMap.Mvc.Data.Migrations +namespace CommentMap.Infrastructure.Data.Migrations { [DbContext(typeof(CommentMapDbContext))] [Migration("20240909164708_AddCountry")] @@ -27,7 +27,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "postgis"); NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - modelBuilder.Entity("CommentMap.Mvc.Data.Entities.Comment", b => + modelBuilder.Entity("CommentMap.Application.Entities.Comment", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -73,7 +73,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("Comments"); }); - modelBuilder.Entity("CommentMap.Mvc.Data.Entities.Country", b => + modelBuilder.Entity("CommentMap.Application.Entities.Country", b => { b.Property("ISO3Code") .HasMaxLength(3) @@ -118,7 +118,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("Countries"); }); - modelBuilder.Entity("CommentMap.Mvc.Data.Entities.Role", b => + modelBuilder.Entity("CommentMap.Application.Entities.Role", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -145,7 +145,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("AspNetRoles", (string)null); }); - modelBuilder.Entity("CommentMap.Mvc.Data.Entities.User", b => + modelBuilder.Entity("CommentMap.Application.Entities.User", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -317,9 +317,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("AspNetUserTokens", (string)null); }); - modelBuilder.Entity("CommentMap.Mvc.Data.Entities.Comment", b => + modelBuilder.Entity("CommentMap.Application.Entities.Comment", b => { - b.HasOne("CommentMap.Mvc.Data.Entities.User", "User") + b.HasOne("CommentMap.Application.Entities.User", "User") .WithMany("Comments") .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -330,7 +330,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => { - b.HasOne("CommentMap.Mvc.Data.Entities.Role", null) + b.HasOne("CommentMap.Application.Entities.Role", null) .WithMany() .HasForeignKey("RoleId") .OnDelete(DeleteBehavior.Cascade) @@ -339,7 +339,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => { - b.HasOne("CommentMap.Mvc.Data.Entities.User", null) + b.HasOne("CommentMap.Application.Entities.User", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -348,7 +348,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => { - b.HasOne("CommentMap.Mvc.Data.Entities.User", null) + b.HasOne("CommentMap.Application.Entities.User", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -357,13 +357,13 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => { - b.HasOne("CommentMap.Mvc.Data.Entities.Role", null) + b.HasOne("CommentMap.Application.Entities.Role", null) .WithMany() .HasForeignKey("RoleId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("CommentMap.Mvc.Data.Entities.User", null) + b.HasOne("CommentMap.Application.Entities.User", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -372,14 +372,14 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => { - b.HasOne("CommentMap.Mvc.Data.Entities.User", null) + b.HasOne("CommentMap.Application.Entities.User", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); }); - modelBuilder.Entity("CommentMap.Mvc.Data.Entities.User", b => + modelBuilder.Entity("CommentMap.Application.Entities.User", b => { b.Navigation("Comments"); }); diff --git a/CommentMap.Mvc/Data/Migrations/20240909164708_AddCountry.cs b/CommentMap.Infrastructure/Data/Migrations/20240909164708_AddCountry.cs similarity index 96% rename from CommentMap.Mvc/Data/Migrations/20240909164708_AddCountry.cs rename to CommentMap.Infrastructure/Data/Migrations/20240909164708_AddCountry.cs index c9496dc..dfdc92d 100644 --- a/CommentMap.Mvc/Data/Migrations/20240909164708_AddCountry.cs +++ b/CommentMap.Infrastructure/Data/Migrations/20240909164708_AddCountry.cs @@ -1,9 +1,9 @@ -using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Migrations; using NetTopologySuite.Geometries; #nullable disable -namespace CommentMap.Mvc.Data.Migrations +namespace CommentMap.Infrastructure.Data.Migrations { /// public partial class AddCountry : Migration diff --git a/CommentMap.Mvc/Data/Migrations/20240921074639_AddISO3CountryCodeToComment.Designer.cs b/CommentMap.Infrastructure/Data/Migrations/20240921074639_AddISO3CountryCodeToComment.Designer.cs similarity index 91% rename from CommentMap.Mvc/Data/Migrations/20240921074639_AddISO3CountryCodeToComment.Designer.cs rename to CommentMap.Infrastructure/Data/Migrations/20240921074639_AddISO3CountryCodeToComment.Designer.cs index 2054ab9..e094faf 100644 --- a/CommentMap.Mvc/Data/Migrations/20240921074639_AddISO3CountryCodeToComment.Designer.cs +++ b/CommentMap.Infrastructure/Data/Migrations/20240921074639_AddISO3CountryCodeToComment.Designer.cs @@ -1,6 +1,6 @@ -// +// using System; -using CommentMap.Mvc.Data; +using CommentMap.Infrastructure.Data; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; @@ -10,7 +10,7 @@ #nullable disable -namespace CommentMap.Mvc.Data.Migrations +namespace CommentMap.Infrastructure.Data.Migrations { [DbContext(typeof(CommentMapDbContext))] [Migration("20240921074639_AddISO3CountryCodeToComment")] @@ -27,7 +27,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "postgis"); NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - modelBuilder.Entity("CommentMap.Mvc.Data.Entities.Comment", b => + modelBuilder.Entity("CommentMap.Application.Entities.Comment", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -78,7 +78,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("Comments"); }); - modelBuilder.Entity("CommentMap.Mvc.Data.Entities.Country", b => + modelBuilder.Entity("CommentMap.Application.Entities.Country", b => { b.Property("ISO3Code") .HasMaxLength(3) @@ -123,7 +123,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("Countries"); }); - modelBuilder.Entity("CommentMap.Mvc.Data.Entities.Role", b => + modelBuilder.Entity("CommentMap.Application.Entities.Role", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -150,7 +150,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("AspNetRoles", (string)null); }); - modelBuilder.Entity("CommentMap.Mvc.Data.Entities.User", b => + modelBuilder.Entity("CommentMap.Application.Entities.User", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -322,14 +322,14 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("AspNetUserTokens", (string)null); }); - modelBuilder.Entity("CommentMap.Mvc.Data.Entities.Comment", b => + modelBuilder.Entity("CommentMap.Application.Entities.Comment", b => { - b.HasOne("CommentMap.Mvc.Data.Entities.Country", "Country") + b.HasOne("CommentMap.Application.Entities.Country", "Country") .WithMany("Comments") .HasForeignKey("ISO3CodeCountry") .OnDelete(DeleteBehavior.SetNull); - b.HasOne("CommentMap.Mvc.Data.Entities.User", "User") + b.HasOne("CommentMap.Application.Entities.User", "User") .WithMany("Comments") .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -342,7 +342,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => { - b.HasOne("CommentMap.Mvc.Data.Entities.Role", null) + b.HasOne("CommentMap.Application.Entities.Role", null) .WithMany() .HasForeignKey("RoleId") .OnDelete(DeleteBehavior.Cascade) @@ -351,7 +351,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => { - b.HasOne("CommentMap.Mvc.Data.Entities.User", null) + b.HasOne("CommentMap.Application.Entities.User", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -360,7 +360,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => { - b.HasOne("CommentMap.Mvc.Data.Entities.User", null) + b.HasOne("CommentMap.Application.Entities.User", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -369,13 +369,13 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => { - b.HasOne("CommentMap.Mvc.Data.Entities.Role", null) + b.HasOne("CommentMap.Application.Entities.Role", null) .WithMany() .HasForeignKey("RoleId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("CommentMap.Mvc.Data.Entities.User", null) + b.HasOne("CommentMap.Application.Entities.User", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -384,19 +384,19 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => { - b.HasOne("CommentMap.Mvc.Data.Entities.User", null) + b.HasOne("CommentMap.Application.Entities.User", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); }); - modelBuilder.Entity("CommentMap.Mvc.Data.Entities.Country", b => + modelBuilder.Entity("CommentMap.Application.Entities.Country", b => { b.Navigation("Comments"); }); - modelBuilder.Entity("CommentMap.Mvc.Data.Entities.User", b => + modelBuilder.Entity("CommentMap.Application.Entities.User", b => { b.Navigation("Comments"); }); diff --git a/CommentMap.Mvc/Data/Migrations/20240921074639_AddISO3CountryCodeToComment.cs b/CommentMap.Infrastructure/Data/Migrations/20240921074639_AddISO3CountryCodeToComment.cs similarity index 93% rename from CommentMap.Mvc/Data/Migrations/20240921074639_AddISO3CountryCodeToComment.cs rename to CommentMap.Infrastructure/Data/Migrations/20240921074639_AddISO3CountryCodeToComment.cs index b98256e..075685c 100644 --- a/CommentMap.Mvc/Data/Migrations/20240921074639_AddISO3CountryCodeToComment.cs +++ b/CommentMap.Infrastructure/Data/Migrations/20240921074639_AddISO3CountryCodeToComment.cs @@ -1,8 +1,8 @@ -using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Migrations; #nullable disable -namespace CommentMap.Mvc.Data.Migrations +namespace CommentMap.Infrastructure.Data.Migrations { /// public partial class AddISO3CountryCodeToComment : Migration diff --git a/CommentMap.Mvc/Data/Migrations/CommentMapDbContextModelSnapshot.cs b/CommentMap.Infrastructure/Data/Migrations/CommentMapDbContextModelSnapshot.cs similarity index 90% rename from CommentMap.Mvc/Data/Migrations/CommentMapDbContextModelSnapshot.cs rename to CommentMap.Infrastructure/Data/Migrations/CommentMapDbContextModelSnapshot.cs index 725d962..190756d 100644 --- a/CommentMap.Mvc/Data/Migrations/CommentMapDbContextModelSnapshot.cs +++ b/CommentMap.Infrastructure/Data/Migrations/CommentMapDbContextModelSnapshot.cs @@ -1,6 +1,6 @@ // using System; -using CommentMap.Mvc.Data; +using CommentMap.Infrastructure.Data; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; @@ -9,7 +9,7 @@ #nullable disable -namespace CommentMap.Mvc.Data.Migrations +namespace CommentMap.Infrastructure.Data.Migrations { [DbContext(typeof(CommentMapDbContext))] partial class CommentMapDbContextModelSnapshot : ModelSnapshot @@ -18,13 +18,13 @@ protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "8.0.5") + .HasAnnotation("ProductVersion", "10.0.10") .HasAnnotation("Relational:MaxIdentifierLength", 63); NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "postgis"); NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - modelBuilder.Entity("CommentMap.Mvc.Data.Entities.Comment", b => + modelBuilder.Entity("CommentMap.Application.Entities.Comment", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -72,10 +72,10 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("UserId"); - b.ToTable("Comments"); + b.ToTable("Comments", (string)null); }); - modelBuilder.Entity("CommentMap.Mvc.Data.Entities.Country", b => + modelBuilder.Entity("CommentMap.Application.Entities.Country", b => { b.Property("ISO3Code") .HasMaxLength(3) @@ -117,10 +117,10 @@ protected override void BuildModel(ModelBuilder modelBuilder) NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex("Boundaries"), "gist"); - b.ToTable("Countries"); + b.ToTable("Countries", (string)null); }); - modelBuilder.Entity("CommentMap.Mvc.Data.Entities.Role", b => + modelBuilder.Entity("CommentMap.Application.Entities.Role", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -147,7 +147,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("AspNetRoles", (string)null); }); - modelBuilder.Entity("CommentMap.Mvc.Data.Entities.User", b => + modelBuilder.Entity("CommentMap.Application.Entities.User", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -319,14 +319,14 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("AspNetUserTokens", (string)null); }); - modelBuilder.Entity("CommentMap.Mvc.Data.Entities.Comment", b => + modelBuilder.Entity("CommentMap.Application.Entities.Comment", b => { - b.HasOne("CommentMap.Mvc.Data.Entities.Country", "Country") + b.HasOne("CommentMap.Application.Entities.Country", "Country") .WithMany("Comments") .HasForeignKey("ISO3CodeCountry") .OnDelete(DeleteBehavior.SetNull); - b.HasOne("CommentMap.Mvc.Data.Entities.User", "User") + b.HasOne("CommentMap.Application.Entities.User", "User") .WithMany("Comments") .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -339,7 +339,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => { - b.HasOne("CommentMap.Mvc.Data.Entities.Role", null) + b.HasOne("CommentMap.Application.Entities.Role", null) .WithMany() .HasForeignKey("RoleId") .OnDelete(DeleteBehavior.Cascade) @@ -348,7 +348,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => { - b.HasOne("CommentMap.Mvc.Data.Entities.User", null) + b.HasOne("CommentMap.Application.Entities.User", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -357,7 +357,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => { - b.HasOne("CommentMap.Mvc.Data.Entities.User", null) + b.HasOne("CommentMap.Application.Entities.User", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -366,13 +366,13 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => { - b.HasOne("CommentMap.Mvc.Data.Entities.Role", null) + b.HasOne("CommentMap.Application.Entities.Role", null) .WithMany() .HasForeignKey("RoleId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("CommentMap.Mvc.Data.Entities.User", null) + b.HasOne("CommentMap.Application.Entities.User", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -381,19 +381,19 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => { - b.HasOne("CommentMap.Mvc.Data.Entities.User", null) + b.HasOne("CommentMap.Application.Entities.User", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); }); - modelBuilder.Entity("CommentMap.Mvc.Data.Entities.Country", b => + modelBuilder.Entity("CommentMap.Application.Entities.Country", b => { b.Navigation("Comments"); }); - modelBuilder.Entity("CommentMap.Mvc.Data.Entities.User", b => + modelBuilder.Entity("CommentMap.Application.Entities.User", b => { b.Navigation("Comments"); }); diff --git a/CommentMap.Infrastructure/DependencyInjection/InfrastructureServiceCollectionExtensions.cs b/CommentMap.Infrastructure/DependencyInjection/InfrastructureServiceCollectionExtensions.cs new file mode 100644 index 0000000..e97c3fd --- /dev/null +++ b/CommentMap.Infrastructure/DependencyInjection/InfrastructureServiceCollectionExtensions.cs @@ -0,0 +1,37 @@ +using CommentMap.Application.Abstractions; +using CommentMap.Application.Entities; +using CommentMap.Infrastructure.Data; +using Microsoft.AspNetCore.Identity; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; + +namespace CommentMap.Infrastructure.DependencyInjection; + +public static class InfrastructureServiceCollectionExtensions +{ + public static IHostApplicationBuilder AddInfrastructure(this IHostApplicationBuilder builder) + { + var connectionString = builder.Configuration.GetConnectionString("comment-map"); + + builder.Services + .AddDbContext(options => options.UseNpgsql( + connectionString, + o => o.UseNetTopologySuite())) + .AddDatabaseDeveloperPageExceptionFilter(); + + builder.EnrichNpgsqlDbContext(); + + builder.Services + .AddIdentity(options => + { + options.Stores.MaxLengthForKeys = 128; + options.SignIn.RequireConfirmedAccount = true; + }) + .AddDefaultTokenProviders() + .AddEntityFrameworkStores(); + + return builder; + } +} diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/ConfirmEmail.cshtml.cs b/CommentMap.Mvc/Areas/Identity/Pages/Account/ConfirmEmail.cshtml.cs index ac885a7..77190e4 100644 --- a/CommentMap.Mvc/Areas/Identity/Pages/Account/ConfirmEmail.cshtml.cs +++ b/CommentMap.Mvc/Areas/Identity/Pages/Account/ConfirmEmail.cshtml.cs @@ -1,36 +1,25 @@ -using System.Text; -using CommentMap.Mvc.Data.Entities; -using Microsoft.AspNetCore.Identity; +using CommentMap.Application.Features.Identity; +using CommentMap.Application.Models; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; -using Microsoft.AspNetCore.WebUtilities; +using Wolverine; namespace CommentMap.Mvc.Areas.Identity.Pages.Account; -public class ConfirmEmailModel(UserManager userManager) : PageModel +public class ConfirmEmailModel(IMessageBus bus) : PageModel { - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// [TempData] public string? StatusMessage { get; set; } public async Task OnGetAsync(string userId, string code) { if (userId == null || code == null) - { return RedirectToPage("/Index"); - } - var user = await userManager.FindByIdAsync(userId); - if (user == null) - { + var result = await bus.InvokeAsync(new ConfirmEmail(userId, code)); + if (result.Errors.Any(e => e.Code == "UserNotFound")) return NotFound($"Unable to load user with ID '{userId}'."); - } - code = Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(code)); - var result = await userManager.ConfirmEmailAsync(user, code); StatusMessage = result.Succeeded ? "Thank you for confirming your email." : "Error confirming your email."; return Page(); } diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/ConfirmEmailChange.cshtml.cs b/CommentMap.Mvc/Areas/Identity/Pages/Account/ConfirmEmailChange.cshtml.cs index a9ebdac..b33a947 100644 --- a/CommentMap.Mvc/Areas/Identity/Pages/Account/ConfirmEmailChange.cshtml.cs +++ b/CommentMap.Mvc/Areas/Identity/Pages/Account/ConfirmEmailChange.cshtml.cs @@ -1,53 +1,31 @@ -using System.Text; -using CommentMap.Mvc.Data.Entities; -using Microsoft.AspNetCore.Identity; +using CommentMap.Application.Features.Identity; +using CommentMap.Application.Models; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; -using Microsoft.AspNetCore.WebUtilities; +using Wolverine; namespace CommentMap.Mvc.Areas.Identity.Pages.Account; -public class ConfirmEmailChangeModel(UserManager userManager, SignInManager signInManager) : PageModel +public class ConfirmEmailChangeModel(IMessageBus bus) : PageModel { - - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// [TempData] - public string StatusMessage { get; set; } + public string StatusMessage { get; set; } = null!; public async Task OnGetAsync(string userId, string email, string code) { if (userId == null || email == null || code == null) - { return RedirectToPage("/Index"); - } - var user = await userManager.FindByIdAsync(userId); - if (user is null) - { + var result = await bus.InvokeAsync(new ConfirmEmailChange(userId, email, code)); + if (result.Errors.Any(e => e.Code == "UserNotFound")) return NotFound($"Unable to load user with ID '{userId}'."); - } - code = Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(code)); - var result = await userManager.ChangeEmailAsync(user, email, code); if (!result.Succeeded) { StatusMessage = "Error changing email."; return Page(); } - // In our UI email and user name are one and the same, so when we update the email - // we need to update the user name. - var setUserNameResult = await userManager.SetUserNameAsync(user, email); - if (!setUserNameResult.Succeeded) - { - StatusMessage = "Error changing user name."; - return Page(); - } - - await signInManager.RefreshSignInAsync(user); StatusMessage = "Thank you for confirming your email change."; return Page(); } diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/ExternalLogin.cshtml.cs b/CommentMap.Mvc/Areas/Identity/Pages/Account/ExternalLogin.cshtml.cs index a00a53d..1ab6a90 100644 --- a/CommentMap.Mvc/Areas/Identity/Pages/Account/ExternalLogin.cshtml.cs +++ b/CommentMap.Mvc/Areas/Identity/Pages/Account/ExternalLogin.cshtml.cs @@ -1,87 +1,44 @@ using System.ComponentModel.DataAnnotations; -using System.Security.Claims; -using CommentMap.Mvc.Data.Entities; +using CommentMap.Application.Entities; +using CommentMap.Application.Features.Identity; +using CommentMap.Application.Models; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; +using Wolverine; namespace CommentMap.Mvc.Areas.Identity.Pages.Account; [AllowAnonymous] -public class ExternalLoginModel : PageModel +public class ExternalLoginModel(IMessageBus bus, SignInManager signInManager) : PageModel { - private readonly SignInManager _signInManager; - private readonly UserManager _userManager; - private readonly IUserStore _userStore; - private readonly ILogger _logger; - - public ExternalLoginModel( - SignInManager signInManager, - UserManager userManager, - IUserStore userStore, - ILogger logger) - { - _signInManager = signInManager; - _userManager = userManager; - _userStore = userStore; - _logger = logger; - } - - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// [BindProperty] - public InputModel Input { get; set; } - - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// - public string ProviderDisplayName { get; set; } - - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// - public string ReturnUrl { get; set; } - - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// + public InputModel Input { get; set; } = null!; + + public string? ProviderDisplayName { get; set; } + + public string? ReturnUrl { get; set; } + [TempData] - public string ErrorMessage { get; set; } + public string? ErrorMessage { get; set; } - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// public class InputModel { - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// [Required] - public string UserName { get; set; } + public string UserName { get; set; } = null!; } - public IActionResult OnGet() - { - return RedirectToPage("./Login"); - } + public IActionResult OnGet() => RedirectToPage("./Login"); - public IActionResult OnPost(string provider, string returnUrl = null) + public IActionResult OnPost(string provider, string? returnUrl = null) { - // Request a redirect to the external login provider. var redirectUrl = Url.Page("./ExternalLogin", pageHandler: "Callback", values: new { returnUrl }); - var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl); + var properties = signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl); return new ChallengeResult(provider, properties); } - public async Task OnGetCallbackAsync(string returnUrl = null, string remoteError = null) + public async Task OnGetCallbackAsync(string? returnUrl = null, string? remoteError = null) { returnUrl ??= Url.Content("~/"); if (remoteError != null) @@ -89,39 +46,33 @@ public async Task OnGetCallbackAsync(string returnUrl = null, str ErrorMessage = $"Error from external provider: {remoteError}"; return RedirectToPage("./Login", new { ReturnUrl = returnUrl }); } - var info = await _signInManager.GetExternalLoginInfoAsync(); + + var info = await signInManager.GetExternalLoginInfoAsync(); if (info == null) { ErrorMessage = "Error loading external login information."; return RedirectToPage("./Login", new { ReturnUrl = returnUrl }); } - // Sign in the user with this external login provider if the user already has a login. - var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false, bypassTwoFactor: true); + var result = await bus.InvokeAsync( + new ExternalLoginSignIn(info.LoginProvider, info.ProviderKey)); + if (result.Succeeded) - { - _logger.LogInformation("{Name} logged in with {LoginProvider} provider.", info.Principal.Identity.Name, info.LoginProvider); return LocalRedirect(returnUrl); - } - // If the user does not have an account, then ask the user to create an account. ReturnUrl = returnUrl; ProviderDisplayName = info.ProviderDisplayName; - if (info.Principal.HasClaim(c => c.Type == ClaimTypes.Name)) - { - Input = new InputModel - { - UserName = info.Principal.FindFirstValue(ClaimTypes.Name) - }; - } + var suggested = ExternalLoginHelpers.SuggestedUserName(info.Principal); + if (suggested != null) + Input = new InputModel { UserName = suggested }; + return Page(); } - public async Task OnPostConfirmationAsync(string returnUrl = null) + public async Task OnPostConfirmationAsync(string? returnUrl = null) { returnUrl ??= Url.Content("~/"); - // Get the information about the user from the external login provider - var info = await _signInManager.GetExternalLoginInfoAsync(); + var info = await signInManager.GetExternalLoginInfoAsync(); if (info == null) { ErrorMessage = "Error loading external login information during confirmation."; @@ -130,44 +81,18 @@ public async Task OnPostConfirmationAsync(string returnUrl = null if (ModelState.IsValid) { - var user = CreateUser(); + var result = await bus.InvokeAsync( + new CreateExternalUser(Input.UserName, info)); - await _userStore.SetUserNameAsync(user, Input.UserName, CancellationToken.None); - - var result = await _userManager.CreateAsync(user); if (result.Succeeded) - { - result = await _userManager.AddLoginAsync(user, info); - if (result.Succeeded) - { - _logger.LogInformation("User created an account using {Name} provider.", info.LoginProvider); - - await _signInManager.SignInAsync(user, isPersistent: false, info.LoginProvider); - return LocalRedirect(returnUrl); - } - } + return LocalRedirect(returnUrl); + foreach (var error in result.Errors) - { ModelState.AddModelError(string.Empty, error.Description); - } } ProviderDisplayName = info.ProviderDisplayName; ReturnUrl = returnUrl; return Page(); } - - private User CreateUser() - { - try - { - return Activator.CreateInstance(); - } - catch - { - throw new InvalidOperationException($"Can't create an instance of '{nameof(User)}'. " + - $"Ensure that '{nameof(User)}' is not an abstract class and has a parameterless constructor, or alternatively " + - $"override the external login page in /Areas/Identity/Pages/Account/ExternalLogin.cshtml"); - } - } } diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/ForgotPassword.cshtml.cs b/CommentMap.Mvc/Areas/Identity/Pages/Account/ForgotPassword.cshtml.cs index a67905e..915fe18 100644 --- a/CommentMap.Mvc/Areas/Identity/Pages/Account/ForgotPassword.cshtml.cs +++ b/CommentMap.Mvc/Areas/Identity/Pages/Account/ForgotPassword.cshtml.cs @@ -1,67 +1,41 @@ using System.ComponentModel.DataAnnotations; -using System.Text; -using CommentMap.Mvc.Data.Entities; +using CommentMap.Application.Features.Identity; using CommentMap.Shared.Messages; -using MassTransit; -using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; -using Microsoft.AspNetCore.WebUtilities; +using Wolverine; namespace CommentMap.Mvc.Areas.Identity.Pages.Account; -public class ForgotPasswordModel(UserManager userManager, ISendEndpointProvider sendEndpointProvider) - : PageModel +public class ForgotPasswordModel(IMessageBus bus) : PageModel { - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// [BindProperty] - public InputModel Input { get; set; } + public InputModel Input { get; set; } = null!; - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// public class InputModel { - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// [Required] [EmailAddress] - public string Email { get; set; } + public string Email { get; set; } = null!; } public async Task OnPostAsync(CancellationToken ct) { if (!ModelState.IsValid) - { return Page(); - } - var user = await userManager.FindByEmailAsync(Input.Email); - if (user == null || !await userManager.IsEmailConfirmedAsync(user)) + var result = await bus.InvokeAsync(new ForgotPassword(Input.Email), ct); + if (result.UserFound) { - // Don't reveal that the user does not exist or is not confirmed - return RedirectToPage("./ForgotPasswordConfirmation"); - } + var callbackUrl = Url.Page( + "/Account/ResetPassword", + pageHandler: null, + values: new { area = "Identity", code = result.EncodedResetCode, userId = result.UserId }, + protocol: Request.Scheme)!; - // For more information on how to enable account confirmation and password reset please - // visit https://go.microsoft.com/fwlink/?LinkID=532713 - var code = await userManager.GeneratePasswordResetTokenAsync(user); - code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code)); - var callbackUrl = Url.Page( - "/Account/ResetPassword", - pageHandler: null, - values: new { area = "Identity", code, userId = user.Id }, - protocol: Request.Scheme); + await bus.PublishAsync(new SendResetPasswordEmail(Input.Email, callbackUrl)); + } - var endpoint = await sendEndpointProvider.GetSendEndpoint(new Uri("queue:" + nameof(SendResetPasswordEmail))); - await endpoint.Send(new SendResetPasswordEmail(Input.Email, callbackUrl), ct); - return RedirectToPage("./ForgotPasswordConfirmation"); } } diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/Login.cshtml.cs b/CommentMap.Mvc/Areas/Identity/Pages/Account/Login.cshtml.cs index 00f2f36..da68599 100644 --- a/CommentMap.Mvc/Areas/Identity/Pages/Account/Login.cshtml.cs +++ b/CommentMap.Mvc/Areas/Identity/Pages/Account/Login.cshtml.cs @@ -1,75 +1,37 @@ using System.ComponentModel.DataAnnotations; -using CommentMap.Mvc.Data.Entities; +using CommentMap.Application.Entities; +using CommentMap.Application.Features.Identity; +using CommentMap.Application.Models; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; +using Wolverine; namespace CommentMap.Mvc.Areas.Identity.Pages.Account; -public class LoginModel : PageModel +public class LoginModel(IMessageBus bus, SignInManager signInManager) : PageModel { - private readonly SignInManager _signInManager; - private readonly ILogger _logger; - - public LoginModel(SignInManager signInManager, ILogger logger) - { - _signInManager = signInManager; - _logger = logger; - } - - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// [BindProperty] - public InputModel Input { get; set; } + public InputModel Input { get; set; } = null!; - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// - public IList ExternalLogins { get; set; } + public IList ExternalLogins { get; set; } = null!; - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// - public string ReturnUrl { get; set; } + public string ReturnUrl { get; set; } = null!; - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// [TempData] - public string ErrorMessage { get; set; } + public string? ErrorMessage { get; set; } - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// public class InputModel { - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// [Required] [EmailAddress] - public string Email { get; set; } + public string Email { get; set; } = null!; - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// [Required] [DataType(DataType.Password)] - public string Password { get; set; } + public string Password { get; set; } = null!; - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// [Display(Name = "Remember me?")] public bool RememberMe { get; set; } } @@ -77,53 +39,33 @@ public class InputModel public async Task OnGetAsync(string? returnUrl = null) { if (!string.IsNullOrEmpty(ErrorMessage)) - { ModelState.AddModelError(string.Empty, ErrorMessage); - } returnUrl ??= Url.Content("~/"); - - // Clear the existing external cookie to ensure a clean login process await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme); - - ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList(); - + ExternalLogins = (await signInManager.GetExternalAuthenticationSchemesAsync()).ToList(); ReturnUrl = returnUrl; } - public async Task OnPostAsync(string returnUrl = null) + public async Task OnPostAsync(string? returnUrl = null) { returnUrl ??= Url.Content("~/"); + ExternalLogins = (await signInManager.GetExternalAuthenticationSchemesAsync()).ToList(); + + if (!ModelState.IsValid) + return Page(); - ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList(); + var result = await bus.InvokeAsync( + new LoginUser(Input.Email, Input.Password, Input.RememberMe)); - if (ModelState.IsValid) - { - // This doesn't count login failures towards account lockout - // To enable password failures to trigger account lockout, set lockoutOnFailure: true - var result = await _signInManager.PasswordSignInAsync(Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: false); - if (result.Succeeded) - { - _logger.LogInformation("User logged in."); - return LocalRedirect(returnUrl); - } - if (result.RequiresTwoFactor) - { - return RedirectToPage("./LoginWith2fa", new { ReturnUrl = returnUrl, Input.RememberMe }); - } - if (result.IsLockedOut) - { - _logger.LogWarning("User account locked out."); - return RedirectToPage("./Lockout"); - } - else - { - ModelState.AddModelError(string.Empty, "Invalid login attempt."); - return Page(); - } - } + if (result.Succeeded) + return LocalRedirect(returnUrl); + if (result.RequiresTwoFactor) + return RedirectToPage("./LoginWith2fa", new { ReturnUrl = returnUrl, Input.RememberMe }); + if (result.IsLockedOut) + return RedirectToPage("./Lockout"); - // If we got this far, something failed, redisplay form + ModelState.AddModelError(string.Empty, "Invalid login attempt."); return Page(); } } diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/LoginWith2fa.cshtml.cs b/CommentMap.Mvc/Areas/Identity/Pages/Account/LoginWith2fa.cshtml.cs index d91df5e..d00b313 100644 --- a/CommentMap.Mvc/Areas/Identity/Pages/Account/LoginWith2fa.cshtml.cs +++ b/CommentMap.Mvc/Areas/Identity/Pages/Account/LoginWith2fa.cshtml.cs @@ -1,120 +1,56 @@ using System.ComponentModel.DataAnnotations; +using CommentMap.Application.Features.Identity; +using CommentMap.Application.Models; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; -using Microsoft.AspNetCore.Identity; -using CommentMap.Mvc.Data.Entities; +using Wolverine; namespace CommentMap.Mvc.Areas.Identity.Pages.Account; -public class LoginWith2faModel : PageModel +public class LoginWith2faModel(IMessageBus bus) : PageModel { - private readonly SignInManager _signInManager; - private readonly UserManager _userManager; - private readonly ILogger _logger; - - public LoginWith2faModel( - SignInManager signInManager, - UserManager userManager, - ILogger logger) - { - _signInManager = signInManager; - _userManager = userManager; - _logger = logger; - } - - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// [BindProperty] - public InputModel Input { get; set; } + public InputModel Input { get; set; } = null!; - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// public bool RememberMe { get; set; } - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// - public string ReturnUrl { get; set; } + public string? ReturnUrl { get; set; } - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// public class InputModel { - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// [Required] [StringLength(7, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)] [DataType(DataType.Text)] [Display(Name = "Authenticator code")] - public string TwoFactorCode { get; set; } + public string TwoFactorCode { get; set; } = null!; - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// [Display(Name = "Remember this machine")] public bool RememberMachine { get; set; } } - public async Task OnGetAsync(bool rememberMe, string returnUrl = null) + public Task OnGetAsync(bool rememberMe, string? returnUrl = null) { - // Ensure the user has gone through the username & password screen first - var user = await _signInManager.GetTwoFactorAuthenticationUserAsync(); - - if (user == null) - { - throw new InvalidOperationException($"Unable to load two-factor authentication user."); - } - ReturnUrl = returnUrl; RememberMe = rememberMe; - - return Page(); + return Task.FromResult(Page()); } - public async Task OnPostAsync(bool rememberMe, string returnUrl = null) + public async Task OnPostAsync(bool rememberMe, string? returnUrl = null) { if (!ModelState.IsValid) - { return Page(); - } - - returnUrl = returnUrl ?? Url.Content("~/"); - - var user = await _signInManager.GetTwoFactorAuthenticationUserAsync(); - if (user == null) - { - throw new InvalidOperationException($"Unable to load two-factor authentication user."); - } - var authenticatorCode = Input.TwoFactorCode.Replace(" ", string.Empty).Replace("-", string.Empty); + returnUrl ??= Url.Content("~/"); - var result = await _signInManager.TwoFactorAuthenticatorSignInAsync(authenticatorCode, rememberMe, Input.RememberMachine); + var result = await bus.InvokeAsync( + new LoginWith2fa(Input.TwoFactorCode, rememberMe, Input.RememberMachine)); if (result.Succeeded) - { - _logger.LogInformation("User with ID '{UserId}' logged in with 2fa.", user.Id); return LocalRedirect(returnUrl); - } - else if (result.IsLockedOut) - { - _logger.LogWarning("User with ID '{UserId}' account locked out.", user.Id); + if (result.IsLockedOut) return RedirectToPage("./Lockout"); - } - else - { - _logger.LogWarning("Invalid authenticator code entered for user with ID '{UserId}'.", user.Id); - ModelState.AddModelError(string.Empty, "Invalid authenticator code."); - return Page(); - } + + ModelState.AddModelError(string.Empty, "Invalid authenticator code."); + return Page(); } } diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/LoginWithRecoveryCode.cshtml.cs b/CommentMap.Mvc/Areas/Identity/Pages/Account/LoginWithRecoveryCode.cshtml.cs index cd5242a..a5f03c0 100644 --- a/CommentMap.Mvc/Areas/Identity/Pages/Account/LoginWithRecoveryCode.cshtml.cs +++ b/CommentMap.Mvc/Areas/Identity/Pages/Account/LoginWithRecoveryCode.cshtml.cs @@ -1,102 +1,49 @@ using System.ComponentModel.DataAnnotations; -using CommentMap.Mvc.Data.Entities; -using Microsoft.AspNetCore.Identity; +using CommentMap.Application.Features.Identity; +using CommentMap.Application.Models; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; +using Wolverine; + namespace CommentMap.Mvc.Areas.Identity.Pages.Account; -public class LoginWithRecoveryCodeModel : PageModel +public class LoginWithRecoveryCodeModel(IMessageBus bus) : PageModel { - private readonly SignInManager _signInManager; - private readonly UserManager _userManager; - private readonly ILogger _logger; - - public LoginWithRecoveryCodeModel( - SignInManager signInManager, - UserManager userManager, - ILogger logger) - { - _signInManager = signInManager; - _userManager = userManager; - _logger = logger; - } - - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// [BindProperty] - public InputModel Input { get; set; } + public InputModel Input { get; set; } = null!; - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// - public string ReturnUrl { get; set; } + public string? ReturnUrl { get; set; } - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// public class InputModel { - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// [BindProperty] [Required] [DataType(DataType.Text)] [Display(Name = "Recovery Code")] - public string RecoveryCode { get; set; } + public string RecoveryCode { get; set; } = null!; } - public async Task OnGetAsync(string returnUrl = null) + public Task OnGetAsync(string? returnUrl = null) { - // Ensure the user has gone through the username & password screen first - var user = await _signInManager.GetTwoFactorAuthenticationUserAsync(); - if (user == null) - { - throw new InvalidOperationException($"Unable to load two-factor authentication user."); - } - ReturnUrl = returnUrl; - - return Page(); + return Task.FromResult(Page()); } - public async Task OnPostAsync(string returnUrl = null) + public async Task OnPostAsync(string? returnUrl = null) { if (!ModelState.IsValid) - { return Page(); - } - - var user = await _signInManager.GetTwoFactorAuthenticationUserAsync(); - if (user == null) - { - throw new InvalidOperationException($"Unable to load two-factor authentication user."); - } - var recoveryCode = Input.RecoveryCode.Replace(" ", string.Empty); + returnUrl ??= Url.Content("~/"); - var result = await _signInManager.TwoFactorRecoveryCodeSignInAsync(recoveryCode); + var result = await bus.InvokeAsync(new LoginWithRecoveryCode(Input.RecoveryCode)); if (result.Succeeded) - { - _logger.LogInformation("User with ID '{UserId}' logged in with a recovery code.", user.Id); - return LocalRedirect(returnUrl ?? Url.Content("~/")); - } + return LocalRedirect(returnUrl); if (result.IsLockedOut) - { - _logger.LogWarning("User account locked out."); return RedirectToPage("./Lockout"); - } - else - { - _logger.LogWarning("Invalid recovery code entered for user with ID '{UserId}' ", user.Id); - ModelState.AddModelError(string.Empty, "Invalid recovery code entered."); - return Page(); - } + + ModelState.AddModelError(string.Empty, "Invalid recovery code entered."); + return Page(); } } diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/Logout.cshtml.cs b/CommentMap.Mvc/Areas/Identity/Pages/Account/Logout.cshtml.cs index 518951d..6f04289 100644 --- a/CommentMap.Mvc/Areas/Identity/Pages/Account/Logout.cshtml.cs +++ b/CommentMap.Mvc/Areas/Identity/Pages/Account/Logout.cshtml.cs @@ -1,34 +1,18 @@ -using CommentMap.Mvc.Data.Entities; -using Microsoft.AspNetCore.Identity; +using CommentMap.Application.Features.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; +using Wolverine; namespace CommentMap.Mvc.Areas.Identity.Pages.Account; -public class LogoutModel : PageModel +public class LogoutModel(IMessageBus bus) : PageModel { - private readonly SignInManager _signInManager; - private readonly ILogger _logger; - - public LogoutModel(SignInManager signInManager, ILogger logger) - { - _signInManager = signInManager; - _logger = logger; - } - public async Task OnPost(string? returnUrl = null) { - await _signInManager.SignOutAsync(); - _logger.LogInformation("User logged out."); + await bus.InvokeAsync(new LogoutUser()); if (returnUrl != null) - { return LocalRedirect(returnUrl); - } - else - { - // This needs to be a redirect so that the browser performs a new - // request and the identity for the user gets updated. - return RedirectToPage(); - } + + return RedirectToPage(); } } diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ChangePassword.cshtml.cs b/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ChangePassword.cshtml.cs index f4a5991..b3d6b64 100644 --- a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ChangePassword.cshtml.cs +++ b/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ChangePassword.cshtml.cs @@ -1,80 +1,48 @@ -using CommentMap.Mvc.Data.Entities; -using Microsoft.AspNetCore.Identity; +using CommentMap.Application.Features.Identity; +using CommentMap.Application.Models; +using CommentMap.Mvc.Extensions; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using System.ComponentModel.DataAnnotations; +using Wolverine; namespace CommentMap.Mvc.Areas.Identity.Pages.Account.Manage; -public class ChangePasswordModel( - UserManager userManager, - SignInManager signInManager, - ILogger logger) - : PageModel +public class ChangePasswordModel(IMessageBus bus) : PageModel { - - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// [BindProperty] - public InputModel Input { get; set; } + public InputModel Input { get; set; } = null!; - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// [TempData] public string? StatusMessage { get; set; } - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// public class InputModel { - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// [Required] [DataType(DataType.Password)] [Display(Name = "Current password")] - public string OldPassword { get; set; } + public string OldPassword { get; set; } = null!; - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// [Required] [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)] [DataType(DataType.Password)] [Display(Name = "New password")] - public string NewPassword { get; set; } + public string NewPassword { get; set; } = null!; - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// [DataType(DataType.Password)] [Display(Name = "Confirm new password")] [Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")] - public string ConfirmPassword { get; set; } + public string ConfirmPassword { get; set; } = null!; } public async Task OnGetAsync() { - var user = await userManager.GetUserAsync(User); - if (user == null) - { - return NotFound($"Unable to load user with ID '{userManager.GetUserId(User)}'."); - } - - var hasPassword = await userManager.HasPasswordAsync(user); - if (!hasPassword) - { + var userId = User.FindUserId(); + var hasPassword = await bus.InvokeAsync(new HasPassword(userId)); + if (!hasPassword.Found) + return NotFound($"Unable to load user with ID '{userId}'."); + if (!hasPassword.HasPassword) return RedirectToPage("./SetPassword"); - } return Page(); } @@ -82,30 +50,23 @@ public async Task OnGetAsync() public async Task OnPostAsync() { if (!ModelState.IsValid) - { return Page(); - } - var user = await userManager.GetUserAsync(User); - if (user == null) - { - return NotFound($"Unable to load user with ID '{userManager.GetUserId(User)}'."); - } + var userId = User.FindUserId(); + var result = await bus.InvokeAsync( + new ChangePassword(userId, Input.OldPassword, Input.NewPassword)); - var changePasswordResult = await userManager.ChangePasswordAsync(user, Input.OldPassword, Input.NewPassword); - if (!changePasswordResult.Succeeded) + if (!result.Succeeded) { - foreach (var error in changePasswordResult.Errors) - { + if (result.Errors.Any(e => e.Code == "UserNotFound")) + return NotFound($"Unable to load user with ID '{userId}'."); + + foreach (var error in result.Errors) ModelState.AddModelError(string.Empty, error.Description); - } return Page(); } - await signInManager.RefreshSignInAsync(user); - logger.LogInformation("User changed their password successfully."); StatusMessage = "Your password has been changed."; - return RedirectToPage(); } } diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/DeleteProfile.cshtml.cs b/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/DeleteProfile.cshtml.cs index 0d94fc0..7de92bd 100644 --- a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/DeleteProfile.cshtml.cs +++ b/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/DeleteProfile.cshtml.cs @@ -1,95 +1,56 @@ using System.ComponentModel.DataAnnotations; -using CommentMap.Mvc.Data.Entities; -using Microsoft.AspNetCore.Identity; +using CommentMap.Application.Features.Identity; +using CommentMap.Application.Models; +using CommentMap.Mvc.Extensions; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; +using Wolverine; namespace CommentMap.Mvc.Areas.Identity.Pages.Account.Manage; -public class DeletePersonalDataModel : PageModel +public class DeletePersonalDataModel(IMessageBus bus) : PageModel { - private readonly UserManager _userManager; - private readonly SignInManager _signInManager; - private readonly ILogger _logger; - - public DeletePersonalDataModel( - UserManager userManager, - SignInManager signInManager, - ILogger logger) - { - _userManager = userManager; - _signInManager = signInManager; - _logger = logger; - } - - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// [BindProperty] - public InputModel Input { get; set; } + public InputModel Input { get; set; } = null!; - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// public class InputModel { - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// [Required] [DataType(DataType.Password)] - public string Password { get; set; } + public string Password { get; set; } = null!; } - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// public bool RequirePassword { get; set; } public async Task OnGet() { - var user = await _userManager.GetUserAsync(User); - if (user == null) - { - return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); - } + var userId = User.FindUserId(); + var info = await bus.InvokeAsync(new GetDeleteProfileInfo(userId)); + if (!info.Found) + return NotFound($"Unable to load user with ID '{userId}'."); - RequirePassword = await _userManager.HasPasswordAsync(user); + RequirePassword = info.RequirePassword; return Page(); } public async Task OnPostAsync() { - var user = await _userManager.GetUserAsync(User); - if (user == null) - { - return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); - } + var userId = User.FindUserId(); + var info = await bus.InvokeAsync(new GetDeleteProfileInfo(userId)); + if (!info.Found) + return NotFound($"Unable to load user with ID '{userId}'."); - RequirePassword = await _userManager.HasPasswordAsync(user); - if (RequirePassword) - { - if (!await _userManager.CheckPasswordAsync(user, Input.Password)) - { - ModelState.AddModelError(string.Empty, "Incorrect password."); - return Page(); - } - } + RequirePassword = info.RequirePassword; + var result = await bus.InvokeAsync( + new DeleteProfile(userId, RequirePassword ? Input.Password : null)); - var result = await _userManager.DeleteAsync(user); if (!result.Succeeded) { - throw new InvalidOperationException($"Unexpected error occurred deleting user."); + foreach (var error in result.Errors) + ModelState.AddModelError(string.Empty, error.Description); + return Page(); } - await _signInManager.SignOutAsync(); - - _logger.LogInformation("User with ID '{UserId}' deleted themselves.", user.Id); - return Redirect("~/"); } } diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/Disable2fa.cshtml.cs b/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/Disable2fa.cshtml.cs index 487c23e..00f83d5 100644 --- a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/Disable2fa.cshtml.cs +++ b/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/Disable2fa.cshtml.cs @@ -1,61 +1,35 @@ -using CommentMap.Mvc.Data.Entities; -using Microsoft.AspNetCore.Identity; +using CommentMap.Application.Features.Identity; +using CommentMap.Mvc.Extensions; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; +using Wolverine; namespace CommentMap.Mvc.Areas.Identity.Pages.Account.Manage; -public class Disable2faModel : PageModel +public class Disable2faModel(IMessageBus bus) : PageModel { - private readonly UserManager _userManager; - private readonly ILogger _logger; - - public Disable2faModel( - UserManager userManager, - ILogger logger) - { - _userManager = userManager; - _logger = logger; - } - - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// [TempData] - public string StatusMessage { get; set; } + public string? StatusMessage { get; set; } public async Task OnGet() { - var user = await _userManager.GetUserAsync(User); - if (user == null) - { - return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); - } - - if (!await _userManager.GetTwoFactorEnabledAsync(user)) - { - throw new InvalidOperationException($"Cannot disable 2FA for user as it's not currently enabled."); - } + var userId = User.FindUserId(); + var status = await bus.InvokeAsync(new GetTwoFactorStatus(userId)); + if (!status.Found) + return NotFound($"Unable to load user with ID '{userId}'."); + if (!status.Is2faEnabled) + throw new InvalidOperationException("Cannot disable 2FA for user as it's not currently enabled."); return Page(); } public async Task OnPostAsync() { - var user = await _userManager.GetUserAsync(User); - if (user == null) - { - return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); - } - - var disable2faResult = await _userManager.SetTwoFactorEnabledAsync(user, false); - if (!disable2faResult.Succeeded) - { - throw new InvalidOperationException($"Unexpected error occurred disabling 2FA."); - } + var userId = User.FindUserId(); + var ok = await bus.InvokeAsync(new Disable2fa(userId)); + if (!ok) + return NotFound($"Unable to load user with ID '{userId}'."); - _logger.LogInformation("User with ID '{UserId}' has disabled 2fa.", _userManager.GetUserId(User)); StatusMessage = "2fa has been disabled. You can reenable 2fa when you setup an authenticator app"; return RedirectToPage("./TwoFactorAuthentication"); } diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/EnableAuthenticator.cshtml.cs b/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/EnableAuthenticator.cshtml.cs index a374f58..a44973d 100644 --- a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/EnableAuthenticator.cshtml.cs +++ b/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/EnableAuthenticator.cshtml.cs @@ -1,165 +1,89 @@ using System.ComponentModel.DataAnnotations; -using System.Text; -using CommentMap.Mvc.Data.Entities; -using CommentMap.Mvc.Services; -using Microsoft.AspNetCore.Identity; +using CommentMap.Application.Features.Identity; +using CommentMap.Application.Models; +using CommentMap.Mvc.Extensions; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; +using Wolverine; namespace CommentMap.Mvc.Areas.Identity.Pages.Account.Manage; -public class EnableAuthenticatorModel : PageModel +public class EnableAuthenticatorModel(IMessageBus bus) : PageModel { - private readonly UserManager _userManager; - private readonly ILogger _logger; - private readonly IEnableAuthenticatorService _enableAuthenticatorService; - - public EnableAuthenticatorModel( - UserManager userManager, - ILogger logger, - IEnableAuthenticatorService enableAuthenticatorService) - { - _userManager = userManager; - _logger = logger; - _enableAuthenticatorService = enableAuthenticatorService; - } - - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// - public string SharedKey { get; set; } - - public string AuthenticatorUri { get; set; } - + public string SharedKey { get; set; } = null!; + public string AuthenticatorUri { get; set; } = null!; public string? QrCode { get; set; } - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// [TempData] - public string[] RecoveryCodes { get; set; } + public string[]? RecoveryCodes { get; set; } - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// [TempData] - public string StatusMessage { get; set; } + public string? StatusMessage { get; set; } - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// [BindProperty] - public InputModel Input { get; set; } + public InputModel Input { get; set; } = null!; - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// public class InputModel { - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// [Required] [StringLength(7, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)] [DataType(DataType.Text)] [Display(Name = "Verification Code")] - public string Code { get; set; } + public string Code { get; set; } = null!; } public async Task OnGetAsync() { - var user = await _userManager.GetUserAsync(User); - if (user == null) - { - return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); - } - - await LoadSharedKeyAndQrCodeUriAsync(user); + var userId = User.FindUserId(); + var setup = await bus.InvokeAsync(new GetAuthenticatorSetup(userId)); + if (setup is null) + return NotFound($"Unable to load user with ID '{userId}'."); + ApplySetup(setup); return Page(); } public async Task OnPostAsync() { - var user = await _userManager.GetUserAsync(User); - if (user == null) - { - return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); - } + var userId = User.FindUserId(); if (!ModelState.IsValid) { - await LoadSharedKeyAndQrCodeUriAsync(user); + var setup = await bus.InvokeAsync(new GetAuthenticatorSetup(userId)); + if (setup is null) + return NotFound($"Unable to load user with ID '{userId}'."); + ApplySetup(setup); return Page(); } - // Strip spaces and hyphens - var verificationCode = Input.Code.Replace(" ", string.Empty).Replace("-", string.Empty); + var result = await bus.InvokeAsync( + new EnableAuthenticator(userId, Input.Code)); - var is2faTokenValid = await _userManager.VerifyTwoFactorTokenAsync( - user, _userManager.Options.Tokens.AuthenticatorTokenProvider, verificationCode); + if (result is { Succeeded: false, Setup: null }) + return NotFound($"Unable to load user with ID '{userId}'."); - if (!is2faTokenValid) + if (result.InvalidCode) { ModelState.AddModelError("Input.Code", "Verification code is invalid."); - await LoadSharedKeyAndQrCodeUriAsync(user); + ApplySetup(result.Setup!); return Page(); } - await _userManager.SetTwoFactorEnabledAsync(user, true); - var userId = await _userManager.GetUserIdAsync(user); - _logger.LogInformation("User with ID '{UserId}' has enabled 2FA with an authenticator app.", userId); - StatusMessage = "Your authenticator app has been verified."; - if (await _userManager.CountRecoveryCodesAsync(user) == 0) + if (result.ShowRecoveryCodes) { - var recoveryCodes = await _userManager.GenerateNewTwoFactorRecoveryCodesAsync(user, 10); - RecoveryCodes = recoveryCodes.ToArray(); + RecoveryCodes = result.RecoveryCodes; return RedirectToPage("./ShowRecoveryCodes"); } - else - { - return RedirectToPage("./TwoFactorAuthentication"); - } - } - - private async Task LoadSharedKeyAndQrCodeUriAsync(User user) - { - // Load the authenticator key & QR code URI to display on the form - var unformattedKey = await _userManager.GetAuthenticatorKeyAsync(user); - if (string.IsNullOrEmpty(unformattedKey)) - { - await _userManager.ResetAuthenticatorKeyAsync(user); - unformattedKey = await _userManager.GetAuthenticatorKeyAsync(user); - } - SharedKey = FormatKey(unformattedKey); - - AuthenticatorUri = _enableAuthenticatorService.GetQRCodeUri("CommentMap", user.UserName, unformattedKey); - QrCode = _enableAuthenticatorService.GetEmbeddedSource(AuthenticatorUri); + return RedirectToPage("./TwoFactorAuthentication"); } - private static string FormatKey(string unformattedKey) + private void ApplySetup(AuthenticatorSetupDto setup) { - var result = new StringBuilder(); - int currentPosition = 0; - while (currentPosition + 4 < unformattedKey.Length) - { - result.Append(unformattedKey.AsSpan(currentPosition, 4)).Append(' '); - currentPosition += 4; - } - if (currentPosition < unformattedKey.Length) - { - result.Append(unformattedKey.AsSpan(currentPosition)); - } - - return result.ToString().ToLowerInvariant(); + SharedKey = setup.SharedKey; + AuthenticatorUri = setup.AuthenticatorUri; + QrCode = setup.QrCodeEmbedded; } } diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ExternalLogins.cshtml.cs b/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ExternalLogins.cshtml.cs index 7571fde..c1c5c9e 100644 --- a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ExternalLogins.cshtml.cs +++ b/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ExternalLogins.cshtml.cs @@ -1,132 +1,71 @@ -using CommentMap.Mvc.Data.Entities; +using CommentMap.Application.Entities; +using CommentMap.Application.Features.Identity; +using CommentMap.Application.Models; +using CommentMap.Mvc.Extensions; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; +using Wolverine; namespace CommentMap.Mvc.Areas.Identity.Pages.Account.Manage; -public class ExternalLoginsModel : PageModel +public class ExternalLoginsModel(IMessageBus bus, SignInManager signInManager) : PageModel { - private readonly UserManager _userManager; - private readonly SignInManager _signInManager; - private readonly IUserStore _userStore; - - public ExternalLoginsModel( - UserManager userManager, - SignInManager signInManager, - IUserStore userStore) - { - _userManager = userManager; - _signInManager = signInManager; - _userStore = userStore; - } - - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// - public IList CurrentLogins { get; set; } - - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// - public IList OtherLogins { get; set; } - - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// + public IList CurrentLogins { get; set; } = null!; + public IList OtherLogins { get; set; } = null!; public bool ShowRemoveButton { get; set; } - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// [TempData] - public string StatusMessage { get; set; } + public string? StatusMessage { get; set; } public async Task OnGetAsync() { - var user = await _userManager.GetUserAsync(User); - if (user == null) - { - return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); - } - - CurrentLogins = await _userManager.GetLoginsAsync(user); - OtherLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()) - .Where(auth => CurrentLogins.All(ul => auth.Name != ul.LoginProvider)) - .ToList(); - - string passwordHash = null; - if (_userStore is IUserPasswordStore userPasswordStore) - { - passwordHash = await userPasswordStore.GetPasswordHashAsync(user, HttpContext.RequestAborted); - } - - ShowRemoveButton = passwordHash != null || CurrentLogins.Count > 1; + var userId = User.FindUserId(); + var dto = await bus.InvokeAsync(new GetExternalLogins(userId)); + if (!dto.Found) + return NotFound($"Unable to load user with ID '{userId}'."); + + CurrentLogins = dto.CurrentLogins.ToList(); + var schemes = await signInManager.GetExternalAuthenticationSchemesAsync(); + OtherLogins = schemes.Where(s => dto.OtherLoginProviderNames.Contains(s.Name!)).ToList(); + ShowRemoveButton = dto.ShowRemoveButton; return Page(); } public async Task OnPostRemoveLoginAsync(string loginProvider, string providerKey) { - var user = await _userManager.GetUserAsync(User); - if (user == null) - { - return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); - } - - var result = await _userManager.RemoveLoginAsync(user, loginProvider, providerKey); - if (!result.Succeeded) - { - StatusMessage = "The external login was not removed."; - return RedirectToPage(); - } + var userId = User.FindUserId(); + var result = await bus.InvokeAsync( + new RemoveExternalLogin(userId, loginProvider, providerKey)); - await _signInManager.RefreshSignInAsync(user); - StatusMessage = "The external login was removed."; + StatusMessage = result.Succeeded + ? "The external login was removed." + : "The external login was not removed."; return RedirectToPage(); } public async Task OnPostLinkLoginAsync(string provider) { - // Clear the existing external cookie to ensure a clean login process await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme); - - // Request a redirect to the external login provider to link a login for the current user var redirectUrl = Url.Page("./ExternalLogins", pageHandler: "LinkLoginCallback"); - var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl, _userManager.GetUserId(User)); + var properties = signInManager.ConfigureExternalAuthenticationProperties( + provider, redirectUrl, User.FindUserId().ToString()); return new ChallengeResult(provider, properties); } public async Task OnGetLinkLoginCallbackAsync() { - var user = await _userManager.GetUserAsync(User); - if (user == null) - { - return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); - } - - var userId = await _userManager.GetUserIdAsync(user); - var info = await _signInManager.GetExternalLoginInfoAsync(userId); - if (info == null) - { - throw new InvalidOperationException($"Unexpected error occurred loading external login info."); - } - - var result = await _userManager.AddLoginAsync(user, info); - if (!result.Succeeded) - { - StatusMessage = "The external login was not added. External logins can only be associated with one account."; - return RedirectToPage(); - } + var userId = User.FindUserId(); + var result = await bus.InvokeAsync(new LinkExternalLogin(userId)); + if (result.Errors.Any(e => e.Code == "UserNotFound")) + return NotFound($"Unable to load user with ID '{userId}'."); - // Clear the existing external cookie to ensure a clean login process await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme); - StatusMessage = "The external login was added."; + StatusMessage = result.Succeeded + ? "The external login was added." + : "The external login was not added. External logins can only be associated with one account."; return RedirectToPage(); } } diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/GenerateRecoveryCodes.cshtml.cs b/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/GenerateRecoveryCodes.cshtml.cs index 8607db8..9398a72 100644 --- a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/GenerateRecoveryCodes.cshtml.cs +++ b/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/GenerateRecoveryCodes.cshtml.cs @@ -1,73 +1,39 @@ -using CommentMap.Mvc.Data.Entities; -using Microsoft.AspNetCore.Identity; +using CommentMap.Application.Features.Identity; +using CommentMap.Mvc.Extensions; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; +using Wolverine; namespace CommentMap.Mvc.Areas.Identity.Pages.Account.Manage; -public class GenerateRecoveryCodesModel : PageModel +public class GenerateRecoveryCodesModel(IMessageBus bus) : PageModel { - private readonly UserManager _userManager; - private readonly ILogger _logger; - - public GenerateRecoveryCodesModel( - UserManager userManager, - ILogger logger) - { - _userManager = userManager; - _logger = logger; - } - - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// [TempData] - public string[] RecoveryCodes { get; set; } + public string[]? RecoveryCodes { get; set; } - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// [TempData] - public string StatusMessage { get; set; } + public string? StatusMessage { get; set; } public async Task OnGetAsync() { - var user = await _userManager.GetUserAsync(User); - if (user == null) - { - return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); - } - - var isTwoFactorEnabled = await _userManager.GetTwoFactorEnabledAsync(user); - if (!isTwoFactorEnabled) - { - throw new InvalidOperationException($"Cannot generate recovery codes for user because they do not have 2FA enabled."); - } + var userId = User.FindUserId(); + var status = await bus.InvokeAsync(new GetTwoFactorStatus(userId)); + if (!status.Found) + return NotFound($"Unable to load user with ID '{userId}'."); + if (!status.Is2faEnabled) + throw new InvalidOperationException("Cannot generate recovery codes for user because they do not have 2FA enabled."); return Page(); } public async Task OnPostAsync() { - var user = await _userManager.GetUserAsync(User); - if (user == null) - { - return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); - } - - var isTwoFactorEnabled = await _userManager.GetTwoFactorEnabledAsync(user); - var userId = await _userManager.GetUserIdAsync(user); - if (!isTwoFactorEnabled) - { - throw new InvalidOperationException($"Cannot generate recovery codes for user as they do not have 2FA enabled."); - } - - var recoveryCodes = await _userManager.GenerateNewTwoFactorRecoveryCodesAsync(user, 10); - RecoveryCodes = recoveryCodes.ToArray(); + var userId = User.FindUserId(); + var result = await bus.InvokeAsync(new GenerateRecoveryCodes(userId)); + if (!result.Found) + return NotFound($"Unable to load user with ID '{userId}'."); - _logger.LogInformation("User with ID '{UserId}' has generated new 2FA recovery codes.", userId); + RecoveryCodes = result.RecoveryCodes; StatusMessage = "You have generated new recovery codes."; return RedirectToPage("./ShowRecoveryCodes"); } diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/Index.cshtml.cs b/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/Index.cshtml.cs index 54fed0e..d5620c6 100644 --- a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/Index.cshtml.cs +++ b/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/Index.cshtml.cs @@ -1,107 +1,76 @@ -using CommentMap.Mvc.Data.Entities; +using CommentMap.Application.Features.Identity; +using CommentMap.Mvc.Extensions; using CommentMap.Shared.Messages; -using MassTransit; -using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; -using Microsoft.AspNetCore.WebUtilities; using System.ComponentModel.DataAnnotations; -using System.Text; +using Wolverine; namespace CommentMap.Mvc.Areas.Identity.Pages.Account.Manage; -public class IndexModel(UserManager userManager, ISendEndpointProvider sendEndpointProvider) - : PageModel +public class IndexModel(IMessageBus bus) : PageModel { - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// public string? Email { get; set; } - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// [TempData] - public string StatusMessage { get; set; } + public string? StatusMessage { get; set; } - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// [BindProperty] - public InputModel Input { get; set; } + public InputModel Input { get; set; } = null!; - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// public class InputModel { - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// [Required] [Display(Name = "New email")] public string? NewEmail { get; set; } } - private void Load(User user) + private void Load(string? email) { - Email = user.Email; - - Input = new InputModel - { - NewEmail = user.Email, - }; + Email = email; + Input = new InputModel { NewEmail = email }; } public async Task OnGetAsync() { - var user = await userManager.GetUserAsync(User); - if (user is null) - { - return NotFound($"Unable to load user with ID '{userManager.GetUserId(User)}'."); - } + var userId = User.FindUserId(); + var profile = await bus.InvokeAsync(new GetProfileEmail(userId)); + if (!profile.Found) + return NotFound($"Unable to load user with ID '{userId}'."); - Load(user); + Load(profile.Email); return Page(); } public async Task OnPostAsync(CancellationToken ct) { - var user = await userManager.GetUserAsync(User); - if (user is null) - { - return NotFound($"Unable to load user with ID '{userManager.GetUserId(User)}'."); - } + var userId = User.FindUserId(); + var profile = await bus.InvokeAsync(new GetProfileEmail(userId), ct); + if (!profile.Found) + return NotFound($"Unable to load user with ID '{userId}'."); if (!ModelState.IsValid) { - Load(user); + Load(profile.Email); return Page(); } - var email = await userManager.GetEmailAsync(user); - if (Input.NewEmail == email) + var result = await bus.InvokeAsync( + new RequestEmailChange(userId, Input.NewEmail!), ct); + + if (result.Unchanged) { StatusMessage = "Your email is unchanged."; return RedirectToPage(); } - var userId = user.Id; - var code = await userManager.GenerateChangeEmailTokenAsync(user, Input.NewEmail); - code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code)); var callbackUrl = Url.Page( "/Account/ConfirmEmailChange", pageHandler: null, - values: new { area = "Identity", userId, email = Input.NewEmail, code }, - protocol: Request.Scheme); + values: new { area = "Identity", userId, email = Input.NewEmail, code = result.EncodedCode }, + protocol: Request.Scheme)!; - var endpoint = await sendEndpointProvider.GetSendEndpoint(new Uri("queue:" + nameof(SendChangeEmail))); - await endpoint.Send(new SendChangeEmail(Input.NewEmail, callbackUrl), ct); + await bus.PublishAsync(new SendChangeEmail(Input.NewEmail!, callbackUrl)); StatusMessage = "Confirmation link to change email sent. Please check your email."; return RedirectToPage(); diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ResetAuthenticator.cshtml.cs b/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ResetAuthenticator.cshtml.cs index b8dd441..4f7810c 100644 --- a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ResetAuthenticator.cshtml.cs +++ b/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ResetAuthenticator.cshtml.cs @@ -1,59 +1,34 @@ -using CommentMap.Mvc.Data.Entities; -using Microsoft.AspNetCore.Identity; +using CommentMap.Application.Features.Identity; +using CommentMap.Mvc.Extensions; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; +using Wolverine; namespace CommentMap.Mvc.Areas.Identity.Pages.Account.Manage; -public class ResetAuthenticatorModel : PageModel +public class ResetAuthenticatorModel(IMessageBus bus) : PageModel { - private readonly UserManager _userManager; - private readonly SignInManager _signInManager; - private readonly ILogger _logger; - - public ResetAuthenticatorModel( - UserManager userManager, - SignInManager signInManager, - ILogger logger) - { - _userManager = userManager; - _signInManager = signInManager; - _logger = logger; - } - - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// [TempData] - public string StatusMessage { get; set; } + public string? StatusMessage { get; set; } public async Task OnGet() { - var user = await _userManager.GetUserAsync(User); - if (user == null) - { - return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); - } + var userId = User.FindUserId(); + var status = await bus.InvokeAsync(new GetTwoFactorStatus(userId)); + if (!status.Found) + return NotFound($"Unable to load user with ID '{userId}'."); return Page(); } public async Task OnPostAsync() { - var user = await _userManager.GetUserAsync(User); - if (user == null) - { - return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); - } - - await _userManager.SetTwoFactorEnabledAsync(user, false); - await _userManager.ResetAuthenticatorKeyAsync(user); - _logger.LogInformation("User with ID '{UserId}' has reset their authentication app key.", user.Id); + var userId = User.FindUserId(); + var ok = await bus.InvokeAsync(new ResetAuthenticator(userId)); + if (!ok) + return NotFound($"Unable to load user with ID '{userId}'."); - await _signInManager.RefreshSignInAsync(user); StatusMessage = "Your authenticator app key has been reset, you will need to configure your authenticator app using the new key."; - return RedirectToPage("./EnableAuthenticator"); } } diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/SetPassword.cshtml.cs b/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/SetPassword.cshtml.cs index 0953c70..6907673 100644 --- a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/SetPassword.cshtml.cs +++ b/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/SetPassword.cshtml.cs @@ -1,78 +1,43 @@ using System.ComponentModel.DataAnnotations; -using CommentMap.Mvc.Data.Entities; -using Microsoft.AspNetCore.Identity; +using CommentMap.Application.Features.Identity; +using CommentMap.Application.Models; +using CommentMap.Mvc.Extensions; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; +using Wolverine; namespace CommentMap.Mvc.Areas.Identity.Pages.Account.Manage; -public class SetPasswordModel : PageModel +public class SetPasswordModel(IMessageBus bus) : PageModel { - private readonly UserManager _userManager; - private readonly SignInManager _signInManager; - - public SetPasswordModel( - UserManager userManager, - SignInManager signInManager) - { - _userManager = userManager; - _signInManager = signInManager; - } - - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// [BindProperty] - public InputModel Input { get; set; } + public InputModel Input { get; set; } = null!; - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// [TempData] - public string StatusMessage { get; set; } + public string? StatusMessage { get; set; } - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// public class InputModel { - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// [Required] [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)] [DataType(DataType.Password)] [Display(Name = "New password")] - public string NewPassword { get; set; } + public string NewPassword { get; set; } = null!; - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// [DataType(DataType.Password)] [Display(Name = "Confirm new password")] [Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")] - public string ConfirmPassword { get; set; } + public string ConfirmPassword { get; set; } = null!; } public async Task OnGetAsync() { - var user = await _userManager.GetUserAsync(User); - if (user == null) - { - return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); - } - - var hasPassword = await _userManager.HasPasswordAsync(user); - - if (hasPassword) - { + var userId = User.FindUserId(); + var hasPassword = await bus.InvokeAsync(new HasPassword(userId)); + if (!hasPassword.Found) + return NotFound($"Unable to load user with ID '{userId}'."); + if (hasPassword.HasPassword) return RedirectToPage("./ChangePassword"); - } return Page(); } @@ -80,29 +45,22 @@ public async Task OnGetAsync() public async Task OnPostAsync() { if (!ModelState.IsValid) - { return Page(); - } - var user = await _userManager.GetUserAsync(User); - if (user == null) - { - return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); - } + var userId = User.FindUserId(); + var result = await bus.InvokeAsync(new SetPassword(userId, Input.NewPassword)); - var addPasswordResult = await _userManager.AddPasswordAsync(user, Input.NewPassword); - if (!addPasswordResult.Succeeded) + if (!result.Succeeded) { - foreach (var error in addPasswordResult.Errors) - { + if (result.Errors.Any(e => e.Code == "UserNotFound")) + return NotFound($"Unable to load user with ID '{userId}'."); + + foreach (var error in result.Errors) ModelState.AddModelError(string.Empty, error.Description); - } return Page(); } - await _signInManager.RefreshSignInAsync(user); StatusMessage = "Your password has been set."; - return RedirectToPage(); } } diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/TwoFactorAuthentication.cshtml.cs b/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/TwoFactorAuthentication.cshtml.cs index 584058b..28e7e09 100644 --- a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/TwoFactorAuthentication.cshtml.cs +++ b/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/TwoFactorAuthentication.cshtml.cs @@ -1,81 +1,45 @@ -using CommentMap.Mvc.Data.Entities; -using Microsoft.AspNetCore.Identity; +using CommentMap.Application.Features.Identity; +using CommentMap.Mvc.Extensions; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; +using Wolverine; namespace CommentMap.Mvc.Areas.Identity.Pages.Account.Manage; -public class TwoFactorAuthenticationModel : PageModel +public class TwoFactorAuthenticationModel(IMessageBus bus) : PageModel { - private readonly UserManager _userManager; - private readonly SignInManager _signInManager; - private readonly ILogger _logger; - - public TwoFactorAuthenticationModel( - UserManager userManager, SignInManager signInManager, ILogger logger) - { - _userManager = userManager; - _signInManager = signInManager; - _logger = logger; - } - - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// public bool HasAuthenticator { get; set; } - - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// public int RecoveryCodesLeft { get; set; } - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// [BindProperty] public bool Is2faEnabled { get; set; } - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// public bool IsMachineRemembered { get; set; } - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// [TempData] - public string StatusMessage { get; set; } + public string? StatusMessage { get; set; } public async Task OnGetAsync() { - var user = await _userManager.GetUserAsync(User); - if (user == null) - { - return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); - } - - HasAuthenticator = await _userManager.GetAuthenticatorKeyAsync(user) != null; - Is2faEnabled = await _userManager.GetTwoFactorEnabledAsync(user); - IsMachineRemembered = await _signInManager.IsTwoFactorClientRememberedAsync(user); - RecoveryCodesLeft = await _userManager.CountRecoveryCodesAsync(user); - + var userId = User.FindUserId(); + var status = await bus.InvokeAsync(new GetTwoFactorStatus(userId)); + if (!status.Found) + return NotFound($"Unable to load user with ID '{userId}'."); + + HasAuthenticator = status.HasAuthenticator; + Is2faEnabled = status.Is2faEnabled; + IsMachineRemembered = status.IsMachineRemembered; + RecoveryCodesLeft = status.RecoveryCodesLeft; return Page(); } public async Task OnPostAsync() { - var user = await _userManager.GetUserAsync(User); - if (user == null) - { - return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); - } + var userId = User.FindUserId(); + var ok = await bus.InvokeAsync(new ForgetTwoFactorClient(userId)); + if (!ok) + return NotFound($"Unable to load user with ID '{userId}'."); - await _signInManager.ForgetTwoFactorClientAsync(); StatusMessage = "The current browser has been forgotten. When you login again from this browser you will be prompted for your 2fa code."; return RedirectToPage(); } diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/Register.cshtml.cs b/CommentMap.Mvc/Areas/Identity/Pages/Account/Register.cshtml.cs index 602e5d0..95b930c 100644 --- a/CommentMap.Mvc/Areas/Identity/Pages/Account/Register.cshtml.cs +++ b/CommentMap.Mvc/Areas/Identity/Pages/Account/Register.cshtml.cs @@ -1,164 +1,78 @@ -using CommentMap.Mvc.Data.Entities; +using CommentMap.Application.Entities; +using CommentMap.Application.Features.Identity; using CommentMap.Shared.Messages; -using MassTransit; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; -using Microsoft.AspNetCore.WebUtilities; using System.ComponentModel.DataAnnotations; -using System.Text; +using Wolverine; namespace CommentMap.Mvc.Areas.Identity.Pages.Account; -public class RegisterModel : PageModel +public class RegisterModel(IMessageBus bus, SignInManager signInManager) : PageModel { - private readonly SignInManager _signInManager; - private readonly UserManager _userManager; - private readonly IUserStore _userStore; - private readonly IUserEmailStore _emailStore; - private readonly ISendEndpointProvider _sendEndpointProvider; - - public RegisterModel( - UserManager userManager, - IUserStore userStore, - SignInManager signInManager, - ISendEndpointProvider sendEndpointProvider) - { - _userManager = userManager; - _userStore = userStore; - _emailStore = GetEmailStore(); - _signInManager = signInManager; - _sendEndpointProvider = sendEndpointProvider; - } - - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// [BindProperty] - public InputModel Input { get; set; } + public InputModel Input { get; set; } = null!; - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// [BindProperty(SupportsGet = true)] public string? ReturnUrl { get; set; } - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// - public IList ExternalLogins { get; set; } + public IList ExternalLogins { get; set; } = null!; - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// public class InputModel { - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// [Required] [EmailAddress] [Display(Name = "Email")] - public string Email { get; set; } + public string Email { get; set; } = null!; - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// [Required] [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)] [DataType(DataType.Password)] [Display(Name = "Password")] - public string Password { get; set; } + public string Password { get; set; } = null!; - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// [DataType(DataType.Password)] [Display(Name = "Confirm password")] [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")] - public string ConfirmPassword { get; set; } + public string ConfirmPassword { get; set; } = null!; } - public async Task OnGetAsync() { - ExternalLogins = [.. await _signInManager.GetExternalAuthenticationSchemesAsync()]; + ExternalLogins = [.. await signInManager.GetExternalAuthenticationSchemesAsync()]; } public async Task OnPostAsync(CancellationToken ct) { ReturnUrl ??= Url.Content("~/"); - ExternalLogins = [.. await _signInManager.GetExternalAuthenticationSchemesAsync()]; - if (ModelState.IsValid) - { - var user = CreateUser(); - - await _userStore.SetUserNameAsync(user, Input.Email, ct); - await _emailStore.SetEmailAsync(user, Input.Email, ct); - var result = await _userManager.CreateAsync(user, Input.Password); - - if (result.Succeeded) - { - var userId = user.Id; - var code = await _userManager.GenerateEmailConfirmationTokenAsync(user); - code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code)); - var callbackUrl = Url.Page( - "/Account/ConfirmEmail", - pageHandler: null, - values: new { area = "Identity", userId, code, ReturnUrl }, - protocol: Request.Scheme); + ExternalLogins = [.. await signInManager.GetExternalAuthenticationSchemesAsync()]; + if (!ModelState.IsValid) + return Page(); - var endpoint = await _sendEndpointProvider.GetSendEndpoint(new Uri("queue:" + nameof(SendConfirmEmail))); - await endpoint.Send(new SendConfirmEmail(Input.Email, callbackUrl), ct); + var result = await bus.InvokeAsync( + new RegisterUser(Input.Email, Input.Password), ct); - if (_userManager.Options.SignIn.RequireConfirmedAccount) - { - return RedirectToPage("RegisterConfirmation"); - } - else - { - await _signInManager.SignInAsync(user, isPersistent: false); - return LocalRedirect(ReturnUrl); - } - } + if (!result.Succeeded) + { foreach (var error in result.Errors) - { ModelState.AddModelError(string.Empty, error.Description); - } + return Page(); } - // If we got this far, something failed, redisplay form - return Page(); - } + var callbackUrl = Url.Page( + "/Account/ConfirmEmail", + pageHandler: null, + values: new { area = "Identity", userId = result.UserId, code = result.EncodedEmailConfirmationCode, ReturnUrl }, + protocol: Request.Scheme)!; - private User CreateUser() - { - try - { - return Activator.CreateInstance(); - } - catch - { - throw new InvalidOperationException($"Can't create an instance of '{nameof(User)}'. " + - $"Ensure that '{nameof(User)}' is not an abstract class and has a parameterless constructor, or alternatively " + - $"override the register page in /Areas/Identity/Pages/Account/Register.cshtml"); - } - } + await bus.PublishAsync(new SendConfirmEmail(Input.Email, callbackUrl)); - private IUserEmailStore GetEmailStore() - { - if (!_userManager.SupportsUserEmail) - { - throw new NotSupportedException("The default UI requires a user store with email support."); - } - return (IUserEmailStore)_userStore; + if (result.RequireConfirmedAccount) + return RedirectToPage("RegisterConfirmation"); + + await bus.InvokeAsync(new SignInAfterRegistration(result.UserId!.Value), ct); + return LocalRedirect(ReturnUrl); } } diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/ResendEmailConfirmation.cshtml.cs b/CommentMap.Mvc/Areas/Identity/Pages/Account/ResendEmailConfirmation.cshtml.cs index 7271702..ee03f62 100644 --- a/CommentMap.Mvc/Areas/Identity/Pages/Account/ResendEmailConfirmation.cshtml.cs +++ b/CommentMap.Mvc/Areas/Identity/Pages/Account/ResendEmailConfirmation.cshtml.cs @@ -1,43 +1,27 @@ using System.ComponentModel.DataAnnotations; -using System.Text; -using CommentMap.Mvc.Data.Entities; +using CommentMap.Application.Features.Identity; using CommentMap.Shared.Messages; -using MassTransit; using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; -using Microsoft.AspNetCore.WebUtilities; +using Wolverine; namespace CommentMap.Mvc.Areas.Identity.Pages.Account; [AllowAnonymous] -public class ResendEmailConfirmationModel(UserManager userManager, ISendEndpointProvider sendEndpointProvider) - : PageModel +public class ResendEmailConfirmationModel(IMessageBus bus) : PageModel { [TempData] - public string StatusMessage { get; set; } + public string? StatusMessage { get; set; } - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// [BindProperty] - public InputModel Input { get; set; } + public InputModel Input { get; set; } = null!; - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// public class InputModel { - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// [Required] [EmailAddress] - public string Email { get; set; } + public string Email { get; set; } = null!; } public void OnGet() @@ -47,28 +31,24 @@ public void OnGet() public async Task OnPostAsync(CancellationToken ct) { if (!ModelState.IsValid) - { return Page(); - } - var user = await userManager.FindByEmailAsync(Input.Email); - if (user is null) + var result = await bus.InvokeAsync( + new ResendEmailConfirmation(Input.Email), ct); + + if (!result.UserFound) { ModelState.AddModelError(string.Empty, "Unable to find user by email."); return Page(); } - var userId = user.Id; - var code = await userManager.GenerateEmailConfirmationTokenAsync(user); - code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code)); var callbackUrl = Url.Page( "/Account/ConfirmEmail", pageHandler: null, - values: new { userId, code }, - protocol: Request.Scheme); + values: new { userId = result.UserId, code = result.EncodedCode }, + protocol: Request.Scheme)!; - var endpoint = await sendEndpointProvider.GetSendEndpoint(new Uri("queue:" + nameof(SendConfirmEmail))); - await endpoint.Send(new SendConfirmEmail(Input.Email, callbackUrl), ct); + await bus.PublishAsync(new SendConfirmEmail(Input.Email, callbackUrl)); StatusMessage = "Verification email sent. Please check your email."; return Page(); diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/ResetPassword.cshtml.cs b/CommentMap.Mvc/Areas/Identity/Pages/Account/ResetPassword.cshtml.cs index aaea2cc..bbb4b1b 100644 --- a/CommentMap.Mvc/Areas/Identity/Pages/Account/ResetPassword.cshtml.cs +++ b/CommentMap.Mvc/Areas/Identity/Pages/Account/ResetPassword.cshtml.cs @@ -1,21 +1,16 @@ using System.ComponentModel.DataAnnotations; -using System.Text; -using CommentMap.Mvc.Data.Entities; -using Microsoft.AspNetCore.Identity; +using CommentMap.Application.Features.Identity; +using CommentMap.Application.Models; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; -using Microsoft.AspNetCore.WebUtilities; +using Wolverine; namespace CommentMap.Mvc.Areas.Identity.Pages.Account; -public class ResetPasswordModel(UserManager userManager) : PageModel +public class ResetPasswordModel(IMessageBus bus) : PageModel { - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// [BindProperty] - public InputModel Input { get; set; } + public InputModel Input { get; set; } = null!; [BindProperty(SupportsGet = true)] public string? UserId { get; set; } @@ -23,68 +18,41 @@ public class ResetPasswordModel(UserManager userManager) : PageModel [BindProperty(SupportsGet = true)] public string? Code { get; set; } - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// public class InputModel { - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// [Required] [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)] [DataType(DataType.Password)] - public string Password { get; set; } + public string Password { get; set; } = null!; - /// - /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// [DataType(DataType.Password)] [Display(Name = "Confirm password")] [Compare(otherProperty: nameof(Password), ErrorMessage = "The password and confirmation password do not match.")] - public string ConfirmPassword { get; set; } + public string ConfirmPassword { get; set; } = null!; } public IActionResult OnGet(string? code = null) { if (code is null) - { return BadRequest("A code must be supplied for password reset."); - } - else - { - return Page(); - } + + return Page(); } public async Task OnPostAsync() { if (!ModelState.IsValid) - { return Page(); - } - var user = await userManager.FindByIdAsync(UserId); - if (user is null) - { - // Don't reveal that the user does not exist - return RedirectToPage("./ResetPasswordConfirmation"); - } + var result = await bus.InvokeAsync( + new ResetPassword(UserId!, Code!, Input.Password)); - var code = Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(Code)); - var result = await userManager.ResetPasswordAsync(user, code, Input.Password); if (result.Succeeded) - { return RedirectToPage("./ResetPasswordConfirmation"); - } foreach (var error in result.Errors) - { ModelState.AddModelError(string.Empty, error.Description); - } + return Page(); } } diff --git a/CommentMap.Mvc/CommentMap.Mvc.csproj b/CommentMap.Mvc/CommentMap.Mvc.csproj index 1732cbf..9c6a18b 100644 --- a/CommentMap.Mvc/CommentMap.Mvc.csproj +++ b/CommentMap.Mvc/CommentMap.Mvc.csproj @@ -33,10 +33,17 @@ + + + + + + + diff --git a/CommentMap.Mvc/Data/Entities/Role.cs b/CommentMap.Mvc/Data/Entities/Role.cs deleted file mode 100644 index f757512..0000000 --- a/CommentMap.Mvc/Data/Entities/Role.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Microsoft.AspNetCore.Identity; - -namespace CommentMap.Mvc.Data.Entities; - -public class Role : IdentityRole -{ - -} \ No newline at end of file diff --git a/CommentMap.Mvc/Extensions/DependencyInjection/ServiceCollectionExtensions.cs b/CommentMap.Mvc/Extensions/DependencyInjection/ServiceCollectionExtensions.cs deleted file mode 100644 index a3e31dc..0000000 --- a/CommentMap.Mvc/Extensions/DependencyInjection/ServiceCollectionExtensions.cs +++ /dev/null @@ -1,23 +0,0 @@ -using CommentMap.Mvc.Data; -using Microsoft.EntityFrameworkCore; -using Npgsql; - -namespace CommentMap.Mvc.Extensions.DependencyInjection; - -public static class ServiceCollectionExtensions -{ - public static IHostApplicationBuilder AddCommentMapDbContext(this IHostApplicationBuilder builder) - { - var connectionString = builder.Configuration.GetConnectionString("comment-map"); - - builder.Services - .AddDbContext(options => options.UseNpgsql( - connectionString, - o => o.UseNetTopologySuite())) - .AddDatabaseDeveloperPageExceptionFilter(); - - builder.EnrichNpgsqlDbContext(); - - return builder; - } -} diff --git a/CommentMap.Mvc/Extensions/QueriableExtensions.cs b/CommentMap.Mvc/Extensions/QueriableExtensions.cs deleted file mode 100644 index 67da888..0000000 --- a/CommentMap.Mvc/Extensions/QueriableExtensions.cs +++ /dev/null @@ -1,17 +0,0 @@ -using CommentMap.Mvc.Data.Entities; -using CommentMap.Mvc.Extensions; -using CommentMap.Mvc.Models; - -namespace CommentMap.Mvc.Extensions; - -public static class QueriableExtensions -{ - public static IOrderedQueryable OrderBy(this IQueryable queryable, Order order) - where T : Comment - => order switch - { - Order.CreatedAt => queryable.OrderBy(c => c.Id), - Order.Title => queryable.OrderBy(c => c.Title), - _ => throw new ArgumentOutOfRangeException(nameof(order), order, "Unexpected order value."), - }; -} \ No newline at end of file diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/AddCommentHandler838741630.cs b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/AddCommentHandler838741630.cs new file mode 100644 index 0000000..3c0d405 --- /dev/null +++ b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/AddCommentHandler838741630.cs @@ -0,0 +1,46 @@ +// +#pragma warning disable +using Microsoft.Extensions.DependencyInjection; + +namespace Internal.Generated.WolverineHandlers +{ + // START: AddCommentHandler838741630 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class AddCommentHandler838741630 : Wolverine.Runtime.Handlers.MessageHandler + { + private readonly Microsoft.Extensions.DependencyInjection.IServiceScopeFactory _serviceScopeFactory; + + public AddCommentHandler838741630(Microsoft.Extensions.DependencyInjection.IServiceScopeFactory serviceScopeFactory) + { + _serviceScopeFactory = serviceScopeFactory; + } + + + + public override async System.Threading.Tasks.Task HandleAsync(Wolverine.Runtime.MessageContext context, System.Threading.CancellationToken cancellation) + { + await using var serviceScope = _serviceScopeFactory.CreateAsyncScope(); + + /* + * Dependency: Descriptor: ServiceType: Microsoft.EntityFrameworkCore.DbContextOptions"1[CommentMap.Infrastructure.Data.CommentMapDbContext] Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions.CreateDbContextOptions + * The service registration for Microsoft.EntityFrameworkCore.DbContextOptions is an 'opaque' lambda factory with the Scoped lifetime and requires service location + */ + var commentMapDbContext = Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(serviceScope.ServiceProvider); + // The actual message body + var addComment = (CommentMap.Application.Features.Comments.AddComment)context.Envelope.Message; + + System.Diagnostics.Activity.Current?.SetTag("message.handler", "CommentMap.Application.Features.Comments.AddCommentHandler"); + System.Diagnostics.Activity.Current?.SetTag("handler.type", "CommentMap.Application.Features.Comments.AddCommentHandler"); + + // The actual message execution + await CommentMap.Application.Features.Comments.AddCommentHandler.Handle(addComment, commentMapDbContext, cancellation).ConfigureAwait(false); + + } + + } + + // END: AddCommentHandler838741630 + + +} + diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ChangePasswordHandler702758377.cs b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ChangePasswordHandler702758377.cs new file mode 100644 index 0000000..c94ae5c --- /dev/null +++ b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ChangePasswordHandler702758377.cs @@ -0,0 +1,95 @@ +// +#pragma warning disable +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; + +namespace Internal.Generated.WolverineHandlers +{ + // START: ChangePasswordHandler702758377 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class ChangePasswordHandler702758377 : Wolverine.Runtime.Handlers.MessageHandler + { + private readonly Microsoft.Extensions.DependencyInjection.IServiceScopeFactory _serviceScopeFactory; + private readonly Microsoft.Extensions.Logging.ILogger _loggerForMessage; + + public ChangePasswordHandler702758377(Microsoft.Extensions.DependencyInjection.IServiceScopeFactory serviceScopeFactory, Microsoft.Extensions.Logging.ILogger loggerForMessage) + { + _serviceScopeFactory = serviceScopeFactory; + _loggerForMessage = loggerForMessage; + } + + + + public override async System.Threading.Tasks.Task HandleAsync(Wolverine.Runtime.MessageContext context, System.Threading.CancellationToken cancellation) + { + await using var serviceScope = _serviceScopeFactory.CreateAsyncScope(); + + /* + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + * + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserClaimsPrincipalFactory"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserClaimsPrincipalFactory"2[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + * + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.RoleManager"1[CommentMap.Application.Entities.Role] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.RoleManager"1[CommentMap.Application.Entities.Role] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IRoleStore"1[CommentMap.Application.Entities.Role] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.RoleStore"5[CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + */ + var signInManagerOfUser = Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(serviceScope.ServiceProvider); + + /* + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + */ + var userManagerOfUser = Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(serviceScope.ServiceProvider); + // The actual message body + var changePassword = (CommentMap.Application.Features.Identity.ChangePassword)context.Envelope.Message; + + System.Diagnostics.Activity.Current?.SetTag("message.handler", "CommentMap.Application.Features.Identity.ChangePasswordHandler"); + System.Diagnostics.Activity.Current?.SetTag("handler.type", "CommentMap.Application.Features.Identity.ChangePasswordHandler"); + + // The actual message execution + var outgoing1 = await CommentMap.Application.Features.Identity.ChangePasswordHandler.Handle(changePassword, userManagerOfUser, signInManagerOfUser, _loggerForMessage).ConfigureAwait(false); + + + // Outgoing, cascaded message + await context.EnqueueCascadingAsync(outgoing1).ConfigureAwait(false); + + } + + } + + // END: ChangePasswordHandler702758377 + + +} + diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ConfirmEmailChangeHandler1497850754.cs b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ConfirmEmailChangeHandler1497850754.cs new file mode 100644 index 0000000..13c3da8 --- /dev/null +++ b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ConfirmEmailChangeHandler1497850754.cs @@ -0,0 +1,92 @@ +// +#pragma warning disable +using Microsoft.Extensions.DependencyInjection; + +namespace Internal.Generated.WolverineHandlers +{ + // START: ConfirmEmailChangeHandler1497850754 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class ConfirmEmailChangeHandler1497850754 : Wolverine.Runtime.Handlers.MessageHandler + { + private readonly Microsoft.Extensions.DependencyInjection.IServiceScopeFactory _serviceScopeFactory; + + public ConfirmEmailChangeHandler1497850754(Microsoft.Extensions.DependencyInjection.IServiceScopeFactory serviceScopeFactory) + { + _serviceScopeFactory = serviceScopeFactory; + } + + + + public override async System.Threading.Tasks.Task HandleAsync(Wolverine.Runtime.MessageContext context, System.Threading.CancellationToken cancellation) + { + await using var serviceScope = _serviceScopeFactory.CreateAsyncScope(); + + /* + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + * + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserClaimsPrincipalFactory"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserClaimsPrincipalFactory"2[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + * + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.RoleManager"1[CommentMap.Application.Entities.Role] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.RoleManager"1[CommentMap.Application.Entities.Role] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IRoleStore"1[CommentMap.Application.Entities.Role] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.RoleStore"5[CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + */ + var signInManagerOfUser = Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(serviceScope.ServiceProvider); + + /* + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + */ + var userManagerOfUser = Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(serviceScope.ServiceProvider); + // The actual message body + var confirmEmailChange = (CommentMap.Application.Features.Identity.ConfirmEmailChange)context.Envelope.Message; + + System.Diagnostics.Activity.Current?.SetTag("message.handler", "CommentMap.Application.Features.Identity.ConfirmEmailChangeHandler"); + System.Diagnostics.Activity.Current?.SetTag("handler.type", "CommentMap.Application.Features.Identity.ConfirmEmailChangeHandler"); + + // The actual message execution + var outgoing1 = await CommentMap.Application.Features.Identity.ConfirmEmailChangeHandler.Handle(confirmEmailChange, userManagerOfUser, signInManagerOfUser).ConfigureAwait(false); + + + // Outgoing, cascaded message + await context.EnqueueCascadingAsync(outgoing1).ConfigureAwait(false); + + } + + } + + // END: ConfirmEmailChangeHandler1497850754 + + +} + diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ConfirmEmailHandler55631218.cs b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ConfirmEmailHandler55631218.cs new file mode 100644 index 0000000..e4ba015 --- /dev/null +++ b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ConfirmEmailHandler55631218.cs @@ -0,0 +1,56 @@ +// +#pragma warning disable +using Microsoft.Extensions.DependencyInjection; + +namespace Internal.Generated.WolverineHandlers +{ + // START: ConfirmEmailHandler55631218 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class ConfirmEmailHandler55631218 : Wolverine.Runtime.Handlers.MessageHandler + { + private readonly Microsoft.Extensions.DependencyInjection.IServiceScopeFactory _serviceScopeFactory; + + public ConfirmEmailHandler55631218(Microsoft.Extensions.DependencyInjection.IServiceScopeFactory serviceScopeFactory) + { + _serviceScopeFactory = serviceScopeFactory; + } + + + + public override async System.Threading.Tasks.Task HandleAsync(Wolverine.Runtime.MessageContext context, System.Threading.CancellationToken cancellation) + { + await using var serviceScope = _serviceScopeFactory.CreateAsyncScope(); + + /* + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + */ + var userManagerOfUser = Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(serviceScope.ServiceProvider); + // The actual message body + var confirmEmail = (CommentMap.Application.Features.Identity.ConfirmEmail)context.Envelope.Message; + + System.Diagnostics.Activity.Current?.SetTag("message.handler", "CommentMap.Application.Features.Identity.ConfirmEmailHandler"); + System.Diagnostics.Activity.Current?.SetTag("handler.type", "CommentMap.Application.Features.Identity.ConfirmEmailHandler"); + + // The actual message execution + var outgoing1 = await CommentMap.Application.Features.Identity.ConfirmEmailHandler.Handle(confirmEmail, userManagerOfUser).ConfigureAwait(false); + + + // Outgoing, cascaded message + await context.EnqueueCascadingAsync(outgoing1).ConfigureAwait(false); + + } + + } + + // END: ConfirmEmailHandler55631218 + + +} + diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/CreateExternalUserHandler966620274.cs b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/CreateExternalUserHandler966620274.cs new file mode 100644 index 0000000..5b4f57a --- /dev/null +++ b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/CreateExternalUserHandler966620274.cs @@ -0,0 +1,101 @@ +// +#pragma warning disable +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; + +namespace Internal.Generated.WolverineHandlers +{ + // START: CreateExternalUserHandler966620274 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class CreateExternalUserHandler966620274 : Wolverine.Runtime.Handlers.MessageHandler + { + private readonly Microsoft.Extensions.DependencyInjection.IServiceScopeFactory _serviceScopeFactory; + private readonly Microsoft.Extensions.Logging.ILogger _loggerForMessage; + + public CreateExternalUserHandler966620274(Microsoft.Extensions.DependencyInjection.IServiceScopeFactory serviceScopeFactory, Microsoft.Extensions.Logging.ILogger loggerForMessage) + { + _serviceScopeFactory = serviceScopeFactory; + _loggerForMessage = loggerForMessage; + } + + + + public override async System.Threading.Tasks.Task HandleAsync(Wolverine.Runtime.MessageContext context, System.Threading.CancellationToken cancellation) + { + await using var serviceScope = _serviceScopeFactory.CreateAsyncScope(); + + /* + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + * + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserClaimsPrincipalFactory"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserClaimsPrincipalFactory"2[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + * + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.RoleManager"1[CommentMap.Application.Entities.Role] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.RoleManager"1[CommentMap.Application.Entities.Role] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IRoleStore"1[CommentMap.Application.Entities.Role] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.RoleStore"5[CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + */ + var signInManagerOfUser = Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(serviceScope.ServiceProvider); + + /* + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + */ + var userStoreOfUser = Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(serviceScope.ServiceProvider); + + /* + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + */ + var userManagerOfUser = Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(serviceScope.ServiceProvider); + // The actual message body + var createExternalUser = (CommentMap.Application.Features.Identity.CreateExternalUser)context.Envelope.Message; + + System.Diagnostics.Activity.Current?.SetTag("message.handler", "CommentMap.Application.Features.Identity.CreateExternalUserHandler"); + System.Diagnostics.Activity.Current?.SetTag("handler.type", "CommentMap.Application.Features.Identity.CreateExternalUserHandler"); + + // The actual message execution + var outgoing1 = await CommentMap.Application.Features.Identity.CreateExternalUserHandler.Handle(createExternalUser, userManagerOfUser, userStoreOfUser, signInManagerOfUser, _loggerForMessage, cancellation).ConfigureAwait(false); + + + // Outgoing, cascaded message + await context.EnqueueCascadingAsync(outgoing1).ConfigureAwait(false); + + } + + } + + // END: CreateExternalUserHandler966620274 + + +} + diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/DeleteCommentHandler107828254.cs b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/DeleteCommentHandler107828254.cs new file mode 100644 index 0000000..2eaafe5 --- /dev/null +++ b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/DeleteCommentHandler107828254.cs @@ -0,0 +1,46 @@ +// +#pragma warning disable +using Microsoft.Extensions.DependencyInjection; + +namespace Internal.Generated.WolverineHandlers +{ + // START: DeleteCommentHandler107828254 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class DeleteCommentHandler107828254 : Wolverine.Runtime.Handlers.MessageHandler + { + private readonly Microsoft.Extensions.DependencyInjection.IServiceScopeFactory _serviceScopeFactory; + + public DeleteCommentHandler107828254(Microsoft.Extensions.DependencyInjection.IServiceScopeFactory serviceScopeFactory) + { + _serviceScopeFactory = serviceScopeFactory; + } + + + + public override async System.Threading.Tasks.Task HandleAsync(Wolverine.Runtime.MessageContext context, System.Threading.CancellationToken cancellation) + { + await using var serviceScope = _serviceScopeFactory.CreateAsyncScope(); + + /* + * Dependency: Descriptor: ServiceType: Microsoft.EntityFrameworkCore.DbContextOptions"1[CommentMap.Infrastructure.Data.CommentMapDbContext] Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions.CreateDbContextOptions + * The service registration for Microsoft.EntityFrameworkCore.DbContextOptions is an 'opaque' lambda factory with the Scoped lifetime and requires service location + */ + var commentMapDbContext = Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(serviceScope.ServiceProvider); + // The actual message body + var deleteComment = (CommentMap.Application.Features.Comments.DeleteComment)context.Envelope.Message; + + System.Diagnostics.Activity.Current?.SetTag("message.handler", "CommentMap.Application.Features.Comments.DeleteCommentHandler"); + System.Diagnostics.Activity.Current?.SetTag("handler.type", "CommentMap.Application.Features.Comments.DeleteCommentHandler"); + + // The actual message execution + await CommentMap.Application.Features.Comments.DeleteCommentHandler.Handle(deleteComment, commentMapDbContext, cancellation).ConfigureAwait(false); + + } + + } + + // END: DeleteCommentHandler107828254 + + +} + diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/DeleteProfileHandler1834710062.cs b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/DeleteProfileHandler1834710062.cs new file mode 100644 index 0000000..5532ade --- /dev/null +++ b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/DeleteProfileHandler1834710062.cs @@ -0,0 +1,95 @@ +// +#pragma warning disable +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; + +namespace Internal.Generated.WolverineHandlers +{ + // START: DeleteProfileHandler1834710062 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class DeleteProfileHandler1834710062 : Wolverine.Runtime.Handlers.MessageHandler + { + private readonly Microsoft.Extensions.DependencyInjection.IServiceScopeFactory _serviceScopeFactory; + private readonly Microsoft.Extensions.Logging.ILogger _loggerForMessage; + + public DeleteProfileHandler1834710062(Microsoft.Extensions.DependencyInjection.IServiceScopeFactory serviceScopeFactory, Microsoft.Extensions.Logging.ILogger loggerForMessage) + { + _serviceScopeFactory = serviceScopeFactory; + _loggerForMessage = loggerForMessage; + } + + + + public override async System.Threading.Tasks.Task HandleAsync(Wolverine.Runtime.MessageContext context, System.Threading.CancellationToken cancellation) + { + await using var serviceScope = _serviceScopeFactory.CreateAsyncScope(); + + /* + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + * + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserClaimsPrincipalFactory"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserClaimsPrincipalFactory"2[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + * + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.RoleManager"1[CommentMap.Application.Entities.Role] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.RoleManager"1[CommentMap.Application.Entities.Role] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IRoleStore"1[CommentMap.Application.Entities.Role] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.RoleStore"5[CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + */ + var signInManagerOfUser = Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(serviceScope.ServiceProvider); + + /* + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + */ + var userManagerOfUser = Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(serviceScope.ServiceProvider); + // The actual message body + var deleteProfile = (CommentMap.Application.Features.Identity.DeleteProfile)context.Envelope.Message; + + System.Diagnostics.Activity.Current?.SetTag("message.handler", "CommentMap.Application.Features.Identity.DeleteProfileHandler"); + System.Diagnostics.Activity.Current?.SetTag("handler.type", "CommentMap.Application.Features.Identity.DeleteProfileHandler"); + + // The actual message execution + var outgoing1 = await CommentMap.Application.Features.Identity.DeleteProfileHandler.Handle(deleteProfile, userManagerOfUser, signInManagerOfUser, _loggerForMessage).ConfigureAwait(false); + + + // Outgoing, cascaded message + await context.EnqueueCascadingAsync(outgoing1).ConfigureAwait(false); + + } + + } + + // END: DeleteProfileHandler1834710062 + + +} + diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/Disable2faHandler1923519541.cs b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/Disable2faHandler1923519541.cs new file mode 100644 index 0000000..f1c8c34 --- /dev/null +++ b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/Disable2faHandler1923519541.cs @@ -0,0 +1,59 @@ +// +#pragma warning disable +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; + +namespace Internal.Generated.WolverineHandlers +{ + // START: Disable2faHandler1923519541 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class Disable2faHandler1923519541 : Wolverine.Runtime.Handlers.MessageHandler + { + private readonly Microsoft.Extensions.DependencyInjection.IServiceScopeFactory _serviceScopeFactory; + private readonly Microsoft.Extensions.Logging.ILogger _loggerForMessage; + + public Disable2faHandler1923519541(Microsoft.Extensions.DependencyInjection.IServiceScopeFactory serviceScopeFactory, Microsoft.Extensions.Logging.ILogger loggerForMessage) + { + _serviceScopeFactory = serviceScopeFactory; + _loggerForMessage = loggerForMessage; + } + + + + public override async System.Threading.Tasks.Task HandleAsync(Wolverine.Runtime.MessageContext context, System.Threading.CancellationToken cancellation) + { + await using var serviceScope = _serviceScopeFactory.CreateAsyncScope(); + + /* + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + */ + var userManagerOfUser = Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(serviceScope.ServiceProvider); + // The actual message body + var disable2fa = (CommentMap.Application.Features.Identity.Disable2fa)context.Envelope.Message; + + System.Diagnostics.Activity.Current?.SetTag("message.handler", "CommentMap.Application.Features.Identity.Disable2faHandler"); + System.Diagnostics.Activity.Current?.SetTag("handler.type", "CommentMap.Application.Features.Identity.Disable2faHandler"); + + // The actual message execution + var outgoing1 = await CommentMap.Application.Features.Identity.Disable2faHandler.Handle(disable2fa, userManagerOfUser, _loggerForMessage).ConfigureAwait(false); + + + // Outgoing, cascaded message + await context.EnqueueCascadingAsync(outgoing1).ConfigureAwait(false); + + } + + } + + // END: Disable2faHandler1923519541 + + +} + diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/EnableAuthenticatorHandler897587120.cs b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/EnableAuthenticatorHandler897587120.cs new file mode 100644 index 0000000..6a2d397 --- /dev/null +++ b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/EnableAuthenticatorHandler897587120.cs @@ -0,0 +1,65 @@ +// +#pragma warning disable +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using QRCoder; +using System.Text.Encodings.Web; + +namespace Internal.Generated.WolverineHandlers +{ + // START: EnableAuthenticatorHandler897587120 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class EnableAuthenticatorHandler897587120 : Wolverine.Runtime.Handlers.MessageHandler + { + private readonly Microsoft.Extensions.DependencyInjection.IServiceScopeFactory _serviceScopeFactory; + private readonly Microsoft.Extensions.Logging.ILogger _loggerForMessage; + private readonly QRCoder.QRCodeGenerator _qrCodeGenerator; + private readonly System.Text.Encodings.Web.UrlEncoder _urlEncoder; + + public EnableAuthenticatorHandler897587120(Microsoft.Extensions.DependencyInjection.IServiceScopeFactory serviceScopeFactory, Microsoft.Extensions.Logging.ILogger loggerForMessage, QRCoder.QRCodeGenerator qrCodeGenerator, System.Text.Encodings.Web.UrlEncoder urlEncoder) + { + _serviceScopeFactory = serviceScopeFactory; + _loggerForMessage = loggerForMessage; + _qrCodeGenerator = qrCodeGenerator; + _urlEncoder = urlEncoder; + } + + + + public override async System.Threading.Tasks.Task HandleAsync(Wolverine.Runtime.MessageContext context, System.Threading.CancellationToken cancellation) + { + await using var serviceScope = _serviceScopeFactory.CreateAsyncScope(); + + /* + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + */ + var userManagerOfUser = Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(serviceScope.ServiceProvider); + // The actual message body + var enableAuthenticator = (CommentMap.Application.Features.Identity.EnableAuthenticator)context.Envelope.Message; + + System.Diagnostics.Activity.Current?.SetTag("message.handler", "CommentMap.Application.Features.Identity.EnableAuthenticatorHandler"); + System.Diagnostics.Activity.Current?.SetTag("handler.type", "CommentMap.Application.Features.Identity.EnableAuthenticatorHandler"); + + // The actual message execution + var outgoing1 = await CommentMap.Application.Features.Identity.EnableAuthenticatorHandler.Handle(enableAuthenticator, userManagerOfUser, _loggerForMessage, _urlEncoder, _qrCodeGenerator).ConfigureAwait(false); + + + // Outgoing, cascaded message + await context.EnqueueCascadingAsync(outgoing1).ConfigureAwait(false); + + } + + } + + // END: EnableAuthenticatorHandler897587120 + + +} + diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ExternalLoginSignInHandler1809594924.cs b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ExternalLoginSignInHandler1809594924.cs new file mode 100644 index 0000000..446acb7 --- /dev/null +++ b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ExternalLoginSignInHandler1809594924.cs @@ -0,0 +1,83 @@ +// +#pragma warning disable +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; + +namespace Internal.Generated.WolverineHandlers +{ + // START: ExternalLoginSignInHandler1809594924 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class ExternalLoginSignInHandler1809594924 : Wolverine.Runtime.Handlers.MessageHandler + { + private readonly Microsoft.Extensions.DependencyInjection.IServiceScopeFactory _serviceScopeFactory; + private readonly Microsoft.Extensions.Logging.ILogger _loggerForMessage; + + public ExternalLoginSignInHandler1809594924(Microsoft.Extensions.DependencyInjection.IServiceScopeFactory serviceScopeFactory, Microsoft.Extensions.Logging.ILogger loggerForMessage) + { + _serviceScopeFactory = serviceScopeFactory; + _loggerForMessage = loggerForMessage; + } + + + + public override async System.Threading.Tasks.Task HandleAsync(Wolverine.Runtime.MessageContext context, System.Threading.CancellationToken cancellation) + { + await using var serviceScope = _serviceScopeFactory.CreateAsyncScope(); + + /* + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + * + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserClaimsPrincipalFactory"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserClaimsPrincipalFactory"2[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + * + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.RoleManager"1[CommentMap.Application.Entities.Role] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.RoleManager"1[CommentMap.Application.Entities.Role] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IRoleStore"1[CommentMap.Application.Entities.Role] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.RoleStore"5[CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + */ + var signInManagerOfUser = Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(serviceScope.ServiceProvider); + // The actual message body + var externalLoginSignIn = (CommentMap.Application.Features.Identity.ExternalLoginSignIn)context.Envelope.Message; + + System.Diagnostics.Activity.Current?.SetTag("message.handler", "CommentMap.Application.Features.Identity.ExternalLoginSignInHandler"); + System.Diagnostics.Activity.Current?.SetTag("handler.type", "CommentMap.Application.Features.Identity.ExternalLoginSignInHandler"); + + // The actual message execution + var outgoing1 = await CommentMap.Application.Features.Identity.ExternalLoginSignInHandler.Handle(externalLoginSignIn, signInManagerOfUser, _loggerForMessage).ConfigureAwait(false); + + + // Outgoing, cascaded message + await context.EnqueueCascadingAsync(outgoing1).ConfigureAwait(false); + + } + + } + + // END: ExternalLoginSignInHandler1809594924 + + +} + diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ForgetTwoFactorClientHandler253588197.cs b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ForgetTwoFactorClientHandler253588197.cs new file mode 100644 index 0000000..ffbba9f --- /dev/null +++ b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ForgetTwoFactorClientHandler253588197.cs @@ -0,0 +1,92 @@ +// +#pragma warning disable +using Microsoft.Extensions.DependencyInjection; + +namespace Internal.Generated.WolverineHandlers +{ + // START: ForgetTwoFactorClientHandler253588197 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class ForgetTwoFactorClientHandler253588197 : Wolverine.Runtime.Handlers.MessageHandler + { + private readonly Microsoft.Extensions.DependencyInjection.IServiceScopeFactory _serviceScopeFactory; + + public ForgetTwoFactorClientHandler253588197(Microsoft.Extensions.DependencyInjection.IServiceScopeFactory serviceScopeFactory) + { + _serviceScopeFactory = serviceScopeFactory; + } + + + + public override async System.Threading.Tasks.Task HandleAsync(Wolverine.Runtime.MessageContext context, System.Threading.CancellationToken cancellation) + { + await using var serviceScope = _serviceScopeFactory.CreateAsyncScope(); + + /* + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + * + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserClaimsPrincipalFactory"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserClaimsPrincipalFactory"2[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + * + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.RoleManager"1[CommentMap.Application.Entities.Role] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.RoleManager"1[CommentMap.Application.Entities.Role] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IRoleStore"1[CommentMap.Application.Entities.Role] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.RoleStore"5[CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + */ + var signInManagerOfUser = Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(serviceScope.ServiceProvider); + + /* + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + */ + var userManagerOfUser = Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(serviceScope.ServiceProvider); + // The actual message body + var forgetTwoFactorClient = (CommentMap.Application.Features.Identity.ForgetTwoFactorClient)context.Envelope.Message; + + System.Diagnostics.Activity.Current?.SetTag("message.handler", "CommentMap.Application.Features.Identity.ForgetTwoFactorClientHandler"); + System.Diagnostics.Activity.Current?.SetTag("handler.type", "CommentMap.Application.Features.Identity.ForgetTwoFactorClientHandler"); + + // The actual message execution + var outgoing1 = await CommentMap.Application.Features.Identity.ForgetTwoFactorClientHandler.Handle(forgetTwoFactorClient, userManagerOfUser, signInManagerOfUser).ConfigureAwait(false); + + + // Outgoing, cascaded message + await context.EnqueueCascadingAsync(outgoing1).ConfigureAwait(false); + + } + + } + + // END: ForgetTwoFactorClientHandler253588197 + + +} + diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ForgotPasswordHandler1306123444.cs b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ForgotPasswordHandler1306123444.cs new file mode 100644 index 0000000..37f09c3 --- /dev/null +++ b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ForgotPasswordHandler1306123444.cs @@ -0,0 +1,56 @@ +// +#pragma warning disable +using Microsoft.Extensions.DependencyInjection; + +namespace Internal.Generated.WolverineHandlers +{ + // START: ForgotPasswordHandler1306123444 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class ForgotPasswordHandler1306123444 : Wolverine.Runtime.Handlers.MessageHandler + { + private readonly Microsoft.Extensions.DependencyInjection.IServiceScopeFactory _serviceScopeFactory; + + public ForgotPasswordHandler1306123444(Microsoft.Extensions.DependencyInjection.IServiceScopeFactory serviceScopeFactory) + { + _serviceScopeFactory = serviceScopeFactory; + } + + + + public override async System.Threading.Tasks.Task HandleAsync(Wolverine.Runtime.MessageContext context, System.Threading.CancellationToken cancellation) + { + await using var serviceScope = _serviceScopeFactory.CreateAsyncScope(); + + /* + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + */ + var userManagerOfUser = Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(serviceScope.ServiceProvider); + // The actual message body + var forgotPassword = (CommentMap.Application.Features.Identity.ForgotPassword)context.Envelope.Message; + + System.Diagnostics.Activity.Current?.SetTag("message.handler", "CommentMap.Application.Features.Identity.ForgotPasswordHandler"); + System.Diagnostics.Activity.Current?.SetTag("handler.type", "CommentMap.Application.Features.Identity.ForgotPasswordHandler"); + + // The actual message execution + var outgoing1 = await CommentMap.Application.Features.Identity.ForgotPasswordHandler.Handle(forgotPassword, userManagerOfUser).ConfigureAwait(false); + + + // Outgoing, cascaded message + await context.EnqueueCascadingAsync(outgoing1).ConfigureAwait(false); + + } + + } + + // END: ForgotPasswordHandler1306123444 + + +} + diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/GenerateRecoveryCodesHandler711237032.cs b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/GenerateRecoveryCodesHandler711237032.cs new file mode 100644 index 0000000..ad67d92 --- /dev/null +++ b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/GenerateRecoveryCodesHandler711237032.cs @@ -0,0 +1,59 @@ +// +#pragma warning disable +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; + +namespace Internal.Generated.WolverineHandlers +{ + // START: GenerateRecoveryCodesHandler711237032 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class GenerateRecoveryCodesHandler711237032 : Wolverine.Runtime.Handlers.MessageHandler + { + private readonly Microsoft.Extensions.DependencyInjection.IServiceScopeFactory _serviceScopeFactory; + private readonly Microsoft.Extensions.Logging.ILogger _loggerForMessage; + + public GenerateRecoveryCodesHandler711237032(Microsoft.Extensions.DependencyInjection.IServiceScopeFactory serviceScopeFactory, Microsoft.Extensions.Logging.ILogger loggerForMessage) + { + _serviceScopeFactory = serviceScopeFactory; + _loggerForMessage = loggerForMessage; + } + + + + public override async System.Threading.Tasks.Task HandleAsync(Wolverine.Runtime.MessageContext context, System.Threading.CancellationToken cancellation) + { + await using var serviceScope = _serviceScopeFactory.CreateAsyncScope(); + + /* + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + */ + var userManagerOfUser = Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(serviceScope.ServiceProvider); + // The actual message body + var generateRecoveryCodes = (CommentMap.Application.Features.Identity.GenerateRecoveryCodes)context.Envelope.Message; + + System.Diagnostics.Activity.Current?.SetTag("message.handler", "CommentMap.Application.Features.Identity.GenerateRecoveryCodesHandler"); + System.Diagnostics.Activity.Current?.SetTag("handler.type", "CommentMap.Application.Features.Identity.GenerateRecoveryCodesHandler"); + + // The actual message execution + var outgoing1 = await CommentMap.Application.Features.Identity.GenerateRecoveryCodesHandler.Handle(generateRecoveryCodes, userManagerOfUser, _loggerForMessage).ConfigureAwait(false); + + + // Outgoing, cascaded message + await context.EnqueueCascadingAsync(outgoing1).ConfigureAwait(false); + + } + + } + + // END: GenerateRecoveryCodesHandler711237032 + + +} + diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/GeneratedHandlerRegistry.cs b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/GeneratedHandlerRegistry.cs new file mode 100644 index 0000000..d05c709 --- /dev/null +++ b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/GeneratedHandlerRegistry.cs @@ -0,0 +1,29 @@ +// +#pragma warning disable + +namespace Internal.Generated.WolverineHandlers +{ + // START: GeneratedHandlerRegistry + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class GeneratedHandlerRegistry : Wolverine.Runtime.Handlers.HandlerRegistry + { + + + public override System.Type[] HandlerTypes() + { + return new System.Type[] { typeof(CommentMap.Application.Features.Comments.AddCommentHandler), typeof(CommentMap.Application.Features.Comments.DeleteCommentHandler), typeof(CommentMap.Application.Features.Comments.GetCommentTitleHandler), typeof(CommentMap.Application.Features.Comments.ListCommentsHandler), typeof(CommentMap.Application.Features.Countries.GetCountryHandler), typeof(CommentMap.Application.Features.Identity.ChangePasswordHandler), typeof(CommentMap.Application.Features.Identity.ConfirmEmailChangeHandler), typeof(CommentMap.Application.Features.Identity.ConfirmEmailHandler), typeof(CommentMap.Application.Features.Identity.CreateExternalUserHandler), typeof(CommentMap.Application.Features.Identity.DeleteProfileHandler), typeof(CommentMap.Application.Features.Identity.Disable2faHandler), typeof(CommentMap.Application.Features.Identity.EnableAuthenticatorHandler), typeof(CommentMap.Application.Features.Identity.ExternalLoginSignInHandler), typeof(CommentMap.Application.Features.Identity.ForgetTwoFactorClientHandler), typeof(CommentMap.Application.Features.Identity.ForgotPasswordHandler), typeof(CommentMap.Application.Features.Identity.GenerateRecoveryCodesHandler), typeof(CommentMap.Application.Features.Identity.GetAuthenticatorSetupHandler), typeof(CommentMap.Application.Features.Identity.GetDeleteProfileInfoHandler), typeof(CommentMap.Application.Features.Identity.GetExternalLoginsHandler), typeof(CommentMap.Application.Features.Identity.GetProfileEmailHandler), typeof(CommentMap.Application.Features.Identity.GetTwoFactorStatusHandler), typeof(CommentMap.Application.Features.Identity.HasPasswordHandler), typeof(CommentMap.Application.Features.Identity.LinkExternalLoginHandler), typeof(CommentMap.Application.Features.Identity.LoginUserHandler), typeof(CommentMap.Application.Features.Identity.LoginWith2faHandler), typeof(CommentMap.Application.Features.Identity.LoginWithRecoveryCodeHandler), typeof(CommentMap.Application.Features.Identity.LogoutUserHandler), typeof(CommentMap.Application.Features.Identity.RegisterUserHandler), typeof(CommentMap.Application.Features.Identity.RemoveExternalLoginHandler), typeof(CommentMap.Application.Features.Identity.RequestEmailChangeHandler), typeof(CommentMap.Application.Features.Identity.ResendEmailConfirmationHandler), typeof(CommentMap.Application.Features.Identity.ResetAuthenticatorHandler), typeof(CommentMap.Application.Features.Identity.ResetPasswordHandler), typeof(CommentMap.Application.Features.Identity.SetPasswordHandler), typeof(CommentMap.Application.Features.Identity.SignInAfterRegistrationHandler) }; + } + + + public override System.Type[] MessageTypes() + { + return System.Array.Empty(); + } + + } + + // END: GeneratedHandlerRegistry + + +} + diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetAuthenticatorSetupHandler507613430.cs b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetAuthenticatorSetupHandler507613430.cs new file mode 100644 index 0000000..8f3ca42 --- /dev/null +++ b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetAuthenticatorSetupHandler507613430.cs @@ -0,0 +1,62 @@ +// +#pragma warning disable +using Microsoft.Extensions.DependencyInjection; +using QRCoder; +using System.Text.Encodings.Web; + +namespace Internal.Generated.WolverineHandlers +{ + // START: GetAuthenticatorSetupHandler507613430 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class GetAuthenticatorSetupHandler507613430 : Wolverine.Runtime.Handlers.MessageHandler + { + private readonly Microsoft.Extensions.DependencyInjection.IServiceScopeFactory _serviceScopeFactory; + private readonly QRCoder.QRCodeGenerator _qrCodeGenerator; + private readonly System.Text.Encodings.Web.UrlEncoder _urlEncoder; + + public GetAuthenticatorSetupHandler507613430(Microsoft.Extensions.DependencyInjection.IServiceScopeFactory serviceScopeFactory, QRCoder.QRCodeGenerator qrCodeGenerator, System.Text.Encodings.Web.UrlEncoder urlEncoder) + { + _serviceScopeFactory = serviceScopeFactory; + _qrCodeGenerator = qrCodeGenerator; + _urlEncoder = urlEncoder; + } + + + + public override async System.Threading.Tasks.Task HandleAsync(Wolverine.Runtime.MessageContext context, System.Threading.CancellationToken cancellation) + { + await using var serviceScope = _serviceScopeFactory.CreateAsyncScope(); + + /* + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + */ + var userManagerOfUser = Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(serviceScope.ServiceProvider); + // The actual message body + var getAuthenticatorSetup = (CommentMap.Application.Features.Identity.GetAuthenticatorSetup)context.Envelope.Message; + + System.Diagnostics.Activity.Current?.SetTag("message.handler", "CommentMap.Application.Features.Identity.GetAuthenticatorSetupHandler"); + System.Diagnostics.Activity.Current?.SetTag("handler.type", "CommentMap.Application.Features.Identity.GetAuthenticatorSetupHandler"); + + // The actual message execution + var outgoing1 = await CommentMap.Application.Features.Identity.GetAuthenticatorSetupHandler.Handle(getAuthenticatorSetup, userManagerOfUser, _urlEncoder, _qrCodeGenerator).ConfigureAwait(false); + + + // Outgoing, cascaded message + await context.EnqueueCascadingAsync(outgoing1).ConfigureAwait(false); + + } + + } + + // END: GetAuthenticatorSetupHandler507613430 + + +} + diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetCommentTitleHandler595995119.cs b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetCommentTitleHandler595995119.cs new file mode 100644 index 0000000..f97b511 --- /dev/null +++ b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetCommentTitleHandler595995119.cs @@ -0,0 +1,50 @@ +// +#pragma warning disable +using Microsoft.Extensions.DependencyInjection; + +namespace Internal.Generated.WolverineHandlers +{ + // START: GetCommentTitleHandler595995119 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class GetCommentTitleHandler595995119 : Wolverine.Runtime.Handlers.MessageHandler + { + private readonly Microsoft.Extensions.DependencyInjection.IServiceScopeFactory _serviceScopeFactory; + + public GetCommentTitleHandler595995119(Microsoft.Extensions.DependencyInjection.IServiceScopeFactory serviceScopeFactory) + { + _serviceScopeFactory = serviceScopeFactory; + } + + + + public override async System.Threading.Tasks.Task HandleAsync(Wolverine.Runtime.MessageContext context, System.Threading.CancellationToken cancellation) + { + await using var serviceScope = _serviceScopeFactory.CreateAsyncScope(); + + /* + * Dependency: Descriptor: ServiceType: Microsoft.EntityFrameworkCore.DbContextOptions"1[CommentMap.Infrastructure.Data.CommentMapDbContext] Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions.CreateDbContextOptions + * The service registration for Microsoft.EntityFrameworkCore.DbContextOptions is an 'opaque' lambda factory with the Scoped lifetime and requires service location + */ + var commentMapDbContext = Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(serviceScope.ServiceProvider); + // The actual message body + var getCommentTitle = (CommentMap.Application.Features.Comments.GetCommentTitle)context.Envelope.Message; + + System.Diagnostics.Activity.Current?.SetTag("message.handler", "CommentMap.Application.Features.Comments.GetCommentTitleHandler"); + System.Diagnostics.Activity.Current?.SetTag("handler.type", "CommentMap.Application.Features.Comments.GetCommentTitleHandler"); + + // The actual message execution + var outgoing1 = await CommentMap.Application.Features.Comments.GetCommentTitleHandler.Handle(getCommentTitle, commentMapDbContext, cancellation).ConfigureAwait(false); + + + // Outgoing, cascaded message + await context.EnqueueCascadingAsync(outgoing1).ConfigureAwait(false); + + } + + } + + // END: GetCommentTitleHandler595995119 + + +} + diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetCountryHandler1133281984.cs b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetCountryHandler1133281984.cs new file mode 100644 index 0000000..eceb903 --- /dev/null +++ b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetCountryHandler1133281984.cs @@ -0,0 +1,50 @@ +// +#pragma warning disable +using Microsoft.Extensions.DependencyInjection; + +namespace Internal.Generated.WolverineHandlers +{ + // START: GetCountryHandler1133281984 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class GetCountryHandler1133281984 : Wolverine.Runtime.Handlers.MessageHandler + { + private readonly Microsoft.Extensions.DependencyInjection.IServiceScopeFactory _serviceScopeFactory; + + public GetCountryHandler1133281984(Microsoft.Extensions.DependencyInjection.IServiceScopeFactory serviceScopeFactory) + { + _serviceScopeFactory = serviceScopeFactory; + } + + + + public override async System.Threading.Tasks.Task HandleAsync(Wolverine.Runtime.MessageContext context, System.Threading.CancellationToken cancellation) + { + await using var serviceScope = _serviceScopeFactory.CreateAsyncScope(); + + /* + * Dependency: Descriptor: ServiceType: Microsoft.EntityFrameworkCore.DbContextOptions"1[CommentMap.Infrastructure.Data.CommentMapDbContext] Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions.CreateDbContextOptions + * The service registration for Microsoft.EntityFrameworkCore.DbContextOptions is an 'opaque' lambda factory with the Scoped lifetime and requires service location + */ + var commentMapDbContext = Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(serviceScope.ServiceProvider); + // The actual message body + var getCountry = (CommentMap.Application.Features.Countries.GetCountry)context.Envelope.Message; + + System.Diagnostics.Activity.Current?.SetTag("message.handler", "CommentMap.Application.Features.Countries.GetCountryHandler"); + System.Diagnostics.Activity.Current?.SetTag("handler.type", "CommentMap.Application.Features.Countries.GetCountryHandler"); + + // The actual message execution + var outgoing1 = await CommentMap.Application.Features.Countries.GetCountryHandler.Handle(getCountry, commentMapDbContext, cancellation).ConfigureAwait(false); + + + // Outgoing, cascaded message + await context.EnqueueCascadingAsync(outgoing1).ConfigureAwait(false); + + } + + } + + // END: GetCountryHandler1133281984 + + +} + diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetDeleteProfileInfoHandler900389426.cs b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetDeleteProfileInfoHandler900389426.cs new file mode 100644 index 0000000..9be34da --- /dev/null +++ b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetDeleteProfileInfoHandler900389426.cs @@ -0,0 +1,56 @@ +// +#pragma warning disable +using Microsoft.Extensions.DependencyInjection; + +namespace Internal.Generated.WolverineHandlers +{ + // START: GetDeleteProfileInfoHandler900389426 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class GetDeleteProfileInfoHandler900389426 : Wolverine.Runtime.Handlers.MessageHandler + { + private readonly Microsoft.Extensions.DependencyInjection.IServiceScopeFactory _serviceScopeFactory; + + public GetDeleteProfileInfoHandler900389426(Microsoft.Extensions.DependencyInjection.IServiceScopeFactory serviceScopeFactory) + { + _serviceScopeFactory = serviceScopeFactory; + } + + + + public override async System.Threading.Tasks.Task HandleAsync(Wolverine.Runtime.MessageContext context, System.Threading.CancellationToken cancellation) + { + await using var serviceScope = _serviceScopeFactory.CreateAsyncScope(); + + /* + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + */ + var userManagerOfUser = Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(serviceScope.ServiceProvider); + // The actual message body + var getDeleteProfileInfo = (CommentMap.Application.Features.Identity.GetDeleteProfileInfo)context.Envelope.Message; + + System.Diagnostics.Activity.Current?.SetTag("message.handler", "CommentMap.Application.Features.Identity.GetDeleteProfileInfoHandler"); + System.Diagnostics.Activity.Current?.SetTag("handler.type", "CommentMap.Application.Features.Identity.GetDeleteProfileInfoHandler"); + + // The actual message execution + var outgoing1 = await CommentMap.Application.Features.Identity.GetDeleteProfileInfoHandler.Handle(getDeleteProfileInfo, userManagerOfUser).ConfigureAwait(false); + + + // Outgoing, cascaded message + await context.EnqueueCascadingAsync(outgoing1).ConfigureAwait(false); + + } + + } + + // END: GetDeleteProfileInfoHandler900389426 + + +} + diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetExternalLoginsHandler199405825.cs b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetExternalLoginsHandler199405825.cs new file mode 100644 index 0000000..828a9d3 --- /dev/null +++ b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetExternalLoginsHandler199405825.cs @@ -0,0 +1,98 @@ +// +#pragma warning disable +using Microsoft.Extensions.DependencyInjection; + +namespace Internal.Generated.WolverineHandlers +{ + // START: GetExternalLoginsHandler199405825 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class GetExternalLoginsHandler199405825 : Wolverine.Runtime.Handlers.MessageHandler + { + private readonly Microsoft.Extensions.DependencyInjection.IServiceScopeFactory _serviceScopeFactory; + + public GetExternalLoginsHandler199405825(Microsoft.Extensions.DependencyInjection.IServiceScopeFactory serviceScopeFactory) + { + _serviceScopeFactory = serviceScopeFactory; + } + + + + public override async System.Threading.Tasks.Task HandleAsync(Wolverine.Runtime.MessageContext context, System.Threading.CancellationToken cancellation) + { + await using var serviceScope = _serviceScopeFactory.CreateAsyncScope(); + + /* + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + */ + var userStoreOfUser = Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(serviceScope.ServiceProvider); + + /* + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + * + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserClaimsPrincipalFactory"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserClaimsPrincipalFactory"2[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + * + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.RoleManager"1[CommentMap.Application.Entities.Role] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.RoleManager"1[CommentMap.Application.Entities.Role] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IRoleStore"1[CommentMap.Application.Entities.Role] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.RoleStore"5[CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + */ + var signInManagerOfUser = Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(serviceScope.ServiceProvider); + + /* + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + */ + var userManagerOfUser = Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(serviceScope.ServiceProvider); + // The actual message body + var getExternalLogins = (CommentMap.Application.Features.Identity.GetExternalLogins)context.Envelope.Message; + + System.Diagnostics.Activity.Current?.SetTag("message.handler", "CommentMap.Application.Features.Identity.GetExternalLoginsHandler"); + System.Diagnostics.Activity.Current?.SetTag("handler.type", "CommentMap.Application.Features.Identity.GetExternalLoginsHandler"); + + // The actual message execution + var outgoing1 = await CommentMap.Application.Features.Identity.GetExternalLoginsHandler.Handle(getExternalLogins, userManagerOfUser, signInManagerOfUser, userStoreOfUser, cancellation).ConfigureAwait(false); + + + // Outgoing, cascaded message + await context.EnqueueCascadingAsync(outgoing1).ConfigureAwait(false); + + } + + } + + // END: GetExternalLoginsHandler199405825 + + +} + diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetProfileEmailHandler1046567855.cs b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetProfileEmailHandler1046567855.cs new file mode 100644 index 0000000..d2ff988 --- /dev/null +++ b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetProfileEmailHandler1046567855.cs @@ -0,0 +1,56 @@ +// +#pragma warning disable +using Microsoft.Extensions.DependencyInjection; + +namespace Internal.Generated.WolverineHandlers +{ + // START: GetProfileEmailHandler1046567855 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class GetProfileEmailHandler1046567855 : Wolverine.Runtime.Handlers.MessageHandler + { + private readonly Microsoft.Extensions.DependencyInjection.IServiceScopeFactory _serviceScopeFactory; + + public GetProfileEmailHandler1046567855(Microsoft.Extensions.DependencyInjection.IServiceScopeFactory serviceScopeFactory) + { + _serviceScopeFactory = serviceScopeFactory; + } + + + + public override async System.Threading.Tasks.Task HandleAsync(Wolverine.Runtime.MessageContext context, System.Threading.CancellationToken cancellation) + { + await using var serviceScope = _serviceScopeFactory.CreateAsyncScope(); + + /* + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + */ + var userManagerOfUser = Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(serviceScope.ServiceProvider); + // The actual message body + var getProfileEmail = (CommentMap.Application.Features.Identity.GetProfileEmail)context.Envelope.Message; + + System.Diagnostics.Activity.Current?.SetTag("message.handler", "CommentMap.Application.Features.Identity.GetProfileEmailHandler"); + System.Diagnostics.Activity.Current?.SetTag("handler.type", "CommentMap.Application.Features.Identity.GetProfileEmailHandler"); + + // The actual message execution + var outgoing1 = await CommentMap.Application.Features.Identity.GetProfileEmailHandler.Handle(getProfileEmail, userManagerOfUser).ConfigureAwait(false); + + + // Outgoing, cascaded message + await context.EnqueueCascadingAsync(outgoing1).ConfigureAwait(false); + + } + + } + + // END: GetProfileEmailHandler1046567855 + + +} + diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetTwoFactorStatusHandler1213804985.cs b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetTwoFactorStatusHandler1213804985.cs new file mode 100644 index 0000000..ea953ef --- /dev/null +++ b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetTwoFactorStatusHandler1213804985.cs @@ -0,0 +1,92 @@ +// +#pragma warning disable +using Microsoft.Extensions.DependencyInjection; + +namespace Internal.Generated.WolverineHandlers +{ + // START: GetTwoFactorStatusHandler1213804985 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class GetTwoFactorStatusHandler1213804985 : Wolverine.Runtime.Handlers.MessageHandler + { + private readonly Microsoft.Extensions.DependencyInjection.IServiceScopeFactory _serviceScopeFactory; + + public GetTwoFactorStatusHandler1213804985(Microsoft.Extensions.DependencyInjection.IServiceScopeFactory serviceScopeFactory) + { + _serviceScopeFactory = serviceScopeFactory; + } + + + + public override async System.Threading.Tasks.Task HandleAsync(Wolverine.Runtime.MessageContext context, System.Threading.CancellationToken cancellation) + { + await using var serviceScope = _serviceScopeFactory.CreateAsyncScope(); + + /* + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + * + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserClaimsPrincipalFactory"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserClaimsPrincipalFactory"2[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + * + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.RoleManager"1[CommentMap.Application.Entities.Role] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.RoleManager"1[CommentMap.Application.Entities.Role] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IRoleStore"1[CommentMap.Application.Entities.Role] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.RoleStore"5[CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + */ + var signInManagerOfUser = Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(serviceScope.ServiceProvider); + + /* + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + */ + var userManagerOfUser = Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(serviceScope.ServiceProvider); + // The actual message body + var getTwoFactorStatus = (CommentMap.Application.Features.Identity.GetTwoFactorStatus)context.Envelope.Message; + + System.Diagnostics.Activity.Current?.SetTag("message.handler", "CommentMap.Application.Features.Identity.GetTwoFactorStatusHandler"); + System.Diagnostics.Activity.Current?.SetTag("handler.type", "CommentMap.Application.Features.Identity.GetTwoFactorStatusHandler"); + + // The actual message execution + var outgoing1 = await CommentMap.Application.Features.Identity.GetTwoFactorStatusHandler.Handle(getTwoFactorStatus, userManagerOfUser, signInManagerOfUser).ConfigureAwait(false); + + + // Outgoing, cascaded message + await context.EnqueueCascadingAsync(outgoing1).ConfigureAwait(false); + + } + + } + + // END: GetTwoFactorStatusHandler1213804985 + + +} + diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/HasPasswordHandler1751871263.cs b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/HasPasswordHandler1751871263.cs new file mode 100644 index 0000000..4a9804f --- /dev/null +++ b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/HasPasswordHandler1751871263.cs @@ -0,0 +1,56 @@ +// +#pragma warning disable +using Microsoft.Extensions.DependencyInjection; + +namespace Internal.Generated.WolverineHandlers +{ + // START: HasPasswordHandler1751871263 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class HasPasswordHandler1751871263 : Wolverine.Runtime.Handlers.MessageHandler + { + private readonly Microsoft.Extensions.DependencyInjection.IServiceScopeFactory _serviceScopeFactory; + + public HasPasswordHandler1751871263(Microsoft.Extensions.DependencyInjection.IServiceScopeFactory serviceScopeFactory) + { + _serviceScopeFactory = serviceScopeFactory; + } + + + + public override async System.Threading.Tasks.Task HandleAsync(Wolverine.Runtime.MessageContext context, System.Threading.CancellationToken cancellation) + { + await using var serviceScope = _serviceScopeFactory.CreateAsyncScope(); + + /* + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + */ + var userManagerOfUser = Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(serviceScope.ServiceProvider); + // The actual message body + var hasPassword = (CommentMap.Application.Features.Identity.HasPassword)context.Envelope.Message; + + System.Diagnostics.Activity.Current?.SetTag("message.handler", "CommentMap.Application.Features.Identity.HasPasswordHandler"); + System.Diagnostics.Activity.Current?.SetTag("handler.type", "CommentMap.Application.Features.Identity.HasPasswordHandler"); + + // The actual message execution + var outgoing1 = await CommentMap.Application.Features.Identity.HasPasswordHandler.Handle(hasPassword, userManagerOfUser).ConfigureAwait(false); + + + // Outgoing, cascaded message + await context.EnqueueCascadingAsync(outgoing1).ConfigureAwait(false); + + } + + } + + // END: HasPasswordHandler1751871263 + + +} + diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/LinkExternalLoginHandler251495890.cs b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/LinkExternalLoginHandler251495890.cs new file mode 100644 index 0000000..726762f --- /dev/null +++ b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/LinkExternalLoginHandler251495890.cs @@ -0,0 +1,92 @@ +// +#pragma warning disable +using Microsoft.Extensions.DependencyInjection; + +namespace Internal.Generated.WolverineHandlers +{ + // START: LinkExternalLoginHandler251495890 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class LinkExternalLoginHandler251495890 : Wolverine.Runtime.Handlers.MessageHandler + { + private readonly Microsoft.Extensions.DependencyInjection.IServiceScopeFactory _serviceScopeFactory; + + public LinkExternalLoginHandler251495890(Microsoft.Extensions.DependencyInjection.IServiceScopeFactory serviceScopeFactory) + { + _serviceScopeFactory = serviceScopeFactory; + } + + + + public override async System.Threading.Tasks.Task HandleAsync(Wolverine.Runtime.MessageContext context, System.Threading.CancellationToken cancellation) + { + await using var serviceScope = _serviceScopeFactory.CreateAsyncScope(); + + /* + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + * + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserClaimsPrincipalFactory"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserClaimsPrincipalFactory"2[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + * + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.RoleManager"1[CommentMap.Application.Entities.Role] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.RoleManager"1[CommentMap.Application.Entities.Role] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IRoleStore"1[CommentMap.Application.Entities.Role] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.RoleStore"5[CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + */ + var signInManagerOfUser = Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(serviceScope.ServiceProvider); + + /* + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + */ + var userManagerOfUser = Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(serviceScope.ServiceProvider); + // The actual message body + var linkExternalLogin = (CommentMap.Application.Features.Identity.LinkExternalLogin)context.Envelope.Message; + + System.Diagnostics.Activity.Current?.SetTag("message.handler", "CommentMap.Application.Features.Identity.LinkExternalLoginHandler"); + System.Diagnostics.Activity.Current?.SetTag("handler.type", "CommentMap.Application.Features.Identity.LinkExternalLoginHandler"); + + // The actual message execution + var outgoing1 = await CommentMap.Application.Features.Identity.LinkExternalLoginHandler.Handle(linkExternalLogin, userManagerOfUser, signInManagerOfUser).ConfigureAwait(false); + + + // Outgoing, cascaded message + await context.EnqueueCascadingAsync(outgoing1).ConfigureAwait(false); + + } + + } + + // END: LinkExternalLoginHandler251495890 + + +} + diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ListCommentsHandler488515704.cs b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ListCommentsHandler488515704.cs new file mode 100644 index 0000000..0e6dcc8 --- /dev/null +++ b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ListCommentsHandler488515704.cs @@ -0,0 +1,50 @@ +// +#pragma warning disable +using Microsoft.Extensions.DependencyInjection; + +namespace Internal.Generated.WolverineHandlers +{ + // START: ListCommentsHandler488515704 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class ListCommentsHandler488515704 : Wolverine.Runtime.Handlers.MessageHandler + { + private readonly Microsoft.Extensions.DependencyInjection.IServiceScopeFactory _serviceScopeFactory; + + public ListCommentsHandler488515704(Microsoft.Extensions.DependencyInjection.IServiceScopeFactory serviceScopeFactory) + { + _serviceScopeFactory = serviceScopeFactory; + } + + + + public override async System.Threading.Tasks.Task HandleAsync(Wolverine.Runtime.MessageContext context, System.Threading.CancellationToken cancellation) + { + await using var serviceScope = _serviceScopeFactory.CreateAsyncScope(); + + /* + * Dependency: Descriptor: ServiceType: Microsoft.EntityFrameworkCore.DbContextOptions"1[CommentMap.Infrastructure.Data.CommentMapDbContext] Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions.CreateDbContextOptions + * The service registration for Microsoft.EntityFrameworkCore.DbContextOptions is an 'opaque' lambda factory with the Scoped lifetime and requires service location + */ + var commentMapDbContext = Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(serviceScope.ServiceProvider); + // The actual message body + var listComments = (CommentMap.Application.Features.Comments.ListComments)context.Envelope.Message; + + System.Diagnostics.Activity.Current?.SetTag("message.handler", "CommentMap.Application.Features.Comments.ListCommentsHandler"); + System.Diagnostics.Activity.Current?.SetTag("handler.type", "CommentMap.Application.Features.Comments.ListCommentsHandler"); + + // The actual message execution + var outgoing1 = await CommentMap.Application.Features.Comments.ListCommentsHandler.Handle(listComments, commentMapDbContext, cancellation).ConfigureAwait(false); + + + // Outgoing, cascaded message + await context.EnqueueCascadingAsync(outgoing1).ConfigureAwait(false); + + } + + } + + // END: ListCommentsHandler488515704 + + +} + diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/LoginUserHandler1789921628.cs b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/LoginUserHandler1789921628.cs new file mode 100644 index 0000000..eae523a --- /dev/null +++ b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/LoginUserHandler1789921628.cs @@ -0,0 +1,83 @@ +// +#pragma warning disable +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; + +namespace Internal.Generated.WolverineHandlers +{ + // START: LoginUserHandler1789921628 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class LoginUserHandler1789921628 : Wolverine.Runtime.Handlers.MessageHandler + { + private readonly Microsoft.Extensions.DependencyInjection.IServiceScopeFactory _serviceScopeFactory; + private readonly Microsoft.Extensions.Logging.ILogger _loggerForMessage; + + public LoginUserHandler1789921628(Microsoft.Extensions.DependencyInjection.IServiceScopeFactory serviceScopeFactory, Microsoft.Extensions.Logging.ILogger loggerForMessage) + { + _serviceScopeFactory = serviceScopeFactory; + _loggerForMessage = loggerForMessage; + } + + + + public override async System.Threading.Tasks.Task HandleAsync(Wolverine.Runtime.MessageContext context, System.Threading.CancellationToken cancellation) + { + await using var serviceScope = _serviceScopeFactory.CreateAsyncScope(); + + /* + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + * + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserClaimsPrincipalFactory"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserClaimsPrincipalFactory"2[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + * + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.RoleManager"1[CommentMap.Application.Entities.Role] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.RoleManager"1[CommentMap.Application.Entities.Role] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IRoleStore"1[CommentMap.Application.Entities.Role] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.RoleStore"5[CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + */ + var signInManagerOfUser = Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(serviceScope.ServiceProvider); + // The actual message body + var loginUser = (CommentMap.Application.Features.Identity.LoginUser)context.Envelope.Message; + + System.Diagnostics.Activity.Current?.SetTag("message.handler", "CommentMap.Application.Features.Identity.LoginUserHandler"); + System.Diagnostics.Activity.Current?.SetTag("handler.type", "CommentMap.Application.Features.Identity.LoginUserHandler"); + + // The actual message execution + var outgoing1 = await CommentMap.Application.Features.Identity.LoginUserHandler.Handle(loginUser, signInManagerOfUser, _loggerForMessage).ConfigureAwait(false); + + + // Outgoing, cascaded message + await context.EnqueueCascadingAsync(outgoing1).ConfigureAwait(false); + + } + + } + + // END: LoginUserHandler1789921628 + + +} + diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/LoginWith2faHandler292869486.cs b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/LoginWith2faHandler292869486.cs new file mode 100644 index 0000000..f84a595 --- /dev/null +++ b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/LoginWith2faHandler292869486.cs @@ -0,0 +1,83 @@ +// +#pragma warning disable +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; + +namespace Internal.Generated.WolverineHandlers +{ + // START: LoginWith2faHandler292869486 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class LoginWith2faHandler292869486 : Wolverine.Runtime.Handlers.MessageHandler + { + private readonly Microsoft.Extensions.DependencyInjection.IServiceScopeFactory _serviceScopeFactory; + private readonly Microsoft.Extensions.Logging.ILogger _loggerForMessage; + + public LoginWith2faHandler292869486(Microsoft.Extensions.DependencyInjection.IServiceScopeFactory serviceScopeFactory, Microsoft.Extensions.Logging.ILogger loggerForMessage) + { + _serviceScopeFactory = serviceScopeFactory; + _loggerForMessage = loggerForMessage; + } + + + + public override async System.Threading.Tasks.Task HandleAsync(Wolverine.Runtime.MessageContext context, System.Threading.CancellationToken cancellation) + { + await using var serviceScope = _serviceScopeFactory.CreateAsyncScope(); + + /* + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + * + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserClaimsPrincipalFactory"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserClaimsPrincipalFactory"2[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + * + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.RoleManager"1[CommentMap.Application.Entities.Role] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.RoleManager"1[CommentMap.Application.Entities.Role] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IRoleStore"1[CommentMap.Application.Entities.Role] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.RoleStore"5[CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + */ + var signInManagerOfUser = Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(serviceScope.ServiceProvider); + // The actual message body + var loginWith2fa = (CommentMap.Application.Features.Identity.LoginWith2fa)context.Envelope.Message; + + System.Diagnostics.Activity.Current?.SetTag("message.handler", "CommentMap.Application.Features.Identity.LoginWith2faHandler"); + System.Diagnostics.Activity.Current?.SetTag("handler.type", "CommentMap.Application.Features.Identity.LoginWith2faHandler"); + + // The actual message execution + var outgoing1 = await CommentMap.Application.Features.Identity.LoginWith2faHandler.Handle(loginWith2fa, signInManagerOfUser, _loggerForMessage).ConfigureAwait(false); + + + // Outgoing, cascaded message + await context.EnqueueCascadingAsync(outgoing1).ConfigureAwait(false); + + } + + } + + // END: LoginWith2faHandler292869486 + + +} + diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/LoginWithRecoveryCodeHandler277354287.cs b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/LoginWithRecoveryCodeHandler277354287.cs new file mode 100644 index 0000000..04f900e --- /dev/null +++ b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/LoginWithRecoveryCodeHandler277354287.cs @@ -0,0 +1,83 @@ +// +#pragma warning disable +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; + +namespace Internal.Generated.WolverineHandlers +{ + // START: LoginWithRecoveryCodeHandler277354287 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class LoginWithRecoveryCodeHandler277354287 : Wolverine.Runtime.Handlers.MessageHandler + { + private readonly Microsoft.Extensions.DependencyInjection.IServiceScopeFactory _serviceScopeFactory; + private readonly Microsoft.Extensions.Logging.ILogger _loggerForMessage; + + public LoginWithRecoveryCodeHandler277354287(Microsoft.Extensions.DependencyInjection.IServiceScopeFactory serviceScopeFactory, Microsoft.Extensions.Logging.ILogger loggerForMessage) + { + _serviceScopeFactory = serviceScopeFactory; + _loggerForMessage = loggerForMessage; + } + + + + public override async System.Threading.Tasks.Task HandleAsync(Wolverine.Runtime.MessageContext context, System.Threading.CancellationToken cancellation) + { + await using var serviceScope = _serviceScopeFactory.CreateAsyncScope(); + + /* + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + * + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserClaimsPrincipalFactory"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserClaimsPrincipalFactory"2[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + * + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.RoleManager"1[CommentMap.Application.Entities.Role] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.RoleManager"1[CommentMap.Application.Entities.Role] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IRoleStore"1[CommentMap.Application.Entities.Role] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.RoleStore"5[CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + */ + var signInManagerOfUser = Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(serviceScope.ServiceProvider); + // The actual message body + var loginWithRecoveryCode = (CommentMap.Application.Features.Identity.LoginWithRecoveryCode)context.Envelope.Message; + + System.Diagnostics.Activity.Current?.SetTag("message.handler", "CommentMap.Application.Features.Identity.LoginWithRecoveryCodeHandler"); + System.Diagnostics.Activity.Current?.SetTag("handler.type", "CommentMap.Application.Features.Identity.LoginWithRecoveryCodeHandler"); + + // The actual message execution + var outgoing1 = await CommentMap.Application.Features.Identity.LoginWithRecoveryCodeHandler.Handle(loginWithRecoveryCode, signInManagerOfUser, _loggerForMessage).ConfigureAwait(false); + + + // Outgoing, cascaded message + await context.EnqueueCascadingAsync(outgoing1).ConfigureAwait(false); + + } + + } + + // END: LoginWithRecoveryCodeHandler277354287 + + +} + diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/LogoutUserHandler132148485.cs b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/LogoutUserHandler132148485.cs new file mode 100644 index 0000000..428642f --- /dev/null +++ b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/LogoutUserHandler132148485.cs @@ -0,0 +1,79 @@ +// +#pragma warning disable +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; + +namespace Internal.Generated.WolverineHandlers +{ + // START: LogoutUserHandler132148485 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class LogoutUserHandler132148485 : Wolverine.Runtime.Handlers.MessageHandler + { + private readonly Microsoft.Extensions.DependencyInjection.IServiceScopeFactory _serviceScopeFactory; + private readonly Microsoft.Extensions.Logging.ILogger _loggerForMessage; + + public LogoutUserHandler132148485(Microsoft.Extensions.DependencyInjection.IServiceScopeFactory serviceScopeFactory, Microsoft.Extensions.Logging.ILogger loggerForMessage) + { + _serviceScopeFactory = serviceScopeFactory; + _loggerForMessage = loggerForMessage; + } + + + + public override async System.Threading.Tasks.Task HandleAsync(Wolverine.Runtime.MessageContext context, System.Threading.CancellationToken cancellation) + { + await using var serviceScope = _serviceScopeFactory.CreateAsyncScope(); + + /* + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + * + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserClaimsPrincipalFactory"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserClaimsPrincipalFactory"2[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + * + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.RoleManager"1[CommentMap.Application.Entities.Role] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.RoleManager"1[CommentMap.Application.Entities.Role] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IRoleStore"1[CommentMap.Application.Entities.Role] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.RoleStore"5[CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + */ + var signInManagerOfUser = Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(serviceScope.ServiceProvider); + // The actual message body + var logoutUser = (CommentMap.Application.Features.Identity.LogoutUser)context.Envelope.Message; + + System.Diagnostics.Activity.Current?.SetTag("message.handler", "CommentMap.Application.Features.Identity.LogoutUserHandler"); + System.Diagnostics.Activity.Current?.SetTag("handler.type", "CommentMap.Application.Features.Identity.LogoutUserHandler"); + + // The actual message execution + await CommentMap.Application.Features.Identity.LogoutUserHandler.Handle(logoutUser, signInManagerOfUser, _loggerForMessage).ConfigureAwait(false); + + } + + } + + // END: LogoutUserHandler132148485 + + +} + diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/RegisterUserHandler1265692392.cs b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/RegisterUserHandler1265692392.cs new file mode 100644 index 0000000..d537c2c --- /dev/null +++ b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/RegisterUserHandler1265692392.cs @@ -0,0 +1,62 @@ +// +#pragma warning disable +using Microsoft.Extensions.DependencyInjection; + +namespace Internal.Generated.WolverineHandlers +{ + // START: RegisterUserHandler1265692392 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class RegisterUserHandler1265692392 : Wolverine.Runtime.Handlers.MessageHandler + { + private readonly Microsoft.Extensions.DependencyInjection.IServiceScopeFactory _serviceScopeFactory; + + public RegisterUserHandler1265692392(Microsoft.Extensions.DependencyInjection.IServiceScopeFactory serviceScopeFactory) + { + _serviceScopeFactory = serviceScopeFactory; + } + + + + public override async System.Threading.Tasks.Task HandleAsync(Wolverine.Runtime.MessageContext context, System.Threading.CancellationToken cancellation) + { + await using var serviceScope = _serviceScopeFactory.CreateAsyncScope(); + + /* + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + */ + var userStoreOfUser = Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(serviceScope.ServiceProvider); + + /* + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + */ + var userManagerOfUser = Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(serviceScope.ServiceProvider); + // The actual message body + var registerUser = (CommentMap.Application.Features.Identity.RegisterUser)context.Envelope.Message; + + System.Diagnostics.Activity.Current?.SetTag("message.handler", "CommentMap.Application.Features.Identity.RegisterUserHandler"); + System.Diagnostics.Activity.Current?.SetTag("handler.type", "CommentMap.Application.Features.Identity.RegisterUserHandler"); + + // The actual message execution + var outgoing1 = await CommentMap.Application.Features.Identity.RegisterUserHandler.Handle(registerUser, userManagerOfUser, userStoreOfUser, cancellation).ConfigureAwait(false); + + + // Outgoing, cascaded message + await context.EnqueueCascadingAsync(outgoing1).ConfigureAwait(false); + + } + + } + + // END: RegisterUserHandler1265692392 + + +} + diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/RemoveExternalLoginHandler62493602.cs b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/RemoveExternalLoginHandler62493602.cs new file mode 100644 index 0000000..f481f8d --- /dev/null +++ b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/RemoveExternalLoginHandler62493602.cs @@ -0,0 +1,92 @@ +// +#pragma warning disable +using Microsoft.Extensions.DependencyInjection; + +namespace Internal.Generated.WolverineHandlers +{ + // START: RemoveExternalLoginHandler62493602 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class RemoveExternalLoginHandler62493602 : Wolverine.Runtime.Handlers.MessageHandler + { + private readonly Microsoft.Extensions.DependencyInjection.IServiceScopeFactory _serviceScopeFactory; + + public RemoveExternalLoginHandler62493602(Microsoft.Extensions.DependencyInjection.IServiceScopeFactory serviceScopeFactory) + { + _serviceScopeFactory = serviceScopeFactory; + } + + + + public override async System.Threading.Tasks.Task HandleAsync(Wolverine.Runtime.MessageContext context, System.Threading.CancellationToken cancellation) + { + await using var serviceScope = _serviceScopeFactory.CreateAsyncScope(); + + /* + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + * + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserClaimsPrincipalFactory"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserClaimsPrincipalFactory"2[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + * + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.RoleManager"1[CommentMap.Application.Entities.Role] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.RoleManager"1[CommentMap.Application.Entities.Role] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IRoleStore"1[CommentMap.Application.Entities.Role] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.RoleStore"5[CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + */ + var signInManagerOfUser = Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(serviceScope.ServiceProvider); + + /* + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + */ + var userManagerOfUser = Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(serviceScope.ServiceProvider); + // The actual message body + var removeExternalLogin = (CommentMap.Application.Features.Identity.RemoveExternalLogin)context.Envelope.Message; + + System.Diagnostics.Activity.Current?.SetTag("message.handler", "CommentMap.Application.Features.Identity.RemoveExternalLoginHandler"); + System.Diagnostics.Activity.Current?.SetTag("handler.type", "CommentMap.Application.Features.Identity.RemoveExternalLoginHandler"); + + // The actual message execution + var outgoing1 = await CommentMap.Application.Features.Identity.RemoveExternalLoginHandler.Handle(removeExternalLogin, userManagerOfUser, signInManagerOfUser).ConfigureAwait(false); + + + // Outgoing, cascaded message + await context.EnqueueCascadingAsync(outgoing1).ConfigureAwait(false); + + } + + } + + // END: RemoveExternalLoginHandler62493602 + + +} + diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/RequestEmailChangeHandler172865511.cs b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/RequestEmailChangeHandler172865511.cs new file mode 100644 index 0000000..b4bd985 --- /dev/null +++ b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/RequestEmailChangeHandler172865511.cs @@ -0,0 +1,56 @@ +// +#pragma warning disable +using Microsoft.Extensions.DependencyInjection; + +namespace Internal.Generated.WolverineHandlers +{ + // START: RequestEmailChangeHandler172865511 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class RequestEmailChangeHandler172865511 : Wolverine.Runtime.Handlers.MessageHandler + { + private readonly Microsoft.Extensions.DependencyInjection.IServiceScopeFactory _serviceScopeFactory; + + public RequestEmailChangeHandler172865511(Microsoft.Extensions.DependencyInjection.IServiceScopeFactory serviceScopeFactory) + { + _serviceScopeFactory = serviceScopeFactory; + } + + + + public override async System.Threading.Tasks.Task HandleAsync(Wolverine.Runtime.MessageContext context, System.Threading.CancellationToken cancellation) + { + await using var serviceScope = _serviceScopeFactory.CreateAsyncScope(); + + /* + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + */ + var userManagerOfUser = Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(serviceScope.ServiceProvider); + // The actual message body + var requestEmailChange = (CommentMap.Application.Features.Identity.RequestEmailChange)context.Envelope.Message; + + System.Diagnostics.Activity.Current?.SetTag("message.handler", "CommentMap.Application.Features.Identity.RequestEmailChangeHandler"); + System.Diagnostics.Activity.Current?.SetTag("handler.type", "CommentMap.Application.Features.Identity.RequestEmailChangeHandler"); + + // The actual message execution + var outgoing1 = await CommentMap.Application.Features.Identity.RequestEmailChangeHandler.Handle(requestEmailChange, userManagerOfUser).ConfigureAwait(false); + + + // Outgoing, cascaded message + await context.EnqueueCascadingAsync(outgoing1).ConfigureAwait(false); + + } + + } + + // END: RequestEmailChangeHandler172865511 + + +} + diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ResendEmailConfirmationHandler19836290.cs b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ResendEmailConfirmationHandler19836290.cs new file mode 100644 index 0000000..82eeb88 --- /dev/null +++ b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ResendEmailConfirmationHandler19836290.cs @@ -0,0 +1,56 @@ +// +#pragma warning disable +using Microsoft.Extensions.DependencyInjection; + +namespace Internal.Generated.WolverineHandlers +{ + // START: ResendEmailConfirmationHandler19836290 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class ResendEmailConfirmationHandler19836290 : Wolverine.Runtime.Handlers.MessageHandler + { + private readonly Microsoft.Extensions.DependencyInjection.IServiceScopeFactory _serviceScopeFactory; + + public ResendEmailConfirmationHandler19836290(Microsoft.Extensions.DependencyInjection.IServiceScopeFactory serviceScopeFactory) + { + _serviceScopeFactory = serviceScopeFactory; + } + + + + public override async System.Threading.Tasks.Task HandleAsync(Wolverine.Runtime.MessageContext context, System.Threading.CancellationToken cancellation) + { + await using var serviceScope = _serviceScopeFactory.CreateAsyncScope(); + + /* + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + */ + var userManagerOfUser = Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(serviceScope.ServiceProvider); + // The actual message body + var resendEmailConfirmation = (CommentMap.Application.Features.Identity.ResendEmailConfirmation)context.Envelope.Message; + + System.Diagnostics.Activity.Current?.SetTag("message.handler", "CommentMap.Application.Features.Identity.ResendEmailConfirmationHandler"); + System.Diagnostics.Activity.Current?.SetTag("handler.type", "CommentMap.Application.Features.Identity.ResendEmailConfirmationHandler"); + + // The actual message execution + var outgoing1 = await CommentMap.Application.Features.Identity.ResendEmailConfirmationHandler.Handle(resendEmailConfirmation, userManagerOfUser).ConfigureAwait(false); + + + // Outgoing, cascaded message + await context.EnqueueCascadingAsync(outgoing1).ConfigureAwait(false); + + } + + } + + // END: ResendEmailConfirmationHandler19836290 + + +} + diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ResetAuthenticatorHandler25524780.cs b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ResetAuthenticatorHandler25524780.cs new file mode 100644 index 0000000..777b3b6 --- /dev/null +++ b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ResetAuthenticatorHandler25524780.cs @@ -0,0 +1,95 @@ +// +#pragma warning disable +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; + +namespace Internal.Generated.WolverineHandlers +{ + // START: ResetAuthenticatorHandler25524780 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class ResetAuthenticatorHandler25524780 : Wolverine.Runtime.Handlers.MessageHandler + { + private readonly Microsoft.Extensions.DependencyInjection.IServiceScopeFactory _serviceScopeFactory; + private readonly Microsoft.Extensions.Logging.ILogger _loggerForMessage; + + public ResetAuthenticatorHandler25524780(Microsoft.Extensions.DependencyInjection.IServiceScopeFactory serviceScopeFactory, Microsoft.Extensions.Logging.ILogger loggerForMessage) + { + _serviceScopeFactory = serviceScopeFactory; + _loggerForMessage = loggerForMessage; + } + + + + public override async System.Threading.Tasks.Task HandleAsync(Wolverine.Runtime.MessageContext context, System.Threading.CancellationToken cancellation) + { + await using var serviceScope = _serviceScopeFactory.CreateAsyncScope(); + + /* + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + * + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserClaimsPrincipalFactory"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserClaimsPrincipalFactory"2[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + * + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.RoleManager"1[CommentMap.Application.Entities.Role] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.RoleManager"1[CommentMap.Application.Entities.Role] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IRoleStore"1[CommentMap.Application.Entities.Role] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.RoleStore"5[CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + */ + var signInManagerOfUser = Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(serviceScope.ServiceProvider); + + /* + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + */ + var userManagerOfUser = Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(serviceScope.ServiceProvider); + // The actual message body + var resetAuthenticator = (CommentMap.Application.Features.Identity.ResetAuthenticator)context.Envelope.Message; + + System.Diagnostics.Activity.Current?.SetTag("message.handler", "CommentMap.Application.Features.Identity.ResetAuthenticatorHandler"); + System.Diagnostics.Activity.Current?.SetTag("handler.type", "CommentMap.Application.Features.Identity.ResetAuthenticatorHandler"); + + // The actual message execution + var outgoing1 = await CommentMap.Application.Features.Identity.ResetAuthenticatorHandler.Handle(resetAuthenticator, userManagerOfUser, signInManagerOfUser, _loggerForMessage).ConfigureAwait(false); + + + // Outgoing, cascaded message + await context.EnqueueCascadingAsync(outgoing1).ConfigureAwait(false); + + } + + } + + // END: ResetAuthenticatorHandler25524780 + + +} + diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ResetPasswordHandler433488700.cs b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ResetPasswordHandler433488700.cs new file mode 100644 index 0000000..cd26f2b --- /dev/null +++ b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ResetPasswordHandler433488700.cs @@ -0,0 +1,56 @@ +// +#pragma warning disable +using Microsoft.Extensions.DependencyInjection; + +namespace Internal.Generated.WolverineHandlers +{ + // START: ResetPasswordHandler433488700 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class ResetPasswordHandler433488700 : Wolverine.Runtime.Handlers.MessageHandler + { + private readonly Microsoft.Extensions.DependencyInjection.IServiceScopeFactory _serviceScopeFactory; + + public ResetPasswordHandler433488700(Microsoft.Extensions.DependencyInjection.IServiceScopeFactory serviceScopeFactory) + { + _serviceScopeFactory = serviceScopeFactory; + } + + + + public override async System.Threading.Tasks.Task HandleAsync(Wolverine.Runtime.MessageContext context, System.Threading.CancellationToken cancellation) + { + await using var serviceScope = _serviceScopeFactory.CreateAsyncScope(); + + /* + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + */ + var userManagerOfUser = Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(serviceScope.ServiceProvider); + // The actual message body + var resetPassword = (CommentMap.Application.Features.Identity.ResetPassword)context.Envelope.Message; + + System.Diagnostics.Activity.Current?.SetTag("message.handler", "CommentMap.Application.Features.Identity.ResetPasswordHandler"); + System.Diagnostics.Activity.Current?.SetTag("handler.type", "CommentMap.Application.Features.Identity.ResetPasswordHandler"); + + // The actual message execution + var outgoing1 = await CommentMap.Application.Features.Identity.ResetPasswordHandler.Handle(resetPassword, userManagerOfUser).ConfigureAwait(false); + + + // Outgoing, cascaded message + await context.EnqueueCascadingAsync(outgoing1).ConfigureAwait(false); + + } + + } + + // END: ResetPasswordHandler433488700 + + +} + diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/SetPasswordHandler836449791.cs b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/SetPasswordHandler836449791.cs new file mode 100644 index 0000000..da1f5e2 --- /dev/null +++ b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/SetPasswordHandler836449791.cs @@ -0,0 +1,92 @@ +// +#pragma warning disable +using Microsoft.Extensions.DependencyInjection; + +namespace Internal.Generated.WolverineHandlers +{ + // START: SetPasswordHandler836449791 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class SetPasswordHandler836449791 : Wolverine.Runtime.Handlers.MessageHandler + { + private readonly Microsoft.Extensions.DependencyInjection.IServiceScopeFactory _serviceScopeFactory; + + public SetPasswordHandler836449791(Microsoft.Extensions.DependencyInjection.IServiceScopeFactory serviceScopeFactory) + { + _serviceScopeFactory = serviceScopeFactory; + } + + + + public override async System.Threading.Tasks.Task HandleAsync(Wolverine.Runtime.MessageContext context, System.Threading.CancellationToken cancellation) + { + await using var serviceScope = _serviceScopeFactory.CreateAsyncScope(); + + /* + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + * + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserClaimsPrincipalFactory"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserClaimsPrincipalFactory"2[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + * + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.RoleManager"1[CommentMap.Application.Entities.Role] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.RoleManager"1[CommentMap.Application.Entities.Role] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IRoleStore"1[CommentMap.Application.Entities.Role] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.RoleStore"5[CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + */ + var signInManagerOfUser = Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(serviceScope.ServiceProvider); + + /* + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + */ + var userManagerOfUser = Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(serviceScope.ServiceProvider); + // The actual message body + var setPassword = (CommentMap.Application.Features.Identity.SetPassword)context.Envelope.Message; + + System.Diagnostics.Activity.Current?.SetTag("message.handler", "CommentMap.Application.Features.Identity.SetPasswordHandler"); + System.Diagnostics.Activity.Current?.SetTag("handler.type", "CommentMap.Application.Features.Identity.SetPasswordHandler"); + + // The actual message execution + var outgoing1 = await CommentMap.Application.Features.Identity.SetPasswordHandler.Handle(setPassword, userManagerOfUser, signInManagerOfUser).ConfigureAwait(false); + + + // Outgoing, cascaded message + await context.EnqueueCascadingAsync(outgoing1).ConfigureAwait(false); + + } + + } + + // END: SetPasswordHandler836449791 + + +} + diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/SignInAfterRegistrationHandler2047984407.cs b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/SignInAfterRegistrationHandler2047984407.cs new file mode 100644 index 0000000..9a73301 --- /dev/null +++ b/CommentMap.Mvc/Internal/Generated/WolverineHandlers/SignInAfterRegistrationHandler2047984407.cs @@ -0,0 +1,88 @@ +// +#pragma warning disable +using Microsoft.Extensions.DependencyInjection; + +namespace Internal.Generated.WolverineHandlers +{ + // START: SignInAfterRegistrationHandler2047984407 + [global::System.CodeDom.Compiler.GeneratedCode("JasperFx", "1.0.0")] + public sealed class SignInAfterRegistrationHandler2047984407 : Wolverine.Runtime.Handlers.MessageHandler + { + private readonly Microsoft.Extensions.DependencyInjection.IServiceScopeFactory _serviceScopeFactory; + + public SignInAfterRegistrationHandler2047984407(Microsoft.Extensions.DependencyInjection.IServiceScopeFactory serviceScopeFactory) + { + _serviceScopeFactory = serviceScopeFactory; + } + + + + public override async System.Threading.Tasks.Task HandleAsync(Wolverine.Runtime.MessageContext context, System.Threading.CancellationToken cancellation) + { + await using var serviceScope = _serviceScopeFactory.CreateAsyncScope(); + + /* + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + * + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserClaimsPrincipalFactory"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserClaimsPrincipalFactory"2[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.UserManager"1[CommentMap.Application.Entities.User] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + * + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.RoleManager"1[CommentMap.Application.Entities.Role] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.RoleManager"1[CommentMap.Application.Entities.Role] + * + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IRoleStore"1[CommentMap.Application.Entities.Role] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.RoleStore"5[CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + */ + var signInManagerOfUser = Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(serviceScope.ServiceProvider); + + /* + * Dependency: Descriptor: ServiceType: Microsoft.AspNetCore.Identity.IUserStore"1[CommentMap.Application.Entities.User] Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore"10[CommentMap.Application.Entities.User,CommentMap.Application.Entities.Role,CommentMap.Infrastructure.Data.CommentMapDbContext,System.Guid,Microsoft.AspNetCore.Identity.IdentityUserClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserRole"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserLogin"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserToken"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityRoleClaim"1[System.Guid],Microsoft.AspNetCore.Identity.IdentityUserPasskey"1[System.Guid]] + * + * Dependency: Descriptor: ServiceType: CommentMap.Infrastructure.Data.CommentMapDbContext Lifetime: Scoped ImplementationFactory: Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions+<>c__10"2.b__10_1 + * The service registration for CommentMap.Infrastructure.Data.CommentMapDbContext is an 'opaque' lambda factory with the Scoped lifetime and requires service location + * + * + * Dependency: Descriptor: ServiceType: System.IServiceProvider Lifetime: Scoped ImplementationType: Microsoft.Extensions.DependencyInjection.ServiceDescriptor + * Your code is directly using IServiceProvider + */ + var userManagerOfUser = Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService>(serviceScope.ServiceProvider); + // The actual message body + var signInAfterRegistration = (CommentMap.Application.Features.Identity.SignInAfterRegistration)context.Envelope.Message; + + System.Diagnostics.Activity.Current?.SetTag("message.handler", "CommentMap.Application.Features.Identity.SignInAfterRegistrationHandler"); + System.Diagnostics.Activity.Current?.SetTag("handler.type", "CommentMap.Application.Features.Identity.SignInAfterRegistrationHandler"); + + // The actual message execution + await CommentMap.Application.Features.Identity.SignInAfterRegistrationHandler.Handle(signInAfterRegistration, userManagerOfUser, signInManagerOfUser).ConfigureAwait(false); + + } + + } + + // END: SignInAfterRegistrationHandler2047984407 + + +} + diff --git a/CommentMap.Mvc/Models/AddNewCommentDto.cs b/CommentMap.Mvc/Models/AddNewCommentDto.cs deleted file mode 100644 index 84922f2..0000000 --- a/CommentMap.Mvc/Models/AddNewCommentDto.cs +++ /dev/null @@ -1,3 +0,0 @@ -namespace CommentMap.Mvc.Models; - -public record AddNewCommentDto(Guid UserId, string Title, string Text, double Longitude, double Latitude); diff --git a/CommentMap.Mvc/Models/AddNewCommentInput.cs b/CommentMap.Mvc/Models/AddNewCommentInput.cs index 6f780e6..9293d2e 100644 --- a/CommentMap.Mvc/Models/AddNewCommentInput.cs +++ b/CommentMap.Mvc/Models/AddNewCommentInput.cs @@ -12,6 +12,6 @@ public class AddNewCommentInput [Required] [StringLength(250)] public string? Text { get; init; } - + public required LocationViewModel Location { get; init; } } diff --git a/CommentMap.Mvc/Models/GetAllCommentsDto.cs b/CommentMap.Mvc/Models/GetAllCommentsDto.cs deleted file mode 100644 index 3af14b2..0000000 --- a/CommentMap.Mvc/Models/GetAllCommentsDto.cs +++ /dev/null @@ -1,3 +0,0 @@ -namespace CommentMap.Mvc.Models; - -public record GetAllCommentsDto(Guid UserId, Order Order); diff --git a/CommentMap.Mvc/Pages/Comments/Add.cshtml.cs b/CommentMap.Mvc/Pages/Comments/Add.cshtml.cs index 43a3c5b..ffe8399 100644 --- a/CommentMap.Mvc/Pages/Comments/Add.cshtml.cs +++ b/CommentMap.Mvc/Pages/Comments/Add.cshtml.cs @@ -1,15 +1,16 @@ +using CommentMap.Application.Features.Comments; using CommentMap.Mvc.Extensions; using CommentMap.Mvc.Models; -using CommentMap.Mvc.Services; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using System.Globalization; +using Wolverine; namespace CommentMap.Mvc.Pages.Comments; [Authorize] -public class AddModel(IAddCommentService addCommentService) : PageModel +public class AddModel(IMessageBus bus) : PageModel { [BindProperty] public required AddNewCommentInput Input { get; init; } @@ -27,9 +28,12 @@ public async Task OnPostAsync(CancellationToken cancellationToken) } var userId = User.FindUserId(); - var addCommentDto = new AddNewCommentDto(userId, Input.Title!, Input.Text!, Input.Location.Longitude!.Value, Input.Location.Latitude!.Value); - - await addCommentService.AddAsync(addCommentDto, cancellationToken); + await bus.InvokeAsync(new AddComment( + userId, + Input.Title!, + Input.Text!, + Input.Location.Longitude!.Value, + Input.Location.Latitude!.Value), cancellationToken); return RedirectToPage("/Comments/Index", new { SelectedOrder }); } diff --git a/CommentMap.Mvc/Pages/Comments/ConfirmDelete.cshtml.cs b/CommentMap.Mvc/Pages/Comments/ConfirmDelete.cshtml.cs index 8a89512..2138f60 100644 --- a/CommentMap.Mvc/Pages/Comments/ConfirmDelete.cshtml.cs +++ b/CommentMap.Mvc/Pages/Comments/ConfirmDelete.cshtml.cs @@ -1,10 +1,13 @@ -using CommentMap.Mvc.Services; +using CommentMap.Application.Features.Comments; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; +using Wolverine; namespace CommentMap.Mvc.Pages.Comments; -public class ConfirmDeleteModel(IConfirmDeleteService confirmDeleteService, IDeleteCommentService deleteCommentService) : PageModel +[Authorize] +public class ConfirmDeleteModel(IMessageBus bus) : PageModel { public string? Title { get; set; } @@ -16,13 +19,13 @@ public class ConfirmDeleteModel(IConfirmDeleteService confirmDeleteService, IDel public async Task OnGetAsync(CancellationToken cancellationToken) { - Title = await confirmDeleteService.GetCommentTitleAsync(Id, cancellationToken); + Title = await bus.InvokeAsync(new GetCommentTitle(Id), cancellationToken); return Page(); } public async Task OnPostAsync(CancellationToken cancellationToken) { - await deleteCommentService.DeleteCommentAsync(Id, cancellationToken); + await bus.InvokeAsync(new DeleteComment(Id), cancellationToken); return RedirectToPage("/Comments/Index", new { SelectedOrder }); } } diff --git a/CommentMap.Mvc/Pages/Comments/Index.cshtml b/CommentMap.Mvc/Pages/Comments/Index.cshtml index d7fc385..fef0858 100644 --- a/CommentMap.Mvc/Pages/Comments/Index.cshtml +++ b/CommentMap.Mvc/Pages/Comments/Index.cshtml @@ -1,5 +1,4 @@ @page -@using CommentMap.Mvc.Models @model IndexModel @{ ViewData["Title"] = "My comments"; diff --git a/CommentMap.Mvc/Pages/Comments/Index.cshtml.cs b/CommentMap.Mvc/Pages/Comments/Index.cshtml.cs index 856abf7..97f9944 100644 --- a/CommentMap.Mvc/Pages/Comments/Index.cshtml.cs +++ b/CommentMap.Mvc/Pages/Comments/Index.cshtml.cs @@ -1,15 +1,16 @@ -using CommentMap.Mvc.Extensions; -using CommentMap.Mvc.Models; -using CommentMap.Mvc.Services; +using CommentMap.Application.Features.Comments; +using CommentMap.Application.Models; +using CommentMap.Mvc.Extensions; using CommentMap.Mvc.ViewModels; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; +using Wolverine; namespace CommentMap.Mvc.Pages.Comments; [Authorize] -public class IndexModel(IListCommentsService listCommentsService) : PageModel +public class IndexModel(IMessageBus bus) : PageModel { public List? Comments { get; private set; } @@ -19,8 +20,16 @@ public class IndexModel(IListCommentsService listCommentsService) : PageModel public async Task OnGetAsync(CancellationToken cancellationToken) { var userId = User.FindUserId(); - var dto = new GetAllCommentsDto(userId, SelectedOrder); - Comments = await listCommentsService.GetAllUserComments(dto, cancellationToken); + var items = await bus.InvokeAsync>( + new ListComments(userId, SelectedOrder), cancellationToken); + + Comments = [.. items.Select(c => new CommentCardViewModel( + c.Id, + new LocationViewModel { Longitude = c.Longitude, Latitude = c.Latitude }, + c.Title, + c.Text, + c.CreatedAt))]; + return Page(); } } diff --git a/CommentMap.Mvc/Pages/Countries/Index.cshtml.cs b/CommentMap.Mvc/Pages/Countries/Index.cshtml.cs index 499043a..681392a 100644 --- a/CommentMap.Mvc/Pages/Countries/Index.cshtml.cs +++ b/CommentMap.Mvc/Pages/Countries/Index.cshtml.cs @@ -1,17 +1,20 @@ -using CommentMap.Mvc.Services; +using CommentMap.Application.Features.Countries; +using CommentMap.Application.Models; using CommentMap.Mvc.ViewModels; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using System.ComponentModel.DataAnnotations; +using Wolverine; namespace CommentMap.Mvc.Pages.Countries; -public class IndexModel(IGetCountryViewModelService getCountryViewModelService) : PageModel +public class IndexModel(IMessageBus bus) : PageModel { [BindProperty(SupportsGet = true)] [Required(ErrorMessage = "ISO 3166-1 alpha-3 code required.")] [StringLength(maximumLength: 3, MinimumLength = 3, ErrorMessage = "ISO 3166-1 alpha-3 code must contains 3 letters.")] public string? ISO3Code { get; set; } + public CountryViewModel? Country { get; private set; } public async Task OnGetAsync(CancellationToken cancellationToken) @@ -21,7 +24,19 @@ public async Task OnGetAsync(CancellationToken cancellationToken) return Page(); } - Country = await getCountryViewModelService.GetCountryViewModelAsync(ISO3Code!, cancellationToken); + var dto = await bus.InvokeAsync(new GetCountry(ISO3Code!), cancellationToken); + if (dto is not null) + { + Country = new CountryViewModel + { + ISO3Code = dto.ISO3Code, + ISO2Code = dto.ISO2Code, + Name = dto.Name, + RegionName = dto.RegionName, + SubregionName = dto.SubregionName, + }; + } + return Page(); } } diff --git a/CommentMap.Mvc/Pages/_ViewImports.cshtml b/CommentMap.Mvc/Pages/_ViewImports.cshtml index 365815a..a2dcccc 100644 --- a/CommentMap.Mvc/Pages/_ViewImports.cshtml +++ b/CommentMap.Mvc/Pages/_ViewImports.cshtml @@ -1,6 +1,7 @@ @using Microsoft.AspNetCore.Identity @using CommentMap.Mvc -@using CommentMap.Mvc.Data +@using CommentMap.Mvc.ViewModels +@using CommentMap.Application.Models @namespace CommentMap.Mvc.Pages @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers @addTagHelper *, CommentMap.Mvc diff --git a/CommentMap.Mvc/Program.cs b/CommentMap.Mvc/Program.cs index d5846c1..a0921ad 100644 --- a/CommentMap.Mvc/Program.cs +++ b/CommentMap.Mvc/Program.cs @@ -1,9 +1,5 @@ -using CommentMap.Mvc.Data; -using CommentMap.Mvc.Data.Entities; -using CommentMap.Mvc.Extensions.DependencyInjection; -using CommentMap.Mvc.Services; -using MassTransit; -using Microsoft.AspNetCore.Identity; +using CommentMap.Application.Features.Comments; +using CommentMap.Infrastructure.DependencyInjection; using CommentMap.Shared.Messages; using JasperFx; using JasperFx.CodeGeneration; @@ -16,7 +12,6 @@ builder.AddServiceDefaults(); -builder.AddCommentMapDbContext(); builder.Host.UseWolverine(opts => { opts.CodeGeneration.TypeLoadMode = TypeLoadMode.Static; @@ -33,14 +28,6 @@ builder.AddInfrastructure(); -builder.Services - .AddIdentity(options => - { - options.Stores.MaxLengthForKeys = 128; - options.SignIn.RequireConfirmedAccount = true; - }) - .AddDefaultTokenProviders() - .AddEntityFrameworkStores(); builder.Services.ConfigureApplicationCookie(options => { options.LoginPath = "/Identity/Account/Login"; @@ -55,27 +42,7 @@ googleOptions.ClientSecret = builder.Configuration["Authentication:Google:ClientSecret"]; }); builder.Services.AddSingleton(); -builder.Services.AddSingleton(); -builder.Services.AddScoped(); -builder.Services.AddScoped(); -builder.Services.AddScoped(); -builder.Services.AddScoped(); -builder.Services.AddScoped(); -builder.Services.AddScoped(); -builder.Services.AddScoped(); - - -var mvcBuilder = builder.Services.AddRazorPages(); -builder.Services.AddMassTransit(x => -{ - x.UsingRabbitMq((ctx, cfg) => - { - var configuration = ctx.GetRequiredService(); - var host = configuration.GetConnectionString("messaging"); - cfg.Host(host); - }); -}); builder.Services.AddRazorPages(); var app = builder.Build(); diff --git a/CommentMap.Mvc/Services/AddCommentService.cs b/CommentMap.Mvc/Services/AddCommentService.cs deleted file mode 100644 index 15dd3d1..0000000 --- a/CommentMap.Mvc/Services/AddCommentService.cs +++ /dev/null @@ -1,17 +0,0 @@ -using CommentMap.Mvc.Data; -using CommentMap.Mvc.Models; - -namespace CommentMap.Mvc.Services; - -public class AddCommentService(ICommentMapDbContext dbContext, ICommentFactory commentFactory) - : IAddCommentService -{ - public async Task AddAsync(AddNewCommentDto addNewCommentDto, CancellationToken cancellationToken) - { - var comment = await commentFactory.CreateAsync(addNewCommentDto, cancellationToken); - - dbContext.Comments.Add(comment); - - await dbContext.SaveChangesAsync(cancellationToken); - } -} diff --git a/CommentMap.Mvc/Services/CommentFactory.cs b/CommentMap.Mvc/Services/CommentFactory.cs deleted file mode 100644 index 00285cf..0000000 --- a/CommentMap.Mvc/Services/CommentFactory.cs +++ /dev/null @@ -1,27 +0,0 @@ -using CommentMap.Mvc.Data.Entities; -using CommentMap.Mvc.Models; -using NetTopologySuite.Geometries; - -namespace CommentMap.Mvc.Services; - -public class CommentFactory(IGuessCountryService guessCountryService) : ICommentFactory -{ - public async Task CreateAsync(AddNewCommentDto addNewCommentDto, CancellationToken cancellationToken = default) - { - var point = new Point(addNewCommentDto.Longitude, addNewCommentDto.Latitude) { SRID = 3857 }; - var iso3Code = await guessCountryService.GetCountryCodeAsync(point, cancellationToken); - var id = Guid.CreateVersion7(); - var createdAt = DateTime.UtcNow; - - return new Comment - { - Id = id, - UserId = addNewCommentDto.UserId, - Location = point, - Title = addNewCommentDto.Title, - Text = addNewCommentDto.Text, - CreatedAt = createdAt, - ISO3CodeCountry = iso3Code, - }; - } -} diff --git a/CommentMap.Mvc/Services/ConfirmDeleteService.cs b/CommentMap.Mvc/Services/ConfirmDeleteService.cs deleted file mode 100644 index 0fd25ef..0000000 --- a/CommentMap.Mvc/Services/ConfirmDeleteService.cs +++ /dev/null @@ -1,17 +0,0 @@ -using CommentMap.Mvc.Data; -using Microsoft.EntityFrameworkCore; - -namespace CommentMap.Mvc.Services; - -public class ConfirmDeleteService(ICommentMapDbContext dbContext) : IConfirmDeleteService -{ - public async Task GetCommentTitleAsync(Guid id, CancellationToken cancellationToken) - { - var title = await dbContext.Comments - .AsNoTracking() - .Where(c => c.Id == id) - .Select(c => c.Title) - .FirstOrDefaultAsync(cancellationToken); - return title; - } -} diff --git a/CommentMap.Mvc/Services/DeleteCommentService.cs b/CommentMap.Mvc/Services/DeleteCommentService.cs deleted file mode 100644 index 6730f21..0000000 --- a/CommentMap.Mvc/Services/DeleteCommentService.cs +++ /dev/null @@ -1,14 +0,0 @@ -using CommentMap.Mvc.Data; -using Microsoft.EntityFrameworkCore; - -namespace CommentMap.Mvc.Services; - -public class DeleteCommentService(ICommentMapDbContext dbContext) : IDeleteCommentService -{ - public Task DeleteCommentAsync(Guid id, CancellationToken cancellationToken = default) - { - return dbContext.Comments - .Where(c => c.Id == id) - .ExecuteUpdateAsync(setters => setters.SetProperty(q => q.IsDeleted, true), cancellationToken); - } -} diff --git a/CommentMap.Mvc/Services/EnableAuthenticatorService.cs b/CommentMap.Mvc/Services/EnableAuthenticatorService.cs deleted file mode 100644 index 76f8159..0000000 --- a/CommentMap.Mvc/Services/EnableAuthenticatorService.cs +++ /dev/null @@ -1,24 +0,0 @@ -using QRCoder; -using System.Text.Encodings.Web; - -namespace CommentMap.Mvc.Services; - -public class EnableAuthenticatorService(UrlEncoder urlEncoder, QRCodeGenerator qRCodeGenerator) - : IEnableAuthenticatorService -{ - public string GetQRCodeUri(string appName, string userName, string key) - { - var encodedAppName = urlEncoder.Encode(appName); - var encodedUserName = urlEncoder.Encode(userName); - return $"otpauth://totp/{encodedAppName}:{encodedUserName}?secret={key}&issuer={encodedAppName}&digits=6"; - } - - public string GetEmbeddedSource(string qrCodeUri, int pixelsPerModule = 6) - { - using var qRCodeData = qRCodeGenerator.CreateQrCode(qrCodeUri, QRCodeGenerator.ECCLevel.Q); - using var base64QRCode = new Base64QRCode(qRCodeData); - - var base64EncodedQrCode = base64QRCode.GetGraphic(pixelsPerModule); - return $"data:image/png;base64,{base64EncodedQrCode}"; - } -} diff --git a/CommentMap.Mvc/Services/GetCountryViewModelService.cs b/CommentMap.Mvc/Services/GetCountryViewModelService.cs deleted file mode 100644 index 085869f..0000000 --- a/CommentMap.Mvc/Services/GetCountryViewModelService.cs +++ /dev/null @@ -1,24 +0,0 @@ -using CommentMap.Mvc.Data; -using CommentMap.Mvc.ViewModels; -using Microsoft.EntityFrameworkCore; - -namespace CommentMap.Mvc.Services; - -public class GetCountryViewModelService(CommentMapDbContext dbContext) : IGetCountryViewModelService -{ - public Task GetCountryViewModelAsync(string iso3code, CancellationToken cancellationToken = default) - { - return dbContext.Countries - .Where(c => c.ISO3Code.ToLower().Equals(iso3code.ToLower())) - .Select(c => new CountryViewModel - { - ISO3Code = c.ISO3Code, - ISO2Code = c.ISO2Code, - Name = c.Name, - RegionName = c.RegionName, - SubregionName = c.SubregionName - }) - .FirstOrDefaultAsync(cancellationToken); - } -} - diff --git a/CommentMap.Mvc/Services/GuessCountryService.cs b/CommentMap.Mvc/Services/GuessCountryService.cs deleted file mode 100644 index 4b52252..0000000 --- a/CommentMap.Mvc/Services/GuessCountryService.cs +++ /dev/null @@ -1,16 +0,0 @@ -using CommentMap.Mvc.Data; -using Microsoft.EntityFrameworkCore; -using NetTopologySuite.Geometries; - -namespace CommentMap.Mvc.Services; - -public class GuessCountryService(ICommentMapDbContext dbContext) : IGuessCountryService -{ - public Task GetCountryCodeAsync(Point point, CancellationToken cancellationToken = default) - { - return dbContext.Countries - .Where(c => c.Boundaries.Intersects(point)) - .Select(c => c.ISO3Code) - .FirstOrDefaultAsync(cancellationToken); - } -} \ No newline at end of file diff --git a/CommentMap.Mvc/Services/IAddCommentService.cs b/CommentMap.Mvc/Services/IAddCommentService.cs deleted file mode 100644 index 38ff377..0000000 --- a/CommentMap.Mvc/Services/IAddCommentService.cs +++ /dev/null @@ -1,8 +0,0 @@ -using CommentMap.Mvc.Models; - -namespace CommentMap.Mvc.Services; - -public interface IAddCommentService -{ - Task AddAsync(AddNewCommentDto addNewCommentDto, CancellationToken cancellationToken); -} \ No newline at end of file diff --git a/CommentMap.Mvc/Services/ICommentFactory.cs b/CommentMap.Mvc/Services/ICommentFactory.cs deleted file mode 100644 index dcc8da6..0000000 --- a/CommentMap.Mvc/Services/ICommentFactory.cs +++ /dev/null @@ -1,9 +0,0 @@ -using CommentMap.Mvc.Data.Entities; -using CommentMap.Mvc.Models; - -namespace CommentMap.Mvc.Services; - -public interface ICommentFactory -{ - Task CreateAsync(AddNewCommentDto addNewCommentDto, CancellationToken cancellationToken = default); -} \ No newline at end of file diff --git a/CommentMap.Mvc/Services/IConfirmDeleteService.cs b/CommentMap.Mvc/Services/IConfirmDeleteService.cs deleted file mode 100644 index ddba2f9..0000000 --- a/CommentMap.Mvc/Services/IConfirmDeleteService.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace CommentMap.Mvc.Services; - -public interface IConfirmDeleteService -{ - Task GetCommentTitleAsync(Guid id, CancellationToken cancellationToken); -} diff --git a/CommentMap.Mvc/Services/IDeleteCommentService.cs b/CommentMap.Mvc/Services/IDeleteCommentService.cs deleted file mode 100644 index c175655..0000000 --- a/CommentMap.Mvc/Services/IDeleteCommentService.cs +++ /dev/null @@ -1,7 +0,0 @@ - -namespace CommentMap.Mvc.Services; - -public interface IDeleteCommentService -{ - Task DeleteCommentAsync(Guid id, CancellationToken cancellationToken = default); -} \ No newline at end of file diff --git a/CommentMap.Mvc/Services/IEnableAuthenticatorService.cs b/CommentMap.Mvc/Services/IEnableAuthenticatorService.cs deleted file mode 100644 index 0fea7c3..0000000 --- a/CommentMap.Mvc/Services/IEnableAuthenticatorService.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace CommentMap.Mvc.Services; - -public interface IEnableAuthenticatorService -{ - string GetQRCodeUri(string appName, string userName, string key); - string GetEmbeddedSource(string qrCodeUri, int pixelsPerModule = 6); -} diff --git a/CommentMap.Mvc/Services/IGetCountryViewModelService.cs b/CommentMap.Mvc/Services/IGetCountryViewModelService.cs deleted file mode 100644 index 1d95192..0000000 --- a/CommentMap.Mvc/Services/IGetCountryViewModelService.cs +++ /dev/null @@ -1,8 +0,0 @@ -using CommentMap.Mvc.ViewModels; - -namespace CommentMap.Mvc.Services; - -public interface IGetCountryViewModelService -{ - Task GetCountryViewModelAsync(string iso3code, CancellationToken cancellationToken = default); -} \ No newline at end of file diff --git a/CommentMap.Mvc/Services/IGuessCountryService.cs b/CommentMap.Mvc/Services/IGuessCountryService.cs deleted file mode 100644 index 1615ff7..0000000 --- a/CommentMap.Mvc/Services/IGuessCountryService.cs +++ /dev/null @@ -1,8 +0,0 @@ -using NetTopologySuite.Geometries; - -namespace CommentMap.Mvc.Services; - -public interface IGuessCountryService -{ - Task GetCountryCodeAsync(Point point, CancellationToken cancellationToken = default); -} \ No newline at end of file diff --git a/CommentMap.Mvc/Services/IListCommentsService.cs b/CommentMap.Mvc/Services/IListCommentsService.cs deleted file mode 100644 index bbdaa0c..0000000 --- a/CommentMap.Mvc/Services/IListCommentsService.cs +++ /dev/null @@ -1,9 +0,0 @@ -using CommentMap.Mvc.Models; -using CommentMap.Mvc.ViewModels; - -namespace CommentMap.Mvc.Services; - -public interface IListCommentsService -{ - Task> GetAllUserComments(GetAllCommentsDto dto, CancellationToken cancellationToken = default); -} \ No newline at end of file diff --git a/CommentMap.Mvc/Services/ListCommentsService.cs b/CommentMap.Mvc/Services/ListCommentsService.cs deleted file mode 100644 index b9a72e8..0000000 --- a/CommentMap.Mvc/Services/ListCommentsService.cs +++ /dev/null @@ -1,21 +0,0 @@ -using CommentMap.Mvc.Data; -using CommentMap.Mvc.Extensions; -using CommentMap.Mvc.Models; -using CommentMap.Mvc.ViewModels; -using Microsoft.EntityFrameworkCore; - -namespace CommentMap.Mvc.Services; - -public class ListCommentsService(ICommentMapDbContext dbContext) : IListCommentsService -{ - public async Task> GetAllUserComments(GetAllCommentsDto dto, CancellationToken cancellationToken = default) - { - var comments = await dbContext.Comments - .Where(c => c.UserId == dto.UserId) - .Where(c => !c.IsDeleted) - .OrderBy(dto.Order) - .Select(c => new CommentCardViewModel(c.Id, new LocationViewModel { Longitude = c.Location.X, Latitude = c.Location.Y }, c.Title, c.Text, c.CreatedAt)) - .ToListAsync(cancellationToken); - return comments; - } -} diff --git a/CommentMap.Mvc/ViewComponents/SignInPanelViewComponent.cs b/CommentMap.Mvc/ViewComponents/SignInPanelViewComponent.cs index 343abe2..45244dd 100644 --- a/CommentMap.Mvc/ViewComponents/SignInPanelViewComponent.cs +++ b/CommentMap.Mvc/ViewComponents/SignInPanelViewComponent.cs @@ -1,4 +1,4 @@ -using CommentMap.Mvc.Data.Entities; +using CommentMap.Application.Entities; using CommentMap.Mvc.ViewModels; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; diff --git a/CommentMap.Mvc/ViewModels/CountryViewModel.cs b/CommentMap.Mvc/ViewModels/CountryViewModel.cs index f9a9d97..5dc9fc2 100644 --- a/CommentMap.Mvc/ViewModels/CountryViewModel.cs +++ b/CommentMap.Mvc/ViewModels/CountryViewModel.cs @@ -8,4 +8,3 @@ public class CountryViewModel public required string RegionName { get; set; } public required string SubregionName { get; set; } } - From 7a367b0597dbab8a5d60ec4e4564784260382ff2 Mon Sep 17 00:00:00 2001 From: Ivan Kozelskikh Date: Tue, 4 Aug 2026 23:18:58 +0500 Subject: [PATCH 05/23] Add MigrationService and wire into AppHost Introduce CommentMap.MigrationService worker project to run EF Core database migrations at startup. Adds Migrator BackgroundService (uses execution strategy, logs progress, then stops host) plus Program, launchSettings, and appsettings. AppHost updated to add the migration service project and wait for its completion before starting the MVC project; AppHost csproj references the new project. This ensures DB migrations are applied before the application serves requests. --- CommentMap.AppHost/AppHost.cs | 6 ++- CommentMap.AppHost/CommentMap.AppHost.csproj | 1 + .../CommentMap.MigrationService.csproj | 23 ++++++++++ CommentMap.MigrationService/Migrator.cs | 45 +++++++++++++++++++ CommentMap.MigrationService/Program.cs | 12 +++++ .../Properties/launchSettings.json | 12 +++++ .../appsettings.Development.json | 8 ++++ CommentMap.MigrationService/appsettings.json | 8 ++++ 8 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 CommentMap.MigrationService/CommentMap.MigrationService.csproj create mode 100644 CommentMap.MigrationService/Migrator.cs create mode 100644 CommentMap.MigrationService/Program.cs create mode 100644 CommentMap.MigrationService/Properties/launchSettings.json create mode 100644 CommentMap.MigrationService/appsettings.Development.json create mode 100644 CommentMap.MigrationService/appsettings.json diff --git a/CommentMap.AppHost/AppHost.cs b/CommentMap.AppHost/AppHost.cs index 9d0f83a..647f518 100644 --- a/CommentMap.AppHost/AppHost.cs +++ b/CommentMap.AppHost/AppHost.cs @@ -31,12 +31,16 @@ .WithReference(mailpit) .WaitFor(mailpit); +var migrationService = builder.AddProject("migration-service") + .WithReference(commentMapDb) + .WaitFor(commentMapDb); builder.AddProject("mvc") .WithReference(rabbitmq) .WaitFor(rabbitmq) .WithReference(commentMapDb) - .WaitFor(commentMapDb); + .WaitFor(commentMapDb) + .WaitForCompletion(migrationService); builder.Build().Run(); diff --git a/CommentMap.AppHost/CommentMap.AppHost.csproj b/CommentMap.AppHost/CommentMap.AppHost.csproj index 3e32e71..52429ef 100644 --- a/CommentMap.AppHost/CommentMap.AppHost.csproj +++ b/CommentMap.AppHost/CommentMap.AppHost.csproj @@ -17,6 +17,7 @@ + diff --git a/CommentMap.MigrationService/CommentMap.MigrationService.csproj b/CommentMap.MigrationService/CommentMap.MigrationService.csproj new file mode 100644 index 0000000..61ce5c3 --- /dev/null +++ b/CommentMap.MigrationService/CommentMap.MigrationService.csproj @@ -0,0 +1,23 @@ + + + + net10.0 + enable + enable + dotnet-CommentMap.MigrationService-9d387752-600f-4908-8c5b-448f40bef97b + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + diff --git a/CommentMap.MigrationService/Migrator.cs b/CommentMap.MigrationService/Migrator.cs new file mode 100644 index 0000000..9207e2c --- /dev/null +++ b/CommentMap.MigrationService/Migrator.cs @@ -0,0 +1,45 @@ +using System.Diagnostics; +using CommentMap.Infrastructure.Data; +using Microsoft.EntityFrameworkCore; + +namespace CommentMap.MigrationService; + +public class Migrator( + IServiceProvider serviceProvider, + IHostApplicationLifetime hostApplicationLifetime, + ILogger logger) : BackgroundService +{ + public const string ActivitySourceName = "Migrations"; + private static readonly ActivitySource ActivitySource = new(ActivitySourceName); + + protected override async Task ExecuteAsync(CancellationToken cancellationToken) + { + using var activity = ActivitySource.StartActivity("Migrating database", ActivityKind.Client); + + try + { + using var scope = serviceProvider.CreateScope(); + var dbContext = scope.ServiceProvider.GetRequiredService(); + + await RunMigrationAsync(dbContext, cancellationToken); + } + catch (Exception ex) + { + activity?.AddException(ex); + throw; + } + + hostApplicationLifetime.StopApplication(); + } + + private async Task RunMigrationAsync(CommentMapDbContext dbContext, CancellationToken cancellationToken) + { + var strategy = dbContext.Database.CreateExecutionStrategy(); + await strategy.ExecuteAsync(async () => + { + logger.LogInformation("Applying database migrations..."); + await dbContext.Database.MigrateAsync(cancellationToken); + logger.LogInformation("Database migrations applied successfully"); + }); + } +} diff --git a/CommentMap.MigrationService/Program.cs b/CommentMap.MigrationService/Program.cs new file mode 100644 index 0000000..2ca3f85 --- /dev/null +++ b/CommentMap.MigrationService/Program.cs @@ -0,0 +1,12 @@ +using CommentMap.Infrastructure.DependencyInjection; +using CommentMap.MigrationService; + +var builder = Host.CreateApplicationBuilder(args); + +builder.AddServiceDefaults(); +builder.AddInfrastructure(); + +builder.Services.AddHostedService(); + +var host = builder.Build(); +host.Run(); diff --git a/CommentMap.MigrationService/Properties/launchSettings.json b/CommentMap.MigrationService/Properties/launchSettings.json new file mode 100644 index 0000000..ad7a792 --- /dev/null +++ b/CommentMap.MigrationService/Properties/launchSettings.json @@ -0,0 +1,12 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "profiles": { + "CommentMap.MigrationService": { + "commandName": "Project", + "dotnetRunMessages": true, + "environmentVariables": { + "DOTNET_ENVIRONMENT": "Development" + } + } + } +} diff --git a/CommentMap.MigrationService/appsettings.Development.json b/CommentMap.MigrationService/appsettings.Development.json new file mode 100644 index 0000000..b2dcdb6 --- /dev/null +++ b/CommentMap.MigrationService/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.Hosting.Lifetime": "Information" + } + } +} diff --git a/CommentMap.MigrationService/appsettings.json b/CommentMap.MigrationService/appsettings.json new file mode 100644 index 0000000..b2dcdb6 --- /dev/null +++ b/CommentMap.MigrationService/appsettings.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.Hosting.Lifetime": "Information" + } + } +} From 7717af2c8b9428c9bdc14ede0fe83784fefa201b Mon Sep 17 00:00:00 2001 From: Ivan Kozelskikh Date: Tue, 4 Aug 2026 23:20:16 +0500 Subject: [PATCH 06/23] Replace jQuery validation with aspnet-client-validation Switch client-side validation from jquery-validation(+unobtrusive) to aspnet-client-validation. --- .../Account/ResendEmailConfirmation.cshtml | 1 - CommentMap.Mvc/Pages/Comments/Add.cshtml | 2 +- CommentMap.Mvc/Pages/Countries/Index.cshtml | 5 ----- CommentMap.Mvc/Pages/Shared/_Layout.cshtml | 1 + .../Shared/_ValidationScriptsPartial.cshtml | 8 ++++++-- ...ummary-errors.css => validation-errors.css} | 10 +++++++++- CommentMap.Mvc/build/build.js | 2 +- CommentMap.Mvc/libman.json | 14 ++++---------- CommentMap.Mvc/package-lock.json | 18 ------------------ CommentMap.Mvc/package.json | 2 -- 10 files changed, 22 insertions(+), 41 deletions(-) rename CommentMap.Mvc/Styles/{validation-summary-errors.css => validation-errors.css} (69%) diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/ResendEmailConfirmation.cshtml b/CommentMap.Mvc/Areas/Identity/Pages/Account/ResendEmailConfirmation.cshtml index f408322..0bbf8fd 100644 --- a/CommentMap.Mvc/Areas/Identity/Pages/Account/ResendEmailConfirmation.cshtml +++ b/CommentMap.Mvc/Areas/Identity/Pages/Account/ResendEmailConfirmation.cshtml @@ -12,7 +12,6 @@
-
diff --git a/CommentMap.Mvc/Pages/Comments/Add.cshtml b/CommentMap.Mvc/Pages/Comments/Add.cshtml index 5023b71..e77fca0 100644 --- a/CommentMap.Mvc/Pages/Comments/Add.cshtml +++ b/CommentMap.Mvc/Pages/Comments/Add.cshtml @@ -1,5 +1,4 @@ @page -@using CommentMap.Mvc.Pages.Comments @model AddModel @{ ViewData["Title"] = "Add new comment"; @@ -51,6 +50,7 @@
@section Scripts { + } diff --git a/CommentMap.Mvc/Pages/Countries/Index.cshtml b/CommentMap.Mvc/Pages/Countries/Index.cshtml index 457a6f4..0b1e63d 100644 --- a/CommentMap.Mvc/Pages/Countries/Index.cshtml +++ b/CommentMap.Mvc/Pages/Countries/Index.cshtml @@ -1,14 +1,9 @@ @page -@using CommentMap.Mvc.Pages.Countries @model IndexModel @{ ViewData["Title"] = "Country"; } -@section Styles { - -} - @if (ModelState.ErrorCount > 0) {
diff --git a/CommentMap.Mvc/Pages/Shared/_Layout.cshtml b/CommentMap.Mvc/Pages/Shared/_Layout.cshtml index 3df55b4..d417989 100644 --- a/CommentMap.Mvc/Pages/Shared/_Layout.cshtml +++ b/CommentMap.Mvc/Pages/Shared/_Layout.cshtml @@ -10,6 +10,7 @@ + @await RenderSectionAsync("Styles", required: false) diff --git a/CommentMap.Mvc/Pages/Shared/_ValidationScriptsPartial.cshtml b/CommentMap.Mvc/Pages/Shared/_ValidationScriptsPartial.cshtml index 5d1f685..d2c8851 100644 --- a/CommentMap.Mvc/Pages/Shared/_ValidationScriptsPartial.cshtml +++ b/CommentMap.Mvc/Pages/Shared/_ValidationScriptsPartial.cshtml @@ -1,2 +1,6 @@ - - + + diff --git a/CommentMap.Mvc/Styles/validation-summary-errors.css b/CommentMap.Mvc/Styles/validation-errors.css similarity index 69% rename from CommentMap.Mvc/Styles/validation-summary-errors.css rename to CommentMap.Mvc/Styles/validation-errors.css index 3e1dda0..b478d97 100644 --- a/CommentMap.Mvc/Styles/validation-summary-errors.css +++ b/CommentMap.Mvc/Styles/validation-errors.css @@ -1,4 +1,12 @@ -.validation-summary-errors { +.input-validation-error { + border-color: var(--bs-form-invalid-border-color); +} + +.field-validation-error { + color: var(--bs-danger-text-emphasis); +} + +.validation-summary-errors { background-color: var(--bs-danger-bg-subtle); border-radius: var(--bs-border-radius); border: var(--bs-border-width) var(--bs-border-style) var(--bs-danger-border-subtle); diff --git a/CommentMap.Mvc/build/build.js b/CommentMap.Mvc/build/build.js index 253d469..3d0055f 100644 --- a/CommentMap.Mvc/build/build.js +++ b/CommentMap.Mvc/build/build.js @@ -5,7 +5,7 @@ await esbuild.build({ "js/Comments.min": "./Scripts/Comments.ts", "js/AddComment.min": "./Scripts/AddComment.ts", "css/ol.min": "./node_modules/ol/ol.css", - "css/validation-summary-errors.min": "./Styles/validation-summary-errors.css" + "css/validation-errors.min": "./Styles/validation-errors.css" }, bundle: true, minify: true, diff --git a/CommentMap.Mvc/libman.json b/CommentMap.Mvc/libman.json index 368d229..965953a 100644 --- a/CommentMap.Mvc/libman.json +++ b/CommentMap.Mvc/libman.json @@ -11,17 +11,11 @@ ] }, { - "library": "jquery-validation@1.20.0", - "destination": "wwwroot/lib/jquery-validation/", + "library": "aspnet-client-validation@0.11.1", + "destination": "wwwroot/lib/aspnet-client-validation/", "files": [ - "dist/jquery.validate.min.js" - ] - }, - { - "library": "jquery-validation-unobtrusive@4.0.0", - "destination": "wwwroot/lib/jquery-validation-unobtrusive/", - "files": [ - "dist/jquery.validate.unobtrusive.min.js" + "dist/aspnet-validation.min.js", + "dist/aspnet-validation.min.js.map" ] }, { diff --git a/CommentMap.Mvc/package-lock.json b/CommentMap.Mvc/package-lock.json index 2440d94..07636dd 100644 --- a/CommentMap.Mvc/package-lock.json +++ b/CommentMap.Mvc/package-lock.json @@ -14,8 +14,6 @@ "@eslint/js": "^9.4.0", "@types/bootstrap": "^5.2.10", "@types/jquery": "^3.5.30", - "@types/jquery-validation-unobtrusive": "^3.2.35", - "@types/jquery.validation": "^1.16.10", "@types/knockout": "^3.4.77", "esbuild": "^0.25.0", "eslint": "^8.56.0", @@ -617,22 +615,6 @@ "@types/sizzle": "*" } }, - "node_modules/@types/jquery-validation-unobtrusive": { - "version": "3.2.35", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/jquery.validation": "*" - } - }, - "node_modules/@types/jquery.validation": { - "version": "1.16.10", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/jquery": "*" - } - }, "node_modules/@types/knockout": { "version": "3.4.77", "resolved": "https://registry.npmjs.org/@types/knockout/-/knockout-3.4.77.tgz", diff --git a/CommentMap.Mvc/package.json b/CommentMap.Mvc/package.json index 07fac59..fd0f22a 100644 --- a/CommentMap.Mvc/package.json +++ b/CommentMap.Mvc/package.json @@ -7,8 +7,6 @@ "@eslint/js": "^9.4.0", "@types/bootstrap": "^5.2.10", "@types/jquery": "^3.5.30", - "@types/jquery-validation-unobtrusive": "^3.2.35", - "@types/jquery.validation": "^1.16.10", "@types/knockout": "^3.4.77", "esbuild": "^0.25.0", "eslint": "^8.56.0", From e6599cc5c0367136d42cf1637171bc30920901d7 Mon Sep 17 00:00:00 2001 From: Ivan Kozelskikh Date: Tue, 4 Aug 2026 23:20:58 +0500 Subject: [PATCH 07/23] Add roslyn language server and opencode config Register roslyn-language-server in dotnet-tools.json (version 5.11.0-1.26379.6, rollForward: false) and add opencode.json LSP config to launch it for C# (.cs, .csx, .razor, .cshtml) via "dotnet roslyn-language-server --stdio --autoLoadProjects". Enables editor/LSP tooling for C# projects. --- dotnet-tools.json | 7 +++++++ opencode.json | 9 +++++++++ 2 files changed, 16 insertions(+) create mode 100644 opencode.json diff --git a/dotnet-tools.json b/dotnet-tools.json index ec72923..404cb7f 100644 --- a/dotnet-tools.json +++ b/dotnet-tools.json @@ -22,6 +22,13 @@ "aspire" ], "rollForward": false + }, + "roslyn-language-server": { + "version": "5.11.0-1.26379.6", + "commands": [ + "roslyn-language-server" + ], + "rollForward": false } } } \ No newline at end of file diff --git a/opencode.json b/opencode.json new file mode 100644 index 0000000..17fd242 --- /dev/null +++ b/opencode.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://opencode.ai/config.json", + "lsp": { + "csharp": { + "command": [ "dotnet", "roslyn-language-server", "--stdio", "--autoLoadProjects" ], + "extensions": [ ".cs", ".csx", ".razor", ".cshtml" ] + } + } +} From c65596bae162d9e826632ccde5340935f34a486f Mon Sep 17 00:00:00 2001 From: Ivan Kozelskikh Date: Fri, 7 Aug 2026 00:01:57 +0500 Subject: [PATCH 08/23] Move projects into src/ and modernize MVC frontend Reorganize repository: move all project folders under src/ and update CommentMap.slnx, aspire.config.json and workflow paths. Add AGENTS.md and register an Aspire MCP agent in opencode.json. Update CI Docker build context to src/CommentMap.Mvc. Modernize MVC frontend: replace legacy scripts/styles with Tailwind + daisyUI, add esbuild/postcss build (src/CommentMap.Mvc/build/build.js), new package.json/tsconfig/package-lock, TypeScript pages and site scripts, and a BuildJS MSBuild target. Remove old frontend artifacts. Bump LICENSE year to 2026. --- .github/workflows/publish-container.yml | 2 +- .gitignore | 3 +- AGENTS.md | 39 + .../Pages/Account/AccessDenied.cshtml | 10 - .../Pages/Account/ExternalLogin.cshtml | 33 - .../Pages/Account/ForgotPassword.cshtml | 26 - .../Areas/Identity/Pages/Account/Login.cshtml | 66 - .../Pages/Account/LoginWith2fa.cshtml | 39 - .../Account/LoginWithRecoveryCode.cshtml | 29 - .../Account/Manage/ChangePassword.cshtml | 37 - .../Pages/Account/Manage/DeleteProfile.cshtml | 35 - .../Pages/Account/Manage/Disable2fa.cshtml | 22 - .../Account/Manage/EnableAuthenticator.cshtml | 52 - .../Account/Manage/ExternalLogins.cshtml | 45 - .../Manage/GenerateRecoveryCodes.cshtml | 24 - .../Pages/Account/Manage/Index.cshtml | 35 - .../Account/Manage/ResetAuthenticator.cshtml | 21 - .../Pages/Account/Manage/SetPassword.cshtml | 36 - .../Account/Manage/ShowRecoveryCodes.cshtml | 24 - .../Manage/TwoFactorAuthentication.cshtml | 70 - .../Pages/Account/Manage/_Layout.cshtml | 22 - .../Pages/Account/Manage/_ManageNav.cshtml | 17 - .../Identity/Pages/Account/Register.cshtml | 56 - .../Account/ResendEmailConfirmation.cshtml | 27 - .../Pages/Account/ResetPassword.cshtml | 31 - .../Identity/Pages/_StatusMessage.cshtml | 10 - CommentMap.Mvc/Pages/Comments/Add.cshtml | 56 - .../Pages/Comments/ConfirmDelete.cshtml | 15 - CommentMap.Mvc/Pages/Comments/Index.cshtml | 58 - CommentMap.Mvc/Pages/Countries/Index.cshtml | 40 - .../Components/SignInPanel/Default.cshtml | 25 - .../Pages/Shared/_CommentCardPartial.cshtml | 29 - CommentMap.Mvc/Pages/Shared/_Layout.cshtml | 46 - CommentMap.Mvc/Scripts/AddComment.ts | 14 - CommentMap.Mvc/Scripts/AddCommentViewModel.ts | 99 - CommentMap.Mvc/Scripts/Comments.ts | 14 - CommentMap.Mvc/Scripts/CommentsViewModel.ts | 72 - CommentMap.Mvc/Styles/validation-errors.css | 26 - CommentMap.Mvc/build/build.js | 14 - CommentMap.Mvc/eslint.config.js | 13 - CommentMap.Mvc/libman.json | 48 - CommentMap.Mvc/package-lock.json | 2295 ----------------- CommentMap.Mvc/package.json | 26 - CommentMap.Mvc/tsconfig.json | 13 - .../wwwroot/assets/favicon-16x16.png | Bin 574 -> 0 bytes .../wwwroot/assets/favicon-32x32.png | Bin 1123 -> 0 bytes .../wwwroot/assets/favicon-96x96.png | Bin 3221 -> 0 bytes CommentMap.Mvc/wwwroot/assets/marker.svg | 6 - CommentMap.slnx | 27 +- LICENSE.txt | 2 +- aspire.config.json | 2 +- clear.ps1 | 1 - dotnet-tools.json | 7 - opencode.json | 7 + .../CommentMap.AppHost}/AppHost.cs | 0 .../CommentMap.AppHost.csproj | 0 .../Properties/launchSettings.json | 0 .../appsettings.Development.json | 0 .../CommentMap.AppHost}/appsettings.json | 0 .../Abstractions/ICommentMapDbContext.cs | 0 .../CommentMap.Application.csproj | 0 .../Entities/Comment.cs | 0 .../Entities/Country.cs | 0 .../CommentMap.Application}/Entities/Role.cs | 0 .../CommentMap.Application}/Entities/User.cs | 0 .../Features/Comments/AddComment.cs | 0 .../Features/Comments/DeleteComment.cs | 0 .../Features/Comments/GetCommentTitle.cs | 0 .../Features/Comments/ListComments.cs | 0 .../Features/Countries/GetCountry.cs | 0 .../Features/Identity/ChangeEmail.cs | 0 .../Features/Identity/ChangePassword.cs | 0 .../Features/Identity/ConfirmEmail.cs | 0 .../Features/Identity/ConfirmEmailChange.cs | 0 .../Features/Identity/DeleteProfile.cs | 0 .../Features/Identity/ExternalLogin.cs | 0 .../Features/Identity/ForgotPassword.cs | 0 .../Features/Identity/IdentityMapping.cs | 0 .../Features/Identity/LoginUser.cs | 0 .../Features/Identity/LogoutUser.cs | 0 .../Features/Identity/RegisterUser.cs | 0 .../Identity/ResendEmailConfirmation.cs | 0 .../Features/Identity/ResetPassword.cs | 0 .../Features/Identity/TwoFactor.cs | 0 .../Models/CommentCardDto.cs | 0 .../Models/CountryDto.cs | 0 .../Models/IdentityResultDto.cs | 0 .../CommentMap.Application}/Models/Order.cs | 0 .../CommentMap.EmailSender.csproj | 0 .../Exceptions/MjmlValidationException.cs | 0 .../Extensions/ServiceCollectionExtensions.cs | 0 .../GeneratedHandlerRegistry.cs | 0 .../SendChangeEmailHandler531316428.cs | 0 .../SendConfirmEmailHandler111886888.cs | 0 .../SendResetPasswordEmailHandler453035410.cs | 0 .../CommentMap.EmailSender}/Logging/Log.cs | 0 .../Options/MailpitClientSettings.cs | 0 .../CommentMap.EmailSender}/Program.cs | 0 .../Properties/launchSettings.json | 0 .../Services/IMessageSenderService.cs | 0 .../Services/ISmtpClientFactory.cs | 0 .../Services/ISmtpEmailSender.cs | 0 .../Services/MessageSenderHandler.cs | 0 .../Services/MessageSenderService.cs | 0 .../Services/SendMessageConsumer.cs | 0 .../Services/SmtpClientFactory.cs | 0 .../Services/SmtpEmailSender.cs | 0 .../Templates/ChangeEmailViewModel.cs | 0 .../Templates/ConfirmEmailViewModel.cs | 0 .../Templates/EmailMessageMjml.cshtml | 0 .../Templates/IEmailMessageViewModel.cs | 0 .../Templates/ResetPasswordViewModel.cs | 0 .../CommentMap.EmailSender}/appsettings.json | 0 .../CommentMap.Infrastructure.csproj | 0 .../Data/CommentMapDbContext.cs | 0 .../Configurations/CommentConfiguration.cs | 0 .../Configurations/CountryConfiguration.cs | 0 ...0240523173725_InitialMigration.Designer.cs | 0 .../20240523173725_InitialMigration.cs | 0 ...525160654_AddCommentProperties.Designer.cs | 0 .../20240525160654_AddCommentProperties.cs | 0 .../20240623144537_AddIsDeleted.Designer.cs | 0 .../Migrations/20240623144537_AddIsDeleted.cs | 0 .../20240909164708_AddCountry.Designer.cs | 0 .../Migrations/20240909164708_AddCountry.cs | 0 ...39_AddISO3CountryCodeToComment.Designer.cs | 0 ...40921074639_AddISO3CountryCodeToComment.cs | 0 .../CommentMapDbContextModelSnapshot.cs | 0 ...frastructureServiceCollectionExtensions.cs | 0 .../CommentMap.MigrationService.csproj | 0 .../CommentMap.MigrationService}/Migrator.cs | 0 .../CommentMap.MigrationService}/Program.cs | 0 .../Properties/launchSettings.json | 0 .../appsettings.Development.json | 0 .../appsettings.json | 0 .../Pages/Account/AccessDenied.cshtml | 10 + .../Pages/Account/AccessDenied.cshtml.cs | 0 .../Pages/Account/ConfirmEmail.cshtml | 2 +- .../Pages/Account/ConfirmEmail.cshtml.cs | 0 .../Pages/Account/ConfirmEmailChange.cshtml | 2 +- .../Account/ConfirmEmailChange.cshtml.cs | 0 .../Pages/Account/ExternalLogin.cshtml | 31 + .../Pages/Account/ExternalLogin.cshtml.cs | 0 .../Pages/Account/ForgotPassword.cshtml | 24 + .../Pages/Account/ForgotPassword.cshtml.cs | 0 .../Account/ForgotPasswordConfirmation.cshtml | 2 +- .../ForgotPasswordConfirmation.cshtml.cs | 0 .../Areas/Identity/Pages/Account/Login.cshtml | 60 + .../Identity/Pages/Account/Login.cshtml.cs | 0 .../Pages/Account/LoginWith2fa.cshtml | 33 + .../Pages/Account/LoginWith2fa.cshtml.cs | 0 .../Account/LoginWithRecoveryCode.cshtml | 27 + .../Account/LoginWithRecoveryCode.cshtml.cs | 0 .../Identity/Pages/Account/Logout.cshtml | 4 +- .../Identity/Pages/Account/Logout.cshtml.cs | 0 .../Account/Manage/ChangePassword.cshtml | 35 + .../Account/Manage/ChangePassword.cshtml.cs | 0 .../Pages/Account/Manage/DeleteProfile.cshtml | 36 + .../Account/Manage/DeleteProfile.cshtml.cs | 0 .../Pages/Account/Manage/Disable2fa.cshtml | 25 + .../Pages/Account/Manage/Disable2fa.cshtml.cs | 0 .../Account/Manage/EnableAuthenticator.cshtml | 50 + .../Manage/EnableAuthenticator.cshtml.cs | 0 .../Account/Manage/ExternalLogins.cshtml | 47 + .../Account/Manage/ExternalLogins.cshtml.cs | 0 .../Manage/GenerateRecoveryCodes.cshtml | 26 + .../Manage/GenerateRecoveryCodes.cshtml.cs | 0 .../Pages/Account/Manage/Index.cshtml | 39 + .../Pages/Account/Manage/Index.cshtml.cs | 0 .../Account/Manage/ResetAuthenticator.cshtml | 23 + .../Manage/ResetAuthenticator.cshtml.cs | 0 .../Pages/Account/Manage/SetPassword.cshtml | 34 + .../Account/Manage/SetPassword.cshtml.cs | 0 .../Account/Manage/ShowRecoveryCodes.cshtml | 25 + .../Manage/ShowRecoveryCodes.cshtml.cs | 0 .../Manage/TwoFactorAuthentication.cshtml | 82 + .../Manage/TwoFactorAuthentication.cshtml.cs | 0 .../Pages/Account/Manage/_Layout.cshtml | 22 + .../Pages/Account/Manage/_ManageNav.cshtml | 7 + .../Identity/Pages/Account/Register.cshtml | 50 + .../Identity/Pages/Account/Register.cshtml.cs | 0 .../Pages/Account/RegisterConfirmation.cshtml | 0 .../Account/RegisterConfirmation.cshtml.cs | 0 .../Account/ResendEmailConfirmation.cshtml | 25 + .../Account/ResendEmailConfirmation.cshtml.cs | 0 .../Pages/Account/ResetPassword.cshtml | 29 + .../Pages/Account/ResetPassword.cshtml.cs | 0 .../Account/ResetPasswordConfirmation.cshtml | 2 +- .../ResetPasswordConfirmation.cshtml.cs | 0 .../Identity/Pages/_StatusMessage.cshtml | 24 + .../Areas/Identity/Pages/_ViewImports.cshtml | 0 .../Areas/Identity/Pages/_ViewStart.cshtml | 0 .../CommentMap.Mvc}/CommentMap.Mvc.csproj | 10 +- .../Extensions/ClaimsPrincipalExtensions.cs | 0 .../AddCommentHandler838741630.cs | 0 .../ChangePasswordHandler702758377.cs | 0 .../ConfirmEmailChangeHandler1497850754.cs | 0 .../ConfirmEmailHandler55631218.cs | 0 .../CreateExternalUserHandler966620274.cs | 0 .../DeleteCommentHandler107828254.cs | 0 .../DeleteProfileHandler1834710062.cs | 0 .../Disable2faHandler1923519541.cs | 0 .../EnableAuthenticatorHandler897587120.cs | 0 .../ExternalLoginSignInHandler1809594924.cs | 0 .../ForgetTwoFactorClientHandler253588197.cs | 0 .../ForgotPasswordHandler1306123444.cs | 0 .../GenerateRecoveryCodesHandler711237032.cs | 0 .../GeneratedHandlerRegistry.cs | 0 .../GetAuthenticatorSetupHandler507613430.cs | 0 .../GetCommentTitleHandler595995119.cs | 0 .../GetCountryHandler1133281984.cs | 0 .../GetDeleteProfileInfoHandler900389426.cs | 0 .../GetExternalLoginsHandler199405825.cs | 0 .../GetProfileEmailHandler1046567855.cs | 0 .../GetTwoFactorStatusHandler1213804985.cs | 0 .../HasPasswordHandler1751871263.cs | 0 .../LinkExternalLoginHandler251495890.cs | 0 .../ListCommentsHandler488515704.cs | 0 .../LoginUserHandler1789921628.cs | 0 .../LoginWith2faHandler292869486.cs | 0 .../LoginWithRecoveryCodeHandler277354287.cs | 0 .../LogoutUserHandler132148485.cs | 0 .../RegisterUserHandler1265692392.cs | 0 .../RemoveExternalLoginHandler62493602.cs | 0 .../RequestEmailChangeHandler172865511.cs | 0 .../ResendEmailConfirmationHandler19836290.cs | 0 .../ResetAuthenticatorHandler25524780.cs | 0 .../ResetPasswordHandler433488700.cs | 0 .../SetPasswordHandler836449791.cs | 0 ...ignInAfterRegistrationHandler2047984407.cs | 0 .../Models/AddNewCommentInput.cs | 0 src/CommentMap.Mvc/Pages/Comments/Add.cshtml | 51 + .../Pages/Comments/Add.cshtml.cs | 0 .../Pages/Comments/Add.cshtml.ts | 99 + .../Pages/Comments/ConfirmDelete.cshtml | 15 + .../Pages/Comments/ConfirmDelete.cshtml.cs | 0 .../Pages/Comments/Index.cshtml | 58 + .../Pages/Comments/Index.cshtml.cs | 0 .../Pages/Comments/Index.cshtml.ts | 68 + .../Pages/Countries/Index.cshtml | 44 + .../Pages/Countries/Index.cshtml.cs | 0 .../CommentMap.Mvc}/Pages/Error.cshtml | 4 +- .../CommentMap.Mvc}/Pages/Error.cshtml.cs | 0 .../CommentMap.Mvc}/Pages/Index.cshtml | 2 +- .../CommentMap.Mvc}/Pages/Index.cshtml.cs | 0 .../Components/SignInPanel/Default.cshtml | 30 + .../Pages/Shared/_CommentCardPartial.cshtml | 36 + .../Pages/Shared/_Layout.cshtml | 56 + .../Shared/_ValidationScriptsPartial.cshtml | 2 +- .../CommentMap.Mvc}/Pages/_ViewImports.cshtml | 0 .../CommentMap.Mvc}/Pages/_ViewStart.cshtml | 0 .../CommentMap.Mvc}/Program.cs | 0 .../Properties/launchSettings.json | 0 src/CommentMap.Mvc/Scripts/site.ts | 31 + src/CommentMap.Mvc/Styles/app.css | 32 + .../TagHelpers/AnchorTagHelper.cs | 0 .../SignInPanelViewComponent.cs | 0 .../ViewModels/CommentCardViewModel.cs | 0 .../ViewModels/CountryViewModel.cs | 0 .../ViewModels/LocationViewModel.cs | 0 .../ViewModels/SignInPanelViewModel.cs | 0 .../CommentMap.Mvc}/appsettings.json | 0 src/CommentMap.Mvc/build/build.js | 43 + src/CommentMap.Mvc/package-lock.json | 1849 +++++++++++++ src/CommentMap.Mvc/package.json | 24 + src/CommentMap.Mvc/tsconfig.json | 21 + .../CommentMap.ServiceDefaults.csproj | 0 .../CommentMap.ServiceDefaults}/Extensions.cs | 0 .../CommentMap.Shared.csproj | 0 .../Messages/SendChangeEmail.cs | 0 .../Messages/SendConfirmEmail.cs | 0 .../Messages/SendResetPasswordEmail.cs | 0 272 files changed, 3307 insertions(+), 3710 deletions(-) create mode 100644 AGENTS.md delete mode 100644 CommentMap.Mvc/Areas/Identity/Pages/Account/AccessDenied.cshtml delete mode 100644 CommentMap.Mvc/Areas/Identity/Pages/Account/ExternalLogin.cshtml delete mode 100644 CommentMap.Mvc/Areas/Identity/Pages/Account/ForgotPassword.cshtml delete mode 100644 CommentMap.Mvc/Areas/Identity/Pages/Account/Login.cshtml delete mode 100644 CommentMap.Mvc/Areas/Identity/Pages/Account/LoginWith2fa.cshtml delete mode 100644 CommentMap.Mvc/Areas/Identity/Pages/Account/LoginWithRecoveryCode.cshtml delete mode 100644 CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ChangePassword.cshtml delete mode 100644 CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/DeleteProfile.cshtml delete mode 100644 CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/Disable2fa.cshtml delete mode 100644 CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/EnableAuthenticator.cshtml delete mode 100644 CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ExternalLogins.cshtml delete mode 100644 CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/GenerateRecoveryCodes.cshtml delete mode 100644 CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/Index.cshtml delete mode 100644 CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ResetAuthenticator.cshtml delete mode 100644 CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/SetPassword.cshtml delete mode 100644 CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ShowRecoveryCodes.cshtml delete mode 100644 CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/TwoFactorAuthentication.cshtml delete mode 100644 CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/_Layout.cshtml delete mode 100644 CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/_ManageNav.cshtml delete mode 100644 CommentMap.Mvc/Areas/Identity/Pages/Account/Register.cshtml delete mode 100644 CommentMap.Mvc/Areas/Identity/Pages/Account/ResendEmailConfirmation.cshtml delete mode 100644 CommentMap.Mvc/Areas/Identity/Pages/Account/ResetPassword.cshtml delete mode 100644 CommentMap.Mvc/Areas/Identity/Pages/_StatusMessage.cshtml delete mode 100644 CommentMap.Mvc/Pages/Comments/Add.cshtml delete mode 100644 CommentMap.Mvc/Pages/Comments/ConfirmDelete.cshtml delete mode 100644 CommentMap.Mvc/Pages/Comments/Index.cshtml delete mode 100644 CommentMap.Mvc/Pages/Countries/Index.cshtml delete mode 100644 CommentMap.Mvc/Pages/Shared/Components/SignInPanel/Default.cshtml delete mode 100644 CommentMap.Mvc/Pages/Shared/_CommentCardPartial.cshtml delete mode 100644 CommentMap.Mvc/Pages/Shared/_Layout.cshtml delete mode 100644 CommentMap.Mvc/Scripts/AddComment.ts delete mode 100644 CommentMap.Mvc/Scripts/AddCommentViewModel.ts delete mode 100644 CommentMap.Mvc/Scripts/Comments.ts delete mode 100644 CommentMap.Mvc/Scripts/CommentsViewModel.ts delete mode 100644 CommentMap.Mvc/Styles/validation-errors.css delete mode 100644 CommentMap.Mvc/build/build.js delete mode 100644 CommentMap.Mvc/eslint.config.js delete mode 100644 CommentMap.Mvc/libman.json delete mode 100644 CommentMap.Mvc/package-lock.json delete mode 100644 CommentMap.Mvc/package.json delete mode 100644 CommentMap.Mvc/tsconfig.json delete mode 100644 CommentMap.Mvc/wwwroot/assets/favicon-16x16.png delete mode 100644 CommentMap.Mvc/wwwroot/assets/favicon-32x32.png delete mode 100644 CommentMap.Mvc/wwwroot/assets/favicon-96x96.png delete mode 100644 CommentMap.Mvc/wwwroot/assets/marker.svg delete mode 100644 clear.ps1 rename {CommentMap.AppHost => src/CommentMap.AppHost}/AppHost.cs (100%) rename {CommentMap.AppHost => src/CommentMap.AppHost}/CommentMap.AppHost.csproj (100%) rename {CommentMap.AppHost => src/CommentMap.AppHost}/Properties/launchSettings.json (100%) rename {CommentMap.AppHost => src/CommentMap.AppHost}/appsettings.Development.json (100%) rename {CommentMap.AppHost => src/CommentMap.AppHost}/appsettings.json (100%) rename {CommentMap.Application => src/CommentMap.Application}/Abstractions/ICommentMapDbContext.cs (100%) rename {CommentMap.Application => src/CommentMap.Application}/CommentMap.Application.csproj (100%) rename {CommentMap.Application => src/CommentMap.Application}/Entities/Comment.cs (100%) rename {CommentMap.Application => src/CommentMap.Application}/Entities/Country.cs (100%) rename {CommentMap.Application => src/CommentMap.Application}/Entities/Role.cs (100%) rename {CommentMap.Application => src/CommentMap.Application}/Entities/User.cs (100%) rename {CommentMap.Application => src/CommentMap.Application}/Features/Comments/AddComment.cs (100%) rename {CommentMap.Application => src/CommentMap.Application}/Features/Comments/DeleteComment.cs (100%) rename {CommentMap.Application => src/CommentMap.Application}/Features/Comments/GetCommentTitle.cs (100%) rename {CommentMap.Application => src/CommentMap.Application}/Features/Comments/ListComments.cs (100%) rename {CommentMap.Application => src/CommentMap.Application}/Features/Countries/GetCountry.cs (100%) rename {CommentMap.Application => src/CommentMap.Application}/Features/Identity/ChangeEmail.cs (100%) rename {CommentMap.Application => src/CommentMap.Application}/Features/Identity/ChangePassword.cs (100%) rename {CommentMap.Application => src/CommentMap.Application}/Features/Identity/ConfirmEmail.cs (100%) rename {CommentMap.Application => src/CommentMap.Application}/Features/Identity/ConfirmEmailChange.cs (100%) rename {CommentMap.Application => src/CommentMap.Application}/Features/Identity/DeleteProfile.cs (100%) rename {CommentMap.Application => src/CommentMap.Application}/Features/Identity/ExternalLogin.cs (100%) rename {CommentMap.Application => src/CommentMap.Application}/Features/Identity/ForgotPassword.cs (100%) rename {CommentMap.Application => src/CommentMap.Application}/Features/Identity/IdentityMapping.cs (100%) rename {CommentMap.Application => src/CommentMap.Application}/Features/Identity/LoginUser.cs (100%) rename {CommentMap.Application => src/CommentMap.Application}/Features/Identity/LogoutUser.cs (100%) rename {CommentMap.Application => src/CommentMap.Application}/Features/Identity/RegisterUser.cs (100%) rename {CommentMap.Application => src/CommentMap.Application}/Features/Identity/ResendEmailConfirmation.cs (100%) rename {CommentMap.Application => src/CommentMap.Application}/Features/Identity/ResetPassword.cs (100%) rename {CommentMap.Application => src/CommentMap.Application}/Features/Identity/TwoFactor.cs (100%) rename {CommentMap.Application => src/CommentMap.Application}/Models/CommentCardDto.cs (100%) rename {CommentMap.Application => src/CommentMap.Application}/Models/CountryDto.cs (100%) rename {CommentMap.Application => src/CommentMap.Application}/Models/IdentityResultDto.cs (100%) rename {CommentMap.Application => src/CommentMap.Application}/Models/Order.cs (100%) rename {CommentMap.EmailSender => src/CommentMap.EmailSender}/CommentMap.EmailSender.csproj (100%) rename {CommentMap.EmailSender => src/CommentMap.EmailSender}/Exceptions/MjmlValidationException.cs (100%) rename {CommentMap.EmailSender => src/CommentMap.EmailSender}/Extensions/ServiceCollectionExtensions.cs (100%) rename {CommentMap.EmailSender => src/CommentMap.EmailSender}/Internal/Generated/WolverineHandlers/GeneratedHandlerRegistry.cs (100%) rename {CommentMap.EmailSender => src/CommentMap.EmailSender}/Internal/Generated/WolverineHandlers/SendChangeEmailHandler531316428.cs (100%) rename {CommentMap.EmailSender => src/CommentMap.EmailSender}/Internal/Generated/WolverineHandlers/SendConfirmEmailHandler111886888.cs (100%) rename {CommentMap.EmailSender => src/CommentMap.EmailSender}/Internal/Generated/WolverineHandlers/SendResetPasswordEmailHandler453035410.cs (100%) rename {CommentMap.EmailSender => src/CommentMap.EmailSender}/Logging/Log.cs (100%) rename {CommentMap.EmailSender => src/CommentMap.EmailSender}/Options/MailpitClientSettings.cs (100%) rename {CommentMap.EmailSender => src/CommentMap.EmailSender}/Program.cs (100%) rename {CommentMap.EmailSender => src/CommentMap.EmailSender}/Properties/launchSettings.json (100%) rename {CommentMap.EmailSender => src/CommentMap.EmailSender}/Services/IMessageSenderService.cs (100%) rename {CommentMap.EmailSender => src/CommentMap.EmailSender}/Services/ISmtpClientFactory.cs (100%) rename {CommentMap.EmailSender => src/CommentMap.EmailSender}/Services/ISmtpEmailSender.cs (100%) rename {CommentMap.EmailSender => src/CommentMap.EmailSender}/Services/MessageSenderHandler.cs (100%) rename {CommentMap.EmailSender => src/CommentMap.EmailSender}/Services/MessageSenderService.cs (100%) rename {CommentMap.EmailSender => src/CommentMap.EmailSender}/Services/SendMessageConsumer.cs (100%) rename {CommentMap.EmailSender => src/CommentMap.EmailSender}/Services/SmtpClientFactory.cs (100%) rename {CommentMap.EmailSender => src/CommentMap.EmailSender}/Services/SmtpEmailSender.cs (100%) rename {CommentMap.EmailSender => src/CommentMap.EmailSender}/Templates/ChangeEmailViewModel.cs (100%) rename {CommentMap.EmailSender => src/CommentMap.EmailSender}/Templates/ConfirmEmailViewModel.cs (100%) rename {CommentMap.EmailSender => src/CommentMap.EmailSender}/Templates/EmailMessageMjml.cshtml (100%) rename {CommentMap.EmailSender => src/CommentMap.EmailSender}/Templates/IEmailMessageViewModel.cs (100%) rename {CommentMap.EmailSender => src/CommentMap.EmailSender}/Templates/ResetPasswordViewModel.cs (100%) rename {CommentMap.EmailSender => src/CommentMap.EmailSender}/appsettings.json (100%) rename {CommentMap.Infrastructure => src/CommentMap.Infrastructure}/CommentMap.Infrastructure.csproj (100%) rename {CommentMap.Infrastructure => src/CommentMap.Infrastructure}/Data/CommentMapDbContext.cs (100%) rename {CommentMap.Infrastructure => src/CommentMap.Infrastructure}/Data/Configurations/CommentConfiguration.cs (100%) rename {CommentMap.Infrastructure => src/CommentMap.Infrastructure}/Data/Configurations/CountryConfiguration.cs (100%) rename {CommentMap.Infrastructure => src/CommentMap.Infrastructure}/Data/Migrations/20240523173725_InitialMigration.Designer.cs (100%) rename {CommentMap.Infrastructure => src/CommentMap.Infrastructure}/Data/Migrations/20240523173725_InitialMigration.cs (100%) rename {CommentMap.Infrastructure => src/CommentMap.Infrastructure}/Data/Migrations/20240525160654_AddCommentProperties.Designer.cs (100%) rename {CommentMap.Infrastructure => src/CommentMap.Infrastructure}/Data/Migrations/20240525160654_AddCommentProperties.cs (100%) rename {CommentMap.Infrastructure => src/CommentMap.Infrastructure}/Data/Migrations/20240623144537_AddIsDeleted.Designer.cs (100%) rename {CommentMap.Infrastructure => src/CommentMap.Infrastructure}/Data/Migrations/20240623144537_AddIsDeleted.cs (100%) rename {CommentMap.Infrastructure => src/CommentMap.Infrastructure}/Data/Migrations/20240909164708_AddCountry.Designer.cs (100%) rename {CommentMap.Infrastructure => src/CommentMap.Infrastructure}/Data/Migrations/20240909164708_AddCountry.cs (100%) rename {CommentMap.Infrastructure => src/CommentMap.Infrastructure}/Data/Migrations/20240921074639_AddISO3CountryCodeToComment.Designer.cs (100%) rename {CommentMap.Infrastructure => src/CommentMap.Infrastructure}/Data/Migrations/20240921074639_AddISO3CountryCodeToComment.cs (100%) rename {CommentMap.Infrastructure => src/CommentMap.Infrastructure}/Data/Migrations/CommentMapDbContextModelSnapshot.cs (100%) rename {CommentMap.Infrastructure => src/CommentMap.Infrastructure}/DependencyInjection/InfrastructureServiceCollectionExtensions.cs (100%) rename {CommentMap.MigrationService => src/CommentMap.MigrationService}/CommentMap.MigrationService.csproj (100%) rename {CommentMap.MigrationService => src/CommentMap.MigrationService}/Migrator.cs (100%) rename {CommentMap.MigrationService => src/CommentMap.MigrationService}/Program.cs (100%) rename {CommentMap.MigrationService => src/CommentMap.MigrationService}/Properties/launchSettings.json (100%) rename {CommentMap.MigrationService => src/CommentMap.MigrationService}/appsettings.Development.json (100%) rename {CommentMap.MigrationService => src/CommentMap.MigrationService}/appsettings.json (100%) create mode 100644 src/CommentMap.Mvc/Areas/Identity/Pages/Account/AccessDenied.cshtml rename {CommentMap.Mvc => src/CommentMap.Mvc}/Areas/Identity/Pages/Account/AccessDenied.cshtml.cs (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Areas/Identity/Pages/Account/ConfirmEmail.cshtml (72%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Areas/Identity/Pages/Account/ConfirmEmail.cshtml.cs (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Areas/Identity/Pages/Account/ConfirmEmailChange.cshtml (73%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Areas/Identity/Pages/Account/ConfirmEmailChange.cshtml.cs (100%) create mode 100644 src/CommentMap.Mvc/Areas/Identity/Pages/Account/ExternalLogin.cshtml rename {CommentMap.Mvc => src/CommentMap.Mvc}/Areas/Identity/Pages/Account/ExternalLogin.cshtml.cs (100%) create mode 100644 src/CommentMap.Mvc/Areas/Identity/Pages/Account/ForgotPassword.cshtml rename {CommentMap.Mvc => src/CommentMap.Mvc}/Areas/Identity/Pages/Account/ForgotPassword.cshtml.cs (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Areas/Identity/Pages/Account/ForgotPasswordConfirmation.cshtml (74%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Areas/Identity/Pages/Account/ForgotPasswordConfirmation.cshtml.cs (100%) create mode 100644 src/CommentMap.Mvc/Areas/Identity/Pages/Account/Login.cshtml rename {CommentMap.Mvc => src/CommentMap.Mvc}/Areas/Identity/Pages/Account/Login.cshtml.cs (100%) create mode 100644 src/CommentMap.Mvc/Areas/Identity/Pages/Account/LoginWith2fa.cshtml rename {CommentMap.Mvc => src/CommentMap.Mvc}/Areas/Identity/Pages/Account/LoginWith2fa.cshtml.cs (100%) create mode 100644 src/CommentMap.Mvc/Areas/Identity/Pages/Account/LoginWithRecoveryCode.cshtml rename {CommentMap.Mvc => src/CommentMap.Mvc}/Areas/Identity/Pages/Account/LoginWithRecoveryCode.cshtml.cs (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Areas/Identity/Pages/Account/Logout.cshtml (74%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Areas/Identity/Pages/Account/Logout.cshtml.cs (100%) create mode 100644 src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ChangePassword.cshtml rename {CommentMap.Mvc => src/CommentMap.Mvc}/Areas/Identity/Pages/Account/Manage/ChangePassword.cshtml.cs (100%) create mode 100644 src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/DeleteProfile.cshtml rename {CommentMap.Mvc => src/CommentMap.Mvc}/Areas/Identity/Pages/Account/Manage/DeleteProfile.cshtml.cs (100%) create mode 100644 src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/Disable2fa.cshtml rename {CommentMap.Mvc => src/CommentMap.Mvc}/Areas/Identity/Pages/Account/Manage/Disable2fa.cshtml.cs (100%) create mode 100644 src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/EnableAuthenticator.cshtml rename {CommentMap.Mvc => src/CommentMap.Mvc}/Areas/Identity/Pages/Account/Manage/EnableAuthenticator.cshtml.cs (100%) create mode 100644 src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ExternalLogins.cshtml rename {CommentMap.Mvc => src/CommentMap.Mvc}/Areas/Identity/Pages/Account/Manage/ExternalLogins.cshtml.cs (100%) create mode 100644 src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/GenerateRecoveryCodes.cshtml rename {CommentMap.Mvc => src/CommentMap.Mvc}/Areas/Identity/Pages/Account/Manage/GenerateRecoveryCodes.cshtml.cs (100%) create mode 100644 src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/Index.cshtml rename {CommentMap.Mvc => src/CommentMap.Mvc}/Areas/Identity/Pages/Account/Manage/Index.cshtml.cs (100%) create mode 100644 src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ResetAuthenticator.cshtml rename {CommentMap.Mvc => src/CommentMap.Mvc}/Areas/Identity/Pages/Account/Manage/ResetAuthenticator.cshtml.cs (100%) create mode 100644 src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/SetPassword.cshtml rename {CommentMap.Mvc => src/CommentMap.Mvc}/Areas/Identity/Pages/Account/Manage/SetPassword.cshtml.cs (100%) create mode 100644 src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ShowRecoveryCodes.cshtml rename {CommentMap.Mvc => src/CommentMap.Mvc}/Areas/Identity/Pages/Account/Manage/ShowRecoveryCodes.cshtml.cs (100%) create mode 100644 src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/TwoFactorAuthentication.cshtml rename {CommentMap.Mvc => src/CommentMap.Mvc}/Areas/Identity/Pages/Account/Manage/TwoFactorAuthentication.cshtml.cs (100%) create mode 100644 src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/_Layout.cshtml create mode 100644 src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/_ManageNav.cshtml create mode 100644 src/CommentMap.Mvc/Areas/Identity/Pages/Account/Register.cshtml rename {CommentMap.Mvc => src/CommentMap.Mvc}/Areas/Identity/Pages/Account/Register.cshtml.cs (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Areas/Identity/Pages/Account/RegisterConfirmation.cshtml (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Areas/Identity/Pages/Account/RegisterConfirmation.cshtml.cs (100%) create mode 100644 src/CommentMap.Mvc/Areas/Identity/Pages/Account/ResendEmailConfirmation.cshtml rename {CommentMap.Mvc => src/CommentMap.Mvc}/Areas/Identity/Pages/Account/ResendEmailConfirmation.cshtml.cs (100%) create mode 100644 src/CommentMap.Mvc/Areas/Identity/Pages/Account/ResetPassword.cshtml rename {CommentMap.Mvc => src/CommentMap.Mvc}/Areas/Identity/Pages/Account/ResetPassword.cshtml.cs (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Areas/Identity/Pages/Account/ResetPasswordConfirmation.cshtml (78%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Areas/Identity/Pages/Account/ResetPasswordConfirmation.cshtml.cs (100%) create mode 100644 src/CommentMap.Mvc/Areas/Identity/Pages/_StatusMessage.cshtml rename {CommentMap.Mvc => src/CommentMap.Mvc}/Areas/Identity/Pages/_ViewImports.cshtml (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Areas/Identity/Pages/_ViewStart.cshtml (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/CommentMap.Mvc.csproj (91%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Extensions/ClaimsPrincipalExtensions.cs (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Internal/Generated/WolverineHandlers/AddCommentHandler838741630.cs (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Internal/Generated/WolverineHandlers/ChangePasswordHandler702758377.cs (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Internal/Generated/WolverineHandlers/ConfirmEmailChangeHandler1497850754.cs (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Internal/Generated/WolverineHandlers/ConfirmEmailHandler55631218.cs (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Internal/Generated/WolverineHandlers/CreateExternalUserHandler966620274.cs (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Internal/Generated/WolverineHandlers/DeleteCommentHandler107828254.cs (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Internal/Generated/WolverineHandlers/DeleteProfileHandler1834710062.cs (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Internal/Generated/WolverineHandlers/Disable2faHandler1923519541.cs (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Internal/Generated/WolverineHandlers/EnableAuthenticatorHandler897587120.cs (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Internal/Generated/WolverineHandlers/ExternalLoginSignInHandler1809594924.cs (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Internal/Generated/WolverineHandlers/ForgetTwoFactorClientHandler253588197.cs (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Internal/Generated/WolverineHandlers/ForgotPasswordHandler1306123444.cs (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Internal/Generated/WolverineHandlers/GenerateRecoveryCodesHandler711237032.cs (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Internal/Generated/WolverineHandlers/GeneratedHandlerRegistry.cs (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Internal/Generated/WolverineHandlers/GetAuthenticatorSetupHandler507613430.cs (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Internal/Generated/WolverineHandlers/GetCommentTitleHandler595995119.cs (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Internal/Generated/WolverineHandlers/GetCountryHandler1133281984.cs (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Internal/Generated/WolverineHandlers/GetDeleteProfileInfoHandler900389426.cs (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Internal/Generated/WolverineHandlers/GetExternalLoginsHandler199405825.cs (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Internal/Generated/WolverineHandlers/GetProfileEmailHandler1046567855.cs (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Internal/Generated/WolverineHandlers/GetTwoFactorStatusHandler1213804985.cs (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Internal/Generated/WolverineHandlers/HasPasswordHandler1751871263.cs (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Internal/Generated/WolverineHandlers/LinkExternalLoginHandler251495890.cs (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Internal/Generated/WolverineHandlers/ListCommentsHandler488515704.cs (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Internal/Generated/WolverineHandlers/LoginUserHandler1789921628.cs (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Internal/Generated/WolverineHandlers/LoginWith2faHandler292869486.cs (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Internal/Generated/WolverineHandlers/LoginWithRecoveryCodeHandler277354287.cs (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Internal/Generated/WolverineHandlers/LogoutUserHandler132148485.cs (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Internal/Generated/WolverineHandlers/RegisterUserHandler1265692392.cs (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Internal/Generated/WolverineHandlers/RemoveExternalLoginHandler62493602.cs (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Internal/Generated/WolverineHandlers/RequestEmailChangeHandler172865511.cs (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Internal/Generated/WolverineHandlers/ResendEmailConfirmationHandler19836290.cs (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Internal/Generated/WolverineHandlers/ResetAuthenticatorHandler25524780.cs (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Internal/Generated/WolverineHandlers/ResetPasswordHandler433488700.cs (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Internal/Generated/WolverineHandlers/SetPasswordHandler836449791.cs (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Internal/Generated/WolverineHandlers/SignInAfterRegistrationHandler2047984407.cs (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Models/AddNewCommentInput.cs (100%) create mode 100644 src/CommentMap.Mvc/Pages/Comments/Add.cshtml rename {CommentMap.Mvc => src/CommentMap.Mvc}/Pages/Comments/Add.cshtml.cs (100%) create mode 100644 src/CommentMap.Mvc/Pages/Comments/Add.cshtml.ts create mode 100644 src/CommentMap.Mvc/Pages/Comments/ConfirmDelete.cshtml rename {CommentMap.Mvc => src/CommentMap.Mvc}/Pages/Comments/ConfirmDelete.cshtml.cs (100%) create mode 100644 src/CommentMap.Mvc/Pages/Comments/Index.cshtml rename {CommentMap.Mvc => src/CommentMap.Mvc}/Pages/Comments/Index.cshtml.cs (100%) create mode 100644 src/CommentMap.Mvc/Pages/Comments/Index.cshtml.ts create mode 100644 src/CommentMap.Mvc/Pages/Countries/Index.cshtml rename {CommentMap.Mvc => src/CommentMap.Mvc}/Pages/Countries/Index.cshtml.cs (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Pages/Error.cshtml (86%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Pages/Error.cshtml.cs (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Pages/Index.cshtml (68%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Pages/Index.cshtml.cs (100%) create mode 100644 src/CommentMap.Mvc/Pages/Shared/Components/SignInPanel/Default.cshtml create mode 100644 src/CommentMap.Mvc/Pages/Shared/_CommentCardPartial.cshtml create mode 100644 src/CommentMap.Mvc/Pages/Shared/_Layout.cshtml rename {CommentMap.Mvc => src/CommentMap.Mvc}/Pages/Shared/_ValidationScriptsPartial.cshtml (58%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Pages/_ViewImports.cshtml (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Pages/_ViewStart.cshtml (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Program.cs (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/Properties/launchSettings.json (100%) create mode 100644 src/CommentMap.Mvc/Scripts/site.ts create mode 100644 src/CommentMap.Mvc/Styles/app.css rename {CommentMap.Mvc => src/CommentMap.Mvc}/TagHelpers/AnchorTagHelper.cs (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/ViewComponents/SignInPanelViewComponent.cs (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/ViewModels/CommentCardViewModel.cs (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/ViewModels/CountryViewModel.cs (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/ViewModels/LocationViewModel.cs (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/ViewModels/SignInPanelViewModel.cs (100%) rename {CommentMap.Mvc => src/CommentMap.Mvc}/appsettings.json (100%) create mode 100644 src/CommentMap.Mvc/build/build.js create mode 100644 src/CommentMap.Mvc/package-lock.json create mode 100644 src/CommentMap.Mvc/package.json create mode 100644 src/CommentMap.Mvc/tsconfig.json rename {CommentMap.ServiceDefaults => src/CommentMap.ServiceDefaults}/CommentMap.ServiceDefaults.csproj (100%) rename {CommentMap.ServiceDefaults => src/CommentMap.ServiceDefaults}/Extensions.cs (100%) rename {CommentMap.Shared => src/CommentMap.Shared}/CommentMap.Shared.csproj (100%) rename {CommentMap.Shared => src/CommentMap.Shared}/Messages/SendChangeEmail.cs (100%) rename {CommentMap.Shared => src/CommentMap.Shared}/Messages/SendConfirmEmail.cs (100%) rename {CommentMap.Shared => src/CommentMap.Shared}/Messages/SendResetPasswordEmail.cs (100%) diff --git a/.github/workflows/publish-container.yml b/.github/workflows/publish-container.yml index 644ddb1..3df9a32 100644 --- a/.github/workflows/publish-container.yml +++ b/.github/workflows/publish-container.yml @@ -51,7 +51,7 @@ jobs: id: build-and-push uses: docker/build-push-action@v6 with: - context: ./CommentMap.Mvc + context: ./src/CommentMap.Mvc push: ${{ github.event_name != 'pull_request' }} tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} diff --git a/.gitignore b/.gitignore index 0808c4a..936466e 100644 --- a/.gitignore +++ b/.gitignore @@ -38,7 +38,8 @@ bld/ # Visual Studio 2015/2017 cache/options directory .vs/ # Uncomment if you have tasks that create the project's static files in wwwroot -#wwwroot/ +wwwroot/ +!wwwroot/assets # Visual Studio 2017 auto generated files Generated\ Files/ diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..e13d1b9 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,39 @@ +# CommentMap — Agent Guide + +## Run + +- Prereqs: .NET 10 SDK, Node.js, Docker (Aspire runs containers). +- `dotnet tool restore` — restores pinned local tools (`dotnet-ef`, `aspire`, `roslyn-language-server`). +- `dotnet run --project src/CommentMap.AppHost` — starts PostGIS + RabbitMQ + MailPit containers and all services. The MVC app waits for MigrationService to apply EF migrations before starting. +- Dev params for RabbitMQ/Postgres live in `src/CommentMap.AppHost/appsettings.Development.json`. Google OAuth keys come from user secrets (`Authentication:Google:ClientId` / `ClientSecret`). + +## Build & Frontend + +- `dotnet build` automatically runs `npm install` + `npm run build` in `CommentMap.Mvc/` (a `BuildJS` target in the csproj) — no separate frontend step. +- Frontend entrypoints are hardcoded in `CommentMap.Mvc/build/build.js`. Adding a new `.ts` page script requires registering it there, or it will silently not be built. +- Stack: esbuild + Tailwind v4 (via PostCSS) + daisyUI + OpenLayers (`ol`). Output goes to `CommentMap.Mvc/wwwroot/{js,css}`. All projects live under `src/`. + +## Architecture + +- Aspire AppHost (`CommentMap.AppHost/AppHost.cs`) orchestrates: `postgis/postgis:18-3.6` (+ pgAdmin), RabbitMQ 4.3.4 (management plugin), MailPit. The EF connection string name is `"comment-map"` (Aspire resource name, not a config-section path). +- Razor Pages page models never touch EF directly. They call `IMessageBus.InvokeAsync(...)` (Wolverine) with a message record; handlers are static classes in `CommentMap.Application/Features/**` — one file per message, `record Xxx` + `static class XxxHandler` with a `Handle` method. Follow this pattern for new features. +- DB access goes through `ICommentMapDbContext` (`CommentMap.Application/Abstractions`), implemented by `CommentMapDbContext` in Infrastructure. Spatial data uses NetTopologySuite `Point` with SRID 3857 against PostGIS. +- Email flow: Mvc publishes `CommentMap.Shared/Messages/*` records to RabbitMQ queues named `nameof(Message)`; EmailSender listens on the same names, renders a RazorBlade `.cshtml` template to MJML (Mjml.Net), and sends via MailKit SMTP (MailPit in dev — check its UI for confirmation emails, since `RequireConfirmedAccount = true`). + +## Wolverine codegen (important) + +- Mvc and EmailSender both set `TypeLoadMode.Static`. The generated handlers under `*/Internal/Generated/WolverineHandlers/` are **committed to git** — do not hand-edit or delete them. +- After adding or changing a message handler, regenerate: + `dotnet run --project src/CommentMap.Mvc -- codegen write` (same for `CommentMap.EmailSender`). +- Wolverine handler discovery includes the `CommentMap.Application` assembly (see Mvc `Program.cs`) — handlers added there are picked up automatically. + +## EF Core / Migrations + +- Add a migration: `dotnet ef migrations add --project src/CommentMap.Infrastructure --startup-project src/CommentMap.Mvc` +- Do NOT run `dotnet ef database update` locally — MigrationService applies migrations automatically at startup. + +## Conventions & Gotchas + +- No test projects, no CI workflows, no lint/format config — verification = build + run via AppHost. +- `opencode.json` configures the C# LSP via the local `roslyn-language-server` tool; run `dotnet tool restore` first or the LSP won't start. +- Solution file is `CommentMap.slnx` (XML format), not `.sln`. diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/AccessDenied.cshtml b/CommentMap.Mvc/Areas/Identity/Pages/Account/AccessDenied.cshtml deleted file mode 100644 index 017f6ff..0000000 --- a/CommentMap.Mvc/Areas/Identity/Pages/Account/AccessDenied.cshtml +++ /dev/null @@ -1,10 +0,0 @@ -@page -@model AccessDeniedModel -@{ - ViewData["Title"] = "Access denied"; -} - -
-

@ViewData["Title"]

-

You do not have access to this resource.

-
diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/ExternalLogin.cshtml b/CommentMap.Mvc/Areas/Identity/Pages/Account/ExternalLogin.cshtml deleted file mode 100644 index c31f4fb..0000000 --- a/CommentMap.Mvc/Areas/Identity/Pages/Account/ExternalLogin.cshtml +++ /dev/null @@ -1,33 +0,0 @@ -@page -@model ExternalLoginModel -@{ - ViewData["Title"] = "Register"; -} - -

@ViewData["Title"]

-

Associate your @Model.ProviderDisplayName account.

-
- -

- You've successfully authenticated with @Model.ProviderDisplayName. - Please enter an username for this site below and click the Register button to finish - logging in. -

- -
-
- - -
- - - -
- - -
-
- -@section Scripts { - -} diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/ForgotPassword.cshtml b/CommentMap.Mvc/Areas/Identity/Pages/Account/ForgotPassword.cshtml deleted file mode 100644 index 106b8d1..0000000 --- a/CommentMap.Mvc/Areas/Identity/Pages/Account/ForgotPassword.cshtml +++ /dev/null @@ -1,26 +0,0 @@ -@page -@model ForgotPasswordModel -@{ - ViewData["Title"] = "Forgot your password?"; -} - -

@ViewData["Title"]

-

Enter your email.

-
-
-
-
- -
- - - -
- -
-
-
- -@section Scripts { - -} diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/Login.cshtml b/CommentMap.Mvc/Areas/Identity/Pages/Account/Login.cshtml deleted file mode 100644 index dbf9fe6..0000000 --- a/CommentMap.Mvc/Areas/Identity/Pages/Account/Login.cshtml +++ /dev/null @@ -1,66 +0,0 @@ -@page -@model LoginModel - -@{ - ViewData["Title"] = "Log in"; -} - -

@ViewData["Title"]

- -
-
-
-
-

Use a local account to log in.

-
- -
- - - -
-
- - - -
-
- -
-
- -
- -
-
-
-
-
-

Use another service to log in.

-
-
- @foreach (var provider in Model.ExternalLogins!) - { - - } -
-
-
-
- -@section Scripts { - -} diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/LoginWith2fa.cshtml b/CommentMap.Mvc/Areas/Identity/Pages/Account/LoginWith2fa.cshtml deleted file mode 100644 index 3c20b19..0000000 --- a/CommentMap.Mvc/Areas/Identity/Pages/Account/LoginWith2fa.cshtml +++ /dev/null @@ -1,39 +0,0 @@ -@page -@model LoginWith2faModel -@{ - ViewData["Title"] = "Two-factor authentication"; -} - -

@ViewData["Title"]

-
-

Your login is protected with an authenticator app. Enter your authenticator code below.

-
-
-
- - -
- - - -
-
- -
-
- -
-
-
-
-

- Don't have access to your authenticator device? You can - log in with a recovery code. -

- -@section Scripts { - -} \ No newline at end of file diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/LoginWithRecoveryCode.cshtml b/CommentMap.Mvc/Areas/Identity/Pages/Account/LoginWithRecoveryCode.cshtml deleted file mode 100644 index 0d44e37..0000000 --- a/CommentMap.Mvc/Areas/Identity/Pages/Account/LoginWithRecoveryCode.cshtml +++ /dev/null @@ -1,29 +0,0 @@ -@page -@model LoginWithRecoveryCodeModel -@{ - ViewData["Title"] = "Recovery code verification"; -} - -

@ViewData["Title"]

-
-

- You have requested to log in with a recovery code. This login will not be remembered until you provide - an authenticator app code at log in or disable 2FA and log in again. -

-
-
-
- -
- - - -
- -
-
-
- -@section Scripts { - -} \ No newline at end of file diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ChangePassword.cshtml b/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ChangePassword.cshtml deleted file mode 100644 index 9f72800..0000000 --- a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ChangePassword.cshtml +++ /dev/null @@ -1,37 +0,0 @@ -@page -@model ChangePasswordModel -@{ - ViewData["Title"] = "Change password"; -} - -

@ViewData["Title"]

- - - -
-
-
- -
- - - -
-
- - - -
-
- - - -
- -
-
-
- -@section Scripts { - -} diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/DeleteProfile.cshtml b/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/DeleteProfile.cshtml deleted file mode 100644 index c607cd5..0000000 --- a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/DeleteProfile.cshtml +++ /dev/null @@ -1,35 +0,0 @@ -@page -@model DeletePersonalDataModel -@{ - ViewData["Title"] = "Delete your profile"; -} - -

@ViewData["Title"]

- - - -
-
-
- - @if (Model.RequirePassword) - { -
- - - -
- } - -
-
-
- -@section Scripts { - -} diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/Disable2fa.cshtml b/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/Disable2fa.cshtml deleted file mode 100644 index 9853e35..0000000 --- a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/Disable2fa.cshtml +++ /dev/null @@ -1,22 +0,0 @@ -@page -@model Disable2faModel -@{ - ViewData["Title"] = "Disable two-factor authentication (2FA)"; -} - - -

@ViewData["Title"]

- - - -
- -
diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/EnableAuthenticator.cshtml b/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/EnableAuthenticator.cshtml deleted file mode 100644 index 1b33af6..0000000 --- a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/EnableAuthenticator.cshtml +++ /dev/null @@ -1,52 +0,0 @@ -@page -@model EnableAuthenticatorModel -@{ - ViewData["Title"] = "Configure authenticator app"; -} - - - -

@ViewData["Title"]

- -
-

To use an authenticator app go through the following steps:

-
    -
  1. -

    - Download a two-factor authenticator app like Microsoft Authenticator for - Android and - iOS or - Google Authenticator for - Android and - iOS. -

    -
  2. -
  3. -

    Scan the QR Code or enter this key @Model.SharedKey into your two factor authenticator app. Spaces and casing do not matter.

    - @Model.AuthenticatorUri -
  4. -
  5. -

    - Once you have scanned the QR code or input the key above, your two factor authentication app will provide you - with a unique code. Enter the code in the confirmation box below. -

    -
    -
    -
    -
    - - - -
    - - -
    -
    -
    -
  6. -
-
- -@section Scripts { - -} diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ExternalLogins.cshtml b/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ExternalLogins.cshtml deleted file mode 100644 index b54cc37..0000000 --- a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ExternalLogins.cshtml +++ /dev/null @@ -1,45 +0,0 @@ -@page -@model ExternalLoginsModel -@{ - ViewData["Title"] = "Manage your external logins"; -} - - - -@if (Model.CurrentLogins?.Count > 0) -{ -

Registered logins

- - - @foreach (var login in Model.CurrentLogins) - { - - - @if (Model.ShowRemoveButton) - { - - } - - } - -
@login.ProviderDisplayName -
-
- - - -
-
-
-} -@if (Model.OtherLogins?.Count > 0) -{ -

Add another service to log in.

-
-
- @foreach (var provider in Model.OtherLogins) - { - - } -
-} diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/GenerateRecoveryCodes.cshtml b/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/GenerateRecoveryCodes.cshtml deleted file mode 100644 index 048a485..0000000 --- a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/GenerateRecoveryCodes.cshtml +++ /dev/null @@ -1,24 +0,0 @@ -@page -@model GenerateRecoveryCodesModel -@{ - ViewData["Title"] = "Generate two-factor authentication (2FA) recovery codes"; -} - - -

@ViewData["Title"]

- -
- -
diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/Index.cshtml b/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/Index.cshtml deleted file mode 100644 index 4db0776..0000000 --- a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/Index.cshtml +++ /dev/null @@ -1,35 +0,0 @@ -@page -@model IndexModel -@{ - ViewData["Title"] = "Manage Email"; -} - -

@ViewData["Title"]

- - - -
-
-
- - -
- - - -
- -
- - - -
- - -
-
-
- -@section Scripts { - -} diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ResetAuthenticator.cshtml b/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ResetAuthenticator.cshtml deleted file mode 100644 index 035bd60..0000000 --- a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ResetAuthenticator.cshtml +++ /dev/null @@ -1,21 +0,0 @@ -@page -@model ResetAuthenticatorModel -@{ - ViewData["Title"] = "Reset authenticator key"; -} - - -

@ViewData["Title"]

- -
- -
\ No newline at end of file diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/SetPassword.cshtml b/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/SetPassword.cshtml deleted file mode 100644 index 9a3a48e..0000000 --- a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/SetPassword.cshtml +++ /dev/null @@ -1,36 +0,0 @@ -@page -@model SetPasswordModel -@{ - ViewData["Title"] = "Set password"; -} - -

Set your password

- - - -

- You do not have a local password for this site. Add a local account - so you can log in without an external login. -

-
-
-
- -
- - - -
-
- - - -
- -
-
-
- -@section Scripts { - -} diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ShowRecoveryCodes.cshtml b/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ShowRecoveryCodes.cshtml deleted file mode 100644 index 304f554..0000000 --- a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ShowRecoveryCodes.cshtml +++ /dev/null @@ -1,24 +0,0 @@ -@page -@model ShowRecoveryCodesModel -@{ - ViewData["Title"] = "Recovery codes"; -} - - -

@ViewData["Title"]

- -
-
- @for (var row = 0; row < Model.RecoveryCodes.Length; row += 2) - { - @Model.RecoveryCodes[row] @Model.RecoveryCodes[row + 1]
- } -
-
diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/TwoFactorAuthentication.cshtml b/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/TwoFactorAuthentication.cshtml deleted file mode 100644 index 1d192f0..0000000 --- a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/TwoFactorAuthentication.cshtml +++ /dev/null @@ -1,70 +0,0 @@ -@page -@using Microsoft.AspNetCore.Http.Features -@model TwoFactorAuthenticationModel -@{ - ViewData["Title"] = "Two-factor authentication (2FA)"; -} - - -

@ViewData["Title"]

-@{ - var consentFeature = HttpContext.Features.Get(); - @if (consentFeature?.CanTrack ?? true) - { - @if (Model.Is2faEnabled) - { - if (Model.RecoveryCodesLeft == 0) - { -
- You have no recovery codes left. -

You must generate a new set of recovery codes before you can log in with a recovery code.

-
- } - else if (Model.RecoveryCodesLeft == 1) - { -
- You have 1 recovery code left. -

You can generate a new set of recovery codes.

-
- } - else if (Model.RecoveryCodesLeft <= 3) - { -
- You have @Model.RecoveryCodesLeft recovery codes left. -

You should generate a new set of recovery codes.

-
- } - - if (Model.IsMachineRemembered) - { -
- -
- } - Disable 2FA - Reset recovery codes - } - -

Authenticator app

- @if (!Model.HasAuthenticator) - { - Add authenticator app - } - else - { - Set up authenticator app - Reset authenticator app - } - } - else - { -
- Privacy and cookie policy have not been accepted. -

You must accept the policy before you can enable two factor authentication.

-
- } -} - -@section Scripts { - -} diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/_Layout.cshtml b/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/_Layout.cshtml deleted file mode 100644 index 25ae720..0000000 --- a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/_Layout.cshtml +++ /dev/null @@ -1,22 +0,0 @@ -@{ - Layout = "/Pages/Shared/_Layout.cshtml"; -} - -

Manage your account

- -
-

Change your account settings

-
-
-
- -
-
- @RenderBody() -
-
-
- -@section Scripts { - @RenderSection("Scripts", required: false) -} diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/_ManageNav.cshtml b/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/_ManageNav.cshtml deleted file mode 100644 index 5d148c3..0000000 --- a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/_ManageNav.cshtml +++ /dev/null @@ -1,17 +0,0 @@ - diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/Register.cshtml b/CommentMap.Mvc/Areas/Identity/Pages/Account/Register.cshtml deleted file mode 100644 index 929a205..0000000 --- a/CommentMap.Mvc/Areas/Identity/Pages/Account/Register.cshtml +++ /dev/null @@ -1,56 +0,0 @@ -@page -@model RegisterModel -@{ - ViewData["Title"] = "Register"; -} - -

@ViewData["Title"]

- -
-
-
-

Create a new account.

-
- -
- - - -
-
- - - -
-
- - - -
-
- -
- -
-
-
-
-

Use another service to register.

-
-
- @foreach (var provider in Model.ExternalLogins!) - { - - } -
-
-
-
- -@section Scripts { - -} diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/ResendEmailConfirmation.cshtml b/CommentMap.Mvc/Areas/Identity/Pages/Account/ResendEmailConfirmation.cshtml deleted file mode 100644 index 0bbf8fd..0000000 --- a/CommentMap.Mvc/Areas/Identity/Pages/Account/ResendEmailConfirmation.cshtml +++ /dev/null @@ -1,27 +0,0 @@ -@page -@model ResendEmailConfirmationModel -@{ - ViewData["Title"] = "Resend email confirmation"; -} - -

@ViewData["Title"]

- - - -

Enter your email.

-
-
-
-
- - - -
- -
-
-
- -@section Scripts { - -} diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/ResetPassword.cshtml b/CommentMap.Mvc/Areas/Identity/Pages/Account/ResetPassword.cshtml deleted file mode 100644 index 1bc8ad8..0000000 --- a/CommentMap.Mvc/Areas/Identity/Pages/Account/ResetPassword.cshtml +++ /dev/null @@ -1,31 +0,0 @@ -@page -@model ResetPasswordModel -@{ - ViewData["Title"] = "Reset password"; -} - -

@ViewData["Title"]

-

Reset your password.

-
-
-
-
- -
- - - -
-
- - - -
- -
-
-
- -@section Scripts { - -} diff --git a/CommentMap.Mvc/Areas/Identity/Pages/_StatusMessage.cshtml b/CommentMap.Mvc/Areas/Identity/Pages/_StatusMessage.cshtml deleted file mode 100644 index c898543..0000000 --- a/CommentMap.Mvc/Areas/Identity/Pages/_StatusMessage.cshtml +++ /dev/null @@ -1,10 +0,0 @@ -@model string - -@if (!String.IsNullOrEmpty(Model)) -{ - var statusMessageClass = Model.StartsWith("Error") ? "danger" : "success"; - -} diff --git a/CommentMap.Mvc/Pages/Comments/Add.cshtml b/CommentMap.Mvc/Pages/Comments/Add.cshtml deleted file mode 100644 index e77fca0..0000000 --- a/CommentMap.Mvc/Pages/Comments/Add.cshtml +++ /dev/null @@ -1,56 +0,0 @@ -@page -@model AddModel -@{ - ViewData["Title"] = "Add new comment"; -} - -@section Styles { - -} - -

Add new comment

- -
-
-
-
-
- - -
-
Your title must be 1-100 characters long.
- -
- -
-
- - -
-
Your text must be 1-250 characters long.
- -
- -
- - -
- -
- - -
- - -
-
-
-
-
-
- -@section Scripts { - - - -} diff --git a/CommentMap.Mvc/Pages/Comments/ConfirmDelete.cshtml b/CommentMap.Mvc/Pages/Comments/ConfirmDelete.cshtml deleted file mode 100644 index b314a45..0000000 --- a/CommentMap.Mvc/Pages/Comments/ConfirmDelete.cshtml +++ /dev/null @@ -1,15 +0,0 @@ -@page -@model ConfirmDeleteModel -@{ - ViewData["Title"] = "Confirm deletion"; -} - -
-
-

Confirm deletion

-

Are you sure you want to delete "@Model.Title" comment?

-
- -
-
-
diff --git a/CommentMap.Mvc/Pages/Comments/Index.cshtml b/CommentMap.Mvc/Pages/Comments/Index.cshtml deleted file mode 100644 index fef0858..0000000 --- a/CommentMap.Mvc/Pages/Comments/Index.cshtml +++ /dev/null @@ -1,58 +0,0 @@ -@page -@model IndexModel -@{ - ViewData["Title"] = "My comments"; - var selectedOrder = (int)Model.SelectedOrder; - ViewData["SelectedOrder"] = selectedOrder; -} - -@section Styles { - -} - -

My comments

- - - -@if (Model.Comments is not null && Model.Comments.Count > 0) -{ -
-
-
- @foreach (var comment in Model.Comments) - { -
- -
- } -
-
-
-
-
-
-} -else -{ -

There is no comments :(

-} - -@section Scripts { - - -} diff --git a/CommentMap.Mvc/Pages/Countries/Index.cshtml b/CommentMap.Mvc/Pages/Countries/Index.cshtml deleted file mode 100644 index 0b1e63d..0000000 --- a/CommentMap.Mvc/Pages/Countries/Index.cshtml +++ /dev/null @@ -1,40 +0,0 @@ -@page -@model IndexModel -@{ - ViewData["Title"] = "Country"; -} - -@if (ModelState.ErrorCount > 0) -{ -
- return; -} - -@if (Model.Country is null) -{ -

Oops... There is no country with code "@Model.ISO3Code"

- return; -} - - - - - - - - - - - - - - - - - - - - - - -
ISO 3166-1 alpha-3@Model.Country.ISO3Code
ISO 3166-1 alpha-2@Model.Country.ISO2Code
Name@Model.Country.Name
Region name@Model.Country.RegionName
Subregion name@Model.Country.SubregionName
diff --git a/CommentMap.Mvc/Pages/Shared/Components/SignInPanel/Default.cshtml b/CommentMap.Mvc/Pages/Shared/Components/SignInPanel/Default.cshtml deleted file mode 100644 index 5f221b0..0000000 --- a/CommentMap.Mvc/Pages/Shared/Components/SignInPanel/Default.cshtml +++ /dev/null @@ -1,25 +0,0 @@ -@using CommentMap.Mvc.ViewModels -@model SignInPanelViewModel - - diff --git a/CommentMap.Mvc/Pages/Shared/_CommentCardPartial.cshtml b/CommentMap.Mvc/Pages/Shared/_CommentCardPartial.cshtml deleted file mode 100644 index a148874..0000000 --- a/CommentMap.Mvc/Pages/Shared/_CommentCardPartial.cshtml +++ /dev/null @@ -1,29 +0,0 @@ -@using CommentMap.Mvc.ViewModels -@using Humanizer -@model CommentCardViewModel -@{ - var elapsedInterval = DateTime.UtcNow - Model.CreatedAt; - var coordinates = Model.Location.GetJsonArray(); -} - -
-
@Model.Title
-
-

@Model.Text

-
- - - - Edit - - - - Delete - -
-
- -
diff --git a/CommentMap.Mvc/Pages/Shared/_Layout.cshtml b/CommentMap.Mvc/Pages/Shared/_Layout.cshtml deleted file mode 100644 index d417989..0000000 --- a/CommentMap.Mvc/Pages/Shared/_Layout.cshtml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - @ViewData["Title"] - CommentMap.Mvc - - - - - - - - - @await RenderSectionAsync("Styles", required: false) - - -
- -
- -
- @RenderBody() -
- - - - - @await RenderSectionAsync("Scripts", required: false) - - \ No newline at end of file diff --git a/CommentMap.Mvc/Scripts/AddComment.ts b/CommentMap.Mvc/Scripts/AddComment.ts deleted file mode 100644 index 5889642..0000000 --- a/CommentMap.Mvc/Scripts/AddComment.ts +++ /dev/null @@ -1,14 +0,0 @@ -import AddCommentViewModel from "./AddCommentViewModel"; - -$(() => { - const root = document.getElementById("root"); - if (!root) { - return; - } - - const longitude = root.querySelector("[data-bind=\"value: localLongitude\"]").getAttribute("value"); - const latitude = root.querySelector("[data-bind=\"value: localLatitude\"]").getAttribute("value"); - const locale = root.querySelector("[data-locale]").getAttribute("data-locale"); - - ko.applyBindings(new AddCommentViewModel(Number(longitude), Number(latitude), locale), root); -}) diff --git a/CommentMap.Mvc/Scripts/AddCommentViewModel.ts b/CommentMap.Mvc/Scripts/AddCommentViewModel.ts deleted file mode 100644 index 15c487a..0000000 --- a/CommentMap.Mvc/Scripts/AddCommentViewModel.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { Coordinate } from "ol/coordinate"; -import Map from "ol/Map"; -import { Tile as TileLayer, Vector as VectorLayer } from "ol/layer"; -import { XYZ, Vector as VectorSource } from "ol/source"; -import { FullScreen, defaults as defaultControls } from "ol/control"; -import View from "ol/View"; -import Draw, { DrawEvent } from 'ol/interaction/Draw'; -import Point from "ol/geom/Point"; -import Feature from "ol/Feature"; - - -export default class AddCommentViewModel { - public longitude: KnockoutObservable; - public latitude: KnockoutObservable; - - private _intl: Intl.NumberFormat; - private _vectorSource: VectorSource>; - private _map: Map; - - constructor(longitude: number, latitude: number, locale: string) { - this.setPoint = this.setPoint.bind(this); - - this.longitude = ko.observable(longitude); - this.latitude = ko.observable(latitude); - - this._intl = new Intl.NumberFormat(locale, { maximumFractionDigits: 10 }); - this._vectorSource = new VectorSource>(); - - this._map = new Map({ - target: "map", - layers: [ - new TileLayer({ - source: new XYZ({ - url: "https://mt0.google.com/vt/lyrs=m&hl=en&x={x}&y={y}&z={z}", - }), - }), - new VectorLayer({ - source: this._vectorSource - }) - ], - view: new View({ - center: this.getCoordinate(), - zoom: 4, - projection: "EPSG:3857" - }), - controls: defaultControls().extend([new FullScreen()]), - }); - - this.restorePoint(); - this.addInteraction(); - } - - private getCoordinate(): Coordinate { - const longitude = this.longitude(); - const latitude = this.latitude(); - - return [longitude, latitude]; - } - - private addInteraction() { - const drawInteraction = new Draw({ - source: this._vectorSource, - type: "Point" - }); - drawInteraction.on("drawend", this.setPoint); - this._map.addInteraction(drawInteraction); - } - - private setPoint({ feature }: DrawEvent) { - this._vectorSource.clear(true); - const geometry = feature.getGeometry(); - if (geometry instanceof Point) { - const coordinate = geometry.getCoordinates(); - this.setCoordinate(coordinate); - } - } - - private setCoordinate(coordinates: Coordinate) { - this.longitude(coordinates[0]); - this.latitude(coordinates[1]); - } - - private restorePoint() { - const longitude = this.longitude(); - const latitude = this.latitude(); - - const point = new Point([longitude, latitude]); - const feature = new Feature(point); - this._vectorSource.addFeature(feature); - } - - public get localLongitude() { - return this._intl.format(this.longitude()).replace(/\s/g, "");; - } - - public get localLatitude() { - return this._intl.format(this.latitude()).replace(/\s/g, ""); - } -} diff --git a/CommentMap.Mvc/Scripts/Comments.ts b/CommentMap.Mvc/Scripts/Comments.ts deleted file mode 100644 index 9199ae2..0000000 --- a/CommentMap.Mvc/Scripts/Comments.ts +++ /dev/null @@ -1,14 +0,0 @@ -import CommentsViewModel from "./CommentsViewModel"; - -$(() => { - const root = document.getElementById("root"); - if (!root) { - return; - } - - const elements = document.querySelectorAll("[data-location]"); - const coordinates: [number, number][] = Array.from(elements) - .map((element) => JSON.parse(element.getAttribute("data-location"))); - - ko.applyBindings(new CommentsViewModel(coordinates), root); -}); diff --git a/CommentMap.Mvc/Scripts/CommentsViewModel.ts b/CommentMap.Mvc/Scripts/CommentsViewModel.ts deleted file mode 100644 index 378338a..0000000 --- a/CommentMap.Mvc/Scripts/CommentsViewModel.ts +++ /dev/null @@ -1,72 +0,0 @@ -import Map from "ol/Map"; -import { Tile as TileLayer, Vector as VectorLayer } from "ol/layer"; -import { XYZ, Vector as VectorSource } from "ol/source"; -import { FullScreen, defaults as defaultControls } from "ol/control"; -import { Coordinate } from "ol/coordinate"; -import View from "ol/View"; -import Feature from "ol/Feature"; -import { Point } from "ol/geom"; -import { Icon, Style } from "ol/style"; - - -export default class CommentsViewModel { - private static readonly DEFAULT_ZOOM = 10; - - private static readonly MARKER_ICON_STYLE = new Style({ - image: new Icon({ - anchor: [0.5, 22], - anchorXUnits: "fraction", - anchorYUnits: "pixels", - src: "/assets/marker.svg", - }), - }); - - private readonly _map: Map; - - constructor(private readonly _coordinates: Coordinate[]) { - this._map = new Map({ - target: "map", - layers: [ - new TileLayer({ - source: new XYZ({ - url: "https://mt0.google.com/vt/lyrs=m&hl=en&x={x}&y={y}&z={z}" - }), - }), - new VectorLayer({ - source: new VectorSource({ - features: this.getPointFeatures() - }), - }) - ], - view: this.getViewAtFirst(), - controls: defaultControls().extend([new FullScreen()]), - }); - } - - private getViewAtFirst(): View { - return new View({ - center: this.first, - zoom: CommentsViewModel.DEFAULT_ZOOM, - projection: "EPSG:3857", - }); - } - - private getPointFeatures(): Feature[] { - return this._coordinates.map((coordinate) => { - const feature = new Feature({ - geometry: new Point(coordinate), - }); - feature.setStyle(CommentsViewModel.MARKER_ICON_STYLE); - return feature; - }); - } - - private get first(): Coordinate { - return this._coordinates.length > 0 ? this._coordinates[0] : [0, 0]; - } - - public goToLocation(coordinate: Coordinate) { - const view = this._map.getView(); - view.setCenter(coordinate); - } -} \ No newline at end of file diff --git a/CommentMap.Mvc/Styles/validation-errors.css b/CommentMap.Mvc/Styles/validation-errors.css deleted file mode 100644 index b478d97..0000000 --- a/CommentMap.Mvc/Styles/validation-errors.css +++ /dev/null @@ -1,26 +0,0 @@ -.input-validation-error { - border-color: var(--bs-form-invalid-border-color); -} - -.field-validation-error { - color: var(--bs-danger-text-emphasis); -} - -.validation-summary-errors { - background-color: var(--bs-danger-bg-subtle); - border-radius: var(--bs-border-radius); - border: var(--bs-border-width) var(--bs-border-style) var(--bs-danger-border-subtle); -} - -.validation-summary-errors > ul { - list-style-type: none; - padding: 16px; - margin: 0; - display: flex; - flex-direction: column; - gap: 8px; -} - -.validation-summary-errors > ul > li { - color: var(--bs-danger-text-emphasis); -} diff --git a/CommentMap.Mvc/build/build.js b/CommentMap.Mvc/build/build.js deleted file mode 100644 index 3d0055f..0000000 --- a/CommentMap.Mvc/build/build.js +++ /dev/null @@ -1,14 +0,0 @@ -import * as esbuild from "esbuild"; - -await esbuild.build({ - entryPoints: { - "js/Comments.min": "./Scripts/Comments.ts", - "js/AddComment.min": "./Scripts/AddComment.ts", - "css/ol.min": "./node_modules/ol/ol.css", - "css/validation-errors.min": "./Styles/validation-errors.css" - }, - bundle: true, - minify: true, - sourcemap: true, - outdir: "./wwwroot", -}); diff --git a/CommentMap.Mvc/eslint.config.js b/CommentMap.Mvc/eslint.config.js deleted file mode 100644 index a8aa3e5..0000000 --- a/CommentMap.Mvc/eslint.config.js +++ /dev/null @@ -1,13 +0,0 @@ -import globals from "globals"; -import pluginJs from "@eslint/js"; -import tseslint from "typescript-eslint"; - - -export default [ - { - languageOptions: { globals: globals.browser }, - ignores: ["./wwwroot", "./build", "./eslint.config.js"], - }, - pluginJs.configs.recommended, - ...tseslint.configs.recommended, -]; diff --git a/CommentMap.Mvc/libman.json b/CommentMap.Mvc/libman.json deleted file mode 100644 index 965953a..0000000 --- a/CommentMap.Mvc/libman.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "version": "1.0", - "defaultProvider": "jsdelivr", - "libraries": [ - { - "library": "jquery@3.7.1", - "destination": "wwwroot/lib/jquery/", - "files": [ - "dist/jquery.min.js", - "dist/jquery.min.map" - ] - }, - { - "library": "aspnet-client-validation@0.11.1", - "destination": "wwwroot/lib/aspnet-client-validation/", - "files": [ - "dist/aspnet-validation.min.js", - "dist/aspnet-validation.min.js.map" - ] - }, - { - "library": "bootstrap@5.3.3", - "destination": "wwwroot/lib/bootstrap/", - "files": [ - "dist/css/bootstrap.min.css", - "dist/css/bootstrap.min.css.map", - "dist/js/bootstrap.bundle.min.js.map", - "dist/js/bootstrap.bundle.min.js" - ] - }, - { - "library": "bootstrap-icons@1.11.3", - "destination": "wwwroot/lib/bootstrap-icons/", - "files": [ - "font/fonts/bootstrap-icons.woff", - "font/fonts/bootstrap-icons.woff2", - "font/bootstrap-icons.min.css" - ] - }, - { - "library": "knockout@3.5.1", - "destination": "wwwroot/lib/knockout/", - "files": [ - "build/output/knockout-latest.min.js" - ] - } - ] -} \ No newline at end of file diff --git a/CommentMap.Mvc/package-lock.json b/CommentMap.Mvc/package-lock.json deleted file mode 100644 index 07636dd..0000000 --- a/CommentMap.Mvc/package-lock.json +++ /dev/null @@ -1,2295 +0,0 @@ -{ - "name": "comment-map-mvc", - "version": "1.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "comment-map-mvc", - "version": "1.0.0", - "dependencies": { - "ol": "^9.2.4" - }, - "devDependencies": { - "@eslint/js": "^9.4.0", - "@types/bootstrap": "^5.2.10", - "@types/jquery": "^3.5.30", - "@types/knockout": "^3.4.77", - "esbuild": "^0.25.0", - "eslint": "^8.56.0", - "globals": "^15.4.0", - "typescript-eslint": "^7.12.0" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.0.tgz", - "integrity": "sha512-O7vun9Sf8DFjH2UtqK8Ku3LkquL9SZL8OLY1T5NZkA34+wG3OQF7cl4Ql8vdNzM6fzBbYfLaiRLIOZ+2FOCgBQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.0.tgz", - "integrity": "sha512-PTyWCYYiU0+1eJKmw21lWtC+d08JDZPQ5g+kFyxP0V+es6VPPSUhM6zk8iImp2jbV6GwjX4pap0JFbUQN65X1g==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.0.tgz", - "integrity": "sha512-grvv8WncGjDSyUBjN9yHXNt+cq0snxXbDxy5pJtzMKGmmpPxeAmAhWxXI+01lU5rwZomDgD3kJwulEnhTRUd6g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.0.tgz", - "integrity": "sha512-m/ix7SfKG5buCnxasr52+LI78SQ+wgdENi9CqyCXwjVR2X4Jkz+BpC3le3AoBPYTC9NHklwngVXvbJ9/Akhrfg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.0.tgz", - "integrity": "sha512-mVwdUb5SRkPayVadIOI78K7aAnPamoeFR2bT5nszFUZ9P8UpK4ratOdYbZZXYSqPKMHfS1wdHCJk1P1EZpRdvw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.0.tgz", - "integrity": "sha512-DgDaYsPWFTS4S3nWpFcMn/33ZZwAAeAFKNHNa1QN0rI4pUjgqf0f7ONmXf6d22tqTY+H9FNdgeaAa+YIFUn2Rg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.0.tgz", - "integrity": "sha512-VN4ocxy6dxefN1MepBx/iD1dH5K8qNtNe227I0mnTRjry8tj5MRk4zprLEdG8WPyAPb93/e4pSgi1SoHdgOa4w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.0.tgz", - "integrity": "sha512-mrSgt7lCh07FY+hDD1TxiTyIHyttn6vnjesnPoVDNmDfOmggTLXRv8Id5fNZey1gl/V2dyVK1VXXqVsQIiAk+A==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.0.tgz", - "integrity": "sha512-vkB3IYj2IDo3g9xX7HqhPYxVkNQe8qTK55fraQyTzTX/fxaDtXiEnavv9geOsonh2Fd2RMB+i5cbhu2zMNWJwg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.0.tgz", - "integrity": "sha512-9QAQjTWNDM/Vk2bgBl17yWuZxZNQIF0OUUuPZRKoDtqF2k4EtYbpyiG5/Dk7nqeK6kIJWPYldkOcBqjXjrUlmg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.0.tgz", - "integrity": "sha512-43ET5bHbphBegyeqLb7I1eYn2P/JYGNmzzdidq/w0T8E2SsYL1U6un2NFROFRg1JZLTzdCoRomg8Rvf9M6W6Gg==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.0.tgz", - "integrity": "sha512-fC95c/xyNFueMhClxJmeRIj2yrSMdDfmqJnyOY4ZqsALkDrrKJfIg5NTMSzVBr5YW1jf+l7/cndBfP3MSDpoHw==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.0.tgz", - "integrity": "sha512-nkAMFju7KDW73T1DdH7glcyIptm95a7Le8irTQNO/qtkoyypZAnjchQgooFUDQhNAy4iu08N79W4T4pMBwhPwQ==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.0.tgz", - "integrity": "sha512-NhyOejdhRGS8Iwv+KKR2zTq2PpysF9XqY+Zk77vQHqNbo/PwZCzB5/h7VGuREZm1fixhs4Q/qWRSi5zmAiO4Fw==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.0.tgz", - "integrity": "sha512-5S/rbP5OY+GHLC5qXp1y/Mx//e92L1YDqkiBbO9TQOvuFXM+iDqUNG5XopAnXoRH3FjIUDkeGcY1cgNvnXp/kA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.0.tgz", - "integrity": "sha512-XM2BFsEBz0Fw37V0zU4CXfcfuACMrppsMFKdYY2WuTS3yi8O1nFOhil/xhKTmE1nPmVyvQJjJivgDT+xh8pXJA==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.0.tgz", - "integrity": "sha512-9yl91rHw/cpwMCNytUDxwj2XjFpxML0y9HAOH9pNVQDpQrBxHy01Dx+vaMu0N1CKa/RzBD2hB4u//nfc+Sd3Cw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.0.tgz", - "integrity": "sha512-RuG4PSMPFfrkH6UwCAqBzauBWTygTvb1nxWasEJooGSJ/NwRw7b2HOwyRTQIU97Hq37l3npXoZGYMy3b3xYvPw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.0.tgz", - "integrity": "sha512-jl+qisSB5jk01N5f7sPCsBENCOlPiS/xptD5yxOx2oqQfyourJwIKLRA2yqWdifj3owQZCL2sn6o08dBzZGQzA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.0.tgz", - "integrity": "sha512-21sUNbq2r84YE+SJDfaQRvdgznTD8Xc0oc3p3iW/a1EVWeNj/SdUCbm5U0itZPQYRuRTW20fPMWMpcrciH2EJw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.0.tgz", - "integrity": "sha512-2gwwriSMPcCFRlPlKx3zLQhfN/2WjJ2NSlg5TKLQOJdV0mSxIcYNTMhk3H3ulL/cak+Xj0lY1Ym9ysDV1igceg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.0.tgz", - "integrity": "sha512-bxI7ThgLzPrPz484/S9jLlvUAHYMzy6I0XiU1ZMeAEOBcS0VePBFxh1JjTQt3Xiat5b6Oh4x7UC7IwKQKIJRIg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.0.tgz", - "integrity": "sha512-ZUAc2YK6JW89xTbXvftxdnYy3m4iHIkDtK3CLce8wg8M2L+YZhIvO1DKpxrd0Yr59AeNNkTiic9YLf6FTtXWMw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.0.tgz", - "integrity": "sha512-eSNxISBu8XweVEWG31/JzjkIGbGIJN/TrRoiSVZwZ6pkC6VX4Im/WV2cz559/TXLcYbcrDN8JtKgd9DJVIo8GA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.0.tgz", - "integrity": "sha512-ZENoHJBxA20C2zFzh6AI4fT6RraMzjYw4xKWemRTRmRVtN9c5DcH9r/f2ihEkMjOW5eGgrwCslG/+Y/3bL+DHQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "dev": true, - "license": "MIT", - "dependencies": { - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.10.1", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/js": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.4.0.tgz", - "integrity": "sha512-fdI7VJjP3Rvc70lC4xkFXHB0fiPeojiL1PxVG6t1ZvXQrarj893PweuBTujxDUFk0Fxj4R7PIIAZ/aiiyZPZcg==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@petamoriken/float16": { - "version": "3.8.7", - "resolved": "https://registry.npmjs.org/@petamoriken/float16/-/float16-3.8.7.tgz", - "integrity": "sha512-/Ri4xDDpe12NT6Ex/DRgHzLlobiQXEW/hmG08w1wj/YU7hLemk97c+zHQFp0iZQ9r7YqgLEXZR2sls4HxBf9NA==", - "license": "MIT" - }, - "node_modules/@popperjs/core": { - "version": "2.11.8", - "dev": true, - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/popperjs" - } - }, - "node_modules/@types/bootstrap": { - "version": "5.2.10", - "dev": true, - "license": "MIT", - "dependencies": { - "@popperjs/core": "^2.9.2" - } - }, - "node_modules/@types/jquery": { - "version": "3.5.30", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/sizzle": "*" - } - }, - "node_modules/@types/knockout": { - "version": "3.4.77", - "resolved": "https://registry.npmjs.org/@types/knockout/-/knockout-3.4.77.tgz", - "integrity": "sha512-RpujDayUysbJlpygCxDnMSOp7DeUIROcoIW0Xf85YkqoZ/DE5R2R4TcFhbgLaGTM5bi4QLTVSG/DUUc0wL4KmQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/sizzle": { - "version": "2.3.8", - "dev": true, - "license": "MIT" - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "7.12.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "7.12.0", - "@typescript-eslint/visitor-keys": "7.12.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/types": { - "version": "7.12.0", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.12.0", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "@typescript-eslint/types": "7.12.0", - "@typescript-eslint/visitor-keys": "7.12.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.4", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.12.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "7.12.0", - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/acorn": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", - "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", - "dev": true, - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, - "license": "Python-2.0" - }, - "node_modules/array-union": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "dev": true, - "license": "MIT" - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/chalk": { - "version": "4.1.2", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "dev": true, - "license": "MIT" - }, - "node_modules/color-parse": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/color-parse/-/color-parse-2.0.2.tgz", - "integrity": "sha512-eCtOz5w5ttWIUcaKLiktF+DxZO1R9KLNY/xhbV6CkhM7sR3GhVghmt6X6yOnzeaM24po+Z9/S1apbXMwA3Iepw==", - "license": "MIT", - "dependencies": { - "color-name": "^2.0.0" - } - }, - "node_modules/color-parse/node_modules/color-name": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.0.0.tgz", - "integrity": "sha512-SbtvAMWvASO5TE2QP07jHBMXKafgdZz8Vrsrn96fiL+O92/FN/PLARzUW5sKt013fjAprK2d2iCn2hk2Xb5oow==", - "license": "MIT", - "engines": { - "node": ">=12.20" - } - }, - "node_modules/color-rgba": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/color-rgba/-/color-rgba-3.0.0.tgz", - "integrity": "sha512-PPwZYkEY3M2THEHHV6Y95sGUie77S7X8v+h1r6LSAPF3/LL2xJ8duUXSrkic31Nzc4odPwHgUbiX/XuTYzQHQg==", - "license": "MIT", - "dependencies": { - "color-parse": "^2.0.0", - "color-space": "^2.0.0" - } - }, - "node_modules/color-space": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-space/-/color-space-2.0.1.tgz", - "integrity": "sha512-nKqUYlo0vZATVOFHY810BSYjmCARrG7e5R3UE3CQlyjJTvv5kSSmPG1kzm/oDyyqjehM+lW1RnEt9It9GNa5JA==", - "license": "MIT" - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true, - "license": "MIT" - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/debug": { - "version": "4.3.5", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "dev": true, - "license": "MIT" - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/earcut": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/earcut/-/earcut-2.2.4.tgz", - "integrity": "sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ==", - "license": "ISC" - }, - "node_modules/esbuild": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.0.tgz", - "integrity": "sha512-BXq5mqc8ltbaN34cDqWuYKyNhX8D/Z0J1xdtdQ8UcIIIyJyz+ZMKUt58tF3SrZ85jcfN/PZYhjR5uDQAYNVbuw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.0", - "@esbuild/android-arm": "0.25.0", - "@esbuild/android-arm64": "0.25.0", - "@esbuild/android-x64": "0.25.0", - "@esbuild/darwin-arm64": "0.25.0", - "@esbuild/darwin-x64": "0.25.0", - "@esbuild/freebsd-arm64": "0.25.0", - "@esbuild/freebsd-x64": "0.25.0", - "@esbuild/linux-arm": "0.25.0", - "@esbuild/linux-arm64": "0.25.0", - "@esbuild/linux-ia32": "0.25.0", - "@esbuild/linux-loong64": "0.25.0", - "@esbuild/linux-mips64el": "0.25.0", - "@esbuild/linux-ppc64": "0.25.0", - "@esbuild/linux-riscv64": "0.25.0", - "@esbuild/linux-s390x": "0.25.0", - "@esbuild/linux-x64": "0.25.0", - "@esbuild/netbsd-arm64": "0.25.0", - "@esbuild/netbsd-x64": "0.25.0", - "@esbuild/openbsd-arm64": "0.25.0", - "@esbuild/openbsd-x64": "0.25.0", - "@esbuild/sunos-x64": "0.25.0", - "@esbuild/win32-arm64": "0.25.0", - "@esbuild/win32-ia32": "0.25.0", - "@esbuild/win32-x64": "0.25.0" - } - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", - "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.56.0", - "@humanwhocodes/config-array": "^0.11.13", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/@eslint/js": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", - "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/eslint/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esquery": { - "version": "1.5.0", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-glob": { - "version": "3.3.2", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "dev": true, - "license": "MIT" - }, - "node_modules/fastq": { - "version": "1.17.1", - "dev": true, - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "license": "MIT", - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", - "dev": true, - "license": "MIT", - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flatted": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", - "dev": true, - "license": "ISC" - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true, - "license": "ISC" - }, - "node_modules/geotiff": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/geotiff/-/geotiff-2.1.3.tgz", - "integrity": "sha512-PT6uoF5a1+kbC3tHmZSUsLHBp2QJlHasxxxxPW47QIY1VBKpFB+FcDvX+MxER6UzgLQZ0xDzJ9s48B9JbOCTqA==", - "license": "MIT", - "dependencies": { - "@petamoriken/float16": "^3.4.7", - "lerc": "^3.0.0", - "pako": "^2.0.4", - "parse-headers": "^2.0.2", - "quick-lru": "^6.1.1", - "web-worker": "^1.2.0", - "xml-utils": "^1.0.2", - "zstddec": "^0.1.0" - }, - "engines": { - "node": ">=10.19" - } - }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/globals": { - "version": "15.4.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-15.4.0.tgz", - "integrity": "sha512-unnwvMZpv0eDUyjNyh9DH/yxUaRYrEjW/qK4QcdrHg3oO11igUQrCSgODHEqxlKg8v2CD2Sd7UkqqEBoz5U7TQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globby": { - "version": "11.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/graphemer": { - "version": "1.4.0", - "dev": true, - "license": "MIT" - }, - "node_modules/has-flag": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "BSD-3-Clause" - }, - "node_modules/ignore": { - "version": "5.3.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "license": "MIT", - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "dev": true, - "license": "ISC", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "dev": true, - "license": "ISC" - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, - "license": "MIT", - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/lerc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lerc/-/lerc-3.0.0.tgz", - "integrity": "sha512-Rm4J/WaHhRa93nCN2mwWDZFoRVF18G1f47C+kvQWyHGEZxFpTUi73p7lMVSAndyxGt6lJ2/CFbOcf9ra5p8aww==", - "license": "Apache-2.0" - }, - "node_modules/levn": { - "version": "0.4.1", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/locate-path": { - "version": "6.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "dev": true, - "license": "MIT" - }, - "node_modules/merge2": { - "version": "1.4.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.7", - "dev": true, - "license": "MIT", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "dev": true, - "license": "MIT" - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "dev": true, - "license": "MIT" - }, - "node_modules/ol": { - "version": "9.2.4", - "resolved": "https://registry.npmjs.org/ol/-/ol-9.2.4.tgz", - "integrity": "sha512-bsbu4ObaAlbELMIZWnYEvX4Z9jO+OyCBshtODhDKmqYTPEfnKOX3RieCr97tpJkqWTZvyV4tS9UQDvHoCdxS+A==", - "license": "BSD-2-Clause", - "dependencies": { - "color-rgba": "^3.0.0", - "color-space": "^2.0.1", - "earcut": "^2.2.3", - "geotiff": "^2.0.7", - "pbf": "3.2.1", - "rbush": "^3.0.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/openlayers" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/optionator": { - "version": "0.9.4", - "dev": true, - "license": "MIT", - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.5" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pako": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz", - "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==", - "license": "(MIT AND Zlib)" - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "license": "MIT", - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-headers": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.5.tgz", - "integrity": "sha512-ft3iAoLOB/MlwbNXgzy43SWGP6sQki2jQvAyBg/zDFAgr9bfNWZIUj42Kw2eJIl8kEi4PbgE6U1Zau/HwI75HA==", - "license": "MIT" - }, - "node_modules/path-exists": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-type": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/pbf": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/pbf/-/pbf-3.2.1.tgz", - "integrity": "sha512-ClrV7pNOn7rtmoQVF4TS1vyU0WhYRnP92fzbfF75jAIwpnzdJXf8iTd4CMEqO4yUenH6NDqLiwjqlh6QgZzgLQ==", - "license": "BSD-3-Clause", - "dependencies": { - "ieee754": "^1.1.12", - "resolve-protobuf-schema": "^2.1.0" - }, - "bin": { - "pbf": "bin/pbf" - } - }, - "node_modules/picomatch": { - "version": "2.3.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/protocol-buffers-schema": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.6.0.tgz", - "integrity": "sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw==", - "license": "MIT" - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/quick-lru": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-6.1.2.tgz", - "integrity": "sha512-AAFUA5O1d83pIHEhJwWCq/RQcRukCkn/NSm2QsTEMle5f2hP0ChI2+3Xb051PZCkLryI/Ir1MVKviT2FIloaTQ==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/quickselect": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/quickselect/-/quickselect-2.0.0.tgz", - "integrity": "sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw==", - "license": "ISC" - }, - "node_modules/rbush": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/rbush/-/rbush-3.0.1.tgz", - "integrity": "sha512-XRaVO0YecOpEuIvbhbpTrZgoiI6xBlz6hnlr6EHhd+0x9ase6EmeN+hdwwUaJvLcsFFQ8iWVF1GAK1yB0BWi0w==", - "license": "MIT", - "dependencies": { - "quickselect": "^2.0.0" - } - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/resolve-protobuf-schema": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/resolve-protobuf-schema/-/resolve-protobuf-schema-2.1.0.tgz", - "integrity": "sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==", - "license": "MIT", - "dependencies": { - "protocol-buffers-schema": "^3.3.1" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "dev": true, - "license": "MIT", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/semver": { - "version": "7.6.2", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/slash": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "dev": true, - "license": "MIT" - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/ts-api-utils": { - "version": "1.3.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "typescript": ">=4.2.0" - } - }, - "node_modules/type-check": { - "version": "0.4.0", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typescript": { - "version": "5.4.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", - "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", - "dev": true, - "license": "Apache-2.0", - "peer": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/typescript-eslint": { - "version": "7.12.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-7.12.0.tgz", - "integrity": "sha512-D6HKNbQcnNu3BaN4HkQCR16tgG8Q2AMUWPgvhrJksOXu+d6ys07yC06ONiV2kcsEfWC22voB6C3PvK2MqlBZ7w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/eslint-plugin": "7.12.0", - "@typescript-eslint/parser": "7.12.0", - "@typescript-eslint/utils": "7.12.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/typescript-eslint/node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.12.0.tgz", - "integrity": "sha512-7F91fcbuDf/d3S8o21+r3ZncGIke/+eWk0EpO21LXhDfLahriZF9CGj4fbAetEjlaBdjdSm9a6VeXbpbT6Z40Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.12.0", - "@typescript-eslint/type-utils": "7.12.0", - "@typescript-eslint/utils": "7.12.0", - "@typescript-eslint/visitor-keys": "7.12.0", - "graphemer": "^1.4.0", - "ignore": "^5.3.1", - "natural-compare": "^1.4.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^7.0.0", - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/typescript-eslint/node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/type-utils": { - "version": "7.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.12.0.tgz", - "integrity": "sha512-lib96tyRtMhLxwauDWUp/uW3FMhLA6D0rJ8T7HmH7x23Gk1Gwwu8UZ94NMXBvOELn6flSPiBrCKlehkiXyaqwA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/typescript-estree": "7.12.0", - "@typescript-eslint/utils": "7.12.0", - "debug": "^4.3.4", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/typescript-eslint/node_modules/@typescript-eslint/parser": { - "version": "7.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.12.0.tgz", - "integrity": "sha512-dm/J2UDY3oV3TKius2OUZIFHsomQmpHtsV0FTh1WO8EKgHLQ1QCADUqscPgTpU+ih1e21FQSRjXckHn3txn6kQ==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "@typescript-eslint/scope-manager": "7.12.0", - "@typescript-eslint/types": "7.12.0", - "@typescript-eslint/typescript-estree": "7.12.0", - "@typescript-eslint/visitor-keys": "7.12.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/typescript-eslint/node_modules/@typescript-eslint/utils": { - "version": "7.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.12.0.tgz", - "integrity": "sha512-Y6hhwxwDx41HNpjuYswYp6gDbkiZ8Hin9Bf5aJQn1bpTs3afYY4GX+MPYxma8jtoIV2GRwTM/UJm/2uGCVv+DQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.12.0", - "@typescript-eslint/types": "7.12.0", - "@typescript-eslint/typescript-estree": "7.12.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/web-worker": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/web-worker/-/web-worker-1.3.0.tgz", - "integrity": "sha512-BSR9wyRsy/KOValMgd5kMyr3JzpdeoR9KVId8u5GVlTTAtNChlsE4yTxeY7zMdNSyOmoKBv8NH2qeRY9Tg+IaA==", - "license": "Apache-2.0" - }, - "node_modules/which": { - "version": "2.0.2", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/word-wrap": { - "version": "1.2.5", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/xml-utils": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/xml-utils/-/xml-utils-1.10.1.tgz", - "integrity": "sha512-Dn6vJ1Z9v1tepSjvnCpwk5QqwIPcEFKdgnjqfYOABv1ngSofuAhtlugcUC3ehS1OHdgDWSG6C5mvj+Qm15udTQ==", - "license": "CC0-1.0" - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/zstddec": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/zstddec/-/zstddec-0.1.0.tgz", - "integrity": "sha512-w2NTI8+3l3eeltKAdK8QpiLo/flRAr2p8AGeakfMZOXBxOg9HIu4LVDxBi81sYgVhFhdJjv1OrB5ssI8uFPoLg==", - "license": "MIT AND BSD-3-Clause" - } - } -} diff --git a/CommentMap.Mvc/package.json b/CommentMap.Mvc/package.json deleted file mode 100644 index fd0f22a..0000000 --- a/CommentMap.Mvc/package.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "name": "comment-map-mvc", - "private": true, - "type": "module", - "version": "1.0.0", - "devDependencies": { - "@eslint/js": "^9.4.0", - "@types/bootstrap": "^5.2.10", - "@types/jquery": "^3.5.30", - "@types/knockout": "^3.4.77", - "esbuild": "^0.25.0", - "eslint": "^8.56.0", - "globals": "^15.4.0", - "typescript-eslint": "^7.12.0" - }, - "scripts": { - "build": "node ./build/build.js" - }, - "volta": { - "node": "20.14.0", - "npm": "10.8.1" - }, - "dependencies": { - "ol": "^9.2.4" - } -} diff --git a/CommentMap.Mvc/tsconfig.json b/CommentMap.Mvc/tsconfig.json deleted file mode 100644 index e158ee7..0000000 --- a/CommentMap.Mvc/tsconfig.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "compilerOptions": { - "target": "ES5", - "lib": [ "DOM", "ES6" ], - "skipLibCheck": true, - "noEmit": true, - "moduleResolution": "Bundler", - "module": "ESNext" - }, - "include": [ - "./Scripts/**/*" - ] -} diff --git a/CommentMap.Mvc/wwwroot/assets/favicon-16x16.png b/CommentMap.Mvc/wwwroot/assets/favicon-16x16.png deleted file mode 100644 index 872cfc3748d0ebc3fb736e0f92c9d9a6b579d027..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 574 zcmV-E0>S->P)f{r zTD4{nD2#1khUpA5fN9JJ1FT%-?^A=q%> z{^|Mv8)F_ww;8CCj0`RIcLXjjkc+BFRo_Be z9}vuUL#%B9O|ysSy);_melnc68iEjOA`~p{6=b-=?(nw)!X}_ACIap_a?Kv;M?&S_ z5Nz$hhAX@M|09Sd+ela55VD!)Q1d3C(e4r~fpy2?k6yqF_5FQ8UEN0Q#pVx!N3RCI z5G<;Qr#p}qmXYO`QOVWF9w>PeFT0=j2;@c=b2H!VL2s=Cv-B86G5=b)BdQXW)HPB2 zuu^S9=F3PdRv{$}M1lniCG)`=i=Q@9+xD;0vyujz_G8nu(H5SEls6p zdBf124vlOE`FZh^G{e_v7kAoPXGV_ diff --git a/CommentMap.Mvc/wwwroot/assets/favicon-32x32.png b/CommentMap.Mvc/wwwroot/assets/favicon-32x32.png deleted file mode 100644 index 93c12517aa847ae3c27da835b223adff0cebcf43..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1123 zcmV-p1f2VcP)|Bj|N{R?{ECcW#X&4BF! z4!Y}M(>69y91xI$GQ$AFz$n%u9;hf=aSw>w*2Av5@wDnHyQ_3P6qkZe^G(%&qPxjz znoWF@C-Y^1_xXJI*&X9$J{_nF z{PTOL8|%}9&{G@=0IX#~T&!!`I%;}77(w$j3Dyb;{-!7_IzL3F2QxRPklo%udi^mN zl?!Y8=0`>DGfECCV_~H3MGkcgKu>Xd&o^fAbao2S)(D!a_f5UGFfg`;*m4GwPjXmH z|7`pomk~9v>)fV{lFUSM8 z`$sX{5;-&_>4>Bx645NB-rW!z-Xn30#In@#3ZlW7JQa7|RPL;0G4gO1U6DDkOg|bl zUUb^q@!)!|Y(6{EhXysDDGHD|VoLHM38y3(*M8glQN7AlVx@&uwpz+02F8%yczie& z|Nc}2dlV*GgsUcqczYL~P7cZ}9v?tL-dFkxe=}g}8^Mw6s*~zAF35k}s1fGK4IU1j(u(rIHIfz z5IORm@D}-gwC53ddQg5$Q!;`6Lnc^0Y7FZi9x{O`DUb+(Bk2kI9CQfw=lj;4t7RI zB+xUHtxzgfLZ8bGv%{ls^Xg479WPZTgCqAup1gaOGrz8N-m{0zUzHEG2>y}^$W7@M z$mS{JB@rk~CD41wBy~yt?O3ifMMeTg<}V~(_=?u~Apt%kCRu+f@U&Ru$;S%qNJ)56 zK>x@)2J5TSl5hOy0l>!}!KY7GVcIhWRhJs1eM1LE`iaOWicVpp&;85xO{|OIZ}f`-N0l95TtalNCIV zbUuUOwR61nmjX|m0#DbK>S#Mv47Vz462BM>>UGVUISz%DXD_2 zi5#`duYPN?MOR;sUC!i@d~nIgaHNKo4Tz37nkw+bu-Pq!wmt8#4P0gi%yhY6b*xo# z`Sz$l$E!>a=w+GuLHGNki6NM{IRJ|@_f<*o`{Vg}a94K0;O%J&0X-%H zuzwSHO5zWC3s_Dn_vxa{&!^kKWov~86Ek5|u{t{k?T*fX@;JGQCjs6JW5DqpnWb>s zRSzp8>Y&F&fWVP|#0B(`L1-^)0gFK$^qeClU_0LoIq5};+x@C|wz8;6gj@*=aReV7 zk0mmYuZe$Q{=m5RY)B*J!_rQJs84N9M!1U5OTyGu&a=Kbw z6$Py@KR&HUK;GfvT~PoIvO7+Iz>%l^0>1h1;Li;YNT8d;fL>(ofO_{P=$*6cTRyb7 z0bU<$`M}5`R2Fnbqzdb)id`84h@m(D+_BbrsJ>7R7Y-Ik-e_^c(nzcdkQLAbz4RKG zPn3iK-3|5b`_OrREdX>a0=&LQ?8m%qcQBZp1QIM9mrf)|RpEEMs~HdQ`vPXd3MxNX3`L|9ntC4we7_?E zTt0Rs0CYTYLzg!y(4!^58>9-S)eSjmg(1M;JsiB36ASoQK0o*w!E?_)TL)E*Ec0op?(*QYGO20pKT5a8}=jj-cp`5#UoMp{cq*q&vd9ntJ>E;BLom z@6~l7F$MT!B-9RuJX65Cns{Rk<9eK2;S3l5;{OfcPrUguP4w zi~x}-09X{nx}a7z26)*#fDOW{ED8cP6J}v3W%B?pyBEYJVj`Of!~VP*T2kBtS!sn} zFYXDcRLkvU$a}Y3a{L^;9m{5?6+%NrUr0AGI`bHeCn_Yz&%xX4EBd6Lq(oCzivT@! zR%-8_5s;N!u=xx%#THW8@^a5s8T=f)-Cs5<)fW12y=GvmEPf8&o|O`PSuFze);YMn zdq#j(V@mCP+dmOec)%?$>kR^_vGT*MZTMLW#8}G4QfEd0&j?^$(Ci*}K{yy?r5Azy zipn5-yaFyBuYi`Jm5}XNHaoot>K!TrslfsH1_zAZ^@VK5!8a$$vSA0|Fm+aHFMB5J zV-IB56EXf3|8cIDJ(6Suh)e+xRtf$|oYLg+rMngJGIl`?6@60lr4+d_0(`qe!iNw4 z7uO4kDZm#Q0iFd$z}_n05hGwv3Fv>-32=MYz;$aLnp-DfXkume33wI900h0Udlrgm z7vvrdeB<8qUL`cw4#L!JPqE zuLky|qs35lsSa`vg}&{MjxS&1OW61_cH9-P-^PGQKyR|SVA|t>wdE-(Y2W(eWf;8P z55;E#-{0~(KKsSA1pUJcaU)=GF@6NJPe0kNZ_+Lj5H09hSrZ>k-Gk=h>*}gFy{U@n zg|$5&12BlNncAi21OECMj}`7b0kMLvMF2ea^^caqtAa+aioqxez*kr+oC9$2q*Jk8 zUFFp~L%^k@;or5@3%VWxV24#P6afLKbbN8!n%lDV2sYTwCyJn_sx}Te<5UR1RFm-n z9dnCfj?o%p9oU5`Xew-jJ3XVY@nl7lhl4S<%f$Fbj+%&m>ZhMT%09Ra#l>zs!J6`*CF?ynkuTG&84mi zoPjG|?e{*0n&vxT78{kb_3{)7PhEkVjv81P3{BK3_sNb%Svm43CIX^yJ)nyUjtzHQ zsE0ef`c+Z%zOpLtmv;^YRRj~z+`j-h)vN_NssUAj>OhsK0Phw#%ioO$j9=0XemDYr zbK@}B)(y_w8uj#z9NoZ^)y-KL+Oiyir^!_1odD_PgCKXr@jngRU}>WJTnOQFnKvhXB0NdmG(g7b;bw zf@rVwi0buE>vu(to)CF@UriOARr*x1boV|C-?#}=?(hTZ!tHBP#DkHKYTG$dFLLyc z21D5wVs5DXO51DDl?)g45je|l1di4yrPi0mio6Dx3^T7-Tbj}Y9%Flq@pICYCtlJT zWgI;b%Zg8mCiPt^{p4POu4eBi<$q7)=t*f=LM2tav#AQ-gV5Rb+R}___=vMwWzgv} zX~hnXyrHy?O - - - - - diff --git a/CommentMap.slnx b/CommentMap.slnx index a3fa809..75d5062 100644 --- a/CommentMap.slnx +++ b/CommentMap.slnx @@ -1,10 +1,21 @@ - - - - - - - - + + + + + + + + + + + + + + + + + + + diff --git a/LICENSE.txt b/LICENSE.txt index fd4f2cf..1c9c086 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2024 Ivan Kozelskikh +Copyright (c) 2026 Ivan Kozelskikh Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/aspire.config.json b/aspire.config.json index c84104c..5e4533d 100644 --- a/aspire.config.json +++ b/aspire.config.json @@ -1,5 +1,5 @@ { "appHost": { - "path": "CommentMap.AppHost/CommentMap.AppHost.csproj" + "path": "src/CommentMap.AppHost/CommentMap.AppHost.csproj" } } \ No newline at end of file diff --git a/clear.ps1 b/clear.ps1 deleted file mode 100644 index cf68bcf..0000000 --- a/clear.ps1 +++ /dev/null @@ -1 +0,0 @@ -Get-ChildItem .\ -include bin,obj -Recurse | ForEach-Object ($_) { Remove-Item $_.FullName -Force -Recurse } diff --git a/dotnet-tools.json b/dotnet-tools.json index 404cb7f..67d639c 100644 --- a/dotnet-tools.json +++ b/dotnet-tools.json @@ -2,13 +2,6 @@ "version": 1, "isRoot": true, "tools": { - "microsoft.web.librarymanager.cli": { - "version": "2.1.175", - "commands": [ - "libman" - ], - "rollForward": false - }, "dotnet-ef": { "version": "10.0.10", "commands": [ diff --git a/opencode.json b/opencode.json index 17fd242..29c4e3f 100644 --- a/opencode.json +++ b/opencode.json @@ -5,5 +5,12 @@ "command": [ "dotnet", "roslyn-language-server", "--stdio", "--autoLoadProjects" ], "extensions": [ ".cs", ".csx", ".razor", ".cshtml" ] } + }, + "mcp": { + "aspire": { + "type": "local", + "command": [ "dotnet", "aspire", "agent", "mcp" ], + "enabled": true + } } } diff --git a/CommentMap.AppHost/AppHost.cs b/src/CommentMap.AppHost/AppHost.cs similarity index 100% rename from CommentMap.AppHost/AppHost.cs rename to src/CommentMap.AppHost/AppHost.cs diff --git a/CommentMap.AppHost/CommentMap.AppHost.csproj b/src/CommentMap.AppHost/CommentMap.AppHost.csproj similarity index 100% rename from CommentMap.AppHost/CommentMap.AppHost.csproj rename to src/CommentMap.AppHost/CommentMap.AppHost.csproj diff --git a/CommentMap.AppHost/Properties/launchSettings.json b/src/CommentMap.AppHost/Properties/launchSettings.json similarity index 100% rename from CommentMap.AppHost/Properties/launchSettings.json rename to src/CommentMap.AppHost/Properties/launchSettings.json diff --git a/CommentMap.AppHost/appsettings.Development.json b/src/CommentMap.AppHost/appsettings.Development.json similarity index 100% rename from CommentMap.AppHost/appsettings.Development.json rename to src/CommentMap.AppHost/appsettings.Development.json diff --git a/CommentMap.AppHost/appsettings.json b/src/CommentMap.AppHost/appsettings.json similarity index 100% rename from CommentMap.AppHost/appsettings.json rename to src/CommentMap.AppHost/appsettings.json diff --git a/CommentMap.Application/Abstractions/ICommentMapDbContext.cs b/src/CommentMap.Application/Abstractions/ICommentMapDbContext.cs similarity index 100% rename from CommentMap.Application/Abstractions/ICommentMapDbContext.cs rename to src/CommentMap.Application/Abstractions/ICommentMapDbContext.cs diff --git a/CommentMap.Application/CommentMap.Application.csproj b/src/CommentMap.Application/CommentMap.Application.csproj similarity index 100% rename from CommentMap.Application/CommentMap.Application.csproj rename to src/CommentMap.Application/CommentMap.Application.csproj diff --git a/CommentMap.Application/Entities/Comment.cs b/src/CommentMap.Application/Entities/Comment.cs similarity index 100% rename from CommentMap.Application/Entities/Comment.cs rename to src/CommentMap.Application/Entities/Comment.cs diff --git a/CommentMap.Application/Entities/Country.cs b/src/CommentMap.Application/Entities/Country.cs similarity index 100% rename from CommentMap.Application/Entities/Country.cs rename to src/CommentMap.Application/Entities/Country.cs diff --git a/CommentMap.Application/Entities/Role.cs b/src/CommentMap.Application/Entities/Role.cs similarity index 100% rename from CommentMap.Application/Entities/Role.cs rename to src/CommentMap.Application/Entities/Role.cs diff --git a/CommentMap.Application/Entities/User.cs b/src/CommentMap.Application/Entities/User.cs similarity index 100% rename from CommentMap.Application/Entities/User.cs rename to src/CommentMap.Application/Entities/User.cs diff --git a/CommentMap.Application/Features/Comments/AddComment.cs b/src/CommentMap.Application/Features/Comments/AddComment.cs similarity index 100% rename from CommentMap.Application/Features/Comments/AddComment.cs rename to src/CommentMap.Application/Features/Comments/AddComment.cs diff --git a/CommentMap.Application/Features/Comments/DeleteComment.cs b/src/CommentMap.Application/Features/Comments/DeleteComment.cs similarity index 100% rename from CommentMap.Application/Features/Comments/DeleteComment.cs rename to src/CommentMap.Application/Features/Comments/DeleteComment.cs diff --git a/CommentMap.Application/Features/Comments/GetCommentTitle.cs b/src/CommentMap.Application/Features/Comments/GetCommentTitle.cs similarity index 100% rename from CommentMap.Application/Features/Comments/GetCommentTitle.cs rename to src/CommentMap.Application/Features/Comments/GetCommentTitle.cs diff --git a/CommentMap.Application/Features/Comments/ListComments.cs b/src/CommentMap.Application/Features/Comments/ListComments.cs similarity index 100% rename from CommentMap.Application/Features/Comments/ListComments.cs rename to src/CommentMap.Application/Features/Comments/ListComments.cs diff --git a/CommentMap.Application/Features/Countries/GetCountry.cs b/src/CommentMap.Application/Features/Countries/GetCountry.cs similarity index 100% rename from CommentMap.Application/Features/Countries/GetCountry.cs rename to src/CommentMap.Application/Features/Countries/GetCountry.cs diff --git a/CommentMap.Application/Features/Identity/ChangeEmail.cs b/src/CommentMap.Application/Features/Identity/ChangeEmail.cs similarity index 100% rename from CommentMap.Application/Features/Identity/ChangeEmail.cs rename to src/CommentMap.Application/Features/Identity/ChangeEmail.cs diff --git a/CommentMap.Application/Features/Identity/ChangePassword.cs b/src/CommentMap.Application/Features/Identity/ChangePassword.cs similarity index 100% rename from CommentMap.Application/Features/Identity/ChangePassword.cs rename to src/CommentMap.Application/Features/Identity/ChangePassword.cs diff --git a/CommentMap.Application/Features/Identity/ConfirmEmail.cs b/src/CommentMap.Application/Features/Identity/ConfirmEmail.cs similarity index 100% rename from CommentMap.Application/Features/Identity/ConfirmEmail.cs rename to src/CommentMap.Application/Features/Identity/ConfirmEmail.cs diff --git a/CommentMap.Application/Features/Identity/ConfirmEmailChange.cs b/src/CommentMap.Application/Features/Identity/ConfirmEmailChange.cs similarity index 100% rename from CommentMap.Application/Features/Identity/ConfirmEmailChange.cs rename to src/CommentMap.Application/Features/Identity/ConfirmEmailChange.cs diff --git a/CommentMap.Application/Features/Identity/DeleteProfile.cs b/src/CommentMap.Application/Features/Identity/DeleteProfile.cs similarity index 100% rename from CommentMap.Application/Features/Identity/DeleteProfile.cs rename to src/CommentMap.Application/Features/Identity/DeleteProfile.cs diff --git a/CommentMap.Application/Features/Identity/ExternalLogin.cs b/src/CommentMap.Application/Features/Identity/ExternalLogin.cs similarity index 100% rename from CommentMap.Application/Features/Identity/ExternalLogin.cs rename to src/CommentMap.Application/Features/Identity/ExternalLogin.cs diff --git a/CommentMap.Application/Features/Identity/ForgotPassword.cs b/src/CommentMap.Application/Features/Identity/ForgotPassword.cs similarity index 100% rename from CommentMap.Application/Features/Identity/ForgotPassword.cs rename to src/CommentMap.Application/Features/Identity/ForgotPassword.cs diff --git a/CommentMap.Application/Features/Identity/IdentityMapping.cs b/src/CommentMap.Application/Features/Identity/IdentityMapping.cs similarity index 100% rename from CommentMap.Application/Features/Identity/IdentityMapping.cs rename to src/CommentMap.Application/Features/Identity/IdentityMapping.cs diff --git a/CommentMap.Application/Features/Identity/LoginUser.cs b/src/CommentMap.Application/Features/Identity/LoginUser.cs similarity index 100% rename from CommentMap.Application/Features/Identity/LoginUser.cs rename to src/CommentMap.Application/Features/Identity/LoginUser.cs diff --git a/CommentMap.Application/Features/Identity/LogoutUser.cs b/src/CommentMap.Application/Features/Identity/LogoutUser.cs similarity index 100% rename from CommentMap.Application/Features/Identity/LogoutUser.cs rename to src/CommentMap.Application/Features/Identity/LogoutUser.cs diff --git a/CommentMap.Application/Features/Identity/RegisterUser.cs b/src/CommentMap.Application/Features/Identity/RegisterUser.cs similarity index 100% rename from CommentMap.Application/Features/Identity/RegisterUser.cs rename to src/CommentMap.Application/Features/Identity/RegisterUser.cs diff --git a/CommentMap.Application/Features/Identity/ResendEmailConfirmation.cs b/src/CommentMap.Application/Features/Identity/ResendEmailConfirmation.cs similarity index 100% rename from CommentMap.Application/Features/Identity/ResendEmailConfirmation.cs rename to src/CommentMap.Application/Features/Identity/ResendEmailConfirmation.cs diff --git a/CommentMap.Application/Features/Identity/ResetPassword.cs b/src/CommentMap.Application/Features/Identity/ResetPassword.cs similarity index 100% rename from CommentMap.Application/Features/Identity/ResetPassword.cs rename to src/CommentMap.Application/Features/Identity/ResetPassword.cs diff --git a/CommentMap.Application/Features/Identity/TwoFactor.cs b/src/CommentMap.Application/Features/Identity/TwoFactor.cs similarity index 100% rename from CommentMap.Application/Features/Identity/TwoFactor.cs rename to src/CommentMap.Application/Features/Identity/TwoFactor.cs diff --git a/CommentMap.Application/Models/CommentCardDto.cs b/src/CommentMap.Application/Models/CommentCardDto.cs similarity index 100% rename from CommentMap.Application/Models/CommentCardDto.cs rename to src/CommentMap.Application/Models/CommentCardDto.cs diff --git a/CommentMap.Application/Models/CountryDto.cs b/src/CommentMap.Application/Models/CountryDto.cs similarity index 100% rename from CommentMap.Application/Models/CountryDto.cs rename to src/CommentMap.Application/Models/CountryDto.cs diff --git a/CommentMap.Application/Models/IdentityResultDto.cs b/src/CommentMap.Application/Models/IdentityResultDto.cs similarity index 100% rename from CommentMap.Application/Models/IdentityResultDto.cs rename to src/CommentMap.Application/Models/IdentityResultDto.cs diff --git a/CommentMap.Application/Models/Order.cs b/src/CommentMap.Application/Models/Order.cs similarity index 100% rename from CommentMap.Application/Models/Order.cs rename to src/CommentMap.Application/Models/Order.cs diff --git a/CommentMap.EmailSender/CommentMap.EmailSender.csproj b/src/CommentMap.EmailSender/CommentMap.EmailSender.csproj similarity index 100% rename from CommentMap.EmailSender/CommentMap.EmailSender.csproj rename to src/CommentMap.EmailSender/CommentMap.EmailSender.csproj diff --git a/CommentMap.EmailSender/Exceptions/MjmlValidationException.cs b/src/CommentMap.EmailSender/Exceptions/MjmlValidationException.cs similarity index 100% rename from CommentMap.EmailSender/Exceptions/MjmlValidationException.cs rename to src/CommentMap.EmailSender/Exceptions/MjmlValidationException.cs diff --git a/CommentMap.EmailSender/Extensions/ServiceCollectionExtensions.cs b/src/CommentMap.EmailSender/Extensions/ServiceCollectionExtensions.cs similarity index 100% rename from CommentMap.EmailSender/Extensions/ServiceCollectionExtensions.cs rename to src/CommentMap.EmailSender/Extensions/ServiceCollectionExtensions.cs diff --git a/CommentMap.EmailSender/Internal/Generated/WolverineHandlers/GeneratedHandlerRegistry.cs b/src/CommentMap.EmailSender/Internal/Generated/WolverineHandlers/GeneratedHandlerRegistry.cs similarity index 100% rename from CommentMap.EmailSender/Internal/Generated/WolverineHandlers/GeneratedHandlerRegistry.cs rename to src/CommentMap.EmailSender/Internal/Generated/WolverineHandlers/GeneratedHandlerRegistry.cs diff --git a/CommentMap.EmailSender/Internal/Generated/WolverineHandlers/SendChangeEmailHandler531316428.cs b/src/CommentMap.EmailSender/Internal/Generated/WolverineHandlers/SendChangeEmailHandler531316428.cs similarity index 100% rename from CommentMap.EmailSender/Internal/Generated/WolverineHandlers/SendChangeEmailHandler531316428.cs rename to src/CommentMap.EmailSender/Internal/Generated/WolverineHandlers/SendChangeEmailHandler531316428.cs diff --git a/CommentMap.EmailSender/Internal/Generated/WolverineHandlers/SendConfirmEmailHandler111886888.cs b/src/CommentMap.EmailSender/Internal/Generated/WolverineHandlers/SendConfirmEmailHandler111886888.cs similarity index 100% rename from CommentMap.EmailSender/Internal/Generated/WolverineHandlers/SendConfirmEmailHandler111886888.cs rename to src/CommentMap.EmailSender/Internal/Generated/WolverineHandlers/SendConfirmEmailHandler111886888.cs diff --git a/CommentMap.EmailSender/Internal/Generated/WolverineHandlers/SendResetPasswordEmailHandler453035410.cs b/src/CommentMap.EmailSender/Internal/Generated/WolverineHandlers/SendResetPasswordEmailHandler453035410.cs similarity index 100% rename from CommentMap.EmailSender/Internal/Generated/WolverineHandlers/SendResetPasswordEmailHandler453035410.cs rename to src/CommentMap.EmailSender/Internal/Generated/WolverineHandlers/SendResetPasswordEmailHandler453035410.cs diff --git a/CommentMap.EmailSender/Logging/Log.cs b/src/CommentMap.EmailSender/Logging/Log.cs similarity index 100% rename from CommentMap.EmailSender/Logging/Log.cs rename to src/CommentMap.EmailSender/Logging/Log.cs diff --git a/CommentMap.EmailSender/Options/MailpitClientSettings.cs b/src/CommentMap.EmailSender/Options/MailpitClientSettings.cs similarity index 100% rename from CommentMap.EmailSender/Options/MailpitClientSettings.cs rename to src/CommentMap.EmailSender/Options/MailpitClientSettings.cs diff --git a/CommentMap.EmailSender/Program.cs b/src/CommentMap.EmailSender/Program.cs similarity index 100% rename from CommentMap.EmailSender/Program.cs rename to src/CommentMap.EmailSender/Program.cs diff --git a/CommentMap.EmailSender/Properties/launchSettings.json b/src/CommentMap.EmailSender/Properties/launchSettings.json similarity index 100% rename from CommentMap.EmailSender/Properties/launchSettings.json rename to src/CommentMap.EmailSender/Properties/launchSettings.json diff --git a/CommentMap.EmailSender/Services/IMessageSenderService.cs b/src/CommentMap.EmailSender/Services/IMessageSenderService.cs similarity index 100% rename from CommentMap.EmailSender/Services/IMessageSenderService.cs rename to src/CommentMap.EmailSender/Services/IMessageSenderService.cs diff --git a/CommentMap.EmailSender/Services/ISmtpClientFactory.cs b/src/CommentMap.EmailSender/Services/ISmtpClientFactory.cs similarity index 100% rename from CommentMap.EmailSender/Services/ISmtpClientFactory.cs rename to src/CommentMap.EmailSender/Services/ISmtpClientFactory.cs diff --git a/CommentMap.EmailSender/Services/ISmtpEmailSender.cs b/src/CommentMap.EmailSender/Services/ISmtpEmailSender.cs similarity index 100% rename from CommentMap.EmailSender/Services/ISmtpEmailSender.cs rename to src/CommentMap.EmailSender/Services/ISmtpEmailSender.cs diff --git a/CommentMap.EmailSender/Services/MessageSenderHandler.cs b/src/CommentMap.EmailSender/Services/MessageSenderHandler.cs similarity index 100% rename from CommentMap.EmailSender/Services/MessageSenderHandler.cs rename to src/CommentMap.EmailSender/Services/MessageSenderHandler.cs diff --git a/CommentMap.EmailSender/Services/MessageSenderService.cs b/src/CommentMap.EmailSender/Services/MessageSenderService.cs similarity index 100% rename from CommentMap.EmailSender/Services/MessageSenderService.cs rename to src/CommentMap.EmailSender/Services/MessageSenderService.cs diff --git a/CommentMap.EmailSender/Services/SendMessageConsumer.cs b/src/CommentMap.EmailSender/Services/SendMessageConsumer.cs similarity index 100% rename from CommentMap.EmailSender/Services/SendMessageConsumer.cs rename to src/CommentMap.EmailSender/Services/SendMessageConsumer.cs diff --git a/CommentMap.EmailSender/Services/SmtpClientFactory.cs b/src/CommentMap.EmailSender/Services/SmtpClientFactory.cs similarity index 100% rename from CommentMap.EmailSender/Services/SmtpClientFactory.cs rename to src/CommentMap.EmailSender/Services/SmtpClientFactory.cs diff --git a/CommentMap.EmailSender/Services/SmtpEmailSender.cs b/src/CommentMap.EmailSender/Services/SmtpEmailSender.cs similarity index 100% rename from CommentMap.EmailSender/Services/SmtpEmailSender.cs rename to src/CommentMap.EmailSender/Services/SmtpEmailSender.cs diff --git a/CommentMap.EmailSender/Templates/ChangeEmailViewModel.cs b/src/CommentMap.EmailSender/Templates/ChangeEmailViewModel.cs similarity index 100% rename from CommentMap.EmailSender/Templates/ChangeEmailViewModel.cs rename to src/CommentMap.EmailSender/Templates/ChangeEmailViewModel.cs diff --git a/CommentMap.EmailSender/Templates/ConfirmEmailViewModel.cs b/src/CommentMap.EmailSender/Templates/ConfirmEmailViewModel.cs similarity index 100% rename from CommentMap.EmailSender/Templates/ConfirmEmailViewModel.cs rename to src/CommentMap.EmailSender/Templates/ConfirmEmailViewModel.cs diff --git a/CommentMap.EmailSender/Templates/EmailMessageMjml.cshtml b/src/CommentMap.EmailSender/Templates/EmailMessageMjml.cshtml similarity index 100% rename from CommentMap.EmailSender/Templates/EmailMessageMjml.cshtml rename to src/CommentMap.EmailSender/Templates/EmailMessageMjml.cshtml diff --git a/CommentMap.EmailSender/Templates/IEmailMessageViewModel.cs b/src/CommentMap.EmailSender/Templates/IEmailMessageViewModel.cs similarity index 100% rename from CommentMap.EmailSender/Templates/IEmailMessageViewModel.cs rename to src/CommentMap.EmailSender/Templates/IEmailMessageViewModel.cs diff --git a/CommentMap.EmailSender/Templates/ResetPasswordViewModel.cs b/src/CommentMap.EmailSender/Templates/ResetPasswordViewModel.cs similarity index 100% rename from CommentMap.EmailSender/Templates/ResetPasswordViewModel.cs rename to src/CommentMap.EmailSender/Templates/ResetPasswordViewModel.cs diff --git a/CommentMap.EmailSender/appsettings.json b/src/CommentMap.EmailSender/appsettings.json similarity index 100% rename from CommentMap.EmailSender/appsettings.json rename to src/CommentMap.EmailSender/appsettings.json diff --git a/CommentMap.Infrastructure/CommentMap.Infrastructure.csproj b/src/CommentMap.Infrastructure/CommentMap.Infrastructure.csproj similarity index 100% rename from CommentMap.Infrastructure/CommentMap.Infrastructure.csproj rename to src/CommentMap.Infrastructure/CommentMap.Infrastructure.csproj diff --git a/CommentMap.Infrastructure/Data/CommentMapDbContext.cs b/src/CommentMap.Infrastructure/Data/CommentMapDbContext.cs similarity index 100% rename from CommentMap.Infrastructure/Data/CommentMapDbContext.cs rename to src/CommentMap.Infrastructure/Data/CommentMapDbContext.cs diff --git a/CommentMap.Infrastructure/Data/Configurations/CommentConfiguration.cs b/src/CommentMap.Infrastructure/Data/Configurations/CommentConfiguration.cs similarity index 100% rename from CommentMap.Infrastructure/Data/Configurations/CommentConfiguration.cs rename to src/CommentMap.Infrastructure/Data/Configurations/CommentConfiguration.cs diff --git a/CommentMap.Infrastructure/Data/Configurations/CountryConfiguration.cs b/src/CommentMap.Infrastructure/Data/Configurations/CountryConfiguration.cs similarity index 100% rename from CommentMap.Infrastructure/Data/Configurations/CountryConfiguration.cs rename to src/CommentMap.Infrastructure/Data/Configurations/CountryConfiguration.cs diff --git a/CommentMap.Infrastructure/Data/Migrations/20240523173725_InitialMigration.Designer.cs b/src/CommentMap.Infrastructure/Data/Migrations/20240523173725_InitialMigration.Designer.cs similarity index 100% rename from CommentMap.Infrastructure/Data/Migrations/20240523173725_InitialMigration.Designer.cs rename to src/CommentMap.Infrastructure/Data/Migrations/20240523173725_InitialMigration.Designer.cs diff --git a/CommentMap.Infrastructure/Data/Migrations/20240523173725_InitialMigration.cs b/src/CommentMap.Infrastructure/Data/Migrations/20240523173725_InitialMigration.cs similarity index 100% rename from CommentMap.Infrastructure/Data/Migrations/20240523173725_InitialMigration.cs rename to src/CommentMap.Infrastructure/Data/Migrations/20240523173725_InitialMigration.cs diff --git a/CommentMap.Infrastructure/Data/Migrations/20240525160654_AddCommentProperties.Designer.cs b/src/CommentMap.Infrastructure/Data/Migrations/20240525160654_AddCommentProperties.Designer.cs similarity index 100% rename from CommentMap.Infrastructure/Data/Migrations/20240525160654_AddCommentProperties.Designer.cs rename to src/CommentMap.Infrastructure/Data/Migrations/20240525160654_AddCommentProperties.Designer.cs diff --git a/CommentMap.Infrastructure/Data/Migrations/20240525160654_AddCommentProperties.cs b/src/CommentMap.Infrastructure/Data/Migrations/20240525160654_AddCommentProperties.cs similarity index 100% rename from CommentMap.Infrastructure/Data/Migrations/20240525160654_AddCommentProperties.cs rename to src/CommentMap.Infrastructure/Data/Migrations/20240525160654_AddCommentProperties.cs diff --git a/CommentMap.Infrastructure/Data/Migrations/20240623144537_AddIsDeleted.Designer.cs b/src/CommentMap.Infrastructure/Data/Migrations/20240623144537_AddIsDeleted.Designer.cs similarity index 100% rename from CommentMap.Infrastructure/Data/Migrations/20240623144537_AddIsDeleted.Designer.cs rename to src/CommentMap.Infrastructure/Data/Migrations/20240623144537_AddIsDeleted.Designer.cs diff --git a/CommentMap.Infrastructure/Data/Migrations/20240623144537_AddIsDeleted.cs b/src/CommentMap.Infrastructure/Data/Migrations/20240623144537_AddIsDeleted.cs similarity index 100% rename from CommentMap.Infrastructure/Data/Migrations/20240623144537_AddIsDeleted.cs rename to src/CommentMap.Infrastructure/Data/Migrations/20240623144537_AddIsDeleted.cs diff --git a/CommentMap.Infrastructure/Data/Migrations/20240909164708_AddCountry.Designer.cs b/src/CommentMap.Infrastructure/Data/Migrations/20240909164708_AddCountry.Designer.cs similarity index 100% rename from CommentMap.Infrastructure/Data/Migrations/20240909164708_AddCountry.Designer.cs rename to src/CommentMap.Infrastructure/Data/Migrations/20240909164708_AddCountry.Designer.cs diff --git a/CommentMap.Infrastructure/Data/Migrations/20240909164708_AddCountry.cs b/src/CommentMap.Infrastructure/Data/Migrations/20240909164708_AddCountry.cs similarity index 100% rename from CommentMap.Infrastructure/Data/Migrations/20240909164708_AddCountry.cs rename to src/CommentMap.Infrastructure/Data/Migrations/20240909164708_AddCountry.cs diff --git a/CommentMap.Infrastructure/Data/Migrations/20240921074639_AddISO3CountryCodeToComment.Designer.cs b/src/CommentMap.Infrastructure/Data/Migrations/20240921074639_AddISO3CountryCodeToComment.Designer.cs similarity index 100% rename from CommentMap.Infrastructure/Data/Migrations/20240921074639_AddISO3CountryCodeToComment.Designer.cs rename to src/CommentMap.Infrastructure/Data/Migrations/20240921074639_AddISO3CountryCodeToComment.Designer.cs diff --git a/CommentMap.Infrastructure/Data/Migrations/20240921074639_AddISO3CountryCodeToComment.cs b/src/CommentMap.Infrastructure/Data/Migrations/20240921074639_AddISO3CountryCodeToComment.cs similarity index 100% rename from CommentMap.Infrastructure/Data/Migrations/20240921074639_AddISO3CountryCodeToComment.cs rename to src/CommentMap.Infrastructure/Data/Migrations/20240921074639_AddISO3CountryCodeToComment.cs diff --git a/CommentMap.Infrastructure/Data/Migrations/CommentMapDbContextModelSnapshot.cs b/src/CommentMap.Infrastructure/Data/Migrations/CommentMapDbContextModelSnapshot.cs similarity index 100% rename from CommentMap.Infrastructure/Data/Migrations/CommentMapDbContextModelSnapshot.cs rename to src/CommentMap.Infrastructure/Data/Migrations/CommentMapDbContextModelSnapshot.cs diff --git a/CommentMap.Infrastructure/DependencyInjection/InfrastructureServiceCollectionExtensions.cs b/src/CommentMap.Infrastructure/DependencyInjection/InfrastructureServiceCollectionExtensions.cs similarity index 100% rename from CommentMap.Infrastructure/DependencyInjection/InfrastructureServiceCollectionExtensions.cs rename to src/CommentMap.Infrastructure/DependencyInjection/InfrastructureServiceCollectionExtensions.cs diff --git a/CommentMap.MigrationService/CommentMap.MigrationService.csproj b/src/CommentMap.MigrationService/CommentMap.MigrationService.csproj similarity index 100% rename from CommentMap.MigrationService/CommentMap.MigrationService.csproj rename to src/CommentMap.MigrationService/CommentMap.MigrationService.csproj diff --git a/CommentMap.MigrationService/Migrator.cs b/src/CommentMap.MigrationService/Migrator.cs similarity index 100% rename from CommentMap.MigrationService/Migrator.cs rename to src/CommentMap.MigrationService/Migrator.cs diff --git a/CommentMap.MigrationService/Program.cs b/src/CommentMap.MigrationService/Program.cs similarity index 100% rename from CommentMap.MigrationService/Program.cs rename to src/CommentMap.MigrationService/Program.cs diff --git a/CommentMap.MigrationService/Properties/launchSettings.json b/src/CommentMap.MigrationService/Properties/launchSettings.json similarity index 100% rename from CommentMap.MigrationService/Properties/launchSettings.json rename to src/CommentMap.MigrationService/Properties/launchSettings.json diff --git a/CommentMap.MigrationService/appsettings.Development.json b/src/CommentMap.MigrationService/appsettings.Development.json similarity index 100% rename from CommentMap.MigrationService/appsettings.Development.json rename to src/CommentMap.MigrationService/appsettings.Development.json diff --git a/CommentMap.MigrationService/appsettings.json b/src/CommentMap.MigrationService/appsettings.json similarity index 100% rename from CommentMap.MigrationService/appsettings.json rename to src/CommentMap.MigrationService/appsettings.json diff --git a/src/CommentMap.Mvc/Areas/Identity/Pages/Account/AccessDenied.cshtml b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/AccessDenied.cshtml new file mode 100644 index 0000000..ce00514 --- /dev/null +++ b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/AccessDenied.cshtml @@ -0,0 +1,10 @@ +@page +@model AccessDeniedModel +@{ + ViewData["Title"] = "Access denied"; +} + +
+

@ViewData["Title"]

+

You do not have access to this resource.

+
diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/AccessDenied.cshtml.cs b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/AccessDenied.cshtml.cs similarity index 100% rename from CommentMap.Mvc/Areas/Identity/Pages/Account/AccessDenied.cshtml.cs rename to src/CommentMap.Mvc/Areas/Identity/Pages/Account/AccessDenied.cshtml.cs diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/ConfirmEmail.cshtml b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/ConfirmEmail.cshtml similarity index 72% rename from CommentMap.Mvc/Areas/Identity/Pages/Account/ConfirmEmail.cshtml rename to src/CommentMap.Mvc/Areas/Identity/Pages/Account/ConfirmEmail.cshtml index 2deb2e5..bf991c6 100644 --- a/CommentMap.Mvc/Areas/Identity/Pages/Account/ConfirmEmail.cshtml +++ b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/ConfirmEmail.cshtml @@ -4,5 +4,5 @@ ViewData["Title"] = "Confirm email"; } -

@ViewData["Title"]

+

@ViewData["Title"]

diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/ConfirmEmail.cshtml.cs b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/ConfirmEmail.cshtml.cs similarity index 100% rename from CommentMap.Mvc/Areas/Identity/Pages/Account/ConfirmEmail.cshtml.cs rename to src/CommentMap.Mvc/Areas/Identity/Pages/Account/ConfirmEmail.cshtml.cs diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/ConfirmEmailChange.cshtml b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/ConfirmEmailChange.cshtml similarity index 73% rename from CommentMap.Mvc/Areas/Identity/Pages/Account/ConfirmEmailChange.cshtml rename to src/CommentMap.Mvc/Areas/Identity/Pages/Account/ConfirmEmailChange.cshtml index 114fa88..9c64de7 100644 --- a/CommentMap.Mvc/Areas/Identity/Pages/Account/ConfirmEmailChange.cshtml +++ b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/ConfirmEmailChange.cshtml @@ -4,5 +4,5 @@ ViewData["Title"] = "Confirm email change"; } -

@ViewData["Title"]

+

@ViewData["Title"]

diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/ConfirmEmailChange.cshtml.cs b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/ConfirmEmailChange.cshtml.cs similarity index 100% rename from CommentMap.Mvc/Areas/Identity/Pages/Account/ConfirmEmailChange.cshtml.cs rename to src/CommentMap.Mvc/Areas/Identity/Pages/Account/ConfirmEmailChange.cshtml.cs diff --git a/src/CommentMap.Mvc/Areas/Identity/Pages/Account/ExternalLogin.cshtml b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/ExternalLogin.cshtml new file mode 100644 index 0000000..2c120a8 --- /dev/null +++ b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/ExternalLogin.cshtml @@ -0,0 +1,31 @@ +@page +@model ExternalLoginModel +@{ + ViewData["Title"] = "Register"; +} + +

@ViewData["Title"]

+

Associate your @Model.ProviderDisplayName account.

+
+ +

+ You've successfully authenticated with @Model.ProviderDisplayName. + Please enter an username for this site below and click the Register button to finish + logging in. +

+ +
+
+ +
+ + + +
+ +
+
+ +@section Scripts { + +} diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/ExternalLogin.cshtml.cs b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/ExternalLogin.cshtml.cs similarity index 100% rename from CommentMap.Mvc/Areas/Identity/Pages/Account/ExternalLogin.cshtml.cs rename to src/CommentMap.Mvc/Areas/Identity/Pages/Account/ExternalLogin.cshtml.cs diff --git a/src/CommentMap.Mvc/Areas/Identity/Pages/Account/ForgotPassword.cshtml b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/ForgotPassword.cshtml new file mode 100644 index 0000000..446e390 --- /dev/null +++ b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/ForgotPassword.cshtml @@ -0,0 +1,24 @@ +@page +@model ForgotPasswordModel +@{ + ViewData["Title"] = "Forgot your password?"; +} + +

@ViewData["Title"]

+

Enter your email.

+
+
+
+ +
+ + + +
+ +
+
+ +@section Scripts { + +} diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/ForgotPassword.cshtml.cs b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/ForgotPassword.cshtml.cs similarity index 100% rename from CommentMap.Mvc/Areas/Identity/Pages/Account/ForgotPassword.cshtml.cs rename to src/CommentMap.Mvc/Areas/Identity/Pages/Account/ForgotPassword.cshtml.cs diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/ForgotPasswordConfirmation.cshtml b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/ForgotPasswordConfirmation.cshtml similarity index 74% rename from CommentMap.Mvc/Areas/Identity/Pages/Account/ForgotPasswordConfirmation.cshtml rename to src/CommentMap.Mvc/Areas/Identity/Pages/Account/ForgotPasswordConfirmation.cshtml index 6315d96..f049ebf 100644 --- a/CommentMap.Mvc/Areas/Identity/Pages/Account/ForgotPasswordConfirmation.cshtml +++ b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/ForgotPasswordConfirmation.cshtml @@ -4,5 +4,5 @@ ViewData["Title"] = "Forgot password confirmation"; } -

@ViewData["Title"]

+

@ViewData["Title"]

Please check your email to reset your password.

diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/ForgotPasswordConfirmation.cshtml.cs b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/ForgotPasswordConfirmation.cshtml.cs similarity index 100% rename from CommentMap.Mvc/Areas/Identity/Pages/Account/ForgotPasswordConfirmation.cshtml.cs rename to src/CommentMap.Mvc/Areas/Identity/Pages/Account/ForgotPasswordConfirmation.cshtml.cs diff --git a/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Login.cshtml b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Login.cshtml new file mode 100644 index 0000000..345f59a --- /dev/null +++ b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Login.cshtml @@ -0,0 +1,60 @@ +@page +@model LoginModel + +@{ + ViewData["Title"] = "Log in"; +} + +

@ViewData["Title"]

+ +
+
+
+
+

Use a local account to log in.

+ +
+ + + +
+
+ + + +
+ + + +
+
+
+
+
+

Use another service to log in.

+
+ @foreach (var provider in Model.ExternalLogins!) + { + + } +
+
+
+
+ +@section Scripts { + +} diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/Login.cshtml.cs b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Login.cshtml.cs similarity index 100% rename from CommentMap.Mvc/Areas/Identity/Pages/Account/Login.cshtml.cs rename to src/CommentMap.Mvc/Areas/Identity/Pages/Account/Login.cshtml.cs diff --git a/src/CommentMap.Mvc/Areas/Identity/Pages/Account/LoginWith2fa.cshtml b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/LoginWith2fa.cshtml new file mode 100644 index 0000000..8f9de3f --- /dev/null +++ b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/LoginWith2fa.cshtml @@ -0,0 +1,33 @@ +@page +@model LoginWith2faModel +@{ + ViewData["Title"] = "Two-factor authentication"; +} + +

@ViewData["Title"]

+
+

Your login is protected with an authenticator app. Enter your authenticator code below.

+
+
+ + +
+ + + +
+ + +
+
+

+ Don't have access to your authenticator device? You can + log in with a recovery code. +

+ +@section Scripts { + +} diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/LoginWith2fa.cshtml.cs b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/LoginWith2fa.cshtml.cs similarity index 100% rename from CommentMap.Mvc/Areas/Identity/Pages/Account/LoginWith2fa.cshtml.cs rename to src/CommentMap.Mvc/Areas/Identity/Pages/Account/LoginWith2fa.cshtml.cs diff --git a/src/CommentMap.Mvc/Areas/Identity/Pages/Account/LoginWithRecoveryCode.cshtml b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/LoginWithRecoveryCode.cshtml new file mode 100644 index 0000000..2df483d --- /dev/null +++ b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/LoginWithRecoveryCode.cshtml @@ -0,0 +1,27 @@ +@page +@model LoginWithRecoveryCodeModel +@{ + ViewData["Title"] = "Recovery code verification"; +} + +

@ViewData["Title"]

+
+

+ You have requested to log in with a recovery code. This login will not be remembered until you provide + an authenticator app code at log in or disable 2FA and log in again. +

+
+
+ +
+ + + +
+ +
+
+ +@section Scripts { + +} diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/LoginWithRecoveryCode.cshtml.cs b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/LoginWithRecoveryCode.cshtml.cs similarity index 100% rename from CommentMap.Mvc/Areas/Identity/Pages/Account/LoginWithRecoveryCode.cshtml.cs rename to src/CommentMap.Mvc/Areas/Identity/Pages/Account/LoginWithRecoveryCode.cshtml.cs diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/Logout.cshtml b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Logout.cshtml similarity index 74% rename from CommentMap.Mvc/Areas/Identity/Pages/Account/Logout.cshtml rename to src/CommentMap.Mvc/Areas/Identity/Pages/Account/Logout.cshtml index 335ef07..1ff2bde 100644 --- a/CommentMap.Mvc/Areas/Identity/Pages/Account/Logout.cshtml +++ b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Logout.cshtml @@ -5,12 +5,12 @@ }
-

@ViewData["Title"]

+

@ViewData["Title"]

@{ if (User.Identity?.IsAuthenticated ?? false) {
- +
} else diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/Logout.cshtml.cs b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Logout.cshtml.cs similarity index 100% rename from CommentMap.Mvc/Areas/Identity/Pages/Account/Logout.cshtml.cs rename to src/CommentMap.Mvc/Areas/Identity/Pages/Account/Logout.cshtml.cs diff --git a/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ChangePassword.cshtml b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ChangePassword.cshtml new file mode 100644 index 0000000..d495dfb --- /dev/null +++ b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ChangePassword.cshtml @@ -0,0 +1,35 @@ +@page +@model ChangePasswordModel +@{ + ViewData["Title"] = "Change password"; +} + +

@ViewData["Title"]

+ + + +
+
+ +
+ + + +
+
+ + + +
+
+ + + +
+ +
+
+ +@section Scripts { + +} diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ChangePassword.cshtml.cs b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ChangePassword.cshtml.cs similarity index 100% rename from CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ChangePassword.cshtml.cs rename to src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ChangePassword.cshtml.cs diff --git a/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/DeleteProfile.cshtml b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/DeleteProfile.cshtml new file mode 100644 index 0000000..da0b3fc --- /dev/null +++ b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/DeleteProfile.cshtml @@ -0,0 +1,36 @@ +@page +@model DeletePersonalDataModel +@{ + ViewData["Title"] = "Delete your profile"; +} + +

@ViewData["Title"]

+ + + +
+
+ + @if (Model.RequirePassword) + { +
+ + + +
+ } + +
+
+ +@section Scripts { + +} diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/DeleteProfile.cshtml.cs b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/DeleteProfile.cshtml.cs similarity index 100% rename from CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/DeleteProfile.cshtml.cs rename to src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/DeleteProfile.cshtml.cs diff --git a/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/Disable2fa.cshtml b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/Disable2fa.cshtml new file mode 100644 index 0000000..63c8bc0 --- /dev/null +++ b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/Disable2fa.cshtml @@ -0,0 +1,25 @@ +@page +@model Disable2faModel +@{ + ViewData["Title"] = "Disable two-factor authentication (2FA)"; +} + + +

@ViewData["Title"]

+ + + +
+ +
diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/Disable2fa.cshtml.cs b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/Disable2fa.cshtml.cs similarity index 100% rename from CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/Disable2fa.cshtml.cs rename to src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/Disable2fa.cshtml.cs diff --git a/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/EnableAuthenticator.cshtml b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/EnableAuthenticator.cshtml new file mode 100644 index 0000000..6f93d7a --- /dev/null +++ b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/EnableAuthenticator.cshtml @@ -0,0 +1,50 @@ +@page +@model EnableAuthenticatorModel +@{ + ViewData["Title"] = "Configure authenticator app"; +} + + + +

@ViewData["Title"]

+ +
+

To use an authenticator app go through the following steps:

+
    +
  1. +

    + Download a two-factor authenticator app like Microsoft Authenticator for + Android and + iOS or + Google Authenticator for + Android and + iOS. +

    +
  2. +
  3. +

    Scan the QR Code or enter this key @Model.SharedKey into your two factor authenticator app. Spaces and casing do not matter.

    + @Model.AuthenticatorUri +
  4. +
  5. +

    + Once you have scanned the QR code or input the key above, your two factor authentication app will provide you + with a unique code. Enter the code in the confirmation box below. +

    +
    +
    +
    + + + +
    + + +
    +
    +
  6. +
+
+ +@section Scripts { + +} diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/EnableAuthenticator.cshtml.cs b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/EnableAuthenticator.cshtml.cs similarity index 100% rename from CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/EnableAuthenticator.cshtml.cs rename to src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/EnableAuthenticator.cshtml.cs diff --git a/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ExternalLogins.cshtml b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ExternalLogins.cshtml new file mode 100644 index 0000000..b0c4c6c --- /dev/null +++ b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ExternalLogins.cshtml @@ -0,0 +1,47 @@ +@page +@model ExternalLoginsModel +@{ + ViewData["Title"] = "Manage your external logins"; +} + + + +@if (Model.CurrentLogins?.Count > 0) +{ +

Registered logins

+
+ + + @foreach (var login in Model.CurrentLogins) + { + + + @if (Model.ShowRemoveButton) + { + + } + + } + +
@login.ProviderDisplayName +
+
+ + + +
+
+
+
+} +@if (Model.OtherLogins?.Count > 0) +{ +

Add another service to log in.

+
+
+ @foreach (var provider in Model.OtherLogins) + { + + } +
+} diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ExternalLogins.cshtml.cs b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ExternalLogins.cshtml.cs similarity index 100% rename from CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ExternalLogins.cshtml.cs rename to src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ExternalLogins.cshtml.cs diff --git a/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/GenerateRecoveryCodes.cshtml b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/GenerateRecoveryCodes.cshtml new file mode 100644 index 0000000..112c241 --- /dev/null +++ b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/GenerateRecoveryCodes.cshtml @@ -0,0 +1,26 @@ +@page +@model GenerateRecoveryCodesModel +@{ + ViewData["Title"] = "Generate two-factor authentication (2FA) recovery codes"; +} + + +

@ViewData["Title"]

+ +
+ +
diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/GenerateRecoveryCodes.cshtml.cs b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/GenerateRecoveryCodes.cshtml.cs similarity index 100% rename from CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/GenerateRecoveryCodes.cshtml.cs rename to src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/GenerateRecoveryCodes.cshtml.cs diff --git a/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/Index.cshtml b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/Index.cshtml new file mode 100644 index 0000000..00e7be4 --- /dev/null +++ b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/Index.cshtml @@ -0,0 +1,39 @@ +@page +@model IndexModel +@{ + ViewData["Title"] = "Manage Email"; +} + +

@ViewData["Title"]

+ + + +
+
+ + +
+ +
+ + + + +
+
+ +
+ + + +
+ + +
+
+ +@section Scripts { + +} diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/Index.cshtml.cs b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/Index.cshtml.cs similarity index 100% rename from CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/Index.cshtml.cs rename to src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/Index.cshtml.cs diff --git a/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ResetAuthenticator.cshtml b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ResetAuthenticator.cshtml new file mode 100644 index 0000000..a70f025 --- /dev/null +++ b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ResetAuthenticator.cshtml @@ -0,0 +1,23 @@ +@page +@model ResetAuthenticatorModel +@{ + ViewData["Title"] = "Reset authenticator key"; +} + + +

@ViewData["Title"]

+ +
+ +
diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ResetAuthenticator.cshtml.cs b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ResetAuthenticator.cshtml.cs similarity index 100% rename from CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ResetAuthenticator.cshtml.cs rename to src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ResetAuthenticator.cshtml.cs diff --git a/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/SetPassword.cshtml b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/SetPassword.cshtml new file mode 100644 index 0000000..34bde6a --- /dev/null +++ b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/SetPassword.cshtml @@ -0,0 +1,34 @@ +@page +@model SetPasswordModel +@{ + ViewData["Title"] = "Set password"; +} + +

Set your password

+ + + +

+ You do not have a local password for this site. Add a local account + so you can log in without an external login. +

+
+
+ +
+ + + +
+
+ + + +
+ +
+
+ +@section Scripts { + +} diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/SetPassword.cshtml.cs b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/SetPassword.cshtml.cs similarity index 100% rename from CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/SetPassword.cshtml.cs rename to src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/SetPassword.cshtml.cs diff --git a/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ShowRecoveryCodes.cshtml b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ShowRecoveryCodes.cshtml new file mode 100644 index 0000000..4e8ca7d --- /dev/null +++ b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ShowRecoveryCodes.cshtml @@ -0,0 +1,25 @@ +@page +@model ShowRecoveryCodesModel +@{ + ViewData["Title"] = "Recovery codes"; +} + + +

@ViewData["Title"]

+ +
+ @for (var row = 0; row < Model.RecoveryCodes.Length; row += 2) + { + @Model.RecoveryCodes[row] @Model.RecoveryCodes[row + 1]
+ } +
diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ShowRecoveryCodes.cshtml.cs b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ShowRecoveryCodes.cshtml.cs similarity index 100% rename from CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ShowRecoveryCodes.cshtml.cs rename to src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/ShowRecoveryCodes.cshtml.cs diff --git a/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/TwoFactorAuthentication.cshtml b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/TwoFactorAuthentication.cshtml new file mode 100644 index 0000000..5b41176 --- /dev/null +++ b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/TwoFactorAuthentication.cshtml @@ -0,0 +1,82 @@ +@page +@using Microsoft.AspNetCore.Http.Features +@model TwoFactorAuthenticationModel +@{ + ViewData["Title"] = "Two-factor authentication (2FA)"; +} + + +

@ViewData["Title"]

+@{ + var consentFeature = HttpContext.Features.Get(); + @if (consentFeature?.CanTrack ?? true) + { + @if (Model.Is2faEnabled) + { + if (Model.RecoveryCodesLeft == 0) + { +
+
+
You have no recovery codes left.
+

You must generate a new set of recovery codes before you can log in with a recovery code.

+
+
+ } + else if (Model.RecoveryCodesLeft == 1) + { +
+
+
You have 1 recovery code left.
+

You can generate a new set of recovery codes.

+
+
+ } + else if (Model.RecoveryCodesLeft <= 3) + { +
+
+
You have @Model.RecoveryCodesLeft recovery codes left.
+

You should generate a new set of recovery codes.

+
+
+ } + + @if (Model.IsMachineRemembered) + { +
+ +
+ } + + } + +

Authenticator app

+ @if (!Model.HasAuthenticator) + { + Add authenticator app + } + else + { + + } + } + else + { +
+
+
Privacy and cookie policy have not been accepted.
+

You must accept the policy before you can enable two factor authentication.

+
+
+ } +} + +@section Scripts { + +} diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/TwoFactorAuthentication.cshtml.cs b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/TwoFactorAuthentication.cshtml.cs similarity index 100% rename from CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/TwoFactorAuthentication.cshtml.cs rename to src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/TwoFactorAuthentication.cshtml.cs diff --git a/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/_Layout.cshtml b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/_Layout.cshtml new file mode 100644 index 0000000..b949f58 --- /dev/null +++ b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/_Layout.cshtml @@ -0,0 +1,22 @@ +@{ + Layout = "/Pages/Shared/_Layout.cshtml"; +} + +

Manage your account

+ +
+

Change your account settings

+
+
+
+ +
+
+ @RenderBody() +
+
+
+ +@section Scripts { + @RenderSection("Scripts", required: false) +} diff --git a/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/_ManageNav.cshtml b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/_ManageNav.cshtml new file mode 100644 index 0000000..982a131 --- /dev/null +++ b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Manage/_ManageNav.cshtml @@ -0,0 +1,7 @@ + diff --git a/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Register.cshtml b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Register.cshtml new file mode 100644 index 0000000..014911d --- /dev/null +++ b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Register.cshtml @@ -0,0 +1,50 @@ +@page +@model RegisterModel +@{ + ViewData["Title"] = "Register"; +} + +

@ViewData["Title"]

+ +
+
+
+

Create a new account.

+ +
+ + + +
+
+ + + +
+
+ + + +
+ +

+ Already have an account? +

+
+
+
+
+

Use another service to register.

+
+ @foreach (var provider in Model.ExternalLogins!) + { + + } +
+
+
+
+ +@section Scripts { + +} diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/Register.cshtml.cs b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/Register.cshtml.cs similarity index 100% rename from CommentMap.Mvc/Areas/Identity/Pages/Account/Register.cshtml.cs rename to src/CommentMap.Mvc/Areas/Identity/Pages/Account/Register.cshtml.cs diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/RegisterConfirmation.cshtml b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/RegisterConfirmation.cshtml similarity index 100% rename from CommentMap.Mvc/Areas/Identity/Pages/Account/RegisterConfirmation.cshtml rename to src/CommentMap.Mvc/Areas/Identity/Pages/Account/RegisterConfirmation.cshtml diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/RegisterConfirmation.cshtml.cs b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/RegisterConfirmation.cshtml.cs similarity index 100% rename from CommentMap.Mvc/Areas/Identity/Pages/Account/RegisterConfirmation.cshtml.cs rename to src/CommentMap.Mvc/Areas/Identity/Pages/Account/RegisterConfirmation.cshtml.cs diff --git a/src/CommentMap.Mvc/Areas/Identity/Pages/Account/ResendEmailConfirmation.cshtml b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/ResendEmailConfirmation.cshtml new file mode 100644 index 0000000..0b215ee --- /dev/null +++ b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/ResendEmailConfirmation.cshtml @@ -0,0 +1,25 @@ +@page +@model ResendEmailConfirmationModel +@{ + ViewData["Title"] = "Resend email confirmation"; +} + +

@ViewData["Title"]

+ + + +

Enter your email.

+
+
+
+ + + +
+ +
+
+ +@section Scripts { + +} diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/ResendEmailConfirmation.cshtml.cs b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/ResendEmailConfirmation.cshtml.cs similarity index 100% rename from CommentMap.Mvc/Areas/Identity/Pages/Account/ResendEmailConfirmation.cshtml.cs rename to src/CommentMap.Mvc/Areas/Identity/Pages/Account/ResendEmailConfirmation.cshtml.cs diff --git a/src/CommentMap.Mvc/Areas/Identity/Pages/Account/ResetPassword.cshtml b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/ResetPassword.cshtml new file mode 100644 index 0000000..7fdaead --- /dev/null +++ b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/ResetPassword.cshtml @@ -0,0 +1,29 @@ +@page +@model ResetPasswordModel +@{ + ViewData["Title"] = "Reset password"; +} + +

@ViewData["Title"]

+

Reset your password.

+
+
+
+ +
+ + + +
+
+ + + +
+ +
+
+ +@section Scripts { + +} diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/ResetPassword.cshtml.cs b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/ResetPassword.cshtml.cs similarity index 100% rename from CommentMap.Mvc/Areas/Identity/Pages/Account/ResetPassword.cshtml.cs rename to src/CommentMap.Mvc/Areas/Identity/Pages/Account/ResetPassword.cshtml.cs diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/ResetPasswordConfirmation.cshtml b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/ResetPasswordConfirmation.cshtml similarity index 78% rename from CommentMap.Mvc/Areas/Identity/Pages/Account/ResetPasswordConfirmation.cshtml rename to src/CommentMap.Mvc/Areas/Identity/Pages/Account/ResetPasswordConfirmation.cshtml index 846037c..e9ae4aa 100644 --- a/CommentMap.Mvc/Areas/Identity/Pages/Account/ResetPasswordConfirmation.cshtml +++ b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/ResetPasswordConfirmation.cshtml @@ -4,6 +4,6 @@ ViewData["Title"] = "Reset password confirmation"; } -

@ViewData["Title"]

+

@ViewData["Title"]

Your password has been reset. Please click here to log in.

diff --git a/CommentMap.Mvc/Areas/Identity/Pages/Account/ResetPasswordConfirmation.cshtml.cs b/src/CommentMap.Mvc/Areas/Identity/Pages/Account/ResetPasswordConfirmation.cshtml.cs similarity index 100% rename from CommentMap.Mvc/Areas/Identity/Pages/Account/ResetPasswordConfirmation.cshtml.cs rename to src/CommentMap.Mvc/Areas/Identity/Pages/Account/ResetPasswordConfirmation.cshtml.cs diff --git a/src/CommentMap.Mvc/Areas/Identity/Pages/_StatusMessage.cshtml b/src/CommentMap.Mvc/Areas/Identity/Pages/_StatusMessage.cshtml new file mode 100644 index 0000000..a6006cd --- /dev/null +++ b/src/CommentMap.Mvc/Areas/Identity/Pages/_StatusMessage.cshtml @@ -0,0 +1,24 @@ +@model string + +@if (!String.IsNullOrEmpty(Model)) +{ + var statusMessageClass = Model.StartsWith("Error") ? "error" : "success"; + +} diff --git a/CommentMap.Mvc/Areas/Identity/Pages/_ViewImports.cshtml b/src/CommentMap.Mvc/Areas/Identity/Pages/_ViewImports.cshtml similarity index 100% rename from CommentMap.Mvc/Areas/Identity/Pages/_ViewImports.cshtml rename to src/CommentMap.Mvc/Areas/Identity/Pages/_ViewImports.cshtml diff --git a/CommentMap.Mvc/Areas/Identity/Pages/_ViewStart.cshtml b/src/CommentMap.Mvc/Areas/Identity/Pages/_ViewStart.cshtml similarity index 100% rename from CommentMap.Mvc/Areas/Identity/Pages/_ViewStart.cshtml rename to src/CommentMap.Mvc/Areas/Identity/Pages/_ViewStart.cshtml diff --git a/CommentMap.Mvc/CommentMap.Mvc.csproj b/src/CommentMap.Mvc/CommentMap.Mvc.csproj similarity index 91% rename from CommentMap.Mvc/CommentMap.Mvc.csproj rename to src/CommentMap.Mvc/CommentMap.Mvc.csproj index 9c6a18b..c2569d4 100644 --- a/CommentMap.Mvc/CommentMap.Mvc.csproj +++ b/src/CommentMap.Mvc/CommentMap.Mvc.csproj @@ -9,14 +9,12 @@ - - @@ -29,7 +27,6 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - @@ -47,5 +44,10 @@ - + + + + + + diff --git a/CommentMap.Mvc/Extensions/ClaimsPrincipalExtensions.cs b/src/CommentMap.Mvc/Extensions/ClaimsPrincipalExtensions.cs similarity index 100% rename from CommentMap.Mvc/Extensions/ClaimsPrincipalExtensions.cs rename to src/CommentMap.Mvc/Extensions/ClaimsPrincipalExtensions.cs diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/AddCommentHandler838741630.cs b/src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/AddCommentHandler838741630.cs similarity index 100% rename from CommentMap.Mvc/Internal/Generated/WolverineHandlers/AddCommentHandler838741630.cs rename to src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/AddCommentHandler838741630.cs diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ChangePasswordHandler702758377.cs b/src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ChangePasswordHandler702758377.cs similarity index 100% rename from CommentMap.Mvc/Internal/Generated/WolverineHandlers/ChangePasswordHandler702758377.cs rename to src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ChangePasswordHandler702758377.cs diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ConfirmEmailChangeHandler1497850754.cs b/src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ConfirmEmailChangeHandler1497850754.cs similarity index 100% rename from CommentMap.Mvc/Internal/Generated/WolverineHandlers/ConfirmEmailChangeHandler1497850754.cs rename to src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ConfirmEmailChangeHandler1497850754.cs diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ConfirmEmailHandler55631218.cs b/src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ConfirmEmailHandler55631218.cs similarity index 100% rename from CommentMap.Mvc/Internal/Generated/WolverineHandlers/ConfirmEmailHandler55631218.cs rename to src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ConfirmEmailHandler55631218.cs diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/CreateExternalUserHandler966620274.cs b/src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/CreateExternalUserHandler966620274.cs similarity index 100% rename from CommentMap.Mvc/Internal/Generated/WolverineHandlers/CreateExternalUserHandler966620274.cs rename to src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/CreateExternalUserHandler966620274.cs diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/DeleteCommentHandler107828254.cs b/src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/DeleteCommentHandler107828254.cs similarity index 100% rename from CommentMap.Mvc/Internal/Generated/WolverineHandlers/DeleteCommentHandler107828254.cs rename to src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/DeleteCommentHandler107828254.cs diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/DeleteProfileHandler1834710062.cs b/src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/DeleteProfileHandler1834710062.cs similarity index 100% rename from CommentMap.Mvc/Internal/Generated/WolverineHandlers/DeleteProfileHandler1834710062.cs rename to src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/DeleteProfileHandler1834710062.cs diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/Disable2faHandler1923519541.cs b/src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/Disable2faHandler1923519541.cs similarity index 100% rename from CommentMap.Mvc/Internal/Generated/WolverineHandlers/Disable2faHandler1923519541.cs rename to src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/Disable2faHandler1923519541.cs diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/EnableAuthenticatorHandler897587120.cs b/src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/EnableAuthenticatorHandler897587120.cs similarity index 100% rename from CommentMap.Mvc/Internal/Generated/WolverineHandlers/EnableAuthenticatorHandler897587120.cs rename to src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/EnableAuthenticatorHandler897587120.cs diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ExternalLoginSignInHandler1809594924.cs b/src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ExternalLoginSignInHandler1809594924.cs similarity index 100% rename from CommentMap.Mvc/Internal/Generated/WolverineHandlers/ExternalLoginSignInHandler1809594924.cs rename to src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ExternalLoginSignInHandler1809594924.cs diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ForgetTwoFactorClientHandler253588197.cs b/src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ForgetTwoFactorClientHandler253588197.cs similarity index 100% rename from CommentMap.Mvc/Internal/Generated/WolverineHandlers/ForgetTwoFactorClientHandler253588197.cs rename to src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ForgetTwoFactorClientHandler253588197.cs diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ForgotPasswordHandler1306123444.cs b/src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ForgotPasswordHandler1306123444.cs similarity index 100% rename from CommentMap.Mvc/Internal/Generated/WolverineHandlers/ForgotPasswordHandler1306123444.cs rename to src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ForgotPasswordHandler1306123444.cs diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/GenerateRecoveryCodesHandler711237032.cs b/src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/GenerateRecoveryCodesHandler711237032.cs similarity index 100% rename from CommentMap.Mvc/Internal/Generated/WolverineHandlers/GenerateRecoveryCodesHandler711237032.cs rename to src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/GenerateRecoveryCodesHandler711237032.cs diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/GeneratedHandlerRegistry.cs b/src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/GeneratedHandlerRegistry.cs similarity index 100% rename from CommentMap.Mvc/Internal/Generated/WolverineHandlers/GeneratedHandlerRegistry.cs rename to src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/GeneratedHandlerRegistry.cs diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetAuthenticatorSetupHandler507613430.cs b/src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetAuthenticatorSetupHandler507613430.cs similarity index 100% rename from CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetAuthenticatorSetupHandler507613430.cs rename to src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetAuthenticatorSetupHandler507613430.cs diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetCommentTitleHandler595995119.cs b/src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetCommentTitleHandler595995119.cs similarity index 100% rename from CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetCommentTitleHandler595995119.cs rename to src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetCommentTitleHandler595995119.cs diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetCountryHandler1133281984.cs b/src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetCountryHandler1133281984.cs similarity index 100% rename from CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetCountryHandler1133281984.cs rename to src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetCountryHandler1133281984.cs diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetDeleteProfileInfoHandler900389426.cs b/src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetDeleteProfileInfoHandler900389426.cs similarity index 100% rename from CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetDeleteProfileInfoHandler900389426.cs rename to src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetDeleteProfileInfoHandler900389426.cs diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetExternalLoginsHandler199405825.cs b/src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetExternalLoginsHandler199405825.cs similarity index 100% rename from CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetExternalLoginsHandler199405825.cs rename to src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetExternalLoginsHandler199405825.cs diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetProfileEmailHandler1046567855.cs b/src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetProfileEmailHandler1046567855.cs similarity index 100% rename from CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetProfileEmailHandler1046567855.cs rename to src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetProfileEmailHandler1046567855.cs diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetTwoFactorStatusHandler1213804985.cs b/src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetTwoFactorStatusHandler1213804985.cs similarity index 100% rename from CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetTwoFactorStatusHandler1213804985.cs rename to src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/GetTwoFactorStatusHandler1213804985.cs diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/HasPasswordHandler1751871263.cs b/src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/HasPasswordHandler1751871263.cs similarity index 100% rename from CommentMap.Mvc/Internal/Generated/WolverineHandlers/HasPasswordHandler1751871263.cs rename to src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/HasPasswordHandler1751871263.cs diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/LinkExternalLoginHandler251495890.cs b/src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/LinkExternalLoginHandler251495890.cs similarity index 100% rename from CommentMap.Mvc/Internal/Generated/WolverineHandlers/LinkExternalLoginHandler251495890.cs rename to src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/LinkExternalLoginHandler251495890.cs diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ListCommentsHandler488515704.cs b/src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ListCommentsHandler488515704.cs similarity index 100% rename from CommentMap.Mvc/Internal/Generated/WolverineHandlers/ListCommentsHandler488515704.cs rename to src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ListCommentsHandler488515704.cs diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/LoginUserHandler1789921628.cs b/src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/LoginUserHandler1789921628.cs similarity index 100% rename from CommentMap.Mvc/Internal/Generated/WolverineHandlers/LoginUserHandler1789921628.cs rename to src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/LoginUserHandler1789921628.cs diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/LoginWith2faHandler292869486.cs b/src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/LoginWith2faHandler292869486.cs similarity index 100% rename from CommentMap.Mvc/Internal/Generated/WolverineHandlers/LoginWith2faHandler292869486.cs rename to src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/LoginWith2faHandler292869486.cs diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/LoginWithRecoveryCodeHandler277354287.cs b/src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/LoginWithRecoveryCodeHandler277354287.cs similarity index 100% rename from CommentMap.Mvc/Internal/Generated/WolverineHandlers/LoginWithRecoveryCodeHandler277354287.cs rename to src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/LoginWithRecoveryCodeHandler277354287.cs diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/LogoutUserHandler132148485.cs b/src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/LogoutUserHandler132148485.cs similarity index 100% rename from CommentMap.Mvc/Internal/Generated/WolverineHandlers/LogoutUserHandler132148485.cs rename to src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/LogoutUserHandler132148485.cs diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/RegisterUserHandler1265692392.cs b/src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/RegisterUserHandler1265692392.cs similarity index 100% rename from CommentMap.Mvc/Internal/Generated/WolverineHandlers/RegisterUserHandler1265692392.cs rename to src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/RegisterUserHandler1265692392.cs diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/RemoveExternalLoginHandler62493602.cs b/src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/RemoveExternalLoginHandler62493602.cs similarity index 100% rename from CommentMap.Mvc/Internal/Generated/WolverineHandlers/RemoveExternalLoginHandler62493602.cs rename to src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/RemoveExternalLoginHandler62493602.cs diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/RequestEmailChangeHandler172865511.cs b/src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/RequestEmailChangeHandler172865511.cs similarity index 100% rename from CommentMap.Mvc/Internal/Generated/WolverineHandlers/RequestEmailChangeHandler172865511.cs rename to src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/RequestEmailChangeHandler172865511.cs diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ResendEmailConfirmationHandler19836290.cs b/src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ResendEmailConfirmationHandler19836290.cs similarity index 100% rename from CommentMap.Mvc/Internal/Generated/WolverineHandlers/ResendEmailConfirmationHandler19836290.cs rename to src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ResendEmailConfirmationHandler19836290.cs diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ResetAuthenticatorHandler25524780.cs b/src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ResetAuthenticatorHandler25524780.cs similarity index 100% rename from CommentMap.Mvc/Internal/Generated/WolverineHandlers/ResetAuthenticatorHandler25524780.cs rename to src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ResetAuthenticatorHandler25524780.cs diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ResetPasswordHandler433488700.cs b/src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ResetPasswordHandler433488700.cs similarity index 100% rename from CommentMap.Mvc/Internal/Generated/WolverineHandlers/ResetPasswordHandler433488700.cs rename to src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/ResetPasswordHandler433488700.cs diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/SetPasswordHandler836449791.cs b/src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/SetPasswordHandler836449791.cs similarity index 100% rename from CommentMap.Mvc/Internal/Generated/WolverineHandlers/SetPasswordHandler836449791.cs rename to src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/SetPasswordHandler836449791.cs diff --git a/CommentMap.Mvc/Internal/Generated/WolverineHandlers/SignInAfterRegistrationHandler2047984407.cs b/src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/SignInAfterRegistrationHandler2047984407.cs similarity index 100% rename from CommentMap.Mvc/Internal/Generated/WolverineHandlers/SignInAfterRegistrationHandler2047984407.cs rename to src/CommentMap.Mvc/Internal/Generated/WolverineHandlers/SignInAfterRegistrationHandler2047984407.cs diff --git a/CommentMap.Mvc/Models/AddNewCommentInput.cs b/src/CommentMap.Mvc/Models/AddNewCommentInput.cs similarity index 100% rename from CommentMap.Mvc/Models/AddNewCommentInput.cs rename to src/CommentMap.Mvc/Models/AddNewCommentInput.cs diff --git a/src/CommentMap.Mvc/Pages/Comments/Add.cshtml b/src/CommentMap.Mvc/Pages/Comments/Add.cshtml new file mode 100644 index 0000000..1f1f941 --- /dev/null +++ b/src/CommentMap.Mvc/Pages/Comments/Add.cshtml @@ -0,0 +1,51 @@ +@page +@model AddModel +@{ + ViewData["Title"] = "Add new comment"; +} + +@section Styles { + +} + +

Add new comment

+ +
+
+
+
+ + +
Your title must be 1-100 characters long.
+ +
+ +
+ + +
Your text must be 1-250 characters long.
+ +
+ +
+ + +
+ +
+ + +
+ + +
+
+
+
+
+
+ +@section Scripts { + + +} diff --git a/CommentMap.Mvc/Pages/Comments/Add.cshtml.cs b/src/CommentMap.Mvc/Pages/Comments/Add.cshtml.cs similarity index 100% rename from CommentMap.Mvc/Pages/Comments/Add.cshtml.cs rename to src/CommentMap.Mvc/Pages/Comments/Add.cshtml.cs diff --git a/src/CommentMap.Mvc/Pages/Comments/Add.cshtml.ts b/src/CommentMap.Mvc/Pages/Comments/Add.cshtml.ts new file mode 100644 index 0000000..8d5df67 --- /dev/null +++ b/src/CommentMap.Mvc/Pages/Comments/Add.cshtml.ts @@ -0,0 +1,99 @@ +import { Coordinate } from "ol/coordinate"; +import Map from "ol/Map"; +import { Tile as TileLayer, Vector as VectorLayer } from "ol/layer"; +import { XYZ, Vector as VectorSource } from "ol/source"; +import { FullScreen, defaults as defaultControls } from "ol/control"; +import View from "ol/View"; +import Draw, { DrawEvent } from "ol/interaction/Draw"; +import Point from "ol/geom/Point"; +import Feature from "ol/Feature"; + +const root = document.getElementById("root"); +if (root) { + const longitudeInput = root.querySelector("[data-longitude=\"true\"]"); + const latitudeInput = root.querySelector("[data-latitude=\"true\"]"); + const locale = root.querySelector("[data-locale]")?.getAttribute("data-locale") ?? "en"; + + if (!longitudeInput || !latitudeInput) { + throw new Error("Coordinate inputs not found."); + } + + const longitudeEl = longitudeInput; + const latitudeEl = latitudeInput; + + const intl = new Intl.NumberFormat(locale, { maximumFractionDigits: 10 }); + + let longitude = Number(longitudeEl.value); + let latitude = Number(latitudeEl.value); + + const vectorSource = new VectorSource(); + + const map = new Map({ + target: "map", + layers: [ + new TileLayer({ + source: new XYZ({ + url: "https://mt0.google.com/vt/lyrs=m&hl=en&x={x}&y={y}&z={z}", + }), + }), + new VectorLayer({ + source: vectorSource, + }), + ], + view: new View({ + center: [longitude, latitude], + zoom: 4, + projection: "EPSG:3857", + }), + controls: defaultControls().extend([new FullScreen()]), + }); + + function format(value: number): string { + return intl.format(value).replace(/\s/g, ""); + } + + function updateInput(input: HTMLInputElement, value: number) { + input.value = format(value); + input.dispatchEvent(new Event("change")); + } + + function setCoordinate(coordinates: Coordinate) { + const [nextLongitude, nextLatitude] = coordinates; + if (nextLongitude === undefined || nextLatitude === undefined) { + return; + } + + longitude = nextLongitude; + latitude = nextLatitude; + + updateInput(longitudeEl, longitude); + updateInput(latitudeEl, latitude); + + } + + function setPoint({ feature }: DrawEvent) { + vectorSource.clear(true); + const geometry = feature.getGeometry(); + if (geometry instanceof Point) { + setCoordinate(geometry.getCoordinates()); + } + } + + function restorePoint() { + const point = new Point([longitude, latitude]); + const feature = new Feature(point); + vectorSource.addFeature(feature); + } + + const drawInteraction = new Draw({ + source: vectorSource, + type: "Point", + }); + drawInteraction.on("drawend", setPoint); + map.addInteraction(drawInteraction); + + updateInput(longitudeInput, longitude); + updateInput(latitudeInput, latitude); + + restorePoint(); +} diff --git a/src/CommentMap.Mvc/Pages/Comments/ConfirmDelete.cshtml b/src/CommentMap.Mvc/Pages/Comments/ConfirmDelete.cshtml new file mode 100644 index 0000000..4440ca8 --- /dev/null +++ b/src/CommentMap.Mvc/Pages/Comments/ConfirmDelete.cshtml @@ -0,0 +1,15 @@ +@page +@model ConfirmDeleteModel +@{ + ViewData["Title"] = "Confirm deletion"; +} + +
+
+

Confirm deletion

+

Are you sure you want to delete "@Model.Title" comment?

+
+ +
+
+
diff --git a/CommentMap.Mvc/Pages/Comments/ConfirmDelete.cshtml.cs b/src/CommentMap.Mvc/Pages/Comments/ConfirmDelete.cshtml.cs similarity index 100% rename from CommentMap.Mvc/Pages/Comments/ConfirmDelete.cshtml.cs rename to src/CommentMap.Mvc/Pages/Comments/ConfirmDelete.cshtml.cs diff --git a/src/CommentMap.Mvc/Pages/Comments/Index.cshtml b/src/CommentMap.Mvc/Pages/Comments/Index.cshtml new file mode 100644 index 0000000..7003387 --- /dev/null +++ b/src/CommentMap.Mvc/Pages/Comments/Index.cshtml @@ -0,0 +1,58 @@ +@page +@model IndexModel +@{ + ViewData["Title"] = "My comments"; + var selectedOrder = (int)Model.SelectedOrder; + ViewData["SelectedOrder"] = selectedOrder; +} + +@section Styles { + +} + +

My comments

+ + + +@if (Model.Comments is not null && Model.Comments.Count > 0) +{ +
+
+
+ @foreach (var comment in Model.Comments) + { + + } +
+
+
+
+
+
+} +else +{ +

There is no comments :(

+} + +@section Scripts { + +} diff --git a/CommentMap.Mvc/Pages/Comments/Index.cshtml.cs b/src/CommentMap.Mvc/Pages/Comments/Index.cshtml.cs similarity index 100% rename from CommentMap.Mvc/Pages/Comments/Index.cshtml.cs rename to src/CommentMap.Mvc/Pages/Comments/Index.cshtml.cs diff --git a/src/CommentMap.Mvc/Pages/Comments/Index.cshtml.ts b/src/CommentMap.Mvc/Pages/Comments/Index.cshtml.ts new file mode 100644 index 0000000..3751483 --- /dev/null +++ b/src/CommentMap.Mvc/Pages/Comments/Index.cshtml.ts @@ -0,0 +1,68 @@ +import Map from "ol/Map"; +import { Tile as TileLayer, Vector as VectorLayer } from "ol/layer"; +import { XYZ, Vector as VectorSource } from "ol/source"; +import { FullScreen, defaults as defaultControls } from "ol/control"; +import { Coordinate } from "ol/coordinate"; +import View from "ol/View"; +import Feature from "ol/Feature"; +import { Point } from "ol/geom"; +import { Icon, Style } from "ol/style"; + +const DEFAULT_ZOOM = 10; + +const markerIconStyle = new Style({ + image: new Icon({ + anchor: [0.5, 22], + anchorXUnits: "fraction", + anchorYUnits: "pixels", + src: "/assets/marker.svg", + }), +}); + +const root = document.getElementById("root"); +if (root) { + const elements = document.querySelectorAll("[data-location]"); + const coordinates: Coordinate[] = Array.from(elements).map((element) => + JSON.parse(element.getAttribute("data-location")!) + ); + + const first = coordinates.length > 0 ? coordinates[0] : [0, 0]; + + const map = new Map({ + target: "map", + layers: [ + new TileLayer({ + source: new XYZ({ + url: "https://mt0.google.com/vt/lyrs=m&hl=en&x={x}&y={y}&z={z}", + }), + }), + new VectorLayer({ + source: new VectorSource({ + features: coordinates.map((coordinate) => { + const feature = new Feature({ + geometry: new Point(coordinate), + }); + feature.setStyle(markerIconStyle); + return feature; + }), + }), + }), + ], + view: new View({ + center: first, + zoom: DEFAULT_ZOOM, + projection: "EPSG:3857", + }), + controls: defaultControls().extend([new FullScreen()]), + }); + + function goToLocation(coordinate: Coordinate) { + map.getView().setCenter(coordinate); + } + + document.querySelectorAll("[data-goto-location]").forEach((element) => { + element.addEventListener("click", () => { + goToLocation(JSON.parse(element.dataset["gotoLocation"]!)); + }); + }); +} diff --git a/src/CommentMap.Mvc/Pages/Countries/Index.cshtml b/src/CommentMap.Mvc/Pages/Countries/Index.cshtml new file mode 100644 index 0000000..a2a9e3a --- /dev/null +++ b/src/CommentMap.Mvc/Pages/Countries/Index.cshtml @@ -0,0 +1,44 @@ +@page +@model IndexModel +@{ + ViewData["Title"] = "Country"; +} + +@if (ModelState.ErrorCount > 0) +{ +
+ return; +} + +@if (Model.Country is null) +{ +

Oops... There is no country with code "@Model.ISO3Code"

+ return; +} + +
+ + + + + + + + + + + + + + + + + + + + + + + +
ISO 3166-1 alpha-3@Model.Country.ISO3Code
ISO 3166-1 alpha-2@Model.Country.ISO2Code
Name@Model.Country.Name
Region name@Model.Country.RegionName
Subregion name@Model.Country.SubregionName
+
diff --git a/CommentMap.Mvc/Pages/Countries/Index.cshtml.cs b/src/CommentMap.Mvc/Pages/Countries/Index.cshtml.cs similarity index 100% rename from CommentMap.Mvc/Pages/Countries/Index.cshtml.cs rename to src/CommentMap.Mvc/Pages/Countries/Index.cshtml.cs diff --git a/CommentMap.Mvc/Pages/Error.cshtml b/src/CommentMap.Mvc/Pages/Error.cshtml similarity index 86% rename from CommentMap.Mvc/Pages/Error.cshtml rename to src/CommentMap.Mvc/Pages/Error.cshtml index 6f92b95..783dd14 100644 --- a/CommentMap.Mvc/Pages/Error.cshtml +++ b/src/CommentMap.Mvc/Pages/Error.cshtml @@ -4,8 +4,8 @@ ViewData["Title"] = "Error"; } -

Error.

-

An error occurred while processing your request.

+

Error.

+

An error occurred while processing your request.

@if (Model.ShowRequestId) { diff --git a/CommentMap.Mvc/Pages/Error.cshtml.cs b/src/CommentMap.Mvc/Pages/Error.cshtml.cs similarity index 100% rename from CommentMap.Mvc/Pages/Error.cshtml.cs rename to src/CommentMap.Mvc/Pages/Error.cshtml.cs diff --git a/CommentMap.Mvc/Pages/Index.cshtml b/src/CommentMap.Mvc/Pages/Index.cshtml similarity index 68% rename from CommentMap.Mvc/Pages/Index.cshtml rename to src/CommentMap.Mvc/Pages/Index.cshtml index 6d11090..00aa6ba 100644 --- a/CommentMap.Mvc/Pages/Index.cshtml +++ b/src/CommentMap.Mvc/Pages/Index.cshtml @@ -5,5 +5,5 @@ }
-

Welcome

+

Welcome

diff --git a/CommentMap.Mvc/Pages/Index.cshtml.cs b/src/CommentMap.Mvc/Pages/Index.cshtml.cs similarity index 100% rename from CommentMap.Mvc/Pages/Index.cshtml.cs rename to src/CommentMap.Mvc/Pages/Index.cshtml.cs diff --git a/src/CommentMap.Mvc/Pages/Shared/Components/SignInPanel/Default.cshtml b/src/CommentMap.Mvc/Pages/Shared/Components/SignInPanel/Default.cshtml new file mode 100644 index 0000000..bbd472c --- /dev/null +++ b/src/CommentMap.Mvc/Pages/Shared/Components/SignInPanel/Default.cshtml @@ -0,0 +1,30 @@ +@using CommentMap.Mvc.ViewModels +@model SignInPanelViewModel + + diff --git a/src/CommentMap.Mvc/Pages/Shared/_CommentCardPartial.cshtml b/src/CommentMap.Mvc/Pages/Shared/_CommentCardPartial.cshtml new file mode 100644 index 0000000..4d30d35 --- /dev/null +++ b/src/CommentMap.Mvc/Pages/Shared/_CommentCardPartial.cshtml @@ -0,0 +1,36 @@ +@using CommentMap.Mvc.ViewModels +@using Humanizer +@model CommentCardViewModel +@{ + var elapsedInterval = DateTime.UtcNow - Model.CreatedAt; + var coordinates = Model.Location.GetJsonArray(); +} + +
+
+
@Model.Title
+

@Model.Text

+
+ + + + Edit + + + + Delete + +
+
@DateTime.UtcNow.Subtract(elapsedInterval).Humanize()
+
+
diff --git a/src/CommentMap.Mvc/Pages/Shared/_Layout.cshtml b/src/CommentMap.Mvc/Pages/Shared/_Layout.cshtml new file mode 100644 index 0000000..cc7113c --- /dev/null +++ b/src/CommentMap.Mvc/Pages/Shared/_Layout.cshtml @@ -0,0 +1,56 @@ + + + + + + @ViewData["Title"] - CommentMap.Mvc + + + + + @await RenderSectionAsync("Styles", required: false) + + + + +
+ @RenderBody() +
+ + + @await RenderSectionAsync("Scripts", required: false) + + diff --git a/CommentMap.Mvc/Pages/Shared/_ValidationScriptsPartial.cshtml b/src/CommentMap.Mvc/Pages/Shared/_ValidationScriptsPartial.cshtml similarity index 58% rename from CommentMap.Mvc/Pages/Shared/_ValidationScriptsPartial.cshtml rename to src/CommentMap.Mvc/Pages/Shared/_ValidationScriptsPartial.cshtml index d2c8851..d43acf0 100644 --- a/CommentMap.Mvc/Pages/Shared/_ValidationScriptsPartial.cshtml +++ b/src/CommentMap.Mvc/Pages/Shared/_ValidationScriptsPartial.cshtml @@ -1,4 +1,4 @@ - + +
+ +``` + +#### Rules + +- daisyUI supports Cally, React Day Picker and Vanilla Calendar Pro diff --git a/.agents/skills/daisyui/components/card.md b/.agents/skills/daisyui/components/card.md new file mode 100644 index 0000000..cb0baef --- /dev/null +++ b/.agents/skills/daisyui/components/card.md @@ -0,0 +1,29 @@ +### card +Cards are used to group and display content + +[card docs](https://daisyui.com/components/card/) + +#### Class names +- component: `card` +- part: `card-title`, `card-body`, `card-actions` +- style: `card-border`, `card-dash` +- modifier: `card-side`, `image-full` +- size: `card-xs`, `card-sm`, `card-md`, `card-lg`, `card-xl` + +#### Syntax +```html +
+
{alt-text}
+
+

{title}

+

{CONTENT}

+
{actions}
+
+
+``` + +#### Rules +- {MODIFIER} is optional and can have one of the modifier class names and one of the size class names +- `
` and `
` are optional +- can use `sm:card-side` for responsive layouts +- If image is placed after `card-body`, the image will be placed at the bottom diff --git a/.agents/skills/daisyui/components/carousel.md b/.agents/skills/daisyui/components/carousel.md new file mode 100644 index 0000000..bc08fe9 --- /dev/null +++ b/.agents/skills/daisyui/components/carousel.md @@ -0,0 +1,20 @@ +### carousel +Carousel show images or content in a scrollable area + +[carousel docs](https://daisyui.com/components/carousel/) + +#### Class names +- component: `carousel` +- part: `carousel-item` +- modifier: `carousel-start`, `carousel-center`, `carousel-end` +- direction: `carousel-horizontal`, `carousel-vertical` + +#### Syntax +```html + +``` + +#### Rules +- {MODIFIER} is optional and can have one of the modifier/direction class names +- Content is a list of `carousel-item` divs: `` +- To create a full-width carousel, add `w-full` to each carousel item diff --git a/.agents/skills/daisyui/components/chat.md b/.agents/skills/daisyui/components/chat.md new file mode 100644 index 0000000..9870025 --- /dev/null +++ b/.agents/skills/daisyui/components/chat.md @@ -0,0 +1,25 @@ +### chat +Chat bubbles are used to show one line of conversation and all its data, including the author image, author name, time, etc + +[chat docs](https://daisyui.com/components/chat/) + +#### Class names +- component: `chat` +- part: `chat-image`, `chat-header`, `chat-footer`, `chat-bubble` +- placement: `chat-start`, `chat-end` +- color: `chat-bubble-neutral`, `chat-bubble-primary`, `chat-bubble-secondary`, `chat-bubble-accent`, `chat-bubble-info`, `chat-bubble-success`, `chat-bubble-warning`, `chat-bubble-error` + +#### Syntax +```html +
+
+
+
Message text
+ +
+``` + +#### Rules +- {PLACEMENT} is required and must be either `chat-start` or `chat-end` +- {COLOR} is optional and can have one of the color class names +- To add an avatar, use `
` and nest the avatar content inside diff --git a/.agents/skills/daisyui/components/checkbox.md b/.agents/skills/daisyui/components/checkbox.md new file mode 100644 index 0000000..d36f90b --- /dev/null +++ b/.agents/skills/daisyui/components/checkbox.md @@ -0,0 +1,17 @@ +### checkbox +Checkboxes are used to select or deselect a value + +[checkbox docs](https://daisyui.com/components/checkbox/) + +#### Class names +- component: `checkbox` +- color: `checkbox-primary`, `checkbox-secondary`, `checkbox-accent`, `checkbox-neutral`, `checkbox-success`, `checkbox-warning`, `checkbox-info`, `checkbox-error` +- size: `checkbox-xs`, `checkbox-sm`, `checkbox-md`, `checkbox-lg`, `checkbox-xl` + +#### Syntax +```html + +``` + +#### Rules +- {MODIFIER} is optional and can have one of each color/size class names diff --git a/.agents/skills/daisyui/components/collapse.md b/.agents/skills/daisyui/components/collapse.md new file mode 100644 index 0000000..37901de --- /dev/null +++ b/.agents/skills/daisyui/components/collapse.md @@ -0,0 +1,22 @@ +### collapse +Collapse is used for showing and hiding content + +[collapse docs](https://daisyui.com/components/collapse/) + +#### Class names +- component: `collapse` +- part: `collapse-title`, `collapse-content` +- modifier: `collapse-arrow`, `collapse-plus`, `collapse-open`, `collapse-close` + +#### Syntax +```html +
+
{title}
+
{CONTENT}
+
+``` + +#### Rules +- {MODIFIER} is optional and can have one of the modifier class names +- instead of `tabindex="0"`, you can use `` as a first child +- Can also be a details/summary tag diff --git a/.agents/skills/daisyui/components/countdown.md b/.agents/skills/daisyui/components/countdown.md new file mode 100644 index 0000000..25e62d3 --- /dev/null +++ b/.agents/skills/daisyui/components/countdown.md @@ -0,0 +1,19 @@ +### countdown +Countdown gives you a transition effect when you change a number between 0 to 999 + +[countdown docs](https://daisyui.com/components/countdown/) + +#### Class names +- component: `countdown` + +#### Syntax +```html + + number + +``` + +#### Rules +- The `--value` CSS variable and text must be a number between 0 and 999 +- you need to change the span text and the `--value` CSS variable using JS +- you need to add `aria-live="polite"` and `aria-label="{number}"` so screen readers can properly read changes diff --git a/.agents/skills/daisyui/components/diff.md b/.agents/skills/daisyui/components/diff.md new file mode 100644 index 0000000..4827db5 --- /dev/null +++ b/.agents/skills/daisyui/components/diff.md @@ -0,0 +1,20 @@ +### diff +Diff component shows a side-by-side comparison of two items + +[diff docs](https://daisyui.com/components/diff/) + +#### Class names +- component: `diff` +- part: `diff-item-1`, `diff-item-2`, `diff-resizer` + +#### Syntax +```html +
+
{item1}
+
{item2}
+
+
+``` + +#### Rules +- To maintain aspect ratio, add `aspect-16/9` or other aspect ratio classes to `
` element diff --git a/.agents/skills/daisyui/components/divider.md b/.agents/skills/daisyui/components/divider.md new file mode 100644 index 0000000..c75f154 --- /dev/null +++ b/.agents/skills/daisyui/components/divider.md @@ -0,0 +1,19 @@ +### divider +Divider will be used to separate content vertically or horizontally + +[divider docs](https://daisyui.com/components/divider/) + +#### Class names +- component: `divider` +- color: `divider-neutral`, `divider-primary`, `divider-secondary`, `divider-accent`, `divider-success`, `divider-warning`, `divider-info`, `divider-error` +- direction: `divider-vertical`, `divider-horizontal` +- placement: `divider-start`, `divider-end` + +#### Syntax +```html +
{text}
+``` + +#### Rules +- {MODIFIER} is optional and can have one of each direction/color/placement class names +- Omit text for a blank divider diff --git a/.agents/skills/daisyui/components/dock.md b/.agents/skills/daisyui/components/dock.md new file mode 100644 index 0000000..0ced8da --- /dev/null +++ b/.agents/skills/daisyui/components/dock.md @@ -0,0 +1,27 @@ +### dock +Dock (also know as Bottom navigation or Bottom bar) is a UI element that provides navigation options to the user. Dock sticks to the bottom of the screen + +[dock docs](https://daisyui.com/components/dock/) + +#### Class names +- component: `dock` +- part: `dock-label` +- modifier: `dock-active` +- size: `dock-xs`, `dock-sm`, `dock-md`, `dock-lg`, `dock-xl` + +#### Syntax +```html +
{CONTENT}
+``` +where content is a list of buttons: +```html + +``` + +#### Rules +- {MODIFIER} is optional and can have one of the size class names +- To make a button active, add `dock-active` class to the button +- add `` is required for responsiveness of the dock in iOS diff --git a/.agents/skills/daisyui/components/drawer.md b/.agents/skills/daisyui/components/drawer.md new file mode 100644 index 0000000..00ceef1 --- /dev/null +++ b/.agents/skills/daisyui/components/drawer.md @@ -0,0 +1,98 @@ +### drawer +Drawer is a grid layout that can show/hide a sidebar on the left or right side of the page + +[drawer docs](https://daisyui.com/components/drawer/) + +#### Class names +- component: `drawer` +- part: `drawer-toggle`, `drawer-content`, `drawer-side`, `drawer-overlay`, `drawer-button` +- placement: `drawer-end` +- modifier: `drawer-open` +- variant: `is-drawer-open:`, `is-drawer-close:` + +#### Syntax +```html +
+ +
{CONTENT}
+
{SIDEBAR}
+
+``` +where {CONTENT} can be navbar, site content, footer, etc +and {SIDEBAR} can be a menu like: +```html + +``` +To open/close the drawer, use a label that points to the `drawer-toggle` input: +```html + +``` +Example: This sidebar is always visible on large screen, can be toggled on small screen: +```html +
+ +
+ + +
+
+ + +
+
+``` + +Example: This sidebar is always visible. When it's close we only see icons, when it's open we see icons and text +```html +
+ +
+ +
+
+ +
+ + + +
+ +
+
+
+
+``` + +#### Rules +- {MODIFIER} is optional and can have one of the modifier/placement class names +- `id` is required for the `drawer-toggle` input. change `my-drawer` to a unique id according to your needs +- `lg:drawer-open` can be used to make sidebar visible on larger screens +- `drawer-toggle` is a hidden checkbox. Use label with "for" attribute to toggle state +- if you want to open the drawer when a button is clicked, use `` where `my-drawer` is the id of the `drawer-toggle` input +- when using drawer, every page content must be inside `drawer-content` element. for example navbar, footer, etc should not be outside of `drawer` diff --git a/.agents/skills/daisyui/components/dropdown.md b/.agents/skills/daisyui/components/dropdown.md new file mode 100644 index 0000000..3cad5bd --- /dev/null +++ b/.agents/skills/daisyui/components/dropdown.md @@ -0,0 +1,32 @@ +### dropdown +Dropdown can open a menu or any other element when the button is clicked + +[dropdown docs](https://daisyui.com/components/dropdown/) + +#### Class names +- component: `dropdown` +- part: `dropdown-content` +- placement: `dropdown-start`, `dropdown-center`, `dropdown-end`, `dropdown-top`, `dropdown-bottom`, `dropdown-left`, `dropdown-right` +- modifier: `dropdown-hover`, `dropdown-open`, `dropdown-close` + +#### Syntax + +Using popover API +```html + + +``` + +Using details and summary (only opens/closes on click) +```html + +``` + +#### Rules +- {MODIFIER} is optional and can have one of the modifier/placement class names +- replace `{id}` and `{anchor}` with a unique name +- The content can be any HTML element (not just `
    `) +- For popover API method, we don't use `dropdown-content`. Only button and a `dropdown` diff --git a/.agents/skills/daisyui/components/fab.md b/.agents/skills/daisyui/components/fab.md new file mode 100644 index 0000000..62e9351 --- /dev/null +++ b/.agents/skills/daisyui/components/fab.md @@ -0,0 +1,98 @@ +### fab +FAB (Floating Action Button) stays in the bottom corner of screen. It includes a focusable and accessible element with button role. Clicking or focusing it shows additional buttons (known as Speed Dial buttons) in a vertical arrangement or a flower shape (quarter circle) + +[fab docs](https://daisyui.com/components/fab/) + +#### Class names +- component: `fab` +- part: `fab-close`, `fab-main-action` +- modifier: `fab-flower` + +#### Syntax +A single FAB in the corner of screen +```html +
    + +
    +``` +A FAB that opens a 3 other buttons in the corner of page vertically +```html +
    +
    {IconOriginal}
    + + + +
    +``` +A FAB that opens a 3 other buttons in the corner of page vertically and they have label text +```html +
    +
    {IconOriginal}
    +
    {Label1}
    +
    {Label2}
    +
    {Label3}
    +
    +``` +FAB with rectangle buttons. These are not circular buttons so they can have more content. +```html +
    +
    {IconOriginal}
    + + + +
    +``` +FAB with close button. When FAB is open, the original button is replaced with a close button +```html +
    +
    {IconOriginal}
    +
    Close ×
    +
    {Label1}
    +
    {Label2}
    +
    {Label3}
    +
    +``` +FAB with Main Action button. When FAB is open, the original button is replaced with a main action button +```html +
    +
    {IconOriginal}
    +
    + {LabelMainAction} +
    +
    {Label1}
    +
    {Label2}
    +
    {Label3}
    +
    +``` +FAB Flower. It opens the buttons in a flower shape (quarter circle) arrangement instead of vertical +```html +
    +
    {IconOriginal}
    + + + + +
    +``` +FAB Flower with tooltips. There's no space for a text label in a quarter circle, so tooltips are used to indicate the button's function +```html +
    +
    {IconOriginal}
    + +
    + +
    +
    + +
    +
    + +
    +
    +``` +#### Rules +- {Icon*} should be replaced with the appropriate icon for each button. SVG icons are recommended +- {IconOriginal} is the icon that we see before opening the FAB +- {IconMainAction} is the icon we see after opening the FAB +- {Icon1}, {Icon2}, {Icon3} are the icons for the additional buttons +- {Label*} is the label text for each button diff --git a/.agents/skills/daisyui/components/fieldset.md b/.agents/skills/daisyui/components/fieldset.md new file mode 100644 index 0000000..7195849 --- /dev/null +++ b/.agents/skills/daisyui/components/fieldset.md @@ -0,0 +1,20 @@ +### fieldset +Fieldset is a container for grouping related form elements. It includes fieldset-legend as a title and label as a description + +[fieldset docs](https://daisyui.com/components/fieldset/) + +#### Class names +- Component: `fieldset`, `label` +- Parts: `fieldset-legend` + +#### Syntax +```html +
    + {title} + {CONTENT} +

    {description}

    +
    +``` + +#### Rules +- You can use any element as a direct child of fieldset to add form elements diff --git a/.agents/skills/daisyui/components/file-input.md b/.agents/skills/daisyui/components/file-input.md new file mode 100644 index 0000000..729b922 --- /dev/null +++ b/.agents/skills/daisyui/components/file-input.md @@ -0,0 +1,18 @@ +### file-input +File Input is an input field for uploading files + +[file-input docs](https://daisyui.com/components/file-input/) + +#### Class Names: +- Component: `file-input` +- Style: `file-input-ghost` +- Color: `file-input-neutral`, `file-input-primary`, `file-input-secondary`, `file-input-accent`, `file-input-info`, `file-input-success`, `file-input-warning`, `file-input-error` +- Size: `file-input-xs`, `file-input-sm`, `file-input-md`, `file-input-lg`, `file-input-xl` + +#### Syntax +```html + +``` + +#### Rules +- {MODIFIER} is optional and can have one of each style/color/size class names diff --git a/.agents/skills/daisyui/components/filter.md b/.agents/skills/daisyui/components/filter.md new file mode 100644 index 0000000..f8c3112 --- /dev/null +++ b/.agents/skills/daisyui/components/filter.md @@ -0,0 +1,33 @@ +### filter +Filter is a group of radio buttons. Choosing one of the options will hide the others and shows a reset button next to the chosen option + +[filter docs](https://daisyui.com/components/filter/) + +#### Class names +- component: `filter` +- part: `filter-reset` + +#### Syntax +Using HTML form +```html +
    + + + +
    +``` +Without HTML form +```html +
    + + + +
    +``` + +#### Rules +- replace `{NAME}` with proper value, according to the context of the filter +- Each set of radio inputs must have unique `name` attributes to avoid conflicts +- Use `
    ` tag when possible and only use `
    ` if you can't use a HTML form for some reason +- Use `filter-reset` class for the reset button +- Do not check any of the radio inputs by default diff --git a/.agents/skills/daisyui/components/footer.md b/.agents/skills/daisyui/components/footer.md new file mode 100644 index 0000000..898ed00 --- /dev/null +++ b/.agents/skills/daisyui/components/footer.md @@ -0,0 +1,21 @@ +### footer +Footer can contain logo, copyright notice, and links to other pages + +[footer docs](https://daisyui.com/components/footer/) + +#### Class names +- component: `footer` +- part: `footer-title` +- placement: `footer-center` +- direction: `footer-horizontal`, `footer-vertical` + +#### Syntax +```html +
    {CONTENT}
    +``` +where content can contain several `