switch to role based auth
This commit is contained in:
parent
019a163176
commit
b15eb449dc
@ -13,16 +13,16 @@ const JWT_EXPIRATION_MINUTES: i64 = 60;
|
|||||||
pub struct Claims {
|
pub struct Claims {
|
||||||
pub id: i64,
|
pub id: i64,
|
||||||
pub username: String,
|
pub username: String,
|
||||||
pub permissions: Vec<String>,
|
pub role: String,
|
||||||
exp: i64,
|
exp: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Claims {
|
impl Claims {
|
||||||
pub fn new(id: i64, username: String, permissions: Vec<String>) -> Self {
|
pub fn new(id: i64, username: String, role: String) -> Self {
|
||||||
Self {
|
Self {
|
||||||
id,
|
id,
|
||||||
username,
|
username,
|
||||||
permissions,
|
role,
|
||||||
exp: (Utc::now() + Duration::minutes(JWT_EXPIRATION_MINUTES)).timestamp(),
|
exp: (Utc::now() + Duration::minutes(JWT_EXPIRATION_MINUTES)).timestamp(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -128,8 +128,6 @@ pub async fn db_get_settings(id: &i64) -> Result<Settings, sqlx::Error> {
|
|||||||
let result: Settings = sqlx::query_as(query).bind(id).fetch_one(&conn).await?;
|
let result: Settings = sqlx::query_as(query).bind(id).fetch_one(&conn).await?;
|
||||||
conn.close().await;
|
conn.close().await;
|
||||||
|
|
||||||
println!("{:#?}", result);
|
|
||||||
|
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use actix_web::{get, http::StatusCode, patch, 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_any_role;
|
||||||
use argon2::{
|
use argon2::{
|
||||||
password_hash::{rand_core::OsRng, PasswordHash, SaltString},
|
password_hash::{rand_core::OsRng, PasswordHash, SaltString},
|
||||||
Argon2, PasswordHasher, PasswordVerifier,
|
Argon2, PasswordHasher, PasswordVerifier,
|
||||||
@ -14,6 +14,7 @@ use crate::api::{
|
|||||||
db_add_user, db_get_settings, db_login, db_role, db_update_settings, db_update_user,
|
db_add_user, db_get_settings, db_login, db_role, db_update_settings, db_update_user,
|
||||||
},
|
},
|
||||||
models::{LoginUser, Settings, User},
|
models::{LoginUser, Settings, User},
|
||||||
|
utils::Role,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
@ -25,7 +26,7 @@ struct ResponseObj<T> {
|
|||||||
|
|
||||||
/// curl -X GET http://127.0.0.1:8080/api/settings/1 -H "Authorization: Bearer <TOKEN>"
|
/// curl -X GET http://127.0.0.1:8080/api/settings/1 -H "Authorization: Bearer <TOKEN>"
|
||||||
#[get("/settings/{id}")]
|
#[get("/settings/{id}")]
|
||||||
#[has_permissions("admin", "user")]
|
#[has_any_role("Role::Admin", "Role::User", type = "Role")]
|
||||||
async fn get_settings(id: web::Path<i64>) -> Result<impl Responder, ServiceError> {
|
async fn get_settings(id: web::Path<i64>) -> Result<impl Responder, ServiceError> {
|
||||||
if let Ok(settings) = db_get_settings(&id).await {
|
if let Ok(settings) = db_get_settings(&id).await {
|
||||||
return Ok(web::Json(ResponseObj {
|
return Ok(web::Json(ResponseObj {
|
||||||
@ -43,7 +44,7 @@ async fn get_settings(id: web::Path<i64>) -> Result<impl Responder, ServiceError
|
|||||||
/// "config_path":"/etc/ffplayout/ffplayout.yml","extra_extensions":".jpg,.jpeg,.png"}' \
|
/// "config_path":"/etc/ffplayout/ffplayout.yml","extra_extensions":".jpg,.jpeg,.png"}' \
|
||||||
/// -H "Authorization: Bearer <TOKEN>"
|
/// -H "Authorization: Bearer <TOKEN>"
|
||||||
#[patch("/settings/{id}")]
|
#[patch("/settings/{id}")]
|
||||||
#[has_permissions("admin")]
|
#[has_any_role("Role::Admin", type = "Role")]
|
||||||
async fn patch_settings(
|
async fn patch_settings(
|
||||||
id: web::Path<i64>,
|
id: web::Path<i64>,
|
||||||
data: web::Json<Settings>,
|
data: web::Json<Settings>,
|
||||||
@ -55,10 +56,22 @@ async fn patch_settings(
|
|||||||
Err(ServiceError::InternalServerError)
|
Err(ServiceError::InternalServerError)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[get("/playout/config/{id}")]
|
||||||
|
#[has_any_role("Role::Admin", "Role::User", type = "Role")]
|
||||||
|
async fn get_playout_config(id: web::Path<i64>) -> Result<impl Responder, ServiceError> {
|
||||||
|
if let Ok(settings) = db_get_settings(&id).await {
|
||||||
|
println!("{:?}", settings.config_path);
|
||||||
|
|
||||||
|
return Ok("settings");
|
||||||
|
};
|
||||||
|
|
||||||
|
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/{id}")]
|
#[put("/user/{id}")]
|
||||||
#[has_permissions("admin", "user")]
|
#[has_any_role("Role::Admin", "Role::User", type = "Role")]
|
||||||
async fn update_user(
|
async fn update_user(
|
||||||
id: web::Path<i64>,
|
id: web::Path<i64>,
|
||||||
user: web::ReqData<LoginUser>,
|
user: web::ReqData<LoginUser>,
|
||||||
@ -98,7 +111,7 @@ async fn update_user(
|
|||||||
/// -d '{"email": "<EMAIL>", "username": "<USER>", "password": "<PASS>", "role_id": 1}' \
|
/// -d '{"email": "<EMAIL>", "username": "<USER>", "password": "<PASS>", "role_id": 1}' \
|
||||||
/// --header 'Authorization: Bearer <TOKEN>'
|
/// --header 'Authorization: Bearer <TOKEN>'
|
||||||
#[post("/user/")]
|
#[post("/user/")]
|
||||||
#[has_permissions("admin")]
|
#[has_any_role("Role::Admin", type = "Role")]
|
||||||
async fn add_user(data: web::Json<User>) -> Result<impl Responder, ServiceError> {
|
async fn add_user(data: web::Json<User>) -> Result<impl Responder, ServiceError> {
|
||||||
match db_add_user(data.into_inner()).await {
|
match db_add_user(data.into_inner()).await {
|
||||||
Ok(_) => Ok("Add User Success"),
|
Ok(_) => Ok("Add User Success"),
|
||||||
@ -127,7 +140,7 @@ pub async fn login(credentials: web::Json<User>) -> impl Responder {
|
|||||||
let role = db_role(&user.role_id.unwrap_or_default())
|
let role = db_role(&user.role_id.unwrap_or_default())
|
||||||
.await
|
.await
|
||||||
.unwrap_or_else(|_| "guest".to_string());
|
.unwrap_or_else(|_| "guest".to_string());
|
||||||
let claims = Claims::new(user.id, user.username.clone(), vec![role.clone()]);
|
let claims = Claims::new(user.id, user.username.clone(), role.clone());
|
||||||
|
|
||||||
if let Ok(token) = create_jwt(claims) {
|
if let Ok(token) = create_jwt(claims) {
|
||||||
user.token = Some(token);
|
user.token = Some(token);
|
||||||
|
@ -7,6 +7,23 @@ use crate::api::{
|
|||||||
models::User,
|
models::User,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[derive(PartialEq, Clone)]
|
||||||
|
pub enum Role {
|
||||||
|
Admin,
|
||||||
|
User,
|
||||||
|
Guest,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Role {
|
||||||
|
pub fn set_role(role: &str) -> Self {
|
||||||
|
match role {
|
||||||
|
"admin" => Role::Admin,
|
||||||
|
"user" => Role::User,
|
||||||
|
_ => Role::Guest,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, sqlx::FromRow)]
|
#[derive(Debug, sqlx::FromRow)]
|
||||||
pub struct GlobalSettings {
|
pub struct GlobalSettings {
|
||||||
pub secret: String,
|
pub secret: String,
|
||||||
|
@ -13,8 +13,8 @@ use ffplayout_engine::{
|
|||||||
args_parse::Args,
|
args_parse::Args,
|
||||||
auth,
|
auth,
|
||||||
models::LoginUser,
|
models::LoginUser,
|
||||||
routes::{add_user, get_settings, login, patch_settings, update_user},
|
routes::{add_user, get_playout_config, get_settings, login, patch_settings, update_user},
|
||||||
utils::{init_config, run_args},
|
utils::{init_config, run_args, Role},
|
||||||
},
|
},
|
||||||
utils::{init_logging, GlobalConfig},
|
utils::{init_logging, GlobalConfig},
|
||||||
};
|
};
|
||||||
@ -22,10 +22,12 @@ use ffplayout_engine::{
|
|||||||
async fn validator(req: ServiceRequest, credentials: BearerAuth) -> Result<ServiceRequest, Error> {
|
async fn validator(req: ServiceRequest, credentials: BearerAuth) -> Result<ServiceRequest, Error> {
|
||||||
// We just get permissions from JWT
|
// We just get permissions from JWT
|
||||||
let claims = auth::decode_jwt(credentials.token()).await?;
|
let claims = auth::decode_jwt(credentials.token()).await?;
|
||||||
req.attach(claims.permissions);
|
req.attach(vec![Role::set_role(&claims.role)]);
|
||||||
|
|
||||||
req.extensions_mut()
|
req.extensions_mut()
|
||||||
.insert(LoginUser::new(claims.id, claims.username));
|
.insert(LoginUser::new(claims.id, claims.username));
|
||||||
|
|
||||||
|
println!("{:#?}", req);
|
||||||
Ok(req)
|
Ok(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,6 +65,7 @@ async fn main() -> std::io::Result<()> {
|
|||||||
web::scope("/api")
|
web::scope("/api")
|
||||||
.wrap(auth)
|
.wrap(auth)
|
||||||
.service(add_user)
|
.service(add_user)
|
||||||
|
.service(get_playout_config)
|
||||||
.service(get_settings)
|
.service(get_settings)
|
||||||
.service(patch_settings)
|
.service(patch_settings)
|
||||||
.service(update_user),
|
.service(update_user),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user