diff --git a/GameDatabase/Context/TaikoDbContext.cs b/GameDatabase/Context/TaikoDbContext.cs index 41badab..79018e6 100644 --- a/GameDatabase/Context/TaikoDbContext.cs +++ b/GameDatabase/Context/TaikoDbContext.cs @@ -22,6 +22,8 @@ namespace GameDatabase.Context } public virtual DbSet Cards { get; set; } = null!; + + public virtual DbSet Credentials { get; set; } = null!; public virtual DbSet SongBestData { get; set; } = null!; public virtual DbSet SongPlayData { get; set; } = null!; public virtual DbSet UserData { get; set; } = null!; @@ -48,9 +50,19 @@ namespace GameDatabase.Context entity.HasKey(e => e.AccessCode); entity.ToTable("Card"); + }); + + modelBuilder.Entity(entity => + { + entity.HasKey(e => e.Baid); - entity.HasIndex(e => e.Baid, "IX_Card_Baid") - .IsUnique(); + entity.ToTable("Credential"); + + entity.HasOne(d => d.Ba) + .WithMany() + .HasPrincipalKey(p => p.Baid) + .HasForeignKey(d => d.Baid) + .OnDelete(DeleteBehavior.Cascade); }); modelBuilder.Entity(entity => diff --git a/GameDatabase/Entities/Card.cs b/GameDatabase/Entities/Card.cs index a3fac1b..a403fae 100644 --- a/GameDatabase/Entities/Card.cs +++ b/GameDatabase/Entities/Card.cs @@ -4,7 +4,5 @@ { public string AccessCode { get; set; } = null!; public ulong Baid { get; set; } - public string Password { get; set; } = null!; - public string Salt { get; set; } = null!; } } \ No newline at end of file diff --git a/GameDatabase/Entities/Credential.cs b/GameDatabase/Entities/Credential.cs new file mode 100644 index 0000000..e4667df --- /dev/null +++ b/GameDatabase/Entities/Credential.cs @@ -0,0 +1,11 @@ +namespace GameDatabase.Entities +{ + public partial class Credential + { + public ulong Baid { get; set; } + public string Password { get; set; } = null!; + public string Salt { get; set; } = null!; + + public virtual Card? Ba { get; set; } + } +} \ No newline at end of file diff --git a/GameDatabase/Migrations/20231111154748_AddCredentialTable.Designer.cs b/GameDatabase/Migrations/20231111154748_AddCredentialTable.Designer.cs new file mode 100644 index 0000000..fccf355 --- /dev/null +++ b/GameDatabase/Migrations/20231111154748_AddCredentialTable.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("20231111154748_AddCredentialTable")] + partial class AddCredentialTable + { + /// + 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.Property("Password") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Salt") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("AccessCode"); + + b.HasIndex(new[] { "Baid" }, "IX_Card_Baid") + .IsUnique(); + + b.ToTable("Card", (string)null); + }); + + modelBuilder.Entity("GameDatabase.Entities.Credential", b => + { + b.Property("Baid") + .ValueGeneratedOnAdd() + .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") + .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("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.Card", "Ba") + .WithMany() + .HasForeignKey("Baid") + .HasPrincipalKey("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.DanScoreDatum", b => + { + b.HasOne("GameDatabase.Entities.Card", "Ba") + .WithMany() + .HasForeignKey("Baid") + .HasPrincipalKey("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.Card", "Ba") + .WithMany() + .HasForeignKey("Baid") + .HasPrincipalKey("Baid") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Ba"); + }); + + modelBuilder.Entity("GameDatabase.Entities.SongPlayDatum", b => + { + b.HasOne("GameDatabase.Entities.Card", "Ba") + .WithMany() + .HasForeignKey("Baid") + .HasPrincipalKey("Baid") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Ba"); + }); + + modelBuilder.Entity("GameDatabase.Entities.UserDatum", b => + { + b.HasOne("GameDatabase.Entities.Card", "Ba") + .WithMany() + .HasForeignKey("Baid") + .HasPrincipalKey("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/20231111154748_AddCredentialTable.cs b/GameDatabase/Migrations/20231111154748_AddCredentialTable.cs new file mode 100644 index 0000000..9097d2b --- /dev/null +++ b/GameDatabase/Migrations/20231111154748_AddCredentialTable.cs @@ -0,0 +1,35 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace GameDatabase.Migrations +{ + /// + public partial class AddCredentialTable : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Credential", + columns: table => new + { + Baid = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Password = table.Column(type: "TEXT", nullable: false), + Salt = table.Column(type: "TEXT", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Credential", x => x.Baid); + }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Credential"); + } + } +} diff --git a/GameDatabase/Migrations/20231111155016_CopyPasswordSaltFromCardToCredential.Designer.cs b/GameDatabase/Migrations/20231111155016_CopyPasswordSaltFromCardToCredential.Designer.cs new file mode 100644 index 0000000..bcf44a2 --- /dev/null +++ b/GameDatabase/Migrations/20231111155016_CopyPasswordSaltFromCardToCredential.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("20231111155016_CopyPasswordSaltFromCardToCredential")] + partial class CopyPasswordSaltFromCardToCredential + { + /// + 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.Property("Password") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Salt") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("AccessCode"); + + b.HasIndex(new[] { "Baid" }, "IX_Card_Baid") + .IsUnique(); + + b.ToTable("Card", (string)null); + }); + + modelBuilder.Entity("GameDatabase.Entities.Credential", b => + { + b.Property("Baid") + .ValueGeneratedOnAdd() + .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") + .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("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.Card", "Ba") + .WithMany() + .HasForeignKey("Baid") + .HasPrincipalKey("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.DanScoreDatum", b => + { + b.HasOne("GameDatabase.Entities.Card", "Ba") + .WithMany() + .HasForeignKey("Baid") + .HasPrincipalKey("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.Card", "Ba") + .WithMany() + .HasForeignKey("Baid") + .HasPrincipalKey("Baid") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Ba"); + }); + + modelBuilder.Entity("GameDatabase.Entities.SongPlayDatum", b => + { + b.HasOne("GameDatabase.Entities.Card", "Ba") + .WithMany() + .HasForeignKey("Baid") + .HasPrincipalKey("Baid") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Ba"); + }); + + modelBuilder.Entity("GameDatabase.Entities.UserDatum", b => + { + b.HasOne("GameDatabase.Entities.Card", "Ba") + .WithMany() + .HasForeignKey("Baid") + .HasPrincipalKey("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/20231111155016_CopyPasswordSaltFromCardToCredential.cs b/GameDatabase/Migrations/20231111155016_CopyPasswordSaltFromCardToCredential.cs new file mode 100644 index 0000000..5562e37 --- /dev/null +++ b/GameDatabase/Migrations/20231111155016_CopyPasswordSaltFromCardToCredential.cs @@ -0,0 +1,30 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace GameDatabase.Migrations +{ + /// + public partial class CopyPasswordSaltFromCardToCredential : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.Sql(@" + INSERT INTO Credential (Baid, Password, Salt) + SELECT Baid, Password, Salt + FROM Card + "); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.Sql(@" + UPDATE Card + SET Password = (SELECT Password FROM Credential WHERE Credential.Baid = Card.Baid), + Salt = (SELECT Salt FROM Credential WHERE Credential.Baid = Card.Baid) + "); + } + } +} diff --git a/GameDatabase/Migrations/20231111155305_RemovePasswordSaltFromCard.Designer.cs b/GameDatabase/Migrations/20231111155305_RemovePasswordSaltFromCard.Designer.cs new file mode 100644 index 0000000..0b88493 --- /dev/null +++ b/GameDatabase/Migrations/20231111155305_RemovePasswordSaltFromCard.Designer.cs @@ -0,0 +1,483 @@ +// +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("20231111155305_RemovePasswordSaltFromCard")] + partial class RemovePasswordSaltFromCard + { + /// + 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(new[] { "Baid" }, "IX_Card_Baid") + .IsUnique(); + + b.ToTable("Card", (string)null); + }); + + modelBuilder.Entity("GameDatabase.Entities.Credential", b => + { + b.Property("Baid") + .ValueGeneratedOnAdd() + .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") + .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("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.Card", "Ba") + .WithMany() + .HasForeignKey("Baid") + .HasPrincipalKey("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.DanScoreDatum", b => + { + b.HasOne("GameDatabase.Entities.Card", "Ba") + .WithMany() + .HasForeignKey("Baid") + .HasPrincipalKey("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.Card", "Ba") + .WithMany() + .HasForeignKey("Baid") + .HasPrincipalKey("Baid") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Ba"); + }); + + modelBuilder.Entity("GameDatabase.Entities.SongPlayDatum", b => + { + b.HasOne("GameDatabase.Entities.Card", "Ba") + .WithMany() + .HasForeignKey("Baid") + .HasPrincipalKey("Baid") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Ba"); + }); + + modelBuilder.Entity("GameDatabase.Entities.UserDatum", b => + { + b.HasOne("GameDatabase.Entities.Card", "Ba") + .WithMany() + .HasForeignKey("Baid") + .HasPrincipalKey("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/20231111155305_RemovePasswordSaltFromCard.cs b/GameDatabase/Migrations/20231111155305_RemovePasswordSaltFromCard.cs new file mode 100644 index 0000000..ac50f0e --- /dev/null +++ b/GameDatabase/Migrations/20231111155305_RemovePasswordSaltFromCard.cs @@ -0,0 +1,40 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace GameDatabase.Migrations +{ + /// + public partial class RemovePasswordSaltFromCard : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Password", + table: "Card"); + + migrationBuilder.DropColumn( + name: "Salt", + table: "Card"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Password", + table: "Card", + type: "TEXT", + nullable: false, + defaultValue: ""); + + migrationBuilder.AddColumn( + name: "Salt", + table: "Card", + type: "TEXT", + nullable: false, + defaultValue: ""); + } + } +} diff --git a/GameDatabase/Migrations/20231111164910_RemoveBaidUniquenessFromCard.Designer.cs b/GameDatabase/Migrations/20231111164910_RemoveBaidUniquenessFromCard.Designer.cs new file mode 100644 index 0000000..117f5ae --- /dev/null +++ b/GameDatabase/Migrations/20231111164910_RemoveBaidUniquenessFromCard.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("20231111164910_RemoveBaidUniquenessFromCard")] + partial class RemoveBaidUniquenessFromCard + { + /// + 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.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") + .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("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.Card", "Ba") + .WithMany() + .HasForeignKey("Baid") + .HasPrincipalKey("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.Credential", b => + { + b.HasOne("GameDatabase.Entities.Card", "Ba") + .WithMany() + .HasForeignKey("Baid") + .HasPrincipalKey("Baid") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Ba"); + }); + + modelBuilder.Entity("GameDatabase.Entities.DanScoreDatum", b => + { + b.HasOne("GameDatabase.Entities.Card", "Ba") + .WithMany() + .HasForeignKey("Baid") + .HasPrincipalKey("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.Card", "Ba") + .WithMany() + .HasForeignKey("Baid") + .HasPrincipalKey("Baid") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Ba"); + }); + + modelBuilder.Entity("GameDatabase.Entities.SongPlayDatum", b => + { + b.HasOne("GameDatabase.Entities.Card", "Ba") + .WithMany() + .HasForeignKey("Baid") + .HasPrincipalKey("Baid") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Ba"); + }); + + modelBuilder.Entity("GameDatabase.Entities.UserDatum", b => + { + b.HasOne("GameDatabase.Entities.Card", "Ba") + .WithMany() + .HasForeignKey("Baid") + .HasPrincipalKey("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/20231111164910_RemoveBaidUniquenessFromCard.cs b/GameDatabase/Migrations/20231111164910_RemoveBaidUniquenessFromCard.cs new file mode 100644 index 0000000..0c048ce --- /dev/null +++ b/GameDatabase/Migrations/20231111164910_RemoveBaidUniquenessFromCard.cs @@ -0,0 +1,58 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace GameDatabase.Migrations +{ + /// + public partial class RemoveBaidUniquenessFromCard : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_Card_Baid", + table: "Card"); + + migrationBuilder.AlterColumn( + name: "Baid", + table: "Credential", + type: "INTEGER", + nullable: false, + oldClrType: typeof(ulong), + oldType: "INTEGER") + .OldAnnotation("Sqlite:Autoincrement", true); + + migrationBuilder.AddForeignKey( + name: "FK_Credential_Card_Baid", + table: "Credential", + column: "Baid", + principalTable: "Card", + principalColumn: "Baid", + onDelete: ReferentialAction.Cascade); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_Credential_Card_Baid", + table: "Credential"); + + migrationBuilder.AlterColumn( + name: "Baid", + table: "Credential", + type: "INTEGER", + nullable: false, + oldClrType: typeof(ulong), + oldType: "INTEGER") + .Annotation("Sqlite:Autoincrement", true); + + migrationBuilder.CreateIndex( + name: "IX_Card_Baid", + table: "Card", + column: "Baid", + unique: true); + } + } +} diff --git a/GameDatabase/Migrations/TaikoDbContextModelSnapshot.cs b/GameDatabase/Migrations/TaikoDbContextModelSnapshot.cs index 09e94da..04a4b68 100644 --- a/GameDatabase/Migrations/TaikoDbContextModelSnapshot.cs +++ b/GameDatabase/Migrations/TaikoDbContextModelSnapshot.cs @@ -15,7 +15,7 @@ namespace TaikoLocalServer.Migrations protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "8.0.0-rc.1.23419.6"); + modelBuilder.HasAnnotation("ProductVersion", "8.0.0-rc.2.23480.1"); modelBuilder.Entity("GameDatabase.Entities.AiScoreDatum", b => { @@ -84,6 +84,16 @@ namespace TaikoLocalServer.Migrations b.Property("Baid") .HasColumnType("INTEGER"); + b.HasKey("AccessCode"); + + b.ToTable("Card", (string)null); + }); + + modelBuilder.Entity("GameDatabase.Entities.Credential", b => + { + b.Property("Baid") + .HasColumnType("INTEGER"); + b.Property("Password") .IsRequired() .HasColumnType("TEXT"); @@ -92,12 +102,9 @@ namespace TaikoLocalServer.Migrations .IsRequired() .HasColumnType("TEXT"); - b.HasKey("AccessCode"); + b.HasKey("Baid"); - b.HasIndex(new[] { "Baid" }, "IX_Card_Baid") - .IsUnique(); - - b.ToTable("Card", (string)null); + b.ToTable("Credential", (string)null); }); modelBuilder.Entity("GameDatabase.Entities.DanScoreDatum", b => @@ -109,6 +116,7 @@ namespace TaikoLocalServer.Migrations .HasColumnType("INTEGER"); b.Property("DanType") + .ValueGeneratedOnAdd() .HasColumnType("INTEGER") .HasDefaultValue(1); @@ -140,6 +148,7 @@ namespace TaikoLocalServer.Migrations .HasColumnType("INTEGER"); b.Property("DanType") + .ValueGeneratedOnAdd() .HasColumnType("INTEGER") .HasDefaultValue(1); @@ -393,6 +402,18 @@ namespace TaikoLocalServer.Migrations b.Navigation("Parent"); }); + modelBuilder.Entity("GameDatabase.Entities.Credential", b => + { + b.HasOne("GameDatabase.Entities.Card", "Ba") + .WithMany() + .HasForeignKey("Baid") + .HasPrincipalKey("Baid") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Ba"); + }); + modelBuilder.Entity("GameDatabase.Entities.DanScoreDatum", b => { b.HasOne("GameDatabase.Entities.Card", "Ba") diff --git a/SharedProject/Models/Requests/SetPasswordRequest.cs b/SharedProject/Models/Requests/SetPasswordRequest.cs index c13c441..a838192 100644 --- a/SharedProject/Models/Requests/SetPasswordRequest.cs +++ b/SharedProject/Models/Requests/SetPasswordRequest.cs @@ -2,7 +2,7 @@ public class SetPasswordRequest { - public string AccessCode { get; set; } = default!; + public uint Baid { get; set; } public string Password { get; set; } = default!; public string Salt { get; set; } = default!; } \ No newline at end of file diff --git a/SharedProject/Models/Responses/DashboardResponse.cs b/SharedProject/Models/Responses/DashboardResponse.cs index 4cd1df3..7bed34b 100644 --- a/SharedProject/Models/Responses/DashboardResponse.cs +++ b/SharedProject/Models/Responses/DashboardResponse.cs @@ -3,4 +3,6 @@ public class DashboardResponse { public List Users { get; set; } = new(); + + public List UserCredentials { get; set; } = new(); } \ No newline at end of file diff --git a/SharedProject/Models/User.cs b/SharedProject/Models/User.cs index 8336e75..663e969 100644 --- a/SharedProject/Models/User.cs +++ b/SharedProject/Models/User.cs @@ -5,8 +5,4 @@ public class User public string AccessCode { get; set; } = string.Empty; public uint Baid { get; set; } - - public string Password { get; set; } = string.Empty; - - public string Salt { get; set; } = string.Empty; } \ No newline at end of file diff --git a/SharedProject/Models/UserCredential.cs b/SharedProject/Models/UserCredential.cs new file mode 100644 index 0000000..ab19f2a --- /dev/null +++ b/SharedProject/Models/UserCredential.cs @@ -0,0 +1,10 @@ +namespace SharedProject.Models; + +public class UserCredential +{ + public uint Baid { get; set; } + + public string Password { get; set; } = string.Empty; + + public string Salt { get; set; } = string.Empty; +} \ No newline at end of file diff --git a/TaikoLocalServer/Controllers/Api/CardsController.cs b/TaikoLocalServer/Controllers/Api/CardsController.cs index 97767e7..81788c2 100644 --- a/TaikoLocalServer/Controllers/Api/CardsController.cs +++ b/TaikoLocalServer/Controllers/Api/CardsController.cs @@ -20,14 +20,4 @@ public class CardsController : BaseController return result ? NoContent() : NotFound(); } - - [HttpPost] - public async Task UpdatePassword(SetPasswordRequest request) - { - var accessCode = request.AccessCode; - var password = request.Password; - var salt = request.Salt; - var result = await cardService.UpdatePassword(accessCode, password, salt); - return result ? NoContent() : NotFound(); - } } \ No newline at end of file diff --git a/TaikoLocalServer/Controllers/Api/CredentialsController.cs b/TaikoLocalServer/Controllers/Api/CredentialsController.cs new file mode 100644 index 0000000..b6ce9c8 --- /dev/null +++ b/TaikoLocalServer/Controllers/Api/CredentialsController.cs @@ -0,0 +1,33 @@ +using SharedProject.Models.Requests; + +namespace TaikoLocalServer.Controllers.Api; + +[ApiController] +[Route("api/[controller]")] +public class CredentialsController : BaseController +{ + private readonly ICredentialService credentialService; + + public CredentialsController(ICredentialService credentialService) + { + this.credentialService = credentialService; + } + + [HttpDelete("{baid}")] + public async Task DeleteUser(uint baid) + { + var result = await credentialService.DeleteCredential(baid); + + return result ? NoContent() : NotFound(); + } + + [HttpPost] + public async Task UpdatePassword(SetPasswordRequest request) + { + var baid = request.Baid; + var password = request.Password; + var salt = request.Salt; + var result = await credentialService.UpdatePassword(baid, password, salt); + return result ? NoContent() : NotFound(); + } +} \ No newline at end of file diff --git a/TaikoLocalServer/Controllers/Api/DashboardController.cs b/TaikoLocalServer/Controllers/Api/DashboardController.cs index be07c28..4f04456 100644 --- a/TaikoLocalServer/Controllers/Api/DashboardController.cs +++ b/TaikoLocalServer/Controllers/Api/DashboardController.cs @@ -7,19 +7,23 @@ namespace TaikoLocalServer.Controllers.Api; public class DashboardController : BaseController { private readonly ICardService cardService; + private readonly ICredentialService credentialService; - public DashboardController(ICardService cardService) + public DashboardController(ICardService cardService, ICredentialService credentialService) { this.cardService = cardService; + this.credentialService = credentialService; } [HttpGet] public async Task GetDashboard() { var users = await cardService.GetUsersFromCards(); + var credentials = await credentialService.GetUserCredentialsFromCredentials(); return new DashboardResponse { - Users = users + Users = users, + UserCredentials = credentials }; } diff --git a/TaikoLocalServer/Controllers/Game/MyDonEntryController.cs b/TaikoLocalServer/Controllers/Game/MyDonEntryController.cs index 5a78d5e..b36e4a1 100644 --- a/TaikoLocalServer/Controllers/Game/MyDonEntryController.cs +++ b/TaikoLocalServer/Controllers/Game/MyDonEntryController.cs @@ -9,11 +9,14 @@ public class MyDonEntryController : BaseController private readonly IUserDatumService userDatumService; private readonly ICardService cardService; + + private readonly ICredentialService credentialService; - public MyDonEntryController(IUserDatumService userDatumService, ICardService cardService) + public MyDonEntryController(IUserDatumService userDatumService, ICardService cardService, ICredentialService credentialService) { this.userDatumService = userDatumService; this.cardService = cardService; + this.credentialService = credentialService; } [HttpPost] @@ -26,6 +29,11 @@ public class MyDonEntryController : BaseController await cardService.AddCard(new Card { AccessCode = request.WechatQrStr, + Baid = newId + }); + + await credentialService.AddCredential(new Credential + { Baid = newId, Password = "", Salt = "" diff --git a/TaikoLocalServer/Services/CardService.cs b/TaikoLocalServer/Services/CardService.cs index 2d3dd30..cfb4426 100644 --- a/TaikoLocalServer/Services/CardService.cs +++ b/TaikoLocalServer/Services/CardService.cs @@ -49,17 +49,4 @@ public class CardService : ICardService return true; } - - public async Task UpdatePassword(string accessCode, string password, string salt) - { - var card = await context.Cards.FindAsync(accessCode); - - if (card is null) return false; - - card.Password = password; - card.Salt = salt; - await context.SaveChangesAsync(); - - return true; - } } \ No newline at end of file diff --git a/TaikoLocalServer/Services/CredentialService.cs b/TaikoLocalServer/Services/CredentialService.cs new file mode 100644 index 0000000..b513ca9 --- /dev/null +++ b/TaikoLocalServer/Services/CredentialService.cs @@ -0,0 +1,52 @@ +using GameDatabase.Context; +using GameDatabase.Entities; +using SharedProject.Models; +using Swan.Mapping; + +namespace TaikoLocalServer.Services; + +public class CredentialService : ICredentialService +{ + private readonly TaikoDbContext context; + + public CredentialService(TaikoDbContext context) + { + this.context = context; + } + + public async Task> GetUserCredentialsFromCredentials() + { + return await context.Credentials.Select(credential => credential.CopyPropertiesToNew(null)).ToListAsync(); + } + + public async Task AddCredential(Credential credential) + { + context.Add(credential); + await context.SaveChangesAsync(); + } + + public async Task DeleteCredential(uint baid) + { + var credential = await context.Credentials.FindAsync((ulong)baid); + + if (credential is null) return false; + + context.Credentials.Remove(credential); + await context.SaveChangesAsync(); + + return true; + } + + public async Task UpdatePassword(uint baid, string password, string salt) + { + var credential = await context.Credentials.FindAsync((ulong)baid); + + if (credential is null) return false; + + credential.Password = password; + credential.Salt = salt; + await context.SaveChangesAsync(); + + return true; + } +} \ No newline at end of file diff --git a/TaikoLocalServer/Services/Extentions/ServiceExtensions.cs b/TaikoLocalServer/Services/Extentions/ServiceExtensions.cs index bd9642b..09d459f 100644 --- a/TaikoLocalServer/Services/Extentions/ServiceExtensions.cs +++ b/TaikoLocalServer/Services/Extentions/ServiceExtensions.cs @@ -5,6 +5,7 @@ public static class ServiceExtensions public static IServiceCollection AddTaikoDbServices(this IServiceCollection services) { services.AddScoped(); + services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); diff --git a/TaikoLocalServer/Services/Interfaces/ICardService.cs b/TaikoLocalServer/Services/Interfaces/ICardService.cs index 3f215f8..4217027 100644 --- a/TaikoLocalServer/Services/Interfaces/ICardService.cs +++ b/TaikoLocalServer/Services/Interfaces/ICardService.cs @@ -14,6 +14,4 @@ public interface ICardService public Task AddCard(Card card); public Task DeleteCard(string accessCode); - - public Task UpdatePassword(string accessCode, string password, string salt); } \ No newline at end of file diff --git a/TaikoLocalServer/Services/Interfaces/ICredentialService.cs b/TaikoLocalServer/Services/Interfaces/ICredentialService.cs new file mode 100644 index 0000000..6995b3f --- /dev/null +++ b/TaikoLocalServer/Services/Interfaces/ICredentialService.cs @@ -0,0 +1,15 @@ +using GameDatabase.Entities; +using SharedProject.Models; + +namespace TaikoLocalServer.Services.Interfaces; + +public interface ICredentialService +{ + public Task> GetUserCredentialsFromCredentials(); + + public Task AddCredential(Credential credential); + + public Task DeleteCredential(uint baid); + + public Task UpdatePassword(uint baid, string password, string salt); +} \ No newline at end of file diff --git a/TaikoWebUI/Pages/ChangePassword.razor b/TaikoWebUI/Pages/ChangePassword.razor index 791bc33..3c5a1e5 100644 --- a/TaikoWebUI/Pages/ChangePassword.razor +++ b/TaikoWebUI/Pages/ChangePassword.razor @@ -3,9 +3,9 @@ @inject LoginService LoginService @inject NavigationManager NavigationManager -@page "/Cards/ChangePassword" +@page "/Users/ChangePassword" -

Cards

+

Users

@if (LoginService.OnlyAdmin || !LoginService.LoginRequired) { diff --git a/TaikoWebUI/Pages/ChangePassword.razor.cs b/TaikoWebUI/Pages/ChangePassword.razor.cs index a1aa606..9cde9a3 100644 --- a/TaikoWebUI/Pages/ChangePassword.razor.cs +++ b/TaikoWebUI/Pages/ChangePassword.razor.cs @@ -29,14 +29,14 @@ public partial class ChangePassword "Error", "Only admin can log in.", "Ok"); - NavigationManager.NavigateTo("/Cards"); + NavigationManager.NavigateTo("/Users"); break; case 1: await DialogService.ShowMessageBox( "Success", "Password changed successfully.", "Ok"); - NavigationManager.NavigateTo("/Cards"); + NavigationManager.NavigateTo("/Users"); break; case 2: await DialogService.ShowMessageBox( diff --git a/TaikoWebUI/Pages/DaniDojo.razor b/TaikoWebUI/Pages/DaniDojo.razor index 4676bb7..5814e4c 100644 --- a/TaikoWebUI/Pages/DaniDojo.razor +++ b/TaikoWebUI/Pages/DaniDojo.razor @@ -2,7 +2,7 @@ @inject HttpClient Client @inject LoginService LoginService -@page "/Cards/{baid:int}/DaniDojo" +@page "/Users/{baid:int}/DaniDojo" @@ -20,7 +20,7 @@ else { - Please log in by clicking on "cards" tab first. + Please log in by clicking on "Users" tab first. } diff --git a/TaikoWebUI/Pages/DaniDojo.razor.cs b/TaikoWebUI/Pages/DaniDojo.razor.cs index 12a1ee2..8c14f4e 100644 --- a/TaikoWebUI/Pages/DaniDojo.razor.cs +++ b/TaikoWebUI/Pages/DaniDojo.razor.cs @@ -11,7 +11,7 @@ public partial class DaniDojo private readonly List breadcrumbs = new() { - new BreadcrumbItem("Cards", href: "/Cards"), + new BreadcrumbItem("Users", href: "/Users"), }; protected override async Task OnInitializedAsync() @@ -24,7 +24,7 @@ public partial class DaniDojo bestDataMap = response.DanBestDataList.ToDictionary(data => data.DanId); breadcrumbs.Add(new BreadcrumbItem($"Card: {Baid}", href: null, disabled: true)); - breadcrumbs.Add(new BreadcrumbItem("Dani Dojo", href: $"/Cards/{Baid}/DaniDojo", disabled: false)); + breadcrumbs.Add(new BreadcrumbItem("Dani Dojo", href: $"/Users/{Baid}/DaniDojo", disabled: false)); } private static string GetDanClearStateString(DanClearState danClearState) diff --git a/TaikoWebUI/Pages/Dialogs/CardDeleteConfirmDialog.razor.cs b/TaikoWebUI/Pages/Dialogs/CardDeleteConfirmDialog.razor.cs deleted file mode 100644 index f34ed76..0000000 --- a/TaikoWebUI/Pages/Dialogs/CardDeleteConfirmDialog.razor.cs +++ /dev/null @@ -1,28 +0,0 @@ -namespace TaikoWebUI.Pages.Dialogs; - -public partial class CardDeleteConfirmDialog -{ - - [CascadingParameter] - MudDialogInstance MudDialog { get; set; } = null!; - - [Parameter] - public User User { get; set; } = new(); - - private void Cancel() => MudDialog.Cancel(); - - private async Task DeleteCard() - { - var responseMessage = await Client.DeleteAsync($"api/Cards/{User.AccessCode}"); - - if (!responseMessage.IsSuccessStatusCode) - { - Snackbar.Add("Something went wrong when deleting card!", Severity.Error); - MudDialog.Close(DialogResult.Ok(false)); - return; - } - - Snackbar.Add("Delete success!", Severity.Success); - MudDialog.Close(DialogResult.Ok(true)); - } -} \ No newline at end of file diff --git a/TaikoWebUI/Pages/Dialogs/CardDeleteConfirmDialog.razor b/TaikoWebUI/Pages/Dialogs/UserDeleteConfirmDialog.razor similarity index 62% rename from TaikoWebUI/Pages/Dialogs/CardDeleteConfirmDialog.razor rename to TaikoWebUI/Pages/Dialogs/UserDeleteConfirmDialog.razor index 95c5c29..042a818 100644 --- a/TaikoWebUI/Pages/Dialogs/CardDeleteConfirmDialog.razor +++ b/TaikoWebUI/Pages/Dialogs/UserDeleteConfirmDialog.razor @@ -5,19 +5,19 @@ - Delete card? + Delete user? - Do you really want to delete the card? - All the related data will also be deleted and this process cannot be undone! + Do you really want to delete this user's data? + All the related data will be deleted and this process cannot be undone! Cancel - - Delete Card + + Delete User \ No newline at end of file diff --git a/TaikoWebUI/Pages/Dialogs/UserDeleteConfirmDialog.razor.cs b/TaikoWebUI/Pages/Dialogs/UserDeleteConfirmDialog.razor.cs new file mode 100644 index 0000000..86c888f --- /dev/null +++ b/TaikoWebUI/Pages/Dialogs/UserDeleteConfirmDialog.razor.cs @@ -0,0 +1,37 @@ +namespace TaikoWebUI.Pages.Dialogs; + +public partial class UserDeleteConfirmDialog +{ + + [CascadingParameter] + MudDialogInstance MudDialog { get; set; } = null!; + + [Parameter] + public User User { get; set; } = new(); + + private void Cancel() => MudDialog.Cancel(); + + private async Task DeleteUser() + { + var credentialResponseMessage = await Client.DeleteAsync($"api/Credentials/{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.AccessCode}"); + + if (!cardResponseMessage.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)); + } +} \ No newline at end of file diff --git a/TaikoWebUI/Pages/HighScores.razor b/TaikoWebUI/Pages/HighScores.razor index c67df3a..ec7cc6b 100644 --- a/TaikoWebUI/Pages/HighScores.razor +++ b/TaikoWebUI/Pages/HighScores.razor @@ -2,7 +2,7 @@ @inject HttpClient Client @inject LoginService LoginService -@page "/Cards/{baid:int}/HighScores" +@page "/Users/{baid:int}/HighScores" @@ -31,7 +31,7 @@ else { - Please log in by clicking on "cards" tab first. + Please log in by clicking on "Users" tab first. } diff --git a/TaikoWebUI/Pages/HighScores.razor.cs b/TaikoWebUI/Pages/HighScores.razor.cs index 821d441..5d10f83 100644 --- a/TaikoWebUI/Pages/HighScores.razor.cs +++ b/TaikoWebUI/Pages/HighScores.razor.cs @@ -16,7 +16,7 @@ public partial class HighScores private readonly List breadcrumbs = new() { - new BreadcrumbItem("Cards", href: "/Cards"), + new BreadcrumbItem("Users", href: "/Users"), }; protected override async Task OnInitializedAsync() @@ -44,7 +44,7 @@ public partial class HighScores breadcrumbs.Add(new BreadcrumbItem($"Card: {Baid}", href: null, disabled: true)); - breadcrumbs.Add(new BreadcrumbItem("High Scores", href: $"/Cards/{Baid}/HighScores", disabled: false)); + breadcrumbs.Add(new BreadcrumbItem("High Scores", href: $"/Users/{Baid}/HighScores", disabled: false)); } private async Task OnFavoriteToggled(SongBestData data) diff --git a/TaikoWebUI/Pages/Profile.razor b/TaikoWebUI/Pages/Profile.razor index 7c251e9..b389eb7 100644 --- a/TaikoWebUI/Pages/Profile.razor +++ b/TaikoWebUI/Pages/Profile.razor @@ -1,4 +1,4 @@ -@page "/Cards/{baid:int}/Profile" +@page "/Users/{baid:int}/Profile" @inject HttpClient Client @inject IGameDataService GameDataService @inject IDialogService DialogService @@ -24,7 +24,7 @@ else { - Please log in by clicking on "cards" tab first. + Please log in by clicking on "Users" tab first. } diff --git a/TaikoWebUI/Pages/Profile.razor.cs b/TaikoWebUI/Pages/Profile.razor.cs index 1d3bb07..41696a7 100644 --- a/TaikoWebUI/Pages/Profile.razor.cs +++ b/TaikoWebUI/Pages/Profile.razor.cs @@ -166,7 +166,7 @@ public partial class Profile private readonly List breadcrumbs = new() { - new BreadcrumbItem("Cards", href: "/Cards"), + new BreadcrumbItem("Users", href: "/Users"), }; private List costumeFlagArraySizes = new(); @@ -178,7 +178,7 @@ public partial class Profile response = await Client.GetFromJsonAsync($"api/UserSettings/{Baid}"); breadcrumbs.Add(new BreadcrumbItem($"Card: {Baid}", href: null, disabled: true)); - breadcrumbs.Add(new BreadcrumbItem("Profile", href: $"/Cards/{Baid}/Profile", disabled: false)); + breadcrumbs.Add(new BreadcrumbItem("Profile", href: $"/Users/{Baid}/Profile", disabled: false)); costumeFlagArraySizes = GameDataService.GetCostumeFlagArraySizes(); } diff --git a/TaikoWebUI/Pages/Register.razor b/TaikoWebUI/Pages/Register.razor index 7c7d6ea..098e6de 100644 --- a/TaikoWebUI/Pages/Register.razor +++ b/TaikoWebUI/Pages/Register.razor @@ -3,9 +3,9 @@ @inject LoginService LoginService @inject NavigationManager NavigationManager -@page "/Cards/Register" +@page "/Users/Register" -

Cards

+

Users

@if (LoginService.OnlyAdmin || !LoginService.LoginRequired) { diff --git a/TaikoWebUI/Pages/Register.razor.cs b/TaikoWebUI/Pages/Register.razor.cs index 17ed09b..641fc30 100644 --- a/TaikoWebUI/Pages/Register.razor.cs +++ b/TaikoWebUI/Pages/Register.razor.cs @@ -27,14 +27,14 @@ public partial class Register "Error", "Only admin can log in.", "Ok"); - NavigationManager.NavigateTo("/Cards"); + NavigationManager.NavigateTo("/Users"); break; case 1: await DialogService.ShowMessageBox( "Success", "Card registered successfully.", "Ok"); - NavigationManager.NavigateTo("/Cards"); + NavigationManager.NavigateTo("/Users"); break; case 2: await DialogService.ShowMessageBox( @@ -55,7 +55,7 @@ public partial class Register (MarkupString) "Card is already registered, please use set password to login.", "Ok"); - NavigationManager.NavigateTo("/Cards"); + NavigationManager.NavigateTo("/Users"); break; } } diff --git a/TaikoWebUI/Pages/Cards.razor b/TaikoWebUI/Pages/Users.razor similarity index 94% rename from TaikoWebUI/Pages/Cards.razor rename to TaikoWebUI/Pages/Users.razor index 9f9b6e9..1a938b9 100644 --- a/TaikoWebUI/Pages/Cards.razor +++ b/TaikoWebUI/Pages/Users.razor @@ -3,9 +3,9 @@ @inject LoginService LoginService @inject NavigationManager NavigationManager -@page "/Cards" +@page "/Users" -

Cards

+

Users

@if (response is null) { @@ -50,9 +50,9 @@ - Delete Card + Delete User @@ -63,7 +63,7 @@ - Edit Profile @@ -77,8 +77,8 @@ FullWidth="true" AnchorOrigin="Origin.BottomCenter" TransformOrigin="Origin.TopCenter"> - High Scores - Dani Dojo + High Scores + Dani Dojo @@ -109,7 +109,7 @@ Login @if (!LoginService.OnlyAdmin) { - Register + Register } @@ -138,9 +138,9 @@ - Delete Card + Delete User @@ -151,7 +151,7 @@ - Edit Profile @@ -165,8 +165,8 @@ FullWidth="true" AnchorOrigin="Origin.BottomCenter" TransformOrigin="Origin.TopCenter"> - High Scores - Dani Dojo + High Scores + Dani Dojo diff --git a/TaikoWebUI/Pages/Cards.razor.cs b/TaikoWebUI/Pages/Users.razor.cs similarity index 89% rename from TaikoWebUI/Pages/Cards.razor.cs rename to TaikoWebUI/Pages/Users.razor.cs index 8e0abbb..33f4c81 100644 --- a/TaikoWebUI/Pages/Cards.razor.cs +++ b/TaikoWebUI/Pages/Users.razor.cs @@ -2,7 +2,7 @@ namespace TaikoWebUI.Pages; -public partial class Cards +public partial class Users { private string cardNum = ""; private MudForm loginForm = default!; @@ -15,19 +15,20 @@ public partial class Cards response = await Client.GetFromJsonAsync("api/Dashboard"); } - private async Task DeleteCard(User user) + private async Task DeleteUser(User user) { var parameters = new DialogParameters { ["user"] = user }; - var dialog = DialogService.Show("Delete Card", parameters); + var dialog = DialogService.Show("Delete User", parameters); var result = await dialog.Result; if (result.Canceled) return; response = await Client.GetFromJsonAsync("api/Dashboard"); + OnLogout(); } private async Task OnLogin() @@ -45,7 +46,7 @@ public partial class Cards await loginForm.ResetAsync(); break; case 1: - NavigationManager.NavigateTo("/Cards"); + NavigationManager.NavigateTo("/Users"); break; case 2: await DialogService.ShowMessageBox( @@ -74,7 +75,7 @@ public partial class Cards private void OnLogout() { LoginService.Logout(); - NavigationManager.NavigateTo("/Cards"); + NavigationManager.NavigateTo("/Users"); } private Task ShowQrCode(User user) diff --git a/TaikoWebUI/Services/LoginService.cs b/TaikoWebUI/Services/LoginService.cs index bf2e318..c15aebe 100644 --- a/TaikoWebUI/Services/LoginService.cs +++ b/TaikoWebUI/Services/LoginService.cs @@ -46,15 +46,17 @@ public class LoginService foreach (var user in response.Users.Where(user => user.AccessCode == inputCardNum)) { - if (user.Password == "") return 4; - if (ComputeHash(inputPassword, user.Salt) != user.Password) return 2; - CardNum = int.Parse(user.AccessCode); - Baid = user.Baid; - IsLoggedIn = true; - IsAdmin = false; - return 1; + 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; + CardNum = int.Parse(user.AccessCode); + Baid = user.Baid; + IsLoggedIn = true; + IsAdmin = false; + return 1; + } } - return 3; } @@ -64,17 +66,20 @@ public class LoginService if (OnlyAdmin) return 0; foreach (var user in response.Users.Where(user => user.AccessCode == inputCardNum)) { - if (user.Password != "") return 4; - if (inputPassword != inputConfirmPassword) return 2; - var salt = CreateSalt(); - var request = new SetPasswordRequest + foreach (var userCredential in response.UserCredentials.Where(userCredential => userCredential.Baid == user.Baid)) { - AccessCode = user.AccessCode, - Password = ComputeHash(inputPassword, salt), - Salt = salt - }; - var responseMessage = await client.PostAsJsonAsync("api/Cards", request); - return responseMessage.IsSuccessStatusCode ? 1 : 3; + if (userCredential.Password != "") return 4; + if (inputPassword != inputConfirmPassword) return 2; + var salt = CreateSalt(); + var request = new SetPasswordRequest + { + Baid = user.Baid, + Password = ComputeHash(inputPassword, salt), + Salt = salt + }; + var responseMessage = await client.PostAsJsonAsync("api/Credentials", request); + return responseMessage.IsSuccessStatusCode ? 1 : 3; + } } return 3; @@ -111,16 +116,19 @@ public class LoginService if (OnlyAdmin) return 0; foreach (var user in response.Users.Where(user => user.AccessCode == inputCardNum)) { - if (user.Password != ComputeHash(inputOldPassword, user.Salt)) return 4; - if (inputNewPassword != inputConfirmNewPassword) return 2; - var request = new SetPasswordRequest + foreach (var userCredential in response.UserCredentials.Where(userCredential => userCredential.Baid == user.Baid)) { - AccessCode = user.AccessCode, - Password = ComputeHash(inputNewPassword, user.Salt), - Salt = user.Salt - }; - var responseMessage = await client.PostAsJsonAsync("api/Cards", request); - return responseMessage.IsSuccessStatusCode ? 1 : 3; + if (userCredential.Password != ComputeHash(inputOldPassword, userCredential.Salt)) return 4; + if (inputNewPassword != inputConfirmNewPassword) return 2; + var request = new SetPasswordRequest + { + Baid = user.Baid, + Password = ComputeHash(inputNewPassword, userCredential.Salt), + Salt = userCredential.Salt + }; + var responseMessage = await client.PostAsJsonAsync("api/Credentials", request); + return responseMessage.IsSuccessStatusCode ? 1 : 3; + } } return 3; diff --git a/TaikoWebUI/Shared/NavMenu.razor b/TaikoWebUI/Shared/NavMenu.razor index 47eff76..463fb9b 100644 --- a/TaikoWebUI/Shared/NavMenu.razor +++ b/TaikoWebUI/Shared/NavMenu.razor @@ -1,4 +1,4 @@  Dashboard - Cards + Users \ No newline at end of file