diff options
-rw-r--r-- | src/bin/server.rs | 17 | ||||
-rw-r--r-- | src/handlers/mod.rs | 1 | ||||
-rw-r--r-- | src/handlers/product.rs | 25 | ||||
-rw-r--r-- | src/handlers/users.rs | 28 | ||||
-rw-r--r-- | src/models.rs | 36 | ||||
-rw-r--r-- | src/schema.rs | 41 |
6 files changed, 117 insertions, 31 deletions
diff --git a/src/bin/server.rs b/src/bin/server.rs index 180c5bc..601d514 100644 --- a/src/bin/server.rs +++ b/src/bin/server.rs | |||
@@ -5,7 +5,7 @@ use actix_web::{web, App, HttpServer}; | |||
5 | use diesel::r2d2::{ConnectionManager, Pool}; | 5 | use diesel::r2d2::{ConnectionManager, Pool}; |
6 | use diesel::MysqlConnection; | 6 | use diesel::MysqlConnection; |
7 | use furby::handlers::smoke::manual_hello; | 7 | use furby::handlers::smoke::manual_hello; |
8 | use furby::handlers::{product, users}; | 8 | use furby::handlers::{cart_items, product, users}; |
9 | use rand::Rng; | 9 | use rand::Rng; |
10 | 10 | ||
11 | #[actix_web::main] | 11 | #[actix_web::main] |
@@ -42,13 +42,26 @@ async fn main() -> std::io::Result<()> { | |||
42 | ) | 42 | ) |
43 | .service( | 43 | .service( |
44 | web::scope("/product") | 44 | web::scope("/product") |
45 | .route("/{id}", web::get().to(product::product_details)) | 45 | .route("/catalog", web::get().to(product::get_all_products)) |
46 | .route("/new", web::post().to(product::new_product)) | 46 | .route("/new", web::post().to(product::new_product)) |
47 | .route("/{id}", web::get().to(product::product_details)) | ||
47 | .route( | 48 | .route( |
48 | "/update_product/{id}", | 49 | "/update_product/{id}", |
49 | web::post().to(product::update_product), | 50 | web::post().to(product::update_product), |
50 | ), | 51 | ), |
51 | ) | 52 | ) |
53 | .service( | ||
54 | web::scope("/cart") | ||
55 | .route( | ||
56 | "/items", | ||
57 | web::get().to(cart_items::get_user_cart_items), | ||
58 | ) | ||
59 | .route("/add", web::post().to(cart_items::add_to_cart)) | ||
60 | .route( | ||
61 | "/remove", | ||
62 | web::post().to(cart_items::remove_from_cart), | ||
63 | ), | ||
64 | ) | ||
52 | .route("/hey", web::get().to(manual_hello)) | 65 | .route("/hey", web::get().to(manual_hello)) |
53 | }) | 66 | }) |
54 | .bind("127.0.0.1:7878")? | 67 | .bind("127.0.0.1:7878")? |
diff --git a/src/handlers/mod.rs b/src/handlers/mod.rs index 41bba8d..28591bc 100644 --- a/src/handlers/mod.rs +++ b/src/handlers/mod.rs | |||
@@ -1,3 +1,4 @@ | |||
1 | pub mod cart_items; | ||
1 | pub mod product; | 2 | pub mod product; |
2 | pub mod smoke; | 3 | pub mod smoke; |
3 | pub mod users; | 4 | pub mod users; |
diff --git a/src/handlers/product.rs b/src/handlers/product.rs index 60a4684..788efb3 100644 --- a/src/handlers/product.rs +++ b/src/handlers/product.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | use crate::models::{NewProduct, Product}; | 1 | use crate::models::{NewProduct, Product, UpdateProduct}; |
2 | use crate::schema::product::dsl::*; | 2 | use crate::schema::product::dsl::*; |
3 | use crate::TPool; | 3 | use crate::TPool; |
4 | 4 | ||
@@ -43,14 +43,6 @@ pub async fn product_details( | |||
43 | } | 43 | } |
44 | } | 44 | } |
45 | 45 | ||
46 | #[derive(Deserialize)] | ||
47 | pub struct UpdateProduct { | ||
48 | name: String, | ||
49 | kind: Option<String>, | ||
50 | price: f32, | ||
51 | description: Option<String>, | ||
52 | } | ||
53 | |||
54 | pub async fn update_product( | 46 | pub async fn update_product( |
55 | pool: web::Data<TPool>, | 47 | pool: web::Data<TPool>, |
56 | product_id: web::Path<i32>, | 48 | product_id: web::Path<i32>, |
@@ -78,3 +70,18 @@ pub async fn update_product( | |||
78 | } | 70 | } |
79 | } | 71 | } |
80 | } | 72 | } |
73 | |||
74 | pub async fn get_all_products(pool: web::Data<TPool>) -> impl Responder { | ||
75 | let conn = pool.get().unwrap(); | ||
76 | info!("Generating and returning catalog ..."); | ||
77 | match product.load::<Product>(&conn) { | ||
78 | Ok(products) => { | ||
79 | return HttpResponse::Ok() | ||
80 | .body(serde_json::to_string(&products).unwrap()) | ||
81 | } | ||
82 | Err(_) => { | ||
83 | return HttpResponse::InternalServerError() | ||
84 | .body("Unable to fetch product catalog") | ||
85 | } | ||
86 | } | ||
87 | } | ||
diff --git a/src/handlers/users.rs b/src/handlers/users.rs index c7bc870..bff532c 100644 --- a/src/handlers/users.rs +++ b/src/handlers/users.rs | |||
@@ -1,5 +1,5 @@ | |||
1 | use crate::models::{Member, NewMember}; | 1 | use crate::models::{Customer, NewCustomer}; |
2 | use crate::schema::members::dsl::*; | 2 | use crate::schema::customer::dsl::*; |
3 | use crate::TPool; | 3 | use crate::TPool; |
4 | 4 | ||
5 | use actix_identity::Identity; | 5 | use actix_identity::Identity; |
@@ -11,14 +11,14 @@ use serde::Deserialize; | |||
11 | 11 | ||
12 | pub async fn new_user( | 12 | pub async fn new_user( |
13 | pool: web::Data<TPool>, | 13 | pool: web::Data<TPool>, |
14 | item: web::Json<NewMember>, | 14 | item: web::Json<NewCustomer>, |
15 | ) -> impl Responder { | 15 | ) -> impl Responder { |
16 | let conn = pool.get().unwrap(); | 16 | let conn = pool.get().unwrap(); |
17 | let hashed_item = NewMember { | 17 | let hashed_item = NewCustomer { |
18 | password: hash(&item.password, DEFAULT_COST).unwrap(), | 18 | password: hash(&item.password, DEFAULT_COST).unwrap(), |
19 | ..(item.into_inner()) | 19 | ..(item.into_inner()) |
20 | }; | 20 | }; |
21 | diesel::insert_into(members) | 21 | diesel::insert_into(customer) |
22 | .values(hashed_item) | 22 | .values(hashed_item) |
23 | .execute(&conn) | 23 | .execute(&conn) |
24 | .expect("Coundn't connect to DB"); | 24 | .expect("Coundn't connect to DB"); |
@@ -31,10 +31,10 @@ pub async fn name_exists( | |||
31 | ) -> impl Responder { | 31 | ) -> impl Responder { |
32 | let conn = pool.get().unwrap(); | 32 | let conn = pool.get().unwrap(); |
33 | info!("target: {:?}", item); | 33 | info!("target: {:?}", item); |
34 | if (members | 34 | if (customer |
35 | .filter(username.eq(&item)) | 35 | .filter(username.eq(&item)) |
36 | .limit(1) | 36 | .limit(1) |
37 | .load::<Member>(&conn) | 37 | .load::<Customer>(&conn) |
38 | .expect("Coundn't connect to DB")) | 38 | .expect("Coundn't connect to DB")) |
39 | .len() | 39 | .len() |
40 | > 0 | 40 | > 0 |
@@ -59,10 +59,10 @@ pub async fn login( | |||
59 | info!("Login hit"); | 59 | info!("Login hit"); |
60 | let conn = pool.get().unwrap(); | 60 | let conn = pool.get().unwrap(); |
61 | let entered_pass = &login_details.password; | 61 | let entered_pass = &login_details.password; |
62 | let selected_user = members | 62 | let selected_user = customer |
63 | .filter(username.eq(&login_details.username)) | 63 | .filter(username.eq(&login_details.username)) |
64 | .limit(1) | 64 | .limit(1) |
65 | .first::<Member>(&conn) | 65 | .first::<Customer>(&conn) |
66 | .expect("Couldn't connect to DB"); | 66 | .expect("Couldn't connect to DB"); |
67 | let hashed_pass = selected_user.password; | 67 | let hashed_pass = selected_user.password; |
68 | if verify(entered_pass, &hashed_pass).unwrap() { | 68 | if verify(entered_pass, &hashed_pass).unwrap() { |
@@ -89,10 +89,10 @@ pub async fn user_details( | |||
89 | let conn = pool.get().unwrap(); | 89 | let conn = pool.get().unwrap(); |
90 | let uname = uname.into_inner(); | 90 | let uname = uname.into_inner(); |
91 | info!("Fetching info for: \"{}\"", uname); | 91 | info!("Fetching info for: \"{}\"", uname); |
92 | let selected_user = members | 92 | let selected_user = customer |
93 | .filter(username.eq(&uname)) | 93 | .filter(username.eq(&uname)) |
94 | .limit(1) | 94 | .limit(1) |
95 | .first::<Member>(&conn); | 95 | .first::<Customer>(&conn); |
96 | match selected_user { | 96 | match selected_user { |
97 | Ok(m) => { | 97 | Ok(m) => { |
98 | info!("Found user: {}", uname); | 98 | info!("Found user: {}", uname); |
@@ -121,16 +121,16 @@ pub async fn change_password( | |||
121 | if let Some(uname) = cookie.identity() { | 121 | if let Some(uname) = cookie.identity() { |
122 | let entered_pass = &password_details.old_password; | 122 | let entered_pass = &password_details.old_password; |
123 | let new_password = &password_details.new_password; | 123 | let new_password = &password_details.new_password; |
124 | let selected_user = members | 124 | let selected_user = customer |
125 | .filter(username.eq(&uname)) | 125 | .filter(username.eq(&uname)) |
126 | .limit(1) | 126 | .limit(1) |
127 | .first::<Member>(&conn) | 127 | .first::<Customer>(&conn) |
128 | .expect("Couldn't connect to DB"); | 128 | .expect("Couldn't connect to DB"); |
129 | let hashed_pass = selected_user.password; | 129 | let hashed_pass = selected_user.password; |
130 | if verify(entered_pass, &hashed_pass).unwrap() { | 130 | if verify(entered_pass, &hashed_pass).unwrap() { |
131 | let hashed_new_password = | 131 | let hashed_new_password = |
132 | hash(&new_password, DEFAULT_COST).unwrap(); | 132 | hash(&new_password, DEFAULT_COST).unwrap(); |
133 | diesel::update(members.filter(id.eq(selected_user.id))) | 133 | diesel::update(customer.filter(id.eq(selected_user.id))) |
134 | .set(password.eq(hashed_new_password)) | 134 | .set(password.eq(hashed_new_password)) |
135 | .execute(&conn) | 135 | .execute(&conn) |
136 | .unwrap(); | 136 | .unwrap(); |
diff --git a/src/models.rs b/src/models.rs index 6af1af6..acd67a6 100644 --- a/src/models.rs +++ b/src/models.rs | |||
@@ -1,26 +1,32 @@ | |||
1 | use super::schema::{members, product}; | 1 | use super::schema::{cart_items, customer, product, rating, transaction}; |
2 | 2 | ||
3 | use diesel::{Insertable, Queryable}; | 3 | use diesel::{Insertable, Queryable}; |
4 | use serde::{Deserialize, Serialize}; | 4 | use serde::{Deserialize, Serialize}; |
5 | 5 | ||
6 | /* Member */ | ||
6 | #[derive(Queryable, Serialize)] | 7 | #[derive(Queryable, Serialize)] |
7 | pub struct Member { | 8 | pub struct Customer { |
8 | pub id: i32, | 9 | pub id: i32, |
9 | pub username: String, | 10 | pub username: String, |
10 | pub password: String, | 11 | pub password: String, |
11 | pub phone_number: String, | 12 | pub phone_number: String, |
12 | pub email_id: String, | 13 | pub email_id: String, |
14 | pub address: Option<String>, | ||
13 | } | 15 | } |
14 | 16 | ||
15 | #[derive(Insertable, Deserialize)] | 17 | #[derive(Insertable, Deserialize)] |
16 | #[table_name = "members"] | 18 | #[table_name = "customer"] |
17 | pub struct NewMember { | 19 | pub struct NewCustomer { |
18 | pub username: String, | 20 | pub username: String, |
19 | pub password: String, | 21 | pub password: String, |
20 | pub phone_number: String, | 22 | pub phone_number: String, |
21 | pub email_id: String, | 23 | pub email_id: String, |
24 | |||
25 | #[serde(skip_serializing_if = "Option::is_none")] | ||
26 | pub address: Option<String>, | ||
22 | } | 27 | } |
23 | 28 | ||
29 | /* Product */ | ||
24 | #[derive(Queryable, Serialize)] | 30 | #[derive(Queryable, Serialize)] |
25 | pub struct Product { | 31 | pub struct Product { |
26 | pub id: i32, | 32 | pub id: i32, |
@@ -42,3 +48,25 @@ pub struct NewProduct { | |||
42 | #[serde(skip_serializing_if = "Option::is_none")] | 48 | #[serde(skip_serializing_if = "Option::is_none")] |
43 | pub description: Option<String>, | 49 | pub description: Option<String>, |
44 | } | 50 | } |
51 | |||
52 | #[derive(Deserialize)] | ||
53 | pub struct UpdateProduct { | ||
54 | pub name: String, | ||
55 | pub kind: Option<String>, | ||
56 | pub price: f32, | ||
57 | pub description: Option<String>, | ||
58 | } | ||
59 | |||
60 | /* Cart Items */ | ||
61 | #[derive(Queryable, Serialize)] | ||
62 | pub struct CartItem { | ||
63 | pub cart_id: i32, | ||
64 | pub product_id: i32, | ||
65 | } | ||
66 | |||
67 | #[derive(Insertable, Deserialize)] | ||
68 | #[table_name = "cart_items"] | ||
69 | pub struct AddCartItem { | ||
70 | pub cart_id: i32, | ||
71 | pub product_id: i32, | ||
72 | } | ||
diff --git a/src/schema.rs b/src/schema.rs index b6074f2..f08221a 100644 --- a/src/schema.rs +++ b/src/schema.rs | |||
@@ -1,10 +1,18 @@ | |||
1 | table! { | 1 | table! { |
2 | members (id) { | 2 | cart_items (cart_id, product_id) { |
3 | cart_id -> Integer, | ||
4 | product_id -> Integer, | ||
5 | } | ||
6 | } | ||
7 | |||
8 | table! { | ||
9 | customer (id) { | ||
3 | id -> Integer, | 10 | id -> Integer, |
4 | username -> Varchar, | 11 | username -> Varchar, |
5 | password -> Varchar, | 12 | password -> Varchar, |
6 | phone_number -> Varchar, | 13 | phone_number -> Varchar, |
7 | email_id -> Varchar, | 14 | email_id -> Varchar, |
15 | address -> Nullable<Text>, | ||
8 | } | 16 | } |
9 | } | 17 | } |
10 | 18 | ||
@@ -18,7 +26,36 @@ table! { | |||
18 | } | 26 | } |
19 | } | 27 | } |
20 | 28 | ||
29 | table! { | ||
30 | rating (id) { | ||
31 | id -> Integer, | ||
32 | comment_text -> Nullable<Text>, | ||
33 | comment_date -> Nullable<Date>, | ||
34 | product_id -> Nullable<Integer>, | ||
35 | customer_id -> Nullable<Integer>, | ||
36 | stars -> Nullable<Integer>, | ||
37 | } | ||
38 | } | ||
39 | |||
40 | table! { | ||
41 | transaction (id) { | ||
42 | id -> Integer, | ||
43 | payment_type -> Varchar, | ||
44 | amount -> Float, | ||
45 | customer_id -> Nullable<Integer>, | ||
46 | } | ||
47 | } | ||
48 | |||
49 | joinable!(cart_items -> customer (cart_id)); | ||
50 | joinable!(cart_items -> product (product_id)); | ||
51 | joinable!(rating -> customer (customer_id)); | ||
52 | joinable!(rating -> product (product_id)); | ||
53 | joinable!(transaction -> customer (customer_id)); | ||
54 | |||
21 | allow_tables_to_appear_in_same_query!( | 55 | allow_tables_to_appear_in_same_query!( |
22 | members, | 56 | cart_items, |
57 | customer, | ||
23 | product, | 58 | product, |
59 | rating, | ||
60 | transaction, | ||
24 | ); | 61 | ); |