Add viewer-range categories, nomination tracking, dynamic showact form, session timeout, share URLs, and workflow-per-season
Features: - Category viewer ranges + subcategory templates (admin group modal, tree workspace) - Nomination enrichment via TwitchTracker API (NominationEnrichmentService, TwitchTrackerViewerStatsProvider) with admin tracking rules editor - Nomination group tracker: CategoryGroupName as primary identifier, CategoryId stays as nullable legacy field; StreamerIdentity table - Dynamic showact application form builder (AdminShowactFormBuilder, ShowactApplicationSchedule) - Session idle timeout setting (AdminSessionTimeoutCard) - Share URLs for X and Discord (SiteSettings, public extras) - Workflow rules now stored per season (falls back to global SiteSettings) - New admin routes: settings/access, settings/workflows, tracking-rules - New admin review workspace with subcategory tabs - AdminCategoriesView rebuilt with group/subcategory modals Migrations (all additive): - AddShareUrls, AddShowactDynamicForm, AddCategoryViewerRanges, AddSessionIdleTimeoutSettings, AddSeasonSubcategoryTemplates, AddNominationGroupTrackerIdentity, AddShowactApplicationSchedule, AddSeasonWorkflowRulesJson Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -12,6 +12,7 @@ public static partial class AuthEndpoints
|
||||
{
|
||||
private static async Task<IResult> DemoLogin(
|
||||
HttpContext context,
|
||||
IHostEnvironment environment,
|
||||
AwardsDbContext db,
|
||||
IConfiguration configuration,
|
||||
DemoLoginRequest request,
|
||||
@@ -23,11 +24,16 @@ public static partial class AuthEndpoints
|
||||
var password = request.Password ?? string.Empty;
|
||||
var settings = await db.SiteSettings.AsNoTracking().FirstOrDefaultAsync(item => item.Id == 1, context.RequestAborted);
|
||||
var databaseDemoConfigured = settings is not null
|
||||
&& (settings.DemoLoginManagedByDatabase || HasDatabaseDemoCredentials(settings));
|
||||
&& settings.DemoLoginManagedByDatabase;
|
||||
|
||||
string twitchUserId;
|
||||
string displayName;
|
||||
bool credentialsMatch;
|
||||
var fallbackConfiguredLogin = ReadDemoLoginIdentifier(configuration);
|
||||
var fallbackConfiguredEmail = ReadDemoSetting(configuration, "Email", "VTSA_DEMO_ADMIN_EMAIL");
|
||||
var fallbackConfiguredPassword = ReadDemoSetting(configuration, "Password", "VTSA_DEMO_ADMIN_PASSWORD");
|
||||
var fallbackConfiguredTwitchUserId = ReadDemoSetting(configuration, "TwitchUserId", "VTSA_DEMO_ADMIN_TWITCH_ID");
|
||||
var fallbackConfiguredDisplayName = ReadDemoSetting(configuration, "DisplayName", "VTSA_DEMO_ADMIN_DISPLAY_NAME");
|
||||
|
||||
if (databaseDemoConfigured && settings is not null)
|
||||
{
|
||||
@@ -53,6 +59,25 @@ public static partial class AuthEndpoints
|
||||
&& DemoCredentialHasher.VerifyPassword(password, settings.DemoLoginPasswordHash, settings.DemoLoginPasswordSalt);
|
||||
twitchUserId = settings.DemoLoginTwitchUserId.Trim();
|
||||
displayName = settings.DemoLoginDisplayName.Trim();
|
||||
|
||||
if (!credentialsMatch
|
||||
&& environment.IsDevelopment()
|
||||
&& IsDemoLoginEnabled(configuration)
|
||||
&& !string.IsNullOrWhiteSpace(fallbackConfiguredLogin)
|
||||
&& !string.IsNullOrWhiteSpace(fallbackConfiguredPassword)
|
||||
&& !string.IsNullOrWhiteSpace(fallbackConfiguredTwitchUserId)
|
||||
&& !string.IsNullOrWhiteSpace(fallbackConfiguredDisplayName))
|
||||
{
|
||||
credentialsMatch = LoginMatchesIdentifier(
|
||||
login,
|
||||
fallbackConfiguredLogin,
|
||||
fallbackConfiguredEmail,
|
||||
fallbackConfiguredTwitchUserId,
|
||||
fallbackConfiguredDisplayName)
|
||||
&& DemoCredentialHasher.FixedTimePlainTextEquals(password, fallbackConfiguredPassword);
|
||||
twitchUserId = fallbackConfiguredTwitchUserId.Trim();
|
||||
displayName = fallbackConfiguredDisplayName.Trim();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -61,16 +86,10 @@ public static partial class AuthEndpoints
|
||||
return Results.NotFound();
|
||||
}
|
||||
|
||||
var configuredLogin = ReadDemoLoginIdentifier(configuration);
|
||||
var configuredEmail = ReadDemoSetting(configuration, "Email", "VTSA_DEMO_ADMIN_EMAIL");
|
||||
var configuredPassword = ReadDemoSetting(configuration, "Password", "VTSA_DEMO_ADMIN_PASSWORD");
|
||||
twitchUserId = ReadDemoSetting(configuration, "TwitchUserId", "VTSA_DEMO_ADMIN_TWITCH_ID");
|
||||
displayName = ReadDemoSetting(configuration, "DisplayName", "VTSA_DEMO_ADMIN_DISPLAY_NAME");
|
||||
|
||||
if (string.IsNullOrWhiteSpace(configuredLogin)
|
||||
|| string.IsNullOrWhiteSpace(configuredPassword)
|
||||
|| string.IsNullOrWhiteSpace(twitchUserId)
|
||||
|| string.IsNullOrWhiteSpace(displayName))
|
||||
if (string.IsNullOrWhiteSpace(fallbackConfiguredLogin)
|
||||
|| string.IsNullOrWhiteSpace(fallbackConfiguredPassword)
|
||||
|| string.IsNullOrWhiteSpace(fallbackConfiguredTwitchUserId)
|
||||
|| string.IsNullOrWhiteSpace(fallbackConfiguredDisplayName))
|
||||
{
|
||||
return Results.Json(
|
||||
new { message = "Demo login is not fully configured." },
|
||||
@@ -79,13 +98,13 @@ public static partial class AuthEndpoints
|
||||
|
||||
credentialsMatch = LoginMatchesIdentifier(
|
||||
login,
|
||||
configuredLogin,
|
||||
configuredEmail,
|
||||
twitchUserId,
|
||||
displayName)
|
||||
&& DemoCredentialHasher.FixedTimePlainTextEquals(password, configuredPassword);
|
||||
twitchUserId = twitchUserId.Trim();
|
||||
displayName = displayName.Trim();
|
||||
fallbackConfiguredLogin,
|
||||
fallbackConfiguredEmail,
|
||||
fallbackConfiguredTwitchUserId,
|
||||
fallbackConfiguredDisplayName)
|
||||
&& DemoCredentialHasher.FixedTimePlainTextEquals(password, fallbackConfiguredPassword);
|
||||
twitchUserId = fallbackConfiguredTwitchUserId.Trim();
|
||||
displayName = fallbackConfiguredDisplayName.Trim();
|
||||
}
|
||||
|
||||
if (!credentialsMatch)
|
||||
@@ -137,7 +156,7 @@ public static partial class AuthEndpoints
|
||||
await db.SaveChangesAsync(context.RequestAborted);
|
||||
}
|
||||
|
||||
return Results.Ok(await ToAuthSessionDtoAsync(db, session, false, context.RequestAborted));
|
||||
return Results.Ok(await ToAuthSessionDtoAsync(db, userSessionService, session, false, context.RequestAborted));
|
||||
}
|
||||
|
||||
private static bool IsDemoLoginEnabled(IConfiguration configuration)
|
||||
|
||||
Reference in New Issue
Block a user