added whitelisting checks in follows

This commit is contained in:
Nicolas Constant 2021-02-04 18:56:14 -05:00
parent 3e772f2cd4
commit 392c7ca494
No known key found for this signature in database
GPG key ID: 1E9F677FB01A5688

View file

@ -10,6 +10,7 @@ using BirdsiteLive.ActivityPub.Converters;
using BirdsiteLive.Common.Settings;
using BirdsiteLive.Cryptography;
using BirdsiteLive.Domain.BusinessUseCases;
using BirdsiteLive.Domain.Repository;
using BirdsiteLive.Domain.Statistics;
using BirdsiteLive.Domain.Tools;
using BirdsiteLive.Twitter;
@ -39,8 +40,10 @@ namespace BirdsiteLive.Domain
private readonly ITwitterUserService _twitterUserService;
private readonly IModerationRepository _moderationRepository;
#region Ctor
public UserService(InstanceSettings instanceSettings, ICryptoService cryptoService, IActivityPubService activityPubService, IProcessFollowUser processFollowUser, IProcessUndoFollowUser processUndoFollowUser, IStatusExtractor statusExtractor, IExtractionStatisticsHandler statisticsHandler, ITwitterUserService twitterUserService)
public UserService(InstanceSettings instanceSettings, ICryptoService cryptoService, IActivityPubService activityPubService, IProcessFollowUser processFollowUser, IProcessUndoFollowUser processUndoFollowUser, IStatusExtractor statusExtractor, IExtractionStatisticsHandler statisticsHandler, ITwitterUserService twitterUserService, IModerationRepository moderationRepository)
{
_instanceSettings = instanceSettings;
_cryptoService = cryptoService;
@ -50,6 +53,7 @@ namespace BirdsiteLive.Domain
_statusExtractor = statusExtractor;
_statisticsHandler = statisticsHandler;
_twitterUserService = twitterUserService;
_moderationRepository = moderationRepository;
}
#endregion
@ -118,62 +122,94 @@ namespace BirdsiteLive.Domain
var sigValidation = await ValidateSignature(activity.actor, signature, method, path, queryString, requestHeaders, body);
if (!sigValidation.SignatureIsValidated) return false;
// Save Follow in DB
var followerUserName = sigValidation.User.preferredUsername.ToLowerInvariant();
// Prepare data
var followerUserName = sigValidation.User.preferredUsername.ToLowerInvariant().Trim();
var followerHost = sigValidation.User.url.Replace("https://", string.Empty).Split('/').First();
var followerInbox = sigValidation.User.inbox;
var followerSharedInbox = sigValidation.User?.endpoints?.sharedInbox;
var twitterUser = activity.apObject.Split('/').Last().Replace("@", string.Empty);
var twitterUser = activity.apObject.Split('/').Last().Replace("@", string.Empty).ToLowerInvariant().Trim();
// Make sure to only keep routes
followerInbox = OnlyKeepRoute(followerInbox, followerHost);
followerSharedInbox = OnlyKeepRoute(followerSharedInbox, followerHost);
// Validate Moderation status
var followerModPolicy = _moderationRepository.GetModerationType(ModerationEntityTypeEnum.Follower);
if (followerModPolicy != ModerationTypeEnum.None)
{
var followerStatus = _moderationRepository.CheckStatus(ModerationEntityTypeEnum.Follower, $"@{followerUserName}@{followerHost}");
if(followerModPolicy == ModerationTypeEnum.WhiteListing && followerStatus != ModeratedTypeEnum.WhiteListed ||
followerModPolicy == ModerationTypeEnum.BlackListing && followerStatus == ModeratedTypeEnum.BlackListed)
return await SendRejectFollowAsync(activity, followerHost);
}
// Validate TwitterAccount status
var twitterAccountModPolicy = _moderationRepository.GetModerationType(ModerationEntityTypeEnum.TwitterAccount);
if (twitterAccountModPolicy != ModerationTypeEnum.None)
{
var twitterUserStatus = _moderationRepository.CheckStatus(ModerationEntityTypeEnum.TwitterAccount, twitterUser);
if (twitterAccountModPolicy == ModerationTypeEnum.WhiteListing && twitterUserStatus != ModeratedTypeEnum.WhiteListed ||
twitterAccountModPolicy == ModerationTypeEnum.BlackListing && twitterUserStatus == ModeratedTypeEnum.BlackListed)
return await SendRejectFollowAsync(activity, followerHost);
}
// Validate User Protected
var user = _twitterUserService.GetUser(twitterUser);
if (!user.Protected)
{
// Execute
await _processFollowUser.ExecuteAsync(followerUserName, followerHost, twitterUser, followerInbox, followerSharedInbox);
// Send Accept Activity
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, followerHost, activity.apObject);
return result == HttpStatusCode.Accepted || result == HttpStatusCode.OK; //TODO: revamp this for better error handling
return await SendAcceptFollowAsync(activity, followerHost);
}
else
{
// Send Reject Activity
var acceptFollow = new ActivityRejectFollow()
{
context = "https://www.w3.org/ns/activitystreams",
id = $"{activity.apObject}#rejects/follows/{Guid.NewGuid()}",
type = "Reject",
actor = activity.apObject,
apObject = new ActivityFollow()
{
id = activity.id,
type = activity.type,
actor = activity.actor,
apObject = activity.apObject
}
};
var result = await _activityPubService.PostDataAsync(acceptFollow, followerHost, activity.apObject);
return result == HttpStatusCode.Accepted || result == HttpStatusCode.OK; //TODO: revamp this for better error handling
return await SendRejectFollowAsync(activity, followerHost);
}
}
private async Task<bool> SendAcceptFollowAsync(ActivityFollow activity, string followerHost)
{
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, followerHost, activity.apObject);
return result == HttpStatusCode.Accepted ||
result == HttpStatusCode.OK; //TODO: revamp this for better error handling
}
private async Task<bool> SendRejectFollowAsync(ActivityFollow activity, string followerHost)
{
var acceptFollow = new ActivityRejectFollow()
{
context = "https://www.w3.org/ns/activitystreams",
id = $"{activity.apObject}#rejects/follows/{Guid.NewGuid()}",
type = "Reject",
actor = activity.apObject,
apObject = new ActivityFollow()
{
id = activity.id,
type = activity.type,
actor = activity.actor,
apObject = activity.apObject
}
};
var result = await _activityPubService.PostDataAsync(acceptFollow, followerHost, activity.apObject);
return result == HttpStatusCode.Accepted ||
result == HttpStatusCode.OK; //TODO: revamp this for better error handling
}
private string OnlyKeepRoute(string inbox, string host)
{