diff --git a/README.md b/README.md index cd0cb24..121322a 100644 --- a/README.md +++ b/README.md @@ -3,20 +3,45 @@ A web application for playing the Shogi boardgame with others, developed as a ho The application uses sockets to allow players to enjoy sessions in real time. ### Technologies used -A Blazor UI backed by an Asp.net Core API service which uses Sql Server for presistent storage. - -### Known Issues - * The app is intended to support logging in via Microsoft accounts or browser-session (Guest) accounts, but currently Microsoft login does not work. - * The workaround is to use the guest login. - * On first load of the UI, guest account login will fail. - * The workaround is to refresh the page and try again. This issue only happens on first load. +A Blazor Web App which uses Sql Server for presistent storage and Identity EF Core for account management. ### Roadmap of features remaining The app is not yet finished, though much of the functionality exists. Here is a list of what remains. * Placing pieces from the hand onto the board. - * Checkmate experience in UI + * Checkmate experience * Preventing the rarely invoked rule where check-mate cannot be gained by placing a pawn from the hand. * Retaining an archive of games played and move history of each game. - * Adaptive UI layout for varying viewport (screen) sizes. \ No newline at end of file + * Adaptive UI layout for varying viewport (screen) sizes. + +### Database Setup +If you don't have them, install the `Data storage and processing` tools through Visual Studio Installer. This gives you a local MSSQL database for you to develop with, which is nice so you aren't touching live data while working. + +After that, you need to set up the database. The database has two sources of table structure. + +#### 1. Shogi.Database project +This project contains the table structure for the game. + +1. Build the Shogi.Database project. +1. Publish the Shogi.Database project (right click in Solution Explorer). + * If you're prompted for a connection string, use the one from `Shogi/appsettings.json`. + +#### 2. EntityFramework via AspNetCore.Identity +This solution uses the `Microsoft.AspNetCore.Identity.EntityFrameworkCore` package to offer authentication and authorization. This uses Entity Framework, which comes with tools to setup our database with the necessary table structure for auth. + +1. Install the Entity Framework dotnet tools that come with the project. Via Powershell run this command: + ``` + dotnet tool restore + ``` +1. Run the database migrations and fill out table structure for auth. Run this command from the MUD.Api project directory: + ``` + cd /path/to/solution/Shogi + dotnet ef database update + ``` + +After this, you should be ready to create some test accounts for local development. + +### Creating Test Accounts +To create test accounts for local development, make sure to build in DEBUG mode and then use the `/debug/create-test-accounts` endpoint +of the API. This will create two accounts. If those accounts already exist, they'll be deleted (along with all game session data associated) and recreated. \ No newline at end of file diff --git a/Shogi.sln b/Shogi.sln index d1948fd..5dcac8c 100644 --- a/Shogi.sln +++ b/Shogi.sln @@ -8,6 +8,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution .editorconfig = .editorconfig .gitignore = .gitignore azure-pipelines.yml = azure-pipelines.yml + Shogi\.config\dotnet-tools.json = Shogi\.config\dotnet-tools.json global.json = global.json README.md = README.md EndProjectSection diff --git a/Shogi/FrontEnd/Components/Routes.razor b/Shogi/FrontEnd/Components/Routes.razor index 71ddacf..f3d6a9f 100644 --- a/Shogi/FrontEnd/Components/Routes.razor +++ b/Shogi/FrontEnd/Components/Routes.razor @@ -2,7 +2,7 @@ - + @* *@ Not found diff --git a/Shogi/Program.cs b/Shogi/Program.cs index f40b040..668ca59 100644 --- a/Shogi/Program.cs +++ b/Shogi/Program.cs @@ -1,4 +1,5 @@ using Microsoft.AspNetCore.Components.Authorization; +using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity.UI.Services; using Microsoft.AspNetCore.ResponseCompression; using Microsoft.EntityFrameworkCore; @@ -76,6 +77,10 @@ app.MapHub("/gamehub"); app.MapRazorComponents() .AddInteractiveServerRenderMode(); +#if DEBUG +MapTestAccountSetupRoute(app); +#endif + app.Run(); static void AddIdentity(WebApplicationBuilder builder, ConfigurationManager configuration) @@ -113,5 +118,68 @@ static void AddIdentity(WebApplicationBuilder builder, ConfigurationManager conf }); } +static void MapTestAccountSetupRoute(WebApplication app) +{ + app.MapPost("/debug/create-test-users", async ( + UserManager userManager, + QueryRepository queryRepository, + SessionRepository sessionRepository) => + { + var testAccounts = new[] + { + new { Email = "test1@example.com", Password = "Test123!" }, + new { Email = "test2@example.com", Password = "Test123!" } + }; + + var createdUsers = new List(); + var errors = new List(); + + foreach (var account in testAccounts) + { + // Delete existing user and their sessions if they exist + var existingUser = await userManager.FindByEmailAsync(account.Email); + if (existingUser != null) + { + // Delete all game sessions associated with this user + var sessions = await queryRepository.ReadSessionsMetadata(existingUser.Id); + foreach (var session in sessions) + { + await sessionRepository.DeleteSession(session.Id); + } + + // Delete the existing user + await userManager.DeleteAsync(existingUser); + } + + // Create fresh test user + var testUser = new ShogiUser + { + UserName = account.Email, + Email = account.Email, + EmailConfirmed = true + }; + + var result = await userManager.CreateAsync(testUser, account.Password); + + if (result.Succeeded) + { + createdUsers.Add(new { email = account.Email, password = account.Password }); + } + else + { + errors.Add(new { email = account.Email, errors = result.Errors }); + } + } + + if (errors.Count > 0) + { + return Results.BadRequest(new { message = "Failed to create some test users", createdUsers, errors }); + } + + return Results.Ok(new { message = "Test users created successfully", users = createdUsers }); + }) + .WithName("CreateTestUsers"); +} + // Make Program accessible for WebApplicationFactory in integration tests public partial class Program { }