ccash_rs/methods/
admin.rs

1//! This module contains all the admin functions that can be mapped to an
2//! endpoint provided by the [`CCash`](https://github.com/EntireTwix/CCash) API.
3//! Non-admin functions can be found within [`methods`].
4//!
5//! [`methods`]: crate::methods
6
7use crate::{request::request, CCashError, CCashResponse, CCashSession, CCashUser};
8use reqwest::Method;
9use velcro::hash_map;
10
11/// Returns a boolean whether or not the [`user`](CCashUser) is an admin
12/// account.
13///
14/// # Errors
15///
16/// Will return a `CCashError` if the request fails or if the `CCash` instance
17/// returns an error code other than 401, as long as the
18/// `interpret_endpoint_errors_as_false` feature is disabled.
19pub async fn verify_account(
20    session: &CCashSession,
21    user: &CCashUser,
22) -> Result<bool, CCashError> {
23    let url = format!("{}/admin/verify_account", &session.session_url);
24
25    let r = request::<()>(Method::POST, session, &url, Some(user), None).await?;
26    match r {
27        CCashResponse::Success { .. } => Ok(true),
28        #[cfg(feature = "interpret_endpoint_errors_as_false")]
29        CCashResponse::Error { .. } => Ok(false),
30        #[cfg(not(feature = "interpret_endpoint_errors_as_false"))]
31        CCashResponse::Error { code: 401, .. } => Ok(false),
32        #[cfg(not(feature = "interpret_endpoint_errors_as_false"))]
33        CCashResponse::Error { .. } => Err(r.into()),
34    }
35}
36
37/// Changes the password for the [`user`](CCashUser). This function modifies
38/// `user` to use the `new_password` instead of the previous password in the
39/// case of a successful password change. This function requires
40/// [`admin_user`](CCashUser) to be equal to the admin user of the `CCash`
41/// instance.
42///
43/// # Errors
44///
45/// Will return a `CCashError` if the request fails or if the `CCash` instance
46/// returns an error code as long as the `interpret_endpoint_errors_as_false`
47/// feature is disabled.
48pub async fn change_password(
49    session: &CCashSession,
50    admin_user: &CCashUser,
51    user: &mut CCashUser,
52    new_password: &str,
53) -> Result<bool, CCashError> {
54    let url = format!("{}/admin/user/change_password", &session.session_url);
55
56    let new_user = CCashUser {
57        username: user.username.clone(),
58        password: new_password.into(),
59    };
60
61    let r = request(
62        Method::PATCH,
63        session,
64        &url,
65        Some(admin_user),
66        Some(&new_user),
67    )
68    .await?;
69
70    match r {
71        CCashResponse::Success { .. } => {
72            *user = new_user;
73            Ok(true)
74        },
75        #[cfg(feature = "interpret_endpoint_errors_as_false")]
76        CCashResponse::Error { .. } => Ok(false),
77        #[cfg(not(feature = "interpret_endpoint_errors_as_false"))]
78        CCashResponse::Error { .. } => Err(r.into()),
79    }
80}
81
82/// Sets the balance of a user with the given `username` to the amount described
83/// by `new_balance`. This function requires [`admin_user`](CCashUser) to be the
84/// admin account for the `CCash` instance.
85///
86/// # Errors
87///
88/// Will return a `CCashError` if the request fails or if the `CCash` instance
89/// returns an error code.
90pub async fn set_balance(
91    session: &CCashSession,
92    admin_user: &CCashUser,
93    username: &str,
94    new_balance: u32,
95) -> Result<(), CCashError> {
96    #[derive(serde::Serialize)]
97    struct SetBalanceData {
98        name: String,
99        amount: u32,
100    }
101
102    let url = format!("{}/admin/set_balance", &session.session_url);
103
104    let body = SetBalanceData {
105        name: username.into(),
106        amount: new_balance,
107    };
108
109    let r = request(Method::PATCH, session, &url, Some(admin_user), Some(&body)).await?;
110    match r {
111        CCashResponse::Success { .. } => Ok(()),
112        CCashResponse::Error { .. } => Err(r.into()),
113    }
114}
115
116/// Impacts the balance of user with the given `username` by the amount
117/// described by `amount`. This function requires [`admin_user`](CCashUser) to
118/// be the admin account for the `CCash` instance.
119///
120/// # Errors
121///
122/// Will return a `CCashError` if the request fails or if the `CCash` instance
123/// returns an error code.
124pub async fn impact_balance(
125    session: &CCashSession,
126    admin_user: &CCashUser,
127    username: &str,
128    amount: i64,
129) -> Result<(), CCashError> {
130    #[derive(serde::Serialize)]
131    struct ImpactBalanceData {
132        name: String,
133        amount: i64,
134    }
135
136    let url = format!("{}/admin/impact_balance", &session.session_url);
137
138    let body = ImpactBalanceData {
139        name: username.into(),
140        amount,
141    };
142
143    let r = request(Method::POST, session, &url, Some(admin_user), Some(&body)).await?;
144    match r {
145        CCashResponse::Success { .. } => Ok(()),
146        CCashResponse::Error { .. } => Err(r.into()),
147    }
148}
149
150/// Adds a [`user`](CCashUser) to the `CCash` session described by
151/// [`session`](CCashSession) with the balance determined by `amount`. This
152/// function requires that [`admin_user`](CCashUser) to be the admin account.
153///
154/// # Errors
155///
156/// Will return `CCashError` if the request fails or if the `CCash` instance
157/// returns an error code other than a 409 as long as the
158/// `interpret_endpoint_errors_as_false` feature is disabled.
159pub async fn add_user(
160    session: &CCashSession,
161    admin_user: &CCashUser,
162    new_user: &CCashUser,
163    amount: u32,
164) -> Result<bool, CCashError> {
165    #[derive(serde::Serialize)]
166    struct AddUserData {
167        #[serde(flatten)]
168        user: CCashUser,
169        amount: u32,
170    }
171
172    let url = format!("{}/admin/user/register", &session.session_url);
173
174    let body = AddUserData {
175        user: new_user.clone(),
176        amount,
177    };
178
179    let r = request(Method::POST, session, &url, Some(admin_user), Some(&body)).await?;
180    match r {
181        CCashResponse::Success { .. } => Ok(true),
182        #[cfg(feature = "interpret_endpoint_errors_as_false")]
183        CCashResponse::Error { .. } => Ok(false),
184        #[cfg(not(feature = "interpret_endpoint_errors_as_false"))]
185        CCashResponse::Error { code: 409, .. } => Ok(false),
186        #[cfg(not(feature = "interpret_endpoint_errors_as_false"))]
187        CCashResponse::Error { .. } => Err(r.into()),
188    }
189}
190
191/// Removes a user associated with the `username` on the `CCash` instance
192/// described by [`session`](CCashSession). This function requires that
193/// [`admin_user`](CCashUser) to be the admin account for the `CCash` instance.
194///
195/// # Errors
196///
197/// Will return `CCashError` if request fails or if the `CCash` instance returns
198/// an error code.
199pub async fn delete_user(
200    session: &CCashSession,
201    admin_user: &CCashUser,
202    username: &str,
203) -> Result<(), CCashError> {
204    let url = format!("{}/admin/user/delete", &session.session_url);
205    let body = hash_map! { "name": username };
206
207    let r = request(Method::DELETE, session, &url, Some(admin_user), Some(&body)).await?;
208    match r {
209        CCashResponse::Success { .. } => Ok(()),
210        CCashResponse::Error { .. } => Err(r.into()),
211    }
212}
213
214/// Prunes users with less than `amount` in balance or users with transactions
215/// older than `time` and less than `amount` in balance. This function requires
216/// that [`admin_user`](CCashUser) be the admin user for the `CCash` instance.
217///
218/// # Errors
219///
220/// Will return `CCashError` if the request fails (could be down to
221/// wrong/incorrect admin credientials) or if the `CCash` instance refuses to
222/// prune it's users for another reason.
223pub async fn prune_users(
224    session: &CCashSession,
225    admin_user: &CCashUser,
226    amount: u32,
227    time: Option<i64>,
228) -> Result<u64, CCashError> {
229    #[derive(serde::Serialize)]
230    struct PruneUsersData {
231        amount: u32,
232        time: Option<i64>,
233    }
234
235    let url = format!("{}/admin/prune_users", &session.session_url);
236
237    let body = PruneUsersData { amount, time };
238
239    let r = request(Method::POST, session, &url, Some(admin_user), Some(&body)).await?;
240    match r {
241        CCashResponse::Success { .. } =>
242            if let Ok(amount) = r.convert_message::<u64>() {
243                Ok(amount)
244            } else {
245                Err(CCashError::Error(
246                    "Could not parse amount of users pruned into a valid u64".into(),
247                ))
248            },
249        CCashResponse::Error { .. } => Err(r.into()),
250    }
251}
252
253/// Saves and closes the `CCash` instance. This updates
254/// [`session`](CCashSession) to reflect that the connection to the `CCash`
255/// instance has closed. This function requires that [`admin_user`](CCashUser)
256/// to be the admin user for the `CCash` instance.
257///
258/// # Errors
259///
260/// Will return `CCashError` if the request fails (could be down to
261/// wrong/incorrect admin credientials) or if the `CCash` instance refuses to
262/// close for another reason.
263pub async fn close(
264    session: &mut CCashSession,
265    admin_user: &CCashUser,
266) -> Result<(), CCashError> {
267    let url = format!("{}/admin/shutdown", &session.session_url);
268
269    let r = request::<()>(Method::POST, session, &url, Some(admin_user), None).await?;
270    match r {
271        CCashResponse::Success { .. } => {
272            session.is_connected = false;
273            session.client = None;
274            session.properties = None;
275
276            Ok(())
277        },
278        CCashResponse::Error { .. } => Err(r.into()),
279    }
280}