mirror of
https://github.com/wabbajack-tools/wabbajack.git
synced 2024-08-30 18:42:17 +00:00
Few more fixes
This commit is contained in:
parent
6c9f6ab5c0
commit
831318c7eb
@ -5,6 +5,7 @@ using Dapper;
|
|||||||
using Wabbajack.Lib;
|
using Wabbajack.Lib;
|
||||||
using Wabbajack.Server.DataLayer;
|
using Wabbajack.Server.DataLayer;
|
||||||
using Wabbajack.Server.DTOs;
|
using Wabbajack.Server.DTOs;
|
||||||
|
using Wabbajack.Server.Services;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
using Xunit.Abstractions;
|
using Xunit.Abstractions;
|
||||||
|
|
||||||
@ -45,6 +46,9 @@ namespace Wabbajack.BuildServer.Test
|
|||||||
Assert.True(dumpResponse.IsSuccessStatusCode);
|
Assert.True(dumpResponse.IsSuccessStatusCode);
|
||||||
var data = await dumpResponse.Content.ReadAsStringAsync();
|
var data = await dumpResponse.Content.ReadAsStringAsync();
|
||||||
Assert.NotEmpty(data);
|
Assert.NotEmpty(data);
|
||||||
|
|
||||||
|
var cache = Fixture.GetService<MetricsKeyCache>();
|
||||||
|
Assert.True(await cache.KeyCount() > 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -550,6 +550,25 @@ CREATE TABLE [dbo].[ModListArchives](
|
|||||||
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
|
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
|
||||||
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
|
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
|
||||||
GO
|
GO
|
||||||
|
|
||||||
|
/****** Object: Table [dbo].[MetricsKeys] Script Date: 2/17/2021 9:20:27 PM ******/
|
||||||
|
SET ANSI_NULLS ON
|
||||||
|
GO
|
||||||
|
|
||||||
|
SET QUOTED_IDENTIFIER ON
|
||||||
|
GO
|
||||||
|
|
||||||
|
CREATE TABLE [dbo].[MetricsKeys](
|
||||||
|
[MetricsKey] [varchar](64) NOT NULL,
|
||||||
|
CONSTRAINT [PK_MetricsKeys] PRIMARY KEY CLUSTERED
|
||||||
|
(
|
||||||
|
[MetricsKey] ASC
|
||||||
|
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
|
||||||
|
) ON [PRIMARY]
|
||||||
|
GO
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/****** Object: Table [dbo].[ModListArchiveStatus] Script Date: 12/29/2020 8:55:04 PM ******/
|
/****** Object: Table [dbo].[ModListArchiveStatus] Script Date: 12/29/2020 8:55:04 PM ******/
|
||||||
SET ANSI_NULLS ON
|
SET ANSI_NULLS ON
|
||||||
GO
|
GO
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
@ -13,6 +14,7 @@ using Wabbajack.Common;
|
|||||||
using Wabbajack.Common.Serialization.Json;
|
using Wabbajack.Common.Serialization.Json;
|
||||||
using Wabbajack.Server.DataLayer;
|
using Wabbajack.Server.DataLayer;
|
||||||
using Wabbajack.Server.DTOs;
|
using Wabbajack.Server.DTOs;
|
||||||
|
using Wabbajack.Server.Services;
|
||||||
|
|
||||||
|
|
||||||
namespace Wabbajack.BuildServer
|
namespace Wabbajack.BuildServer
|
||||||
@ -31,14 +33,18 @@ namespace Wabbajack.BuildServer
|
|||||||
private readonly SqlService _sql;
|
private readonly SqlService _sql;
|
||||||
private const string ApiKeyHeaderName = "X-Api-Key";
|
private const string ApiKeyHeaderName = "X-Api-Key";
|
||||||
|
|
||||||
|
private MetricsKeyCache _keyCache;
|
||||||
|
|
||||||
public ApiKeyAuthenticationHandler(
|
public ApiKeyAuthenticationHandler(
|
||||||
IOptionsMonitor<ApiKeyAuthenticationOptions> options,
|
IOptionsMonitor<ApiKeyAuthenticationOptions> options,
|
||||||
ILoggerFactory logger,
|
ILoggerFactory logger,
|
||||||
UrlEncoder encoder,
|
UrlEncoder encoder,
|
||||||
ISystemClock clock,
|
ISystemClock clock,
|
||||||
|
MetricsKeyCache keyCache,
|
||||||
SqlService db) : base(options, logger, encoder, clock)
|
SqlService db) : base(options, logger, encoder, clock)
|
||||||
{
|
{
|
||||||
_sql = db;
|
_sql = db;
|
||||||
|
_keyCache = keyCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
|
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
|
||||||
@ -88,8 +94,9 @@ namespace Wabbajack.BuildServer
|
|||||||
|
|
||||||
return AuthenticateResult.Success(ticket);
|
return AuthenticateResult.Success(ticket);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!await _sql.ValidMetricsKey(metricsKey))
|
if (!await _keyCache.IsValidKey(metricsKey))
|
||||||
{
|
{
|
||||||
return AuthenticateResult.Fail("Invalid Metrics Key");
|
return AuthenticateResult.Fail("Invalid Metrics Key");
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@ using Wabbajack.Common;
|
|||||||
using Wabbajack.Server;
|
using Wabbajack.Server;
|
||||||
using Wabbajack.Server.DataLayer;
|
using Wabbajack.Server.DataLayer;
|
||||||
using Wabbajack.Server.DTOs;
|
using Wabbajack.Server.DTOs;
|
||||||
|
using Wabbajack.Server.Services;
|
||||||
using WebSocketSharp;
|
using WebSocketSharp;
|
||||||
using LogLevel = Microsoft.Extensions.Logging.LogLevel;
|
using LogLevel = Microsoft.Extensions.Logging.LogLevel;
|
||||||
|
|
||||||
@ -26,11 +27,13 @@ namespace Wabbajack.BuildServer.Controllers
|
|||||||
{
|
{
|
||||||
private SqlService _sql;
|
private SqlService _sql;
|
||||||
private ILogger<MetricsController> _logger;
|
private ILogger<MetricsController> _logger;
|
||||||
|
private MetricsKeyCache _keyCache;
|
||||||
|
|
||||||
public MetricsController(ILogger<MetricsController> logger, SqlService sql)
|
public MetricsController(ILogger<MetricsController> logger, SqlService sql, MetricsKeyCache keyCache)
|
||||||
{
|
{
|
||||||
_sql = sql;
|
_sql = sql;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
_keyCache = keyCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
@ -38,12 +41,15 @@ namespace Wabbajack.BuildServer.Controllers
|
|||||||
public async Task<Result> LogMetricAsync(string subject, string value)
|
public async Task<Result> LogMetricAsync(string subject, string value)
|
||||||
{
|
{
|
||||||
var date = DateTime.UtcNow;
|
var date = DateTime.UtcNow;
|
||||||
|
var metricsKey = Request.Headers[Consts.MetricsKeyHeader].FirstOrDefault();
|
||||||
|
if (metricsKey != null)
|
||||||
|
await _keyCache.AddKey(metricsKey);
|
||||||
|
|
||||||
// Used in tests
|
// Used in tests
|
||||||
if (value == "Default" || value == "untitled" || Guid.TryParse(value, out _))
|
if (value == "Default" || value == "untitled" || subject == "failed_download" || Guid.TryParse(value, out _))
|
||||||
return new Result { Timestamp = date};
|
return new Result { Timestamp = date};
|
||||||
|
|
||||||
await Log(date, subject, value, Request.Headers[Consts.MetricsKeyHeader].FirstOrDefault());
|
await Log(date, subject, value, metricsKey);
|
||||||
return new Result { Timestamp = date};
|
return new Result { Timestamp = date};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,6 +180,7 @@ namespace Wabbajack.BuildServer.Controllers
|
|||||||
|
|
||||||
private static Func<object, string> _totalListTemplate;
|
private static Func<object, string> _totalListTemplate;
|
||||||
|
|
||||||
|
|
||||||
private static Func<object, string> TotalListTemplate
|
private static Func<object, string> TotalListTemplate
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@ -189,6 +196,8 @@ namespace Wabbajack.BuildServer.Controllers
|
|||||||
return _totalListTemplate;
|
return _totalListTemplate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[HttpGet("total_installs.html")]
|
[HttpGet("total_installs.html")]
|
||||||
[ResponseCache(Duration = 60 * 60)]
|
[ResponseCache(Duration = 60 * 60)]
|
||||||
@ -231,6 +240,6 @@ namespace Wabbajack.BuildServer.Controllers
|
|||||||
{
|
{
|
||||||
return Ok(await _sql.MetricsDump().ToArrayAsync());
|
return Ok(await _sql.MetricsDump().ToArrayAsync());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -70,8 +70,28 @@ namespace Wabbajack.Server.DataLayer
|
|||||||
public async Task<bool> ValidMetricsKey(string metricsKey)
|
public async Task<bool> ValidMetricsKey(string metricsKey)
|
||||||
{
|
{
|
||||||
await using var conn = await Open();
|
await using var conn = await Open();
|
||||||
return (await conn.QueryAsync<string>("SELECT TOP(1) MetricsKey from Metrics Where MetricsKey = @MetricsKey",
|
return (await conn.QuerySingleOrDefaultAsync<string>("SELECT TOP(1) MetricsKey from dbo.MetricsKeys Where MetricsKey = @MetricsKey",
|
||||||
new {MetricsKey = metricsKey})).FirstOrDefault() != null;
|
new {MetricsKey = metricsKey})) != default;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task AddMetricsKey(string metricsKey)
|
||||||
|
{
|
||||||
|
await using var conn = await Open();
|
||||||
|
await using var trans = conn.BeginTransaction();
|
||||||
|
|
||||||
|
if ((await conn.QuerySingleOrDefaultAsync<string>(
|
||||||
|
"SELECT TOP(1) MetricsKey from dbo.MetricsKeys Where MetricsKey = @MetricsKey",
|
||||||
|
new {MetricsKey = metricsKey}, trans)) != default)
|
||||||
|
return;
|
||||||
|
|
||||||
|
await conn.ExecuteAsync("INSERT INTO dbo.MetricsKeys (MetricsKey) VALUES (@MetricsKey)",
|
||||||
|
new {MetricsKey = metricsKey}, trans);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string[]> AllKeys()
|
||||||
|
{
|
||||||
|
await using var conn = await Open();
|
||||||
|
return (await conn.QueryAsync<string>("SELECT MetricsKey from dbo.MetricsKeys")).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -19,8 +19,9 @@ namespace Wabbajack.Server.Services
|
|||||||
private QuickSync _quickSync;
|
private QuickSync _quickSync;
|
||||||
private DiscordSocketClient _client;
|
private DiscordSocketClient _client;
|
||||||
private SqlService _sql;
|
private SqlService _sql;
|
||||||
|
private MetricsKeyCache _keyCache;
|
||||||
|
|
||||||
public DiscordFrontend(ILogger<DiscordFrontend> logger, AppSettings settings, QuickSync quickSync, SqlService sql)
|
public DiscordFrontend(ILogger<DiscordFrontend> logger, AppSettings settings, QuickSync quickSync, SqlService sql, MetricsKeyCache keyCache)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_settings = settings;
|
_settings = settings;
|
||||||
@ -33,6 +34,7 @@ namespace Wabbajack.Server.Services
|
|||||||
_client.MessageReceived += MessageReceivedAsync;
|
_client.MessageReceived += MessageReceivedAsync;
|
||||||
|
|
||||||
_sql = sql;
|
_sql = sql;
|
||||||
|
_keyCache = keyCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task MessageReceivedAsync(SocketMessage arg)
|
private async Task MessageReceivedAsync(SocketMessage arg)
|
||||||
@ -88,6 +90,10 @@ namespace Wabbajack.Server.Services
|
|||||||
await ReplyTo(arg, $"Purged all traces of #{parts[2]} from the server, triggered list downloading. {deleted} records removed");
|
await ReplyTo(arg, $"Purged all traces of #{parts[2]} from the server, triggered list downloading. {deleted} records removed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (parts[1] == "users")
|
||||||
|
{
|
||||||
|
await ReplyTo(arg, $"Wabbajack has {await _keyCache.KeyCount()} known unique users");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
62
Wabbajack.Server/Services/MetricsKeyCache.cs
Normal file
62
Wabbajack.Server/Services/MetricsKeyCache.cs
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Wabbajack.Common;
|
||||||
|
using Wabbajack.Server.DataLayer;
|
||||||
|
|
||||||
|
namespace Wabbajack.Server.Services
|
||||||
|
{
|
||||||
|
public class MetricsKeyCache : IStartable
|
||||||
|
{
|
||||||
|
private ILogger<MetricsKeyCache> _logger;
|
||||||
|
private SqlService _sql;
|
||||||
|
private HashSet<string> _knownKeys = new();
|
||||||
|
private AsyncLock _lock = new();
|
||||||
|
|
||||||
|
public MetricsKeyCache(ILogger<MetricsKeyCache> logger, SqlService sql)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_sql = sql;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> IsValidKey(string key)
|
||||||
|
{
|
||||||
|
using (var _ = await _lock.WaitAsync())
|
||||||
|
{
|
||||||
|
if (_knownKeys.Contains(key)) return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (await _sql.ValidMetricsKey(key))
|
||||||
|
{
|
||||||
|
using var _ = await _lock.WaitAsync();
|
||||||
|
_knownKeys.Add(key);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task AddKey(string key)
|
||||||
|
{
|
||||||
|
using (var _ = await _lock.WaitAsync())
|
||||||
|
{
|
||||||
|
if (_knownKeys.Contains(key)) return;
|
||||||
|
_knownKeys.Add(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
await _sql.AddMetricsKey(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Start()
|
||||||
|
{
|
||||||
|
_knownKeys = (_sql.AllKeys().Result).ToHashSet();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<long> KeyCount()
|
||||||
|
{
|
||||||
|
using var _ = await _lock.WaitAsync();
|
||||||
|
return _knownKeys.Count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -77,6 +77,7 @@ namespace Wabbajack.Server
|
|||||||
services.AddSingleton<Watchdog>();
|
services.AddSingleton<Watchdog>();
|
||||||
services.AddSingleton<DiscordFrontend>();
|
services.AddSingleton<DiscordFrontend>();
|
||||||
services.AddSingleton<AuthoredFilesCleanup>();
|
services.AddSingleton<AuthoredFilesCleanup>();
|
||||||
|
services.AddSingleton<MetricsKeyCache>();
|
||||||
services.AddResponseCompression(options =>
|
services.AddResponseCompression(options =>
|
||||||
{
|
{
|
||||||
options.Providers.Add<BrotliCompressionProvider>();
|
options.Providers.Add<BrotliCompressionProvider>();
|
||||||
@ -145,6 +146,7 @@ namespace Wabbajack.Server
|
|||||||
app.UseService<Watchdog>();
|
app.UseService<Watchdog>();
|
||||||
app.UseService<DiscordFrontend>();
|
app.UseService<DiscordFrontend>();
|
||||||
app.UseService<AuthoredFilesCleanup>();
|
app.UseService<AuthoredFilesCleanup>();
|
||||||
|
app.UseService<MetricsKeyCache>();
|
||||||
|
|
||||||
app.Use(next =>
|
app.Use(next =>
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user