From 3314326b052e31d4d89db9436f2fcabaeadcfd80 Mon Sep 17 00:00:00 2001 From: Timothy Baldridge Date: Thu, 6 Aug 2020 16:40:07 -0600 Subject: [PATCH] Add no-patch commandline option --- Wabbajack.CLI/OptionsDefinition.cs | 3 ++- Wabbajack.CLI/Verbs/NoPatch.cs | 24 ++++++++++++++++++++++ Wabbajack.Lib/FileUploader/AuthorAPI.cs | 7 +++++++ Wabbajack.Server.Test/ModlistUpdater.cs | 7 +++++++ Wabbajack.Server.Test/sql/wabbajack_db.sql | 20 ++++++++++++++++++ Wabbajack.Server/Controllers/ModUpgrade.cs | 18 ++++++++++++++++ Wabbajack.Server/DataLayer/Patches.cs | 23 +++++++++++++++++++++ 7 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 Wabbajack.CLI/Verbs/NoPatch.cs diff --git a/Wabbajack.CLI/OptionsDefinition.cs b/Wabbajack.CLI/OptionsDefinition.cs index 204d6b9e..8c73a6da 100644 --- a/Wabbajack.CLI/OptionsDefinition.cs +++ b/Wabbajack.CLI/OptionsDefinition.cs @@ -28,7 +28,8 @@ namespace Wabbajack.CLI typeof(PurgeNexusCache), typeof(ForceHealing), typeof(HashVariants), - typeof(ParseMeta) + typeof(ParseMeta), + typeof(NoPatch) }; } } diff --git a/Wabbajack.CLI/Verbs/NoPatch.cs b/Wabbajack.CLI/Verbs/NoPatch.cs new file mode 100644 index 00000000..65a599c9 --- /dev/null +++ b/Wabbajack.CLI/Verbs/NoPatch.cs @@ -0,0 +1,24 @@ +using System; +using System.Threading.Tasks; +using CommandLine; +using Wabbajack.Common; +using Wabbajack.Lib.FileUploader; + +namespace Wabbajack.CLI.Verbs +{ + [Verb("no-patch", HelpText = "Add a hash to the no-patch list and purge existing patches")] + public class NoPatch : AVerb + { + [Option('h', "hash", Required = true, HelpText = "Hash to purge")] + public string NoPatchHash { get; set; } = ""; + + [Option('r', "rationale", Required = true, HelpText = "Why are you purging this?")] + public string Rationale { get; set; } = ""; + protected override async Task Run() + { + var hash = Hash.FromBase64(NoPatchHash); + Console.WriteLine(await AuthorAPI.NoPatch(hash, Rationale)); + return ExitCode.Ok; + } + } +} diff --git a/Wabbajack.Lib/FileUploader/AuthorAPI.cs b/Wabbajack.Lib/FileUploader/AuthorAPI.cs index 4ffabd9f..5a857d75 100644 --- a/Wabbajack.Lib/FileUploader/AuthorAPI.cs +++ b/Wabbajack.Lib/FileUploader/AuthorAPI.cs @@ -73,5 +73,12 @@ namespace Wabbajack.Lib.FileUploader { return await (await GetAuthorizedClient()).GetStringAsync($"{Consts.WabbajackBuildServerUri}purge_nexus_cache/{modId}"); } + + public static async Task NoPatch(Hash hash, string rationale) + { + var client = await GetAuthorizedClient(); + return await client.GetStringAsync( + $"{Consts.WabbajackBuildServerUri}mod_upgrade/no_patch/{hash.ToHex()}/{Encoding.UTF8.GetBytes(rationale).ToHex()}"); + } } } diff --git a/Wabbajack.Server.Test/ModlistUpdater.cs b/Wabbajack.Server.Test/ModlistUpdater.cs index fbcd9810..9e03ce2c 100644 --- a/Wabbajack.Server.Test/ModlistUpdater.cs +++ b/Wabbajack.Server.Test/ModlistUpdater.cs @@ -7,6 +7,7 @@ using Wabbajack.Common; using Wabbajack.Common.Exceptions; using Wabbajack.Lib; using Wabbajack.Lib.Downloaders; +using Wabbajack.Lib.FileUploader; using Wabbajack.Server.DataLayer; using Wabbajack.Server.Services; using Xunit; @@ -71,6 +72,12 @@ namespace Wabbajack.Server.Test Assert.True(await patcher.Execute() > 1); Assert.Equal(new Uri("https://wabbajacktest.b-cdn.net/79223277e28e1b7b_3286c571d95f5666"),await ClientAPI.GetModUpgrade(oldArchive, newArchive, TimeSpan.Zero, TimeSpan.Zero)); + + Assert.Equal("Purged", await AuthorAPI.NoPatch(oldArchive.Hash, "Testing NoPatch")); + + await Assert.ThrowsAsync(async () => await ClientAPI.GetModUpgrade(oldArchive, newArchive, TimeSpan.Zero, TimeSpan.Zero)); + Assert.True(await sql.IsNoPatch(oldArchive.Hash)); + } [Fact] diff --git a/Wabbajack.Server.Test/sql/wabbajack_db.sql b/Wabbajack.Server.Test/sql/wabbajack_db.sql index 5833e1fb..9ba90c06 100644 --- a/Wabbajack.Server.Test/sql/wabbajack_db.sql +++ b/Wabbajack.Server.Test/sql/wabbajack_db.sql @@ -689,6 +689,26 @@ CREATE TABLE [dbo].[MirroredArchives]( ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] GO +/****** Object: Table [dbo].[NoPatch] Script Date: 8/3/2020 8:39:33 PM ******/ +SET ANSI_NULLS ON +GO + +SET QUOTED_IDENTIFIER ON +GO + +CREATE TABLE [dbo].[NoPatch]( + [Hash] [bigint] NOT NULL, + [Created] [datetime] NOT NULL, + [Rationale] [nvarchar](max) NOT NULL, + CONSTRAINT [PK_NoPatch] PRIMARY KEY CLUSTERED + ( + [Hash] 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] TEXTIMAGE_ON [PRIMARY] +GO + + + /****** Object: Table [dbo].[GameMetadata] Script Date: 8/3/2020 8:39:33 PM ******/ SET ANSI_NULLS ON GO diff --git a/Wabbajack.Server/Controllers/ModUpgrade.cs b/Wabbajack.Server/Controllers/ModUpgrade.cs index f26c24c2..cda3e11a 100644 --- a/Wabbajack.Server/Controllers/ModUpgrade.cs +++ b/Wabbajack.Server/Controllers/ModUpgrade.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using System.Security.Claims; +using System.Text; using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; @@ -85,6 +86,12 @@ namespace Wabbajack.BuildServer.Controllers } var oldDownload = await _sql.GetOrEnqueueArchive(request.OldArchive); + + if (await _sql.IsNoPatch(oldDownload.Archive.Hash)) + { + return BadRequest("File has NoPatch attached"); + } + var newDownload = await _sql.GetOrEnqueueArchive(request.NewArchive); var patch = await _sql.FindOrEnqueuePatch(oldDownload.Id, newDownload.Id); @@ -127,6 +134,17 @@ namespace Wabbajack.BuildServer.Controllers var patches = await _sql.PatchesForSource(hash); return Ok(patches.Select(p => p.Dest.Archive).ToList().ToJson()); } + + [HttpGet] + [Authorize(Roles = "Author")] + [Route("/mod_upgrade/no_patch/{hashAsHex}/{rationaleAsHex}")] + public async Task PurgePatch(string hashAsHex, string rationaleAsHex) + { + var hash = Hash.FromHex(hashAsHex); + var rationale = Encoding.UTF8.GetString(rationaleAsHex.FromHex()); + await _sql.PurgePatch(hash, rationale); + return Ok("Purged"); + } } diff --git a/Wabbajack.Server/DataLayer/Patches.cs b/Wabbajack.Server/DataLayer/Patches.cs index e8b97508..7cae5508 100644 --- a/Wabbajack.Server/DataLayer/Patches.cs +++ b/Wabbajack.Server/DataLayer/Patches.cs @@ -226,5 +226,28 @@ namespace Wabbajack.Server.DataLayer } + public async Task PurgePatch(Hash hash, string rationale) + { + await using var conn = await Open(); + await using var tx = await conn.BeginTransactionAsync(); + + await conn.ExecuteAsync( + "DELETE p FROM dbo.Patches p LEFT JOIN dbo.ArchiveDownloads ad ON ad.Id = p.SrcId WHERE ad.Hash = @Hash ", + new {Hash = hash}, tx); + await conn.ExecuteAsync( + "INSERT INTO dbo.NoPatch (Hash, Created, Rationale) VALUES (@Hash, GETUTCDATE(), @Rationale)", + new + { + Hash = hash, + Rationale = rationale + }, tx); + await tx.CommitAsync(); + } + + public async Task IsNoPatch(Hash hash) + { + await using var conn = await Open(); + return await conn.QueryFirstOrDefaultAsync("SELECT Hash FROM NoPatch WHERE Hash = @Hash", new {Hash = hash}) != default; + } } }