yep
This commit is contained in:
41
README.md
41
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.
|
The application uses sockets to allow players to enjoy sessions in real time.
|
||||||
|
|
||||||
### Technologies used
|
### Technologies used
|
||||||
A Blazor UI backed by an Asp.net Core API service which uses Sql Server for presistent storage.
|
A Blazor Web App which uses Sql Server for presistent storage and Identity EF Core for account management.
|
||||||
|
|
||||||
### 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.
|
|
||||||
|
|
||||||
|
|
||||||
### Roadmap of features remaining
|
### Roadmap of features remaining
|
||||||
The app is not yet finished, though much of the functionality exists. Here is a list of what remains.
|
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.
|
* 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.
|
* 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.
|
* Retaining an archive of games played and move history of each game.
|
||||||
* Adaptive UI layout for varying viewport (screen) sizes.
|
* 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.
|
||||||
@@ -8,6 +8,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
|
|||||||
.editorconfig = .editorconfig
|
.editorconfig = .editorconfig
|
||||||
.gitignore = .gitignore
|
.gitignore = .gitignore
|
||||||
azure-pipelines.yml = azure-pipelines.yml
|
azure-pipelines.yml = azure-pipelines.yml
|
||||||
|
Shogi\.config\dotnet-tools.json = Shogi\.config\dotnet-tools.json
|
||||||
global.json = global.json
|
global.json = global.json
|
||||||
README.md = README.md
|
README.md = README.md
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<Router AppAssembly="@typeof(Routes).Assembly">
|
<Router AppAssembly="@typeof(Routes).Assembly">
|
||||||
<Found Context="routeData">
|
<Found Context="routeData">
|
||||||
<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
|
<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
|
||||||
<FocusOnNavigate RouteData="@routeData" Selector="h1" />
|
@* <FocusOnNavigate RouteData="@routeData" Selector="h1" /> *@
|
||||||
</Found>
|
</Found>
|
||||||
<NotFound>
|
<NotFound>
|
||||||
<PageTitle>Not found</PageTitle>
|
<PageTitle>Not found</PageTitle>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Microsoft.AspNetCore.Components.Authorization;
|
using Microsoft.AspNetCore.Components.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Identity;
|
||||||
using Microsoft.AspNetCore.Identity.UI.Services;
|
using Microsoft.AspNetCore.Identity.UI.Services;
|
||||||
using Microsoft.AspNetCore.ResponseCompression;
|
using Microsoft.AspNetCore.ResponseCompression;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
@@ -76,6 +77,10 @@ app.MapHub<GameHub>("/gamehub");
|
|||||||
app.MapRazorComponents<App>()
|
app.MapRazorComponents<App>()
|
||||||
.AddInteractiveServerRenderMode();
|
.AddInteractiveServerRenderMode();
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
MapTestAccountSetupRoute(app);
|
||||||
|
#endif
|
||||||
|
|
||||||
app.Run();
|
app.Run();
|
||||||
|
|
||||||
static void AddIdentity(WebApplicationBuilder builder, ConfigurationManager configuration)
|
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<ShogiUser> 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<object>();
|
||||||
|
var errors = new List<object>();
|
||||||
|
|
||||||
|
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
|
// Make Program accessible for WebApplicationFactory in integration tests
|
||||||
public partial class Program { }
|
public partial class Program { }
|
||||||
|
|||||||
Reference in New Issue
Block a user