Skip to content

Commit

Permalink
User CRUD (#493)
Browse files Browse the repository at this point in the history
* added get_username for all users logged in

* updted user crud

* efficient user get fucntion

* finished user but no testing

* finished user crud

* docker working file

* set users `created_at` and `updated_at` to not null

* set optional fields to `Option` in `User` struct

* fix `query_as` with custom enums

* finished user crud

* changed User CRUD to use handler struct

* move `User` DB logic to `models::User` file

* add pronouns and gender to `User`

* remove TODO comment

* fixed errors and warnings with adding new user fields

---------

Co-authored-by: Alex_Miao_WSL <yuan_sen.miao@student.unsw.edu.au>
Co-authored-by: Kavika <kbpalletenne@gmail.com>
  • Loading branch information
3 people authored Aug 2, 2024
1 parent f140dd6 commit 45c8324
Show file tree
Hide file tree
Showing 8 changed files with 255 additions and 15 deletions.
2 changes: 2 additions & 0 deletions backend/migrations/20240406023149_create_users.sql
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ CREATE TABLE users (
email TEXT NOT NULL UNIQUE,
zid TEXT,
name TEXT NOT NULL,
pronouns TEXT NOT NULL,
gender TEXT NOT NULL,
degree_name TEXT,
degree_starting_year INTEGER,
role user_role NOT NULL,
Expand Down
3 changes: 2 additions & 1 deletion backend/server/src/handler/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
pub mod auth;
pub mod user;
pub mod campaign;
pub mod organisation;
pub mod role;
pub mod application;
pub mod application;
77 changes: 77 additions & 0 deletions backend/server/src/handler/user.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
use crate::models::app::AppState;
use crate::models::auth::AuthUser;
use crate::models::error::ChaosError;
use axum::extract::{Json, State};
use axum::http::StatusCode;
use axum::response::IntoResponse;
use crate::models::user::{User, UserDegree, UserGender, UserName, UserPronouns, UserZid};

pub struct UserHandler;

impl UserHandler {
pub async fn get(
State(state): State<AppState>,
user: AuthUser,
) -> Result<impl IntoResponse, ChaosError> {
let user = User::get(user.user_id, &state.db).await?;
Ok((StatusCode::OK, Json(user)))
}

pub async fn update_name(
State(state): State<AppState>,
user: AuthUser,
Json(request_body): Json<UserName>,
) -> Result<impl IntoResponse, ChaosError> {
User::update_name(user.user_id, request_body.name, &state.db).await?;

Ok((StatusCode::OK, "Updated username"))
}

pub async fn update_pronouns(
State(state): State<AppState>,
user: AuthUser,
Json(request_body): Json<UserPronouns>,
) -> Result<impl IntoResponse, ChaosError> {
User::update_pronouns(user.user_id, request_body.pronouns, &state.db).await?;

Ok((StatusCode::OK, "Updated pronouns"))
}

pub async fn update_gender(
State(state): State<AppState>,
user: AuthUser,
Json(request_body): Json<UserGender>,
) -> Result<impl IntoResponse, ChaosError> {
User::update_gender(user.user_id, request_body.gender, &state.db).await?;

Ok((StatusCode::OK, "Updated gender"))
}

pub async fn update_zid(
State(state): State<AppState>,
user: AuthUser,
Json(request_body): Json<UserZid>,
) -> Result<impl IntoResponse, ChaosError> {
User::update_zid(user.user_id, request_body.zid, &state.db).await?;

Ok((StatusCode::OK, "Updated zid"))
}

pub async fn update_degree(
State(state): State<AppState>,
user: AuthUser,
Json(request_body): Json<UserDegree>,
) -> Result<impl IntoResponse, ChaosError> {
User::update_degree(
user.user_id,
request_body.degree_name,
request_body.degree_starting_year,
&state.db
)
.await?;

Ok((StatusCode::OK, "Updated user degree"))
}
}


7 changes: 7 additions & 0 deletions backend/server/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::handler::auth::google_callback;
use handler::user::UserHandler;
use crate::handler::campaign::CampaignHandler;
use crate::handler::organisation::OrganisationHandler;
use crate::handler::application::ApplicationHandler;
Expand Down Expand Up @@ -67,6 +68,12 @@ 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", get(UserHandler::get))
.route("/api/v1/user/name", patch(UserHandler::update_name))
.route("/api/v1/user/pronouns", patch(UserHandler::update_pronouns))
.route("/api/v1/user/gender", patch(UserHandler::update_gender))
.route("/api/v1/user/zid", patch(UserHandler::update_zid))
.route("/api/v1/user/degree", patch(UserHandler::update_degree))
.route(
"/api/v1/user/applications",
get(ApplicationHandler::get_from_curr_user),
Expand Down
34 changes: 24 additions & 10 deletions backend/server/src/models/application.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize};
use snowflake::SnowflakeIdGenerator;
use sqlx::{FromRow, Pool, Postgres, Transaction};
use std::ops::DerefMut;
use crate::models::user::User;
use crate::models::user::UserDetails;

#[derive(Deserialize, Serialize, Clone, FromRow, Debug)]
pub struct Application {
Expand Down Expand Up @@ -38,7 +38,7 @@ pub struct NewApplication {
pub struct ApplicationDetails {
pub id: i64,
pub campaign_id: i64,
pub user: User,
pub user: UserDetails,
pub status: ApplicationStatus,
pub private_status: ApplicationStatus,
pub applied_roles: Vec<ApplicationAppliedRoleDetails>
Expand All @@ -52,6 +52,8 @@ pub struct ApplicationData {
pub user_email: String,
pub user_zid: Option<String>,
pub user_name: String,
pub user_pronouns: String,
pub user_gender: String,
pub user_degree_name: Option<String>,
pub user_degree_starting_year: Option<i32>,
pub status: ApplicationStatus,
Expand Down Expand Up @@ -122,7 +124,8 @@ impl Application {
"
SELECT a.id AS id, campaign_id, user_id, status AS \"status: ApplicationStatus\",
private_status AS \"private_status: ApplicationStatus\", u.email AS user_email,
u.zid AS user_zid, u.name AS user_name, u.degree_name AS user_degree_name,
u.zid AS user_zid, u.name AS user_name, u.gender AS user_gender,
u.pronouns AS user_pronouns, u.degree_name AS user_degree_name,
u.degree_starting_year AS user_degree_starting_year
FROM applications a LEFT JOIN users u ON u.id = a.user_id
WHERE a.id = $1
Expand Down Expand Up @@ -153,11 +156,13 @@ impl Application {
status: application_data.status,
private_status: application_data.private_status,
applied_roles,
user: User {
user: UserDetails {
id: application_data.user_id,
email: application_data.user_email,
zid: application_data.user_zid,
name: application_data.user_name,
pronouns: application_data.user_pronouns,
gender: application_data.user_gender,
degree_name: application_data.user_degree_name,
degree_starting_year: application_data.user_degree_starting_year,
},
Expand All @@ -176,7 +181,8 @@ impl Application {
"
SELECT a.id AS id, campaign_id, user_id, status AS \"status: ApplicationStatus\",
private_status AS \"private_status: ApplicationStatus\", u.email AS user_email,
u.zid AS user_zid, u.name AS user_name, u.degree_name AS user_degree_name,
u.zid AS user_zid, u.name AS user_name, u.gender AS user_gender,
u.pronouns AS user_pronouns, u.degree_name AS user_degree_name,
u.degree_starting_year AS user_degree_starting_year
FROM applications a LEFT JOIN users u ON u.id = a.user_id LEFT JOIN application_roles ar on ar.application_id = a.id
WHERE ar.id = $1
Expand Down Expand Up @@ -208,11 +214,13 @@ impl Application {
status: application_data.status,
private_status: application_data.private_status,
applied_roles,
user: User {
user: UserDetails {
id: application_data.user_id,
email: application_data.user_email,
zid: application_data.user_zid,
name: application_data.user_name,
pronouns: application_data.user_pronouns,
gender: application_data.user_gender,
degree_name: application_data.user_degree_name,
degree_starting_year: application_data.user_degree_starting_year,
},
Expand All @@ -234,7 +242,8 @@ impl Application {
"
SELECT a.id AS id, campaign_id, user_id, status AS \"status: ApplicationStatus\",
private_status AS \"private_status: ApplicationStatus\", u.email AS user_email,
u.zid AS user_zid, u.name AS user_name, u.degree_name AS user_degree_name,
u.zid AS user_zid, u.name AS user_name, u.gender AS user_gender,
u.pronouns AS user_pronouns, u.degree_name AS user_degree_name,
u.degree_starting_year AS user_degree_starting_year
FROM applications a LEFT JOIN users u ON u.id = a.user_id
WHERE a.campaign_id = $1
Expand Down Expand Up @@ -266,11 +275,13 @@ impl Application {
status: application_data.status,
private_status: application_data.private_status,
applied_roles,
user: User {
user: UserDetails {
id: application_data.user_id,
email: application_data.user_email,
zid: application_data.user_zid,
name: application_data.user_name,
pronouns: application_data.user_pronouns,
gender: application_data.user_gender,
degree_name: application_data.user_degree_name,
degree_starting_year: application_data.user_degree_starting_year,
},
Expand All @@ -292,7 +303,8 @@ impl Application {
"
SELECT a.id AS id, campaign_id, user_id, status AS \"status: ApplicationStatus\",
private_status AS \"private_status: ApplicationStatus\", u.email AS user_email,
u.zid AS user_zid, u.name AS user_name, u.degree_name AS user_degree_name,
u.zid AS user_zid, u.name AS user_name, u.gender AS user_gender,
u.pronouns AS user_pronouns, u.degree_name AS user_degree_name,
u.degree_starting_year AS user_degree_starting_year
FROM applications a LEFT JOIN users u ON u.id = a.user_id
WHERE a.user_id = $1
Expand Down Expand Up @@ -324,11 +336,13 @@ impl Application {
status: application_data.status,
private_status: application_data.private_status,
applied_roles,
user: User {
user: UserDetails {
id: application_data.user_id,
email: application_data.user_email,
zid: application_data.user_zid,
name: application_data.user_name,
pronouns: application_data.user_pronouns,
gender: application_data.user_gender,
degree_name: application_data.user_degree_name,
degree_starting_year: application_data.user_degree_starting_year,
},
Expand Down
3 changes: 3 additions & 0 deletions backend/server/src/models/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use axum::{async_trait, RequestPartsExt};
use axum_extra::{headers::Cookie, TypedHeader};
use serde::{Deserialize, Serialize};

// tells the web framework how to take the url query params they will have
#[derive(Deserialize, Serialize)]
pub struct AuthRequest {
pub code: String,
Expand All @@ -39,6 +40,8 @@ pub struct AuthUser {
pub user_id: i64,
}

// extractor - takes a request, and we define what we do to it,
// returns the struct of the type defined
#[async_trait]
impl<S> FromRequestParts<S> for AuthUser
where
Expand Down
2 changes: 1 addition & 1 deletion backend/server/src/models/storage.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::models::error::ChaosError;
use s3::creds::Credentials;
use s3::{Bucket, BucketConfiguration, Region};
use s3::{Bucket, Region};
use std::env;

pub struct Storage;
Expand Down
Loading

0 comments on commit 45c8324

Please sign in to comment.