Storing the user password with secret-service

This commit is contained in:
Daniel García Moreno 2017-08-18 13:12:26 +02:00
parent 654dea7dbb
commit 908b88ebf4
3 changed files with 95 additions and 9 deletions

View file

@ -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"

View file

@ -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>

View file

@ -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);