Docs authorization for protected routes
This commit is contained in:
parent
bc3469fa88
commit
2673f48ade
3
TODO.md
3
TODO.md
@ -4,7 +4,8 @@ Tasks that have been completed in commits before this one have been omitted from
|
|||||||
|
|
||||||
- [x] /video PUT route
|
- [x] /video PUT route
|
||||||
- [x] /channel PUT route
|
- [x] /channel PUT route
|
||||||
- [x] OpenAPI documentation
|
- [x] OpenAPI docs
|
||||||
|
- [x] Add authorization for protected routes in API docs
|
||||||
|
|
||||||
## Planned features
|
## Planned features
|
||||||
|
|
||||||
|
24
src/doc.rs
24
src/doc.rs
@ -1,4 +1,10 @@
|
|||||||
use utoipa::OpenApi;
|
use utoipa::{
|
||||||
|
Modify, OpenApi,
|
||||||
|
openapi::{
|
||||||
|
Components,
|
||||||
|
security::{ApiKey, ApiKeyValue, SecurityScheme},
|
||||||
|
},
|
||||||
|
};
|
||||||
use utoipa_swagger_ui::SwaggerUi;
|
use utoipa_swagger_ui::SwaggerUi;
|
||||||
|
|
||||||
// Because apparently the OpenApi macro can't import these on its own
|
// Because apparently the OpenApi macro can't import these on its own
|
||||||
@ -36,10 +42,24 @@ use crate::routes::{
|
|||||||
info(
|
info(
|
||||||
title = "Almond API",
|
title = "Almond API",
|
||||||
description = "Interface to archive YouTube videos."
|
description = "Interface to archive YouTube videos."
|
||||||
)
|
),
|
||||||
|
modifiers(&SecurityAddon),
|
||||||
)]
|
)]
|
||||||
struct ApiDoc;
|
struct ApiDoc;
|
||||||
|
|
||||||
|
struct SecurityAddon;
|
||||||
|
|
||||||
|
impl Modify for SecurityAddon {
|
||||||
|
fn modify(&self, openapi: &mut utoipa::openapi::OpenApi) {
|
||||||
|
let components = openapi.components.get_or_insert_with(Components::default);
|
||||||
|
|
||||||
|
components.add_security_scheme(
|
||||||
|
"authKey",
|
||||||
|
SecurityScheme::ApiKey(ApiKey::Header(ApiKeyValue::with_description("almond-api-key", "The API key/password that must be sent at the request header for protected routes."))),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn docs_router() -> SwaggerUi {
|
pub fn docs_router() -> SwaggerUi {
|
||||||
SwaggerUi::new("/docs").url("/api-doc/openapi.json", ApiDoc::openapi())
|
SwaggerUi::new("/docs").url("/api-doc/openapi.json", ApiDoc::openapi())
|
||||||
}
|
}
|
||||||
|
@ -104,7 +104,7 @@ pub struct UploadChannelQuery {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Upload a channel's metadata to the database
|
/// Upload a channel's metadata to the database
|
||||||
#[utoipa::path(post, path = "/channel", request_body = UploadChannelQuery, params(("url" = String, Query), ("almond-api-key" = String, description = "API key")), tags = ["channel"], responses((status = 200, description = "Channel already exists, skipping"), (status = 201, description = "Channel uploaded successfully"), (status = 400, description = "Bad request, likely a malformed URL"), (status = 401, description = "Unauthorized"), (status = 500, description = "Failed to upload channel to database")))]
|
#[utoipa::path(post, path = "/channel", request_body = UploadChannelQuery, params(("url" = String, Query)), tags = ["channel"], responses((status = 200, description = "Channel already exists, skipping"), (status = 201, description = "Channel uploaded successfully"), (status = 400, description = "Bad request, likely a malformed URL"), (status = 401, description = "Unauthorized"), (status = 500, description = "Failed to upload channel to database")), security(("authKey" = [])))]
|
||||||
pub async fn upload_channel(
|
pub async fn upload_channel(
|
||||||
State(state): State<Instance>,
|
State(state): State<Instance>,
|
||||||
Query(query): Query<UploadChannelQuery>,
|
Query(query): Query<UploadChannelQuery>,
|
||||||
@ -177,7 +177,7 @@ pub async fn upload_channel(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Update an existing channel from the database
|
/// Update an existing channel from the database
|
||||||
#[utoipa::path(put, path = "/channel/{id}", params(("almond-api-key" = String, description = "API key")), tags = ["channel"], responses((status = 204, description = "Channel updated successfully"), (status = 404, description = "Video with specified ID not found"), (status = 500, description = "Failed to update channel from database")))]
|
#[utoipa::path(put, path = "/channel/{id}", params(("almond-api-key" = String, description = "API key")), tags = ["channel"], responses((status = 204, description = "Channel updated successfully"), (status = 404, description = "Video with specified ID not found"), (status = 500, description = "Failed to update channel from database")), security(("authKey" = [])))]
|
||||||
pub async fn update_channel(State(state): State<Instance>, Path(id): Path<String>) -> StatusCode {
|
pub async fn update_channel(State(state): State<Instance>, Path(id): Path<String>) -> StatusCode {
|
||||||
match sqlx::query_as!(Channel, "SELECT * FROM channel WHERE youtube_id = ?", id)
|
match sqlx::query_as!(Channel, "SELECT * FROM channel WHERE youtube_id = ?", id)
|
||||||
.fetch_optional(&state.pool)
|
.fetch_optional(&state.pool)
|
||||||
@ -222,7 +222,7 @@ pub async fn update_channel(State(state): State<Instance>, Path(id): Path<String
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Delete a channel from the database
|
/// Delete a channel from the database
|
||||||
#[utoipa::path(delete, path = "/channel/{id}", params(("almond-api-key" = String, description = "API key")), tags = ["channel"], responses((status = 204, description = "Channel deleted successfully"), (status = 404, description = "Video with specified ID not found"), (status = 500, description = "Failed to delete channel from database")))]
|
#[utoipa::path(delete, path = "/channel/{id}", params(("almond-api-key" = String, description = "API key")), tags = ["channel"], responses((status = 204, description = "Channel deleted successfully"), (status = 404, description = "Video with specified ID not found"), (status = 500, description = "Failed to delete channel from database")), security(("authKey" = [])))]
|
||||||
pub async fn delete_channel(State(state): State<Instance>, Path(id): Path<String>) -> StatusCode {
|
pub async fn delete_channel(State(state): State<Instance>, Path(id): Path<String>) -> StatusCode {
|
||||||
match sqlx::query!("DELETE FROM channel WHERE youtube_id = ?", id)
|
match sqlx::query!("DELETE FROM channel WHERE youtube_id = ?", id)
|
||||||
.fetch_optional(&state.pool)
|
.fetch_optional(&state.pool)
|
||||||
|
@ -85,7 +85,7 @@ pub struct UploadVideoQuery {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Upload a video to the database
|
/// Upload a video to the database
|
||||||
#[utoipa::path(post, path = "/video", request_body = UploadVideoQuery, params(("url" = String, Query), ("almond-api-key" = String, description = "API key")), tags = ["video"], responses((status = 200, description = "Video already exists, skipping"), (status = 201, description = "Video uploaded successfully"), (status = 400, description = "Bad request, likely a malformed URL"), (status = 401, description = "Unauthorized"), (status = 500, description = "Failed to upload video to database")))]
|
#[utoipa::path(post, path = "/video", request_body = UploadVideoQuery, params(("url" = String, Query), ("almond-api-key" = String, description = "API key")), tags = ["video"], responses((status = 200, description = "Video already exists, skipping"), (status = 201, description = "Video uploaded successfully"), (status = 400, description = "Bad request, likely a malformed URL"), (status = 401, description = "Unauthorized"), (status = 500, description = "Failed to upload video to database")), security(("authKey" = [])))]
|
||||||
pub async fn upload_video(
|
pub async fn upload_video(
|
||||||
State(state): State<Instance>,
|
State(state): State<Instance>,
|
||||||
Query(query): Query<UploadVideoQuery>,
|
Query(query): Query<UploadVideoQuery>,
|
||||||
@ -162,7 +162,7 @@ pub async fn upload_video(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Update an existing video from the database
|
/// Update an existing video from the database
|
||||||
#[utoipa::path(put, path = "/video/{id}", params(("almond-api-key" = String, description = "API key")), tags = ["video"], responses((status = 204, description = "Video updated successfully"), (status = 404, description = "Video with specified ID not found"), (status = 500, description = "Failed to update video from database")))]
|
#[utoipa::path(put, path = "/video/{id}", params(("almond-api-key" = String, description = "API key")), tags = ["video"], responses((status = 204, description = "Video updated successfully"), (status = 404, description = "Video with specified ID not found"), (status = 500, description = "Failed to update video from database")), security(("authKey" = [])))]
|
||||||
pub async fn update_video(State(state): State<Instance>, Path(id): Path<String>) -> StatusCode {
|
pub async fn update_video(State(state): State<Instance>, Path(id): Path<String>) -> StatusCode {
|
||||||
match sqlx::query_as!(Video, "SELECT * FROM video WHERE youtube_id = ?", id)
|
match sqlx::query_as!(Video, "SELECT * FROM video WHERE youtube_id = ?", id)
|
||||||
.fetch_optional(&state.pool)
|
.fetch_optional(&state.pool)
|
||||||
@ -205,7 +205,7 @@ pub async fn update_video(State(state): State<Instance>, Path(id): Path<String>)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Delete a video from the database
|
/// Delete a video from the database
|
||||||
#[utoipa::path(delete, path = "/video/{id}", params(("almond-api-key" = String, description = "API key")), tags = ["video"], responses((status = 204, description = "Video deleted successfully"), (status = 404, description = "Video with specified ID not found"), (status = 500, description = "Failed to delete video from database")))]
|
#[utoipa::path(delete, path = "/video/{id}", params(("almond-api-key" = String, description = "API key")), tags = ["video"], responses((status = 204, description = "Video deleted successfully"), (status = 404, description = "Video with specified ID not found"), (status = 500, description = "Failed to delete video from database")), security(("authKey" = [])))]
|
||||||
pub async fn delete_video(State(state): State<Instance>, Path(id): Path<String>) -> StatusCode {
|
pub async fn delete_video(State(state): State<Instance>, Path(id): Path<String>) -> StatusCode {
|
||||||
match sqlx::query!("DELETE FROM video WHERE youtube_id = ?", id)
|
match sqlx::query!("DELETE FROM video WHERE youtube_id = ?", id)
|
||||||
.fetch_optional(&state.pool)
|
.fetch_optional(&state.pool)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user