use rand; use ring::{digest, pbkdf2}; use db::schema::*; // Collection content #[derive(Debug, Queryable, Serialize)] pub struct Song { #[serde(skip_serializing)] id: i32, pub path: String, #[serde(skip_serializing)] pub parent: String, pub track_number: Option, pub disc_number: Option, pub title: Option, pub artist: Option, pub album_artist: Option, pub year: Option, pub album: Option, pub artwork: Option, } #[derive(Debug, Queryable, Serialize)] pub struct Directory { #[serde(skip_serializing)] id: i32, pub path: String, #[serde(skip_serializing)] pub parent: Option, pub artist: Option, pub year: Option, pub album: Option, pub artwork: Option, pub date_added: i32, } #[derive(Debug, Serialize)] pub enum CollectionFile { Directory(Directory), Song(Song), } // User #[derive(Debug, Queryable)] pub struct User { id: i32, pub name: String, pub password_salt: Vec, pub password_hash: Vec, } impl User { pub fn verify_password(&self, attempted_password: &str) -> bool { pbkdf2::verify(DIGEST_ALG, HASH_ITERATIONS, &self.password_salt, attempted_password.as_bytes(), &self.password_hash) .is_ok() } } #[derive(Debug, Insertable)] #[table_name="users"] pub struct NewUser { pub name: String, pub password_salt: Vec, pub password_hash: Vec, } static DIGEST_ALG: &'static pbkdf2::PRF = &pbkdf2::HMAC_SHA256; const CREDENTIAL_LEN: usize = digest::SHA256_OUTPUT_LEN; const HASH_ITERATIONS: u32 = 10000; type PasswordHash = [u8; CREDENTIAL_LEN]; impl NewUser { pub fn new(name: &str, password: &str) -> NewUser { let salt = rand::random::<[u8; 16]>().to_vec(); let hash = NewUser::hash_password(&salt, password); NewUser { name: name.to_owned(), password_salt: salt, password_hash: hash, } } pub fn hash_password(salt: &Vec, password: &str) -> Vec { let mut hash: PasswordHash = [0; CREDENTIAL_LEN]; pbkdf2::derive(DIGEST_ALG, HASH_ITERATIONS, salt, password.as_bytes(), &mut hash); hash.to_vec() } } // Misc Settings #[derive(Debug, Queryable)] pub struct MiscSettings { id: i32, pub auth_secret: String, pub index_sleep_duration_seconds: i32, pub index_album_art_pattern: String, }