Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CloudEvents support #673

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions source/DasBlog.Services/ConfigFile/Interfaces/ISiteConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,9 @@ public interface ISiteConfig

bool EnableCrossposts { get; set; }

bool UseUserCulture { get; set; }
bool EnableCloudEvents { get; set; }

bool UseUserCulture { get; set; }

bool ShowItemSummaryInAggregatedViews { get; set; }

Expand Down Expand Up @@ -199,7 +201,13 @@ public interface ISiteConfig
[XmlArray("CrosspostSites")]
CrosspostSite[] CrosspostSiteArray { get; set; }

bool Pop3DeleteAllMessages { get; set; }
[XmlIgnore]
CloudEventsTargetCollection CloudEventsTargets { get; set; }

[XmlArray("CloudEventsTargets")]
CloudEventsTarget[] CloudEventsTargetArray { get; set; }

bool Pop3DeleteAllMessages { get; set; }

bool Pop3LogIgnoredEmails { get; set; }

Expand Down
8 changes: 5 additions & 3 deletions source/DasBlog.Services/ConfigFile/SiteConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,10 @@ public SiteConfig() { }
public ContentFilterCollection ContentFilters { get; set; }
public ContentFilter[] ContentFilterArray { get; set; }
public CrosspostSiteCollection CrosspostSites { get; set; }
public CrosspostSite[] CrosspostSiteArray { get; set; }
public bool Pop3DeleteAllMessages { get; set; }
public CloudEventsTargetCollection CloudEventsTargets { get; set; }
public CrosspostSite[] CrosspostSiteArray { get; set; }
public CloudEventsTarget[] CloudEventsTargetArray { get; set; }
public bool Pop3DeleteAllMessages { get; set; }
public bool Pop3LogIgnoredEmails { get; set; }
public bool EnableReferralUrlBlackList { get; set; }
public string ReferralUrlBlackList { get; set; }
Expand Down Expand Up @@ -224,6 +226,6 @@ public SiteConfig() { }
public string MastodonServerUrl { get; set; }

public string MastodonAccount { get; set; }

public bool EnableCloudEvents { get; set; }
}
}
1 change: 1 addition & 0 deletions source/DasBlog.Services/IDasBlogSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,6 @@ public interface IDasBlogSettings
SendMailInfo GetMailInfo(MailMessage emailmessage);
DateTime GetDisplayTime(DateTime datetime);
DateTime GetCreateTime(DateTime datetime);
string GetRssEntryUrl(string entryId);
}
}
5 changes: 4 additions & 1 deletion source/DasBlog.Services/Rss/Rss.cs
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,10 @@ public class RssItem
[XmlAttribute("xml:lang")]
public string Language;

[XmlElement("author")]
[XmlAttribute("id")]
public string Id;

[XmlElement("author")]
public string Author { get; set; }

[XmlElement("title")]
Expand Down
5 changes: 5 additions & 0 deletions source/DasBlog.Tests/UnitTests/DasBlogSettingTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -272,5 +272,10 @@ public DateTime GetCreateTime(DateTime datetime)
{
throw new NotImplementedException();
}

public string GetRssEntryUrl(string entryId)
{
throw new NotImplementedException();
}
}
}
5 changes: 4 additions & 1 deletion source/DasBlog.Tests/UnitTests/SiteConfigTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -171,5 +171,8 @@ public class SiteConfigTest : ISiteConfig
public string MastodonServerUrl { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
public string MastodonAccount { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
public bool AllowMarkdownInComments { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
}
public bool EnableCloudEvents { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
public CloudEventsTargetCollection CloudEventsTargets { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
public CloudEventsTarget[] CloudEventsTargetArray { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
}
}
109 changes: 108 additions & 1 deletion source/DasBlog.Web.Repositories/BlogManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@
using System.Net.Mail;
using System.Net;
using System.IO;
using CloudNative.CloudEvents;
using System.Xml.Linq;
using CloudNative.CloudEvents.Http;
using CloudNative.CloudEvents.SystemTextJson;
using System.Net.Http;

namespace DasBlog.Managers
{
Expand Down Expand Up @@ -187,22 +192,124 @@ public EntrySaveState CreateEntry(Entry entry)
{
var rtn = InternalSaveEntry(entry, null, null);
LogEvent(EventCodes.EntryAdded, entry);
RaisePostCreatedCloudEvent(entry);
return rtn;
}


private void RaisePostCreatedCloudEvent(Entry entry)
{
var cloudEvent = CreateCloudEvent(entry);
cloudEvent.Type = "dasblog.post.created";
RaiseCloudEvent(cloudEvent);
}

private CloudEvent CreateCloudEvent(Entry entry)
{
var ext = CloudEventAttribute.CreateExtension("tags", CloudEventAttributeType.String);
var cloudEvent = new CloudEvent(CloudEventsSpecVersion.V1_0, new[] { ext })
{
Source = new Uri(dasBlogSettings.GetBaseUrl()),
Subject = MakePermaLinkFromCompressedTitle(entry).ToString(),
Data = MapEntryToCloudEventData(entry),
Id = Guid.NewGuid().ToString(),
Time = DateTime.UtcNow,
};
if (!string.IsNullOrEmpty(entry.Categories))
{
cloudEvent.SetAttributeFromString("tags", entry.Categories);
}
return cloudEvent;
}

private void RaiseCloudEvent(CloudEvent cloudEvent)
{
if ( dasBlogSettings.SiteConfiguration.EnableCloudEvents &&
dasBlogSettings.SiteConfiguration.CloudEventsTargets != null)
{
foreach (var target in dasBlogSettings.SiteConfiguration.CloudEventsTargets)
{
if (!string.IsNullOrEmpty(target.Uri))
{
try
{
var content = cloudEvent.ToHttpContent(ContentMode.Structured, new JsonEventFormatter());
var uriBuilder = new UriBuilder(target.Uri);
if (target.Headers != null)
{
foreach (var header in target.Headers)
{
if (!string.IsNullOrEmpty(header.Name))
{
content.Headers.Add(header.Name, header.Value);
}
}
}
if (target.QueryArgs!= null)
{
foreach (var queryArgs in target.QueryArgs)
{
uriBuilder.Query = (string.IsNullOrEmpty(uriBuilder.Query) ? string.Empty : uriBuilder.Query + "&") + queryArgs.Name + "=" + queryArgs.Value;
}
}
var httpClient = new HttpClient();
var result = httpClient.PostAsync(uriBuilder.Uri, content).GetAwaiter().GetResult();
}
catch(Exception ex)
{
logger.LogError(ex, "Failed to post CloudEvent");
}
}
}
}
}

private EntryCloudEventData MapEntryToCloudEventData(Entry entry)
{
var data = new EntryCloudEventData();
data.Id = entry.EntryId;
data.Title = entry.Title;
data.CreatedUtc = entry.CreatedUtc;
data.ModifiedUtc = entry.ModifiedUtc;
data.Tags = entry.Categories;
data.Description = entry.Description;
data.PermaLink = MakePermaLinkFromCompressedTitle(entry).ToString();
data.DetailsLink = dasBlogSettings.GetRssEntryUrl(entry.EntryId);
data.IsPublic = entry.IsPublic;
data.Author = entry.Author;
data.Longitude = entry.Longitude;
data.Latitude = entry.Latitude;
return data;
}

public EntrySaveState UpdateEntry(Entry entry)
{
var rtn = InternalSaveEntry(entry, null, null);
LogEvent(EventCodes.EntryChanged, entry);
RaisePostUpdatedCloudEvent(entry);
return rtn;
}

private void RaisePostUpdatedCloudEvent(Entry entry)
{
var cloudEvent = CreateCloudEvent(entry);
cloudEvent.Type = "dasblog.post.updated";
RaiseCloudEvent(cloudEvent);
}

public void DeleteEntry(string postid)
{
var entry = GetEntryForEdit(postid);
dataService.DeleteEntry(postid, null);

LogEvent(EventCodes.EntryDeleted, entry);
RaisePostDeletedCloudEvent(entry);
}

private void RaisePostDeletedCloudEvent(Entry entry)
{
var cloudEvent = CreateCloudEvent(entry);
cloudEvent.Type = "dasblog.post.deleted";
RaiseCloudEvent(cloudEvent);
}

private static StringCollection GetSearchWords(string searchString)
Expand Down
4 changes: 3 additions & 1 deletion source/DasBlog.Web.Repositories/DasBlog.Managers.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="CloudNative.CloudEvents" Version="2.5.1" />
<PackageReference Include="CloudNative.CloudEvents.SystemTextJson" Version="2.5.1" />
<PackageReference Include="NodaTime" Version="3.0.9" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All"/>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
</ItemGroup>
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
Expand Down
34 changes: 34 additions & 0 deletions source/DasBlog.Web.Repositories/EntryCloudEventData.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using System;
using System.Text.Json.Serialization;

namespace DasBlog.Managers
{
internal class EntryCloudEventData
{
[JsonPropertyName("id")]
public string Id { get; internal set; }
[JsonPropertyName("title")]
public string Title { get; internal set; }
[JsonPropertyName("createdUtc")]
public DateTime CreatedUtc { get; internal set; }
[JsonPropertyName("modifiedUtc")]
public DateTime ModifiedUtc { get; internal set; }
[JsonPropertyName("tags")]
public string Tags { get; internal set; }
[JsonPropertyName("description")]
public string Description { get; internal set; }
[JsonPropertyName("permaLink")]
public string PermaLink { get; internal set; }
[JsonPropertyName("detailsLink")]
public string DetailsLink { get; internal set; }
[JsonPropertyName("isPublic")]
public bool IsPublic { get; internal set; }
[JsonPropertyName("author")]
public string Author { get; internal set; }
[JsonPropertyName("longitude")]
public double? Longitude { get; internal set; }
[JsonPropertyName("latitude")]
public double? Latitude { get; internal set; }

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ public interface ISubscriptionManager
RssRoot GetAtom();
RssRoot GetAtomCategory(string categoryName);
RsdRoot GetRsd();
}
RssItem GetRssItem(string entryId);
}
}
Loading