commit
29d2cf8b81
|
@ -1,18 +1,126 @@
|
||||||
pub mod register {
|
pub mod register {
|
||||||
use custom_error::custom_error;
|
|
||||||
use reqwest::Client;
|
use reqwest::Client;
|
||||||
use serde_json::json;
|
use serde_json::{from_str, json, Value};
|
||||||
|
|
||||||
use crate::{api::schemas::schemas::RegisterSchema, instance::Instance};
|
use crate::{
|
||||||
|
api::{
|
||||||
|
limits::LimitType,
|
||||||
|
schemas::schemas::{ErrorResponse, RegisterSchema},
|
||||||
|
},
|
||||||
|
errors::InstanceServerError,
|
||||||
|
instance::{Instance, Token},
|
||||||
|
};
|
||||||
|
|
||||||
impl Instance {
|
impl Instance {
|
||||||
pub fn register(&mut self, register_schema: &RegisterSchema) {
|
/**
|
||||||
|
Registers a new user on the Spacebar server.
|
||||||
|
# Arguments
|
||||||
|
* `register_schema` - The [`RegisterSchema`] that contains all the information that is needed to register a new user.
|
||||||
|
# Errors
|
||||||
|
* [`InstanceServerError`] - If the server does not respond.
|
||||||
|
*/
|
||||||
|
pub async fn register(
|
||||||
|
&mut self,
|
||||||
|
register_schema: &RegisterSchema,
|
||||||
|
) -> Result<Token, InstanceServerError> {
|
||||||
let json_schema = json!(register_schema);
|
let json_schema = json!(register_schema);
|
||||||
let limited_requester = &self.requester;
|
let limited_requester = &mut self.requester;
|
||||||
let client = Client::new();
|
let client = Client::new();
|
||||||
let endpoint_url = self.urls.get_api().to_string() + "/auth/register";
|
let endpoint_url = self.urls.get_api().to_string() + "/auth/register";
|
||||||
let request_builder = client.post(endpoint_url).body(json_schema.to_string());
|
let request_builder = client.post(endpoint_url).body(json_schema.to_string());
|
||||||
// TODO
|
let response = limited_requester
|
||||||
|
.send_request(request_builder, LimitType::AuthRegister)
|
||||||
|
.await;
|
||||||
|
if response.is_none() {
|
||||||
|
return Err(InstanceServerError::NoResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
let response_unwrap = response.unwrap();
|
||||||
|
let status = response_unwrap.status();
|
||||||
|
let response_text_string = response_unwrap.text().await.unwrap();
|
||||||
|
if status.is_client_error() {
|
||||||
|
let json: ErrorResponse = serde_json::from_str(&response_text_string).unwrap();
|
||||||
|
let error_type = json.errors.errors.iter().next().unwrap().0.to_owned();
|
||||||
|
let mut error = "".to_string();
|
||||||
|
for (_, value) in json.errors.errors.iter() {
|
||||||
|
for error_item in value._errors.iter() {
|
||||||
|
error += &(error_item.message.to_string() + " (" + &error_item.code + ")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Err(InstanceServerError::InvalidFormBodyError { error_type, error });
|
||||||
|
}
|
||||||
|
return Ok(Token {
|
||||||
|
token: response_text_string,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use crate::api::schemas::schemas::RegisterSchema;
|
||||||
|
use crate::errors::InstanceServerError;
|
||||||
|
use crate::instance::Instance;
|
||||||
|
use crate::limit::LimitedRequester;
|
||||||
|
use crate::URLBundle;
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_incomplete_registration() {
|
||||||
|
let urls = URLBundle::new(
|
||||||
|
"http://localhost:3001/api".to_string(),
|
||||||
|
"http://localhost:3001".to_string(),
|
||||||
|
"http://localhost:3001".to_string(),
|
||||||
|
);
|
||||||
|
let limited_requester = LimitedRequester::new(urls.get_api().to_string()).await;
|
||||||
|
let mut test_instance = Instance::new(urls.clone(), limited_requester)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let reg = RegisterSchema::new(
|
||||||
|
"aaa".to_string(),
|
||||||
|
None,
|
||||||
|
true,
|
||||||
|
Some("me@mail.xy".to_string()),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
InstanceServerError::InvalidFormBodyError {
|
||||||
|
error_type: "date_of_birth".to_string(),
|
||||||
|
error: "This field is required (BASE_TYPE_REQUIRED)".to_string()
|
||||||
|
},
|
||||||
|
test_instance.register(®).await.err().unwrap()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_registration() {
|
||||||
|
let urls = URLBundle::new(
|
||||||
|
"http://localhost:3001/api".to_string(),
|
||||||
|
"http://localhost:3001".to_string(),
|
||||||
|
"http://localhost:3001".to_string(),
|
||||||
|
);
|
||||||
|
let limited_requester = LimitedRequester::new(urls.get_api().to_string()).await;
|
||||||
|
let mut test_instance = Instance::new(urls.clone(), limited_requester)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let reg = RegisterSchema::new(
|
||||||
|
"Hiiii".to_string(),
|
||||||
|
Some("mysupersecurepass123!".to_string()),
|
||||||
|
true,
|
||||||
|
Some("flori@mail.xyz".to_string()),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
Some("2000-01-01".to_string()),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
let token = test_instance.register(®).await.unwrap().token;
|
||||||
|
println!("{}", token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,32 +1,25 @@
|
||||||
pub mod instance {
|
pub mod instance {
|
||||||
use custom_error::custom_error;
|
|
||||||
use reqwest::Client;
|
use reqwest::Client;
|
||||||
use serde_json::from_str;
|
use serde_json::from_str;
|
||||||
|
|
||||||
|
use crate::errors::InstanceServerError;
|
||||||
use crate::{api::schemas::schemas::InstancePoliciesSchema, instance::Instance};
|
use crate::{api::schemas::schemas::InstancePoliciesSchema, instance::Instance};
|
||||||
|
|
||||||
custom_error! {
|
|
||||||
#[derive(PartialEq, Eq)]
|
|
||||||
pub InstancePoliciesError
|
|
||||||
RequestErrorError{url:String, error:String} = "An error occured while trying to GET from {url}: {error}",
|
|
||||||
ReceivedErrorCodeError{error_code:String} = "Received the following error code while requesting from the route: {error_code}"
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Instance {
|
impl Instance {
|
||||||
/**
|
/**
|
||||||
Gets the instance policies schema.
|
Gets the instance policies schema.
|
||||||
# Errors
|
# Errors
|
||||||
[`InstancePoliciesError`] - If the request fails.
|
[`InstanceServerError`] - If the request fails.
|
||||||
*/
|
*/
|
||||||
pub async fn instance_policies_schema(
|
pub async fn instance_policies_schema(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<InstancePoliciesSchema, InstancePoliciesError> {
|
) -> Result<InstancePoliciesSchema, InstanceServerError> {
|
||||||
let client = Client::new();
|
let client = Client::new();
|
||||||
let endpoint_url = self.urls.get_api().to_string() + "/policies/instance/";
|
let endpoint_url = self.urls.get_api().to_string() + "/policies/instance/";
|
||||||
let request = match client.get(&endpoint_url).send().await {
|
let request = match client.get(&endpoint_url).send().await {
|
||||||
Ok(result) => result,
|
Ok(result) => result,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
return Err(InstancePoliciesError::RequestErrorError {
|
return Err(InstanceServerError::RequestErrorError {
|
||||||
url: endpoint_url,
|
url: endpoint_url,
|
||||||
error: e.to_string(),
|
error: e.to_string(),
|
||||||
});
|
});
|
||||||
|
@ -34,7 +27,7 @@ pub mod instance {
|
||||||
};
|
};
|
||||||
|
|
||||||
if request.status().as_str().chars().next().unwrap() != '2' {
|
if request.status().as_str().chars().next().unwrap() != '2' {
|
||||||
return Err(InstancePoliciesError::ReceivedErrorCodeError {
|
return Err(InstanceServerError::ReceivedErrorCodeError {
|
||||||
error_code: request.status().to_string(),
|
error_code: request.status().to_string(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
pub mod schemas {
|
pub mod schemas {
|
||||||
use std::fmt;
|
|
||||||
|
|
||||||
use custom_error::custom_error;
|
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
use crate::errors::FieldFormatError;
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
|
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
|
@ -20,23 +20,14 @@ pub mod schemas {
|
||||||
promotional_email_opt_in: Option<bool>,
|
promotional_email_opt_in: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
custom_error! {
|
|
||||||
#[derive(PartialEq, Eq)]
|
|
||||||
pub RegisterSchemaError
|
|
||||||
PasswordError = "Password must be between 1 and 72 characters.",
|
|
||||||
UsernameError = "Username must be between 2 and 32 characters.",
|
|
||||||
ConsentError = "Consent must be 'true' to register.",
|
|
||||||
EmailError = "The provided email address is in an invalid format."
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RegisterSchema {
|
impl RegisterSchema {
|
||||||
/**
|
/**
|
||||||
Returns a new [`Result<RegisterSchema, RegisterSchemaError>`].
|
Returns a new [`Result<RegisterSchema, FieldFormatError>`].
|
||||||
## Arguments
|
## Arguments
|
||||||
All but "String::username" and "bool::consent" are optional.
|
All but "String::username" and "bool::consent" are optional.
|
||||||
|
|
||||||
## Errors
|
## Errors
|
||||||
You will receive a [`RegisterSchemaError`], if:
|
You will receive a [`FieldFormatError`], if:
|
||||||
- The username is less than 2 or more than 32 characters in length
|
- The username is less than 2 or more than 32 characters in length
|
||||||
- You supply a `password` which is less than 1 or more than 72 characters in length.
|
- You supply a `password` which is less than 1 or more than 72 characters in length.
|
||||||
|
|
||||||
|
@ -53,22 +44,22 @@ pub mod schemas {
|
||||||
gift_code_sku_id: Option<String>,
|
gift_code_sku_id: Option<String>,
|
||||||
captcha_key: Option<String>,
|
captcha_key: Option<String>,
|
||||||
promotional_email_opt_in: Option<bool>,
|
promotional_email_opt_in: Option<bool>,
|
||||||
) -> Result<RegisterSchema, RegisterSchemaError> {
|
) -> Result<RegisterSchema, FieldFormatError> {
|
||||||
if username.len() < 2 || username.len() > 32 {
|
if username.len() < 2 || username.len() > 32 {
|
||||||
return Err(RegisterSchemaError::UsernameError);
|
return Err(FieldFormatError::UsernameError);
|
||||||
}
|
}
|
||||||
if password.is_some()
|
if password.is_some()
|
||||||
&& (password.as_ref().unwrap().len() < 1 || password.as_ref().unwrap().len() > 72)
|
&& (password.as_ref().unwrap().len() < 1 || password.as_ref().unwrap().len() > 72)
|
||||||
{
|
{
|
||||||
return Err(RegisterSchemaError::PasswordError);
|
return Err(FieldFormatError::PasswordError);
|
||||||
}
|
}
|
||||||
if !consent {
|
if !consent {
|
||||||
return Err(RegisterSchemaError::ConsentError);
|
return Err(FieldFormatError::ConsentError);
|
||||||
}
|
}
|
||||||
|
|
||||||
let regex = Regex::new(r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$").unwrap();
|
let regex = Regex::new(r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$").unwrap();
|
||||||
if email.clone().is_some() && !regex.is_match(email.clone().unwrap().as_str()) {
|
if email.clone().is_some() && !regex.is_match(email.clone().unwrap().as_str()) {
|
||||||
return Err(RegisterSchemaError::EmailError);
|
return Err(FieldFormatError::EmailError);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(RegisterSchema {
|
return Ok(RegisterSchema {
|
||||||
|
@ -159,6 +150,31 @@ pub mod schemas {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct ErrorResponse {
|
||||||
|
pub code: i32,
|
||||||
|
pub message: String,
|
||||||
|
pub errors: IntermittentError,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct IntermittentError {
|
||||||
|
#[serde(flatten)]
|
||||||
|
pub errors: std::collections::HashMap<String, ErrorField>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Default)]
|
||||||
|
pub struct ErrorField {
|
||||||
|
#[serde(default)]
|
||||||
|
pub _errors: Vec<Error>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct Error {
|
||||||
|
pub message: String,
|
||||||
|
pub code: String,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// I know that some of these tests are... really really basic and unneccessary, but sometimes, I
|
// I know that some of these tests are... really really basic and unneccessary, but sometimes, I
|
||||||
|
@ -166,6 +182,7 @@ pub mod schemas {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod schemas_tests {
|
mod schemas_tests {
|
||||||
use super::schemas::*;
|
use super::schemas::*;
|
||||||
|
use crate::errors::FieldFormatError;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn password_too_short() {
|
fn password_too_short() {
|
||||||
|
@ -182,7 +199,7 @@ mod schemas_tests {
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
Err(RegisterSchemaError::PasswordError)
|
Err(FieldFormatError::PasswordError)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,7 +222,7 @@ mod schemas_tests {
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
Err(RegisterSchemaError::PasswordError)
|
Err(FieldFormatError::PasswordError)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,7 +241,7 @@ mod schemas_tests {
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
Err(RegisterSchemaError::UsernameError)
|
Err(FieldFormatError::UsernameError)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,7 +253,7 @@ mod schemas_tests {
|
||||||
}
|
}
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
RegisterSchema::new(long_un, None, true, None, None, None, None, None, None, None,),
|
RegisterSchema::new(long_un, None, true, None, None, None, None, None, None, None,),
|
||||||
Err(RegisterSchemaError::UsernameError)
|
Err(FieldFormatError::UsernameError)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -255,7 +272,7 @@ mod schemas_tests {
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
Err(RegisterSchemaError::ConsentError)
|
Err(FieldFormatError::ConsentError)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -274,7 +291,7 @@ mod schemas_tests {
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
Err(RegisterSchemaError::EmailError)
|
Err(FieldFormatError::EmailError)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -292,6 +309,6 @@ mod schemas_tests {
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
assert_ne!(reg, Err(RegisterSchemaError::EmailError));
|
assert_ne!(reg, Err(FieldFormatError::EmailError));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
use custom_error::custom_error;
|
||||||
|
|
||||||
|
custom_error! {
|
||||||
|
#[derive(PartialEq, Eq)]
|
||||||
|
pub FieldFormatError
|
||||||
|
PasswordError = "Password must be between 1 and 72 characters.",
|
||||||
|
UsernameError = "Username must be between 2 and 32 characters.",
|
||||||
|
ConsentError = "Consent must be 'true' to register.",
|
||||||
|
EmailError = "The provided email address is in an invalid format.",
|
||||||
|
}
|
||||||
|
|
||||||
|
custom_error! {
|
||||||
|
#[derive(PartialEq, Eq)]
|
||||||
|
pub InstanceServerError
|
||||||
|
NoResponse = "Did not receive a response from the Server.",
|
||||||
|
RequestErrorError{url:String, error:String} = "An error occured while trying to GET from {url}: {error}",
|
||||||
|
ReceivedErrorCodeError{error_code:String} = "Received the following error code while requesting from the route: {error_code}",
|
||||||
|
CantGetInfoError{error:String} = "Something seems to be wrong with the instance. Cannot get information about the instance: {error}",
|
||||||
|
InvalidFormBodyError{error_type: String, error:String} = "The server responded with: {error_type}: {error}",
|
||||||
|
}
|
|
@ -1,8 +1,5 @@
|
||||||
use regex::internal::Inst;
|
|
||||||
|
|
||||||
use crate::api::instance;
|
|
||||||
use crate::api::schemas::schemas::InstancePoliciesSchema;
|
use crate::api::schemas::schemas::InstancePoliciesSchema;
|
||||||
use crate::gateway::Gateway;
|
use crate::errors::{FieldFormatError, InstanceServerError};
|
||||||
use crate::limit::LimitedRequester;
|
use crate::limit::LimitedRequester;
|
||||||
use crate::URLBundle;
|
use crate::URLBundle;
|
||||||
|
|
||||||
|
@ -31,7 +28,7 @@ impl Instance {
|
||||||
pub async fn new(
|
pub async fn new(
|
||||||
urls: URLBundle,
|
urls: URLBundle,
|
||||||
requester: LimitedRequester,
|
requester: LimitedRequester,
|
||||||
) -> Result<Instance, InstanceError> {
|
) -> Result<Instance, InstanceServerError> {
|
||||||
let users: HashMap<Token, Username> = HashMap::new();
|
let users: HashMap<Token, Username> = HashMap::new();
|
||||||
let mut instance = Instance {
|
let mut instance = Instance {
|
||||||
urls,
|
urls,
|
||||||
|
@ -51,36 +48,27 @@ impl Instance {
|
||||||
};
|
};
|
||||||
instance.instance_info = match instance.instance_policies_schema().await {
|
instance.instance_info = match instance.instance_policies_schema().await {
|
||||||
Ok(schema) => schema,
|
Ok(schema) => schema,
|
||||||
Err(e) => return Err(InstanceError{message: format!("Something seems to be wrong with the instance. Cannot get information about the instance: {}", e)}),
|
Err(e) => {
|
||||||
|
return Err(InstanceServerError::CantGetInfoError {
|
||||||
|
error: e.to_string(),
|
||||||
|
})
|
||||||
|
}
|
||||||
};
|
};
|
||||||
Ok(instance)
|
Ok(instance)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
|
||||||
pub struct InstanceError {
|
|
||||||
pub message: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl InstanceError {
|
|
||||||
fn new(message: String) -> Self {
|
|
||||||
InstanceError { message }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for InstanceError {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
write!(f, "{}", self.message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::error::Error for InstanceError {}
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub struct Token {
|
pub struct Token {
|
||||||
pub token: String,
|
pub token: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Token {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "{}", self.token)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub struct Username {
|
pub struct Username {
|
||||||
pub username: String,
|
pub username: String,
|
||||||
|
@ -92,31 +80,10 @@ impl Username {
|
||||||
/// * `username` - The username that will be used to create the [`Username`].
|
/// * `username` - The username that will be used to create the [`Username`].
|
||||||
/// # Errors
|
/// # Errors
|
||||||
/// * [`UsernameFormatError`] - If the username is not between 2 and 32 characters.
|
/// * [`UsernameFormatError`] - If the username is not between 2 and 32 characters.
|
||||||
pub fn new(username: String) -> Result<Username, UsernameFormatError> {
|
pub fn new(username: String) -> Result<Username, FieldFormatError> {
|
||||||
if username.len() < 2 || username.len() > 32 {
|
if username.len() < 2 || username.len() > 32 {
|
||||||
return Err(UsernameFormatError::new(
|
return Err(FieldFormatError::UsernameError);
|
||||||
"Username must be between 2 and 32 characters".to_string(),
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
return Ok(Username { username });
|
return Ok(Username { username });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
|
||||||
pub struct UsernameFormatError {
|
|
||||||
pub message: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl UsernameFormatError {
|
|
||||||
fn new(message: String) -> Self {
|
|
||||||
UsernameFormatError { message }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for UsernameFormatError {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
write!(f, "{}", self.message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::error::Error for UsernameFormatError {}
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
mod api;
|
mod api;
|
||||||
|
mod errors;
|
||||||
mod gateway;
|
mod gateway;
|
||||||
mod instance;
|
mod instance;
|
||||||
mod limit;
|
mod limit;
|
||||||
|
|
Loading…
Reference in New Issue