get specific network
This commit is contained in:
parent
359f5be936
commit
6d97826050
|
@ -72,6 +72,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
||||||
.service(routes::v1::auth::totp::totp_request)
|
.service(routes::v1::auth::totp::totp_request)
|
||||||
.service(routes::v1::networks::get_networks)
|
.service(routes::v1::networks::get_networks)
|
||||||
.service(routes::v1::organization::create_org_request)
|
.service(routes::v1::organization::create_org_request)
|
||||||
|
.service(routes::v1::networks::get_network_request)
|
||||||
}).bind(CONFIG.server.bind)?.run().await?;
|
}).bind(CONFIG.server.bind)?.run().await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
use actix_web::{get, HttpRequest, HttpResponse};
|
use actix_web::{get, HttpRequest, HttpResponse};
|
||||||
use actix_web::web::{Data, Query};
|
use actix_web::web::{Data, Path, Query};
|
||||||
use chrono::{TimeZone, Utc};
|
use chrono::{TimeZone, Utc};
|
||||||
use log::error;
|
use log::error;
|
||||||
use sea_orm::{ColumnTrait, EntityTrait, PaginatorTrait, QueryFilter, QueryOrder};
|
use sea_orm::{ColumnTrait, EntityTrait, PaginatorTrait, QueryFilter, QueryOrder};
|
||||||
|
@ -26,7 +26,7 @@ pub struct GetNetworksResponseData {
|
||||||
#[serde(rename = "signingCAID")]
|
#[serde(rename = "signingCAID")]
|
||||||
pub signing_ca_id: String,
|
pub signing_ca_id: String,
|
||||||
#[serde(rename = "createdAt")]
|
#[serde(rename = "createdAt")]
|
||||||
pub created_at: String, // 2023-03-22T18:55:47.009Z, %Y-%m-%dT%H-%M-%S.%.3fZ
|
pub created_at: String, // 2023-03-22T18:55:47.009Z, %Y-%m-%dT%H-%M-%S%.3fZ
|
||||||
pub name: String,
|
pub name: String,
|
||||||
#[serde(rename = "lighthousesAsRelays")]
|
#[serde(rename = "lighthousesAsRelays")]
|
||||||
pub lighthouses_as_relays: bool
|
pub lighthouses_as_relays: bool
|
||||||
|
@ -247,4 +247,87 @@ pub async fn get_networks(opts: Query<GetNetworksQueryParams>, req_info: HttpReq
|
||||||
} else { None },
|
} else { None },
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[get("/v1/networks/{network_id}")]
|
||||||
|
pub async fn get_network_request(net: Path<String>, req_info: HttpRequest, db: Data<AppState>) -> HttpResponse {
|
||||||
|
// For this endpoint, you either need to be a fully authenticated user OR a token with networks:list
|
||||||
|
let session_info = enforce_2fa(&req_info, &db.conn).await.unwrap_or(TokenInfo::NotPresent);
|
||||||
|
let api_token_info = enforce_api_token(&req_info, &["networks:read"], &db.conn).await.unwrap_or(TokenInfo::NotPresent);
|
||||||
|
|
||||||
|
// If neither are present, throw an error
|
||||||
|
if matches!(session_info, TokenInfo::NotPresent) && matches!(api_token_info, TokenInfo::NotPresent) {
|
||||||
|
return HttpResponse::Unauthorized().json(APIErrorsResponse {
|
||||||
|
errors: vec![
|
||||||
|
APIError {
|
||||||
|
code: "ERR_UNAUTHORIZED".to_string(),
|
||||||
|
message: "This endpoint requires either a fully authenticated user or a token with the networks:read scope".to_string(),
|
||||||
|
path: None,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// If both are present, throw an error
|
||||||
|
if matches!(session_info, TokenInfo::AuthToken(_)) && matches!(api_token_info, TokenInfo::ApiToken(_)) {
|
||||||
|
return HttpResponse::BadRequest().json(APIErrorsResponse {
|
||||||
|
errors: vec![
|
||||||
|
APIError {
|
||||||
|
code: "ERR_AMBIGUOUS_AUTHENTICATION".to_string(),
|
||||||
|
message: "Both a user token and an API token with the proper scope was provided. Please only provide one.".to_string(),
|
||||||
|
path: None
|
||||||
|
}
|
||||||
|
],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
let network: Option<network::Model> = match network::Entity::find().filter(network::Column::Id.eq(net.into_inner())).one(&db.conn).await {
|
||||||
|
Ok(r) => r,
|
||||||
|
Err(e) => {
|
||||||
|
error!("database error: {}", e);
|
||||||
|
return HttpResponse::InternalServerError().json(APIErrorsResponse {
|
||||||
|
errors: vec![
|
||||||
|
APIError {
|
||||||
|
code: "ERR_DB_ERROR".to_string(),
|
||||||
|
message: "There was an error performing the database request, please try again later.".to_string(),
|
||||||
|
path: None,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(network) = network {
|
||||||
|
HttpResponse::Ok().json(GetNetworkResponse {
|
||||||
|
data: GetNetworksResponseData {
|
||||||
|
id: network.id,
|
||||||
|
cidr: network.cidr,
|
||||||
|
organization_id: network.organization,
|
||||||
|
signing_ca_id: network.signing_ca,
|
||||||
|
created_at: Utc.timestamp_opt(network.created_at, 0).unwrap().format("%Y-%m-%dT%H-%M-%S%.3fZ").to_string(),
|
||||||
|
name: network.name,
|
||||||
|
lighthouses_as_relays: network.lighthouses_as_relays,
|
||||||
|
},
|
||||||
|
metadata: GetNetworkResponseMetadata {},
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
HttpResponse::NotFound().json(APIErrorsResponse {
|
||||||
|
errors: vec![
|
||||||
|
APIError {
|
||||||
|
code: "ERR_MISSING_NETWORK".to_string(),
|
||||||
|
message: "Network does not exist".to_string(),
|
||||||
|
path: None,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
pub struct GetNetworkResponse {
|
||||||
|
pub data: GetNetworksResponseData,
|
||||||
|
pub metadata: GetNetworkResponseMetadata
|
||||||
|
}
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
pub struct GetNetworkResponseMetadata {}
|
Loading…
Reference in New Issue