diff --git a/src/BirdsiteLive.Domain/MigrationService.cs b/src/BirdsiteLive.Domain/MigrationService.cs new file mode 100644 index 0000000..2e4a1d5 --- /dev/null +++ b/src/BirdsiteLive.Domain/MigrationService.cs @@ -0,0 +1,77 @@ +using System; +using System.Linq; +using BirdsiteLive.Twitter; +using System.Security.Cryptography; +using System.Text; +using System.Threading.Tasks; + +namespace BirdsiteLive.Domain +{ + public class MigrationService + { + private readonly ITwitterTweetsService _twitterTweetsService; + + #region Ctor + public MigrationService(ITwitterTweetsService twitterTweetsService) + { + _twitterTweetsService = twitterTweetsService; + } + #endregion + + public string GetMigrationCode(string acct) + { + var hash = GetHashString(acct); + return $"[[BirdsiteLIVE-MigrationCode|{hash.Substring(0, 10)}]]"; + } + + public bool ValidateTweet(string acct, string tweetId) + { + var code = GetMigrationCode(acct); + + var castedTweetId = ExtractedTweetId(tweetId); + var tweet = _twitterTweetsService.GetTweet(castedTweetId); + + if (tweet == null) throw new Exception("Tweet not found"); + if (!tweet.MessageContent.Contains(code)) throw new Exception("Tweet don't have migration code"); + + return true; + } + + private long ExtractedTweetId(string tweetId) + { + long castedId; + if (long.TryParse(tweetId, out castedId)) + return castedId; + + var urlPart = tweetId.Split('/').LastOrDefault(); + if (long.TryParse(urlPart, out castedId)) + return castedId; + + throw new ArgumentException("Unvalid Tweet ID"); + } + + public async Task ValidateFediverseAcctAsync(string fediverseAcct) + { + return true; + } + + public async Task MigrateAccountAsync(string acct, string tweetId, string fediverseAcct, bool triggerRemoteMigration) + { + } + + private byte[] GetHash(string inputString) + { + using (HashAlgorithm algorithm = SHA256.Create()) + return algorithm.ComputeHash(Encoding.UTF8.GetBytes(inputString)); + } + + private string GetHashString(string inputString) + { + StringBuilder sb = new StringBuilder(); + foreach (byte b in GetHash(inputString)) + sb.Append(b.ToString("X2")); + + return sb.ToString(); + } + } +} \ No newline at end of file diff --git a/src/BirdsiteLive/Controllers/MigrationController.cs b/src/BirdsiteLive/Controllers/MigrationController.cs index a0b84aa..d0e121f 100644 --- a/src/BirdsiteLive/Controllers/MigrationController.cs +++ b/src/BirdsiteLive/Controllers/MigrationController.cs @@ -1,17 +1,29 @@ -using Microsoft.AspNetCore.Mvc; +using System; +using Microsoft.AspNetCore.Mvc; using System.Security.Cryptography; using System.Text; +using System.Threading.Tasks; using Npgsql.TypeHandlers; +using BirdsiteLive.Domain; namespace BirdsiteLive.Controllers { public class MigrationController : Controller { + private readonly MigrationService _migrationService; + + #region Ctor + public MigrationController(MigrationService migrationService) + { + _migrationService = migrationService; + } + #endregion + [HttpGet] [Route("/migration/{id}")] public IActionResult Index(string id) { - var migrationCode = GetMigrationCode(id); + var migrationCode = _migrationService.GetMigrationCode(id); var data = new MigrationData() { Acct = id, @@ -23,9 +35,10 @@ namespace BirdsiteLive.Controllers [HttpPost] [Route("/migration/{id}")] - public IActionResult Migrate(string id, string tweetid, string handle) + public async Task Migrate(string id, string tweetid, string handle) { - var migrationCode = GetMigrationCode(id); + var migrationCode = _migrationService.GetMigrationCode(id); + var data = new MigrationData() { Acct = id, @@ -38,28 +51,51 @@ namespace BirdsiteLive.Controllers FediverseAccount = handle }; + try + { + var isAcctValid = await _migrationService.ValidateFediverseAcctAsync(handle); + var isTweetValid = _migrationService.ValidateTweet(id, tweetid); + + data.IsAcctValid = isAcctValid; + data.IsTweetValid = isTweetValid; + } + catch (Exception e) + { + data.ErrorMessage = e.Message; + } + + + if (data.IsAcctValid && data.IsTweetValid) + { + try + { + await _migrationService.MigrateAccountAsync(id, tweetid, handle, true); + data.MigrationSuccess = true; + } + catch (Exception e) + { + Console.WriteLine(e); + data.ErrorMessage = e.Message; + } + } + return View("Index", data); } - public byte[] GetHash(string inputString) + [HttpPost] + [Route("/migration/{id}/{tweetid}/{handle}")] + public async Task RemoteMigrate(string id, string tweetid, string handle) { - using (HashAlgorithm algorithm = SHA256.Create()) - return algorithm.ComputeHash(Encoding.UTF8.GetBytes(inputString)); - } + var isAcctValid = await _migrationService.ValidateFediverseAcctAsync(handle); + var isTweetValid = _migrationService.ValidateTweet(id, tweetid); - public string GetHashString(string inputString) - { - StringBuilder sb = new StringBuilder(); - foreach (byte b in GetHash(inputString)) - sb.Append(b.ToString("X2")); + if (isAcctValid && isTweetValid) + { + await _migrationService.MigrateAccountAsync(id, tweetid, handle, false); + return Ok(); + } - return sb.ToString(); - } - - public string GetMigrationCode(string acct) - { - var hash = GetHashString(acct); - return $"[[BirdsiteLIVE-MigrationCode|{hash.Substring(0, 10)}]]"; + return StatusCode(500); } } @@ -81,6 +117,6 @@ namespace BirdsiteLive.Controllers public bool IsAcctValid { get; set; } public string ErrorMessage { get; set; } - + public bool MigrationSuccess { get; set; } } } diff --git a/src/BirdsiteLive/Views/Migration/Index.cshtml b/src/BirdsiteLive/Views/Migration/Index.cshtml index dfdf14d..422b8f7 100644 --- a/src/BirdsiteLive/Views/Migration/Index.cshtml +++ b/src/BirdsiteLive/Views/Migration/Index.cshtml @@ -4,9 +4,16 @@ }
+ @if (!string.IsNullOrWhiteSpace(ViewData.Model.ErrorMessage)) + { + + } +

Migrate @@@ViewData.Model.Acct

- - @if (!ViewData.Model.IsAcctProvided && !ViewData.Model.IsAcctProvided) + + @if (!ViewData.Model.IsAcctProvided && !ViewData.Model.IsTweetProvided) {

What is needed?

@@ -19,12 +26,12 @@ }

Start the migration!

- +

Please copy and post this string in a Tweet (the string must be untampered, but you can write anything you want before or after it):

- - + +
- +

Provide migration information:

@*