Add get_person route
This commit is contained in:
parent
7770ab958a
commit
d2a94b078c
51
backend/Cargo.lock
generated
51
backend/Cargo.lock
generated
|
|
@ -295,12 +295,31 @@ version = "0.13.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.21.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a"
|
||||
|
||||
[[package]]
|
||||
name = "base64ct"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
|
||||
|
||||
[[package]]
|
||||
name = "bcrypt"
|
||||
version = "0.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9df288bec72232f78c1ec5fe4e8f1d108aa0265476e93097593c803c8c02062a"
|
||||
dependencies = [
|
||||
"base64 0.21.0",
|
||||
"blowfish",
|
||||
"getrandom",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bigdecimal"
|
||||
version = "0.3.1"
|
||||
|
|
@ -342,6 +361,16 @@ dependencies = [
|
|||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "blowfish"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e412e2cd0f2b2d93e02543ceae7917b3c70331573df19ee046bcbc35e45e87d7"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"cipher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "borsh"
|
||||
version = "0.10.3"
|
||||
|
|
@ -455,6 +484,16 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cipher"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
|
||||
dependencies = [
|
||||
"crypto-common",
|
||||
"inout",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "3.2.25"
|
||||
|
|
@ -554,6 +593,7 @@ name = "crabfit_backend"
|
|||
version = "1.1.0"
|
||||
dependencies = [
|
||||
"axum",
|
||||
"bcrypt",
|
||||
"chrono",
|
||||
"common",
|
||||
"dotenv",
|
||||
|
|
@ -1119,6 +1159,15 @@ dependencies = [
|
|||
"hashbrown 0.12.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "inout"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "instant"
|
||||
version = "0.1.12"
|
||||
|
|
@ -2280,7 +2329,7 @@ checksum = "fa8241483a83a3f33aa5fff7e7d9def398ff9990b2752b6c6112b83c6d246029"
|
|||
dependencies = [
|
||||
"ahash 0.7.6",
|
||||
"atoi",
|
||||
"base64",
|
||||
"base64 0.13.1",
|
||||
"bigdecimal",
|
||||
"bitflags",
|
||||
"byteorder",
|
||||
|
|
|
|||
|
|
@ -20,3 +20,4 @@ regex = "1.8.1"
|
|||
tracing = "0.1.37"
|
||||
tracing-subscriber = "0.3.17"
|
||||
chrono = "0.4.24"
|
||||
bcrypt = "0.14.0"
|
||||
|
|
|
|||
|
|
@ -71,17 +71,23 @@ impl Adaptor for SqlAdaptor {
|
|||
}
|
||||
|
||||
async fn upsert_person(&self, event_id: String, person: Person) -> Result<Person, Self::Error> {
|
||||
Ok(person::ActiveModel {
|
||||
name: Set(person.name),
|
||||
let data = person::ActiveModel {
|
||||
name: Set(person.name.clone()),
|
||||
password_hash: Set(person.password_hash),
|
||||
created_at: Set(person.created_at.naive_utc()),
|
||||
availability: Set(serde_json::to_value(person.availability).unwrap_or(json!([]))),
|
||||
event_id: Set(event_id),
|
||||
}
|
||||
.save(&self.db)
|
||||
.await?
|
||||
.try_into_model()?
|
||||
.into())
|
||||
event_id: Set(event_id.clone()),
|
||||
};
|
||||
|
||||
Ok(
|
||||
match person::Entity::find_by_id((event_id, person.name))
|
||||
.one(&self.db)
|
||||
.await?
|
||||
{
|
||||
Some(_) => data.update(&self.db).await?.try_into_model()?.into(),
|
||||
None => data.insert(&self.db).await?.try_into_model()?.into(),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
async fn get_event(&self, id: String) -> Result<Option<Event>, Self::Error> {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use common::adaptor::Adaptor;
|
|||
pub enum ApiError<A: Adaptor> {
|
||||
AdaptorError(A::Error),
|
||||
NotFound,
|
||||
// NotAuthorized,
|
||||
NotAuthorized,
|
||||
}
|
||||
|
||||
// Define what the error types above should return
|
||||
|
|
@ -16,7 +16,7 @@ impl<A: Adaptor> IntoResponse for ApiError<A> {
|
|||
StatusCode::INTERNAL_SERVER_ERROR.into_response()
|
||||
}
|
||||
ApiError::NotFound => StatusCode::NOT_FOUND.into_response(),
|
||||
// ApiError::NotAuthorized => StatusCode::UNAUTHORIZED.into_response(),
|
||||
ApiError::NotAuthorized => StatusCode::UNAUTHORIZED.into_response(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,9 +39,10 @@ async fn main() {
|
|||
let app = Router::new()
|
||||
.route("/", get(get_root))
|
||||
.route("/stats", get(get_stats))
|
||||
.route("/event/:event_id", get(get_event))
|
||||
.route("/event", post(create_event))
|
||||
.route("/event/:event_id", get(get_event))
|
||||
.route("/event/:event_id/people", get(get_people))
|
||||
.route("/event/:event_id/people/:person_name", get(get_person))
|
||||
.with_state(shared_state);
|
||||
|
||||
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
|
||||
|
|
|
|||
|
|
@ -58,3 +58,8 @@ impl From<Person> for PersonResponse {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct PersonInput {
|
||||
pub password: Option<String>,
|
||||
}
|
||||
|
|
|
|||
87
backend/src/routes/get_person.rs
Normal file
87
backend/src/routes/get_person.rs
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
use axum::{
|
||||
extract::{self, Path},
|
||||
Json,
|
||||
};
|
||||
use common::{adaptor::Adaptor, person::Person};
|
||||
|
||||
use crate::{
|
||||
errors::ApiError,
|
||||
payloads::{ApiResult, PersonInput, PersonResponse},
|
||||
State,
|
||||
};
|
||||
|
||||
pub async fn get_person<A: Adaptor>(
|
||||
extract::State(state): State<A>,
|
||||
Path((event_id, person_name)): Path<(String, String)>,
|
||||
input: Option<Json<PersonInput>>,
|
||||
) -> ApiResult<PersonResponse, A> {
|
||||
let adaptor = &state.lock().await.adaptor;
|
||||
|
||||
// Get inputted password
|
||||
let password = match input {
|
||||
Some(Json(i)) => i.password,
|
||||
None => None,
|
||||
};
|
||||
|
||||
let existing_people = adaptor
|
||||
.get_people(event_id.clone())
|
||||
.await
|
||||
.map_err(ApiError::AdaptorError)?;
|
||||
|
||||
// Event not found
|
||||
if existing_people.is_none() {
|
||||
return Err(ApiError::NotFound);
|
||||
}
|
||||
|
||||
// Check if the user already exists
|
||||
let existing_person = existing_people
|
||||
.unwrap()
|
||||
.into_iter()
|
||||
.find(|p| p.name == person_name);
|
||||
|
||||
match existing_person {
|
||||
// Login
|
||||
Some(p) => {
|
||||
// Verify password (if set)
|
||||
if verify_password(&p, password) {
|
||||
Ok(Json(p.into()))
|
||||
} else {
|
||||
Err(ApiError::NotAuthorized)
|
||||
}
|
||||
}
|
||||
// Signup
|
||||
None => {
|
||||
// Update stats
|
||||
adaptor
|
||||
.increment_stat_person_count()
|
||||
.await
|
||||
.map_err(ApiError::AdaptorError)?;
|
||||
|
||||
Ok(Json(
|
||||
adaptor
|
||||
.upsert_person(
|
||||
event_id,
|
||||
Person {
|
||||
name: person_name,
|
||||
password_hash: password
|
||||
.map(|raw| bcrypt::hash(raw, 10).unwrap_or(String::from(""))),
|
||||
created_at: chrono::offset::Utc::now(),
|
||||
availability: vec![],
|
||||
},
|
||||
)
|
||||
.await
|
||||
.map_err(ApiError::AdaptorError)?
|
||||
.into(),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn verify_password(person: &Person, raw: Option<String>) -> bool {
|
||||
match &person.password_hash {
|
||||
Some(hash) => bcrypt::verify(raw.unwrap_or(String::from("")), hash).unwrap_or(false),
|
||||
// Specifically allow a user who doesn't have a password
|
||||
// set to log in with or without any password input
|
||||
None => true,
|
||||
}
|
||||
}
|
||||
|
|
@ -9,3 +9,6 @@ pub use create_event::create_event;
|
|||
|
||||
mod get_people;
|
||||
pub use get_people::get_people;
|
||||
|
||||
mod get_person;
|
||||
pub use get_person::get_person;
|
||||
|
|
|
|||
Loading…
Reference in a new issue