From 3b08f75204efd2651dbc6f179c28c6680c78202d Mon Sep 17 00:00:00 2001 From: Nicolas Constant Date: Sun, 28 Jun 2020 21:56:10 -0400 Subject: [PATCH] following working --- src/BirdsiteLive.Domain/ActivityPubService.cs | 42 ++++++++++++++++++- src/BirdsiteLive.Domain/UserService.cs | 24 +++++++++-- .../Controllers/UsersController.cs | 2 +- 3 files changed, 62 insertions(+), 6 deletions(-) diff --git a/src/BirdsiteLive.Domain/ActivityPubService.cs b/src/BirdsiteLive.Domain/ActivityPubService.cs index e80877c..93db1a4 100644 --- a/src/BirdsiteLive.Domain/ActivityPubService.cs +++ b/src/BirdsiteLive.Domain/ActivityPubService.cs @@ -1,17 +1,31 @@ -using System.Net.Http; +using System; +using System.Net; +using System.Net.Http; +using System.Text; using System.Threading.Tasks; using BirdsiteLive.ActivityPub; using Newtonsoft.Json; +using Org.BouncyCastle.Bcpg; namespace BirdsiteLive.Domain { public interface IActivityPubService { Task GetUser(string objectId); + Task PostDataAsync(T data, string targetHost, string actorUrl); } public class ActivityPubService : IActivityPubService { + private readonly ICryptoService _cryptoService; + + #region Ctor + public ActivityPubService(ICryptoService cryptoService) + { + _cryptoService = cryptoService; + } + #endregion + public async Task GetUser(string objectId) { using (var httpClient = new HttpClient()) @@ -22,5 +36,31 @@ namespace BirdsiteLive.Domain return JsonConvert.DeserializeObject(content); } } + + public async Task PostDataAsync(T data, string targetHost, string actorUrl) + { + var json = JsonConvert.SerializeObject(data); + + var date = DateTime.UtcNow.ToUniversalTime(); + var httpDate = date.ToString("r"); + var signature = _cryptoService.SignAndGetSignatureHeader(date, actorUrl, targetHost); + + var client = new HttpClient(); + var httpRequestMessage = new HttpRequestMessage + { + Method = HttpMethod.Post, + RequestUri = new Uri($"https://{targetHost}/inbox"), + Headers = + { + {"Host", targetHost}, + {"Date", httpDate}, + {"Signature", signature} + }, + Content = new StringContent(json, Encoding.UTF8, "application/ld+json") + }; + + var response = await client.SendAsync(httpRequestMessage); + return response.StatusCode; + } } } \ No newline at end of file diff --git a/src/BirdsiteLive.Domain/UserService.cs b/src/BirdsiteLive.Domain/UserService.cs index 174fbab..5c569f5 100644 --- a/src/BirdsiteLive.Domain/UserService.cs +++ b/src/BirdsiteLive.Domain/UserService.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; +using System.Linq; +using System.Net; using System.Security.Cryptography; using System.Text; using System.Threading.Tasks; @@ -69,11 +71,25 @@ namespace BirdsiteLive.Domain if (!await ValidateSignature(activity.actor, signature, method, path, queryString, requestHeaders)) return false; // Save Follow in DB - - // Send Accept Activity - - throw new NotImplementedException(); + // Send Accept Activity + var targetHost = activity.actor.Replace("https://", string.Empty).Split('/').First(); + var acceptFollow = new ActivityAcceptFollow() + { + context = "https://www.w3.org/ns/activitystreams", + id = $"{activity.apObject}#accepts/follows/{Guid.NewGuid()}", + type = "Accept", + actor = activity.apObject, + apObject = new ActivityFollow() + { + id = activity.id, + type = activity.type, + actor = activity.actor, + apObject = activity.apObject + } + }; + var result = await _activityPubService.PostDataAsync(acceptFollow, targetHost, activity.apObject); + return result == HttpStatusCode.Accepted; } private async Task ValidateSignature(string actor, string rawSig, string method, string path, string queryString, Dictionary requestHeaders) diff --git a/src/BirdsiteLive/Controllers/UsersController.cs b/src/BirdsiteLive/Controllers/UsersController.cs index 91c8d69..02f4937 100644 --- a/src/BirdsiteLive/Controllers/UsersController.cs +++ b/src/BirdsiteLive/Controllers/UsersController.cs @@ -60,7 +60,7 @@ namespace BirdsiteLive.Controllers { case "Follow": var succeeded = await _userService.FollowRequestedAsync(r.Headers["Signature"].First(), r.Method, r.Path, r.QueryString.ToString(), RequestHeaders(r.Headers), activity as ActivityFollow); - if (succeeded) return Ok(); + if (succeeded) return Accepted(); else return Unauthorized(); break; default: