Fix user locks & change return strings to blah.blah.blah
This commit is contained in:
parent
9abd013e91
commit
7da97dbeb6
6 changed files with 56 additions and 49 deletions
|
|
@ -118,7 +118,7 @@ public class Requests
|
||||||
);
|
);
|
||||||
if (!createHolder.TryGetValue(serializedBody.idKey, out CreateHolder entry))
|
if (!createHolder.TryGetValue(serializedBody.idKey, out CreateHolder entry))
|
||||||
{
|
{
|
||||||
await context.Response.WriteAsync("Account request expired");
|
await context.Response.WriteAsync("error:account.creation.request.expired");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -133,13 +133,13 @@ public class Requests
|
||||||
|
|
||||||
if (!Utils.IsValidUsername(entry.name, out string message))
|
if (!Utils.IsValidUsername(entry.name, out string message))
|
||||||
{
|
{
|
||||||
await context.Response.WriteAsync("Username: " + message);
|
await context.Response.WriteAsync($"error:invalid.username.{{{message}}}");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Utils.IsValidPassword(entry.pass, out message))
|
if (!Utils.IsValidPassword(entry.pass, out message))
|
||||||
{
|
{
|
||||||
await context.Response.WriteAsync("Password: " + message);
|
await context.Response.WriteAsync($"error:invalid.password.{{{message}}}");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -162,14 +162,14 @@ public class Requests
|
||||||
);
|
);
|
||||||
if (!createHolder.TryGetValue(serialized.idKey, out var entry))
|
if (!createHolder.TryGetValue(serialized.idKey, out var entry))
|
||||||
{
|
{
|
||||||
await context.Response.WriteAsync("Account request expired");
|
await context.Response.WriteAsync("error:account.creation.request.expired");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entry.captcha.ToLower() != serialized.captcha.ToLower())
|
if (entry.captcha.ToLower() != serialized.captcha.ToLower())
|
||||||
{
|
{
|
||||||
createHolder.TryRemove(serialized.idKey, out _);
|
createHolder.TryRemove(serialized.idKey, out _);
|
||||||
await context.Response.WriteAsync("Incorrect captcha. Please try again");
|
await context.Response.WriteAsync("error:incorrect.captcha");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -177,7 +177,7 @@ public class Requests
|
||||||
|
|
||||||
if (Fs.Exists($"{ACCOUNTS_NAME_DIR}/{lowerName}"))
|
if (Fs.Exists($"{ACCOUNTS_NAME_DIR}/{lowerName}"))
|
||||||
{
|
{
|
||||||
await context.Response.WriteAsync("This username is already taken");
|
await context.Response.WriteAsync("error:username.taken");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -185,7 +185,7 @@ public class Requests
|
||||||
Encoding.UTF8.GetString(await Fs.ReadFile($"{ACCOUNTS_DIR}/registration"));
|
Encoding.UTF8.GetString(await Fs.ReadFile($"{ACCOUNTS_DIR}/registration"));
|
||||||
if (registrationString.StartsWith("0;"))
|
if (registrationString.StartsWith("0;"))
|
||||||
{
|
{
|
||||||
await context.Response.WriteAsync("Account creation is currently disabled. Try again later");
|
await context.Response.WriteAsync("error:registration.disabled");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -217,7 +217,7 @@ public class Requests
|
||||||
if (!valid)
|
if (!valid)
|
||||||
{
|
{
|
||||||
await context.Response.WriteAsync(
|
await context.Response.WriteAsync(
|
||||||
"Account creation is currently disabled. Try again later");
|
"error:registration.disabled");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -240,7 +240,7 @@ public class Requests
|
||||||
if (id == ulong.MaxValue)
|
if (id == ulong.MaxValue)
|
||||||
{
|
{
|
||||||
await context.Response.WriteAsync(
|
await context.Response.WriteAsync(
|
||||||
"Server is full, cannot create new accounts. Try again later.");
|
"error:accounts.slots.full");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -264,7 +264,7 @@ public class Requests
|
||||||
userLock.Release();
|
userLock.Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
await context.Response.WriteAsync("Account created");
|
await context.Response.WriteAsync("success:account.created");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -389,7 +389,7 @@ public class Requests
|
||||||
userLock.Release();
|
userLock.Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
await context.Response.WriteAsync("Password changed successfully");
|
await context.Response.WriteAsync("success:password.changed");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -444,7 +444,7 @@ public class Requests
|
||||||
//string publicKey = serializedBody.string1;
|
//string publicKey = serializedBody.string1;
|
||||||
//string privateEncryptedKey = serializedBody.string2;
|
//string privateEncryptedKey = serializedBody.string2;
|
||||||
await Utils.UpdateUserKeys(id, body);
|
await Utils.UpdateUserKeys(id, body);
|
||||||
return "Keys updated successfully";
|
return "success:keys.updated";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task GetUserPublicKey(HttpContext context, Func<Task> next, IQueryCollection query, StreamReader bodyReader)
|
public static async Task GetUserPublicKey(HttpContext context, Func<Task> next, IQueryCollection query, StreamReader bodyReader)
|
||||||
|
|
@ -565,6 +565,11 @@ public class Requests
|
||||||
await Room.Requests.DmCreate(id, serializedBody.string2)
|
await Room.Requests.DmCreate(id, serializedBody.string2)
|
||||||
, password));
|
, password));
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
await context.Response.WriteAsync(Encryption.Encryption.EncryptString(
|
||||||
|
$"error:unknown.request.{{{serializedBody.string1}}}"
|
||||||
|
, password));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ public class Utils
|
||||||
{
|
{
|
||||||
private static readonly Regex USERNAME_REGEX = new Regex(@"^[a-zA-Z0-9_]+$");
|
private static readonly Regex USERNAME_REGEX = new Regex(@"^[a-zA-Z0-9_]+$");
|
||||||
|
|
||||||
public static string LOGIN_SUCCESS = "Login successful";
|
public static string LOGIN_SUCCESS = "success:login.successful";
|
||||||
|
|
||||||
public static ConcurrentDictionary<string, SemaphoreSlim> userLocks = new();
|
public static ConcurrentDictionary<string, SemaphoreSlim> userLocks = new();
|
||||||
public static ConcurrentQueue<string> keyQueue = new();
|
public static ConcurrentQueue<string> keyQueue = new();
|
||||||
|
|
@ -58,16 +58,16 @@ public class Utils
|
||||||
|
|
||||||
public static bool IsValidUsername(string username, out string message)
|
public static bool IsValidUsername(string username, out string message)
|
||||||
{
|
{
|
||||||
message = "Username must be 3-18 characters long";
|
message = "error:username.length.{3-18}";
|
||||||
if (string.IsNullOrWhiteSpace(username)) return false;
|
if (string.IsNullOrWhiteSpace(username)) return false;
|
||||||
if (username.Length is < 3 or > 18) return false;
|
if (username.Length is < 3 or > 18) return false;
|
||||||
message = "Only letters, numbers, and underscores allowed";
|
message = "error:username.conditions.allowed.{letters,numbers,underscores}";
|
||||||
return USERNAME_REGEX.IsMatch(username);
|
return USERNAME_REGEX.IsMatch(username);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool IsValidPassword(string password, out string message)
|
public static bool IsValidPassword(string password, out string message)
|
||||||
{
|
{
|
||||||
message = "Password is not hashed properly";
|
message = "error:password.not.hashed.properly";
|
||||||
if (password.Length != 128)
|
if (password.Length != 128)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -126,11 +126,11 @@ public class Utils
|
||||||
{
|
{
|
||||||
if (!Fs.Exists($"{ACCOUNTS_DATA_DIR}/{id}"))
|
if (!Fs.Exists($"{ACCOUNTS_DATA_DIR}/{id}"))
|
||||||
{
|
{
|
||||||
return "Invalid username or password";
|
return "error:invalid.username.or.password";
|
||||||
}
|
}
|
||||||
if (password != password2)
|
if (password != password2)
|
||||||
{
|
{
|
||||||
return "Invalid password";
|
return "error:invalid.password";
|
||||||
}
|
}
|
||||||
|
|
||||||
await UpdateLastLogin(id);
|
await UpdateLastLogin(id);
|
||||||
|
|
@ -141,7 +141,7 @@ public class Utils
|
||||||
{
|
{
|
||||||
if (!Requests.nonceHolder.TryGetValue(username, out (string, DateTimeOffset) nonce))
|
if (!Requests.nonceHolder.TryGetValue(username, out (string, DateTimeOffset) nonce))
|
||||||
{
|
{
|
||||||
return "Invalid nonce";
|
return "error:invalid.nonce";
|
||||||
}
|
}
|
||||||
string decBody = Encryption.Encryption.PacketDecPass(body, password, nonce.Item1);
|
string decBody = Encryption.Encryption.PacketDecPass(body, password, nonce.Item1);
|
||||||
if (delEntry)
|
if (delEntry)
|
||||||
|
|
@ -275,7 +275,7 @@ public class Utils
|
||||||
{
|
{
|
||||||
if (!Fs.Exists($"{ACCOUNTS_DATA_DIR}/{id}/secret"))
|
if (!Fs.Exists($"{ACCOUNTS_DATA_DIR}/{id}/secret"))
|
||||||
{
|
{
|
||||||
return "Account does not exist";
|
return "error:account.not.exist";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsValidUsername(newName, out string message))
|
if (!IsValidUsername(newName, out string message))
|
||||||
|
|
@ -290,13 +290,13 @@ public class Utils
|
||||||
{
|
{
|
||||||
if (Fs.Exists($"{ACCOUNTS_NAME_DIR}/{lowerNewName}"))
|
if (Fs.Exists($"{ACCOUNTS_NAME_DIR}/{lowerNewName}"))
|
||||||
{
|
{
|
||||||
return "This username is already taken";
|
return "error:username.taken";
|
||||||
}
|
}
|
||||||
|
|
||||||
Fs.MoveFile($"{ACCOUNTS_NAME_DIR}/{lowerOldName}", $"{ACCOUNTS_NAME_DIR}/{lowerNewName}");
|
Fs.MoveFile($"{ACCOUNTS_NAME_DIR}/{lowerOldName}", $"{ACCOUNTS_NAME_DIR}/{lowerNewName}");
|
||||||
}
|
}
|
||||||
await Fs.WriteFile($"{ACCOUNTS_DATA_DIR}/{id}/username", Encoding.UTF8.GetBytes(newName));
|
await Fs.WriteFile($"{ACCOUNTS_DATA_DIR}/{id}/username", Encoding.UTF8.GetBytes(newName));
|
||||||
|
|
||||||
return "Username changed successfully";
|
return "success:username.changed";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -32,7 +32,7 @@ public class Receiver
|
||||||
|
|
||||||
if (!await Sender.HasSentDmInvite(ids[1], domain, ids[0]))
|
if (!await Sender.HasSentDmInvite(ids[1], domain, ids[0]))
|
||||||
{
|
{
|
||||||
await context.Response.WriteAsync( "Bad request" );
|
await context.Response.WriteAsync( "error:bad.request" );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -43,7 +43,7 @@ public class Receiver
|
||||||
string inviteFile = ACCOUNTS_DATA_DIR + $"/{ids[0]}/dminvites/recv/{ids[1]};{domain}";
|
string inviteFile = ACCOUNTS_DATA_DIR + $"/{ids[0]}/dminvites/recv/{ids[1]};{domain}";
|
||||||
if (Fs.Exists(inviteFile))
|
if (Fs.Exists(inviteFile))
|
||||||
{
|
{
|
||||||
await context.Response.WriteAsync("User already invited");
|
await context.Response.WriteAsync("info:user.already.invited");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await Fs.WriteFile(inviteFile, Encoding.UTF8.GetBytes("0"));
|
await Fs.WriteFile(inviteFile, Encoding.UTF8.GetBytes("0"));
|
||||||
|
|
@ -54,7 +54,7 @@ public class Receiver
|
||||||
userLock.Release();
|
userLock.Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
await context.Response.WriteAsync("User invited");
|
await context.Response.WriteAsync("success:user.invited");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
case "dm/invite/hassent":
|
case "dm/invite/hassent":
|
||||||
|
|
@ -77,7 +77,7 @@ public class Receiver
|
||||||
inviteSentFile = ACCOUNTS_DATA_DIR + $"/{ids[0]}/dminvites/sent/{ids[1]};{domain}";
|
inviteSentFile = ACCOUNTS_DATA_DIR + $"/{ids[0]}/dminvites/sent/{ids[1]};{domain}";
|
||||||
if (!Fs.Exists(inviteSentFile))
|
if (!Fs.Exists(inviteSentFile))
|
||||||
{
|
{
|
||||||
await context.Response.WriteAsync( "Failed to add. No invite found" );
|
await context.Response.WriteAsync( "error:no.invite.found" );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Fs.DeleteFile(inviteSentFile);
|
Fs.DeleteFile(inviteSentFile);
|
||||||
|
|
@ -99,7 +99,7 @@ public class Receiver
|
||||||
DateTimeOffset.UtcNow.ToUnixTimeMilliseconds().ToString());
|
DateTimeOffset.UtcNow.ToUnixTimeMilliseconds().ToString());
|
||||||
|
|
||||||
|
|
||||||
await context.Response.WriteAsync("DM accepted");
|
await context.Response.WriteAsync("success:dm.accepted");
|
||||||
return;
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -184,6 +184,7 @@ public class Program
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
await context.Response.WriteAsync($"error:unknown.error");
|
||||||
Console.WriteLine(ex);
|
Console.WriteLine(ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,23 +14,24 @@ public class Requests
|
||||||
{
|
{
|
||||||
if (!Account.Utils.IsUserLocal(username2, out string domain)) //federation
|
if (!Account.Utils.IsUserLocal(username2, out string domain)) //federation
|
||||||
{
|
{
|
||||||
SemaphoreSlim userLock = Account.Utils.GetUserLock(id);
|
|
||||||
await userLock.WaitAsync();
|
username2 = username2.Split(":")[0];
|
||||||
try
|
string remoteId2 = await Federation.Sender.GetUserId(username2, domain);
|
||||||
{
|
await Fs.WriteFile(ACCOUNTS_DATA_DIR + $"/{id}/dminvites/sent/{remoteId2};{domain}", []); //only save sent while federating
|
||||||
username2 = username2.Split(":")[0];
|
return await Federation.Sender.DmInvite(id, domain, remoteId2);
|
||||||
string remoteId2 = await Federation.Sender.GetUserId(username2, domain);
|
|
||||||
await Fs.WriteFile(ACCOUNTS_DATA_DIR + $"/{id}/dminvites/sent/{remoteId2};{domain}", []); //only save sent while federating
|
|
||||||
return await Federation.Sender.DmInvite(id, domain, remoteId2);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
userLock.Release();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
username2 = username2.Split(":")[0];
|
username2 = username2.Split(":")[0];
|
||||||
string id2 = await Account.Utils.IdFromName(username2);
|
string id2 = await Account.Utils.IdFromName(username2);
|
||||||
|
if (id2 == "0")
|
||||||
|
{
|
||||||
|
return "error:user.not.found";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (id2 == id)
|
||||||
|
{
|
||||||
|
return "error:cant.invite.urself";
|
||||||
|
}
|
||||||
SemaphoreSlim userLock2 = Account.Utils.GetUserLock(id2);
|
SemaphoreSlim userLock2 = Account.Utils.GetUserLock(id2);
|
||||||
await userLock2.WaitAsync();
|
await userLock2.WaitAsync();
|
||||||
|
|
||||||
|
|
@ -39,7 +40,7 @@ public class Requests
|
||||||
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))
|
||||||
{
|
{
|
||||||
return "User already invited";
|
return "info:user.already.invited";
|
||||||
}
|
}
|
||||||
|
|
||||||
await Fs.WriteFile(inviteFile, Encoding.UTF8.GetBytes("0"));
|
await Fs.WriteFile(inviteFile, Encoding.UTF8.GetBytes("0"));
|
||||||
|
|
@ -52,7 +53,7 @@ public class Requests
|
||||||
userLock2.Release();
|
userLock2.Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
return "User invited";
|
return "success:user.invited";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<string> DmCreate(string id, string body)
|
public static async Task<string> DmCreate(string id, string body)
|
||||||
|
|
@ -93,7 +94,7 @@ public class Requests
|
||||||
{
|
{
|
||||||
if (!await Federation.Sender.HasSentDmInvite(id2, domain, id))
|
if (!await Federation.Sender.HasSentDmInvite(id2, domain, id))
|
||||||
{
|
{
|
||||||
return "You can't create a DM without an invitation";
|
return "error:cant.create.dm.without.invitation";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -123,7 +124,7 @@ public class Requests
|
||||||
startingMessage.timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds().ToString();
|
startingMessage.timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds().ToString();
|
||||||
startingMessage.type = "larp.info";
|
startingMessage.type = "larp.info";
|
||||||
startingMessage.content =
|
startingMessage.content =
|
||||||
"At the beginning of a DM, you should always verify that the person you're talking to is the intended recipient";
|
"dm.begin.notice";
|
||||||
startingMessage.key = ""; //no key == NOT encrypted
|
startingMessage.key = ""; //no key == NOT encrypted
|
||||||
startingMessage.pervious = "";
|
startingMessage.pervious = "";
|
||||||
|
|
||||||
|
|
@ -169,10 +170,10 @@ public class Requests
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
|
||||||
return "Failed to accept DM. Ask for another invite";
|
return "error:failed.accept.dm";
|
||||||
}
|
}
|
||||||
|
|
||||||
return "DM accepted";
|
return "success:dm.accepted";
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -181,6 +182,6 @@ public class Requests
|
||||||
{
|
{
|
||||||
createLock.Release();
|
createLock.Release();
|
||||||
}
|
}
|
||||||
return "You can't create a DM without an invitation";
|
return "error:cant.create.dm.without.invitation";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -109,7 +109,7 @@ public class Utils
|
||||||
totalRead += read;
|
totalRead += read;
|
||||||
|
|
||||||
if (totalRead > MAX_BODY_SIZE)
|
if (totalRead > MAX_BODY_SIZE)
|
||||||
throw new Exception("Body too large");
|
throw new Exception("error:body.too.large");
|
||||||
|
|
||||||
bodyBuilder.Append(buffer, 0, read);
|
bodyBuilder.Append(buffer, 0, read);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue