Skip to content

Commit 4a70a00

Browse files
committed
fix(db): cast UUID/JSONB/TIMESTAMPTZ columns to text in bots repo
Add BOT_COLS and BOT_INSTALL_COLS to select_cols.rs. Replace all SELECT */RETURNING * in bots.rs so JSONB redirect_uris and scopes columns decode correctly through AnyPool, fixing 500 on the server bots settings tab.
1 parent 84a2f14 commit 4a70a00

2 files changed

Lines changed: 25 additions & 11 deletions

File tree

crates/nexus-db/src/repository/bots.rs

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use sqlx::Row;
55
use uuid::Uuid;
66

77
use nexus_common::models::bot::{BotApplication, BotServerInstall};
8+
use crate::select_cols::{BOT_COLS, BOT_INSTALL_COLS};
89

910
fn row_to_bot(row: &sqlx::any::AnyRow) -> BotApplication {
1011
BotApplication {
@@ -46,7 +47,7 @@ fn row_to_server_install(row: &sqlx::any::AnyRow) -> BotServerInstall {
4647
// ============================================================================
4748

4849
pub async fn get_bot(pool: &sqlx::AnyPool, bot_id: Uuid) -> Result<Option<BotApplication>> {
49-
let row = sqlx::query("SELECT * FROM bot_applications WHERE id = $1")
50+
let row = sqlx::query(&format!("SELECT {} FROM bot_applications WHERE id = $1", BOT_COLS))
5051
.bind(bot_id.to_string())
5152
.fetch_optional(pool)
5253
.await?;
@@ -55,7 +56,7 @@ pub async fn get_bot(pool: &sqlx::AnyPool, bot_id: Uuid) -> Result<Option<BotApp
5556

5657
pub async fn get_bots_by_owner(pool: &sqlx::AnyPool, owner_id: Uuid) -> Result<Vec<BotApplication>> {
5758
let rows = sqlx::query(
58-
"SELECT * FROM bot_applications WHERE owner_id = $1 ORDER BY created_at DESC",
59+
&format!("SELECT {} FROM bot_applications WHERE owner_id = $1 ORDER BY created_at DESC", BOT_COLS),
5960
)
6061
.bind(owner_id.to_string())
6162
.fetch_all(pool)
@@ -67,7 +68,7 @@ pub async fn get_bot_by_token_hash(
6768
pool: &sqlx::AnyPool,
6869
token_hash: &str,
6970
) -> Result<Option<BotApplication>> {
70-
let row = sqlx::query("SELECT * FROM bot_applications WHERE token_hash = $1")
71+
let row = sqlx::query(&format!("SELECT {} FROM bot_applications WHERE token_hash = $1", BOT_COLS))
7172
.bind(token_hash)
7273
.fetch_optional(pool)
7374
.await?;
@@ -88,11 +89,11 @@ pub async fn create_bot(
8889
) -> Result<BotApplication> {
8990
let uris = serde_json::to_string(redirect_uris)?;
9091
let row = sqlx::query(
91-
r#"INSERT INTO bot_applications
92+
&format!(r#"INSERT INTO bot_applications
9293
(id, owner_id, name, description, token_hash, public_key, is_public,
9394
redirect_uris, interactions_endpoint_url)
9495
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
95-
RETURNING *"#,
96+
RETURNING {}"#, BOT_COLS),
9697
)
9798
.bind(id.to_string())
9899
.bind(owner_id.to_string())
@@ -120,7 +121,7 @@ pub async fn update_bot(
120121
) -> Result<Option<BotApplication>> {
121122
let uris = redirect_uris.map(|r| serde_json::to_string(r)).transpose()?;
122123
let row = sqlx::query(
123-
r#"UPDATE bot_applications SET
124+
&format!(r#"UPDATE bot_applications SET
124125
name = COALESCE($1, name),
125126
description = COALESCE($2, description),
126127
avatar = COALESCE($3, avatar),
@@ -129,7 +130,7 @@ pub async fn update_bot(
129130
interactions_endpoint_url = COALESCE($6, interactions_endpoint_url),
130131
updated_at = CURRENT_TIMESTAMP
131132
WHERE id = $7
132-
RETURNING *"#,
133+
RETURNING {}"#, BOT_COLS),
133134
)
134135
.bind(name)
135136
.bind(description)
@@ -176,12 +177,12 @@ pub async fn install_bot_to_server(
176177
) -> Result<BotServerInstall> {
177178
let scopes_json = serde_json::to_string(scopes)?;
178179
let row = sqlx::query(
179-
r#"INSERT INTO bot_server_installs (bot_id, server_id, installed_by, scopes, permissions)
180+
&format!(r#"INSERT INTO bot_server_installs (bot_id, server_id, installed_by, scopes, permissions)
180181
VALUES ($1, $2, $3, $4, $5)
181182
ON CONFLICT (bot_id, server_id) DO UPDATE
182183
SET scopes = EXCLUDED.scopes,
183184
permissions = EXCLUDED.permissions
184-
RETURNING *"#,
185+
RETURNING {}"#, BOT_INSTALL_COLS),
185186
)
186187
.bind(bot_id.to_string())
187188
.bind(server_id.to_string())
@@ -195,7 +196,7 @@ pub async fn install_bot_to_server(
195196

196197
pub async fn get_server_bots(pool: &sqlx::AnyPool, server_id: Uuid) -> Result<Vec<BotServerInstall>> {
197198
let rows = sqlx::query(
198-
"SELECT * FROM bot_server_installs WHERE server_id = $1 ORDER BY installed_at DESC",
199+
&format!("SELECT {} FROM bot_server_installs WHERE server_id = $1 ORDER BY installed_at DESC", BOT_INSTALL_COLS),
199200
)
200201
.bind(server_id.to_string())
201202
.fetch_all(pool)
@@ -206,7 +207,7 @@ pub async fn get_server_bots(pool: &sqlx::AnyPool, server_id: Uuid) -> Result<Ve
206207
/// Return all servers a given bot is installed in.
207208
pub async fn get_bot_servers(pool: &sqlx::AnyPool, bot_id: Uuid) -> Result<Vec<BotServerInstall>> {
208209
let rows = sqlx::query(
209-
"SELECT * FROM bot_server_installs WHERE bot_id = $1 ORDER BY installed_at DESC",
210+
&format!("SELECT {} FROM bot_server_installs WHERE bot_id = $1 ORDER BY installed_at DESC", BOT_INSTALL_COLS),
210211
)
211212
.bind(bot_id.to_string())
212213
.fetch_all(pool)

crates/nexus-db/src/select_cols.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,19 @@ pub const ATTACHMENT_COLS_A: &str =
128128
a.width, a.height, a.duration_secs, a.spoiler, a.blurhash, a.sha256, a.status, \
129129
a.created_at::text AS created_at, a.updated_at::text AS updated_at";
130130

131+
// ── bot_applications ──────────────────────────────────────────────────────────
132+
pub const BOT_COLS: &str =
133+
"id::text AS id, owner_id::text AS owner_id, name, description, avatar, \
134+
token_hash, public_key, redirect_uris::text AS redirect_uris, permissions, \
135+
verified, is_public, interactions_endpoint_url, flags, \
136+
created_at::text AS created_at, updated_at::text AS updated_at";
137+
138+
// ── bot_server_installs ───────────────────────────────────────────────────────
139+
pub const BOT_INSTALL_COLS: &str =
140+
"id::text AS id, bot_id::text AS bot_id, server_id::text AS server_id, \
141+
installed_by::text AS installed_by, scopes::text AS scopes, permissions, \
142+
installed_at::text AS installed_at";
143+
131144
// ── threads ───────────────────────────────────────────────────────────────────
132145
/// Columns for the `threads` table (no prefix). Used in RETURNING clauses
133146
/// where `parent_channel_id` is appended as a separate expression.

0 commit comments

Comments
 (0)