Add team roles and content management updates
This commit is contained in:
@@ -17,6 +17,8 @@ public sealed class AwardsDbContext(DbContextOptions<AwardsDbContext> options) :
|
||||
public DbSet<AdminAuditEntry> AdminAuditEntries => Set<AdminAuditEntry>();
|
||||
public DbSet<ClipSubmission> ClipSubmissions => Set<ClipSubmission>();
|
||||
public DbSet<SiteSettings> SiteSettings => Set<SiteSettings>();
|
||||
public DbSet<TeamMember> TeamMembers => Set<TeamMember>();
|
||||
public DbSet<TeamRolePermission> TeamRolePermissions => Set<TeamRolePermission>();
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
@@ -43,10 +45,36 @@ public sealed class AwardsDbContext(DbContextOptions<AwardsDbContext> options) :
|
||||
entity.Property(item => item.DemoLoginPasswordSalt).HasMaxLength(80);
|
||||
entity.Property(item => item.DemoLoginTwitchUserId).HasMaxLength(120);
|
||||
entity.Property(item => item.DemoLoginDisplayName).HasMaxLength(120);
|
||||
entity.Property(item => item.TwitchClientId).HasMaxLength(120);
|
||||
entity.Property(item => item.TwitchClientSecret).HasMaxLength(180);
|
||||
entity.Property(item => item.TwitchRedirectUri).HasMaxLength(400);
|
||||
entity.Property(item => item.TwitchScope).HasMaxLength(300);
|
||||
entity.Property(item => item.MaintenanceTitle).HasMaxLength(120);
|
||||
entity.Property(item => item.MaintenanceMessage).HasMaxLength(600);
|
||||
});
|
||||
|
||||
modelBuilder.Entity<TeamMember>(entity =>
|
||||
{
|
||||
entity.HasIndex(item => item.Login).IsUnique();
|
||||
entity.HasIndex(item => item.BoundTwitchUserId).IsUnique();
|
||||
entity.Property(item => item.Login).HasMaxLength(80);
|
||||
entity.Property(item => item.DisplayName).HasMaxLength(120);
|
||||
entity.Property(item => item.Role).HasMaxLength(40);
|
||||
entity.Property(item => item.PasswordHash).HasMaxLength(120);
|
||||
entity.Property(item => item.PasswordSalt).HasMaxLength(80);
|
||||
entity.Property(item => item.BoundTwitchUserId).HasMaxLength(120);
|
||||
entity.Property(item => item.BoundTwitchDisplayName).HasMaxLength(120);
|
||||
entity.Property(item => item.CreatedByTwitchId).HasMaxLength(120);
|
||||
entity.Property(item => item.UpdatedByTwitchId).HasMaxLength(120);
|
||||
});
|
||||
|
||||
modelBuilder.Entity<TeamRolePermission>(entity =>
|
||||
{
|
||||
entity.HasIndex(item => item.Role).IsUnique();
|
||||
entity.Property(item => item.Role).HasMaxLength(40);
|
||||
entity.Property(item => item.UpdatedByTwitchId).HasMaxLength(120);
|
||||
});
|
||||
|
||||
modelBuilder.Entity<Category>(entity =>
|
||||
{
|
||||
entity.HasIndex(item => new { item.SeasonId, item.Slug }).IsUnique();
|
||||
|
||||
@@ -16,6 +16,21 @@ public static class OperationalTablesBootstrapper
|
||||
ALTER TABLE "SiteSettings"
|
||||
ADD COLUMN IF NOT EXISTS "RiskRulesJson" text NOT NULL DEFAULT '[]';
|
||||
|
||||
ALTER TABLE "SiteSettings"
|
||||
ADD COLUMN IF NOT EXISTS "TwitchAuthManagedByDatabase" boolean NOT NULL DEFAULT false;
|
||||
|
||||
ALTER TABLE "SiteSettings"
|
||||
ADD COLUMN IF NOT EXISTS "TwitchClientId" character varying(120) NOT NULL DEFAULT '';
|
||||
|
||||
ALTER TABLE "SiteSettings"
|
||||
ADD COLUMN IF NOT EXISTS "TwitchClientSecret" character varying(180) NOT NULL DEFAULT '';
|
||||
|
||||
ALTER TABLE "SiteSettings"
|
||||
ADD COLUMN IF NOT EXISTS "TwitchRedirectUri" character varying(400) NOT NULL DEFAULT '';
|
||||
|
||||
ALTER TABLE "SiteSettings"
|
||||
ADD COLUMN IF NOT EXISTS "TwitchScope" character varying(300) NOT NULL DEFAULT '';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "RiskFlags" (
|
||||
"Id" integer GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
"SeasonId" integer NULL,
|
||||
@@ -128,5 +143,52 @@ public static class OperationalTablesBootstrapper
|
||||
|
||||
CREATE INDEX IF NOT EXISTS "IX_Nominations_SeasonId_Status"
|
||||
ON "Nominations" ("SeasonId", "Status");
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "TeamMembers" (
|
||||
"Id" integer GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
"Login" character varying(80) NOT NULL,
|
||||
"DisplayName" character varying(120) NOT NULL,
|
||||
"Role" character varying(40) NOT NULL,
|
||||
"PasswordHash" character varying(120) NOT NULL,
|
||||
"PasswordSalt" character varying(80) NOT NULL,
|
||||
"BoundTwitchUserId" character varying(120) NULL,
|
||||
"BoundTwitchDisplayName" character varying(120) NULL,
|
||||
"MustChangePassword" boolean NOT NULL,
|
||||
"IsActive" boolean NOT NULL,
|
||||
"CreatedByTwitchId" character varying(120) NOT NULL,
|
||||
"UpdatedByTwitchId" character varying(120) NULL,
|
||||
"CreatedAt" timestamp with time zone NOT NULL,
|
||||
"UpdatedAt" timestamp with time zone NULL,
|
||||
"LastLoginAt" timestamp with time zone NULL,
|
||||
"TwitchBoundAt" timestamp with time zone NULL,
|
||||
"PasswordResetAt" timestamp with time zone NULL
|
||||
);
|
||||
|
||||
ALTER TABLE "TeamMembers"
|
||||
ADD COLUMN IF NOT EXISTS "BoundTwitchUserId" character varying(120) NULL;
|
||||
|
||||
ALTER TABLE "TeamMembers"
|
||||
ADD COLUMN IF NOT EXISTS "BoundTwitchDisplayName" character varying(120) NULL;
|
||||
|
||||
ALTER TABLE "TeamMembers"
|
||||
ADD COLUMN IF NOT EXISTS "TwitchBoundAt" timestamp with time zone NULL;
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS "IX_TeamMembers_Login"
|
||||
ON "TeamMembers" ("Login");
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS "IX_TeamMembers_BoundTwitchUserId"
|
||||
ON "TeamMembers" ("BoundTwitchUserId")
|
||||
WHERE "BoundTwitchUserId" IS NOT NULL;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "TeamRolePermissions" (
|
||||
"Id" integer GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
"Role" character varying(40) NOT NULL,
|
||||
"PermissionsJson" text NOT NULL,
|
||||
"UpdatedByTwitchId" character varying(120) NOT NULL,
|
||||
"UpdatedAt" timestamp with time zone NOT NULL
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS "IX_TeamRolePermissions_Role"
|
||||
ON "TeamRolePermissions" ("Role");
|
||||
""");
|
||||
}
|
||||
|
||||
@@ -55,6 +55,35 @@ internal static class SeedCatalog
|
||||
new("Discord", "discord", "https://discord.gg/jayuhime", "discord"),
|
||||
];
|
||||
|
||||
internal const string DefaultImprintContent = """
|
||||
Anbieter
|
||||
VTuber Star Awards, vertreten durch Jayuhime.
|
||||
|
||||
Kontakt
|
||||
Nutze fuer organisatorische Fragen bitte die Kontaktseite oder die hinterlegte Kontaktadresse.
|
||||
|
||||
Hinweis
|
||||
Dieses Impressum ist ein redaktioneller Platzhalter und sollte vor dem Livegang mit den tatsaechlichen Anbieterangaben ersetzt werden.
|
||||
""";
|
||||
|
||||
internal const string DefaultContactContent = """
|
||||
Kontakt zum Award-Team
|
||||
Du hast Fragen zur Nominierung, zum Voting, zu Clips oder zur Show? Schreib dem Team ueber die hinterlegte Kontaktseite.
|
||||
|
||||
Datenschutzfragen
|
||||
Fuer Datenschutzanfragen nutze bitte die Datenschutz-E-Mail aus diesem Footer.
|
||||
|
||||
Community & Kooperationen
|
||||
Social Links und Partneranfragen werden vom Admin-Team gepflegt und koordiniert.
|
||||
""";
|
||||
|
||||
internal const string DefaultSponsorsContent = """
|
||||
Sponsoren & Partner
|
||||
Hier koennen Sponsor:innen, Medienpartner, Community-Partner und Supporter des VTuber Star Awards vorgestellt werden.
|
||||
|
||||
Partner werden im Rahmen der Show und auf den oeffentlichen Kontaktflaechen genannt, sobald sie final bestaetigt sind.
|
||||
""";
|
||||
|
||||
internal static readonly CandidateSeed[] CurrentCandidateSeeds =
|
||||
[
|
||||
new("vtuber-des-jahres", "Hoshimi Miyu", "@hoshimimiyu", "Twitch"),
|
||||
|
||||
@@ -43,8 +43,11 @@ Keine Weitergabe zu Werbezwecken. Technische Dienstleister verarbeiten Daten aus
|
||||
PrivacyPolicyUpdatedBy = "seed",
|
||||
PrivacyPolicyUpdatedAt = new DateTimeOffset(2026, 6, 23, 0, 0, 0, TimeSpan.Zero),
|
||||
ImprintUrl = "https://vtuber-star-awards.de/impressum",
|
||||
ImprintContent = SeedCatalog.DefaultImprintContent,
|
||||
ContactUrl = "https://vtuber-star-awards.de/kontakt",
|
||||
ContactContent = SeedCatalog.DefaultContactContent,
|
||||
SponsorsUrl = "https://vtuber-star-awards.de/partner",
|
||||
SponsorsContent = SeedCatalog.DefaultSponsorsContent,
|
||||
RiskRulesJson = RiskRuleSettings.Serialize(RiskRuleSettings.Defaults),
|
||||
SocialLinksJson = JsonSerializer.Serialize(new[]
|
||||
{
|
||||
|
||||
@@ -40,6 +40,21 @@ public static partial class SeedDataBootstrapper
|
||||
{
|
||||
settings.RiskRulesJson = RiskRuleSettings.Serialize(RiskRuleSettings.Defaults);
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(settings.ImprintContent))
|
||||
{
|
||||
settings.ImprintContent = SeedCatalog.DefaultImprintContent;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(settings.ContactContent))
|
||||
{
|
||||
settings.ContactContent = SeedCatalog.DefaultContactContent;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(settings.SponsorsContent))
|
||||
{
|
||||
settings.SponsorsContent = SeedCatalog.DefaultSponsorsContent;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool HasValidSiteArray(string? json, params string[] requiredKeys)
|
||||
|
||||
Reference in New Issue
Block a user