From f85081e449d9e87e37867637f774bfd8e6892881 Mon Sep 17 00:00:00 2001 From: antifallobst Date: Wed, 1 Nov 2023 20:20:17 +0100 Subject: [PATCH] feat: added support for account registration --- src/error.rs | 30 +++++++++++++++++++++++++++ src/lib.rs | 55 ++++++++++++++++++++++++++++++++++++++++++++++--- src/request.rs | 9 +++++++- src/response.rs | 17 ++++++++++++++- 4 files changed, 106 insertions(+), 5 deletions(-) diff --git a/src/error.rs b/src/error.rs index 5d4323d..5b32cf3 100644 --- a/src/error.rs +++ b/src/error.rs @@ -23,3 +23,33 @@ pub enum AuthError { #[error("Failed to authenticate: account not verified")] NotVerified, } + +#[derive(Debug, Error)] +pub enum RegisterError { + #[error("Failed to register: the API complains about a malformed request")] + BadRequest, + + #[error("Failed to register: unprocessable API response")] + BadResponse, + + #[error("Failed to register: failed to send request")] + RequestSend(reqwest::Error), + + #[error("Failed to register: blocked for security reasons")] + Forbidden, + + #[error("Failed to register: the username is already taken")] + UsernameTaken, + + #[error("Failed to register: the email is already in use")] + EmailTaken, + + #[error("Failed to register: the username does not meet the criteria")] + UsernameInvalid, + + #[error("Failed to register: the email is not a valid email address")] + EmailInvalid, + + #[error("Failed to register: password does not meet the criteria")] + PasswordInvalid, +} diff --git a/src/lib.rs b/src/lib.rs index f09dee2..c11a2d4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,7 +2,7 @@ mod error; pub mod request; pub mod response; -use crate::{error::AuthError, request::AccountAuthenticate}; +use crate::error::{AuthError, RegisterError}; use anyhow::Result; use reqwest::StatusCode; use std::fmt::Debug; @@ -40,7 +40,7 @@ impl Session { ) -> Result<(), AuthError> { let url = format!("{}/account/authenticate", &self.base_url); - let body = AccountAuthenticate { username, password }; + let body = request::AccountAuthenticate { username, password }; let request = self.client.post(&url).json(&body); let response = request @@ -52,7 +52,7 @@ impl Session { StatusCode::OK => { self.auth_token = Some( response - .json::() + .json::() .await .map_err(|_| AuthError::BadResponse)? .token, @@ -68,6 +68,55 @@ impl Session { } } + pub async fn register( + &self, + username: String, + password: String, + email: String, + ) -> Result<(), RegisterError> { + let url = format!("{}/account/register", &self.base_url); + + let body = request::AccountRegister { + username, + password, + email, + }; + + let request = self.client.post(&url).json(&body); + let response = request + .send() + .await + .map_err(|e| RegisterError::RequestSend(e))?; + + match response.status() { + StatusCode::OK => Ok(()), + StatusCode::BAD_REQUEST => Err(RegisterError::BadRequest), + StatusCode::FORBIDDEN => Err(RegisterError::Forbidden), + StatusCode::CONFLICT => match response + .json::() + .await + .map_err(|_| RegisterError::BadResponse)? + { + response::AccountRegisterConflict::Username => Err(RegisterError::UsernameTaken), + response::AccountRegisterConflict::Email => Err(RegisterError::EmailTaken), + }, + StatusCode::UNPROCESSABLE_ENTITY => match response + .json::() + .await + .map_err(|_| RegisterError::BadResponse)? + { + response::AccountRegisterUnprocessable::Username => { + Err(RegisterError::UsernameInvalid) + } + response::AccountRegisterUnprocessable::Email => Err(RegisterError::EmailInvalid), + response::AccountRegisterUnprocessable::Password => { + Err(RegisterError::PasswordInvalid) + } + }, + _ => Err(RegisterError::BadResponse), + } + } + pub fn is_authenticated(&self) -> bool { self.auth_token.is_some() } diff --git a/src/request.rs b/src/request.rs index 9f361bf..70ad992 100644 --- a/src/request.rs +++ b/src/request.rs @@ -4,4 +4,11 @@ use serde::Serialize; pub struct AccountAuthenticate { pub username: String, pub password: String, -} \ No newline at end of file +} + +#[derive(Debug, Serialize, Clone)] +pub struct AccountRegister { + pub username: String, + pub password: String, + pub email: String, +} diff --git a/src/response.rs b/src/response.rs index 83c6572..fb8235b 100644 --- a/src/response.rs +++ b/src/response.rs @@ -1,6 +1,21 @@ use serde::Deserialize; #[derive(Debug, Deserialize, Clone)] -pub struct AccountAuthenticateResponse { +pub struct AccountAuthenticate { pub token: String, } + +#[derive(Debug, Deserialize, Clone)] +#[serde(tag = "conflict", rename_all = "snake_case")] +pub enum AccountRegisterConflict { + Username, + Email, +} + +#[derive(Debug, Deserialize, Clone)] +#[serde(tag = "problem", rename_all = "snake_case")] +pub enum AccountRegisterUnprocessable { + Username, + Email, + Password, +}