[fractal] AppOp: Store all login-dependent data into an optional field



commit 5571bb4cb668560d2e905d05a22715ccf438020e
Author: Alejandro Domínguez <adomu net-c com>
Date:   Mon Dec 2 12:09:14 2019 +0100

    AppOp: Store all login-dependent data into an optional field

 fractal-gtk/src/actions/global.rs          |   2 +-
 fractal-gtk/src/app/backend_loop.rs        |   4 +-
 fractal-gtk/src/app/connect/account.rs     |  33 ++++----
 fractal-gtk/src/app/connect/language.rs    |   8 +-
 fractal-gtk/src/appop/account.rs           | 103 ++++++++++++-----------
 fractal-gtk/src/appop/directory.rs         |  12 +--
 fractal-gtk/src/appop/invite.rs            |  16 ++--
 fractal-gtk/src/appop/login.rs             | 130 +++++++++++------------------
 fractal-gtk/src/appop/media_viewer.rs      |   6 +-
 fractal-gtk/src/appop/member.rs            |   8 +-
 fractal-gtk/src/appop/message.rs           |  61 +++++++-------
 fractal-gtk/src/appop/mod.rs               |  46 +++++-----
 fractal-gtk/src/appop/notify.rs            |   3 +-
 fractal-gtk/src/appop/room.rs              |  94 +++++++++++----------
 fractal-gtk/src/appop/room_settings.rs     |   8 +-
 fractal-gtk/src/appop/start_chat.rs        |   6 +-
 fractal-gtk/src/appop/sync.rs              |   6 +-
 fractal-gtk/src/appop/user.rs              |  66 ++++++++-------
 fractal-gtk/src/passwd.rs                  |  19 ++---
 fractal-gtk/src/widgets/address.rs         |   7 +-
 fractal-gtk/src/widgets/login.rs           |   9 +-
 fractal-gtk/src/widgets/member.rs          |  22 ++---
 fractal-gtk/src/widgets/room.rs            |   7 +-
 fractal-gtk/src/widgets/room_history.rs    |   8 +-
 fractal-gtk/src/widgets/room_settings.rs   |  23 ++---
 fractal-matrix-api/src/backend/mod.rs      |  12 +--
 fractal-matrix-api/src/backend/register.rs |  57 ++++++-------
 fractal-matrix-api/src/backend/types.rs    |  10 +--
 28 files changed, 377 insertions(+), 409 deletions(-)
---
diff --git a/fractal-gtk/src/actions/global.rs b/fractal-gtk/src/actions/global.rs
index 0c6a6eeb..fcf6742f 100644
--- a/fractal-gtk/src/actions/global.rs
+++ b/fractal-gtk/src/actions/global.rs
@@ -271,7 +271,7 @@ pub fn new(app: &gtk::Application, op: &Arc<Mutex<AppOp>>) {
             debug!("There is no state to go back to. Go back to state NoRoom");
             if let Some(op) = App::get_op() {
                 let mut op = op.lock().unwrap();
-                if op.logged_in {
+                if op.login_data.is_some() {
                     op.set_state(AppState::NoRoom);
                 }
             }
diff --git a/fractal-gtk/src/app/backend_loop.rs b/fractal-gtk/src/app/backend_loop.rs
index 51f9c04e..d11ab419 100644
--- a/fractal-gtk/src/app/backend_loop.rs
+++ b/fractal-gtk/src/app/backend_loop.rs
@@ -21,8 +21,8 @@ pub fn backend_loop(rx: Receiver<BKResponse>) {
                 BKResponse::ShutDown => {
                     break;
                 }
-                BKResponse::Token(uid, tk, dev) => {
-                    APPOP!(bk_login, (uid, tk, dev));
+                BKResponse::Token(uid, tk, dev, server_url, id_url) => {
+                    APPOP!(bk_login, (uid, tk, dev, server_url, id_url));
                 }
                 BKResponse::Logout(Ok(_)) => {
                     APPOP!(bk_logout);
diff --git a/fractal-gtk/src/app/connect/account.rs b/fractal-gtk/src/app/connect/account.rs
index 8521a482..f63a2679 100644
--- a/fractal-gtk/src/app/connect/account.rs
+++ b/fractal-gtk/src/app/connect/account.rs
@@ -11,7 +11,7 @@ use crate::actions::{AccountSettings, StateExt};
 impl App {
     pub fn connect_account_settings(&self) {
         let op = &self.op;
-        let access_token = unwrap_or_unit_return!(op.lock().unwrap().access_token.clone());
+        let login_data = unwrap_or_unit_return!(op.lock().unwrap().login_data.clone());
         let builder = &self.ui.builder;
         let cancel_password = self
             .ui
@@ -77,8 +77,12 @@ impl App {
         // FIXME: don't clone the backend
         let backend = self.op.lock().unwrap().backend.clone();
         let window = self.main_window.upcast_ref::<gtk::Window>();
-        let server_url = self.op.lock().unwrap().server_url.clone();
-        let actions = AccountSettings::new(&window, &backend, server_url, access_token);
+        let actions = AccountSettings::new(
+            &window,
+            &backend,
+            login_data.server_url,
+            login_data.access_token,
+        );
         let container = self
             .ui
             .builder
@@ -110,21 +114,14 @@ impl App {
 
         let button = name_btn.clone();
         name_entry.connect_property_text_notify(clone!(op => move |w| {
-            if let Some(text) = w.get_text() {
-                if text != "" {
-                    let lock = op.try_lock();
-                    let username = if let Ok(guard) = lock {
-                        guard.username.clone()
-                    }
-                    else {
-                        None
-                    };
-                    if let Some(username) = username {
-                        if username == text {
-                            button.hide();
-                            return;
-                        }
-                    }
+            if let Some(text) = w.get_text().filter(|text| !text.is_empty()) {
+                if op.try_lock()
+                    .ok()
+                    .and_then(|guard| guard.login_data.clone())
+                    .and_then(|login_data| login_data.username)
+                    .filter(|username| *username != text)
+                    .is_some()
+                {
                     button.show();
                     return;
                 }
diff --git a/fractal-gtk/src/app/connect/language.rs b/fractal-gtk/src/app/connect/language.rs
index 86889576..fae0194d 100644
--- a/fractal-gtk/src/app/connect/language.rs
+++ b/fractal-gtk/src/app/connect/language.rs
@@ -25,11 +25,11 @@ impl App {
                     due to the user switching rooms, the op mutex is locked already.
                     If the checker is modified by gtk due to the user switching the language, the op mutex 
is unlocked. */
                     if let Ok(op) = op.try_lock() {
-                        if let Some(active_room) = &op.active_room {
-                            let server = &op.server_url;
-                            let access_token = unwrap_or_unit_return!(op.access_token.clone());
+                        if let (Some(active_room), Some(login_data)) = (&op.active_room, &op.login_data) {
+                            let server = login_data.server_url.clone();
+                            let access_token = login_data.access_token.clone();
                             op.backend
-                                .send(BKCommand::ChangeLanguage(access_token, server.clone(), lang_code, 
active_room.clone()))
+                                .send(BKCommand::ChangeLanguage(access_token, server, lang_code, 
active_room.clone()))
                                 .unwrap();
                         }
                     }
diff --git a/fractal-gtk/src/appop/account.rs b/fractal-gtk/src/appop/account.rs
index ef75de8e..f583d4c1 100644
--- a/fractal-gtk/src/appop/account.rs
+++ b/fractal-gtk/src/appop/account.rs
@@ -14,17 +14,19 @@ use crate::cache::download_to_cache;
 use fractal_api::r0::contact::get_identifiers::ThirdPartyIdentifier;
 use fractal_api::r0::Medium;
 
+use super::LoginData;
+
 impl AppOp {
     pub fn set_three_pid(&self, data: Option<Vec<ThirdPartyIdentifier>>) {
         self.update_address(data);
     }
 
     pub fn get_three_pid(&self) {
-        let access_token = unwrap_or_unit_return!(self.access_token.clone());
+        let login_data = unwrap_or_unit_return!(self.login_data.clone());
         self.backend
             .send(BKCommand::GetThreePID(
-                self.server_url.clone(),
-                access_token,
+                login_data.server_url,
+                login_data.access_token,
             ))
             .unwrap();
     }
@@ -34,13 +36,13 @@ impl AppOp {
     }
 
     pub fn valid_phone_token(&self, sid: Option<String>, secret: Option<String>) {
-        let access_token = unwrap_or_unit_return!(self.access_token.clone());
+        let login_data = unwrap_or_unit_return!(self.login_data.clone());
         if let Some(sid) = sid {
             if let Some(secret) = secret {
                 let _ = self.backend.send(BKCommand::AddThreePID(
-                    self.server_url.clone(),
-                    access_token,
-                    self.identity_url.clone(),
+                    login_data.server_url,
+                    login_data.access_token,
+                    login_data.identity_url,
                     secret.clone(),
                     sid.clone(),
                 ));
@@ -51,6 +53,7 @@ impl AppOp {
     }
 
     pub fn show_phone_dialog(&self, sid: String, secret: String) {
+        let login_data = unwrap_or_unit_return!(self.login_data.clone());
         let parent = self
             .ui
             .builder
@@ -94,13 +97,12 @@ impl AppOp {
         });
 
         let value = entry.clone();
-        let server_url = self.server_url.clone();
         dialog.connect_response(move |w, r| {
             match gtk::ResponseType::from(r) {
                 gtk::ResponseType::Ok => {
                     if let Some(token) = value.get_text() {
                         let _ = backend.send(BKCommand::SubmitPhoneToken(
-                            server_url.clone(),
+                            login_data.server_url.clone(),
                             secret.clone(),
                             sid.clone(),
                             token.to_string(),
@@ -116,7 +118,7 @@ impl AppOp {
     }
 
     pub fn show_email_dialog(&self, sid: String, secret: String) {
-        let access_token = unwrap_or_unit_return!(self.access_token.clone());
+        let login_data = unwrap_or_unit_return!(self.login_data.clone());
         let parent = self
             .ui
             .builder
@@ -133,17 +135,15 @@ impl AppOp {
             &msg,
         );
         let backend = self.backend.clone();
-        let id_server = self.identity_url.clone();
-        let server_url = self.server_url.clone();
         dialog.add_button(&i18n("Cancel"), gtk::ResponseType::Cancel.into());
         dialog.add_button(&i18n("Continue"), gtk::ResponseType::Ok.into());
         dialog.connect_response(move |w, r| {
             match gtk::ResponseType::from(r) {
                 gtk::ResponseType::Ok => {
                     let _ = backend.send(BKCommand::AddThreePID(
-                        server_url.clone(),
-                        access_token.clone(),
-                        id_server.clone(),
+                        login_data.server_url.clone(),
+                        login_data.access_token.clone(),
+                        login_data.identity_url.clone(),
                         secret.clone(),
                         sid.clone(),
                     ));
@@ -208,6 +208,7 @@ impl AppOp {
     }
 
     pub fn show_account_settings_dialog(&mut self) {
+        let login_data = unwrap_or_unit_return!(self.login_data.clone());
         // Reset view before displaying it
         self.close_account_settings_dialog();
         let avatar_spinner = self
@@ -288,10 +289,10 @@ impl AppOp {
 
         stack.set_visible_child_name("loading");
         self.get_three_pid();
-        uid.set_text(&self.uid.clone().unwrap_or_default());
+        uid.set_text(&login_data.uid);
         device_id.set_text(&self.device_id.clone().unwrap_or_default());
-        homeserver.set_text(self.server_url.as_str());
-        name.set_text(&self.username.clone().unwrap_or_default());
+        homeserver.set_text(login_data.server_url.as_str());
+        name.set_text(&login_data.username.unwrap_or_default());
         name.grab_focus_without_selecting();
         name.set_position(-1);
 
@@ -452,6 +453,7 @@ impl AppOp {
     }
 
     pub fn show_new_avatar(&mut self, path: Option<String>) {
+        let login_data = unwrap_or_unit_return!(self.login_data.clone());
         let avatar_spinner = self
             .ui
             .builder
@@ -464,13 +466,17 @@ impl AppOp {
             .expect("Can't find account_settings_avatar_button in ui file.");
 
         info!("Request finished");
-        self.set_avatar(path.clone());
+        self.set_login_data(LoginData {
+            avatar: path,
+            ..login_data
+        });
         avatar_spinner.hide();
         avatar_btn.set_sensitive(true);
         self.show_avatar();
     }
 
     pub fn show_avatar(&self) {
+        let login_data = unwrap_or_unit_return!(self.login_data.clone());
         let stack = self
             .ui
             .builder
@@ -496,12 +502,11 @@ impl AppOp {
         let w = widgets::Avatar::avatar_new(Some(100));
         avatar.add(&w);
 
-        let uid = self.uid.clone().unwrap_or_default();
-        let data = w.circle(uid.clone(), self.username.clone(), 100, None, None);
+        let data = w.circle(login_data.uid.clone(), login_data.username, 100, None, None);
         download_to_cache(
             self.backend.clone(),
-            self.server_url.clone(),
-            uid.clone(),
+            login_data.server_url,
+            login_data.uid,
             data.clone(),
         );
 
@@ -514,6 +519,7 @@ impl AppOp {
     }
 
     pub fn show_new_username(&mut self, name: Option<String>) {
+        let login_data = unwrap_or_unit_return!(self.login_data.clone());
         let entry = self
             .ui
             .builder
@@ -533,11 +539,14 @@ impl AppOp {
             entry.set_editable(true);
             entry.set_text(&name);
         }
-        self.set_username(name);
+        self.set_login_data(LoginData {
+            username: name,
+            ..login_data
+        });
     }
 
     pub fn update_username_account_settings(&self) {
-        let access_token = unwrap_or_unit_return!(self.access_token.clone());
+        let login_data = unwrap_or_unit_return!(self.login_data.clone());
         let name = self
             .ui
             .builder
@@ -549,7 +558,7 @@ impl AppOp {
             .get_object::<gtk::Button>("account_settings_name_button")
             .expect("Can't find account_settings_name_button in ui file.");
 
-        let old_username = self.username.clone().unwrap_or_default();
+        let old_username = login_data.username.unwrap_or_default();
         let username = name
             .get_text()
             .map_or(String::new(), |gstr| gstr.to_string());
@@ -562,8 +571,8 @@ impl AppOp {
             name.set_editable(false);
             self.backend
                 .send(BKCommand::SetUserName(
-                    self.server_url.clone(),
-                    access_token,
+                    login_data.server_url,
+                    login_data.access_token,
                     username,
                 ))
                 .unwrap();
@@ -595,7 +604,7 @@ impl AppOp {
     }
 
     pub fn set_new_password(&mut self) {
-        let access_token = unwrap_or_unit_return!(self.access_token.clone());
+        let login_data = unwrap_or_unit_return!(self.login_data.clone());
         let old_password = self
             .ui
             .builder
@@ -619,18 +628,16 @@ impl AppOp {
 
         if let Some(old) = old_password.get_text() {
             if let Some(new) = new_password.get_text() {
-                if let Some(mxid) = self.uid.clone() {
-                    if old != "" && new != "" {
-                        password_btn.set_sensitive(false);
-                        password_btn_stack.set_visible_child_name("spinner");
-                        let _ = self.backend.send(BKCommand::ChangePassword(
-                            self.server_url.clone(),
-                            access_token,
-                            mxid,
-                            old.to_string(),
-                            new.to_string(),
-                        ));
-                    }
+                if old != "" && new != "" {
+                    password_btn.set_sensitive(false);
+                    password_btn_stack.set_visible_child_name("spinner");
+                    let _ = self.backend.send(BKCommand::ChangePassword(
+                        login_data.server_url,
+                        login_data.access_token,
+                        login_data.uid,
+                        old.to_string(),
+                        new.to_string(),
+                    ));
                 }
             }
         }
@@ -696,7 +703,7 @@ impl AppOp {
     }
 
     pub fn account_destruction(&self) {
-        let access_token = unwrap_or_unit_return!(self.access_token.clone());
+        let login_data = unwrap_or_unit_return!(self.login_data.clone());
         let entry = self
             .ui
             .builder
@@ -727,18 +734,16 @@ impl AppOp {
         dialog.add_button("Cancel", gtk::ResponseType::Cancel.into());
 
         let _flag = mark.get_active(); // TODO: This is not used, remove from UI?
-        let server_url = self.server_url.clone();
-        if let (Some(password), Some(mxid)) = (entry.get_text(), self.uid.clone()) {
+        if let Some(password) = entry.get_text() {
             let backend = self.backend.clone();
-            let password = password.to_string();
             dialog.connect_response(move |w, r| {
                 match gtk::ResponseType::from(r) {
                     gtk::ResponseType::Ok => {
                         let _ = backend.send(BKCommand::AccountDestruction(
-                            server_url.clone(),
-                            access_token.clone(),
-                            mxid.clone(),
-                            password.clone(),
+                            login_data.server_url.clone(),
+                            login_data.access_token.clone(),
+                            login_data.uid.clone(),
+                            password.to_string(),
                         ));
                     }
                     _ => {}
diff --git a/fractal-gtk/src/appop/directory.rs b/fractal-gtk/src/appop/directory.rs
index e7711c34..3a65f1b6 100644
--- a/fractal-gtk/src/appop/directory.rs
+++ b/fractal-gtk/src/appop/directory.rs
@@ -12,11 +12,11 @@ use fractal_api::r0::thirdparty::get_supported_protocols::ProtocolInstance;
 
 impl AppOp {
     pub fn init_protocols(&self) {
-        let access_token = unwrap_or_unit_return!(self.access_token.clone());
+        let login_data = unwrap_or_unit_return!(self.login_data.clone());
         self.backend
             .send(BKCommand::DirectoryProtocols(
-                self.server_url.clone(),
-                access_token,
+                login_data.server_url,
+                login_data.access_token,
             ))
             .unwrap();
     }
@@ -35,7 +35,7 @@ impl AppOp {
     }
 
     pub fn search_rooms(&mut self, more: bool) {
-        let access_token = unwrap_or_unit_return!(self.access_token.clone());
+        let login_data = unwrap_or_unit_return!(self.login_data.clone());
         let other_protocol_radio = self
             .ui
             .builder
@@ -123,8 +123,8 @@ impl AppOp {
 
         self.backend
             .send(BKCommand::DirectorySearch(
-                self.server_url.clone(),
-                access_token,
+                login_data.server_url,
+                login_data.access_token,
                 homeserver,
                 q.get_text().unwrap().to_string(),
                 protocol,
diff --git a/fractal-gtk/src/appop/invite.rs b/fractal-gtk/src/appop/invite.rs
index 301405ad..aa5bd09c 100644
--- a/fractal-gtk/src/appop/invite.rs
+++ b/fractal-gtk/src/appop/invite.rs
@@ -156,13 +156,13 @@ impl AppOp {
     }
 
     pub fn invite(&mut self) {
-        let access_token = unwrap_or_unit_return!(self.access_token.clone());
+        let login_data = unwrap_or_unit_return!(self.login_data.clone());
         if let &Some(ref r) = &self.active_room {
             for user in &self.invite_list {
                 self.backend
                     .send(BKCommand::Invite(
-                        self.server_url.clone(),
-                        access_token.clone(),
+                        login_data.server_url.clone(),
+                        login_data.access_token.clone(),
                         r.clone(),
                         user.0.uid.clone(),
                     ))
@@ -215,22 +215,22 @@ impl AppOp {
     }
 
     pub fn accept_inv(&mut self, accept: bool) {
-        let access_token = unwrap_or_unit_return!(self.access_token.clone());
+        let login_data = unwrap_or_unit_return!(self.login_data.clone());
         let rid = self.invitation_roomid.clone();
         if let Some(rid) = rid {
             if accept {
                 self.backend
                     .send(BKCommand::AcceptInv(
-                        self.server_url.clone(),
-                        access_token,
+                        login_data.server_url,
+                        login_data.access_token,
                         rid.clone(),
                     ))
                     .unwrap();
             } else {
                 self.backend
                     .send(BKCommand::RejectInv(
-                        self.server_url.clone(),
-                        access_token,
+                        login_data.server_url,
+                        login_data.access_token,
                         rid.clone(),
                     ))
                     .unwrap();
diff --git a/fractal-gtk/src/appop/login.rs b/fractal-gtk/src/appop/login.rs
index 4eed2321..2cad9027 100644
--- a/fractal-gtk/src/appop/login.rs
+++ b/fractal-gtk/src/appop/login.rs
@@ -1,11 +1,7 @@
-use crate::i18n::i18n;
 use log::error;
 
 use fractal_api::r0::AccessToken;
 
-use gtk;
-use gtk::prelude::*;
-
 use url::Url;
 
 use crate::appop::AppOp;
@@ -23,31 +19,38 @@ use crate::app::backend_loop;
 use crate::passwd::PasswordStorage;
 
 use crate::actions::AppState;
-use crate::widgets::ErrorDialog;
+
+use super::LoginData;
 
 impl AppOp {
-    pub fn bk_login(&mut self, uid: String, token: Option<AccessToken>, device: Option<String>) {
-        self.logged_in = true;
-        if let Err(_) = self.store_token(uid.clone(), token.clone()) {
+    pub fn bk_login(
+        &mut self,
+        uid: String,
+        access_token: AccessToken,
+        device: Option<String>,
+        server_url: Url,
+        identity_url: Url,
+    ) {
+        if let Err(_) = self.store_token(uid.clone(), access_token.clone()) {
             error!("Can't store the token using libsecret");
         }
 
+        self.set_login_data(LoginData {
+            access_token,
+            uid,
+            username: None,
+            avatar: None,
+            server_url,
+            identity_url,
+        });
+
         self.set_state(AppState::NoRoom);
-        self.set_uid(Some(uid.clone()));
-        if self.device_id == None {
-            self.set_device(device);
-        }
-        /* Do we need to set the username to uid
-        self.set_username(Some(uid));*/
+        self.device_id = self.device_id.clone().or(device);
         self.get_username();
 
-        self.set_access_token(token);
-
         // initial sync, we're shoing some feedback to the user
         self.initial_sync(true);
-
         self.sync(true);
-
         self.init_protocols();
     }
 
@@ -57,14 +60,11 @@ impl AppOp {
             error!("Error removing cache file");
         }
 
-        self.logged_in = false;
         self.syncing = false;
 
         self.set_state(AppState::Login);
-        self.set_uid(None);
-        self.set_device(None);
-        self.set_username(None);
-        self.set_avatar(None);
+        self.login_data = None;
+        self.device_id = None;
 
         // stoping the backend and starting again, we don't want to receive more messages from
         // backend
@@ -77,6 +77,8 @@ impl AppOp {
     }
 
     #[allow(dead_code)]
+    // TODO
+    /*
     pub fn register(&mut self) {
         let user_entry: gtk::Entry = self
             .ui
@@ -123,19 +125,20 @@ impl AppOp {
             return;
         }
 
-        if let Some(s) = server_entry.get_text() {
-            match Url::parse(&s) {
-                Ok(u) => {
-                    self.server_url = u;
-                }
-                Err(_) => {
-                    let msg = i18n("Malformed server URL");
-                    ErrorDialog::new(false, &msg);
-                    return;
-                }
+        let server = match server_entry
+            .get_text()
+            .as_ref()
+            .map(Url::parse)
+            .unwrap_or(Ok(globals::DEFAULT_HOMESERVER))
+        {
+            Ok(u) => u,
+            Err(_) => {
+                let msg = i18n("Malformed server URL");
+                ErrorDialog::new(false, &msg);
+                return;
             }
         }
-        /* FIXME ask also for the identity server */
+        // FIXME: ask also for the identity server
 
         //self.store_pass(username.clone(), password.clone(), server_url.clone())
         //    .unwrap_or_else(|_| {
@@ -143,62 +146,26 @@ impl AppOp {
         //        error!("Can't store the password using libsecret");
         //    });
 
-        let uname = username.clone();
-        let pass = password.clone();
-        let ser = self.server_url.clone();
         self.backend
-            .send(BKCommand::Register(uname, pass, ser))
+            .send(BKCommand::Register(username, password, server, id_s))
             .unwrap();
     }
+    */
 
-    pub fn connect(
-        &mut self,
-        username: Option<String>,
-        password: Option<String>,
-        server: Url,
-        identity: Url,
-    ) -> Option<()> {
-        self.server_url = server;
-        self.identity_url = identity;
-
+    pub fn connect(&mut self, username: String, password: String, server: Url, identity: Url) {
         self.store_pass(
-            username.clone()?,
-            password.clone()?,
-            self.server_url.clone(),
-            self.identity_url.clone(),
+            username.clone(),
+            password.clone(),
+            server.clone(),
+            identity.clone(),
         )
         .unwrap_or_else(|_| {
             // TODO: show an error
             error!("Can't store the password using libsecret");
         });
 
-        let uname = username?;
-        let pass = password?;
-        let ser = self.server_url.clone();
-        self.backend
-            .send(BKCommand::Login(uname, pass, ser))
-            .unwrap();
-        Some(())
-    }
-
-    pub fn set_token(
-        &mut self,
-        token: AccessToken,
-        uid: Option<String>,
-        server: Url,
-    ) -> Option<()> {
-        self.server_url = server;
-
-        self.backend.send(BKCommand::SetToken(token, uid?)).unwrap();
-        Some(())
-    }
-
-    #[allow(dead_code)]
-    pub fn connect_guest(&mut self, server: Url) {
-        self.server_url = server;
-
         self.backend
-            .send(BKCommand::Guest(self.server_url.clone()))
+            .send(BKCommand::Login(username, password, server, identity))
             .unwrap();
     }
 
@@ -207,10 +174,13 @@ impl AppOp {
     }
 
     pub fn logout(&mut self) {
-        let access_token = unwrap_or_unit_return!(self.access_token.clone());
+        let login_data = unwrap_or_unit_return!(self.login_data.clone());
         let _ = self.delete_pass("fractal");
         self.backend
-            .send(BKCommand::Logout(self.server_url.clone(), access_token))
+            .send(BKCommand::Logout(
+                login_data.server_url,
+                login_data.access_token,
+            ))
             .unwrap();
         self.bk_logout();
     }
diff --git a/fractal-gtk/src/appop/media_viewer.rs b/fractal-gtk/src/appop/media_viewer.rs
index e883dff1..69d03ac0 100644
--- a/fractal-gtk/src/appop/media_viewer.rs
+++ b/fractal-gtk/src/appop/media_viewer.rs
@@ -11,7 +11,7 @@ use crate::types::Message;
 impl AppOp {
     /* FIXME: take msg by reference and maybe create an action for this */
     pub fn create_media_viewer(&mut self, msg: Message) -> Option<()> {
-        let access_token = self.access_token.clone()?;
+        let login_data = self.login_data.clone()?;
         let stack = self
             .ui
             .builder
@@ -37,8 +37,8 @@ impl AppOp {
                 main_window.clone(),
                 room,
                 &msg,
-                self.server_url.clone(),
-                access_token,
+                login_data.server_url,
+                login_data.access_token,
             );
             panel.display_media_viewer(msg);
             let (body, header) = panel.create()?;
diff --git a/fractal-gtk/src/appop/member.rs b/fractal-gtk/src/appop/member.rs
index b4315581..9e60ccc3 100644
--- a/fractal-gtk/src/appop/member.rs
+++ b/fractal-gtk/src/appop/member.rs
@@ -190,9 +190,13 @@ impl AppOp {
     }
 
     pub fn search_invite_user(&self, term: Option<String>) {
-        if let (Some(t), Some(token)) = (term, self.access_token.clone()) {
+        if let (Some(t), Some(login_data)) = (term, self.login_data.clone()) {
             self.backend
-                .send(BKCommand::UserSearch(self.server_url.clone(), token, t))
+                .send(BKCommand::UserSearch(
+                    login_data.server_url,
+                    login_data.access_token,
+                    t,
+                ))
                 .unwrap();
         }
     }
diff --git a/fractal-gtk/src/appop/message.rs b/fractal-gtk/src/appop/message.rs
index 64bfbfbc..0f06f4a2 100644
--- a/fractal-gtk/src/appop/message.rs
+++ b/fractal-gtk/src/appop/message.rs
@@ -63,11 +63,11 @@ impl AppOp {
     }
 
     pub fn add_tmp_room_message(&mut self, msg: Message) -> Option<()> {
+        let login_data = self.login_data.clone()?;
         let messages = self.history.as_ref()?.get_listbox();
         if let Some(ui_msg) = self.create_new_room_message(&msg) {
             let backend = self.backend.clone();
-            let mb =
-                widgets::MessageBox::new(backend, self.server_url.clone()).tmpwidget(&ui_msg)?;
+            let mb = widgets::MessageBox::new(backend, login_data.server_url).tmpwidget(&ui_msg)?;
             let m = mb.get_listbox_row()?;
             messages.add(m);
 
@@ -94,6 +94,7 @@ impl AppOp {
     }
 
     pub fn append_tmp_msgs(&mut self) -> Option<()> {
+        let login_data = self.login_data.clone()?;
         let messages = self.history.as_ref()?.get_listbox();
 
         let r = self.rooms.get(self.active_room.as_ref()?)?;
@@ -101,7 +102,7 @@ impl AppOp {
         for t in self.msg_queue.iter().rev().filter(|m| m.msg.room == r.id) {
             if let Some(ui_msg) = self.create_new_room_message(&t.msg) {
                 let backend = self.backend.clone();
-                let mb = widgets::MessageBox::new(backend, self.server_url.clone())
+                let mb = widgets::MessageBox::new(backend, login_data.server_url.clone())
                     .tmpwidget(&ui_msg)?;
                 let m = mb.get_listbox_row()?;
                 messages.add(m);
@@ -119,7 +120,7 @@ impl AppOp {
     }
 
     pub fn mark_last_message_as_read(&mut self, Force(force): Force) -> Option<()> {
-        let access_token = self.access_token.clone()?;
+        let login_data = self.login_data.clone()?;
         let window: gtk::Window = self
             .ui
             .builder
@@ -129,19 +130,19 @@ impl AppOp {
             /* Move the last viewed mark to the last message */
             let active_room_id = self.active_room.as_ref()?;
             let room = self.rooms.get_mut(active_room_id)?;
-            let uid = self.uid.clone()?;
+            let uid = login_data.uid;
             room.messages.iter_mut().for_each(|msg| {
                 if msg.receipt.contains_key(&uid) {
                     msg.receipt.remove(&uid);
                 }
             });
             let last_message = room.messages.last_mut()?;
-            last_message.receipt.insert(self.uid.clone()?, 0);
+            last_message.receipt.insert(uid, 0);
 
             self.backend
                 .send(BKCommand::MarkAsRead(
-                    self.server_url.clone(),
-                    access_token,
+                    login_data.server_url,
+                    login_data.access_token,
                     last_message.room.clone(),
                     last_message.id.clone(),
                 ))
@@ -176,7 +177,7 @@ impl AppOp {
     }
 
     pub fn dequeue_message(&mut self) -> Option<()> {
-        let access_token = self.access_token.clone()?;
+        let login_data = self.login_data.clone()?;
         if self.sending_message {
             return None;
         }
@@ -188,8 +189,8 @@ impl AppOp {
                 "m.image" | "m.file" | "m.audio" => {
                     self.backend
                         .send(BKCommand::AttachFile(
-                            self.server_url.clone(),
-                            access_token,
+                            login_data.server_url,
+                            login_data.access_token,
                             msg,
                         ))
                         .unwrap();
@@ -197,8 +198,8 @@ impl AppOp {
                 _ => {
                     self.backend
                         .send(BKCommand::SendMsg(
-                            self.server_url.clone(),
-                            access_token,
+                            login_data.server_url,
+                            login_data.access_token,
                             msg,
                         ))
                         .unwrap();
@@ -217,7 +218,7 @@ impl AppOp {
         }
 
         if let Some(room) = self.active_room.clone() {
-            if let Some(sender) = self.uid.clone() {
+            if let Some(sender) = self.login_data.as_ref().map(|ld| ld.uid.clone()) {
                 let body = msg.clone();
                 let mtype = String::from("m.text");
                 let mut m = Message::new(room, sender, body, mtype);
@@ -265,7 +266,7 @@ impl AppOp {
 
     pub fn attach_message(&mut self, path: PathBuf) {
         if let Some(room) = self.active_room.clone() {
-            if let Some(sender) = self.uid.clone() {
+            if let Some(sender) = self.login_data.as_ref().map(|ld| ld.uid.clone()) {
                 if let Ok(info) = gio::File::new_for_path(&path).query_info(
                     &gio::FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
                     gio::FileQueryInfoFlags::NONE,
@@ -350,10 +351,11 @@ impl AppOp {
         }
 
         let mut msg_in_active = false;
-        let uid = self.uid.clone()?;
+        let login_data = self.login_data.clone()?;
+        let uid = login_data.uid;
         for msg in msgs.iter() {
             let should_notify = msg.sender != uid
-                && (msg.body.contains(&self.username.clone()?)
+                && (msg.body.contains(&login_data.username.clone()?)
                     || self.rooms.get(&msg.room).map_or(false, |r| r.direct));
 
             if should_notify {
@@ -430,6 +432,7 @@ impl AppOp {
 
     /* parese a backend Message into a Message for the UI */
     pub fn create_new_room_message(&self, msg: &Message) -> Option<MessageContent> {
+        let login_data = self.login_data.clone()?;
         let mut highlights = vec![];
         lazy_static! {
             static ref EMOJI_REGEX: regex::Regex = regex::Regex::new(r"(?x)
@@ -452,19 +455,17 @@ impl AppOp {
             _ => {
                 /* set message type to mention if the body contains the username, we should
                  * also match for MXID */
-                let is_mention = if let Some(user) = self.username.clone() {
-                    msg.sender != self.uid.clone()? && msg.body.contains(&user)
+                let is_mention = if let Some(user) = login_data.username.clone() {
+                    msg.sender != login_data.uid.clone() && msg.body.contains(&user)
                 } else {
                     false
                 };
 
                 if is_mention {
-                    if let Some(user) = self.username.clone() {
+                    if let Some(user) = login_data.username {
                         highlights.push(user);
                     }
-                    if let Some(mxid) = self.uid.clone() {
-                        highlights.push(mxid);
-                    }
+                    highlights.push(login_data.uid.clone());
                     highlights.push(String::from("message_menu"));
 
                     RowType::Mention
@@ -483,14 +484,14 @@ impl AppOp {
             None
         };
 
-        let uid = self.uid.clone().unwrap_or_default();
-        let admin = match self.uid.clone().and_then(|uid| room.admins.get(&uid)) {
-            Some(&pl) => pl,
-            None => 0,
-        };
-        let redactable = admin != 0 || uid == msg.sender;
+        let admin = room
+            .admins
+            .get(&login_data.uid)
+            .map(|n| *n)
+            .unwrap_or_default();
+        let redactable = admin != 0 || login_data.uid.clone() == msg.sender;
 
-        let is_last_viewed = msg.receipt.contains_key(&uid);
+        let is_last_viewed = msg.receipt.contains_key(&login_data.uid);
         Some(create_ui_message(
             msg.clone(),
             name,
diff --git a/fractal-gtk/src/appop/mod.rs b/fractal-gtk/src/appop/mod.rs
index ffd5abc6..5c5074dc 100644
--- a/fractal-gtk/src/appop/mod.rs
+++ b/fractal-gtk/src/appop/mod.rs
@@ -44,21 +44,26 @@ mod user;
 use self::member::SearchType;
 use self::message::TmpMsg;
 
+#[derive(Clone, Debug)]
+pub struct LoginData {
+    pub access_token: AccessToken,
+    pub uid: String,
+    pub username: Option<String>,
+    pub avatar: Option<String>,
+    pub server_url: Url,
+    pub identity_url: Url,
+}
+
 pub struct AppOp {
     pub ui: uibuilder::UI,
     pub backend: Sender<backend::BKCommand>,
 
-    pub syncing: bool,
+    pub syncing: bool, // TODO: Replace with a Mutex
     pub msg_queue: Vec<TmpMsg>,
     pub sending_message: bool,
 
-    pub access_token: Option<AccessToken>,
-    pub username: Option<String>,
-    pub uid: Option<String>,
+    pub login_data: Option<LoginData>,
     pub device_id: Option<String>,
-    pub avatar: Option<String>,
-    pub server_url: Url,
-    pub identity_url: Url,
 
     pub active_room: Option<String>,
     pub rooms: RoomList,
@@ -71,8 +76,6 @@ pub struct AppOp {
     pub state: AppState,
     pub since: Option<String>,
 
-    pub logged_in: bool,
-
     pub invitation_roomid: Option<String>,
     pub md_enabled: bool,
     pub invite_list: Vec<(Member, gtk::TextChildAnchor)>,
@@ -98,13 +101,8 @@ impl AppOp {
             rooms: HashMap::new(),
             room_settings: None,
             history: None,
-            access_token: None,
-            username: None,
-            uid: None,
+            login_data: None,
             device_id: None,
-            avatar: None,
-            server_url: globals::DEFAULT_HOMESERVER.clone(),
-            identity_url: globals::DEFAULT_IDENTITYSERVER.clone(),
             syncing: false,
             msg_queue: vec![],
             sending_message: false,
@@ -114,8 +112,6 @@ impl AppOp {
             unsent_messages: HashMap::new(),
             typing: HashMap::new(),
 
-            logged_in: false,
-
             md_enabled: false,
             invitation_roomid: None,
             invite_list: vec![],
@@ -129,21 +125,25 @@ impl AppOp {
     pub fn init(&mut self) {
         self.set_state(AppState::Loading);
 
+        // FIXME: Username and uid should not be duplicated in cache.
         if let Ok(data) = cache::load() {
             let r: Vec<Room> = data.rooms.values().cloned().collect();
             self.set_rooms(r, true);
             /* Make sure that since is never an empty string */
             self.since = data.since.filter(|s| !s.is_empty());
-            self.username = Some(data.username);
-            self.uid = Some(data.uid);
             self.device_id = Some(data.device_id);
         }
 
-        if let Ok(pass) = self.get_pass() {
-            if let Ok((Some(token), uid)) = self.get_token() {
-                self.set_token(token, Some(uid), pass.2);
+        // FIXME: Storing and getting the password is insecure.
+        //        Only the access token should be used.
+        if let Ok((username, password, server, id_url)) = self.get_pass() {
+            if let Ok((Some(access_token), uid)) = self.get_token() {
+                self.backend
+                    .send(BKCommand::SetUserID(uid.clone()))
+                    .unwrap();
+                self.bk_login(uid, access_token, self.device_id.clone(), server, id_url);
             } else {
-                self.connect(Some(pass.0), Some(pass.1), pass.2, pass.3);
+                self.connect(username, password, server, id_url);
             }
         } else {
             self.set_state(AppState::Login);
diff --git a/fractal-gtk/src/appop/notify.rs b/fractal-gtk/src/appop/notify.rs
index cce0d0c5..ed964c9b 100644
--- a/fractal-gtk/src/appop/notify.rs
+++ b/fractal-gtk/src/appop/notify.rs
@@ -41,6 +41,7 @@ impl AppOp {
     }
 
     pub fn notify(&self, app: gtk::Application, room_id: &str, id: &str) -> Option<()> {
+        let server_url = self.login_data.clone()?.server_url;
         let msg = self.get_message_by_id(room_id, id)?;
         let r = self.rooms.get(room_id)?;
         let short_body = dirty_truncate(&msg.body, 80).to_string();
@@ -57,7 +58,7 @@ impl AppOp {
 
         let (tx, rx): (Sender<(String, String)>, Receiver<(String, String)>) = channel();
         let _ = self.backend.send(BKCommand::GetUserInfoAsync(
-            self.server_url.clone(),
+            server_url,
             msg.sender.clone(),
             Some(tx),
         ));
diff --git a/fractal-gtk/src/appop/room.rs b/fractal-gtk/src/appop/room.rs
index f2ca6d13..7bbe95f5 100644
--- a/fractal-gtk/src/appop/room.rs
+++ b/fractal-gtk/src/appop/room.rs
@@ -42,7 +42,7 @@ impl AppOp {
     }
 
     pub fn set_rooms(&mut self, mut rooms: Vec<Room>, clear_room_list: bool) {
-        let access_token = unwrap_or_unit_return!(self.access_token.clone());
+        let login_data = unwrap_or_unit_return!(self.login_data.clone());
         if clear_room_list {
             self.rooms.clear();
         }
@@ -81,8 +81,8 @@ impl AppOp {
                 // Request all joined members for each new room
                 self.backend
                     .send(BKCommand::GetRoomMembers(
-                        self.server_url.clone(),
-                        access_token.clone(),
+                        login_data.server_url.clone(),
+                        login_data.access_token.clone(),
                         room.id.clone(),
                     ))
                     .unwrap();
@@ -90,8 +90,8 @@ impl AppOp {
                 // TODO: Use the avatar url returned by sync
                 self.backend
                     .send(BKCommand::GetRoomAvatar(
-                        self.server_url.clone(),
-                        access_token.clone(),
+                        login_data.server_url.clone(),
+                        login_data.access_token.clone(),
                         room.id.clone(),
                     ))
                     .unwrap();
@@ -128,16 +128,15 @@ impl AppOp {
                 });
             });
 
-            self.roomlist = widgets::RoomList::new(adj, Some(self.server_url.clone()));
+            self.roomlist = widgets::RoomList::new(adj, Some(login_data.server_url.clone()));
             self.roomlist.add_rooms(roomlist);
             container.add(self.roomlist.widget());
 
             let bk = self.backend.clone();
-            let server_url = self.server_url.clone();
             self.roomlist.connect_fav(move |room, tofav| {
                 bk.send(BKCommand::AddToFav(
-                    server_url.clone(),
-                    access_token.clone(),
+                    login_data.server_url.clone(),
+                    login_data.access_token.clone(),
                     room.id.clone(),
                     tofav,
                 ))
@@ -157,7 +156,7 @@ impl AppOp {
     }
 
     pub fn set_active_room_by_id(&mut self, id: String) {
-        let access_token = unwrap_or_unit_return!(self.access_token.clone());
+        let login_data = unwrap_or_unit_return!(self.login_data.clone());
         if let Some(room) = self.rooms.get(&id) {
             if let Some(language) = room.language.clone() {
                 self.set_language(language);
@@ -176,7 +175,7 @@ impl AppOp {
                 .downcast::<gtk::Stack>()
                 .unwrap();
 
-            let user_power = match room.admins.get(&self.uid.clone().unwrap_or_default()) {
+            let user_power = match room.admins.get(&login_data.uid) {
                 Some(p) => *p,
                 None => room
                     .power_levels
@@ -228,8 +227,8 @@ impl AppOp {
         // getting room details
         self.backend
             .send(BKCommand::SetRoom(
-                self.server_url.clone(),
-                access_token.clone(),
+                login_data.server_url.clone(),
+                login_data.access_token.clone(),
                 active_room.clone(),
             ))
             .unwrap();
@@ -261,13 +260,17 @@ impl AppOp {
 
         let actions = actions::RoomHistory::new(
             self.backend.clone(),
-            self.server_url.clone(),
-            access_token,
+            login_data.server_url,
+            login_data.access_token,
             self.ui.clone(),
         );
-        let mut history = widgets::RoomHistory::new(actions, active_room.clone(), self);
-        history.create(messages);
-        self.history = Some(history);
+        let history = widgets::RoomHistory::new(actions, active_room.clone(), self);
+        self.history = if let Some(mut history) = history {
+            history.create(messages);
+            Some(history)
+        } else {
+            None
+        };
 
         self.active_room = Some(active_room);
         self.set_state(AppState::Room);
@@ -277,12 +280,12 @@ impl AppOp {
     }
 
     pub fn really_leave_active_room(&mut self) {
-        let access_token = unwrap_or_unit_return!(self.access_token.clone());
+        let login_data = unwrap_or_unit_return!(self.login_data.clone());
         let r = self.active_room.clone().unwrap_or_default();
         self.backend
             .send(BKCommand::LeaveRoom(
-                self.server_url.clone(),
-                access_token,
+                login_data.server_url,
+                login_data.access_token,
                 r.clone(),
             ))
             .unwrap();
@@ -328,7 +331,7 @@ impl AppOp {
     }
 
     pub fn create_new_room(&mut self) {
-        let access_token = unwrap_or_unit_return!(self.access_token.clone());
+        let login_data = unwrap_or_unit_return!(self.login_data.clone());
         let name = self
             .ui
             .builder
@@ -353,8 +356,8 @@ impl AppOp {
         let internal_id: String = thread_rng().sample_iter(&Alphanumeric).take(10).collect();
         self.backend
             .send(BKCommand::NewRoom(
-                self.server_url.clone(),
-                access_token,
+                login_data.server_url,
+                login_data.access_token,
                 n.clone(),
                 p,
                 internal_id.clone(),
@@ -369,11 +372,12 @@ impl AppOp {
     }
 
     pub fn cache_rooms(&self) {
+        let login_data = unwrap_or_unit_return!(self.login_data.clone());
         // serializing rooms
         let rooms = self.rooms.clone();
         let since = self.since.clone();
-        let username = self.username.clone().unwrap_or_default();
-        let uid = self.uid.clone().unwrap_or_default();
+        let username = login_data.username.unwrap_or_default();
+        let uid = login_data.uid;
         let device_id = self.device_id.clone().unwrap_or_default();
 
         if let Err(_) = cache::store(&rooms, since, username, uid, device_id) {
@@ -401,6 +405,7 @@ impl AppOp {
     }
 
     pub fn set_room_avatar(&mut self, roomid: String, avatar: Option<Url>) {
+        let login_data = unwrap_or_unit_return!(self.login_data.clone());
         if avatar.is_none() {
             if let Ok(dest) = cache_dir_path(None, &roomid) {
                 let _ = remove_file(dest);
@@ -408,15 +413,13 @@ impl AppOp {
         }
         if let Some(r) = self.rooms.get_mut(&roomid) {
             if avatar.is_none() && r.members.len() == 2 {
-                if let Some(ref uid) = self.uid {
-                    for m in r.members.keys() {
-                        if m != uid {
-                            //FIXME: Find a better solution
-                            // create a symlink from user avatar to room avatar (works only on unix)
-                            if let Ok(source) = cache_dir_path(None, m) {
-                                if let Ok(dest) = cache_dir_path(None, &roomid) {
-                                    let _ = fs::symlink(source, dest);
-                                }
+                for m in r.members.keys() {
+                    if *m != login_data.uid {
+                        //FIXME: Find a better solution
+                        // create a symlink from user avatar to room avatar (works only on unix)
+                        if let Ok(source) = cache_dir_path(None, m) {
+                            if let Ok(dest) = cache_dir_path(None, &roomid) {
+                                let _ = fs::symlink(source, dest);
                             }
                         }
                     }
@@ -481,7 +484,7 @@ impl AppOp {
     }
 
     pub fn join_to_room(&mut self) {
-        let access_token = unwrap_or_unit_return!(self.access_token.clone());
+        let login_data = unwrap_or_unit_return!(self.login_data.clone());
         let name = self
             .ui
             .builder
@@ -496,8 +499,8 @@ impl AppOp {
 
         self.backend
             .send(BKCommand::JoinRoom(
-                self.server_url.clone(),
-                access_token,
+                login_data.server_url,
+                login_data.access_token,
                 n.clone(),
             ))
             .unwrap();
@@ -533,6 +536,7 @@ impl AppOp {
     /// For this we use the members in the room. If there's only one member we'll return that
     /// member name, if there's more than one we'll return the first one and others
     pub fn recalculate_room_name(&mut self, roomid: String) {
+        let login_data = unwrap_or_unit_return!(self.login_data.clone());
         if !self.rooms.contains_key(&roomid) {
             return;
         }
@@ -547,7 +551,7 @@ impl AppOp {
 
             // removing one because the user should be in the room
             let n = r.members.len() - 1;
-            let suid = self.uid.clone().unwrap_or_default();
+            let suid = login_data.uid;
             let mut members = r.members.iter().filter(|&(uid, _)| uid != &suid);
 
             let m1 = match members.next() {
@@ -643,15 +647,15 @@ impl AppOp {
     }
 
     pub fn new_room_avatar(&self, roomid: String) {
-        let access_token = unwrap_or_unit_return!(self.access_token.clone());
+        let login_data = unwrap_or_unit_return!(self.login_data.clone());
         if !self.rooms.contains_key(&roomid) {
             return;
         }
 
         self.backend
             .send(BKCommand::GetRoomAvatar(
-                self.server_url.clone(),
-                access_token,
+                login_data.server_url,
+                login_data.access_token,
                 roomid,
             ))
             .unwrap();
@@ -689,7 +693,7 @@ impl AppOp {
     }
 
     pub fn send_typing(&mut self) {
-        let access_token = unwrap_or_unit_return!(self.access_token.clone());
+        let login_data = unwrap_or_unit_return!(self.login_data.clone());
         if let Some(ref active_room) = self.active_room {
             let now = Instant::now();
             if let Some(last_typing) = self.typing.get(active_room) {
@@ -701,8 +705,8 @@ impl AppOp {
             self.typing.insert(active_room.clone(), now);
             self.backend
                 .send(BKCommand::SendTyping(
-                    self.server_url.clone(),
-                    access_token,
+                    login_data.server_url,
+                    login_data.access_token,
                     active_room.clone(),
                 ))
                 .unwrap();
diff --git a/fractal-gtk/src/appop/room_settings.rs b/fractal-gtk/src/appop/room_settings.rs
index f994a8f0..85e4def2 100644
--- a/fractal-gtk/src/appop/room_settings.rs
+++ b/fractal-gtk/src/appop/room_settings.rs
@@ -8,7 +8,7 @@ use crate::widgets;
 
 impl AppOp {
     pub fn create_room_settings(&mut self) -> Option<()> {
-        let access_token = self.access_token.clone()?;
+        let login_data = self.login_data.clone()?;
         let window = self
             .ui
             .builder
@@ -30,10 +30,10 @@ impl AppOp {
             let mut panel = widgets::RoomSettings::new(
                 &window,
                 self.backend.clone(),
-                self.uid.clone(),
+                login_data.uid,
                 room.clone(),
-                self.server_url.clone(),
-                access_token,
+                login_data.server_url,
+                login_data.access_token,
             );
             let (body, header) = panel.create()?;
 
diff --git a/fractal-gtk/src/appop/start_chat.rs b/fractal-gtk/src/appop/start_chat.rs
index 0c6d9c70..3cff43fd 100644
--- a/fractal-gtk/src/appop/start_chat.rs
+++ b/fractal-gtk/src/appop/start_chat.rs
@@ -13,18 +13,18 @@ use rand::{thread_rng, Rng};
 
 impl AppOp {
     pub fn start_chat(&mut self) {
-        let access_token = unwrap_or_unit_return!(self.access_token.clone());
         if self.invite_list.len() != 1 {
             return;
         }
 
+        let login_data = unwrap_or_unit_return!(self.login_data.clone());
         let user = self.invite_list[0].clone();
 
         let internal_id: String = thread_rng().sample_iter(&Alphanumeric).take(10).collect();
         self.backend
             .send(BKCommand::DirectChat(
-                self.server_url.clone(),
-                access_token,
+                login_data.server_url,
+                login_data.access_token,
                 user.0.clone(),
                 internal_id.clone(),
             ))
diff --git a/fractal-gtk/src/appop/sync.rs b/fractal-gtk/src/appop/sync.rs
index 1ad66b98..af3082a4 100644
--- a/fractal-gtk/src/appop/sync.rs
+++ b/fractal-gtk/src/appop/sync.rs
@@ -14,7 +14,7 @@ impl AppOp {
     }
 
     pub fn sync(&mut self, initial: bool) {
-        if let (Some(token), true) = (self.access_token.clone(), !self.syncing && self.logged_in) {
+        if let (Some(login_data), true) = (self.login_data.clone(), !self.syncing) {
             self.syncing = true;
             // for the initial sync we set the since to None to avoid long syncing
             // the since can be a very old value and following the spec we should
@@ -23,8 +23,8 @@ impl AppOp {
             let since = if initial { None } else { self.since.clone() };
             self.backend
                 .send(BKCommand::Sync(
-                    self.server_url.clone(),
-                    token.clone(),
+                    login_data.server_url,
+                    login_data.access_token,
                     since,
                     initial,
                 ))
diff --git a/fractal-gtk/src/appop/user.rs b/fractal-gtk/src/appop/user.rs
index f19fc558..1cf8a8a9 100644
--- a/fractal-gtk/src/appop/user.rs
+++ b/fractal-gtk/src/appop/user.rs
@@ -1,5 +1,3 @@
-use fractal_api::r0::AccessToken;
-
 use gtk;
 use gtk::prelude::*;
 
@@ -11,17 +9,21 @@ use crate::backend::BKCommand;
 use crate::widgets;
 use crate::widgets::AvatarExt;
 
+use super::LoginData;
+
 impl AppOp {
     pub fn get_username(&self) {
+        let login_data = unwrap_or_unit_return!(self.login_data.clone());
         self.backend
-            .send(BKCommand::GetUsername(self.server_url.clone()))
+            .send(BKCommand::GetUsername(login_data.server_url.clone()))
             .unwrap();
         self.backend
-            .send(BKCommand::GetAvatar(self.server_url.clone()))
+            .send(BKCommand::GetAvatar(login_data.server_url))
             .unwrap();
     }
 
     pub fn show_user_info(&self) {
+        let login_data = unwrap_or_unit_return!(self.login_data.clone());
         let stack = self
             .ui
             .builder
@@ -29,7 +31,7 @@ impl AppOp {
             .expect("Can't find user_info_avatar in ui file.");
 
         /* Show user infos inside the popover but wait for all data to arrive */
-        if self.avatar.is_some() && self.username.is_some() && self.uid.is_some() {
+        if login_data.avatar.is_some() && login_data.username.is_some() {
             let avatar = self
                 .ui
                 .builder
@@ -48,8 +50,8 @@ impl AppOp {
                 .get_object::<gtk::Label>("user_info_uid")
                 .expect("Can't find user_info_avatar in ui file.");
 
-            uid.set_text(&self.uid.clone().unwrap_or_default());
-            name.set_text(&self.username.clone().unwrap_or_default());
+            uid.set_text(&login_data.uid);
+            name.set_text(&login_data.username.clone().unwrap_or_default());
 
             /* remove all old avatar from the popover */
             for w in avatar.get_children().iter() {
@@ -57,12 +59,17 @@ impl AppOp {
             }
 
             let w = widgets::Avatar::avatar_new(Some(40));
-            let uid = self.uid.clone().unwrap_or_default();
-            let data = w.circle(uid.clone(), self.username.clone(), 40, None, None);
+            let data = w.circle(
+                login_data.uid.clone(),
+                login_data.username.clone(),
+                40,
+                None,
+                None,
+            );
             download_to_cache(
                 self.backend.clone(),
-                self.server_url.clone(),
-                uid.clone(),
+                login_data.server_url.clone(),
+                login_data.uid.clone(),
                 data.clone(),
             );
 
@@ -73,15 +80,14 @@ impl AppOp {
         }
 
         let eb = gtk::EventBox::new();
-        match self.avatar.clone() {
+        match login_data.avatar.clone() {
             Some(_) => {
                 let w = widgets::Avatar::avatar_new(Some(24));
-                let uid = self.uid.clone().unwrap_or_default();
-                let data = w.circle(uid.clone(), self.username.clone(), 24, None, None);
+                let data = w.circle(login_data.uid.clone(), login_data.username, 24, None, None);
                 download_to_cache(
                     self.backend.clone(),
-                    self.server_url.clone(),
-                    uid.clone(),
+                    login_data.server_url.clone(),
+                    login_data.uid.clone(),
                     data.clone(),
                 );
 
@@ -98,26 +104,24 @@ impl AppOp {
         eb.connect_button_press_event(move |_, _| Inhibit(false));
     }
 
-    pub fn set_access_token(&mut self, access_token: Option<AccessToken>) {
-        self.access_token = access_token;
-    }
-
-    pub fn set_username(&mut self, username: Option<String>) {
-        self.username = username;
+    pub fn set_login_data(&mut self, login_data: LoginData) {
+        self.login_data = Some(login_data);
         self.show_user_info();
     }
 
-    pub fn set_uid(&mut self, uid: Option<String>) {
-        self.uid = uid;
-        self.show_user_info();
-    }
-
-    pub fn set_device(&mut self, device: Option<String>) {
-        self.device_id = device;
+    pub fn set_username(&mut self, username: Option<String>) {
+        let login_data = unwrap_or_unit_return!(self.login_data.clone());
+        self.set_login_data(LoginData {
+            username,
+            ..login_data
+        });
     }
 
     pub fn set_avatar(&mut self, fname: Option<String>) {
-        self.avatar = fname;
-        self.show_user_info();
+        let login_data = unwrap_or_unit_return!(self.login_data.clone());
+        self.set_login_data(LoginData {
+            avatar: fname,
+            ..login_data
+        });
     }
 }
diff --git a/fractal-gtk/src/passwd.rs b/fractal-gtk/src/passwd.rs
index 16afa93d..e7448066 100644
--- a/fractal-gtk/src/passwd.rs
+++ b/fractal-gtk/src/passwd.rs
@@ -37,7 +37,7 @@ pub trait PasswordStorage {
         ss_storage::get_pass()
     }
 
-    fn store_token(&self, uid: String, token: Option<AccessToken>) -> Result<(), Error> {
+    fn store_token(&self, uid: String, token: AccessToken) -> Result<(), Error> {
         ss_storage::store_token(uid, token)
     }
 
@@ -73,7 +73,7 @@ mod ss_storage {
         Ok(())
     }
 
-    pub fn store_token(uid: String, token: Option<AccessToken>) -> Result<(), Error> {
+    pub fn store_token(uid: String, token: AccessToken) -> Result<(), Error> {
         let ss = SecretService::new(EncryptionType::Dh)?;
         let collection = ss.get_default_collection()?;
         let key = "fractal-token";
@@ -84,16 +84,11 @@ mod ss_storage {
         // create new item
         collection.unlock()?;
         collection.create_item(
-            key,                 // label
-            vec![("uid", &uid)], // properties
-            token
-                .as_ref()
-                .map(ToString::to_string)
-                .as_ref()
-                .map(String::as_bytes)
-                .unwrap_or_default(), //secret
-            true,                // replace item with same attributes
-            "text/plain",        // secret content type
+            key,                          // label
+            vec![("uid", &uid)],          // properties
+            token.to_string().as_bytes(), // secret
+            true,                         // replace item with same attributes
+            "text/plain",                 // secret content type
         )?;
 
         Ok(())
diff --git a/fractal-gtk/src/widgets/address.rs b/fractal-gtk/src/widgets/address.rs
index 93634609..3c852eb9 100644
--- a/fractal-gtk/src/widgets/address.rs
+++ b/fractal-gtk/src/widgets/address.rs
@@ -131,7 +131,7 @@ impl<'a> Address<'a> {
     }
 
     fn connect(&mut self) {
-        let access_token = unwrap_or_unit_return!(self.op.access_token.clone());
+        let login_data = unwrap_or_unit_return!(self.op.login_data.clone());
         let button = self.button.clone();
         let medium = self.medium.clone();
         self.entry.connect_property_text_notify(move |w| {
@@ -162,8 +162,9 @@ impl<'a> Address<'a> {
         let action = self.action.clone();
         let entry = self.entry.clone();
         let address = self.address.clone();
-        let server_url = self.op.server_url.clone();
-        let id_server = self.op.identity_url.clone();
+        let access_token = login_data.access_token;
+        let server_url = login_data.server_url;
+        let id_server = login_data.identity_url;
         let backend = self.op.backend.clone();
         self.signal_id = Some(self.button.clone().connect_clicked(move |w| {
             if !w.get_sensitive() || !w.is_visible() {
diff --git a/fractal-gtk/src/widgets/login.rs b/fractal-gtk/src/widgets/login.rs
index 74ccbff1..6491e167 100644
--- a/fractal-gtk/src/widgets/login.rs
+++ b/fractal-gtk/src/widgets/login.rs
@@ -118,12 +118,9 @@ impl LoginWidget {
                     err_label.hide();
                     op.lock().unwrap().set_state(AppState::Loading);
                     op.lock().unwrap().since = None;
-                    op.lock().unwrap().connect(
-                        Some(username),
-                        Some(password),
-                        homeserver_url,
-                        idserver,
-                    );
+                    op.lock()
+                        .unwrap()
+                        .connect(username, password, homeserver_url, idserver);
                 } else {
                     err_label.show();
                 }
diff --git a/fractal-gtk/src/widgets/member.rs b/fractal-gtk/src/widgets/member.rs
index b2911c14..0d219f38 100644
--- a/fractal-gtk/src/widgets/member.rs
+++ b/fractal-gtk/src/widgets/member.rs
@@ -26,7 +26,6 @@ impl<'a> MemberBox<'a> {
     }
 
     pub fn widget(&self, show_uid: bool) -> gtk::EventBox {
-        let backend = self.op.backend.clone();
         let username = gtk::Label::new(None);
         let uid = gtk::Label::new(None);
         let event_box = gtk::EventBox::new();
@@ -62,13 +61,11 @@ impl<'a> MemberBox<'a> {
             badge,
             None,
         );
+        let backend = self.op.backend.clone();
         let member_id = self.member.uid.clone();
-        download_to_cache(
-            backend.clone(),
-            self.op.server_url.clone(),
-            member_id.clone(),
-            data.clone(),
-        );
+        if let Some(login_data) = self.op.login_data.clone() {
+            download_to_cache(backend, login_data.server_url, member_id, data);
+        };
 
         avatar.set_margin_start(3);
         avatar.set_valign(gtk::Align::Center);
@@ -88,7 +85,6 @@ impl<'a> MemberBox<'a> {
     }
 
     pub fn pill(&self) -> gtk::Box {
-        let backend = self.op.backend.clone();
         let pill = gtk::Box::new(gtk::Orientation::Horizontal, 3);
 
         let username = gtk::Label::new(None);
@@ -105,13 +101,11 @@ impl<'a> MemberBox<'a> {
             None,
             None,
         );
+        let backend = self.op.backend.clone();
         let member_id = self.member.uid.clone();
-        download_to_cache(
-            backend.clone(),
-            self.op.server_url.clone(),
-            member_id.clone(),
-            data.clone(),
-        );
+        if let Some(login_data) = self.op.login_data.clone() {
+            download_to_cache(backend, login_data.server_url, member_id, data);
+        };
 
         avatar.set_margin_start(3);
 
diff --git a/fractal-gtk/src/widgets/room.rs b/fractal-gtk/src/widgets/room.rs
index 96b3f9fd..109f9ba3 100644
--- a/fractal-gtk/src/widgets/room.rs
+++ b/fractal-gtk/src/widgets/room.rs
@@ -44,7 +44,7 @@ impl<'a> RoomBox<'a> {
     fn build_room_box(&self) -> gtk::Box {
         let widget_box = gtk::Box::new(gtk::Orientation::Horizontal, 0);
 
-        if let Some(access_token) = self.op.access_token.clone() {
+        if let Some(login_data) = self.op.login_data.clone() {
             let room = self.room;
 
             let avatar = widgets::Avatar::avatar_new(Some(AVATAR_SIZE));
@@ -120,12 +120,11 @@ impl<'a> RoomBox<'a> {
             let join_button = gtk::Button::new_with_label(i18n("Join").as_str());
             let room_id = room.id.clone();
             let backend = self.op.backend.clone();
-            let server_url = self.op.server_url.clone();
             join_button.connect_clicked(move |_| {
                 backend
                     .send(BKCommand::JoinRoom(
-                        server_url.clone(),
-                        access_token.clone(),
+                        login_data.server_url.clone(),
+                        login_data.access_token.clone(),
                         room_id.clone(),
                     ))
                     .unwrap();
diff --git a/fractal-gtk/src/widgets/room_history.rs b/fractal-gtk/src/widgets/room_history.rs
index 2ff289a6..b4fe309b 100644
--- a/fractal-gtk/src/widgets/room_history.rs
+++ b/fractal-gtk/src/widgets/room_history.rs
@@ -96,7 +96,7 @@ pub struct RoomHistory {
 }
 
 impl RoomHistory {
-    pub fn new(actions: SimpleActionGroup, room_id: String, op: &AppOp) -> RoomHistory {
+    pub fn new(actions: SimpleActionGroup, room_id: String, op: &AppOp) -> Option<RoomHistory> {
         let history_container = op
             .ui
             .builder
@@ -115,13 +115,13 @@ impl RoomHistory {
         /* Add the action groupe to the room_history */
         listbox.insert_action_group("room_history", Some(&actions));
 
-        RoomHistory {
+        Some(RoomHistory {
             rows: Rc::new(RefCell::new(List::new(scroll, listbox))),
             backend: op.backend.clone(),
-            server_url: op.server_url.clone(),
+            server_url: op.login_data.clone()?.server_url.clone(),
             source_id: Rc::new(RefCell::new(None)),
             queue: Rc::new(RefCell::new(VecDeque::new())),
-        }
+        })
     }
 
     pub fn create(&mut self, mut messages: Vec<MessageContent>) -> Option<()> {
diff --git a/fractal-gtk/src/widgets/room_settings.rs b/fractal-gtk/src/widgets/room_settings.rs
index b2f9f77d..48d8baee 100644
--- a/fractal-gtk/src/widgets/room_settings.rs
+++ b/fractal-gtk/src/widgets/room_settings.rs
@@ -25,7 +25,7 @@ use fractal_api::types::Room;
 pub struct RoomSettings {
     actions: gio::SimpleActionGroup,
     room: Room,
-    uid: Option<String>,
+    uid: String,
     builder: gtk::Builder,
     members_list: Option<MembersList>,
     backend: Sender<BKCommand>,
@@ -37,7 +37,7 @@ impl RoomSettings {
     pub fn new(
         window: &gtk::Window,
         backend: Sender<BKCommand>,
-        uid: Option<String>,
+        uid: String,
         room: Room,
         server_url: Url,
         access_token: AccessToken,
@@ -189,13 +189,13 @@ impl RoomSettings {
         }
     }
 
-    fn init_room_settings(&mut self) -> Option<()> {
+    fn init_room_settings(&mut self) {
         let name = self.room.name.clone();
         let topic = self.room.topic.clone();
         let mut is_room = true;
         let mut is_group = false;
         let members: Vec<Member> = self.room.members.values().cloned().collect();
-        let power = *self.room.admins.get(&self.uid.clone()?).unwrap_or(&0);
+        let power = *self.room.admins.get(&self.uid.clone()).unwrap_or(&0);
 
         let edit = power >= 50 && !self.room.direct;
 
@@ -228,20 +228,15 @@ impl RoomSettings {
         self.room_settings_show_admin_groupe(is_group && edit);
         self.room_settings_show_admin_room(is_room && edit);
         self.room_settings_hide_not_implemented_widgets();
-
-        None
     }
 
     /* returns the uid of the fisrt member in the room, ignoring the current user */
     fn get_direct_partner_uid(&self, members: Vec<Member>) -> Option<String> {
-        let mut uid = None;
-        for member in members {
-            if member.uid != self.uid.clone()? {
-                uid = Some(member.uid);
-                break;
-            }
-        }
-        uid
+        members
+            .iter()
+            .map(|m| m.uid.clone())
+            .filter(|uid| *uid != self.uid)
+            .nth(0)
     }
 
     pub fn room_settings_show_room_name(&self, text: Option<String>, edit: bool) -> Option<()> {
diff --git a/fractal-matrix-api/src/backend/mod.rs b/fractal-matrix-api/src/backend/mod.rs
index 6ac048b8..d5dc58ae 100644
--- a/fractal-matrix-api/src/backend/mod.rs
+++ b/fractal-matrix-api/src/backend/mod.rs
@@ -87,17 +87,17 @@ impl Backend {
 
         match cmd {
             // Register module
-            Ok(BKCommand::Login(user, passwd, server)) => {
-                register::login(self, user, passwd, server)
+            Ok(BKCommand::Login(user, passwd, server, id_url)) => {
+                register::login(self, user, passwd, server, id_url)
             }
             Ok(BKCommand::Logout(server, access_token)) => {
                 register::logout(self, server, access_token)
             }
-            Ok(BKCommand::Register(user, passwd, server)) => {
-                register::register(self, user, passwd, server)
+            Ok(BKCommand::Register(user, passwd, server, id_url)) => {
+                register::register(self, user, passwd, server, id_url)
             }
-            Ok(BKCommand::Guest(server)) => register::guest(self, server),
-            Ok(BKCommand::SetToken(token, uid)) => register::set_token(self, token, uid),
+            Ok(BKCommand::Guest(server, id_url)) => register::guest(self, server, id_url),
+            Ok(BKCommand::SetUserID(uid)) => register::set_uid(self, uid),
 
             // User module
             Ok(BKCommand::GetUsername(server)) => user::get_username(self, server),
diff --git a/fractal-matrix-api/src/backend/register.rs b/fractal-matrix-api/src/backend/register.rs
index db9b81e3..2dc8ee9c 100644
--- a/fractal-matrix-api/src/backend/register.rs
+++ b/fractal-matrix-api/src/backend/register.rs
@@ -27,7 +27,7 @@ use crate::util::HTTP_CLIENT;
 use crate::backend::types::BKResponse;
 use crate::backend::types::Backend;
 
-pub fn guest(bk: &Backend, base: Url) {
+pub fn guest(bk: &Backend, server: Url, id_url: Url) {
     let tx = bk.tx.clone();
     let data = bk.data.clone();
 
@@ -37,7 +37,7 @@ pub fn guest(bk: &Backend, base: Url) {
     let body = Default::default();
 
     thread::spawn(move || {
-        let query = register_req(base, &params, &body)
+        let query = register_req(server.clone(), &params, &body)
             .map_err(Into::into)
             .and_then(|request| {
                 HTTP_CLIENT
@@ -50,15 +50,19 @@ pub fn guest(bk: &Backend, base: Url) {
         match query {
             Ok(response) => {
                 let uid = response.user_id;
-                let tk = response.access_token;
                 let dev = response.device_id;
 
-                data.lock().unwrap().user_id = uid.clone();
-                data.lock().unwrap().since = None;
-                tx.send(BKResponse::Token(uid, tk, dev))
-                    .expect_log("Connection closed");
-                tx.send(BKResponse::Rooms(vec![], None))
-                    .expect_log("Connection closed");
+                if let Some(tk) = response.access_token {
+                    data.lock().unwrap().user_id = uid.clone();
+                    data.lock().unwrap().since = None;
+                    tx.send(BKResponse::Token(uid, tk, dev, server, id_url))  // TODO: Use UserId and 
DeviceId
+                        .expect_log("Connection closed");
+                    tx.send(BKResponse::Rooms(vec![], None))
+                        .expect_log("Connection closed");
+                } else {
+                    tx.send(BKResponse::GuestLoginError(Error::BackendError))
+                        .expect_log("Connection closed");
+                }
             }
             Err(err) => {
                 tx.send(BKResponse::GuestLoginError(err))
@@ -68,7 +72,7 @@ pub fn guest(bk: &Backend, base: Url) {
     });
 }
 
-pub fn login(bk: &Backend, user: String, password: String, base: Url) {
+pub fn login(bk: &Backend, user: String, password: String, server: Url, id_url: Url) {
     let tx = bk.tx.clone();
     let data = bk.data.clone();
 
@@ -92,7 +96,7 @@ pub fn login(bk: &Backend, user: String, password: String, base: Url) {
     };
 
     thread::spawn(move || {
-        let query = login_req(base, &body)
+        let query = login_req(server.clone(), &body)
             .map_err(Into::into)
             .and_then(|request| {
                 HTTP_CLIENT
@@ -105,16 +109,15 @@ pub fn login(bk: &Backend, user: String, password: String, base: Url) {
         match query {
             Ok(response) => {
                 let uid = response.user_id.unwrap_or(user);
-                let tk = response.access_token;
                 let dev = response.device_id;
 
-                if uid.is_empty() || tk.is_none() {
-                    tx.send(BKResponse::LoginError(Error::BackendError))
-                        .expect_log("Connection closed");
-                } else {
+                if let (Some(tk), false) = (response.access_token, uid.is_empty()) {
                     data.lock().unwrap().user_id = uid.clone();
                     data.lock().unwrap().since = None;
-                    tx.send(BKResponse::Token(uid, tk, dev))
+                    tx.send(BKResponse::Token(uid, tk, dev, server, id_url))  // TODO: Use UserId and 
DeviceId
+                        .expect_log("Connection closed");
+                } else {
+                    tx.send(BKResponse::LoginError(Error::BackendError))
                         .expect_log("Connection closed");
                 }
             }
@@ -126,12 +129,9 @@ pub fn login(bk: &Backend, user: String, password: String, base: Url) {
     });
 }
 
-pub fn set_token(bk: &Backend, token: AccessToken, uid: String) {
+pub fn set_uid(bk: &Backend, uid: String) {
     bk.data.lock().unwrap().user_id = uid.clone();
     bk.data.lock().unwrap().since = None;
-    bk.tx
-        .send(BKResponse::Token(uid, Some(token), None))
-        .expect_log("Connection closed");
 }
 
 pub fn logout(bk: &Backend, server: Url, access_token: AccessToken) {
@@ -161,7 +161,7 @@ pub fn logout(bk: &Backend, server: Url, access_token: AccessToken) {
     });
 }
 
-pub fn register(bk: &Backend, user: String, password: String, base: Url) {
+pub fn register(bk: &Backend, user: String, password: String, server: Url, id_url: Url) {
     let data = bk.data.clone();
     let tx = bk.tx.clone();
 
@@ -173,7 +173,7 @@ pub fn register(bk: &Backend, user: String, password: String, base: Url) {
     };
 
     thread::spawn(move || {
-        let query = register_req(base, &params, &body)
+        let query = register_req(server.clone(), &params, &body)
             .map_err(Into::into)
             .and_then(|request| {
                 HTTP_CLIENT
@@ -186,13 +186,14 @@ pub fn register(bk: &Backend, user: String, password: String, base: Url) {
         match query {
             Ok(response) => {
                 let uid = response.user_id;
-                let tk = response.access_token;
                 let dev = response.device_id;
 
-                data.lock().unwrap().user_id = uid.clone();
-                data.lock().unwrap().since = None;
-                tx.send(BKResponse::Token(uid, tk, dev))
-                    .expect_log("Connection closed");
+                if let Some(tk) = response.access_token {
+                    data.lock().unwrap().user_id = uid.clone();
+                    data.lock().unwrap().since = None;
+                    tx.send(BKResponse::Token(uid, tk, dev, server, id_url))  // TODO: Use UserId
+                        .expect_log("Connection closed");
+                }
             }
             Err(err) => {
                 tx.send(BKResponse::LoginError(err))
diff --git a/fractal-matrix-api/src/backend/types.rs b/fractal-matrix-api/src/backend/types.rs
index 1d05bd04..808c185a 100644
--- a/fractal-matrix-api/src/backend/types.rs
+++ b/fractal-matrix-api/src/backend/types.rs
@@ -20,13 +20,13 @@ use url::Url;
 
 #[derive(Debug)]
 pub enum BKCommand {
-    Login(String, String, Url),
-    SetToken(AccessToken, String),
+    Login(String, String, Url, Url),
+    SetUserID(String),
     Logout(Url, AccessToken),
     #[allow(dead_code)]
-    Register(String, String, Url),
+    Register(String, String, Url, Url),
     #[allow(dead_code)]
-    Guest(Url),
+    Guest(Url, Url),
     GetUsername(Url),
     SetUserName(Url, AccessToken, String),
     GetThreePID(Url, AccessToken),
@@ -92,7 +92,7 @@ pub enum BKCommand {
 #[derive(Debug)]
 pub enum BKResponse {
     ShutDown,
-    Token(String, Option<AccessToken>, Option<String>),
+    Token(String, AccessToken, Option<String>, Url, Url),
     Logout(Result<(), Error>),
     Name(Result<String, Error>),
     SetUserName(Result<String, Error>),


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