Storing the user password with secret-service
This commit is contained in:
parent
654dea7dbb
commit
908b88ebf4
3 changed files with 95 additions and 9 deletions
|
@ -2,12 +2,12 @@
|
|||
authors = ["Daniel Garcia <danigm@wadobo.com>"]
|
||||
name = "guillotine"
|
||||
version = "0.1.0"
|
||||
|
||||
[dependencies]
|
||||
gdk-pixbuf = "0.1.3"
|
||||
gio = "0.1.3"
|
||||
regex = "0.2.2"
|
||||
reqwest = "0.7.2"
|
||||
secret-service = "0.4.0"
|
||||
serde = "1.0.11"
|
||||
serde_derive = "1.0.11"
|
||||
serde_json = "1.0.2"
|
||||
|
|
|
@ -394,7 +394,7 @@
|
|||
<child>
|
||||
<object class="GtkImage" id="profile_image">
|
||||
<property name="can_focus">False</property>
|
||||
<property name="icon_name">address-book-new</property>
|
||||
<property name="icon_name">image-missing</property>
|
||||
<property name="icon_size">3</property>
|
||||
</object>
|
||||
<packing>
|
||||
|
|
100
src/app.rs
100
src/app.rs
|
@ -2,6 +2,10 @@ extern crate gtk;
|
|||
extern crate gio;
|
||||
extern crate gdk_pixbuf;
|
||||
|
||||
extern crate secret_service;
|
||||
use self::secret_service::SecretService;
|
||||
use self::secret_service::EncryptionType;
|
||||
|
||||
use std::env;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::sync::mpsc::channel;
|
||||
|
@ -14,6 +18,25 @@ use backend::Backend;
|
|||
use backend;
|
||||
|
||||
|
||||
macro_rules! derror {
|
||||
($from: path, $to: path) => {
|
||||
impl From<$from> for Error {
|
||||
fn from(_: $from) -> Error {
|
||||
$to
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
SecretServiceError,
|
||||
}
|
||||
|
||||
derror!(secret_service::SsError, Error::SecretServiceError);
|
||||
|
||||
|
||||
// TODO: Is this the correct format for GApplication IDs?
|
||||
const APP_ID: &'static str = "org.gnome.guillotine";
|
||||
|
||||
|
@ -24,7 +47,7 @@ struct AppOp {
|
|||
}
|
||||
|
||||
impl AppOp {
|
||||
pub fn login(&mut self) {
|
||||
pub fn login(&self) {
|
||||
let user_entry: gtk::Entry = self.gtk_builder.get_object("login_username").unwrap();
|
||||
let pass_entry: gtk::Entry = self.gtk_builder.get_object("login_password").unwrap();
|
||||
let server_entry: gtk::Entry = self.gtk_builder.get_object("login_server").unwrap();
|
||||
|
@ -35,18 +58,24 @@ impl AppOp {
|
|||
self.connect(username, password, server_entry.get_text());
|
||||
}
|
||||
|
||||
pub fn connect(&mut self, username: String, password: String, server: Option<String>) {
|
||||
pub fn connect(&self, username: String, password: String, server: Option<String>) {
|
||||
let server_url = match server {
|
||||
Some(s) => s,
|
||||
None => String::from("https://matrix.org")
|
||||
};
|
||||
|
||||
self.store_pass(username.clone(), password.clone(), server_url.clone())
|
||||
.unwrap_or_else(|_| {
|
||||
// TODO: show an error
|
||||
println!("Error: Can't store the password using libsecret");
|
||||
});
|
||||
|
||||
self.show_loading();
|
||||
self.backend.login(username, password, server_url).unwrap();
|
||||
self.hide_popup();
|
||||
}
|
||||
|
||||
pub fn connect_guest(&mut self, server: Option<String>) {
|
||||
pub fn connect_guest(&self, server: Option<String>) {
|
||||
let server_url = match server {
|
||||
Some(s) => s,
|
||||
None => String::from("https://matrix.org")
|
||||
|
@ -103,9 +132,68 @@ impl AppOp {
|
|||
user_menu.hide();
|
||||
}
|
||||
|
||||
pub fn disconnect(&mut self) {
|
||||
pub fn disconnect(&self) {
|
||||
println!("Disconnecting");
|
||||
}
|
||||
|
||||
pub fn store_pass(&self, username: String, password: String, server: String) -> Result<(), Error> {
|
||||
let ss = SecretService::new(EncryptionType::Dh)?;
|
||||
let collection = ss.get_default_collection()?;
|
||||
|
||||
//create new item
|
||||
collection.create_item(
|
||||
"guillotine", // label
|
||||
vec![
|
||||
("username", &username),
|
||||
("server", &server),
|
||||
], // properties
|
||||
password.as_bytes(), //secret
|
||||
true, // replace item with same attributes
|
||||
"text/plain" // secret content type
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_pass(&self) -> Result<(String, String, String), Error> {
|
||||
let ss = SecretService::new(EncryptionType::Dh)?;
|
||||
let collection = ss.get_default_collection()?;
|
||||
let allpass = collection.get_all_items()?;
|
||||
|
||||
let passwd = allpass.iter()
|
||||
.find(|x| x.get_label().unwrap_or(String::from("")) == "guillotine");
|
||||
|
||||
if passwd.is_none() {
|
||||
return Err(Error::SecretServiceError);
|
||||
}
|
||||
|
||||
let p = passwd.unwrap();
|
||||
let attrs = p.get_attributes()?;
|
||||
let secret = p.get_secret()?;
|
||||
|
||||
let mut attr = attrs.iter().find(|&ref x| x.0 == "username")
|
||||
.ok_or(Error::SecretServiceError)?;
|
||||
let username = attr.1.clone();
|
||||
attr = attrs.iter().find(|&ref x| x.0 == "server")
|
||||
.ok_or(Error::SecretServiceError)?;
|
||||
let server = attr.1.clone();
|
||||
|
||||
let tup = (
|
||||
username,
|
||||
String::from_utf8(secret).unwrap(),
|
||||
server,
|
||||
);
|
||||
|
||||
Ok(tup)
|
||||
}
|
||||
|
||||
pub fn init(&self) {
|
||||
if let Ok(pass) = self.get_pass() {
|
||||
self.connect(pass.0, pass.1, Some(pass.2));
|
||||
} else {
|
||||
self.connect_guest(None);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// State for the main thread.
|
||||
|
@ -212,9 +300,7 @@ impl App {
|
|||
let args = env::args().collect::<Vec<_>>();
|
||||
let args_refs = args.iter().map(|x| &x[..]).collect::<Vec<_>>();
|
||||
|
||||
// connecting as guest
|
||||
// TODO: Use stored user if exists
|
||||
self.op.lock().unwrap().connect_guest(None);
|
||||
self.op.lock().unwrap().init();
|
||||
|
||||
// Run the main loop.
|
||||
self.gtk_app.run(args_refs.len() as i32, &args_refs);
|
||||
|
|
Loading…
Reference in a new issue