1
0
mirror of synced 2024-11-15 02:47:35 +01:00

Add webUI apis to manager user's access codes, take 2

This commit is contained in:
S-Sebb 2023-11-12 17:56:57 +00:00
parent de1671aac9
commit 293f162b3f
25 changed files with 426 additions and 86 deletions

View File

@ -0,0 +1,8 @@
namespace SharedProject.Models.Requests;
public class BindAccessCodeRequest
{
public string AccessCode { get; set; } = string.Empty;
public uint Baid { get; set; }
}

View File

@ -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();
}
}

View File

@ -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)

View 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();
}
}

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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)
{

View 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>
}
}

View 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;
}
}
}
}

View File

@ -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));
}

View 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>

View File

@ -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));
}
}

View File

@ -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>

View File

@ -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));
}

View File

@ -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));
}

View File

@ -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();

View File

@ -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"

View File

@ -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;

View File

@ -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.

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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; }
}

View File

@ -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>

View File

@ -3,6 +3,7 @@
"LoginRequired": "false",
"AdminUserName": "admin",
"AdminPassword": "admin",
"OnlyAdmin": "false"
"OnlyAdmin": "false",
"BoundAccessCodeUpperLimit": "3"
}
}