{"id":28702128,"url":"https://github.com/aksellercan/kwiatluxerestapi","last_synced_at":"2025-10-06T03:12:01.848Z","repository":{"id":298591866,"uuid":"1000461646","full_name":"Aksellercan/KwiatLuxeRESTAPI","owner":"Aksellercan","description":"KwiatLuxe REST API is a backend system for an e-commerce application.","archived":false,"fork":false,"pushed_at":"2025-08-07T20:51:09.000Z","size":98,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-08-07T22:23:53.327Z","etag":null,"topics":["api-rest","asp-net","cache","file-upload","jwt-authentication","mysql","policies","refresh-tokens","relational-databases","swagger","web"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Aksellercan.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-06-11T20:26:29.000Z","updated_at":"2025-08-07T20:51:12.000Z","dependencies_parsed_at":"2025-06-11T22:45:27.318Z","dependency_job_id":"9a765730-52ab-4369-b9b1-68f06a0fad6b","html_url":"https://github.com/Aksellercan/KwiatLuxeRESTAPI","commit_stats":null,"previous_names":["aksellercan/kwiatluxerestapi"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Aksellercan/KwiatLuxeRESTAPI","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Aksellercan%2FKwiatLuxeRESTAPI","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Aksellercan%2FKwiatLuxeRESTAPI/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Aksellercan%2FKwiatLuxeRESTAPI/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Aksellercan%2FKwiatLuxeRESTAPI/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Aksellercan","download_url":"https://codeload.github.com/Aksellercan/KwiatLuxeRESTAPI/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Aksellercan%2FKwiatLuxeRESTAPI/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278551858,"owners_count":26005459,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-06T02:00:05.630Z","response_time":65,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api-rest","asp-net","cache","file-upload","jwt-authentication","mysql","policies","refresh-tokens","relational-databases","swagger","web"],"created_at":"2025-06-14T12:10:21.954Z","updated_at":"2025-10-06T03:12:01.841Z","avatar_url":"https://github.com/Aksellercan.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# KwiatLuxe REST API\r\n\r\nThe **KwiatLuxe REST API** is a secure, token-authenticated backend system for an e-commerce application, supporting cart management, dynamic product ordering, and user-specific data access. Built with ASP.NET Web API and Entity Framework, the system is designed with maintainability and scalability in mind.\r\n\r\n---\r\n\r\n## Features\r\n\r\n- **Secure Cart System**  \r\n  - Each user can have **only one cart** (One-to-One relationship).\r\n  - Supports cart creation, item addition/update, and deletion.\r\n  - Real-time total cost calculation with precision updates based on item quantity.\r\n\r\n- **Robust Order Placement**  \r\n  - Each user can have **multiple orders** (One-to-Many relationship).\r\n  - Orders are created from cart data, with all associated products captured via linking tables.\r\n  - Supports viewing personal order history and cancelling specific orders.\r\n\r\n- **JWT Authorization**  \r\n  - All cart and order endpoints require valid authentication tokens.\r\n  - Uses user claims to resolve identity securely.\r\n\r\n- **Custom Logging Mechanism**  \r\n  - Logs critical operations at key points using `Logger.Log(Severity.WARN, ...)`.\r\n  - Can also write logs to file in `\\Logs` folder.\r\n  - Severity-based color-coded console logs\r\n  - Toggleable debug output\r\n---\r\n\r\n## Implementation\r\n\r\n### 1. **Handling One-to-One Cart Logic**\r\nOnly one cart per user is allowed. Before creating a new cart:\r\n```csharp\r\nvar identicalUserCart = await _db.Carts.Where(c =\u003e c.UserId == userId).FirstOrDefaultAsync();\r\nif (identicalUserCart != null) \r\n{\r\n    return BadRequest(new { CartExists = $\"Cart with UserId {userId} already exists.\" });\r\n}\r\n```\r\nThis guards against duplication and enforces the one-to-one relationship programmatically.\r\n\r\n2. Dynamic Cost Recalculation for Cart Updates\r\n\r\nWhen updating the quantity of an item in a cart:\r\n\r\n- The system recalculates only the delta between new and old quantity.\r\n- Prevents re-looping over the entire cart, improving performance and clarity.\r\n```csharp\r\nif (currentQuantity \u003e targetQuantity) {\r\n    newCost -= (newQuantity * getProduct.ProductPrice);\r\n}\r\nelse if (currentQuantity \u003c targetQuantity) {\r\n    newCost += (newQuantity * getProduct.ProductPrice);\r\n}\r\n```\r\n3. Cart-to-Order Transition On order placement:\r\n\r\nCart data is transformed into order entities.\r\n\r\n- Products from CartProducts are converted into OrderProducts.\r\n- The system does not clear the cart automatically, giving flexibility for future enhancement (e.g., transactional rollback or user confirmation).\r\n\r\n```csharp\r\nforeach (var product in getUserCart.CartProducts)\r\n{\r\n    var orderProduct = new OrderProduct\r\n    {\r\n        OrderId = order.Id,\r\n        ProductId = product.ProductId,\r\n        Quantity = product.Quantity\r\n    };\r\n    _db.OrderProducts.Add(orderProduct);\r\n}\r\n```\r\n4. Explicit Deletion Logic\r\n\r\nBoth carts and orders are deleted manually along with their child product entries, preventing orphan records:\r\n```csharp\r\nforeach (var cartProducts in removeAllCartProducts)\r\n{\r\n    _db.CartProducts.Remove(cartProducts);\r\n}\r\n```\r\nThis avoids relying solely on cascade deletes and gives more control over clean-up logic.\r\n\r\n## Authentication \u0026 Authorization\r\n\r\n- **JWT-based access and refresh token system**\r\n  - Separate `AccessToken` and `RefreshToken` lifecycle\r\n  - `RefreshToken` persisted in the Database\r\n- **Role-based policies** (`User`, `Admin`) and **custom policy-based claims** (`AccessToken`, `RefreshToken`)\r\n- **Custom Token validation and logging events** like:\r\n  - `OnTokenValidated`\r\n  - `OnAuthenticationFailed`\r\n  - `OnChallenge`\r\n  - `OnForbidden`\r\n\r\nSupports both **cookie-based** and **header-based** auth (configurable via `USE_COOKIES` flag).\r\n\r\n## Database Structure\r\n\r\nThe application uses the following tables:\r\n| Table\t| Description|\r\n|-------|------------|\r\n|Users\t|Stores user information.|\r\n|Products|\tStores available products and prices.|\r\n|Carts|\tOne-to-One with Users. Each user has a single cart.|\r\n|CartProducts\t|Links products to a cart (many-to-one).|\r\n|Orders\t|One-to-Many with Users. Stores all user orders.|\r\n|OrderProducts|\tLinks products to an order (many-to-one).|\r\n|Tokens|One-to-One with Users. Stores long term refresh tokens|\r\n\r\n## Entity Relationships\r\n\r\n    One-to-One:\r\n    User → Carts\r\n    User → Tokens \r\n\r\n    One-to-Many:\r\n    User → Orders\r\n    Order → OrderProducts\r\n    Carts → CartProducts\r\n\r\n## API Endpoints Overview\r\n|Method|\tRoute|\tDescription|\r\n|------|--------|--------------|\r\n|POST|\t/cart/createcart|\tCreates a new cart for a user.|\r\nPOST|\t/cart/addcart|\tAdds or updates products in cart.|\r\nGET\t|/cart/mycart|\tGets the current user’s cart.|\r\nDELETE|\t/cart/removecart|\tDeletes user’s cart and its items.|\r\nPOST|\t/order/placeorder|\tConverts cart into a placed order.|\r\nGET\t|/order/myorders\t| Retrieves all user’s past orders.|\r\n|DELETE|\t/order/cancelorder{id}|\tCancels a specific order.|\r\n\r\n## Tech Stack\r\n\r\n- Backend: ASP.NET Web API\r\n- Database: MySQL (via phpMyAdmin/XAMPP)\r\n- Auth: JWT Bearer Tokens\r\n- Testing Tool: Swagger UI\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faksellercan%2Fkwiatluxerestapi","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faksellercan%2Fkwiatluxerestapi","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faksellercan%2Fkwiatluxerestapi/lists"}