tetratto_core/database/
ipblocks.rs1use oiseau::cache::Cache;
2use crate::model::addr::RemoteAddr;
3use crate::model::{Error, Result, auth::User, auth::IpBlock, permissions::FinePermission};
4use crate::{auto_method, DataManager};
5use oiseau::{query_rows, PostgresRow, execute, get, query_row, params};
6
7impl DataManager {
8 pub(crate) fn get_ipblock_from_row(x: &PostgresRow) -> IpBlock {
10 IpBlock {
11 id: get!(x->0(i64)) as usize,
12 created: get!(x->1(i64)) as usize,
13 initiator: get!(x->2(i64)) as usize,
14 receiver: get!(x->3(String)),
15 }
16 }
17
18 auto_method!(get_ipblock_by_id()@get_ipblock_from_row -> "SELECT * FROM ipblocks WHERE id = $1" --name="ip block" --returns=IpBlock --cache-key-tmpl="atto.ipblock:{}");
19
20 pub async fn get_ipblock_by_initiator_receiver(
22 &self,
23 initiator: usize,
24 receiver: &RemoteAddr,
25 ) -> Result<IpBlock> {
26 let conn = match self.0.connect().await {
27 Ok(c) => c,
28 Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
29 };
30
31 let res = query_row!(
32 &conn,
33 "SELECT * FROM ipblocks WHERE initiator = $1 AND receiver LIKE $2",
34 params![&(initiator as i64), &format!("{}%", receiver.prefix(None))],
35 |x| { Ok(Self::get_ipblock_from_row(x)) }
36 );
37
38 if res.is_err() {
39 return Err(Error::GeneralNotFound("ip block".to_string()));
40 }
41
42 Ok(res.unwrap())
43 }
44
45 pub async fn get_ipblock_by_receiver_initiator(
47 &self,
48 receiver: &str,
49 initiator: usize,
50 ) -> Result<IpBlock> {
51 let conn = match self.0.connect().await {
52 Ok(c) => c,
53 Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
54 };
55
56 let res = query_row!(
57 &conn,
58 "SELECT * FROM ipblocks WHERE receiver = $1 AND initiator = $2",
59 params![&receiver, &(initiator as i64)],
60 |x| { Ok(Self::get_ipblock_from_row(x)) }
61 );
62
63 if res.is_err() {
64 return Err(Error::GeneralNotFound("ip block".to_string()));
65 }
66
67 Ok(res.unwrap())
68 }
69
70 pub async fn get_ipblocks_by_initiator(&self, initiator: usize) -> Result<Vec<IpBlock>> {
72 let conn = match self.0.connect().await {
73 Ok(c) => c,
74 Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
75 };
76
77 let res = query_rows!(
78 &conn,
79 "SELECT * FROM ipblocks WHERE initiator = $1",
80 params![&(initiator as i64)],
81 |x| { Self::get_ipblock_from_row(x) }
82 );
83
84 if res.is_err() {
85 return Err(Error::GeneralNotFound("ip block".to_string()));
86 }
87
88 Ok(res.unwrap())
89 }
90
91 pub async fn create_ipblock(&self, data: IpBlock) -> Result<()> {
96 let conn = match self.0.connect().await {
97 Ok(c) => c,
98 Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
99 };
100
101 let res = execute!(
102 &conn,
103 "INSERT INTO ipblocks VALUES ($1, $2, $3, $4)",
104 params![
105 &(data.id as i64),
106 &(data.created as i64),
107 &(data.initiator as i64),
108 &data.receiver
109 ]
110 );
111
112 if let Err(e) = res {
113 return Err(Error::DatabaseError(e.to_string()));
114 }
115
116 Ok(())
118 }
119
120 pub async fn delete_ipblock(&self, id: usize, user: User) -> Result<()> {
121 let block = self.get_ipblock_by_id(id).await?;
122
123 if user.id != block.initiator {
124 if !user.permissions.check(FinePermission::MANAGE_FOLLOWS) {
126 return Err(Error::NotAllowed);
127 }
128 }
129
130 let conn = match self.0.connect().await {
131 Ok(c) => c,
132 Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
133 };
134
135 let res = execute!(&conn, "DELETE FROM ipblocks WHERE id = $1", &[&(id as i64)]);
136
137 if let Err(e) = res {
138 return Err(Error::DatabaseError(e.to_string()));
139 }
140
141 self.0.1.remove(format!("atto.ipblock:{}", id)).await;
142
143 Ok(())
145 }
146}