better account deletion, add keys to password change,add updating user storage
This commit is contained in:
parent
6571f38afa
commit
499de238cb
5 changed files with 168 additions and 28 deletions
|
|
@ -44,7 +44,10 @@ public class BackgroundDelete : BackgroundService
|
|||
try
|
||||
{
|
||||
string username = await Account.Utils.NameFromId(id);
|
||||
Fs.DeleteFile($"{LarpixServer.Utils.Utils.ACCOUNTS_NAME_DIR}/{username.ToLower()}");
|
||||
if (!string.IsNullOrEmpty(username))
|
||||
{
|
||||
Fs.DeleteFile($"{LarpixServer.Utils.Utils.ACCOUNTS_NAME_DIR}/{username.ToLower()}");
|
||||
}
|
||||
Fs.DeleteDirectory(account);
|
||||
Fs.WriteFile($"{LarpixServer.Utils.Utils.ACCOUNTS_FREEID_DIR}/{id}", []);
|
||||
Console.WriteLine($"Deleted {id} ({username})");
|
||||
|
|
|
|||
|
|
@ -53,8 +53,7 @@ public class Requests
|
|||
userLock.Release();
|
||||
}
|
||||
|
||||
await context.Response.WriteAsync(
|
||||
"ok|Your account will be deleted in one month|Please make sure you are logged out on all devices. Logging back into your account during this period will stop the deletion process");
|
||||
await context.Response.WriteAsync("success:account.deleted.scheduled");
|
||||
}
|
||||
|
||||
public static async Task Create(HttpContext context, Func<Task> next, IQueryCollection query,
|
||||
|
|
@ -232,33 +231,32 @@ public class Requests
|
|||
|
||||
ulong id = ulong.Parse(await Fs.ReadFile($"{ACCOUNTS_DIR}/last"));
|
||||
id++;
|
||||
var freeid = Path.GetFileName(Directory.EnumerateFiles(ACCOUNTS_FREEID_DIR).FirstOrDefault());
|
||||
if (freeid != null)
|
||||
if (id == ulong.MaxValue)
|
||||
{
|
||||
id = ulong.Parse(freeid);
|
||||
Fs.DeleteFile($"{ACCOUNTS_FREEID_DIR}/{freeid}");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (id == ulong.MaxValue)
|
||||
{
|
||||
await context.Response.WriteAsync(
|
||||
"error:accounts.slots.full");
|
||||
return;
|
||||
}
|
||||
|
||||
await Fs.WriteFile($"{ACCOUNTS_DIR}/last", Encoding.UTF8.GetBytes(id.ToString()));
|
||||
await context.Response.WriteAsync("error:accounts.slots.full");
|
||||
return;
|
||||
}
|
||||
await Fs.WriteFile($"{ACCOUNTS_DIR}/last", Encoding.UTF8.GetBytes(id.ToString()));
|
||||
|
||||
SemaphoreSlim userLock = Utils.GetUserLock(id.ToString());
|
||||
await userLock.WaitAsync();
|
||||
try
|
||||
{
|
||||
await Fs.WriteFile($"{ACCOUNTS_NAME_DIR}/{lowerName}", Encoding.UTF8.GetBytes(id.ToString()));
|
||||
await Fs.WriteFile($"{ACCOUNTS_DATA_DIR}/{id.ToString()}/username",
|
||||
Encoding.UTF8.GetBytes(entry.name));
|
||||
await Fs.WriteFile($"{ACCOUNTS_DATA_DIR}/{id.ToString()}/secret",
|
||||
Encoding.UTF8.GetBytes(entry.pass));
|
||||
|
||||
try
|
||||
{
|
||||
await Fs.WriteFile($"{ACCOUNTS_DATA_DIR}/{id.ToString()}/username",
|
||||
Encoding.UTF8.GetBytes(entry.name));
|
||||
await Fs.WriteFile($"{ACCOUNTS_DATA_DIR}/{id.ToString()}/secret",
|
||||
Encoding.UTF8.GetBytes(entry.pass));
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Fs.DeleteFile($"{ACCOUNTS_NAME_DIR}/{lowerName}");
|
||||
throw;
|
||||
}
|
||||
|
||||
createHolder.TryRemove(serialized.idKey, out _);
|
||||
await Utils.UpdateLastLogin(id.ToString());
|
||||
}
|
||||
|
|
@ -408,7 +406,7 @@ public static async Task Auth(HttpContext context, Func<Task> next, IQueryCollec
|
|||
string id = Utils.GetValidIdOrZero(idQuery.ToString());
|
||||
string body = await LoadBody(bodyReader);
|
||||
string password = await Utils.GetPassword(id);
|
||||
string newPass = await Utils.NonceDecryptBody(id, password, body, false);
|
||||
string bodyDecrypted = await Utils.NonceDecryptBody(id, password, body, false);
|
||||
secret = await Utils.NonceDecryptBody(id, password, secret);
|
||||
|
||||
string auth = await Utils.Auth(id, password, secret);
|
||||
|
|
@ -419,6 +417,20 @@ public static async Task Auth(HttpContext context, Func<Task> next, IQueryCollec
|
|||
return;
|
||||
}
|
||||
|
||||
string newPass = bodyDecrypted;
|
||||
string newKeysBody = null;
|
||||
|
||||
try
|
||||
{
|
||||
Universal2String parsedBody = JsonSerializer.Deserialize(bodyDecrypted, AppJsonSerializerContext.Default.Universal2String);
|
||||
if (parsedBody != null && !string.IsNullOrWhiteSpace(parsedBody.string1) && !string.IsNullOrWhiteSpace(parsedBody.string2))
|
||||
{
|
||||
newPass = parsedBody.string1;
|
||||
newKeysBody = parsedBody.string2;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
SemaphoreSlim userLock = Utils.GetUserLock(id);
|
||||
await userLock.WaitAsync();
|
||||
try
|
||||
|
|
@ -429,7 +441,30 @@ public static async Task Auth(HttpContext context, Func<Task> next, IQueryCollec
|
|||
return;
|
||||
}
|
||||
|
||||
await Utils.SetPassword(id, newPass);
|
||||
string oldKeys = null;
|
||||
if (newKeysBody != null)
|
||||
{
|
||||
oldKeys = await Utils.GetUserKeys(id);
|
||||
string keyUpdateResult = await UpdateUserKeys(id, newKeysBody);
|
||||
if (keyUpdateResult.StartsWith("error:"))
|
||||
{
|
||||
await context.Response.WriteAsync(keyUpdateResult);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
await Utils.SetPassword(id, newPass);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
if (newKeysBody != null && oldKeys != null)
|
||||
{
|
||||
await Utils.UpdateUserKeys(id, oldKeys);
|
||||
}
|
||||
throw;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
|
@ -620,6 +655,30 @@ public static async Task Auth(HttpContext context, Func<Task> next, IQueryCollec
|
|||
await Utils.GetUserKeys(id)
|
||||
, password));
|
||||
break;
|
||||
case "user/storage/public/update":
|
||||
{
|
||||
Universal2String storageUpdate = JsonSerializer.Deserialize(
|
||||
serializedBody.string2,
|
||||
AppJsonSerializerContext.Default.Universal2String
|
||||
);
|
||||
await context.Response.WriteAsync(
|
||||
Encryption.Encryption.EncryptString(
|
||||
await Utils.UpdateUserPublicStorageEntry(id, storageUpdate.string1, storageUpdate.string2)
|
||||
, password));
|
||||
break;
|
||||
}
|
||||
case "user/storage/private/update":
|
||||
{
|
||||
Universal2String storageUpdate = JsonSerializer.Deserialize(
|
||||
serializedBody.string2,
|
||||
AppJsonSerializerContext.Default.Universal2String
|
||||
);
|
||||
await context.Response.WriteAsync(
|
||||
Encryption.Encryption.EncryptString(
|
||||
await Utils.UpdateUserPrivateStorageEntry(id, storageUpdate.string1, storageUpdate.string2)
|
||||
, password));
|
||||
break;
|
||||
}
|
||||
case "user/dm/list":
|
||||
await context.Response.WriteAsync(
|
||||
Encryption.Encryption.EncryptString(
|
||||
|
|
|
|||
|
|
@ -304,6 +304,72 @@ public class Utils
|
|||
return await Fs.ReadFile(path);
|
||||
}
|
||||
|
||||
public static async Task<string> UpdateUserPublicStorageEntry(string id, string entry, string contentBase64)
|
||||
{
|
||||
if (string.IsNullOrEmpty(entry) || entry.Contains("..") || entry.Contains("/") || entry.Contains("\\"))
|
||||
{
|
||||
return "error:invalid.entry.name";
|
||||
}
|
||||
byte[] contentBytes;
|
||||
try
|
||||
{
|
||||
contentBytes = Convert.FromBase64String(contentBase64);
|
||||
}
|
||||
catch
|
||||
{
|
||||
contentBytes = Encoding.UTF8.GetBytes(contentBase64);
|
||||
}
|
||||
|
||||
if (contentBytes.Length > PUBLIC_STORAGE_LIMIT)
|
||||
{
|
||||
return "error:storage.limit.exceeded";
|
||||
}
|
||||
|
||||
string path = $"{ACCOUNTS_DATA_DIR}/{id}/storage/public/{entry}";
|
||||
await Fs.WriteFile(path, contentBytes);
|
||||
return "success:storage.entry.updated";
|
||||
}
|
||||
|
||||
public static async Task<byte[]> GetUserPrivateStorageEntry(string id, string entry)
|
||||
{
|
||||
if (string.IsNullOrEmpty(entry) || entry.Contains("..") || entry.Contains("/") || entry.Contains("\\"))
|
||||
{
|
||||
return new byte[] {};
|
||||
}
|
||||
string path = $"{ACCOUNTS_DATA_DIR}/{id}/storage/private/{entry}";
|
||||
if (!Fs.Exists(path))
|
||||
{
|
||||
return new byte[] {};
|
||||
}
|
||||
return await Fs.ReadFile(path);
|
||||
}
|
||||
|
||||
public static async Task<string> UpdateUserPrivateStorageEntry(string id, string entry, string contentBase64)
|
||||
{
|
||||
if (string.IsNullOrEmpty(entry) || entry.Contains("..") || entry.Contains("/") || entry.Contains("\\"))
|
||||
{
|
||||
return "error:invalid.entry.name";
|
||||
}
|
||||
byte[] contentBytes;
|
||||
try
|
||||
{
|
||||
contentBytes = Convert.FromBase64String(contentBase64);
|
||||
}
|
||||
catch
|
||||
{
|
||||
contentBytes = Encoding.UTF8.GetBytes(contentBase64);
|
||||
}
|
||||
|
||||
if (contentBytes.Length > PRIVATE_STORAGE_LIMIT)
|
||||
{
|
||||
return "error:storage.limit.exceeded";
|
||||
}
|
||||
|
||||
string path = $"{ACCOUNTS_DATA_DIR}/{id}/storage/private/{entry}";
|
||||
await Fs.WriteFile(path, contentBytes);
|
||||
return "success:storage.entry.updated";
|
||||
}
|
||||
|
||||
public static async Task UpdateUserDm(string id, string dmId, string isRead = "false", string timestamp = "")
|
||||
{
|
||||
|
||||
|
|
@ -394,7 +460,19 @@ public class Utils
|
|||
|
||||
Fs.MoveFile($"{ACCOUNTS_NAME_DIR}/{lowerOldName}", $"{ACCOUNTS_NAME_DIR}/{lowerNewName}");
|
||||
}
|
||||
await Fs.WriteFile($"{ACCOUNTS_DATA_DIR}/{id}/username", Encoding.UTF8.GetBytes(newName));
|
||||
|
||||
try
|
||||
{
|
||||
await Fs.WriteFile($"{ACCOUNTS_DATA_DIR}/{id}/username", Encoding.UTF8.GetBytes(newName));
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
if (lowerNewName != lowerOldName)
|
||||
{
|
||||
Fs.MoveFile($"{ACCOUNTS_NAME_DIR}/{lowerNewName}", $"{ACCOUNTS_NAME_DIR}/{lowerOldName}");
|
||||
}
|
||||
throw;
|
||||
}
|
||||
|
||||
return "success:username.changed";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -396,7 +396,7 @@ public class Requests
|
|||
msg.type = "larp.text";
|
||||
msg.content = content;
|
||||
msg.attachment = attachment;
|
||||
msg.key = "0"; // Flag for encrypted content
|
||||
msg.key = "0"; //empty = no encryption, value = encryption key index
|
||||
msg.pervious = "";
|
||||
msg.responded = responded ?? "";
|
||||
msg.reactions = "";
|
||||
|
|
@ -435,7 +435,7 @@ public class Requests
|
|||
}
|
||||
}
|
||||
}
|
||||
return "success:message.sent";
|
||||
return $"success:{nextId}";
|
||||
}
|
||||
|
||||
public static async Task<string> DmMessageDelete(string id, string body)
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ public class Utils
|
|||
public static int DIR_CACHE_SIZE = 800000;
|
||||
public static int LOCK_SIZE = 1000000;
|
||||
|
||||
public static int MAX_BODY_SIZE = 524288; //0.5mb
|
||||
public static int MAX_BODY_SIZE = 20971520; //20mb //2621440; //2.5mb
|
||||
|
||||
public static int PRIVATE_STORAGE_LIMIT = 5242880;
|
||||
public static int PUBLIC_STORAGE_LIMIT = 10485760;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue