ccash_rs/methods/
mod.rs

1//! This module contains all the non-admin functions that can be mapped to an
2//! endpoint provided by the [`CCash`](https://github.com/EntireTwix/CCash) API.
3//! All admin functions can be found within the [`admin`] module.
4
5pub mod admin;
6
7use crate::{
8    request::request, CCashError, CCashResponse, CCashSession, CCashUser, TransactionLog,
9};
10use reqwest::Method;
11use velcro::hash_map;
12
13/// Returns the balance of the [`user`](CCashUser).
14///
15/// # Errors
16///
17/// Will return `CCashError` if the request fails or if the response from
18/// `CCash` cannot be parsed as a valid `u32`.
19pub async fn get_balance(
20    session: &CCashSession,
21    user: &CCashUser,
22) -> Result<u32, CCashError> {
23    let url = format!(
24        "{}/user/balance?name={}",
25        &session.session_url, &user.username
26    );
27
28    let r = request::<()>(Method::GET, session, &url, Some(user), None).await?;
29    if let Ok(v) = r.convert_message::<u32>() {
30        Ok(v)
31    } else {
32        Err(r.into())
33    }
34}
35
36/// Returns the transaction logs for a given [`user`](CCashUser). This function
37/// requires a correct password.
38///
39/// # Errors
40///
41/// Will return a `CCashError` if the request fails or if the data returned by
42/// `CCash` cannot be parsed into a valid `Vec<TransactionLog>`.
43pub async fn get_logs(
44    session: &CCashSession,
45    user: &CCashUser,
46) -> Result<Vec<TransactionLog>, CCashError> {
47    let url = format!("{}/user/log", &session.session_url);
48
49    let r = request::<()>(Method::GET, session, &url, Some(user), None).await?;
50    if let Ok(v) = r.convert_message::<Vec<TransactionLog>>() {
51        Ok(v)
52    } else {
53        Err(r.into())
54    }
55}
56
57/// Returns a `bool` about whether or not the the user with a given
58/// [`user`](CCashUser) exists. This function does not require a password.
59///
60/// # Errors
61///
62/// Will return a `CCashError` if the request fails or if the `CCash` instance
63/// returns an error code as long as the error code isn't a 401 and as long as
64/// the `interpret_endpoint_errors_as_false` is disabled.
65pub async fn contains_user(
66    session: &CCashSession,
67    user: &CCashUser,
68) -> Result<bool, CCashError> {
69    let url = format!(
70        "{}/user/exists?name={}",
71        &session.session_url, &user.username
72    );
73
74    let r = request::<()>(Method::GET, session, &url, Some(user), None).await?;
75    match r {
76        CCashResponse::Success { .. } => Ok(true),
77        #[cfg(feature = "interpret_endpoint_errors_as_false")]
78        CCashResponse::Error { .. } => Ok(false),
79        #[cfg(not(feature = "interpret_endpoint_errors_as_false"))]
80        CCashResponse::Error { code: 401, .. } => Ok(false),
81        #[cfg(not(feature = "interpret_endpoint_errors_as_false"))]
82        CCashResponse::Error { .. } => Err(r.into()),
83    }
84}
85
86/// Returns a `bool` about whether or not the `password` for a
87/// given [`user`](CCashUser) is correct.
88///
89/// # Errors
90///
91/// Will return a `CCashError` if the request fails or if the `CCash` instance
92/// returns an error code when verifing the password as long as the
93/// `interpret_endpoint_errors_as_false` feature is disabled.
94pub async fn verify_password(
95    session: &CCashSession,
96    user: &CCashUser,
97) -> Result<bool, CCashError> {
98    let url = format!("{}/user/verify_password", &session.session_url);
99
100    let r = request::<()>(Method::POST, session, &url, Some(user), None).await?;
101    match r {
102        CCashResponse::Success { .. } => Ok(true),
103        #[cfg(feature = "interpret_endpoint_errors_as_false")]
104        CCashResponse::Error { .. } => Ok(false),
105        #[cfg(not(feature = "interpret_endpoint_errors_as_false"))]
106        CCashResponse::Error { code: 401, .. } => Ok(false),
107        #[cfg(not(feature = "interpret_endpoint_errors_as_false"))]
108        CCashResponse::Error { .. } => Err(r.into()),
109    }
110}
111
112/// Returns `true` about if a password change was successful for the given
113/// [`user`](CCashUser). This function modifies `user` to use the `new_password`
114/// instead of the previous password in the case of a successful password
115/// change.
116///
117/// # Errors
118///
119/// Will return a `CCashError` if the request fails or if `CCash` instance
120/// returns an error code when changing the password for the `user`, as long as
121/// the `interpret_endpoint_errors_as_false` feature is disabled.
122pub async fn change_password(
123    session: &CCashSession,
124    user: &mut CCashUser,
125    new_password: &str,
126) -> Result<bool, CCashError> {
127    let url = format!("{}/user/change_password", &session.session_url);
128    let body = hash_map! { "pass": new_password };
129
130    let r = request(Method::PATCH, session, &url, Some(user), Some(&body)).await?;
131    match r {
132        CCashResponse::Success { .. } => {
133            user.update_password(new_password);
134            Ok(true)
135        },
136        #[cfg(feature = "interpret_endpoint_errors_as_false")]
137        CCashResponse::Error { .. } => Ok(false),
138        #[cfg(not(feature = "interpret_endpoint_errors_as_false"))]
139        CCashResponse::Error { .. } => Err(r.into()),
140    }
141}
142
143/// Sends funds from the [`user`](CCashUser) to the user with the
144/// `recipient_name`. This function returns the [`user`](CCashUser)'s balance
145/// after a successful transaction has been made.
146///
147/// # Errors
148///
149/// Will return a `CCashError` if the request fails or if the message returned
150/// back by `CCash` cannot be parsed into a `u32`.
151pub async fn send_funds(
152    session: &CCashSession,
153    user: &CCashUser,
154    recipient_name: &str,
155    amount: u32,
156) -> Result<u32, CCashError> {
157    #[derive(serde::Serialize)]
158    struct FundsTransfer {
159        name: String,
160        amount: u32,
161    }
162
163    let url = format!("{}/user/transfer", &session.session_url);
164    let body = FundsTransfer {
165        name: recipient_name.into(),
166        amount,
167    };
168
169    let r = request(Method::POST, session, &url, Some(user), Some(&body)).await?;
170
171    if let Ok(v) = r.convert_message::<u32>() {
172        Ok(v)
173    } else {
174        Err(r.into())
175    }
176}
177
178/// Adds a [`user`](CCashUser) with a balance of 0.
179///
180/// Returns:
181/// * `Ok(true)` if the `user` was created successfully on the `CCash` instance.
182/// * `Ok(false)` if the `user` failed to be created on the `CCash` instance.
183///   This either happens only an a 409 response from the instance or if the
184///   feature `interpret_endpoint_errors_as_false` is enabled.
185///
186/// # Errors
187///
188/// Will return `CCashError` if the instance returns an error response
189/// (other than a 409) *and* the feature `interpret_endpoint_errors_as_false` is
190/// disabled.
191pub async fn add_user(
192    session: &CCashSession,
193    user: &CCashUser,
194) -> Result<bool, CCashError> {
195    let url = format!("{}/user/register", &session.session_url);
196
197    let r = request(Method::POST, session, &url, None, Some(user)).await?;
198    match r {
199        CCashResponse::Success { .. } => Ok(true),
200        #[cfg(feature = "interpret_endpoint_errors_as_false")]
201        CCashResponse::Error { .. } => Ok(false),
202        #[cfg(not(feature = "interpret_endpoint_errors_as_false"))]
203        CCashResponse::Error { code: 409, .. } => Ok(false),
204        #[cfg(not(feature = "interpret_endpoint_errors_as_false"))]
205        CCashResponse::Error { .. } => Err(r.into()),
206    }
207}
208
209/// Removes the [`user`](CCashUser). This function requires the
210/// [`user`](CCashUser) to be a valid username and password otherwise the
211/// endpoint will return an error.
212///
213/// # Errors
214///
215/// Will return [`CCashError`] if request fails.
216pub async fn delete_user(
217    session: &CCashSession,
218    user: &CCashUser,
219) -> Result<(), CCashError> {
220    let url = format!("{}/user/delete", &session.session_url);
221
222    let r = request::<()>(Method::DELETE, session, &url, Some(user), None).await?;
223    match r {
224        CCashResponse::Success { .. } => Ok(()),
225        CCashResponse::Error { .. } => Err(r.into()),
226    }
227}