using System.Diagnostics.CodeAnalysis; using System.Text; using Microsoft.AspNetCore.WebUtilities; namespace Houston.Model.Documents; /// /// Public URL id of a customer document. /// /// /// The identifier used in URLs (e.g. /document/{id}/download or /document/{id}/share) /// is the URL base64 encoding of the document path without the customer/organization /// folder. For an object stored at OrgX/TypeY/FileZ.pdf the id therefore encodes /// TypeY/FileZ.pdf. The organization part is never part of the id, so it can only ever be /// derived server side from the authenticated user. /// public readonly record struct DocumentId(string Value) { public static DocumentId Encode(DocumentRelativePath relativePath) => new(WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(relativePath.ToString()))); public bool TryDecode([NotNullWhen(true)] out DocumentRelativePath? relativePath) { relativePath = null; if (String.IsNullOrEmpty(Value)) return false; try { var decoded = Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(Value)); return DocumentRelativePath.TryFromS3Key(decoded, out relativePath); } catch (FormatException) { relativePath = null; return false; } } public override string ToString() => Value; }