added Delete logic

This commit is contained in:
Nicolas Constant 2021-12-13 20:43:57 -05:00
parent 93b43ee4a0
commit 7205a09eaa
No known key found for this signature in database
GPG Key ID: 1E9F677FB01A5688
6 changed files with 199 additions and 69 deletions

View File

@ -0,0 +1,51 @@
using System.Linq;
using System.Threading.Tasks;
using BirdsiteLive.DAL.Contracts;
using BirdsiteLive.DAL.Models;
namespace BirdsiteLive.Domain.BusinessUseCases
{
public interface IProcessDeleteUser
{
Task ExecuteAsync(Follower follower);
Task ExecuteAsync(string followerUsername, string followerDomain);
}
public class ProcessDeleteUser : IProcessDeleteUser
{
private readonly IFollowersDal _followersDal;
private readonly ITwitterUserDal _twitterUserDal;
#region Ctor
public ProcessDeleteUser(IFollowersDal followersDal, ITwitterUserDal twitterUserDal)
{
_followersDal = followersDal;
_twitterUserDal = twitterUserDal;
}
#endregion
public async Task ExecuteAsync(string followerUsername, string followerDomain)
{
// Get Follower and Twitter Users
var follower = await _followersDal.GetFollowerAsync(followerUsername, followerDomain);
if (follower == null) return;
await ExecuteAsync(follower);
}
public async Task ExecuteAsync(Follower follower)
{
// Remove twitter users if no more followers
var followings = follower.Followings;
foreach (var following in followings)
{
var followers = await _followersDal.GetFollowersAsync(following);
if (followers.Length == 1 && followers.First().Id == follower.Id)
await _twitterUserDal.DeleteTwitterUserAsync(following);
}
// Remove follower from DB
await _followersDal.DeleteFollowerAsync(follower.Id);
}
}
}

View File

@ -0,0 +1,22 @@
using System.Linq;
namespace BirdsiteLive.Domain.Tools
{
public class SigValidationResultExtractor
{
public static string GetUserName(SignatureValidationResult result)
{
return result.User.preferredUsername.ToLowerInvariant().Trim();
}
public static string GetHost(SignatureValidationResult result)
{
return result.User.url.Replace("https://", string.Empty).Split('/').First();
}
public static string GetSharedInbox(SignatureValidationResult result)
{
return result.User?.endpoints?.sharedInbox;
}
}
}

View File

@ -34,6 +34,7 @@ namespace BirdsiteLive.Domain
public class UserService : IUserService
{
private readonly IProcessDeleteUser _processDeleteUser;
private readonly IProcessFollowUser _processFollowUser;
private readonly IProcessUndoFollowUser _processUndoFollowUser;
@ -48,7 +49,7 @@ namespace BirdsiteLive.Domain
private readonly IModerationRepository _moderationRepository;
#region Ctor
public UserService(InstanceSettings instanceSettings, ICryptoService cryptoService, IActivityPubService activityPubService, IProcessFollowUser processFollowUser, IProcessUndoFollowUser processUndoFollowUser, IStatusExtractor statusExtractor, IExtractionStatisticsHandler statisticsHandler, ITwitterUserService twitterUserService, IModerationRepository moderationRepository)
public UserService(InstanceSettings instanceSettings, ICryptoService cryptoService, IActivityPubService activityPubService, IProcessFollowUser processFollowUser, IProcessUndoFollowUser processUndoFollowUser, IStatusExtractor statusExtractor, IExtractionStatisticsHandler statisticsHandler, ITwitterUserService twitterUserService, IModerationRepository moderationRepository, IProcessDeleteUser processDeleteUser)
{
_instanceSettings = instanceSettings;
_cryptoService = cryptoService;
@ -59,6 +60,7 @@ namespace BirdsiteLive.Domain
_statisticsHandler = statisticsHandler;
_twitterUserService = twitterUserService;
_moderationRepository = moderationRepository;
_processDeleteUser = processDeleteUser;
}
#endregion
@ -128,10 +130,10 @@ namespace BirdsiteLive.Domain
if (!sigValidation.SignatureIsValidated) return false;
// Prepare data
var followerUserName = sigValidation.User.preferredUsername.ToLowerInvariant().Trim();
var followerHost = sigValidation.User.url.Replace("https://", string.Empty).Split('/').First();
var followerUserName = SigValidationResultExtractor.GetUserName(sigValidation);
var followerHost = SigValidationResultExtractor.GetHost(sigValidation);
var followerInbox = sigValidation.User.inbox;
var followerSharedInbox = sigValidation.User?.endpoints?.sharedInbox;
var followerSharedInbox = SigValidationResultExtractor.GetSharedInbox(sigValidation);
var twitterUser = activity.apObject.Split('/').Last().Replace("@", string.Empty).ToLowerInvariant().Trim();
// Make sure to only keep routes
@ -268,7 +270,10 @@ namespace BirdsiteLive.Domain
if (!sigValidation.SignatureIsValidated) return false;
// Remove user and followings
throw new NotImplementedException();
var followerUserName = SigValidationResultExtractor.GetUserName(sigValidation);
var followerHost = SigValidationResultExtractor.GetHost(sigValidation);
await _processDeleteUser.ExecuteAsync(followerUserName, followerHost);
return true;
}

View File

@ -1,12 +1,6 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using BirdsiteLive.ActivityPub;
using BirdsiteLive.ActivityPub.Converters;
using BirdsiteLive.Common.Settings;
using BirdsiteLive.DAL.Contracts;
using System.Threading.Tasks;
using BirdsiteLive.DAL.Models;
using BirdsiteLive.Domain;
using BirdsiteLive.Domain.BusinessUseCases;
namespace BirdsiteLive.Moderation.Actions
{
@ -17,16 +11,14 @@ namespace BirdsiteLive.Moderation.Actions
public class RemoveFollowerAction : IRemoveFollowerAction
{
private readonly IFollowersDal _followersDal;
private readonly ITwitterUserDal _twitterUserDal;
private readonly IRejectAllFollowingsAction _rejectAllFollowingsAction;
private readonly IProcessDeleteUser _processDeleteUser;
#region Ctor
public RemoveFollowerAction(IFollowersDal followersDal, ITwitterUserDal twitterUserDal, IRejectAllFollowingsAction rejectAllFollowingsAction)
public RemoveFollowerAction(IRejectAllFollowingsAction rejectAllFollowingsAction, IProcessDeleteUser processDeleteUser)
{
_followersDal = followersDal;
_twitterUserDal = twitterUserDal;
_rejectAllFollowingsAction = rejectAllFollowingsAction;
_processDeleteUser = processDeleteUser;
}
#endregion
@ -36,16 +28,7 @@ namespace BirdsiteLive.Moderation.Actions
await _rejectAllFollowingsAction.ProcessAsync(follower);
// Remove twitter users if no more followers
var followings = follower.Followings;
foreach (var following in followings)
{
var followers = await _followersDal.GetFollowersAsync(following);
if (followers.Length == 1 && followers.First().Id == follower.Id)
await _twitterUserDal.DeleteTwitterUserAsync(following);
}
// Remove follower from DB
await _followersDal.DeleteFollowerAsync(follower.Id);
await _processDeleteUser.ExecuteAsync(follower);
}
}
}

View File

@ -0,0 +1,97 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using BirdsiteLive.DAL.Contracts;
using BirdsiteLive.DAL.Models;
using BirdsiteLive.Domain.BusinessUseCases;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
namespace BirdsiteLive.Domain.Tests.BusinessUseCases
{
[TestClass]
public class ProcessDeleteUserTests
{
[TestMethod]
public async Task ExecuteAsync_NoMoreFollowings()
{
#region Stubs
var follower = new Follower
{
Id = 12,
Followings = new List<int> { 1 }
};
#endregion
#region Mocks
var followersDalMock = new Mock<IFollowersDal>(MockBehavior.Strict);
followersDalMock
.Setup(x => x.GetFollowersAsync(
It.Is<int>(y => y == 1)))
.ReturnsAsync(new[] { follower });
followersDalMock
.Setup(x => x.DeleteFollowerAsync(
It.Is<int>(y => y == 12)))
.Returns(Task.CompletedTask);
var twitterUserDalMock = new Mock<ITwitterUserDal>(MockBehavior.Strict);
twitterUserDalMock
.Setup(x => x.DeleteTwitterUserAsync(
It.Is<int>(y => y == 1)))
.Returns(Task.CompletedTask);
#endregion
var action = new ProcessDeleteUser(followersDalMock.Object, twitterUserDalMock.Object);
await action.ExecuteAsync(follower);
#region Validations
followersDalMock.VerifyAll();
twitterUserDalMock.VerifyAll();
#endregion
}
[TestMethod]
public async Task ExecuteAsync_HaveFollowings()
{
#region Stubs
var follower = new Follower
{
Id = 12,
Followings = new List<int> { 1 }
};
var followers = new List<Follower>
{
follower,
new Follower
{
Id = 11
}
};
#endregion
#region Mocks
var followersDalMock = new Mock<IFollowersDal>(MockBehavior.Strict);
followersDalMock
.Setup(x => x.GetFollowersAsync(
It.Is<int>(y => y == 1)))
.ReturnsAsync(followers.ToArray());
followersDalMock
.Setup(x => x.DeleteFollowerAsync(
It.Is<int>(y => y == 12)))
.Returns(Task.CompletedTask);
var twitterUserDalMock = new Mock<ITwitterUserDal>(MockBehavior.Strict);
#endregion
var action = new ProcessDeleteUser(followersDalMock.Object, twitterUserDalMock.Object);
await action.ExecuteAsync(follower);
#region Validations
followersDalMock.VerifyAll();
twitterUserDalMock.VerifyAll();
#endregion
}
}
}

View File

@ -2,6 +2,7 @@
using System.Threading.Tasks;
using BirdsiteLive.DAL.Contracts;
using BirdsiteLive.DAL.Models;
using BirdsiteLive.Domain.BusinessUseCases;
using BirdsiteLive.Moderation.Actions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
@ -29,31 +30,19 @@ namespace BirdsiteLive.Moderation.Tests.Actions
It.Is<Follower>(y => y.Id == follower.Id)))
.Returns(Task.CompletedTask);
var followersDalMock = new Mock<IFollowersDal>(MockBehavior.Strict);
followersDalMock
.Setup(x => x.GetFollowersAsync(
It.Is<int>(y => y == 1)))
.ReturnsAsync(new[] {follower});
followersDalMock
.Setup(x => x.DeleteFollowerAsync(
It.Is<int>(y => y == 12)))
.Returns(Task.CompletedTask);
var twitterUserDalMock = new Mock<ITwitterUserDal>(MockBehavior.Strict);
twitterUserDalMock
.Setup(x => x.DeleteTwitterUserAsync(
It.Is<int>(y => y == 1)))
var processDeleteUserMock = new Mock<IProcessDeleteUser>(MockBehavior.Strict);
processDeleteUserMock
.Setup(x => x.ExecuteAsync(
It.Is<Follower>(y => y.Id == follower.Id)))
.Returns(Task.CompletedTask);
#endregion
var action = new RemoveFollowerAction(followersDalMock.Object, twitterUserDalMock.Object, rejectAllFollowingsActionMock.Object);
var action = new RemoveFollowerAction(rejectAllFollowingsActionMock.Object, processDeleteUserMock.Object);
await action.ProcessAsync(follower);
#region Validations
followersDalMock.VerifyAll();
twitterUserDalMock.VerifyAll();
rejectAllFollowingsActionMock.VerifyAll();
processDeleteUserMock.VerifyAll();
#endregion
}
@ -66,15 +55,6 @@ namespace BirdsiteLive.Moderation.Tests.Actions
Id = 12,
Followings = new List<int> { 1 }
};
var followers = new List<Follower>
{
follower,
new Follower
{
Id = 11
}
};
#endregion
#region Mocks
@ -84,27 +64,19 @@ namespace BirdsiteLive.Moderation.Tests.Actions
It.Is<Follower>(y => y.Id == follower.Id)))
.Returns(Task.CompletedTask);
var followersDalMock = new Mock<IFollowersDal>(MockBehavior.Strict);
followersDalMock
.Setup(x => x.GetFollowersAsync(
It.Is<int>(y => y == 1)))
.ReturnsAsync(followers.ToArray());
followersDalMock
.Setup(x => x.DeleteFollowerAsync(
It.Is<int>(y => y == 12)))
var processDeleteUserMock = new Mock<IProcessDeleteUser>(MockBehavior.Strict);
processDeleteUserMock
.Setup(x => x.ExecuteAsync(
It.Is<Follower>(y => y.Id == follower.Id)))
.Returns(Task.CompletedTask);
var twitterUserDalMock = new Mock<ITwitterUserDal>(MockBehavior.Strict);
#endregion
var action = new RemoveFollowerAction(followersDalMock.Object, twitterUserDalMock.Object, rejectAllFollowingsActionMock.Object);
var action = new RemoveFollowerAction(rejectAllFollowingsActionMock.Object, processDeleteUserMock.Object);
await action.ProcessAsync(follower);
#region Validations
followersDalMock.VerifyAll();
twitterUserDalMock.VerifyAll();
rejectAllFollowingsActionMock.VerifyAll();
processDeleteUserMock.VerifyAll();
#endregion
}
}