From cfd8ea055e6fa8b878d425d6c68b346f2ee7939b Mon Sep 17 00:00:00 2001 From: evgeny Date: Wed, 4 Nov 2026 00:31:01 +0100 Subject: [PATCH] Keep pending member profiles out of frontend reads and local edits --- src/chat/chat_core.c | 11 ++++++----- src/chat/chat_member.c | 2 +- src/chat/chat_profile.c | 5 +++-- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/chat/chat_core.c b/src/chat/chat_core.c index f8aa7274c..4f87e9c75 100644 --- a/src/chat/chat_core.c +++ b/src/chat/chat_core.c @@ -434,8 +434,8 @@ int chat_core_get_channels_json(struct UTUN_INSTANCE* inst, char* buf, size_t bu sqlite3_int64 messages, count = 0, online = 0; stage = "history count"; if (json_message_count(cc->db, channel, &messages)) { rc = SQLITE_ERROR; goto error; } - char table[80], sql[160]; peers_table_name(channel, table, sizeof(table)); - snprintf(sql, sizeof(sql), "SELECT node_id FROM \"%s\" WHERE deleted=0 AND admitted=1", table); + char table[80], sql[192]; peers_table_name(channel, table, sizeof(table)); + snprintf(sql, sizeof(sql), "SELECT node_id FROM \"%s\" WHERE record_state=0 AND deleted=0 AND admitted=1", table); stage = "members"; rc = sqlite3_prepare_v2(cc->db, sql, -1, &peers, NULL); if (rc != SQLITE_OK) goto error; while ((rc = sqlite3_step(peers)) == SQLITE_ROW) { count++; online += chat_core_member_online(inst, channel, (uint64_t)sqlite3_column_int64(peers, 0)); @@ -509,7 +509,7 @@ int chat_core_get_members_json(struct UTUN_INSTANCE* inst, const char* ch_id, ch if (!chat_channel_id(ch_id)) { DEBUG_ERROR(DEBUG_CATEGORY_CHAT_SYNC, "members JSON: invalid channel"); return -1; } char table[80], sql[256]; peers_table_name(ch_id, table, sizeof(table)); snprintf(sql, sizeof(sql), "SELECT p.node_id,n.name,n.x25519_pubkey,n.ed25519_pubkey,p.adm_tags,p.deleted" - " FROM \"%s\" p LEFT JOIN nodes n ON p.node_id=n.node_id ORDER BY p.node_id", table); + " FROM \"%s\" p LEFT JOIN nodes n ON p.node_id=n.node_id WHERE p.record_state=0 ORDER BY p.node_id", table); sqlite3_stmt *st = NULL, *addresses = NULL; struct strbuf json = strbuf_new(); const char* stage = "prepare"; int rc = sqlite3_prepare_v2(cc->db, sql, -1, &st, NULL); if (rc != SQLITE_OK) goto error; stage = "JSON"; rc = SQLITE_NOMEM; if (strbuf_addf(&json, "[") < 0) goto error; @@ -675,7 +675,8 @@ struct chat_member_tags* chat_member_tags_load(struct UTUN_INSTANCE* inst, const char peers_tbl[80]; peers_table_name(ch_id, peers_tbl, sizeof(peers_tbl)); sqlite3_stmt* st = NULL; - char sql[256]; snprintf(sql, sizeof(sql), "SELECT adm_tags,adm_tags_sig,x25519_pubkey,ed25519_pubkey,source FROM \"%s\" WHERE node_id=?", peers_tbl); + char sql[256]; snprintf(sql, sizeof(sql), "SELECT adm_tags,adm_tags_sig,x25519_pubkey,ed25519_pubkey,source" + " FROM \"%s\" WHERE node_id=? AND record_state=0", peers_tbl); const char* stage = "prepare"; int rc = sqlite3_prepare_v2(cc->db, sql, -1, &st, NULL); if (rc == SQLITE_OK) { stage = "bind"; rc = sqlite3_bind_int64(st, 1, (sqlite3_int64)node_id); } if (rc == SQLITE_OK) { stage = "step"; rc = sqlite3_step(st); } @@ -832,7 +833,7 @@ static int tags_build_json(struct UTUN_INSTANCE* inst, struct chat_member_tags* /* Выполнить UPDATE внутри транзакции владельца; пустое имя снимает локальный псевдоним. */ static int member_write_nickname(sqlite3* db, const char* channel, uint64_t node, const char* nickname) { char table[80], sql[160]; peers_table_name(channel, table, sizeof(table)); - snprintf(sql, sizeof(sql), "UPDATE \"%s\" SET local_nick=? WHERE node_id=?", table); + snprintf(sql, sizeof(sql), "UPDATE \"%s\" SET local_nick=? WHERE node_id=? AND record_state=0", table); sqlite3_stmt* st = NULL; const char* stage = "prepare"; int rc = sqlite3_prepare_v2(db, sql, -1, &st, NULL); if (rc == SQLITE_OK) { stage = "bind nickname"; rc = sqlite3_bind_text(st, 1, nickname[0] ? nickname : NULL, -1, SQLITE_STATIC); } diff --git a/src/chat/chat_member.c b/src/chat/chat_member.c index 9ad46ef41..136121539 100644 --- a/src/chat/chat_member.c +++ b/src/chat/chat_member.c @@ -217,7 +217,7 @@ static int member_query(struct UTUN_INSTANCE* inst, const char* ch_id, int singl " WHEN MAX(addr_type=2) THEN 2 WHEN MAX(addr_type=6) THEN 6 WHEN MAX(addr_type=4) THEN 4" " WHEN MAX(addr_type=3) THEN 3 ELSE 0 END FROM node_addresses WHERE node_id=p.node_id)" " FROM \"%s\" p LEFT JOIN nodes n ON n.node_id=p.node_id" - " WHERE (p.admitted=1 OR p.source!=0 OR p.deleted!=0) %s ORDER BY p.node_id ASC", + " WHERE p.record_state=0 AND (p.admitted=1 OR p.source!=0 OR p.deleted!=0) %s ORDER BY p.node_id ASC", table, single ? "AND p.node_id=?" : ""); sqlite3_stmt* st = NULL; int rc = sqlite3_prepare_v2(cc->db, sql, -1, &st, NULL); diff --git a/src/chat/chat_profile.c b/src/chat/chat_profile.c index 1e53d9c27..2e3a3b9c2 100644 --- a/src/chat/chat_profile.c +++ b/src/chat/chat_profile.c @@ -103,7 +103,8 @@ int chat_core_get_my_profile(struct UTUN_INSTANCE* inst, const char* channel, ch DEBUG_ERROR(DEBUG_CATEGORY_CHAT, "profile: invalid read request"); return -1; } char table[80], sql[256]; peers_table_name(channel, table, sizeof(table)); - snprintf(sql, sizeof(sql), "SELECT userinfo,update_sig,update_ts,join_sig,ed25519_pubkey,source,join_ts FROM \"%s\" WHERE node_id=?", table); + snprintf(sql, sizeof(sql), "SELECT userinfo,update_sig,update_ts,join_sig,ed25519_pubkey,source,join_ts" + " FROM \"%s\" WHERE node_id=? AND record_state=0", table); sqlite3_stmt* st = NULL; const char* stage = "prepare"; char profile[MS_USERINFO_MAX + 1]; uint8_t update[64], join[64], body[MS_USERINFO_MAX + 73]; uint64_t version, join_ts; int rc = sqlite3_prepare_v2(cc->db, sql, -1, &st, NULL); @@ -149,7 +150,7 @@ struct profile_current { static int profile_read_current(struct UTUN_INSTANCE* inst, const char* channel, struct profile_current* out) { sqlite3* db = CC(inst)->db; char table[80], sql[384]; peers_table_name(channel, table, sizeof(table)); snprintf(sql, sizeof(sql), "SELECT join_sig,join_ts,update_ts,userinfo,update_sig,x25519_pubkey,ed25519_pubkey,source" - " FROM \"%s\" WHERE node_id=?", table); + " FROM \"%s\" WHERE node_id=? AND record_state=0", table); sqlite3_stmt* st = NULL; const char* stage = "prepare"; int found = 0; int rc = sqlite3_prepare_v2(db, sql, -1, &st, NULL); if (rc == SQLITE_OK) { stage = "bind"; rc = sqlite3_bind_int64(st, 1, (sqlite3_int64)inst->node_id); }