[fractal] API, user: Separate endpoint connection from query build
- From: Christopher Davis <christopherdavis src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [fractal] API, user: Separate endpoint connection from query build
- Date: Tue, 20 Aug 2019 20:56:42 +0000 (UTC)
commit 50803772f2834b792fad02951cad9347119fe0f1
Author: Alejandro DomÃnguez <adomu net-c com>
Date: Tue Mar 12 12:21:58 2019 +0100
API, user: Separate endpoint connection from query build
fractal-gtk/src/appop/account.rs | 4 +-
fractal-gtk/src/widgets/address.rs | 2 +-
fractal-matrix-api/src/backend/mod.rs | 63 +-
fractal-matrix-api/src/backend/register.rs | 2 +-
fractal-matrix-api/src/backend/types.rs | 4 +-
fractal-matrix-api/src/backend/user.rs | 792 +++++++++++----------
fractal-matrix-api/src/identity.rs | 1 +
fractal-matrix-api/src/identity/r0.rs | 1 +
fractal-matrix-api/src/identity/r0/association.rs | 1 +
.../src/identity/r0/association/msisdn.rs | 1 +
.../identity/r0/association/msisdn/submit_token.rs | 25 +
fractal-matrix-api/src/lib.rs | 1 +
fractal-matrix-api/src/meson.build | 23 +-
fractal-matrix-api/src/model/member.rs | 2 +-
fractal-matrix-api/src/model/mod.rs | 1 -
fractal-matrix-api/src/model/user.rs | 126 ----
fractal-matrix-api/src/r0.rs | 20 +
fractal-matrix-api/src/r0/account.rs | 20 +-
.../src/r0/account/change_password.rs | 27 +
fractal-matrix-api/src/r0/account/deactivate.rs | 26 +
fractal-matrix-api/src/r0/contact.rs | 5 +
fractal-matrix-api/src/r0/contact/create.rs | 27 +
fractal-matrix-api/src/r0/contact/delete.rs | 25 +
.../src/r0/contact/get_identifiers.rs | 33 +
.../r0/contact/request_verification_token_email.rs | 33 +
.../contact/request_verification_token_msisdn.rs | 34 +
fractal-matrix-api/src/r0/media.rs | 1 +
fractal-matrix-api/src/r0/media/create.rs | 40 ++
fractal-matrix-api/src/r0/profile.rs | 4 +
.../src/r0/profile/get_display_name.rs | 21 +
fractal-matrix-api/src/r0/profile/get_profile.rs | 19 +
.../src/r0/profile/set_avatar_url.rs | 31 +
.../src/r0/profile/set_display_name.rs | 32 +
fractal-matrix-api/src/r0/search.rs | 1 +
fractal-matrix-api/src/r0/search/user.rs | 53 ++
fractal-matrix-api/src/types.rs | 1 -
fractal-matrix-api/src/util.rs | 64 +-
37 files changed, 971 insertions(+), 595 deletions(-)
---
diff --git a/fractal-gtk/src/appop/account.rs b/fractal-gtk/src/appop/account.rs
index c12dabc2..5a4533a2 100644
--- a/fractal-gtk/src/appop/account.rs
+++ b/fractal-gtk/src/appop/account.rs
@@ -12,8 +12,8 @@ use crate::widgets;
use crate::widgets::AvatarExt;
use crate::cache::download_to_cache;
-use fractal_api::r0::account::Medium;
-use fractal_api::types::ThirdPartyIdentifier;
+use fractal_api::r0::contact::get_identifiers::ThirdPartyIdentifier;
+use fractal_api::r0::Medium;
impl AppOp {
pub fn set_three_pid(&self, data: Option<Vec<ThirdPartyIdentifier>>) {
diff --git a/fractal-gtk/src/widgets/address.rs b/fractal-gtk/src/widgets/address.rs
index d99a9aa4..ed191a1d 100644
--- a/fractal-gtk/src/widgets/address.rs
+++ b/fractal-gtk/src/widgets/address.rs
@@ -1,4 +1,4 @@
-use fractal_api::r0::account::Medium;
+use fractal_api::r0::Medium;
use glib::signal;
use gtk;
use gtk::prelude::*;
diff --git a/fractal-matrix-api/src/backend/mod.rs b/fractal-matrix-api/src/backend/mod.rs
index 3ff9b45c..3212fc38 100644
--- a/fractal-matrix-api/src/backend/mod.rs
+++ b/fractal-matrix-api/src/backend/mod.rs
@@ -105,69 +105,40 @@ impl Backend {
}
// User module
- Ok(BKCommand::GetUsername) => {
- let r = user::get_username(self);
- bkerror!(r, tx, BKResponse::UserNameError);
- }
- Ok(BKCommand::SetUserName(name)) => {
- let r = user::set_username(self, name);
- bkerror!(r, tx, BKResponse::SetUserNameError);
- }
- Ok(BKCommand::GetThreePID) => {
- let r = user::get_threepid(self);
- bkerror!(r, tx, BKResponse::GetThreePIDError);
- }
+ Ok(BKCommand::GetUsername) => user::get_username(self),
+ Ok(BKCommand::SetUserName(name)) => user::set_username(self, name),
+ Ok(BKCommand::GetThreePID) => user::get_threepid(self),
Ok(BKCommand::GetTokenEmail(identity, email, client_secret)) => {
- let r = user::get_email_token(self, identity, email, client_secret);
- bkerror!(r, tx, BKResponse::GetTokenEmailError);
+ user::get_email_token(self, identity, email, client_secret)
}
Ok(BKCommand::GetTokenPhone(identity, phone, client_secret)) => {
- let r = user::get_phone_token(self, identity, phone, client_secret);
- bkerror!(r, tx, BKResponse::GetTokenEmailError);
+ user::get_phone_token(self, identity, phone, client_secret)
}
- Ok(BKCommand::SubmitPhoneToken(identity, client_secret, sid, token)) => {
- let r = user::submit_phone_token(self, &identity, client_secret, sid, token);
- bkerror!(r, tx, BKResponse::SubmitPhoneTokenError);
+ Ok(BKCommand::SubmitPhoneToken(_, client_secret, sid, token)) => {
+ user::submit_phone_token(self, client_secret, sid, token)
}
Ok(BKCommand::AddThreePID(identity, client_secret, sid)) => {
- let r = user::add_threepid(self, identity, client_secret, sid);
- bkerror!(r, tx, BKResponse::AddThreePIDError);
+ user::add_threepid(self, identity, client_secret, sid)
}
Ok(BKCommand::DeleteThreePID(medium, address)) => {
- user::delete_three_pid(self, medium, address);
+ user::delete_three_pid(self, medium, address)
}
Ok(BKCommand::ChangePassword(username, old_password, new_password)) => {
- let r = user::change_password(self, username, old_password, new_password);
- bkerror!(r, tx, BKResponse::ChangePasswordError);
+ user::change_password(self, username, old_password, new_password)
}
Ok(BKCommand::AccountDestruction(username, password, _)) => {
- let r = user::account_destruction(self, username, password);
- bkerror!(r, tx, BKResponse::AccountDestructionError);
- }
- Ok(BKCommand::GetAvatar) => {
- let r = user::get_avatar(self);
- bkerror!(r, tx, BKResponse::AvatarError);
- }
- Ok(BKCommand::SetUserAvatar(file)) => {
- let r = user::set_user_avatar(self, file);
- bkerror!(r, tx, BKResponse::SetUserAvatarError);
- }
- Ok(BKCommand::GetAvatarAsync(member, ctx)) => {
- let r = user::get_avatar_async(self, member, ctx);
- bkerror!(r, tx, BKResponse::CommandError);
+ user::account_destruction(self, username, password)
}
+ Ok(BKCommand::GetAvatar) => user::get_avatar(self),
+ Ok(BKCommand::SetUserAvatar(file)) => user::set_user_avatar(self, file),
+ Ok(BKCommand::GetAvatarAsync(member, ctx)) => user::get_avatar_async(self, member, ctx),
Ok(BKCommand::GetUserInfoAsync(sender, ctx)) => {
- let r = user::get_user_info_async(self, &sender, ctx);
- bkerror!(r, tx, BKResponse::CommandError);
+ user::get_user_info_async(self, &sender, ctx)
}
Ok(BKCommand::GetUserNameAsync(sender, ctx)) => {
- let r = user::get_username_async(self, sender, ctx);
- bkerror!(r, tx, BKResponse::CommandError);
- }
- Ok(BKCommand::UserSearch(term)) => {
- let r = user::search(self, term);
- bkerror!(r, tx, BKResponse::CommandError);
+ user::get_username_async(self, sender, ctx)
}
+ Ok(BKCommand::UserSearch(term)) => user::search(self, term),
// Sync module
Ok(BKCommand::Sync(since, initial)) => sync::sync(self, since, initial),
diff --git a/fractal-matrix-api/src/backend/register.rs b/fractal-matrix-api/src/backend/register.rs
index 6d32ebb2..5e42043f 100644
--- a/fractal-matrix-api/src/backend/register.rs
+++ b/fractal-matrix-api/src/backend/register.rs
@@ -16,10 +16,10 @@ use crate::r0::account::register::Parameters as RegisterParameters;
use crate::r0::account::register::RegistrationKind;
use crate::r0::account::register::Response as RegisterResponse;
use crate::r0::account::Identifier;
-use crate::r0::account::Medium;
use crate::r0::account::UserIdentifier;
use crate::r0::server::domain_info::request as domain_info;
use crate::r0::server::domain_info::Response as DomainInfoResponse;
+use crate::r0::Medium;
use crate::util::HTTP_CLIENT;
use crate::backend::types::BKResponse;
diff --git a/fractal-matrix-api/src/backend/types.rs b/fractal-matrix-api/src/backend/types.rs
index 0b4a1aad..afb66cb6 100644
--- a/fractal-matrix-api/src/backend/types.rs
+++ b/fractal-matrix-api/src/backend/types.rs
@@ -4,15 +4,15 @@ use std::sync::{Arc, Condvar, Mutex};
use crate::error::Error;
-use crate::r0::account::Medium;
+use crate::r0::contact::get_identifiers::ThirdPartyIdentifier;
use crate::r0::thirdparty::get_supported_protocols::ProtocolInstance;
+use crate::r0::Medium;
use crate::types::Event;
use crate::types::Member;
use crate::types::Message;
use crate::types::Room;
use crate::types::Sticker;
use crate::types::StickerGroup;
-use crate::types::ThirdPartyIdentifier;
use crate::cache::CacheMap;
use url::Url;
diff --git a/fractal-matrix-api/src/backend/user.rs b/fractal-matrix-api/src/backend/user.rs
index 9acb8c94..3dcbe51e 100644
--- a/fractal-matrix-api/src/backend/user.rs
+++ b/fractal-matrix-api/src/backend/user.rs
@@ -1,7 +1,4 @@
-use log::info;
-use serde_json::json;
-use std::fs::File;
-use std::io::prelude::*;
+use std::fs;
use crate::backend::types::BKResponse;
use crate::backend::types::Backend;
@@ -9,155 +6,226 @@ use crate::error::Error;
use crate::util::encode_uid;
use crate::util::get_user_avatar;
use crate::util::get_user_avatar_img;
-use crate::util::json_q;
-use crate::util::put_media;
use crate::util::semaphore;
-use crate::util::{build_url, media_url};
+use crate::util::HTTP_CLIENT;
+use reqwest::header::HeaderValue;
use std::sync::mpsc::Sender;
use std::sync::{Arc, Mutex};
use std::thread;
-use url::Url;
+use crate::identity::r0::association::msisdn::submit_token::request as submit_phone_token_req;
+use crate::identity::r0::association::msisdn::submit_token::Body as SubmitPhoneTokenBody;
+use crate::identity::r0::association::msisdn::submit_token::Response as SubmitPhoneTokenResponse;
+use crate::r0::account::change_password::request as change_password_req;
+use crate::r0::account::change_password::Body as ChangePasswordBody;
+use crate::r0::account::change_password::Parameters as ChangePasswordParameters;
+use crate::r0::account::deactivate::request as deactivate;
+use crate::r0::account::deactivate::Body as DeactivateBody;
+use crate::r0::account::deactivate::Parameters as DeactivateParameters;
use crate::r0::account::AuthenticationData;
use crate::r0::account::Identifier;
-use crate::r0::account::Medium;
-use crate::r0::account::ThreePIDCredentials;
use crate::r0::account::UserIdentifier;
-use crate::types::AddThreePIDRequest;
-use crate::types::ChangePasswordRequest;
-use crate::types::DeactivateAccountRequest;
-use crate::types::DeleteThreePIDRequest;
-use crate::types::EmailTokenRequest;
-use crate::types::GetDisplayNameResponse;
+use crate::r0::contact::create::request as create_contact;
+use crate::r0::contact::create::Body as AddThreePIDBody;
+use crate::r0::contact::create::Parameters as AddThreePIDParameters;
+use crate::r0::contact::delete::request as delete_contact;
+use crate::r0::contact::delete::Body as DeleteThreePIDBody;
+use crate::r0::contact::delete::Parameters as DeleteThreePIDParameters;
+use crate::r0::contact::get_identifiers::request as get_identifiers;
+use crate::r0::contact::get_identifiers::Parameters as ThirdPartyIDParameters;
+use crate::r0::contact::get_identifiers::Response as ThirdPartyIDResponse;
+use crate::r0::contact::request_verification_token_email::request as
request_contact_verification_token_email;
+use crate::r0::contact::request_verification_token_email::Body as EmailTokenBody;
+use crate::r0::contact::request_verification_token_email::Parameters as EmailTokenParameters;
+use crate::r0::contact::request_verification_token_email::Response as EmailTokenResponse;
+use crate::r0::contact::request_verification_token_msisdn::request as
request_contact_verification_token_msisdn;
+use crate::r0::contact::request_verification_token_msisdn::Body as PhoneTokenBody;
+use crate::r0::contact::request_verification_token_msisdn::Parameters as PhoneTokenParameters;
+use crate::r0::contact::request_verification_token_msisdn::Response as PhoneTokenResponse;
+use crate::r0::media::create::request as create_content;
+use crate::r0::media::create::Parameters as CreateContentParameters;
+use crate::r0::media::create::Response as CreateContentResponse;
+use crate::r0::profile::get_display_name::request as get_display_name;
+use crate::r0::profile::get_display_name::Response as GetDisplayNameResponse;
+use crate::r0::profile::set_avatar_url::request as set_avatar_url;
+use crate::r0::profile::set_avatar_url::Body as SetAvatarUrlBody;
+use crate::r0::profile::set_avatar_url::Parameters as SetAvatarUrlParameters;
+use crate::r0::profile::set_display_name::request as set_display_name;
+use crate::r0::profile::set_display_name::Body as SetDisplayNameBody;
+use crate::r0::profile::set_display_name::Parameters as SetDisplayNameParameters;
+use crate::r0::search::user::request as user_directory;
+use crate::r0::search::user::Body as UserDirectoryBody;
+use crate::r0::search::user::Parameters as UserDirectoryParameters;
+use crate::r0::search::user::Response as UserDirectoryResponse;
+use crate::r0::Medium;
+use crate::r0::ThreePIDCredentials;
use crate::types::Member;
-use crate::types::PhoneTokenRequest;
-use crate::types::PutDisplayNameRequest;
-use crate::types::SearchUserRequest;
-use crate::types::SearchUserResponse;
-use crate::types::SubmitPhoneTokenRequest;
-use crate::types::SubmitPhoneTokenResponse;
-use crate::types::ThirdPartyIDResponse;
-use crate::types::ThirdPartyTokenResponse;
-
-use serde_json;
-use serde_json::Value as JsonValue;
-
-pub fn get_username(bk: &Backend) -> Result<(), Error> {
- let id = bk.data.lock().unwrap().user_id.clone();
- let url = bk.url(&format!("profile/{}/displayname", encode_uid(&id)), vec![])?;
+
+pub fn get_username(bk: &Backend) {
let tx = bk.tx.clone();
- get!(
- &url,
- |r: JsonValue| if let Ok(response) = serde_json::from_value::<GetDisplayNameResponse>(r) {
- let name = response.displayname.unwrap_or(id);
- tx.send(BKResponse::Name(name)).unwrap();
- } else {
- tx.send(BKResponse::UserNameError(Error::BackendError))
- .unwrap();
- },
- |err| tx.send(BKResponse::UserNameError(err)).unwrap()
- );
+ let uid = bk.data.lock().unwrap().user_id.clone();
+ let base = bk.get_base_url();
+
+ thread::spawn(move || {
+ let query = get_display_name(base, &encode_uid(&uid))
+ .map_err(Into::into)
+ .and_then(|request| {
+ HTTP_CLIENT
+ .get_client()?
+ .execute(request)?
+ .json::<GetDisplayNameResponse>()
+ .map_err(Into::into)
+ });
- Ok(())
+ match query {
+ Ok(response) => {
+ let name = response.displayname.unwrap_or(uid);
+ let _ = tx.send(BKResponse::Name(name));
+ }
+ Err(err) => {
+ let _ = tx.send(BKResponse::UserNameError(err));
+ }
+ }
+ });
}
-pub fn set_username(bk: &Backend, name: String) -> Result<(), Error> {
- let id = bk.data.lock().unwrap().user_id.clone();
- let url = bk.url(&format!("profile/{}/displayname", encode_uid(&id)), vec![])?;
+// FIXME: This function manages errors *really* wrong and isn't more async
+// than the normal function. It should be removed.
+pub fn get_username_async(bk: &Backend, uid: String, tx: Sender<String>) {
+ let base = bk.get_base_url();
+
+ thread::spawn(move || {
+ let query = get_display_name(base, &encode_uid(&uid))
+ .map_err::<Error, _>(Into::into)
+ .and_then(|request| {
+ HTTP_CLIENT
+ .get_client()?
+ .execute(request)?
+ .json::<GetDisplayNameResponse>()
+ .map_err(Into::into)
+ });
+
+ match query {
+ Ok(response) => {
+ let name = response.displayname.unwrap_or(uid);
+ let _ = tx.send(name);
+ }
+ Err(_) => {
+ let _ = tx.send(uid);
+ }
+ }
+ });
+}
- let attrs = PutDisplayNameRequest {
+pub fn set_username(bk: &Backend, name: String) {
+ let tx = bk.tx.clone();
+
+ let base = bk.get_base_url();
+ let access_token = bk.data.lock().unwrap().access_token.clone();
+ let uid = bk.data.lock().unwrap().user_id.clone();
+ let params = SetDisplayNameParameters { access_token };
+ let body = SetDisplayNameBody {
displayname: Some(name.clone()),
};
- let attrs_json =
- serde_json::to_value(attrs).expect("Failed to serialize display name setting request");
- let tx = bk.tx.clone();
- query!(
- "put",
- &url,
- &attrs_json,
- |_| {
- tx.send(BKResponse::SetUserName(name)).unwrap();
- },
- |err| {
- tx.send(BKResponse::SetUserNameError(err)).unwrap();
- }
- );
+ thread::spawn(move || {
+ let query = set_display_name(base, ¶ms, &body, &encode_uid(&uid))
+ .map_err(Into::into)
+ .and_then(|request| {
+ HTTP_CLIENT
+ .get_client()?
+ .execute(request)
+ .map_err(Into::into)
+ });
- Ok(())
+ match query {
+ Ok(_) => {
+ let _ = tx.send(BKResponse::SetUserName(name));
+ }
+ Err(err) => {
+ let _ = tx.send(BKResponse::SetUserNameError(err));
+ }
+ }
+ });
}
-pub fn get_threepid(bk: &Backend) -> Result<(), Error> {
- let url = bk.url(&format!("account/3pid"), vec![])?;
+pub fn get_threepid(bk: &Backend) {
let tx = bk.tx.clone();
- get!(
- &url,
- |r: JsonValue| if let Ok(response) = serde_json::from_value::<ThirdPartyIDResponse>(r) {
- tx.send(BKResponse::GetThreePID(response.threepids))
- .unwrap();
- } else {
- tx.send(BKResponse::GetThreePIDError(Error::BackendError))
- .unwrap();
- },
- |err| tx.send(BKResponse::GetThreePIDError(err)).unwrap()
- );
- Ok(())
+ let base = bk.get_base_url();
+ let access_token = bk.data.lock().unwrap().access_token.clone();
+ let params = ThirdPartyIDParameters { access_token };
+
+ thread::spawn(move || {
+ let query = get_identifiers(base, ¶ms)
+ .map_err(Into::into)
+ .and_then(|request| {
+ HTTP_CLIENT
+ .get_client()?
+ .execute(request)?
+ .json::<ThirdPartyIDResponse>()
+ .map_err(Into::into)
+ });
+
+ match query {
+ Ok(response) => {
+ let _ = tx.send(BKResponse::GetThreePID(response.threepids));
+ }
+ Err(err) => {
+ let _ = tx.send(BKResponse::GetThreePIDError(err));
+ }
+ }
+ });
}
-pub fn get_email_token(
- bk: &Backend,
- identity: String,
- email: String,
- client_secret: String,
-) -> Result<(), Error> {
- let url = bk.url("account/3pid/email/requestToken", vec![])?;
+pub fn get_email_token(bk: &Backend, identity: String, email: String, client_secret: String) {
+ let tx = bk.tx.clone();
- let attrs = EmailTokenRequest {
+ let base = bk.get_base_url();
+ let access_token = bk.data.lock().unwrap().access_token.clone();
+ let params = EmailTokenParameters { access_token };
+ let body = EmailTokenBody {
id_server: identity[8..].into(),
client_secret: client_secret.clone(),
- email: email,
+ email,
send_attempt: 1,
next_link: None,
};
- let attrs_json = serde_json::to_value(attrs).expect("Failed to serialize email token request");
+ thread::spawn(move || {
+ let query = request_contact_verification_token_email(base, ¶ms, &body)
+ .map_err(Into::into)
+ .and_then(|request| {
+ HTTP_CLIENT
+ .get_client()?
+ .execute(request)?
+ .json::<EmailTokenResponse>()
+ .map_err(Into::into)
+ });
- let tx = bk.tx.clone();
- post!(
- &url,
- &attrs_json,
- |r: JsonValue| if let Ok(response) = serde_json::from_value::<ThirdPartyTokenResponse>(r) {
- tx.send(BKResponse::GetTokenEmail(response.sid, client_secret))
- .unwrap();
- } else {
- tx.send(BKResponse::GetTokenEmailError(Error::BackendError))
- .unwrap();
- },
- |err| match err {
- Error::MatrixError(ref js)
+ match query {
+ Ok(response) => {
+ let _ = tx.send(BKResponse::GetTokenEmail(response.sid, client_secret));
+ }
+ Err(Error::MatrixError(ref js))
if js["errcode"].as_str().unwrap_or_default() == "M_THREEPID_IN_USE" =>
{
- tx.send(BKResponse::GetTokenEmailUsed).unwrap();
+ let _ = tx.send(BKResponse::GetTokenEmailUsed);
}
- _ => {
- tx.send(BKResponse::GetTokenEmailError(err)).unwrap();
+ Err(err) => {
+ let _ = tx.send(BKResponse::GetTokenEmailError(err));
}
}
- );
-
- Ok(())
+ });
}
-pub fn get_phone_token(
- bk: &Backend,
- identity: String,
- phone: String,
- client_secret: String,
-) -> Result<(), Error> {
- let url = bk.url(&format!("account/3pid/msisdn/requestToken"), vec![])?;
+pub fn get_phone_token(bk: &Backend, identity: String, phone: String, client_secret: String) {
+ let tx = bk.tx.clone();
- let attrs = PhoneTokenRequest {
+ let base = bk.get_base_url();
+ let access_token = bk.data.lock().unwrap().access_token.clone();
+ let params = PhoneTokenParameters { access_token };
+ let body = PhoneTokenBody {
id_server: identity[8..].into(),
client_secret: client_secret.clone(),
phone_number: phone,
@@ -166,42 +234,40 @@ pub fn get_phone_token(
next_link: None,
};
- let attrs_json = serde_json::to_value(attrs).expect("Failed to serialize phone token request");
+ thread::spawn(move || {
+ let query = request_contact_verification_token_msisdn(base, ¶ms, &body)
+ .map_err(Into::into)
+ .and_then(|request| {
+ HTTP_CLIENT
+ .get_client()?
+ .execute(request)?
+ .json::<PhoneTokenResponse>()
+ .map_err(Into::into)
+ });
- let tx = bk.tx.clone();
- post!(
- &url,
- &attrs_json,
- |r: JsonValue| if let Ok(response) = serde_json::from_value::<ThirdPartyTokenResponse>(r) {
- tx.send(BKResponse::GetTokenPhone(response.sid, client_secret))
- .unwrap();
- } else {
- tx.send(BKResponse::GetTokenPhoneError(Error::BackendError))
- .unwrap();
- },
- |err| match err {
- Error::MatrixError(ref js)
+ match query {
+ Ok(response) => {
+ let _ = tx.send(BKResponse::GetTokenPhone(response.sid, client_secret));
+ }
+ Err(Error::MatrixError(ref js))
if js["errcode"].as_str().unwrap_or_default() == "M_THREEPID_IN_USE" =>
{
- tx.send(BKResponse::GetTokenPhoneUsed).unwrap();
+ let _ = tx.send(BKResponse::GetTokenPhoneUsed);
}
- _ => {
- tx.send(BKResponse::GetTokenPhoneError(err)).unwrap();
+ Err(err) => {
+ let _ = tx.send(BKResponse::GetTokenPhoneError(err));
}
}
- );
-
- Ok(())
+ });
}
-pub fn add_threepid(
- bk: &Backend,
- identity: String,
- client_secret: String,
- sid: String,
-) -> Result<(), Error> {
- let url = bk.url(&format!("account/3pid"), vec![])?;
- let attrs = AddThreePIDRequest {
+pub fn add_threepid(bk: &Backend, identity: String, client_secret: String, sid: String) {
+ let tx = bk.tx.clone();
+
+ let base = bk.get_base_url();
+ let access_token = bk.data.lock().unwrap().access_token.clone();
+ let params = AddThreePIDParameters { access_token };
+ let body = AddThreePIDBody {
three_pid_creds: ThreePIDCredentials {
id_server: identity[8..].into(),
sid: sid.clone(),
@@ -210,97 +276,96 @@ pub fn add_threepid(
bind: true,
};
- let attrs_json = serde_json::to_value(attrs)
- .expect("Failed to serialize add third party information request");
+ thread::spawn(move || {
+ let query = create_contact(base, ¶ms, &body)
+ .map_err(Into::into)
+ .and_then(|request| {
+ HTTP_CLIENT
+ .get_client()?
+ .execute(request)
+ .map_err(Into::into)
+ });
- let tx = bk.tx.clone();
- post!(
- &url,
- &attrs_json,
- |_| {
- tx.send(BKResponse::AddThreePID(sid)).unwrap();
- },
- |err| {
- tx.send(BKResponse::AddThreePIDError(err)).unwrap();
+ match query {
+ Ok(_) => {
+ let _ = tx.send(BKResponse::AddThreePID(sid));
+ }
+ Err(err) => {
+ let _ = tx.send(BKResponse::AddThreePIDError(err));
+ }
}
- );
-
- Ok(())
+ });
}
-pub fn submit_phone_token(
- bk: &Backend,
- url: &str,
- client_secret: String,
- sid: String,
- token: String,
-) -> Result<(), Error> {
- let path = "/_matrix/identity/api/v1/validate/msisdn/submitToken";
- let url = build_url(&Url::parse(url)?, path, &[])?;
-
- let attrs = SubmitPhoneTokenRequest {
+pub fn submit_phone_token(bk: &Backend, client_secret: String, sid: String, token: String) {
+ let tx = bk.tx.clone();
+
+ let base = bk.get_base_url();
+ let body = SubmitPhoneTokenBody {
sid: sid.clone(),
client_secret: client_secret.clone(),
token,
};
- let attrs_json =
- serde_json::to_value(attrs).expect("Failed to serialize phone token submit request");
- let tx = bk.tx.clone();
- post!(
- &url,
- &attrs_json,
- |r: JsonValue| if let Ok(response) = serde_json::from_value::<SubmitPhoneTokenResponse>(r) {
- let result = Some(sid).filter(|_| response.success);
- tx.send(BKResponse::SubmitPhoneToken(result, client_secret))
- .unwrap();
- } else {
- tx.send(BKResponse::SubmitPhoneTokenError(Error::BackendError))
- .unwrap();
- },
- |err| {
- tx.send(BKResponse::SubmitPhoneTokenError(err)).unwrap();
- }
- );
+ thread::spawn(move || {
+ let query = submit_phone_token_req(base, &body)
+ .map_err(Into::into)
+ .and_then(|request| {
+ HTTP_CLIENT
+ .get_client()?
+ .execute(request)?
+ .json::<SubmitPhoneTokenResponse>()
+ .map_err(Into::into)
+ });
- Ok(())
+ match query {
+ Ok(response) => {
+ let result = Some(sid).filter(|_| response.success);
+ let _ = tx.send(BKResponse::SubmitPhoneToken(result, client_secret));
+ }
+ Err(err) => {
+ let _ = tx.send(BKResponse::SubmitPhoneTokenError(err));
+ }
+ }
+ });
}
pub fn delete_three_pid(bk: &Backend, medium: Medium, address: String) {
- let baseu = bk.get_base_url();
- let tk = bk.data.lock().unwrap().access_token.clone();
- let mut url = baseu
- .join("/_matrix/client/r0/account/3pid/delete")
- .expect("Wrong URL in delete_three_pid()");
- url.query_pairs_mut()
- .clear()
- .append_pair("access_token", &tk);
- let attrs = DeleteThreePIDRequest { medium, address };
-
- let attrs_json =
- serde_json::to_value(attrs).expect("Failed to serialize third party ID delete request");
let tx = bk.tx.clone();
- post!(
- &url,
- &attrs_json,
- |_r: JsonValue| {
- tx.send(BKResponse::DeleteThreePID).unwrap();
- },
- |err| {
- tx.send(BKResponse::DeleteThreePIDError(err)).unwrap();
+
+ let base = bk.get_base_url();
+ let access_token = bk.data.lock().unwrap().access_token.clone();
+ let params = DeleteThreePIDParameters { access_token };
+ let body = DeleteThreePIDBody { address, medium };
+
+ thread::spawn(move || {
+ let query = delete_contact(base, ¶ms, &body)
+ .map_err(Into::into)
+ .and_then(|request| {
+ HTTP_CLIENT
+ .get_client()?
+ .execute(request)
+ .map_err(Into::into)
+ });
+
+ match query {
+ Ok(_) => {
+ let _ = tx.send(BKResponse::DeleteThreePID);
+ }
+ Err(err) => {
+ let _ = tx.send(BKResponse::DeleteThreePIDError(err));
+ }
}
- );
+ });
}
-pub fn change_password(
- bk: &Backend,
- user: String,
- old_password: String,
- new_password: String,
-) -> Result<(), Error> {
- let url = bk.url(&format!("account/password"), vec![])?;
+pub fn change_password(bk: &Backend, user: String, old_password: String, new_password: String) {
+ let tx = bk.tx.clone();
- let attrs = ChangePasswordRequest {
+ let access_token = bk.data.lock().unwrap().access_token.clone();
+ let base = bk.get_base_url();
+ let params = ChangePasswordParameters { access_token };
+ let body = ChangePasswordBody {
new_password,
auth: Some(AuthenticationData::Password {
identifier: Identifier::new(UserIdentifier::User { user }),
@@ -309,28 +374,34 @@ pub fn change_password(
}),
};
- let attrs_json =
- serde_json::to_value(attrs).expect("Failed to serialize password change request");
- let tx = bk.tx.clone();
- post!(
- &url,
- &attrs_json,
- |r: JsonValue| {
- info!("{}", r);
- tx.send(BKResponse::ChangePassword).unwrap();
- },
- |err| {
- tx.send(BKResponse::ChangePasswordError(err)).unwrap();
- }
- );
+ thread::spawn(move || {
+ let query = change_password_req(base, ¶ms, &body)
+ .map_err(Into::into)
+ .and_then(|request| {
+ HTTP_CLIENT
+ .get_client()?
+ .execute(request)
+ .map_err(Into::into)
+ });
- Ok(())
+ match query {
+ Ok(_) => {
+ let _ = tx.send(BKResponse::ChangePassword);
+ }
+ Err(err) => {
+ let _ = tx.send(BKResponse::ChangePasswordError(err));
+ }
+ }
+ });
}
-pub fn account_destruction(bk: &Backend, user: String, password: String) -> Result<(), Error> {
- let url = bk.url(&format!("account/deactivate"), vec![])?;
+pub fn account_destruction(bk: &Backend, user: String, password: String) {
+ let tx = bk.tx.clone();
- let attrs = DeactivateAccountRequest {
+ let base = bk.get_base_url();
+ let access_token = bk.data.lock().unwrap().access_token.clone();
+ let params = DeactivateParameters { access_token };
+ let body = DeactivateBody {
auth: Some(AuthenticationData::Password {
identifier: Identifier::new(UserIdentifier::User { user }),
password,
@@ -338,49 +409,120 @@ pub fn account_destruction(bk: &Backend, user: String, password: String) -> Resu
}),
};
- let attrs_json =
- serde_json::to_value(attrs).expect("Failed to serialize account deactivation request");
- let tx = bk.tx.clone();
- post!(
- &url,
- &attrs_json,
- |r: JsonValue| {
- info!("{}", r);
- tx.send(BKResponse::AccountDestruction).unwrap();
- },
- |err| {
- tx.send(BKResponse::AccountDestructionError(err)).unwrap();
- }
- );
+ thread::spawn(move || {
+ let query = deactivate(base, ¶ms, &body)
+ .map_err(Into::into)
+ .and_then(|request| {
+ HTTP_CLIENT
+ .get_client()?
+ .execute(request)
+ .map_err(Into::into)
+ });
- Ok(())
+ match query {
+ Ok(_) => {
+ let _ = tx.send(BKResponse::AccountDestruction);
+ }
+ Err(err) => {
+ let _ = tx.send(BKResponse::AccountDestructionError(err));
+ }
+ }
+ });
}
-pub fn get_avatar(bk: &Backend) -> Result<(), Error> {
- let baseu = bk.get_base_url();
+pub fn get_avatar(bk: &Backend) {
+ let base = bk.get_base_url();
let userid = bk.data.lock().unwrap().user_id.clone();
let tx = bk.tx.clone();
- thread::spawn(move || match get_user_avatar(&baseu, &userid) {
+ thread::spawn(move || match get_user_avatar(&base, &userid) {
Ok((_, fname)) => {
- tx.send(BKResponse::Avatar(fname)).unwrap();
+ let _ = tx.send(BKResponse::Avatar(fname));
}
Err(err) => {
- tx.send(BKResponse::AvatarError(err)).unwrap();
+ let _ = tx.send(BKResponse::AvatarError(err));
}
});
+}
+
+pub fn get_avatar_async(bk: &Backend, member: Option<Member>, tx: Sender<String>) {
+ if let Some(member) = member {
+ let base = bk.get_base_url();
+ let uid = member.uid.clone();
+ let avatar = member.avatar.clone().unwrap_or_default();
+
+ semaphore(
+ bk.limit_threads.clone(),
+ move || match get_user_avatar_img(&base, &uid, &avatar) {
+ Ok(fname) => {
+ let _ = tx.send(fname);
+ }
+ Err(_) => {
+ let _ = tx.send(Default::default());
+ }
+ },
+ );
+ } else {
+ let _ = tx.send(Default::default());
+ }
+}
+
+pub fn set_user_avatar(bk: &Backend, avatar: String) {
+ let tx = bk.tx.clone();
- Ok(())
+ let base = bk.get_base_url();
+ let id = bk.data.lock().unwrap().user_id.clone();
+ let access_token = bk.data.lock().unwrap().access_token.clone();
+ let params_upload = CreateContentParameters {
+ access_token: access_token.clone(),
+ filename: None,
+ };
+
+ thread::spawn(move || {
+ let query = fs::read(&avatar).map_err(Into::into).and_then(|contents| {
+ let (mime, _) = gio::content_type_guess(None, &contents);
+ let mime_value = HeaderValue::from_str(&mime).or(Err(Error::BackendError))?;
+ let upload_response =
+ create_content(base.clone(), ¶ms_upload, contents, Some(mime_value))
+ .map_err::<Error, _>(Into::into)
+ .and_then(|request| {
+ HTTP_CLIENT
+ .get_client()?
+ .execute(request)?
+ .json::<CreateContentResponse>()
+ .map_err(Into::into)
+ })?;
+
+ let params_avatar = SetAvatarUrlParameters { access_token };
+ let body = SetAvatarUrlBody {
+ avatar_url: Some(upload_response.content_uri),
+ };
+
+ set_avatar_url(base, ¶ms_avatar, &body, &encode_uid(&id))
+ .map_err(Into::into)
+ .and_then(|request| {
+ HTTP_CLIENT
+ .get_client()?
+ .execute(request)
+ .map_err(Into::into)
+ })
+ });
+
+ match query {
+ Ok(_) => {
+ let _ = tx.send(BKResponse::SetUserAvatar(avatar));
+ }
+ Err(err) => {
+ let _ = tx.send(BKResponse::SetUserAvatarError(err));
+ }
+ }
+ });
}
-pub fn get_user_info_async(
- bk: &mut Backend,
- uid: &str,
- tx: Option<Sender<(String, String)>>,
-) -> Result<(), Error> {
+pub fn get_user_info_async(bk: &mut Backend, uid: &str, tx: Option<Sender<(String, String)>>) {
let baseu = bk.get_base_url();
- let u = String::from(uid);
+ let u = uid.to_string();
if let Some(info) = bk.user_info_cache.get(&u) {
if let Some(tx) = tx.clone() {
@@ -390,7 +532,7 @@ pub fn get_user_info_async(
tx.send(i).unwrap();
});
}
- return Ok(());
+ return;
}
let info = Arc::new(Mutex::new((String::new(), String::new())));
@@ -417,118 +559,38 @@ pub fn get_user_info_async(
});
bk.user_info_cache.insert(cache_key, cache_value);
-
- Ok(())
-}
-
-pub fn get_username_async(bk: &Backend, uid: String, tx: Sender<String>) -> Result<(), Error> {
- let url = bk.url(&format!("profile/{}/displayname", encode_uid(&uid)), vec![])?;
- get!(
- &url,
- |r: JsonValue| if let Ok(response) = serde_json::from_value::<GetDisplayNameResponse>(r) {
- let name = response.displayname.unwrap_or(uid);
- tx.send(name).unwrap();
- } else {
- tx.send(uid.to_string()).unwrap();
- },
- |_| tx.send(uid.to_string()).unwrap()
- );
-
- Ok(())
-}
-
-pub fn get_avatar_async(
- bk: &Backend,
- member: Option<Member>,
- tx: Sender<String>,
-) -> Result<(), Error> {
- let baseu = bk.get_base_url();
-
- if member.is_none() {
- tx.send(String::new()).unwrap();
- return Ok(());
- }
-
- let m = member.unwrap();
-
- let uid = m.uid.clone();
- let avatar = m.avatar.clone();
-
- semaphore(bk.limit_threads.clone(), move || match get_user_avatar_img(
- &baseu,
- &uid,
- &avatar.unwrap_or_default(),
- ) {
- Ok(fname) => {
- tx.send(fname.clone()).unwrap();
- }
- Err(_) => {
- tx.send(String::new()).unwrap();
- }
- });
-
- Ok(())
}
-pub fn set_user_avatar(bk: &Backend, avatar: String) -> Result<(), Error> {
- let baseu = bk.get_base_url();
- let id = bk.data.lock().unwrap().user_id.clone();
- let tk = bk.data.lock().unwrap().access_token.clone();
- let params = &[("access_token", tk.clone())];
- let mediaurl = media_url(&baseu, "upload", params)?;
- let url = bk.url(&format!("profile/{}/avatar_url", encode_uid(&id)), vec![])?;
-
- let mut file = File::open(&avatar)?;
- let mut contents: Vec<u8> = vec![];
- file.read_to_end(&mut contents)?;
-
+pub fn search(bk: &Backend, search_term: String) {
let tx = bk.tx.clone();
- thread::spawn(move || {
- match put_media(mediaurl.as_str(), contents) {
- Err(err) => {
- tx.send(BKResponse::SetUserAvatarError(err)).unwrap();
- }
- Ok(js) => {
- let uri = js["content_uri"].as_str().unwrap_or_default();
- let attrs = json!({ "avatar_url": uri });
- put!(
- &url,
- &attrs,
- |_| tx.send(BKResponse::SetUserAvatar(avatar)).unwrap(),
- |err| tx.send(BKResponse::SetUserAvatarError(err)).unwrap()
- );
- }
- };
- });
-
- Ok(())
-}
-pub fn search(bk: &Backend, search_term: String) -> Result<(), Error> {
- let url = bk.url(&format!("user_directory/search"), vec![])?;
-
- let attrs = SearchUserRequest {
+ let base = bk.get_base_url();
+ let access_token = bk.data.lock().unwrap().access_token.clone();
+ let params = UserDirectoryParameters { access_token };
+ let body = UserDirectoryBody {
search_term,
..Default::default()
};
- let attrs_json =
- serde_json::to_value(attrs).expect("Failed to serialize user directory search request");
- let tx = bk.tx.clone();
- post!(
- &url,
- &attrs_json,
- |r: JsonValue| if let Ok(response) = serde_json::from_value::<SearchUserResponse>(r) {
- let users = response.results.into_iter().map(Into::into).collect();
- tx.send(BKResponse::UserSearch(users)).unwrap();
- } else {
- tx.send(BKResponse::CommandError(Error::BackendError))
- .unwrap();
- },
- |err| {
- tx.send(BKResponse::CommandError(err)).unwrap();
- }
- );
+ thread::spawn(move || {
+ let query = user_directory(base, ¶ms, &body)
+ .map_err(Into::into)
+ .and_then(|request| {
+ HTTP_CLIENT
+ .get_client()?
+ .execute(request)?
+ .json::<UserDirectoryResponse>()
+ .map_err(Into::into)
+ });
- Ok(())
+ match query {
+ Ok(response) => {
+ let users = response.results.into_iter().map(Into::into).collect();
+ let _ = tx.send(BKResponse::UserSearch(users));
+ }
+ Err(err) => {
+ let _ = tx.send(BKResponse::CommandError(err));
+ }
+ }
+ });
}
diff --git a/fractal-matrix-api/src/identity.rs b/fractal-matrix-api/src/identity.rs
new file mode 100644
index 00000000..026b9976
--- /dev/null
+++ b/fractal-matrix-api/src/identity.rs
@@ -0,0 +1 @@
+pub mod r0;
diff --git a/fractal-matrix-api/src/identity/r0.rs b/fractal-matrix-api/src/identity/r0.rs
new file mode 100644
index 00000000..6cddc6e6
--- /dev/null
+++ b/fractal-matrix-api/src/identity/r0.rs
@@ -0,0 +1 @@
+pub mod association;
diff --git a/fractal-matrix-api/src/identity/r0/association.rs
b/fractal-matrix-api/src/identity/r0/association.rs
new file mode 100644
index 00000000..6872e520
--- /dev/null
+++ b/fractal-matrix-api/src/identity/r0/association.rs
@@ -0,0 +1 @@
+pub mod msisdn;
diff --git a/fractal-matrix-api/src/identity/r0/association/msisdn.rs
b/fractal-matrix-api/src/identity/r0/association/msisdn.rs
new file mode 100644
index 00000000..73f1eccd
--- /dev/null
+++ b/fractal-matrix-api/src/identity/r0/association/msisdn.rs
@@ -0,0 +1 @@
+pub mod submit_token;
diff --git a/fractal-matrix-api/src/identity/r0/association/msisdn/submit_token.rs
b/fractal-matrix-api/src/identity/r0/association/msisdn/submit_token.rs
new file mode 100644
index 00000000..7d7a47eb
--- /dev/null
+++ b/fractal-matrix-api/src/identity/r0/association/msisdn/submit_token.rs
@@ -0,0 +1,25 @@
+use reqwest::Client;
+use reqwest::Error;
+use reqwest::Request;
+use serde::{Deserialize, Serialize};
+use url::Url;
+
+#[derive(Clone, Debug, Serialize)]
+pub struct Body {
+ pub sid: String,
+ pub client_secret: String,
+ pub token: String,
+}
+
+#[derive(Clone, Debug, Deserialize)]
+pub struct Response {
+ pub success: bool,
+}
+
+pub fn request(base: Url, body: &Body) -> Result<Request, Error> {
+ let url = base
+ .join("/_matrix/identity/api/v1/validate/msisdn/submitToken")
+ .expect("Malformed URL in msisdn submit_token");
+
+ Client::new().post(url).json(body).build()
+}
diff --git a/fractal-matrix-api/src/lib.rs b/fractal-matrix-api/src/lib.rs
index 8f600d45..bc71a688 100644
--- a/fractal-matrix-api/src/lib.rs
+++ b/fractal-matrix-api/src/lib.rs
@@ -6,6 +6,7 @@ pub mod globals;
pub mod backend;
pub mod cache;
mod client;
+pub mod identity;
mod model;
pub mod r0;
mod ser;
diff --git a/fractal-matrix-api/src/meson.build b/fractal-matrix-api/src/meson.build
index 8a65d647..937aff55 100644
--- a/fractal-matrix-api/src/meson.build
+++ b/fractal-matrix-api/src/meson.build
@@ -8,6 +8,10 @@ api_sources = files(
'backend/sync.rs',
'backend/types.rs',
'backend/user.rs',
+ 'identity/r0/association/msisdn/submit_token.rs',
+ 'identity/r0/association/msisdn.rs',
+ 'identity/r0/association.rs',
+ 'identity/r0.rs',
'model/event.rs',
'model/fileinfo.rs',
'model/member.rs',
@@ -15,17 +19,33 @@ api_sources = files(
'model/mod.rs',
'model/room.rs',
'model/stickers.rs',
- 'model/user.rs',
+ 'r0/account/change_password.rs',
+ 'r0/account/deactivate.rs',
'r0/account/login.rs',
'r0/account/logout.rs',
'r0/account/register.rs',
+ 'r0/contact/create.rs',
+ 'r0/contact/delete.rs',
+ 'r0/contact/get_identifiers.rs',
+ 'r0/contact/request_verification_token_email.rs',
+ 'r0/contact/request_verification_token_msisdn.rs',
'r0/directory/post_public_rooms.rs',
+ 'r0/media/create.rs',
+ 'r0/profile/get_display_name.rs',
+ 'r0/profile/get_profile.rs',
+ 'r0/profile/set_avatar_url.rs',
+ 'r0/profile/set_display_name.rs',
+ 'r0/search/user.rs',
'r0/server/domain_info.rs',
'r0/sync/sync_events.rs',
'r0/thirdparty/get_supported_protocols.rs',
'r0/account.rs',
+ 'r0/contact.rs',
'r0/directory.rs',
'r0/filter.rs',
+ 'r0/media.rs',
+ 'r0/profile.rs',
+ 'r0/search.rs',
'r0/server.rs',
'r0/sync.rs',
'r0/thirdparty.rs',
@@ -33,6 +53,7 @@ api_sources = files(
'client.rs',
'error.rs',
'globals.rs',
+ 'identity.rs',
'lib.rs',
'r0.rs',
'ser.rs',
diff --git a/fractal-matrix-api/src/model/member.rs b/fractal-matrix-api/src/model/member.rs
index a2ff4b1b..fd1fbfd5 100644
--- a/fractal-matrix-api/src/model/member.rs
+++ b/fractal-matrix-api/src/model/member.rs
@@ -1,4 +1,4 @@
-use crate::types::User;
+use crate::r0::search::user::User;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
diff --git a/fractal-matrix-api/src/model/mod.rs b/fractal-matrix-api/src/model/mod.rs
index 14db5456..836fd935 100644
--- a/fractal-matrix-api/src/model/mod.rs
+++ b/fractal-matrix-api/src/model/mod.rs
@@ -4,4 +4,3 @@ pub mod member;
pub mod message;
pub mod room;
pub mod stickers;
-pub mod user;
diff --git a/fractal-matrix-api/src/r0.rs b/fractal-matrix-api/src/r0.rs
index 13090a6c..86c74a3a 100644
--- a/fractal-matrix-api/src/r0.rs
+++ b/fractal-matrix-api/src/r0.rs
@@ -1,6 +1,26 @@
pub mod account;
+pub mod contact;
pub mod directory;
pub mod filter;
+pub mod media;
+pub mod profile;
+pub mod search;
pub mod server;
pub mod sync;
pub mod thirdparty;
+
+use serde::{Deserialize, Serialize};
+
+#[derive(Clone, Debug, Deserialize, Serialize)]
+#[serde(rename = "lowercase")]
+pub enum Medium {
+ Email,
+ MsIsdn,
+}
+
+#[derive(Clone, Debug, Serialize)]
+pub struct ThreePIDCredentials {
+ pub client_secret: String,
+ pub id_server: String,
+ pub sid: String,
+}
diff --git a/fractal-matrix-api/src/r0/account.rs b/fractal-matrix-api/src/r0/account.rs
index 3cad3482..9e4b667d 100644
--- a/fractal-matrix-api/src/r0/account.rs
+++ b/fractal-matrix-api/src/r0/account.rs
@@ -1,16 +1,11 @@
+pub mod change_password;
+pub mod deactivate;
pub mod login;
pub mod logout;
pub mod register;
-use serde::{Deserialize, Serialize};
-
-#[derive(Clone, Debug, Deserialize, Serialize)]
-pub enum Medium {
- #[serde(rename = "email")]
- Email,
- #[serde(rename = "msisdn")]
- MsIsdn,
-}
+use crate::r0::{Medium, ThreePIDCredentials};
+use serde::Serialize;
#[derive(Clone, Debug, Serialize)]
#[serde(tag = "type")]
@@ -66,13 +61,6 @@ impl Identifier {
}
}
-#[derive(Clone, Debug, Serialize)]
-pub struct ThreePIDCredentials {
- pub client_secret: String,
- pub id_server: String,
- pub sid: String,
-}
-
#[derive(Clone, Debug, Serialize)]
#[serde(tag = "type")]
pub enum AuthenticationData {
diff --git a/fractal-matrix-api/src/r0/account/change_password.rs
b/fractal-matrix-api/src/r0/account/change_password.rs
new file mode 100644
index 00000000..21e9cd01
--- /dev/null
+++ b/fractal-matrix-api/src/r0/account/change_password.rs
@@ -0,0 +1,27 @@
+use super::AuthenticationData;
+use reqwest::Client;
+use reqwest::Error;
+use reqwest::Request;
+use serde::Serialize;
+use url::Url;
+
+#[derive(Clone, Debug, Serialize)]
+pub struct Parameters {
+ #[serde(skip_serializing_if = "String::is_empty")]
+ pub access_token: String,
+}
+
+#[derive(Clone, Debug, Serialize)]
+pub struct Body {
+ pub new_password: String,
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub auth: Option<AuthenticationData>,
+}
+
+pub fn request(base: Url, params: &Parameters, body: &Body) -> Result<Request, Error> {
+ let url = base
+ .join("/_matrix/client/r0/account/password")
+ .expect("Malformed URL in change_password");
+
+ Client::new().post(url).query(params).json(body).build()
+}
diff --git a/fractal-matrix-api/src/r0/account/deactivate.rs b/fractal-matrix-api/src/r0/account/deactivate.rs
new file mode 100644
index 00000000..6a322a80
--- /dev/null
+++ b/fractal-matrix-api/src/r0/account/deactivate.rs
@@ -0,0 +1,26 @@
+use super::AuthenticationData;
+use reqwest::Client;
+use reqwest::Error;
+use reqwest::Request;
+use serde::Serialize;
+use url::Url;
+
+#[derive(Clone, Debug, Serialize)]
+pub struct Parameters {
+ #[serde(skip_serializing_if = "String::is_empty")]
+ pub access_token: String,
+}
+
+#[derive(Clone, Debug, Serialize)]
+pub struct Body {
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub auth: Option<AuthenticationData>,
+}
+
+pub fn request(base: Url, params: &Parameters, body: &Body) -> Result<Request, Error> {
+ let url = base
+ .join("/_matrix/client/r0/account/deactivate")
+ .expect("Malformed URL in deactivate");
+
+ Client::new().post(url).query(params).json(body).build()
+}
diff --git a/fractal-matrix-api/src/r0/contact.rs b/fractal-matrix-api/src/r0/contact.rs
new file mode 100644
index 00000000..972b7381
--- /dev/null
+++ b/fractal-matrix-api/src/r0/contact.rs
@@ -0,0 +1,5 @@
+pub mod create;
+pub mod delete;
+pub mod get_identifiers;
+pub mod request_verification_token_email;
+pub mod request_verification_token_msisdn;
diff --git a/fractal-matrix-api/src/r0/contact/create.rs b/fractal-matrix-api/src/r0/contact/create.rs
new file mode 100644
index 00000000..76db1892
--- /dev/null
+++ b/fractal-matrix-api/src/r0/contact/create.rs
@@ -0,0 +1,27 @@
+use crate::r0::ThreePIDCredentials;
+use reqwest::Client;
+use reqwest::Error;
+use reqwest::Request;
+use serde::Serialize;
+use std::ops::Not;
+use url::Url;
+
+#[derive(Debug, Clone, Serialize)]
+pub struct Parameters {
+ pub access_token: String,
+}
+
+#[derive(Clone, Debug, Serialize)]
+pub struct Body {
+ pub three_pid_creds: ThreePIDCredentials,
+ #[serde(skip_serializing_if = "Not::not")]
+ pub bind: bool,
+}
+
+pub fn request(base: Url, params: &Parameters, body: &Body) -> Result<Request, Error> {
+ let url = base
+ .join("/_matrix/client/r0/account/3pid")
+ .expect("Malformed URL in contact create");
+
+ Client::new().post(url).query(params).json(body).build()
+}
diff --git a/fractal-matrix-api/src/r0/contact/delete.rs b/fractal-matrix-api/src/r0/contact/delete.rs
new file mode 100644
index 00000000..541b0058
--- /dev/null
+++ b/fractal-matrix-api/src/r0/contact/delete.rs
@@ -0,0 +1,25 @@
+use crate::r0::Medium;
+use reqwest::Client;
+use reqwest::Error;
+use reqwest::Request;
+use serde::Serialize;
+use url::Url;
+
+#[derive(Debug, Clone, Serialize)]
+pub struct Parameters {
+ pub access_token: String,
+}
+
+#[derive(Clone, Debug, Serialize)]
+pub struct Body {
+ pub address: String,
+ pub medium: Medium,
+}
+
+pub fn request(base: Url, params: &Parameters, body: &Body) -> Result<Request, Error> {
+ let url = base
+ .join("/_matrix/client/r0/account/3pid/delete")
+ .expect("Malformed URL in contact delete");
+
+ Client::new().post(url).query(params).json(body).build()
+}
diff --git a/fractal-matrix-api/src/r0/contact/get_identifiers.rs
b/fractal-matrix-api/src/r0/contact/get_identifiers.rs
new file mode 100644
index 00000000..50d1d1d6
--- /dev/null
+++ b/fractal-matrix-api/src/r0/contact/get_identifiers.rs
@@ -0,0 +1,33 @@
+use crate::r0::Medium;
+use reqwest::Client;
+use reqwest::Error;
+use reqwest::Request;
+use serde::{Deserialize, Serialize};
+use url::Url;
+
+#[derive(Debug, Clone, Serialize)]
+pub struct Parameters {
+ pub access_token: String,
+}
+
+#[derive(Debug, Clone, Deserialize)]
+pub struct Response {
+ #[serde(default)]
+ pub threepids: Vec<ThirdPartyIdentifier>,
+}
+
+#[derive(Debug, Clone, Deserialize)]
+pub struct ThirdPartyIdentifier {
+ pub added_at: u64,
+ pub medium: Medium,
+ pub validated_at: u64,
+ pub address: String,
+}
+
+pub fn request(base: Url, params: &Parameters) -> Result<Request, Error> {
+ let url = base
+ .join("/_matrix/client/r0/account/3pid")
+ .expect("Malformed URL in get_identifiers");
+
+ Client::new().get(url).query(params).build()
+}
diff --git a/fractal-matrix-api/src/r0/contact/request_verification_token_email.rs
b/fractal-matrix-api/src/r0/contact/request_verification_token_email.rs
new file mode 100644
index 00000000..7ae47cc3
--- /dev/null
+++ b/fractal-matrix-api/src/r0/contact/request_verification_token_email.rs
@@ -0,0 +1,33 @@
+use reqwest::Client;
+use reqwest::Error;
+use reqwest::Request;
+use serde::{Deserialize, Serialize};
+use url::Url;
+
+#[derive(Clone, Debug, Serialize)]
+pub struct Parameters {
+ pub access_token: String,
+}
+
+#[derive(Clone, Debug, Serialize)]
+pub struct Body {
+ pub client_secret: String,
+ pub email: String,
+ pub id_server: String,
+ pub send_attempt: u64,
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub next_link: Option<String>,
+}
+
+#[derive(Clone, Debug, Deserialize)]
+pub struct Response {
+ pub sid: String,
+}
+
+pub fn request(base: Url, params: &Parameters, body: &Body) -> Result<Request, Error> {
+ let url = base
+ .join("/_matrix/client/r0/account/3pid/email/requestToken")
+ .expect("Malformed URL in request_verification_token_email");
+
+ Client::new().post(url).query(params).json(body).build()
+}
diff --git a/fractal-matrix-api/src/r0/contact/request_verification_token_msisdn.rs
b/fractal-matrix-api/src/r0/contact/request_verification_token_msisdn.rs
new file mode 100644
index 00000000..c1dae91e
--- /dev/null
+++ b/fractal-matrix-api/src/r0/contact/request_verification_token_msisdn.rs
@@ -0,0 +1,34 @@
+use reqwest::Client;
+use reqwest::Error;
+use reqwest::Request;
+use serde::{Deserialize, Serialize};
+use url::Url;
+
+#[derive(Clone, Debug, Serialize)]
+pub struct Parameters {
+ pub access_token: String,
+}
+
+#[derive(Clone, Debug, Serialize)]
+pub struct Body {
+ pub client_secret: String,
+ pub phone_number: String,
+ pub country: String,
+ pub id_server: String,
+ pub send_attempt: u64,
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub next_link: Option<String>,
+}
+
+#[derive(Clone, Debug, Deserialize)]
+pub struct Response {
+ pub sid: String,
+}
+
+pub fn request(base: Url, params: &Parameters, body: &Body) -> Result<Request, Error> {
+ let url = base
+ .join("/_matrix/client/r0/account/3pid/msisdn/requestToken")
+ .expect("Malformed URL in request_verification_token_msisdn");
+
+ Client::new().post(url).query(params).json(body).build()
+}
diff --git a/fractal-matrix-api/src/r0/media.rs b/fractal-matrix-api/src/r0/media.rs
new file mode 100644
index 00000000..c5fb369c
--- /dev/null
+++ b/fractal-matrix-api/src/r0/media.rs
@@ -0,0 +1 @@
+pub mod create;
diff --git a/fractal-matrix-api/src/r0/media/create.rs b/fractal-matrix-api/src/r0/media/create.rs
new file mode 100644
index 00000000..8e8b0fc8
--- /dev/null
+++ b/fractal-matrix-api/src/r0/media/create.rs
@@ -0,0 +1,40 @@
+use reqwest::header::{HeaderValue, CONTENT_TYPE};
+use reqwest::Client;
+use reqwest::Error;
+use reqwest::Request;
+use serde::{Deserialize, Serialize};
+use url::Url;
+
+#[derive(Clone, Debug, Serialize)]
+pub struct Parameters {
+ pub access_token: String,
+ pub filename: Option<String>,
+}
+
+#[derive(Clone, Debug, Deserialize)]
+pub struct Response {
+ pub content_uri: String,
+}
+
+pub fn request(
+ base: Url,
+ params: &Parameters,
+ file: Vec<u8>,
+ content_type: Option<HeaderValue>,
+) -> Result<Request, Error> {
+ let header = content_type
+ .map(|mime| (CONTENT_TYPE, mime))
+ .into_iter()
+ .collect();
+
+ let url = base
+ .join("/_matrix/media/r0/upload")
+ .expect("Malformed URL in upload");
+
+ Client::new()
+ .post(url)
+ .query(params)
+ .body(file)
+ .headers(header)
+ .build()
+}
diff --git a/fractal-matrix-api/src/r0/profile.rs b/fractal-matrix-api/src/r0/profile.rs
new file mode 100644
index 00000000..c556486e
--- /dev/null
+++ b/fractal-matrix-api/src/r0/profile.rs
@@ -0,0 +1,4 @@
+pub mod get_display_name;
+pub mod get_profile;
+pub mod set_avatar_url;
+pub mod set_display_name;
diff --git a/fractal-matrix-api/src/r0/profile/get_display_name.rs
b/fractal-matrix-api/src/r0/profile/get_display_name.rs
new file mode 100644
index 00000000..a871b55c
--- /dev/null
+++ b/fractal-matrix-api/src/r0/profile/get_display_name.rs
@@ -0,0 +1,21 @@
+use reqwest::Client;
+use reqwest::Error;
+use reqwest::Request;
+use serde::Deserialize;
+use url::Url;
+
+#[derive(Clone, Debug, Deserialize)]
+pub struct Response {
+ pub displayname: Option<String>,
+}
+
+pub fn request(base: Url, user_id: &str) -> Result<Request, Error> {
+ let url = base
+ .join(&format!(
+ "/_matrix/client/r0/profile/{}/displayname",
+ user_id
+ ))
+ .expect("Malformed URL in get_display_name");
+
+ Client::new().get(url).build()
+}
diff --git a/fractal-matrix-api/src/r0/profile/get_profile.rs
b/fractal-matrix-api/src/r0/profile/get_profile.rs
new file mode 100644
index 00000000..50afd968
--- /dev/null
+++ b/fractal-matrix-api/src/r0/profile/get_profile.rs
@@ -0,0 +1,19 @@
+use reqwest::Client;
+use reqwest::Error;
+use reqwest::Request;
+use serde::Deserialize;
+use url::Url;
+
+#[derive(Clone, Debug, Deserialize)]
+pub struct Response {
+ pub avatar_url: Option<String>,
+ pub displayname: Option<String>,
+}
+
+pub fn request(base: Url, user_id: &str) -> Result<Request, Error> {
+ let url = base
+ .join(&format!("/_matrix/client/r0/profile/{}", user_id))
+ .expect("Malformed URL in get_profile_avatar");
+
+ Client::new().get(url).build()
+}
diff --git a/fractal-matrix-api/src/r0/profile/set_avatar_url.rs
b/fractal-matrix-api/src/r0/profile/set_avatar_url.rs
new file mode 100644
index 00000000..0d2a87ce
--- /dev/null
+++ b/fractal-matrix-api/src/r0/profile/set_avatar_url.rs
@@ -0,0 +1,31 @@
+use reqwest::Client;
+use reqwest::Error;
+use reqwest::Request;
+use serde::Serialize;
+use url::Url;
+
+#[derive(Clone, Debug, Serialize)]
+pub struct Parameters {
+ pub access_token: String,
+}
+
+#[derive(Clone, Debug, Serialize)]
+pub struct Body {
+ pub avatar_url: Option<String>,
+}
+
+pub fn request(
+ base: Url,
+ params: &Parameters,
+ body: &Body,
+ user_id: &str,
+) -> Result<Request, Error> {
+ let url = base
+ .join(&format!(
+ "/_matrix/client/r0/profile/{}/avatar_url",
+ user_id
+ ))
+ .expect("Malformed URL in set_avatar_url");
+
+ Client::new().put(url).query(params).json(body).build()
+}
diff --git a/fractal-matrix-api/src/r0/profile/set_display_name.rs
b/fractal-matrix-api/src/r0/profile/set_display_name.rs
new file mode 100644
index 00000000..198c53ed
--- /dev/null
+++ b/fractal-matrix-api/src/r0/profile/set_display_name.rs
@@ -0,0 +1,32 @@
+use reqwest::Client;
+use reqwest::Error;
+use reqwest::Request;
+use serde::Serialize;
+use url::Url;
+
+#[derive(Clone, Debug, Serialize)]
+pub struct Parameters {
+ pub access_token: String,
+}
+
+#[derive(Clone, Debug, Serialize)]
+pub struct Body {
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub displayname: Option<String>,
+}
+
+pub fn request(
+ base: Url,
+ params: &Parameters,
+ body: &Body,
+ user_id: &str,
+) -> Result<Request, Error> {
+ let url = base
+ .join(&format!(
+ "/_matrix/client/r0/profile/{}/displayname",
+ user_id
+ ))
+ .expect("Malformed URL in set_display_name");
+
+ Client::new().put(url).query(params).json(body).build()
+}
diff --git a/fractal-matrix-api/src/r0/search.rs b/fractal-matrix-api/src/r0/search.rs
new file mode 100644
index 00000000..22d12a38
--- /dev/null
+++ b/fractal-matrix-api/src/r0/search.rs
@@ -0,0 +1 @@
+pub mod user;
diff --git a/fractal-matrix-api/src/r0/search/user.rs b/fractal-matrix-api/src/r0/search/user.rs
new file mode 100644
index 00000000..65ad510c
--- /dev/null
+++ b/fractal-matrix-api/src/r0/search/user.rs
@@ -0,0 +1,53 @@
+use reqwest::Client;
+use reqwest::Error;
+use reqwest::Request;
+use serde::{Deserialize, Serialize};
+use url::Url;
+
+#[derive(Clone, Debug, Serialize)]
+pub struct Parameters {
+ pub access_token: String,
+}
+
+#[derive(Clone, Debug, Serialize)]
+pub struct Body {
+ pub search_term: String,
+ #[serde(skip_serializing_if = "u64_is_10")]
+ pub limit: u64,
+}
+
+impl Default for Body {
+ fn default() -> Self {
+ Self {
+ search_term: Default::default(),
+ limit: 10,
+ }
+ }
+}
+
+#[derive(Clone, Debug, Deserialize)]
+pub struct Response {
+ pub results: Vec<User>,
+ pub limited: bool,
+}
+
+#[derive(Clone, Debug, Deserialize)]
+pub struct User {
+ pub user_id: String,
+ #[serde(default)]
+ pub display_name: Option<String>,
+ #[serde(default)]
+ pub avatar_url: Option<String>,
+}
+
+fn u64_is_10(number: &u64) -> bool {
+ number == &10
+}
+
+pub fn request(base: Url, params: &Parameters, body: &Body) -> Result<Request, Error> {
+ let url = base
+ .join("/_matrix/client/r0/user_directory/search")
+ .expect("Malformed URL in user_directory");
+
+ Client::new().post(url).query(params).json(body).build()
+}
diff --git a/fractal-matrix-api/src/types.rs b/fractal-matrix-api/src/types.rs
index 9d02a8fb..28cc3307 100644
--- a/fractal-matrix-api/src/types.rs
+++ b/fractal-matrix-api/src/types.rs
@@ -11,4 +11,3 @@ pub use crate::model::room::RoomMembership;
pub use crate::model::room::RoomTag;
pub use crate::model::stickers::Sticker;
pub use crate::model::stickers::StickerGroup;
-pub use crate::model::user::*;
diff --git a/fractal-matrix-api/src/util.rs b/fractal-matrix-api/src/util.rs
index fd3c867d..f310d74d 100644
--- a/fractal-matrix-api/src/util.rs
+++ b/fractal-matrix-api/src/util.rs
@@ -21,6 +21,8 @@ use std::thread;
use crate::client::Client;
use crate::error::Error;
use crate::r0::filter::RoomEventFilter;
+use crate::r0::profile::get_profile::request as get_profile;
+use crate::r0::profile::get_profile::Response as GetProfileResponse;
use crate::types::Message;
use reqwest::header::CONTENT_LENGTH;
@@ -238,20 +240,16 @@ pub fn get_media(url: &str) -> Result<Vec<u8>, Error> {
}
pub fn put_media(url: &str, file: Vec<u8>) -> Result<JsonValue, Error> {
- let (mime, _) = gio::content_type_guess(None, file.as_slice());
+ let (mime, _) = gio::content_type_guess(None, &file);
- let conn = HTTP_CLIENT
+ HTTP_CLIENT
.get_client()?
.post(url)
.body(file)
- .header(CONTENT_TYPE, mime.to_string());
-
- let mut res = conn.send()?;
-
- match res.json() {
- Ok(js) => Ok(js),
- Err(_) => Err(Error::BackendError),
- }
+ .header(CONTENT_TYPE, mime.to_string())
+ .send()?
+ .json()
+ .or(Err(Error::BackendError))
}
pub fn resolve_media_url(base: &Url, url: &str, thumb: bool, w: i32, h: i32) -> Result<Url, Error> {
@@ -391,29 +389,31 @@ pub fn json_q(method: &str, url: &Url, attrs: &JsonValue) -> Result<JsonValue, E
}
}
-pub fn get_user_avatar(baseu: &Url, userid: &str) -> Result<(String, String), Error> {
- let url = client_url(baseu, &format!("profile/{}", encode_uid(userid)), &[])?;
- let attrs = json!(null);
+pub fn get_user_avatar(base: &Url, userid: &str) -> Result<(String, String), Error> {
+ let response = get_profile(base.clone(), &encode_uid(userid))
+ .map_err::<Error, _>(Into::into)
+ .and_then(|request| {
+ HTTP_CLIENT
+ .get_client()?
+ .execute(request)?
+ .json::<GetProfileResponse>()
+ .map_err(Into::into)
+ })?;
+
+ let name = response
+ .displayname
+ .filter(|n| !n.is_empty())
+ .unwrap_or(userid.to_string());
+
+ let img = response
+ .avatar_url
+ .map(|url| {
+ let dest = cache_path(userid)?;
+ thumb(base, &url, Some(&dest))
+ })
+ .unwrap_or(Ok(Default::default()))?;
- match json_q("get", &url, &attrs) {
- Ok(js) => {
- let name = match js["displayname"].as_str() {
- Some(n) if n.is_empty() => userid.to_string(),
- Some(n) => n.to_string(),
- None => userid.to_string(),
- };
-
- match js["avatar_url"].as_str() {
- Some(url) => {
- let dest = cache_path(userid)?;
- let img = thumb(baseu, &url, Some(&dest))?;
- Ok((name.clone(), img))
- }
- None => Ok((name.clone(), String::new())),
- }
- }
- Err(_) => Ok((String::from(userid), String::new())),
- }
+ Ok((name, img))
}
pub fn build_url(base: &Url, path: &str, params: &[(&str, String)]) -> Result<Url, Error> {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]