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