made session, network and help have the new structure. + removed cli temporarily from the workspace
This commit is contained in:
parent
370cc97f61
commit
02559e2fbc
|
@ -2,26 +2,6 @@
|
|||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "ansi_term"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.0.1"
|
||||
|
@ -85,35 +65,6 @@ version = "1.0.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "2.33.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
|
||||
dependencies = [
|
||||
"ansi_term",
|
||||
"atty",
|
||||
"bitflags",
|
||||
"strsim",
|
||||
"textwrap",
|
||||
"unicode-width",
|
||||
"vec_map",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cli"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"rpassword",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"shellexpand",
|
||||
"socialvoid",
|
||||
"socialvoid_rawclient",
|
||||
"structopt",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation"
|
||||
version = "0.9.1"
|
||||
|
@ -148,27 +99,6 @@ dependencies = [
|
|||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs-next"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"dirs-sys-next",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs-sys-next"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"redox_users",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "encoding_rs"
|
||||
version = "0.8.28"
|
||||
|
@ -370,15 +300,6 @@ version = "0.11.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
|
||||
dependencies = [
|
||||
"unicode-segmentation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.1.19"
|
||||
|
@ -771,30 +692,6 @@ version = "0.2.10"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
|
||||
dependencies = [
|
||||
"proc-macro-error-attr",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error-attr"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-hack"
|
||||
version = "0.5.19"
|
||||
|
@ -921,16 +818,6 @@ dependencies = [
|
|||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_users"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"redox_syscall",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "remove_dir_all"
|
||||
version = "0.5.3"
|
||||
|
@ -976,16 +863,6 @@ dependencies = [
|
|||
"winreg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rpassword"
|
||||
version = "5.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ffc936cf8a7ea60c58f030fd36a612a48f440610214dc54bc36431f9ea0c3efb"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rust-crypto"
|
||||
version = "0.2.36"
|
||||
|
@ -1116,15 +993,6 @@ dependencies = [
|
|||
"sha2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shellexpand"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "83bdb7831b2d85ddf4a7b148aa19d0587eddbe8671a436b7bd1182eaad0f2829"
|
||||
dependencies = [
|
||||
"dirs-next",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook-registry"
|
||||
version = "1.4.0"
|
||||
|
@ -1197,36 +1065,6 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
||||
|
||||
[[package]]
|
||||
name = "structopt"
|
||||
version = "0.3.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf9d950ef167e25e0bdb073cf1d68e9ad2795ac826f2f3f59647817cf23c0bfa"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"lazy_static",
|
||||
"structopt-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "structopt-derive"
|
||||
version = "0.4.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "134d838a2c9943ac3125cf6df165eda53493451b719f3255b2a26b85f772d0ba"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.76"
|
||||
|
@ -1252,15 +1090,6 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "textwrap"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
|
||||
dependencies = [
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.1.43"
|
||||
|
@ -1403,12 +1232,6 @@ dependencies = [
|
|||
"tinyvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-segmentation"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.9"
|
||||
|
@ -1439,12 +1262,6 @@ version = "0.2.15"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|
||||
|
||||
[[package]]
|
||||
name = "vec_map"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.3"
|
||||
|
|
|
@ -3,6 +3,5 @@ members = [
|
|||
"client",
|
||||
"types",
|
||||
"rawclient",
|
||||
"jsonrpc2-client",
|
||||
"cli"
|
||||
"jsonrpc2-client"
|
||||
]
|
||||
|
|
|
@ -9,27 +9,27 @@
|
|||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
let creds1: serde_json::Value =
|
||||
serde_json::from_str(&std::fs::read_to_string("test_creds.test").unwrap())
|
||||
.expect("Couldn't read the credentials. Check the JSON format or something");
|
||||
// WIP
|
||||
// let creds1: serde_json::Value =
|
||||
// serde_json::from_str(&std::fs::read_to_string("test_creds.test").unwrap())
|
||||
// .expect("Couldn't read the credentials. Check the JSON format or something");
|
||||
|
||||
let mut client1 = socialvoid::new_with_defaults().await.unwrap();
|
||||
client1
|
||||
.authenticate_user(
|
||||
creds1["username"].as_str().unwrap().to_string(),
|
||||
creds1["password"].as_str().unwrap().to_string(),
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
// let mut sv = socialvoid::new_with_defaults().await.unwrap();
|
||||
// sv
|
||||
// .authenticate_user(
|
||||
// creds1["username"].as_str().unwrap().to_string(),
|
||||
// creds1["password"].as_str().unwrap().to_string(),
|
||||
// None,
|
||||
// )
|
||||
// .await
|
||||
// .unwrap();
|
||||
|
||||
let handle = tokio::spawn(async move {
|
||||
let post = client1.compose_post("Yayaya", vec![]).await.unwrap();
|
||||
println!("Made post!");
|
||||
if client1.delete_post(post.id).await.unwrap() {
|
||||
println!("Deleted successfully!");
|
||||
}
|
||||
});
|
||||
|
||||
handle.await.unwrap();
|
||||
// let handle = tokio::spawn(async move {
|
||||
// let post = sv.compose_post("Yayaya", vec![]).await.unwrap();
|
||||
// println!("Made post!");
|
||||
// if sv.delete_post(post.id).await.unwrap() {
|
||||
// println!("Deleted successfully!");
|
||||
// }
|
||||
// });
|
||||
// handle.await.unwrap();
|
||||
}
|
||||
|
|
|
@ -13,8 +13,8 @@ async fn main() {
|
|||
serde_json::from_str(&std::fs::read_to_string("test_creds.test").unwrap())
|
||||
.expect("Couldn't read the credentials. Check the JSON format or something");
|
||||
|
||||
let mut client = socialvoid::new_with_defaults().await.unwrap();
|
||||
client
|
||||
let sv = socialvoid::new_with_defaults().await.unwrap();
|
||||
sv.session
|
||||
.authenticate_user(
|
||||
creds["username"].as_str().unwrap().to_string(),
|
||||
creds["password"].as_str().unwrap().to_string(),
|
||||
|
@ -23,10 +23,10 @@ async fn main() {
|
|||
.await
|
||||
.unwrap();
|
||||
|
||||
let peer = client.get_me().await.unwrap();
|
||||
let peer = sv.network.get_me().await.unwrap();
|
||||
|
||||
println!("{:?}", peer);
|
||||
client.logout().await.unwrap();
|
||||
sv.session.logout().await.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
peer.username,
|
||||
|
|
|
@ -1,19 +1,30 @@
|
|||
use serde_json::json;
|
||||
use socialvoid_rawclient::Error;
|
||||
use socialvoid_types::SessionIdentification;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub async fn set_profile_picture(
|
||||
client: &socialvoid_rawclient::Client,
|
||||
session_identification: SessionIdentification,
|
||||
document_id: String,
|
||||
) -> Result<bool, Error> {
|
||||
client
|
||||
.send_request(
|
||||
"account.set_profile_picture",
|
||||
json!({
|
||||
"session_identification": serde_json::to_value(session_identification)?,
|
||||
"document": document_id,
|
||||
}),
|
||||
)
|
||||
.await
|
||||
pub struct SVAccountMethods {
|
||||
client: Arc<socialvoid_rawclient::Client>,
|
||||
}
|
||||
|
||||
impl SVAccountMethods {
|
||||
pub fn new(client: Arc<socialvoid_rawclient::Client>) -> Self {
|
||||
Self { client }
|
||||
}
|
||||
|
||||
pub async fn set_profile_picture(
|
||||
&self,
|
||||
session_identification: SessionIdentification,
|
||||
document_id: String,
|
||||
) -> Result<bool, Error> {
|
||||
self.client
|
||||
.send_request(
|
||||
"account.set_profile_picture",
|
||||
json!({
|
||||
"session_identification": serde_json::to_value(session_identification)?,
|
||||
"document": document_id,
|
||||
}),
|
||||
)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,11 +5,14 @@ pub mod network;
|
|||
pub mod session;
|
||||
pub mod timeline;
|
||||
|
||||
use account::SVAccountMethods;
|
||||
pub use error::ClientError;
|
||||
pub use error::SocialvoidError;
|
||||
use help::SVHelpMethods;
|
||||
use network::SVNetworkMethods;
|
||||
use session::ClientInfo;
|
||||
use session::RegisterRequest;
|
||||
use session::SVSessionMethods;
|
||||
use session::Session;
|
||||
use session::SessionHolder;
|
||||
use socialvoid_types::Document;
|
||||
|
@ -17,34 +20,46 @@ use socialvoid_types::HelpDocument;
|
|||
use socialvoid_types::Peer;
|
||||
use socialvoid_types::Post;
|
||||
use socialvoid_types::Profile;
|
||||
use std::sync::Arc;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
/// A client that can be used to call methods and manage sessions for Social Void
|
||||
pub struct Client {
|
||||
client_info: Arc<ClientInfo>,
|
||||
session_holder: Arc<Mutex<SessionHolder>>,
|
||||
rpc_client: Arc<socialvoid_rawclient::Client>,
|
||||
cdn_client: Arc<socialvoid_rawclient::CdnClient>,
|
||||
pub help: Arc<SVHelpMethods>,
|
||||
pub session: Arc<SVSessionMethods>,
|
||||
pub network: Arc<SVNetworkMethods>,
|
||||
pub account: Arc<SVAccountMethods>,
|
||||
}
|
||||
|
||||
/// Create a client and establish a new session
|
||||
pub async fn new_with_defaults() -> Result<Client, SocialvoidError> {
|
||||
let rpc_client = Arc::new(socialvoid_rawclient::new());
|
||||
let cdn_client = make_cdn_client_from(Arc::clone(&rpc_client)).await?;
|
||||
let client_info = ClientInfo::generate();
|
||||
let mut session = SessionHolder::new(client_info.clone());
|
||||
session.create(&rpc_client).await?;
|
||||
let sessions = vec![session];
|
||||
let (help) = init_methods(Arc::clone(&rpc_client));
|
||||
let cdn_client = Arc::new(make_cdn_client_from(Arc::clone(&rpc_client)).await?);
|
||||
let client_info = Arc::new(ClientInfo::generate());
|
||||
let session_holder = Arc::new(Mutex::new(SessionHolder::new(Arc::clone(&client_info))));
|
||||
let (session, network, account, help) = init_methods(
|
||||
Arc::clone(&rpc_client),
|
||||
Arc::clone(&cdn_client),
|
||||
Arc::clone(&session_holder),
|
||||
);
|
||||
|
||||
session.create().await?;
|
||||
let client = Client {
|
||||
current_session: Some(0),
|
||||
sessions,
|
||||
client_info,
|
||||
rpc_client: socialvoid_rawclient::new(), //temporary,.. TODO: remove this
|
||||
// rpc_client: &rpc_client,
|
||||
session_holder,
|
||||
rpc_client,
|
||||
cdn_client,
|
||||
help,
|
||||
network,
|
||||
session,
|
||||
account,
|
||||
};
|
||||
Ok(client)
|
||||
}
|
||||
|
||||
pub fn init_methods(client: Arc<socialvoid_rawclient::Client>) -> (SVHelpMethods) {
|
||||
(SVHelpMethods::new(client))
|
||||
}
|
||||
|
||||
/// Creates the CDN client by resolving the host url from server information
|
||||
async fn make_cdn_client_from(
|
||||
rpc_client: Arc<socialvoid_rawclient::Client>,
|
||||
|
@ -58,24 +73,30 @@ async fn make_cdn_client_from(
|
|||
))
|
||||
}
|
||||
|
||||
/// Create a client with user defined client info and sessions
|
||||
/// Create a client with user defined client info and session
|
||||
/// 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>,
|
||||
session: SessionHolder,
|
||||
) -> Result<Client, SocialvoidError> {
|
||||
let rpc_client = Arc::new(socialvoid_rawclient::new());
|
||||
let cdn_client = make_cdn_client_from(Arc::clone(&rpc_client)).await?;
|
||||
let current_session = if sessions.is_empty() { None } else { Some(0) };
|
||||
let (help) = init_methods(Arc::clone(&rpc_client));
|
||||
let cdn_client = Arc::new(make_cdn_client_from(Arc::clone(&rpc_client)).await?);
|
||||
let session_holder = Arc::new(Mutex::new(session));
|
||||
let (session, network, account, help) = init_methods(
|
||||
Arc::clone(&rpc_client),
|
||||
Arc::clone(&cdn_client),
|
||||
Arc::clone(&session_holder),
|
||||
);
|
||||
Ok(Client {
|
||||
current_session,
|
||||
sessions,
|
||||
client_info,
|
||||
rpc_client: socialvoid_rawclient::new(),
|
||||
session,
|
||||
session_holder,
|
||||
client_info: Arc::new(client_info),
|
||||
rpc_client,
|
||||
cdn_client,
|
||||
help,
|
||||
network,
|
||||
account,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -83,252 +104,58 @@ pub async fn new(
|
|||
/// Note that, cdn client may not be the one taken from server information
|
||||
pub fn new_empty_client() -> Client {
|
||||
let rpc_client = Arc::new(socialvoid_rawclient::new());
|
||||
let (help) = init_methods(Arc::clone(&rpc_client));
|
||||
let client_info = Arc::new(ClientInfo::generate());
|
||||
let session_holder = Arc::new(Mutex::new(SessionHolder::new(Arc::clone(&client_info))));
|
||||
let (session, network, account, help) = init_methods(
|
||||
Arc::clone(&rpc_client),
|
||||
Arc::new(socialvoid_rawclient::CdnClient::new()),
|
||||
Arc::clone(&session_holder),
|
||||
);
|
||||
Client {
|
||||
current_session: None,
|
||||
sessions: Vec::new(),
|
||||
client_info: ClientInfo::generate(),
|
||||
rpc_client: socialvoid_rawclient::new(),
|
||||
cdn_client: socialvoid_rawclient::CdnClient::new(),
|
||||
client_info,
|
||||
session_holder,
|
||||
rpc_client,
|
||||
cdn_client: Arc::new(socialvoid_rawclient::CdnClient::new()),
|
||||
help,
|
||||
network,
|
||||
session,
|
||||
account,
|
||||
}
|
||||
}
|
||||
|
||||
/// A client that can be used to call methods and manage sessions for Social Void
|
||||
pub struct Client {
|
||||
pub sessions: Vec<SessionHolder>,
|
||||
current_session: Option<usize>, //Index of the current session
|
||||
client_info: ClientInfo,
|
||||
rpc_client: socialvoid_rawclient::Client,
|
||||
cdn_client: socialvoid_rawclient::CdnClient,
|
||||
pub help: SVHelpMethods,
|
||||
pub fn init_methods(
|
||||
client: Arc<socialvoid_rawclient::Client>,
|
||||
cdn_client: Arc<socialvoid_rawclient::CdnClient>,
|
||||
session_holder: Arc<Mutex<SessionHolder>>,
|
||||
) -> (
|
||||
Arc<SVSessionMethods>,
|
||||
Arc<SVNetworkMethods>,
|
||||
Arc<SVAccountMethods>,
|
||||
Arc<SVHelpMethods>,
|
||||
) {
|
||||
let session = Arc::new(SVSessionMethods::new(
|
||||
Arc::clone(&client),
|
||||
Arc::clone(&cdn_client),
|
||||
Arc::clone(&session_holder),
|
||||
));
|
||||
(
|
||||
Arc::clone(&session),
|
||||
Arc::new(SVNetworkMethods::new(
|
||||
Arc::clone(&client),
|
||||
Arc::clone(&session),
|
||||
)),
|
||||
Arc::new(SVAccountMethods::new(Arc::clone(&client))),
|
||||
Arc::new(SVHelpMethods::new(client)),
|
||||
)
|
||||
}
|
||||
|
||||
impl Client {
|
||||
/// Set the CDN server URL from the ServerInfomation
|
||||
pub async fn reset_cdn_url(&mut self) -> Result<(), SocialvoidError> {
|
||||
self.cdn_client = make_cdn_client_from(Arc::new(socialvoid_rawclient::new())).await?; //todo: fix
|
||||
self.cdn_client =
|
||||
Arc::new(make_cdn_client_from(Arc::new(socialvoid_rawclient::new())).await?); //todo: maybe propagate the change??
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Saves all your sessions to a file
|
||||
pub fn save_sessions(&self, filename: &str) -> Result<(), std::io::Error> {
|
||||
// let filename = "social-void-rust.sessions";
|
||||
serde_json::to_writer(&std::fs::File::create(filename)?, &self.sessions)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Loads all sessions from a file and adds them to the client
|
||||
pub fn load_sessions(&mut self, fpath: &str) -> Result<(), std::io::Error> {
|
||||
let sessions: Vec<SessionHolder> = serde_json::from_reader(&std::fs::File::open(fpath)?)?;
|
||||
if self.sessions.is_empty() && !sessions.is_empty() {
|
||||
self.current_session = Some(0);
|
||||
}
|
||||
self.sessions.extend(sessions);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Get another video
|
||||
|
||||
/// 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, SocialvoidError> {
|
||||
let mut session = SessionHolder::new(self.client_info.clone());
|
||||
session.create(&self.rpc_client).await?;
|
||||
self.sessions.push(session);
|
||||
|
||||
Ok(self.sessions.len() - 1)
|
||||
}
|
||||
|
||||
/// Removes the current session and returns it
|
||||
pub fn delete_session(&mut self) -> Result<SessionHolder, SocialvoidError> {
|
||||
if self.current_session.is_none() {
|
||||
Err(SocialvoidError::Client(ClientError::NoSessionsExist))
|
||||
} else {
|
||||
let sesh_key = self.current_session.unwrap();
|
||||
self.current_session = if sesh_key == self.sessions.len() - 1 {
|
||||
if sesh_key != 0 {
|
||||
Some(sesh_key - 1)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
Some(sesh_key)
|
||||
};
|
||||
Ok(self.sessions.remove(sesh_key))
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the current session to session_key if exists
|
||||
pub fn set_current_session(&mut self, session_key: usize) -> Result<(), SocialvoidError> {
|
||||
if self.sessions.len() > session_key {
|
||||
self.current_session = Some(session_key);
|
||||
Ok(())
|
||||
} else {
|
||||
Err(SocialvoidError::Client(
|
||||
ClientError::SessionIndexOutOfBounds {
|
||||
session_count: self.sessions.len(),
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the current session key
|
||||
pub fn get_current_session_key(&self) -> Option<usize> {
|
||||
self.current_session
|
||||
}
|
||||
|
||||
/// Gets a Session object for the current session
|
||||
pub async fn get_session(&mut self) -> Result<Session, SocialvoidError> {
|
||||
match self.current_session {
|
||||
Some(session_key) => Ok(self.sessions[session_key].get(&self.rpc_client).await?),
|
||||
None => Err(SocialvoidError::Client(ClientError::NoSessionsExist)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get terms of service
|
||||
pub async fn get_terms_of_service(&self) -> Result<HelpDocument, SocialvoidError> {
|
||||
Ok(self.help.get_terms_of_service().await?)
|
||||
}
|
||||
|
||||
/// Accept terms of service for the current session
|
||||
pub fn accept_tos(&mut self, tos: HelpDocument) -> Result<(), SocialvoidError> {
|
||||
match self.current_session {
|
||||
Some(session_key) => {
|
||||
self.sessions[session_key].accept_terms_of_service(tos);
|
||||
Ok(())
|
||||
}
|
||||
None => Err(SocialvoidError::Client(ClientError::NoSessionsExist)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Register an account using the current session
|
||||
pub async fn register(&mut self, req: RegisterRequest) -> Result<Peer, SocialvoidError> {
|
||||
match self.current_session {
|
||||
Some(session_key) => Ok(self.sessions[session_key]
|
||||
.register(req, &self.rpc_client)
|
||||
.await?),
|
||||
None => Err(SocialvoidError::Client(ClientError::NoSessionsExist)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Login to an account using the current session
|
||||
pub async fn authenticate_user(
|
||||
&mut self,
|
||||
username: String,
|
||||
password: String,
|
||||
otp: Option<String>,
|
||||
) -> Result<bool, SocialvoidError> {
|
||||
match self.current_session {
|
||||
Some(session_key) => Ok(self.sessions[session_key]
|
||||
.authenticate_user(&self.rpc_client, username, password, otp)
|
||||
.await?),
|
||||
None => Err(SocialvoidError::Client(ClientError::NoSessionsExist)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Check if current session is authenticated
|
||||
pub fn is_authenticated(&self) -> Result<bool, SocialvoidError> {
|
||||
match self.current_session {
|
||||
Some(session_key) => Ok(self.sessions[session_key].authenticated()),
|
||||
None => Err(SocialvoidError::Client(ClientError::NoSessionsExist)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Log out from the current session
|
||||
pub async fn logout(&mut self) -> Result<bool, SocialvoidError> {
|
||||
match self.current_session {
|
||||
Some(session_key) => {
|
||||
let log_out_resp = self.sessions[session_key].logout(&self.rpc_client).await?;
|
||||
self.delete_session()?;
|
||||
Ok(log_out_resp)
|
||||
}
|
||||
None => Err(SocialvoidError::Client(ClientError::NoSessionsExist)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get Peer object of the authenticated user on the current session.
|
||||
pub async fn get_me(&self) -> Result<Peer, SocialvoidError> {
|
||||
match self.current_session {
|
||||
Some(session_key) => Ok(network::get_me(
|
||||
&self.rpc_client,
|
||||
self.sessions[session_key].session_identification()?,
|
||||
)
|
||||
.await?),
|
||||
None => Err(SocialvoidError::Client(ClientError::NoSessionsExist)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the profile of the authenticated user on the current session
|
||||
pub async fn get_my_profile(&self) -> Result<Profile, SocialvoidError> {
|
||||
match self.current_session {
|
||||
Some(session_key) => Ok(network::get_profile(
|
||||
&self.rpc_client,
|
||||
self.sessions[session_key].session_identification()?,
|
||||
None,
|
||||
)
|
||||
.await?),
|
||||
None => Err(SocialvoidError::Client(ClientError::NoSessionsExist)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the profile picture of the user on current session
|
||||
pub async fn set_profile_picture(&self, filepath: String) -> Result<Document, SocialvoidError> {
|
||||
match self.current_session {
|
||||
Some(session_key) => {
|
||||
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
|
||||
Ok(document)
|
||||
}
|
||||
None => Err(SocialvoidError::Client(ClientError::NoSessionsExist)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Compose a new post to put on the timeline
|
||||
/// text: The text contents of the post to compose
|
||||
/// attachments: A vector of Document IDs to attach to the post
|
||||
pub async fn compose_post(
|
||||
&self,
|
||||
text: &str,
|
||||
attachments: Vec<String>,
|
||||
) -> Result<Post, SocialvoidError> {
|
||||
match self.current_session {
|
||||
Some(session_key) => {
|
||||
let sesh_id = self.sessions[session_key].session_identification()?;
|
||||
Ok(
|
||||
timeline::compose(&self.rpc_client, sesh_id, text.to_string(), attachments)
|
||||
.await?,
|
||||
)
|
||||
}
|
||||
None => Err(SocialvoidError::Client(ClientError::NoSessionsExist)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Delete your post to from the timeline
|
||||
/// post: ID of the post you want to delete
|
||||
pub async fn delete_post(&self, post: String) -> Result<bool, SocialvoidError> {
|
||||
match self.current_session {
|
||||
Some(session_key) => {
|
||||
let sesh_id = self.sessions[session_key].session_identification()?;
|
||||
Ok(timeline::delete(&self.rpc_client, sesh_id, post).await?)
|
||||
}
|
||||
None => Err(SocialvoidError::Client(ClientError::NoSessionsExist)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieve the posts from the authenticated users timeline
|
||||
/// post: ID of the post you want to delete
|
||||
pub async fn retrieve_feed_max(&self) -> Result<Vec<Post>, SocialvoidError> {
|
||||
match self.current_session {
|
||||
Some(session_key) => {
|
||||
let sesh_id = self.sessions[session_key].session_identification()?;
|
||||
let page = Some(10); //TODO:GET THIS FROM server information which will be cached or smn
|
||||
Ok(timeline::retrieve_feed(&self.rpc_client, sesh_id, page).await?)
|
||||
}
|
||||
None => Err(SocialvoidError::Client(ClientError::NoSessionsExist)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -346,8 +173,8 @@ mod tests {
|
|||
let creds: serde_json::Value =
|
||||
serde_json::from_str(&std::fs::read_to_string(CREDS_FILE_1).unwrap())?;
|
||||
|
||||
let mut client = new_with_defaults().await?;
|
||||
client
|
||||
let mut sv = new_with_defaults().await?;
|
||||
sv.session
|
||||
.authenticate_user(
|
||||
creds["username"].as_str().unwrap().to_string(),
|
||||
creds["password"].as_str().unwrap().to_string(),
|
||||
|
@ -355,10 +182,10 @@ mod tests {
|
|||
)
|
||||
.await?;
|
||||
|
||||
let peer = client.get_me().await?;
|
||||
let peer = sv.network.get_me().await?;
|
||||
|
||||
println!("{:?}", peer);
|
||||
client.logout().await?;
|
||||
sv.session.logout().await?;
|
||||
assert_eq!(
|
||||
peer.username,
|
||||
creds["username"].as_str().unwrap().to_string()
|
||||
|
@ -367,28 +194,28 @@ mod tests {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn it_should_create_post_and_delete_it() -> Result<(), SocialvoidError> {
|
||||
let creds: serde_json::Value =
|
||||
serde_json::from_str(&std::fs::read_to_string(CREDS_FILE_1).unwrap())?;
|
||||
let mut client = new_with_defaults().await?;
|
||||
client
|
||||
.authenticate_user(
|
||||
creds["username"].as_str().unwrap().to_string(),
|
||||
creds["password"].as_str().unwrap().to_string(),
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
// #[tokio::test]
|
||||
// async fn it_should_create_post_and_delete_it() -> Result<(), SocialvoidError> {
|
||||
// let creds: serde_json::Value =
|
||||
// serde_json::from_str(&std::fs::read_to_string(CREDS_FILE_1).unwrap())?;
|
||||
// let mut sv = new_with_defaults().await?;
|
||||
// sv.session
|
||||
// .authenticate_user(
|
||||
// creds["username"].as_str().unwrap().to_string(),
|
||||
// creds["password"].as_str().unwrap().to_string(),
|
||||
// None,
|
||||
// )
|
||||
// .await?;
|
||||
|
||||
let post_text = thread_rng()
|
||||
.sample_iter(&Alphanumeric)
|
||||
.take(30)
|
||||
.map(char::from)
|
||||
.collect::<String>();
|
||||
let post = client.compose_post(&post_text, Vec::new()).await?;
|
||||
if !client.delete_post(post.id).await? {
|
||||
panic!("Delete post returned false unexpectedly.")
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
// let post_text = thread_rng()
|
||||
// .sample_iter(&Alphanumeric)
|
||||
// .take(30)
|
||||
// .map(char::from)
|
||||
// .collect::<String>();
|
||||
// let post = client.compose_post(&post_text, Vec::new()).await?;
|
||||
// if !client.delete_post(post.id).await? {
|
||||
// panic!("Delete post returned false unexpectedly.")
|
||||
// }
|
||||
// Ok(())
|
||||
// }
|
||||
}
|
||||
|
|
|
@ -1,118 +1,115 @@
|
|||
use crate::SVSessionMethods;
|
||||
use serde_json::json;
|
||||
use socialvoid_rawclient as rawclient;
|
||||
use socialvoid_rawclient::Error;
|
||||
use socialvoid_types::Peer;
|
||||
use socialvoid_types::Profile;
|
||||
use socialvoid_types::RelationshipType;
|
||||
use socialvoid_types::SessionIdentification;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// GetMe
|
||||
/// Returns the peer object of the authenticated peer
|
||||
pub async fn get_me(
|
||||
client: &rawclient::Client,
|
||||
session_identification: SessionIdentification,
|
||||
) -> Result<Peer, Error> {
|
||||
client
|
||||
.send_request(
|
||||
"network.get_me",
|
||||
json!({
|
||||
"session_identification": serde_json::to_value(session_identification)?
|
||||
}),
|
||||
)
|
||||
.await
|
||||
pub struct SVNetworkMethods {
|
||||
client: Arc<rawclient::Client>,
|
||||
session: Arc<SVSessionMethods>,
|
||||
}
|
||||
|
||||
/// GetProfile
|
||||
/// `peer` can be 'None' for own profile, otherwise,
|
||||
/// 'peer' can be Some(p) where p can be the id or username(with leading @) of the peer.
|
||||
pub async fn get_profile(
|
||||
client: &rawclient::Client,
|
||||
session_identification: SessionIdentification,
|
||||
peer: Option<String>,
|
||||
) -> Result<Profile, Error> {
|
||||
client
|
||||
.send_request(
|
||||
"network.get_profile",
|
||||
json!({
|
||||
"session_identification": serde_json::to_value(session_identification)?,
|
||||
"peer": peer,
|
||||
}),
|
||||
)
|
||||
.await
|
||||
}
|
||||
impl SVNetworkMethods {
|
||||
pub fn new(client: Arc<rawclient::Client>, session: Arc<SVSessionMethods>) -> SVNetworkMethods {
|
||||
SVNetworkMethods { client, session }
|
||||
}
|
||||
|
||||
/// ResolvePeer
|
||||
pub async fn resolve_peer(
|
||||
client: &rawclient::Client,
|
||||
session_identification: SessionIdentification,
|
||||
peer: String,
|
||||
) -> Result<Peer, Error> {
|
||||
client
|
||||
.send_request(
|
||||
"network.resolve_peer",
|
||||
json!({
|
||||
"session_identification": serde_json::to_value(session_identification)?,
|
||||
"peer": peer,
|
||||
}),
|
||||
)
|
||||
.await
|
||||
}
|
||||
/// GetMe
|
||||
/// Returns the peer object of the authenticated peer
|
||||
pub async fn get_me(&self) -> Result<Peer, Error> {
|
||||
let session_identification = self.session.session_identification()?;
|
||||
self.client
|
||||
.send_request(
|
||||
"network.get_me",
|
||||
json!({
|
||||
"session_identification": serde_json::to_value(session_identification)?
|
||||
}),
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
/// UnfollowPeer
|
||||
pub async fn unfollow_peer(
|
||||
client: &rawclient::Client,
|
||||
session_identification: SessionIdentification,
|
||||
peer: String,
|
||||
) -> Result<RelationshipType, Error> {
|
||||
client
|
||||
.send_request(
|
||||
"network.unfollow_peer",
|
||||
json!({
|
||||
"session_identification": serde_json::to_value(session_identification)?,
|
||||
"peer": peer,
|
||||
}),
|
||||
)
|
||||
.await
|
||||
}
|
||||
/// GetProfile
|
||||
/// `peer` can be 'None' for own profile, otherwise,
|
||||
/// 'peer' can be Some(p) where p can be the id or username(with leading @) of the peer.
|
||||
pub async fn get_profile(&self, peer: Option<String>) -> Result<Profile, Error> {
|
||||
let session_identification = self.session.session_identification()?;
|
||||
self.client
|
||||
.send_request(
|
||||
"network.get_profile",
|
||||
json!({
|
||||
"session_identification": serde_json::to_value(session_identification)?,
|
||||
"peer": peer,
|
||||
}),
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
/// FollowPeer
|
||||
pub async fn follow_peer(
|
||||
client: &rawclient::Client,
|
||||
session_identification: SessionIdentification,
|
||||
peer: String,
|
||||
) -> Result<RelationshipType, Error> {
|
||||
client
|
||||
.send_request(
|
||||
"network.follow_peer",
|
||||
json!({
|
||||
"session_identification": serde_json::to_value(session_identification)?,
|
||||
"peer": peer,
|
||||
}),
|
||||
)
|
||||
.await
|
||||
/// ResolvePeer
|
||||
pub async fn resolve_peer(&self, peer: String) -> Result<Peer, Error> {
|
||||
let session_identification = self.session.session_identification()?;
|
||||
self.client
|
||||
.send_request(
|
||||
"network.resolve_peer",
|
||||
json!({
|
||||
"session_identification": serde_json::to_value(session_identification)?,
|
||||
"peer": peer,
|
||||
}),
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
/// UnfollowPeer
|
||||
pub async fn unfollow_peer(&self, peer: String) -> Result<RelationshipType, Error> {
|
||||
let session_identification = self.session.session_identification()?;
|
||||
self.client
|
||||
.send_request(
|
||||
"network.unfollow_peer",
|
||||
json!({
|
||||
"session_identification": serde_json::to_value(session_identification)?,
|
||||
"peer": peer,
|
||||
}),
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
/// FollowPeer
|
||||
pub async fn follow_peer(&self, peer: String) -> Result<RelationshipType, Error> {
|
||||
let session_identification = self.session.session_identification()?;
|
||||
self.client
|
||||
.send_request(
|
||||
"network.follow_peer",
|
||||
json!({
|
||||
"session_identification": serde_json::to_value(session_identification)?,
|
||||
"peer": peer,
|
||||
}),
|
||||
)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::session::{ClientInfo, SessionHolder};
|
||||
use crate::session::{ClientInfo, SVSessionMethods, SessionHolder};
|
||||
use rawclient::{AuthenticationError, ErrorKind};
|
||||
use std::sync::{Arc, Mutex};
|
||||
#[tokio::test]
|
||||
async fn it_should_return_a_notauthenticated_error() {
|
||||
let client = rawclient::new();
|
||||
let mut session = SessionHolder::new(ClientInfo::generate());
|
||||
session
|
||||
.create(&client)
|
||||
.await
|
||||
.expect("Couldn't create a session.");
|
||||
match get_me(
|
||||
&client,
|
||||
session
|
||||
.session_identification()
|
||||
.expect("Couldn't get session identification object (unestablished session)"),
|
||||
)
|
||||
.await
|
||||
{
|
||||
let client = Arc::new(socialvoid_rawclient::new());
|
||||
let session = Arc::new(SVSessionMethods::new(
|
||||
Arc::clone(&client),
|
||||
Arc::new(socialvoid_rawclient::CdnClient::new()),
|
||||
Arc::new(Mutex::new(SessionHolder::new(Arc::new(
|
||||
ClientInfo::generate(),
|
||||
)))),
|
||||
));
|
||||
session.create().await.expect("Couldn't create a session.");
|
||||
|
||||
let network = SVNetworkMethods::new(Arc::clone(&client), Arc::clone(&session));
|
||||
match network.get_me().await {
|
||||
Ok(_) => panic!("Session found for some reason.?"),
|
||||
Err(error) => match error.kind {
|
||||
ErrorKind::Authentication(error) => match error {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
mod client_info;
|
||||
mod session;
|
||||
mod session_challenge;
|
||||
pub use client_info::ClientInfo;
|
||||
pub use session::RegisterRequest;
|
||||
pub use session::Session;
|
||||
pub use session::SessionEstablished;
|
||||
pub use session::SessionHolder;
|
||||
pub use session::SessionRegisterInput;
|
||||
|
|
|
@ -1,14 +1,7 @@
|
|||
use super::ClientInfo;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::json;
|
||||
use socialvoid_rawclient::ClientError;
|
||||
use socialvoid_rawclient::Error;
|
||||
use socialvoid_types::Document;
|
||||
pub use socialvoid_types::HelpDocument;
|
||||
use socialvoid_types::Peer;
|
||||
use socialvoid_types::SessionIdentification;
|
||||
|
||||
use super::session_challenge::answer_challenge;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct Session {
|
||||
|
@ -25,16 +18,17 @@ pub struct SessionEstablished {
|
|||
pub challenge: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
//TODO: maybe do serde thing
|
||||
#[derive(Debug)]
|
||||
pub struct SessionHolder {
|
||||
pub established: Option<SessionEstablished>,
|
||||
authenticated: bool,
|
||||
client_info: ClientInfo,
|
||||
tos_read: Option<String>, //Holds the terms of service ID
|
||||
pub authenticated: bool,
|
||||
pub client_info: Arc<ClientInfo>,
|
||||
pub tos_read: Option<String>, //Holds the terms of service ID
|
||||
}
|
||||
|
||||
impl SessionHolder {
|
||||
pub fn new(client_info: ClientInfo) -> SessionHolder {
|
||||
pub fn new(client_info: Arc<ClientInfo>) -> SessionHolder {
|
||||
SessionHolder {
|
||||
established: None,
|
||||
client_info,
|
||||
|
@ -42,178 +36,6 @@ impl SessionHolder {
|
|||
authenticated: false,
|
||||
}
|
||||
}
|
||||
|
||||
/// `session.create`
|
||||
/// Creates a session and sets a session established object which contains a challenge.
|
||||
/// A session object is not yet returned - the challenge needs to be solved and sent inside a session identification
|
||||
/// object using the `get_session` method to get the Session object.
|
||||
pub async fn create(&mut self, rpc_client: &socialvoid_rawclient::Client) -> Result<(), Error> {
|
||||
let client_info = &self.client_info;
|
||||
self.established = Some(
|
||||
rpc_client
|
||||
.send_request("session.create", serde_json::value::to_value(client_info)?)
|
||||
.await?,
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// `session.get`
|
||||
/// Returns a `Session`
|
||||
pub async fn get(
|
||||
&mut self,
|
||||
rpc_client: &socialvoid_rawclient::Client,
|
||||
) -> Result<Session, Error> {
|
||||
let session_identification = self.session_identification()?;
|
||||
let sesh: Session = rpc_client
|
||||
.send_request(
|
||||
"session.get",
|
||||
json!({"session_identification": serde_json::value::to_value(session_identification)?}),
|
||||
)
|
||||
.await?;
|
||||
self.authenticated = sesh.authenticated;
|
||||
Ok(sesh)
|
||||
}
|
||||
|
||||
/// `session.authenticate_user`
|
||||
/// Authenticates a user via a username & password and optionally an OTP - extends session expiration time
|
||||
pub async fn authenticate_user(
|
||||
&mut self,
|
||||
rpc_client: &socialvoid_rawclient::Client,
|
||||
username: String,
|
||||
password: String,
|
||||
otp: Option<String>,
|
||||
) -> Result<bool, Error> {
|
||||
let session_identification = self.session_identification()?;
|
||||
let response = rpc_client
|
||||
.send_request(
|
||||
"session.authenticate_user",
|
||||
json!({
|
||||
"session_identification": serde_json::to_value(session_identification)?,
|
||||
"username": username,
|
||||
"password": password,
|
||||
"otp": otp
|
||||
}),
|
||||
)
|
||||
.await?;
|
||||
self.authenticated = true;
|
||||
Ok(response)
|
||||
}
|
||||
|
||||
/// `session.logout`
|
||||
/// Log out without destroying the session - changes the session expiration date too
|
||||
pub async fn logout(
|
||||
&mut self,
|
||||
rpc_client: &socialvoid_rawclient::Client,
|
||||
) -> Result<bool, Error> {
|
||||
let session_identification = self.session_identification()?;
|
||||
let response = rpc_client
|
||||
.send_request(
|
||||
"session.logout",
|
||||
json!({
|
||||
"session_identification":serde_json::value::to_value(session_identification)?
|
||||
}),
|
||||
)
|
||||
.await?;
|
||||
self.authenticated = false;
|
||||
Ok(response)
|
||||
}
|
||||
|
||||
/// session.register
|
||||
/// Registers a new user to the network
|
||||
pub async fn register(
|
||||
&mut self,
|
||||
request: RegisterRequest,
|
||||
rpc_client: &socialvoid_rawclient::Client,
|
||||
) -> Result<Peer, Error> {
|
||||
let session_identification = self.session_identification()?;
|
||||
|
||||
let request = SessionRegisterInput {
|
||||
session_identification,
|
||||
terms_of_service_id: self
|
||||
.tos_read
|
||||
.take()
|
||||
.ok_or_else(|| Error::new_client_error(ClientError::TermsOfServiceNotAgreed))?,
|
||||
terms_of_service_agree: true,
|
||||
username: request.username,
|
||||
password: request.password,
|
||||
first_name: request.first_name,
|
||||
last_name: request.last_name,
|
||||
};
|
||||
|
||||
rpc_client
|
||||
.send_request("session.register", serde_json::to_value(request)?)
|
||||
.await
|
||||
}
|
||||
|
||||
/// Upload a file to the CDN
|
||||
pub async fn upload_file(
|
||||
&self,
|
||||
file: &str,
|
||||
cdn_client: &socialvoid_rawclient::CdnClient,
|
||||
) -> Result<Document, Error> {
|
||||
let session_identification = self.session_identification()?;
|
||||
cdn_client
|
||||
.upload(session_identification, file.to_string())
|
||||
.await
|
||||
}
|
||||
|
||||
/// Download a file from the CDN
|
||||
pub async fn download_file(
|
||||
&self,
|
||||
document_id: String,
|
||||
cdn_client: &socialvoid_rawclient::CdnClient,
|
||||
) -> Result<Vec<u8>, Error> {
|
||||
let session_identification = self.session_identification()?;
|
||||
cdn_client
|
||||
.download(session_identification, document_id)
|
||||
.await
|
||||
}
|
||||
|
||||
/// Accepts the terms of service
|
||||
/// The client must explicitly call `session.accept_terms_of_service(terms_of_service)` to
|
||||
/// accept the terms of service. The HelpDocument can be acquired via `help::get_terms_of_service(socialvoid_rawclient)`
|
||||
pub fn accept_terms_of_service(&mut self, tos: HelpDocument) {
|
||||
self.tos_read = Some(tos.id);
|
||||
}
|
||||
|
||||
pub fn session_identification(&self) -> Result<SessionIdentification, Error> {
|
||||
if self.established.is_none() {
|
||||
return Err(Error::new_client_error(ClientError::SessionNotEstablished));
|
||||
}
|
||||
let session_id = self
|
||||
.established
|
||||
.as_ref()
|
||||
.map(|s| &s.id)
|
||||
.unwrap()
|
||||
.to_string();
|
||||
let challenge = self
|
||||
.established
|
||||
.as_ref()
|
||||
.map(|s| &s.challenge)
|
||||
.unwrap()
|
||||
.to_string();
|
||||
let client_public_hash = self.client_info.public_hash.clone();
|
||||
Ok(SessionIdentification {
|
||||
session_id,
|
||||
client_public_hash,
|
||||
challenge_answer: answer_challenge(self.client_info.private_hash.clone(), challenge),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn authenticated(&self) -> bool {
|
||||
self.authenticated
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Debug)]
|
||||
struct SessionRegisterInput {
|
||||
session_identification: SessionIdentification,
|
||||
terms_of_service_id: String,
|
||||
terms_of_service_agree: bool,
|
||||
username: String,
|
||||
password: String,
|
||||
first_name: String,
|
||||
last_name: Option<String>,
|
||||
}
|
||||
|
||||
pub struct RegisterRequest {
|
||||
|
@ -222,3 +44,14 @@ pub struct RegisterRequest {
|
|||
pub first_name: String,
|
||||
pub last_name: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Debug)]
|
||||
pub struct SessionRegisterInput {
|
||||
pub session_identification: SessionIdentification,
|
||||
pub terms_of_service_id: String,
|
||||
pub terms_of_service_agree: bool,
|
||||
pub username: String,
|
||||
pub password: String,
|
||||
pub first_name: String,
|
||||
pub last_name: Option<String>,
|
||||
}
|
||||
|
|
|
@ -1,10 +1,193 @@
|
|||
mod entities;
|
||||
mod session_challenge;
|
||||
|
||||
pub use entities::ClientInfo;
|
||||
pub use entities::RegisterRequest;
|
||||
pub use entities::Session;
|
||||
pub use entities::SessionEstablished;
|
||||
pub use entities::SessionHolder;
|
||||
use entities::SessionRegisterInput;
|
||||
use session_challenge::answer_challenge;
|
||||
use socialvoid_rawclient::ClientError;
|
||||
use socialvoid_rawclient::Error;
|
||||
use socialvoid_types::Document;
|
||||
pub use socialvoid_types::HelpDocument;
|
||||
use socialvoid_types::Peer;
|
||||
use socialvoid_types::SessionIdentification;
|
||||
|
||||
use serde_json::json;
|
||||
use std::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
|
||||
pub struct SVSessionMethods {
|
||||
client: Arc<socialvoid_rawclient::Client>,
|
||||
cdn_client: Arc<socialvoid_rawclient::CdnClient>,
|
||||
session: Arc<Mutex<SessionHolder>>,
|
||||
}
|
||||
|
||||
impl SVSessionMethods {
|
||||
pub fn new(
|
||||
client: Arc<socialvoid_rawclient::Client>,
|
||||
cdn_client: Arc<socialvoid_rawclient::CdnClient>,
|
||||
session: Arc<Mutex<SessionHolder>>,
|
||||
) -> Self {
|
||||
Self {
|
||||
client,
|
||||
cdn_client,
|
||||
session,
|
||||
}
|
||||
}
|
||||
|
||||
/// `session.create`
|
||||
/// Creates a session and sets a session established object which contains a challenge.
|
||||
/// A session object is not yet returned - the challenge needs to be solved and sent inside a session identification
|
||||
/// object using the `get_session` method to get the Session object.
|
||||
pub async fn create(&self) -> Result<(), Error> {
|
||||
let mut session = self.session.lock().unwrap();
|
||||
let client_info = &*session.client_info.clone();
|
||||
session.established = Some(
|
||||
self.client
|
||||
.send_request("session.create", serde_json::value::to_value(client_info)?)
|
||||
.await?,
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// `session.get`
|
||||
/// Returns a `Session`
|
||||
pub async fn get(&self) -> Result<Session, Error> {
|
||||
let session_identification = self.session_identification()?;
|
||||
let mut session = self.session.lock().unwrap();
|
||||
let sesh: Session = self.client
|
||||
.send_request(
|
||||
"session.get",
|
||||
json!({"session_identification": serde_json::value::to_value(session_identification)?}),
|
||||
)
|
||||
.await?;
|
||||
session.authenticated = sesh.authenticated;
|
||||
Ok(sesh)
|
||||
}
|
||||
|
||||
/// `session.authenticate_user`
|
||||
/// Authenticates a user via a username & password and optionally an OTP - extends session expiration time
|
||||
pub async fn authenticate_user(
|
||||
&self,
|
||||
username: String,
|
||||
password: String,
|
||||
otp: Option<String>,
|
||||
) -> Result<bool, Error> {
|
||||
let session_identification = self.session_identification()?;
|
||||
let response = self
|
||||
.client
|
||||
.send_request(
|
||||
"session.authenticate_user",
|
||||
json!({
|
||||
"session_identification": serde_json::to_value(session_identification)?,
|
||||
"username": username,
|
||||
"password": password,
|
||||
"otp": otp
|
||||
}),
|
||||
)
|
||||
.await?;
|
||||
self.session.lock().unwrap().authenticated = true;
|
||||
Ok(response)
|
||||
}
|
||||
|
||||
/// `session.logout`
|
||||
/// Log out without destroying the session - changes the session expiration date too
|
||||
pub async fn logout(&self) -> Result<bool, Error> {
|
||||
let session_identification = self.session_identification()?;
|
||||
let response = self
|
||||
.client
|
||||
.send_request(
|
||||
"session.logout",
|
||||
json!({
|
||||
"session_identification":serde_json::value::to_value(session_identification)?
|
||||
}),
|
||||
)
|
||||
.await?;
|
||||
self.session.lock().unwrap().authenticated = false;
|
||||
Ok(response)
|
||||
}
|
||||
|
||||
/// session.register
|
||||
/// Registers a new user to the network
|
||||
pub async fn register(&self, request: RegisterRequest) -> Result<Peer, Error> {
|
||||
let session_identification = self.session_identification()?;
|
||||
|
||||
let request = SessionRegisterInput {
|
||||
session_identification,
|
||||
terms_of_service_id: self
|
||||
.session
|
||||
.lock()
|
||||
.unwrap()
|
||||
.tos_read
|
||||
.take()
|
||||
.ok_or_else(|| Error::new_client_error(ClientError::TermsOfServiceNotAgreed))?,
|
||||
terms_of_service_agree: true,
|
||||
username: request.username,
|
||||
password: request.password,
|
||||
first_name: request.first_name,
|
||||
last_name: request.last_name,
|
||||
};
|
||||
|
||||
self.client
|
||||
.send_request("session.register", serde_json::to_value(request)?)
|
||||
.await
|
||||
}
|
||||
|
||||
/// Upload a file to the CDN
|
||||
pub async fn upload_file(&self, file: &str) -> Result<Document, Error> {
|
||||
let session_identification = self.session_identification()?;
|
||||
self.cdn_client
|
||||
.upload(session_identification, file.to_string())
|
||||
.await
|
||||
}
|
||||
|
||||
/// Download a file from the CDN
|
||||
pub async fn download_file(&self, document_id: String) -> Result<Vec<u8>, Error> {
|
||||
let session_identification = self.session_identification()?;
|
||||
self.cdn_client
|
||||
.download(session_identification, document_id)
|
||||
.await
|
||||
}
|
||||
|
||||
/// Accepts the terms of service
|
||||
/// The client must explicitly call `session.accept_terms_of_service(terms_of_service)` to
|
||||
/// accept the terms of service. The HelpDocument can be acquired via `help::get_terms_of_service(socialvoid_rawclient)`
|
||||
pub fn accept_terms_of_service(&self, tos: HelpDocument) {
|
||||
self.session.lock().unwrap().tos_read = Some(tos.id);
|
||||
}
|
||||
|
||||
pub fn session_identification(&self) -> Result<SessionIdentification, Error> {
|
||||
let session = self.session.lock().unwrap();
|
||||
if session.established.is_none() {
|
||||
return Err(Error::new_client_error(ClientError::SessionNotEstablished));
|
||||
}
|
||||
let session_id = session
|
||||
.established
|
||||
.as_ref()
|
||||
.map(|s| &s.id)
|
||||
.unwrap()
|
||||
.to_string();
|
||||
let challenge = session
|
||||
.established
|
||||
.as_ref()
|
||||
.map(|s| &s.challenge)
|
||||
.unwrap()
|
||||
.to_string();
|
||||
let client_public_hash = session.client_info.public_hash.clone();
|
||||
Ok(SessionIdentification {
|
||||
session_id,
|
||||
client_public_hash,
|
||||
challenge_answer: answer_challenge(session.client_info.private_hash.clone(), challenge),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn authenticated(&self) -> bool {
|
||||
self.session.lock().unwrap().authenticated
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
@ -15,11 +198,16 @@ mod tests {
|
|||
use socialvoid_rawclient::{ClientError, Error, ErrorKind};
|
||||
#[tokio::test]
|
||||
async fn it_should_establish_a_session_and_get_it() -> Result<(), Error> {
|
||||
let mut session = SessionHolder::new(ClientInfo::generate());
|
||||
let client = socialvoid_rawclient::new();
|
||||
session.create(&client).await?;
|
||||
let mut session = SVSessionMethods::new(
|
||||
Arc::new(socialvoid_rawclient::new()),
|
||||
Arc::new(socialvoid_rawclient::CdnClient::new()),
|
||||
Arc::new(Mutex::new(SessionHolder::new(Arc::new(
|
||||
ClientInfo::generate(),
|
||||
)))),
|
||||
);
|
||||
session.create().await?;
|
||||
|
||||
let sesh = session.get(&client).await?;
|
||||
let sesh = session.get().await?;
|
||||
println!("{:?}", sesh);
|
||||
// assert_eq!(established.id, sesh.id);
|
||||
Ok(())
|
||||
|
@ -28,14 +216,18 @@ mod tests {
|
|||
async fn it_should_establish_a_session_and_upload_and_download_a_file() -> Result<(), Error> {
|
||||
let creds: serde_json::Value =
|
||||
serde_json::from_str(&std::fs::read_to_string("../client/test_creds.test").unwrap())?;
|
||||
let mut session = SessionHolder::new(ClientInfo::generate());
|
||||
let client = socialvoid_rawclient::new();
|
||||
session.create(&client).await?;
|
||||
let mut session = SVSessionMethods::new(
|
||||
Arc::new(socialvoid_rawclient::new()),
|
||||
Arc::new(socialvoid_rawclient::CdnClient::new()),
|
||||
Arc::new(Mutex::new(SessionHolder::new(Arc::new(
|
||||
ClientInfo::generate(),
|
||||
)))),
|
||||
);
|
||||
session.create().await?;
|
||||
|
||||
assert_eq!(
|
||||
session
|
||||
.authenticate_user(
|
||||
&client,
|
||||
creds["username"].as_str().unwrap().to_string(),
|
||||
creds["password"].as_str().unwrap().to_string(),
|
||||
None
|
||||
|
@ -51,13 +243,13 @@ mod tests {
|
|||
.map(char::from)
|
||||
.collect();
|
||||
std::fs::write(file_name, file_content.clone()).unwrap();
|
||||
let cdn_client = socialvoid_rawclient::CdnClient::new();
|
||||
let document = session.upload_file(file_name, &cdn_client).await?;
|
||||
|
||||
let document = session.upload_file(file_name).await?;
|
||||
println!("Document: {:#?}", document);
|
||||
std::fs::remove_file(file_name).unwrap();
|
||||
|
||||
let id = document.id;
|
||||
let downloaded_file = session.download_file(id, &cdn_client).await?;
|
||||
let downloaded_file = session.download_file(id).await?;
|
||||
assert_eq!(String::from_utf8_lossy(&downloaded_file), file_content);
|
||||
// assert_eq!(established.id, sesh.id);
|
||||
Ok(())
|
||||
|
@ -78,19 +270,22 @@ mod tests {
|
|||
|
||||
#[tokio::test]
|
||||
async fn it_should_throw_a_terms_of_service_not_agreed_error() -> Result<(), Error> {
|
||||
let mut session = SessionHolder::new(ClientInfo::generate());
|
||||
let client = socialvoid_rawclient::new();
|
||||
session.create(&client).await?;
|
||||
let mut session = SVSessionMethods::new(
|
||||
Arc::new(socialvoid_rawclient::new()),
|
||||
Arc::new(socialvoid_rawclient::CdnClient::new()),
|
||||
Arc::new(Mutex::new(SessionHolder::new(Arc::new(
|
||||
ClientInfo::generate(),
|
||||
)))),
|
||||
);
|
||||
|
||||
session.create().await?;
|
||||
let response = session
|
||||
.register(
|
||||
RegisterRequest {
|
||||
first_name: "Light".to_string(),
|
||||
last_name: None,
|
||||
username: "justanotherlight".to_string(),
|
||||
password: "SuperStrongPassword".to_string(),
|
||||
},
|
||||
&client,
|
||||
)
|
||||
.register(RegisterRequest {
|
||||
first_name: "Light".to_string(),
|
||||
last_name: None,
|
||||
username: "justanotherlight".to_string(),
|
||||
password: "SuperStrongPassword".to_string(),
|
||||
})
|
||||
.await;
|
||||
match response {
|
||||
Err(e) => match e.kind {
|
||||
|
@ -104,4 +299,40 @@ mod tests {
|
|||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn it_should_calculate_the_correct_answer() {
|
||||
//This test creates a session and calculates the challenge answer
|
||||
// using the python script in the standard and the current implementation and
|
||||
// compares both
|
||||
use crate::ClientInfo;
|
||||
use std::process::Command;
|
||||
|
||||
let client_info = ClientInfo::generate();
|
||||
let private_hash = client_info.private_hash.clone();
|
||||
let mut session = SVSessionMethods::new(
|
||||
Arc::new(socialvoid_rawclient::new()),
|
||||
Arc::new(socialvoid_rawclient::CdnClient::new()),
|
||||
Arc::new(Mutex::new(SessionHolder::new(Arc::new(
|
||||
ClientInfo::generate(),
|
||||
)))),
|
||||
);
|
||||
session.create().await.expect("Couldn't create the session");
|
||||
let established = session.session.lock().unwrap().established.unwrap();
|
||||
let challenge_answer =
|
||||
answer_challenge(private_hash.clone(), established.challenge.clone());
|
||||
|
||||
let output = Command::new("python3")
|
||||
.arg("src/session/test-hotp.py")
|
||||
.arg(&private_hash)
|
||||
.arg(&established.challenge)
|
||||
.output()
|
||||
.expect("Couldn't run python script");
|
||||
println!(
|
||||
"output: {}, err: {}",
|
||||
String::from_utf8_lossy(&output.stdout),
|
||||
String::from_utf8_lossy(&output.stderr)
|
||||
);
|
||||
assert_eq!(String::from_utf8_lossy(&output.stdout), challenge_answer);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -69,39 +69,4 @@ mod tests {
|
|||
println!("{}", otp_string);
|
||||
assert_eq!(otp_string.len(), 6);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn it_should_calculate_the_correct_answer() {
|
||||
//This test creates a session and calculates the challenge answer
|
||||
// using the python script in the standard and the current implementation and
|
||||
// compares both
|
||||
use crate::ClientInfo;
|
||||
use crate::SessionHolder;
|
||||
use std::process::Command;
|
||||
|
||||
let client_info = ClientInfo::generate();
|
||||
let private_hash = client_info.private_hash.clone();
|
||||
let mut session = SessionHolder::new(client_info);
|
||||
let client = socialvoid_rawclient::new();
|
||||
session
|
||||
.create(&client)
|
||||
.await
|
||||
.expect("Couldn't create the session");
|
||||
let established = session.established.unwrap();
|
||||
let challenge_answer =
|
||||
answer_challenge(private_hash.clone(), established.challenge.clone());
|
||||
|
||||
let output = Command::new("python3")
|
||||
.arg("src/session/test-hotp.py")
|
||||
.arg(&private_hash)
|
||||
.arg(&established.challenge)
|
||||
.output()
|
||||
.expect("Couldn't run python script");
|
||||
println!(
|
||||
"output: {}, err: {}",
|
||||
String::from_utf8_lossy(&output.stdout),
|
||||
String::from_utf8_lossy(&output.stderr)
|
||||
);
|
||||
assert_eq!(String::from_utf8_lossy(&output.stdout), challenge_answer);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue