Skip to content

Commit

Permalink
Chaos 502 application crud (#503)
Browse files Browse the repository at this point in the history
* feat: added model file for application; added create method. fix: changed schema for application_role, fixed id type for role.

* attempt to implement get for application; added additional fields for role response struct

* added additional field to Application response type

* feat: added get methods for application in model

* fix pool usage in model/role, added set_status methods to application, patched API routes for get_all routes

* added handlers for application; implemented Auth for ApplicationAdmin

* added routes for applications in main; implement more handlers; moved some application handler methods to other more appropriate handlers

* change `*Admin` `FromRequest` implementations to use HashMap of path variables

* make 'Pending' the default Application status

* return user info with `ApplicationDetails`

---------

Co-authored-by: Alex_Miao_WSL <[email protected]>
Co-authored-by: Kavika <[email protected]>
  • Loading branch information
3 people authored Aug 2, 2024
1 parent ba6fb2b commit f140dd6
Show file tree
Hide file tree
Showing 13 changed files with 615 additions and 29 deletions.
8 changes: 4 additions & 4 deletions backend/migrations/20240406031915_create_applications.sql
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ CREATE TABLE applications (
id BIGINT PRIMARY KEY,
campaign_id BIGINT NOT NULL,
user_id BIGINT NOT NULL,
status application_status NOT NULL,
private_status application_status NOT NULL,
status application_status NOT NULL DEFAULT 'Pending',
private_status application_status NOT NULL DEFAULT 'Pending',
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP NOT NULL,
updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP NOT NULL,
CONSTRAINT FK_applications_campaigns
Expand All @@ -22,8 +22,8 @@ CREATE TABLE applications (

CREATE TABLE application_roles (
id BIGSERIAL PRIMARY KEY,
application_id INTEGER NOT NULL,
campaign_role_id INTEGER NOT NULL,
application_id BIGINT NOT NULL,
campaign_role_id BIGINT NOT NULL,
CONSTRAINT FK_application_roles_applications
FOREIGN KEY(application_id)
REFERENCES applications(id)
Expand Down
51 changes: 51 additions & 0 deletions backend/server/src/handler/application.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
use crate::models::app::AppState;
use crate::models::application::{Application, ApplicationStatus};
use crate::models::auth::{AuthUser, ApplicationAdmin};
use crate::models::error::ChaosError;
use crate::models::transaction::DBTransaction;
use axum::extract::{Json, Path, State};
use axum::http::StatusCode;
use axum::response::IntoResponse;

pub struct ApplicationHandler;

impl ApplicationHandler {
pub async fn get(
Path(application_id): Path<i64>,
_admin: ApplicationAdmin,
mut transaction: DBTransaction<'_>,
) -> Result<impl IntoResponse, ChaosError> {
let application = Application::get(application_id, &mut transaction.tx).await?;
transaction.tx.commit().await?;
Ok((StatusCode::OK, Json(application)))
}

pub async fn set_status(
State(state): State<AppState>,
Path(application_id): Path<i64>,
_admin: ApplicationAdmin,
Json(data): Json<ApplicationStatus>,
) -> Result<impl IntoResponse, ChaosError> {
Application::set_status(application_id, data, &state.db).await?;
Ok((StatusCode::OK, "Status successfully updated"))
}

pub async fn set_private_status(
State(state): State<AppState>,
Path(application_id): Path<i64>,
_admin: ApplicationAdmin,
Json(data): Json<ApplicationStatus>,
) -> Result<impl IntoResponse, ChaosError> {
Application::set_private_status(application_id, data, &state.db).await?;
Ok((StatusCode::OK, "Private Status successfully updated"))
}

pub async fn get_from_curr_user(
user: AuthUser,
mut transaction: DBTransaction<'_>,
) -> Result<impl IntoResponse, ChaosError> {
let applications = Application::get_from_user_id(user.user_id, &mut transaction.tx).await?;
transaction.tx.commit().await?;
Ok((StatusCode::OK, Json(applications)))
}
}
25 changes: 25 additions & 0 deletions backend/server/src/handler/campaign.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
use crate::models;
use crate::models::app::AppState;
use crate::models::application::Application;
use crate::models::application::NewApplication;
use crate::models::auth::AuthUser;
use crate::models::auth::CampaignAdmin;
use crate::models::campaign::Campaign;
use crate::models::error::ChaosError;
use crate::models::role::{Role, RoleUpdate};
use crate::models::transaction::DBTransaction;
use axum::extract::{Json, Path, State};
use axum::http::StatusCode;
use axum::response::IntoResponse;
Expand Down Expand Up @@ -75,4 +78,26 @@ impl CampaignHandler {

Ok((StatusCode::OK, Json(roles)))
}

pub async fn create_application(
State(state): State<AppState>,
Path(id): Path<i64>,
user: AuthUser,
mut transaction: DBTransaction<'_>,
Json(data): Json<NewApplication>,
) -> Result<impl IntoResponse, ChaosError> {
Application::create(id, user.user_id, data, state.snowflake_generator, &mut transaction.tx).await?;
transaction.tx.commit().await?;
Ok((StatusCode::OK, "Successfully created application"))
}

pub async fn get_applications(
Path(id): Path<i64>,
_admin: CampaignAdmin,
mut transaction: DBTransaction<'_>,
) -> Result<impl IntoResponse, ChaosError> {
let applications = Application::get_from_campaign_id(id, &mut transaction.tx).await?;
transaction.tx.commit().await?;
Ok((StatusCode::OK, Json(applications)))
}
}
1 change: 1 addition & 0 deletions backend/server/src/handler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ pub mod auth;
pub mod campaign;
pub mod organisation;
pub mod role;
pub mod application;
12 changes: 12 additions & 0 deletions backend/server/src/handler/role.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use crate::models::app::AppState;
use crate::models::application::Application;
use crate::models::auth::{AuthUser, RoleAdmin};
use crate::models::error::ChaosError;
use crate::models::role::{Role, RoleUpdate};
use axum::extract::{Json, Path, State};
use crate::models::transaction::DBTransaction;
use axum::http::StatusCode;
use axum::response::IntoResponse;

Expand Down Expand Up @@ -36,4 +38,14 @@ impl RoleHandler {
Role::update(id, data, &state.db).await?;
Ok((StatusCode::OK, "Successfully updated role"))
}

pub async fn get_applications(
Path(id): Path<i64>,
_admin: RoleAdmin,
mut transaction: DBTransaction<'_>,
) -> Result<impl IntoResponse, ChaosError> {
let applications = Application::get_from_role_id(id, &mut transaction.tx).await?;
transaction.tx.commit().await?;
Ok((StatusCode::OK, Json(applications)))
}
}
45 changes: 34 additions & 11 deletions backend/server/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::handler::auth::google_callback;
use crate::handler::campaign::CampaignHandler;
use crate::handler::organisation::OrganisationHandler;
use crate::handler::application::ApplicationHandler;
use crate::models::storage::Storage;
use anyhow::Result;
use axum::routing::{get, patch, post};
Expand Down Expand Up @@ -66,56 +67,78 @@ async fn main() -> Result<()> {
let app = Router::new()
.route("/", get(|| async { "Hello, World!" }))
.route("/api/auth/callback/google", get(google_callback))
.route(
"/api/v1/user/applications",
get(ApplicationHandler::get_from_curr_user),
)
.route("/api/v1/organisation", post(OrganisationHandler::create))
.route(
"/api/v1/organisation/:id",
"/api/v1/organisation/:organisation_id",
get(OrganisationHandler::get).delete(OrganisationHandler::delete),
)
.route(
"/api/v1/organisation/:id/campaign",
get(OrganisationHandler::get_campaigns).post(OrganisationHandler::create_campaign),
"/api/v1/organisation/:organisation_id/campaign",
post(OrganisationHandler::create_campaign),
)
.route(
"/api/v1/organisation/:id/logo",
"/api/v1/organisation/:organisation_id/campaigns",
get(OrganisationHandler::get_campaigns),
)
.route(
"/api/v1/organisation/:organisation_id/logo",
patch(OrganisationHandler::update_logo),
)
.route(
"/api/v1/organisation/:id/member",
"/api/v1/organisation/:organisation_id/member",
get(OrganisationHandler::get_members)
.put(OrganisationHandler::update_members)
.delete(OrganisationHandler::remove_member),
)
.route(
"/api/v1/organisation/:id/admin",
"/api/v1/organisation/:organisation_id/admin",
get(OrganisationHandler::get_admins)
.put(OrganisationHandler::update_admins)
.delete(OrganisationHandler::remove_admin),
)
.route(
"/api/v1/campaign/:id/role",
"/api/v1/campaign/:campaign_id/role",
post(CampaignHandler::create_role),
)
.route(
"/api/v1/campaign/:id/roles",
"/api/v1/campaign/:campaign_id/roles",
get(CampaignHandler::get_roles),
)
.route(
"/api/v1/role/:id",
"/api/v1/campaign/:campaign_id/applications",
get(CampaignHandler::get_applications),
)
.route(
"/api/v1/role/:role_id",
get(RoleHandler::get)
.put(RoleHandler::update)
.delete(RoleHandler::delete),
)
.route(
"/api/v1/campaign/:id",
"/api/v1/role/:role_id/applications",
get(RoleHandler::get_applications)
)
.route(
"/api/v1/campaign/:campaign_id",
get(CampaignHandler::get)
.put(CampaignHandler::update)
.delete(CampaignHandler::delete),
)
.route("/api/v1/campaign", get(CampaignHandler::get_all))
.route(
"/api/v1/campaign/:id/banner",
"/api/v1/campaign/:campaign_id/banner",
patch(CampaignHandler::update_banner),
)
.route("api/v1/campaign/:campaign_id/application",
post(CampaignHandler::create_application)
)
.route("api/v1/application/:application_id", get(ApplicationHandler::get))
.route("api/v1/application/:application_id/status", patch(ApplicationHandler::set_status))
.route("api/v1/application/:application_id/private", patch(ApplicationHandler::set_private_status))
.with_state(state);

let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
Expand Down
Loading

0 comments on commit f140dd6

Please sign in to comment.