62 lines
3.5 KiB
C#
62 lines
3.5 KiB
C#
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();
|
|
}
|
|
}
|
|
}
|