Add webUI apis to manager user's access codes, take 2
This commit is contained in:
parent
de1671aac9
commit
293f162b3f
8
SharedProject/Models/Requests/BindAccessCodeRequest.cs
Normal file
8
SharedProject/Models/Requests/BindAccessCodeRequest.cs
Normal file
@ -0,0 +1,8 @@
|
||||
namespace SharedProject.Models.Requests;
|
||||
|
||||
public class BindAccessCodeRequest
|
||||
{
|
||||
public string AccessCode { get; set; } = string.Empty;
|
||||
|
||||
public uint Baid { get; set; }
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
using SharedProject.Models.Requests;
|
||||
using GameDatabase.Entities;
|
||||
using SharedProject.Models.Requests;
|
||||
|
||||
namespace TaikoLocalServer.Controllers.Api;
|
||||
|
||||
@ -12,12 +13,31 @@ public class CardsController : BaseController<CardsController>
|
||||
{
|
||||
this.cardService = cardService;
|
||||
}
|
||||
|
||||
|
||||
[HttpDelete("{accessCode}")]
|
||||
public async Task<IActionResult> DeleteUser(uint baid)
|
||||
public async Task<IActionResult> DeleteUser(string accessCode)
|
||||
{
|
||||
var result = await cardService.DeleteCard(baid);
|
||||
var result = await cardService.DeleteCard(accessCode);
|
||||
|
||||
return result ? NoContent() : NotFound();
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> BindAccessCode(BindAccessCodeRequest request)
|
||||
{
|
||||
var accessCode = request.AccessCode;
|
||||
var baid = request.Baid;
|
||||
var existingCard = await cardService.GetCardByAccessCode(accessCode);
|
||||
if (existingCard is not null)
|
||||
{
|
||||
return BadRequest("Access code already exists");
|
||||
}
|
||||
var newCard = new Card
|
||||
{
|
||||
Baid = baid,
|
||||
AccessCode = accessCode
|
||||
};
|
||||
await cardService.AddCard(newCard);
|
||||
return NoContent();
|
||||
}
|
||||
}
|
@ -12,14 +12,6 @@ public class CredentialsController : BaseController<CredentialsController>
|
||||
{
|
||||
this.credentialService = credentialService;
|
||||
}
|
||||
|
||||
[HttpDelete("{baid}")]
|
||||
public async Task<IActionResult> DeleteUser(uint baid)
|
||||
{
|
||||
var result = await credentialService.DeleteCredential(baid);
|
||||
|
||||
return result ? NoContent() : NotFound();
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> UpdatePassword(SetPasswordRequest request)
|
||||
|
23
TaikoLocalServer/Controllers/Api/UsersController.cs
Normal file
23
TaikoLocalServer/Controllers/Api/UsersController.cs
Normal file
@ -0,0 +1,23 @@
|
||||
using SharedProject.Models.Requests;
|
||||
|
||||
namespace TaikoLocalServer.Controllers.Api;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
public class UsersController : BaseController<UsersController>
|
||||
{
|
||||
private readonly IUserDatumService userDatumService;
|
||||
|
||||
public UsersController(IUserDatumService userDatumService)
|
||||
{
|
||||
this.userDatumService = userDatumService;
|
||||
}
|
||||
|
||||
[HttpDelete("{baid}")]
|
||||
public async Task<IActionResult> DeleteUser(uint baid)
|
||||
{
|
||||
var result = await userDatumService.DeleteUser(baid);
|
||||
|
||||
return result ? NoContent() : NotFound();
|
||||
}
|
||||
}
|
@ -58,17 +58,13 @@ public class CardService : ICardService
|
||||
context.Add(card);
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task<bool> DeleteCard(uint baid)
|
||||
|
||||
public async Task<bool> DeleteCard(string accessCode)
|
||||
{
|
||||
var cards = await context.Cards.ToListAsync();
|
||||
var deletingCards = cards.Where(card => card.Baid == baid).ToList();
|
||||
|
||||
if (deletingCards.Count == 0) return false;
|
||||
|
||||
context.RemoveRange(deletingCards);
|
||||
var card = await context.Cards.FindAsync(accessCode);
|
||||
if (card == null) return false;
|
||||
context.Cards.Remove(card);
|
||||
await context.SaveChangesAsync();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@ -12,6 +12,6 @@ public interface ICardService
|
||||
public Task<List<User>> GetUsersFromCards();
|
||||
|
||||
public Task AddCard(Card card);
|
||||
|
||||
public Task<bool> DeleteCard(uint baid);
|
||||
|
||||
public Task<bool> DeleteCard(string accessCode);
|
||||
}
|
@ -16,9 +16,9 @@ public interface IUserDatumService
|
||||
|
||||
public Task UpdateUserDatum(UserDatum userDatum);
|
||||
|
||||
public Task<bool> DeleteUser(uint baid);
|
||||
|
||||
public Task<List<uint>> GetFavoriteSongIds(ulong baid);
|
||||
|
||||
public Task UpdateFavoriteSong(ulong baid, uint songId, bool isFavorite);
|
||||
|
||||
|
||||
}
|
@ -56,6 +56,16 @@ public class UserDatumService : IUserDatumService
|
||||
context.Update(userDatum);
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task<bool> DeleteUser(uint baid)
|
||||
{
|
||||
var userDatum = await context.UserData.FindAsync((ulong)baid);
|
||||
if (userDatum == null) return false;
|
||||
context.UserData.Remove(userDatum);
|
||||
await context.SaveChangesAsync();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public async Task<List<uint>> GetFavoriteSongIds(ulong baid)
|
||||
{
|
||||
|
87
TaikoWebUI/Pages/AccessCode.razor
Normal file
87
TaikoWebUI/Pages/AccessCode.razor
Normal file
@ -0,0 +1,87 @@
|
||||
@page "/Users/{baid:int}/AccessCode"
|
||||
@inject HttpClient Client
|
||||
@inject IDialogService DialogService
|
||||
@inject LoginService LoginService
|
||||
@inject NavigationManager NavigationManager
|
||||
|
||||
<MudBreadcrumbs Items="breadcrumbs" Class="px-0"></MudBreadcrumbs>
|
||||
|
||||
<h1>Access Code Management</h1>
|
||||
<MudText Typo="Typo.caption">User: @Baid</MudText>
|
||||
|
||||
@if (response is null)
|
||||
{
|
||||
@for (uint i = 0; i < 3; i++)
|
||||
{
|
||||
<MudItem xs="12" md="6" lg="4">
|
||||
<MudCard Outlined="true">
|
||||
<MudCardContent>
|
||||
<MudSkeleton Width="30%" Height="42px;" Class="mb-5"/>
|
||||
<MudSkeleton Width="80%"/>
|
||||
<MudSkeleton Width="100%"/>
|
||||
</MudCardContent>
|
||||
<MudCardActions>
|
||||
<MudStack Row="true" Style="width:100%" Spacing="4" Justify="Justify.FlexEnd">
|
||||
<MudSkeleton Width="64px" Height="40px"/>
|
||||
<MudSkeleton Width="64px" Height="40px"/>
|
||||
</MudStack>
|
||||
</MudCardActions>
|
||||
</MudCard>
|
||||
</MudItem>
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@if ((LoginService.LoginRequired && (!LoginService.IsLoggedIn || (LoginService.GetLoggedInUser().Baid != Baid && !LoginService.IsAdmin))) || User is null)
|
||||
{
|
||||
<MudItem xs="12">
|
||||
<MudText Align="Align.Center" Class="my-8">
|
||||
Please log in by clicking on "Users" tab first.
|
||||
</MudText>
|
||||
</MudItem>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudGrid Justify="Justify.Center">
|
||||
<MudItem xs="6" md="4" lg="4">
|
||||
<MudCard>
|
||||
<MudCardContent>
|
||||
<MudForm @ref="bindAccessCodeForm">
|
||||
<MudText Typo="Typo.h4" Align="Align.Center">Bind New Access Code</MudText>
|
||||
<MudTextField @bind-value="inputAccessCode" InputType="InputType.Text" T="string"
|
||||
FullWidth="true" Required="@true" RequiredError="Access Code is required"
|
||||
Label="New Access Code"/>
|
||||
<MudButton OnClick="OnBind" FullWidth="true" Class="mt-3" StartIcon="@Icons.Material.Filled.AddCard" Color="Color.Primary" Variant="Variant.Filled">Bind</MudButton>
|
||||
</MudForm>
|
||||
</MudCardContent>
|
||||
</MudCard>
|
||||
</MudItem>
|
||||
<MudDivider/>
|
||||
@for (var idx = 0; idx < User.AccessCodes.Count; idx++)
|
||||
{
|
||||
var accessCode = User.AccessCodes[idx];
|
||||
var localIdx = idx + 1;
|
||||
<MudItem xs="6" md="4" lg="4">
|
||||
<MudCard Outlined="true">
|
||||
<MudCardHeader>
|
||||
<CardHeaderContent>
|
||||
<MudText Typo="Typo.h6" Style="font-weight:bold">User Access Code @localIdx</MudText>
|
||||
</CardHeaderContent>
|
||||
</MudCardHeader>
|
||||
<MudCardContent>
|
||||
<MudText Style="font-weight:bold">@accessCode</MudText>
|
||||
</MudCardContent>
|
||||
<MudCardActions>
|
||||
<MudButton OnClick="@(_ => DeleteAccessCode(accessCode))"
|
||||
Size="Size.Small" Variant="Variant.Text" StartIcon="@Icons.Material.Filled.Delete"
|
||||
Color="Color.Primary">
|
||||
Delete Access Code
|
||||
</MudButton>
|
||||
</MudCardActions>
|
||||
</MudCard>
|
||||
</MudItem>
|
||||
<MudDivider/>
|
||||
}
|
||||
</MudGrid>
|
||||
}
|
||||
}
|
105
TaikoWebUI/Pages/AccessCode.razor.cs
Normal file
105
TaikoWebUI/Pages/AccessCode.razor.cs
Normal file
@ -0,0 +1,105 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using System.Linq;
|
||||
using TaikoWebUI.Pages.Dialogs;
|
||||
|
||||
namespace TaikoWebUI.Pages;
|
||||
|
||||
public partial class AccessCode
|
||||
{
|
||||
[Parameter]
|
||||
public int Baid { get; set; }
|
||||
|
||||
private string inputAccessCode = "";
|
||||
private MudForm bindAccessCodeForm = default!;
|
||||
|
||||
private User? User { get; set; } = new();
|
||||
|
||||
private DashboardResponse? response;
|
||||
|
||||
private readonly List<BreadcrumbItem> breadcrumbs = new()
|
||||
{
|
||||
new BreadcrumbItem("Users", href: "/Users"),
|
||||
};
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await base.OnInitializedAsync();
|
||||
await InitializeUser();
|
||||
breadcrumbs.Add(new BreadcrumbItem($"User: {Baid}", href: null, disabled: true));
|
||||
breadcrumbs.Add(new BreadcrumbItem("Access Code Management", href: $"/Users/{Baid}/AccessCode", disabled: false));
|
||||
}
|
||||
|
||||
private async Task InitializeUser()
|
||||
{
|
||||
response = await Client.GetFromJsonAsync<DashboardResponse>("api/Dashboard");
|
||||
LoginService.ResetLoggedInUser(response);
|
||||
if (LoginService.IsAdmin || !LoginService.LoginRequired)
|
||||
{
|
||||
if (response is not null)
|
||||
{
|
||||
User = response.Users.FirstOrDefault(u => u.Baid == Baid);
|
||||
}
|
||||
}
|
||||
else if (LoginService.IsLoggedIn)
|
||||
{
|
||||
User = LoginService.GetLoggedInUser();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task DeleteAccessCode(string accessCode)
|
||||
{
|
||||
var parameters = new DialogParameters<AccessCodeDeleteConfirmDialog>
|
||||
{
|
||||
{ x => x.User, User },
|
||||
{ x => x.AccessCode, accessCode }
|
||||
};
|
||||
|
||||
var dialog = DialogService.Show<AccessCodeDeleteConfirmDialog>("Delete Access Code", parameters);
|
||||
var result = await dialog.Result;
|
||||
|
||||
if (result.Canceled) return;
|
||||
|
||||
await InitializeUser();
|
||||
NavigationManager.NavigateTo(NavigationManager.Uri);
|
||||
}
|
||||
|
||||
private async Task OnBind()
|
||||
{
|
||||
if (response != null)
|
||||
{
|
||||
var result = await LoginService.BindAccessCode(inputAccessCode, Client);
|
||||
switch (result)
|
||||
{
|
||||
case 0:
|
||||
await DialogService.ShowMessageBox(
|
||||
"Error",
|
||||
(MarkupString)
|
||||
"Not logged in.<br />Please log in first and try again.",
|
||||
"Ok");
|
||||
break;
|
||||
case 1:
|
||||
await DialogService.ShowMessageBox(
|
||||
"Success",
|
||||
"New access code bound successfully.",
|
||||
"Ok");
|
||||
await InitializeUser();
|
||||
NavigationManager.NavigateTo(NavigationManager.Uri);
|
||||
break;
|
||||
case 2:
|
||||
await DialogService.ShowMessageBox(
|
||||
"Error",
|
||||
(MarkupString)
|
||||
"Bound access code upper limit reached.<br />Please delete one access code first.",
|
||||
"Ok");
|
||||
break;
|
||||
case 3:
|
||||
await DialogService.ShowMessageBox(
|
||||
"Error",
|
||||
(MarkupString)
|
||||
"Access code already bound.<br />Please delete it from the bound user first.",
|
||||
"Ok");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -23,7 +23,7 @@ public partial class DaniDojo
|
||||
.Sort((stageData, otherStageData) => stageData.SongNumber.CompareTo(otherStageData.SongNumber)));
|
||||
bestDataMap = response.DanBestDataList.ToDictionary(data => data.DanId);
|
||||
|
||||
breadcrumbs.Add(new BreadcrumbItem($"Card: {Baid}", href: null, disabled: true));
|
||||
breadcrumbs.Add(new BreadcrumbItem($"User: {Baid}", href: null, disabled: true));
|
||||
breadcrumbs.Add(new BreadcrumbItem("Dani Dojo", href: $"/Users/{Baid}/DaniDojo", disabled: false));
|
||||
}
|
||||
|
||||
|
23
TaikoWebUI/Pages/Dialogs/AccessCodeDeleteConfirmDialog.razor
Normal file
23
TaikoWebUI/Pages/Dialogs/AccessCodeDeleteConfirmDialog.razor
Normal file
@ -0,0 +1,23 @@
|
||||
@inject HttpClient Client
|
||||
@inject ISnackbar Snackbar
|
||||
|
||||
<MudDialog>
|
||||
<TitleContent>
|
||||
<MudText Typo="Typo.h6">
|
||||
<MudIcon Icon="@Icons.Material.Filled.DeleteForever" Class="mr-3 mb-n1"/>
|
||||
Delete user?
|
||||
</MudText>
|
||||
</TitleContent>
|
||||
<DialogContent>
|
||||
<MudText>
|
||||
Do you really want to delete the access code @AccessCode?
|
||||
This process cannot be undone!
|
||||
</MudText>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<MudButton OnClick="Cancel">CANCEL</MudButton>
|
||||
<MudButton Color="Color.Error" OnClick="DeleteAccessCode">
|
||||
<MudText>DELETE</MudText>
|
||||
</MudButton>
|
||||
</DialogActions>
|
||||
</MudDialog>
|
@ -0,0 +1,38 @@
|
||||
namespace TaikoWebUI.Pages.Dialogs;
|
||||
|
||||
public partial class AccessCodeDeleteConfirmDialog
|
||||
{
|
||||
|
||||
[CascadingParameter]
|
||||
MudDialogInstance MudDialog { get; set; } = null!;
|
||||
|
||||
[Parameter]
|
||||
public User User { get; set; } = new();
|
||||
|
||||
[Parameter]
|
||||
public string AccessCode { get; set; } = "";
|
||||
|
||||
private void Cancel() => MudDialog.Cancel();
|
||||
|
||||
private async Task DeleteAccessCode()
|
||||
{
|
||||
if (User.AccessCodes.Count == 1)
|
||||
{
|
||||
Snackbar.Add("Cannot delete last access code!", Severity.Error);
|
||||
MudDialog.Close(DialogResult.Ok(false));
|
||||
return;
|
||||
}
|
||||
|
||||
var cardResponseMessage = await Client.DeleteAsync($"api/Cards/{AccessCode}");
|
||||
|
||||
if (!cardResponseMessage.IsSuccessStatusCode)
|
||||
{
|
||||
Snackbar.Add("Something went wrong when deleting access code!", Severity.Error);
|
||||
MudDialog.Close(DialogResult.Ok(false));
|
||||
return;
|
||||
}
|
||||
|
||||
Snackbar.Add("Delete success!", Severity.Success);
|
||||
MudDialog.Close(DialogResult.Ok(true));
|
||||
}
|
||||
}
|
@ -15,9 +15,9 @@
|
||||
</MudText>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<MudButton OnClick="Cancel">Cancel</MudButton>
|
||||
<MudButton OnClick="Cancel">CANCEL</MudButton>
|
||||
<MudButton Color="Color.Error" OnClick="DeleteUser">
|
||||
<MudText>Delete User</MudText>
|
||||
<MudText>DELETE</MudText>
|
||||
</MudButton>
|
||||
</DialogActions>
|
||||
</MudDialog>
|
@ -13,24 +13,15 @@ public partial class UserDeleteConfirmDialog
|
||||
|
||||
private async Task DeleteUser()
|
||||
{
|
||||
var credentialResponseMessage = await Client.DeleteAsync($"api/Credentials/{User.Baid}");
|
||||
var responseMessage = await Client.DeleteAsync($"api/Users/{User.Baid}");
|
||||
|
||||
if (!credentialResponseMessage.IsSuccessStatusCode)
|
||||
{
|
||||
Snackbar.Add("Something went wrong when deleting user credentials!", Severity.Error);
|
||||
MudDialog.Close(DialogResult.Ok(false));
|
||||
return;
|
||||
}
|
||||
|
||||
var cardResponseMessage = await Client.DeleteAsync($"api/Cards/{User.Baid}");
|
||||
|
||||
if (!cardResponseMessage.IsSuccessStatusCode)
|
||||
if (!responseMessage.IsSuccessStatusCode)
|
||||
{
|
||||
Snackbar.Add("Something went wrong when deleting user!", Severity.Error);
|
||||
MudDialog.Close(DialogResult.Ok(false));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Snackbar.Add("Delete success!", Severity.Success);
|
||||
MudDialog.Close(DialogResult.Ok(true));
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ public partial class HighScores
|
||||
}
|
||||
|
||||
|
||||
breadcrumbs.Add(new BreadcrumbItem($"Card: {Baid}", href: null, disabled: true));
|
||||
breadcrumbs.Add(new BreadcrumbItem($"User: {Baid}", href: null, disabled: true));
|
||||
breadcrumbs.Add(new BreadcrumbItem("High Scores", href: $"/Users/{Baid}/HighScores", disabled: false));
|
||||
}
|
||||
|
||||
|
@ -177,7 +177,7 @@ public partial class Profile
|
||||
isSavingOptions = false;
|
||||
response = await Client.GetFromJsonAsync<UserSetting>($"api/UserSettings/{Baid}");
|
||||
|
||||
breadcrumbs.Add(new BreadcrumbItem($"Card: {Baid}", href: null, disabled: true));
|
||||
breadcrumbs.Add(new BreadcrumbItem($"User: {Baid}", href: null, disabled: true));
|
||||
breadcrumbs.Add(new BreadcrumbItem("Profile", href: $"/Users/{Baid}/Profile", disabled: false));
|
||||
|
||||
costumeFlagArraySizes = GameDataService.GetCostumeFlagArraySizes();
|
||||
|
@ -20,9 +20,9 @@ else
|
||||
<MudCardContent>
|
||||
<MudForm @ref="registerForm">
|
||||
<MudText Typo="Typo.h4" Align="Align.Center">Register</MudText>
|
||||
<MudTextField @bind-value="cardNum" InputType="InputType.Text" T="string"
|
||||
FullWidth="true" Required="@true" RequiredError="Card Number is required"
|
||||
Label="Card Number"/>
|
||||
<MudTextField @bind-value="accessCode" InputType="InputType.Text" T="string"
|
||||
FullWidth="true" Required="@true" RequiredError="Access Code is required"
|
||||
Label="Access Code"/>
|
||||
<MudTextField @bind-Value="password" InputType="InputType.Password"
|
||||
T="string" FullWidth="true" Required="@true"
|
||||
RequiredError="Password is required"
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
public partial class Register
|
||||
{
|
||||
private string cardNum = "";
|
||||
private string accessCode = "";
|
||||
private string confirmPassword = "";
|
||||
private string password = "";
|
||||
private MudForm registerForm = default!;
|
||||
@ -19,7 +19,7 @@ public partial class Register
|
||||
{
|
||||
if (response != null)
|
||||
{
|
||||
var result = await LoginService.Register(cardNum, password, confirmPassword, response, Client);
|
||||
var result = await LoginService.Register(accessCode, password, confirmPassword, response, Client);
|
||||
switch (result)
|
||||
{
|
||||
case 0:
|
||||
@ -32,7 +32,7 @@ public partial class Register
|
||||
case 1:
|
||||
await DialogService.ShowMessageBox(
|
||||
"Success",
|
||||
"Card registered successfully.",
|
||||
"Access code registered successfully.",
|
||||
"Ok");
|
||||
NavigationManager.NavigateTo("/Users");
|
||||
break;
|
||||
@ -46,14 +46,14 @@ public partial class Register
|
||||
await DialogService.ShowMessageBox(
|
||||
"Error",
|
||||
(MarkupString)
|
||||
"Card number not found.<br />Please play one game with this card number to register it.",
|
||||
"Access code not found.<br />Please play one game with this access code to register it.",
|
||||
"Ok");
|
||||
break;
|
||||
case 4:
|
||||
await DialogService.ShowMessageBox(
|
||||
"Error",
|
||||
(MarkupString)
|
||||
"Card is already registered, please use set password to login.",
|
||||
"Access code is already registered, please use set password to login.",
|
||||
"Ok");
|
||||
NavigationManager.NavigateTo("/Users");
|
||||
break;
|
||||
|
@ -30,7 +30,7 @@
|
||||
}
|
||||
else if (response.Users.Count != 0)
|
||||
{
|
||||
if (LoginService.IsAdmin || !LoginService.LoginRequired)
|
||||
if (LoginService.IsAdmin || !LoginService.LoginRequired) // Admin mode, can see all users
|
||||
{
|
||||
@foreach (var user in response.Users)
|
||||
{
|
||||
@ -38,7 +38,7 @@
|
||||
<MudCard Outlined="true">
|
||||
<MudCardHeader>
|
||||
<CardHeaderContent>
|
||||
<MudText Typo="Typo.h6" Style="font-weight:bold">@user.Baid</MudText>
|
||||
<MudText Typo="Typo.h6" Style="font-weight:bold">User: @user.Baid</MudText>
|
||||
</CardHeaderContent>
|
||||
<CardHeaderActions>
|
||||
<MudMenu Icon="@Icons.Material.Filled.MoreVert" Dense="true" AnchorOrigin="Origin.BottomLeft"
|
||||
@ -49,6 +49,12 @@
|
||||
Show QR Code
|
||||
</MudMenuItem>
|
||||
<MudDivider/>
|
||||
<MudMenuItem Icon="@Icons.Material.Filled.FeaturedPlayList"
|
||||
Href="@($"Users/{user.Baid}/AccessCode")"
|
||||
IconColor="@Color.Primary">
|
||||
Manage Access Codes
|
||||
</MudMenuItem>
|
||||
<MudDivider/>
|
||||
<MudMenuItem Icon="@Icons.Material.Filled.Delete"
|
||||
OnClick="@(_ => DeleteUser(user))"
|
||||
IconColor="@Color.Error">
|
||||
@ -59,14 +65,11 @@
|
||||
</MudCardHeader>
|
||||
<MudCardContent>
|
||||
<MudText Style="font-weight:bold">Access Code</MudText>
|
||||
<MudGrid>
|
||||
@foreach (var accessCode in user.AccessCodes)
|
||||
{
|
||||
<MudItem xs="12">
|
||||
<MudText Style="font-family:monospace;overflow:hidden;overflow-x:scroll">@accessCode</MudText>
|
||||
</MudItem>
|
||||
}
|
||||
</MudGrid>
|
||||
<MudText Style="font-family:monospace;overflow:hidden;overflow-x:scroll">@user.AccessCodes[0]</MudText>
|
||||
@if (user.AccessCodes.Count > 1)
|
||||
{
|
||||
<MudText Style="font-family:monospace;overflow:hidden;overflow-x:scroll">... and @(user.AccessCodes.Count-1) other access code(s)</MudText>
|
||||
}
|
||||
</MudCardContent>
|
||||
<MudCardActions>
|
||||
<MudStack Row="true" Style="width:100%" Spacing="4" Justify="Justify.FlexEnd">
|
||||
@ -95,7 +98,7 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
@if (!LoginService.IsLoggedIn)
|
||||
@if (!LoginService.IsLoggedIn) // Not logged in, show login form
|
||||
{
|
||||
<MudContainer>
|
||||
<MudGrid Justify="Justify.Center">
|
||||
@ -104,10 +107,10 @@
|
||||
<MudCardContent>
|
||||
<MudForm @ref="loginForm">
|
||||
<MudText Typo="Typo.h4" Align="Align.Center">Login</MudText>
|
||||
<MudTextField @bind-value="cardNum" InputType="InputType.Text" T="string"
|
||||
FullWidth="true" Required="@true" RequiredError="Card Number is required"
|
||||
Label="Card Number"/>
|
||||
<MudTextField @bind-Value="password" InputType="InputType.Password"
|
||||
<MudTextField @bind-value="inputAccessCode" InputType="InputType.Text" T="string"
|
||||
FullWidth="true" Required="@true" RequiredError="Access code is required"
|
||||
Label="Access code"/>
|
||||
<MudTextField @bind-Value="inputPassword" InputType="InputType.Password"
|
||||
T="string" FullWidth="true" Required="@true"
|
||||
RequiredError="Password is required"
|
||||
Label="Password">
|
||||
@ -128,13 +131,13 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
var user = LoginService.GetLoggedInUser();
|
||||
var user = LoginService.GetLoggedInUser(); // Logged in, show only own user
|
||||
<MudGrid Justify="Justify.Center">
|
||||
<MudItem xs="12" md="6" lg="4">
|
||||
<MudCard Outlined="true">
|
||||
<MudCardHeader>
|
||||
<CardHeaderContent>
|
||||
<MudText Typo="Typo.h6" Style="font-weight:bold">@user.Baid</MudText>
|
||||
<MudText Typo="Typo.h6" Style="font-weight:bold">User: @user.Baid</MudText>
|
||||
</CardHeaderContent>
|
||||
<CardHeaderActions>
|
||||
<MudMenu Icon="@Icons.Material.Filled.MoreVert" Dense="true" AnchorOrigin="Origin.BottomLeft"
|
||||
@ -145,6 +148,12 @@
|
||||
Show QR Code
|
||||
</MudMenuItem>
|
||||
<MudDivider/>
|
||||
<MudMenuItem Icon="@Icons.Material.Filled.FeaturedPlayList"
|
||||
Href="@($"Users/{user.Baid}/AccessCode")"
|
||||
IconColor="@Color.Primary">
|
||||
Manage Access Codes
|
||||
</MudMenuItem>
|
||||
<MudDivider/>
|
||||
<MudMenuItem Icon="@Icons.Material.Filled.Delete"
|
||||
OnClick="@(_ => DeleteUser(user))"
|
||||
IconColor="@Color.Error">
|
||||
@ -155,14 +164,11 @@
|
||||
</MudCardHeader>
|
||||
<MudCardContent>
|
||||
<MudText Style="font-weight:bold">Access Code</MudText>
|
||||
<MudGrid>
|
||||
@foreach (var accessCode in user.AccessCodes)
|
||||
{
|
||||
<MudItem xs="12">
|
||||
<MudText Style="font-family:monospace;overflow:hidden;overflow-x:scroll">@accessCode</MudText>
|
||||
</MudItem>
|
||||
}
|
||||
</MudGrid>
|
||||
<MudText Style="font-family:monospace;overflow:hidden;overflow-x:scroll">@user.AccessCodes[0]</MudText>
|
||||
@if (user.AccessCodes.Count > 1)
|
||||
{
|
||||
<MudText Style="font-family:monospace;overflow:hidden;overflow-x:scroll">... and @(user.AccessCodes.Count-1) other access code(s)</MudText>
|
||||
}
|
||||
</MudCardContent>
|
||||
<MudCardActions>
|
||||
<MudStack Row="true" Style="width:100%" Spacing="4" Justify="Justify.FlexEnd">
|
||||
@ -175,7 +181,7 @@
|
||||
Dense="true"
|
||||
Color="Color.Primary"
|
||||
Label="View Play Data"
|
||||
StartIcon="@Icons.Material.Filled.FeaturedPlayList"
|
||||
StartIcon="@Icons.Material.Filled.DataExploration"
|
||||
EndIcon="@Icons.Material.Filled.KeyboardArrowDown"
|
||||
FullWidth="true"
|
||||
AnchorOrigin="Origin.BottomCenter"
|
||||
@ -192,7 +198,7 @@
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
{ // No users in the database
|
||||
<MudItem xs="12">
|
||||
<MudText Align="Align.Center" Class="my-8">
|
||||
No data.
|
||||
|
@ -4,9 +4,9 @@ namespace TaikoWebUI.Pages;
|
||||
|
||||
public partial class Users
|
||||
{
|
||||
private string cardNum = "";
|
||||
private string inputAccessCode = "";
|
||||
private MudForm loginForm = default!;
|
||||
private string password = "";
|
||||
private string inputPassword = "";
|
||||
private DashboardResponse? response;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
@ -35,7 +35,7 @@ public partial class Users
|
||||
{
|
||||
if (response != null)
|
||||
{
|
||||
var result = LoginService.Login(cardNum, password, response);
|
||||
var result = LoginService.Login(inputAccessCode, inputPassword, response);
|
||||
switch (result)
|
||||
{
|
||||
case 0:
|
||||
@ -58,14 +58,14 @@ public partial class Users
|
||||
await DialogService.ShowMessageBox(
|
||||
"Error",
|
||||
(MarkupString)
|
||||
"Card number not found.<br />Please play one game with this card number to register it.",
|
||||
"Access code not found.<br />Please play one game with this access code to register it.",
|
||||
"Ok");
|
||||
break;
|
||||
case 4:
|
||||
await DialogService.ShowMessageBox(
|
||||
"Error",
|
||||
(MarkupString)
|
||||
"Card number not registered.<br />Please use register button to create a password first.",
|
||||
"Access code not registered.<br />Please use register button to create a password first.",
|
||||
"Ok");
|
||||
break;
|
||||
}
|
||||
|
@ -9,6 +9,9 @@ public class LoginService
|
||||
{
|
||||
private readonly string adminPassword;
|
||||
private readonly string adminUsername;
|
||||
public bool LoginRequired { get; }
|
||||
public bool OnlyAdmin { get; }
|
||||
private int BoundAccessCodeUpperLimit;
|
||||
|
||||
public LoginService(IOptions<WebUiSettings> settings)
|
||||
{
|
||||
@ -19,15 +22,13 @@ public class LoginService
|
||||
adminPassword = webUiSettings.AdminPassword;
|
||||
LoginRequired = webUiSettings.LoginRequired;
|
||||
OnlyAdmin = webUiSettings.OnlyAdmin;
|
||||
BoundAccessCodeUpperLimit = webUiSettings.BoundAccessCodeUpperLimit;
|
||||
}
|
||||
|
||||
public bool IsLoggedIn { get; private set; }
|
||||
private User LoggedInUser { get; set; } = new();
|
||||
public bool IsAdmin { get; private set; }
|
||||
|
||||
public bool LoginRequired { get; }
|
||||
public bool OnlyAdmin { get; }
|
||||
|
||||
public int Login(string inputCardNum, string inputPassword, DashboardResponse response)
|
||||
{
|
||||
if (inputCardNum == adminUsername && inputPassword == adminPassword)
|
||||
@ -139,4 +140,26 @@ public class LoginService
|
||||
{
|
||||
return LoggedInUser;
|
||||
}
|
||||
|
||||
public void ResetLoggedInUser(DashboardResponse? response)
|
||||
{
|
||||
if (response is null) return;
|
||||
var baid = LoggedInUser.Baid;
|
||||
var newLoggedInUser = response.Users.FirstOrDefault(u => u.Baid == baid);
|
||||
if (newLoggedInUser is null) return;
|
||||
LoggedInUser = newLoggedInUser;
|
||||
}
|
||||
|
||||
public async Task<int> BindAccessCode(string inputAccessCode, HttpClient client)
|
||||
{
|
||||
if (!IsLoggedIn) return 0;
|
||||
if (LoggedInUser.AccessCodes.Count >= BoundAccessCodeUpperLimit) return 2;
|
||||
var request = new BindAccessCodeRequest
|
||||
{
|
||||
AccessCode = inputAccessCode,
|
||||
Baid = LoggedInUser.Baid
|
||||
};
|
||||
var responseMessage = await client.PostAsJsonAsync("api/Cards", request);
|
||||
return responseMessage.IsSuccessStatusCode ? 1 : 3;
|
||||
}
|
||||
}
|
@ -6,4 +6,6 @@ public class WebUiSettings
|
||||
public string AdminUsername { get; set; } = string.Empty;
|
||||
public string AdminPassword { get; set; } = string.Empty;
|
||||
public bool OnlyAdmin { get; set; }
|
||||
|
||||
public int BoundAccessCodeUpperLimit { get; set; }
|
||||
}
|
@ -46,5 +46,20 @@
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<_ContentIncludedByDefault Remove="Pages\Pages\AccessCode.razor" />
|
||||
<_ContentIncludedByDefault Remove="Pages\Pages\ChangePassword.razor" />
|
||||
<_ContentIncludedByDefault Remove="Pages\Pages\DaniDojo.razor" />
|
||||
<_ContentIncludedByDefault Remove="Pages\Pages\Dashboard.razor" />
|
||||
<_ContentIncludedByDefault Remove="Pages\Pages\Dialogs\AccessCodeDeleteConfirmDialog.razor" />
|
||||
<_ContentIncludedByDefault Remove="Pages\Pages\Dialogs\ChooseTitleDialog.razor" />
|
||||
<_ContentIncludedByDefault Remove="Pages\Pages\Dialogs\UserDeleteConfirmDialog.razor" />
|
||||
<_ContentIncludedByDefault Remove="Pages\Pages\Dialogs\UserQrCodeDialog.razor" />
|
||||
<_ContentIncludedByDefault Remove="Pages\Pages\HighScores.razor" />
|
||||
<_ContentIncludedByDefault Remove="Pages\Pages\Profile.razor" />
|
||||
<_ContentIncludedByDefault Remove="Pages\Pages\Register.razor" />
|
||||
<_ContentIncludedByDefault Remove="Pages\Pages\Users.razor" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
</Project>
|
@ -3,6 +3,7 @@
|
||||
"LoginRequired": "false",
|
||||
"AdminUserName": "admin",
|
||||
"AdminPassword": "admin",
|
||||
"OnlyAdmin": "false"
|
||||
"OnlyAdmin": "false",
|
||||
"BoundAccessCodeUpperLimit": "3"
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user