From 963f9ae6cb932ac5fe8a17f9127a6530f6caf9dd Mon Sep 17 00:00:00 2001 From: Bulat Kurbanov Date: Mon, 16 Feb 2026 21:09:56 +0100 Subject: [PATCH] Add default_search to user_settings Add migration to add a nullable VARCHAR(32) column with a CHECK constraint restricting values to book, author, series, translator. Update SQLx query artifacts, handlers, and serializers to read and write the new field. --- ...c021837cd8b6fb5841c9644f268b89963b98.json} | 10 ++++++-- ...524eee4e07fae9a979022319ba106f17effd.json} | 13 +++++++--- ...247cad8b941d5fe9090e27427915d172b4a6.json} | 10 ++++++-- ...cebf1f09256351ce80e4201ca0012427664d.json} | 10 ++++++-- ...54d176bf9c967e6dd1a6e659c36a6cdb31f3.json} | 12 +++++++--- ...40101000006_add_default_search_setting.sql | 4 ++++ src/views/users/mod.rs | 24 ++++++++++--------- src/views/users/serializers.rs | 3 +++ 8 files changed, 63 insertions(+), 23 deletions(-) rename .sqlx/{query-f1ec22528fd84d652379dfe739d9ef7a7b5cad5609c5734c845bf0b6da0a5150.json => query-512725635fb38c268949661cf2bdc021837cd8b6fb5841c9644f268b89963b98.json} (69%) rename .sqlx/{query-51d29079e7c27eb0a59d309255e37fd595887cc3faf60a93533e9eadadcab1da.json => query-9ce4bb739dd3e8e8b0b8be165c13524eee4e07fae9a979022319ba106f17effd.json} (62%) rename .sqlx/{query-160ba7ba8bd514083af2a982dca1a0f1bc85e5b73d81a12b67d6c2b0d90e5740.json => query-b1f635ae66d1905c3b2b6dbb4fd9247cad8b941d5fe9090e27427915d172b4a6.json} (70%) rename .sqlx/{query-30aefca980d6708fa760e7cb4196224c1c597c70e57ec71e6deb4556385d355d.json => query-cca138dcdd45bec0bfe0341c851bcebf1f09256351ce80e4201ca0012427664d.json} (69%) rename .sqlx/{query-468d4e044e88a95969f77dc74c6e1c17907571e5119bf240e4facefef508b510.json => query-f208a1162fac1ff6ad8041c4408054d176bf9c967e6dd1a6e659c36a6cdb31f3.json} (73%) create mode 100644 migrations/20240101000006_add_default_search_setting.sql diff --git a/.sqlx/query-f1ec22528fd84d652379dfe739d9ef7a7b5cad5609c5734c845bf0b6da0a5150.json b/.sqlx/query-512725635fb38c268949661cf2bdc021837cd8b6fb5841c9644f268b89963b98.json similarity index 69% rename from .sqlx/query-f1ec22528fd84d652379dfe739d9ef7a7b5cad5609c5734c845bf0b6da0a5150.json rename to .sqlx/query-512725635fb38c268949661cf2bdc021837cd8b6fb5841c9644f268b89963b98.json index 5341532..a322983 100644 --- a/.sqlx/query-f1ec22528fd84d652379dfe739d9ef7a7b5cad5609c5734c845bf0b6da0a5150.json +++ b/.sqlx/query-512725635fb38c268949661cf2bdc021837cd8b6fb5841c9644f268b89963b98.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n user_settings.id,\n user_settings.user_id,\n user_settings.last_name,\n user_settings.first_name,\n user_settings.username,\n user_settings.source,\n COALESCE(\n ARRAY_AGG(ROW(\n languages.id,\n languages.label,\n languages.code\n )::user_language_type) FILTER (WHERE languages.id IS NOT NULL),\n ARRAY[]::user_language_type[]\n ) AS \"allowed_langs!: Vec\"\n FROM user_settings\n LEFT JOIN users_languages ON user_settings.id = users_languages.user\n LEFT JOIN languages ON users_languages.language = languages.id\n WHERE user_settings.user_id = $1\n GROUP BY user_settings.id\n ", + "query": "\n SELECT\n user_settings.id,\n user_settings.user_id,\n user_settings.last_name,\n user_settings.first_name,\n user_settings.username,\n user_settings.source,\n user_settings.default_search,\n COALESCE(\n ARRAY_AGG(ROW(\n languages.id,\n languages.label,\n languages.code\n )::user_language_type) FILTER (WHERE languages.id IS NOT NULL),\n ARRAY[]::user_language_type[]\n ) AS \"allowed_langs!: Vec\"\n FROM user_settings\n LEFT JOIN users_languages ON user_settings.id = users_languages.user\n LEFT JOIN languages ON users_languages.language = languages.id\n WHERE user_settings.user_id = $1\n GROUP BY user_settings.id\n ", "describe": { "columns": [ { @@ -35,6 +35,11 @@ }, { "ordinal": 6, + "name": "default_search", + "type_info": "Varchar" + }, + { + "ordinal": 7, "name": "allowed_langs!: Vec", "type_info": { "Custom": { @@ -78,8 +83,9 @@ false, false, false, + true, null ] }, - "hash": "f1ec22528fd84d652379dfe739d9ef7a7b5cad5609c5734c845bf0b6da0a5150" + "hash": "512725635fb38c268949661cf2bdc021837cd8b6fb5841c9644f268b89963b98" } diff --git a/.sqlx/query-51d29079e7c27eb0a59d309255e37fd595887cc3faf60a93533e9eadadcab1da.json b/.sqlx/query-9ce4bb739dd3e8e8b0b8be165c13524eee4e07fae9a979022319ba106f17effd.json similarity index 62% rename from .sqlx/query-51d29079e7c27eb0a59d309255e37fd595887cc3faf60a93533e9eadadcab1da.json rename to .sqlx/query-9ce4bb739dd3e8e8b0b8be165c13524eee4e07fae9a979022319ba106f17effd.json index a1e97f2..1c52f15 100644 --- a/.sqlx/query-51d29079e7c27eb0a59d309255e37fd595887cc3faf60a93533e9eadadcab1da.json +++ b/.sqlx/query-9ce4bb739dd3e8e8b0b8be165c13524eee4e07fae9a979022319ba106f17effd.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n INSERT INTO user_settings (user_id, last_name, first_name, username, source)\n VALUES ($1, $2, $3, $4, $5)\n ON CONFLICT (user_id) DO UPDATE\n SET last_name = $2, first_name = $3, username = $4, source = $5\n RETURNING id, user_id, last_name, first_name, username, source\n ", + "query": "\n INSERT INTO user_settings (user_id, last_name, first_name, username, source, default_search)\n VALUES ($1, $2, $3, $4, $5, $6)\n ON CONFLICT (user_id) DO UPDATE\n SET last_name = $2, first_name = $3, username = $4, source = $5, default_search = $6\n RETURNING id, user_id, last_name, first_name, username, source, default_search\n ", "describe": { "columns": [ { @@ -32,6 +32,11 @@ "ordinal": 5, "name": "source", "type_info": "Varchar" + }, + { + "ordinal": 6, + "name": "default_search", + "type_info": "Varchar" } ], "parameters": { @@ -40,6 +45,7 @@ "Varchar", "Varchar", "Varchar", + "Varchar", "Varchar" ] }, @@ -49,8 +55,9 @@ false, false, false, - false + false, + true ] }, - "hash": "51d29079e7c27eb0a59d309255e37fd595887cc3faf60a93533e9eadadcab1da" + "hash": "9ce4bb739dd3e8e8b0b8be165c13524eee4e07fae9a979022319ba106f17effd" } diff --git a/.sqlx/query-160ba7ba8bd514083af2a982dca1a0f1bc85e5b73d81a12b67d6c2b0d90e5740.json b/.sqlx/query-b1f635ae66d1905c3b2b6dbb4fd9247cad8b941d5fe9090e27427915d172b4a6.json similarity index 70% rename from .sqlx/query-160ba7ba8bd514083af2a982dca1a0f1bc85e5b73d81a12b67d6c2b0d90e5740.json rename to .sqlx/query-b1f635ae66d1905c3b2b6dbb4fd9247cad8b941d5fe9090e27427915d172b4a6.json index ebf59e0..4dcbf28 100644 --- a/.sqlx/query-160ba7ba8bd514083af2a982dca1a0f1bc85e5b73d81a12b67d6c2b0d90e5740.json +++ b/.sqlx/query-b1f635ae66d1905c3b2b6dbb4fd9247cad8b941d5fe9090e27427915d172b4a6.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n user_settings.id,\n user_settings.user_id,\n user_settings.last_name,\n user_settings.first_name,\n user_settings.username,\n user_settings.source,\n COALESCE(\n ARRAY_AGG(ROW(\n languages.id,\n languages.label,\n languages.code\n )::user_language_type),\n ARRAY[]::user_language_type[]\n ) AS \"allowed_langs!: Vec\"\n FROM user_settings\n LEFT JOIN users_languages ON user_settings.id = users_languages.user\n LEFT JOIN languages ON users_languages.language = languages.id\n WHERE user_settings.id = $1\n GROUP BY user_settings.id\n ", + "query": "\n SELECT\n user_settings.id,\n user_settings.user_id,\n user_settings.last_name,\n user_settings.first_name,\n user_settings.username,\n user_settings.source,\n user_settings.default_search,\n COALESCE(\n ARRAY_AGG(ROW(\n languages.id,\n languages.label,\n languages.code\n )::user_language_type),\n ARRAY[]::user_language_type[]\n ) AS \"allowed_langs!: Vec\"\n FROM user_settings\n LEFT JOIN users_languages ON user_settings.id = users_languages.user\n LEFT JOIN languages ON users_languages.language = languages.id\n WHERE user_settings.id = $1\n GROUP BY user_settings.id\n ", "describe": { "columns": [ { @@ -35,6 +35,11 @@ }, { "ordinal": 6, + "name": "default_search", + "type_info": "Varchar" + }, + { + "ordinal": 7, "name": "allowed_langs!: Vec", "type_info": { "Custom": { @@ -78,8 +83,9 @@ false, false, false, + true, null ] }, - "hash": "160ba7ba8bd514083af2a982dca1a0f1bc85e5b73d81a12b67d6c2b0d90e5740" + "hash": "b1f635ae66d1905c3b2b6dbb4fd9247cad8b941d5fe9090e27427915d172b4a6" } diff --git a/.sqlx/query-30aefca980d6708fa760e7cb4196224c1c597c70e57ec71e6deb4556385d355d.json b/.sqlx/query-cca138dcdd45bec0bfe0341c851bcebf1f09256351ce80e4201ca0012427664d.json similarity index 69% rename from .sqlx/query-30aefca980d6708fa760e7cb4196224c1c597c70e57ec71e6deb4556385d355d.json rename to .sqlx/query-cca138dcdd45bec0bfe0341c851bcebf1f09256351ce80e4201ca0012427664d.json index 299faba..647feb5 100644 --- a/.sqlx/query-30aefca980d6708fa760e7cb4196224c1c597c70e57ec71e6deb4556385d355d.json +++ b/.sqlx/query-cca138dcdd45bec0bfe0341c851bcebf1f09256351ce80e4201ca0012427664d.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT\n user_settings.id,\n user_settings.user_id,\n user_settings.last_name,\n user_settings.first_name,\n user_settings.username,\n user_settings.source,\n COALESCE(\n ARRAY_AGG(ROW(\n languages.id,\n languages.label,\n languages.code\n )::user_language_type),\n ARRAY[]::user_language_type[]\n ) AS \"allowed_langs!: Vec\"\n FROM user_settings\n LEFT JOIN users_languages ON user_settings.id = users_languages.user\n LEFT JOIN languages ON users_languages.language = languages.id\n GROUP BY user_settings.id\n ORDER BY user_settings.id ASC\n OFFSET $1\n LIMIT $2\n ", + "query": "\n SELECT\n user_settings.id,\n user_settings.user_id,\n user_settings.last_name,\n user_settings.first_name,\n user_settings.username,\n user_settings.source,\n user_settings.default_search,\n COALESCE(\n ARRAY_AGG(ROW(\n languages.id,\n languages.label,\n languages.code\n )::user_language_type),\n ARRAY[]::user_language_type[]\n ) AS \"allowed_langs!: Vec\"\n FROM user_settings\n LEFT JOIN users_languages ON user_settings.id = users_languages.user\n LEFT JOIN languages ON users_languages.language = languages.id\n GROUP BY user_settings.id\n ORDER BY user_settings.id ASC\n OFFSET $1\n LIMIT $2\n ", "describe": { "columns": [ { @@ -35,6 +35,11 @@ }, { "ordinal": 6, + "name": "default_search", + "type_info": "Varchar" + }, + { + "ordinal": 7, "name": "allowed_langs!: Vec", "type_info": { "Custom": { @@ -79,8 +84,9 @@ false, false, false, + true, null ] }, - "hash": "30aefca980d6708fa760e7cb4196224c1c597c70e57ec71e6deb4556385d355d" + "hash": "cca138dcdd45bec0bfe0341c851bcebf1f09256351ce80e4201ca0012427664d" } diff --git a/.sqlx/query-468d4e044e88a95969f77dc74c6e1c17907571e5119bf240e4facefef508b510.json b/.sqlx/query-f208a1162fac1ff6ad8041c4408054d176bf9c967e6dd1a6e659c36a6cdb31f3.json similarity index 73% rename from .sqlx/query-468d4e044e88a95969f77dc74c6e1c17907571e5119bf240e4facefef508b510.json rename to .sqlx/query-f208a1162fac1ff6ad8041c4408054d176bf9c967e6dd1a6e659c36a6cdb31f3.json index 155515f..0c192eb 100644 --- a/.sqlx/query-468d4e044e88a95969f77dc74c6e1c17907571e5119bf240e4facefef508b510.json +++ b/.sqlx/query-f208a1162fac1ff6ad8041c4408054d176bf9c967e6dd1a6e659c36a6cdb31f3.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT id, user_id, last_name, first_name, username, source\n FROM user_settings\n WHERE user_id = $1\n ", + "query": "\n SELECT id, user_id, last_name, first_name, username, source, default_search\n FROM user_settings\n WHERE user_id = $1\n ", "describe": { "columns": [ { @@ -32,6 +32,11 @@ "ordinal": 5, "name": "source", "type_info": "Varchar" + }, + { + "ordinal": 6, + "name": "default_search", + "type_info": "Varchar" } ], "parameters": { @@ -45,8 +50,9 @@ false, false, false, - false + false, + true ] }, - "hash": "468d4e044e88a95969f77dc74c6e1c17907571e5119bf240e4facefef508b510" + "hash": "f208a1162fac1ff6ad8041c4408054d176bf9c967e6dd1a6e659c36a6cdb31f3" } diff --git a/migrations/20240101000006_add_default_search_setting.sql b/migrations/20240101000006_add_default_search_setting.sql new file mode 100644 index 0000000..0afd0f0 --- /dev/null +++ b/migrations/20240101000006_add_default_search_setting.sql @@ -0,0 +1,4 @@ +-- Add default search setting: NULL = not selected, or one of: book, author, series, translator +ALTER TABLE user_settings +ADD COLUMN default_search VARCHAR(32) NULL +CHECK (default_search IS NULL OR default_search IN ('book', 'author', 'series', 'translator')); diff --git a/src/views/users/mod.rs b/src/views/users/mod.rs index 569d701..3bac951 100644 --- a/src/views/users/mod.rs +++ b/src/views/users/mod.rs @@ -1,6 +1,10 @@ pub mod serializers; pub mod utils; +use self::{ + serializers::{CreateOrUpdateUserData, SimpleUser, UserDetail, UserLanguage}, + utils::update_languages, +}; use axum::{ extract::{Path, Query}, http::StatusCode, @@ -8,12 +12,6 @@ use axum::{ routing::{get, post}, Json, Router, }; -use serializers::SimpleUser; - -use self::{ - serializers::{CreateOrUpdateUserData, UserDetail, UserLanguage}, - utils::update_languages, -}; use super::{ pagination::{Page, Pagination}, @@ -38,6 +36,7 @@ async fn get_users(pagination: Query, db: Database) -> impl IntoResp user_settings.first_name, user_settings.username, user_settings.source, + user_settings.default_search, COALESCE( ARRAY_AGG(ROW( languages.id, @@ -75,6 +74,7 @@ async fn get_user(Path(user_id): Path, db: Database) -> impl IntoResponse { user_settings.first_name, user_settings.username, user_settings.source, + user_settings.default_search, COALESCE( ARRAY_AGG(ROW( languages.id, @@ -109,17 +109,18 @@ async fn create_or_update_user( let user = sqlx::query_as!( SimpleUser, r#" - INSERT INTO user_settings (user_id, last_name, first_name, username, source) - VALUES ($1, $2, $3, $4, $5) + INSERT INTO user_settings (user_id, last_name, first_name, username, source, default_search) + VALUES ($1, $2, $3, $4, $5, $6) ON CONFLICT (user_id) DO UPDATE - SET last_name = $2, first_name = $3, username = $4, source = $5 - RETURNING id, user_id, last_name, first_name, username, source + SET last_name = $2, first_name = $3, username = $4, source = $5, default_search = $6 + RETURNING id, user_id, last_name, first_name, username, source, default_search "#, data.user_id, data.last_name, data.first_name, data.username, data.source, + data.default_search, ) .fetch_one(&db.0) .await @@ -137,6 +138,7 @@ async fn create_or_update_user( user_settings.first_name, user_settings.username, user_settings.source, + user_settings.default_search, COALESCE( ARRAY_AGG(ROW( languages.id, @@ -164,7 +166,7 @@ async fn update_activity(Path(user_id): Path, db: Database) -> impl IntoRes let user = sqlx::query_as!( SimpleUser, r#" - SELECT id, user_id, last_name, first_name, username, source + SELECT id, user_id, last_name, first_name, username, source, default_search FROM user_settings WHERE user_id = $1 "#, diff --git a/src/views/users/serializers.rs b/src/views/users/serializers.rs index beb81fd..ddbb0f7 100644 --- a/src/views/users/serializers.rs +++ b/src/views/users/serializers.rs @@ -16,6 +16,7 @@ pub struct SimpleUser { pub first_name: String, pub username: String, pub source: String, + pub default_search: Option, } #[derive(sqlx::FromRow, Serialize)] @@ -26,6 +27,7 @@ pub struct UserDetail { pub first_name: String, pub username: String, pub source: String, + pub default_search: Option, pub allowed_langs: Vec, } @@ -36,5 +38,6 @@ pub struct CreateOrUpdateUserData { pub first_name: String, pub username: String, pub source: String, + pub default_search: Option, pub allowed_langs: Vec, }