-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
new file: .gitignore new file: Cargo.toml new file: src/entities/cart.rs new file: src/entities/category.rs new file: src/entities/mod.rs new file: src/entities/product.rs new file: src/entities/user.rs new file: src/main.rs new file: src/middleware/auth.rs new file: src/middleware/mod.rs new file: src/routes/auth_routes.rs new file: src/routes/mod.rs new file: tests/auth.rs
- Loading branch information
1 parent
ec2ab99
commit bd766e7
Showing
14 changed files
with
568 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
DATABASE_URL=sqlite::memory: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
/target | ||
/Cargo.lock | ||
/TODO |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
[package] | ||
name = "rust-baranki" | ||
version = "0.1.0" | ||
edition = "2021" | ||
|
||
[dependencies] | ||
axum = "0.7.9" | ||
serde = { version = "1.0.215", features = ["derive"] } | ||
serde_json = "1.0" | ||
tokio = { version = "1.41.1", features = ["full"] } | ||
sea-orm = { version = "1.1.2", features = ["sqlx-sqlite", "runtime-tokio-rustls", "macros"] } | ||
tracing-subscriber = { version = "0.3.19", features = ["fmt", "env-filter"] } | ||
dotenvy = "0.15" | ||
argon2 = "0.4" | ||
chrono = { version = "0.4", features = ["serde"] } | ||
jsonwebtoken = "8.3" | ||
rand = "0.8.5" | ||
|
||
[dev-dependencies] | ||
reqwest = { version = "0.11", features = ["json"] } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
use sea_orm::entity::prelude::*; | ||
use crate::entities::user::Entity as User; | ||
use crate::entities::product::Entity as Product; | ||
|
||
#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] | ||
#[sea_orm(table_name = "cart")] | ||
pub struct Model { | ||
#[sea_orm(primary_key)] | ||
pub id: i32, | ||
#[sea_orm(indexed)] | ||
pub user_id: i32, | ||
pub item_id: i32, | ||
pub quantity: i32, | ||
} | ||
|
||
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] | ||
pub enum Relation { | ||
#[sea_orm( | ||
belongs_to = "User", | ||
from = "crate::entities::cart::Column::UserId", | ||
to = "crate::entities::user::Column::Id", | ||
on_update = "Cascade", | ||
on_delete = "Cascade" | ||
)] | ||
User, | ||
#[sea_orm( | ||
belongs_to = "Product", | ||
from = "crate::entities::cart::Column::ItemId", | ||
to = "crate::entities::product::Column::Id", | ||
on_update = "Cascade", | ||
on_delete = "Cascade" | ||
)] | ||
Product, | ||
} | ||
|
||
|
||
impl ActiveModelBehavior for ActiveModel {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
use sea_orm::entity::prelude::*; | ||
|
||
#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] | ||
#[sea_orm(table_name = "category")] | ||
pub struct Model { | ||
#[sea_orm(primary_key)] | ||
pub id: i32, | ||
#[sea_orm(unique)] | ||
pub name: String, | ||
pub image_url: String, | ||
#[sea_orm(default = false)] | ||
pub is_featured: bool, | ||
#[sea_orm(default = true)] | ||
pub is_available: bool, | ||
} | ||
|
||
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] | ||
pub enum Relation {} | ||
|
||
impl ActiveModelBehavior for ActiveModel {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
pub mod user; | ||
pub mod product; | ||
pub mod cart; | ||
pub mod category; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
use sea_orm::entity::prelude::*; | ||
use crate::entities::category::Entity as Category; | ||
|
||
#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] | ||
#[sea_orm(table_name = "products")] | ||
pub struct Model { | ||
#[sea_orm(primary_key)] | ||
pub id: i32, | ||
#[sea_orm(unique)] | ||
pub name: String, | ||
pub price: f32, | ||
#[sea_orm(column_type = "Text")] | ||
pub description: String, | ||
pub image_url: String, | ||
pub category_id: i32, | ||
#[sea_orm(default = false)] | ||
pub is_featured: bool, | ||
#[sea_orm(default = true)] | ||
pub is_available: bool, | ||
} | ||
|
||
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] | ||
pub enum Relation { | ||
#[sea_orm( | ||
belongs_to = "Category", | ||
from = "crate::entities::product::Column::CategoryId", | ||
to = "crate::entities::category::Column::Id", | ||
on_update = "Cascade", | ||
on_delete = "Cascade" | ||
)] | ||
Category, | ||
} | ||
|
||
impl ActiveModelBehavior for ActiveModel {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
use sea_orm::entity::prelude::*; | ||
|
||
use argon2::{ | ||
password_hash::PasswordVerifier, | ||
Argon2, | ||
PasswordHash, | ||
}; | ||
|
||
//use crate::entity::jwt_token; | ||
|
||
#[derive(Clone, Debug, PartialEq, DeriveEntityModel)] | ||
#[sea_orm(table_name = "users")] | ||
pub struct Model { | ||
#[sea_orm(primary_key)] | ||
pub id: i32, | ||
#[sea_orm(unique)] | ||
pub username: String, | ||
pub password: String, | ||
} | ||
|
||
impl Model { | ||
pub fn check_hash(&self, password: &str) -> Result<(), String> { | ||
let parsed_hash = PasswordHash::new(&self.password).unwrap(); | ||
|
||
let argon2 = Argon2::default(); | ||
argon2.verify_password(password.as_bytes(), &parsed_hash) | ||
.map_err(|_| "Password verification failed")?; | ||
|
||
Ok(()) | ||
} | ||
} | ||
|
||
|
||
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] | ||
pub enum Relation {} | ||
|
||
impl ActiveModelBehavior for ActiveModel {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
use axum::{routing::get, Router}; | ||
use sea_orm::{ConnectionTrait, Schema}; | ||
use sea_orm::{Database, DatabaseConnection}; | ||
use std::sync::Arc; | ||
use tokio::sync::Mutex; | ||
|
||
mod entities; | ||
mod routes; | ||
mod middleware; | ||
|
||
use crate::entities::{ | ||
cart::Entity as Crate, | ||
category::Entity as Category, | ||
user::Entity as User, | ||
product::Entity as Product, | ||
}; | ||
use crate::routes::auth_routes::auth_routes; | ||
|
||
pub async fn setup_schema(db: &DatabaseConnection) { | ||
let schema = Schema::new(db.get_database_backend()); | ||
let create_cart_table = schema.create_table_from_entity(Crate); | ||
let create_category_table = schema.create_table_from_entity(Category); | ||
let create_user_table = schema.create_table_from_entity(User); | ||
let create_product_table = schema.create_table_from_entity(Product); | ||
|
||
db.execute(db.get_database_backend().build(&create_cart_table)) | ||
.await | ||
.expect("Failed to create cart schema"); | ||
db.execute(db.get_database_backend().build(&create_category_table)) | ||
.await | ||
.expect("Failed to create category schema"); | ||
db.execute(db.get_database_backend().build(&create_user_table)) | ||
.await | ||
.expect("Failed to create user schema"); | ||
db.execute(db.get_database_backend().build(&create_product_table)) | ||
.await | ||
.expect("Failed to create product schema"); | ||
} | ||
|
||
|
||
#[tokio::main] | ||
async fn main() { | ||
tracing_subscriber::fmt::init(); | ||
|
||
dotenvy::dotenv().ok(); | ||
|
||
let database_url = std::env::var("DATABASE_URL").expect("Databse url must be set"); | ||
let db: DatabaseConnection = Database::connect(&database_url).await.unwrap(); | ||
|
||
setup_schema(&db).await; | ||
|
||
let shared_db = Arc::new(Mutex::new(db)); | ||
let user_routes = auth_routes(shared_db.clone()).await; | ||
|
||
let app = Router::new().route("/", get(root)).nest("/", user_routes); | ||
|
||
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap(); | ||
println!("Running at {:?}", listener); | ||
axum::serve(listener, app).await.unwrap(); | ||
} | ||
|
||
async fn root() -> &'static str { | ||
"Hello, World!" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
use axum::{ | ||
body::Body, | ||
extract::Request, | ||
http::StatusCode, | ||
middleware::Next, | ||
response::IntoResponse, | ||
Json, | ||
}; | ||
use jsonwebtoken::{decode, Algorithm, DecodingKey, Validation}; | ||
use serde::{Deserialize, Serialize}; | ||
|
||
const SECRET: &str = "very_secret"; | ||
|
||
pub async fn jwt_middleware(mut req: Request<Body>, next: Next) -> impl IntoResponse { | ||
if let Some(auth_header) = req.headers().get("Authorization") { | ||
if let Ok(auth_header) = auth_header.to_str() { | ||
if auth_header.starts_with("Bearer ") { | ||
let token: &str = &auth_header[7..]; | ||
match validate_token(token) { | ||
Ok(claims) => { | ||
req.extensions_mut().insert(claims.username.clone()); | ||
return next.run(req).await; | ||
} | ||
Err(_) => { | ||
return ( | ||
StatusCode::UNAUTHORIZED, | ||
Json(ResponseMessage { | ||
message: "Invalid token".to_string(), | ||
}), | ||
) | ||
.into_response(); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
( | ||
StatusCode::UNAUTHORIZED, | ||
Json(ResponseMessage { | ||
message: "Missing or invalid Authorization header".to_string(), | ||
}), | ||
) | ||
.into_response() | ||
} | ||
|
||
fn validate_token(token: &str) -> Result<Claims, jsonwebtoken::errors::Error> { | ||
decode::<Claims>( | ||
token, | ||
&DecodingKey::from_secret(SECRET.as_ref()), | ||
&Validation::new(Algorithm::HS256), | ||
) | ||
.map(|data| data.claims) | ||
} | ||
|
||
#[derive(Debug, Serialize, Deserialize)] | ||
struct ResponseMessage { | ||
message: String, | ||
} | ||
|
||
#[derive(Debug, Serialize, Deserialize)] | ||
struct Claims { | ||
username: String, | ||
exp: usize, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
pub mod auth; |
Oops, something went wrong.