This project is a rewrite of my original college project which - compared to this - was very poorly written and insecure
Originally, it was written using PHP. This is written using C# on .NET 6 and 9
It's also rewritten to utilize my Azure and DevOps skills since I had earned Microsoft's Azure Certifications and needed a way to prove my skills with a project
View the AZ-400 that I prepared for and took here
As of right now, the solution is completed locally, and in Azure
Scroll down to the Demos section to see it in Azure
Initially I intended to make it cloud-native but I'd rather have it cloud-ready since "native" means it only runs in the cloud
The definition of "cloud-native" seems to be up for debate from what I've seen and it makes sense as to why it is one
NOTE: Since this project is a proof-of-concept, the payment system isn't integrated
NOTE: A Wiki is now available on how the solution is built, ensure to have a look at it 🥹
In the beginning, it was a distributed monolith with a frontend and backend API with a single database shared between both the projects
The API has been broken down into microservices which then invited a backend-for-frontend to have a single point of entry into the microservices from the frontend
The solution now comprises of 10 runnable projects with 18 projects in total
- A very simple and easy to navigate user interface
- An Admin Portal protected by ASP.NET Core Identity
- Admin Portal features:
- View the database structure [even though it's split]
- Add and update tyre catalog with the ability to add and update images
- View undelivered orders and mark them as delivered
- View the receipt of an order
- Related commits:
- admin: efficiently use the partial view for the tyres table
- implement functionality to add tyres
- implement functionality for updating tyres
- implement the logic for the shopping cart and the placing of orders
- implement the viewing of orders in the admin portal
- implement the viewing of receipts from the admin portal
- admin portal: use restful routing for updating a tyre
- add a missing feature to set the tyre's availability and adjust what customers see accordingly
- create an image service
- azure: implement the cloud version of the image service
- the blob client has the uri 😐
- Admin Portal features:
- A custom footer with a link to the commit on GitHub referencing the version its built on
- Customers can perform updates to their account, add addresses, view their previous orders, reset their password and delete their account
- Related commits:
- implement the logic for addresses in the account
- fix the post request for add new address
- implement the logic for the shopping cart and the placing of orders
- implement the viewing of orders on the account
- account: ensure a customer makes their first address a preferred one
- implement the functionality to reset password
- Related commits:
- An email service that sends emails with FluentEmail using embedded razor templates
- Emails sent:
- A receipt when a user completes an order
- Sends the user a token to reset their password
- Related commits:
- Emails sent:
- The entire architecture is protected using IdentityServer4
- User login session management
- Hybrid-encryption for customer data on POST and PUT requests
- Custom authorization requirements and policies for customers and the administrator. Customers can only access their own data
- Utilizing the repository pattern to access the database and perform CRUD operations
- AutoMapper is used to map between database entities and models returned to the client
- Using middleware to return a ProblemDetails model when a non-success status code is returned
- Related commits:
- Protected by IdentityServer4 and custom authorization policies
- Related commits:
- [WIP] An efficient API versioning strategy
- Related commits:
- resolve some of the duplication
- cleanup: centralize models-library using statements in a globalusings.cs file
- models: align with the semver versioning strategy and introduce model wrappers
- models: allow backwards compatibility
- models: introduce a static class called AvailableModels that's tied to a version of the models and allow the model type to be specified in the model wrapper
- models: the model version doesn't need to be static
- Related commits:
- An API Gateway to have a single point of entry into the microservices as exposing the APIs to the world without it is not a best practice
- Related commits:
- Effectively dealing with cross-cutting concerns like logging and distributed tracing
- Related commits:
- prep for centralized logging with serilog and elasticsearch
- the days and nights were long and so too, was the logging spree
- containerize and MOSTLY orchestrate the solution locally
- centralize the logging configuration in a shared library
- implement rabbitmq and complete the architecture locally
- implement a more correct way to maintain distributed tracing over a message bus
- okay, duplication is a bit too high
- Related commits:
- The codebase version with a link to the commit on GitHub is used to enrich the logs. This is useful in the following ways:
- Tracing back to new code that's causing failures to occur
- In a system where security is a priority, if a developer goes rogue and decides to allow fraud to occur by modifying the code, it can be traced back to them and can be under investigation
- CODE REVIEWS ARE IMPORTANT
- Related commits:
- An efficient data synchronization strategy across microservices
- Site Reliability Engineering possibilities like creating an actionable alerting strategy and monitoring application health
- Related commits:
- the days and nights were long and so too, was the logging spree
- communicate to users that the system is degraded
- implement application health checks
- enable the system degraded state by default when using docker compose
- implement liveness checks
- perform the liveness checks from the health checks ui
- azure: instrument the solution with application insights telemetry
- overhaul the existing health checks
- implement environment specific health checks
- azure: implement the system-degraded toggler azure function app
- Related commits:
- An easy-to-maintain codebase that's polyrepo-ready
- Related commits:
- A build system optimized with CMake to make the local building and running of the solution seamless
- All projects are versioned according to the codebase version
- Little (unavoidable) technical debt due to necessary code duplication
- Sonarcloud is used to provide feedback on technical debt to which I take and clean up the solution
- Related commits:
- C# 10 and .NET 6 [Paperback]
- Author: Mark J. Price
- Designing and Implementing Microsoft DevOps Solutions (AZ-400)
- Authors: John Savill | David Tucker | Neil Morrissey | Marcel de Vries | Chris Behrens | Adam Bertram | Daniel Krzyczkowski
- Developing Solutions for Microsoft Azure (AZ-204)
- Authors: Matthew Kruczek | Anthony Nocentino | Mike Pfeiffer | Mark Heath | David Tucker | Thomas Claudius Huber | Sahil Malik | Reza Salehi | James Millar | Daniel Krzyczkowski | Matthew Soucoup
- ASP.NET Microservices
- Authors: Antonio Goncalves | Roland Guijt | Gill Cleeren | Neil Morrissey | Kevin Dockx | Mark Heath | Marcel de Vries | Steve Gordan | Rag Dhiman
- Certified Kubernetes Administrator (CKA)
- Author: Anthony Nocentino
- Building a Web App with ASP.NET Core 5, MVC, Entity Framework Core, Bootstrap, and Angular
- Author: Shawn Wildermuth
- ASP.NET Core 6 Web API Fundamentals
- Author: Kevin Dockx
- ASP.NET Core 6 Fundamentals
- Author: Gill Cleeren
- Your Microservices Transition
- Author: Rag Dhiman
- Microservices Architecture: The Design Principles
- Author: Rag Dhiman
- Securing ASP.NET Core 3 with OAuth2 and OpenID Connect
- Author: Kevin Dockx
- Cryptography in .NET 6
- Author: Stephen Haunts
- Logging and Monitoring in ASP.NET Core 6
- Author: Erik Dahl
- RabbitMQ by Example
- Author: Stephen Haunts
- Building ASP.NET Core 3 Hosted Services and .NET Core 3 Worker Services
- Author: Steve Gordan
- Fundamentals of Docker and Kubernetes for .NET 5 Developers
- Author: Erik Dahl
- Deploying ASP.NET Core 6 Using Kubernetes
- Author: Marcel de Vries
- Securing ASP.NET Core 6 with OAuth2 and OpenID Connect
- Author: Kevin Dockx
- Deploying Azure Resources Using Bicep
- Author: Ben Weissman
- The IT Ops Sessions: ARM Templates vs. Terraform
- Author: Tim Warner
- ASP.NET Core 6 Performance
- Author: Erik Dahl
- Documenting an ASP.NET Core 6 Web API Using Swagger
- Author: Kevin Dockx
- Globalization and Internationalization in .NET 6
- Author: Filip Ekberg
- John Savill's Technical Training
- Author: John Savill
- Sending Email in C# using FluentEmail
- Author: IAmTimCorey
- Intro to Health Checks in .NET Core
- Author: IAmTimCorey
- Intro to Redis in C# - Caching Made Easy
- Author: IAmTimCorey
- RabbitMQ Custom Docker Image with Custom Configuration and Definitions
- Author: Mike Møller Nielsen
- Leveling up data: Upgrade from EF6 to EF7 and blast off! | .NET Conf 2022
- Author: dotnet
- Authoring and deploying Azure resources with Bicep | Azure Friday
- Author: Microsoft Azure
- Microsoft Learn
- Stack Overflow [Obviously]
- How export or import RabbitMQ configuration
- Docker Security Cheat Sheet
- Visual Studio 2022 17.12.1 or later
- Latest .NET SDK 6 and 9
- CMake 3.29.0 or later
- An Instance of SQL Server 2022 Express [Default, not named]
- SQL Server Management Studio
- WSL 1.0.3 [this is the version that I stick to because the Docker Engine fails to start on anything newer]
- Docker Desktop
- PowerToys 0.77.0 or later [For the hosts file editor and environment variables utility]
-
Ensure to set environment variables listed in the
RequiredEnvironmentVariables.txt
file- Press 🪟 and search for
Edit environment variables for your account
- When setting this for the first time, restart your computer
- Press 🪟 and search for
-
All build scripts are in the
scripts
folder -
In order to build, I've provided four options for you:
build.cmd
which is the regular buildbuild-with-docker.cmd
to run with docker-composebuild-with-services.cmd
which is the regular build + elasticsearch, kibana and rabbitmq orchestrated with docker-compose- Kubernetes:
- All scripts for Kubernetes are in the
scripts/kubernetes
folder and should be run in order00-applied-once.cmd
- Note: This adds the nginx ingress to the cluster from the original repo
01-build-images.cmd
02-deploy.cmd
03-delete.cmd
- All scripts for Kubernetes are in the
-
NOTE: For Docker builds, run the
pull-required-docker-images.cmd
script beforehand -
Once you run either
build.cmd
orbuild-with-services.cmd
, CMake will generaterun-all.cmd
-
Thereafter, run
run-all.cmd
which will start all applications minimized and launch the site, simulating orchestration