fix: postgres

This commit is contained in:
trisua 2025-04-03 15:07:57 -04:00
parent dcd5f359c6
commit 27d7c2f4b5
29 changed files with 298 additions and 224 deletions

View file

@ -188,6 +188,8 @@ pub(crate) async fn write_assets(config: &Config) -> PathBufD {
/// Set up extra directories. /// Set up extra directories.
pub(crate) async fn init_dirs(config: &Config) { pub(crate) async fn init_dirs(config: &Config) {
create_dir_if_not_exists!(&config.dirs.templates);
// images // images
create_dir_if_not_exists!(&config.dirs.media); create_dir_if_not_exists!(&config.dirs.media);
let images_path = PathBufD::current().extend(&[config.dirs.media.as_str(), "images"]); let images_path = PathBufD::current().extend(&[config.dirs.media.as_str(), "images"]);

View file

@ -73,7 +73,7 @@ pub async fn avatar_request(
let path = PathBufD::current().extend(&[ let path = PathBufD::current().extend(&[
data.0.dirs.media.as_str(), data.0.dirs.media.as_str(),
"avatars", "avatars",
&format!("{}.avif", &user.id), &format!("{}.avif", &(user.id as i64)),
]); ]);
if !exists(&path).unwrap() { if !exists(&path).unwrap() {
@ -118,7 +118,7 @@ pub async fn banner_request(
let path = PathBufD::current().extend(&[ let path = PathBufD::current().extend(&[
data.0.dirs.media.as_str(), data.0.dirs.media.as_str(),
"banners", "banners",
&format!("{}.avif", &user.id), &format!("{}.avif", &(user.id as i64)),
]); ]);
if !exists(&path).unwrap() { if !exists(&path).unwrap() {

View file

@ -9,10 +9,7 @@ pub struct SecurityConfig {
/// If registrations are enabled. /// If registrations are enabled.
#[serde(default = "default_security_registration_enabled")] #[serde(default = "default_security_registration_enabled")]
pub registration_enabled: bool, pub registration_enabled: bool,
/// If registrations are enabled. /// The name of the header which will contain the real IP of the connecting user.
#[serde(default = "default_security_admin_user")]
pub admin_user: String,
/// If registrations are enabled.
#[serde(default = "default_real_ip_header")] #[serde(default = "default_real_ip_header")]
pub real_ip_header: String, pub real_ip_header: String,
} }
@ -21,10 +18,6 @@ fn default_security_registration_enabled() -> bool {
true true
} }
fn default_security_admin_user() -> String {
"admin".to_string()
}
fn default_real_ip_header() -> String { fn default_real_ip_header() -> String {
"CF-Connecting-IP".to_string() "CF-Connecting-IP".to_string()
} }
@ -33,7 +26,6 @@ impl Default for SecurityConfig {
fn default() -> Self { fn default() -> Self {
Self { Self {
registration_enabled: default_security_registration_enabled(), registration_enabled: default_security_registration_enabled(),
admin_user: default_security_admin_user(),
real_ip_header: default_real_ip_header(), real_ip_header: default_real_ip_header(),
} }
} }
@ -202,7 +194,7 @@ fn default_name() -> String {
} }
fn default_description() -> String { fn default_description() -> String {
"🐐 tetratto!".to_string() "🐇 tetratto!".to_string()
} }
fn default_color() -> String { fn default_color() -> String {

View file

@ -1,7 +1,7 @@
use super::*; use super::*;
use crate::cache::Cache; use crate::cache::Cache;
use crate::model::{Error, Result, auth::User, moderation::AuditLogEntry, permissions::FinePermission}; use crate::model::{Error, Result, auth::User, moderation::AuditLogEntry, permissions::FinePermission};
use crate::{auto_method, execute, get, query_row, query_rows}; use crate::{auto_method, execute, get, params, query_row, query_rows};
#[cfg(feature = "sqlite")] #[cfg(feature = "sqlite")]
use rusqlite::Row; use rusqlite::Row;
@ -23,7 +23,7 @@ impl DataManager {
} }
} }
auto_method!(get_audit_log_entry_by_id(usize)@get_audit_log_entry_from_row -> "SELECT * FROM audit_log WHERE id = $1" --name="audit log entry" --returns=AuditLogEntry --cache-key-tmpl="atto.audit_log:{}"); auto_method!(get_audit_log_entry_by_id(usize as i64)@get_audit_log_entry_from_row -> "SELECT * FROM audit_log WHERE id = $1" --name="audit log entry" --returns=AuditLogEntry --cache-key-tmpl="atto.audit_log:{}");
/// Get all audit log entries (paginated). /// Get all audit log entries (paginated).
/// ///
@ -67,10 +67,10 @@ impl DataManager {
let res = execute!( let res = execute!(
&conn, &conn,
"INSERT INTO audit_log VALUES ($1, $2, $3, $4)", "INSERT INTO audit_log VALUES ($1, $2, $3, $4)",
&[ params![
&data.id.to_string().as_str(), &(data.id as i64),
&data.created.to_string().as_str(), &(data.created as i64),
&data.moderator.to_string().as_str(), &(data.moderator as i64),
&data.content.as_str(), &data.content.as_str(),
] ]
); );
@ -96,7 +96,7 @@ impl DataManager {
let res = execute!( let res = execute!(
&conn, &conn,
"DELETE FROM audit_log WHERE id = $1", "DELETE FROM audit_log WHERE id = $1",
&[&id.to_string()] &[&(id as i64)]
); );
if let Err(e) = res { if let Err(e) = res {

View file

@ -6,7 +6,7 @@ use crate::model::{
auth::{Token, User, UserSettings}, auth::{Token, User, UserSettings},
permissions::FinePermission, permissions::FinePermission,
}; };
use crate::{auto_method, execute, get, query_row}; use crate::{auto_method, execute, get, query_row, params};
use pathbufd::PathBufD; use pathbufd::PathBufD;
use std::fs::{exists, remove_file}; use std::fs::{exists, remove_file};
use tetratto_shared::hash::{hash_salted, salt}; use tetratto_shared::hash::{hash_salted, salt};
@ -32,8 +32,12 @@ impl DataManager {
salt: get!(x->4(String)), salt: get!(x->4(String)),
settings: serde_json::from_str(&get!(x->5(String)).to_string()).unwrap(), settings: serde_json::from_str(&get!(x->5(String)).to_string()).unwrap(),
tokens: serde_json::from_str(&get!(x->6(String)).to_string()).unwrap(), tokens: serde_json::from_str(&get!(x->6(String)).to_string()).unwrap(),
permissions: FinePermission::from_bits(get!(x->7(u32))).unwrap(), permissions: FinePermission::from_bits(get!(x->7(i64)) as u32).unwrap(),
is_verified: if get!(x->8(i8)) == 1 { true } else { false }, is_verified: if get!(x->8(i64)) as i8 == 1 {
true
} else {
false
},
notification_count: get!(x->9(i64)) as usize, notification_count: get!(x->9(i64)) as usize,
follower_count: get!(x->10(i64)) as usize, follower_count: get!(x->10(i64)) as usize,
following_count: get!(x->11(i64)) as usize, following_count: get!(x->11(i64)) as usize,
@ -41,7 +45,7 @@ impl DataManager {
} }
} }
auto_method!(get_user_by_id(usize)@get_user_from_row -> "SELECT * FROM users WHERE id = $1" --name="user" --returns=User --cache-key-tmpl="atto.user:{}"); auto_method!(get_user_by_id(usize as i64)@get_user_from_row -> "SELECT * FROM users WHERE id = $1" --name="user" --returns=User --cache-key-tmpl="atto.user:{}");
auto_method!(get_user_by_username(&str)@get_user_from_row -> "SELECT * FROM users WHERE username = $1" --name="user" --returns=User --cache-key-tmpl="atto.user:{}"); auto_method!(get_user_by_username(&str)@get_user_from_row -> "SELECT * FROM users WHERE username = $1" --name="user" --returns=User --cache-key-tmpl="atto.user:{}");
/// Get a user given just their auth token. /// Get a user given just their auth token.
@ -106,20 +110,20 @@ impl DataManager {
let res = execute!( let res = execute!(
&conn, &conn,
"INSERT INTO users VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)", "INSERT INTO users VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)",
&[ params![
&data.id.to_string().as_str(), &(data.id as i64),
&data.created.to_string().as_str(), &(data.created as i64),
&data.username.to_lowercase().as_str(), &data.username.to_lowercase(),
&data.password.as_str(), &data.password,
&data.salt.as_str(), &data.salt,
&serde_json::to_string(&data.settings).unwrap().as_str(), &serde_json::to_string(&data.settings).unwrap(),
&serde_json::to_string(&data.tokens).unwrap().as_str(), &serde_json::to_string(&data.tokens).unwrap(),
&(FinePermission::DEFAULT.bits()).to_string().as_str(), &(FinePermission::DEFAULT.bits() as i64),
&(if data.is_verified { 1 } else { 0 }).to_string().as_str(), &(if data.is_verified { 1 as i64 } else { 0 as i64 }),
&0.to_string().as_str(), &(0 as i64),
&0.to_string().as_str(), &(0 as i64),
&0.to_string().as_str(), &(0 as i64),
&data.last_seen.to_string().as_str(), &(data.last_seen as i64),
] ]
); );
@ -213,13 +217,13 @@ impl DataManager {
let avatar = PathBufD::current().extend(&[ let avatar = PathBufD::current().extend(&[
self.0.dirs.media.as_str(), self.0.dirs.media.as_str(),
"avatars", "avatars",
&format!("{}.avif", &user.id), &format!("{}.avif", &(user.id as i64)),
]); ]);
let banner = PathBufD::current().extend(&[ let banner = PathBufD::current().extend(&[
self.0.dirs.media.as_str(), self.0.dirs.media.as_str(),
"banners", "banners",
&format!("{}.avif", &user.id), &format!("{}.avif", &(user.id as i64)),
]); ]);
if exists(&avatar).unwrap() { if exists(&avatar).unwrap() {
@ -249,10 +253,7 @@ impl DataManager {
let res = execute!( let res = execute!(
&conn, &conn,
"UPDATE users SET verified = $1 WHERE id = $2", "UPDATE users SET verified = $1 WHERE id = $2",
&[ params![&(if x { 1 } else { 0 } as i64), &(id as i64)]
&(if x { 1 } else { 0 }).to_string().as_str(),
&id.to_string().as_str()
]
); );
if let Err(e) = res { if let Err(e) = res {
@ -299,11 +300,7 @@ impl DataManager {
let res = execute!( let res = execute!(
&conn, &conn,
"UPDATE users SET password = $1, salt = $2 WHERE id = $3", "UPDATE users SET password = $1, salt = $2 WHERE id = $3",
&[ params![&new_password.as_str(), &new_salt.as_str(), &(id as i64)]
&new_password.as_str(),
&new_salt.as_str(),
&id.to_string().as_str()
]
); );
if let Err(e) = res { if let Err(e) = res {
@ -324,7 +321,7 @@ impl DataManager {
let res = execute!( let res = execute!(
&conn, &conn,
"UPDATE users SET username = $1 WHERE id = $3", "UPDATE users SET username = $1 WHERE id = $3",
&[&to.as_str(), &id.to_string().as_str()] params![&to.as_str(), &(id as i64)]
); );
if let Err(e) = res { if let Err(e) = res {
@ -370,10 +367,7 @@ impl DataManager {
let res = execute!( let res = execute!(
&conn, &conn,
"UPDATE users SET permissions = $1 WHERE id = $2", "UPDATE users SET permissions = $1 WHERE id = $2",
&[ params![&(role.bits() as i64), &(id as i64)]
&(role.bits()).to_string().as_str(),
&id.to_string().as_str()
]
); );
if let Err(e) = res { if let Err(e) = res {
@ -406,10 +400,7 @@ impl DataManager {
let res = execute!( let res = execute!(
&conn, &conn,
"UPDATE users SET last_seen = $1 WHERE id = $2", "UPDATE users SET last_seen = $1 WHERE id = $2",
&[ params![&(unix_epoch_timestamp() as i64), &(user.id as i64)]
&unix_epoch_timestamp().to_string().as_str(),
&user.id.to_string().as_str()
]
); );
if let Err(e) = res { if let Err(e) = res {

View file

@ -131,6 +131,41 @@ macro_rules! auto_method {
} }
}; };
($name:ident($selector_t:ty as i64)@$select_fn:ident -> $query:literal --name=$name_:literal --returns=$returns_:tt --cache-key-tmpl=$cache_key_tmpl:literal) => {
pub async fn $name(&self, selector: $selector_t) -> Result<$returns_> {
if let Some(cached) = self
.2
.get(format!($cache_key_tmpl, selector.to_string()))
.await
{
return Ok(serde_json::from_str(&cached).unwrap());
}
let conn = match self.connect().await {
Ok(c) => c,
Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
};
let res = query_row!(&conn, $query, &[&(selector as i64)], |x| {
Ok(Self::$select_fn(x))
});
if res.is_err() {
return Err(Error::GeneralNotFound($name_.to_string()));
}
let x = res.unwrap();
self.2
.set(
format!($cache_key_tmpl, selector),
serde_json::to_string(&x).unwrap(),
)
.await;
Ok(x)
}
};
($name:ident()@$select_fn:ident:$permission:ident -> $query:literal) => { ($name:ident()@$select_fn:ident:$permission:ident -> $query:literal) => {
pub async fn $name(&self, id: usize, user: User) -> Result<()> { pub async fn $name(&self, id: usize, user: User) -> Result<()> {
let y = self.$select_fn(id).await?; let y = self.$select_fn(id).await?;
@ -151,7 +186,7 @@ macro_rules! auto_method {
Err(e) => return Err(Error::DatabaseConnection(e.to_string())), Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
}; };
let res = execute!(&conn, $query, &[&id.to_string()]); let res = execute!(&conn, $query, &[&(id as i64)]);
if let Err(e) = res { if let Err(e) = res {
return Err(Error::DatabaseError(e.to_string())); return Err(Error::DatabaseError(e.to_string()));
@ -181,7 +216,7 @@ macro_rules! auto_method {
Err(e) => return Err(Error::DatabaseConnection(e.to_string())), Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
}; };
let res = execute!(&conn, $query, &[&id.to_string()]); let res = execute!(&conn, $query, &[&(id as i64)]);
if let Err(e) = res { if let Err(e) = res {
return Err(Error::DatabaseError(e.to_string())); return Err(Error::DatabaseError(e.to_string()));
@ -214,7 +249,7 @@ macro_rules! auto_method {
Err(e) => return Err(Error::DatabaseConnection(e.to_string())), Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
}; };
let res = execute!(&conn, $query, &[&x, &id.to_string()]); let res = execute!(&conn, $query, &[&x, &(id as i64)]);
if let Err(e) = res { if let Err(e) = res {
return Err(Error::DatabaseError(e.to_string())); return Err(Error::DatabaseError(e.to_string()));
@ -245,7 +280,7 @@ macro_rules! auto_method {
Err(e) => return Err(Error::DatabaseConnection(e.to_string())), Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
}; };
let res = execute!(&conn, $query, &[&x, &id.to_string()]); let res = execute!(&conn, $query, params![&x, &(id as i64)]);
if let Err(e) = res { if let Err(e) = res {
return Err(Error::DatabaseError(e.to_string())); return Err(Error::DatabaseError(e.to_string()));
@ -281,7 +316,7 @@ macro_rules! auto_method {
let res = execute!( let res = execute!(
&conn, &conn,
$query, $query,
&[&serde_json::to_string(&x).unwrap(), &id.to_string()] &[&serde_json::to_string(&x).unwrap(), &(id as i64)]
); );
if let Err(e) = res { if let Err(e) = res {
@ -316,7 +351,7 @@ macro_rules! auto_method {
let res = execute!( let res = execute!(
&conn, &conn,
$query, $query,
&[&serde_json::to_string(&x).unwrap(), &id.to_string()] &[&serde_json::to_string(&x).unwrap(), &(id as i64)]
); );
if let Err(e) = res { if let Err(e) = res {
@ -336,7 +371,7 @@ macro_rules! auto_method {
Err(e) => return Err(Error::DatabaseConnection(e.to_string())), Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
}; };
let res = execute!(&conn, $query, &[&x, &id.to_string()]); let res = execute!(&conn, $query, &[&x, &(id as i64)]);
if let Err(e) = res { if let Err(e) = res {
return Err(Error::DatabaseError(e.to_string())); return Err(Error::DatabaseError(e.to_string()));
@ -353,7 +388,7 @@ macro_rules! auto_method {
Err(e) => return Err(Error::DatabaseConnection(e.to_string())), Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
}; };
let res = execute!(&conn, $query, &[&x, &id.to_string()]); let res = execute!(&conn, $query, &[&x, &(id as i64)]);
if let Err(e) = res { if let Err(e) = res {
return Err(Error::DatabaseError(e.to_string())); return Err(Error::DatabaseError(e.to_string()));
@ -375,7 +410,7 @@ macro_rules! auto_method {
let res = execute!( let res = execute!(
&conn, &conn,
$query, $query,
&[&serde_json::to_string(&x).unwrap(), &id.to_string()] &[&serde_json::to_string(&x).unwrap(), &(id as i64)]
); );
if let Err(e) = res { if let Err(e) = res {
@ -396,7 +431,7 @@ macro_rules! auto_method {
let res = execute!( let res = execute!(
&conn, &conn,
$query, $query,
&[&serde_json::to_string(&x).unwrap(), &id.to_string()] &[&serde_json::to_string(&x).unwrap(), &(id as i64)]
); );
if let Err(e) = res { if let Err(e) = res {
@ -416,7 +451,7 @@ macro_rules! auto_method {
Err(e) => return Err(Error::DatabaseConnection(e.to_string())), Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
}; };
let res = execute!(&conn, $query, &[&id.to_string()]); let res = execute!(&conn, $query, &[&(id as i64)]);
if let Err(e) = res { if let Err(e) = res {
return Err(Error::DatabaseError(e.to_string())); return Err(Error::DatabaseError(e.to_string()));
@ -435,7 +470,7 @@ macro_rules! auto_method {
Err(e) => return Err(Error::DatabaseConnection(e.to_string())), Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
}; };
let res = execute!(&conn, $query, &[&id.to_string()]); let res = execute!(&conn, $query, &[&(id as i64)]);
if let Err(e) = res { if let Err(e) = res {
return Err(Error::DatabaseError(e.to_string())); return Err(Error::DatabaseError(e.to_string()));
@ -468,7 +503,7 @@ macro_rules! auto_method {
Err(e) => return Err(Error::DatabaseConnection(e.to_string())), Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
}; };
let res = execute!(&conn, $query, &[&id.to_string()]); let res = execute!(&conn, $query, &[&(id as i64)]);
if let Err(e) = res { if let Err(e) = res {
return Err(Error::DatabaseError(e.to_string())); return Err(Error::DatabaseError(e.to_string()));
@ -501,7 +536,7 @@ macro_rules! auto_method {
Err(e) => return Err(Error::DatabaseConnection(e.to_string())), Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
}; };
let res = execute!(&conn, $query, &[&x, &id.to_string()]); let res = execute!(&conn, $query, params![&x, &(id as i64)]);
if let Err(e) = res { if let Err(e) = res {
return Err(Error::DatabaseError(e.to_string())); return Err(Error::DatabaseError(e.to_string()));
@ -525,7 +560,7 @@ macro_rules! auto_method {
let res = execute!( let res = execute!(
&conn, &conn,
$query, $query,
&[&serde_json::to_string(&x).unwrap(), &id.to_string()] params![&serde_json::to_string(&x).unwrap(), &(id as i64)]
); );
if let Err(e) = res { if let Err(e) = res {
@ -562,7 +597,7 @@ macro_rules! auto_method {
let res = execute!( let res = execute!(
&conn, &conn,
$query, $query,
&[&serde_json::to_string(&x).unwrap(), &id.to_string()] params![&serde_json::to_string(&x).unwrap(), &(id as i64)]
); );
if let Err(e) = res { if let Err(e) = res {
@ -584,7 +619,7 @@ macro_rules! auto_method {
Err(e) => return Err(Error::DatabaseConnection(e.to_string())), Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
}; };
let res = execute!(&conn, $query, &[&id.to_string()]); let res = execute!(&conn, $query, &[&(id as i64)]);
if let Err(e) = res { if let Err(e) = res {
return Err(Error::DatabaseError(e.to_string())); return Err(Error::DatabaseError(e.to_string()));
@ -605,7 +640,7 @@ macro_rules! auto_method {
Err(e) => return Err(Error::DatabaseConnection(e.to_string())), Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
}; };
let res = execute!(&conn, $query, &[&id.to_string()]); let res = execute!(&conn, $query, &[&(id as i64)]);
if let Err(e) = res { if let Err(e) = res {
return Err(Error::DatabaseError(e.to_string())); return Err(Error::DatabaseError(e.to_string()));

View file

@ -9,7 +9,7 @@ use crate::model::{
communities::{CommunityReadAccess, CommunityWriteAccess}, communities::{CommunityReadAccess, CommunityWriteAccess},
permissions::FinePermission, permissions::FinePermission,
}; };
use crate::{auto_method, execute, get, query_row, query_rows}; use crate::{auto_method, execute, get, query_row, query_rows, params};
use pathbufd::PathBufD; use pathbufd::PathBufD;
use std::fs::{exists, remove_file}; use std::fs::{exists, remove_file};
@ -96,7 +96,7 @@ impl DataManager {
let res = query_row!( let res = query_row!(
&conn, &conn,
"SELECT * FROM communities WHERE title = $1", "SELECT * FROM communities WHERE title = $1",
&[&id], params![&id],
|x| { Ok(Self::get_community_from_row(x)) } |x| { Ok(Self::get_community_from_row(x)) }
); );
@ -202,18 +202,18 @@ impl DataManager {
let res = execute!( let res = execute!(
&conn, &conn,
"INSERT INTO communities VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)", "INSERT INTO communities VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)",
&[ params![
&data.id.to_string().as_str(), &(data.id as i64),
&data.created.to_string().as_str(), &(data.created as i64),
&data.title.to_lowercase().as_str(), &data.title.to_lowercase(),
&serde_json::to_string(&data.context).unwrap().as_str(), &serde_json::to_string(&data.context).unwrap().as_str(),
&data.owner.to_string().as_str(), &(data.owner as i64),
&serde_json::to_string(&data.read_access).unwrap().as_str(), &serde_json::to_string(&data.read_access).unwrap().as_str(),
&serde_json::to_string(&data.write_access).unwrap().as_str(), &serde_json::to_string(&data.write_access).unwrap().as_str(),
&serde_json::to_string(&data.join_access).unwrap().as_str(), &serde_json::to_string(&data.join_access).unwrap().as_str(),
&0.to_string().as_str(), &(0 as i64),
&0.to_string().as_str(), &(0 as i64),
&0.to_string().as_str() &(1 as i64)
] ]
); );
@ -266,7 +266,7 @@ impl DataManager {
let res = execute!( let res = execute!(
&conn, &conn,
"DELETE FROM communities WHERE id = $1", "DELETE FROM communities WHERE id = $1",
&[&id.to_string()] &[&(id as i64)]
); );
if let Err(e) = res { if let Err(e) = res {
@ -279,7 +279,7 @@ impl DataManager {
let res = execute!( let res = execute!(
&conn, &conn,
"DELETE FROM memberships WHERE community = $1", "DELETE FROM memberships WHERE community = $1",
&[&id.to_string()] &[&(id as i64)]
); );
if let Err(e) = res { if let Err(e) = res {

View file

@ -13,6 +13,7 @@ use bb8_postgres::{
use std::collections::HashMap; use std::collections::HashMap;
use tetratto_l10n::{LangFile, read_langs}; use tetratto_l10n::{LangFile, read_langs};
use tokio_postgres::{Config as PgConfig, NoTls, Row, types::ToSql}; use tokio_postgres::{Config as PgConfig, NoTls, Row, types::ToSql};
use std::str::FromStr;
pub type Result<T> = std::result::Result<T, tokio_postgres::Error>; pub type Result<T> = std::result::Result<T, tokio_postgres::Error>;
pub type Connection<'a> = PooledConnection<'a, PostgresConnectionManager<NoTls>>; pub type Connection<'a> = PooledConnection<'a, PostgresConnectionManager<NoTls>>;
@ -35,13 +36,14 @@ impl DataManager {
/// Create a new [`DataManager`] (and init database). /// Create a new [`DataManager`] (and init database).
pub async fn new(config: Config) -> Result<Self> { pub async fn new(config: Config) -> Result<Self> {
let manager = PostgresConnectionManager::new( let manager = PostgresConnectionManager::new(
{ PgConfig::from_str(&format!(
let mut c = PgConfig::new(); "postgresql://{}:{}@{}/{}?target_session_attrs=read-write",
c.user(&config.database.user); config.database.user,
c.password(&config.database.password); config.database.password,
c.dbname(&config.database.name); config.database.url,
c config.database.name
}, ))
.unwrap(),
NoTls, NoTls,
); );
@ -144,3 +146,13 @@ macro_rules! execute {
crate::database::execute_helper($conn, $sql, &[]).await crate::database::execute_helper($conn, $sql, &[]).await
}; };
} }
#[macro_export]
macro_rules! params {
() => {
&[]
};
($($x:expr),+ $(,)?) => {
&[$(&$x),+]
};
}

View file

@ -1,6 +1,6 @@
CREATE TABLE IF NOT EXISTS audit_log ( CREATE TABLE IF NOT EXISTS audit_log (
id INTEGER NOT NULL PRIMARY KEY, id BIGINT NOT NULL PRIMARY KEY,
created INTEGER NOT NULL, created BIGINT NOT NULL,
owner INTEGER NOT NULL, owner BIGINT NOT NULL,
content TEXT NOT NULL content TEXT NOT NULL
) )

View file

@ -1,15 +1,15 @@
CREATE TABLE IF NOT EXISTS communities ( CREATE TABLE IF NOT EXISTS communities (
id INTEGER NOT NULL PRIMARY KEY, id BIGINT NOT NULL PRIMARY KEY,
created INTEGER NOT NULL, created BIGINT NOT NULL,
title TEXT NOT NULL, title TEXT NOT NULL,
context TEXT NOT NULL, context TEXT NOT NULL,
owner INTEGER NOT NULL, owner BIGINT NOT NULL,
read_access TEXT NOT NULL, read_access TEXT NOT NULL,
write_access TEXT NOT NULL, write_access TEXT NOT NULL,
join_access TEXT NOT NULL, join_access TEXT NOT NULL,
-- likes -- likes
likes INTEGER NOT NULL, likes BIGINT NOT NULL,
dislikes INTEGER NOT NULL, dislikes BIGINT NOT NULL,
-- counts -- counts
member_count INTEGER NOT NULL member_count BIGINT NOT NULL
) )

View file

@ -1,6 +1,6 @@
CREATE TABLE IF NOT EXISTS ipbans ( CREATE TABLE IF NOT EXISTS ipbans (
ip TEXT NOT NULL, ip TEXT NOT NULL,
created INTEGER NOT NULL PRIMARY KEY, created BIGINT NOT NULL PRIMARY KEY,
reason TEXT NOT NULL, reason TEXT NOT NULL,
moderator TEXT NOT NULL moderator TEXT NOT NULL
) )

View file

@ -1,7 +1,7 @@
CREATE TABLE IF NOT EXISTS memberships ( CREATE TABLE IF NOT EXISTS memberships (
id INTEGER NOT NULL PRIMARY KEY, id BIGINT NOT NULL PRIMARY KEY,
created INTEGER NOT NULL, created BIGINT NOT NULL,
owner INTEGER NOT NULL, owner BIGINT NOT NULL,
community INTEGER NOT NULL, community BIGINT NOT NULL,
role INTEGER NOT NULL role BIGINT NOT NULL
) )

View file

@ -1,8 +1,8 @@
CREATE TABLE IF NOT EXISTS notifications ( CREATE TABLE IF NOT EXISTS notifications (
id INTEGER NOT NULL PRIMARY KEY, id BIGINT NOT NULL PRIMARY KEY,
created INTEGER NOT NULL, created BIGINT NOT NULL,
title TEXT NOT NULL, title TEXT NOT NULL,
content TEXT NOT NULL, content TEXT NOT NULL,
owner INTEGER NOT NULL, owner BIGINT NOT NULL,
read INTEGER NOT NULL read BIGINT NOT NULL
) )

View file

@ -1,14 +1,14 @@
CREATE TABLE IF NOT EXISTS posts ( CREATE TABLE IF NOT EXISTS posts (
id INTEGER NOT NULL PRIMARY KEY, id BIGINT NOT NULL PRIMARY KEY,
created INTEGER NOT NULL, created BIGINT NOT NULL,
content TEXT NOT NULL, content TEXT NOT NULL,
owner INTEGER NOT NULL, owner BIGINT NOT NULL,
community INTEGER NOT NULL, community BIGINT NOT NULL,
context TEXT NOT NULL, context TEXT NOT NULL,
replying_to INTEGER, -- the ID of the post this is a comment on... NULL means it isn't a reply replying_to BIGINT, -- the ID of the post this is a comment on... NULL means it isn't a reply
-- likes -- likes
likes INTEGER NOT NULL, likes BIGINT NOT NULL,
dislikes INTEGER NOT NULL, dislikes BIGINT NOT NULL,
-- other counts -- other counts
comment_count INTEGER NOT NULL comment_count BIGINT NOT NULL
) )

View file

@ -1,8 +1,8 @@
CREATE TABLE IF NOT EXISTS reactions ( CREATE TABLE IF NOT EXISTS reactions (
id INTEGER NOT NULL PRIMARY KEY, id BIGINT NOT NULL PRIMARY KEY,
created INTEGER NOT NULL, created BIGINT NOT NULL,
owner INTEGER NOT NULL, owner BIGINT NOT NULL,
asset INTEGER NOT NULL, asset BIGINT NOT NULL,
asset_type TEXT NOT NULL, asset_type TEXT NOT NULL,
is_like INTEGER NOT NULL is_like BIGINT NOT NULL
) )

View file

@ -1,8 +1,8 @@
CREATE TABLE IF NOT EXISTS reports ( CREATE TABLE IF NOT EXISTS reports (
id INTEGER NOT NULL PRIMARY KEY, id BIGINT NOT NULL PRIMARY KEY,
created INTEGER NOT NULL, created BIGINT NOT NULL,
owner INTEGER NOT NULL, owner BIGINT NOT NULL,
content TEXT NOT NULL, content TEXT NOT NULL,
asset INTEGER NOT NULL, asset BIGINT NOT NULL,
asset_type TEXT NOT NULL asset_type TEXT NOT NULL
) )

View file

@ -1,6 +1,6 @@
CREATE TABLE IF NOT EXISTS userblocks ( CREATE TABLE IF NOT EXISTS userblocks (
id INTEGER NOT NULL PRIMARY KEY, id BIGINT NOT NULL PRIMARY KEY,
created INTEGER NOT NULL, created BIGINT NOT NULL,
initiator INTEGER NOT NULL, initiator BIGINT NOT NULL,
receiver INTEGER NOT NULL receiver BIGINT NOT NULL
) )

View file

@ -1,6 +1,6 @@
CREATE TABLE IF NOT EXISTS userfollows ( CREATE TABLE IF NOT EXISTS userfollows (
id INTEGER NOT NULL PRIMARY KEY, id BIGINT NOT NULL PRIMARY KEY,
created INTEGER NOT NULL, created BIGINT NOT NULL,
initiator INTEGER NOT NULL, initiator BIGINT NOT NULL,
receiver INTEGER NOT NULL receiver BIGINT NOT NULL
) )

View file

@ -1,15 +1,15 @@
CREATE TABLE IF NOT EXISTS users ( CREATE TABLE IF NOT EXISTS users (
id INTEGER NOT NULL PRIMARY KEY, id BIGINT NOT NULL PRIMARY KEY,
created INTEGER NOT NULL, created BIGINT NOT NULL,
username TEXT NOT NULL, username TEXT NOT NULL,
password TEXT NOT NULL, password TEXT NOT NULL,
salt TEXT NOT NULL, salt TEXT NOT NULL,
settings TEXT NOT NULL, settings TEXT NOT NULL,
tokens TEXT NOT NULL, tokens TEXT NOT NULL,
permissions INTEGER NOT NULL, permissions BIGINT NOT NULL,
verified INTEGER NOT NULL, verified BIGINT NOT NULL,
notification_count INTEGER NOT NULL, notification_count BIGINT NOT NULL,
follower_count INTEGER NOT NULL, follower_count BIGINT NOT NULL,
following_count INTEGER NOT NULL, following_count BIGINT NOT NULL,
last_seen INTEGER NOT NULL last_seen BIGINT NOT NULL
) )

View file

@ -86,3 +86,13 @@ macro_rules! execute {
$conn.prepare($sql).unwrap().execute(()) $conn.prepare($sql).unwrap().execute(())
}; };
} }
#[macro_export]
macro_rules! params {
() => {
rusqlite::params![]
};
($($params:expr),+ $(,)?) => {
rusqlite::params![$($params),+]
};
}

View file

@ -2,7 +2,7 @@ use super::*;
use crate::cache::Cache; use crate::cache::Cache;
use crate::model::moderation::AuditLogEntry; use crate::model::moderation::AuditLogEntry;
use crate::model::{Error, Result, auth::IpBan, auth::User, permissions::FinePermission}; use crate::model::{Error, Result, auth::IpBan, auth::User, permissions::FinePermission};
use crate::{auto_method, execute, get, query_row, query_rows}; use crate::{auto_method, execute, get, query_row, query_rows, params};
#[cfg(feature = "sqlite")] #[cfg(feature = "sqlite")]
use rusqlite::Row; use rusqlite::Row;
@ -71,11 +71,11 @@ impl DataManager {
let res = execute!( let res = execute!(
&conn, &conn,
"INSERT INTO ipbans VALUES ($1, $2, $3, $4)", "INSERT INTO ipbans VALUES ($1, $2, $3, $4)",
&[ params![
&data.ip.as_str(), &data.ip.as_str(),
&data.created.to_string().as_str(), &(data.created as i64),
&data.reason.as_str(), &data.reason.as_str(),
&data.moderator.to_string().as_str() &(data.moderator as i64)
] ]
); );

View file

@ -9,7 +9,7 @@ use crate::model::{
communities_permissions::CommunityPermission, communities_permissions::CommunityPermission,
permissions::FinePermission, permissions::FinePermission,
}; };
use crate::{auto_method, execute, get, query_row, query_rows}; use crate::{auto_method, execute, get, query_row, query_rows, params};
#[cfg(feature = "sqlite")] #[cfg(feature = "sqlite")]
use rusqlite::Row; use rusqlite::Row;
@ -28,7 +28,7 @@ impl DataManager {
created: get!(x->1(i64)) as usize, created: get!(x->1(i64)) as usize,
owner: get!(x->2(i64)) as usize, owner: get!(x->2(i64)) as usize,
community: get!(x->3(i64)) as usize, community: get!(x->3(i64)) as usize,
role: CommunityPermission::from_bits(get!(x->4(u32))).unwrap(), role: CommunityPermission::from_bits(get!(x->4(i64)) as u32).unwrap(),
} }
} }
@ -78,7 +78,7 @@ impl DataManager {
let res = query_rows!( let res = query_rows!(
&conn, &conn,
// 33 = banned, 65 = pending membership // 33 = banned, 65 = pending membership
"SELECT * FROM memberships WHERE owner = $1 AND role IS NOT 33 AND role IS NOT 65 ORDER BY created DESC", "SELECT * FROM memberships WHERE owner = $1 AND NOT role = 33 AND NOT role = 65 ORDER BY created DESC",
&[&(owner as i64)], &[&(owner as i64)],
|x| { Self::get_membership_from_row(x) } |x| { Self::get_membership_from_row(x) }
); );
@ -142,12 +142,12 @@ impl DataManager {
let res = execute!( let res = execute!(
&conn, &conn,
"INSERT INTO memberships VALUES ($1, $2, $3, $4, $5)", "INSERT INTO memberships VALUES ($1, $2, $3, $4, $5)",
&[ params![
&data.id.to_string().as_str(), &(data.id as i64),
&data.created.to_string().as_str(), &(data.created as i64),
&data.owner.to_string().as_str(), &(data.owner as i64),
&data.community.to_string().as_str(), &(data.community as i64),
&(data.role.bits()).to_string().as_str(), &(data.role.bits() as i64),
] ]
); );
@ -198,7 +198,7 @@ impl DataManager {
let res = execute!( let res = execute!(
&conn, &conn,
"DELETE FROM memberships WHERE id = $1", "DELETE FROM memberships WHERE id = $1",
&[&id.to_string()] &[&(id as i64)]
); );
if let Err(e) = res { if let Err(e) = res {
@ -226,7 +226,7 @@ impl DataManager {
let res = execute!( let res = execute!(
&conn, &conn,
"UPDATE memberships SET role = $1 WHERE id = $2", "UPDATE memberships SET role = $1 WHERE id = $2",
&[&(new_role.bits()).to_string(), &id.to_string()] params![&(new_role.bits() as i64), &(id as i64)]
); );
if let Err(e) = res { if let Err(e) = res {

View file

@ -1,7 +1,7 @@
use super::*; use super::*;
use crate::cache::Cache; use crate::cache::Cache;
use crate::model::{Error, Result, auth::Notification, auth::User, permissions::FinePermission}; use crate::model::{Error, Result, auth::Notification, auth::User, permissions::FinePermission};
use crate::{auto_method, execute, get, query_row, query_rows}; use crate::{auto_method, execute, get, query_row, query_rows, params};
#[cfg(feature = "sqlite")] #[cfg(feature = "sqlite")]
use rusqlite::Row; use rusqlite::Row;
@ -21,7 +21,11 @@ impl DataManager {
title: get!(x->2(String)), title: get!(x->2(String)),
content: get!(x->3(String)), content: get!(x->3(String)),
owner: get!(x->4(i64)) as usize, owner: get!(x->4(i64)) as usize,
read: if get!(x->5(i8)) == 1 { true } else { false }, read: if get!(x->5(i64)) as i8 == 1 {
true
} else {
false
},
} }
} }
@ -61,13 +65,13 @@ impl DataManager {
let res = execute!( let res = execute!(
&conn, &conn,
"INSERT INTO notifications VALUES ($1, $2, $3, $4, $5, $6)", "INSERT INTO notifications VALUES ($1, $2, $3, $4, $5, $6)",
&[ params![
&data.id.to_string().as_str(), &(data.id as i64),
&data.created.to_string().as_str(), &(data.created as i64),
&data.title.to_string().as_str(), &data.title,
&data.content.to_string().as_str(), &data.content,
&data.owner.to_string().as_str(), &(data.owner as i64),
&(if data.read { 1 } else { 0 }).to_string().as_str() &(if data.read { 1 } else { 0 } as i64)
] ]
); );
@ -99,7 +103,7 @@ impl DataManager {
let res = execute!( let res = execute!(
&conn, &conn,
"DELETE FROM notifications WHERE id = $1", "DELETE FROM notifications WHERE id = $1",
&[&id.to_string()] &[&(id as i64)]
); );
if let Err(e) = res { if let Err(e) = res {
@ -158,7 +162,7 @@ impl DataManager {
let res = execute!( let res = execute!(
&conn, &conn,
"UPDATE notifications SET read = $1 WHERE id = $2", "UPDATE notifications SET read = $1 WHERE id = $2",
&[&(if new_read { 1 } else { 0 }).to_string(), &id.to_string()] params![&(if new_read { 1 } else { 0 } as i64), &(id as i64)]
); );
if let Err(e) = res { if let Err(e) = res {

View file

@ -11,7 +11,7 @@ use crate::model::{
communities::{Community, CommunityWriteAccess, Post, PostContext}, communities::{Community, CommunityWriteAccess, Post, PostContext},
permissions::FinePermission, permissions::FinePermission,
}; };
use crate::{auto_method, execute, get, query_row, query_rows}; use crate::{auto_method, execute, get, query_row, query_rows, params};
#[cfg(feature = "sqlite")] #[cfg(feature = "sqlite")]
use rusqlite::Row; use rusqlite::Row;
@ -174,7 +174,7 @@ impl DataManager {
let res = query_rows!( let res = query_rows!(
&conn, &conn,
"SELECT * FROM posts WHERE community = $1 AND replying_to IS NULL ORDER BY created DESC LIMIT $2 OFFSET $3", "SELECT * FROM posts WHERE community = $1 AND replying_to = 0 AND NOT context LIKE '%\"is_pinned\":true%' ORDER BY created DESC LIMIT $2 OFFSET $3",
&[&(id as i64), &(batch as i64), &((page * batch) as i64)], &[&(id as i64), &(batch as i64), &((page * batch) as i64)],
|x| { Self::get_post_from_row(x) } |x| { Self::get_post_from_row(x) }
); );
@ -223,7 +223,7 @@ impl DataManager {
let res = query_rows!( let res = query_rows!(
&conn, &conn,
"SELECT * FROM posts ORDER BY likes DESC, created ASC LIMIT $2 OFFSET $3", "SELECT * FROM posts ORDER BY likes DESC, created ASC LIMIT $1 OFFSET $2",
&[&(batch as i64), &((page * batch) as i64)], &[&(batch as i64), &((page * batch) as i64)],
|x| { Self::get_post_from_row(x) } |x| { Self::get_post_from_row(x) }
); );
@ -395,21 +395,21 @@ impl DataManager {
let res = execute!( let res = execute!(
&conn, &conn,
"INSERT INTO posts VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)", "INSERT INTO posts VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)",
&[ params![
&Some(data.id.to_string().as_str()), &(data.id as i64),
&Some(data.created.to_string().as_str()), &(data.created as i64),
&Some(&data.content), &data.content,
&Some(data.owner.to_string().as_str()), &(data.owner as i64),
&Some(data.community.to_string().as_str()), &(data.community as i64),
&Some(&serde_json::to_string(&data.context).unwrap()), &serde_json::to_string(&data.context).unwrap(),
&if replying_to_id != "0" { &if replying_to_id != "0" {
Some(replying_to_id.as_str()) replying_to_id.parse::<i64>().unwrap()
} else { } else {
None 0 as i64
}, },
&Some(0.to_string().as_str()), &(0 as i64),
&Some(0.to_string().as_str()), &(0 as i64),
&Some(0.to_string().as_str()) &(0 as i64)
] ]
); );
@ -472,7 +472,7 @@ impl DataManager {
Err(e) => return Err(Error::DatabaseConnection(e.to_string())), Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
}; };
let res = execute!(&conn, "DELETE FROM posts WHERE id = $1", &[&id.to_string()]); let res = execute!(&conn, "DELETE FROM posts WHERE id = $1", &[&(id as i64)]);
if let Err(e) = res { if let Err(e) = res {
return Err(Error::DatabaseError(e.to_string())); return Err(Error::DatabaseError(e.to_string()));
@ -538,7 +538,7 @@ impl DataManager {
let res = execute!( let res = execute!(
&conn, &conn,
"UPDATE posts SET context = $1 WHERE id = $2", "UPDATE posts SET context = $1 WHERE id = $2",
&[&serde_json::to_string(&x).unwrap(), &id.to_string()] params![&serde_json::to_string(&x).unwrap(), &(id as i64)]
); );
if let Err(e) = res { if let Err(e) = res {

View file

@ -6,7 +6,7 @@ use crate::model::{
permissions::FinePermission, permissions::FinePermission,
reactions::{AssetType, Reaction}, reactions::{AssetType, Reaction},
}; };
use crate::{auto_method, execute, get, query_row}; use crate::{auto_method, execute, get, query_row, params};
#[cfg(feature = "sqlite")] #[cfg(feature = "sqlite")]
use rusqlite::Row; use rusqlite::Row;
@ -26,7 +26,11 @@ impl DataManager {
owner: get!(x->2(i64)) as usize, owner: get!(x->2(i64)) as usize,
asset: get!(x->3(i64)) as usize, asset: get!(x->3(i64)) as usize,
asset_type: serde_json::from_str(&get!(x->4(String))).unwrap(), asset_type: serde_json::from_str(&get!(x->4(String))).unwrap(),
is_like: if get!(x->5(i8)) == 1 { true } else { false }, is_like: if get!(x->5(i64)) as i8 == 1 {
true
} else {
false
},
} }
} }
@ -70,13 +74,13 @@ impl DataManager {
let res = execute!( let res = execute!(
&conn, &conn,
"INSERT INTO reactions VALUES ($1, $2, $3, $4, $5, $6)", "INSERT INTO reactions VALUES ($1, $2, $3, $4, $5, $6)",
&[ params![
&data.id.to_string().as_str(), &(data.id as i64),
&data.created.to_string().as_str(), &(data.created as i64),
&data.owner.to_string().as_str(), &(data.owner as i64),
&data.asset.to_string().as_str(), &(data.asset as i64),
&serde_json::to_string(&data.asset_type).unwrap().as_str(), &serde_json::to_string(&data.asset_type).unwrap().as_str(),
&(if data.is_like { 1 } else { 0 }).to_string().as_str() &(if data.is_like { 1 } else { 0 } as i64)
] ]
); );
@ -170,7 +174,7 @@ impl DataManager {
let res = execute!( let res = execute!(
&conn, &conn,
"DELETE FROM reactions WHERE id = $1", "DELETE FROM reactions WHERE id = $1",
&[&id.to_string()] &[&(id as i64)]
); );
if let Err(e) = res { if let Err(e) = res {

View file

@ -2,7 +2,7 @@ use super::*;
use crate::cache::Cache; use crate::cache::Cache;
use crate::model::moderation::AuditLogEntry; use crate::model::moderation::AuditLogEntry;
use crate::model::{Error, Result, auth::User, moderation::Report, permissions::FinePermission}; use crate::model::{Error, Result, auth::User, moderation::Report, permissions::FinePermission};
use crate::{auto_method, execute, get, query_row, query_rows}; use crate::{auto_method, execute, get, query_row, query_rows, params};
#[cfg(feature = "sqlite")] #[cfg(feature = "sqlite")]
use rusqlite::Row; use rusqlite::Row;
@ -26,7 +26,7 @@ impl DataManager {
} }
} }
auto_method!(get_report_by_id(usize)@get_report_from_row -> "SELECT * FROM reports WHERE id = $1" --name="report" --returns=Report --cache-key-tmpl="atto.reports:{}"); auto_method!(get_report_by_id(usize as i64)@get_report_from_row -> "SELECT * FROM reports WHERE id = $1" --name="report" --returns=Report --cache-key-tmpl="atto.reports:{}");
/// Get all reports (paginated). /// Get all reports (paginated).
/// ///
@ -66,12 +66,12 @@ impl DataManager {
let res = execute!( let res = execute!(
&conn, &conn,
"INSERT INTO reports VALUES ($1, $2, $3, $4, $5, $6)", "INSERT INTO reports VALUES ($1, $2, $3, $4, $5, $6)",
&[ params![
&data.id.to_string().as_str(), &(data.id as i64),
&data.created.to_string().as_str(), &(data.created as i64),
&data.owner.to_string().as_str(), &(data.owner as i64),
&data.content.as_str(), &data.content.as_str(),
&data.asset.to_string().as_str(), &(data.asset as i64),
&serde_json::to_string(&data.asset_type).unwrap().as_str(), &serde_json::to_string(&data.asset_type).unwrap().as_str(),
] ]
); );
@ -94,11 +94,7 @@ impl DataManager {
Err(e) => return Err(Error::DatabaseConnection(e.to_string())), Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
}; };
let res = execute!( let res = execute!(&conn, "DELETE FROM reports WHERE id = $1", &[&(id as i64)]);
&conn,
"DELETE FROM reports WHERE id = $1",
&[&id.to_string()]
);
if let Err(e) = res { if let Err(e) = res {
return Err(Error::DatabaseError(e.to_string())); return Err(Error::DatabaseError(e.to_string()));

View file

@ -1,7 +1,7 @@
use super::*; use super::*;
use crate::cache::Cache; use crate::cache::Cache;
use crate::model::{Error, Result, auth::User, auth::UserBlock, permissions::FinePermission}; use crate::model::{Error, Result, auth::User, auth::UserBlock, permissions::FinePermission};
use crate::{auto_method, execute, get, query_row}; use crate::{auto_method, execute, get, query_row, params};
#[cfg(feature = "sqlite")] #[cfg(feature = "sqlite")]
use rusqlite::Row; use rusqlite::Row;
@ -88,11 +88,11 @@ impl DataManager {
let res = execute!( let res = execute!(
&conn, &conn,
"INSERT INTO userblocks VALUES ($1, $2, $3, $4)", "INSERT INTO userblocks VALUES ($1, $2, $3, $4)",
&[ params![
&data.id.to_string().as_str(), &(data.id as i64),
&data.created.to_string().as_str(), &(data.created as i64),
&data.initiator.to_string().as_str(), &(data.initiator as i64),
&data.receiver.to_string().as_str() &(data.receiver as i64)
] ]
); );
@ -122,7 +122,7 @@ impl DataManager {
let res = execute!( let res = execute!(
&conn, &conn,
"DELETE FROM userblocks WHERE id = $1", "DELETE FROM userblocks WHERE id = $1",
&[&id.to_string()] &[&(id as i64)]
); );
if let Err(e) = res { if let Err(e) = res {

View file

@ -1,7 +1,7 @@
use super::*; use super::*;
use crate::cache::Cache; use crate::cache::Cache;
use crate::model::{Error, Result, auth::User, auth::UserFollow, permissions::FinePermission}; use crate::model::{Error, Result, auth::User, auth::UserFollow, permissions::FinePermission};
use crate::{auto_method, execute, get, query_row, query_rows}; use crate::{auto_method, execute, get, query_row, query_rows, params};
#[cfg(feature = "sqlite")] #[cfg(feature = "sqlite")]
use rusqlite::Row; use rusqlite::Row;
@ -180,11 +180,11 @@ impl DataManager {
let res = execute!( let res = execute!(
&conn, &conn,
"INSERT INTO userfollows VALUES ($1, $2, $3, $4)", "INSERT INTO userfollows VALUES ($1, $2, $3, $4)",
&[ params![
&data.id.to_string().as_str(), &(data.id as i64),
&data.created.to_string().as_str(), &(data.created as i64),
&data.initiator.to_string().as_str(), &(data.initiator as i64),
&data.receiver.to_string().as_str() &(data.receiver as i64)
] ]
); );
@ -220,7 +220,7 @@ impl DataManager {
let res = execute!( let res = execute!(
&conn, &conn,
"DELETE FROM userfollows WHERE id = $1", "DELETE FROM userfollows WHERE id = $1",
&[&id.to_string()] &[&(id as i64)]
); );
if let Err(e) = res { if let Err(e) = res {

View file

@ -1,12 +1,40 @@
name = "Tetratto" name = "Tetratto"
description = "🐇 tetratto!"
color = "#c9b1bc"
port = 4118 port = 4118
banned_hosts = []
no_track = []
banned_usernames = [
"admin",
"owner",
"moderator",
"api",
"communities",
"notifs",
"notification",
"post",
"void",
]
[security] [security]
registration_enabled = true registration_enabled = true
real_ip_header = "CF-Connecting-IP"
[dirs] [dirs]
templates = "html" templates = "html"
assets = "public" assets = "public"
media = "media"
icons = "icons"
[database]
name = "tetratto"
url = "localhost:5432"
user = "hkau"
password = "postgres"
[policies]
terms_of_service = "/public/tos.html"
privacy = "/public/privacy.html"
[turnstile] [turnstile]
site_key = "1x00000000000000000000AA" site_key = "1x00000000000000000000AA"