feat: add cache item delete service

This commit is contained in:
EETagent 2022-12-05 20:13:17 +01:00
parent 699ef3ce9a
commit e360983d88
3 changed files with 105 additions and 36 deletions

View file

@ -1,10 +1,10 @@
#[macro_use]
extern crate rocket;
use rocket::fairing::{self, AdHoc, Fairing, Kind, Info};
use rocket::fairing::{self, AdHoc, Fairing, Info, Kind};
use rocket::http::Header;
use rocket::{Build, Rocket, Request, Response};
use rocket::{Build, Request, Response, Rocket};
use migration::MigratorTrait;
use sea_orm_rocket::Database;
@ -27,14 +27,20 @@ impl Fairing for CORS {
fn info(&self) -> Info {
Info {
name: "Add CORS headers to responses",
kind: Kind::Response
kind: Kind::Response,
}
}
#[cfg(debug_assertions)]
async fn on_response<'r>(&self, _request: &'r Request<'_>, response: &mut Response<'r>) {
response.set_header(Header::new("Access-Control-Allow-Origin", "http://localhost:5173"));
response.set_header(Header::new("Access-Control-Allow-Methods", "POST, GET, OPTIONS"));
response.set_header(Header::new(
"Access-Control-Allow-Origin",
"http://localhost:5173",
));
response.set_header(Header::new(
"Access-Control-Allow-Methods",
"POST, GET, OPTIONS",
));
response.set_header(Header::new("Access-Control-Allow-Headers", "content-type"));
response.set_header(Header::new("Access-Control-Allow-Credentials", "true"));
}
@ -61,7 +67,7 @@ async fn run_migrations(rocket: Rocket<Build>) -> fairing::Result {
Ok(rocket)
}
pub fn rocket() -> Rocket<Build>{
pub fn rocket() -> Rocket<Build> {
rocket::build()
.attach(CORS)
.attach(Db::init())
@ -86,6 +92,14 @@ pub fn rocket() -> Rocket<Build>{
routes::candidate::upload_cover_letter,
],
)
.mount(
"/candidate/remove",
routes![
routes::candidate::delete_portfolio_letter,
routes::candidate::delete_portfolio_zip,
routes::candidate::delete_cover_letter,
],
)
.mount(
"/candidate/portfolio",
routes![
@ -108,20 +122,13 @@ pub fn rocket() -> Rocket<Build>{
routes::admin::get_candidate_portfolio,
],
)
.mount(
"/admin/list",
routes![
routes::admin::list_candidates,
])
.mount("/admin/list", routes![routes::admin::list_candidates,])
.register("/", catchers![])
}
#[tokio::main]
async fn start() -> Result<(), rocket::Error> {
rocket()
.launch()
.await
.map(|_| ())
rocket().launch().await.map(|_| ())
}
pub fn main() {

View file

@ -33,8 +33,8 @@ pub async fn login(
login_form.password.to_string(),
ip_addr.ip().to_string(),
)
.await
.map_err(to_custom_error)?;
.await
.map_err(to_custom_error)?;
cookies.add_private(Cookie::new("id", session_token.clone()));
cookies.add_private(Cookie::new("key", private_key.clone()));
@ -43,14 +43,22 @@ pub async fn login(
}
#[post("/logout")]
pub async fn logout(conn: Connection<'_, Db>, _session: CandidateAuth, cookies: &CookieJar<'_>,) -> Result<(), Custom<String>> {
pub async fn logout(
conn: Connection<'_, Db>,
_session: CandidateAuth,
cookies: &CookieJar<'_>,
) -> Result<(), Custom<String>> {
let db = conn.into_inner();
let cookie = cookies.get_private("id") // unwrap would be safe here because of the auth guard
.ok_or(Custom(Status::Unauthorized, "No session cookie".to_string()))?;
let cookie = cookies
.get_private("id") // unwrap would be safe here because of the auth guard
.ok_or(Custom(
Status::Unauthorized,
"No session cookie".to_string(),
))?;
let session_id = Uuid::try_parse(cookie.value()) // unwrap would be safe here because of the auth guard
.map_err(|e| Custom(Status::BadRequest, e.to_string()))?;
CandidateService::logout(db, session_id)
.await
.map_err(to_custom_error)?;
@ -82,9 +90,7 @@ pub async fn post_details(
.await
.map_err(to_custom_error)?;
Ok(
Json(form)
)
Ok(Json(form))
}
#[get("/details")]
@ -118,18 +124,18 @@ pub async fn upload_cover_letter(
Ok(())
}
#[get("/submission_progress")]
pub async fn submission_progress(
session: CandidateAuth
) -> Result<Json<SubmissionProgress>, Custom<String>> {
#[delete("/cover_letter")]
pub async fn delete_cover_letter(session: CandidateAuth) -> Result<(), Custom<String>> {
let candidate: entity::candidate::Model = session.into();
let progress = PortfolioService::get_submission_progress(candidate.application)
.await
.map(|x| Json(x))
.map_err(to_custom_error);
PortfolioService::delete_cache_item(
candidate.application,
portfolio_core::services::portfolio_service::FileType::CoverLetterPdf,
)
.await
.map_err(to_custom_error)?;
progress
Ok(())
}
#[post("/portfolio_letter", data = "<letter>")]
@ -146,6 +152,20 @@ pub async fn upload_portfolio_letter(
Ok(())
}
#[delete("/portfolio_letter")]
pub async fn delete_portfolio_letter(session: CandidateAuth) -> Result<(), Custom<String>> {
let candidate: entity::candidate::Model = session.into();
PortfolioService::delete_cache_item(
candidate.application,
portfolio_core::services::portfolio_service::FileType::PortfolioLetterPdf,
)
.await
.map_err(to_custom_error)?;
Ok(())
}
#[post("/portfolio_zip", data = "<portfolio>")]
pub async fn upload_portfolio_zip(
session: CandidateAuth,
@ -160,6 +180,34 @@ pub async fn upload_portfolio_zip(
Ok(())
}
#[delete("/portfolio_zip")]
pub async fn delete_portfolio_zip(session: CandidateAuth) -> Result<(), Custom<String>> {
let candidate: entity::candidate::Model = session.into();
PortfolioService::delete_cache_item(
candidate.application,
portfolio_core::services::portfolio_service::FileType::PortfolioZip,
)
.await
.map_err(to_custom_error)?;
Ok(())
}
#[get("/submission_progress")]
pub async fn submission_progress(
session: CandidateAuth,
) -> Result<Json<SubmissionProgress>, Custom<String>> {
let candidate: entity::candidate::Model = session.into();
let progress = PortfolioService::get_submission_progress(candidate.application)
.await
.map(|x| Json(x))
.map_err(to_custom_error);
progress
}
#[post("/submit")]
pub async fn submit_portfolio(
conn: Connection<'_, Db>,
@ -177,7 +225,9 @@ pub async fn submit_portfolio(
// TODO: Více kontrol?
if e.code() == 500 {
// Cleanup
PortfolioService::delete_portfolio(candidate.application).await.unwrap();
PortfolioService::delete_portfolio(candidate.application)
.await
.unwrap();
}
return Err(to_custom_error(e));
}
@ -213,13 +263,16 @@ pub async fn download_portfolio(session: CandidateAuth) -> Result<Vec<u8>, Custo
#[cfg(test)]
mod tests {
use portfolio_core::{models::candidate::ApplicationDetails, crypto, sea_orm::prelude::Uuid};
use portfolio_core::{crypto, models::candidate::ApplicationDetails, sea_orm::prelude::Uuid};
use rocket::{
http::{Cookie, Status},
local::blocking::Client,
};
use crate::{test::tests::{test_client, APPLICATION_ID, CANDIDATE_PASSWORD}, routes::admin::tests::admin_login};
use crate::{
routes::admin::tests::admin_login,
test::tests::{test_client, APPLICATION_ID, CANDIDATE_PASSWORD},
};
fn candidate_login(client: &Client) -> (Cookie, Cookie) {
let response = client

View file

@ -224,6 +224,15 @@ impl PortfolioService {
true
}
// Delete single item from cache
pub async fn delete_cache_item(candidate_id: i32, file_type: FileType) -> Result<(), ServiceError> {
let cache_path = Self::get_file_store_path().join(&candidate_id.to_string()).join("cache");
tokio::fs::remove_file(cache_path.join(file_type.as_str())).await?;
Ok(())
}
/// Removes all files from cache
pub async fn delete_cache(candidate_id: i32) -> Result<(), ServiceError> {
let cache_path = Self::get_file_store_path().join(&candidate_id.to_string()).join("cache");