Request Inheritance (#209)

This commit is contained in:
Gregory Schier
2025-05-23 08:13:25 -07:00
committed by GitHub
parent 13d959799a
commit 4cd2e9cd31
41 changed files with 1031 additions and 403 deletions

View File

@@ -2,10 +2,12 @@ use crate::connection_or_tx::ConnectionOrTx;
use crate::db_context::DbContext;
use crate::error::Result;
use crate::models::{
Folder, FolderIden, GrpcRequest, GrpcRequestIden, HttpRequest, HttpRequestIden,
WebsocketRequest, WebsocketRequestIden,
Folder, FolderIden, GrpcRequest, GrpcRequestIden, HttpRequest, HttpRequestHeader,
HttpRequestIden, WebsocketRequest, WebsocketRequestIden,
};
use crate::util::UpdateSource;
use serde_json::Value;
use std::collections::BTreeMap;
impl<'a> DbContext<'a> {
pub fn get_folder(&self, id: &str) -> Result<Folder> {
@@ -110,4 +112,40 @@ impl<'a> DbContext<'a> {
Ok(new_folder)
}
pub fn resolve_auth_for_folder(
&self,
folder: Folder,
) -> Result<(Option<String>, BTreeMap<String, Value>)> {
if let Some(at) = folder.authentication_type {
return Ok((Some(at), folder.authentication));
}
if let Some(folder_id) = folder.folder_id {
let folder = self.get_folder(&folder_id)?;
return self.resolve_auth_for_folder(folder);
}
let workspace = self.get_workspace(&folder.workspace_id)?;
Ok(self.resolve_auth_for_workspace(&workspace))
}
pub fn resolve_headers_for_folder(&self, folder: &Folder) -> Result<Vec<HttpRequestHeader>> {
let mut headers = Vec::new();
if let Some(folder_id) = folder.folder_id.clone() {
let parent_folder = self.get_folder(&folder_id)?;
let mut folder_headers = self.resolve_headers_for_folder(&parent_folder)?;
// NOTE: Add parent headers first, so overrides are logical
headers.append(&mut folder_headers);
} else {
let workspace = self.get_workspace(&folder.workspace_id)?;
let mut workspace_headers = self.resolve_headers_for_workspace(&workspace);
headers.append(&mut workspace_headers);
}
headers.append(&mut folder.headers.clone());
Ok(headers)
}
}

View File

@@ -1,7 +1,9 @@
use crate::db_context::DbContext;
use crate::error::Result;
use crate::models::{GrpcRequest, GrpcRequestIden};
use crate::models::{GrpcRequest, GrpcRequestIden, HttpRequestHeader};
use crate::util::UpdateSource;
use serde_json::Value;
use std::collections::BTreeMap;
impl<'a> DbContext<'a> {
pub fn get_grpc_request(&self, id: &str) -> Result<GrpcRequest> {
@@ -48,4 +50,43 @@ impl<'a> DbContext<'a> {
) -> Result<GrpcRequest> {
self.upsert(grpc_request, source)
}
pub fn resolve_auth_for_grpc_request(
&self,
grpc_request: &GrpcRequest,
) -> Result<(Option<String>, BTreeMap<String, Value>)> {
if let Some(at) = grpc_request.authentication_type.clone() {
return Ok((Some(at), grpc_request.authentication.clone()));
}
if let Some(folder_id) = grpc_request.folder_id.clone() {
let folder = self.get_folder(&folder_id)?;
return self.resolve_auth_for_folder(folder);
}
let workspace = self.get_workspace(&grpc_request.workspace_id)?;
Ok(self.resolve_auth_for_workspace(&workspace))
}
pub fn resolve_metadata_for_grpc_request(
&self,
grpc_request: &GrpcRequest,
) -> Result<Vec<HttpRequestHeader>> {
// Resolved headers should be from furthest to closest ancestor, to override logically.
let mut metadata = Vec::new();
if let Some(folder_id) = grpc_request.folder_id.clone() {
let parent_folder = self.get_folder(&folder_id)?;
let mut folder_headers = self.resolve_headers_for_folder(&parent_folder)?;
metadata.append(&mut folder_headers);
} else {
let workspace = self.get_workspace(&grpc_request.workspace_id)?;
let mut workspace_metadata = self.resolve_headers_for_workspace(&workspace);
metadata.append(&mut workspace_metadata);
}
metadata.append(&mut grpc_request.metadata.clone());
Ok(metadata)
}
}

View File

@@ -1,7 +1,9 @@
use crate::db_context::DbContext;
use crate::error::Result;
use crate::models::{HttpRequest, HttpRequestIden};
use crate::models::{HttpRequest, HttpRequestHeader, HttpRequestIden};
use crate::util::UpdateSource;
use serde_json::Value;
use std::collections::BTreeMap;
impl<'a> DbContext<'a> {
pub fn get_http_request(&self, id: &str) -> Result<HttpRequest> {
@@ -48,4 +50,43 @@ impl<'a> DbContext<'a> {
) -> Result<HttpRequest> {
self.upsert(http_request, source)
}
pub fn resolve_auth_for_http_request(
&self,
http_request: &HttpRequest,
) -> Result<(Option<String>, BTreeMap<String, Value>)> {
if let Some(at) = http_request.authentication_type.clone() {
return Ok((Some(at), http_request.authentication.clone()));
}
if let Some(folder_id) = http_request.folder_id.clone() {
let folder = self.get_folder(&folder_id)?;
return self.resolve_auth_for_folder(folder);
}
let workspace = self.get_workspace(&http_request.workspace_id)?;
Ok(self.resolve_auth_for_workspace(&workspace))
}
pub fn resolve_headers_for_http_request(
&self,
http_request: &HttpRequest,
) -> Result<Vec<HttpRequestHeader>> {
// Resolved headers should be from furthest to closest ancestor, to override logically.
let mut headers = Vec::new();
if let Some(folder_id) = http_request.folder_id.clone() {
let parent_folder = self.get_folder(&folder_id)?;
let mut folder_headers = self.resolve_headers_for_folder(&parent_folder)?;
headers.append(&mut folder_headers);
} else {
let workspace = self.get_workspace(&http_request.workspace_id)?;
let mut workspace_headers = self.resolve_headers_for_workspace(&workspace);
headers.append(&mut workspace_headers);
}
headers.append(&mut http_request.headers.clone());
Ok(headers)
}
}

View File

@@ -1,7 +1,9 @@
use crate::db_context::DbContext;
use crate::error::Result;
use crate::models::{WebsocketRequest, WebsocketRequestIden};
use crate::models::{HttpRequestHeader, WebsocketRequest, WebsocketRequestIden};
use crate::util::UpdateSource;
use serde_json::Value;
use std::collections::BTreeMap;
impl<'a> DbContext<'a> {
pub fn get_websocket_request(&self, id: &str) -> Result<WebsocketRequest> {
@@ -48,4 +50,47 @@ impl<'a> DbContext<'a> {
) -> Result<WebsocketRequest> {
self.upsert(websocket_request, source)
}
pub fn resolve_auth_for_websocket_request(
&self,
websocket_request: &WebsocketRequest,
) -> Result<(Option<String>, BTreeMap<String, Value>)> {
if let Some(at) = websocket_request.authentication_type.clone() {
return Ok((Some(at), websocket_request.authentication.clone()));
}
if let Some(folder_id) = websocket_request.folder_id.clone() {
let folder = self.get_folder(&folder_id)?;
return self.resolve_auth_for_folder(folder);
}
let workspace = self.get_workspace(&websocket_request.workspace_id)?;
Ok(self.resolve_auth_for_workspace(&workspace))
}
pub fn resolve_headers_for_websocket_request(
&self,
websocket_request: &WebsocketRequest,
) -> Result<Vec<HttpRequestHeader>> {
let workspace = self.get_workspace(&websocket_request.workspace_id)?;
// Resolved headers should be from furthest to closest ancestor, to override logically.
let mut headers = Vec::new();
headers.append(&mut workspace.headers.clone());
if let Some(folder_id) = websocket_request.folder_id.clone() {
let parent_folder = self.get_folder(&folder_id)?;
let mut folder_headers = self.resolve_headers_for_folder(&parent_folder)?;
headers.append(&mut folder_headers);
} else {
let workspace = self.get_workspace(&websocket_request.workspace_id)?;
let mut workspace_headers = self.resolve_headers_for_workspace(&workspace);
headers.append(&mut workspace_headers);
}
headers.append(&mut websocket_request.headers.clone());
Ok(headers)
}
}

View File

@@ -1,10 +1,12 @@
use crate::db_context::DbContext;
use crate::error::Result;
use crate::models::{
EnvironmentIden, FolderIden, GrpcRequestIden, HttpRequestIden, WebsocketRequestIden, Workspace,
WorkspaceIden,
EnvironmentIden, FolderIden, GrpcRequestIden, HttpRequestHeader, HttpRequestIden,
WebsocketRequestIden, Workspace, WorkspaceIden,
};
use crate::util::UpdateSource;
use serde_json::Value;
use std::collections::BTreeMap;
impl<'a> DbContext<'a> {
pub fn get_workspace(&self, id: &str) -> Result<Workspace> {
@@ -65,4 +67,15 @@ impl<'a> DbContext<'a> {
pub fn upsert_workspace(&self, w: &Workspace, source: &UpdateSource) -> Result<Workspace> {
self.upsert(w, source)
}
pub fn resolve_auth_for_workspace(
&self,
workspace: &Workspace,
) -> (Option<String>, BTreeMap<String, Value>) {
(workspace.authentication_type.clone(), workspace.authentication.clone())
}
pub fn resolve_headers_for_workspace(&self, workspace: &Workspace) -> Vec<HttpRequestHeader> {
workspace.headers.clone()
}
}