Added API endpoint to unlink last.fm account
This commit is contained in:
parent
a84f13214d
commit
f905bc4f73
8 changed files with 172 additions and 103 deletions
74
src/api.rs
74
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<DB>, index: &Arc<Mutex<Sender<index::Command>>>) ->
|
|||
let mut api_chain = Chain::new(api_handler);
|
||||
|
||||
let auth_secret = get_auth_secret(db.deref())?;
|
||||
let session_manager =
|
||||
ChaCha20Poly1305SessionManager::<Session>::from_key(auth_secret);
|
||||
let session_manager = ChaCha20Poly1305SessionManager::<Session>::from_key(auth_secret);
|
||||
let session_config = SessionConfig::default();
|
||||
let session_middleware = SessionMiddleware::<
|
||||
Session,
|
||||
|
@ -221,22 +225,39 @@ fn get_endpoints(db: &Arc<DB>, index_channel: &Arc<Mutex<Sender<index::Command>>
|
|||
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<Response> {
|
|||
Ok(Response::with(status::Ok))
|
||||
}
|
||||
|
||||
fn lastfm_auth(request: &mut Request, db: &DB) -> IronResult<Response> {
|
||||
fn lastfm_link(request: &mut Request, db: &DB) -> IronResult<Response> {
|
||||
let input = request.get_ref::<params::Params>().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<Response> {
|
|||
_ => 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<Response> {
|
|||
Ok(Response::with((mime, status::Ok, popup_content)))
|
||||
}
|
||||
|
||||
fn lastfm_unlink(request: &mut Request, db: &DB) -> IronResult<Response> {
|
||||
let username = match request.extensions.get::<SessionKey>() {
|
||||
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<Response> {
|
||||
let username = match request.extensions.get::<SessionKey>() {
|
||||
Some(s) => s.username.clone(),
|
||||
|
|
|
@ -26,7 +26,9 @@ pub struct MiscSettings {
|
|||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Preferences {}
|
||||
pub struct Preferences {
|
||||
pub lastfm_username: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct ConfigUser {
|
||||
|
@ -252,11 +254,19 @@ where
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn read_preferences<T>(_: &T, _: &str) -> Result<Preferences>
|
||||
pub fn read_preferences<T>(db: &T, username: &str) -> Result<Preferences>
|
||||
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>(_: &T, _: &str, _: &Preferences) -> Result<()>
|
||||
|
|
140
src/db/schema.rs
140
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<Text>,
|
||||
artist -> Nullable<Text>,
|
||||
year -> Nullable<Integer>,
|
||||
album -> Nullable<Text>,
|
||||
artwork -> Nullable<Text>,
|
||||
date_added -> Integer,
|
||||
}
|
||||
directories (id) {
|
||||
id -> Integer,
|
||||
path -> Text,
|
||||
parent -> Nullable<Text>,
|
||||
artist -> Nullable<Text>,
|
||||
year -> Nullable<Integer>,
|
||||
album -> Nullable<Text>,
|
||||
artwork -> Nullable<Text>,
|
||||
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<Integer>,
|
||||
disc_number -> Nullable<Integer>,
|
||||
title -> Nullable<Text>,
|
||||
artist -> Nullable<Text>,
|
||||
album_artist -> Nullable<Text>,
|
||||
year -> Nullable<Integer>,
|
||||
album -> Nullable<Text>,
|
||||
artwork -> Nullable<Text>,
|
||||
duration -> Nullable<Integer>,
|
||||
}
|
||||
songs (id) {
|
||||
id -> Integer,
|
||||
path -> Text,
|
||||
parent -> Text,
|
||||
track_number -> Nullable<Integer>,
|
||||
disc_number -> Nullable<Integer>,
|
||||
title -> Nullable<Text>,
|
||||
artist -> Nullable<Text>,
|
||||
album_artist -> Nullable<Text>,
|
||||
year -> Nullable<Integer>,
|
||||
album -> Nullable<Text>,
|
||||
artwork -> Nullable<Text>,
|
||||
duration -> Nullable<Integer>,
|
||||
}
|
||||
}
|
||||
|
||||
table! {
|
||||
users (id) {
|
||||
id -> Integer,
|
||||
name -> Text,
|
||||
password_salt -> Binary,
|
||||
password_hash -> Binary,
|
||||
admin -> Integer,
|
||||
lastfm_username -> Nullable<Text>,
|
||||
lastfm_session_key -> Nullable<Text>,
|
||||
}
|
||||
users (id) {
|
||||
id -> Integer,
|
||||
name -> Text,
|
||||
password_salt -> Binary,
|
||||
password_hash -> Binary,
|
||||
admin -> Integer,
|
||||
lastfm_username -> Nullable<Text>,
|
||||
lastfm_session_key -> Nullable<Text>,
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
);
|
||||
|
|
|
@ -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()));
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -59,7 +59,7 @@ where
|
|||
))
|
||||
}
|
||||
|
||||
pub fn auth<T>(db: &T, username: &str, token: &str) -> Result<(), errors::Error>
|
||||
pub fn link<T>(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<T>(db: &T, username: &str) -> Result<(), errors::Error>
|
||||
where
|
||||
T: ConnectionSource + VFSSource,
|
||||
{
|
||||
user::lastfm_unlink(db, username)
|
||||
}
|
||||
|
||||
pub fn scrobble<T>(db: &T, username: &str, track: &Path) -> Result<(), errors::Error>
|
||||
|
|
|
@ -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::*;
|
||||
|
||||
|
|
20
src/user.rs
20
src/user.rs
|
@ -101,15 +101,17 @@ where
|
|||
Ok(is_admin != 0)
|
||||
}
|
||||
|
||||
pub fn set_lastfm_session_key<T>(db: &T, username: &str, token: &str) -> Result<()>
|
||||
pub fn lastfm_link<T>(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<T>(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(())
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue