Save and use authentication token
This commit is contained in:
parent
3054e724fd
commit
a9c1d6ed01
@ -7,6 +7,11 @@ edition = "2018"
|
|||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
anyhow = "1.0"
|
||||||
|
dirs-next = "2.0"
|
||||||
iced = { git = "https://github.com/hecrj/iced", rev = "fc4270f", features = ["debug", "tokio"] }
|
iced = { git = "https://github.com/hecrj/iced", rev = "fc4270f", features = ["debug", "tokio"] }
|
||||||
|
hostname = "0.3"
|
||||||
matrix-sdk = { git = "https://github.com/matrix-org/matrix-rust-sdk", rev = "27c6f30" }
|
matrix-sdk = { git = "https://github.com/matrix-org/matrix-rust-sdk", rev = "27c6f30" }
|
||||||
tokio = { version = "0.2", features = ["macros"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
tokio = "0.2"
|
||||||
|
toml = "0.5"
|
||||||
|
17
src/main.rs
17
src/main.rs
@ -1,9 +1,22 @@
|
|||||||
|
extern crate dirs_next as dirs;
|
||||||
|
|
||||||
|
use std::fs::Permissions;
|
||||||
|
use std::os::unix::fs::PermissionsExt;
|
||||||
|
|
||||||
use iced::Application;
|
use iced::Application;
|
||||||
|
|
||||||
pub mod matrix;
|
pub mod matrix;
|
||||||
pub mod ui;
|
pub mod ui;
|
||||||
|
|
||||||
#[tokio::main]
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
async fn main() {
|
let config_dir = dirs::config_dir().unwrap().join("retrix");
|
||||||
|
// Make sure config dir exists and is not accessible by other users.
|
||||||
|
if !config_dir.is_dir() {
|
||||||
|
std::fs::create_dir(&config_dir)?;
|
||||||
|
std::fs::set_permissions(&config_dir, Permissions::from_mode(0o700))?;
|
||||||
|
}
|
||||||
|
|
||||||
ui::Retrix::run(iced::Settings::default());
|
ui::Retrix::run(iced::Settings::default());
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,38 @@
|
|||||||
use matrix_sdk::{reqwest::Url, Client, Session, SyncSettings};
|
use matrix_sdk::{
|
||||||
|
identifiers::DeviceId, identifiers::UserId, reqwest::Url, Client, ClientConfig, Session,
|
||||||
|
SyncSettings,
|
||||||
|
};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
pub type Error = Box<dyn std::error::Error>;
|
pub type Error = anyhow::Error;
|
||||||
|
|
||||||
|
// Needed to be able to serialize `Session`s. Should be done with serde remote.
|
||||||
|
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||||
|
pub struct SessionWrapper {
|
||||||
|
access_token: String,
|
||||||
|
user_id: UserId,
|
||||||
|
device_id: Box<DeviceId>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<SessionWrapper> for Session {
|
||||||
|
fn from(s: SessionWrapper) -> Self {
|
||||||
|
Self {
|
||||||
|
access_token: s.access_token,
|
||||||
|
user_id: s.user_id,
|
||||||
|
device_id: s.device_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Session> for SessionWrapper {
|
||||||
|
fn from(s: Session) -> Self {
|
||||||
|
Self {
|
||||||
|
access_token: s.access_token,
|
||||||
|
user_id: s.user_id,
|
||||||
|
device_id: s.device_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn login(
|
pub async fn login(
|
||||||
username: &str,
|
username: &str,
|
||||||
@ -8,17 +40,57 @@ pub async fn login(
|
|||||||
server: &str,
|
server: &str,
|
||||||
) -> Result<(Client, Session), Error> {
|
) -> Result<(Client, Session), Error> {
|
||||||
let url = Url::parse(server)?;
|
let url = Url::parse(server)?;
|
||||||
let client = Client::new(url)?;
|
let config = ClientConfig::new().store_path(&dirs::config_dir().unwrap().join("retrix"));
|
||||||
|
let client = Client::new_with_config(url, config)?;
|
||||||
|
|
||||||
let response = client
|
let session = match get_session()? {
|
||||||
.login(username, password, None, Some("retrix"))
|
Some(session) => {
|
||||||
.await?;
|
client.restore_login(session.clone()).await?;
|
||||||
let session = Session {
|
session
|
||||||
access_token: response.access_token,
|
}
|
||||||
user_id: response.user_id,
|
None => {
|
||||||
device_id: response.device_id,
|
let response = client
|
||||||
|
.login(username, password, None, Some("retrix"))
|
||||||
|
.await?;
|
||||||
|
let session = Session {
|
||||||
|
access_token: response.access_token,
|
||||||
|
user_id: response.user_id,
|
||||||
|
device_id: response.device_id,
|
||||||
|
};
|
||||||
|
write_session(session.clone())?;
|
||||||
|
session
|
||||||
|
}
|
||||||
};
|
};
|
||||||
client.sync(SyncSettings::new()).await;
|
client.sync_once(SyncSettings::new()).await?;
|
||||||
|
|
||||||
Ok((client, session))
|
Ok((client, session))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// File path to store session data in
|
||||||
|
fn session_path() -> std::path::PathBuf {
|
||||||
|
dirs::config_dir()
|
||||||
|
.unwrap()
|
||||||
|
.join("retrix")
|
||||||
|
.join("session.toml")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read session data from config file
|
||||||
|
fn get_session() -> Result<Option<Session>, Error> {
|
||||||
|
let path = session_path();
|
||||||
|
if !path.is_file() {
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
let session: SessionWrapper = toml::from_slice(&std::fs::read(path)?)?;
|
||||||
|
Ok(Some(session.into()))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Save session data to config file
|
||||||
|
fn write_session(session: Session) -> Result<(), Error> {
|
||||||
|
let session: SessionWrapper = session.into();
|
||||||
|
let path = session_path();
|
||||||
|
|
||||||
|
let serialized = toml::to_string(&session)?;
|
||||||
|
std::fs::write(path, serialized)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
51
src/ui.rs
51
src/ui.rs
@ -1,6 +1,6 @@
|
|||||||
use iced::{
|
use iced::{
|
||||||
text_input::{self, TextInput},
|
text_input::{self, TextInput},
|
||||||
Application, Button, Column, Command, Container, Element, Text,
|
Application, Button, Column, Command, Container, Element, Length, Row, Text,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::matrix;
|
use crate::matrix;
|
||||||
@ -21,17 +21,23 @@ pub enum Retrix {
|
|||||||
LoggedIn {
|
LoggedIn {
|
||||||
client: matrix_sdk::Client,
|
client: matrix_sdk::Client,
|
||||||
session: matrix_sdk::Session,
|
session: matrix_sdk::Session,
|
||||||
|
|
||||||
|
rooms: Vec<matrix_sdk::Room>,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Message {
|
pub enum Message {
|
||||||
|
// Login form messages
|
||||||
SetUser(String),
|
SetUser(String),
|
||||||
SetPassword(String),
|
SetPassword(String),
|
||||||
SetServer(String),
|
SetServer(String),
|
||||||
Login,
|
Login,
|
||||||
LoggedIn(matrix_sdk::Client, matrix_sdk::Session),
|
LoggedIn(matrix_sdk::Client, matrix_sdk::Session),
|
||||||
SetError(String),
|
SetError(String),
|
||||||
|
|
||||||
|
// Main state messages
|
||||||
|
ResetRooms(Vec<matrix_sdk::Room>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Application for Retrix {
|
impl Application for Retrix {
|
||||||
@ -83,10 +89,32 @@ impl Application for Retrix {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Message::LoggedIn(client, session) => *self = Retrix::LoggedIn { client, session },
|
Message::LoggedIn(client, session) => {
|
||||||
|
*self = Retrix::LoggedIn {
|
||||||
|
client: client.clone(),
|
||||||
|
session,
|
||||||
|
rooms: Vec::new(),
|
||||||
|
};
|
||||||
|
let client = client.clone();
|
||||||
|
Command::perform(
|
||||||
|
async move {
|
||||||
|
let mut list = Vec::new();
|
||||||
|
for (id, room) in client.joined_rooms().read().await.iter() {
|
||||||
|
let room = room.read().await;
|
||||||
|
list.push(room.clone());
|
||||||
|
}
|
||||||
|
list
|
||||||
|
},
|
||||||
|
|rooms| Message::ResetRooms(rooms),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
},
|
},
|
||||||
_ => (),
|
Retrix::LoggedIn { ref mut rooms, .. } => match message {
|
||||||
}
|
Message::ResetRooms(r) => *rooms = r,
|
||||||
|
_ => (),
|
||||||
|
},
|
||||||
|
};
|
||||||
Command::none()
|
Command::none()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,6 +130,7 @@ impl Application for Retrix {
|
|||||||
ref server,
|
ref server,
|
||||||
ref error,
|
ref error,
|
||||||
} => {
|
} => {
|
||||||
|
// Login form
|
||||||
let mut content = Column::new()
|
let mut content = Column::new()
|
||||||
.width(500.into())
|
.width(500.into())
|
||||||
.push(Text::new("Username"))
|
.push(Text::new("Username"))
|
||||||
@ -136,10 +165,16 @@ impl Application for Retrix {
|
|||||||
.height(iced::Length::Fill)
|
.height(iced::Length::Fill)
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
Retrix::LoggedIn {
|
Retrix::LoggedIn { ref rooms, .. } => {
|
||||||
ref client,
|
//let mut root_row = Row::new().width(Length::Fill).height(Length::Fill);
|
||||||
ref session,
|
let mut room_col = Column::new().width(400.into()).height(Length::Fill);
|
||||||
} => Text::new(format!("Logged in to {}", session.user_id)).into(),
|
for room in rooms {
|
||||||
|
room_col = room_col.push(Text::new(room.display_name()));
|
||||||
|
}
|
||||||
|
room_col.into()
|
||||||
|
//root_row = root_row.push(room_col);
|
||||||
|
//root_row.into()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user