feat: add auth

This commit is contained in:
brian
2025-06-08 22:24:44 +08:00
parent c3493cbe6f
commit e6a32eab51
3 changed files with 40 additions and 30 deletions

View File

@@ -6,6 +6,8 @@ use axum::{
}; };
use axum_macros::debug_handler; use axum_macros::debug_handler;
use crate::middleware::auth;
use crate::middleware::auth::Claims;
use crate::model::db::book::ActiveModel as BookActiveModel; use crate::model::db::book::ActiveModel as BookActiveModel;
use crate::model::db::book::Column as BookColumn; use crate::model::db::book::Column as BookColumn;
use crate::model::db::book::Model as BookModel; use crate::model::db::book::Model as BookModel;
@@ -31,10 +33,10 @@ pub fn get_nest_handlers() -> Router<crate::AppState> {
// //
#[debug_handler] #[debug_handler]
async fn get_all_books_handler( async fn get_all_books_handler(
state: State<AppState> state: State<AppState>,
claims: Claims,
) -> Result<Json<Vec<book::BookItem>>, (StatusCode, String)> { ) -> Result<Json<Vec<book::BookItem>>, (StatusCode, String)> {
// let conn = state.conn.get_postgres_connection_pool(); let uid: i64 = claims.uid.clone();
let uid :i64 = 1;
let all_books = Book::find() let all_books = Book::find()
.filter(BookColumn::Uid.eq(uid)) .filter(BookColumn::Uid.eq(uid))
.all(&state.conn) .all(&state.conn)
@@ -56,9 +58,9 @@ async fn get_all_books_handler(
async fn get_book_by_id_handler( async fn get_book_by_id_handler(
Path(id): Path<i64>, Path(id): Path<i64>,
state: State<AppState>, state: State<AppState>,
claims: Claims,
) -> Result<Json<BookItem>, (StatusCode, String)> { ) -> Result<Json<BookItem>, (StatusCode, String)> {
// let conn = state.conn.get_postgres_connection_pool(); let uid: i64 = claims.uid.clone();
let uid: i64 = 1;
let book_query = Book::find() let book_query = Book::find()
.filter(BookColumn::Uid.eq(uid)) .filter(BookColumn::Uid.eq(uid))
.filter(BookColumn::Id.eq(id)) .filter(BookColumn::Id.eq(id))
@@ -84,10 +86,10 @@ async fn get_book_by_id_handler(
#[debug_handler] #[debug_handler]
async fn create_book_handler( async fn create_book_handler(
state: State<AppState>, state: State<AppState>,
claims: Claims,
Json(payload): Json<BookInfo>, Json(payload): Json<BookInfo>,
) -> Result<Json<SimpleResponse>, (StatusCode, String)> { ) -> Result<Json<SimpleResponse>, (StatusCode, String)> {
// let conn = state.conn.get_postgres_connection_pool(); let uid: i64 = claims.uid.clone();
let uid: i64 = 1;
let book = BookActiveModel { let book = BookActiveModel {
name: Set(payload.name.clone().to_owned()), name: Set(payload.name.clone().to_owned()),
@@ -121,10 +123,10 @@ async fn create_book_handler(
async fn update_book_handler( async fn update_book_handler(
Path(id): Path<i64>, Path(id): Path<i64>,
state: State<AppState>, state: State<AppState>,
claims: Claims,
Json(payload): Json<BookInfo>, Json(payload): Json<BookInfo>,
) -> Result<Json<SimpleResponse>, (StatusCode, String)> { ) -> Result<Json<SimpleResponse>, (StatusCode, String)> {
// let conn = state.conn.get_postgres_connection_pool(); let uid: i64 = claims.uid.clone();
let uid: i64 = 1;
let exist_book = Book::find() let exist_book = Book::find()
.filter(BookColumn::Uid.eq(uid)) .filter(BookColumn::Uid.eq(uid))

View File

@@ -1,3 +1,4 @@
use crate::middleware::auth;
use axum::{http::Method, Router}; use axum::{http::Method, Router};
use clap::Parser; use clap::Parser;
use sea_orm::{Database, DatabaseConnection}; use sea_orm::{Database, DatabaseConnection};
@@ -91,6 +92,8 @@ async fn start_server(config: &Config) {
.await .await
.expect("Database connection failed."); .expect("Database connection failed.");
auth::initialize_jwt_key(config.keys.jwt.clone());
let state = AppState { conn }; let state = AppState { conn };
// Build router // Build router
let cors_layer = CorsLayer::new() let cors_layer = CorsLayer::new()

View File

@@ -1,22 +1,18 @@
use axum::{ use axum::{
extract::FromRequestParts, extract::FromRequestParts,
http::{ http::{request::Parts, StatusCode},
request::Parts,
StatusCode,
},
Json, RequestPartsExt,
response::{IntoResponse, Response}, response::{IntoResponse, Response},
Json, RequestPartsExt,
}; };
use axum_extra::{ use axum_extra::{
headers::{authorization::Bearer, Authorization}, headers::{authorization::Bearer, Authorization},
TypedHeader, TypedHeader,
}; };
use jsonwebtoken::{decode, encode, DecodingKey, EncodingKey, Header, Validation};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serde_json::json; use serde_json::json;
use jsonwebtoken::{decode,encode, DecodingKey, EncodingKey, Header, Validation};
use std::fmt::Display; use std::fmt::Display;
use once_cell::sync::Lazy; use std::sync::OnceLock;
use crate::util;
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
pub struct Claims { pub struct Claims {
@@ -46,10 +42,15 @@ pub enum AuthError {
InvalidToken, InvalidToken,
} }
static KEYS: Lazy<Keys> = Lazy::new(|| { static KEYS: OnceLock<Keys> = OnceLock::new();
let secret = std::env::var("JWT_SECRET").expect("JWT_SECRET must be set");
Keys::new(secret.as_bytes()) pub fn initialize_jwt_key(key_str: String) {
}); let res = KEYS.set(Keys::new(key_str.as_bytes()));
match res {
Ok(_) => {}
Err(_) => panic!("jwt key initialize failed"),
}
}
struct Keys { struct Keys {
encoding: EncodingKey, encoding: EncodingKey,
@@ -93,7 +94,11 @@ where
.await .await
.map_err(|_| AuthError::InvalidToken)?; .map_err(|_| AuthError::InvalidToken)?;
// Decode the user data // Decode the user data
let token_data = decode::<Claims>(bearer.token(), &KEYS.decoding, &Validation::default()) let token_data = decode::<Claims>(
bearer.token(),
&KEYS.get().unwrap().decoding,
&Validation::default(),
)
.map_err(|_| AuthError::InvalidToken)?; .map_err(|_| AuthError::InvalidToken)?;
Ok(token_data.claims) Ok(token_data.claims)