basic add permissions

This commit is contained in:
beckerinj
2022-11-24 00:54:54 -08:00
parent 7a4cf8be2d
commit e5bd6493f5
11 changed files with 121 additions and 37 deletions
+1 -1
View File
@@ -26,7 +26,7 @@ pub fn router() -> Router {
async fn create(
Extension(db): DbExtension,
Extension(user): RequestUserExtension,
Extension(update_ws): update::WsSenderExtension,
Extension(update_ws): update::UpdateWsSenderExtension,
Json(mut build): Json<Build>,
) -> anyhow::Result<()> {
let build_server = db
+1 -1
View File
@@ -23,7 +23,7 @@ pub fn router() -> Router {
async fn create(
Extension(db): DbExtension,
Extension(user): RequestUserExtension,
Extension(update_ws): update::WsSenderExtension,
Extension(update_ws): update::UpdateWsSenderExtension,
Json(mut deployment): Json<Deployment>,
) -> anyhow::Result<()> {
deployment.permissions = [(user.id.clone(), PermissionLevel::Write)]
+3 -1
View File
@@ -15,6 +15,7 @@ use crate::{
mod build;
mod deployment;
mod permissions;
mod server;
type PeripheryExtension = Extension<Arc<PeripheryClient>>;
@@ -28,6 +29,7 @@ pub fn router() -> Router {
.nest("/build", build::router())
.nest("/deployment", deployment::router())
.nest("/server", server::router())
.nest("/permissions", permissions::router())
.layer(Extension(Arc::new(PeripheryClient::new())))
.layer(middleware::from_fn(auth_request))
}
@@ -48,7 +50,7 @@ async fn get_user(
async fn add_update(
mut update: Update,
db: &DbClient,
update_ws: &update::WsSender,
update_ws: &update::UpdateWsSender,
) -> anyhow::Result<()> {
let update_id = db
.updates
+73
View File
@@ -0,0 +1,73 @@
use anyhow::{anyhow, Context};
use axum::{routing::post, Extension, Json, Router};
use db::DbExtension;
use helpers::handle_anyhow_error;
use mungos::{doc, Deserialize, Update};
use types::{PermissionLevel, PermissionsTarget, Server};
use crate::{auth::RequestUserExtension, helpers::get_user_permissions};
#[derive(Deserialize)]
struct PermissionsUpdate {
user_id: String,
permission: PermissionLevel,
target_type: PermissionsTarget,
target_id: String,
}
pub fn router() -> Router {
Router::new().route(
"/add",
post(|db, user, update| async {
add_permissions(db, user, update)
.await
.map_err(handle_anyhow_error)
}),
)
}
async fn add_permissions(
Extension(db): DbExtension,
Extension(user): RequestUserExtension,
Json(update): Json<PermissionsUpdate>,
) -> anyhow::Result<()> {
match update.target_type {
PermissionsTarget::Server => {
let server = db
.servers
.find_one_by_id(&update.target_id)
.await
.context("failed at find server query")?
.ok_or(anyhow!(
"failed to find a server with id {}",
update.target_id
))?;
let permissions = get_user_permissions(&user.id, &server.permissions);
if user.is_admin || permissions == PermissionLevel::Write {
let target_user = db
.users
.find_one_by_id(&update.user_id)
.await
.context("failed at find target user query")?
.ok_or(anyhow!("failed to find a user with id {}", update.user_id))?;
if !target_user.enabled {
return Err(anyhow!("target user not enabled"));
}
db.servers
.update_one::<Server>(&update.target_id, Update::Set(doc! {
format!("permissions.{}", update.user_id): update.permission.to_string()
}))
.await?;
Ok(())
} else {
Err(anyhow!("user is not authorized for this action"))
}
}
PermissionsTarget::Deployment => {
todo!()
}
PermissionsTarget::Build => {
todo!()
}
}
}
+1 -1
View File
@@ -57,7 +57,7 @@ async fn list(
async fn create(
Extension(db): DbExtension,
Extension(user): RequestUserExtension,
Extension(update_ws): update::WsSenderExtension,
Extension(update_ws): update::UpdateWsSenderExtension,
Json(mut server): Json<Server>,
) -> anyhow::Result<()> {
server.permissions = [(user.id.clone(), PermissionLevel::Write)]
+1 -1
View File
@@ -25,5 +25,5 @@ fn print_startup_log(config: &CoreConfig) {
}
pub fn default_config_path() -> String {
"/config/config.json".to_string()
"/config/config.toml".to_string()
}
+6
View File
@@ -1,6 +1,12 @@
use types::{PermissionLevel, PermissionsMap};
#[macro_export]
macro_rules! response {
($x:expr) => {
Ok::<_, (axum::http::StatusCode, String)>($x)
};
}
pub fn get_user_permissions(user_id: &str, permissions: &PermissionsMap) -> PermissionLevel {
*permissions.get(user_id).unwrap_or(&PermissionLevel::None)
}
+1 -2
View File
@@ -21,9 +21,8 @@ async fn main() {
let app = Router::new()
.nest("/api", api::router())
.nest("/auth", auth::router(&config))
.nest("/ws", ws::router())
.nest("/ws", ws::router(reciever))
.layer(sender)
.layer(reciever)
.layer(DbClient::extension(config.mongo.clone()).await)
.layer(JwtClient::extension(&config));
+5 -5
View File
@@ -6,10 +6,10 @@ pub mod update;
pub use update::make_update_ws_sender_reciver;
pub fn router() -> Router {
Router::new().route("/update", get(update::ws_handler))
}
use self::update::UpdateWsRecieverExtension;
fn user_permissions(user_id: &str, permissions: &PermissionsMap) -> PermissionLevel {
*permissions.get(user_id).unwrap_or(&PermissionLevel::None)
pub fn router(reciever: UpdateWsRecieverExtension) -> Router {
Router::new()
.route("/update", get(update::ws_handler))
.layer(reciever)
}
+15 -20
View File
@@ -21,17 +21,18 @@ use tokio::{
},
};
use tokio_util::sync::CancellationToken;
use types::{PermissionLevel, Update, User, UpdateTarget};
use types::{PermissionLevel, Update, UpdateTarget, User};
use crate::auth::{JwtClient, JwtExtension};
use crate::{
auth::{JwtClient, JwtExtension},
helpers::get_user_permissions,
};
use super::user_permissions;
pub type UpdateWsSender = Arc<Mutex<Sender<Update>>>;
pub type UpdateWsSenderExtension = Extension<UpdateWsSender>;
pub type WsSender = Arc<Mutex<Sender<Update>>>;
pub type WsSenderExtension = Extension<WsSender>;
pub type WsReciever = Receiver<Update>;
pub type WsRecieverExtension = Extension<WsReciever>;
pub type UpdateWsReciever = Receiver<Update>;
pub type UpdateWsRecieverExtension = Extension<UpdateWsReciever>;
#[derive(Serialize)]
struct UpdateMsg {
@@ -58,7 +59,7 @@ impl UpdateMsg {
}
}
pub fn make_update_ws_sender_reciver() -> (WsSenderExtension, WsRecieverExtension) {
pub fn make_update_ws_sender_reciver() -> (UpdateWsSenderExtension, UpdateWsRecieverExtension) {
let (sender, reciever) = watch::channel(Default::default());
(
Extension(Arc::new(Mutex::new((sender)))),
@@ -69,7 +70,7 @@ pub fn make_update_ws_sender_reciver() -> (WsSenderExtension, WsRecieverExtensio
pub async fn ws_handler(
Extension(jwt_client): JwtExtension,
Extension(db_client): DbExtension,
Extension(mut reciever): WsRecieverExtension,
Extension(mut reciever): UpdateWsRecieverExtension,
ws: WebSocketUpgrade,
) -> impl IntoResponse {
ws.on_upgrade(|socket| async move {
@@ -101,13 +102,7 @@ pub async fn ws_handler(
}
let user = user.unwrap().unwrap(); // already handle cases where this panics in the above early return
let update = reciever.borrow().to_owned();
match user_can_see_update(
&user,
&user_id,
&update.target,
&db_client,
)
.await
match user_can_see_update(&user, &user_id, &update.target, &db_client).await
{
Ok(_) => {
let _ = ws_sender
@@ -216,7 +211,7 @@ async fn user_can_see_update(
.await
.context(format!("failed at query to get server at {server_id}"))?
.ok_or(anyhow!("did not server with id {server_id}"))?;
if user_permissions(user_id, &server.permissions) != PermissionLevel::None {
if get_user_permissions(user_id, &server.permissions) != PermissionLevel::None {
Ok(())
} else {
Err(anyhow!("user does not have permissions on server"))
@@ -231,7 +226,7 @@ async fn user_can_see_update(
"failed at query to get deployment at {deployment_id}"
))?
.ok_or(anyhow!("did not deployment with id {deployment_id}"))?;
if user_permissions(user_id, &deployment.permissions) != PermissionLevel::None {
if get_user_permissions(user_id, &deployment.permissions) != PermissionLevel::None {
Ok(())
} else {
Err(anyhow!("user does not have permissions on deployment"))
@@ -244,7 +239,7 @@ async fn user_can_see_update(
.await
.context(format!("failed at query to get build at {build_id}"))?
.ok_or(anyhow!("did not build with id {build_id}"))?;
if user_permissions(user_id, &build.permissions) != PermissionLevel::None {
if get_user_permissions(user_id, &build.permissions) != PermissionLevel::None {
Ok(())
} else {
Err(anyhow!("user does not have permissions on build"))
+14 -5
View File
@@ -269,10 +269,6 @@ pub struct CoreConfig {
#[serde(default = "default_core_port")]
pub port: u16,
// github integration
pub github_oauth: OauthCredentials,
pub github_webhook_secret: Option<String>,
// jwt config
pub jwt_secret: String,
#[serde(default = "default_jwt_valid_for")]
@@ -281,6 +277,10 @@ pub struct CoreConfig {
// integration with slack app
pub slack_url: Option<String>,
// github integration
pub github_oauth: OauthCredentials,
pub github_webhook_secret: Option<String>,
// mongo config
pub mongo: MongoConfig,
}
@@ -386,7 +386,7 @@ pub enum UpdateTarget {
System,
Build(String),
Deployment(String),
Server(String)
Server(String),
}
impl Default for UpdateTarget {
@@ -443,6 +443,15 @@ pub enum PermissionLevel {
Write,
}
#[derive(Serialize, Deserialize, Debug, Display, EnumString, PartialEq, Hash, Eq, Clone, Copy)]
#[serde(rename_all = "snake_case")]
#[strum(serialize_all = "snake_case")]
pub enum PermissionsTarget {
Server,
Deployment,
Build,
}
#[derive(Serialize, Deserialize, Debug, Display, EnumString, PartialEq, Hash, Eq, Clone, Copy)]
#[serde(rename_all = "snake_case")]
#[strum(serialize_all = "snake_case")]