🐛 Fix bugs

This commit is contained in:
LittleSheep 2025-06-17 00:40:05 +08:00
parent b868d0c153
commit 1a5d0bbfc0
5 changed files with 108 additions and 48 deletions

View File

@ -1,5 +1,6 @@
Keys Keys
Uploads Uploads
DataProtection-Keys
node_modules node_modules
bun.lock bun.lock

View File

@ -192,32 +192,51 @@ public class ConnectionController(
} }
catch (Exception ex) catch (Exception ex)
{ {
return BadRequest($"Error processing callback: {ex.Message}"); return BadRequest($"Error processing {provider} authentication: {ex.Message}");
} }
if (string.IsNullOrEmpty(userInfo.UserId))
{
return BadRequest($"{provider} did not return a valid user identifier.");
}
// Check if this provider account is already connected to any user
var existingConnection = await db.AccountConnections var existingConnection = await db.AccountConnections
.FirstOrDefaultAsync(c => .FirstOrDefaultAsync(c =>
c.Provider.Equals(provider, StringComparison.OrdinalIgnoreCase) && c.Provider.Equals(provider, StringComparison.OrdinalIgnoreCase) &&
c.ProvidedIdentifier == userInfo.UserId); c.ProvidedIdentifier == userInfo.UserId);
// If it's connected to a different user, return error
if (existingConnection != null && existingConnection.AccountId != accountId) if (existingConnection != null && existingConnection.AccountId != accountId)
{ {
return BadRequest($"This {provider} account is already linked to another user."); return BadRequest($"This {provider} account is already linked to another user.");
} }
var userConnection = await db.AccountConnections // Check if the current user already has this provider connected
.FirstOrDefaultAsync(c => var userHasProvider = await db.AccountConnections
c.AccountId == accountId && c.Provider.Equals(provider, StringComparison.OrdinalIgnoreCase)); .AnyAsync(c =>
c.AccountId == accountId &&
c.Provider.Equals(provider, StringComparison.OrdinalIgnoreCase));
var clock = SystemClock.Instance; if (userHasProvider)
if (userConnection != null)
{ {
userConnection.AccessToken = userInfo.AccessToken; // Update existing connection with new tokens
userConnection.RefreshToken = userInfo.RefreshToken; var connection = await db.AccountConnections
userConnection.LastUsedAt = clock.GetCurrentInstant(); .FirstOrDefaultAsync(c =>
c.AccountId == accountId &&
c.Provider.Equals(provider, StringComparison.OrdinalIgnoreCase));
if (connection != null)
{
connection.AccessToken = userInfo.AccessToken;
connection.RefreshToken = userInfo.RefreshToken;
connection.LastUsedAt = SystemClock.Instance.GetCurrentInstant();
connection.Meta = userInfo.ToMetadata();
}
} }
else else
{ {
// Create new connection
db.AccountConnections.Add(new AccountConnection db.AccountConnections.Add(new AccountConnection
{ {
AccountId = accountId, AccountId = accountId,
@ -225,17 +244,26 @@ public class ConnectionController(
ProvidedIdentifier = userInfo.UserId!, ProvidedIdentifier = userInfo.UserId!,
AccessToken = userInfo.AccessToken, AccessToken = userInfo.AccessToken,
RefreshToken = userInfo.RefreshToken, RefreshToken = userInfo.RefreshToken,
LastUsedAt = clock.GetCurrentInstant(), LastUsedAt = SystemClock.Instance.GetCurrentInstant(),
Meta = userInfo.ToMetadata(), Meta = userInfo.ToMetadata(),
}); });
} }
await db.SaveChangesAsync(); try
{
await db.SaveChangesAsync();
}
catch (DbUpdateException ex)
{
return StatusCode(500, $"Failed to save {provider} connection. Please try again.");
}
// Clean up and redirect
var returnUrl = HttpContext.Session.GetString($"oidc_return_url_{callbackData.State}"); var returnUrl = HttpContext.Session.GetString($"oidc_return_url_{callbackData.State}");
HttpContext.Session.Remove($"oidc_return_url_{callbackData.State}"); HttpContext.Session.Remove($"oidc_return_url_{callbackData.State}");
HttpContext.Session.Remove($"oidc_state_{callbackData.State}");
return Redirect(string.IsNullOrEmpty(returnUrl) ? "/" : returnUrl); return Redirect(string.IsNullOrEmpty(returnUrl) ? "/settings/connections" : returnUrl);
} }
private async Task<IActionResult> HandleLoginOrRegistration( private async Task<IActionResult> HandleLoginOrRegistration(

View File

@ -23,7 +23,7 @@ public class OidcController(
{ {
var oidcService = GetOidcService(provider); var oidcService = GetOidcService(provider);
// If user is already authenticated, treat as an account connection request // If the user is already authenticated, treat as an account connection request
if (HttpContext.Items["CurrentUser"] is Account.Account currentUser) if (HttpContext.Items["CurrentUser"] is Account.Account currentUser)
{ {
var state = Guid.NewGuid().ToString(); var state = Guid.NewGuid().ToString();

View File

@ -16,38 +16,39 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3"/> <PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
<PackageReference Include="BlurHashSharp.SkiaSharp" Version="1.3.4"/> <PackageReference Include="BlurHashSharp.SkiaSharp" Version="1.3.4" />
<PackageReference Include="EFCore.BulkExtensions" Version="9.0.1"/> <PackageReference Include="EFCore.BulkExtensions" Version="9.0.1" />
<PackageReference Include="EFCore.BulkExtensions.PostgreSql" Version="9.0.1"/> <PackageReference Include="EFCore.BulkExtensions.PostgreSql" Version="9.0.1" />
<PackageReference Include="EFCore.NamingConventions" Version="9.0.0"/> <PackageReference Include="EFCore.NamingConventions" Version="9.0.0" />
<PackageReference Include="FFMpegCore" Version="5.2.0"/> <PackageReference Include="FFMpegCore" Version="5.2.0" />
<PackageReference Include="Livekit.Server.Sdk.Dotnet" Version="1.0.8" /> <PackageReference Include="Livekit.Server.Sdk.Dotnet" Version="1.0.8" />
<PackageReference Include="MailKit" Version="4.11.0"/> <PackageReference Include="MailKit" Version="4.11.0" />
<PackageReference Include="MaxMind.GeoIP2" Version="5.3.0"/> <PackageReference Include="MaxMind.GeoIP2" Version="5.3.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.4"/> <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.4" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.2"/> <PackageReference Include="Microsoft.AspNetCore.DataProtection.Extensions" Version="8.0.0" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.3"> <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.3">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.4"/> <PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.4" />
<PackageReference Include="MimeTypes" Version="2.5.2"> <PackageReference Include="MimeTypes" Version="2.5.2">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Minio" Version="6.0.4"/> <PackageReference Include="Minio" Version="6.0.4" />
<PackageReference Include="NetVips" Version="3.0.1"/> <PackageReference Include="NetVips" Version="3.0.1" />
<PackageReference Include="NetVips.Native.linux-x64" Version="8.16.1"/> <PackageReference Include="NetVips.Native.linux-x64" Version="8.16.1" />
<PackageReference Include="NetVips.Native.osx-arm64" Version="8.16.1"/> <PackageReference Include="NetVips.Native.osx-arm64" Version="8.16.1" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="NodaTime" Version="3.2.2"/> <PackageReference Include="NodaTime" Version="3.2.2" />
<PackageReference Include="NodaTime.Serialization.JsonNet" Version="3.2.0" /> <PackageReference Include="NodaTime.Serialization.JsonNet" Version="3.2.0" />
<PackageReference Include="NodaTime.Serialization.SystemTextJson" Version="1.3.0"/> <PackageReference Include="NodaTime.Serialization.SystemTextJson" Version="1.3.0" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.4"/> <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.4" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL.Design" Version="1.1.0"/> <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL.Design" Version="1.1.0" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL.NetTopologySuite" Version="9.0.4"/> <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL.NetTopologySuite" Version="9.0.4" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL.NodaTime" Version="9.0.4"/> <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL.NodaTime" Version="9.0.4" />
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.12.0" /> <PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.12.0" />
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.12.0" /> <PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.12.0" />
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.12.0" /> <PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.12.0" />
@ -59,18 +60,18 @@
<PackageReference Include="prometheus-net.DotNetRuntime" Version="4.4.1" /> <PackageReference Include="prometheus-net.DotNetRuntime" Version="4.4.1" />
<PackageReference Include="prometheus-net.EntityFramework" Version="0.9.5" /> <PackageReference Include="prometheus-net.EntityFramework" Version="0.9.5" />
<PackageReference Include="prometheus-net.SystemMetrics" Version="3.1.0" /> <PackageReference Include="prometheus-net.SystemMetrics" Version="3.1.0" />
<PackageReference Include="Quartz" Version="3.14.0"/> <PackageReference Include="Quartz" Version="3.14.0" />
<PackageReference Include="Quartz.AspNetCore" Version="3.14.0"/> <PackageReference Include="Quartz.AspNetCore" Version="3.14.0" />
<PackageReference Include="Quartz.Extensions.Hosting" Version="3.14.0"/> <PackageReference Include="Quartz.Extensions.Hosting" Version="3.14.0" />
<PackageReference Include="SkiaSharp" Version="2.88.9" /> <PackageReference Include="SkiaSharp" Version="2.88.9" />
<PackageReference Include="SkiaSharp.NativeAssets.Linux" Version="2.88.9" /> <PackageReference Include="SkiaSharp.NativeAssets.Linux" Version="2.88.9" />
<PackageReference Include="SkiaSharp.NativeAssets.Linux.NoDependencies" Version="2.88.9" /> <PackageReference Include="SkiaSharp.NativeAssets.Linux.NoDependencies" Version="2.88.9" />
<PackageReference Include="SkiaSharp.NativeAssets.macOS" Version="2.88.9" /> <PackageReference Include="SkiaSharp.NativeAssets.macOS" Version="2.88.9" />
<PackageReference Include="StackExchange.Redis" Version="2.8.37" /> <PackageReference Include="StackExchange.Redis" Version="2.8.37" />
<PackageReference Include="StackExchange.Redis.Extensions.AspNetCore" Version="11.0.0" /> <PackageReference Include="StackExchange.Redis.Extensions.AspNetCore" Version="11.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="8.1.0"/> <PackageReference Include="Swashbuckle.AspNetCore" Version="8.1.0" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="8.1.0"/> <PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="8.1.0" />
<PackageReference Include="tusdotnet" Version="2.8.1"/> <PackageReference Include="tusdotnet" Version="2.8.1" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@ -80,7 +81,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Folder Include="Migrations\"/> <Folder Include="Migrations\" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@ -151,13 +152,13 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<_ContentIncludedByDefault Remove="app\publish\appsettings.json"/> <_ContentIncludedByDefault Remove="app\publish\appsettings.json" />
<_ContentIncludedByDefault Remove="app\publish\DysonNetwork.Sphere.deps.json"/> <_ContentIncludedByDefault Remove="app\publish\DysonNetwork.Sphere.deps.json" />
<_ContentIncludedByDefault Remove="app\publish\DysonNetwork.Sphere.runtimeconfig.json"/> <_ContentIncludedByDefault Remove="app\publish\DysonNetwork.Sphere.runtimeconfig.json" />
<_ContentIncludedByDefault Remove="app\publish\DysonNetwork.Sphere.staticwebassets.endpoints.json"/> <_ContentIncludedByDefault Remove="app\publish\DysonNetwork.Sphere.staticwebassets.endpoints.json" />
<_ContentIncludedByDefault Remove="app\publish\Keys\Solian.json"/> <_ContentIncludedByDefault Remove="app\publish\Keys\Solian.json" />
<_ContentIncludedByDefault Remove="app\publish\package-lock.json"/> <_ContentIncludedByDefault Remove="app\publish\package-lock.json" />
<_ContentIncludedByDefault Remove="app\publish\package.json"/> <_ContentIncludedByDefault Remove="app\publish\package.json" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -35,6 +35,7 @@ using Quartz;
using StackExchange.Redis; using StackExchange.Redis;
using tusdotnet; using tusdotnet;
using tusdotnet.Stores; using tusdotnet.Stores;
using Microsoft.AspNetCore.DataProtection;
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
@ -90,12 +91,41 @@ builder.Services.AddSingleton<ICacheService, CacheServiceRedis>();
builder.Services.AddHttpClient(); builder.Services.AddHttpClient();
// Configure Data Protection for persistent session keys
var keysDirectory = Path.Combine(builder.Environment.ContentRootPath, "DataProtection-Keys");
Directory.CreateDirectory(keysDirectory);
builder.Services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(keysDirectory))
.SetApplicationName("DysonNetwork.Sphere");
// Configure cookie policy to be essential for session
builder.Services.Configure<CookiePolicyOptions>(options =>
{
options.CheckConsentNeeded = _ => false; // Required for session to work without consent
options.MinimumSameSitePolicy = SameSiteMode.Lax;
});
// Add session with consistent cookie settings
builder.Services.AddSession(options =>
{
options.Cookie.Name = "_dynses";
options.Cookie.HttpOnly = true;
options.Cookie.IsEssential = true;
options.IdleTimeout = TimeSpan.FromMinutes(30);
});
// Register OIDC services // Register OIDC services
builder.Services.AddScoped<OidcService, GoogleOidcService>(); builder.Services.AddScoped<OidcService, GoogleOidcService>();
builder.Services.AddScoped<OidcService, AppleOidcService>(); builder.Services.AddScoped<OidcService, AppleOidcService>();
builder.Services.AddScoped<OidcService, GitHubOidcService>(); builder.Services.AddScoped<OidcService, GitHubOidcService>();
builder.Services.AddScoped<OidcService, MicrosoftOidcService>(); builder.Services.AddScoped<OidcService, MicrosoftOidcService>();
builder.Services.AddScoped<OidcService, DiscordOidcService>(); builder.Services.AddScoped<OidcService, DiscordOidcService>();
builder.Services.AddScoped<GoogleOidcService>();
builder.Services.AddScoped<AppleOidcService>();
builder.Services.AddScoped<GitHubOidcService>();
builder.Services.AddScoped<MicrosoftOidcService>();
builder.Services.AddScoped<DiscordOidcService>();
builder.Services.AddControllers().AddJsonOptions(options => builder.Services.AddControllers().AddJsonOptions(options =>
{ {
options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower; options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower;