tablo_core/auth/
columns.rs1use topcoat::context::Cx;
5
6use super::signed;
7use crate::{table::ColumnChoice, topcoat_compat::href};
8
9#[derive(Debug, Clone, toasty::Model)]
17pub struct ColumnPreference {
18 #[key]
20 pub key: String,
21 #[index]
24 pub user_id: String,
25 pub panel: String,
27 pub resource: String,
29 #[column(type = text)]
32 pub columns: String,
33}
34
35fn preference_key(panel: &str, user_id: &str, slug: &str) -> String {
37 href::encode_query(&[
38 ("panel".to_string(), panel),
39 ("user".to_string(), user_id),
40 ("resource".to_string(), slug),
41 ])
42}
43
44pub(crate) async fn load_choice(cx: &Cx, slug: &str) -> ColumnChoice {
47 let Some(signed) = signed(cx) else {
48 return ColumnChoice::default();
49 };
50 let key = preference_key(&signed.realm.prefix, &signed.user.user_id(), slug);
51 let Ok(mut db) = crate::db::db(cx) else {
52 return ColumnChoice::default();
53 };
54 match ColumnPreference::filter(ColumnPreference::fields().key().eq(key))
55 .first()
56 .exec(&mut db)
57 .await
58 {
59 Ok(row) => row.map_or_else(ColumnChoice::default, |row| {
60 ColumnChoice::decode(&row.columns)
61 }),
62 Err(error) => {
63 tracing::warn!(resource = slug, error = %error, "column preference load failed");
64 ColumnChoice::default()
65 }
66 }
67}
68
69pub(crate) async fn save_choice(cx: &Cx, slug: &str, choice: &ColumnChoice) -> topcoat::Result<()> {
77 let Some(signed) = signed(cx) else {
78 return Err(topcoat::router::error::forbidden().into());
79 };
80 let user_id = signed.user.user_id();
81 let panel = signed.realm.prefix.clone();
82 let key = preference_key(&panel, &user_id, slug);
83 let mut db = crate::db::db(cx)?;
84 let mut tx = db.transaction().await.map_err(crate::error::unavailable)?;
85 ColumnPreference::filter(ColumnPreference::fields().key().eq(key.clone()))
86 .delete()
87 .exec(&mut tx)
88 .await
89 .map_err(crate::error::unavailable)?;
90 if !choice.is_default() {
91 toasty::create!(ColumnPreference {
92 key,
93 user_id,
94 panel,
95 resource: slug.to_string(),
96 columns: choice.encode(),
97 })
98 .exec(&mut tx)
99 .await
100 .map_err(crate::error::unavailable)?;
101 }
102 tx.commit().await.map_err(crate::error::unavailable)
103}