Wrapper around raw errors to support client errors

This commit is contained in:
Mahesh Bansod 2021-10-23 19:52:08 +05:30
parent bc4e8c2216
commit 27aa49685b
4 changed files with 107 additions and 55 deletions

View File

@ -1,39 +1,50 @@
use socialvoid::{ClientError, SocialvoidError};
use socialvoid_rawclient::ErrorKind;
pub struct MyFriendlyError(socialvoid_rawclient::Error);
pub struct MyFriendlyError(SocialvoidError);
impl std::convert::From<socialvoid_rawclient::Error> for MyFriendlyError {
fn from(err: socialvoid_rawclient::Error) -> Self {
Self(err)
impl std::convert::From<SocialvoidError> for MyFriendlyError {
fn from(err: SocialvoidError) -> Self {
Self(err.into())
}
}
impl std::fmt::Display for MyFriendlyError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match &self.0.kind {
ErrorKind::Authentication(err) => {
write!(f, "This method needs you to log in.
match &self.0 {
SocialvoidError::RawClient(err) => match &err.kind {
ErrorKind::Authentication(err) => {
write!(f, "This method needs you to log in.
Authentication Error: {:#?}\nIf you are already logged in, then try logging out and logging in again.
To log in:
socialvoid-cli login
To log out:
socialvoid-cli logout", err)
}
ErrorKind::Cdn(err) => {
write!(
f,
"There was a problem while uploading/downloading the file from CDN.
}
ErrorKind::Cdn(err) => {
write!(
f,
"There was a problem while uploading/downloading the file from CDN.
CDN Error: {:#?}\nIf it was an authentication error, try logging in.
To log in:
socialvoid-cli login
To log out:
socialvoid-cli logout",
err
)
}
_ => {
write!(f, "{:#?}", self.0)
}
err
)
}
_ => {
write!(f, "{:#?}", self.0)
}
},
SocialvoidError::Client(err) => match err {
ClientError::NoSessionsExist => {
write!(f, "Seems you need to create a session.")
}
ClientError::SerdeJson(err) => {
write!(f, "Error while parsing JSON.\n{:?}", err)
}
},
}
}
}

View File

@ -1,6 +1,7 @@
use rpassword::read_password;
use serde::{Deserialize, Serialize};
use socialvoid as sv_client;
use socialvoid::SocialvoidError;
use socialvoid_rawclient::{AuthenticationError, ErrorKind};
use std::io::{stdin, stdout, Write};
@ -31,17 +32,25 @@ pub async fn setup_sessions(config: &Config, sv: &mut sv_client::Client, sesh_ke
match sv.get_session(*sesh_key).await {
Ok(_) => {}
Err(err) => match err.kind {
ErrorKind::Authentication(AuthenticationError::SessionExpired)
| ErrorKind::Authentication(AuthenticationError::SessionNotFound) => {
println!("This session either didn't exist or is expired.\nDeleting it and creating a new one.");
sv.delete_session(*sesh_key).await;
let new_sesh_key = sv
.new_session()
.await
.expect("Couldn't create a new session.");
*sesh_key = new_sesh_key;
}
Err(err) => match err {
SocialvoidError::RawClient(err) => match err.kind {
ErrorKind::Authentication(AuthenticationError::SessionExpired)
| ErrorKind::Authentication(AuthenticationError::SessionNotFound) => {
println!("This session either didn't exist or is expired.\nDeleting it and creating a new one.");
sv.delete_session(*sesh_key).await;
let new_sesh_key = sv
.new_session()
.await
.expect("Couldn't create a new session.");
*sesh_key = new_sesh_key;
}
_ => {
panic!(
"Couldn't `get` session. The session is probably corrupt.
Either delete the sessions file or fix the corrupt session."
);
}
},
_ => {
panic!(
"Couldn't `get` session. The session is probably corrupt.

27
client/src/error.rs Normal file
View File

@ -0,0 +1,27 @@
#[derive(Debug)]
pub enum SocialvoidError {
RawClient(socialvoid_rawclient::Error),
Client(ClientError),
}
/// Errors generated by the client
#[derive(Debug)]
pub enum ClientError {
/// Thrown when `current_session` is `None`, typically means there aren't any
/// sessions and you should create one.
NoSessionsExist,
/// Errors thrown by serde json
SerdeJson(serde_json::Error),
}
impl From<socialvoid_rawclient::Error> for SocialvoidError {
fn from(err: socialvoid_rawclient::Error) -> Self {
SocialvoidError::RawClient(err)
}
}
impl From<serde_json::Error> for SocialvoidError {
fn from(err: serde_json::Error) -> Self {
SocialvoidError::Client(ClientError::SerdeJson(err))
}
}

View File

@ -1,20 +1,22 @@
pub mod account;
pub mod error;
pub mod help;
pub mod network;
pub mod session;
pub use error::ClientError;
pub use error::SocialvoidError;
use session::ClientInfo;
use session::RegisterRequest;
use session::Session;
use session::SessionHolder;
use socialvoid_rawclient::Error;
use socialvoid_types::Document;
use socialvoid_types::HelpDocument;
use socialvoid_types::Peer;
use socialvoid_types::Profile;
/// Create a client and establish a new session
pub async fn new_with_defaults() -> Result<Client, Error> {
pub async fn new_with_defaults() -> Result<Client, SocialvoidError> {
let rpc_client = socialvoid_rawclient::new();
let cdn_client = make_cdn_client_from(&rpc_client).await?;
let client_info = ClientInfo::generate();
@ -33,7 +35,7 @@ pub async fn new_with_defaults() -> Result<Client, Error> {
/// Creates the CDN client by resolving the host url from server information
async fn make_cdn_client_from(
rpc_client: &socialvoid_rawclient::Client,
) -> Result<socialvoid_rawclient::CdnClient, Error> {
) -> Result<socialvoid_rawclient::CdnClient, SocialvoidError> {
let server_info = help::get_server_information(&rpc_client).await?;
Ok(socialvoid_rawclient::CdnClient::with_cdn_url(
@ -44,7 +46,10 @@ async fn make_cdn_client_from(
/// Create a client with user defined client info and sessions
/// And CDN as gven in the server information
/// TODO: maybe verify the session and return an error if session is invalid
pub async fn new(client_info: ClientInfo, sessions: Vec<SessionHolder>) -> Result<Client, Error> {
pub async fn new(
client_info: ClientInfo,
sessions: Vec<SessionHolder>,
) -> Result<Client, SocialvoidError> {
let rpc_client = socialvoid_rawclient::new();
let cdn_client = make_cdn_client_from(&rpc_client).await?;
Ok(Client {
@ -76,7 +81,7 @@ pub struct Client {
impl Client {
/// Set the CDN server URL from the ServerInfomation
pub async fn reset_cdn_url(&mut self) -> Result<(), Error> {
pub async fn reset_cdn_url(&mut self) -> Result<(), SocialvoidError> {
self.cdn_client = make_cdn_client_from(&self.rpc_client).await?;
Ok(())
}
@ -96,7 +101,7 @@ impl Client {
}
/// Tries to establish another session adds it to the client if successful and returns the key of the session
pub async fn new_session(&mut self) -> Result<usize, Error> {
pub async fn new_session(&mut self) -> Result<usize, SocialvoidError> {
let mut session = SessionHolder::new(self.client_info.clone());
session.create(&self.rpc_client).await?;
self.sessions.push(session);
@ -110,13 +115,13 @@ impl Client {
}
/// Gets a Session object for a specific session
pub async fn get_session(&mut self, session_key: usize) -> Result<Session, Error> {
self.sessions[session_key].get(&self.rpc_client).await
pub async fn get_session(&mut self, session_key: usize) -> Result<Session, SocialvoidError> {
Ok(self.sessions[session_key].get(&self.rpc_client).await?)
}
/// Get terms of service
pub async fn get_terms_of_service(&self) -> Result<HelpDocument, Error> {
help::get_terms_of_service(&self.rpc_client).await
pub async fn get_terms_of_service(&self) -> Result<HelpDocument, SocialvoidError> {
Ok(help::get_terms_of_service(&self.rpc_client).await?)
}
/// Accept terms of service for a specific session
@ -129,10 +134,10 @@ impl Client {
&mut self,
session_key: usize,
req: RegisterRequest,
) -> Result<Peer, Error> {
self.sessions[session_key]
) -> Result<Peer, SocialvoidError> {
Ok(self.sessions[session_key]
.register(req, &self.rpc_client)
.await
.await?)
}
/// Login to an account using a specific session
@ -142,10 +147,10 @@ impl Client {
username: String,
password: String,
otp: Option<String>,
) -> Result<bool, Error> {
self.sessions[session_key]
) -> Result<bool, SocialvoidError> {
Ok(self.sessions[session_key]
.authenticate_user(&self.rpc_client, username, password, otp)
.await
.await?)
}
/// Check if a session is authenticated
@ -154,32 +159,32 @@ impl Client {
}
/// Log out from a session. Maybe destroy the session??
pub async fn logout(&mut self, session_key: usize) -> Result<bool, Error> {
self.sessions[session_key].logout(&self.rpc_client).await
pub async fn logout(&mut self, session_key: usize) -> Result<bool, SocialvoidError> {
Ok(self.sessions[session_key].logout(&self.rpc_client).await?)
}
pub async fn get_me(&self, session_key: usize) -> Result<Peer, Error> {
network::get_me(
pub async fn get_me(&self, session_key: usize) -> Result<Peer, SocialvoidError> {
Ok(network::get_me(
&self.rpc_client,
self.sessions[session_key].session_identification()?,
)
.await
.await?)
}
pub async fn get_my_profile(&self, session_key: usize) -> Result<Profile, Error> {
network::get_profile(
pub async fn get_my_profile(&self, session_key: usize) -> Result<Profile, SocialvoidError> {
Ok(network::get_profile(
&self.rpc_client,
self.sessions[session_key].session_identification()?,
None,
)
.await
.await?)
}
pub async fn set_profile_picture(
&self,
session_key: usize,
filepath: String,
) -> Result<Document, Error> {
) -> Result<Document, SocialvoidError> {
let sesh_id = self.sessions[session_key].session_identification()?;
let document = self.cdn_client.upload(sesh_id.clone(), filepath).await?;
account::set_profile_picture(&self.rpc_client, sesh_id, document.id.clone()).await?; //TODO: use result and send client error if false
@ -192,7 +197,7 @@ mod tests {
use super::*;
#[tokio::test]
async fn it_should_log_in_and_get_the_correct_peer() -> Result<(), Error> {
async fn it_should_log_in_and_get_the_correct_peer() -> Result<(), SocialvoidError> {
// let sessions_file = "sessions.test";
let creds: serde_json::Value =