Improve federation design in DM creation
This commit is contained in:
parent
0ac6ff9196
commit
8de0e0cacb
3 changed files with 174 additions and 94 deletions
6
LarpixServer/Federation/Receiver.cs
Normal file
6
LarpixServer/Federation/Receiver.cs
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
namespace LarpixServer.Federation;
|
||||||
|
|
||||||
|
public class Receiver
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
24
LarpixServer/Federation/Sender.cs
Normal file
24
LarpixServer/Federation/Sender.cs
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
namespace LarpixServer.Federation;
|
||||||
|
|
||||||
|
public class Sender
|
||||||
|
{
|
||||||
|
public static async Task<string> GetUserId(string username, string domain)
|
||||||
|
{
|
||||||
|
return "?";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task<bool> HasSentDmInvite(string senderId, string domain, string receiverId) //receiver is always from local domain
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task CreateDm(string id, string domain, string dmId)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task<string> DmInvite(string senderId, string domain, string receiverId) //sender is always from local domain
|
||||||
|
{
|
||||||
|
return "User invited";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -14,16 +14,21 @@ public class Requests
|
||||||
{
|
{
|
||||||
if (!Account.Utils.IsUserLocal(username2, out string domain)) //federation
|
if (!Account.Utils.IsUserLocal(username2, out string domain)) //federation
|
||||||
{
|
{
|
||||||
return "";
|
username2 = username2.Split(":")[0];
|
||||||
|
string remoteId2 = await Federation.Sender.GetUserId(username2, domain);
|
||||||
|
await Fs.WriteFile(ACCOUNTS_DATA_DIR + $"/{id}/dminvites/sent/{remoteId2};{domain}", []);
|
||||||
|
return await Federation.Sender.DmInvite(id, domain, remoteId2);
|
||||||
}
|
}
|
||||||
username2 = username2.Split(":")[0];
|
username2 = username2.Split(":")[0];
|
||||||
string id2 = await Account.Utils.IdFromName(username2);
|
string id2 = await Account.Utils.IdFromName(username2);
|
||||||
|
|
||||||
SemaphoreSlim userLock = Account.Utils.GetUserLock(id2);
|
SemaphoreSlim userLock2 = Account.Utils.GetUserLock(id2);
|
||||||
|
await userLock2.WaitAsync();
|
||||||
|
SemaphoreSlim userLock = Account.Utils.GetUserLock(id);
|
||||||
await userLock.WaitAsync();
|
await userLock.WaitAsync();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
string inviteSentFile = ACCOUNTS_DATA_DIR + $"/{id}/dminvites/sent/{id2};{domain}";
|
||||||
string inviteFile = ACCOUNTS_DATA_DIR + $"/{id2}/dminvites/recv/{id};{DOMAIN}";
|
string inviteFile = ACCOUNTS_DATA_DIR + $"/{id2}/dminvites/recv/{id};{DOMAIN}";
|
||||||
if (Fs.Exists(inviteFile))
|
if (Fs.Exists(inviteFile))
|
||||||
{
|
{
|
||||||
|
|
@ -31,6 +36,7 @@ public class Requests
|
||||||
switch (inviteState)
|
switch (inviteState)
|
||||||
{
|
{
|
||||||
case "0": //invited
|
case "0": //invited
|
||||||
|
await Fs.WriteFile(inviteSentFile, []); //just in case
|
||||||
return "User already invited";
|
return "User already invited";
|
||||||
case "1": //accepted
|
case "1": //accepted
|
||||||
return "You already have a DM with this user";
|
return "You already have a DM with this user";
|
||||||
|
|
@ -39,10 +45,11 @@ public class Requests
|
||||||
}
|
}
|
||||||
|
|
||||||
await Fs.WriteFile(inviteFile, Encoding.UTF8.GetBytes("0"));
|
await Fs.WriteFile(inviteFile, Encoding.UTF8.GetBytes("0"));
|
||||||
await Fs.WriteFile(ACCOUNTS_DATA_DIR + $"/{id}/dminvites/sent/{id2};{domain}", []); //we should also save that this user invited someone, because this will act as dm accept verification while federating
|
await Fs.WriteFile(inviteSentFile, []); //we should also save that this user invited someone, because this will act as dm accept verification while federating
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
userLock2.Release();
|
||||||
userLock.Release();
|
userLock.Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -67,9 +74,26 @@ public class Requests
|
||||||
{
|
{
|
||||||
id2 = await Account.Utils.IdFromName(username2);
|
id2 = await Account.Utils.IdFromName(username2);
|
||||||
}
|
}
|
||||||
else //id z federacji
|
else //get id from federation
|
||||||
{
|
{
|
||||||
id2 = "?";
|
id2 = await Federation.Sender.GetUserId(username2, domain);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isUserLocal)
|
||||||
|
{
|
||||||
|
string inviteSentFile = ACCOUNTS_DATA_DIR + $"/{id2}/dminvites/sent/{id};{DOMAIN}";
|
||||||
|
if (!Fs.Exists(inviteSentFile))
|
||||||
|
{
|
||||||
|
return "You can't create a DM without an invitation";
|
||||||
|
}
|
||||||
|
Fs.DeleteFile(inviteSentFile);
|
||||||
|
}
|
||||||
|
else //also check this on federated server
|
||||||
|
{
|
||||||
|
if (!await Federation.Sender.HasSentDmInvite(id2, domain, id))
|
||||||
|
{
|
||||||
|
return "You can't create a DM without an invitation";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
string inviteFile = ACCOUNTS_DATA_DIR + $"/{id}/dminvites/recv/{id2};{domain}";
|
string inviteFile = ACCOUNTS_DATA_DIR + $"/{id}/dminvites/recv/{id2};{domain}";
|
||||||
|
|
@ -79,36 +103,40 @@ public class Requests
|
||||||
switch (inviteState)
|
switch (inviteState)
|
||||||
{
|
{
|
||||||
case "0": //invited
|
case "0": //invited
|
||||||
|
|
||||||
|
List<(string file, string todo, string content)> restoreList = new();
|
||||||
|
try //try because federation is involved, if it fails we should just clean all written files
|
||||||
|
{
|
||||||
|
restoreList.Add((inviteFile, "delete", ""));
|
||||||
await Fs.WriteFile(inviteFile, Encoding.UTF8.GetBytes("1")); //we are setting this to 1,
|
await Fs.WriteFile(inviteFile, Encoding.UTF8.GetBytes("1")); //we are setting this to 1,
|
||||||
//so now we should have an option to delete id from dmslist and still search it
|
//so now we should have an option to delete id from dmslist and still search it
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
BigInteger dmId =
|
BigInteger dmId =
|
||||||
BigInteger.Parse(Encoding.UTF8.GetString(await Fs.ReadFile($"{ROOMS_DIR}/lastdm")));
|
BigInteger.Parse(Encoding.UTF8.GetString(await Fs.ReadFile($"{ROOMS_DIR}/lastdm")));
|
||||||
dmId++;
|
dmId++;
|
||||||
var freeid =
|
var freeid =
|
||||||
Path.GetFileName(Directory.EnumerateFiles(ROOMS_DIR + "/freedms").FirstOrDefault());
|
Path.GetFileName(Directory.EnumerateFiles(ROOMS_DIR + "/freedms").FirstOrDefault());
|
||||||
if (!isUserLocal) //federacja
|
|
||||||
{
|
|
||||||
//jezeli freeid tez jest wolne na innym serwerze (tez jako freeid) to wszystko zostawiamy tak jak jest
|
|
||||||
//w przeciwnym razie porownojemy lastid z 2 serwerow i bierzemy to większe + 1 jako docelowe id dma
|
|
||||||
|
|
||||||
//no ale moze to byc problematyczne
|
|
||||||
}
|
|
||||||
|
|
||||||
if (freeid != null)
|
if (freeid != null)
|
||||||
{
|
{
|
||||||
dmId = BigInteger.Parse(freeid);
|
dmId = BigInteger.Parse(freeid);
|
||||||
Fs.DeleteFile($"{ROOMS_DIR}/freedms/{freeid}");
|
Fs.DeleteFile($"{ROOMS_DIR}/freedms/{freeid}");
|
||||||
|
restoreList.Add(($"{ROOMS_DIR}/freedms/{freeid}", "write", ""));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
restoreList.Add(($"{ROOMS_DIR}/lastdm", "write", Encoding.UTF8.GetString(await Fs.ReadFile($"{ROOMS_DIR}/lastdm"))));
|
||||||
await Fs.WriteFile($"{ROOMS_DIR}/lastdm", Encoding.UTF8.GetBytes(dmId.ToString()));
|
await Fs.WriteFile($"{ROOMS_DIR}/lastdm", Encoding.UTF8.GetBytes(dmId.ToString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
await Fs.WriteFile($"{ROOMS_DIR}/dms/{dmId}/members",
|
await Fs.WriteFile($"{ROOMS_DIR}/dms/{DOMAIN}/{dmId}/members",
|
||||||
Encoding.UTF8.GetBytes($"{id}:{DOMAIN};{id2}:{domain}"));
|
Encoding.UTF8.GetBytes($"{id}:{DOMAIN};{id2}:{domain}"));
|
||||||
await Fs.WriteFile($"{ROOMS_DIR}/dms/{dmId}/messages/last", Encoding.UTF8.GetBytes($"0"));
|
await Fs.WriteFile($"{ROOMS_DIR}/dms/{DOMAIN}/{dmId}/messages/last", Encoding.UTF8.GetBytes($"0"));
|
||||||
|
|
||||||
|
|
||||||
Message startingMessage = new();
|
Message startingMessage = new();
|
||||||
startingMessage.attachment = "";
|
startingMessage.attachment = "";
|
||||||
|
|
@ -120,7 +148,7 @@ public class Requests
|
||||||
startingMessage.key = ""; //no key == NOT encrypted
|
startingMessage.key = ""; //no key == NOT encrypted
|
||||||
startingMessage.pervious = "";
|
startingMessage.pervious = "";
|
||||||
|
|
||||||
await Fs.WriteFile($"{ROOMS_DIR}/dms/{dmId}/keys/0/{id};{DOMAIN}", //klucz dla uzytkownika tworzącego jest juz gotowy i ma zwykly zapis
|
await Fs.WriteFile($"{ROOMS_DIR}/dms/{DOMAIN}/{dmId}/keys/0/{id};{DOMAIN}", //klucz dla uzytkownika tworzącego jest juz gotowy i ma zwykly zapis
|
||||||
Encoding.UTF8.GetBytes(serializedBody.string2));
|
Encoding.UTF8.GetBytes(serializedBody.string2));
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -128,15 +156,16 @@ public class Requests
|
||||||
await Account.Utils.GetUserKeys(id),
|
await Account.Utils.GetUserKeys(id),
|
||||||
AppJsonSerializerContext.Default.Universal2String
|
AppJsonSerializerContext.Default.Universal2String
|
||||||
);
|
);
|
||||||
await Fs.WriteFile($"{ROOMS_DIR}/dms/{dmId}/keys/0/{id2};{domain}",
|
await Fs.WriteFile($"{ROOMS_DIR}/dms/{DOMAIN}/{dmId}/keys/0/{id2};{domain}",
|
||||||
Encoding.UTF8.GetBytes($"SETUP:{keys.string2};{serializedBody.string3}")); //jezeli mamy setup to [1] to jest publiczny klucz drugiej osoby,
|
Encoding.UTF8.GetBytes($"SETUP:{keys.string2};{serializedBody.string3}")); //jezeli mamy setup to [1] to jest publiczny klucz drugiej osoby,
|
||||||
//a string 3 to zaszyfrowany klucz pokoju ktory musi odszyfrowac za pomoca swoich kluczy i tego publicznego
|
//a string 3 to zaszyfrowany klucz pokoju ktory musi odszyfrowac za pomoca swoich kluczy i tego publicznego
|
||||||
|
|
||||||
|
await Fs.WriteFile($"{ROOMS_DIR}/dms/{DOMAIN}/{dmId}/messages/0", Encoding.UTF8.GetBytes(
|
||||||
await Fs.WriteFile($"{ROOMS_DIR}/dms/{dmId}/messages/0", Encoding.UTF8.GetBytes(
|
|
||||||
JsonSerializer.Serialize(startingMessage, AppJsonSerializerContext.Default.Message)
|
JsonSerializer.Serialize(startingMessage, AppJsonSerializerContext.Default.Message)
|
||||||
));
|
));
|
||||||
|
|
||||||
|
restoreList.Add(($"{ROOMS_DIR}/dms/{DOMAIN}/{dmId}", "deletef", ""));
|
||||||
|
|
||||||
string dmspath = $"{ACCOUNTS_DATA_DIR}/{id}/dms";
|
string dmspath = $"{ACCOUNTS_DATA_DIR}/{id}/dms";
|
||||||
string dms;
|
string dms;
|
||||||
if (!Fs.Exists(dmspath))
|
if (!Fs.Exists(dmspath))
|
||||||
|
|
@ -147,7 +176,7 @@ public class Requests
|
||||||
{
|
{
|
||||||
dms = Encoding.UTF8.GetString(await Fs.ReadFile(dmspath));
|
dms = Encoding.UTF8.GetString(await Fs.ReadFile(dmspath));
|
||||||
}
|
}
|
||||||
|
restoreList.Add((dmspath, "write", dms));
|
||||||
await Fs.WriteFile(dmspath, Encoding.UTF8.GetBytes($"{dmId};{dms}"));
|
await Fs.WriteFile(dmspath, Encoding.UTF8.GetBytes($"{dmId};{dms}"));
|
||||||
|
|
||||||
if (isUserLocal)
|
if (isUserLocal)
|
||||||
|
|
@ -180,8 +209,29 @@ public class Requests
|
||||||
}
|
}
|
||||||
else //federacja
|
else //federacja
|
||||||
{
|
{
|
||||||
|
await Federation.Sender.CreateDm(id2, domain, dmId.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
foreach (var entry in restoreList)
|
||||||
|
{
|
||||||
|
if (entry.todo == "delete")
|
||||||
|
{
|
||||||
|
Fs.DeleteFile(entry.file);
|
||||||
|
}
|
||||||
|
if (entry.todo == "deletef")
|
||||||
|
{
|
||||||
|
Fs.DeleteDirectory(entry.file);
|
||||||
|
}
|
||||||
|
if (entry.todo == "write")
|
||||||
|
{
|
||||||
|
await Fs.WriteFile(entry.file, Encoding.UTF8.GetBytes(entry.content));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "Failed to accept DM. Ask for another invite";
|
||||||
|
}
|
||||||
|
|
||||||
return "DM accepted";
|
return "DM accepted";
|
||||||
case "1": //accepted
|
case "1": //accepted
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue