🐛 Better override host
This commit is contained in:
@@ -16,7 +16,16 @@ public class ActivityPubDeliveryService(
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
private string Domain => configuration["ActivityPub:Domain"] ?? "localhost";
|
private string Domain => configuration["ActivityPub:Domain"] ?? "localhost";
|
||||||
private HttpClient HttpClient => httpClientFactory.CreateClient();
|
|
||||||
|
private HttpClient HttpClient
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var client = httpClientFactory.CreateClient();
|
||||||
|
client.DefaultRequestHeaders.Clear();
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<bool> SendAcceptActivityAsync(
|
public async Task<bool> SendAcceptActivityAsync(
|
||||||
Guid publisherId,
|
Guid publisherId,
|
||||||
@@ -27,17 +36,17 @@ public class ActivityPubDeliveryService(
|
|||||||
var publisher = await db.Publishers.FindAsync(publisherId);
|
var publisher = await db.Publishers.FindAsync(publisherId);
|
||||||
if (publisher == null)
|
if (publisher == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var actorUrl = $"https://{Domain}/activitypub/actors/{publisher.Name}";
|
var actorUrl = $"https://{Domain}/activitypub/actors/{publisher.Name}";
|
||||||
var followerActor = await db.FediverseActors
|
var followerActor = await db.FediverseActors
|
||||||
.FirstOrDefaultAsync(a => a.Uri == followerActorUri);
|
.FirstOrDefaultAsync(a => a.Uri == followerActorUri);
|
||||||
|
|
||||||
if (followerActor?.InboxUri == null)
|
if (followerActor?.InboxUri == null)
|
||||||
{
|
{
|
||||||
logger.LogWarning("Follower actor or inbox not found: {Uri}", followerActorUri);
|
logger.LogWarning("Follower actor or inbox not found: {Uri}", followerActorUri);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var activity = new Dictionary<string, object>
|
var activity = new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
["@context"] = "https://www.w3.org/ns/activitystreams",
|
["@context"] = "https://www.w3.org/ns/activitystreams",
|
||||||
@@ -46,7 +55,7 @@ public class ActivityPubDeliveryService(
|
|||||||
["actor"] = actorUrl,
|
["actor"] = actorUrl,
|
||||||
["object"] = followActivityId
|
["object"] = followActivityId
|
||||||
};
|
};
|
||||||
|
|
||||||
return await SendActivityToInboxAsync(activity, followerActor.InboxUri, actorUrl);
|
return await SendActivityToInboxAsync(activity, followerActor.InboxUri, actorUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,17 +67,17 @@ public class ActivityPubDeliveryService(
|
|||||||
var publisher = await db.Publishers.FindAsync(publisherId);
|
var publisher = await db.Publishers.FindAsync(publisherId);
|
||||||
if (publisher == null)
|
if (publisher == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var actorUrl = $"https://{Domain}/activitypub/actors/{publisher.Name}";
|
var actorUrl = $"https://{Domain}/activitypub/actors/{publisher.Name}";
|
||||||
var targetActor = await GetOrFetchActorAsync(targetActorUri);
|
var targetActor = await GetOrFetchActorAsync(targetActorUri);
|
||||||
var localActor = await GetOrCreateLocalActorAsync(publisher);
|
var localActor = await GetOrCreateLocalActorAsync(publisher);
|
||||||
|
|
||||||
if (targetActor?.InboxUri == null || localActor == null)
|
if (targetActor?.InboxUri == null || localActor == null)
|
||||||
{
|
{
|
||||||
logger.LogWarning("Target actor or inbox not found: {Uri}", targetActorUri);
|
logger.LogWarning("Target actor or inbox not found: {Uri}", targetActorUri);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var activity = new Dictionary<string, object>
|
var activity = new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
["@context"] = "https://www.w3.org/ns/activitystreams",
|
["@context"] = "https://www.w3.org/ns/activitystreams",
|
||||||
@@ -77,7 +86,7 @@ public class ActivityPubDeliveryService(
|
|||||||
["actor"] = actorUrl,
|
["actor"] = actorUrl,
|
||||||
["object"] = targetActorUri
|
["object"] = targetActorUri
|
||||||
};
|
};
|
||||||
|
|
||||||
await db.FediverseRelationships.AddAsync(new SnFediverseRelationship
|
await db.FediverseRelationships.AddAsync(new SnFediverseRelationship
|
||||||
{
|
{
|
||||||
IsLocalActor = true,
|
IsLocalActor = true,
|
||||||
@@ -88,9 +97,9 @@ public class ActivityPubDeliveryService(
|
|||||||
IsFollowing = true,
|
IsFollowing = true,
|
||||||
IsFollowedBy = false
|
IsFollowedBy = false
|
||||||
});
|
});
|
||||||
|
|
||||||
await db.SaveChangesAsync();
|
await db.SaveChangesAsync();
|
||||||
|
|
||||||
return await SendActivityToInboxAsync(activity, targetActor.InboxUri, actorUrl);
|
return await SendActivityToInboxAsync(activity, targetActor.InboxUri, actorUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,10 +108,10 @@ public class ActivityPubDeliveryService(
|
|||||||
var publisher = await db.Publishers.FindAsync(post.PublisherId);
|
var publisher = await db.Publishers.FindAsync(post.PublisherId);
|
||||||
if (publisher == null)
|
if (publisher == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var actorUrl = $"https://{Domain}/activitypub/actors/{publisher.Name}";
|
var actorUrl = $"https://{Domain}/activitypub/actors/{publisher.Name}";
|
||||||
var postUrl = $"https://{Domain}/posts/{post.Id}";
|
var postUrl = $"https://{Domain}/posts/{post.Id}";
|
||||||
|
|
||||||
var activity = new Dictionary<string, object>
|
var activity = new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
["@context"] = "https://www.w3.org/ns/activitystreams",
|
["@context"] = "https://www.w3.org/ns/activitystreams",
|
||||||
@@ -129,23 +138,21 @@ public class ActivityPubDeliveryService(
|
|||||||
}).ToList<object>()
|
}).ToList<object>()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var followers = await GetRemoteFollowersAsync(publisher.Id);
|
var followers = await GetRemoteFollowersAsync(publisher.Id);
|
||||||
var successCount = 0;
|
var successCount = 0;
|
||||||
|
|
||||||
foreach (var follower in followers)
|
foreach (var follower in followers)
|
||||||
{
|
{
|
||||||
if (follower.InboxUri != null)
|
if (follower.InboxUri == null) continue;
|
||||||
{
|
var success = await SendActivityToInboxAsync(activity, follower.InboxUri, actorUrl);
|
||||||
var success = await SendActivityToInboxAsync(activity, follower.InboxUri, actorUrl);
|
if (success)
|
||||||
if (success)
|
successCount++;
|
||||||
successCount++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.LogInformation("Sent Create activity to {Count}/{Total} followers",
|
logger.LogInformation("Sent Create activity to {Count}/{Total} followers",
|
||||||
successCount, followers.Count);
|
successCount, followers.Count);
|
||||||
|
|
||||||
return successCount > 0;
|
return successCount > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,17 +166,17 @@ public class ActivityPubDeliveryService(
|
|||||||
.Include(p => p.Members)
|
.Include(p => p.Members)
|
||||||
.Where(p => p.Members.Any(m => m.AccountId == accountId))
|
.Where(p => p.Members.Any(m => m.AccountId == accountId))
|
||||||
.FirstOrDefaultAsync();
|
.FirstOrDefaultAsync();
|
||||||
|
|
||||||
if (publisher == null)
|
if (publisher == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var actorUrl = $"https://{Domain}/activitypub/actors/{publisher.Name}";
|
var actorUrl = $"https://{Domain}/activitypub/actors/{publisher.Name}";
|
||||||
var postUrl = $"https://{Domain}/posts/{postId}";
|
var postUrl = $"https://{Domain}/posts/{postId}";
|
||||||
var targetActor = await GetOrFetchActorAsync(targetActorUri);
|
var targetActor = await GetOrFetchActorAsync(targetActorUri);
|
||||||
|
|
||||||
if (targetActor?.InboxUri == null)
|
if (targetActor?.InboxUri == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var activity = new Dictionary<string, object>
|
var activity = new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
["@context"] = "https://www.w3.org/ns/activitystreams",
|
["@context"] = "https://www.w3.org/ns/activitystreams",
|
||||||
@@ -178,7 +185,7 @@ public class ActivityPubDeliveryService(
|
|||||||
["actor"] = actorUrl,
|
["actor"] = actorUrl,
|
||||||
["object"] = postUrl
|
["object"] = postUrl
|
||||||
};
|
};
|
||||||
|
|
||||||
return await SendActivityToInboxAsync(activity, targetActor.InboxUri, actorUrl);
|
return await SendActivityToInboxAsync(activity, targetActor.InboxUri, actorUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,10 +198,10 @@ public class ActivityPubDeliveryService(
|
|||||||
var publisher = await db.Publishers.FindAsync(publisherId);
|
var publisher = await db.Publishers.FindAsync(publisherId);
|
||||||
if (publisher == null)
|
if (publisher == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var actorUrl = $"https://{Domain}/activitypub/actors/{publisher.Name}";
|
var actorUrl = $"https://{Domain}/activitypub/actors/{publisher.Name}";
|
||||||
var followers = await GetRemoteFollowersAsync(publisher.Id);
|
var followers = await GetRemoteFollowersAsync(publisher.Id);
|
||||||
|
|
||||||
var activity = new Dictionary<string, object>
|
var activity = new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
["@context"] = "https://www.w3.org/ns/activitystreams",
|
["@context"] = "https://www.w3.org/ns/activitystreams",
|
||||||
@@ -207,7 +214,7 @@ public class ActivityPubDeliveryService(
|
|||||||
["object"] = objectUri
|
["object"] = objectUri
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var successCount = 0;
|
var successCount = 0;
|
||||||
foreach (var follower in followers)
|
foreach (var follower in followers)
|
||||||
{
|
{
|
||||||
@@ -218,7 +225,7 @@ public class ActivityPubDeliveryService(
|
|||||||
successCount++;
|
successCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return successCount > 0;
|
return successCount > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -232,48 +239,45 @@ public class ActivityPubDeliveryService(
|
|||||||
{
|
{
|
||||||
var json = JsonSerializer.Serialize(activity);
|
var json = JsonSerializer.Serialize(activity);
|
||||||
var request = new HttpRequestMessage(HttpMethod.Post, inboxUrl);
|
var request = new HttpRequestMessage(HttpMethod.Post, inboxUrl);
|
||||||
|
|
||||||
request.Content = new StringContent(json, Encoding.UTF8, "application/activity+json");
|
request.Content = new StringContent(json, Encoding.UTF8, "application/activity+json");
|
||||||
request.Headers.Date = DateTimeOffset.UtcNow;
|
request.Headers.Date = DateTimeOffset.UtcNow;
|
||||||
|
|
||||||
var bodyBytes = Encoding.UTF8.GetBytes(json);
|
var bodyBytes = Encoding.UTF8.GetBytes(json);
|
||||||
using var sha256 = SHA256.Create();
|
var hash = SHA256.HashData(bodyBytes);
|
||||||
var hash = sha256.ComputeHash(bodyBytes);
|
|
||||||
var digest = $"SHA-256={Convert.ToBase64String(hash)}";
|
var digest = $"SHA-256={Convert.ToBase64String(hash)}";
|
||||||
request.Headers.Add("Digest", digest);
|
request.Headers.Add("Digest", digest);
|
||||||
request.Headers.Add("Host", new Uri(inboxUrl).Host);
|
request.Headers.Host = new Uri(inboxUrl).Host;
|
||||||
|
|
||||||
logger.LogInformation("Preparing request to {Inbox}", inboxUrl);
|
logger.LogInformation("Preparing request to {Inbox}", inboxUrl);
|
||||||
logger.LogInformation("Request body (truncated): {Body}", json.Substring(0, Math.Min(200, json.Length)) + "...");
|
logger.LogInformation("Request body (truncated): {Body}", json[..Math.Min(200, json.Length)] + "...");
|
||||||
logger.LogInformation("Request headers before signing: Date={Date}, Digest={Digest}, Host={Host}",
|
logger.LogInformation("Request headers before signing: Date={Date}, Digest={Digest}, Host={Host}",
|
||||||
request.Headers.Date, digest, request.Headers.Host);
|
request.Headers.Date, digest, request.Headers.Host);
|
||||||
|
|
||||||
var signatureHeaders = await signatureService.SignOutgoingRequest(request, actorUri);
|
var signatureHeaders = await signatureService.SignOutgoingRequest(request, actorUri);
|
||||||
|
|
||||||
var signatureString = $"keyId=\"{signatureHeaders["keyId"]}\"," +
|
var signatureString = $"keyId=\"{signatureHeaders["keyId"]}\"," +
|
||||||
$"algorithm=\"{signatureHeaders["algorithm"]}\"," +
|
$"algorithm=\"{signatureHeaders["algorithm"]}\"," +
|
||||||
$"headers=\"{signatureHeaders["headers"]}\"," +
|
$"headers=\"{signatureHeaders["headers"]}\"," +
|
||||||
$"signature=\"{signatureHeaders["signature"]}\"";
|
$"signature=\"{signatureHeaders["signature"]}\"";
|
||||||
|
|
||||||
request.Headers.Add("Signature", signatureString);
|
request.Headers.Add("Signature", signatureString);
|
||||||
|
|
||||||
logger.LogInformation("Full signature header: {Signature}", signatureString);
|
logger.LogInformation("Full signature header: {Signature}", signatureString);
|
||||||
logger.LogInformation("Request headers after signing:");
|
logger.LogInformation("Request headers after signing:");
|
||||||
foreach (var header in request.Headers)
|
foreach (var header in request.Headers)
|
||||||
{
|
{
|
||||||
var value = header.Value.Any() ? header.Value.First() : string.Empty;
|
var value = header.Value.Any() ? header.Value.First() : string.Empty;
|
||||||
if (header.Key == "signature")
|
if (header.Key == "signature")
|
||||||
{
|
value = value[..Math.Min(100, value.Length)] + "...";
|
||||||
value = value.Substring(0, Math.Min(100, value.Length)) + "...";
|
|
||||||
}
|
|
||||||
logger.LogInformation(" {Key}: {Value}", header.Key, value);
|
logger.LogInformation(" {Key}: {Value}", header.Key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
var response = await HttpClient.SendAsync(request);
|
var response = await HttpClient.SendAsync(request);
|
||||||
var responseContent = await response.Content.ReadAsStringAsync();
|
var responseContent = await response.Content.ReadAsStringAsync();
|
||||||
|
|
||||||
logger.LogInformation("Response from {Inbox}. Status: {Status}", inboxUrl, response.StatusCode);
|
logger.LogInformation("Response from {Inbox}. Status: {Status}", inboxUrl, response.StatusCode);
|
||||||
|
|
||||||
if (!response.IsSuccessStatusCode)
|
if (!response.IsSuccessStatusCode)
|
||||||
{
|
{
|
||||||
logger.LogError("Failed to send activity to {Inbox}. Status: {Status}, Response: {Response}",
|
logger.LogError("Failed to send activity to {Inbox}. Status: {Status}, Response: {Response}",
|
||||||
@@ -282,7 +286,7 @@ public class ActivityPubDeliveryService(
|
|||||||
request.Method, request.RequestUri, request.Content?.Headers.ContentType);
|
request.Method, request.RequestUri, request.Content?.Headers.ContentType);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.LogInformation("Successfully sent activity to {Inbox}", inboxUrl);
|
logger.LogInformation("Successfully sent activity to {Inbox}", inboxUrl);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -297,9 +301,9 @@ public class ActivityPubDeliveryService(
|
|||||||
{
|
{
|
||||||
return await db.FediverseRelationships
|
return await db.FediverseRelationships
|
||||||
.Include(r => r.TargetActor)
|
.Include(r => r.TargetActor)
|
||||||
.Where(r =>
|
.Where(r =>
|
||||||
r.LocalPublisherId == publisherId &&
|
r.LocalPublisherId == publisherId &&
|
||||||
r.IsFollowedBy &&
|
r.IsFollowedBy &&
|
||||||
r.IsLocalActor)
|
r.IsLocalActor)
|
||||||
.Select(r => r.TargetActor)
|
.Select(r => r.TargetActor)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
@@ -308,16 +312,16 @@ public class ActivityPubDeliveryService(
|
|||||||
private async Task<SnFediverseActor?> GetOrCreateLocalActorAsync(SnPublisher publisher)
|
private async Task<SnFediverseActor?> GetOrCreateLocalActorAsync(SnPublisher publisher)
|
||||||
{
|
{
|
||||||
var actorUrl = $"https://{Domain}/activitypub/actors/{publisher.Name}";
|
var actorUrl = $"https://{Domain}/activitypub/actors/{publisher.Name}";
|
||||||
|
|
||||||
var localActor = await db.FediverseActors
|
var localActor = await db.FediverseActors
|
||||||
.FirstOrDefaultAsync(a => a.Uri == actorUrl);
|
.FirstOrDefaultAsync(a => a.Uri == actorUrl);
|
||||||
|
|
||||||
if (localActor != null)
|
if (localActor != null)
|
||||||
return localActor;
|
return localActor;
|
||||||
|
|
||||||
var instance = await db.FediverseInstances
|
var instance = await db.FediverseInstances
|
||||||
.FirstOrDefaultAsync(i => i.Domain == Domain);
|
.FirstOrDefaultAsync(i => i.Domain == Domain);
|
||||||
|
|
||||||
if (instance == null)
|
if (instance == null)
|
||||||
{
|
{
|
||||||
instance = new SnFediverseInstance
|
instance = new SnFediverseInstance
|
||||||
@@ -330,7 +334,7 @@ public class ActivityPubDeliveryService(
|
|||||||
}
|
}
|
||||||
|
|
||||||
var assetsBaseUrl = configuration["ActivityPub:FileBaseUrl"] ?? $"https://{Domain}/files";
|
var assetsBaseUrl = configuration["ActivityPub:FileBaseUrl"] ?? $"https://{Domain}/files";
|
||||||
|
|
||||||
localActor = new SnFediverseActor
|
localActor = new SnFediverseActor
|
||||||
{
|
{
|
||||||
Uri = actorUrl,
|
Uri = actorUrl,
|
||||||
@@ -345,10 +349,10 @@ public class ActivityPubDeliveryService(
|
|||||||
HeaderUrl = publisher.Background != null ? $"{assetsBaseUrl}/{publisher.Background.Id}" : null,
|
HeaderUrl = publisher.Background != null ? $"{assetsBaseUrl}/{publisher.Background.Id}" : null,
|
||||||
InstanceId = instance.Id
|
InstanceId = instance.Id
|
||||||
};
|
};
|
||||||
|
|
||||||
db.FediverseActors.Add(localActor);
|
db.FediverseActors.Add(localActor);
|
||||||
await db.SaveChangesAsync();
|
await db.SaveChangesAsync();
|
||||||
|
|
||||||
return localActor;
|
return localActor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -356,26 +360,26 @@ public class ActivityPubDeliveryService(
|
|||||||
{
|
{
|
||||||
var actor = await db.FediverseActors
|
var actor = await db.FediverseActors
|
||||||
.FirstOrDefaultAsync(a => a.Uri == actorUri);
|
.FirstOrDefaultAsync(a => a.Uri == actorUri);
|
||||||
|
|
||||||
if (actor != null)
|
if (actor != null)
|
||||||
return actor;
|
return actor;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var response = await HttpClient.GetAsync(actorUri);
|
var response = await HttpClient.GetAsync(actorUri);
|
||||||
if (!response.IsSuccessStatusCode)
|
if (!response.IsSuccessStatusCode)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
var json = await response.Content.ReadAsStringAsync();
|
var json = await response.Content.ReadAsStringAsync();
|
||||||
var actorData = JsonSerializer.Deserialize<Dictionary<string, object>>(json);
|
var actorData = JsonSerializer.Deserialize<Dictionary<string, object>>(json);
|
||||||
|
|
||||||
if (actorData == null)
|
if (actorData == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
var domain = new Uri(actorUri).Host;
|
var domain = new Uri(actorUri).Host;
|
||||||
var instance = await db.FediverseInstances
|
var instance = await db.FediverseInstances
|
||||||
.FirstOrDefaultAsync(i => i.Domain == domain);
|
.FirstOrDefaultAsync(i => i.Domain == domain);
|
||||||
|
|
||||||
if (instance == null)
|
if (instance == null)
|
||||||
{
|
{
|
||||||
instance = new SnFediverseInstance
|
instance = new SnFediverseInstance
|
||||||
@@ -387,7 +391,7 @@ public class ActivityPubDeliveryService(
|
|||||||
await db.SaveChangesAsync();
|
await db.SaveChangesAsync();
|
||||||
await discoveryService.FetchInstanceMetadataAsync(instance);
|
await discoveryService.FetchInstanceMetadataAsync(instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
actor = new SnFediverseActor
|
actor = new SnFediverseActor
|
||||||
{
|
{
|
||||||
Uri = actorUri,
|
Uri = actorUri,
|
||||||
@@ -401,10 +405,10 @@ public class ActivityPubDeliveryService(
|
|||||||
AvatarUrl = actorData.GetValueOrDefault("icon")?.ToString(),
|
AvatarUrl = actorData.GetValueOrDefault("icon")?.ToString(),
|
||||||
InstanceId = instance.Id
|
InstanceId = instance.Id
|
||||||
};
|
};
|
||||||
|
|
||||||
db.FediverseActors.Add(actor);
|
db.FediverseActors.Add(actor);
|
||||||
await db.SaveChangesAsync();
|
await db.SaveChangesAsync();
|
||||||
|
|
||||||
return actor;
|
return actor;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -418,4 +422,4 @@ public class ActivityPubDeliveryService(
|
|||||||
{
|
{
|
||||||
return actorUri.Split('/').Last();
|
return actorUri.Split('/').Last();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,5 @@
|
|||||||
using System.Security.Cryptography;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using DysonNetwork.Shared.Models;
|
using DysonNetwork.Shared.Models;
|
||||||
using DysonNetwork.Sphere.ActivityPub;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using NodaTime;
|
using NodaTime;
|
||||||
|
|
||||||
@@ -105,7 +102,7 @@ public class ActivityPubSignatureService(
|
|||||||
logger.LogInformation("Signing outgoing request. ActorUri: {ActorUri}, PublisherId: {PublisherId}",
|
logger.LogInformation("Signing outgoing request. ActorUri: {ActorUri}, PublisherId: {PublisherId}",
|
||||||
actorUri, publisher.Id);
|
actorUri, publisher.Id);
|
||||||
|
|
||||||
var headersToSign = new[] { "(request-target)", "host", "date", "digest" };
|
var headersToSign = new[] { RequestTarget, "host", "date", "digest" };
|
||||||
var signingString = BuildSigningStringForRequest(request, headersToSign);
|
var signingString = BuildSigningStringForRequest(request, headersToSign);
|
||||||
|
|
||||||
logger.LogInformation("Signing string for outgoing request: {SigningString}", signingString);
|
logger.LogInformation("Signing string for outgoing request: {SigningString}", signingString);
|
||||||
@@ -215,7 +212,7 @@ public class ActivityPubSignatureService(
|
|||||||
sb.Append(header.ToLower());
|
sb.Append(header.ToLower());
|
||||||
sb.Append(": ");
|
sb.Append(": ");
|
||||||
|
|
||||||
if (header == "(request-target)")
|
if (header == RequestTarget)
|
||||||
{
|
{
|
||||||
var method = context.Request.Method.ToLower();
|
var method = context.Request.Method.ToLower();
|
||||||
var path = context.Request.Path.Value ?? "";
|
var path = context.Request.Path.Value ?? "";
|
||||||
@@ -244,56 +241,51 @@ public class ActivityPubSignatureService(
|
|||||||
foreach (var header in headers)
|
foreach (var header in headers)
|
||||||
{
|
{
|
||||||
if (sb.Length > 0)
|
if (sb.Length > 0)
|
||||||
sb.Append("\n");
|
sb.Append('\n');
|
||||||
|
|
||||||
sb.Append(header.ToLower());
|
sb.Append(header.ToLower());
|
||||||
sb.Append(": ");
|
sb.Append(": ");
|
||||||
|
|
||||||
if (header == "(request-target)")
|
switch (header)
|
||||||
{
|
{
|
||||||
var method = request.Method.Method.ToLower();
|
case RequestTarget:
|
||||||
var path = request.RequestUri?.PathAndQuery ?? "/";
|
{
|
||||||
sb.Append($"{method} {path}");
|
var method = request.Method.Method.ToLower();
|
||||||
logger.LogInformation(" (request-target): {Value}", $"{method} {path}");
|
var path = request.RequestUri?.PathAndQuery ?? "/";
|
||||||
}
|
sb.Append($"{method} {path}");
|
||||||
else if (header == "host")
|
logger.LogInformation(" {Key}: {Value}", RequestTarget, $"{method} {path}");
|
||||||
{
|
break;
|
||||||
if (request.Headers.Contains("Host"))
|
}
|
||||||
|
case "host" when request.Headers.Contains("Host"):
|
||||||
{
|
{
|
||||||
var value = request.Headers.GetValues("Host").First();
|
var value = request.Headers.GetValues("Host").First();
|
||||||
sb.Append(value);
|
sb.Append(value);
|
||||||
logger.LogInformation(" host: {Value}", value);
|
logger.LogInformation(" host: {Value}", value);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else
|
case "host":
|
||||||
{
|
|
||||||
logger.LogWarning("Host header not found in request");
|
logger.LogWarning("Host header not found in request");
|
||||||
}
|
break;
|
||||||
}
|
case "date" when request.Headers.Contains("Date"):
|
||||||
else if (header == "date")
|
|
||||||
{
|
|
||||||
if (request.Headers.Contains("Date"))
|
|
||||||
{
|
{
|
||||||
var value = request.Headers.GetValues("Date").First();
|
var value = request.Headers.GetValues("Date").First();
|
||||||
sb.Append(value);
|
sb.Append(value);
|
||||||
logger.LogInformation(" date: {Value}", value);
|
logger.LogInformation(" date: {Value}", value);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else
|
case "date":
|
||||||
{
|
|
||||||
logger.LogWarning("Date header not found in request");
|
logger.LogWarning("Date header not found in request");
|
||||||
}
|
break;
|
||||||
}
|
case "digest" when request.Headers.Contains("Digest"):
|
||||||
else if (header == "digest")
|
|
||||||
{
|
|
||||||
if (request.Headers.Contains("Digest"))
|
|
||||||
{
|
{
|
||||||
var value = request.Headers.GetValues("Digest").First();
|
var value = request.Headers.GetValues("Digest").First();
|
||||||
sb.Append(value);
|
sb.Append(value);
|
||||||
logger.LogInformation(" digest: {Value}", value);
|
logger.LogInformation(" digest: {Value}", value);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else
|
case "digest":
|
||||||
{
|
|
||||||
logger.LogWarning("Digest header not found in request");
|
logger.LogWarning("Digest header not found in request");
|
||||||
}
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -68,6 +68,7 @@
|
|||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AForwardedHeaders_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fcfe5737f9bb84738979cbfedd11822a8ea00_003F50_003F9a335f87_003FForwardedHeaders_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AForwardedHeaders_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2024_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fcfe5737f9bb84738979cbfedd11822a8ea00_003F50_003F9a335f87_003FForwardedHeaders_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AForwardedTransformExtensions_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fbf3f51607a3e4e76b5b91640cd7409195c430_003F03_003F36e779df_003FForwardedTransformExtensions_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AForwardedTransformExtensions_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fbf3f51607a3e4e76b5b91640cd7409195c430_003F03_003F36e779df_003FForwardedTransformExtensions_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AGrpcChannel_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F33b697967214455ca048862a59bf98a457c60_003Fc0_003Fd99cb5be_003FGrpcChannel_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AGrpcChannel_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F33b697967214455ca048862a59bf98a457c60_003Fc0_003Fd99cb5be_003FGrpcChannel_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AHttpClient_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E3_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fe2a45b06be5b46e99e816c528ca681d21dff08_003Fcc_003F25010ffa_003FHttpClient_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AHttpContext_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fc181aff8c6ec418494a7efcfec578fc154e00_003Fd0_003Fcc905531_003FHttpContext_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AHttpContext_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fc181aff8c6ec418494a7efcfec578fc154e00_003Fd0_003Fcc905531_003FHttpContext_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AHttpRequestHeaders_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fb904f9896c4049fabd596decf1be9c381dc400_003F32_003F906beb77_003FHttpRequestHeaders_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AHttpRequestHeaders_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fb904f9896c4049fabd596decf1be9c381dc400_003F32_003F906beb77_003FHttpRequestHeaders_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AHttpStatusCode_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fb3f2e07d4b3f4b42a41fbcf3137e534f3be00_003Fe2_003F215f9441_003FHttpStatusCode_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AHttpStatusCode_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002E_002E_003FLibrary_003FApplication_0020Support_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fb3f2e07d4b3f4b42a41fbcf3137e534f3be00_003Fe2_003F215f9441_003FHttpStatusCode_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
|
|||||||
Reference in New Issue
Block a user