validating tweet
This commit is contained in:
parent
cc9985eb1d
commit
ec3234324c
3 changed files with 147 additions and 27 deletions
77
src/BirdsiteLive.Domain/MigrationService.cs
Normal file
77
src/BirdsiteLive.Domain/MigrationService.cs
Normal file
|
@ -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<bool> 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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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<IActionResult> 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<IActionResult> 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; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,9 +4,16 @@
|
|||
}
|
||||
|
||||
<div class="col-12 col-sm-10 col-md-8 col-lg-6 mx-auto">
|
||||
@if (!string.IsNullOrWhiteSpace(ViewData.Model.ErrorMessage))
|
||||
{
|
||||
<div class="alert alert-danger" role="alert">
|
||||
@ViewData.Model.ErrorMessage
|
||||
</div>
|
||||
}
|
||||
|
||||
<h1 class="display-4 migration__title">Migrate @@@ViewData.Model.Acct</h1>
|
||||
|
||||
@if (!ViewData.Model.IsAcctProvided && !ViewData.Model.IsAcctProvided)
|
||||
|
||||
@if (!ViewData.Model.IsAcctProvided && !ViewData.Model.IsTweetProvided)
|
||||
{
|
||||
<h2 class="display-4 migration__subtitle">What is needed?</h2>
|
||||
|
||||
|
@ -19,12 +26,12 @@
|
|||
}
|
||||
|
||||
<h2 class="display-4 migration__subtitle">Start the migration!</h2>
|
||||
|
||||
|
||||
<p>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):</p>
|
||||
|
||||
<input type="text" name="textbox" value="@ViewData.Model.MigrationCode" onclick="this.select()" class="form-control" readonly />
|
||||
|
||||
<input type="text" name="textbox" value="@ViewData.Model.MigrationCode" onclick="this.select()" class="form-control" readonly/>
|
||||
<br/>
|
||||
|
||||
|
||||
<h2 class="display-4 migration__subtitle">Provide migration information:</h2>
|
||||
<form method="POST">
|
||||
@*<div class="form-group">
|
||||
|
|
Reference in a new issue