feat: add auth
This commit is contained in:
@@ -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,19 +33,19 @@ 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>,
|
||||||
) -> Result<Json<Vec<book::BookItem>>,(StatusCode,String)> {
|
claims: Claims,
|
||||||
// let conn = state.conn.get_postgres_connection_pool();
|
) -> Result<Json<Vec<book::BookItem>>, (StatusCode, String)> {
|
||||||
let uid :i64 = 1;
|
let uid: i64 = claims.uid.clone();
|
||||||
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)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR,e.to_string()))?;
|
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
|
||||||
|
|
||||||
let mut books: Vec<BookItem> = Vec::new();
|
let mut books: Vec<BookItem> = Vec::new();
|
||||||
for b in all_books {
|
for b in all_books {
|
||||||
let book_resp = BookItem{
|
let book_resp = BookItem {
|
||||||
id: b.id,
|
id: b.id,
|
||||||
name: b.name,
|
name: b.name,
|
||||||
};
|
};
|
||||||
@@ -54,11 +56,11 @@ async fn get_all_books_handler(
|
|||||||
|
|
||||||
#[debug_handler]
|
#[debug_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>,
|
||||||
) -> Result<Json<BookItem>,(StatusCode,String)> {
|
claims: Claims,
|
||||||
// let conn = state.conn.get_postgres_connection_pool();
|
) -> Result<Json<BookItem>, (StatusCode, String)> {
|
||||||
let uid: i64 = 1;
|
let uid: i64 = claims.uid.clone();
|
||||||
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))
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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,8 +94,12 @@ 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>(
|
||||||
.map_err(|_| AuthError::InvalidToken)?;
|
bearer.token(),
|
||||||
|
&KEYS.get().unwrap().decoding,
|
||||||
|
&Validation::default(),
|
||||||
|
)
|
||||||
|
.map_err(|_| AuthError::InvalidToken)?;
|
||||||
|
|
||||||
Ok(token_data.claims)
|
Ok(token_data.claims)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user