Fix user locks & change return strings to blah.blah.blah
All checks were successful
Server Build / publish (push) Successful in 27s
Voice Build / publish (push) Successful in 25s

This commit is contained in:
olcxja 2026-05-10 20:55:24 +02:00
commit 7da97dbeb6
6 changed files with 56 additions and 49 deletions

View file

@ -118,7 +118,7 @@ public class Requests
);
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;
}
@ -133,13 +133,13 @@ public class Requests
if (!Utils.IsValidUsername(entry.name, out string message))
{
await context.Response.WriteAsync("Username: " + message);
await context.Response.WriteAsync($"error:invalid.username.{{{message}}}");
return;
}
if (!Utils.IsValidPassword(entry.pass, out message))
{
await context.Response.WriteAsync("Password: " + message);
await context.Response.WriteAsync($"error:invalid.password.{{{message}}}");
return;
}
@ -162,14 +162,14 @@ public class Requests
);
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;
}
if (entry.captcha.ToLower() != serialized.captcha.ToLower())
{
createHolder.TryRemove(serialized.idKey, out _);
await context.Response.WriteAsync("Incorrect captcha. Please try again");
await context.Response.WriteAsync("error:incorrect.captcha");
return;
}
@ -177,7 +177,7 @@ public class Requests
if (Fs.Exists($"{ACCOUNTS_NAME_DIR}/{lowerName}"))
{
await context.Response.WriteAsync("This username is already taken");
await context.Response.WriteAsync("error:username.taken");
return;
}
@ -185,7 +185,7 @@ public class Requests
Encoding.UTF8.GetString(await Fs.ReadFile($"{ACCOUNTS_DIR}/registration"));
if (registrationString.StartsWith("0;"))
{
await context.Response.WriteAsync("Account creation is currently disabled. Try again later");
await context.Response.WriteAsync("error:registration.disabled");
return;
}
@ -217,7 +217,7 @@ public class Requests
if (!valid)
{
await context.Response.WriteAsync(
"Account creation is currently disabled. Try again later");
"error:registration.disabled");
return;
}
}
@ -240,7 +240,7 @@ public class Requests
if (id == ulong.MaxValue)
{
await context.Response.WriteAsync(
"Server is full, cannot create new accounts. Try again later.");
"error:accounts.slots.full");
return;
}
@ -264,7 +264,7 @@ public class Requests
userLock.Release();
}
await context.Response.WriteAsync("Account created");
await context.Response.WriteAsync("success:account.created");
return;
}
}
@ -389,7 +389,7 @@ public class Requests
userLock.Release();
}
await context.Response.WriteAsync("Password changed successfully");
await context.Response.WriteAsync("success:password.changed");
return;
}
@ -444,7 +444,7 @@ public class Requests
//string publicKey = serializedBody.string1;
//string privateEncryptedKey = serializedBody.string2;
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)
@ -565,6 +565,11 @@ public class Requests
await Room.Requests.DmCreate(id, serializedBody.string2)
, password));
break;
default:
await context.Response.WriteAsync(Encryption.Encryption.EncryptString(
$"error:unknown.request.{{{serializedBody.string1}}}"
, password));
break;
}
}
finally

View file

@ -13,7 +13,7 @@ public class Utils
{
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 ConcurrentQueue<string> keyQueue = new();
@ -58,16 +58,16 @@ public class Utils
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 (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);
}
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)
{
return false;
@ -126,11 +126,11 @@ public class Utils
{
if (!Fs.Exists($"{ACCOUNTS_DATA_DIR}/{id}"))
{
return "Invalid username or password";
return "error:invalid.username.or.password";
}
if (password != password2)
{
return "Invalid password";
return "error:invalid.password";
}
await UpdateLastLogin(id);
@ -141,7 +141,7 @@ public class Utils
{
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);
if (delEntry)
@ -275,7 +275,7 @@ public class Utils
{
if (!Fs.Exists($"{ACCOUNTS_DATA_DIR}/{id}/secret"))
{
return "Account does not exist";
return "error:account.not.exist";
}
if (!IsValidUsername(newName, out string message))
@ -290,13 +290,13 @@ public class Utils
{
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}");
}
await Fs.WriteFile($"{ACCOUNTS_DATA_DIR}/{id}/username", Encoding.UTF8.GetBytes(newName));
return "Username changed successfully";
return "success:username.changed";
}
}

View file

@ -32,7 +32,7 @@ public class Receiver
if (!await Sender.HasSentDmInvite(ids[1], domain, ids[0]))
{
await context.Response.WriteAsync( "Bad request" );
await context.Response.WriteAsync( "error:bad.request" );
return;
}
@ -43,7 +43,7 @@ public class Receiver
string inviteFile = ACCOUNTS_DATA_DIR + $"/{ids[0]}/dminvites/recv/{ids[1]};{domain}";
if (Fs.Exists(inviteFile))
{
await context.Response.WriteAsync("User already invited");
await context.Response.WriteAsync("info:user.already.invited");
return;
}
await Fs.WriteFile(inviteFile, Encoding.UTF8.GetBytes("0"));
@ -54,7 +54,7 @@ public class Receiver
userLock.Release();
}
await context.Response.WriteAsync("User invited");
await context.Response.WriteAsync("success:user.invited");
return;
case "dm/invite/hassent":
@ -77,7 +77,7 @@ public class Receiver
inviteSentFile = ACCOUNTS_DATA_DIR + $"/{ids[0]}/dminvites/sent/{ids[1]};{domain}";
if (!Fs.Exists(inviteSentFile))
{
await context.Response.WriteAsync( "Failed to add. No invite found" );
await context.Response.WriteAsync( "error:no.invite.found" );
return;
}
Fs.DeleteFile(inviteSentFile);
@ -99,7 +99,7 @@ public class Receiver
DateTimeOffset.UtcNow.ToUnixTimeMilliseconds().ToString());
await context.Response.WriteAsync("DM accepted");
await context.Response.WriteAsync("success:dm.accepted");
return;
}

View file

@ -184,6 +184,7 @@ public class Program
}
catch (Exception ex)
{
await context.Response.WriteAsync($"error:unknown.error");
Console.WriteLine(ex);
}

View file

@ -14,23 +14,24 @@ public class Requests
{
if (!Account.Utils.IsUserLocal(username2, out string domain)) //federation
{
SemaphoreSlim userLock = Account.Utils.GetUserLock(id);
await userLock.WaitAsync();
try
{
username2 = username2.Split(":")[0];
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];
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);
}
username2 = username2.Split(":")[0];
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);
await userLock2.WaitAsync();
@ -39,7 +40,7 @@ public class Requests
string inviteFile = ACCOUNTS_DATA_DIR + $"/{id2}/dminvites/recv/{id};{DOMAIN}";
if (Fs.Exists(inviteFile))
{
return "User already invited";
return "info:user.already.invited";
}
await Fs.WriteFile(inviteFile, Encoding.UTF8.GetBytes("0"));
@ -52,7 +53,7 @@ public class Requests
userLock2.Release();
}
return "User invited";
return "success:user.invited";
}
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))
{
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.type = "larp.info";
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.pervious = "";
@ -169,10 +170,10 @@ public class Requests
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();
}
return "You can't create a DM without an invitation";
return "error:cant.create.dm.without.invitation";
}
}

View file

@ -109,7 +109,7 @@ public class Utils
totalRead += read;
if (totalRead > MAX_BODY_SIZE)
throw new Exception("Body too large");
throw new Exception("error:body.too.large");
bodyBuilder.Append(buffer, 0, read);
}