Skip to main content

dinio_sdk/api/
geo_bans.rs

1//! `/api/v1/geo-bans` (`../core/src/api/geo_bans.ts`). Bans are read nested in their record
2//! group (`Records::get(.., with_geo_bans = true)`); there is no list route.
3
4use reqwest::Method;
5use serde_json::json;
6use uuid::Uuid;
7
8use crate::client::Client;
9use crate::error::Result;
10use crate::models::GeoBan;
11use crate::ops::GeoArea;
12
13/// Geo ban routes, from [`Client::geo_bans`].
14///
15/// A ban stops Relay from answering with one record value to clients in an area. Access
16/// follows the value's zone. To work by area names instead of uuids, see
17/// [`ops::add_geo_bans`](crate::ops::add_geo_bans) and
18/// [`ops::select_geo_bans`](crate::ops::select_geo_bans).
19pub struct GeoBans<'a> {
20    client: &'a Client,
21}
22
23impl<'a> GeoBans<'a> {
24    pub(crate) fn new(client: &'a Client) -> Self {
25        Self { client }
26    }
27
28    /// Bans `area` for the record value `record_id`. Core does not refuse a duplicate;
29    /// [`ops::add_geo_bans`](crate::ops::add_geo_bans) skips areas already banned.
30    ///
31    /// `POST /api/v1/geo-bans`
32    ///
33    /// # Errors
34    ///
35    /// [`ErrorCode::NotFound`](crate::ErrorCode::NotFound) if there is no such value.
36    pub async fn create(&self, record_id: Uuid, area: GeoArea) -> Result<GeoBan> {
37        let request = self
38            .client
39            .request(Method::POST, &["geo-bans"])?
40            .json(&json!({
41                "record_id": record_id,
42                "level": area.level.as_wire(),
43                "code": area.code,
44            }));
45        Ok(self.client.send(request).await?.0)
46    }
47
48    /// Moves a ban to another area.
49    ///
50    /// `PATCH /api/v1/geo-bans/:uuid`
51    ///
52    /// # Errors
53    ///
54    /// [`ErrorCode::NotFound`](crate::ErrorCode::NotFound) if there is no such ban.
55    pub async fn update(&self, uuid: Uuid, area: GeoArea) -> Result<GeoBan> {
56        let request = self
57            .client
58            .request(Method::PATCH, &["geo-bans", &uuid.to_string()])?
59            .json(&json!({ "level": area.level.as_wire(), "code": area.code }));
60        Ok(self.client.send(request).await?.0)
61    }
62
63    /// Removes a ban. `record_id`, when given, must be the ban's value (Core checks it), a
64    /// guard against removing a ban of the wrong value.
65    ///
66    /// `DELETE /api/v1/geo-bans/:uuid[?record_id=...]`
67    ///
68    /// # Errors
69    ///
70    /// [`ErrorCode::NotFound`](crate::ErrorCode::NotFound) if there is no such ban, or it
71    /// belongs to another value than `record_id`.
72    pub async fn delete(&self, uuid: Uuid, record_id: Option<Uuid>) -> Result<()> {
73        let mut request = self
74            .client
75            .request(Method::DELETE, &["geo-bans", &uuid.to_string()])?;
76        if let Some(record_id) = record_id {
77            request = request.query(&[("record_id", record_id.to_string())]);
78        }
79        self.client.send_empty(request).await
80    }
81}