Compare commits
5 Commits
bf84ff6e33
...
f5779ec55f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f5779ec55f | ||
|
|
8a3eb8027b | ||
|
|
3c6e6c8656 | ||
|
|
b038811b58 | ||
|
|
8b704120d2 |
146
src/main.rs
146
src/main.rs
@ -1,6 +1,7 @@
|
||||
// Webserver
|
||||
#[macro_use] extern crate rocket;
|
||||
|
||||
use entities::members::ActiveModel;
|
||||
use rocket::{State, Error};
|
||||
use rocket::response::status;
|
||||
use rocket::serde::{Serialize, Deserialize, json::Json};
|
||||
@ -20,6 +21,16 @@ struct RfidCard {
|
||||
cardComment: String
|
||||
}
|
||||
|
||||
// Implement `.into()` to auto map values from the database model to the local struct
|
||||
impl From<<entities::rfid_cards::Entity as sea_orm::EntityTrait>::Model> for RfidCard {
|
||||
fn from(rfid_card: <entities::rfid_cards::Entity as sea_orm::EntityTrait>::Model) -> RfidCard {
|
||||
RfidCard {
|
||||
cardId: rfid_card.card_id,
|
||||
cardComment: rfid_card.card_comment,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct Member {
|
||||
id: i32,
|
||||
@ -32,6 +43,51 @@ struct Member {
|
||||
rfidCards: Vec<RfidCard>
|
||||
}
|
||||
|
||||
// Create the `.into()` functionality to auto map values from the database model to the local struct
|
||||
// Don't be scared by the long model name, I typed `Members::Model` and applied the auto fix vscode suggested
|
||||
impl From<entities::members::Model> for Member {
|
||||
fn from(member: entities::members::Model) -> Member {
|
||||
Member {
|
||||
id: member.id,
|
||||
ntnuUsername: member.ntnu_username,
|
||||
firstName: member.first_name,
|
||||
lastName: member.last_name,
|
||||
email: member.email,
|
||||
balance: member.balance,
|
||||
imagePreference: member.image_preference,
|
||||
rfidCards: Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Implement DB Member Model -> MinimalMember
|
||||
impl From<entities::members::Model> for MinimalMember {
|
||||
fn from(member: entities::members::Model) -> MinimalMember {
|
||||
MinimalMember {
|
||||
id: member.id,
|
||||
ntnuUsername: member.ntnu_username,
|
||||
firstName: member.first_name,
|
||||
lastName: member.last_name,
|
||||
email: member.email,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create the functionality to create a database model member from the local struct model member
|
||||
impl Into<entities::members::ActiveModel> for rocket::serde::json::Json<MinimalMemberWithoutId> {
|
||||
fn into(self) -> entities::members::ActiveModel {
|
||||
entities::members::ActiveModel {
|
||||
ntnu_username: ActiveValue::Set(self.ntnuUsername.to_owned()),
|
||||
first_name: ActiveValue::Set(self.firstName.to_owned()),
|
||||
last_name: ActiveValue::Set(self.lastName.to_owned()),
|
||||
email: ActiveValue::Set(self.email.to_owned()),
|
||||
balance: ActiveValue::Set(0),
|
||||
image_preference: ActiveValue::Set("".to_string()),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct MinimalMember {
|
||||
id: i32,
|
||||
@ -49,6 +105,11 @@ struct MinimalMemberWithoutId {
|
||||
email: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct MultipleMembersStruct {
|
||||
members: Vec<Member>,
|
||||
}
|
||||
|
||||
#[derive(Responder)]
|
||||
#[response(status = 500, content_type = "text/plain")]
|
||||
struct ErrorResponder {
|
||||
@ -76,14 +137,47 @@ fn index() -> &'static str {
|
||||
"Hello, world!\nNothing useful is served here."
|
||||
}
|
||||
|
||||
#[post("/member", data = "<minimalMemberWithoutId>")]
|
||||
async fn add_member(db: &State<DatabaseConnection>, minimalMemberWithoutId: Json<MinimalMemberWithoutId>) -> Result<Json<MinimalMember>, ErrorResponder> {
|
||||
#[get("/members")]
|
||||
async fn get_members(db: &State<DatabaseConnection>) -> Result<Json<MultipleMembersStruct>, ErrorResponder> {
|
||||
let db = db as &DatabaseConnection;
|
||||
|
||||
// Get a list of all members from the database
|
||||
let members = Members::find().all(db).await?;
|
||||
|
||||
// Convert this vector from the database model to the local struct model
|
||||
let mut members: Vec<Member> = members.into_iter().map(Member::from).collect();
|
||||
|
||||
// Fetch the member's RFID card
|
||||
for member in &mut members {
|
||||
// Look up all RFID cards associated with this member
|
||||
let rfid_cards = RfidCards::find()
|
||||
.filter(rfid_cards::Column::MemberId.eq(member.id))
|
||||
.all(db)
|
||||
.await?;
|
||||
|
||||
// Convert the RFID cards vector from the database model to the local struct model
|
||||
let rfid_cards: Vec<RfidCard> = rfid_cards.into_iter().map(RfidCard::from).collect();
|
||||
|
||||
// Add these cards to the member's rfidCards field
|
||||
member.rfidCards = rfid_cards;
|
||||
}
|
||||
|
||||
|
||||
// Put this into the `MultipleMembersStruct` so that the aquired JSON will look as the API demands
|
||||
let output = MultipleMembersStruct { members };
|
||||
|
||||
// Return the output
|
||||
Ok(Json(output))
|
||||
}
|
||||
|
||||
#[post("/member", data = "<minimal_member_without_id>")]
|
||||
async fn add_member(db: &State<DatabaseConnection>, minimal_member_without_id: Json<MinimalMemberWithoutId>) -> Result<Json<MinimalMember>, ErrorResponder> {
|
||||
// Grab the database connection
|
||||
let db = db as &DatabaseConnection;
|
||||
|
||||
// Check if a member with the same NTNU username already exists
|
||||
let matching_member: Option<members::Model> = Members::find() // Find a member in the "Members" table
|
||||
.filter(members::Column::NtnuUsername.eq(minimalMemberWithoutId.ntnuUsername.to_owned())) // Filter by the provided username in the NtnuUsername column
|
||||
.filter(members::Column::NtnuUsername.eq(minimal_member_without_id.ntnuUsername.to_owned())) // Filter by the provided username in the NtnuUsername column
|
||||
.one(db) // We only care about one result
|
||||
.await?; // Wait for the result
|
||||
|
||||
@ -97,15 +191,7 @@ async fn add_member(db: &State<DatabaseConnection>, minimalMemberWithoutId: Json
|
||||
}
|
||||
|
||||
// Create the new member info from the provided JSON
|
||||
let new_member = members::ActiveModel {
|
||||
ntnu_username: ActiveValue::Set(minimalMemberWithoutId.ntnuUsername.to_owned()),
|
||||
first_name: ActiveValue::Set(minimalMemberWithoutId.firstName.to_owned()),
|
||||
last_name: ActiveValue::Set(minimalMemberWithoutId.lastName.to_owned()),
|
||||
email: ActiveValue::Set(minimalMemberWithoutId.email.to_owned()),
|
||||
balance: ActiveValue::Set(0),
|
||||
image_preference: ActiveValue::Set("Money".to_string()),
|
||||
..Default::default()
|
||||
};
|
||||
let new_member: members::ActiveModel = minimal_member_without_id.into();
|
||||
|
||||
// Add the new member to the database
|
||||
let res = Members::insert(new_member).exec(db).await?;
|
||||
@ -124,13 +210,7 @@ async fn add_member(db: &State<DatabaseConnection>, minimalMemberWithoutId: Json
|
||||
}
|
||||
|
||||
// Put the fetched info into a minimal member for returning
|
||||
let member = MinimalMember {
|
||||
id: new_member.id,
|
||||
ntnuUsername: new_member.ntnu_username,
|
||||
firstName: new_member.first_name,
|
||||
lastName: new_member.last_name,
|
||||
email: new_member.email,
|
||||
};
|
||||
let member: MinimalMember = new_member.into();
|
||||
|
||||
Ok(Json(member))
|
||||
}
|
||||
@ -139,34 +219,27 @@ async fn add_member(db: &State<DatabaseConnection>, minimalMemberWithoutId: Json
|
||||
async fn get_member_by_id(db: &State<DatabaseConnection>, memberId: i32) -> Result<Json<Member>, ErrorResponder> {
|
||||
let db = db as &DatabaseConnection;
|
||||
|
||||
// Create an empty variable to store the resulting member info
|
||||
let database_member;
|
||||
// Search the database for the member based on the ID
|
||||
match Members::find_by_id(memberId).one(db).await? {
|
||||
Some(model) => database_member = model,
|
||||
Some(model) => database_member = model, // If the member is found, add the info to the previously created variable
|
||||
None => {
|
||||
return Err(
|
||||
ErrorResponder {
|
||||
message: format!("Failed to fetch member by ID. memberId: {}", memberId)
|
||||
message: format!("Failed to fetch member by ID. memberId: {}", memberId) // If it is not found return with this error
|
||||
}
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
// Get the member's RFID cards
|
||||
let member_rfid_cards: Vec<rfid_cards::Model> = database_member.find_related(RfidCards).all(db).await?;
|
||||
let rfids: Vec<RfidCard> = member_rfid_cards.iter().map(|model| RfidCard {
|
||||
cardId: model.card_id.clone(),
|
||||
cardComment: model.card_comment.clone()
|
||||
}).collect();
|
||||
let rfids: Vec<RfidCard> = member_rfid_cards.into_iter().map(RfidCard::from).collect();
|
||||
|
||||
let member = Member {
|
||||
id: database_member.id,
|
||||
ntnuUsername: database_member.ntnu_username,
|
||||
firstName: database_member.first_name,
|
||||
lastName: database_member.last_name,
|
||||
email: database_member.email,
|
||||
balance: database_member.balance,
|
||||
imagePreference: database_member.image_preference,
|
||||
rfidCards: rfids
|
||||
};
|
||||
// Create a member from the database model and append the RFID cards
|
||||
let mut member: Member = database_member.into();
|
||||
member.rfidCards = rfids;
|
||||
|
||||
Ok(Json(member))
|
||||
}
|
||||
@ -183,6 +256,7 @@ async fn rocket() -> _ {
|
||||
.mount("/", routes![
|
||||
index,
|
||||
get_member_by_id,
|
||||
add_member
|
||||
add_member,
|
||||
get_members
|
||||
])
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user