added Delete logic
This commit is contained in:
parent
93b43ee4a0
commit
7205a09eaa
6 changed files with 199 additions and 69 deletions
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
Reference in a new issue