diff --git a/src/api/handles.rs b/src/api/handles.rs index db54cc9f..89f14da3 100644 --- a/src/api/handles.rs +++ b/src/api/handles.rs @@ -1,11 +1,12 @@ use std::path::Path; +use actix_web::web; use faccess::PathExt; use rand::{distributions::Alphanumeric, Rng}; use simplelog::*; use sqlx::{migrate::MigrateDatabase, sqlite::SqliteQueryResult, Pool, Sqlite, SqlitePool}; -use crate::api::models::User; +use crate::api::models::{Settings, User}; use crate::api::utils::GlobalSettings; #[derive(Debug, sqlx::FromRow)] @@ -46,7 +47,7 @@ async fn cretea_schema() -> Result { id INTEGER PRIMARY KEY AUTOINCREMENT, channel_name TEXT NOT NULL, preview_url TEXT NOT NULL, - settings_path TEXT NOT NULL, + config_path TEXT NOT NULL, extra_extensions TEXT NOT NULL, UNIQUE(channel_name) ); @@ -93,7 +94,7 @@ pub async fn db_init() -> Result<&'static str, Box> { END; INSERT INTO global(secret) VALUES($1); INSERT INTO roles(name) VALUES('admin'), ('user'), ('guest'); - INSERT INTO settings(channel_name, preview_url, settings_path, extra_extensions) + INSERT INTO settings(channel_name, preview_url, config_path, extra_extensions) VALUES('Channel 1', 'http://localhost/live/preview.m3u8', '/etc/ffplayout/ffplayout.yml', '.jpg,.jpeg,.png');"; sqlx::query(query).bind(secret).execute(&instances).await?; @@ -118,6 +119,36 @@ pub async fn db_global() -> Result { Ok(result) } +pub async fn db_get_settings(id: &i64) -> Result { + let conn = db_connection().await?; + let query = "SELECT * FROM settings WHERE id = $1"; + let result: Settings = sqlx::query_as(query).bind(id).fetch_one(&conn).await?; + conn.close().await; + + println!("{:#?}", result); + + Ok(result) +} + +pub async fn db_update_settings( + id: i64, + s: web::Json, +) -> Result { + let conn = db_connection().await?; + let query = "UPDATE settings SET channel_name = $2, preview_url = $3, config_path = $4, extra_extensions = $5 WHERE id = $1"; + let result: SqliteQueryResult = sqlx::query(query) + .bind(id) + .bind(s.channel_name.clone()) + .bind(s.preview_url.clone()) + .bind(s.config_path.clone()) + .bind(s.extra_extensions.clone()) + .execute(&conn) + .await?; + conn.close().await; + + Ok(result) +} + pub async fn db_role(id: &i64) -> Result { let conn = db_connection().await?; let query = "SELECT name FROM roles WHERE id = $1"; diff --git a/src/api/models.rs b/src/api/models.rs index 8b781f61..b656d693 100644 --- a/src/api/models.rs +++ b/src/api/models.rs @@ -39,12 +39,13 @@ impl LoginUser { #[derive(Debug, Deserialize, Serialize, sqlx::FromRow)] pub struct Settings { + #[serde(skip_deserializing)] pub id: i64, pub channel_name: String, pub preview_url: String, - pub settings_path: String, + pub config_path: String, pub extra_extensions: String, #[sqlx(default)] - #[serde(skip_serializing)] + #[serde(skip_serializing, skip_deserializing)] pub secret: String, } diff --git a/src/api/routes.rs b/src/api/routes.rs index c0eef682..ed8d3992 100644 --- a/src/api/routes.rs +++ b/src/api/routes.rs @@ -1,4 +1,4 @@ -use actix_web::{get, http::StatusCode, post, put, web, Responder}; +use actix_web::{get, http::StatusCode, patch, post, put, web, Responder}; use actix_web_grants::proc_macro::has_permissions; use argon2::{ password_hash::{rand_core::OsRng, PasswordHash, SaltString}, @@ -10,8 +10,8 @@ use simplelog::*; use crate::api::{ auth::{create_jwt, Claims}, errors::ServiceError, - handles::{db_login, db_role, db_update_user}, - models::{LoginUser, User}, + handles::{db_get_settings, db_login, db_role, db_update_settings, db_update_user}, + models::{LoginUser, Settings, User}, }; #[derive(Serialize)] @@ -21,24 +21,48 @@ struct ResponseObj { data: Option, } -/// curl -X GET http://127.0.0.1:8080/api/settings -H "Authorization: Bearer " -#[get("/settings")] +/// curl -X GET http://127.0.0.1:8080/api/settings/1 -H "Authorization: Bearer " +#[get("/settings/{id}")] +#[has_permissions("admin", "user")] +async fn get_settings(id: web::Path) -> Result { + if let Ok(settings) = db_get_settings(&id).await { + return Ok(web::Json(ResponseObj { + message: format!("Settings from {}", settings.channel_name), + status: 200, + data: Some(settings), + })); + } + + Err(ServiceError::InternalServerError) +} + +/// curl -X PATCH http://127.0.0.1:8080/api/settings/1 -H "Content-Type: application/json" \ +/// --data '{"id":1,"channel_name":"Channel 1","preview_url":"http://localhost/live/stream.m3u8", \ +/// "config_path":"/etc/ffplayout/ffplayout.yml","extra_extensions":".jpg,.jpeg,.png"}' \ +/// -H "Authorization: Bearer " +#[patch("/settings/{id}")] #[has_permissions("admin")] -async fn settings(user: web::ReqData) -> Result { - println!("{:?}", user); - Ok("Hello from settings!") +async fn patch_settings( + id: web::Path, + data: web::Json, +) -> Result { + if db_update_settings(*id, data).await.is_ok() { + return Ok("Update Success"); + }; + + Err(ServiceError::InternalServerError) } /// curl -X PUT http://localhost:8080/api/user/1 --header 'Content-Type: application/json' \ /// --data '{"email": "", "password": ""}' --header 'Authorization: ' -#[put("/user/{user_id}")] -#[has_permissions("admin")] +#[put("/user/{id}")] +#[has_permissions("admin", "user")] async fn update_user( - user_id: web::Path, + id: web::Path, user: web::ReqData, data: web::Json, ) -> Result { - if user_id.into_inner() == user.id { + if id.into_inner() == user.id { let mut fields = String::new(); if let Some(email) = data.email.clone() { diff --git a/src/bin/ffpapi.rs b/src/bin/ffpapi.rs index cd289775..aca8e375 100644 --- a/src/bin/ffpapi.rs +++ b/src/bin/ffpapi.rs @@ -13,7 +13,7 @@ use ffplayout_engine::{ args_parse::Args, auth, models::LoginUser, - routes::{login, settings, update_user}, + routes::{get_settings, login, patch_settings, update_user}, utils::{init_config, run_args}, }, utils::{init_logging, GlobalConfig}, @@ -62,7 +62,8 @@ async fn main() -> std::io::Result<()> { .service( web::scope("/api") .wrap(auth) - .service(settings) + .service(get_settings) + .service(patch_settings) .service(update_user), ) })