1
0
mirror of synced 2025-01-31 12:23:50 +01:00

Change database foreign key relationship

This commit is contained in:
S-Sebb 2023-11-11 23:12:26 +00:00
parent cae9f09f15
commit 38374fe017
22 changed files with 843 additions and 154 deletions

View File

@ -22,7 +22,6 @@ 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!;
@ -50,6 +49,12 @@ namespace GameDatabase.Context
entity.HasKey(e => e.AccessCode);
entity.ToTable("Card");
entity.HasOne(d => d.Ba)
.WithMany()
.HasPrincipalKey(p => p.Baid)
.HasForeignKey(d => d.Baid)
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity<Credential>(entity =>
@ -115,12 +120,6 @@ namespace GameDatabase.Context
entity.Property(e => e.LastPlayDatetime).HasColumnType("datetime");
entity.HasOne(d => d.Ba)
.WithMany()
.HasPrincipalKey(p => p.Baid)
.HasForeignKey(d => d.Baid)
.OnDelete(DeleteBehavior.Cascade);
entity.Property(e => e.AchievementDisplayDifficulty)
.HasConversion<uint>();
});

View File

@ -1,4 +1,5 @@
using SharedProject.Enums;
using SharedProject.Models;
namespace GameDatabase.Entities;
@ -14,5 +15,5 @@ public class AiScoreDatum
public List<AiSectionScoreDatum> AiSectionScoreData { get; set; } = new();
public virtual Card? Ba { get; set; }
public virtual UserDatum? Ba { get; set; }
}

View File

@ -4,5 +4,7 @@
{
public string AccessCode { get; set; } = null!;
public ulong Baid { get; set; }
public virtual UserDatum? Ba { get; set; }
}
}

View File

@ -6,6 +6,6 @@
public string Password { get; set; } = null!;
public string Salt { get; set; } = null!;
public virtual Card? Ba { get; set; }
public virtual UserDatum? Ba { get; set; }
}
}

View File

@ -13,5 +13,5 @@ public class DanScoreDatum
public DanClearState ClearState { get; set; }
public List<DanStageScoreDatum> DanStageScoreData { get; set; } = new();
public virtual Card? Ba { get; set; }
public virtual UserDatum? Ba { get; set; }
}

View File

@ -12,6 +12,6 @@ namespace GameDatabase.Entities
public CrownType BestCrown { get; set; }
public ScoreRank BestScoreRank { get; set; }
public virtual Card? Ba { get; set; }
public virtual UserDatum? Ba { get; set; }
}
}

View File

@ -24,6 +24,6 @@ namespace GameDatabase.Entities
public bool Skipped { get; set; }
public DateTime PlayTime { get; set; }
public virtual Card? Ba { get; set; }
public virtual UserDatum? Ba { get; set; }
}
}

View File

@ -33,6 +33,5 @@ namespace GameDatabase.Entities
public int AiWinCount { get; set; }
public string TokenCountDict { get; set; } = "{}";
public string UnlockedSongIdList { get; set; } = "[]";
public virtual Card? Ba { get; set; }
}
}

View File

@ -0,0 +1,488 @@
// <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("20231111225534_AlterForeignKeyToUserDatum")]
partial class AlterForeignKeyToUserDatum
{
/// <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("Baid");
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")
.ValueGeneratedOnAdd()
.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.UserDatum", "Ba")
.WithMany()
.HasForeignKey("Baid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Ba");
});
modelBuilder.Entity("GameDatabase.Entities.AiSectionScoreDatum", b =>
{
b.HasOne("GameDatabase.Entities.AiScoreDatum", "Parent")
.WithMany("AiSectionScoreData")
.HasForeignKey("Baid", "SongId", "Difficulty")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Parent");
});
modelBuilder.Entity("GameDatabase.Entities.Card", b =>
{
b.HasOne("GameDatabase.Entities.UserDatum", "Ba")
.WithMany()
.HasForeignKey("Baid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Ba");
});
modelBuilder.Entity("GameDatabase.Entities.Credential", b =>
{
b.HasOne("GameDatabase.Entities.UserDatum", "Ba")
.WithMany()
.HasForeignKey("Baid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Ba");
});
modelBuilder.Entity("GameDatabase.Entities.DanScoreDatum", b =>
{
b.HasOne("GameDatabase.Entities.UserDatum", "Ba")
.WithMany()
.HasForeignKey("Baid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Ba");
});
modelBuilder.Entity("GameDatabase.Entities.DanStageScoreDatum", b =>
{
b.HasOne("GameDatabase.Entities.DanScoreDatum", "Parent")
.WithMany("DanStageScoreData")
.HasForeignKey("Baid", "DanId", "DanType")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Parent");
});
modelBuilder.Entity("GameDatabase.Entities.SongBestDatum", b =>
{
b.HasOne("GameDatabase.Entities.UserDatum", "Ba")
.WithMany()
.HasForeignKey("Baid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Ba");
});
modelBuilder.Entity("GameDatabase.Entities.SongPlayDatum", b =>
{
b.HasOne("GameDatabase.Entities.UserDatum", "Ba")
.WithMany()
.HasForeignKey("Baid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Ba");
});
modelBuilder.Entity("GameDatabase.Entities.AiScoreDatum", b =>
{
b.Navigation("AiSectionScoreData");
});
modelBuilder.Entity("GameDatabase.Entities.DanScoreDatum", b =>
{
b.Navigation("DanStageScoreData");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,198 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace GameDatabase.Migrations
{
/// <inheritdoc />
public partial class AlterForeignKeyToUserDatum : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_AiScoreData_Card_Baid",
table: "AiScoreData");
migrationBuilder.DropForeignKey(
name: "FK_Credential_Card_Baid",
table: "Credential");
migrationBuilder.DropForeignKey(
name: "FK_DanScoreData_Card_Baid",
table: "DanScoreData");
migrationBuilder.DropForeignKey(
name: "FK_SongBestData_Card_Baid",
table: "SongBestData");
migrationBuilder.DropForeignKey(
name: "FK_SongPlayData_Card_Baid",
table: "SongPlayData");
migrationBuilder.DropForeignKey(
name: "FK_UserData_Card_Baid",
table: "UserData");
migrationBuilder.DropUniqueConstraint(
name: "AK_Card_Baid",
table: "Card");
migrationBuilder.AlterColumn<ulong>(
name: "Baid",
table: "UserData",
type: "INTEGER",
nullable: false,
oldClrType: typeof(ulong),
oldType: "INTEGER")
.Annotation("Sqlite:Autoincrement", true);
migrationBuilder.CreateIndex(
name: "IX_Card_Baid",
table: "Card",
column: "Baid");
migrationBuilder.AddForeignKey(
name: "FK_AiScoreData_UserData_Baid",
table: "AiScoreData",
column: "Baid",
principalTable: "UserData",
principalColumn: "Baid",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_Card_UserData_Baid",
table: "Card",
column: "Baid",
principalTable: "UserData",
principalColumn: "Baid",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_Credential_UserData_Baid",
table: "Credential",
column: "Baid",
principalTable: "UserData",
principalColumn: "Baid",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_DanScoreData_UserData_Baid",
table: "DanScoreData",
column: "Baid",
principalTable: "UserData",
principalColumn: "Baid",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_SongBestData_UserData_Baid",
table: "SongBestData",
column: "Baid",
principalTable: "UserData",
principalColumn: "Baid",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_SongPlayData_UserData_Baid",
table: "SongPlayData",
column: "Baid",
principalTable: "UserData",
principalColumn: "Baid",
onDelete: ReferentialAction.Cascade);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_AiScoreData_UserData_Baid",
table: "AiScoreData");
migrationBuilder.DropForeignKey(
name: "FK_Card_UserData_Baid",
table: "Card");
migrationBuilder.DropForeignKey(
name: "FK_Credential_UserData_Baid",
table: "Credential");
migrationBuilder.DropForeignKey(
name: "FK_DanScoreData_UserData_Baid",
table: "DanScoreData");
migrationBuilder.DropForeignKey(
name: "FK_SongBestData_UserData_Baid",
table: "SongBestData");
migrationBuilder.DropForeignKey(
name: "FK_SongPlayData_UserData_Baid",
table: "SongPlayData");
migrationBuilder.DropIndex(
name: "IX_Card_Baid",
table: "Card");
migrationBuilder.AlterColumn<ulong>(
name: "Baid",
table: "UserData",
type: "INTEGER",
nullable: false,
oldClrType: typeof(ulong),
oldType: "INTEGER")
.OldAnnotation("Sqlite:Autoincrement", true);
migrationBuilder.AddUniqueConstraint(
name: "AK_Card_Baid",
table: "Card",
column: "Baid");
migrationBuilder.AddForeignKey(
name: "FK_AiScoreData_Card_Baid",
table: "AiScoreData",
column: "Baid",
principalTable: "Card",
principalColumn: "Baid",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_Credential_Card_Baid",
table: "Credential",
column: "Baid",
principalTable: "Card",
principalColumn: "Baid",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_DanScoreData_Card_Baid",
table: "DanScoreData",
column: "Baid",
principalTable: "Card",
principalColumn: "Baid",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_SongBestData_Card_Baid",
table: "SongBestData",
column: "Baid",
principalTable: "Card",
principalColumn: "Baid",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_SongPlayData_Card_Baid",
table: "SongPlayData",
column: "Baid",
principalTable: "Card",
principalColumn: "Baid",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_UserData_Card_Baid",
table: "UserData",
column: "Baid",
principalTable: "Card",
principalColumn: "Baid",
onDelete: ReferentialAction.Cascade);
}
}
}

View File

@ -86,6 +86,8 @@ namespace TaikoLocalServer.Migrations
b.HasKey("AccessCode");
b.HasIndex("Baid");
b.ToTable("Card", (string)null);
});
@ -276,6 +278,7 @@ namespace TaikoLocalServer.Migrations
modelBuilder.Entity("GameDatabase.Entities.UserDatum", b =>
{
b.Property<ulong>("Baid")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<uint>("AchievementDisplayDifficulty")
@ -381,10 +384,9 @@ namespace TaikoLocalServer.Migrations
modelBuilder.Entity("GameDatabase.Entities.AiScoreDatum", b =>
{
b.HasOne("GameDatabase.Entities.Card", "Ba")
b.HasOne("GameDatabase.Entities.UserDatum", "Ba")
.WithMany()
.HasForeignKey("Baid")
.HasPrincipalKey("Baid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
@ -402,12 +404,22 @@ namespace TaikoLocalServer.Migrations
b.Navigation("Parent");
});
modelBuilder.Entity("GameDatabase.Entities.Credential", b =>
modelBuilder.Entity("GameDatabase.Entities.Card", b =>
{
b.HasOne("GameDatabase.Entities.Card", "Ba")
b.HasOne("GameDatabase.Entities.UserDatum", "Ba")
.WithMany()
.HasForeignKey("Baid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Ba");
});
modelBuilder.Entity("GameDatabase.Entities.Credential", b =>
{
b.HasOne("GameDatabase.Entities.UserDatum", "Ba")
.WithMany()
.HasForeignKey("Baid")
.HasPrincipalKey("Baid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
@ -416,10 +428,9 @@ namespace TaikoLocalServer.Migrations
modelBuilder.Entity("GameDatabase.Entities.DanScoreDatum", b =>
{
b.HasOne("GameDatabase.Entities.Card", "Ba")
b.HasOne("GameDatabase.Entities.UserDatum", "Ba")
.WithMany()
.HasForeignKey("Baid")
.HasPrincipalKey("Baid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
@ -439,10 +450,9 @@ namespace TaikoLocalServer.Migrations
modelBuilder.Entity("GameDatabase.Entities.SongBestDatum", b =>
{
b.HasOne("GameDatabase.Entities.Card", "Ba")
b.HasOne("GameDatabase.Entities.UserDatum", "Ba")
.WithMany()
.HasForeignKey("Baid")
.HasPrincipalKey("Baid")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
@ -451,22 +461,9 @@ namespace TaikoLocalServer.Migrations
modelBuilder.Entity("GameDatabase.Entities.SongPlayDatum", b =>
{
b.HasOne("GameDatabase.Entities.Card", "Ba")
b.HasOne("GameDatabase.Entities.UserDatum", "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();

View File

@ -2,7 +2,7 @@
public class User
{
public string AccessCode { get; set; } = string.Empty;
public uint Baid { get; set; }
public List<string> AccessCodes { get; set; } = new();
}

View File

@ -14,9 +14,9 @@ public class CardsController : BaseController<CardsController>
}
[HttpDelete("{accessCode}")]
public async Task<IActionResult> DeleteUser(string accessCode)
public async Task<IActionResult> DeleteUser(uint baid)
{
var result = await cardService.DeleteCard(accessCode);
var result = await cardService.DeleteCard(baid);
return result ? NoContent() : NotFound();
}

View File

@ -1,5 +1,6 @@
using GameDatabase.Context;
using GameDatabase.Entities;
using OneOf.Types;
using SharedProject.Models;
using Swan.Mapping;
@ -26,7 +27,30 @@ public class CardService : ICardService
public async Task<List<User>> GetUsersFromCards()
{
return await context.Cards.Select(card => card.CopyPropertiesToNew<User>(null)).ToListAsync();
var cardEntries = await context.Cards.ToListAsync();
List<User> users = new();
var found = false;
foreach (var cardEntry in cardEntries)
{
foreach (var user in users.Where(user => user.Baid == cardEntry.Baid))
{
user.AccessCodes.Add(cardEntry.AccessCode);
found = true;
}
if (!found)
{
var user = new User
{
Baid = (uint)cardEntry.Baid,
AccessCodes = new List<string> {cardEntry.AccessCode}
};
users.Add(user);
}
found = false;
}
return users;
}
public async Task AddCard(Card card)
@ -35,16 +59,14 @@ public class CardService : ICardService
await context.SaveChangesAsync();
}
public async Task<bool> DeleteCard(string accessCode)
public async Task<bool> DeleteCard(uint baid)
{
var card = await context.Cards.FindAsync(accessCode);
var cards = await context.Cards.ToListAsync();
var deletingCards = cards.Where(card => card.Baid == baid).ToList();
if (card is null)
{
return false;
}
if (deletingCards.Count == 0) return false;
context.Cards.Remove(card);
context.RemoveRange(deletingCards);
await context.SaveChangesAsync();
return true;

View File

@ -13,5 +13,5 @@ public interface ICardService
public Task AddCard(Card card);
public Task<bool> DeleteCard(string accessCode);
public Task<bool> DeleteCard(uint baid);
}

View File

@ -7,16 +7,9 @@
<MudBreadcrumbs Items="breadcrumbs" Class="px-0"></MudBreadcrumbs>
<h1>Dani Dojo</h1>
@if (LoginService.LoginRequired)
{
<MudText Typo="Typo.caption">Card: @LoginService.GetCardNum()</MudText>
}
else
{
<MudText Typo="Typo.caption">Card: @Baid</MudText>
}
<MudText Typo="Typo.caption">User: @Baid</MudText>
@if (LoginService.LoginRequired && (!LoginService.IsLoggedIn || (LoginService.Baid != Baid && !LoginService.IsAdmin)))
@if (LoginService.LoginRequired && (!LoginService.IsLoggedIn || (LoginService.GetLoggedInUser().Baid != Baid && !LoginService.IsAdmin)))
{
<MudItem xs="12">
<MudText Align="Align.Center" Class="my-8">

View File

@ -22,7 +22,7 @@ public partial class UserDeleteConfirmDialog
return;
}
var cardResponseMessage = await Client.DeleteAsync($"api/Cards/{User.AccessCode}");
var cardResponseMessage = await Client.DeleteAsync($"api/Cards/{User.Baid}");
if (!cardResponseMessage.IsSuccessStatusCode)
{

View File

@ -28,7 +28,7 @@
protected override void OnInitialized()
{
base.OnInitialized();
qrCode = "BNTTCNID" + User.AccessCode;
qrCode = "BNTTCNID" + User.AccessCodes.First();
}
private void Submit()

View File

@ -7,14 +7,8 @@
<MudBreadcrumbs Items="breadcrumbs" Class="px-0"></MudBreadcrumbs>
<h1>High Scores</h1>
@if (LoginService.LoginRequired)
{
<MudText Typo="Typo.caption">Card: @LoginService.GetCardNum()</MudText>
}
else
{
<MudText Typo="Typo.caption">Card: @Baid</MudText>
}
<MudText Typo="Typo.caption">User: @Baid</MudText>
<MudGrid Class="my-8">
@if (response is null)
@ -27,7 +21,7 @@ else
}
else
{
@if (LoginService.LoginRequired && (!LoginService.IsLoggedIn || (LoginService.Baid != Baid && !LoginService.IsAdmin)))
@if (LoginService.LoginRequired && (!LoginService.IsLoggedIn || (LoginService.GetLoggedInUser().Baid != Baid && !LoginService.IsAdmin)))
{
<MudItem xs="12">
<MudText Align="Align.Center" Class="my-8">

View File

@ -3,24 +3,17 @@
@inject IGameDataService GameDataService
@inject IDialogService DialogService
@inject LoginService LoginService
@inject IJSRuntime JS
@inject IJSRuntime Js
<MudBreadcrumbs Items="breadcrumbs" Class="px-0"></MudBreadcrumbs>
<h1>Profile</h1>
@if (LoginService.LoginRequired)
{
<MudText Typo="Typo.caption">Card: @LoginService.GetCardNum()</MudText>
}
else
{
<MudText Typo="Typo.caption">Card: @Baid</MudText>
}
<MudText Typo="Typo.caption">User: @Baid</MudText>
@if (response is not null)
{
@if (LoginService.LoginRequired && (!LoginService.IsLoggedIn || (LoginService.Baid != Baid && !LoginService.IsAdmin)))
@if (LoginService.LoginRequired && (!LoginService.IsLoggedIn || (LoginService.GetLoggedInUser().Baid != Baid && !LoginService.IsAdmin)))
{
<MudItem xs="12">
<MudText Align="Align.Center" Class="my-8">
@ -333,11 +326,11 @@ else
@code {
private async Task UpdateMyDonName()
{
@if (response is not null) await JS.InvokeVoidAsync("updateMyDonName", response.MyDonName);
@if (response is not null) await Js.InvokeVoidAsync("updateMyDonName", response.MyDonName);
}
private async Task UpdateTitle()
{
@if (response is not null) await JS.InvokeVoidAsync("updateTitle", response.Title);
@if (response is not null) await Js.InvokeVoidAsync("updateTitle", response.Title);
}
}

View File

@ -59,7 +59,14 @@
</MudCardHeader>
<MudCardContent>
<MudText Style="font-weight:bold">Access Code</MudText>
<MudText Style="font-family:monospace;overflow:hidden;overflow-x:scroll">@user.AccessCode</MudText>
<MudGrid>
@foreach (var accessCode in user.AccessCodes)
{
<MudItem xs="12">
<MudText Style="font-family:monospace;overflow:hidden;overflow-x:scroll">@accessCode</MudText>
</MudItem>
}
</MudGrid>
</MudCardContent>
<MudCardActions>
<MudStack Row="true" Style="width:100%" Spacing="4" Justify="Justify.FlexEnd">
@ -121,57 +128,66 @@
}
else
{
var user = response.Users[LoginService.GetBaid() - 1];
<MudItem xs="12" md="6" lg="4">
<MudCard Outlined="true">
<MudCardHeader>
<CardHeaderContent>
<MudText Typo="Typo.h6" Style="font-weight:bold">@user.Baid</MudText>
</CardHeaderContent>
<CardHeaderActions>
<MudMenu Icon="@Icons.Material.Filled.MoreVert" Dense="true" AnchorOrigin="Origin.BottomLeft"
TransformOrigin="Origin.TopLeft" Size="Size.Small">
<MudMenuItem Icon="@Icons.Material.Filled.QrCode"
OnClick="@(_ => ShowQrCode(user))"
IconColor="@Color.Primary">
Show QR Code
</MudMenuItem>
<MudDivider/>
<MudMenuItem Icon="@Icons.Material.Filled.Delete"
OnClick="@(_ => DeleteUser(user))"
IconColor="@Color.Error">
Delete User
</MudMenuItem>
</MudMenu>
</CardHeaderActions>
</MudCardHeader>
<MudCardContent>
<MudText Style="font-weight:bold">Access Code</MudText>
<MudText Style="font-family:monospace;overflow:hidden;overflow-x:scroll">@user.AccessCode</MudText>
</MudCardContent>
<MudCardActions>
<MudStack Row="true" Style="width:100%" Spacing="4" Justify="Justify.FlexEnd">
<MudButton Href="@($"Users/{user.Baid}/Profile")"
Size="Size.Small" Variant="Variant.Text" StartIcon="@Icons.Material.Filled.Edit"
Color="Color.Primary">
Edit Profile
</MudButton>
<MudMenu Size="Size.Small"
Dense="true"
Color="Color.Primary"
Label="View Play Data"
StartIcon="@Icons.Material.Filled.FeaturedPlayList"
EndIcon="@Icons.Material.Filled.KeyboardArrowDown"
FullWidth="true"
AnchorOrigin="Origin.BottomCenter"
TransformOrigin="Origin.TopCenter">
<MudMenuItem Href="@($"Users/{user.Baid}/HighScores")">High Scores</MudMenuItem>
<MudMenuItem Href="@($"Users/{user.Baid}/DaniDojo")">Dani Dojo</MudMenuItem>
</MudMenu>
</MudStack>
</MudCardActions>
</MudCard>
</MudItem>
var user = LoginService.GetLoggedInUser();
<MudGrid Justify="Justify.Center">
<MudItem xs="12" md="6" lg="4">
<MudCard Outlined="true">
<MudCardHeader>
<CardHeaderContent>
<MudText Typo="Typo.h6" Style="font-weight:bold">@user.Baid</MudText>
</CardHeaderContent>
<CardHeaderActions>
<MudMenu Icon="@Icons.Material.Filled.MoreVert" Dense="true" AnchorOrigin="Origin.BottomLeft"
TransformOrigin="Origin.TopLeft" Size="Size.Small">
<MudMenuItem Icon="@Icons.Material.Filled.QrCode"
OnClick="@(_ => ShowQrCode(user))"
IconColor="@Color.Primary">
Show QR Code
</MudMenuItem>
<MudDivider/>
<MudMenuItem Icon="@Icons.Material.Filled.Delete"
OnClick="@(_ => DeleteUser(user))"
IconColor="@Color.Error">
Delete User
</MudMenuItem>
</MudMenu>
</CardHeaderActions>
</MudCardHeader>
<MudCardContent>
<MudText Style="font-weight:bold">Access Code</MudText>
<MudGrid>
@foreach (var accessCode in user.AccessCodes)
{
<MudItem xs="12">
<MudText Style="font-family:monospace;overflow:hidden;overflow-x:scroll">@accessCode</MudText>
</MudItem>
}
</MudGrid>
</MudCardContent>
<MudCardActions>
<MudStack Row="true" Style="width:100%" Spacing="4" Justify="Justify.FlexEnd">
<MudButton Href="@($"Users/{user.Baid}/Profile")"
Size="Size.Small" Variant="Variant.Text" StartIcon="@Icons.Material.Filled.Edit"
Color="Color.Primary">
Edit Profile
</MudButton>
<MudMenu Size="Size.Small"
Dense="true"
Color="Color.Primary"
Label="View Play Data"
StartIcon="@Icons.Material.Filled.FeaturedPlayList"
EndIcon="@Icons.Material.Filled.KeyboardArrowDown"
FullWidth="true"
AnchorOrigin="Origin.BottomCenter"
TransformOrigin="Origin.TopCenter">
<MudMenuItem Href="@($"Users/{user.Baid}/HighScores")">High Scores</MudMenuItem>
<MudMenuItem Href="@($"Users/{user.Baid}/DaniDojo")">Dani Dojo</MudMenuItem>
</MudMenu>
</MudStack>
</MudCardActions>
</MudCard>
</MudItem>
</MudGrid>
}
}
}

View File

@ -13,8 +13,6 @@ public class LoginService
public LoginService(IOptions<WebUiSettings> settings)
{
IsLoggedIn = false;
Baid = 0;
CardNum = 0;
IsAdmin = false;
var webUiSettings = settings.Value;
adminUsername = webUiSettings.AdminUsername;
@ -24,8 +22,7 @@ public class LoginService
}
public bool IsLoggedIn { get; private set; }
public uint Baid { get; private set; }
private int CardNum { get; set; }
private User LoggedInUser { get; set; } = new();
public bool IsAdmin { get; private set; }
public bool LoginRequired { get; }
@ -35,8 +32,6 @@ public class LoginService
{
if (inputCardNum == adminUsername && inputPassword == adminPassword)
{
CardNum = 0;
Baid = 0;
IsLoggedIn = true;
IsAdmin = true;
return 1;
@ -44,15 +39,14 @@ public class LoginService
if (OnlyAdmin) return 0;
foreach (var user in response.Users.Where(user => user.AccessCode == inputCardNum))
foreach (var user in response.Users.Where(user => user.AccessCodes.Contains(inputCardNum)))
{
foreach (var userCredential in response.UserCredentials.Where(userCredential => userCredential.Baid == user.Baid))
{
if (userCredential.Password == "") return 4;
if (ComputeHash(inputPassword, userCredential.Salt) != userCredential.Password) return 2;
CardNum = int.Parse(user.AccessCode);
Baid = user.Baid;
IsLoggedIn = true;
LoggedInUser = user;
IsAdmin = false;
return 1;
}
@ -64,7 +58,7 @@ public class LoginService
DashboardResponse response, HttpClient client)
{
if (OnlyAdmin) return 0;
foreach (var user in response.Users.Where(user => user.AccessCode == inputCardNum))
foreach (var user in response.Users.Where(user => user.AccessCodes.Contains(inputCardNum)))
{
foreach (var userCredential in response.UserCredentials.Where(userCredential => userCredential.Baid == user.Baid))
{
@ -114,7 +108,7 @@ public class LoginService
string inputConfirmNewPassword, DashboardResponse response, HttpClient client)
{
if (OnlyAdmin) return 0;
foreach (var user in response.Users.Where(user => user.AccessCode == inputCardNum))
foreach (var user in response.Users.Where(user => user.AccessCodes.Contains(inputCardNum)))
{
foreach (var userCredential in response.UserCredentials.Where(userCredential => userCredential.Baid == user.Baid))
{
@ -137,19 +131,12 @@ public class LoginService
public void Logout()
{
IsLoggedIn = false;
LoggedInUser = new User();
IsAdmin = false;
Baid = 0;
CardNum = 0;
}
public int GetBaid()
public User GetLoggedInUser()
{
return checked((int)Baid);
}
public string GetCardNum()
{
if (IsAdmin) return "Admin";
return CardNum == 0 ? "Not logged in" : CardNum.ToString();
return LoggedInUser;
}
}