mirror of
https://github.com/spacebarchat/server.git
synced 2026-08-28 13:54:08 +00:00
cdn-cs updates
This commit is contained in:
@@ -53,4 +53,12 @@ public class GetImageController(LruFileCache lfc, IFileSource fs, DiscordImageRe
|
||||
// byte array with mime type result
|
||||
return new FileContentResult(entry.Data, entry.MimeType);
|
||||
}
|
||||
|
||||
// TODO: is message_id required? Can't tell from discord.food: /attachments/{channel_id}/[{message_id]/attachment_id}/{attachment_filename}
|
||||
[HttpGet("/attachments/{channel_id:required}/{message_id:required}/{attachment_id:required}/{filename:required}")]
|
||||
[HttpGet("/ephemeral-attachments/{application_id:required}/{attachment_id:required}/{attachment_filename:required}")]
|
||||
public async Task<IActionResult> GetAttachmentImage() {
|
||||
// TODO: url signing, file type checks
|
||||
return await GetImage("");
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ using Spacebar.Cdn.Extensions;
|
||||
using Spacebar.Interop.Cdn.Abstractions;
|
||||
|
||||
namespace Spacebar.Cdn.Controllers.Internal;
|
||||
|
||||
/*
|
||||
[ApiController]
|
||||
public class IsPixelArtController(LruFileCache lfc, IFileSource fs, PixelArtDetectionService pads, DiscordImageResizeService dirs) : ControllerBase {
|
||||
private static readonly LruCache<bool> _isPixelArtCache = new(100_000);
|
||||
@@ -145,4 +145,5 @@ public class IsPixelArtController(LruFileCache lfc, IFileSource fs, PixelArtDete
|
||||
};
|
||||
}).ContinueWith(t => File(t.Result.Data, t.Result.MimeType));
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
@@ -41,6 +41,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Spacebar.Cdn.Fsck", "Utilit
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Spacebar.Interop.Cdn.Abstractions", "Interop\Spacebar.Interop.Cdn.Abstractions\Spacebar.Interop.Cdn.Abstractions.csproj", "{B494C58D-2D53-49F4-9E3E-1DCF60828802}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Spacebar.Cdn.Migration", "Utilities\Spacebar.Cdn.Migration\Spacebar.Cdn.Migration.csproj", "{2B18EB6B-331D-41A9-A9D1-C2518E2AD914}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Spacebar.Interop.Cdn.Signing", "Interop\Spacebar.Interop.Cdn.Signing\Spacebar.Interop.Cdn.Signing.csproj", "{95A8E8CC-53B2-4FC6-B41E-196BE5F96BB5}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -243,6 +247,30 @@ Global
|
||||
{B494C58D-2D53-49F4-9E3E-1DCF60828802}.Release|x64.Build.0 = Release|Any CPU
|
||||
{B494C58D-2D53-49F4-9E3E-1DCF60828802}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{B494C58D-2D53-49F4-9E3E-1DCF60828802}.Release|x86.Build.0 = Release|Any CPU
|
||||
{2B18EB6B-331D-41A9-A9D1-C2518E2AD914}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2B18EB6B-331D-41A9-A9D1-C2518E2AD914}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2B18EB6B-331D-41A9-A9D1-C2518E2AD914}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{2B18EB6B-331D-41A9-A9D1-C2518E2AD914}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{2B18EB6B-331D-41A9-A9D1-C2518E2AD914}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{2B18EB6B-331D-41A9-A9D1-C2518E2AD914}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{2B18EB6B-331D-41A9-A9D1-C2518E2AD914}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2B18EB6B-331D-41A9-A9D1-C2518E2AD914}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2B18EB6B-331D-41A9-A9D1-C2518E2AD914}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{2B18EB6B-331D-41A9-A9D1-C2518E2AD914}.Release|x64.Build.0 = Release|Any CPU
|
||||
{2B18EB6B-331D-41A9-A9D1-C2518E2AD914}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{2B18EB6B-331D-41A9-A9D1-C2518E2AD914}.Release|x86.Build.0 = Release|Any CPU
|
||||
{95A8E8CC-53B2-4FC6-B41E-196BE5F96BB5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{95A8E8CC-53B2-4FC6-B41E-196BE5F96BB5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{95A8E8CC-53B2-4FC6-B41E-196BE5F96BB5}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{95A8E8CC-53B2-4FC6-B41E-196BE5F96BB5}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{95A8E8CC-53B2-4FC6-B41E-196BE5F96BB5}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{95A8E8CC-53B2-4FC6-B41E-196BE5F96BB5}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{95A8E8CC-53B2-4FC6-B41E-196BE5F96BB5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{95A8E8CC-53B2-4FC6-B41E-196BE5F96BB5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{95A8E8CC-53B2-4FC6-B41E-196BE5F96BB5}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{95A8E8CC-53B2-4FC6-B41E-196BE5F96BB5}.Release|x64.Build.0 = Release|Any CPU
|
||||
{95A8E8CC-53B2-4FC6-B41E-196BE5F96BB5}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{95A8E8CC-53B2-4FC6-B41E-196BE5F96BB5}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@@ -262,5 +290,7 @@ Global
|
||||
{2D8F75C2-C4DC-4DBC-A880-5BF021D637E5} = {16DBEA54-D51A-4D91-84DF-C701B6B4786F}
|
||||
{05B1FEDA-1112-49C8-B7E8-539B5ED8C05D} = {04787943-EBB6-4DE4-96D5-4CFB4A2CEE99}
|
||||
{B494C58D-2D53-49F4-9E3E-1DCF60828802} = {16DBEA54-D51A-4D91-84DF-C701B6B4786F}
|
||||
{2B18EB6B-331D-41A9-A9D1-C2518E2AD914} = {04787943-EBB6-4DE4-96D5-4CFB4A2CEE99}
|
||||
{95A8E8CC-53B2-4FC6-B41E-196BE5F96BB5} = {16DBEA54-D51A-4D91-84DF-C701B6B4786F}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
||||
@@ -5,7 +5,8 @@ using Spacebar.Interop.Cdn.Abstractions;
|
||||
using Spacebar.Models.Db.Contexts;
|
||||
|
||||
var builder = Host.CreateApplicationBuilder(args);
|
||||
builder.Services.AddSingleton<IFileSource>(new ProxyFileSource("http://cdn.old.server.spacebar.chat"));
|
||||
// builder.Services.AddSingleton<IFileSource>(new ProxyFileSource("http://cdn.old.server.spacebar.chat"));
|
||||
builder.Services.AddSingleton<IFileSource>(new FilesystemFileSource("/mnt/data/dedicated/spacebar-storage"));
|
||||
builder.Services.AddSingleton<LruFileCache>(new LruFileCache(1*1024*1024*1024));
|
||||
builder.Services.AddHostedService<FsckService>();
|
||||
|
||||
@@ -18,4 +19,5 @@ builder.Services.AddDbContextPool<SpacebarDbContext>(options => {
|
||||
StreamingHttpClient.LogRequests = false;
|
||||
|
||||
var host = builder.Build();
|
||||
await host.Services.GetRequiredService<IFileSource>().Init();
|
||||
host.Start();
|
||||
@@ -0,0 +1,210 @@
|
||||
using System.Diagnostics;
|
||||
using ArcaneLibs.Extensions;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Spacebar.Interop.Cdn.Signing;
|
||||
using Spacebar.Models.Db.Contexts;
|
||||
|
||||
namespace Spacebar.Cdn.Fsck;
|
||||
|
||||
public class FsckService(ILogger<FsckService> logger, IServiceScopeFactory serviceScopeFactory, MigrationFileStores stores, CdnSigningService sigService) : IHostedService {
|
||||
private SpacebarDbContext _db = null!;
|
||||
|
||||
public async Task StartAsync(CancellationToken cancellationToken) {
|
||||
var sw = Stopwatch.StartNew();
|
||||
await using var scope = serviceScopeFactory.CreateAsyncScope();
|
||||
_db = scope.ServiceProvider.GetRequiredService<SpacebarDbContext>();
|
||||
logger.LogInformation("Starting migrations from {source} to {dest}...", $"{stores.From.GetType().FullName}({stores.From.BaseUrl})",
|
||||
$"{stores.To.GetType().FullName}({stores.To.BaseUrl})");
|
||||
await RunFsckAsync("User Avatars", "/avatars", EnumerateUserAvatarFilesAsync(), cancellationToken);
|
||||
await RunFsckAsync("User Banners", "/banners", EnumerateUserBannerPathsAsync(), cancellationToken);
|
||||
await RunFsckAsync("Guild Icons", "/icons", EnumerateGuildIconPathsAsync(), cancellationToken);
|
||||
await RunFsckAsync("Stickers", "/stickers", EnumerateStickerPathsAsync(), cancellationToken);
|
||||
await RunFsckAsync("Emojis", "/emojis", EnumerateEmojiPathsAsync(), cancellationToken);
|
||||
|
||||
// var atts = EnumerateAttachmentPathsAsync();
|
||||
// var refreshedAtts = new List<FsckItem>();
|
||||
// var attRefreshedTasks = atts.Chunk(40).Select(async x => {
|
||||
// var req =
|
||||
// return new FsckItem[10];
|
||||
// });
|
||||
// await foreach (var attRefreshedChunk in attRefreshedTasks.ToAsyncResultEnumerable()) {
|
||||
// refreshedAtts.AddRange(attRefreshedChunk);
|
||||
// }
|
||||
|
||||
await RunFsckAsync("Attachments", "/attachments", EnumerateAttachmentPathsAsync(), cancellationToken);
|
||||
logger.LogInformation("Fsck complete in {time}.", sw.Elapsed);
|
||||
}
|
||||
|
||||
public async Task StopAsync(CancellationToken cancellationToken) { }
|
||||
|
||||
private readonly Stopwatch _lastUpdateSw = Stopwatch.StartNew();
|
||||
private readonly SemaphoreSlim _fsckSemaphore = new(32, 32);
|
||||
|
||||
public struct FsckItem {
|
||||
public string Path;
|
||||
public string ItemId;
|
||||
}
|
||||
|
||||
private async Task RunFsckAsync(string name, string path, IQueryable<FsckItem> items, CancellationToken? cancellationToken = null) {
|
||||
int i = 0, notFound = 0, alreadyLocal = 0, count = await items.CountAsync();
|
||||
List<Task> tasks = [];
|
||||
|
||||
await foreach (var item in items.AsAsyncEnumerable()) {
|
||||
tasks.Add(Task.Run(async () => {
|
||||
try {
|
||||
await _fsckSemaphore.WaitAsync();
|
||||
if (cancellationToken?.IsCancellationRequested ?? false)
|
||||
return;
|
||||
|
||||
if (await stores.To.FileExists(item.Path)) {
|
||||
alreadyLocal++;
|
||||
logger.LogInformation("TO: {itemType} {itemId} already exists at {path}, skipping.", name, item.ItemId, item.Path);
|
||||
}
|
||||
else if (!await stores.From.FileExists(item.Path)) {
|
||||
notFound++;
|
||||
logger.LogWarning("FROM: {itemType} {itemId} is missing at {path}", name, item.ItemId, stores.From.BaseUrl + item.Path);
|
||||
}
|
||||
else {
|
||||
// logger.LogInformation("Migrating {itemType} {itemId} at {path}", name, item.ItemId, item.Path);
|
||||
await using var f = await stores.From.GetFile(item.Path);
|
||||
// logger.LogInformation("Got file {itemType} {itemId} at {path}, writing to destination...", name, item.ItemId, item.Path);
|
||||
await stores.To.WriteFile(item.Path, f.Stream);
|
||||
}
|
||||
|
||||
if (true || _lastUpdateSw.ElapsedMilliseconds >= 1000 / 30 || i == 0) {
|
||||
_lastUpdateSw.Restart();
|
||||
Console.Write($"{name} download: {i}/{count}: {item.Path,-64}\r");
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
logger.LogError(ex, "Error processing {itemType} {itemId} at {path}: {message}", name, item.ItemId, item.Path, ex.Message);
|
||||
}
|
||||
finally {
|
||||
_fsckSemaphore.Release();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
await Task.WhenAll(tasks);
|
||||
logger.LogInformation("Validated {count} items for {path}: {alreadyLocal} already local, {notFound} not found", i, path, alreadyLocal, notFound);
|
||||
}
|
||||
|
||||
#region User Assets
|
||||
|
||||
public IQueryable<FsckItem> EnumerateUserAvatarFilesAsync() =>
|
||||
_db.Users
|
||||
.Where(x => !string.IsNullOrWhiteSpace(x.Avatar))
|
||||
.OrderBy(x => x.Id)
|
||||
.Select(x => new FsckItem {
|
||||
Path = $"/avatars/{x.Id}/{x.Avatar}",
|
||||
ItemId = x.Id
|
||||
});
|
||||
|
||||
public IQueryable<FsckItem> EnumerateUserBannerPathsAsync() =>
|
||||
_db.Users
|
||||
.Where(x => !string.IsNullOrWhiteSpace(x.Banner))
|
||||
.OrderBy(x => x.Id)
|
||||
.Select(x => new FsckItem {
|
||||
Path = $"/banners/{x.Id}/{x.Banner}",
|
||||
ItemId = x.Id
|
||||
});
|
||||
|
||||
#endregion
|
||||
|
||||
#region Guild Assets
|
||||
|
||||
public IQueryable<FsckItem> EnumerateGuildIconPathsAsync() =>
|
||||
_db.Guilds
|
||||
.Where(x => !string.IsNullOrWhiteSpace(x.Icon))
|
||||
.OrderBy(x => x.Id)
|
||||
.Select(x => new FsckItem {
|
||||
Path = $"/icons/{x.Id}/{x.Icon}",
|
||||
ItemId = x.Id
|
||||
});
|
||||
|
||||
public IQueryable<FsckItem> EnumerateRoleIconPathsAsync() =>
|
||||
_db.Roles
|
||||
.Where(x => !string.IsNullOrWhiteSpace(x.Icon))
|
||||
.OrderBy(x => x.Id)
|
||||
.Select(x => new FsckItem {
|
||||
Path = $"/role-icons/{x.Id}/{x.Icon}",
|
||||
ItemId = x.Id
|
||||
});
|
||||
|
||||
public IQueryable<FsckItem> EnumerateStickerPathsAsync() =>
|
||||
_db.Stickers
|
||||
.OrderBy(x => x.Id)
|
||||
.Select(x => new FsckItem {
|
||||
Path = $"/stickers/{x.Id}.png",
|
||||
ItemId = x.Id
|
||||
});
|
||||
|
||||
public IQueryable<FsckItem> EnumerateEmojiPathsAsync() =>
|
||||
_db.Emojis
|
||||
.OrderBy(x => x.Id)
|
||||
.Select(x => new FsckItem {
|
||||
Path = $"/emojis/{x.Id}",
|
||||
ItemId = x.Id
|
||||
});
|
||||
|
||||
#endregion
|
||||
|
||||
#region Application Assets
|
||||
|
||||
public IQueryable<FsckItem> EnumerateApplicationIconPathsAsync() =>
|
||||
_db.Applications
|
||||
.Where(x => !string.IsNullOrWhiteSpace(x.Icon))
|
||||
.OrderBy(x => x.Id)
|
||||
.Select(x => new FsckItem {
|
||||
Path = $"/app-icons/{x.Id}/{x.Icon}",
|
||||
ItemId = x.Id
|
||||
});
|
||||
|
||||
public IQueryable<FsckItem> EnumerateApplicationCoverPathsAsync() =>
|
||||
_db.Applications
|
||||
.Where(x => !string.IsNullOrWhiteSpace(x.Icon))
|
||||
.OrderBy(x => x.Id)
|
||||
.Select(x => new FsckItem {
|
||||
Path = $"/app-icons/{x.Id}/{x.CoverImage}",
|
||||
ItemId = x.Id
|
||||
});
|
||||
|
||||
// TODO: not implemented?
|
||||
// public IQueryable<FsckItem> EnumerateApplicationSplashPathsAsync() =>
|
||||
// _db.Applications
|
||||
// .Where(x => !string.IsNullOrWhiteSpace(x.Icon))
|
||||
// .OrderBy(x => x.Id)
|
||||
// .Select(x => new FsckItem {
|
||||
// Path = $"/app-icons/{x.Id}/{x.OwnerId}", // TODO - no db property for splash?
|
||||
// ItemId = x.Id
|
||||
// });
|
||||
//
|
||||
// public IQueryable<FsckItem> EnumerateApplicationAssets() =>
|
||||
// _db.Applications
|
||||
// .Where(x => !string.IsNullOrWhiteSpace(x.Icon))
|
||||
// .OrderBy(x => x.Id)
|
||||
// .Select(x => new FsckItem {
|
||||
// Path = $"/app-icons/{x.Id}/{x.Icon}",
|
||||
// ItemId = x.Id
|
||||
// });
|
||||
|
||||
#endregion
|
||||
|
||||
#region Attachments
|
||||
|
||||
public IQueryable<FsckItem> EnumerateAttachmentPathsAsync() =>
|
||||
_db.Attachments
|
||||
.OrderBy(x => x.Id)
|
||||
.Select(x => new FsckItem {
|
||||
Path = sigService.Sign(new() {
|
||||
Path = $"/attachments/{x.Message!.ChannelId}/{x.Id}/{x.Filename}",
|
||||
IpAddress = "109.128.185.4"
|
||||
}).GetSignedPath(),
|
||||
// Path = $"/attachments/{x.Message!.ChannelId}/{x.Id}/{x.Filename}",
|
||||
ItemId = x.Id
|
||||
});
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
using Spacebar.Interop.Cdn.Abstractions;
|
||||
|
||||
namespace Spacebar.Cdn.Fsck;
|
||||
|
||||
public class MigrationFileStores {
|
||||
public required IFileSource From { get; init; }
|
||||
public required IFileSource To { get; init; }
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
using System.Buffers.Text;
|
||||
using ArcaneLibs;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Spacebar.Cdn.Fsck;
|
||||
using Spacebar.Interop.Cdn.Abstractions;
|
||||
using Spacebar.Interop.Cdn.Signing;
|
||||
using Spacebar.Models.Db.Contexts;
|
||||
|
||||
var builder = Host.CreateApplicationBuilder(args);
|
||||
// builder.Services.AddSingleton<IFileSource>(new ProxyFileSource("http://cdn.old.server.spacebar.chat"));
|
||||
IFileSource fromSrc, toSrc;
|
||||
|
||||
if (args.Length != 2) {
|
||||
Console.WriteLine("Usage: Spacebar.Cdn.Migration <from-path> <to-path>");
|
||||
return;
|
||||
}
|
||||
|
||||
if (args[0].StartsWith("http://"))
|
||||
fromSrc = new ProxyFileSource(args[0]);
|
||||
else
|
||||
fromSrc = new FilesystemFileSource(args[0]);
|
||||
|
||||
if (args[1].StartsWith("http://"))
|
||||
toSrc = new ProxyFileSource(args[1]);
|
||||
else
|
||||
toSrc = new FilesystemFileSource(args[1]);
|
||||
|
||||
builder.Services.AddSingleton(new MigrationFileStores() {
|
||||
From = fromSrc,
|
||||
To = toSrc
|
||||
});
|
||||
|
||||
builder.Services.AddSingleton<CdnSigningService>(sp =>
|
||||
new CdnSigningService(
|
||||
sp.GetRequiredService<ILogger<CdnSigningService>>(),
|
||||
Convert.FromBase64String(""),
|
||||
false,
|
||||
true,
|
||||
TimeSpan.FromMinutes(5)
|
||||
)
|
||||
);
|
||||
builder.Services.AddHostedService<FsckService>();
|
||||
|
||||
builder.Services.AddDbContextPool<SpacebarDbContext>(options => {
|
||||
options
|
||||
.UseNpgsql(builder.Configuration.GetConnectionString("Spacebar"))
|
||||
.EnableDetailedErrors();
|
||||
});
|
||||
|
||||
StreamingHttpClient.LogRequests = false;
|
||||
|
||||
var host = builder.Build();
|
||||
|
||||
await host.Services.GetRequiredService<MigrationFileStores>().From.Init();
|
||||
await host.Services.GetRequiredService<MigrationFileStores>().To.Init();
|
||||
|
||||
host.Start();
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/launchsettings.json",
|
||||
"profiles": {
|
||||
"Development": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"Local": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Local"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Worker">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<UserSecretsId>dotnet-Spacebar.Cdn.Fsck-a4aee86f-7e64-4c71-88d7-d2a76cc8b77e</UserSecretsId>
|
||||
<NoDefaultLaunchSettingsFile>True</NoDefaultLaunchSettingsFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="10.0.2"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Interop\Spacebar.Interop.Cdn.Abstractions\Spacebar.Interop.Cdn.Abstractions.csproj" />
|
||||
<ProjectReference Include="..\..\Interop\Spacebar.Interop.Cdn.Signing\Spacebar.Interop.Cdn.Signing.csproj" />
|
||||
<ProjectReference Include="..\..\Models\Spacebar.Models.Db\Spacebar.Models.Db.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,332 @@
|
||||
[
|
||||
{
|
||||
"pname": "ArcaneLibs",
|
||||
"version": "1.0.1-preview.20260126-091403",
|
||||
"hash": "sha256-CSmNE16nDi05qyDAcJR+8SqQQ2ReAeX0+/dRP3WpNsg="
|
||||
},
|
||||
{
|
||||
"pname": "Humanizer.Core",
|
||||
"version": "2.14.1",
|
||||
"hash": "sha256-EXvojddPu+9JKgOG9NSQgUTfWq1RpOYw7adxDPKDJ6o="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.Build.Framework",
|
||||
"version": "17.11.31",
|
||||
"hash": "sha256-YS4oASrmC5dmZrx5JPS7SfKmUpIJErlUpVDsU3VrfFE="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.Build.Framework",
|
||||
"version": "18.0.2",
|
||||
"hash": "sha256-fO31KAdDs2J0RUYD1ov9UB3ucsbALan7K0YdWW+yg7A="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.CodeAnalysis.Analyzers",
|
||||
"version": "3.11.0",
|
||||
"hash": "sha256-hQ2l6E6PO4m7i+ZsfFlEx+93UsLPo4IY3wDkNG11/Sw="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.CodeAnalysis.Common",
|
||||
"version": "5.0.0",
|
||||
"hash": "sha256-g4ALvBSNyHEmSb1l5TFtWW7zEkiRmhqLx4XWZu9sr2U="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.CodeAnalysis.CSharp",
|
||||
"version": "5.0.0",
|
||||
"hash": "sha256-ctBCkQGFpH/xT5rRE3xibu9YxPD108RuC4a4Z25koG8="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.CodeAnalysis.CSharp.Workspaces",
|
||||
"version": "5.0.0",
|
||||
"hash": "sha256-yWVcLt/f2CouOfFy966glGdtSFy+RcgrU1dd9UtlL/Q="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.CodeAnalysis.Workspaces.Common",
|
||||
"version": "5.0.0",
|
||||
"hash": "sha256-Bir5e1gEhgQQ6upQmVKQHAKLRfenAu60DAzNupNnZsQ="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.CodeAnalysis.Workspaces.MSBuild",
|
||||
"version": "5.0.0",
|
||||
"hash": "sha256-+58+iqTayTiE0pDaog1U8mjaDA8bNNDLA8gjCQZZudo="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.EntityFrameworkCore",
|
||||
"version": "10.0.0",
|
||||
"hash": "sha256-xfgrlxhtOkQwF5Q7j8gSm41URJiH8IuJ/T/Dh88++hE="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.EntityFrameworkCore",
|
||||
"version": "10.0.2",
|
||||
"hash": "sha256-FS6T8EnaWCMtj4PnZhh+oF8mcM44VlM3wkTSMlpte9A="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.EntityFrameworkCore.Abstractions",
|
||||
"version": "10.0.2",
|
||||
"hash": "sha256-qkDfIJpcPO2kk4n5OE/13hI/0mUygpTofInn95XjRZI="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.EntityFrameworkCore.Analyzers",
|
||||
"version": "10.0.2",
|
||||
"hash": "sha256-yOv78rgAACBz1zjitpcZbQQ3zx8huJongZTHkhN4PQ0="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.EntityFrameworkCore.Design",
|
||||
"version": "10.0.2",
|
||||
"hash": "sha256-bTShsGux0y/49PIIMb/4ZX3x5+rPacvT5/NcooNCI1Y="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.EntityFrameworkCore.Relational",
|
||||
"version": "10.0.0",
|
||||
"hash": "sha256-vOP2CE5YA551BlpbOuIy6RuAiAEPEpCVS1cEE33/zN4="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.EntityFrameworkCore.Relational",
|
||||
"version": "10.0.2",
|
||||
"hash": "sha256-Y4jPpoYhKizg5wF6QfkBX4sYlE2FU1bYhfoDN3xkhKM="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.Extensions.Caching.Abstractions",
|
||||
"version": "10.0.2",
|
||||
"hash": "sha256-nKmQuZTt1g5/8gBajo7wdCV64kdCucdiQR8JTt7ZZb0="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.Extensions.Caching.Memory",
|
||||
"version": "10.0.2",
|
||||
"hash": "sha256-sRUF7DM0s1yzZnfjM/hF9A/IysE6Er23gZ6jST+RWh0="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.Extensions.Configuration",
|
||||
"version": "10.0.2",
|
||||
"hash": "sha256-dBJAKDyp/sm+ZSMQfH0+4OH8Jnv1s20aHlWS6HNnH+c="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.Extensions.Configuration.Abstractions",
|
||||
"version": "10.0.2",
|
||||
"hash": "sha256-P+0kaDGO+xB9KxF9eWHDJ4hzi05sUGM/uMNEX5NdBTE="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.Extensions.Configuration.Binder",
|
||||
"version": "10.0.2",
|
||||
"hash": "sha256-resI9gIxHh2cc+258/i+TjW8xxzKf4ZBTLIcWAMEYz0="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.Extensions.Configuration.CommandLine",
|
||||
"version": "10.0.2",
|
||||
"hash": "sha256-2+bwt7N721EO3/uy2rnungaFguA2WNJ7pO1XKVClPKw="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.Extensions.Configuration.EnvironmentVariables",
|
||||
"version": "10.0.2",
|
||||
"hash": "sha256-tjqCocpGVX4jg6z8VXjjooOqegcoqJA0sjIIslQPLyU="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.Extensions.Configuration.FileExtensions",
|
||||
"version": "10.0.2",
|
||||
"hash": "sha256-oOHg4UShuRyaflHJL1YLbkHSlwQtpZW2wONnsTKKiE4="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.Extensions.Configuration.Json",
|
||||
"version": "10.0.2",
|
||||
"hash": "sha256-RDfVyrOP9E5kVax3VswqJzPFTHSm3MZ45gSRLO0qFWs="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.Extensions.Configuration.UserSecrets",
|
||||
"version": "10.0.2",
|
||||
"hash": "sha256-O7yda5ebH81nOAOVOrW+CaqtPcsJmWscLV41T40hHHk="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.Extensions.DependencyInjection",
|
||||
"version": "10.0.2",
|
||||
"hash": "sha256-/9UWQRAI2eoocnJWWf1ktnAx/1Gt65c16fc0Xqr9+CQ="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.Extensions.DependencyInjection",
|
||||
"version": "9.0.0",
|
||||
"hash": "sha256-dAH52PPlTLn7X+1aI/7npdrDzMEFPMXRv4isV1a+14k="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.Extensions.DependencyInjection.Abstractions",
|
||||
"version": "10.0.2",
|
||||
"hash": "sha256-UF9T13V5SQxJy2msfLmyovLmitZrjJayf8gHH+uK2eg="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.Extensions.DependencyModel",
|
||||
"version": "10.0.2",
|
||||
"hash": "sha256-w/dGIjtZiGH+KW3969BPOdQpQEV+WB7RPTa2MK2DavE="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.Extensions.Diagnostics",
|
||||
"version": "10.0.2",
|
||||
"hash": "sha256-Zb/qJA0cZYiPQO7I3AegZCcNT0aJlKTycUP11Mqbm6o="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.Extensions.Diagnostics.Abstractions",
|
||||
"version": "10.0.2",
|
||||
"hash": "sha256-Aob6wq51LdquE7SkkxtCzcuHBKWrJcb3Ebi/dU3aqA4="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.Extensions.FileProviders.Abstractions",
|
||||
"version": "10.0.2",
|
||||
"hash": "sha256-tibCkkT9WliU2E/i0ufx7/Va6H6QZX4hR/1oUp8ecgQ="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.Extensions.FileProviders.Physical",
|
||||
"version": "10.0.2",
|
||||
"hash": "sha256-HtzaL9KEFkyIyG31RIjj57yFBw6Ja3U6UYLP0LLesvw="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.Extensions.FileSystemGlobbing",
|
||||
"version": "10.0.2",
|
||||
"hash": "sha256-WHqwQLBlb4w+fw1KZVPvunir5cM/4jXExWRofgfVAxs="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.Extensions.Hosting",
|
||||
"version": "10.0.2",
|
||||
"hash": "sha256-q+GiN081aRi0690nHVhWmAynfokQINPuvGzKiXh6oIM="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.Extensions.Hosting.Abstractions",
|
||||
"version": "10.0.2",
|
||||
"hash": "sha256-mkeKUXepn4bfEdZFXdURmNEFdGiHQdpcxnm6joG+pUA="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.Extensions.Logging",
|
||||
"version": "10.0.2",
|
||||
"hash": "sha256-9+gfQwK32JMYscW1YvyCWEzc9mRZOjCACoD9U1vVaJI="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.Extensions.Logging",
|
||||
"version": "9.0.0",
|
||||
"hash": "sha256-kR16c+N8nQrWeYLajqnXPg7RiXjZMSFLnKLEs4VfjcM="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.Extensions.Logging.Abstractions",
|
||||
"version": "10.0.0",
|
||||
"hash": "sha256-BnhgGZc01HwTSxogavq7Ueq4V7iMA3wPnbfRwQ4RhGk="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.Extensions.Logging.Abstractions",
|
||||
"version": "10.0.2",
|
||||
"hash": "sha256-ndKGzq8+2J/hvaIULwBui0L/jDyMQTAY24j+ohX5VX8="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.Extensions.Logging.Abstractions",
|
||||
"version": "9.0.0",
|
||||
"hash": "sha256-iBTs9twjWXFeERt4CErkIIcoJZU1jrd1RWCI8V5j7KU="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.Extensions.Logging.Configuration",
|
||||
"version": "10.0.2",
|
||||
"hash": "sha256-eSfmagvrcdRVmTXEdzfvWEDNBewB/YClOGSDq4gThk0="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.Extensions.Logging.Console",
|
||||
"version": "10.0.2",
|
||||
"hash": "sha256-mfaypUwMZxEIKBfnmzhnCScC/uPpZBRYN+/2SNcxcu4="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.Extensions.Logging.Debug",
|
||||
"version": "10.0.2",
|
||||
"hash": "sha256-hcHfYTWyQzRHEkuo9ejkUZxfJC0+JMLOgq51jpDJwOI="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.Extensions.Logging.EventLog",
|
||||
"version": "10.0.2",
|
||||
"hash": "sha256-LFbcqm2JfDowycOiVWNzWrF0vAsP3ug6c1njt373nE4="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.Extensions.Logging.EventSource",
|
||||
"version": "10.0.2",
|
||||
"hash": "sha256-1vp78PlJpE+zyWknU7imDTq0mC8Fk0wU11DqDRuuEF4="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.Extensions.Options",
|
||||
"version": "10.0.2",
|
||||
"hash": "sha256-12AfUEDdta/pmZUyEyqSUfOk0YoA7JOfGmIYnZQ//qk="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.Extensions.Options",
|
||||
"version": "9.0.0",
|
||||
"hash": "sha256-DT5euAQY/ItB5LPI8WIp6Dnd0lSvBRP35vFkOXC68ck="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.Extensions.Options.ConfigurationExtensions",
|
||||
"version": "10.0.2",
|
||||
"hash": "sha256-WJahsWyT5wYdLPEJufHKpb3l/dl7D2iw2SnMK0Jr53U="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.Extensions.Primitives",
|
||||
"version": "10.0.2",
|
||||
"hash": "sha256-8Ccrjjv9cFVf9RyCc7GS/Byt8+DXdSNea0UX3A5BEdA="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.Extensions.Primitives",
|
||||
"version": "9.0.0",
|
||||
"hash": "sha256-ZNLusK1CRuq5BZYZMDqaz04PIKScE2Z7sS2tehU7EJs="
|
||||
},
|
||||
{
|
||||
"pname": "Microsoft.VisualStudio.SolutionPersistence",
|
||||
"version": "1.0.52",
|
||||
"hash": "sha256-KZGPtOXe6Hv8RrkcsgoLKTRyaCScIpQEa2NhNB3iOXw="
|
||||
},
|
||||
{
|
||||
"pname": "Mono.TextTemplating",
|
||||
"version": "3.0.0",
|
||||
"hash": "sha256-VlgGDvgNZb7MeBbIZ4DE2Nn/j2aD9k6XqNHnASUSDr0="
|
||||
},
|
||||
{
|
||||
"pname": "Newtonsoft.Json",
|
||||
"version": "13.0.3",
|
||||
"hash": "sha256-hy/BieY4qxBWVVsDqqOPaLy1QobiIapkbrESm6v2PHc="
|
||||
},
|
||||
{
|
||||
"pname": "Npgsql",
|
||||
"version": "10.0.0",
|
||||
"hash": "sha256-UVKz9dH/rVCCbMyFdqA31RYpht1XgDRLIqUy0Dp9ACQ="
|
||||
},
|
||||
{
|
||||
"pname": "Npgsql.EntityFrameworkCore.PostgreSQL",
|
||||
"version": "10.0.0",
|
||||
"hash": "sha256-XIJxnTMektQVP1qtslEIGbmBGrIQsvjQjCMRTs9UIbg="
|
||||
},
|
||||
{
|
||||
"pname": "System.CodeDom",
|
||||
"version": "6.0.0",
|
||||
"hash": "sha256-uPetUFZyHfxjScu5x4agjk9pIhbCkt5rG4Axj25npcQ="
|
||||
},
|
||||
{
|
||||
"pname": "System.Composition",
|
||||
"version": "9.0.0",
|
||||
"hash": "sha256-FehOkQ2u1p8mQ0/wn3cZ+24HjhTLdck8VZYWA1CcgbM="
|
||||
},
|
||||
{
|
||||
"pname": "System.Composition.AttributedModel",
|
||||
"version": "9.0.0",
|
||||
"hash": "sha256-a7y7H6zj+kmYkllNHA402DoVfY9IaqC3Ooys8Vzl24M="
|
||||
},
|
||||
{
|
||||
"pname": "System.Composition.Convention",
|
||||
"version": "9.0.0",
|
||||
"hash": "sha256-tw4vE5JRQ60ubTZBbxoMPhtjOQCC3XoDFUH7NHO7o8U="
|
||||
},
|
||||
{
|
||||
"pname": "System.Composition.Hosting",
|
||||
"version": "9.0.0",
|
||||
"hash": "sha256-oOxU+DPEEfMCuNLgW6wSkZp0JY5gYt44FJNnWt+967s="
|
||||
},
|
||||
{
|
||||
"pname": "System.Composition.Runtime",
|
||||
"version": "9.0.0",
|
||||
"hash": "sha256-AyIe+di1TqwUBbSJ/sJ8Q8tzsnTN+VBdJw4K8xZz43s="
|
||||
},
|
||||
{
|
||||
"pname": "System.Composition.TypedParts",
|
||||
"version": "9.0.0",
|
||||
"hash": "sha256-F5fpTUs3Rr7yP/NyIzr+Xn5NdTXXp8rrjBnF9UBBUog="
|
||||
},
|
||||
{
|
||||
"pname": "System.Diagnostics.EventLog",
|
||||
"version": "10.0.2",
|
||||
"hash": "sha256-rezZk0M4+MWRxwGSFzXfvekrhL8qLTp7Pc8YsSy/4nE="
|
||||
}
|
||||
]
|
||||
Reference in New Issue
Block a user