feat(api): add account workspaces and signed content events

This commit is contained in:
justme committed 2026-10-14 04:05:30 +08:00
1 parent 937b774a93
commit 7b8d61d1ba
63 files changed
+5407 -370

No files matched your search

@@ -0,0 +1,61 @@
using WebDrop.Core;
namespace WebDrop.Storage;
public sealed record StoredPasskey(string Id, string Username, string Name, string Data, string PrfSalt, string? KeyEnvelope, long CreatedAt);
public sealed partial class SqliteAccountStore
{
public IReadOnlyList<StoredPasskey> Passkeys(string username)
{
lock (_gate)
{
using var cmd = _connection.CreateCommand(); cmd.CommandText = "SELECT id,username,name,data,prf_salt,key_envelope,created_at FROM account_passkeys WHERE username=$u ORDER BY created_at";
cmd.Parameters.AddWithValue("$u", username); using var reader = cmd.ExecuteReader(); var rows = new List<StoredPasskey>();
while (reader.Read()) rows.Add(new(reader.GetString(0), reader.GetString(1), reader.GetString(2), reader.GetString(3), reader.GetString(4), reader.IsDBNull(5) ? null : reader.GetString(5), reader.GetInt64(6)));
return rows;
}
}
public StoredPasskey? Passkey(string id)
{
lock (_gate)
{
using var cmd = _connection.CreateCommand(); cmd.CommandText = "SELECT username FROM account_passkeys WHERE id=$i"; cmd.Parameters.AddWithValue("$i", id);
return cmd.ExecuteScalar() is string username ? Passkeys(username).FirstOrDefault(p => p.Id == id) : null;
}
}
public void AddPasskey(StoredPasskey passkey)
{
lock (_gate)
{
if (Passkeys(passkey.Username).Count >= 16 || Passkey(passkey.Id) is not null) throw new WebDropException(ErrorCode.Conflict);
using var cmd = _connection.CreateCommand(); cmd.CommandText = "INSERT INTO account_passkeys(id,username,name,data,prf_salt,key_envelope,created_at) VALUES($i,$u,$n,$d,$s,$k,$t)";
cmd.Parameters.AddWithValue("$i", passkey.Id); cmd.Parameters.AddWithValue("$u", passkey.Username); cmd.Parameters.AddWithValue("$n", passkey.Name);
cmd.Parameters.AddWithValue("$d", passkey.Data); cmd.Parameters.AddWithValue("$s", passkey.PrfSalt); cmd.Parameters.AddWithValue("$k", (object?)passkey.KeyEnvelope ?? DBNull.Value); cmd.Parameters.AddWithValue("$t", passkey.CreatedAt); cmd.ExecuteNonQuery();
}
}
public bool UpdatePasskeyData(string id, string username, string oldData, string newData)
{
lock (_gate)
{
using var cmd = _connection.CreateCommand(); cmd.CommandText = "UPDATE account_passkeys SET data=$n WHERE id=$i AND username=$u AND data=$old";
cmd.Parameters.AddWithValue("$i", id); cmd.Parameters.AddWithValue("$u", username); cmd.Parameters.AddWithValue("$n", newData); cmd.Parameters.AddWithValue("$old", oldData); return cmd.ExecuteNonQuery() == 1;
}
}
public void UpdatePasskeyEnvelope(string id, string username, string envelope)
{
lock (_gate)
{
using var cmd = _connection.CreateCommand(); cmd.CommandText = "UPDATE account_passkeys SET key_envelope=$k WHERE id=$i AND username=$u";
cmd.Parameters.AddWithValue("$i", id); cmd.Parameters.AddWithValue("$u", username); cmd.Parameters.AddWithValue("$k", envelope);
if (cmd.ExecuteNonQuery() != 1) throw new WebDropException(ErrorCode.NotFound);
}
}
public void RemovePasskey(string id, string username)
{
lock (_gate)
{
using var cmd = _connection.CreateCommand(); cmd.CommandText = "DELETE FROM account_passkeys WHERE id=$i AND username=$u";
cmd.Parameters.AddWithValue("$i", id); cmd.Parameters.AddWithValue("$u", username); cmd.ExecuteNonQuery();
}
}
}