added follow debug + ap models + header signing
This commit is contained in:
parent
cf2c8a38d4
commit
f5fe4f53f9
11 changed files with 200 additions and 3 deletions
|
@ -16,6 +16,31 @@ namespace BirdsiteLive.ActivityPub
|
||||||
if(a.apObject.type == "Follow")
|
if(a.apObject.type == "Follow")
|
||||||
return JsonConvert.DeserializeObject<ActivityUndoFollow>(json);
|
return JsonConvert.DeserializeObject<ActivityUndoFollow>(json);
|
||||||
break;
|
break;
|
||||||
|
case "Accept":
|
||||||
|
var accept = JsonConvert.DeserializeObject<ActivityAccept>(json);
|
||||||
|
//var acceptType = JsonConvert.DeserializeObject<Activity>(accept.apObject);
|
||||||
|
switch ((accept.apObject as dynamic).type.ToString())
|
||||||
|
{
|
||||||
|
case "Follow":
|
||||||
|
var acceptFollow = new ActivityAcceptFollow()
|
||||||
|
{
|
||||||
|
type = accept.type,
|
||||||
|
id = accept.id,
|
||||||
|
actor = accept.actor,
|
||||||
|
context = accept.context,
|
||||||
|
apObject = new ActivityFollow()
|
||||||
|
{
|
||||||
|
id = (accept.apObject as dynamic).id?.ToString(),
|
||||||
|
type = (accept.apObject as dynamic).type?.ToString(),
|
||||||
|
actor = (accept.apObject as dynamic).actor?.ToString(),
|
||||||
|
context = (accept.apObject as dynamic).context?.ToString(),
|
||||||
|
apObject = (accept.apObject as dynamic).@object?.ToString()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return acceptFollow;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
|
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
|
||||||
<PackageReference Include="System.Text.Json" Version="4.7.2" />
|
<PackageReference Include="System.Text.Json" Version="4.7.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
@ -10,6 +10,7 @@ namespace BirdsiteLive.ActivityPub
|
||||||
public string id { get; set; }
|
public string id { get; set; }
|
||||||
public string type { get; set; }
|
public string type { get; set; }
|
||||||
public string actor { get; set; }
|
public string actor { get; set; }
|
||||||
|
|
||||||
//[JsonProperty("object")]
|
//[JsonProperty("object")]
|
||||||
//public string apObject { get; set; }
|
//public string apObject { get; set; }
|
||||||
}
|
}
|
||||||
|
|
10
src/BirdsiteLive.ActivityPub/Models/ActivityAccept.cs
Normal file
10
src/BirdsiteLive.ActivityPub/Models/ActivityAccept.cs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace BirdsiteLive.ActivityPub
|
||||||
|
{
|
||||||
|
public class ActivityAccept : Activity
|
||||||
|
{
|
||||||
|
[JsonProperty("object")]
|
||||||
|
public object apObject { get; set; }
|
||||||
|
}
|
||||||
|
}
|
10
src/BirdsiteLive.ActivityPub/Models/ActivityAcceptFollow.cs
Normal file
10
src/BirdsiteLive.ActivityPub/Models/ActivityAcceptFollow.cs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace BirdsiteLive.ActivityPub
|
||||||
|
{
|
||||||
|
public class ActivityAcceptFollow : Activity
|
||||||
|
{
|
||||||
|
[JsonProperty("object")]
|
||||||
|
public ActivityFollow apObject { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,10 +1,13 @@
|
||||||
using BirdsiteLive.Domain.Factories;
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
using BirdsiteLive.Domain.Factories;
|
||||||
|
|
||||||
namespace BirdsiteLive.Domain
|
namespace BirdsiteLive.Domain
|
||||||
{
|
{
|
||||||
public interface ICryptoService
|
public interface ICryptoService
|
||||||
{
|
{
|
||||||
string GetUserPem(string id);
|
string GetUserPem(string id);
|
||||||
|
string SignAndGetSignatureHeader(DateTime date, string actor, string host);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class CryptoService : ICryptoService
|
public class CryptoService : ICryptoService
|
||||||
|
@ -22,5 +25,25 @@ namespace BirdsiteLive.Domain
|
||||||
{
|
{
|
||||||
return _magicKeyFactory.GetMagicKey().AsPEM;
|
return _magicKeyFactory.GetMagicKey().AsPEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="data"></param>
|
||||||
|
/// <param name="actor">in the form of https://domain.io/actor</param>
|
||||||
|
/// <param name="host">in the form of domain.io</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public string SignAndGetSignatureHeader(DateTime date, string actor, string targethost)
|
||||||
|
{
|
||||||
|
var httpDate = date.ToString("r");
|
||||||
|
|
||||||
|
var signedString = $"(request-target): post /inbox\nhost: {targethost}\ndate: {httpDate}";
|
||||||
|
var signedStringBytes = Encoding.UTF8.GetBytes(signedString);
|
||||||
|
var signature = _magicKeyFactory.GetMagicKey().Sign(signedStringBytes);
|
||||||
|
var sig64 = Convert.ToBase64String(signature);
|
||||||
|
|
||||||
|
var header = "keyId=\"" + actor + "\",headers=\"(request-target) host date\",signature=\"" + sig64 + "\"";
|
||||||
|
return header;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -9,7 +9,7 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Lamar.Microsoft.DependencyInjection" Version="4.1.0" />
|
<PackageReference Include="Lamar.Microsoft.DependencyInjection" Version="4.1.0" />
|
||||||
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.10.8" />
|
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.10.8" />
|
||||||
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="3.1.1" />
|
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="3.1.3" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
94
src/BirdsiteLive/Controllers/DebugController.cs
Normal file
94
src/BirdsiteLive/Controllers/DebugController.cs
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using BirdsiteLive.ActivityPub;
|
||||||
|
using BirdsiteLive.Common.Settings;
|
||||||
|
using BirdsiteLive.Domain;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace BirdsiteLive.Controllers
|
||||||
|
{
|
||||||
|
public class DebugController : Controller
|
||||||
|
{
|
||||||
|
private readonly InstanceSettings _instanceSettings;
|
||||||
|
private readonly ICryptoService _cryptoService;
|
||||||
|
|
||||||
|
#region Ctor
|
||||||
|
public DebugController(InstanceSettings instanceSettings, ICryptoService cryptoService)
|
||||||
|
{
|
||||||
|
_instanceSettings = instanceSettings;
|
||||||
|
_cryptoService = cryptoService;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public IActionResult Index()
|
||||||
|
{
|
||||||
|
return View();
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
public async Task<IActionResult> Follow()
|
||||||
|
{
|
||||||
|
var actor = $"https://{_instanceSettings.Domain}/users/gra";
|
||||||
|
var targethost = "mamot.fr";
|
||||||
|
var followActivity = new ActivityFollow()
|
||||||
|
{
|
||||||
|
context = "https://www.w3.org/ns/activitystreams",
|
||||||
|
id = $"https://{_instanceSettings.Domain}/{Guid.NewGuid()}",
|
||||||
|
type = "Follow",
|
||||||
|
actor = actor,
|
||||||
|
apObject = $"https://{targethost}/users/testtest"
|
||||||
|
};
|
||||||
|
|
||||||
|
var json = JsonConvert.SerializeObject(followActivity);
|
||||||
|
|
||||||
|
var date = DateTime.UtcNow.ToUniversalTime();
|
||||||
|
var httpDate = date.ToString("r");
|
||||||
|
var signature = _cryptoService.SignAndGetSignatureHeader(date, actor, 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")
|
||||||
|
};
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var response = await client.SendAsync(httpRequestMessage);
|
||||||
|
var re = response.ReasonPhrase;
|
||||||
|
var t = await response.Content.ReadAsStringAsync();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
return View("Index");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class HtmlHelperExtensions
|
||||||
|
{
|
||||||
|
public static bool IsDebug()
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
|
@ -14,6 +15,15 @@ namespace BirdsiteLive.Controllers
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public async Task<IActionResult> Inbox()
|
public async Task<IActionResult> Inbox()
|
||||||
{
|
{
|
||||||
|
var r = Request;
|
||||||
|
using (var reader = new StreamReader(Request.Body))
|
||||||
|
{
|
||||||
|
var body = await reader.ReadToEndAsync();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,15 @@
|
||||||
@{
|
@using BirdsiteLive.Controllers;
|
||||||
|
@{
|
||||||
ViewData["Title"] = "Home Page";
|
ViewData["Title"] = "Home Page";
|
||||||
}
|
}
|
||||||
|
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<h1 class="display-4">Welcome</h1>
|
<h1 class="display-4">Welcome</h1>
|
||||||
<p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
|
<p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
|
||||||
|
|
||||||
|
|
||||||
|
@if (HtmlHelperExtensions.IsDebug())
|
||||||
|
{
|
||||||
|
<a class="nav-link text-dark" asp-area="" asp-controller="Debug" asp-action="Index">Debug</a>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -31,5 +31,21 @@ namespace BirdsiteLive.ActivityPub.Tests
|
||||||
Assert.AreEqual("https://mastodon.technology/users/testtest", data.apObject.actor);
|
Assert.AreEqual("https://mastodon.technology/users/testtest", data.apObject.actor);
|
||||||
Assert.AreEqual("https://4a120ca2680e.ngrok.io/users/manu", data.apObject.apObject);
|
Assert.AreEqual("https://4a120ca2680e.ngrok.io/users/manu", data.apObject.apObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void AcceptDeserializationTest()
|
||||||
|
{
|
||||||
|
var json = "{\"@context\":\"https://www.w3.org/ns/activitystreams\",\"id\":\"https://mamot.fr/users/testtest#accepts/follows/333879\",\"type\":\"Accept\",\"actor\":\"https://mamot.fr/users/testtest\",\"object\":{\"id\":\"https://85da1577f778.ngrok.io/f89dfd87-f5ce-4603-83d9-405c0e229989\",\"type\":\"Follow\",\"actor\":\"https://85da1577f778.ngrok.io/users/gra\",\"object\":\"https://mamot.fr/users/testtest\"}}";
|
||||||
|
|
||||||
|
|
||||||
|
var data = ApDeserializer.ProcessActivity(json) as ActivityAcceptFollow;
|
||||||
|
Assert.AreEqual("https://mamot.fr/users/testtest#accepts/follows/333879", data.id);
|
||||||
|
Assert.AreEqual("Accept", data.type);
|
||||||
|
Assert.AreEqual("https://mamot.fr/users/testtest", data.actor);
|
||||||
|
Assert.AreEqual("https://85da1577f778.ngrok.io/f89dfd87-f5ce-4603-83d9-405c0e229989", data.apObject.id);
|
||||||
|
Assert.AreEqual("https://85da1577f778.ngrok.io/users/gra", data.apObject.actor);
|
||||||
|
Assert.AreEqual("Follow", data.apObject.type);
|
||||||
|
Assert.AreEqual("https://mamot.fr/users/testtest", data.apObject.apObject);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Add table
Reference in a new issue