added attending endpoints, added some events endpoints

This commit is contained in:
Mitchell Marino 2023-04-14 22:17:16 -05:00
parent 9da2d2db91
commit 6a3e8508a7
5 changed files with 179 additions and 12 deletions

150
src/attending.rs Normal file
View File

@ -0,0 +1,150 @@
use axum::{extract::State, http::StatusCode, response::IntoResponse, Json};
use axum_auth::AuthBearer;
use serde_json::json;
use sqlx::query;
use crate::{
jwt::handle_token,
models::{ConfirmAttending, MarkAttending, Role},
AppState,
};
pub async fn confirm_attending(
AuthBearer(token): AuthBearer,
State(app_state): State<AppState>,
Json(body): Json<ConfirmAttending>,
) -> impl IntoResponse {
let token_data = match handle_token(token, &app_state, Role::Teacher) {
Ok(token_data) => token_data,
Err(err) => return err,
};
let result = query!(
r#"
UPDATE event_attendees
SET
confirmed = $1
WHERE event_id = $2
AND user_id = $3
AND event_id IN (SELECT id FROM events WHERE created_by = $4);
"#,
body.new_confirmed,
body.event_id,
body.user_id,
token_data.id,
)
.execute(&app_state.db_pool)
.await;
match result {
Ok(success) => {
if success.rows_affected() > 0 {
(StatusCode::OK, Json(json!({})))
} else {
(
StatusCode::NOT_FOUND,
Json(json!({"error": "no record matched the parameters."})),
)
}
}
Err(err) => (
StatusCode::INTERNAL_SERVER_ERROR,
Json(json!({
"error": format!("Unknown error confirming attendence: {:?}", err)
})),
),
}
.into_response()
}
pub async fn mark_attending(
AuthBearer(token): AuthBearer,
State(app_state): State<AppState>,
Json(body): Json<MarkAttending>,
) -> impl IntoResponse {
let token_data = match handle_token(token, &app_state, Role::Student) {
Ok(token_data) => token_data,
Err(err) => return err,
};
let result = query!(
r#"
INSERT INTO event_attendees
(event_id, user_id)
VALUES
($1, $2)
"#,
body.event_id,
token_data.id,
)
.execute(&app_state.db_pool)
.await;
match result {
Ok(_) => (StatusCode::OK, Json(json!({}))),
Err(err) => {
// See if we get an error for marking an already marked.
if let sqlx::Error::Database(database_err) = &err {
if let Some(err_code) = database_err.code() {
if err_code == "23505" {
return (StatusCode::OK, Json(json!({}))).into_response();
}
}
}
(
StatusCode::INTERNAL_SERVER_ERROR,
Json(json!({
"error": format!("Unknown error marking attendance: {:?}", err)
})),
)
}
}
.into_response()
}
pub async fn unmark_attending(
AuthBearer(token): AuthBearer,
State(app_state): State<AppState>,
Json(body): Json<MarkAttending>,
) -> impl IntoResponse {
let token_data = match handle_token(token, &app_state, Role::Student) {
Ok(token_data) => token_data,
Err(err) => return err,
};
let result = query!(
r#"
DELETE FROM event_attendees
WHERE
event_id = $1 AND
user_id = $2
"#,
body.event_id,
token_data.id,
)
.execute(&app_state.db_pool)
.await;
match result {
Ok(_) => (StatusCode::OK, Json(json!({}))),
Err(err) => {
// See if we get an error for marking an already marked.
if let sqlx::Error::Database(database_err) = &err {
if let Some(err_code) = database_err.code() {
if err_code == "23505" {
return (StatusCode::OK, Json(json!({}))).into_response();
}
}
}
(
StatusCode::INTERNAL_SERVER_ERROR,
Json(json!({
"error": format!("Unknown error unmarking attendance: {:?}", err)
})),
)
}
}
.into_response()
}

View File

@ -55,7 +55,7 @@ LIMIT
Err(err) => ( Err(err) => (
StatusCode::INTERNAL_SERVER_ERROR, StatusCode::INTERNAL_SERVER_ERROR,
Json(json!({ Json(json!({
"error": format!("Unknown error getting events: {}", err) "error": format!("Unknown error getting events: {:?}", err)
})), })),
), ),
} }
@ -103,7 +103,7 @@ LIMIT
Err(err) => ( Err(err) => (
StatusCode::INTERNAL_SERVER_ERROR, StatusCode::INTERNAL_SERVER_ERROR,
Json(json!({ Json(json!({
"error": format!("Unknown error getting events: {}", err) "error": format!("Unknown error getting events: {:?}", err)
})), })),
), ),
} }
@ -158,7 +158,7 @@ pub async fn get_event(
( (
StatusCode::INTERNAL_SERVER_ERROR, StatusCode::INTERNAL_SERVER_ERROR,
Json(json!({ Json(json!({
"error": format!("Unknown error getting event: {}", err) "error": format!("Unknown error getting event: {:?}", err)
})), })),
) )
} }
@ -199,7 +199,7 @@ pub async fn create_event(
Err(err) => ( Err(err) => (
StatusCode::BAD_REQUEST, StatusCode::BAD_REQUEST,
Json(json!({ Json(json!({
"error": format!("Unknown error creating event: {}", err) "error": format!("Unknown error creating event: {:?}", err)
})), })),
) )
.into_response(), .into_response(),

View File

@ -1,3 +1,4 @@
mod attending;
mod events; mod events;
mod jwt; mod jwt;
mod models; mod models;
@ -5,7 +6,7 @@ mod report;
mod user; mod user;
use axum::{ use axum::{
routing::{get, post}, routing::{delete, get, post, put},
Router, Router,
}; };
use jsonwebtoken::{DecodingKey, EncodingKey}; use jsonwebtoken::{DecodingKey, EncodingKey};
@ -38,15 +39,17 @@ async fn main() {
.await .await
.expect("could not connect to database_url"); .expect("could not connect to database_url");
// build our application with a route
let app = Router::new() let app = Router::new()
.route("/", get(root)) .route("/", get(root))
.route("/user/signup", post(signup)) .route("/user/signup", post(signup))
.route("/user/signin", post(signin)) .route("/user/signin", post(signin))
.route("/event", post(events::create_event).get(events::get_event)) .route("/event", get(events::get_event).post(events::create_event))
.route("/event/preview", get(events::get_events_preview)) .route("/event/preview", get(events::get_events_preview))
.route("/event/all", get(events::get_all_events)) .route("/event/future", get(events::get_all_events))
.route("/report", get(report::get_report)) .route("/report", get(report::get_report))
.route("/attending/confirm", put(attending::confirm_attending))
.route("/attending/mark", post(attending::mark_attending))
.route("/attending/unmark", delete(attending::unmark_attending))
.with_state(AppState { .with_state(AppState {
db_pool, db_pool,
jwt_encode, jwt_encode,

View File

@ -69,7 +69,7 @@ pub struct Signup {
#[derive( #[derive(
sqlx::Type, Copy, Clone, Hash, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, sqlx::Type, Copy, Clone, Hash, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize,
)] )]
// #[sqlx(type_name = "role", rename_all = "snake_case")] #[sqlx(type_name = "role", rename_all = "snake_case")]
pub enum Role { pub enum Role {
Student, Student,
Teacher, Teacher,
@ -89,6 +89,20 @@ pub struct ReportQuery {
pub grade: Option<i32>, pub grade: Option<i32>,
} }
/// The model for the confirm attending request.
#[derive(Copy, Clone, Hash, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct ConfirmAttending {
pub new_confirmed: bool,
pub event_id: i32,
pub user_id: i32,
}
/// The model for the mark attending request.
#[derive(Copy, Clone, Hash, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct MarkAttending {
pub event_id: i32,
}
/// The claims for the JWT. /// The claims for the JWT.
#[derive(Clone, Serialize, Deserialize, Debug, Hash)] #[derive(Clone, Serialize, Deserialize, Debug, Hash)]
pub struct Claims { pub struct Claims {

View File

@ -49,7 +49,7 @@ pub async fn signup(
( (
StatusCode::INTERNAL_SERVER_ERROR, StatusCode::INTERNAL_SERVER_ERROR,
Json(json!({ Json(json!({
"error": format!("Unknown error signing up: {}", err) "error": format!("Unknown error signing up: {:?}", err)
})), })),
) )
} }
@ -93,7 +93,7 @@ pub async fn signin(
StatusCode::INTERNAL_SERVER_ERROR, StatusCode::INTERNAL_SERVER_ERROR,
Json(json!({ Json(json!({
"error": "error":
format!("Unknown error signing in when creating JWT: {}", err) format!("Unknown error signing in when creating JWT: {:?}", err)
})), })),
) )
} }
@ -113,7 +113,7 @@ pub async fn signin(
return ( return (
StatusCode::INTERNAL_SERVER_ERROR, StatusCode::INTERNAL_SERVER_ERROR,
Json(json!({ Json(json!({
"error": format!("Unknown error signing in: {}", err) "error": format!("Unknown error signing in: {:?}", err)
})), })),
) )
} }