[fractal] Backend: Implement and use login request and response types



commit e24ef247c7e15125b8ce06d93e1558b8b84e9266
Author: Alejandro Domínguez <adomu net-c com>
Date:   Sun Jan 20 02:26:29 2019 +0100

    Backend: Implement and use login request and response types

 fractal-matrix-api/src/backend/mod.rs      |   2 +-
 fractal-matrix-api/src/backend/register.rs |  50 ++++---------
 fractal-matrix-api/src/model/mod.rs        |   1 +
 fractal-matrix-api/src/model/register.rs   | 115 +++++++++++++++++++++++++++++
 fractal-matrix-api/src/types.rs            |   1 +
 5 files changed, 133 insertions(+), 36 deletions(-)
---
diff --git a/fractal-matrix-api/src/backend/mod.rs b/fractal-matrix-api/src/backend/mod.rs
index 7153dfc6..5dfdb781 100644
--- a/fractal-matrix-api/src/backend/mod.rs
+++ b/fractal-matrix-api/src/backend/mod.rs
@@ -87,7 +87,7 @@ impl Backend {
         match cmd {
             // Register module
             Ok(BKCommand::Login(user, passwd, server)) => {
-                let r = register::login(self, &user, &passwd, &server);
+                let r = register::login(self, user, passwd, &server);
                 bkerror!(r, tx, BKResponse::LoginError);
             }
             Ok(BKCommand::Logout) => {
diff --git a/fractal-matrix-api/src/backend/register.rs b/fractal-matrix-api/src/backend/register.rs
index 3c5c3a1b..8623427f 100644
--- a/fractal-matrix-api/src/backend/register.rs
+++ b/fractal-matrix-api/src/backend/register.rs
@@ -8,6 +8,9 @@ use crate::error::Error;
 use crate::globals;
 use crate::util::json_q;
 
+use crate::types::LoginRequest;
+use crate::types::LoginResponse;
+
 use crate::backend::types::BKResponse;
 use crate::backend::types::Backend;
 
@@ -40,48 +43,22 @@ pub fn guest(bk: &Backend, server: &str) -> Result<(), Error> {
     Ok(())
 }
 
-fn build_login_attrs(user: &str, password: &str) -> Result<JsonValue, Error> {
-    // Email
-    let attrs = if globals::EMAIL_RE.is_match(&user) {
-        json!({
-            "type": "m.login.password",
-            "password": password,
-            "initial_device_display_name": "Fractal",
-            "medium": "email",
-            "address": user,
-            "identifier": {
-                "type": "m.id.thirdparty",
-                "medium": "email",
-                "address": user,
-            }
-        })
-    } else {
-        json!({
-            "type": "m.login.password",
-            "initial_device_display_name": "Fractal",
-            "user": user,
-            "password": password
-        })
-    };
-
-    Ok(attrs)
-}
-
-pub fn login(bk: &Backend, user: &str, password: &str, server: &str) -> Result<(), Error> {
+pub fn login(bk: &Backend, user: String, password: String, server: &str) -> Result<(), Error> {
     bk.data.lock().unwrap().server_url = Url::parse(server)?;
     let url = bk.url("login", vec![])?;
 
-    let attrs = build_login_attrs(user, password)?;
+    let attrs = LoginRequest::new(user.clone(), password);
+    let attrs_json = serde_json::to_value(attrs).expect("Failed to serialize login request");
     let data = bk.data.clone();
 
     let tx = bk.tx.clone();
     post!(
         &url,
-        &attrs,
-        |r: JsonValue| {
-            let uid = String::from(r["user_id"].as_str().unwrap_or_default());
-            let tk = String::from(r["access_token"].as_str().unwrap_or_default());
-            let dev = String::from(r["device_id"].as_str().unwrap_or_default());
+        &attrs_json,
+        |r: JsonValue| if let Ok(response) = serde_json::from_value::<LoginResponse>(r) {
+            let uid = response.user_id.unwrap_or(user);
+            let tk = response.access_token.unwrap_or_default();
+            let dev = response.device_id;
 
             if uid.is_empty() || tk.is_empty() {
                 tx.send(BKResponse::LoginError(Error::BackendError))
@@ -90,8 +67,11 @@ pub fn login(bk: &Backend, user: &str, password: &str, server: &str) -> Result<(
                 data.lock().unwrap().user_id = uid.clone();
                 data.lock().unwrap().access_token = tk.clone();
                 data.lock().unwrap().since = None;
-                tx.send(BKResponse::Token(uid, tk, Some(dev))).unwrap();
+                tx.send(BKResponse::Token(uid, tk, dev)).unwrap();
             }
+        } else {
+            tx.send(BKResponse::LoginError(Error::BackendError))
+                .unwrap();
         },
         |err| tx.send(BKResponse::LoginError(err)).unwrap()
     );
diff --git a/fractal-matrix-api/src/model/mod.rs b/fractal-matrix-api/src/model/mod.rs
index 18076d97..07faeeb8 100644
--- a/fractal-matrix-api/src/model/mod.rs
+++ b/fractal-matrix-api/src/model/mod.rs
@@ -2,6 +2,7 @@ pub mod event;
 pub mod member;
 pub mod message;
 pub mod protocol;
+pub mod register;
 pub mod room;
 pub mod stickers;
 pub mod userinfo;
diff --git a/fractal-matrix-api/src/model/register.rs b/fractal-matrix-api/src/model/register.rs
new file mode 100644
index 00000000..34a90d5b
--- /dev/null
+++ b/fractal-matrix-api/src/model/register.rs
@@ -0,0 +1,115 @@
+use crate::globals;
+use serde::{Deserialize, Serialize};
+
+#[derive(Clone, Debug, Serialize)]
+pub struct LoginRequest {
+    #[serde(flatten)]
+    pub identifier: Identifier,
+    #[serde(flatten)]
+    pub auth: Auth,
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub device_id: Option<String>,
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub initial_device_display_name: Option<String>,
+}
+
+#[derive(Clone, Debug, Deserialize)]
+pub struct LoginResponse {
+    pub access_token: Option<String>,
+    pub user_id: Option<String>,
+    pub device_id: Option<String>,
+}
+
+#[derive(Clone, Debug, Serialize)]
+pub enum Medium {
+    #[serde(rename = "email")]
+    Email,
+    #[serde(rename = "msisdn")]
+    MsIsdn,
+}
+
+#[derive(Clone, Debug, Serialize)]
+#[serde(tag = "type")]
+pub enum Auth {
+    #[serde(rename = "m.login.password")]
+    Password { password: String },
+    #[serde(rename = "m.login.token")]
+    Token { token: String },
+}
+
+#[derive(Clone, Debug, Serialize)]
+#[serde(tag = "type")]
+pub enum UserIdentifier {
+    #[serde(rename = "m.id.user")]
+    User { user: String },
+    #[serde(rename = "m.id.thirdparty")]
+    ThirdParty { medium: Medium, address: String },
+    #[serde(rename = "m.id.phone")]
+    Phone { country: String, phone: String },
+}
+
+#[derive(Clone, Debug, Serialize)]
+enum LegacyMedium {
+    #[serde(rename = "email")]
+    Email,
+}
+
+#[derive(Clone, Debug, Serialize)]
+#[serde(untagged)]
+enum LegacyIdentifier {
+    User {
+        user: String,
+    },
+    Email {
+        medium: LegacyMedium,
+        address: String,
+    },
+}
+
+#[derive(Clone, Debug, Serialize)]
+pub struct Identifier {
+    identifier: UserIdentifier,
+    #[serde(flatten)]
+    legacy_identifier: Option<LegacyIdentifier>,
+}
+
+impl Identifier {
+    pub fn new(identifier: UserIdentifier) -> Self {
+        Self {
+            identifier: identifier.clone(),
+            legacy_identifier: match identifier {
+                UserIdentifier::User { user } => Some(LegacyIdentifier::User { user }),
+                UserIdentifier::ThirdParty { medium: _, address } => {
+                    Some(LegacyIdentifier::Email {
+                        medium: LegacyMedium::Email,
+                        address,
+                    })
+                }
+                UserIdentifier::Phone { .. } => None,
+            },
+        }
+    }
+}
+
+impl LoginRequest {
+    pub fn new(user: String, password: String) -> Self {
+        if globals::EMAIL_RE.is_match(&user) {
+            Self {
+                auth: Auth::Password { password },
+                initial_device_display_name: Some(String::from("Fractal")),
+                identifier: Identifier::new(UserIdentifier::ThirdParty {
+                    medium: Medium::Email,
+                    address: user,
+                }),
+                device_id: None,
+            }
+        } else {
+            Self {
+                auth: Auth::Password { password },
+                initial_device_display_name: Some(String::from("Fractal")),
+                identifier: Identifier::new(UserIdentifier::User { user }),
+                device_id: None,
+            }
+        }
+    }
+}
diff --git a/fractal-matrix-api/src/types.rs b/fractal-matrix-api/src/types.rs
index 0a534e76..3d2e4c23 100644
--- a/fractal-matrix-api/src/types.rs
+++ b/fractal-matrix-api/src/types.rs
@@ -4,6 +4,7 @@ pub use crate::model::member::MemberList;
 pub use crate::model::message::Message;
 pub use crate::model::protocol::ProtocolInstance;
 pub use crate::model::protocol::SupportedProtocols;
+pub use crate::model::register::*;
 pub use crate::model::room::PublicRoomsRequest;
 pub use crate::model::room::PublicRoomsResponse;
 pub use crate::model::room::Room;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]