diff --git a/src/api.rs b/src/api.rs index 845ade4..f1db58f 100644 --- a/src/api.rs +++ b/src/api.rs @@ -1,4 +1,5 @@ use base64; +use crypto::scrypt; use diesel::prelude::*; use iron::headers::{Authorization, Basic, Range}; use iron::mime::Mime; @@ -7,7 +8,6 @@ use iron::{status, AroundMiddleware, Handler}; use mount::Mount; use params; use router::Router; -use crypto::scrypt; use secure_session::middleware::{SessionConfig, SessionMiddleware}; use secure_session::session::ChaCha20Poly1305SessionManager; use serde_json; @@ -57,7 +57,12 @@ where let params = scrypt::ScryptParams::new(12, 8, 1); let mut secret = [0; 32]; - scrypt::scrypt(misc.auth_secret.as_bytes(), b"polaris-salt-and-pepper-with-cheese", ¶ms, &mut secret); + scrypt::scrypt( + misc.auth_secret.as_bytes(), + b"polaris-salt-and-pepper-with-cheese", + ¶ms, + &mut secret, + ); Ok(secret) } @@ -66,8 +71,7 @@ pub fn get_handler(db: &Arc, index: &Arc>>) -> let mut api_chain = Chain::new(api_handler); let auth_secret = get_auth_secret(db.deref())?; - let session_manager = - ChaCha20Poly1305SessionManager::::from_key(auth_secret); + let session_manager = ChaCha20Poly1305SessionManager::::from_key(auth_secret); let session_config = SessionConfig::default(); let session_middleware = SessionMiddleware::< Session, @@ -221,22 +225,39 @@ fn get_endpoints(db: &Arc, index_channel: &Arc> auth_api_mount.mount("/playlist/", playlist_router); } { - let db = db.clone(); - auth_api_mount.mount("/lastfm/auth/", move |request: &mut Request| { - self::lastfm_auth(request, db.deref()) - }); - } - { - let db = db.clone(); - auth_api_mount.mount("/lastfm/now_playing/", move |request: &mut Request| { - self::lastfm_now_playing(request, db.deref()) - }); - } - { - let db = db.clone(); - auth_api_mount.mount("/lastfm/scrobble/", move |request: &mut Request| { - self::lastfm_scrobble(request, db.deref()) - }); + let mut lastfm_router = Router::new(); + let now_playing_db = db.clone(); + let link_db = db.clone(); + let unlink_db = db.clone(); + let scrobble_db = db.clone(); + + lastfm_router.put( + "/now_playing", + move |request: &mut Request| { + self::lastfm_now_playing(request, now_playing_db.deref()) + }, + "now_playing", + ); + + lastfm_router.get( + "/link", + move |request: &mut Request| self::lastfm_link(request, link_db.deref()), + "link", + ); + + lastfm_router.delete( + "/link", + move |request: &mut Request| self::lastfm_unlink(request, unlink_db.deref()), + "unlink", + ); + + lastfm_router.get( + "/scrobble", + move |request: &mut Request| self::lastfm_scrobble(request, scrobble_db.deref()), + "auth", + ); + + auth_api_mount.mount("/lastfm/", lastfm_router); } let mut auth_api_chain = Chain::new(auth_api_mount); @@ -715,7 +736,7 @@ fn delete_playlist(request: &mut Request, db: &DB) -> IronResult { Ok(Response::with(status::Ok)) } -fn lastfm_auth(request: &mut Request, db: &DB) -> IronResult { +fn lastfm_link(request: &mut Request, db: &DB) -> IronResult { let input = request.get_ref::().unwrap(); let username = match input.find(&["username"]) { Some(¶ms::Value::String(ref username)) => username.clone(), @@ -726,7 +747,7 @@ fn lastfm_auth(request: &mut Request, db: &DB) -> IronResult { _ => return Err(Error::from(ErrorKind::MissingPassword).into()), }; - lastfm::auth(db, &username, &token)?; + lastfm::link(db, &username, &token)?; let url_encoded_content = match input.find(&["content"]) { Some(¶ms::Value::String(ref content)) => content.clone(), @@ -748,6 +769,15 @@ fn lastfm_auth(request: &mut Request, db: &DB) -> IronResult { Ok(Response::with((mime, status::Ok, popup_content))) } +fn lastfm_unlink(request: &mut Request, db: &DB) -> IronResult { + let username = match request.extensions.get::() { + Some(s) => s.username.clone(), + None => return Err(Error::from(ErrorKind::AuthenticationRequired).into()), + }; + lastfm::unlink(db, &username)?; + Ok(Response::with(status::Ok)) +} + fn lastfm_now_playing(request: &mut Request, db: &DB) -> IronResult { let username = match request.extensions.get::() { Some(s) => s.username.clone(), diff --git a/src/config.rs b/src/config.rs index ac22c12..8e6da98 100644 --- a/src/config.rs +++ b/src/config.rs @@ -26,7 +26,9 @@ pub struct MiscSettings { } #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -pub struct Preferences {} +pub struct Preferences { + pub lastfm_username: Option, +} #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct ConfigUser { @@ -252,11 +254,19 @@ where Ok(()) } -pub fn read_preferences(_: &T, _: &str) -> Result +pub fn read_preferences(db: &T, username: &str) -> Result where T: ConnectionSource, { - Ok(Preferences {}) + use self::users::dsl::*; + let connection = db.get_connection(); + let read_lastfm_username = users + .select(lastfm_username) + .filter(name.eq(username)) + .get_result(connection.deref())?; + Ok(Preferences { + lastfm_username: read_lastfm_username, + }) } pub fn write_preferences(_: &T, _: &str, _: &Preferences) -> Result<()> diff --git a/src/db/schema.rs b/src/db/schema.rs index fbc9e6c..7ea047a 100644 --- a/src/db/schema.rs +++ b/src/db/schema.rs @@ -1,99 +1,99 @@ table! { - ddns_config (id) { - id -> Integer, - host -> Text, - username -> Text, - password -> Text, - } + ddns_config (id) { + id -> Integer, + host -> Text, + username -> Text, + password -> Text, + } } table! { - directories (id) { - id -> Integer, - path -> Text, - parent -> Nullable, - artist -> Nullable, - year -> Nullable, - album -> Nullable, - artwork -> Nullable, - date_added -> Integer, - } + directories (id) { + id -> Integer, + path -> Text, + parent -> Nullable, + artist -> Nullable, + year -> Nullable, + album -> Nullable, + artwork -> Nullable, + date_added -> Integer, + } } table! { - misc_settings (id) { - id -> Integer, - auth_secret -> Text, - index_sleep_duration_seconds -> Integer, - index_album_art_pattern -> Text, - prefix_url -> Text, - } + misc_settings (id) { + id -> Integer, + auth_secret -> Text, + index_sleep_duration_seconds -> Integer, + index_album_art_pattern -> Text, + prefix_url -> Text, + } } table! { - mount_points (id) { - id -> Integer, - source -> Text, - name -> Text, - } + mount_points (id) { + id -> Integer, + source -> Text, + name -> Text, + } } table! { - playlist_songs (id) { - id -> Integer, - playlist -> Integer, - path -> Text, - ordering -> Integer, - } + playlist_songs (id) { + id -> Integer, + playlist -> Integer, + path -> Text, + ordering -> Integer, + } } table! { - playlists (id) { - id -> Integer, - owner -> Integer, - name -> Text, - } + playlists (id) { + id -> Integer, + owner -> Integer, + name -> Text, + } } table! { - songs (id) { - id -> Integer, - path -> Text, - parent -> Text, - track_number -> Nullable, - disc_number -> Nullable, - title -> Nullable, - artist -> Nullable, - album_artist -> Nullable, - year -> Nullable, - album -> Nullable, - artwork -> Nullable, - duration -> Nullable, - } + songs (id) { + id -> Integer, + path -> Text, + parent -> Text, + track_number -> Nullable, + disc_number -> Nullable, + title -> Nullable, + artist -> Nullable, + album_artist -> Nullable, + year -> Nullable, + album -> Nullable, + artwork -> Nullable, + duration -> Nullable, + } } table! { - users (id) { - id -> Integer, - name -> Text, - password_salt -> Binary, - password_hash -> Binary, - admin -> Integer, - lastfm_username -> Nullable, - lastfm_session_key -> Nullable, - } + users (id) { + id -> Integer, + name -> Text, + password_salt -> Binary, + password_hash -> Binary, + admin -> Integer, + lastfm_username -> Nullable, + lastfm_session_key -> Nullable, + } } joinable!(playlist_songs -> playlists (playlist)); joinable!(playlists -> users (owner)); allow_tables_to_appear_in_same_query!( - ddns_config, - directories, - misc_settings, - mount_points, - playlist_songs, - playlists, - songs, - users, + ddns_config, + directories, + misc_settings, + mount_points, + playlist_songs, + playlists, + songs, + users, ); diff --git a/src/ddns.rs b/src/ddns.rs index ea2b11e..1ab6d6e 100644 --- a/src/ddns.rs +++ b/src/ddns.rs @@ -71,7 +71,10 @@ where let full_url = format!("{}?host={}", DDNS_UPDATE_URL, &config.host); let client = reqwest::ClientBuilder::new().build()?; - let res = client.get(full_url.as_str()).basic_auth(config.username, Some(config.password)).send()?; + let res = client + .get(full_url.as_str()) + .basic_auth(config.username, Some(config.password)) + .send()?; if !res.status().is_success() { return Err(DDNSError::Update(res.status())); } diff --git a/src/index.rs b/src/index.rs index 1b20fd6..90b7823 100644 --- a/src/index.rs +++ b/src/index.rs @@ -2,8 +2,8 @@ use core::ops::Deref; use diesel; use diesel::dsl::sql; use diesel::prelude::*; -use diesel::sqlite::SqliteConnection; use diesel::sql_types; +use diesel::sqlite::SqliteConnection; use regex::Regex; use std::fs; use std::path::Path; diff --git a/src/lastfm.rs b/src/lastfm.rs index 09efcaa..c865b4e 100644 --- a/src/lastfm.rs +++ b/src/lastfm.rs @@ -59,7 +59,7 @@ where )) } -pub fn auth(db: &T, username: &str, token: &str) -> Result<(), errors::Error> +pub fn link(db: &T, username: &str, token: &str) -> Result<(), errors::Error> where T: ConnectionSource + VFSSource, { @@ -82,7 +82,19 @@ where Err(_) => bail!(errors::ErrorKind::LastFMDeserializationError), }; - user::set_lastfm_session_key(db, username, &auth_response.session.key.body) + user::lastfm_link( + db, + username, + &auth_response.session.name.body, + &auth_response.session.key.body, + ) +} + +pub fn unlink(db: &T, username: &str) -> Result<(), errors::Error> +where + T: ConnectionSource + VFSSource, +{ + user::lastfm_unlink(db, username) } pub fn scrobble(db: &T, username: &str, track: &Path) -> Result<(), errors::Error> diff --git a/src/thumbnails.rs b/src/thumbnails.rs index 901cd77..68082f4 100644 --- a/src/thumbnails.rs +++ b/src/thumbnails.rs @@ -5,7 +5,7 @@ use image::GenericImageView; use image::ImageBuffer; use std::cmp; use std::collections::hash_map::DefaultHasher; -use std::fs::{DirBuilder}; +use std::fs::DirBuilder; use std::hash::{Hash, Hasher}; use std::path::*; diff --git a/src/user.rs b/src/user.rs index ef83f2a..96f19ee 100644 --- a/src/user.rs +++ b/src/user.rs @@ -101,15 +101,17 @@ where Ok(is_admin != 0) } -pub fn set_lastfm_session_key(db: &T, username: &str, token: &str) -> Result<()> +pub fn lastfm_link(db: &T, username: &str, lastfm_login: &str, session_key: &str) -> Result<()> where T: ConnectionSource, { use db::users::dsl::*; let connection = db.get_connection(); diesel::update(users.filter(name.eq(username))) - .set(lastfm_session_key.eq(token)) - .execute(connection.deref())?; + .set(( + lastfm_username.eq(lastfm_login), + lastfm_session_key.eq(session_key), + )).execute(connection.deref())?; Ok(()) } @@ -128,3 +130,15 @@ where _ => bail!(ErrorKind::MissingLastFMCredentials), } } + +pub fn lastfm_unlink(db: &T, username: &str) -> Result<()> +where + T: ConnectionSource, +{ + use db::users::dsl::*; + let connection = db.get_connection(); + diesel::update(users.filter(name.eq(username))) + .set((lastfm_session_key.eq(""), lastfm_username.eq(""))) + .execute(connection.deref())?; + Ok(()) +}