feat(saas): wire llm_routing into account CRUD and auth responses

- Add llm_routing to all list_accounts/get_account SQL queries and JSON responses
- Add llm_routing to UpdateAccountRequest with COALESCE update
- Add llm_routing to AccountPublic struct in auth types
- Wire llm_routing into register (default 'local'), login, and me handlers
- Add llm_routing field to AccountRow, AccountAuthRow, AccountLoginRow model structs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
iven
2026-03-31 03:21:19 +08:00
parent c9b9c5231b
commit 49abd0fe89
5 changed files with 27 additions and 17 deletions

View File

@@ -23,7 +23,7 @@ pub async fn list_accounts(
"SELECT COUNT(*) FROM accounts WHERE role = $1 AND status = $2 AND (username LIKE $3 OR email LIKE $3 OR display_name LIKE $3)"
).bind(role).bind(status).bind(&pattern).fetch_one(db).await?;
let rows = sqlx::query_as::<_, AccountRow>(
"SELECT id, username, email, display_name, role, status, totp_enabled, last_login_at, created_at
"SELECT id, username, email, display_name, role, status, totp_enabled, last_login_at, created_at, llm_routing
FROM accounts WHERE role = $1 AND status = $2 AND (username LIKE $3 OR email LIKE $3 OR display_name LIKE $3)
ORDER BY created_at DESC LIMIT $4 OFFSET $5"
).bind(role).bind(status).bind(&pattern).bind(page_size as i64).bind(offset as i64).fetch_all(db).await?;
@@ -35,7 +35,7 @@ pub async fn list_accounts(
"SELECT COUNT(*) FROM accounts WHERE role = $1 AND status = $2"
).bind(role).bind(status).fetch_one(db).await?;
let rows = sqlx::query_as::<_, AccountRow>(
"SELECT id, username, email, display_name, role, status, totp_enabled, last_login_at, created_at
"SELECT id, username, email, display_name, role, status, totp_enabled, last_login_at, created_at, llm_routing
FROM accounts WHERE role = $1 AND status = $2
ORDER BY created_at DESC LIMIT $3 OFFSET $4"
).bind(role).bind(status).bind(page_size as i64).bind(offset as i64).fetch_all(db).await?;
@@ -48,7 +48,7 @@ pub async fn list_accounts(
"SELECT COUNT(*) FROM accounts WHERE role = $1 AND (username LIKE $2 OR email LIKE $2 OR display_name LIKE $2)"
).bind(role).bind(&pattern).fetch_one(db).await?;
let rows = sqlx::query_as::<_, AccountRow>(
"SELECT id, username, email, display_name, role, status, totp_enabled, last_login_at, created_at
"SELECT id, username, email, display_name, role, status, totp_enabled, last_login_at, created_at, llm_routing
FROM accounts WHERE role = $1 AND (username LIKE $2 OR email LIKE $2 OR display_name LIKE $2)
ORDER BY created_at DESC LIMIT $3 OFFSET $4"
).bind(role).bind(&pattern).bind(page_size as i64).bind(offset as i64).fetch_all(db).await?;
@@ -61,7 +61,7 @@ pub async fn list_accounts(
"SELECT COUNT(*) FROM accounts WHERE status = $1 AND (username LIKE $2 OR email LIKE $2 OR display_name LIKE $2)"
).bind(status).bind(&pattern).fetch_one(db).await?;
let rows = sqlx::query_as::<_, AccountRow>(
"SELECT id, username, email, display_name, role, status, totp_enabled, last_login_at, created_at
"SELECT id, username, email, display_name, role, status, totp_enabled, last_login_at, created_at, llm_routing
FROM accounts WHERE status = $1 AND (username LIKE $2 OR email LIKE $2 OR display_name LIKE $2)
ORDER BY created_at DESC LIMIT $3 OFFSET $4"
).bind(status).bind(&pattern).bind(page_size as i64).bind(offset as i64).fetch_all(db).await?;
@@ -73,7 +73,7 @@ pub async fn list_accounts(
"SELECT COUNT(*) FROM accounts WHERE role = $1"
).bind(role).fetch_one(db).await?;
let rows = sqlx::query_as::<_, AccountRow>(
"SELECT id, username, email, display_name, role, status, totp_enabled, last_login_at, created_at
"SELECT id, username, email, display_name, role, status, totp_enabled, last_login_at, created_at, llm_routing
FROM accounts WHERE role = $1
ORDER BY created_at DESC LIMIT $2 OFFSET $3"
).bind(role).bind(page_size as i64).bind(offset as i64).fetch_all(db).await?;
@@ -85,7 +85,7 @@ pub async fn list_accounts(
"SELECT COUNT(*) FROM accounts WHERE status = $1"
).bind(status).fetch_one(db).await?;
let rows = sqlx::query_as::<_, AccountRow>(
"SELECT id, username, email, display_name, role, status, totp_enabled, last_login_at, created_at
"SELECT id, username, email, display_name, role, status, totp_enabled, last_login_at, created_at, llm_routing
FROM accounts WHERE status = $1
ORDER BY created_at DESC LIMIT $2 OFFSET $3"
).bind(status).bind(page_size as i64).bind(offset as i64).fetch_all(db).await?;
@@ -98,7 +98,7 @@ pub async fn list_accounts(
"SELECT COUNT(*) FROM accounts WHERE (username LIKE $1 OR email LIKE $1 OR display_name LIKE $1)"
).bind(&pattern).fetch_one(db).await?;
let rows = sqlx::query_as::<_, AccountRow>(
"SELECT id, username, email, display_name, role, status, totp_enabled, last_login_at, created_at
"SELECT id, username, email, display_name, role, status, totp_enabled, last_login_at, created_at, llm_routing
FROM accounts WHERE (username LIKE $1 OR email LIKE $1 OR display_name LIKE $1)
ORDER BY created_at DESC LIMIT $2 OFFSET $3"
).bind(&pattern).bind(page_size as i64).bind(offset as i64).fetch_all(db).await?;
@@ -110,7 +110,7 @@ pub async fn list_accounts(
"SELECT COUNT(*) FROM accounts"
).fetch_one(db).await?;
let rows = sqlx::query_as::<_, AccountRow>(
"SELECT id, username, email, display_name, role, status, totp_enabled, last_login_at, created_at
"SELECT id, username, email, display_name, role, status, totp_enabled, last_login_at, created_at, llm_routing
FROM accounts ORDER BY created_at DESC LIMIT $1 OFFSET $2"
).bind(page_size as i64).bind(offset as i64).fetch_all(db).await?;
(total, rows)
@@ -123,7 +123,7 @@ pub async fn list_accounts(
serde_json::json!({
"id": r.id, "username": r.username, "email": r.email, "display_name": r.display_name,
"role": r.role, "status": r.status, "totp_enabled": r.totp_enabled,
"last_login_at": r.last_login_at, "created_at": r.created_at,
"last_login_at": r.last_login_at, "created_at": r.created_at, "llm_routing": r.llm_routing,
})
})
.collect();
@@ -134,7 +134,7 @@ pub async fn list_accounts(
pub async fn get_account(db: &PgPool, account_id: &str) -> SaasResult<serde_json::Value> {
let row: Option<AccountRow> =
sqlx::query_as(
"SELECT id, username, email, display_name, role, status, totp_enabled, last_login_at, created_at
"SELECT id, username, email, display_name, role, status, totp_enabled, last_login_at, created_at, llm_routing
FROM accounts WHERE id = $1"
)
.bind(account_id)
@@ -146,7 +146,7 @@ pub async fn get_account(db: &PgPool, account_id: &str) -> SaasResult<serde_json
Ok(serde_json::json!({
"id": r.id, "username": r.username, "email": r.email, "display_name": r.display_name,
"role": r.role, "status": r.status, "totp_enabled": r.totp_enabled,
"last_login_at": r.last_login_at, "created_at": r.created_at,
"last_login_at": r.last_login_at, "created_at": r.created_at, "llm_routing": r.llm_routing,
}))
}
@@ -165,13 +165,15 @@ pub async fn update_account(
email = COALESCE($2, email),
role = COALESCE($3, role),
avatar_url = COALESCE($4, avatar_url),
updated_at = $5
WHERE id = $6"
llm_routing = COALESCE($5, llm_routing),
updated_at = $6
WHERE id = $7"
)
.bind(req.display_name.as_deref())
.bind(req.email.as_deref())
.bind(req.role.as_deref())
.bind(req.avatar_url.as_deref())
.bind(req.llm_routing.as_deref())
.bind(&now)
.bind(account_id)
.execute(db).await?;