diff --git a/GameDatabase/Entities/UserDatum.cs b/GameDatabase/Entities/UserDatum.cs
index fed00bc..a39f448 100644
--- a/GameDatabase/Entities/UserDatum.cs
+++ b/GameDatabase/Entities/UserDatum.cs
@@ -33,5 +33,6 @@ namespace GameDatabase.Entities
public int AiWinCount { get; set; }
public string TokenCountDict { get; set; } = "{}";
public string UnlockedSongIdList { get; set; } = "[]";
+ public bool IsAdmin { get; set; }
}
}
\ No newline at end of file
diff --git a/GameDatabase/Migrations/20231218152045_AddIsAdminToUserDatum.Designer.cs b/GameDatabase/Migrations/20231218152045_AddIsAdminToUserDatum.Designer.cs
new file mode 100644
index 0000000..54a7fa9
--- /dev/null
+++ b/GameDatabase/Migrations/20231218152045_AddIsAdminToUserDatum.Designer.cs
@@ -0,0 +1,491 @@
+//
+using System;
+using GameDatabase.Context;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+
+#nullable disable
+
+namespace GameDatabase.Migrations
+{
+ [DbContext(typeof(TaikoDbContext))]
+ [Migration("20231218152045_AddIsAdminToUserDatum")]
+ partial class AddIsAdminToUserDatum
+ {
+ ///
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder.HasAnnotation("ProductVersion", "8.0.0-rc.2.23480.1");
+
+ modelBuilder.Entity("GameDatabase.Entities.AiScoreDatum", b =>
+ {
+ b.Property("Baid")
+ .HasColumnType("INTEGER");
+
+ b.Property("SongId")
+ .HasColumnType("INTEGER");
+
+ b.Property("Difficulty")
+ .HasColumnType("INTEGER");
+
+ b.Property("IsWin")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("Baid", "SongId", "Difficulty");
+
+ b.ToTable("AiScoreData");
+ });
+
+ modelBuilder.Entity("GameDatabase.Entities.AiSectionScoreDatum", b =>
+ {
+ b.Property("Baid")
+ .HasColumnType("INTEGER");
+
+ b.Property("SongId")
+ .HasColumnType("INTEGER");
+
+ b.Property("Difficulty")
+ .HasColumnType("INTEGER");
+
+ b.Property("SectionIndex")
+ .HasColumnType("INTEGER");
+
+ b.Property("Crown")
+ .HasColumnType("INTEGER");
+
+ b.Property("DrumrollCount")
+ .HasColumnType("INTEGER");
+
+ b.Property("GoodCount")
+ .HasColumnType("INTEGER");
+
+ b.Property("IsWin")
+ .HasColumnType("INTEGER");
+
+ b.Property("MissCount")
+ .HasColumnType("INTEGER");
+
+ b.Property("OkCount")
+ .HasColumnType("INTEGER");
+
+ b.Property("Score")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("Baid", "SongId", "Difficulty", "SectionIndex");
+
+ b.ToTable("AiSectionScoreData");
+ });
+
+ modelBuilder.Entity("GameDatabase.Entities.Card", b =>
+ {
+ b.Property("AccessCode")
+ .HasColumnType("TEXT");
+
+ b.Property("Baid")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("AccessCode");
+
+ b.HasIndex("Baid");
+
+ b.ToTable("Card", (string)null);
+ });
+
+ modelBuilder.Entity("GameDatabase.Entities.Credential", b =>
+ {
+ b.Property("Baid")
+ .HasColumnType("INTEGER");
+
+ b.Property("Password")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("Salt")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.HasKey("Baid");
+
+ b.ToTable("Credential", (string)null);
+ });
+
+ modelBuilder.Entity("GameDatabase.Entities.DanScoreDatum", b =>
+ {
+ b.Property("Baid")
+ .HasColumnType("INTEGER");
+
+ b.Property("DanId")
+ .HasColumnType("INTEGER");
+
+ b.Property("DanType")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER")
+ .HasDefaultValue(1);
+
+ b.Property("ArrivalSongCount")
+ .HasColumnType("INTEGER");
+
+ b.Property("ClearState")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER")
+ .HasDefaultValue(0u);
+
+ b.Property("ComboCountTotal")
+ .HasColumnType("INTEGER");
+
+ b.Property("SoulGaugeTotal")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("Baid", "DanId", "DanType");
+
+ b.ToTable("DanScoreData");
+ });
+
+ modelBuilder.Entity("GameDatabase.Entities.DanStageScoreDatum", b =>
+ {
+ b.Property("Baid")
+ .HasColumnType("INTEGER");
+
+ b.Property("DanId")
+ .HasColumnType("INTEGER");
+
+ b.Property("DanType")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER")
+ .HasDefaultValue(1);
+
+ b.Property("SongNumber")
+ .HasColumnType("INTEGER");
+
+ b.Property("BadCount")
+ .HasColumnType("INTEGER");
+
+ b.Property("ComboCount")
+ .HasColumnType("INTEGER");
+
+ b.Property("DrumrollCount")
+ .HasColumnType("INTEGER");
+
+ b.Property("GoodCount")
+ .HasColumnType("INTEGER");
+
+ b.Property("HighScore")
+ .HasColumnType("INTEGER");
+
+ b.Property("OkCount")
+ .HasColumnType("INTEGER");
+
+ b.Property("PlayScore")
+ .HasColumnType("INTEGER");
+
+ b.Property("TotalHitCount")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("Baid", "DanId", "DanType", "SongNumber");
+
+ b.ToTable("DanStageScoreData");
+ });
+
+ modelBuilder.Entity("GameDatabase.Entities.SongBestDatum", b =>
+ {
+ b.Property("Baid")
+ .HasColumnType("INTEGER");
+
+ b.Property("SongId")
+ .HasColumnType("INTEGER");
+
+ b.Property("Difficulty")
+ .HasColumnType("INTEGER");
+
+ b.Property("BestCrown")
+ .HasColumnType("INTEGER");
+
+ b.Property("BestRate")
+ .HasColumnType("INTEGER");
+
+ b.Property("BestScore")
+ .HasColumnType("INTEGER");
+
+ b.Property("BestScoreRank")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("Baid", "SongId", "Difficulty");
+
+ b.ToTable("SongBestData");
+ });
+
+ modelBuilder.Entity("GameDatabase.Entities.SongPlayDatum", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property("Baid")
+ .HasColumnType("INTEGER");
+
+ b.Property("ComboCount")
+ .HasColumnType("INTEGER");
+
+ b.Property("Crown")
+ .HasColumnType("INTEGER");
+
+ b.Property("Difficulty")
+ .HasColumnType("INTEGER");
+
+ b.Property("DrumrollCount")
+ .HasColumnType("INTEGER");
+
+ b.Property("GoodCount")
+ .HasColumnType("INTEGER");
+
+ b.Property("HitCount")
+ .HasColumnType("INTEGER");
+
+ b.Property("MissCount")
+ .HasColumnType("INTEGER");
+
+ b.Property("OkCount")
+ .HasColumnType("INTEGER");
+
+ b.Property("PlayTime")
+ .HasColumnType("datetime");
+
+ b.Property("Score")
+ .HasColumnType("INTEGER");
+
+ b.Property("ScoreRank")
+ .HasColumnType("INTEGER");
+
+ b.Property("ScoreRate")
+ .HasColumnType("INTEGER");
+
+ b.Property("Skipped")
+ .HasColumnType("INTEGER");
+
+ b.Property("SongId")
+ .HasColumnType("INTEGER");
+
+ b.Property("SongNumber")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("Id");
+
+ b.HasIndex("Baid");
+
+ b.ToTable("SongPlayData");
+ });
+
+ modelBuilder.Entity("GameDatabase.Entities.UserDatum", b =>
+ {
+ b.Property("Baid")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property("AchievementDisplayDifficulty")
+ .HasColumnType("INTEGER");
+
+ b.Property("AiWinCount")
+ .HasColumnType("INTEGER");
+
+ b.Property("ColorBody")
+ .HasColumnType("INTEGER");
+
+ b.Property("ColorFace")
+ .HasColumnType("INTEGER");
+
+ b.Property("ColorLimb")
+ .HasColumnType("INTEGER");
+
+ b.Property("CostumeData")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("CostumeFlgArray")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("DifficultyPlayedArray")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("DifficultySettingArray")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("DisplayAchievement")
+ .HasColumnType("INTEGER");
+
+ b.Property("DisplayDan")
+ .HasColumnType("INTEGER");
+
+ b.Property("FavoriteSongsArray")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("GenericInfoFlgArray")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("IsAdmin")
+ .HasColumnType("INTEGER");
+
+ b.Property("IsSkipOn")
+ .HasColumnType("INTEGER");
+
+ b.Property("IsVoiceOn")
+ .HasColumnType("INTEGER");
+
+ b.Property("LastPlayDatetime")
+ .HasColumnType("datetime");
+
+ b.Property("LastPlayMode")
+ .HasColumnType("INTEGER");
+
+ b.Property("MyDonName")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("MyDonNameLanguage")
+ .HasColumnType("INTEGER");
+
+ b.Property("NotesPosition")
+ .HasColumnType("INTEGER");
+
+ b.Property("OptionSetting")
+ .HasColumnType("INTEGER");
+
+ b.Property("SelectedToneId")
+ .HasColumnType("INTEGER");
+
+ b.Property("Title")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("TitleFlgArray")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("TitlePlateId")
+ .HasColumnType("INTEGER");
+
+ b.Property("TokenCountDict")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("ToneFlgArray")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("UnlockedSongIdList")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.HasKey("Baid");
+
+ b.ToTable("UserData");
+ });
+
+ modelBuilder.Entity("GameDatabase.Entities.AiScoreDatum", b =>
+ {
+ b.HasOne("GameDatabase.Entities.UserDatum", "Ba")
+ .WithMany()
+ .HasForeignKey("Baid")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Ba");
+ });
+
+ modelBuilder.Entity("GameDatabase.Entities.AiSectionScoreDatum", b =>
+ {
+ b.HasOne("GameDatabase.Entities.AiScoreDatum", "Parent")
+ .WithMany("AiSectionScoreData")
+ .HasForeignKey("Baid", "SongId", "Difficulty")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Parent");
+ });
+
+ modelBuilder.Entity("GameDatabase.Entities.Card", b =>
+ {
+ b.HasOne("GameDatabase.Entities.UserDatum", "Ba")
+ .WithMany()
+ .HasForeignKey("Baid")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Ba");
+ });
+
+ modelBuilder.Entity("GameDatabase.Entities.Credential", b =>
+ {
+ b.HasOne("GameDatabase.Entities.UserDatum", "Ba")
+ .WithMany()
+ .HasForeignKey("Baid")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Ba");
+ });
+
+ modelBuilder.Entity("GameDatabase.Entities.DanScoreDatum", b =>
+ {
+ b.HasOne("GameDatabase.Entities.UserDatum", "Ba")
+ .WithMany()
+ .HasForeignKey("Baid")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Ba");
+ });
+
+ modelBuilder.Entity("GameDatabase.Entities.DanStageScoreDatum", b =>
+ {
+ b.HasOne("GameDatabase.Entities.DanScoreDatum", "Parent")
+ .WithMany("DanStageScoreData")
+ .HasForeignKey("Baid", "DanId", "DanType")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Parent");
+ });
+
+ modelBuilder.Entity("GameDatabase.Entities.SongBestDatum", b =>
+ {
+ b.HasOne("GameDatabase.Entities.UserDatum", "Ba")
+ .WithMany()
+ .HasForeignKey("Baid")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Ba");
+ });
+
+ modelBuilder.Entity("GameDatabase.Entities.SongPlayDatum", b =>
+ {
+ b.HasOne("GameDatabase.Entities.UserDatum", "Ba")
+ .WithMany()
+ .HasForeignKey("Baid")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Ba");
+ });
+
+ modelBuilder.Entity("GameDatabase.Entities.AiScoreDatum", b =>
+ {
+ b.Navigation("AiSectionScoreData");
+ });
+
+ modelBuilder.Entity("GameDatabase.Entities.DanScoreDatum", b =>
+ {
+ b.Navigation("DanStageScoreData");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/GameDatabase/Migrations/20231218152045_AddIsAdminToUserDatum.cs b/GameDatabase/Migrations/20231218152045_AddIsAdminToUserDatum.cs
new file mode 100644
index 0000000..26be68b
--- /dev/null
+++ b/GameDatabase/Migrations/20231218152045_AddIsAdminToUserDatum.cs
@@ -0,0 +1,29 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace GameDatabase.Migrations
+{
+ ///
+ public partial class AddIsAdminToUserDatum : Migration
+ {
+ ///
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.AddColumn(
+ name: "IsAdmin",
+ table: "UserData",
+ type: "INTEGER",
+ nullable: false,
+ defaultValue: false);
+ }
+
+ ///
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropColumn(
+ name: "IsAdmin",
+ table: "UserData");
+ }
+ }
+}
diff --git a/GameDatabase/Migrations/TaikoDbContextModelSnapshot.cs b/GameDatabase/Migrations/TaikoDbContextModelSnapshot.cs
index 4ac180c..f0e4507 100644
--- a/GameDatabase/Migrations/TaikoDbContextModelSnapshot.cs
+++ b/GameDatabase/Migrations/TaikoDbContextModelSnapshot.cs
@@ -326,6 +326,9 @@ namespace TaikoLocalServer.Migrations
.IsRequired()
.HasColumnType("TEXT");
+ b.Property("IsAdmin")
+ .HasColumnType("INTEGER");
+
b.Property("IsSkipOn")
.HasColumnType("INTEGER");
diff --git a/SharedProject/Models/User.cs b/SharedProject/Models/User.cs
index b59026b..2dedcc4 100644
--- a/SharedProject/Models/User.cs
+++ b/SharedProject/Models/User.cs
@@ -5,4 +5,6 @@ public class User
public uint Baid { get; set; }
public List AccessCodes { get; set; } = new();
+
+ public bool IsAdmin { get; set; }
}
\ No newline at end of file
diff --git a/TaikoLocalServer/Services/CardService.cs b/TaikoLocalServer/Services/CardService.cs
index 58a17de..c9b1bcf 100644
--- a/TaikoLocalServer/Services/CardService.cs
+++ b/TaikoLocalServer/Services/CardService.cs
@@ -28,28 +28,13 @@ public class CardService : ICardService
public async Task> GetUsersFromCards()
{
var cardEntries = await context.Cards.ToListAsync();
- List users = new();
- var found = false;
- foreach (var cardEntry in cardEntries)
+ var userEntries = await context.UserData.ToListAsync();
+ var users = userEntries.Select(userEntry => new User
{
- foreach (var user in users.Where(user => user.Baid == cardEntry.Baid))
- {
- user.AccessCodes.Add(cardEntry.AccessCode);
- found = true;
- }
-
- if (!found)
- {
- var user = new User
- {
- Baid = (uint)cardEntry.Baid,
- AccessCodes = new List {cardEntry.AccessCode}
- };
- users.Add(user);
- }
-
- found = false;
- }
+ Baid = (uint)userEntry.Baid,
+ AccessCodes = cardEntries.Where(cardEntry => cardEntry.Baid == userEntry.Baid).Select(cardEntry => cardEntry.AccessCode).ToList(),
+ IsAdmin = userEntry.IsAdmin
+ }).ToList();
return users;
}
diff --git a/TaikoWebUI/Pages/Users.razor b/TaikoWebUI/Pages/Users.razor
index 9a1e59d..61bbc60 100644
--- a/TaikoWebUI/Pages/Users.razor
+++ b/TaikoWebUI/Pages/Users.razor
@@ -54,6 +54,12 @@
IconColor="@Color.Primary">
Manage Access Codes
+
+
+ Change Password
+
@if (LoginService.AllowUserDelete)
{
@@ -156,6 +162,12 @@
IconColor="@Color.Primary">
Manage Access Codes
+
+
+ Change Password
+
@if (LoginService.AllowUserDelete)
{
diff --git a/TaikoWebUI/Services/LoginService.cs b/TaikoWebUI/Services/LoginService.cs
index e2b0ff4..94bd83f 100644
--- a/TaikoWebUI/Services/LoginService.cs
+++ b/TaikoWebUI/Services/LoginService.cs
@@ -7,8 +7,6 @@ namespace TaikoWebUI.Services;
public class LoginService
{
- private readonly string adminPassword;
- private readonly string adminUsername;
public bool LoginRequired { get; }
public bool OnlyAdmin { get; }
private readonly int boundAccessCodeUpperLimit;
@@ -21,8 +19,6 @@ public class LoginService
IsLoggedIn = false;
IsAdmin = false;
var webUiSettings = settings.Value;
- adminUsername = webUiSettings.AdminUsername;
- adminPassword = webUiSettings.AdminPassword;
LoginRequired = webUiSettings.LoginRequired;
OnlyAdmin = webUiSettings.OnlyAdmin;
boundAccessCodeUpperLimit = webUiSettings.BoundAccessCodeUpperLimit;
@@ -37,24 +33,16 @@ public class LoginService
public int Login(string inputCardNum, string inputPassword, DashboardResponse response)
{
- if (inputCardNum == adminUsername && inputPassword == adminPassword)
- {
- IsLoggedIn = true;
- IsAdmin = true;
- return 1;
- }
-
- if (OnlyAdmin) return 0;
-
foreach (var user in response.Users.Where(user => user.AccessCodes.Contains(inputCardNum)))
{
foreach (var userCredential in response.UserCredentials.Where(userCredential => userCredential.Baid == user.Baid))
{
if (userCredential.Password == "") return 4;
if (ComputeHash(inputPassword, userCredential.Salt) != userCredential.Password) return 2;
+ IsAdmin = user.IsAdmin;
+ if (!IsAdmin && OnlyAdmin) return 0;
IsLoggedIn = true;
LoggedInUser = user;
- IsAdmin = false;
return 1;
}
}
diff --git a/TaikoWebUI/Settings/WebUiSettings.cs b/TaikoWebUI/Settings/WebUiSettings.cs
index 5bbf4d5..874688b 100644
--- a/TaikoWebUI/Settings/WebUiSettings.cs
+++ b/TaikoWebUI/Settings/WebUiSettings.cs
@@ -3,8 +3,6 @@
public class WebUiSettings
{
public bool LoginRequired { get; set; }
- public string AdminUsername { get; set; } = string.Empty;
- public string AdminPassword { get; set; } = string.Empty;
public bool OnlyAdmin { get; set; }
public int BoundAccessCodeUpperLimit { get; set; }
public bool RegisterWithLastPlayTime { get; set; }
diff --git a/TaikoWebUI/wwwroot/appsettings.json b/TaikoWebUI/wwwroot/appsettings.json
index a84a7b7..5c6140f 100644
--- a/TaikoWebUI/wwwroot/appsettings.json
+++ b/TaikoWebUI/wwwroot/appsettings.json
@@ -1,8 +1,6 @@
{
"WebUiSettings": {
"LoginRequired": "false",
- "AdminUserName": "admin",
- "AdminPassword": "admin",
"OnlyAdmin": "false",
"BoundAccessCodeUpperLimit": "3",
"RegisterWithLastPlayTime": "false",