autter_core/database/
ip_bans.rs1use crate::{
2 DataManager,
3 model::{AuditLogEntry, Error, IpBan, Result, User, UserPermission},
4};
5use oiseau::cache::Cache;
6use oiseau::{PostgresRow, execute, get, params, query_row, query_rows};
7use tetratto_core2::{
8 auto_method,
9 model::{addr::RemoteAddr, id::Id},
10};
11
12impl DataManager {
13 pub(crate) fn get_ipban_from_row(x: &PostgresRow) -> IpBan {
15 IpBan {
16 ip: get!(x->0(String)),
17 created: get!(x->1(i64)) as u128,
18 reason: get!(x->2(String)),
19 moderator: Id::Legacy(get!(x->3(i64)) as usize),
20 }
21 }
22
23 auto_method!(get_ipban_by_ip(&str)@get_ipban_from_row -> "SELECT * FROM a_ip_bans WHERE ip = $1" --name="ip ban" --returns=IpBan --cache-key-tmpl="srmp.ipban:{}");
24
25 pub async fn get_ipban_by_addr(&self, addr: &RemoteAddr) -> Result<IpBan> {
30 let conn = match self.0.connect().await {
31 Ok(c) => c,
32 Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
33 };
34
35 let res = query_row!(
36 &conn,
37 "SELECT * FROM a_ip_bans WHERE ip = $1",
38 &[&addr.prefix(None)],
39 |x| { Ok(Self::get_ipban_from_row(x)) }
40 );
41
42 if res.is_err() {
43 return Err(Error::GeneralNotFound("ip ban".to_string()));
44 }
45
46 Ok(res.unwrap())
47 }
48
49 pub async fn get_ip_bans(&self, batch: usize, page: usize) -> Result<Vec<IpBan>> {
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_rows!(
61 &conn,
62 "SELECT * FROM a_ip_bans ORDER BY created DESC LIMIT $1 OFFSET $2",
63 &[&(batch as i64), &((page * batch) as i64)],
64 |x| { Self::get_ipban_from_row(x) }
65 );
66
67 if res.is_err() {
68 return Err(Error::GeneralNotFound("ip ban".to_string()));
69 }
70
71 Ok(res.unwrap())
72 }
73
74 pub async fn create_ipban(&self, data: IpBan) -> Result<()> {
79 let user = self.get_user_by_id(&data.moderator).await?;
80
81 if !user.permissions.contains(&UserPermission::ManageBans) {
83 return Err(Error::NotAllowed);
84 }
85
86 let conn = match self.0.connect().await {
87 Ok(c) => c,
88 Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
89 };
90
91 let res = execute!(
92 &conn,
93 "INSERT INTO a_ip_bans VALUES ($1, $2, $3, $4)",
94 params![
95 &data.ip.as_str(),
96 &(data.created as i64),
97 &data.reason.as_str(),
98 &(data.moderator.as_usize() as i64)
99 ]
100 );
101
102 if let Err(e) = res {
103 return Err(Error::DatabaseError(e.to_string()));
104 }
105
106 self.create_audit_log_entry(AuditLogEntry::new(
108 user.id,
109 format!("invoked `create_ipban` with x value `{}`", data.ip),
110 ))
111 .await?;
112
113 Ok(())
115 }
116
117 pub async fn delete_ipban(&self, ip: &str, user: User) -> Result<()> {
118 if !user.permissions.contains(&UserPermission::ManageBans) {
120 return Err(Error::NotAllowed);
121 }
122
123 let conn = match self.0.connect().await {
124 Ok(c) => c,
125 Err(e) => return Err(Error::DatabaseConnection(e.to_string())),
126 };
127
128 let res = execute!(&conn, "DELETE FROM a_ip_bans WHERE ip = $1", &[&ip]);
129
130 if let Err(e) = res {
131 return Err(Error::DatabaseError(e.to_string()));
132 }
133
134 self.0.1.remove(format!("srmp.ipban:{}", ip)).await;
135
136 self.create_audit_log_entry(AuditLogEntry::new(
138 user.id,
139 format!("invoked `delete_ipban` with x value `{ip}`"),
140 ))
141 .await?;
142
143 Ok(())
145 }
146}