Skip to content

Commit

Permalink
aide working, to test if openapi if good
Browse files Browse the repository at this point in the history
  • Loading branch information
Zac Ecob committed Jul 19, 2024
1 parent 16972da commit f896c6f
Show file tree
Hide file tree
Showing 9 changed files with 77 additions and 30 deletions.
2 changes: 2 additions & 0 deletions backend/server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,6 @@ rust-s3 = "0.34.0"
rs-snowflake = "0.6"
jsonwebtoken = "9.1"
dotenvy = "0.15"
aide = { version = "0.13.4", features = ["axum", "macros"]}
schemars = {version = "0.8.21", features = ["chrono"]}

26 changes: 14 additions & 12 deletions backend/server/src/handler/organisation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ use crate::service;
use axum::extract::{Json, Path, State};
use axum::http::StatusCode;
use axum::response::IntoResponse;
use aide::OperationOutput;
use aide::axum::IntoApiResponse;

pub struct OrganisationHandler;

Expand All @@ -18,7 +20,7 @@ impl OrganisationHandler {
_user: SuperUser,
mut transaction: DBTransaction<'_>,
Json(data): Json<NewOrganisation>,
) -> Result<impl IntoResponse, ChaosError> {
) -> Result<impl IntoApiResponse, ChaosError> {
Organisation::create(
data.admin,
data.name,
Expand All @@ -35,7 +37,7 @@ impl OrganisationHandler {
State(state): State<AppState>,
Path(id): Path<i64>,
_user: AuthUser,
) -> Result<impl IntoResponse, ChaosError> {
) -> Result<impl IntoApiResponse, ChaosError> {
let org = Organisation::get(id, &state.db).await?;
Ok((StatusCode::OK, Json(org)))
}
Expand All @@ -44,7 +46,7 @@ impl OrganisationHandler {
State(state): State<AppState>,
Path(id): Path<i64>,
_user: SuperUser,
) -> Result<impl IntoResponse, ChaosError> {
) -> Result<impl IntoApiResponse, ChaosError> {
Organisation::delete(id, &state.db).await?;
Ok((StatusCode::OK, "Successfully deleted organisation"))
}
Expand All @@ -53,7 +55,7 @@ impl OrganisationHandler {
State(state): State<AppState>,
Path(id): Path<i64>,
_user: SuperUser,
) -> Result<impl IntoResponse, ChaosError> {
) -> Result<impl IntoApiResponse, ChaosError> {
let members = Organisation::get_admins(id, &state.db).await?;
Ok((StatusCode::OK, Json(members)))
}
Expand All @@ -62,7 +64,7 @@ impl OrganisationHandler {
State(state): State<AppState>,
Path(id): Path<i64>,
_admin: OrganisationAdmin,
) -> Result<impl IntoResponse, ChaosError> {
) -> Result<impl IntoApiResponse, ChaosError> {
let members = Organisation::get_members(id, &state.db).await?;
Ok((StatusCode::OK, Json(members)))
}
Expand All @@ -73,7 +75,7 @@ impl OrganisationHandler {
_super_user: SuperUser,
mut transaction: DBTransaction<'_>,
Json(request_body): Json<AdminUpdateList>,
) -> Result<impl IntoResponse, ChaosError> {
) -> Result<impl IntoApiResponse, ChaosError> {
Organisation::update_admins(id, request_body.members, &mut transaction.tx).await?;

transaction.tx.commit().await?;
Expand All @@ -86,7 +88,7 @@ impl OrganisationHandler {
Path(id): Path<i64>,
_admin: OrganisationAdmin,
Json(request_body): Json<AdminUpdateList>,
) -> Result<impl IntoResponse, ChaosError> {
) -> Result<impl IntoApiResponse, ChaosError> {
Organisation::update_members(id, request_body.members, &mut transaction.tx).await?;

transaction.tx.commit().await?;
Expand All @@ -98,7 +100,7 @@ impl OrganisationHandler {
Path(id): Path<i64>,
_super_user: SuperUser,
Json(request_body): Json<AdminToRemove>,
) -> Result<impl IntoResponse, ChaosError> {
) -> Result<impl IntoApiResponse, ChaosError> {
Organisation::remove_admin(id, request_body.user_id, &state.db).await?;

Ok((
Expand All @@ -112,7 +114,7 @@ impl OrganisationHandler {
Path(id): Path<i64>,
_admin: OrganisationAdmin,
Json(request_body): Json<AdminToRemove>,
) -> Result<impl IntoResponse, ChaosError> {
) -> Result<impl IntoApiResponse, ChaosError> {
Organisation::remove_member(id, request_body.user_id, &state.db).await?;

Ok((
Expand All @@ -125,7 +127,7 @@ impl OrganisationHandler {
State(state): State<AppState>,
Path(id): Path<i64>,
_admin: OrganisationAdmin,
) -> Result<impl IntoResponse, ChaosError> {
) -> Result<impl IntoApiResponse, ChaosError> {
let logo_url = Organisation::update_logo(id, &state.db, &state.storage_bucket).await?;
Ok((StatusCode::OK, Json(logo_url)))
}
Expand All @@ -134,7 +136,7 @@ impl OrganisationHandler {
State(state): State<AppState>,
Path(id): Path<i64>,
_user: AuthUser,
) -> Result<impl IntoResponse, ChaosError> {
) -> Result<impl IntoApiResponse, ChaosError> {
let campaigns = Organisation::get_campaigns(id, &state.db).await?;

Ok((StatusCode::OK, Json(campaigns)))
Expand All @@ -144,7 +146,7 @@ impl OrganisationHandler {
State(mut state): State<AppState>,
_admin: OrganisationAdmin,
Json(request_body): Json<models::campaign::Campaign>,
) -> Result<impl IntoResponse, ChaosError> {
) -> Result<impl IntoApiResponse, ChaosError> {
Organisation::create_campaign(
request_body.name,
request_body.description,
Expand Down
46 changes: 35 additions & 11 deletions backend/server/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,30 @@ use crate::handler::auth::google_callback;
use crate::handler::organisation::OrganisationHandler;
use crate::models::storage::Storage;
use anyhow::Result;
use axum::routing::{get, patch, post, put};
use axum::Router;
use axum::{Router, Extension};
use jsonwebtoken::{Algorithm, DecodingKey, EncodingKey, Header, Validation};
use models::app::AppState;
use snowflake::SnowflakeIdGenerator;
use sqlx::postgres::PgPoolOptions;
use std::env;

use axum::Json;
use aide::{
axum::{
routing::{get, post, patch, put},
ApiRouter, IntoApiResponse,
},
openapi::{Info, OpenApi},
};

mod handler;
mod models;
mod service;

async fn serve_api(Extension(api): Extension<OpenApi>) -> impl IntoApiResponse {
Json(api)
}

#[tokio::main]
async fn main() -> Result<()> {
dotenvy::dotenv()?;
Expand Down Expand Up @@ -61,29 +73,38 @@ async fn main() -> Result<()> {
storage_bucket,
};

let app = Router::new()
let mut api = OpenApi {
info: Info {
description: Some("an example API".to_string()),
..Info::default()
},
..OpenApi::default()
};

let app = ApiRouter::new()
.route("/", get(|| async { "Hello, World!" }))
.route("/api/auth/callback/google", get(google_callback))
.route("/api/v1/organisation", post(OrganisationHandler::create))
.route(
.route("/api.json", get(serve_api))
//.route("/api/auth/callback/google", get(google_callback))
.api_route("/api/v1/organisation", post(OrganisationHandler::create))
.api_route(
"/api/v1/organisation/:id",
get(OrganisationHandler::get).delete(OrganisationHandler::delete),
)
.route(
.api_route(
"/api/v1/organisation/:id/campaign",
get(OrganisationHandler::get_campaigns).post(OrganisationHandler::create_campaign),
)
.route(
.api_route(
"/api/v1/organisation/:id/logo",
patch(OrganisationHandler::update_logo),
)
.route(
.api_route(
"/api/v1/organisation/:id/member",
get(OrganisationHandler::get_members)
.put(OrganisationHandler::update_members)
.delete(OrganisationHandler::remove_member),
)
.route(
.api_route(
"/api/v1/organisation/:id/admin",
get(OrganisationHandler::get_admins)
.put(OrganisationHandler::update_admins)
Expand All @@ -92,7 +113,10 @@ async fn main() -> Result<()> {
.with_state(state);

let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
axum::serve(listener, app).await.unwrap();
axum::serve(listener,
app.finish_api(&mut api)
.layer(Extension(api))
.into_make_service()).await.unwrap();

Ok(())
}
3 changes: 3 additions & 0 deletions backend/server/src/models/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use reqwest::Client as ReqwestClient;
use s3::Bucket;
use snowflake::SnowflakeIdGenerator;
use sqlx::{Pool, Postgres};
use aide::{OperationInput, OperationIo};

#[derive(Clone)]
pub struct AppState {
Expand All @@ -15,3 +16,5 @@ pub struct AppState {
pub snowflake_generator: SnowflakeIdGenerator,
pub storage_bucket: Bucket,
}

impl OperationInput for AppState {}
11 changes: 9 additions & 2 deletions backend/server/src/models/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use axum::response::{IntoResponse, Redirect, Response};
use axum::{async_trait, RequestPartsExt};
use axum_extra::{headers::Cookie, TypedHeader};
use serde::{Deserialize, Serialize};
use aide::{OperationInput, OperationIo};

#[derive(Deserialize, Serialize)]
pub struct AuthRequest {
Expand All @@ -30,11 +31,13 @@ impl IntoResponse for AuthRedirect {
}
}

#[derive(Deserialize, Serialize)]
#[derive(Deserialize, Serialize, OperationIo)]
#[aide(input)]
pub struct AuthUser {
pub user_id: i64,
}


#[async_trait]
impl<S> FromRequestParts<S> for AuthUser
where
Expand Down Expand Up @@ -63,7 +66,9 @@ where
}
}

#[derive(Deserialize, Serialize)]

#[derive(Deserialize, Serialize, OperationIo)]
#[aide(input)]
pub struct SuperUser {
pub user_id: i64,
}
Expand Down Expand Up @@ -105,6 +110,8 @@ where
}
}

#[derive(OperationIo)]
#[aide(input)]
pub struct OrganisationAdmin {
pub user_id: i64,
}
Expand Down
3 changes: 2 additions & 1 deletion backend/server/src/models/campaign.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use schemars::JsonSchema;

#[derive(Deserialize, Serialize, Clone, Debug)]
#[derive(Deserialize, Serialize, Clone, Debug, JsonSchema)]
pub struct Campaign {
pub id: i64,
pub name: String,
Expand Down
4 changes: 3 additions & 1 deletion backend/server/src/models/error.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
use axum::http::StatusCode;
use axum::response::{IntoResponse, Redirect, Response};
use aide::OperationIo;

/// Custom error enum for Chaos.
///
/// Handles all errors thrown by libraries (when `?` is used) alongside
/// specific errors for business logic.
#[derive(thiserror::Error, Debug)]
#[derive(thiserror::Error, Debug, OperationIo)]
#[aide(output)]
pub enum ChaosError {
#[error("Not logged in")]
NotLoggedIn,
Expand Down
9 changes: 6 additions & 3 deletions backend/server/src/models/organisation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ use snowflake::SnowflakeIdGenerator;
use sqlx::{FromRow, Pool, Postgres, Transaction};
use std::ops::DerefMut;
use uuid::Uuid;
use aide::{OperationInput, OperationIo};
use schemars::JsonSchema;

#[derive(Deserialize, Serialize, Clone, FromRow, Debug)]
pub struct Organisation {
Expand All @@ -20,12 +22,13 @@ pub struct Organisation {
pub organisation_admins: Vec<i64>,
}

#[derive(Deserialize, Serialize)]
#[derive(Deserialize, Serialize, JsonSchema)]
pub struct NewOrganisation {
pub name: String,
pub admin: i64,
}


#[derive(Deserialize, Serialize)]
pub struct OrganisationDetails {
pub id: i64,
Expand Down Expand Up @@ -53,12 +56,12 @@ pub struct MemberList {
pub members: Vec<Member>,
}

#[derive(Deserialize, Serialize)]
#[derive(Deserialize, Serialize, JsonSchema)]
pub struct AdminUpdateList {
pub members: Vec<i64>,
}

#[derive(Deserialize, Serialize)]
#[derive(Deserialize, Serialize, JsonSchema)]
pub struct AdminToRemove {
pub user_id: i64,
}
Expand Down
3 changes: 3 additions & 0 deletions backend/server/src/models/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ use axum::async_trait;
use axum::extract::{FromRef, FromRequestParts};
use axum::http::request::Parts;
use sqlx::{Postgres, Transaction};
use aide::{OperationInput, OperationIo};

#[derive(OperationIo)]
#[aide(input)]
pub struct DBTransaction<'a> {
pub tx: Transaction<'a, Postgres>,
}
Expand Down

0 comments on commit f896c6f

Please sign in to comment.