diff --git a/Cargo.lock b/Cargo.lock index 62b275d..7837383 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -43,9 +43,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.80" +version = "0.1.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" +checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" dependencies = [ "proc-macro2", "quote", @@ -114,6 +114,29 @@ dependencies = [ "tracing", ] +[[package]] +name = "axum-extra" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0be6ea09c9b96cb5076af0de2e383bd2bc0c18f827cf1967bdd353e0b910d733" +dependencies = [ + "axum", + "axum-core", + "bytes", + "futures-util", + "headers", + "http", + "http-body", + "http-body-util", + "mime", + "pin-project-lite", + "serde", + "tower", + "tower-layer", + "tower-service", + "tracing", +] + [[package]] name = "axum-macros" version = "0.4.1" @@ -141,12 +164,33 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + [[package]] name = "bitflags" version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + [[package]] name = "bumpalo" version = "3.16.0" @@ -198,6 +242,25 @@ version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +[[package]] +name = "cpufeatures" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + [[package]] name = "darling" version = "0.20.9" @@ -273,6 +336,15 @@ dependencies = [ "deadpool-runtime", ] +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", +] + [[package]] name = "diesel" version = "2.2.1" @@ -309,6 +381,16 @@ dependencies = [ "syn", ] +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + [[package]] name = "dotenvy" version = "0.15.7" @@ -383,12 +465,59 @@ dependencies = [ "pin-utils", ] +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + [[package]] name = "gimli" version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" +[[package]] +name = "headers" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "322106e6bd0cba2d5ead589ddb8150a13d7c4217cf80d7c4f682ca994ccc6aa9" +dependencies = [ + "base64 0.21.7", + "bytes", + "headers-core", + "http", + "httpdate", + "mime", + "sha1", +] + +[[package]] +name = "headers-core" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54b4a22553d4242c49fddb9ba998a99962b5cc6f22cb5a3482bec22522403ce4" +dependencies = [ + "http", +] + [[package]] name = "heck" version = "0.4.1" @@ -405,14 +534,21 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" name = "helios-server-rs" version = "0.1.0" dependencies = [ + "async-trait", "axum", + "axum-extra", + "axum-macros", "chrono", "deadpool-diesel", "diesel", "dotenvy", + "jsonwebtoken", + "once_cell", "serde", "serde_json", "tokio", + "tower", + "tower-http", "tracing", "tracing-subscriber", ] @@ -547,6 +683,21 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "jsonwebtoken" +version = "9.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9ae10193d25051e74945f1ea2d0b42e03cc3b890f7e4cc5faa44997d808193f" +dependencies = [ + "base64 0.21.7", + "js-sys", + "pem", + "ring", + "serde", + "serde_json", + "simple_asn1", +] + [[package]] name = "lazy_static" version = "1.5.0" @@ -632,6 +783,31 @@ dependencies = [ "winapi", ] +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -695,6 +871,16 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "pem" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e459365e590736a54c3fa561947c84837534b8e9af6fc5bf781307e82658fae" +dependencies = [ + "base64 0.22.1", + "serde", +] + [[package]] name = "percent-encoding" version = "2.3.1" @@ -733,6 +919,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "pq-sys" version = "0.6.1" @@ -813,6 +1005,21 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin", + "untrusted", + "windows-sys 0.52.0", +] + [[package]] name = "rustc-demangle" version = "0.1.24" @@ -890,6 +1097,17 @@ dependencies = [ "serde", ] +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "sharded-slab" version = "0.1.7" @@ -908,6 +1126,18 @@ dependencies = [ "libc", ] +[[package]] +name = "simple_asn1" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adc4e5204eb1910f40f9cfa375f6f05b68c3abac4b6fd879c8ff5e7ae8a0a085" +dependencies = [ + "num-bigint", + "num-traits", + "thiserror", + "time", +] + [[package]] name = "smallvec" version = "1.13.2" @@ -924,6 +1154,12 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + [[package]] name = "strsim" version = "0.11.1" @@ -953,6 +1189,26 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +[[package]] +name = "thiserror" +version = "1.0.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "thread_local" version = "1.1.8" @@ -963,6 +1219,37 @@ dependencies = [ "once_cell", ] +[[package]] +name = "time" +version = "0.3.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +dependencies = [ + "num-conv", + "time-core", +] + [[package]] name = "tokio" version = "1.38.0" @@ -1009,6 +1296,23 @@ dependencies = [ "tracing", ] +[[package]] +name = "tower-http" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5" +dependencies = [ + "bitflags", + "bytes", + "http", + "http-body", + "http-body-util", + "pin-project-lite", + "tower-layer", + "tower-service", + "tracing", +] + [[package]] name = "tower-layer" version = "0.3.2" @@ -1083,12 +1387,24 @@ dependencies = [ "tracing-log", ] +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + [[package]] name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "valuable" version = "0.1.0" @@ -1101,6 +1417,12 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" diff --git a/Cargo.toml b/Cargo.toml index 40e3ddf..2682e59 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,13 +6,20 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +async-trait = "0.1.81" axum = {version = "0.7.5", features = ["macros"]} +axum-extra = { version = "0.9.3", features = ["typed-header"] } chrono = {version = "0.4", features = ["serde"]} deadpool-diesel = {version ="0.6.1", features = ["postgres"]} diesel = { version = "2", features = ["postgres", "chrono"] } dotenvy = "0.15" +jsonwebtoken = "9.3.0" serde = { version = "1.0.202", features = ["derive"] } serde_json = "1" tokio = { version = "1.37.0", features = ["full"] } +tower = "0.4.13" +tower-http = {version= "0.5.2", features=["trace", "cors"] } tracing = "0.1" tracing-subscriber = { version = "0.3", features = ["env-filter"] } +once_cell = "1.19.0" +axum-macros = "0.4.1" diff --git a/src/category/handler.rs b/src/category/handler.rs index 804f2c9..65af9ed 100644 --- a/src/category/handler.rs +++ b/src/category/handler.rs @@ -1,16 +1,24 @@ // use std::sync::Arc; -use axum::{http::StatusCode, extract::{State,Path}, Json, Router}; use axum::routing::{get, post}; +use axum::{ + extract::{Path, State}, + http::StatusCode, + Json, Router, +}; +use axum_macros::debug_handler; use diesel::prelude::*; // use diesel::update; use serde::{Deserialize, Serialize}; // use serde_json::to_string; -use crate::util; -use crate::model::schema; use crate::model::db_model; +use crate::model::schema; +use crate::util; // use crate::model::schema::categories::dsl::categories; use crate::util::req::CommonResp; use chrono::prelude::*; +use tracing::info; +use crate::middleware::auth; +use crate::middleware::auth::Claims; #[derive(Serialize)] pub struct CreateCategoryResponse { @@ -29,16 +37,22 @@ pub struct CreateCategoryRequest { name: String, } +#[debug_handler] pub async fn create_category( State(app_state): State, - Json(Payload): Json, + claims: Claims, + Json(payload): Json, ) -> Result, (StatusCode, String)> { - let uid: i64 = 123214124; // TODO replace with actual user id. - // let ret = CreateCategoryResponse{id: 134132413541, name: "24532452".to_string()}; - let conn = app_state.db.get().await.map_err(util::req::internal_error)?; - let new_category = db_model::CategoryForm{ - name: Payload.name, - uid: uid, + let uid: i64 = claims.uid.clone(); // TODO replace with actual user id. + // let ret = CreateCategoryResponse{id: 134132413541, name: "24532452".to_string()}; + let conn = app_state + .db + .get() + .await + .map_err(util::req::internal_error)?; + let new_category = db_model::CategoryForm { + name: payload.name, + uid, }; let res = conn .interact(move |conn| { @@ -57,11 +71,16 @@ pub async fn create_category( pub async fn update_category( Path(id): Path, State(app_state): State, - Json(Payload): Json, + claims: Claims, + Json(payload): Json, ) -> Result, (StatusCode, String)> { - let uid: i64 = 123214124; // TODO replace with actual user id. - // let ret = CreateCategoryResponse{id: 134132413541, name: "24532452".to_string()}; - let conn = app_state.db.get().await.map_err(util::req::internal_error)?; + let uid: i64 = claims.uid.clone(); // TODO replace with actual user id. + // let ret = CreateCategoryResponse{id: 134132413541, name: "24532452".to_string()}; + let conn = app_state + .db + .get() + .await + .map_err(util::req::internal_error)?; let now = Utc::now().naive_utc(); let res = conn .interact(move |conn| { @@ -69,8 +88,8 @@ pub async fn update_category( .filter(schema::categories::id.eq(id)) .filter(schema::categories::uid.eq(uid)) .set(( - schema::categories::name.eq(Payload.name), - schema::categories::update_at.eq(now), + schema::categories::name.eq(payload.name), + schema::categories::update_at.eq(now), )) .execute(conn) }) @@ -78,18 +97,21 @@ pub async fn update_category( .map_err(util::req::internal_error)? .map_err(util::req::internal_error)?; // let ret = CreateCategoryResponse{id: res.id, name: res.name}; - let resp = util::req::CommonResp{ - code: 0, - }; + let resp = util::req::CommonResp { code: 0 }; Ok(Json(resp)) } pub async fn get_category( Path(id): Path, State(app_state): State, -) -> Result, (StatusCode, String)>{ - let uid: i64 = 123214124; // TODO replace with actual user id. - let conn = app_state.db.get().await.map_err(util::req::internal_error)?; + claims: Claims, +) -> Result, (StatusCode, String)> { + let uid: i64 = claims.uid.clone(); + let conn = app_state + .db + .get() + .await + .map_err(util::req::internal_error)?; let res = conn .interact(move |conn| { schema::categories::table @@ -107,9 +129,14 @@ pub async fn get_category( pub async fn get_all_categories( State(app_state): State, -) -> Result>, (StatusCode, String)>{ - let uid: i64 = 123214124; // TODO replace with actual user id. - let conn = app_state.db.get().await.map_err(util::req::internal_error)?; + claims: Claims, +) -> Result>, (StatusCode, String)> { + let uid: i64 = claims.uid.clone(); + let conn = app_state + .db + .get() + .await + .map_err(util::req::internal_error)?; let res = conn .interact(move |conn| { schema::categories::table diff --git a/src/category/mod.rs b/src/category/mod.rs index ef7d850..062ae9d 100644 --- a/src/category/mod.rs +++ b/src/category/mod.rs @@ -1 +1 @@ -pub mod handler; \ No newline at end of file +pub mod handler; diff --git a/src/main.rs b/src/main.rs index cc8c945..7988cb8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,25 +4,32 @@ use axum::{ // Json, Router, }; +use axum::http::Method; use serde::{Deserialize, Serialize}; +use tower::ServiceBuilder; +use tower_http::cors::{Any, CorsLayer}; +use tower_http::trace::TraceLayer; use tracing::info; use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt}; // Project modules mod category; +mod middleware; mod model; mod util; // Passed App State #[derive(Clone)] -pub struct AppState{ +pub struct AppState { db: deadpool_diesel::postgres::Pool, } #[tokio::main] async fn main() { dotenvy::dotenv().unwrap(); - tracing_subscriber::registry().with(tracing_subscriber::fmt::layer()).init(); + tracing_subscriber::registry() + .with(tracing_subscriber::fmt::layer()) + .init(); // initialize db connection let db_url = std::env::var("DATABASE_URL").unwrap(); @@ -31,14 +38,22 @@ async fn main() { .build() .unwrap(); - - let shared_state = AppState {db: pool,}; + let shared_state = AppState { db: pool }; // Register routers + let cors_layer = CorsLayer::new() + .allow_methods([Method::GET, Method::POST]) + .allow_origin(Any); + let global_layer = ServiceBuilder::new() + .layer(TraceLayer::new_for_http()) + .layer(cors_layer); + let app = Router::new() // V1 apis .nest("/api/v1/category", category::handler::get_nest_handlers()) - .with_state(shared_state); + .nest("/api/v1/v2", category::handler::get_nest_handlers()) + .with_state(shared_state) + .layer(global_layer); let listener = tokio::net::TcpListener::bind("0.0.0.0:8987").await.unwrap(); info!("starting server on 0.0.0.0:8987"); diff --git a/src/middleware/auth.rs b/src/middleware/auth.rs new file mode 100644 index 0000000..b9e12c3 --- /dev/null +++ b/src/middleware/auth.rs @@ -0,0 +1,118 @@ +use axum::{ + async_trait, + extract::FromRequestParts, + http::{ + request::Parts, + StatusCode, + }, + Json, RequestPartsExt, + response::{IntoResponse, Response}, +}; +use axum_extra::{ + headers::{authorization::Bearer, Authorization}, + TypedHeader, +}; +use serde::{Deserialize, Serialize}; +use serde_json::json; +use jsonwebtoken::{decode,encode, DecodingKey, EncodingKey, Header, Validation}; +use std::fmt::Display; +use once_cell::sync::Lazy; +use crate::util; + +#[derive(Debug, Serialize, Deserialize)] +pub struct Claims { + sub: String, + company: String, + exp: usize, + pub uid: i64, +} + +#[derive(Debug, Serialize)] +struct AuthBody { + access_token: String, + token_type: String, +} + +#[derive(Debug, Deserialize)] +struct AuthPayload { + client_id: String, + client_secret: String, +} + +#[derive(Debug)] +pub enum AuthError { + WrongCredentials, + MissingCredentials, + TokenCreation, + InvalidToken, +} + +static KEYS: Lazy = Lazy::new(|| { + let secret = std::env::var("JWT_SECRET").expect("JWT_SECRET must be set"); + Keys::new(secret.as_bytes()) +}); + +struct Keys { + encoding: EncodingKey, + decoding: DecodingKey, +} + +impl Keys { + fn new(secret: &[u8]) -> Self { + Self { + encoding: EncodingKey::from_secret(secret), + decoding: DecodingKey::from_secret(secret), + } + } +} + +impl Display for Claims { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "Email: {}\nCompany: {}", self.sub, self.company) + } +} + +impl AuthBody { + fn new(access_token: String) -> Self { + Self { + access_token, + token_type: "Bearer".to_string(), + } + } +} + +#[async_trait] +impl FromRequestParts for Claims +where + S: Send + Sync, +{ + type Rejection = (StatusCode, String); + + async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result { + // Extract the token from the authorization header + let TypedHeader(Authorization(bearer)) = parts + .extract::>>() + .await + .map_err(util::req::internal_error)?; + // Decode the user data + let token_data = decode::(bearer.token(), &KEYS.decoding, &Validation::default()) + .map_err(util::req::internal_error)?; + + Ok(token_data.claims) + } +} + +impl IntoResponse for AuthError { + fn into_response(self) -> Response { + let (status, error_message) = match self { + AuthError::WrongCredentials => (StatusCode::UNAUTHORIZED, "Wrong credentials"), + AuthError::MissingCredentials => (StatusCode::BAD_REQUEST, "Missing credentials"), + AuthError::TokenCreation => (StatusCode::INTERNAL_SERVER_ERROR, "Token creation error"), + AuthError::InvalidToken => (StatusCode::BAD_REQUEST, "Invalid token"), + }; + let body = Json(json!({ + "error": error_message, + })); + (status, body).into_response() + } +} diff --git a/src/middleware/mod.rs b/src/middleware/mod.rs new file mode 100644 index 0000000..0e4a05d --- /dev/null +++ b/src/middleware/mod.rs @@ -0,0 +1 @@ +pub mod auth; diff --git a/src/model/db_model.rs b/src/model/db_model.rs index 5e5f85a..17123cd 100644 --- a/src/model/db_model.rs +++ b/src/model/db_model.rs @@ -1,8 +1,7 @@ -use diesel::prelude::*; use crate::model::schema; +use diesel::prelude::*; -#[derive(Queryable, Selectable)] -#[derive(serde::Serialize, serde::Deserialize)] +#[derive(Queryable, Selectable, serde::Serialize, serde::Deserialize)] #[diesel(table_name = schema::categories)] #[diesel(check_for_backend(diesel::pg::Pg))] pub struct Category { diff --git a/src/model/mod.rs b/src/model/mod.rs index 8aa3176..37c9ce0 100644 --- a/src/model/mod.rs +++ b/src/model/mod.rs @@ -1,2 +1,2 @@ +pub mod db_model; pub mod schema; -pub mod db_model; \ No newline at end of file diff --git a/src/util/mod.rs b/src/util/mod.rs index 37c6167..1b7e472 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -1 +1 @@ -pub mod req; \ No newline at end of file +pub mod req;