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

@@ -44,6 +44,8 @@ public sealed class SqliteChannelStore : IResourceStore, IDisposable
created_at INTEGER NOT NULL, PRIMARY KEY (channel_id, username)
) WITHOUT ROWID;
CREATE INDEX IF NOT EXISTS ix_channel_keys_username ON channel_key_packages(username);
CREATE TABLE IF NOT EXISTS workspace_structures (space_id BLOB PRIMARY KEY, state TEXT NOT NULL) WITHOUT ROWID;
CREATE TABLE IF NOT EXISTS workspace_crypto (space_id BLOB PRIMARY KEY, state TEXT NOT NULL) WITHOUT ROWID;
""");
}
@@ -253,6 +255,19 @@ public sealed class SqliteChannelStore : IResourceStore, IDisposable
private sealed class SqliteTx(SqliteConnection conn) : IResourceTx
{
private const string ChannelCols = "id, mode, settings, read_hash, write_hash, owner_hash, created_at, expires_at, last_seq, compacted_through, bytes, creator_account, join_password_hash, join_password_salt";
public WorkspaceState? GetWorkspace(Id16 id) => One("SELECT state FROM workspace_structures WHERE space_id=@id",
r => JsonSerializer.Deserialize(r.GetString(0), WorkspaceJson.Default.WorkspaceState)!, ("@id", id.ToArray()));
public CryptoState GetWorkspaceCrypto(Id16 id) => One("SELECT state FROM workspace_crypto WHERE space_id=@id",
r => JsonSerializer.Deserialize(r.GetString(0), WorkspaceCryptoJson.Default.CryptoState)!, ("@id", id.ToArray())) ?? new CryptoState();
public void PutWorkspaceCrypto(Id16 id, CryptoState state) => Run(
"INSERT INTO workspace_crypto(space_id,state) VALUES(@id,@s) ON CONFLICT(space_id) DO UPDATE SET state=excluded.state",
("@id", id.ToArray()), ("@s", JsonSerializer.Serialize(state, WorkspaceCryptoJson.Default.CryptoState)));
public IReadOnlyList<Id16> ListAccountSpaces(string username, long now) => Many(
"SELECT c.id FROM channels c JOIN channel_members m ON m.channel_id=c.id WHERE m.username=@u AND c.expires_at>@n ORDER BY c.created_at DESC",
r => Id16.FromBytes((byte[])r[0]), ("@u", username), ("@n", now));
public void PutWorkspace(Id16 id, WorkspaceState state) => Run(
"INSERT INTO workspace_structures(space_id,state) VALUES(@id,@s) ON CONFLICT(space_id) DO UPDATE SET state=excluded.state",
("@id", id.ToArray()), ("@s", JsonSerializer.Serialize(state, WorkspaceJson.Default.WorkspaceState)));
private const string ItemCols = "channel_id, item_id, author_hash, flags, max_downloads, downloads, frame_count, max_index, final_index, bytes, created_at, expires_at, close_deadline, author_account";
private const string FrameCols = "channel_id, item_id, frame_index, seq, length, digest, inline_blob, blob_key";
private const string ShareItemCols = "share_id, item_id, flags, max_downloads, downloads, frame_count, max_index, final_index, bytes, created_at, expires_at, close_deadline";
@@ -487,6 +502,8 @@ public sealed class SqliteChannelStore : IResourceStore, IDisposable
Run("DELETE FROM channels WHERE id=@c", ("@c", key));
Run("DELETE FROM channel_invitations WHERE channel_id=@c", ("@c", key));
Run("DELETE FROM channel_key_packages WHERE channel_id=@c", ("@c", key));
Run("DELETE FROM workspace_structures WHERE space_id=@c", ("@c", key));
Run("DELETE FROM workspace_crypto WHERE space_id=@c", ("@c", key));
Run("DELETE FROM channel_members WHERE channel_id=@c", ("@c", key));
Run("DELETE FROM channel_join_denials WHERE channel_id=@c", ("@c", key));
}
@@ -505,6 +522,9 @@ public sealed class SqliteChannelStore : IResourceStore, IDisposable
public int CountSeats(Id16 channelId) =>
(int)(long)Scalar("SELECT COUNT(*) FROM seats WHERE channel_id=@c", ("@c", channelId.ToArray()))!;
public int CountMembers(Id16 channelId) =>
(int)(long)Scalar("SELECT (SELECT COUNT(*) FROM channel_members WHERE channel_id=@c) + (SELECT COUNT(*) FROM seats WHERE channel_id=@c AND account_name IS NULL)", ("@c", channelId.ToArray()))!;
public void InsertSeat(Id16 channelId, Seat seat) => Run(
"INSERT INTO seats (channel_id, endpoint_hash, label, joined_at,account_name,account_device_id) VALUES (@c,@e,@l,@j,@a,@d)",
("@c", channelId.ToArray()), ("@e", seat.EndpointHash), ("@l", seat.Label), ("@j", seat.JoinedAt), ("@a", seat.AccountName), ("@d", seat.AccountDeviceId));