diff --git a/src/uActivityPub.Tests/ServiceTests/UActivitySettingsServiceTests.cs b/src/uActivityPub.Tests/ServiceTests/UActivitySettingsServiceTests.cs index 9fbc2b4..90ec8b7 100644 --- a/src/uActivityPub.Tests/ServiceTests/UActivitySettingsServiceTests.cs +++ b/src/uActivityPub.Tests/ServiceTests/UActivitySettingsServiceTests.cs @@ -11,7 +11,7 @@ namespace uActivityPub.Tests.ServiceTests; public class UActivitySettingsServiceTests { - private readonly IUActivitySettingsService _unitUnderTest; + private readonly UActivitySettingsService _unitUnderTest; // Mock private readonly Mock _dataBaseMock; diff --git a/src/uActivityPub/App_Plugins/uActivityPub/backoffice/uactivitypub/uactivitypub.dashboard.controller.js b/src/uActivityPub/App_Plugins/uActivityPub/backoffice/uactivitypub/uactivitypub.dashboard.controller.js index 874a13d..3a86320 100644 --- a/src/uActivityPub/App_Plugins/uActivityPub/backoffice/uactivitypub/uactivitypub.dashboard.controller.js +++ b/src/uActivityPub/App_Plugins/uActivityPub/backoffice/uactivitypub/uactivitypub.dashboard.controller.js @@ -4,8 +4,8 @@ function dashboardController($controller, $scope, $http, $timeout, navigationService, eventsService, notificationsService) { $scope.loaded = false; - var vm = this; - + let vm = this; + vm.settings = { singleUserMode: false, singleUserModeUserName: '', @@ -15,7 +15,7 @@ }; function loadSettings () { - var url = Umbraco.Sys.ServerVariables.uActivityPub.uActivityPubService; + let url = Umbraco.Sys.ServerVariables.uActivityPub.uActivityPubService; $http({ method: 'get', diff --git a/src/uActivityPub/Controllers/ActivityPubController.cs b/src/uActivityPub/Controllers/ActivityPubController.cs index 930c4c4..de8386b 100644 --- a/src/uActivityPub/Controllers/ActivityPubController.cs +++ b/src/uActivityPub/Controllers/ActivityPubController.cs @@ -52,7 +52,7 @@ public async Task> GetFollowersCollection(string userNa scope.Database.FetchAsync( "SELECT * FROM receivedActivityPubActivities WHERE Type = @0", "Follow"); - if (!followers.Any()) + if (followers.Count == 0) return Ok(new Collection()); var collection = new Collection(); @@ -91,19 +91,16 @@ public async Task> PostInbox(string userName, [FromBody] activityPubUserName = uActivitySettingsService.GetSettings(uActivitySettingKeys.SingleUserModeUserName)!.Value; } - var signature = Request.Headers["Signature"]; + var signature = Request.Headers["Signature"].FirstOrDefault() ?? string.Empty; try { - switch (activity.Type) + return activity.Type switch { - case "Follow": - return Ok(await inboxService.HandleFollow(activity, signature, activityPubUserName, userId)); - case "Undo": - return Ok(await inboxService.HandleUndo(activity, signature)); - default: - return BadRequest($"{activity.Type} is not supported on this server"); - } + "Follow" => Ok(await inboxService.HandleFollow(activity, signature, activityPubUserName, userId)), + "Undo" => Ok(await inboxService.HandleUndo(activity, signature)), + _ => BadRequest($"{activity.Type} is not supported on this server") + }; } catch { diff --git a/src/uActivityPub/Expansions/SettingsTreeController.cs b/src/uActivityPub/Expansions/SettingsTreeController.cs index dee8edb..ebc4197 100644 --- a/src/uActivityPub/Expansions/SettingsTreeController.cs +++ b/src/uActivityPub/Expansions/SettingsTreeController.cs @@ -44,7 +44,7 @@ protected override ActionResult GetMenuForNode(string id, Fo return rootResult; } - var root = rootResult.Value ?? throw new NullReferenceException(nameof(rootResult)); + var root = rootResult.Value ?? throw new InvalidOperationException($"The value of {nameof(rootResult)} is unexpectedly null"); //set the route root.RoutePath = $"{SectionAlias}/{uActivityPubConstants.Package.TreeName}/dashboard"; diff --git a/src/uActivityPub/Models/Actor.cs b/src/uActivityPub/Models/Actor.cs index 05859f0..fdb357d 100644 --- a/src/uActivityPub/Models/Actor.cs +++ b/src/uActivityPub/Models/Actor.cs @@ -19,7 +19,7 @@ public class Actor : ActivityPubBase public string? Outbox { get; set; } public string? Followers { get; set; } public Icon? Icon { get; set; } - public DateTime? Published { get; set; } = new DateTime(2023, 07, 17, 12, 00, 00); + public DateTime? Published { get; set; } = DateTime.Now.AddDays(-1); public DateTime? Updated { get; set; } = DateTime.Now; public bool ManuallyApprovesFollowers { get; set; } = false; diff --git a/src/uActivityPub/Notifications/uActivityPubServerVariablesHandler.cs b/src/uActivityPub/Notifications/uActivityPubServerVariablesHandler.cs index ac49220..a29dc83 100644 --- a/src/uActivityPub/Notifications/uActivityPubServerVariablesHandler.cs +++ b/src/uActivityPub/Notifications/uActivityPubServerVariablesHandler.cs @@ -13,12 +13,12 @@ public class uActivityPubServerVariablesHandler : INotificationHandler public uActivityPubServerVariablesHandler(LinkGenerator linkGenerator) { - _linkGenerator = linkGenerator; + _linkGenerator = linkGenerator ?? throw new ArgumentNullException(nameof(linkGenerator)); } public void Handle(ServerVariablesParsingNotification notification) { - notification.ServerVariables.Add("uActivityPub", new Dictionary + notification.ServerVariables.Add("uActivityPub", new Dictionary { { "uActivityPubService", _linkGenerator.GetUmbracoApiServiceBaseUrl(controller => controller.GetApi()) } }); diff --git a/src/uActivityPub/Services/ContentPublishPostHandler.cs b/src/uActivityPub/Services/ContentPublishPostHandler.cs index 27ced90..4f2f47f 100644 --- a/src/uActivityPub/Services/ContentPublishPostHandler.cs +++ b/src/uActivityPub/Services/ContentPublishPostHandler.cs @@ -14,6 +14,12 @@ namespace uActivityPub.Services; // ReSharper disable once ClassNeverInstantiated.Global public class ContentPublishPostHandler : INotificationHandler { + private static readonly JsonSerializerOptions JsonSerializerOptions = new() + { + DictionaryKeyPolicy = JsonNamingPolicy.CamelCase, + PropertyNamingPolicy = JsonNamingPolicy.CamelCase + }; + private readonly IUmbracoDatabaseFactory _databaseFactory; private readonly IOptions _webRoutingSettings; private readonly IUserService _userService; @@ -37,9 +43,9 @@ public ContentPublishPostHandler(IUmbracoDatabaseFactory databaseFactory, public void Handle(ContentPublishedNotification notification) { - var settings = _uActivitySettingsService.GetAllSettings(); - var contentAlias = settings?.FirstOrDefault(s => s.Key == uActivitySettingKeys.ContentTypeAlias); - var userPropertyAlias = settings?.FirstOrDefault(s => s.Key == uActivitySettingKeys.UserNameContentAlias); + var settings = _uActivitySettingsService.GetAllSettings()?.ToList(); + var contentAlias = settings?.Find(s => s.Key == uActivitySettingKeys.ContentTypeAlias); + var userPropertyAlias = settings?.Find(s => s.Key == uActivitySettingKeys.UserNameContentAlias); if (contentAlias == null) throw new InvalidOperationException("Could not find configured key for the content type"); @@ -67,7 +73,7 @@ public void Handle(ContentPublishedNotification notification) if (_uActivitySettingsService.GetSettings(uActivitySettingKeys.SingleUserMode)!.Value == "false") { - userId = post.GetValue(userPropertyAlias!.Value); + userId = post.GetValue(userPropertyAlias.Value); var user = _userService.GetUserById(userId); if (user == null) { @@ -87,11 +93,7 @@ public void Handle(ContentPublishedNotification notification) var activity = _activityHelper.GetActivityFromContent(post, actor); var keyInfo = _signatureService.GetPrimaryKeyForUser(userName, userId).Result; - var serializedActivity = JsonSerializer.Serialize(activity, new JsonSerializerOptions - { - DictionaryKeyPolicy = JsonNamingPolicy.CamelCase, - PropertyNamingPolicy = JsonNamingPolicy.CamelCase - }); + var serializedActivity = JsonSerializer.Serialize(activity, JsonSerializerOptions); var followers = database.Query( diff --git a/src/uActivityPub/Services/InboxService.cs b/src/uActivityPub/Services/InboxService.cs index 07b4f2e..6f1c0a2 100644 --- a/src/uActivityPub/Services/InboxService.cs +++ b/src/uActivityPub/Services/InboxService.cs @@ -3,10 +3,8 @@ using Newtonsoft.Json.Linq; using Serilog; using uActivityPub.Data; -using uActivityPub.Helpers; using uActivityPub.Models; using Umbraco.Cms.Core.Configuration.Models; -using Umbraco.Cms.Core.Models.Membership; using Umbraco.Cms.Infrastructure.Persistence; namespace uActivityPub.Services; @@ -18,6 +16,12 @@ public class InboxService( ISingedRequestHandler singedRequestHandler) : IInboxService { + private static readonly JsonSerializerOptions JsonSerializerOptions = new() + { + DictionaryKeyPolicy = JsonNamingPolicy.CamelCase, + PropertyNamingPolicy = JsonNamingPolicy.CamelCase + }; + public async Task HandleFollow(Activity activity, string signature, string userName, int userId) { Log.Information("Handling follow request for {Actor}. with activity {@Activity}", activity.Actor, activity); @@ -30,7 +34,7 @@ public class InboxService( var publicPem = actor.PublicKey?.PublicKeyPem; var signatureParts = signature.Split(','); - if (!string.IsNullOrEmpty(publicPem) && signatureParts.Any()) + if (!string.IsNullOrEmpty(publicPem) && signatureParts.Length != 0) { //we have a pem file and signature header parts // var rsa = publicPem.GetRSAFromPem(); @@ -64,11 +68,7 @@ public class InboxService( var keyInfo = await signatureService.GetPrimaryKeyForUser(userName, userId); - var response = await singedRequestHandler.SendSingedPost(new Uri(actor.Inbox), keyInfo.Rsa, JsonSerializer.Serialize(responseActivity, new JsonSerializerOptions - { - DictionaryKeyPolicy = JsonNamingPolicy.CamelCase, - PropertyNamingPolicy = JsonNamingPolicy.CamelCase - }), keyInfo.KeyId); + var response = await singedRequestHandler.SendSingedPost(new Uri(actor.Inbox), keyInfo.Rsa, JsonSerializer.Serialize(responseActivity, JsonSerializerOptions), keyInfo.KeyId); Log.Information("Send {@ResponseActivity} to {@Actor} response is {@Response} with content {Content}", responseActivity, actor, response, await response.Content.ReadAsStringAsync());