Refactor app architecture and clean local artifacts
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
using Backend.Common;
|
||||
using Backend.Contracts;
|
||||
using Backend.Data;
|
||||
using Backend.Security;
|
||||
using Backend.Services;
|
||||
|
||||
namespace Backend.Endpoints;
|
||||
|
||||
public static partial class AuthEndpoints
|
||||
{
|
||||
private const int MaxTwitchUserIdLength = 64;
|
||||
private const int MaxDisplayNameLength = 80;
|
||||
|
||||
private static async Task<IResult> DevLogin(
|
||||
HttpContext context,
|
||||
IHostEnvironment environment,
|
||||
LoginRequest request,
|
||||
AwardsDbContext db,
|
||||
IUserSessionService userSessionService,
|
||||
IRiskFlagService riskFlagService,
|
||||
IRiskRuleService riskRuleService)
|
||||
{
|
||||
if (!environment.IsDevelopment())
|
||||
{
|
||||
return Results.NotFound();
|
||||
}
|
||||
|
||||
var normalizedTwitchUserId = request.TwitchUserId?.Trim() ?? string.Empty;
|
||||
var normalizedDisplayName = request.DisplayName?.Trim() ?? string.Empty;
|
||||
var normalizedRole = AdminRoles.Normalize(request.Role);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(normalizedTwitchUserId) || normalizedTwitchUserId.Length > MaxTwitchUserIdLength)
|
||||
{
|
||||
return Results.BadRequest(new { message = $"Twitch user id is required and must stay below {MaxTwitchUserIdLength} characters." });
|
||||
}
|
||||
|
||||
if (!normalizedTwitchUserId.All(value => char.IsLetterOrDigit(value) || value is '_' or '-'))
|
||||
{
|
||||
return Results.BadRequest(new { message = "Twitch user id contains unsupported characters." });
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(normalizedDisplayName) || normalizedDisplayName.Length > MaxDisplayNameLength)
|
||||
{
|
||||
return Results.BadRequest(new { message = $"Display name is required and must stay below {MaxDisplayNameLength} characters." });
|
||||
}
|
||||
|
||||
if (!AdminRoles.IsKnownRole(request.Role))
|
||||
{
|
||||
return Results.BadRequest(new { message = "Role must be viewer, content_admin, admin or owner." });
|
||||
}
|
||||
|
||||
var requestMetadata = RequestMetadataReader.Read(context);
|
||||
var session = await userSessionService.CreateDevSessionAsync(
|
||||
request with
|
||||
{
|
||||
TwitchUserId = normalizedTwitchUserId,
|
||||
DisplayName = normalizedDisplayName,
|
||||
Role = normalizedRole,
|
||||
},
|
||||
requestMetadata,
|
||||
context.RequestAborted);
|
||||
|
||||
var rapidLoginRule = await riskRuleService.GetRuleAsync("rapid_login_ip", context.RequestAborted);
|
||||
var recentSessionsFromIp = await userSessionService.CountRecentSessionsFromIpAsync(
|
||||
requestMetadata.ClientIp,
|
||||
DateTimeOffset.UtcNow.AddMinutes(-rapidLoginRule.WindowMinutes),
|
||||
context.RequestAborted);
|
||||
|
||||
if (rapidLoginRule.Enabled && recentSessionsFromIp >= rapidLoginRule.Threshold)
|
||||
{
|
||||
await riskFlagService.AddIfMissingAsync(
|
||||
null,
|
||||
session.TwitchUserId,
|
||||
"login",
|
||||
"rapid_login_ip",
|
||||
rapidLoginRule.Severity,
|
||||
"Mehrere neue Sessions wurden in kurzer Zeit von derselben IP erzeugt.",
|
||||
requestMetadata,
|
||||
new
|
||||
{
|
||||
recentSessionsFromIp,
|
||||
threshold = rapidLoginRule.Threshold,
|
||||
windowMinutes = rapidLoginRule.WindowMinutes,
|
||||
entityLinks = new[]
|
||||
{
|
||||
new
|
||||
{
|
||||
label = "Audit-Log öffnen",
|
||||
entityType = "session",
|
||||
entityId = session.TwitchUserId,
|
||||
to = $"/admin/users-logs?query={Uri.EscapeDataString(session.TwitchUserId)}",
|
||||
},
|
||||
},
|
||||
},
|
||||
context.RequestAborted);
|
||||
await db.SaveChangesAsync(context.RequestAborted);
|
||||
}
|
||||
|
||||
return Results.Ok(ToAuthSessionDto(session));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user