Skip to content

Commit

Permalink
API: First tests (#13)
Browse files Browse the repository at this point in the history
  • Loading branch information
Arthi-chaud authored Mar 7, 2024
2 parents a570898 + 796bfed commit 9d052ea
Show file tree
Hide file tree
Showing 26 changed files with 470 additions and 98 deletions.
2 changes: 2 additions & 0 deletions api/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion api/api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,8 @@ image = "0.24.9"
color-thief = "0.2"
colors-transform = "0.2.11"
webp = "0.2"
tempfile = "3.10.1"
tempfile = "3.10.1"

[dev-dependencies]
once_cell = "1.9.0"
regex = "1.10.3"
7 changes: 4 additions & 3 deletions api/api/src/controllers/artists.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use crate::config::Config;
use crate::error_handling::{ApiError, ApiResult};
use crate::error_handling::{ApiError, ApiRawResult, ApiResult};
use crate::responses::artist::ArtistResponse;
use crate::{services, utils};
use diesel::Connection;
use domain::models::image::{Image, ImageType};
use infrastructure::Database;
use rocket::fs::TempFile;
use rocket::response::status;
use rocket::serde::json::Json;
use rocket::State;
use rocket_okapi::okapi::openapi3::OpenApi;
Expand Down Expand Up @@ -33,7 +34,7 @@ async fn post_artist_image(
slug_or_uuid: String,
data: TempFile<'_>,
config: &State<Config>,
) -> ApiResult<Image> {
) -> ApiRawResult<status::Created<Json<Image>>> {
let bytes = utils::temp_file_to_bytes_vec(data).await?;
let c: Config = config.inner().clone();
db.run(move |handle| {
Expand All @@ -51,5 +52,5 @@ async fn post_artist_image(
})
})
.await
.map(|v| Json(v))
.map(|v| status::Created::new("").body(Json(v)))
}
14 changes: 11 additions & 3 deletions api/api/src/controllers/extras.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use crate::dto::extra::NewExtra;
use crate::error_handling::{ApiError, ApiResult};
use crate::error_handling::{ApiError, ApiRawResult};
use crate::responses::extra_creation::ExtraCreationResponse;
use crate::services;
use diesel::Connection;
use domain::models::artist::Artist;
use infrastructure::Database;
use rocket::response::status;
use rocket::{post, serde::json::Json};
use rocket_okapi::okapi::openapi3::OpenApi;
use rocket_okapi::settings::OpenApiSettings;
Expand All @@ -17,7 +18,10 @@ pub fn get_routes_and_docs(settings: &OpenApiSettings) -> (Vec<rocket::Route>, O
/// Create a new extra
#[openapi(tag = "Extras")]
#[post("/", format = "json", data = "<data>")]
async fn new_extra(_db: Database, data: Json<NewExtra>) -> ApiResult<ExtraCreationResponse> {
async fn new_extra(
_db: Database,
data: Json<NewExtra>,
) -> ApiRawResult<status::Created<Json<ExtraCreationResponse>>> {
_db.run(move |conn| {
conn.transaction::<ExtraCreationResponse, diesel::result::Error, _>(
move |connection| -> _ {
Expand Down Expand Up @@ -60,10 +64,14 @@ async fn new_extra(_db: Database, data: Json<NewExtra>) -> ApiResult<ExtraCreati
package_artist_id: package_artist.map(|a| a.id),
package_id: package.id,
extra_id: extra.id,
file_id: file.id,
})
},
)
})
.await
.map_or_else(|e| Err(ApiError::from(e)), |v| Ok(Json(v)))
.map_or_else(
|e| Err(ApiError::from(e)),
|v| Ok(status::Created::new("").body(Json(v))),
)
}
14 changes: 11 additions & 3 deletions api/api/src/controllers/movies.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use crate::dto::movie::NewMovie;
use crate::error_handling::{ApiError, ApiResult};
use crate::error_handling::{ApiError, ApiRawResult};
use crate::responses::movie_creation::MovieCreationResponse;
use crate::services;
use diesel::Connection;
use domain::models::artist::Artist;
use infrastructure::Database;
use rocket::response::status;
use rocket::{post, serde::json::Json};
use rocket_okapi::okapi::openapi3::OpenApi;
use rocket_okapi::settings::OpenApiSettings;
Expand All @@ -17,7 +18,10 @@ pub fn get_routes_and_docs(settings: &OpenApiSettings) -> (Vec<rocket::Route>, O
/// Create a new movie with its chapters
#[openapi(tag = "Movies")]
#[post("/", format = "json", data = "<data>")]
async fn new_movie(_db: Database, data: Json<NewMovie>) -> ApiResult<MovieCreationResponse> {
async fn new_movie(
_db: Database,
data: Json<NewMovie>,
) -> ApiRawResult<status::Created<Json<MovieCreationResponse>>> {
_db.run(move |conn| {
conn.transaction::<MovieCreationResponse, diesel::result::Error, _>(
move |connection| -> _ {
Expand Down Expand Up @@ -62,10 +66,14 @@ async fn new_movie(_db: Database, data: Json<NewMovie>) -> ApiResult<MovieCreati
package_id: package.id,
movie_id: movie.id,
chapters_id: chapter_results.iter().map(|c| c.id).collect(),
file_id: file.id,
})
},
)
})
.await
.map_or_else(|e| Err(ApiError::from(e)), |v| Ok(Json(v)))
.map_or_else(
|e| Err(ApiError::from(e)),
|v| Ok(status::Created::new("").body(Json(v))),
)
}
4 changes: 2 additions & 2 deletions api/api/src/dto/chapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ use crate::swagger_examples::*;
use domain::models::chapter::ChapterType;
use rocket_okapi::okapi::schemars;
use rocket_okapi::okapi::schemars::JsonSchema;
use serde::Deserialize;
use serde::{Deserialize, Serialize};

/// DTO to create a new chapter
#[derive(Deserialize, JsonSchema)]
#[derive(Deserialize, JsonSchema, Serialize)]
#[serde(crate = "rocket::serde")]
pub struct NewChapter {
#[schemars(example = "example_chapter_name")]
Expand Down
4 changes: 2 additions & 2 deletions api/api/src/dto/extra.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ use crate::swagger_examples::*;
use domain::models::extra::ExtraType;
use rocket_okapi::okapi::schemars;
use rocket_okapi::okapi::schemars::JsonSchema;
use serde::Deserialize;
use serde::{Deserialize, Serialize};

use super::file::NewFile;

/// DTO to create a new Extra
#[derive(Deserialize, JsonSchema)]
#[derive(Deserialize, Serialize, JsonSchema)]
#[serde(crate = "rocket::serde")]
pub struct NewExtra {
#[schemars(example = "example_artist_name")]
Expand Down
4 changes: 2 additions & 2 deletions api/api/src/dto/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ use crate::swagger_examples::*;
use domain::models::video_quality::VideoQuality;
use rocket_okapi::okapi::schemars;
use rocket_okapi::okapi::schemars::JsonSchema;
use serde::Deserialize;
use serde::{Deserialize, Serialize};

/// DTO to create a new File
#[derive(Deserialize, JsonSchema, Clone)]
#[derive(Deserialize, Serialize, JsonSchema, Clone)]
#[serde(crate = "rocket::serde")]
pub struct NewFile {
/// The aboslute path of the file
Expand Down
4 changes: 2 additions & 2 deletions api/api/src/dto/movie.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ use crate::swagger_examples::*;
use domain::models::movie::MovieType;
use rocket_okapi::okapi::schemars;
use rocket_okapi::okapi::schemars::JsonSchema;
use serde::Deserialize;
use serde::{Deserialize, Serialize};

use super::chapter::NewChapter;
use super::file::NewFile;

/// DTO to create a new Movie
#[derive(Deserialize, JsonSchema)]
#[derive(Deserialize, JsonSchema, Serialize)]
#[serde(crate = "rocket::serde")]
pub struct NewMovie {
#[schemars(example = "example_artist_name")]
Expand Down
2 changes: 2 additions & 0 deletions api/api/src/error_handling.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ pub struct ErrorResponse<'s> {

pub type ApiResult<T> = Result<Json<T>, ApiError>;

pub type ApiRawResult<T> = Result<T, ApiError>;

impl<'r> Responder<'r, 'static> for ApiError {
fn respond_to(self, _: &'r Request<'_>) -> response::Result<'static> {
let response_body: ErrorResponse = match self {
Expand Down
75 changes: 75 additions & 0 deletions api/api/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
use crate::config::Config;
use crate::controllers::index::index;
use crate::error_handling::not_found;
use crate::swagger::custom_openapi_spec;
use infrastructure::{apply_migrations, Database};
use rocket::fairing::AdHoc;
use rocket::figment::providers::Serialized;
use rocket::figment::Figment;
use rocket::{Build, Rocket};
use rocket_okapi::settings::OpenApiSettings;
use rocket_okapi::{mount_endpoints_and_merged_docs, swagger_ui::*};
use std::env;

pub mod config;
mod controllers;
pub mod dto;
mod error_handling;
pub mod responses;
pub mod services;
mod swagger;
mod swagger_examples;
pub mod utils;

#[macro_use]
extern crate rocket;

#[launch]
pub fn rocket() -> Rocket<Build> {
create_server()
}

async fn run_migrations(rocket: Rocket<Build>) -> Rocket<Build> {
let _ = Database::get_one(&rocket)
.await
.expect("Get DB Handle from Rocket")
.run(|conn| apply_migrations(conn))
.await;

rocket
}

fn create_server() -> Rocket<Build> {
let data_dir = env::var("CONFIG_DIR").expect("env variable `CONFIG_DIR` not set.");
let figment = Figment::from(rocket::Config::figment()).merge(Serialized::defaults(Config {
data_folder: data_dir,
}));
let mut building_rocket = rocket::custom(figment)
.attach(Database::fairing())
.attach(AdHoc::config::<Config>())
.attach(AdHoc::on_ignite("Run migrations", run_migrations))
.register("/", catchers![not_found])
.mount(
"/swagger",
make_swagger_ui(&SwaggerUIConfig {
url: "./openapi.json".to_owned(),
..Default::default()
}),
)
.mount("/", routes![index]);

let openapi_settings = OpenApiSettings {
json_path: "/swagger/openapi.json".to_owned(),
..OpenApiSettings::default()
};
mount_endpoints_and_merged_docs! {
building_rocket, "/".to_owned(), openapi_settings,
"/artists" => controllers::artists::get_routes_and_docs(&openapi_settings),
"/extras" => controllers::extras::get_routes_and_docs(&openapi_settings),
"/images" => controllers::images::get_routes_and_docs(&openapi_settings),
"/movies" => controllers::movies::get_routes_and_docs(&openapi_settings),
"/swagger" => (vec![], custom_openapi_spec()),
};

building_rocket
}
78 changes: 6 additions & 72 deletions api/api/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,75 +1,9 @@
use crate::config::Config;
use crate::controllers::index::index;
use crate::error_handling::not_found;
use crate::swagger::custom_openapi_spec;
use infrastructure::{apply_migrations, Database};
use rocket::fairing::AdHoc;
use rocket::figment::providers::Serialized;
use rocket::figment::Figment;
use rocket::{Build, Rocket};
use rocket_okapi::settings::OpenApiSettings;
use rocket_okapi::{mount_endpoints_and_merged_docs, swagger_ui::*};
use std::env;
use api;
use rocket;

mod config;
mod controllers;
mod dto;
mod error_handling;
mod responses;
mod services;
mod swagger;
mod swagger_examples;
mod utils;
#[rocket::main]
async fn main() -> Result<(), rocket::Error> {
let _ = api::rocket().launch().await;

#[macro_use]
extern crate rocket;

#[launch]
fn rocket() -> Rocket<Build> {
create_server()
}

async fn run_migrations(rocket: Rocket<Build>) -> Rocket<Build> {
let _ = Database::get_one(&rocket)
.await
.expect("Get DB Handle from Rocket")
.run(|conn| apply_migrations(conn))
.await;

rocket
}

pub fn create_server() -> Rocket<Build> {
let data_dir = env::var("CONFIG_DIR").expect("env variable `CONFIG_DIR` not set.");
let figment = Figment::from(rocket::Config::figment()).merge(Serialized::defaults(Config {
data_folder: data_dir,
}));
let mut building_rocket = rocket::custom(figment)
.attach(Database::fairing())
.attach(AdHoc::config::<Config>())
.attach(AdHoc::on_ignite("Run migrations", run_migrations))
.register("/", catchers![not_found])
.mount(
"/swagger",
make_swagger_ui(&SwaggerUIConfig {
url: "./openapi.json".to_owned(),
..Default::default()
}),
)
.mount("/", routes![index]);

let openapi_settings = OpenApiSettings {
json_path: "/swagger/openapi.json".to_owned(),
..OpenApiSettings::default()
};
mount_endpoints_and_merged_docs! {
building_rocket, "/".to_owned(), openapi_settings,
"/artists" => controllers::artists::get_routes_and_docs(&openapi_settings),
"/extras" => controllers::extras::get_routes_and_docs(&openapi_settings),
"/images" => controllers::images::get_routes_and_docs(&openapi_settings),
"/movies" => controllers::movies::get_routes_and_docs(&openapi_settings),
"/swagger" => (vec![], custom_openapi_spec()),
};

building_rocket
Ok(())
}
2 changes: 2 additions & 0 deletions api/api/src/responses/extra_creation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,6 @@ pub struct ExtraCreationResponse {
pub package_id: Uuid,
#[schemars(example = "example_uuid")]
pub extra_id: Uuid,
#[schemars(example = "example_uuid")]
pub file_id: Uuid,
}
2 changes: 2 additions & 0 deletions api/api/src/responses/movie_creation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,7 @@ pub struct MovieCreationResponse {
pub package_id: Uuid,
#[schemars(example = "example_uuid")]
pub movie_id: Uuid,
#[schemars(example = "example_uuid")]
pub file_id: Uuid,
pub chapters_id: Vec<Uuid>,
}
Loading

0 comments on commit 9d052ea

Please sign in to comment.