Files
0qln bff34658b8 appendix: 23 Code-Ausschnitte aus dem Houston-Repository
Pin nixpkgs to the revision used by itc.componentware: the channel version
ships a latexminted that crashes on Python 3.14, which made every listing
fail and sent latexmk into an endless error prompt. Also force
nonstopmode/halt-on-error so a broken listing can never loop again.
2026-08-25 21:38:22 +02:00

42 lines
1.4 KiB
C#

using System.Diagnostics.CodeAnalysis;
using System.Text;
using Microsoft.AspNetCore.WebUtilities;
namespace Houston.Model.Documents;
/// <summary>
/// Public URL id of a customer document.
/// </summary>
/// <remarks>
/// The identifier used in URLs (e.g. <c>/document/{id}/download</c> or <c>/document/{id}/share</c>)
/// is the URL base64 encoding of the document path <em>without</em> the customer/organization
/// folder. For an object stored at <c>OrgX/TypeY/FileZ.pdf</c> the id therefore encodes
/// <c>TypeY/FileZ.pdf</c>. The organization part is never part of the id, so it can only ever be
/// derived server side from the authenticated user.
/// </remarks>
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;
}