summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.toml2
-rw-r--r--README.md4
-rw-r--r--src/api/search_results.rs18
-rw-r--r--src/database/artist.rs5
-rw-r--r--src/database/search_results.rs15
-rw-r--r--src/database/song.rs3
-rw-r--r--src/main.rs44
7 files changed, 56 insertions, 35 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 8da9c88..d418e8c 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -14,6 +14,8 @@ env_logger = "0.11.6"
jsonwebtoken = "9.3.0"
chrono = "0.4.39"
utoipa-actix-web = "0.1.2"
+utoipa = { version = "5.3.1", features= ["actix_extras", "chrono"] }
+utoipa-swagger-ui = { version = "9.0.0", features = ["actix-web"] }
[package.metadata.scripts]
db_create = "bash ./scripts/create_db.sh"
diff --git a/README.md b/README.md
index 5c8db30..08f887b 100644
--- a/README.md
+++ b/README.md
@@ -31,3 +31,7 @@ attempts to use a backup sql file to create the database.
You can only search a parameter at a time.
This is because Rust needs to process the sql queries ahead of time
in order to make them safe to injection attacks.
+
+## TODO
+[ ] - User / Password system, use user id to generate tokens
+[ ] - Add documentation (Utoipa)
diff --git a/src/api/search_results.rs b/src/api/search_results.rs
index 8f01e56..9ccb013 100644
--- a/src/api/search_results.rs
+++ b/src/api/search_results.rs
@@ -7,7 +7,6 @@ use serde::Deserialize;
#[derive(Deserialize)]
struct SearchQueryOptions {
- id: Option<String>,
name: Option<String>,
}
@@ -16,23 +15,6 @@ pub async fn search_results(
app_state: web::Data<AppState>,
get_args: web::Query<SearchQueryOptions>,
) -> HttpResponse {
- let default: String = String::default();
-
- if get_args.id.is_some() {
- let id: &str = get_args.id.as_ref().unwrap_or(&default);
- let search_attempt: (
- sqlx::Result<Option<Artist>, sqlx::Error>,
- sqlx::Result<Option<Album>, sqlx::Error>,
- sqlx::Result<Option<Song>, sqlx::Error>,
- ) = { app_state.database.search_results_by_id(id).await };
-
- return HttpResponse::Ok().json((
- search_attempt.0.unwrap_or(None),
- search_attempt.1.unwrap_or(None),
- search_attempt.2.unwrap_or(None),
- ));
- };
-
let search_attempt: (
sqlx::Result<Vec<Artist>, sqlx::Error>,
sqlx::Result<Vec<Album>, sqlx::Error>,
diff --git a/src/database/artist.rs b/src/database/artist.rs
index 018bc17..5dda7a8 100644
--- a/src/database/artist.rs
+++ b/src/database/artist.rs
@@ -1,10 +1,13 @@
use crate::database::DatabaseWrapper;
use serde::{Deserialize, Serialize};
use sqlx::mysql::MySqlQueryResult;
+use utoipa::ToSchema;
-#[derive(Serialize)]
+#[derive(Serialize, ToSchema)]
pub struct Artist {
+ #[schema(example = "Attempt", required = true)]
name: Option<String>,
+ #[schema(example = 3, required = true)]
id: Option<i32>,
}
diff --git a/src/database/search_results.rs b/src/database/search_results.rs
index 1468111..027d160 100644
--- a/src/database/search_results.rs
+++ b/src/database/search_results.rs
@@ -4,21 +4,6 @@ use crate::database::artist::Artist;
use crate::database::album::Album;
impl DatabaseWrapper {
- pub async fn search_results_by_id(
- &self,
- id: &str,
- ) -> (
- Result<Option<Artist>, sqlx::Error>,
- Result<Option<Album>, sqlx::Error>,
- Result<Option<Song>, sqlx::Error>,
- ) {
- (
- self.select_artist_by_id(id).await,
- self.select_album_by_id(id).await,
- self.select_song_by_id(id).await,
- )
- }
-
pub async fn search_results_by_name(
&self,
name: &str,
diff --git a/src/database/song.rs b/src/database/song.rs
index 2b45065..45c217b 100644
--- a/src/database/song.rs
+++ b/src/database/song.rs
@@ -1,8 +1,9 @@
use crate::database::DatabaseWrapper;
use serde::{Deserialize, Serialize};
use sqlx::mysql::MySqlQueryResult;
+use utoipa::ToSchema;
-#[derive(Serialize)]
+#[derive(Serialize, ToSchema)]
pub struct Song {
name: Option<String>,
id: Option<i32>,
diff --git a/src/main.rs b/src/main.rs
index 0151c47..595723a 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -8,6 +8,14 @@ use dotenv::dotenv;
use std::env;
use std::sync::Arc;
+use utoipa::{
+ openapi::security::{HttpAuthScheme, HttpBuilder, SecurityScheme},
+ Modify, OpenApi, ToSchema,
+};
+
+use utoipa_swagger_ui::SwaggerUi;
+use database::artist::Artist;
+
#[derive(Clone)]
struct AppState {
database: Arc<database::DatabaseWrapper>,
@@ -40,11 +48,47 @@ async fn main() -> std::io::Result<()> {
secret: jwt_secret,
};
+ /* utoipa setup */
+ #[derive(OpenApi)]
+ #[openapi(
+ paths(
+ ),
+ components(
+ schemas(
+ Artist
+ )
+ ),
+ modifiers(&SecurityAddon)
+ )]
+ struct ApiDoc;
+
+ struct SecurityAddon;
+ impl Modify for SecurityAddon {
+ fn modify(&self, openapi : &mut utoipa::openapi::OpenApi) {
+ let components = openapi.components.as_mut().unwrap();
+ components.add_security_scheme(
+ "bearer_auth",
+ SecurityScheme::Http(
+ HttpBuilder::new()
+ .scheme(HttpAuthScheme::Bearer)
+ .bearer_format("JWT")
+ .build()
+ ),
+ );
+ }
+ }
+
+ let openapi = ApiDoc::openapi();
+
/* main server setup */
HttpServer::new(move || {
App::new()
.app_data(web::Data::new(app_state.clone()))
.route("/", web::get().to(root))
+ .service(SwaggerUi::new("/docs/{_:.*}").url(
+ "/docs/openapi.json",
+ openapi.clone(),
+ ))
.service(api::api_scope())
.service(auth::auth_scope())
})