get and patch settngs

This commit is contained in:
jb-alvarado 2022-06-12 22:37:29 +02:00
parent ca5ac810be
commit c4d599ff31
4 changed files with 76 additions and 19 deletions

View File

@ -1,11 +1,12 @@
use std::path::Path; use std::path::Path;
use actix_web::web;
use faccess::PathExt; use faccess::PathExt;
use rand::{distributions::Alphanumeric, Rng}; use rand::{distributions::Alphanumeric, Rng};
use simplelog::*; use simplelog::*;
use sqlx::{migrate::MigrateDatabase, sqlite::SqliteQueryResult, Pool, Sqlite, SqlitePool}; 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; use crate::api::utils::GlobalSettings;
#[derive(Debug, sqlx::FromRow)] #[derive(Debug, sqlx::FromRow)]
@ -46,7 +47,7 @@ async fn cretea_schema() -> Result<SqliteQueryResult, sqlx::Error> {
id INTEGER PRIMARY KEY AUTOINCREMENT, id INTEGER PRIMARY KEY AUTOINCREMENT,
channel_name TEXT NOT NULL, channel_name TEXT NOT NULL,
preview_url TEXT NOT NULL, preview_url TEXT NOT NULL,
settings_path TEXT NOT NULL, config_path TEXT NOT NULL,
extra_extensions TEXT NOT NULL, extra_extensions TEXT NOT NULL,
UNIQUE(channel_name) UNIQUE(channel_name)
); );
@ -93,7 +94,7 @@ pub async fn db_init() -> Result<&'static str, Box<dyn std::error::Error>> {
END; END;
INSERT INTO global(secret) VALUES($1); INSERT INTO global(secret) VALUES($1);
INSERT INTO roles(name) VALUES('admin'), ('user'), ('guest'); 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', VALUES('Channel 1', 'http://localhost/live/preview.m3u8',
'/etc/ffplayout/ffplayout.yml', '.jpg,.jpeg,.png');"; '/etc/ffplayout/ffplayout.yml', '.jpg,.jpeg,.png');";
sqlx::query(query).bind(secret).execute(&instances).await?; sqlx::query(query).bind(secret).execute(&instances).await?;
@ -118,6 +119,36 @@ pub async fn db_global() -> Result<GlobalSettings, sqlx::Error> {
Ok(result) Ok(result)
} }
pub async fn db_get_settings(id: &i64) -> Result<Settings, sqlx::Error> {
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<Settings>,
) -> Result<SqliteQueryResult, sqlx::Error> {
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<String, sqlx::Error> { pub async fn db_role(id: &i64) -> Result<String, sqlx::Error> {
let conn = db_connection().await?; let conn = db_connection().await?;
let query = "SELECT name FROM roles WHERE id = $1"; let query = "SELECT name FROM roles WHERE id = $1";

View File

@ -39,12 +39,13 @@ impl LoginUser {
#[derive(Debug, Deserialize, Serialize, sqlx::FromRow)] #[derive(Debug, Deserialize, Serialize, sqlx::FromRow)]
pub struct Settings { pub struct Settings {
#[serde(skip_deserializing)]
pub id: i64, pub id: i64,
pub channel_name: String, pub channel_name: String,
pub preview_url: String, pub preview_url: String,
pub settings_path: String, pub config_path: String,
pub extra_extensions: String, pub extra_extensions: String,
#[sqlx(default)] #[sqlx(default)]
#[serde(skip_serializing)] #[serde(skip_serializing, skip_deserializing)]
pub secret: String, pub secret: String,
} }

View File

@ -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 actix_web_grants::proc_macro::has_permissions;
use argon2::{ use argon2::{
password_hash::{rand_core::OsRng, PasswordHash, SaltString}, password_hash::{rand_core::OsRng, PasswordHash, SaltString},
@ -10,8 +10,8 @@ use simplelog::*;
use crate::api::{ use crate::api::{
auth::{create_jwt, Claims}, auth::{create_jwt, Claims},
errors::ServiceError, errors::ServiceError,
handles::{db_login, db_role, db_update_user}, handles::{db_get_settings, db_login, db_role, db_update_settings, db_update_user},
models::{LoginUser, User}, models::{LoginUser, Settings, User},
}; };
#[derive(Serialize)] #[derive(Serialize)]
@ -21,24 +21,48 @@ struct ResponseObj<T> {
data: Option<T>, data: Option<T>,
} }
/// curl -X GET http://127.0.0.1:8080/api/settings -H "Authorization: Bearer <TOKEN>" /// curl -X GET http://127.0.0.1:8080/api/settings/1 -H "Authorization: Bearer <TOKEN>"
#[get("/settings")] #[get("/settings/{id}")]
#[has_permissions("admin", "user")]
async fn get_settings(id: web::Path<i64>) -> Result<impl Responder, ServiceError> {
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 <TOKEN>"
#[patch("/settings/{id}")]
#[has_permissions("admin")] #[has_permissions("admin")]
async fn settings(user: web::ReqData<LoginUser>) -> Result<impl Responder, ServiceError> { async fn patch_settings(
println!("{:?}", user); id: web::Path<i64>,
Ok("Hello from settings!") data: web::Json<Settings>,
) -> Result<impl Responder, ServiceError> {
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' \ /// curl -X PUT http://localhost:8080/api/user/1 --header 'Content-Type: application/json' \
/// --data '{"email": "<EMAIL>", "password": "<PASS>"}' --header 'Authorization: <TOKEN>' /// --data '{"email": "<EMAIL>", "password": "<PASS>"}' --header 'Authorization: <TOKEN>'
#[put("/user/{user_id}")] #[put("/user/{id}")]
#[has_permissions("admin")] #[has_permissions("admin", "user")]
async fn update_user( async fn update_user(
user_id: web::Path<i64>, id: web::Path<i64>,
user: web::ReqData<LoginUser>, user: web::ReqData<LoginUser>,
data: web::Json<User>, data: web::Json<User>,
) -> Result<impl Responder, ServiceError> { ) -> Result<impl Responder, ServiceError> {
if user_id.into_inner() == user.id { if id.into_inner() == user.id {
let mut fields = String::new(); let mut fields = String::new();
if let Some(email) = data.email.clone() { if let Some(email) = data.email.clone() {

View File

@ -13,7 +13,7 @@ use ffplayout_engine::{
args_parse::Args, args_parse::Args,
auth, auth,
models::LoginUser, models::LoginUser,
routes::{login, settings, update_user}, routes::{get_settings, login, patch_settings, update_user},
utils::{init_config, run_args}, utils::{init_config, run_args},
}, },
utils::{init_logging, GlobalConfig}, utils::{init_logging, GlobalConfig},
@ -62,7 +62,8 @@ async fn main() -> std::io::Result<()> {
.service( .service(
web::scope("/api") web::scope("/api")
.wrap(auth) .wrap(auth)
.service(settings) .service(get_settings)
.service(patch_settings)
.service(update_user), .service(update_user),
) )
}) })