Compare commits
No commits in common. "bf84ff6e337f090bbae8ad4b02f96a7076bc144d" and "ab81d241df52ad8e3766ff546f7cbbc9cf878696" have entirely different histories.
bf84ff6e33
...
ab81d241df
1653
Cargo.lock
generated
1653
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -8,5 +8,3 @@ edition = "2021"
|
||||
[dependencies]
|
||||
rocket = {version = "0.5.0", features = ["json"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
sea-orm = { version = "^0.12.0", features = [ "sqlx-sqlite", "runtime-tokio-native-tls", "macros", "mock" ] }
|
||||
futures = "0.3.28"
|
||||
@ -1,34 +0,0 @@
|
||||
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.10
|
||||
|
||||
use sea_orm::entity::prelude::*;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
|
||||
#[sea_orm(table_name = "members")]
|
||||
pub struct Model {
|
||||
#[sea_orm(primary_key, auto_increment = false)]
|
||||
pub id: i32,
|
||||
#[sea_orm(column_name = "ntnuUsername")]
|
||||
pub ntnu_username: String,
|
||||
#[sea_orm(column_name = "firstName")]
|
||||
pub first_name: String,
|
||||
#[sea_orm(column_name = "lastName")]
|
||||
pub last_name: String,
|
||||
pub email: String,
|
||||
pub balance: i32,
|
||||
#[sea_orm(column_name = "imagePreference")]
|
||||
pub image_preference: String,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||
pub enum Relation {
|
||||
#[sea_orm(has_many = "super::rfid_cards::Entity")]
|
||||
RfidCards,
|
||||
}
|
||||
|
||||
impl Related<super::rfid_cards::Entity> for Entity {
|
||||
fn to() -> RelationDef {
|
||||
Relation::RfidCards.def()
|
||||
}
|
||||
}
|
||||
|
||||
impl ActiveModelBehavior for ActiveModel {}
|
||||
@ -1,6 +0,0 @@
|
||||
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.10
|
||||
|
||||
pub mod prelude;
|
||||
|
||||
pub mod members;
|
||||
pub mod rfid_cards;
|
||||
@ -1,4 +0,0 @@
|
||||
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.10
|
||||
|
||||
pub use super::members::Entity as Members;
|
||||
pub use super::rfid_cards::Entity as RfidCards;
|
||||
@ -1,33 +0,0 @@
|
||||
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.12.10
|
||||
|
||||
use sea_orm::entity::prelude::*;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
|
||||
#[sea_orm(table_name = "rfid_cards")]
|
||||
pub struct Model {
|
||||
#[sea_orm(column_name = "cardId", primary_key, auto_increment = false)]
|
||||
pub card_id: String,
|
||||
#[sea_orm(column_name = "cardComment")]
|
||||
pub card_comment: String,
|
||||
pub member_id: Option<i32>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||
pub enum Relation {
|
||||
#[sea_orm(
|
||||
belongs_to = "super::members::Entity",
|
||||
from = "Column::MemberId",
|
||||
to = "super::members::Column::Id",
|
||||
on_update = "NoAction",
|
||||
on_delete = "NoAction"
|
||||
)]
|
||||
Members,
|
||||
}
|
||||
|
||||
impl Related<super::members::Entity> for Entity {
|
||||
fn to() -> RelationDef {
|
||||
Relation::Members.def()
|
||||
}
|
||||
}
|
||||
|
||||
impl ActiveModelBehavior for ActiveModel {}
|
||||
168
src/main.rs
168
src/main.rs
@ -1,18 +1,9 @@
|
||||
// Webserver
|
||||
#[macro_use] extern crate rocket;
|
||||
|
||||
use rocket::{State, Error};
|
||||
use rocket::response::status;
|
||||
use rocket::serde::{Serialize, Deserialize, json::Json};
|
||||
|
||||
// Database
|
||||
use sea_orm::*;
|
||||
|
||||
mod setup;
|
||||
use setup::set_up_db;
|
||||
|
||||
mod entities;
|
||||
use entities::{prelude::*, *};
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct RfidCard {
|
||||
@ -22,167 +13,40 @@ struct RfidCard {
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct Member {
|
||||
id: i32,
|
||||
id: u64,
|
||||
ntnuUsername: String,
|
||||
firstName: String,
|
||||
lastName: String,
|
||||
email: String,
|
||||
balance: i32,
|
||||
balance: i64,
|
||||
imagePreference: String,
|
||||
rfidCards: Vec<RfidCard>
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct MinimalMember {
|
||||
id: i32,
|
||||
ntnuUsername: String,
|
||||
firstName: String,
|
||||
lastName: String,
|
||||
email: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct MinimalMemberWithoutId {
|
||||
ntnuUsername: String,
|
||||
firstName: String,
|
||||
lastName: String,
|
||||
email: String,
|
||||
}
|
||||
|
||||
#[derive(Responder)]
|
||||
#[response(status = 500, content_type = "text/plain")]
|
||||
struct ErrorResponder {
|
||||
message: String
|
||||
}
|
||||
|
||||
impl From<DbErr> for ErrorResponder {
|
||||
fn from(err: DbErr) -> ErrorResponder {
|
||||
ErrorResponder { message: err.to_string() }
|
||||
}
|
||||
}
|
||||
impl From<String> for ErrorResponder {
|
||||
fn from(string: String) -> ErrorResponder {
|
||||
ErrorResponder { message: string }
|
||||
}
|
||||
}
|
||||
impl From<&str> for ErrorResponder {
|
||||
fn from(str: &str) -> ErrorResponder {
|
||||
ErrorResponder { message: str.to_owned().into() }
|
||||
}
|
||||
}
|
||||
|
||||
#[get("/")]
|
||||
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> {
|
||||
// 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
|
||||
.one(db) // We only care about one result
|
||||
.await?; // Wait for the result
|
||||
|
||||
// If a member exists return an error
|
||||
if matching_member.is_some() {
|
||||
return Err(
|
||||
ErrorResponder {
|
||||
message: "A member with this NTNU username already exists".to_string(),
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
// 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()
|
||||
};
|
||||
|
||||
// Add the new member to the database
|
||||
let res = Members::insert(new_member).exec(db).await?;
|
||||
|
||||
// Fetch the member's info back from the DB to verify
|
||||
let new_member;
|
||||
match Members::find_by_id(res.last_insert_id).one(db).await? {
|
||||
Some(model) => new_member = model,
|
||||
None => {
|
||||
return Err(
|
||||
ErrorResponder {
|
||||
message: format!("Failed to fetch member for verification of creating new member with ID. memberId: {}", res.last_insert_id)
|
||||
}
|
||||
);
|
||||
},
|
||||
}
|
||||
|
||||
// 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,
|
||||
};
|
||||
|
||||
Ok(Json(member))
|
||||
}
|
||||
|
||||
#[get("/member/<memberId>")]
|
||||
async fn get_member_by_id(db: &State<DatabaseConnection>, memberId: i32) -> Result<Json<Member>, ErrorResponder> {
|
||||
let db = db as &DatabaseConnection;
|
||||
|
||||
let database_member;
|
||||
match Members::find_by_id(memberId).one(db).await? {
|
||||
Some(model) => database_member = model,
|
||||
None => {
|
||||
return Err(
|
||||
ErrorResponder {
|
||||
message: format!("Failed to fetch member by ID. memberId: {}", memberId)
|
||||
}
|
||||
);
|
||||
},
|
||||
fn get_member(memberId: u64) -> Json<Member> {
|
||||
let sebasthg = Member {
|
||||
id: 1,
|
||||
ntnuUsername: "sebasthg".to_string(),
|
||||
firstName: "Sebastian".to_string(),
|
||||
lastName: "Gabrielli".to_string(),
|
||||
email: "sebastian@fastmail.mx".to_string(),
|
||||
balance: 50,
|
||||
imagePreference: "Money".to_string(),
|
||||
rfidCards: vec![ RfidCard { cardId: "0364249683".to_string(), cardComment: "Studentkort".to_string() } ]
|
||||
};
|
||||
|
||||
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 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
|
||||
};
|
||||
|
||||
Ok(Json(member))
|
||||
Json(sebasthg)
|
||||
}
|
||||
|
||||
#[launch]
|
||||
async fn rocket() -> _ {
|
||||
let db = match set_up_db().await {
|
||||
Ok(db) => db,
|
||||
Err(err) => panic!("{}", err)
|
||||
};
|
||||
|
||||
fn rocket() -> _ {
|
||||
rocket::build()
|
||||
.manage(db)
|
||||
.mount("/", routes![
|
||||
index,
|
||||
get_member_by_id,
|
||||
add_member
|
||||
])
|
||||
.mount("/", routes![index])
|
||||
.mount("/", routes![get_member])
|
||||
}
|
||||
|
||||
39
src/setup.rs
39
src/setup.rs
@ -1,39 +0,0 @@
|
||||
use sea_orm::*;
|
||||
|
||||
const DATABASE_URL: &str = "sqlite:./test.db";
|
||||
const DB_NAME: &str = "omegav";
|
||||
|
||||
pub(super) async fn set_up_db() -> Result<DatabaseConnection, DbErr> {
|
||||
let db = Database::connect(DATABASE_URL).await?;
|
||||
|
||||
let db = match db.get_database_backend() {
|
||||
DbBackend::MySql => {
|
||||
db.execute(Statement::from_string(
|
||||
db.get_database_backend(),
|
||||
format!("CREATE DATABASE IF NOT EXISTS `{}`;", DB_NAME),
|
||||
))
|
||||
.await?;
|
||||
|
||||
let url = format!("{}/{}", DATABASE_URL, DB_NAME);
|
||||
Database::connect(&url).await?
|
||||
}
|
||||
DbBackend::Postgres => {
|
||||
db.execute(Statement::from_string(
|
||||
db.get_database_backend(),
|
||||
format!("DROP DATABASE IF EXISTS \"{}\";", DB_NAME),
|
||||
))
|
||||
.await?;
|
||||
db.execute(Statement::from_string(
|
||||
db.get_database_backend(),
|
||||
format!("CREATE DATABASE \"{}\";", DB_NAME),
|
||||
))
|
||||
.await?;
|
||||
|
||||
let url = format!("{}/{}", DATABASE_URL, DB_NAME);
|
||||
Database::connect(&url).await?
|
||||
}
|
||||
DbBackend::Sqlite => db,
|
||||
};
|
||||
|
||||
Ok(db)
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user