feat: initial work on file upload

This commit is contained in:
EETagent 2022-11-07 19:53:04 +01:00
parent 9f47bff2fa
commit 78d77cd735
2 changed files with 120 additions and 33 deletions

View file

@ -8,6 +8,8 @@ use rocket::serde::json::Json;
use sea_orm_rocket::Connection;
use crate::guards::data::letter::Letter;
use crate::guards::data::portfolio::Portfolio;
use crate::{guards::request::auth::CandidateAuth, pool::Db, requests};
#[post("/login", data = "<login_form>")]
@ -47,7 +49,7 @@ pub async fn whoami(session: CandidateAuth) -> Result<String, Custom<String>> {
Ok(candidate.application.to_string())
}
#[put("/details", data = "<details>")]
#[post("/details", data = "<details>")]
pub async fn fill_details(
conn: Connection<'_, Db>,
details: Json<UserDetails>,
@ -70,3 +72,66 @@ pub async fn fill_details(
Ok("Details added".to_string())
}
#[post("/coverletter", data = "<letter>")]
pub async fn upload_cover_letter(
session: CandidateAuth,
letter: Letter,
) -> Result<String, Custom<String>> {
let candidate: entity::candidate::Model = session.into();
let candidate = CandidateService::add_cover_letter(candidate.application, letter.into()).await;
if candidate.is_err() {
// TODO cleanup
let e = candidate.err().unwrap();
return Err(Custom(
Status::from_code(e.code()).unwrap_or_default(),
e.message(),
));
}
Ok("Letter added".to_string())
}
#[post("/portfolioletter", data = "<letter>")]
pub async fn upload_portfolio_letter(
session: CandidateAuth,
letter: Letter,
) -> Result<String, Custom<String>> {
let candidate: entity::candidate::Model = session.into();
let candidate = CandidateService::add_portfolio_letter(candidate.application, letter.into()).await;
if candidate.is_err() {
// TODO cleanup
let e = candidate.err().unwrap();
return Err(Custom(
Status::from_code(e.code()).unwrap_or_default(),
e.message(),
));
}
Ok("Letter added".to_string())
}
#[post("/portfolio", data = "<portfolio>")]
pub async fn upload_portfolio_zip(
session: CandidateAuth,
portfolio: Portfolio,
) -> Result<String, Custom<String>> {
let candidate: entity::candidate::Model = session.into();
let candidate = CandidateService::add_portfolio_zip(candidate.application, portfolio.into()).await;
if candidate.is_err() {
// TODO cleanup
let e = candidate.err().unwrap();
return Err(Custom(
Status::from_code(e.code()).unwrap_or_default(),
e.message(),
));
}
Ok("Letter added".to_string())
}

View file

@ -67,7 +67,9 @@ impl EncryptedUserDetails {
}
}
fn extract_enc_candidate_details(candidate: candidate::Model) -> Result<UserDetails, ServiceError> {
fn extract_enc_candidate_details(
candidate: candidate::Model,
) -> Result<UserDetails, ServiceError> {
let ( // TODO: simplify??
Some(name),
Some(surname),
@ -152,20 +154,18 @@ impl EncryptedUserDetails {
panic!("Failed to encrypt user details"); // TODO
};
Ok(
UserDetails {
name,
surname,
birthplace,
// birthdate: NaiveDate::from_ymd(2000, 1, 1),
address,
telephone,
citizenship,
email,
sex,
study,
}
)
Ok(UserDetails {
name,
surname,
birthplace,
// birthdate: NaiveDate::from_ymd(2000, 1, 1),
address,
telephone,
citizenship,
email,
sex,
study,
})
}
}
@ -183,7 +183,6 @@ pub struct UserDetails {
pub study: String,
}
pub struct CandidateService;
impl CandidateService {
@ -259,13 +258,9 @@ impl CandidateService {
let enc_details = EncryptedUserDetails::encrypt_form(form, recipients).await;
Mutation::add_candidate_details(
db,
user,
enc_details,
)
.await
.map_err(|_| ServiceError::DbError)
Mutation::add_candidate_details(db, user, enc_details)
.await
.map_err(|_| ServiceError::DbError)
}
pub async fn decrypt_details(
@ -282,18 +277,36 @@ impl CandidateService {
match crypto::verify_password((&password).to_string(), candidate.code.clone()).await {
Ok(valid) => {
if !valid {
return Err(ServiceError::InvalidCredentials)
return Err(ServiceError::InvalidCredentials);
}
},
Err(_) => {return Err(ServiceError::InvalidCredentials)}
}
Err(_) => return Err(ServiceError::InvalidCredentials),
}
let dec_priv_key = crypto::decrypt_password(candidate.private_key.clone(), password).await.ok().unwrap();
let dec_priv_key = crypto::decrypt_password(candidate.private_key.clone(), password)
.await
.ok()
.unwrap();
let enc_details = EncryptedUserDetails::from_model(candidate)?;
enc_details.decrypt(dec_priv_key).await
}
pub async fn add_cover_letter(candidate_id: i32, letter: Vec<u8>) -> Result<(), ServiceError> {
// TODO
Ok(())
}
pub async fn add_portfolio_letter(candidate_id: i32, letter: Vec<u8>) -> Result<(), ServiceError> {
// TODO
Ok(())
}
pub async fn add_portfolio_zip(candidate_id: i32, zip: Vec<u8>) -> Result<(), ServiceError> {
// TODO
Ok(())
}
pub async fn login(
db: &DbConn,
user_id: i32,
@ -326,10 +339,13 @@ impl CandidateService {
#[cfg(test)]
mod tests {
use sea_orm::{Database, DbConn};
use entity::candidate::Model;
use sea_orm::{Database, DbConn};
use crate::{crypto, services::candidate_service::{CandidateService, UserDetails}};
use crate::{
crypto,
services::candidate_service::{CandidateService, UserDetails},
};
use super::EncryptedUserDetails;
@ -398,7 +414,6 @@ mod tests {
assert_eq!(secret_message, decrypted_message);
}
#[cfg(test)]
async fn put_user_data(db: &DbConn) -> Model {
let plain_text_password = "test".to_string();
@ -419,7 +434,10 @@ mod tests {
sex: "test".to_string(),
study: "test".to_string(),
};
CandidateService::add_user_details(&db, candidate, form).await.ok().unwrap()
CandidateService::add_user_details(&db, candidate, form)
.await
.ok()
.unwrap()
}
#[tokio::test]
@ -438,7 +456,11 @@ mod tests {
let dec_priv_key = crypto::decrypt_password(enc_candidate.private_key.clone(), password)
.await
.unwrap();
let dec_candidate = EncryptedUserDetails::from_model(enc_candidate).unwrap().decrypt(dec_priv_key).await.unwrap();
let dec_candidate = EncryptedUserDetails::from_model(enc_candidate)
.unwrap()
.decrypt(dec_priv_key)
.await
.unwrap();
assert_eq!(dec_candidate.name, "test");
}