diff options
author | vnugent <public@vaughnnugent.com> | 2024-08-17 22:35:53 -0400 |
---|---|---|
committer | vnugent <public@vaughnnugent.com> | 2024-08-17 22:35:53 -0400 |
commit | ac67c472f9f70cc60e749283a9a6fc32e5f65fe6 (patch) | |
tree | 985d0b921ed8912cdbf9a1402e7422102956bf5a /back-end/src | |
parent | 85540afac8a5ba822d845039c8a61fe48b3a1b6a (diff) |
update glance widget
Diffstat (limited to 'back-end/src')
-rw-r--r-- | back-end/src/Endpoints/WidgetEndpoint.cs | 123 |
1 files changed, 99 insertions, 24 deletions
diff --git a/back-end/src/Endpoints/WidgetEndpoint.cs b/back-end/src/Endpoints/WidgetEndpoint.cs index d72030b..ad2fa39 100644 --- a/back-end/src/Endpoints/WidgetEndpoint.cs +++ b/back-end/src/Endpoints/WidgetEndpoint.cs @@ -1,4 +1,4 @@ -W// Copyright (C) 2024 Vaughn Nugent +// Copyright (C) 2024 Vaughn Nugent // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as @@ -13,39 +13,37 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see <https://www.gnu.org/licenses/>. +using System; using System.Net; using System.Threading.Tasks; +using System.Text; +using VNLib.Utils.IO; +using VNLib.Utils.Memory; +using VNLib.Utils.Logging; +using VNLib.Utils.Extensions; +using VNLib.Net.Http; using VNLib.Plugins; using VNLib.Plugins.Essentials; using VNLib.Plugins.Essentials.Endpoints; using VNLib.Plugins.Extensions.Loading; using VNLib.Plugins.Essentials.Extensions; +using VNLib.Plugins.Extensions.Loading.Routing; using SimpleBookmark.Model; using SimpleBookmark.Model.Widget; namespace SimpleBookmark.Endpoints { + [EndpointPath("{{path}}")] + [EndpointLogName("widget-endpoint")] [ConfigurationName("widgets")] - internal sealed class WidgetEndpoint : UnprotectedWebEndpoint + internal sealed class WidgetEndpoint(PluginBase plugin, IConfigScope config) : UnprotectedWebEndpoint { - private readonly BookmarkStore bookmarks; - private readonly WidgetAuthManager authManager; - private readonly bool Enabled; - private readonly string? CorsAclHeaerDomains; - - public WidgetEndpoint(PluginBase plugin, IConfigScope config) - { - string path = config.GetRequiredProperty("path", static p => p.GetString()!); - InitPathAndLog(path, plugin.Log.CreateScope("widget-endpoint")); - - Enabled = config.GetValueOrDefault("enabled", static p => p.GetBoolean(), false); - CorsAclHeaerDomains = config.GetValueOrDefault("cors-urls", static p => p.GetString(), null); - - bookmarks = plugin.GetOrCreateSingleton<BookmarkStore>(); - authManager = plugin.GetOrCreateSingleton<WidgetAuthManager>(); - } + private readonly BookmarkStore bookmarks = plugin.GetOrCreateSingleton<BookmarkStore>(); + private readonly WidgetAuthManager authManager = plugin.GetOrCreateSingleton<WidgetAuthManager>(); + private readonly bool Enabled = config.GetValueOrDefault("enabled", false); + private readonly string? CorsAclHeaerDomains = config.GetValueOrDefault<string?>("cors-urls", null); protected override async ValueTask<VfReturnType> GetAsync(HttpEntity entity) { @@ -54,13 +52,13 @@ namespace SimpleBookmark.Endpoints return VfReturnType.NotFound; } - /* if (!await authManager.IsTokenValidAsync(entity)) - { - return VirtualClose(entity, HttpStatusCode.Unauthorized); - }*/ + /* if (!await authManager.IsTokenValidAsync(entity)) + { + return VirtualClose(entity, HttpStatusCode.Unauthorized); + }*/ //Widgets might be loaded in an iframe, so we need to allow cross-site requests - if(CorsAclHeaerDomains is not null && entity.Server.IsCrossSite()) + if (CorsAclHeaerDomains is not null && entity.Server.IsCrossSite()) { entity.Server.Headers.Append("Access-Control-Allow-Origin", CorsAclHeaerDomains); } @@ -79,7 +77,84 @@ namespace SimpleBookmark.Endpoints entity.EventCancellation ); - return VirtualCloseJson(entity, boomarks, HttpStatusCode.OK); + //Output memory buffer + VnMemoryStream output = new(32 * 1024, false); + + try + { + string baseUrl = entity.Server.RequestUri.GetLeftPart(UriPartial.Authority); + + CompileGlanceTemplate(baseUrl, output, boomarks); + + //Assign glance template + entity.Server.Headers["Widget-Title"] = "Simple-Bookmark Widget"; + entity.Server.Headers["Widget-Content-Type"] = "html"; + + return VirtualClose(entity, HttpStatusCode.OK, ContentType.Html, output); + } + catch(Exception ex) + { + output.Dispose(); + + Log.Error(ex, "Failed to complie glance template"); + return VirtualClose(entity, HttpStatusCode.InternalServerError); + } + } + + private static void CompileGlanceTemplate(string hostUrl, VnMemoryStream vms, BookmarkEntry[] bookmarks) + { + using IMemoryHandle<char> buffer = MemoryUtil.SafeAlloc<char>(32 * 1024, false); + + ForwardOnlyWriter<char> writer = new(buffer.Span); + + writer.Append("<!DOCTYPE html>"); + writer.Append("<html>"); + writer.Append("<head>"); + writer.Append("<title>Simple-Bookmark Widget</title>"); + writer.Append("</head>"); + writer.Append("<body>"); + + writer.Append("<p class='size-h3'>"); + writer.Append("<a class='bookmarks-link color-highlight size-h3' href='"); + writer.Append(hostUrl); + writer.Append("'>Favorites:</a>"); + writer.Append("</p>"); + writer.Append("<hr class='margin-block-15'/>"); + + //Start bookmarks list + writer.Append("<ul class='list-horizontal-text'>"); + + foreach (BookmarkEntry entry in bookmarks) + { + writer.Append("<li>"); + + //Enable the built-in bookmarks link (makes it prettier) + writer.Append("<a class='bookmarks-link color-highlight size-h4' href='"); + writer.Append(entry.Url); + writer.Append("'>"); + writer.Append(entry.Name); + + writer.Append("</a>"); + writer.Append("</li>"); + } + + writer.Append("</ul>"); + + //Close the document + writer.Append("</body>"); + writer.Append("</html>"); + + int byteCount = Encoding.UTF8.GetByteCount(writer.AsSpan()); + + using (UnsafeMemoryHandle<byte> utf8Buffer = MemoryUtil.UnsafeAllocNearestPage(byteCount, true)) + { + //Encode utf8 bytes + Encoding.UTF8.GetBytes(writer.AsSpan(), utf8Buffer.Span); + + vms.Write(utf8Buffer.AsSpan(0, byteCount)); + } + + vms.Seek(0, System.IO.SeekOrigin.Begin); } } } |