Skip to content

Instantly share code, notes, and snippets.

@georgiosd
Created November 14, 2023 13:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save georgiosd/6a3244e334bb355bb9e1e80fae2272da to your computer and use it in GitHub Desktop.
Save georgiosd/6a3244e334bb355bb9e1e80fae2272da to your computer and use it in GitHub Desktop.
RavenDB ASP.NET Data Protection Repository
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Linq;
using System.Xml.Linq;
using Microsoft.AspNetCore.DataProtection.KeyManagement;
using Microsoft.AspNetCore.DataProtection.Repositories;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Raven.Client.Documents;
using Raven.Client.Documents.Session;
namespace Microsoft.AspNetCore.DataProtection
{
public static class DataProtectionBuilderExtensions
{
public static IDataProtectionBuilder PersistKeysToRaven(this IDataProtectionBuilder builder)
{
if (builder == null)
{
throw new ArgumentNullException(nameof(builder));
}
builder.Services.AddSingleton<IConfigureOptions<KeyManagementOptions>>(services =>
{
var store = services.GetRequiredService<IDocumentStore>();
return new ConfigureOptions<KeyManagementOptions>(options =>
{
options.XmlRepository = new RavenXmlRepository(store);
});
});
return builder;
}
class RavenXmlRepository : IXmlRepository
{
private readonly IDocumentStore store;
public RavenXmlRepository(IDocumentStore store)
{
this.store = store;
}
public IReadOnlyCollection<XElement> GetAllElements()
{
using var session = store.OpenSession();
var docs = session.Advanced
.LoadStartingWith<XmlDocument>(CollectionName + "/",
pageSize: int.MaxValue);
return new ReadOnlyCollection<XElement>(
docs.Select(x => XElement.Parse(x.SerializedXml)).ToArray());
}
public void StoreElement(XElement element, string friendlyName)
{
string? id = element.Attribute("id")?.Value;
if (id == null
|| !DateTime.TryParse(element.Element("expirationDate")?.Value, null, DateTimeStyles.AssumeUniversal, out var expirationDate))
{
throw new NotSupportedException($"Not supported Xml: {element}");
}
using var session = store.OpenSession();
var document = new XmlDocument
{
Id = $"{CollectionName}/{id}",
SerializedXml = element.ToString()
};
session.Store(document);
var metadata = session.Advanced.GetMetadataFor(document);
meta[Constants.Documents.Metadata.Expires] = expirationDate;
session.SaveChanges();
}
private const string CollectionName = "XmlDocuments";
class XmlDocument
{
public string Id { get; set; } = null!;
public string SerializedXml { get; set; } = null!;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment