Compare commits
3 Commits
69652743b5
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 1c8fe09b1f | |||
| ce04aa5947 | |||
| 4251f6981d |
15
Cargo.lock
generated
15
Cargo.lock
generated
@@ -70,6 +70,7 @@ dependencies = [
|
||||
"sqlx",
|
||||
"tokio",
|
||||
"tower",
|
||||
"tower-http",
|
||||
"utoipa",
|
||||
"utoipa-axum",
|
||||
"utoipa-swagger-ui",
|
||||
@@ -1889,6 +1890,20 @@ dependencies = [
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tower-http"
|
||||
version = "0.6.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"bytes",
|
||||
"http",
|
||||
"pin-project-lite",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tower-layer"
|
||||
version = "0.3.3"
|
||||
|
||||
@@ -7,6 +7,7 @@ edition = "2021"
|
||||
axum = { version = "0.8.1", features = ["macros", "json"] }
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
tower = "0.5"
|
||||
tower-http = { version = "0.6.2", features = ["cors"] }
|
||||
utoipa = { version = "5.3.1", features = ["axum_extras"] }
|
||||
utoipa-swagger-ui = { version = "9.0.0", features = ["axum"] }
|
||||
utoipa-axum = "0.2.0"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
mod db
|
||||
_default:
|
||||
just --list api
|
||||
just --list
|
||||
|
||||
migrate:
|
||||
sqlx migrate run
|
||||
@@ -9,4 +9,7 @@ build:
|
||||
cargo build --release
|
||||
|
||||
run:
|
||||
cargo run
|
||||
cargo run
|
||||
|
||||
dev:
|
||||
cargo watch -x run -i "openapi.json"
|
||||
@@ -2,7 +2,7 @@ name: uplifting-api
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:latest
|
||||
container_name: postgres-uplifting-api
|
||||
container_name: postgres
|
||||
ports:
|
||||
- "5401:5432"
|
||||
environment:
|
||||
@@ -10,7 +10,7 @@ services:
|
||||
POSTGRES_PASSWORD: postgres
|
||||
POSTGRES_DB: postgres
|
||||
volumes:
|
||||
- ~/databases/uplifting-api-postgres-data:/var/lib/postgresql
|
||||
- pg-data:/var/lib/postgresql
|
||||
|
||||
volumes:
|
||||
postgres-data:
|
||||
pg-data:
|
||||
|
||||
1
openapi.json
Normal file
1
openapi.json
Normal file
@@ -0,0 +1 @@
|
||||
{"openapi":"3.1.0","info":{"title":"api","description":"","license":{"name":""},"version":"0.1.0"},"paths":{"/":{"get":{"operationId":"index","responses":{"200":{"description":"Success","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/.well-known/health-check":{"get":{"summary":"Get health of the API.","operationId":"health_check","responses":{"200":{"description":"Success","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/api/v1/auth/login":{"post":{"tags":["auth"],"summary":"Login","operationId":"login","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginBody"}}},"required":true},"responses":{"200":{"description":"","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/api/v1/auth/signup":{"post":{"tags":["auth"],"summary":"Sign up","operationId":"signup","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignupBody"}}},"required":true},"responses":{"200":{"description":"","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/api/v1/exercises/create":{"post":{"tags":["exercises"],"operationId":"create","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateExerciseBody"}}},"required":true},"responses":{"200":{"description":"","content":{"text/plain":{"schema":{"type":"string"}}}}}}},"/api/v1/muscles/all":{"get":{"tags":["muscles"],"operationId":"get_all","responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Muscle"}}}}}}},"/api/v1/muscles/create":{"post":{"tags":["muscles"],"operationId":"create","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateMuscleBody"}}},"required":true},"responses":{"200":{"description":"","content":{"text/plain":{"schema":{"type":"string"}}}}}}}},"components":{"schemas":{"CreateExerciseBody":{"type":"object","required":["name","exercise_type","description","body_parts","primary_muscles","secondary_muscles"],"properties":{"body_parts":{"type":"array","items":{"type":"string"}},"description":{"type":"string"},"exercise_type":{"$ref":"#/components/schemas/ExerciseType"},"name":{"type":"string"},"primary_muscles":{"type":"array","items":{"type":"string"}},"secondary_muscles":{"type":"array","items":{"type":"string"}}}},"CreateMuscleBody":{"type":"object","required":["name","scientific_name","major_group","minor_group"],"properties":{"major_group":{"type":"string"},"minor_group":{"type":"string"},"name":{"type":"string"},"scientific_name":{"type":"string"}}},"ExerciseType":{"type":"string","enum":["Dumbbell","Barbell","Bodyweight","Machine","Kettlebell","ResistanceBand","Cable","MedicineBall","Plyometric","PlateLoadedMachine"]},"LoginBody":{"type":"object","required":["username","password"],"properties":{"password":{"type":"string"},"username":{"type":"string"}}},"Muscle":{"type":"object","required":["id","name","minor_group"],"properties":{"id":{"type":"string"},"major_group":{"type":["string","null"]},"minor_group":{"type":"string"},"name":{"type":"string"},"scientific_name":{"type":["string","null"]}}},"SignupBody":{"type":"object","required":["real_name","username","email","password"],"properties":{"email":{"type":"string"},"password":{"type":"string"},"real_name":{"type":"string"},"username":{"type":"string"}}}}},"tags":[{"name":"auth","description":"Authentication API endpoints"},{"name":"exercises","description":"Exercise API endpoints"},{"name":"muscles","description":"Muscle API endpoints"}]}
|
||||
10
src/main.rs
10
src/main.rs
@@ -1,6 +1,8 @@
|
||||
use std::{net::Ipv4Addr, sync::Arc};
|
||||
use axum::http::Method;
|
||||
use hmac::{Hmac, Mac};
|
||||
use tokio::net::TcpListener;
|
||||
use tower_http::cors::{Any, CorsLayer};
|
||||
use utoipa::OpenApi;
|
||||
use utoipa_axum::{router::OpenApiRouter, routes};
|
||||
use utoipa_swagger_ui::SwaggerUi;
|
||||
@@ -69,13 +71,21 @@ async fn main() -> anyhow::Result<()> {
|
||||
jwt_key: Hmac::new_from_slice(jwt_secret.as_bytes()).context("Failed to create HMAC")?
|
||||
};
|
||||
|
||||
let cors = CorsLayer::new()
|
||||
.allow_methods(Any)
|
||||
.allow_origin(["http://localhost:5173".parse().unwrap()])
|
||||
.allow_headers(Any);
|
||||
|
||||
let (router, api) = OpenApiRouter::with_openapi(ApiDoc::openapi())
|
||||
.routes(routes!(health_check))
|
||||
.routes(routes!(index))
|
||||
.with_state(state.clone())
|
||||
.nest("/api/v1", v1::router(state.clone()))
|
||||
.layer(cors)
|
||||
.split_for_parts();
|
||||
|
||||
tokio::fs::write("openapi.json", api.to_json()?).await?;
|
||||
|
||||
let router = router.merge(SwaggerUi::new("/docs").url("/docs/openapi.json", api));
|
||||
|
||||
println!("Listening on http://localhost:{port}");
|
||||
|
||||
@@ -29,7 +29,7 @@ pub async fn login(
|
||||
.await?;
|
||||
|
||||
let argon2 = Argon2::default();
|
||||
let hash = PasswordHash::new(&body.password).expect("Password hashing failed");
|
||||
let hash = PasswordHash::new(&user.password_hash).expect("Password hashing failed");
|
||||
|
||||
if !argon2
|
||||
.verify_password(body.password.as_bytes(), &hash)
|
||||
|
||||
Reference in New Issue
Block a user