diff --git a/README.md b/README.md index 70991dfee..f979a10e9 100644 --- a/README.md +++ b/README.md @@ -156,7 +156,7 @@ Has the following top level entries: * `enabled` _optional_ default is `true`, if you disable the processing is skipped * `name` _optional_ default is `default`, if not default it has to be unique, for running selective targets * `sort` _optional_ -* `output` _optional_ list of output formats +* `output` _mandatory_ list of output formats * `processing_order` _optional_ default is `frm` * `options` _optional_ * `filter` _mandatory_, diff --git a/frontend/src/component/user-view/user-view.tsx b/frontend/src/component/user-view/user-view.tsx index 1eb600088..75dc0b5ef 100644 --- a/frontend/src/component/user-view/user-view.tsx +++ b/frontend/src/component/user-view/user-view.tsx @@ -99,7 +99,14 @@ export default function UserView(props: UserViewProps) { usernames[user.username] = true; } } - const targetUser = targets.map(t => ({target: t.target, credentials: t.credentials})); + const targetUser = targets.map(t => { + t.credentials.forEach(c => { + c.username = c.username.trim(); + c.password = c.password.trim(); + c.token = c.token.trim(); + }) + return {target: t.target, credentials: t.credentials} + }); services.config().saveTargetUser(targetUser).subscribe({ next: () => enqueueSnackbar("User saved!", {variant: 'success'}), error: (err) => enqueueSnackbar("Failed to save user!", {variant: 'error'}) diff --git a/src/api/api_model.rs b/src/api/api_model.rs index ef1e11d93..293418a3a 100644 --- a/src/api/api_model.rs +++ b/src/api/api_model.rs @@ -46,7 +46,7 @@ pub(crate) struct XtreamAuthorizationResponse { } -#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Debug, serde::Serialize, serde::Deserialize)] pub(crate) struct UserApiRequest { #[serde(default = "default_as_empty_str")] pub username: String, diff --git a/src/api/api_utils.rs b/src/api/api_utils.rs index 133950900..e02578b0d 100644 --- a/src/api/api_utils.rs +++ b/src/api/api_utils.rs @@ -20,12 +20,12 @@ pub(crate) async fn serve_file(file_path: &PathBuf, req: &HttpRequest) -> HttpRe } pub(crate) fn get_user_target<'a>(api_req: &'a web::Query, app_state: &'a web::Data) -> Option<(&'a UserCredentials, &'a ConfigTarget)> { - let username = api_req.username.as_str(); - let password = api_req.password.as_str(); + let username = api_req.username.as_str().trim(); + let password = api_req.password.as_str().trim(); if !username.is_empty() && !password.is_empty() { app_state.config.get_target_for_user(username, password) } else { - let token = api_req.token.as_str(); + let token = api_req.token.as_str().trim(); if !token.is_empty() { app_state.config.get_target_for_user_by_token(token) } else { diff --git a/src/api/v1_api.rs b/src/api/v1_api.rs index ee479ef37..1d80f200c 100644 --- a/src/api/v1_api.rs +++ b/src/api/v1_api.rs @@ -30,6 +30,7 @@ pub(crate) async fn config_user( ) -> HttpResponse { // TODO implement info!("{:?}", req.0); + // dont forget to trim() HttpResponse::Ok().finish() } diff --git a/src/api/xtream_player_api.rs b/src/api/xtream_player_api.rs index 4776c832a..f419b7574 100644 --- a/src/api/xtream_player_api.rs +++ b/src/api/xtream_player_api.rs @@ -2,6 +2,7 @@ use actix_web::{get, HttpRequest, HttpResponse, web}; use chrono::{Duration, Local}; +use log::debug; use crate::api::api_utils::{get_user_target, serve_file}; use crate::api::api_model::{AppState, UserApiRequest, XtreamAuthorizationResponse, XtreamServerInfo, XtreamUserInfo}; @@ -47,35 +48,43 @@ pub(crate) async fn xtream_player_api( req: HttpRequest, _app_state: web::Data, ) -> HttpResponse { + debug!("Incoming request {:?}", &api_req.0); match get_user_target(&api_req, &_app_state) { Some((user, target)) => { + let action = api_req.action.trim(); let target_name = &target.name; if target.has_output(&TargetType::Xtream) { - if api_req.action.is_empty() { + if action.is_empty() { return HttpResponse::Ok().json(get_user_info(user, &_app_state.config)); } - match match api_req.action.as_str() { + match match action { "get_live_categories" => xtream_get_all(&_app_state.config, target_name, COL_CAT_LIVE), "get_vod_categories" => xtream_get_all(&_app_state.config, target_name, COL_CAT_VOD), "get_series_categories" => xtream_get_all(&_app_state.config, target_name, COL_CAT_SERIES), "get_live_streams" => xtream_get_all(&_app_state.config, target_name, COL_LIVE), "get_vod_streams" => xtream_get_all(&_app_state.config, target_name, COL_VOD), "get_series" => xtream_get_all(&_app_state.config, target_name, COL_SERIES), - _ => Err(std::io::Error::new(std::io::ErrorKind::Unsupported, format!("Cant find action: {}/{}", target_name, &api_req.action))), + _ => Err(std::io::Error::new(std::io::ErrorKind::Unsupported, format!("Cant find action: {}/{}", target_name, action))), } { Ok(file_path) => { serve_file(&file_path, &req).await } - Err(_) => HttpResponse::BadRequest().finish() + Err(err) => { + debug!("Could not open file for xtream target: {} {}", target_name, err); + HttpResponse::BadRequest().finish() + } } } else { + debug!("Target has not output xtream {}", target_name); HttpResponse::BadRequest().finish() } } _ => { if api_req.action.is_empty() { + debug!("Paremeter action is empty!"); HttpResponse::Unauthorized().finish() } else { + debug!("cant find user!"); HttpResponse::BadRequest().finish() } } diff --git a/src/model/config.rs b/src/model/config.rs index 341a325b9..19621f467 100644 --- a/src/model/config.rs +++ b/src/model/config.rs @@ -173,7 +173,7 @@ pub(crate) struct ConfigTarget { #[serde(skip_serializing_if = "Option::is_none")] pub sort: Option, pub filter: String, - #[serde(alias = "type")] + #[serde(alias = "type", default="default_as_empty_list")] pub output: Vec, #[serde(skip_serializing_if = "Option::is_none")] pub rename: Option>,