add new upload endpoint, so we can get rid of base64 for uploading images
This commit is contained in:
parent
499de238cb
commit
e15ce6ba8b
4 changed files with 111 additions and 1 deletions
|
|
@ -764,6 +764,54 @@ public static async Task Auth(HttpContext context, Func<Task> next, IQueryCollec
|
|||
}
|
||||
return;
|
||||
}
|
||||
public static async Task Upload(HttpContext context, Func<Task> next, IQueryCollection query)
|
||||
{
|
||||
if (!query.TryGetValue("id", out var idQuery))
|
||||
return;
|
||||
|
||||
if (!context.Request.Headers.TryGetValue("secret", out var secret))
|
||||
return;
|
||||
|
||||
if (!context.Request.Headers.TryGetValue("target", out var targetHeader))
|
||||
return;
|
||||
|
||||
string id = Utils.GetValidIdOrZero(idQuery.ToString());
|
||||
string password = await Utils.GetPassword(id);
|
||||
|
||||
string target = await Utils.NonceDecryptBody(id, password, targetHeader, false);
|
||||
string secretStr = await Utils.NonceDecryptBody(id, password, secret, false);
|
||||
|
||||
string auth = await Utils.Auth(id, secretStr, password);
|
||||
|
||||
if (auth != Utils.LOGIN_SUCCESS)
|
||||
{
|
||||
await context.Response.WriteAsync(Encryption.Encryption.EncryptString(auth, secretStr));
|
||||
return;
|
||||
}
|
||||
|
||||
byte[] bodyBytes = await LarpixServer.Utils.Utils.LoadBodyBytes(context.Request.Body, LarpixServer.Utils.Utils.PUBLIC_STORAGE_LIMIT);
|
||||
byte[] fileBytes = await Utils.NonceDecryptBytes(id, password, bodyBytes, true);
|
||||
|
||||
if (fileBytes == null)
|
||||
{
|
||||
await context.Response.WriteAsync(Encryption.Encryption.EncryptString("error:invalid.nonce", password));
|
||||
return;
|
||||
}
|
||||
|
||||
SemaphoreSlim userLock = Utils.GetUserLock(id);
|
||||
await userLock.WaitAsync();
|
||||
try
|
||||
{
|
||||
await context.Response.WriteAsync(
|
||||
Encryption.Encryption.EncryptString(
|
||||
await Utils.UpdateUserPublicStorageEntryRaw(id, target, fileBytes)
|
||||
, password));
|
||||
}
|
||||
finally
|
||||
{
|
||||
userLock.Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class CreateHolder
|
||||
|
|
|
|||
|
|
@ -173,6 +173,27 @@ public class Utils
|
|||
return decBody;
|
||||
}
|
||||
|
||||
public static async Task<byte[]> NonceDecryptBytes(string id, string password, byte[] body, bool delEntry = true)
|
||||
{
|
||||
(string, DateTimeOffset) nonce;
|
||||
if (delEntry)
|
||||
{
|
||||
if (!Requests.nonceHolder.TryRemove(id, out nonce))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!Requests.nonceHolder.TryGetValue(id, out nonce))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return Encryption.Encryption.DecryptByte(body, nonce.Item1 + password);
|
||||
}
|
||||
|
||||
public static async Task UpdateLastLogin(string id)
|
||||
{
|
||||
if (!Fs.Exists($"{ACCOUNTS_DATA_DIR}/{id}/secret"))
|
||||
|
|
@ -304,6 +325,23 @@ public class Utils
|
|||
return await Fs.ReadFile(path);
|
||||
}
|
||||
|
||||
public static async Task<string> UpdateUserPublicStorageEntryRaw(string id, string entry, byte[] contentBytes)
|
||||
{
|
||||
if (string.IsNullOrEmpty(entry) || entry.Contains("..") || entry.Contains("/") || entry.Contains("\\"))
|
||||
{
|
||||
return "error:invalid.entry.name";
|
||||
}
|
||||
|
||||
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<string> UpdateUserPublicStorageEntry(string id, string entry, string contentBase64)
|
||||
{
|
||||
if (string.IsNullOrEmpty(entry) || entry.Contains("..") || entry.Contains("/") || entry.Contains("\\"))
|
||||
|
|
|
|||
|
|
@ -188,6 +188,9 @@ public class Program
|
|||
case "/_larpix/encryptedrequest":
|
||||
await Account.Requests.EncryptedRequest(context, next, query, reader);
|
||||
return;
|
||||
case "/_larpix/upload":
|
||||
await Account.Requests.Upload(context, next, query);
|
||||
return;
|
||||
case "/_larpix/federation":
|
||||
await Federation.Receiver.FederationRequest(context, next, query, reader);
|
||||
return;
|
||||
|
|
@ -201,7 +204,10 @@ public class Program
|
|||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await context.Response.WriteAsync($"error:unknown.error");
|
||||
if (ex.Message.StartsWith("error:"))
|
||||
await context.Response.WriteAsync(ex.Message);
|
||||
else
|
||||
await context.Response.WriteAsync($"error:unknown.error");
|
||||
Console.WriteLine(ex);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -211,7 +211,25 @@ public class Utils
|
|||
}
|
||||
|
||||
return bodyBuilder.ToString();
|
||||
}
|
||||
|
||||
public static async Task<byte[]> LoadBodyBytes(Stream bodyStream, int maxBodySize)
|
||||
{
|
||||
using MemoryStream ms = new MemoryStream();
|
||||
byte[] buffer = new byte[8192];
|
||||
int read;
|
||||
int totalRead = 0;
|
||||
|
||||
while ((read = await bodyStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
|
||||
{
|
||||
totalRead += read;
|
||||
if (totalRead > maxBodySize)
|
||||
throw new Exception("error:body.too.large");
|
||||
|
||||
ms.Write(buffer, 0, read);
|
||||
}
|
||||
|
||||
return ms.ToArray();
|
||||
}
|
||||
|
||||
public static async Task LoadEnv()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue