Fixed a bug where password where not preserved when ammending config

This commit is contained in:
Antoine Gersant 2017-07-01 21:10:00 -07:00
parent 921ea0f8e5
commit 54aab4badf
3 changed files with 100 additions and 17 deletions

View file

@ -24,13 +24,13 @@ pub struct MiscSettings {
pub index_album_art_pattern: String, pub index_album_art_pattern: String,
} }
#[derive(Debug, PartialEq, Serialize, Deserialize)] #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct ConfigUser { pub struct ConfigUser {
pub name: String, pub name: String,
pub password: String, pub password: String,
} }
#[derive(Debug, PartialEq, Serialize, Deserialize)] #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct Config { pub struct Config {
pub album_art_pattern: Option<String>, pub album_art_pattern: Option<String>,
pub reindex_every_n_seconds: Option<i32>, pub reindex_every_n_seconds: Option<i32>,
@ -155,8 +155,28 @@ pub fn ammend<T>(db: &T, new_config: &Config) -> Result<()>
} }
if let Some(ref config_users) = new_config.users { if let Some(ref config_users) = new_config.users {
diesel::delete(users::table).execute(connection)?; let old_usernames: Vec<String> = users::table
for config_user in config_users { .select(users::name)
.get_results(connection)?;
// Delete users that are not in new list
// Delete users that have a new password
let delete_usernames: Vec<String> = old_usernames
.into_iter()
.filter(|old_name| match config_users.iter().find(|u| &u.name == old_name) {
None => true,
Some(new_user) => !new_user.password.is_empty(),
})
.collect::<_>();
diesel::delete(users::table.filter(users::name.eq_any(&delete_usernames)))
.execute(connection)?;
// Insert users that have a new password
let insert_users: Vec<&ConfigUser> = config_users
.iter()
.filter(|u| !u.password.is_empty())
.collect::<_>();
for ref config_user in insert_users {
let new_user = User::new(&config_user.name, &config_user.password); let new_user = User::new(&config_user.name, &config_user.password);
diesel::insert(&new_user) diesel::insert(&new_user)
.into(users::table) .into(users::table)
@ -221,25 +241,21 @@ fn test_ammend() {
}]), }]),
users: Some(vec![ConfigUser { users: Some(vec![ConfigUser {
name: "Teddy🐻".into(), name: "Teddy🐻".into(),
password: "".into(), password: "Tasty🍖".into(),
}]), }]),
ydns: Some(DDNSConfig { ydns: None,
host: "🐻🐻🐻.ydns.eu".into(),
username: "be🐻r".into(),
password: "yummy🐇".into(),
}),
}; };
let final_config = Config { let new_config = Config {
album_art_pattern: Some("🖼️\\.jpg".into()), album_art_pattern: Some("🖼️\\.jpg".into()),
reindex_every_n_seconds: Some(7734), reindex_every_n_seconds: None,
mount_dirs: Some(vec![MountPoint { mount_dirs: Some(vec![MountPoint {
source: "/home/music".into(), source: "/home/music".into(),
name: "🎵📁".into(), name: "🎵📁".into(),
}]), }]),
users: Some(vec![ConfigUser { users: Some(vec![ConfigUser {
name: "Kermit🐸".into(), name: "Kermit🐸".into(),
password: "".into(), password: "🐞🐞".into(),
}]), }]),
ydns: Some(DDNSConfig { ydns: Some(DDNSConfig {
host: "🐸🐸🐸.ydns.eu".into(), host: "🐸🐸🐸.ydns.eu".into(),
@ -248,10 +264,77 @@ fn test_ammend() {
}), }),
}; };
let mut expected_config = new_config.clone();
expected_config.reindex_every_n_seconds = initial_config.reindex_every_n_seconds;
if let Some(ref mut users) = expected_config.users {
users[0].password = "".into();
}
ammend(&db, &initial_config).unwrap(); ammend(&db, &initial_config).unwrap();
ammend(&db, &final_config).unwrap(); ammend(&db, &new_config).unwrap();
let db_config = read(&db).unwrap(); let db_config = read(&db).unwrap();
assert_eq!(db_config, final_config); assert_eq!(db_config, expected_config);
}
#[test]
fn test_ammend_preserve_password_hashes() {
use self::users::dsl::*;
let db = _get_test_db("ammend_preserve_password_hashes.sqlite");
let initial_hash: Vec<u8>;
let new_hash: Vec<u8>;
let initial_config = Config {
album_art_pattern: None,
reindex_every_n_seconds: None,
mount_dirs: None,
users: Some(vec![ConfigUser {
name: "Teddy🐻".into(),
password: "Tasty🍖".into(),
}]),
ydns: None,
};
ammend(&db, &initial_config).unwrap();
{
let connection = db.get_connection();
let connection = connection.lock().unwrap();
let connection = connection.deref();
initial_hash = users
.select(password_hash)
.filter(name.eq("Teddy🐻"))
.get_result(connection)
.unwrap();
}
let new_config = Config {
album_art_pattern: None,
reindex_every_n_seconds: None,
mount_dirs: None,
users: Some(vec![ConfigUser {
name: "Kermit🐸".into(),
password: "tasty🐞".into(),
},
ConfigUser {
name: "Teddy🐻".into(),
password: "".into(),
}]),
ydns: None,
};
ammend(&db, &new_config).unwrap();
{
let connection = db.get_connection();
let connection = connection.lock().unwrap();
let connection = connection.deref();
new_hash = users
.select(password_hash)
.filter(name.eq("Teddy🐻"))
.get_result(connection)
.unwrap();
}
assert_eq!(new_hash, initial_hash);
} }
#[test] #[test]

View file

@ -10,7 +10,7 @@ use db::{ConnectionSource, DB};
use db::ddns_config; use db::ddns_config;
use errors; use errors;
#[derive(Debug, Deserialize, Insertable, PartialEq, Queryable, Serialize)] #[derive(Clone, Debug, Deserialize, Insertable, PartialEq, Queryable, Serialize)]
#[table_name="ddns_config"] #[table_name="ddns_config"]
pub struct DDNSConfig { pub struct DDNSConfig {
pub host: String, pub host: String,

View file

@ -29,7 +29,7 @@ impl VFSSource for DB {
} }
} }
#[derive(Debug, Deserialize, Insertable, PartialEq, Queryable, Serialize)] #[derive(Clone, Debug, Deserialize, Insertable, PartialEq, Queryable, Serialize)]
#[table_name="mount_points"] #[table_name="mount_points"]
pub struct MountPoint { pub struct MountPoint {
pub source: String, pub source: String,