diff options
Diffstat (limited to 'src/SMAPI.Web')
6 files changed, 44 insertions, 29 deletions
diff --git a/src/SMAPI.Web/Controllers/JsonValidatorController.cs b/src/SMAPI.Web/Controllers/JsonValidatorController.cs index 6ba97749..c77a3036 100644 --- a/src/SMAPI.Web/Controllers/JsonValidatorController.cs +++ b/src/SMAPI.Web/Controllers/JsonValidatorController.cs @@ -58,7 +58,7 @@ namespace StardewModdingAPI.Web.Controllers /// <summary>Render the schema validator UI.</summary> /// <param name="schemaName">The schema name with which to validate the JSON, or 'edit' to return to the edit screen.</param> /// <param name="id">The stored file ID.</param> - /// <param name="operation">The operation to perform for the selected log ID. This can be 'edit', or any other value to view.</param> + /// <param name="operation">The operation to perform for the selected log ID. This can be 'edit', 'renew', or any other value to view.</param> [HttpGet] [Route("json")] [Route("json/{schemaName}")] @@ -68,8 +68,10 @@ namespace StardewModdingAPI.Web.Controllers { // parse arguments schemaName = this.NormalizeSchemaName(schemaName); + operation = operation?.Trim().ToLower(); bool hasId = !string.IsNullOrWhiteSpace(id); - bool isEditView = !hasId || operation?.Trim().ToLower() == "edit"; + bool isEditView = !hasId || operation == "edit"; + bool renew = operation == "renew"; // build result model var result = this.GetModel(id, schemaName, isEditView); @@ -77,7 +79,7 @@ namespace StardewModdingAPI.Web.Controllers return this.View("Index", result); // fetch raw JSON - StoredFileInfo file = await this.Storage.GetAsync(id); + StoredFileInfo file = await this.Storage.GetAsync(id, renew); if (string.IsNullOrWhiteSpace(file.Content)) return this.View("Index", result.SetUploadError("The JSON file seems to be empty.")); result.SetContent(file.Content, expiry: file.Expiry, uploadWarning: file.Warning); diff --git a/src/SMAPI.Web/Controllers/LogParserController.cs b/src/SMAPI.Web/Controllers/LogParserController.cs index 97c419d9..39de4b5d 100644 --- a/src/SMAPI.Web/Controllers/LogParserController.cs +++ b/src/SMAPI.Web/Controllers/LogParserController.cs @@ -40,17 +40,18 @@ namespace StardewModdingAPI.Web.Controllers /// <summary>Render the log parser UI.</summary> /// <param name="id">The stored file ID.</param> /// <param name="raw">Whether to display the raw unparsed log.</param> + /// <param name="renew">Whether to reset the log expiry.</param> [HttpGet] [Route("log")] [Route("log/{id}")] - public async Task<ViewResult> Index(string id = null, bool raw = false) + public async Task<ViewResult> Index(string id = null, bool raw = false, bool renew = false) { // fresh page if (string.IsNullOrWhiteSpace(id)) return this.View("Index", this.GetModel(id)); // log page - StoredFileInfo file = await this.Storage.GetAsync(id); + StoredFileInfo file = await this.Storage.GetAsync(id, renew); ParsedLog log = file.Success ? new LogParser().Parse(file.Content) : new ParsedLog { IsValid = false, Error = file.Error }; diff --git a/src/SMAPI.Web/Framework/Storage/IStorageProvider.cs b/src/SMAPI.Web/Framework/Storage/IStorageProvider.cs index 96a34fbb..dfc1fb47 100644 --- a/src/SMAPI.Web/Framework/Storage/IStorageProvider.cs +++ b/src/SMAPI.Web/Framework/Storage/IStorageProvider.cs @@ -13,6 +13,7 @@ namespace StardewModdingAPI.Web.Framework.Storage /// <summary>Fetch raw text from storage.</summary> /// <param name="id">The storage ID returned by <see cref="SaveAsync"/>.</param> - Task<StoredFileInfo> GetAsync(string id); + /// <param name="renew">Whether to reset the file expiry.</param> + Task<StoredFileInfo> GetAsync(string id, bool renew); } } diff --git a/src/SMAPI.Web/Framework/Storage/StorageProvider.cs b/src/SMAPI.Web/Framework/Storage/StorageProvider.cs index 35538443..c6f8bac1 100644 --- a/src/SMAPI.Web/Framework/Storage/StorageProvider.cs +++ b/src/SMAPI.Web/Framework/Storage/StorageProvider.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.IO; using System.Text; using System.Threading.Tasks; @@ -48,10 +49,7 @@ namespace StardewModdingAPI.Web.Framework.Storage this.GzipHelper = gzipHelper; } - /// <summary>Save a text file to storage.</summary> - /// <param name="content">The content to upload.</param> - /// <param name="compress">Whether to gzip the text.</param> - /// <returns>Returns metadata about the save attempt.</returns> + /// <inheritdoc /> public async Task<UploadResult> SaveAsync(string content, bool compress = true) { string id = Guid.NewGuid().ToString("N"); @@ -84,9 +82,8 @@ namespace StardewModdingAPI.Web.Framework.Storage } } - /// <summary>Fetch raw text from storage.</summary> - /// <param name="id">The storage ID returned by <see cref="SaveAsync"/>.</param> - public async Task<StoredFileInfo> GetAsync(string id) + /// <inheritdoc /> + public async Task<StoredFileInfo> GetAsync(string id, bool renew) { // fetch from blob storage if (Guid.TryParseExact(id, "N", out Guid _)) @@ -96,14 +93,21 @@ namespace StardewModdingAPI.Web.Framework.Storage { try { + // get client BlobClient blob = this.GetAzureBlobClient(id); + + // extend expiry + if (renew) + await blob.SetMetadataAsync(new Dictionary<string, string> { ["expiryRenewed"] = DateTime.UtcNow.ToString("O") }); // change the blob's last-modified date (the specific property set doesn't matter) + + // fetch file Response<BlobDownloadInfo> response = await blob.DownloadAsync(); using BlobDownloadInfo result = response.Value; - using StreamReader reader = new StreamReader(result.Content); DateTimeOffset expiry = result.Details.LastModified + TimeSpan.FromDays(this.ExpiryDays); string content = this.GzipHelper.DecompressString(reader.ReadToEnd()); + // build model return new StoredFileInfo { Success = true, @@ -125,25 +129,32 @@ namespace StardewModdingAPI.Web.Framework.Storage // local filesystem for testing else { + // get file FileInfo file = new FileInfo(this.GetDevFilePath(id)); - if (file.Exists) + if (file.Exists && file.LastWriteTimeUtc.AddDays(this.ExpiryDays) < DateTime.UtcNow) // expired + file.Delete(); + if (!file.Exists) { - if (file.LastWriteTimeUtc.AddDays(this.ExpiryDays) < DateTime.UtcNow) - file.Delete(); - else + return new StoredFileInfo { - return new StoredFileInfo - { - Success = true, - Content = File.ReadAllText(file.FullName), - Expiry = DateTime.UtcNow.AddDays(this.ExpiryDays), - Warning = "This file was saved temporarily to the local computer. This should only happen in a local development environment." - }; - } + Error = "There's no file with that ID." + }; } + + // renew + if (renew) + { + File.SetLastWriteTimeUtc(file.FullName, DateTime.UtcNow); + file.Refresh(); + } + + // build model return new StoredFileInfo { - Error = "There's no file with that ID." + Success = true, + Content = File.ReadAllText(file.FullName), + Expiry = DateTime.UtcNow.AddDays(this.ExpiryDays), + Warning = "This file was saved temporarily to the local computer. This should only happen in a local development environment." }; } } diff --git a/src/SMAPI.Web/Views/JsonValidator/Index.cshtml b/src/SMAPI.Web/Views/JsonValidator/Index.cshtml index 7b89a23d..1db79857 100644 --- a/src/SMAPI.Web/Views/JsonValidator/Index.cshtml +++ b/src/SMAPI.Web/Views/JsonValidator/Index.cshtml @@ -76,7 +76,7 @@ else if (!Model.IsEditView && Model.PasteID != null) <div class="save-metadata" v-pre> @if (Model.Expiry != null) { - <text>This JSON file will expire in @((DateTime.UtcNow - Model.Expiry.Value).Humanize()). </text> + <text>This JSON file will expire in @((DateTime.UtcNow - Model.Expiry.Value).Humanize()) (<a href="@(this.Url.PlainAction("Index", "JsonValidator", new { schemaName = this.Model.SchemaName, id = this.Model.PasteID, operation = "renew" }))">renew</a>).</text> } <!--@Model.UploadWarning--> </div> diff --git a/src/SMAPI.Web/Views/LogParser/Index.cshtml b/src/SMAPI.Web/Views/LogParser/Index.cshtml index 71e12d47..d4ff4f10 100644 --- a/src/SMAPI.Web/Views/LogParser/Index.cshtml +++ b/src/SMAPI.Web/Views/LogParser/Index.cshtml @@ -78,7 +78,7 @@ else if (Model.ParsedLog?.IsValid == true) <div class="save-metadata" v-pre> @if (Model.Expiry != null) { - <text>This log will expire in @((DateTime.UtcNow - Model.Expiry.Value).Humanize()).</text> + <text>This log will expire in @((DateTime.UtcNow - Model.Expiry.Value).Humanize()) (<a href="@(this.Url.PlainAction("Index", "LogParser", new { id = this.Model.PasteID, renew = true }))">renew</a>).</text> } </div> } |