Skip to content

Commit

Permalink
Merge admin routes with private routes (#11)
Browse files Browse the repository at this point in the history
* ENG-3184: Merge `admin` routes into private routes

* Removing admin route test

* Removing admin routes from tests

* Removing unused route

* Removing tests of unused routes

* Removing unused imports

* Ignoring tests until we figure jwt -> auth flow

* Fixing all tests
  • Loading branch information
sagojez authored Apr 26, 2024
1 parent 7ff89fa commit 9b291ac
Show file tree
Hide file tree
Showing 29 changed files with 516 additions and 846 deletions.
620 changes: 295 additions & 325 deletions Cargo.lock

Large diffs are not rendered by default.

3 changes: 0 additions & 3 deletions api/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ pub struct Config {
pub access_key_cache_ttl_secs: u64,
#[envconfig(from = "ACCESS_KEY_WHITELIST_REFRESH_INTERVAL_SECS", default = "60")]
pub access_key_whitelist_refresh_interval_secs: u64,
#[envconfig(from = "IS_ADMIN", default = "false")]
pub is_admin: bool,
#[envconfig(from = "ENGINEERING_ACCOUNT_ID", default = "engineering_account")]
pub engineering_account_id: String,
#[envconfig(
Expand Down Expand Up @@ -94,7 +92,6 @@ impl Display for Config {
"ACCESS_KEY_WHITELIST_REFRESH_INTERVAL_SECS: {}",
self.access_key_whitelist_refresh_interval_secs
)?;
writeln!(f, "IS_ADMIN: {}", self.is_admin)?;
writeln!(f, "EVENT_ACCESS_PASSWORD: ***")?;
writeln!(
f,
Expand Down
2 changes: 1 addition & 1 deletion api/src/endpoints/common_enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ pub async fn read(
query: Option<Query<BTreeMap<String, String>>>,
State(state): State<Arc<AppState>>,
) -> Result<Json<ReadResponse<CommonEnum>>, ApiError> {
let mut query = shape_mongo_filter(query, None, None);
let mut query = shape_mongo_filter(query, None, None, false);
query.filter.remove(DELETED_STR);

let store = &state.app_stores.common_enum;
Expand Down
4 changes: 4 additions & 0 deletions api/src/endpoints/common_model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ impl CrudHook<CommonModel> for CreateRequest {
impl CrudRequest for CreateRequest {
type Output = CommonModel;

fn filterable() -> bool {
false
}

fn output(&self) -> Option<Self::Output> {
let mut record = Self::Output {
id: Id::now(IdPrefix::CommonModel),
Expand Down
13 changes: 11 additions & 2 deletions api/src/endpoints/connection_definition.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use super::{
create, delete, update, ApiResult, CachedRequest, CrudHook, CrudRequest, ReadResponse, Unit,
create, delete, read, update, ApiResult, CachedRequest, CrudHook, CrudRequest, ReadResponse,
Unit,
};
use crate::{
internal_server_error, not_found,
Expand Down Expand Up @@ -31,7 +32,11 @@ use tracing::error;

pub fn get_router() -> Router<Arc<AppState>> {
Router::new()
.route("/", post(create::<CreateRequest, ConnectionDefinition>))
.route(
"/",
post(create::<CreateRequest, ConnectionDefinition>)
.get(read::<CreateRequest, ConnectionDefinition>),
)
.route(
"/:id",
patch(update::<CreateRequest, ConnectionDefinition>)
Expand Down Expand Up @@ -254,6 +259,10 @@ pub async fn public_get_connection_details(
impl CrudRequest for CreateRequest {
type Output = ConnectionDefinition;

fn filterable() -> bool {
false
}

fn output(&self) -> Option<Self::Output> {
let auth_secrets: Vec<AuthSecret> = self
.authentication
Expand Down
4 changes: 4 additions & 0 deletions api/src/endpoints/connection_model_definition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,10 @@ impl CrudHook<ConnectionModelDefinition> for CreateRequest {}
impl CrudRequest for CreateRequest {
type Output = ConnectionModelDefinition;

fn filterable() -> bool {
false
}

fn output(&self) -> Option<Self::Output> {
let key = format!(
"api::{}::{}::{}::{}::{}::{}",
Expand Down
102 changes: 11 additions & 91 deletions api/src/endpoints/connection_model_schema.rs
Original file line number Diff line number Diff line change
@@ -1,32 +1,23 @@
use super::{
create, delete, read, update, ApiError, ApiResult, CrudHook, CrudRequest, ReadResponse,
};
use super::{create, delete, read, update, ApiResult, CrudHook, CrudRequest};
use crate::{
api_payloads::ErrorResponse,
internal_server_error,
server::{AppState, AppStores},
util::shape_mongo_filter,
};
use axum::{
extract::{Path, Query, State},
extract::{Path, State},
routing::{patch, post},
Extension, Json, Router,
Json, Router,
};
use http::StatusCode;
use integrationos_domain::{
algebra::{MongoStore, StoreExt},
connection_model_schema::{
ConnectionModelSchema, Mappings, PublicConnectionModelSchema, SchemaPaths,
},
event_access::EventAccess,
connection_model_schema::{ConnectionModelSchema, Mappings, SchemaPaths},
id::{prefix::IdPrefix, Id},
json_schema::JsonSchema,
};
use mongodb::bson::doc;
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::{collections::BTreeMap, sync::Arc};
use tokio::try_join;
use std::sync::Arc;
use tracing::error;

pub fn get_router() -> Router<Arc<AppState>> {
Expand All @@ -43,74 +34,7 @@ pub fn get_router() -> Router<Arc<AppState>> {
)
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
#[cfg_attr(feature = "dummy", derive(fake::Dummy))]
#[serde(rename_all = "camelCase")]
pub struct PublicGetConnectionModelSchema {
pub connection_definition_id: Id,
}

pub async fn public_get_connection_model_schema<T, U>(
event_access: Option<Extension<Arc<EventAccess>>>,
query: Option<Query<BTreeMap<String, String>>>,
State(state): State<Arc<AppState>>,
) -> Result<Json<ReadResponse<U>>, ApiError>
where
T: CrudRequest<Output = U> + 'static,
U: Serialize + DeserializeOwned + Unpin + Sync + Send + 'static,
{
match query.as_ref().and_then(|q| q.get("connectionDefinitionId")) {
Some(id) => id.to_string(),
None => {
return Err((
StatusCode::BAD_REQUEST,
Json(ErrorResponse {
error: "connectionDefinitionId is required".to_string(),
}),
))
}
};

let mut query = shape_mongo_filter(
query,
event_access.map(|e| {
let Extension(e) = e;
e
}),
None,
);

query.filter.remove("ownership.buildableId");
query.filter.remove("environment");
query.filter.insert("mapping", doc! { "$ne": null });

let store = T::get_store(state.app_stores.clone());
let count = store.count(query.filter.clone(), None);
let find = store.get_many(
Some(query.filter),
None,
None,
Some(query.limit),
Some(query.skip),
);

let res = match try_join!(count, find) {
Ok((total, rows)) => ReadResponse {
rows,
skip: query.skip,
limit: query.limit,
total,
},
Err(e) => {
error!("Error reading from store: {e}");
return Err(internal_server_error!());
}
};

Ok(Json(res))
}

pub async fn public_get_platform_models(
pub async fn get_platform_models(
Path(platform_name): Path<String>,
State(state): State<Arc<AppState>>,
) -> ApiResult<Vec<String>> {
Expand Down Expand Up @@ -142,14 +66,6 @@ pub async fn public_get_platform_models(
Ok(Json(common_model_names))
}

impl CrudRequest for PublicGetConnectionModelSchema {
type Output = PublicConnectionModelSchema;

fn get_store(stores: AppStores) -> MongoStore<Self::Output> {
stores.public_model_schema.clone()
}
}

#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
#[cfg_attr(feature = "dummy", derive(fake::Dummy))]
#[serde(rename_all = "camelCase")]
Expand All @@ -172,6 +88,10 @@ impl CrudHook<ConnectionModelSchema> for CreateRequest {}
impl CrudRequest for CreateRequest {
type Output = ConnectionModelSchema;

fn filterable() -> bool {
false
}

fn output(&self) -> Option<Self::Output> {
let key = format!(
"api::{}::{}::{}",
Expand Down
4 changes: 4 additions & 0 deletions api/src/endpoints/connection_oauth_definition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ fn default_separator() -> Option<String> {
impl CrudRequest for CreateRequest {
type Output = ConnectionOAuthDefinition;

fn filterable() -> bool {
false
}

fn output(&self) -> Option<Self::Output> {
Some(Self::Output {
id: Id::new(IdPrefix::ConnectionOAuthDefinition, Utc::now()),
Expand Down
4 changes: 0 additions & 4 deletions api/src/endpoints/metrics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,6 @@ pub async fn get_metrics(
let query_params = query_params.unwrap_or_default();

let metric_type = query_params.metric_type.unwrap_or(MetricType::Unified);
println!(
"metric type: {:?} - {}",
query_params.metric_type, metric_type
);
let Ok(doc) = doc.get_document(metric_type.to_string()) else {
return Ok(Json(MetricResponse { count: 0 }));
};
Expand Down
56 changes: 34 additions & 22 deletions api/src/endpoints/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use integrationos_domain::{
use moka::future::Cache;
use mongodb::options::FindOneOptions;
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use std::{collections::BTreeMap, sync::Arc};
use std::{collections::BTreeMap, fmt::Debug, sync::Arc};
use tokio::try_join;
use tracing::error;

Expand Down Expand Up @@ -63,8 +63,15 @@ pub trait CrudRequest: Sized {
None
}

///
/// Update the output of the request based on the input.
fn update(&self, _: &mut Self::Output) -> Unit {}

/// Whether the Output can be filtered by the environment and ownership.
fn filterable() -> bool {
true
}

/// Get the store for the request.
fn get_store(stores: AppStores) -> MongoStore<Self::Output>;
}

Expand Down Expand Up @@ -118,18 +125,14 @@ pub async fn create<T, U>(
) -> ApiResult<U>
where
T: CrudRequest<Output = U> + CrudHook<U> + 'static,
U: Serialize + DeserializeOwned + Unpin + Sync + Send + 'static,
U: Serialize + DeserializeOwned + Unpin + Sync + Send + Debug + 'static,
{
let output = if let Some(Extension(event_access)) = event_access {
req.event_access(event_access)
} else {
req.output()
};

let output = match output {
Some(output) => output,
None => return Err(not_found!("Record")),
};
let output = event_access
.map_or_else(
|| req.output(),
|event_access| req.event_access(event_access.0).or(req.output()),
)
.ok_or_else(|| not_found!("Record"))?;

match T::get_store(state.app_stores.clone())
.create_one(&output)
Expand Down Expand Up @@ -168,7 +171,7 @@ pub async fn read<T, U>(
) -> Result<Json<ReadResponse<U>>, ApiError>
where
T: CrudRequest<Output = U> + 'static,
U: Serialize + DeserializeOwned + Unpin + Sync + Send + 'static,
U: Serialize + DeserializeOwned + Unpin + Sync + Send + Debug + 'static,
{
let query = shape_mongo_filter(
query,
Expand All @@ -177,6 +180,7 @@ where
e
}),
Some(headers),
T::filterable(),
);

let store = T::get_store(state.app_stores.clone());
Expand All @@ -198,6 +202,7 @@ where
},
Err(e) => {
error!("Error reading from store: {e}");
println!("{:?}", e);
return Err(internal_server_error!());
}
};
Expand All @@ -211,14 +216,15 @@ pub async fn read_cached<T, U>(
) -> Result<Json<Arc<ReadResponse<U>>>, ApiError>
where
T: CachedRequest<Output = U> + 'static,
U: Clone + Serialize + DeserializeOwned + Unpin + Sync + Send + 'static,
U: Clone + Serialize + DeserializeOwned + Unpin + Sync + Send + Debug + 'static,
{
let cache = T::get_cache(state.clone());

let res = cache
.try_get_with(query.as_ref().map(|q| q.0.clone()), async {
let query = shape_mongo_filter(query, None, None);
let query = shape_mongo_filter(query, None, None, T::filterable());

println!("{:?}", query);
let store = T::get_store(state.app_stores.clone());
let count = store.count(query.filter.clone(), None);
let find = store.get_many(
Expand All @@ -230,12 +236,16 @@ where
);

let res = match try_join!(count, find) {
Ok((total, rows)) => Arc::new(ReadResponse {
rows,
skip: query.skip,
limit: query.limit,
total,
}),
Ok((total, rows)) => {
println!("{:?}", total);

Arc::new(ReadResponse {
rows,
skip: query.skip,
limit: query.limit,
total,
})
}
Err(e) => {
error!("Error reading from store: {e}");
return Err(internal_server_error!());
Expand Down Expand Up @@ -272,6 +282,7 @@ where
e
}),
None,
T::filterable(),
);
query.filter.insert("_id", id.clone());

Expand Down Expand Up @@ -337,6 +348,7 @@ where
e
}),
None,
T::filterable(),
);
query.filter.insert("_id", id.clone());

Expand Down
7 changes: 1 addition & 6 deletions api/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,8 @@ use tracing::info;
fn main() -> Result<()> {
dotenv().ok();
let config = Config::init_from_env()?;
let name = if config.is_admin {
"admin-api"
} else {
"event-api"
};

let subscriber = get_subscriber(name.into(), "info".into(), std::io::stdout);
let subscriber = get_subscriber("connections-api".into(), "info".into(), std::io::stdout);
init_subscriber(subscriber);

info!("Starting API with config:\n{config}");
Expand Down
Loading

0 comments on commit 9b291ac

Please sign in to comment.