actor ap retrieval functionnal

This commit is contained in:
Nicolas Constant 2020-06-06 00:14:42 -04:00
parent 3aed16024f
commit e1ef37d504
No known key found for this signature in database
GPG Key ID: 1E9F677FB01A5688
17 changed files with 268 additions and 39 deletions

1
.gitignore vendored
View File

@ -4,6 +4,7 @@
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
appsettings.*.json
key.json
# User-specific files
*.rsuser

View File

@ -0,0 +1,21 @@
using System;
using System.Text.Json.Serialization;
namespace BirdsiteLive.ActivityPub
{
public class Actor
{
[JsonPropertyName("@context")]
public string[] context { get; set; } = new[] {"https://www.w3.org/ns/activitystreams", "https://w3id.org/security/v1"};
public string id { get; set; }
public string type { get; set; }
public string preferredUsername { get; set; }
public string name { get; set; }
public string summary { get; set; }
public string url { get; set; }
public string inbox { get; set; }
public PublicKey publicKey { get; set; }
public Image icon { get; set; }
public Image image { get; set; }
}
}

View File

@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Text.Json" Version="4.7.2" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,9 @@
namespace BirdsiteLive.ActivityPub
{
public class Image
{
public string type { get; set; } = "image";
public string mediaType { get; set; }
public string url { get; set; }
}
}

View File

@ -0,0 +1,9 @@
namespace BirdsiteLive.ActivityPub
{
public class PublicKey
{
public string id { get; set; }
public string owner { get; set; }
public string publicKeyPem { get; set; }
}
}

View File

@ -1,4 +1,4 @@
namespace BirdsiteLive.Models
namespace BirdsiteLive.Common.Settings
{
public class InstanceSettings
{

View File

@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\BirdsiteLive.ActivityPub\BirdsiteLive.ActivityPub.csproj" />
<ProjectReference Include="..\BirdsiteLive.Cryptography\BirdsiteLive.Cryptography.csproj" />
<ProjectReference Include="..\BirdsiteLive.Twitter\BirdsiteLive.Twitter.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,26 @@
using BirdsiteLive.Domain.Factories;
namespace BirdsiteLive.Domain
{
public interface ICryptoService
{
string GetUserPem(string id);
}
public class CryptoService : ICryptoService
{
private readonly IMagicKeyFactory _magicKeyFactory;
#region Ctor
public CryptoService(IMagicKeyFactory magicKeyFactory)
{
_magicKeyFactory = magicKeyFactory;
}
#endregion
public string GetUserPem(string id)
{
return _magicKeyFactory.GetMagicKey().AsPEM;
}
}
}

View File

@ -0,0 +1,41 @@
using System.IO;
using BirdsiteLive.Cryptography;
namespace BirdsiteLive.Domain.Factories
{
public interface IMagicKeyFactory
{
MagicKey GetMagicKey();
}
public class MagicKeyFactory : IMagicKeyFactory
{
private const string Path = "key.json";
private static MagicKey _magicKey;
#region Ctor
public MagicKeyFactory()
{
}
#endregion
public MagicKey GetMagicKey()
{
//Cached key
if (_magicKey != null) return _magicKey;
//Generate key if needed
if (!File.Exists(Path))
{
var key = MagicKey.Generate();
File.WriteAllText(Path, key.PrivateKey);
}
//Load and return key
var serializedKey = File.ReadAllText(Path);
_magicKey = new MagicKey(serializedKey);
return _magicKey;
}
}
}

View File

@ -0,0 +1,57 @@
using System;
using BirdsiteLive.ActivityPub;
using BirdsiteLive.Common.Settings;
using BirdsiteLive.Twitter.Models;
namespace BirdsiteLive.Domain
{
public interface IUserService
{
Actor GetUser(TwitterUser twitterUser);
}
public class UserService : IUserService
{
private readonly ICryptoService _cryptoService;
private readonly string _host;
#region Ctor
public UserService(InstanceSettings instanceSettings, ICryptoService cryptoService)
{
_cryptoService = cryptoService;
_host = $"https://{instanceSettings.Domain.Replace("https://",string.Empty).Replace("http://", string.Empty).TrimEnd('/')}";
}
#endregion
public Actor GetUser(TwitterUser twitterUser)
{
var user = new Actor
{
id = $"{_host}/users/{twitterUser.Acct}",
type = "Person",
preferredUsername = twitterUser.Acct,
name = twitterUser.Name,
inbox = $"{_host}/users/{twitterUser.Acct}/inbox",
summary = twitterUser.Description,
url = $"{_host}/@{twitterUser.Acct}",
publicKey = new PublicKey()
{
id = $"{_host}/users/{twitterUser.Acct}#main-key",
owner = $"{_host}/users/{twitterUser.Acct}",
publicKeyPem = _cryptoService.GetUserPem(twitterUser.Acct)
},
icon = new Image
{
mediaType = "image/jpeg",
url = twitterUser.ProfileImageUrl
},
image = new Image
{
mediaType = "image/jpeg",
url = twitterUser.ProfileBannerURL
}
};
return user;
}
}
}

View File

@ -15,7 +15,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BirdsiteLive.Common", "Bird
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{A32D3458-09D0-4E0A-BA4B-8C411B816B94}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BirdsiteLive.Cryptography.Tests", "Tests\BirdsiteLive.Cryptography.Tests\BirdsiteLive.Cryptography.Tests.csproj", "{155D46A4-2D05-47F2-8FFC-0B7C412A7652}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BirdsiteLive.Cryptography.Tests", "Tests\BirdsiteLive.Cryptography.Tests\BirdsiteLive.Cryptography.Tests.csproj", "{155D46A4-2D05-47F2-8FFC-0B7C412A7652}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BirdsiteLive.Domain", "BirdsiteLive.Domain\BirdsiteLive.Domain.csproj", "{D48450EE-D8BD-4228-9864-043AC88F7EE0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BirdsiteLive.ActivityPub", "BirdsiteLive.ActivityPub\BirdsiteLive.ActivityPub.csproj", "{7463E1E2-9736-4A46-8507-010BDD8ECFBB}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -43,6 +47,14 @@ Global
{155D46A4-2D05-47F2-8FFC-0B7C412A7652}.Debug|Any CPU.Build.0 = Debug|Any CPU
{155D46A4-2D05-47F2-8FFC-0B7C412A7652}.Release|Any CPU.ActiveCfg = Release|Any CPU
{155D46A4-2D05-47F2-8FFC-0B7C412A7652}.Release|Any CPU.Build.0 = Release|Any CPU
{D48450EE-D8BD-4228-9864-043AC88F7EE0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D48450EE-D8BD-4228-9864-043AC88F7EE0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D48450EE-D8BD-4228-9864-043AC88F7EE0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D48450EE-D8BD-4228-9864-043AC88F7EE0}.Release|Any CPU.Build.0 = Release|Any CPU
{7463E1E2-9736-4A46-8507-010BDD8ECFBB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7463E1E2-9736-4A46-8507-010BDD8ECFBB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7463E1E2-9736-4A46-8507-010BDD8ECFBB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7463E1E2-9736-4A46-8507-010BDD8ECFBB}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -52,6 +64,8 @@ Global
{77C559D1-80A2-4B1C-A566-AE2D156944A4} = {4FEAD6BC-3C8E-451A-8CA1-FF1AF47D26CC}
{E64E7501-5DB8-4620-BA35-BA59FD746ABA} = {4FEAD6BC-3C8E-451A-8CA1-FF1AF47D26CC}
{155D46A4-2D05-47F2-8FFC-0B7C412A7652} = {A32D3458-09D0-4E0A-BA4B-8C411B816B94}
{D48450EE-D8BD-4228-9864-043AC88F7EE0} = {4FEAD6BC-3C8E-451A-8CA1-FF1AF47D26CC}
{7463E1E2-9736-4A46-8507-010BDD8ECFBB} = {4FEAD6BC-3C8E-451A-8CA1-FF1AF47D26CC}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {69E8DCAD-4C37-4010-858F-5F94E6FBABCE}

View File

@ -15,6 +15,7 @@
<ItemGroup>
<ProjectReference Include="..\BirdsiteLive.Common\BirdsiteLive.Common.csproj" />
<ProjectReference Include="..\BirdsiteLive.Cryptography\BirdsiteLive.Cryptography.csproj" />
<ProjectReference Include="..\BirdsiteLive.Domain\BirdsiteLive.Domain.csproj" />
<ProjectReference Include="..\BirdsiteLive.Twitter\BirdsiteLive.Twitter.csproj" />
</ItemGroup>

View File

@ -1,37 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using BirdsiteLive.Twitter;
using Microsoft.AspNetCore.Mvc;
namespace BirdsiteLive.Controllers
{
public class UserController : Controller
{
private readonly ITwitterService _twitterService;
#region Ctor
public UserController(ITwitterService twitterService)
{
_twitterService = twitterService;
}
#endregion
[Route("/@{id}")]
[Route("/user/{id}")]
public IActionResult Index(string id)
{
var user = _twitterService.GetUser(id);
if (user == null) return NotFound();
var r = Request.Headers["Accept"].First();
if (r.Contains("application/activity+json"))
return Json(new { test = "test" });
return View(user);
}
}
}

View File

@ -0,0 +1,58 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using BirdsiteLive.Domain;
using BirdsiteLive.Twitter;
using Microsoft.AspNetCore.Mvc;
namespace BirdsiteLive.Controllers
{
public class UsersController : Controller
{
private readonly ITwitterService _twitterService;
private readonly IUserService _userService;
#region Ctor
public UsersController(ITwitterService twitterService, IUserService userService)
{
_twitterService = twitterService;
_userService = userService;
}
#endregion
[Route("/@{id}")]
[Route("/users/{id}")]
public IActionResult Index(string id)
{
var user = _twitterService.GetUser(id);
if (user == null) return NotFound();
var r = Request.Headers["Accept"].First();
if (r.Contains("application/activity+json"))
{
var apUser = _userService.GetUser(user);
return Json(apUser);
}
return View(user);
}
[Route("/users/{id}/inbox")]
[HttpPost]
public async Task<IActionResult> Inbox()
{
var r = Request;
using (var reader = new StreamReader(Request.Body))
{
var body = await reader.ReadToEndAsync();
// Do something
}
return Ok();
}
}
}

View File

@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using BirdsiteLive.Common.Settings;
using BirdsiteLive.Models;
using BirdsiteLive.Twitter;
using Microsoft.AspNetCore.Mvc;

View File

@ -45,9 +45,13 @@ namespace BirdsiteLive
var twitterSettings = Configuration.GetSection("Twitter").Get<TwitterSettings>();
services.For<TwitterSettings>().Use(x => twitterSettings);
var instanceSettings = Configuration.GetSection("Instance").Get<InstanceSettings>();
services.For<InstanceSettings>().Use(x => instanceSettings);
services.Scan(_ =>
{
_.Assembly("BirdsiteLive.Twitter");
_.Assembly("BirdsiteLive.Domain");
_.TheCallingAssembly();
//_.AssemblyContainingType<IDal>();