1
0
mirror of synced 2025-01-18 15:54:06 +01:00

Add credential table, refactored related webUI code

This commit is contained in:
S-Sebb 2023-11-11 21:04:11 +00:00
parent f8378e5a14
commit cae9f09f15
42 changed files with 2418 additions and 143 deletions

View File

@ -22,6 +22,8 @@ namespace GameDatabase.Context
}
public virtual DbSet<Card> Cards { get; set; } = null!;
public virtual DbSet<Credential> Credentials { get; set; } = null!;
public virtual DbSet<SongBestDatum> SongBestData { get; set; } = null!;
public virtual DbSet<SongPlayDatum> SongPlayData { get; set; } = null!;
public virtual DbSet<UserDatum> UserData { get; set; } = null!;
@ -48,9 +50,19 @@ namespace GameDatabase.Context
entity.HasKey(e => e.AccessCode);
entity.ToTable("Card");
});
modelBuilder.Entity<Credential>(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<SongBestDatum>(entity =>

View File

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

View File

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

View File

@ -0,0 +1,491 @@
// <auto-generated />
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
{
/// <inheritdoc />
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<ulong>("Baid")
.HasColumnType("INTEGER");
b.Property<uint>("SongId")
.HasColumnType("INTEGER");
b.Property<uint>("Difficulty")
.HasColumnType("INTEGER");
b.Property<bool>("IsWin")
.HasColumnType("INTEGER");
b.HasKey("Baid", "SongId", "Difficulty");
b.ToTable("AiScoreData");
});
modelBuilder.Entity("GameDatabase.Entities.AiSectionScoreDatum", b =>
{
b.Property<ulong>("Baid")
.HasColumnType("INTEGER");
b.Property<uint>("SongId")
.HasColumnType("INTEGER");
b.Property<uint>("Difficulty")
.HasColumnType("INTEGER");
b.Property<int>("SectionIndex")
.HasColumnType("INTEGER");
b.Property<int>("Crown")
.HasColumnType("INTEGER");
b.Property<uint>("DrumrollCount")
.HasColumnType("INTEGER");
b.Property<uint>("GoodCount")
.HasColumnType("INTEGER");
b.Property<bool>("IsWin")
.HasColumnType("INTEGER");
b.Property<uint>("MissCount")
.HasColumnType("INTEGER");
b.Property<uint>("OkCount")
.HasColumnType("INTEGER");
b.Property<uint>("Score")
.HasColumnType("INTEGER");
b.HasKey("Baid", "SongId", "Difficulty", "SectionIndex");
b.ToTable("AiSectionScoreData");
});
modelBuilder.Entity("GameDatabase.Entities.Card", b =>
{
b.Property<string>("AccessCode")
.HasColumnType("TEXT");
b.Property<ulong>("Baid")
.HasColumnType("INTEGER");
b.Property<string>("Password")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("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<ulong>("Baid")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Password")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Salt")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Baid");
b.ToTable("Credential", (string)null);
});
modelBuilder.Entity("GameDatabase.Entities.DanScoreDatum", b =>
{
b.Property<ulong>("Baid")
.HasColumnType("INTEGER");
b.Property<uint>("DanId")
.HasColumnType("INTEGER");
b.Property<int>("DanType")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER")
.HasDefaultValue(1);
b.Property<uint>("ArrivalSongCount")
.HasColumnType("INTEGER");
b.Property<uint>("ClearState")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER")
.HasDefaultValue(0u);
b.Property<uint>("ComboCountTotal")
.HasColumnType("INTEGER");
b.Property<uint>("SoulGaugeTotal")
.HasColumnType("INTEGER");
b.HasKey("Baid", "DanId", "DanType");
b.ToTable("DanScoreData");
});
modelBuilder.Entity("GameDatabase.Entities.DanStageScoreDatum", b =>
{
b.Property<ulong>("Baid")
.HasColumnType("INTEGER");
b.Property<uint>("DanId")
.HasColumnType("INTEGER");
b.Property<int>("DanType")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER")
.HasDefaultValue(1);
b.Property<uint>("SongNumber")
.HasColumnType("INTEGER");
b.Property<uint>("BadCount")
.HasColumnType("INTEGER");
b.Property<uint>("ComboCount")
.HasColumnType("INTEGER");
b.Property<uint>("DrumrollCount")
.HasColumnType("INTEGER");
b.Property<uint>("GoodCount")
.HasColumnType("INTEGER");
b.Property<uint>("HighScore")
.HasColumnType("INTEGER");
b.Property<uint>("OkCount")
.HasColumnType("INTEGER");
b.Property<uint>("PlayScore")
.HasColumnType("INTEGER");
b.Property<uint>("TotalHitCount")
.HasColumnType("INTEGER");
b.HasKey("Baid", "DanId", "DanType", "SongNumber");
b.ToTable("DanStageScoreData");
});
modelBuilder.Entity("GameDatabase.Entities.SongBestDatum", b =>
{
b.Property<ulong>("Baid")
.HasColumnType("INTEGER");
b.Property<uint>("SongId")
.HasColumnType("INTEGER");
b.Property<uint>("Difficulty")
.HasColumnType("INTEGER");
b.Property<uint>("BestCrown")
.HasColumnType("INTEGER");
b.Property<uint>("BestRate")
.HasColumnType("INTEGER");
b.Property<uint>("BestScore")
.HasColumnType("INTEGER");
b.Property<uint>("BestScoreRank")
.HasColumnType("INTEGER");
b.HasKey("Baid", "SongId", "Difficulty");
b.ToTable("SongBestData");
});
modelBuilder.Entity("GameDatabase.Entities.SongPlayDatum", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<ulong>("Baid")
.HasColumnType("INTEGER");
b.Property<uint>("ComboCount")
.HasColumnType("INTEGER");
b.Property<uint>("Crown")
.HasColumnType("INTEGER");
b.Property<uint>("Difficulty")
.HasColumnType("INTEGER");
b.Property<uint>("DrumrollCount")
.HasColumnType("INTEGER");
b.Property<uint>("GoodCount")
.HasColumnType("INTEGER");
b.Property<uint>("HitCount")
.HasColumnType("INTEGER");
b.Property<uint>("MissCount")
.HasColumnType("INTEGER");
b.Property<uint>("OkCount")
.HasColumnType("INTEGER");
b.Property<DateTime>("PlayTime")
.HasColumnType("datetime");
b.Property<uint>("Score")
.HasColumnType("INTEGER");
b.Property<uint>("ScoreRank")
.HasColumnType("INTEGER");
b.Property<uint>("ScoreRate")
.HasColumnType("INTEGER");
b.Property<bool>("Skipped")
.HasColumnType("INTEGER");
b.Property<uint>("SongId")
.HasColumnType("INTEGER");
b.Property<uint>("SongNumber")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("Baid");
b.ToTable("SongPlayData");
});
modelBuilder.Entity("GameDatabase.Entities.UserDatum", b =>
{
b.Property<ulong>("Baid")
.HasColumnType("INTEGER");
b.Property<uint>("AchievementDisplayDifficulty")
.HasColumnType("INTEGER");
b.Property<int>("AiWinCount")
.HasColumnType("INTEGER");
b.Property<uint>("ColorBody")
.HasColumnType("INTEGER");
b.Property<uint>("ColorFace")
.HasColumnType("INTEGER");
b.Property<uint>("ColorLimb")
.HasColumnType("INTEGER");
b.Property<string>("CostumeData")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("CostumeFlgArray")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("DifficultyPlayedArray")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("DifficultySettingArray")
.IsRequired()
.HasColumnType("TEXT");
b.Property<bool>("DisplayAchievement")
.HasColumnType("INTEGER");
b.Property<bool>("DisplayDan")
.HasColumnType("INTEGER");
b.Property<string>("FavoriteSongsArray")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("GenericInfoFlgArray")
.IsRequired()
.HasColumnType("TEXT");
b.Property<bool>("IsSkipOn")
.HasColumnType("INTEGER");
b.Property<bool>("IsVoiceOn")
.HasColumnType("INTEGER");
b.Property<DateTime>("LastPlayDatetime")
.HasColumnType("datetime");
b.Property<uint>("LastPlayMode")
.HasColumnType("INTEGER");
b.Property<string>("MyDonName")
.IsRequired()
.HasColumnType("TEXT");
b.Property<uint>("MyDonNameLanguage")
.HasColumnType("INTEGER");
b.Property<int>("NotesPosition")
.HasColumnType("INTEGER");
b.Property<short>("OptionSetting")
.HasColumnType("INTEGER");
b.Property<uint>("SelectedToneId")
.HasColumnType("INTEGER");
b.Property<string>("Title")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("TitleFlgArray")
.IsRequired()
.HasColumnType("TEXT");
b.Property<uint>("TitlePlateId")
.HasColumnType("INTEGER");
b.Property<string>("TokenCountDict")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("ToneFlgArray")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("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
}
}
}

View File

@ -0,0 +1,35 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace GameDatabase.Migrations
{
/// <inheritdoc />
public partial class AddCredentialTable : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Credential",
columns: table => new
{
Baid = table.Column<ulong>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
Password = table.Column<string>(type: "TEXT", nullable: false),
Salt = table.Column<string>(type: "TEXT", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Credential", x => x.Baid);
});
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Credential");
}
}
}

View File

@ -0,0 +1,491 @@
// <auto-generated />
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
{
/// <inheritdoc />
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<ulong>("Baid")
.HasColumnType("INTEGER");
b.Property<uint>("SongId")
.HasColumnType("INTEGER");
b.Property<uint>("Difficulty")
.HasColumnType("INTEGER");
b.Property<bool>("IsWin")
.HasColumnType("INTEGER");
b.HasKey("Baid", "SongId", "Difficulty");
b.ToTable("AiScoreData");
});
modelBuilder.Entity("GameDatabase.Entities.AiSectionScoreDatum", b =>
{
b.Property<ulong>("Baid")
.HasColumnType("INTEGER");
b.Property<uint>("SongId")
.HasColumnType("INTEGER");
b.Property<uint>("Difficulty")
.HasColumnType("INTEGER");
b.Property<int>("SectionIndex")
.HasColumnType("INTEGER");
b.Property<int>("Crown")
.HasColumnType("INTEGER");
b.Property<uint>("DrumrollCount")
.HasColumnType("INTEGER");
b.Property<uint>("GoodCount")
.HasColumnType("INTEGER");
b.Property<bool>("IsWin")
.HasColumnType("INTEGER");
b.Property<uint>("MissCount")
.HasColumnType("INTEGER");
b.Property<uint>("OkCount")
.HasColumnType("INTEGER");
b.Property<uint>("Score")
.HasColumnType("INTEGER");
b.HasKey("Baid", "SongId", "Difficulty", "SectionIndex");
b.ToTable("AiSectionScoreData");
});
modelBuilder.Entity("GameDatabase.Entities.Card", b =>
{
b.Property<string>("AccessCode")
.HasColumnType("TEXT");
b.Property<ulong>("Baid")
.HasColumnType("INTEGER");
b.Property<string>("Password")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("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<ulong>("Baid")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Password")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Salt")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Baid");
b.ToTable("Credential", (string)null);
});
modelBuilder.Entity("GameDatabase.Entities.DanScoreDatum", b =>
{
b.Property<ulong>("Baid")
.HasColumnType("INTEGER");
b.Property<uint>("DanId")
.HasColumnType("INTEGER");
b.Property<int>("DanType")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER")
.HasDefaultValue(1);
b.Property<uint>("ArrivalSongCount")
.HasColumnType("INTEGER");
b.Property<uint>("ClearState")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER")
.HasDefaultValue(0u);
b.Property<uint>("ComboCountTotal")
.HasColumnType("INTEGER");
b.Property<uint>("SoulGaugeTotal")
.HasColumnType("INTEGER");
b.HasKey("Baid", "DanId", "DanType");
b.ToTable("DanScoreData");
});
modelBuilder.Entity("GameDatabase.Entities.DanStageScoreDatum", b =>
{
b.Property<ulong>("Baid")
.HasColumnType("INTEGER");
b.Property<uint>("DanId")
.HasColumnType("INTEGER");
b.Property<int>("DanType")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER")
.HasDefaultValue(1);
b.Property<uint>("SongNumber")
.HasColumnType("INTEGER");
b.Property<uint>("BadCount")
.HasColumnType("INTEGER");
b.Property<uint>("ComboCount")
.HasColumnType("INTEGER");
b.Property<uint>("DrumrollCount")
.HasColumnType("INTEGER");
b.Property<uint>("GoodCount")
.HasColumnType("INTEGER");
b.Property<uint>("HighScore")
.HasColumnType("INTEGER");
b.Property<uint>("OkCount")
.HasColumnType("INTEGER");
b.Property<uint>("PlayScore")
.HasColumnType("INTEGER");
b.Property<uint>("TotalHitCount")
.HasColumnType("INTEGER");
b.HasKey("Baid", "DanId", "DanType", "SongNumber");
b.ToTable("DanStageScoreData");
});
modelBuilder.Entity("GameDatabase.Entities.SongBestDatum", b =>
{
b.Property<ulong>("Baid")
.HasColumnType("INTEGER");
b.Property<uint>("SongId")
.HasColumnType("INTEGER");
b.Property<uint>("Difficulty")
.HasColumnType("INTEGER");
b.Property<uint>("BestCrown")
.HasColumnType("INTEGER");
b.Property<uint>("BestRate")
.HasColumnType("INTEGER");
b.Property<uint>("BestScore")
.HasColumnType("INTEGER");
b.Property<uint>("BestScoreRank")
.HasColumnType("INTEGER");
b.HasKey("Baid", "SongId", "Difficulty");
b.ToTable("SongBestData");
});
modelBuilder.Entity("GameDatabase.Entities.SongPlayDatum", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<ulong>("Baid")
.HasColumnType("INTEGER");
b.Property<uint>("ComboCount")
.HasColumnType("INTEGER");
b.Property<uint>("Crown")
.HasColumnType("INTEGER");
b.Property<uint>("Difficulty")
.HasColumnType("INTEGER");
b.Property<uint>("DrumrollCount")
.HasColumnType("INTEGER");
b.Property<uint>("GoodCount")
.HasColumnType("INTEGER");
b.Property<uint>("HitCount")
.HasColumnType("INTEGER");
b.Property<uint>("MissCount")
.HasColumnType("INTEGER");
b.Property<uint>("OkCount")
.HasColumnType("INTEGER");
b.Property<DateTime>("PlayTime")
.HasColumnType("datetime");
b.Property<uint>("Score")
.HasColumnType("INTEGER");
b.Property<uint>("ScoreRank")
.HasColumnType("INTEGER");
b.Property<uint>("ScoreRate")
.HasColumnType("INTEGER");
b.Property<bool>("Skipped")
.HasColumnType("INTEGER");
b.Property<uint>("SongId")
.HasColumnType("INTEGER");
b.Property<uint>("SongNumber")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("Baid");
b.ToTable("SongPlayData");
});
modelBuilder.Entity("GameDatabase.Entities.UserDatum", b =>
{
b.Property<ulong>("Baid")
.HasColumnType("INTEGER");
b.Property<uint>("AchievementDisplayDifficulty")
.HasColumnType("INTEGER");
b.Property<int>("AiWinCount")
.HasColumnType("INTEGER");
b.Property<uint>("ColorBody")
.HasColumnType("INTEGER");
b.Property<uint>("ColorFace")
.HasColumnType("INTEGER");
b.Property<uint>("ColorLimb")
.HasColumnType("INTEGER");
b.Property<string>("CostumeData")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("CostumeFlgArray")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("DifficultyPlayedArray")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("DifficultySettingArray")
.IsRequired()
.HasColumnType("TEXT");
b.Property<bool>("DisplayAchievement")
.HasColumnType("INTEGER");
b.Property<bool>("DisplayDan")
.HasColumnType("INTEGER");
b.Property<string>("FavoriteSongsArray")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("GenericInfoFlgArray")
.IsRequired()
.HasColumnType("TEXT");
b.Property<bool>("IsSkipOn")
.HasColumnType("INTEGER");
b.Property<bool>("IsVoiceOn")
.HasColumnType("INTEGER");
b.Property<DateTime>("LastPlayDatetime")
.HasColumnType("datetime");
b.Property<uint>("LastPlayMode")
.HasColumnType("INTEGER");
b.Property<string>("MyDonName")
.IsRequired()
.HasColumnType("TEXT");
b.Property<uint>("MyDonNameLanguage")
.HasColumnType("INTEGER");
b.Property<int>("NotesPosition")
.HasColumnType("INTEGER");
b.Property<short>("OptionSetting")
.HasColumnType("INTEGER");
b.Property<uint>("SelectedToneId")
.HasColumnType("INTEGER");
b.Property<string>("Title")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("TitleFlgArray")
.IsRequired()
.HasColumnType("TEXT");
b.Property<uint>("TitlePlateId")
.HasColumnType("INTEGER");
b.Property<string>("TokenCountDict")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("ToneFlgArray")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("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
}
}
}

View File

@ -0,0 +1,30 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace GameDatabase.Migrations
{
/// <inheritdoc />
public partial class CopyPasswordSaltFromCardToCredential : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.Sql(@"
INSERT INTO Credential (Baid, Password, Salt)
SELECT Baid, Password, Salt
FROM Card
");
}
/// <inheritdoc />
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)
");
}
}
}

View File

@ -0,0 +1,483 @@
// <auto-generated />
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
{
/// <inheritdoc />
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<ulong>("Baid")
.HasColumnType("INTEGER");
b.Property<uint>("SongId")
.HasColumnType("INTEGER");
b.Property<uint>("Difficulty")
.HasColumnType("INTEGER");
b.Property<bool>("IsWin")
.HasColumnType("INTEGER");
b.HasKey("Baid", "SongId", "Difficulty");
b.ToTable("AiScoreData");
});
modelBuilder.Entity("GameDatabase.Entities.AiSectionScoreDatum", b =>
{
b.Property<ulong>("Baid")
.HasColumnType("INTEGER");
b.Property<uint>("SongId")
.HasColumnType("INTEGER");
b.Property<uint>("Difficulty")
.HasColumnType("INTEGER");
b.Property<int>("SectionIndex")
.HasColumnType("INTEGER");
b.Property<int>("Crown")
.HasColumnType("INTEGER");
b.Property<uint>("DrumrollCount")
.HasColumnType("INTEGER");
b.Property<uint>("GoodCount")
.HasColumnType("INTEGER");
b.Property<bool>("IsWin")
.HasColumnType("INTEGER");
b.Property<uint>("MissCount")
.HasColumnType("INTEGER");
b.Property<uint>("OkCount")
.HasColumnType("INTEGER");
b.Property<uint>("Score")
.HasColumnType("INTEGER");
b.HasKey("Baid", "SongId", "Difficulty", "SectionIndex");
b.ToTable("AiSectionScoreData");
});
modelBuilder.Entity("GameDatabase.Entities.Card", b =>
{
b.Property<string>("AccessCode")
.HasColumnType("TEXT");
b.Property<ulong>("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<ulong>("Baid")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Password")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Salt")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Baid");
b.ToTable("Credential", (string)null);
});
modelBuilder.Entity("GameDatabase.Entities.DanScoreDatum", b =>
{
b.Property<ulong>("Baid")
.HasColumnType("INTEGER");
b.Property<uint>("DanId")
.HasColumnType("INTEGER");
b.Property<int>("DanType")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER")
.HasDefaultValue(1);
b.Property<uint>("ArrivalSongCount")
.HasColumnType("INTEGER");
b.Property<uint>("ClearState")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER")
.HasDefaultValue(0u);
b.Property<uint>("ComboCountTotal")
.HasColumnType("INTEGER");
b.Property<uint>("SoulGaugeTotal")
.HasColumnType("INTEGER");
b.HasKey("Baid", "DanId", "DanType");
b.ToTable("DanScoreData");
});
modelBuilder.Entity("GameDatabase.Entities.DanStageScoreDatum", b =>
{
b.Property<ulong>("Baid")
.HasColumnType("INTEGER");
b.Property<uint>("DanId")
.HasColumnType("INTEGER");
b.Property<int>("DanType")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER")
.HasDefaultValue(1);
b.Property<uint>("SongNumber")
.HasColumnType("INTEGER");
b.Property<uint>("BadCount")
.HasColumnType("INTEGER");
b.Property<uint>("ComboCount")
.HasColumnType("INTEGER");
b.Property<uint>("DrumrollCount")
.HasColumnType("INTEGER");
b.Property<uint>("GoodCount")
.HasColumnType("INTEGER");
b.Property<uint>("HighScore")
.HasColumnType("INTEGER");
b.Property<uint>("OkCount")
.HasColumnType("INTEGER");
b.Property<uint>("PlayScore")
.HasColumnType("INTEGER");
b.Property<uint>("TotalHitCount")
.HasColumnType("INTEGER");
b.HasKey("Baid", "DanId", "DanType", "SongNumber");
b.ToTable("DanStageScoreData");
});
modelBuilder.Entity("GameDatabase.Entities.SongBestDatum", b =>
{
b.Property<ulong>("Baid")
.HasColumnType("INTEGER");
b.Property<uint>("SongId")
.HasColumnType("INTEGER");
b.Property<uint>("Difficulty")
.HasColumnType("INTEGER");
b.Property<uint>("BestCrown")
.HasColumnType("INTEGER");
b.Property<uint>("BestRate")
.HasColumnType("INTEGER");
b.Property<uint>("BestScore")
.HasColumnType("INTEGER");
b.Property<uint>("BestScoreRank")
.HasColumnType("INTEGER");
b.HasKey("Baid", "SongId", "Difficulty");
b.ToTable("SongBestData");
});
modelBuilder.Entity("GameDatabase.Entities.SongPlayDatum", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<ulong>("Baid")
.HasColumnType("INTEGER");
b.Property<uint>("ComboCount")
.HasColumnType("INTEGER");
b.Property<uint>("Crown")
.HasColumnType("INTEGER");
b.Property<uint>("Difficulty")
.HasColumnType("INTEGER");
b.Property<uint>("DrumrollCount")
.HasColumnType("INTEGER");
b.Property<uint>("GoodCount")
.HasColumnType("INTEGER");
b.Property<uint>("HitCount")
.HasColumnType("INTEGER");
b.Property<uint>("MissCount")
.HasColumnType("INTEGER");
b.Property<uint>("OkCount")
.HasColumnType("INTEGER");
b.Property<DateTime>("PlayTime")
.HasColumnType("datetime");
b.Property<uint>("Score")
.HasColumnType("INTEGER");
b.Property<uint>("ScoreRank")
.HasColumnType("INTEGER");
b.Property<uint>("ScoreRate")
.HasColumnType("INTEGER");
b.Property<bool>("Skipped")
.HasColumnType("INTEGER");
b.Property<uint>("SongId")
.HasColumnType("INTEGER");
b.Property<uint>("SongNumber")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("Baid");
b.ToTable("SongPlayData");
});
modelBuilder.Entity("GameDatabase.Entities.UserDatum", b =>
{
b.Property<ulong>("Baid")
.HasColumnType("INTEGER");
b.Property<uint>("AchievementDisplayDifficulty")
.HasColumnType("INTEGER");
b.Property<int>("AiWinCount")
.HasColumnType("INTEGER");
b.Property<uint>("ColorBody")
.HasColumnType("INTEGER");
b.Property<uint>("ColorFace")
.HasColumnType("INTEGER");
b.Property<uint>("ColorLimb")
.HasColumnType("INTEGER");
b.Property<string>("CostumeData")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("CostumeFlgArray")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("DifficultyPlayedArray")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("DifficultySettingArray")
.IsRequired()
.HasColumnType("TEXT");
b.Property<bool>("DisplayAchievement")
.HasColumnType("INTEGER");
b.Property<bool>("DisplayDan")
.HasColumnType("INTEGER");
b.Property<string>("FavoriteSongsArray")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("GenericInfoFlgArray")
.IsRequired()
.HasColumnType("TEXT");
b.Property<bool>("IsSkipOn")
.HasColumnType("INTEGER");
b.Property<bool>("IsVoiceOn")
.HasColumnType("INTEGER");
b.Property<DateTime>("LastPlayDatetime")
.HasColumnType("datetime");
b.Property<uint>("LastPlayMode")
.HasColumnType("INTEGER");
b.Property<string>("MyDonName")
.IsRequired()
.HasColumnType("TEXT");
b.Property<uint>("MyDonNameLanguage")
.HasColumnType("INTEGER");
b.Property<int>("NotesPosition")
.HasColumnType("INTEGER");
b.Property<short>("OptionSetting")
.HasColumnType("INTEGER");
b.Property<uint>("SelectedToneId")
.HasColumnType("INTEGER");
b.Property<string>("Title")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("TitleFlgArray")
.IsRequired()
.HasColumnType("TEXT");
b.Property<uint>("TitlePlateId")
.HasColumnType("INTEGER");
b.Property<string>("TokenCountDict")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("ToneFlgArray")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("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
}
}
}

View File

@ -0,0 +1,40 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace GameDatabase.Migrations
{
/// <inheritdoc />
public partial class RemovePasswordSaltFromCard : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "Password",
table: "Card");
migrationBuilder.DropColumn(
name: "Salt",
table: "Card");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "Password",
table: "Card",
type: "TEXT",
nullable: false,
defaultValue: "");
migrationBuilder.AddColumn<string>(
name: "Salt",
table: "Card",
type: "TEXT",
nullable: false,
defaultValue: "");
}
}
}

View File

@ -0,0 +1,491 @@
// <auto-generated />
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
{
/// <inheritdoc />
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<ulong>("Baid")
.HasColumnType("INTEGER");
b.Property<uint>("SongId")
.HasColumnType("INTEGER");
b.Property<uint>("Difficulty")
.HasColumnType("INTEGER");
b.Property<bool>("IsWin")
.HasColumnType("INTEGER");
b.HasKey("Baid", "SongId", "Difficulty");
b.ToTable("AiScoreData");
});
modelBuilder.Entity("GameDatabase.Entities.AiSectionScoreDatum", b =>
{
b.Property<ulong>("Baid")
.HasColumnType("INTEGER");
b.Property<uint>("SongId")
.HasColumnType("INTEGER");
b.Property<uint>("Difficulty")
.HasColumnType("INTEGER");
b.Property<int>("SectionIndex")
.HasColumnType("INTEGER");
b.Property<int>("Crown")
.HasColumnType("INTEGER");
b.Property<uint>("DrumrollCount")
.HasColumnType("INTEGER");
b.Property<uint>("GoodCount")
.HasColumnType("INTEGER");
b.Property<bool>("IsWin")
.HasColumnType("INTEGER");
b.Property<uint>("MissCount")
.HasColumnType("INTEGER");
b.Property<uint>("OkCount")
.HasColumnType("INTEGER");
b.Property<uint>("Score")
.HasColumnType("INTEGER");
b.HasKey("Baid", "SongId", "Difficulty", "SectionIndex");
b.ToTable("AiSectionScoreData");
});
modelBuilder.Entity("GameDatabase.Entities.Card", b =>
{
b.Property<string>("AccessCode")
.HasColumnType("TEXT");
b.Property<ulong>("Baid")
.HasColumnType("INTEGER");
b.HasKey("AccessCode");
b.ToTable("Card", (string)null);
});
modelBuilder.Entity("GameDatabase.Entities.Credential", b =>
{
b.Property<ulong>("Baid")
.HasColumnType("INTEGER");
b.Property<string>("Password")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Salt")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Baid");
b.ToTable("Credential", (string)null);
});
modelBuilder.Entity("GameDatabase.Entities.DanScoreDatum", b =>
{
b.Property<ulong>("Baid")
.HasColumnType("INTEGER");
b.Property<uint>("DanId")
.HasColumnType("INTEGER");
b.Property<int>("DanType")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER")
.HasDefaultValue(1);
b.Property<uint>("ArrivalSongCount")
.HasColumnType("INTEGER");
b.Property<uint>("ClearState")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER")
.HasDefaultValue(0u);
b.Property<uint>("ComboCountTotal")
.HasColumnType("INTEGER");
b.Property<uint>("SoulGaugeTotal")
.HasColumnType("INTEGER");
b.HasKey("Baid", "DanId", "DanType");
b.ToTable("DanScoreData");
});
modelBuilder.Entity("GameDatabase.Entities.DanStageScoreDatum", b =>
{
b.Property<ulong>("Baid")
.HasColumnType("INTEGER");
b.Property<uint>("DanId")
.HasColumnType("INTEGER");
b.Property<int>("DanType")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER")
.HasDefaultValue(1);
b.Property<uint>("SongNumber")
.HasColumnType("INTEGER");
b.Property<uint>("BadCount")
.HasColumnType("INTEGER");
b.Property<uint>("ComboCount")
.HasColumnType("INTEGER");
b.Property<uint>("DrumrollCount")
.HasColumnType("INTEGER");
b.Property<uint>("GoodCount")
.HasColumnType("INTEGER");
b.Property<uint>("HighScore")
.HasColumnType("INTEGER");
b.Property<uint>("OkCount")
.HasColumnType("INTEGER");
b.Property<uint>("PlayScore")
.HasColumnType("INTEGER");
b.Property<uint>("TotalHitCount")
.HasColumnType("INTEGER");
b.HasKey("Baid", "DanId", "DanType", "SongNumber");
b.ToTable("DanStageScoreData");
});
modelBuilder.Entity("GameDatabase.Entities.SongBestDatum", b =>
{
b.Property<ulong>("Baid")
.HasColumnType("INTEGER");
b.Property<uint>("SongId")
.HasColumnType("INTEGER");
b.Property<uint>("Difficulty")
.HasColumnType("INTEGER");
b.Property<uint>("BestCrown")
.HasColumnType("INTEGER");
b.Property<uint>("BestRate")
.HasColumnType("INTEGER");
b.Property<uint>("BestScore")
.HasColumnType("INTEGER");
b.Property<uint>("BestScoreRank")
.HasColumnType("INTEGER");
b.HasKey("Baid", "SongId", "Difficulty");
b.ToTable("SongBestData");
});
modelBuilder.Entity("GameDatabase.Entities.SongPlayDatum", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<ulong>("Baid")
.HasColumnType("INTEGER");
b.Property<uint>("ComboCount")
.HasColumnType("INTEGER");
b.Property<uint>("Crown")
.HasColumnType("INTEGER");
b.Property<uint>("Difficulty")
.HasColumnType("INTEGER");
b.Property<uint>("DrumrollCount")
.HasColumnType("INTEGER");
b.Property<uint>("GoodCount")
.HasColumnType("INTEGER");
b.Property<uint>("HitCount")
.HasColumnType("INTEGER");
b.Property<uint>("MissCount")
.HasColumnType("INTEGER");
b.Property<uint>("OkCount")
.HasColumnType("INTEGER");
b.Property<DateTime>("PlayTime")
.HasColumnType("datetime");
b.Property<uint>("Score")
.HasColumnType("INTEGER");
b.Property<uint>("ScoreRank")
.HasColumnType("INTEGER");
b.Property<uint>("ScoreRate")
.HasColumnType("INTEGER");
b.Property<bool>("Skipped")
.HasColumnType("INTEGER");
b.Property<uint>("SongId")
.HasColumnType("INTEGER");
b.Property<uint>("SongNumber")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("Baid");
b.ToTable("SongPlayData");
});
modelBuilder.Entity("GameDatabase.Entities.UserDatum", b =>
{
b.Property<ulong>("Baid")
.HasColumnType("INTEGER");
b.Property<uint>("AchievementDisplayDifficulty")
.HasColumnType("INTEGER");
b.Property<int>("AiWinCount")
.HasColumnType("INTEGER");
b.Property<uint>("ColorBody")
.HasColumnType("INTEGER");
b.Property<uint>("ColorFace")
.HasColumnType("INTEGER");
b.Property<uint>("ColorLimb")
.HasColumnType("INTEGER");
b.Property<string>("CostumeData")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("CostumeFlgArray")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("DifficultyPlayedArray")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("DifficultySettingArray")
.IsRequired()
.HasColumnType("TEXT");
b.Property<bool>("DisplayAchievement")
.HasColumnType("INTEGER");
b.Property<bool>("DisplayDan")
.HasColumnType("INTEGER");
b.Property<string>("FavoriteSongsArray")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("GenericInfoFlgArray")
.IsRequired()
.HasColumnType("TEXT");
b.Property<bool>("IsSkipOn")
.HasColumnType("INTEGER");
b.Property<bool>("IsVoiceOn")
.HasColumnType("INTEGER");
b.Property<DateTime>("LastPlayDatetime")
.HasColumnType("datetime");
b.Property<uint>("LastPlayMode")
.HasColumnType("INTEGER");
b.Property<string>("MyDonName")
.IsRequired()
.HasColumnType("TEXT");
b.Property<uint>("MyDonNameLanguage")
.HasColumnType("INTEGER");
b.Property<int>("NotesPosition")
.HasColumnType("INTEGER");
b.Property<short>("OptionSetting")
.HasColumnType("INTEGER");
b.Property<uint>("SelectedToneId")
.HasColumnType("INTEGER");
b.Property<string>("Title")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("TitleFlgArray")
.IsRequired()
.HasColumnType("TEXT");
b.Property<uint>("TitlePlateId")
.HasColumnType("INTEGER");
b.Property<string>("TokenCountDict")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("ToneFlgArray")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("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
}
}
}

View File

@ -0,0 +1,58 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace GameDatabase.Migrations
{
/// <inheritdoc />
public partial class RemoveBaidUniquenessFromCard : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropIndex(
name: "IX_Card_Baid",
table: "Card");
migrationBuilder.AlterColumn<ulong>(
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);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_Credential_Card_Baid",
table: "Credential");
migrationBuilder.AlterColumn<ulong>(
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);
}
}
}

View File

@ -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<ulong>("Baid")
.HasColumnType("INTEGER");
b.HasKey("AccessCode");
b.ToTable("Card", (string)null);
});
modelBuilder.Entity("GameDatabase.Entities.Credential", b =>
{
b.Property<ulong>("Baid")
.HasColumnType("INTEGER");
b.Property<string>("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<int>("DanType")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER")
.HasDefaultValue(1);
@ -140,6 +148,7 @@ namespace TaikoLocalServer.Migrations
.HasColumnType("INTEGER");
b.Property<int>("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")

View File

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

View File

@ -3,4 +3,6 @@
public class DashboardResponse
{
public List<User> Users { get; set; } = new();
public List<UserCredential> UserCredentials { get; set; } = new();
}

View File

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

View File

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

View File

@ -20,14 +20,4 @@ public class CardsController : BaseController<CardsController>
return result ? NoContent() : NotFound();
}
[HttpPost]
public async Task<IActionResult> 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();
}
}

View File

@ -0,0 +1,33 @@
using SharedProject.Models.Requests;
namespace TaikoLocalServer.Controllers.Api;
[ApiController]
[Route("api/[controller]")]
public class CredentialsController : BaseController<CredentialsController>
{
private readonly ICredentialService credentialService;
public CredentialsController(ICredentialService credentialService)
{
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)
{
var baid = request.Baid;
var password = request.Password;
var salt = request.Salt;
var result = await credentialService.UpdatePassword(baid, password, salt);
return result ? NoContent() : NotFound();
}
}

View File

@ -7,19 +7,23 @@ namespace TaikoLocalServer.Controllers.Api;
public class DashboardController : BaseController<DashboardController>
{
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<DashboardResponse> GetDashboard()
{
var users = await cardService.GetUsersFromCards();
var credentials = await credentialService.GetUserCredentialsFromCredentials();
return new DashboardResponse
{
Users = users
Users = users,
UserCredentials = credentials
};
}

View File

@ -9,11 +9,14 @@ public class MyDonEntryController : BaseController<MyDonEntryController>
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<MyDonEntryController>
await cardService.AddCard(new Card
{
AccessCode = request.WechatQrStr,
Baid = newId
});
await credentialService.AddCredential(new Credential
{
Baid = newId,
Password = "",
Salt = ""

View File

@ -49,17 +49,4 @@ public class CardService : ICardService
return true;
}
public async Task<bool> 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;
}
}

View File

@ -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<List<UserCredential>> GetUserCredentialsFromCredentials()
{
return await context.Credentials.Select(credential => credential.CopyPropertiesToNew<UserCredential>(null)).ToListAsync();
}
public async Task AddCredential(Credential credential)
{
context.Add(credential);
await context.SaveChangesAsync();
}
public async Task<bool> 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<bool> 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;
}
}

View File

@ -5,6 +5,7 @@ public static class ServiceExtensions
public static IServiceCollection AddTaikoDbServices(this IServiceCollection services)
{
services.AddScoped<ICardService, CardService>();
services.AddScoped<ICredentialService, CredentialService>();
services.AddScoped<IUserDatumService, UserDatumService>();
services.AddScoped<ISongPlayDatumService, SongPlayDatumService>();
services.AddScoped<ISongBestDatumService, SongBestDatumService>();

View File

@ -14,6 +14,4 @@ public interface ICardService
public Task AddCard(Card card);
public Task<bool> DeleteCard(string accessCode);
public Task<bool> UpdatePassword(string accessCode, string password, string salt);
}

View File

@ -0,0 +1,15 @@
using GameDatabase.Entities;
using SharedProject.Models;
namespace TaikoLocalServer.Services.Interfaces;
public interface ICredentialService
{
public Task<List<UserCredential>> GetUserCredentialsFromCredentials();
public Task AddCredential(Credential credential);
public Task<bool> DeleteCredential(uint baid);
public Task<bool> UpdatePassword(uint baid, string password, string salt);
}

View File

@ -3,9 +3,9 @@
@inject LoginService LoginService
@inject NavigationManager NavigationManager
@page "/Cards/ChangePassword"
@page "/Users/ChangePassword"
<h1>Cards</h1>
<h1>Users</h1>
@if (LoginService.OnlyAdmin || !LoginService.LoginRequired)
{

View File

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

View File

@ -2,7 +2,7 @@
@inject HttpClient Client
@inject LoginService LoginService
@page "/Cards/{baid:int}/DaniDojo"
@page "/Users/{baid:int}/DaniDojo"
<MudBreadcrumbs Items="breadcrumbs" Class="px-0"></MudBreadcrumbs>
@ -20,7 +20,7 @@ else
{
<MudItem xs="12">
<MudText Align="Align.Center" Class="my-8">
Please log in by clicking on "cards" tab first.
Please log in by clicking on "Users" tab first.
</MudText>
</MudItem>
}

View File

@ -11,7 +11,7 @@ public partial class DaniDojo
private readonly List<BreadcrumbItem> 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)

View File

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

View File

@ -5,19 +5,19 @@
<TitleContent>
<MudText Typo="Typo.h6">
<MudIcon Icon="@Icons.Material.Filled.DeleteForever" Class="mr-3 mb-n1"/>
Delete card?
Delete user?
</MudText>
</TitleContent>
<DialogContent>
<MudText>
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!
</MudText>
</DialogContent>
<DialogActions>
<MudButton OnClick="Cancel">Cancel</MudButton>
<MudButton Color="Color.Error" OnClick="DeleteCard">
<MudText>Delete Card</MudText>
<MudButton Color="Color.Error" OnClick="DeleteUser">
<MudText>Delete User</MudText>
</MudButton>
</DialogActions>
</MudDialog>

View File

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

View File

@ -2,7 +2,7 @@
@inject HttpClient Client
@inject LoginService LoginService
@page "/Cards/{baid:int}/HighScores"
@page "/Users/{baid:int}/HighScores"
<MudBreadcrumbs Items="breadcrumbs" Class="px-0"></MudBreadcrumbs>
@ -31,7 +31,7 @@ else
{
<MudItem xs="12">
<MudText Align="Align.Center" Class="my-8">
Please log in by clicking on "cards" tab first.
Please log in by clicking on "Users" tab first.
</MudText>
</MudItem>
}

View File

@ -16,7 +16,7 @@ public partial class HighScores
private readonly List<BreadcrumbItem> 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)

View File

@ -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
{
<MudItem xs="12">
<MudText Align="Align.Center" Class="my-8">
Please log in by clicking on "cards" tab first.
Please log in by clicking on "Users" tab first.
</MudText>
</MudItem>
}

View File

@ -166,7 +166,7 @@ public partial class Profile
private readonly List<BreadcrumbItem> breadcrumbs = new()
{
new BreadcrumbItem("Cards", href: "/Cards"),
new BreadcrumbItem("Users", href: "/Users"),
};
private List<int> costumeFlagArraySizes = new();
@ -178,7 +178,7 @@ public partial class Profile
response = await Client.GetFromJsonAsync<UserSetting>($"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();
}

View File

@ -3,9 +3,9 @@
@inject LoginService LoginService
@inject NavigationManager NavigationManager
@page "/Cards/Register"
@page "/Users/Register"
<h1>Cards</h1>
<h1>Users</h1>
@if (LoginService.OnlyAdmin || !LoginService.LoginRequired)
{

View File

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

View File

@ -3,9 +3,9 @@
@inject LoginService LoginService
@inject NavigationManager NavigationManager
@page "/Cards"
@page "/Users"
<h1>Cards</h1>
<h1>Users</h1>
<MudGrid Class="my-8">
@if (response is null)
{
@ -50,9 +50,9 @@
</MudMenuItem>
<MudDivider/>
<MudMenuItem Icon="@Icons.Material.Filled.Delete"
OnClick="@(_ => DeleteCard(user))"
OnClick="@(_ => DeleteUser(user))"
IconColor="@Color.Error">
Delete Card
Delete User
</MudMenuItem>
</MudMenu>
</CardHeaderActions>
@ -63,7 +63,7 @@
</MudCardContent>
<MudCardActions>
<MudStack Row="true" Style="width:100%" Spacing="4" Justify="Justify.FlexEnd">
<MudButton Href="@($"Cards/{user.Baid}/Profile")"
<MudButton Href="@($"Users/{user.Baid}/Profile")"
Size="Size.Small" Variant="Variant.Text" StartIcon="@Icons.Material.Filled.Edit"
Color="Color.Primary">
Edit Profile
@ -77,8 +77,8 @@
FullWidth="true"
AnchorOrigin="Origin.BottomCenter"
TransformOrigin="Origin.TopCenter">
<MudMenuItem Href="@($"Cards/{user.Baid}/HighScores")">High Scores</MudMenuItem>
<MudMenuItem Href="@($"Cards/{user.Baid}/DaniDojo")">Dani Dojo</MudMenuItem>
<MudMenuItem Href="@($"Users/{user.Baid}/HighScores")">High Scores</MudMenuItem>
<MudMenuItem Href="@($"Users/{user.Baid}/DaniDojo")">Dani Dojo</MudMenuItem>
</MudMenu>
</MudStack>
</MudCardActions>
@ -109,7 +109,7 @@
<MudButton OnClick="OnLogin" FullWidth="true" Class="mt-3" StartIcon="@Icons.Material.Filled.Login" Color="Color.Primary" Variant="Variant.Filled">Login</MudButton>
@if (!LoginService.OnlyAdmin)
{
<MudButton Href="@("Cards/Register")" FullWidth="true" Class="mt-3" StartIcon="@Icons.Material.Filled.AddCard" Color="Color.Primary" Variant="Variant.Filled">Register</MudButton>
<MudButton Href="@("Users/Register")" FullWidth="true" Class="mt-3" StartIcon="@Icons.Material.Filled.AddCard" Color="Color.Primary" Variant="Variant.Filled">Register</MudButton>
}
</MudStack>
</MudForm>
@ -138,9 +138,9 @@
</MudMenuItem>
<MudDivider/>
<MudMenuItem Icon="@Icons.Material.Filled.Delete"
OnClick="@(_ => DeleteCard(user))"
OnClick="@(_ => DeleteUser(user))"
IconColor="@Color.Error">
Delete Card
Delete User
</MudMenuItem>
</MudMenu>
</CardHeaderActions>
@ -151,7 +151,7 @@
</MudCardContent>
<MudCardActions>
<MudStack Row="true" Style="width:100%" Spacing="4" Justify="Justify.FlexEnd">
<MudButton Href="@($"Cards/{user.Baid}/Profile")"
<MudButton Href="@($"Users/{user.Baid}/Profile")"
Size="Size.Small" Variant="Variant.Text" StartIcon="@Icons.Material.Filled.Edit"
Color="Color.Primary">
Edit Profile
@ -165,8 +165,8 @@
FullWidth="true"
AnchorOrigin="Origin.BottomCenter"
TransformOrigin="Origin.TopCenter">
<MudMenuItem Href="@($"Cards/{user.Baid}/HighScores")">High Scores</MudMenuItem>
<MudMenuItem Href="@($"Cards/{user.Baid}/DaniDojo")">Dani Dojo</MudMenuItem>
<MudMenuItem Href="@($"Users/{user.Baid}/HighScores")">High Scores</MudMenuItem>
<MudMenuItem Href="@($"Users/{user.Baid}/DaniDojo")">Dani Dojo</MudMenuItem>
</MudMenu>
</MudStack>
</MudCardActions>

View File

@ -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<DashboardResponse>("api/Dashboard");
}
private async Task DeleteCard(User user)
private async Task DeleteUser(User user)
{
var parameters = new DialogParameters
{
["user"] = user
};
var dialog = DialogService.Show<CardDeleteConfirmDialog>("Delete Card", parameters);
var dialog = DialogService.Show<UserDeleteConfirmDialog>("Delete User", parameters);
var result = await dialog.Result;
if (result.Canceled) return;
response = await Client.GetFromJsonAsync<DashboardResponse>("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)

View File

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

View File

@ -1,4 +1,4 @@
<MudNavMenu>
<MudNavLink Href="/" Match="NavLinkMatch.All" Icon="@Icons.Material.Filled.Dashboard">Dashboard</MudNavLink>
<MudNavLink Href="/Cards" Match="NavLinkMatch.Prefix" Icon="@Icons.Material.Filled.CreditCard">Cards</MudNavLink>
<MudNavLink Href="/Users" Match="NavLinkMatch.Prefix" Icon="@Icons.Material.Filled.CreditCard">Users</MudNavLink>
</MudNavMenu>