Skip to content

About

Full Stack Property Management app built with Angular and .NET Core, deployed on Azure.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Latest commit

Β 

History

10 Commits

Folders and files

Repository files navigation

🏨 Property Master

.NET 6.0 Angular 21 MongoDB RabbitMQ Docker Azure

A comprehensive property management system built with .NET 6 backend, Angular 21 frontend, and microservices architecture featuring real-time messaging, email notifications, and access logging capabilities.

πŸ“‹ Table of Contents

🎯 Overview

Property Master V4.0 is a full-stack property management application designed with a modern microservices architecture. The system handles property listings, partner management, bookings, transactions, and includes advanced features like real-time access logging, email notifications, and comprehensive API versioning.

Key Highlights

  • Clean Architecture: Domain-Driven Design (DDD) with CQRS pattern using MediatR
  • Microservices: Separate worker services for access logging and email processing
  • Real-time Communication: SignalR integration for live updates
  • Message Queue: RabbitMQ for asynchronous event processing
  • NoSQL Database: MongoDB for flexible data storage
  • Authentication: JWT-based authentication with Google OAuth2 support
  • API Versioning: RESTful API with Swagger/OpenAPI documentation
  • Containerization: Full Docker support with docker-compose orchestration
  • Cloud Deployment: Deployed on Microsoft Azure (Azure App Service + Azure Static Web Apps)

πŸ“Έ Screenshots

To add screenshots: Create a docs/screenshots/ folder in the repo root, place your .png images there, commit them, and they will display here automatically.

Login Page

Login Page

Property Selection

Property Selection

Dashboard β€” Room Planner (Gantt)

Dashboard Gantt

Dashboard β€” Widgets (KPI Cards & Analytics)

Dashboard Widgets

Property Management

Property Management

Bookings

Bookings

Swagger API Docs

Swagger


πŸ—οΈ Architecture

The application follows a Clean Architecture pattern with clear separation of concerns:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                     Presentation Layer                       β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚  Angular 21 SPA  β”‚              β”‚   WebAPI (.NET)  β”‚    β”‚
β”‚  β”‚   (Frontend)     │◄────────────►│   Controllers    β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                            β”‚
                            β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    Application Layer                         β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚  MediatR (CQRS)  β”‚  AutoMapper  β”‚  FluentValidation β”‚  β”‚
β”‚  β”‚  Commands/Queries β”‚  Behaviors   β”‚  Validators       β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                            β”‚
                            β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                      Domain Layer                            β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚  Entities  β”‚  Value Objects  β”‚  Domain Events        β”‚  β”‚
β”‚  β”‚  Product   β”‚  Partner        β”‚  Property             β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                            β”‚
                            β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                  Infrastructure Layer                        β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚  MongoDB   β”‚  RabbitMQ    β”‚  JWT Auth  β”‚  Serilog   β”‚  β”‚
β”‚  β”‚  Identity  β”‚  AutoMapper  β”‚  Azure KV  β”‚  Redis     β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                            β”‚
                            β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    Worker Services                           β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚ AccessLogWorker       β”‚  β”‚ EmailWorker              β”‚   β”‚
β”‚  β”‚ (.NET 8 Background)   β”‚  β”‚ (.NET 8 Background)      β”‚   β”‚
β”‚  β”‚ Consumes RabbitMQ     β”‚  β”‚ Processes Email Outbox   β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Message Flow Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   WebAPI     │────────►│   RabbitMQ   │────────►│ AccessLog    β”‚
β”‚              β”‚ Publish β”‚   Exchange   β”‚ Consume β”‚   Worker     β”‚
β”‚              β”‚         β”‚   + Queue    β”‚         β”‚              β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                                          β”‚
                                                          β–Ό
                                                   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                                                   β”‚   MongoDB    β”‚
                                                   β”‚   Storage    β”‚
                                                   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ› οΈ Technology Stack

Backend Technologies

Core Framework

  • .NET 6.0 - Main WebAPI framework
  • .NET 8.0 - Worker services (AccessLogWorker, EmailWorker)
  • C# 10.0 - Programming language
  • ASP.NET Core 6.0 - Web framework

Architecture & Patterns

  • MediatR 10.0.1 - CQRS and Mediator pattern implementation
  • AutoMapper 11.0.0 - Object-to-object mapping
  • FluentValidation 11.1.0 - Input validation
  • Clean Architecture - Separation of concerns
  • Domain-Driven Design (DDD) - Domain modeling

Database & Storage

  • MongoDB 2.19.1 / 3.6.0 - Primary NoSQL database
    • Used for: Properties, Partners, Products, Bookings, Transactions, Users, Access Logs
    • Custom repository pattern with Unit of Work
    • Connection string: MongoDB Atlas or Azure Cosmos DB for MongoDB
  • Entity Framework Core 6.0.6 - ORM (for SQL Server support)
  • AspNetCore.Identity.MongoDbCore 3.1.2 - Identity management with MongoDB
  • Redis - Caching layer (configured, connection: machost:6379)

Message Queue & Events

  • RabbitMQ.Client 7.2.0/7.2.1 - Message broker
    • CloudAMQP (raccoon.lmq.cloudamqp.com) - Hosted RabbitMQ service
    • Exchange: accesslog.exchange (Direct)
    • Queue: accesslog.queue
    • Routing Key: accesslog
    • SSL/TLS enabled (Port 5671)
    • Used for: Access log event streaming, asynchronous processing

Authentication & Security

  • Microsoft.AspNetCore.Authentication.JwtBearer 6.0.6 - JWT authentication
  • Microsoft.IdentityModel.Tokens - Token validation
  • Google.Apis.Auth 1.57.0 - Google OAuth2 authentication
  • Azure.Identity 1.6.0 - Azure authentication
  • Azure Key Vault - Secret management (optional)
    • Azure.Extensions.AspNetCore.Configuration.Secrets 1.2.2

Logging & Monitoring

  • Serilog 5.0.0 - Structured logging
    • Serilog.AspNetCore
    • Serilog.Enrichers.Environment 2.2.0
    • Serilog.Sinks.Loggly 5.4.0
  • Loggly - Cloud-based log management (configured)
  • File logging to logs/Error_log-.txt
  • Enrichers: MachineName, ProcessId, ThreadId, LogContext

API Documentation & Versioning

  • Swashbuckle.AspNetCore 6.3.1 - Swagger/OpenAPI
  • Microsoft.AspNetCore.Mvc.Versioning.ApiExplorer 5.0.0 - API versioning
  • Custom Swagger filters for authorization and grouping

Email Services

  • Resend 0.2.1 - Modern email API service (EmailWorker)
  • MailKit 4.14.1 - Email client library
  • FluentEmail.Core 3.0.2 - Email composition
  • Outbox pattern for reliable email delivery

Real-time Communication

  • Microsoft.AspNetCore.SignalR 1.1.0 - Real-time web functionality
  • ChatHub implementation for live messaging

Development & Code Quality

  • Microsoft.CodeAnalysis.NetAnalyzers 6.0.0 - Static code analysis
  • Microsoft.EntityFrameworkCore.Design 6.0.6 - Design-time tools
  • Microsoft.VisualStudio.Azure.Containers.Tools.Targets - Docker integration
  • StringToExpression 1.1.1 - Dynamic LINQ expressions

Frontend Technologies

Core Framework

  • Angular 21.1.1 - Single Page Application framework
  • TypeScript 5.9.3 - Programming language
  • RxJS 7.8.0 - Reactive programming
  • Zone.js 0.15.0 - Execution context management

UI Components & Design

  • Angular Material 21.1.1 - Material Design components
    • @angular/cdk 21.1.1 (Component Dev Kit)
  • FontAwesome 7.1.0 - Icon library
    • @fortawesome/angular-fontawesome 4.0.0
    • @fortawesome/fontawesome-svg-core 7.1.0
    • @fortawesome/free-solid-svg-icons 7.1.0

Utilities

  • jwt-decode 4.0.0 - JWT token decoding
  • Express 5.1.0 - Server-side rendering (SSR)
  • @angular/ssr - Angular Server-Side Rendering

Build & Development Tools

  • @angular/cli 21.1.1 - Command-line interface
  • @angular/build 21.1.1 - Build system
  • @angular/compiler-cli 21.1.1 - Template compiler

Testing

  • Jasmine 5.7.0 - Testing framework
  • Karma 6.4.0 - Test runner
    • karma-chrome-launcher
    • karma-coverage
    • karma-jasmine 5.1.0
    • karma-jasmine-html-reporter 2.1.0

DevOps & Infrastructure

Containerization

  • Docker - Container platform
    • Multi-stage Dockerfiles for optimized images
    • .dockerignore for build optimization
  • Docker Compose - Multi-container orchestration
    • Services: api, accesslog-worker, mongo, rabbitmq
    • Volumes: mongo-data, rabbitmq-data

Cloud Services & Hosting

Production Deployment
  • Azure App Service - Backend hosting

    • Resource Group: rg-propertymaster-dev
    • Region: France Central
    • WebAPI: https://propertymaster-api-de09-h0hqbzgsc4arfvez.francecentral-01.azurewebsites.net
    • Environment variable management via Azure App Service Configuration
    • Published via Web Deploy
  • Azure Static Web Apps - Frontend hosting

    • Angular SPA deployment: https://brave-rock-0db8c8503.7.azurestaticapps.net
    • Global CDN distribution
    • SPA navigation fallback via staticwebapp.config.json
External Services
  • CloudAMQP - Managed RabbitMQ service

    • Host: raccoon.lmq.cloudamqp.com
    • Plan: Free tier with SSL
    • Virtual host: fqccxvvi
  • Resend.com - Email delivery service

    • Transactional email API
    • High deliverability rates

Version Control

  • Git - Source control
  • GitHub - Repository hosting
    • Repository: https://github.com/NevilleColaco23/testAngularAPIDocker
    • Branch: Mar2026

Additional Libraries & Packages

Shared Libraries

  • Messaging.Shared - Custom shared library
    • Multi-targeting: .NET 6.0 and .NET 8.0
    • RabbitMQ models and interfaces
    • AccessLogEvent models

Other Dependencies

  • Newtonsoft.Json 13.0.3 - JSON serialization
  • System.Text.Json - Built-in JSON handling

πŸ“ Project Structure

PropertyMasterV4.0/
β”‚
β”œβ”€β”€ πŸ“ app/                                    # Angular Frontend
β”‚   β”œβ”€β”€ src/
β”‚   β”‚   β”œβ”€β”€ app/
β”‚   β”‚   β”‚   β”œβ”€β”€ core/                         # Core modules (auth, system)
β”‚   β”‚   β”‚   β”œβ”€β”€ Menu/                         # Menu components
β”‚   β”‚   β”‚   β”œβ”€β”€ property/                     # Property feature module
β”‚   β”‚   β”‚   └── environments/                 # Environment configs
β”‚   β”‚   β”œβ”€β”€ public/                           # Static assets
β”‚   β”‚   └── styles/                           # Global styles
β”‚   β”œβ”€β”€ angular.json                          # Angular configuration
β”‚   β”œβ”€β”€ package.json                          # NPM dependencies
β”‚   └── tsconfig.json                         # TypeScript config
β”‚
β”œβ”€β”€ πŸ“ WebApi/                                # Main Web API Project
β”‚   β”œβ”€β”€ API/
β”‚   β”‚   β”œβ”€β”€ V1/                               # Version 1 API endpoints
β”‚   β”‚   β”‚   β”œβ”€β”€ AccountController.cs          # Authentication endpoints
β”‚   β”‚   β”‚   β”œβ”€β”€ PropertyController.cs         # Property CRUD
β”‚   β”‚   β”‚   β”œβ”€β”€ PartnerController.cs          # Partner management
β”‚   β”‚   β”‚   β”œβ”€β”€ ProductController.cs          # Product management
β”‚   β”‚   β”‚   β”œβ”€β”€ BookingsController.cs         # Booking operations
β”‚   β”‚   β”‚   β”œβ”€β”€ TransactionController.cs      # Transaction handling
β”‚   β”‚   β”‚   β”œβ”€β”€ AccessLoggingController.cs    # Access log endpoints
β”‚   β”‚   β”‚   └── MessageController.cs          # Messaging endpoints
β”‚   β”‚   β”œβ”€β”€ DomainControllers/
β”‚   β”‚   β”‚   └── MenuController.cs             # Menu/Navigation
β”‚   β”‚   └── ApiStartup.cs                     # API configuration
β”‚   β”‚
β”‚   β”œβ”€β”€ Authentication/                        # Auth services
β”‚   β”‚   β”œβ”€β”€ Services/
β”‚   β”‚   β”‚   └── CurrentUserService.cs         # Current user context
β”‚   β”‚   β”œβ”€β”€ Dtos/                             # Auth DTOs
β”‚   β”‚   └── AuthenticationStartup.cs
β”‚   β”‚
β”‚   β”œβ”€β”€ Messaging Queue/
β”‚   β”‚   └── RabbitMqPublisher.cs              # RabbitMQ publisher
β”‚   β”‚
β”‚   β”œβ”€β”€ SignalR/
β”‚   β”‚   └── ChatHub.cs                        # Real-time chat hub
β”‚   β”‚
β”‚   β”œβ”€β”€ CORS/                                 # CORS configuration
β”‚   β”œβ”€β”€ ErrorHandling/                        # Global error handling
β”‚   β”œβ”€β”€ Logging/                              # Logging configuration
β”‚   β”œβ”€β”€ Swagger/                              # API documentation
β”‚   β”œβ”€β”€ Versioning/                           # API versioning
β”‚   β”‚
β”‚   β”œβ”€β”€ Program.cs                            # Application entry point
β”‚   β”œβ”€β”€ Startup.cs                            # Services configuration
β”‚   β”œβ”€β”€ Dockerfile                            # Docker configuration
β”‚   β”œβ”€β”€ docker-compose.yml                    # Multi-container setup
β”‚   β”œβ”€β”€ appsettings.json                      # Application settings
β”‚   └── WebApi.csproj                         # Project file
β”‚
β”œβ”€β”€ πŸ“ classfiles/                            # Core Business Logic
β”‚   β”‚
β”‚   β”œβ”€β”€ πŸ“ Domain/                            # Domain Layer (Entities)
β”‚   β”‚   β”œβ”€β”€ Property/
β”‚   β”‚   β”‚   └── Property.cs                   # Property entity
β”‚   β”‚   β”œβ”€β”€ Partners/
β”‚   β”‚   β”‚   β”œβ”€β”€ Partner.cs                    # Partner entity
β”‚   β”‚   β”‚   └── Address.cs                    # Value object
β”‚   β”‚   β”œβ”€β”€ Products/
β”‚   β”‚   β”‚   └── Product.cs                    # Product entity
β”‚   β”‚   β”œβ”€β”€ Bookings/
β”‚   β”‚   β”‚   └── Bookings.cs                   # Booking entity
β”‚   β”‚   β”œβ”€β”€ Transactions/
β”‚   β”‚   β”‚   β”œβ”€β”€ Transaction.cs                # Transaction entity
β”‚   β”‚   β”‚   └── TransactionLine.cs            # Transaction details
β”‚   β”‚   β”œβ”€β”€ AccessLog/
β”‚   β”‚   β”‚   └── AccessLog.cs                  # Access log entity
β”‚   β”‚   β”œβ”€β”€ Users/
β”‚   β”‚   β”‚   └── Users.cs                      # User entity
β”‚   β”‚   β”œβ”€β”€ Common/
β”‚   β”‚   β”‚   β”œβ”€β”€ Menus/                        # Menu entities
β”‚   β”‚   β”‚   β”œβ”€β”€ ValueObjects/                 # Money, Mass value objects
β”‚   β”‚   β”‚   β”œβ”€β”€ IEntity.cs                    # Entity interface
β”‚   β”‚   β”‚   β”œβ”€β”€ IAudited.cs                   # Audit interface
β”‚   β”‚   β”‚   └── ISoftDeletable.cs             # Soft delete interface
β”‚   β”‚   └── Domain.csproj
β”‚   β”‚
β”‚   β”œβ”€β”€ πŸ“ Application/                       # Application Layer (CQRS)
β”‚   β”‚   β”œβ”€β”€ Property/
β”‚   β”‚   β”‚   β”œβ”€β”€ CreateProperty/
β”‚   β”‚   β”‚   β”‚   └── CreatePropertyCommand.cs
β”‚   β”‚   β”‚   β”œβ”€β”€ GetProperty/
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ GetPropertyListQuery.cs
β”‚   β”‚   β”‚   β”‚   └── GetPropertyDTO.cs
β”‚   β”‚   β”‚   └── UpdateProperty/
β”‚   β”‚   β”‚       └── UpdatePropertyCommand.cs
β”‚   β”‚   β”œβ”€β”€ Partners/
β”‚   β”‚   β”‚   β”œβ”€β”€ UpdatePartner/
β”‚   β”‚   β”‚   └── DeletePartner/
β”‚   β”‚   β”œβ”€β”€ Products/
β”‚   β”‚   β”‚   β”œβ”€β”€ UpdateProduct/
β”‚   β”‚   β”‚   └── DeleteProduct/
β”‚   β”‚   β”œβ”€β”€ Logging/
β”‚   β”‚   β”‚   └── CreateLog/
β”‚   β”‚   β”‚       └── CreateLogCommand.cs
β”‚   β”‚   β”œβ”€β”€ Common/
β”‚   β”‚   β”‚   β”œβ”€β”€ Behaviors/
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ RequestValidationBehavior.cs
β”‚   β”‚   β”‚   β”‚   └── ExceptionLoggingBehavior.cs
β”‚   β”‚   β”‚   └── Dependencies/
β”‚   β”‚   β”‚       └── DataAccess/
β”‚   β”‚   β”‚           └── Repositories/
β”‚   β”‚   β”œβ”€β”€ ApplicationStartup.cs             # Application DI setup
β”‚   β”‚   └── Application.csproj
β”‚   β”‚
β”‚   β”œβ”€β”€ πŸ“ Infrastructure/                    # Infrastructure Layer
β”‚   β”‚   β”œβ”€β”€ Authentication/                   # JWT, OAuth2
β”‚   β”‚   β”‚   β”œβ”€β”€ Core/
β”‚   β”‚   β”‚   β”‚   └── Services/
β”‚   β”‚   β”‚   β”‚       β”œβ”€β”€ UserService.cs
β”‚   β”‚   β”‚   β”‚       └── JwtTokenService.cs
β”‚   β”‚   β”‚   β”œβ”€β”€ External/
β”‚   β”‚   β”‚   β”‚   └── Services/
β”‚   β”‚   β”‚   β”‚       β”œβ”€β”€ ExternalAuthenticationVerifier.cs
β”‚   β”‚   β”‚   β”‚       └── ExternalSignInService.cs
β”‚   β”‚   β”‚   └── Startup.cs
β”‚   β”‚   β”œβ”€β”€ Identity/                         # ASP.NET Identity
β”‚   β”‚   β”œβ”€β”€ Persistence/                      # Data access
β”‚   β”‚   β”œβ”€β”€ AzureKeyVault/                    # Secret management
β”‚   β”‚   β”œβ”€β”€ ApplicationDependencies/          # DI configuration
β”‚   β”‚   β”œβ”€β”€ InfrastructureStartup.cs
β”‚   β”‚   └── Infrastructure.csproj
β”‚   β”‚
β”‚   β”œβ”€β”€ πŸ“ MongoDBBackend/                    # MongoDB Abstraction
β”‚   β”‚   β”œβ”€β”€ IMongoRepository.cs               # Repository interface
β”‚   β”‚   β”œβ”€β”€ MongoRepository.cs                # Repository implementation
β”‚   β”‚   β”œβ”€β”€ MongoContext.cs                   # DB context
β”‚   β”‚   β”œβ”€β”€ MongoUnitOfWork.cs                # Unit of work pattern
β”‚   β”‚   β”œβ”€β”€ CounterService.cs                 # Auto-increment IDs
β”‚   β”‚   └── MongoDBBackend.csproj
β”‚   β”‚
β”‚   └── πŸ“ SampleData/                        # Seed data
β”‚       └── SampleData.csproj
β”‚
β”œβ”€β”€ πŸ“ AccessLogWorker/                       # Access Log Consumer Service
β”‚   β”œβ”€β”€ Services/
β”‚   β”‚   └── AccessLogMessageProcessor.cs      # Message processing logic
β”‚   β”œβ”€β”€ Worker.cs                             # Background service
β”‚   β”œβ”€β”€ Program.cs                            # Entry point
β”‚   β”œβ”€β”€ Dockerfile                            # Docker config
β”‚   β”œβ”€β”€ appsettings.json                      # Worker settings
β”‚   └── AccessLogConsumerWorker.csproj
β”‚
β”œβ”€β”€ πŸ“ EmailWorker/                           # Email Processing Service
β”‚   β”œβ”€β”€ ResendEmailSender.cs                  # Resend integration
β”‚   β”œβ”€β”€ Worker.cs                             # Background service
β”‚   β”œβ”€β”€ Program.cs                            # Entry point
β”‚   β”œβ”€β”€ Dockerfile                            # Docker config
β”‚   β”œβ”€β”€ appsettings.json                      # Worker settings
β”‚   └── EmailWorker.csproj
β”‚
β”œβ”€β”€ πŸ“ Messaging.Shared/                      # Shared Messaging Library
β”‚   β”œβ”€β”€ Models/
β”‚   β”‚   └── AccessLogEvent.cs                 # Event model
β”‚   β”œβ”€β”€ RabbitMqOptions.cs                    # Configuration model
β”‚   β”œβ”€β”€ IRabbitMqPublisher.cs                 # Publisher interface
β”‚   └── Messaging.Shared.csproj
β”‚
β”œβ”€β”€ πŸ“ APIUnitProject.Tests/                  # Unit Tests
β”‚   └── APIUnitProject.Tests.csproj
β”‚
β”œβ”€β”€ πŸ“ Project.Documentation/                 # Documentation
β”‚   β”œβ”€β”€ Messaging Queue/
β”‚   β”‚   └── README.md.txt
β”‚   └── Project.Documentation.csproj
β”‚
β”œβ”€β”€ .dockerignore                             # Docker ignore file
└── PropertyMasterV4.0.sln                    # Solution file

✨ Features

Core Functionality

1. Property Management

  • Create, Read, Update, Delete (CRUD) properties
  • Property listing with filtering and pagination
  • Image upload and management
  • Property details with rich metadata

2. Partner Management

  • Partner profiles and contact information
  • Address management (Value Object pattern)
  • Partner-specific business rules (invariants)
  • Soft delete capability

3. Product Management

  • Product catalog with categories
  • Stock management
  • Product invariants and validation
  • Product variants support

4. Bookings System

  • Property booking management
  • Booking status tracking
  • Date range validation
  • Conflict detection

5. Transaction Management

  • Transaction recording
  • Transaction lines (line items)
  • Transaction types (Sale, Purchase, etc.)
  • Financial reporting data

Advanced Features

6. User Management & Authentication

  • User registration and login
  • JWT token-based authentication
  • Google OAuth2 integration
  • Role-based authorization
  • User profile management

7. Access Logging & Monitoring

  • Automatic request/response logging
  • IP address tracking
  • User agent detection
  • Action tracking
  • Asynchronous log processing via RabbitMQ
  • Centralized log storage in MongoDB

8. Email System (Resend + MongoDB Queue)

  • Queue-based email delivery using MongoDB outbox pattern
  • Resend.com integration for transactional emails
  • Custom domain support (masterproperty.site via Namecheap)
  • Automated retry mechanism with exponential backoff (up to 5 attempts)
  • EmailWorker background service (.NET 8) for processing
  • Email templates for user activation, notifications
  • Delivery tracking with status persistence (Pending, Sent, Failed)
  • High deliverability with SPF, DKIM, and DMARC configuration
  • Production-ready deployment on Azure App Service
  • Email templates (Razor templates)
  • Bid invite notifications
  • Transactional emails via Resend
  • Background processing worker

9. Real-time Features

  • SignalR chat functionality
  • Live notifications
  • Real-time updates

10. API Features

  • RESTful API design
  • API versioning (v1)
  • Swagger/OpenAPI documentation
  • Health check endpoints
  • CORS configuration
  • Rate limiting ready

Technical Features

11. Architecture Patterns

  • CQRS (Command Query Responsibility Segregation)
  • Mediator Pattern via MediatR
  • Repository Pattern with Unit of Work
  • Domain-Driven Design
  • Value Objects (Money, Mass, Address)
  • Specification Pattern

12. Data Validation

  • FluentValidation for input validation
  • Pipeline behaviors for cross-cutting concerns
  • Exception handling middleware
  • Model state validation

13. Logging & Diagnostics

  • Structured logging with Serilog
  • Log enrichment (machine name, process ID, thread ID)
  • Error file logging
  • Loggly integration for cloud logging
  • Request/response logging

14. Security Features

  • JWT token authentication
  • Secure password hashing (Identity)
  • HTTPS enforcement (development)
  • CORS policy configuration
  • Azure Key Vault integration (optional)
  • Secret management

15. Performance & Scalability

  • MongoDB for horizontal scalability
  • Redis caching layer
  • Message queue for async processing
  • Background workers for heavy tasks
  • Connection pooling

πŸ“‹ Prerequisites

Required Software

  1. .NET SDK

  2. Node.js & NPM

  3. Angular CLI

    npm install -g @angular/cli@21
  4. MongoDB

  5. RabbitMQ

Optional Software

  1. Docker Desktop

  2. Redis (optional, for caching)

  3. Visual Studio 2022 or VS Code

    • Visual Studio 2022 (recommended for .NET development)
    • VS Code with C# extension

Cloud Services (Production)

  1. Azure Account (for App Service + Static Web Apps hosting)
  2. CloudAMQP Account (for managed RabbitMQ)
  3. Resend Account (for email delivery)

πŸš€ Installation

1. Clone the Repository

git clone https://github.com/NevilleColaco23/testAngularAPIDocker.git
cd testAngularAPIDocker

2. Backend Setup

Install .NET Dependencies

# Restore all NuGet packages
dotnet restore PropertyMasterV4.0.sln

Configure Backend Settings

Edit WebApi/appsettings.json:

{
  "ConnectionStrings": {
    "MongoDb": "mongodb://localhost:27017/ListingDB",
    "Redis": "localhost:6379"
  },
  "RabbitMq": {
    "Host": "localhost",
    "Port": 5672,
    "Username": "guest",
    "Password": "guest",
    "VirtualHost": "/",
    "Exchange": "accesslog.exchange",
    "Queue": "accesslog.queue",
    "RoutingKey": "accesslog",
    "UseSsl": false
  },
  "AuthenticationSettings": {
    "JwtIssuer": "PropertyMaster",
    "JwtAudience": "PropertyMaster",
    "TokenExpirationSeconds": 86400,
    "JwtSigningKeyBase64": "your-secret-key-here-min-32-chars"
  },
  "ExternalAuthenticationSettings": {
    "GoogleClientId": "your-google-client-id"
  },
  "CorsSettings": {
    "AllowedOrigins": [
      "http://localhost:4200",
      "https://localhost:4200"
    ]
  }
}

Configure Worker Services

Edit AccessLogWorker/appsettings.json:

{
  "ConnectionStrings": {
    "MongoDb": "mongodb://localhost:27017/ListingDB"
  },
  "RabbitMq": {
    "Host": "localhost",
    "Port": 5672,
    "Username": "guest",
    "Password": "guest",
    "VirtualHost": "/",
    "Exchange": "accesslog.exchange",
    "Queue": "accesslog.queue",
    "RoutingKey": "accesslog",
    "UseSsl": false
  }
}

Edit EmailWorker/appsettings.json:

{
  "ConnectionStrings": {
    "MongoDb": "mongodb://localhost:27017/ListingDB"
  },
  "Email": {
    "ApiKey": "your-resend-api-key",
    "From": "noreply@yourdomain.com"
  }
}

3. Frontend Setup

# Navigate to Angular app
cd app

# Install NPM packages
npm install

# Return to root
cd ..

Configure Frontend Environment

Edit app/src/app/environments/environment.ts:

export const environment = {
  production: false,
  apiUrl: 'https://localhost:44346/api/v1'
};

4. Database Setup

MongoDB

  1. Start MongoDB service:

    # Windows
    net start MongoDB
    
    # macOS (Homebrew)
    brew services start mongodb-community
    
    # Linux
    sudo systemctl start mongod
  2. Create database (automatic on first run)

    • Database: ListingDB
    • Collections created automatically by application

RabbitMQ

  1. Start RabbitMQ service:

    # Windows
    rabbitmq-server
    
    # macOS
    brew services start rabbitmq
    
    # Linux
    sudo systemctl start rabbitmq-server
  2. Access Management UI:

  3. Create exchange and queue (or let application auto-create):

    • Exchange: accesslog.exchange (type: direct, durable)
    • Queue: accesslog.queue (durable)
    • Binding: Route queue to exchange with key accesslog

βš™οΈ Configuration

Environment Variables

WebAPI

Variable Description Default Required
PORT HTTP port 5000 No
ASPNETCORE_ENVIRONMENT Environment Development No
MONGODB_URI MongoDB connection See appsettings Yes
RabbitMq__Host RabbitMQ host localhost Yes
RabbitMq__Port RabbitMQ port 5672 Yes
RabbitMq__Username RabbitMQ user guest Yes
RabbitMq__Password RabbitMQ password guest Yes
JWT_SIGNING_KEY JWT secret See appsettings Yes

AccessLogWorker

Variable Description Default Required
MONGODB_URI MongoDB connection See appsettings Yes
RabbitMq__Host RabbitMQ host localhost Yes
RabbitMq__Port RabbitMQ port 5672 Yes

EmailWorker

Variable Description Default Required
MONGODB_URI MongoDB connection See appsettings Yes
RESEND_API_KEY Resend API key None Yes
EMAIL_FROM Sender email address noreply@yourdomain.com Yes
AppSettings__MongoDbDatabaseName Database name ListingDB Yes

πŸ“§ Email System Setup

The email system uses Resend.com for transactional email delivery with a MongoDB-based outbox pattern for reliability.

Architecture Overview

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   WebAPI     │────────►│   MongoDB    │────────►│ EmailWorker  β”‚
β”‚              β”‚  Queue  β”‚  EmailOutbox β”‚  Poll   β”‚ (Background) β”‚
β”‚              β”‚         β”‚  Collection  β”‚         β”‚              β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                                          β”‚
                                                          β–Ό
                                                   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                                                   β”‚  Resend API  β”‚
                                                   β”‚  (Delivery)  β”‚
                                                   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Email Flow

  1. User Action (e.g., signup) β†’ WebAPI
  2. EmailQueueService inserts email into MongoDB EmailOutbox collection
  3. EmailWorker polls MongoDB every 2 seconds for pending emails
  4. EmailWorker sends email via Resend API
  5. Status Updated in MongoDB (Sent/Failed with retry logic)

Setup Instructions

1. Create Resend Account

  1. Go to Resend.com and sign up
  2. Navigate to API Keys
  3. Create a new API key
  4. Copy the API key (starts with re_...)

2. Domain Configuration (Namecheap)

To send emails from your custom domain (e.g., masterproperty.site):

2.1 Purchase Domain (if needed)
  1. Go to Namecheap
  2. Search and purchase your domain
  3. Go to Domain List β†’ Manage
2.2 Add DNS Records in Resend
  1. In Resend dashboard, go to Domains
  2. Click Add Domain
  3. Enter your domain (e.g., masterproperty.site)
  4. Copy the DNS records provided by Resend
2.3 Configure DNS in Namecheap
  1. In Namecheap, go to your domain β†’ Advanced DNS tab
  2. Add the following records from Resend:
Record Type Host Value TTL
TXT (DKIM) resend._domainkey p=... (from Resend) Automatic
TXT (SPF) send v=spf1 include:send.resend.com ~all Automatic
MX send feedback-smtp.{region}.amazonses.com Automatic
TXT (DMARC) _dmarc v=DMARC1; p=none; (optional) Automatic
  1. Click Save All Changes
2.4 Verify DNS Propagation
  1. Wait 5-30 minutes for DNS to propagate
  2. Check propagation: DNSChecker.org
  3. Enter your domain and select TXT/MX records
  4. Wait for green checkmarks globally
2.5 Verify Domain in Resend
  1. Return to Resend β†’ Domains
  2. Click Verify Domain
  3. Status should change to Verified βœ…
  4. You can now send from noreply@masterproperty.site

3. Configure EmailWorker

Local Development

Edit EmailWorker/appsettings.json:

{
  "ConnectionStrings": {
    "MongoDb": "mongodb://localhost:27017/ListingDB"
  },
  "AppSettings": {
    "MongoDbDatabaseName": "ListingDB"
  }
}

Note: Do NOT put sensitive credentials in appsettings.json. Use environment variables or user secrets:

# Using .NET User Secrets (Development)
cd EmailWorker
dotnet user-secrets set "Resend:ApiKey" "re_your_api_key_here"
dotnet user-secrets set "Email:From" "noreply@masterproperty.site"
Production (Azure App Service)

Set environment variables in the Azure Portal under App Service β†’ Configuration β†’ Application Settings:

RESEND_API_KEY=re_your_api_key_here
EMAIL_FROM=noreply@masterproperty.site
ConnectionStrings__MongoDb=mongodb://your-atlas-or-cosmos-url
AppSettings__MongoDbDatabaseName=ListingDB
ASPNETCORE_ENVIRONMENT=Production

4. Email Templates

Email templates are defined in code. Example from UserService.cs:

var htmlBody = $@"
    <html>
    <body>
        <h2>Welcome to Property Master!</h2>
        <p>Hi {username},</p>
        <p>Thank you for signing up. Please activate your account by clicking the link below:</p>
        <p><a href='{activationLink}'>Activate Account</a></p>
        <p>If you did not sign up for this account, please ignore this email.</p>
        <p>Best regards,<br/>Property Master Team</p>
    </body>
    </html>";

await _emailQueueService.QueueEmailAsync(email, "Activate Your Account", htmlBody, "activation");

5. MongoDB EmailOutbox Schema

The system uses a MongoDB collection called EmailOutbox:

{
  _id: 1,                           // Auto-increment ID
  type: "activation",               // Email type
  to: "user@example.com",          // Recipient
  subject: "Activate Your Account", // Subject line
  bodyHtml: "<html>...</html>",    // HTML body
  status: 0,                        // 0=Pending, 1=Processing, 2=Sent, 3=Failed
  attempts: 0,                      // Retry count
  nextRunAtUtc: ISODate("..."),    // When to process
  createdAtUtc: ISODate("..."),    // Creation timestamp
  sentAtUtc: null,                  // When sent (null if not sent)
  lockedUntilUtc: null,             // Processing lock
  lastError: null                   // Last error message
}

6. Testing the Email System

Test Locally
  1. Start MongoDB and EmailWorker:
# Terminal 1: Start EmailWorker
cd EmailWorker
dotnet run
  1. Start WebAPI:
# Terminal 2: Start WebAPI
cd WebApi
dotnet run
  1. Sign up a new user via API:
curl -X POST http://localhost:5000/api/v1/account/SignUp \
  -H "Content-Type: application/json" \
  -d '{
    "username": "testuser",
    "email": "your-email@example.com",
    "password": "Test@1234",
    "phone": "1234567890"
  }'
  1. Check EmailWorker logs:
info: EmailWorker.Worker[0]
      Sent outbox email 1 -> your-email@example.com
  1. Check your email inbox!
Test on Azure
  1. Deploy EmailWorker to Azure (see Deployment section)
  2. Verify environment variables are set in Azure App Service Configuration
  3. Test via the deployed WebAPI URL
  4. Monitor logs via Azure Portal β†’ App Service β†’ Log stream or Application Insights

7. Monitoring & Troubleshooting

Check Email Status in MongoDB
// Connect to MongoDB
use ListingDB

// View pending emails
db.EmailOutbox.find({ status: 0 })

// View sent emails
db.EmailOutbox.find({ status: 2 })

// View failed emails
db.EmailOutbox.find({ status: 3 })

// Count emails by status
db.EmailOutbox.aggregate([
  { $group: { _id: "$status", count: { $sum: 1 } } }
])
Common Issues
Issue Cause Solution
Domain not verified DNS records not propagated Wait 30 minutes, check DNSChecker.org
"You can only send to your own email" Using test mode Verify domain in Resend
Emails not sending EmailWorker not running Check Azure Log Stream, restart App Service
Missing API key error Environment variable not set Set RESEND_API_KEY in Azure App Service Configuration
MongoDB connection failed Wrong connection string Verify ConnectionStrings__MongoDb
Email Retry Logic

The EmailWorker has built-in retry logic:

  • Max Attempts: 5
  • Retry Delays: Exponential backoff (2, 4, 8, 16, 32 minutes)
  • Status Tracking: Pending β†’ Processing β†’ Sent/Failed
  • Automatic Recovery: Crashed sends are retried after 2 minutes

8. Email Service Comparison

Feature Resend SMTP (Gmail) SendGrid
Azure Compatible βœ… Yes βœ… Yes βœ… Yes
Setup Complexity ⭐⭐ Easy ⭐⭐⭐⭐ Hard ⭐⭐⭐ Medium
Custom Domain βœ… Yes (Namecheap) ❌ Complex βœ… Yes
Deliverability ⭐⭐⭐⭐⭐ Excellent ⭐⭐⭐ Good ⭐⭐⭐⭐ Very Good
Free Tier 100/day 500/day 100/day
Pricing $20/month (50k) Free (limited) $20/month (40k)
Our Choice βœ… Selected ❌ Not compatible ⚠️ Alternative

Why we chose Resend:

  • βœ… Works perfectly on Azure App Service
  • βœ… Simple API integration
  • βœ… Excellent deliverability with verified domains
  • βœ… Easy domain setup with Namecheap
  • βœ… Modern developer-friendly platform
  • βœ… Built-in bounce handling

πŸƒ Running the Application

Development Mode

Option 1: Run Individually

Terminal 1 - MongoDB:

mongod

Terminal 2 - RabbitMQ:

rabbitmq-server

Terminal 3 - WebAPI:

cd WebApi
dotnet run
# API available at: https://localhost:44346

Terminal 4 - AccessLogWorker:

cd AccessLogWorker
dotnet run

Terminal 5 - EmailWorker:

cd EmailWorker
dotnet run

Terminal 6 - Angular Frontend:

cd app
npm start
# or: ng serve
# App available at: http://localhost:4200

EmailWorker

Variable Description Default Required
MONGODB_URI MongoDB connection See appsettings Yes
RESEND_API_KEY Resend API key None Yes
EMAIL_FROM Sender email address noreply@yourdomain.com Yes
EMAIL_FROM Sender email - Yes
RESEND_API_KEY Resend API key - Yes

CORS Configuration

Configure allowed origins in WebApi/appsettings.json:

{
  "CorsSettings": {
    "AllowedOrigins": [
      "http://localhost:4200",
      "https://your-production-domain.com"
    ]
  }
}

Swagger Configuration

{
  "SwaggerSettings": {
    "ApiName": "PropertyMaster",
    "UseSwagger": true,
    "LoginPath": "/account/oauth2/access_token"
  }
}

πŸƒ Running the Application

Option 1: Run Locally (Development)

Start Backend Services

Terminal 1 - WebAPI:

cd WebApi
dotnet run
# API runs on https://localhost:44346

Terminal 2 - AccessLog Worker:

cd AccessLogWorker
dotnet run

Terminal 3 - Email Worker:

cd EmailWorker
dotnet run

Start Frontend

Terminal 4 - Angular:

cd app
ng serve
# App runs on http://localhost:4200

Option 2: Run with Docker Compose

# Build and start all services
docker-compose -f WebApi/docker-compose.yml up --build

# Services:
# - WebAPI: http://localhost:8080
# - MongoDB: localhost:27017
# - RabbitMQ: localhost:5672 (Management UI: http://localhost:15672)
# - AccessLog Worker: Running in background

Option 3: Run Individual Docker Containers

# Build WebAPI image
docker build -t propertymaster-api -f WebApi/Dockerfile .

# Build AccessLog Worker image
docker build -t accesslog-worker -f AccessLogWorker/Dockerfile .

# Build Email Worker image
docker build -t email-worker -f EmailWorker/Dockerfile .

# Run containers (after starting MongoDB and RabbitMQ)
docker run -p 8080:80 propertymaster-api
docker run accesslog-worker
docker run email-worker

Verification

  1. WebAPI Health Check:

    GET http://localhost:8080/health
    Expected: 200 OK
    
  2. Swagger UI:

    http://localhost:8080/swagger
    
  3. Angular Application:

    http://localhost:4200
    
  4. RabbitMQ Management:

    http://localhost:15672
    Login: guest/guest
    

🌐 Deployment

Azure App Service (Backend)

Prerequisites

Deployment via Visual Studio (Recommended)

  1. Right-click WebApi project β†’ Publish
  2. Select Azure β†’ Azure App Service (Windows)
  3. Sign in to your Azure account and select or create an App Service
  4. Click Publish β€” Visual Studio handles the rest

The included publish profile (propertymaster-api-de09 - Web Deploy.pubxml) deploys to:

https://propertymaster-api-de09-h0hqbzgsc4arfvez.francecentral-01.azurewebsites.net

Deployment via Azure CLI

# Login to Azure
az login

# Deploy WebAPI (from WebApi directory)
az webapp deploy --resource-group rg-propertymaster-dev \
  --name propertymaster-api-de09 \
  --src-path ./publish

Configure App Service Application Settings

In Azure Portal β†’ App Service β†’ Configuration β†’ Application Settings, add:

Key Value
ASPNETCORE_ENVIRONMENT Production
ConnectionStrings__MongoDb Your MongoDB Atlas / Cosmos DB URI
ConnectionStrings__DefaultConnection Your Azure SQL connection string
AuthenticationSettings__JwtSigningKeyBase64 Your base64 JWT key
RabbitMq__Host CloudAMQP host
RabbitMq__Username CloudAMQP username
RabbitMq__Password CloudAMQP password

Deploy Workers as Azure Container Apps (or App Service)

# Build and push worker images
docker build -f EmailWorker/Dockerfile -t propertymaster-emailworker .
docker build -f AccessLogWorker/Dockerfile -t propertymaster-accesslogworker .

# Push to Azure Container Registry, then deploy via Azure Portal or CLI

Azure Static Web Apps (Frontend)

Prerequisites

Deployment Steps

  1. Update Production Environment:

    Edit app/src/app/environments/environment.prod.ts:

    export const environment = {
      production: true,
      apiUrl: 'https://propertymaster-api-de09-h0hqbzgsc4arfvez.francecentral-01.azurewebsites.net/api/v1'
    };
  2. Build for Production:

    cd app
    ng build --configuration production
  3. Deploy to Azure Static Web Apps:

    • In the Azure Portal, create a new Static Web App
    • Connect it to your GitHub repository for CI/CD, or use the SWA CLI:
    npm install -g @azure/static-web-apps-cli
    swa deploy ./dist/propertyMasterV3.0/browser --env production
  4. SPA Routing is pre-configured via app/public/staticwebapp.config.json:

    {
      "navigationFallback": {
        "rewrite": "/index.html"
      }
    }

Deployed at: https://brave-rock-0db8c8503.7.azurestaticapps.net

CloudAMQP Setup (RabbitMQ)

  1. Create Account:

  2. Create Instance:

    • Select plan (Free tier available)
    • Choose region closest to your Azure App Service region
    • Note connection details
  3. Get Connection Information:

    • Host: e.g., raccoon.lmq.cloudamqp.com
    • Port: 5671 (SSL)
    • Virtual Host: Your instance name
    • Username: Provided
    • Password: Provided
  4. Update Configuration:

    • Update appsettings.json with CloudAMQP details
    • Ensure UseSsl: true

Database Backup & Migration

Backup MongoDB

# Local backup
mongodump --uri="mongodb://localhost:27017/ListingDB" --out=./backup

# Remote MongoDB backup (Atlas / Cosmos DB)
mongodump --uri="your-production-mongodb-uri" --out=./backup

Restore MongoDB

# Restore to local
mongorestore --uri="mongodb://localhost:27017/ListingDB" ./backup/ListingDB

# Restore to production
mongorestore --uri="your-production-mongodb-uri" ./backup/ListingDB

πŸ“š API Documentation

API Base URL

  • Local Development: https://localhost:44346/api/v1
  • Production: https://propertymaster-api-de09-h0hqbzgsc4arfvez.francecentral-01.azurewebsites.net/api/v1

Swagger Documentation

Access interactive API documentation:

  • Local: https://localhost:44346/swagger
  • Production: https://propertymaster-api-de09-h0hqbzgsc4arfvez.francecentral-01.azurewebsites.net/swagger

Authentication

All protected endpoints require JWT token in Authorization header:

Authorization: Bearer <your-jwt-token>

API Endpoints

Authentication

POST /api/v1/account/signup
POST /api/v1/account/login
POST /api/v1/account/oauth2/google
POST /api/v1/account/refresh-token
GET  /api/v1/account/user-info

Properties

GET    /api/v1/property                    # List properties
GET    /api/v1/property/{id}               # Get property by ID
POST   /api/v1/property                    # Create property
PUT    /api/v1/property/{id}               # Update property
DELETE /api/v1/property/{id}               # Delete property

Partners

GET    /api/v1/partner                     # List partners
GET    /api/v1/partner/{id}                # Get partner by ID
POST   /api/v1/partner                     # Create partner
PUT    /api/v1/partner/{id}                # Update partner
DELETE /api/v1/partner/{id}                # Delete partner

Products

GET    /api/v1/product                     # List products
GET    /api/v1/product/{id}                # Get product by ID
POST   /api/v1/product                     # Create product
PUT    /api/v1/product/{id}                # Update product
DELETE /api/v1/product/{id}                # Delete product

Bookings

GET    /api/v1/bookings                    # List bookings
GET    /api/v1/bookings/{id}               # Get booking by ID
POST   /api/v1/bookings                    # Create booking
PUT    /api/v1/bookings/{id}               # Update booking
DELETE /api/v1/bookings/{id}               # Delete booking

Transactions

GET    /api/v1/transaction                 # List transactions
GET    /api/v1/transaction/{id}            # Get transaction by ID
POST   /api/v1/transaction                 # Create transaction
PUT    /api/v1/transaction/{id}            # Update transaction
DELETE /api/v1/transaction/{id}            # Delete transaction

Access Logs

GET    /api/v1/accesslogging               # List access logs
GET    /api/v1/accesslogging/{id}          # Get log by ID
POST   /api/v1/accesslogging               # Create log entry

Menus & Navigation

GET    /api/menu                           # Get menu structure
GET    /api/menu/permissions/{roleId}      # Get menu permissions

Health & Status

GET    /health                             # Health check
GET    /                                   # API status

Sample Request/Response

Create Property

Request:

POST /api/v1/property
Content-Type: application/json
Authorization: Bearer <token>

{
  "name": "Luxury Apartment",
  "address": "123 Main St, City, State",
  "price": 500000,
  "bedrooms": 3,
  "bathrooms": 2,
  "squareFeet": 1500,
  "description": "Beautiful modern apartment"
}

Response:

{
  "id": 1,
  "name": "Luxury Apartment",
  "address": "123 Main St, City, State",
  "price": 500000,
  "bedrooms": 3,
  "bathrooms": 2,
  "squareFeet": 1500,
  "description": "Beautiful modern apartment",
  "createdAt": "2025-01-15T10:30:00Z",
  "updatedAt": "2025-01-15T10:30:00Z"
}

Error Responses

All errors follow consistent format:

{
  "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
  "title": "One or more validation errors occurred.",
  "status": 400,
  "errors": {
    "Name": ["The Name field is required."]
  },
  "traceId": "00-abc123-def456-00"
}

πŸ§ͺ Testing

Unit Tests

# Run all tests
dotnet test PropertyMasterV4.0.sln

# Run tests with coverage
dotnet test --collect:"XPlat Code Coverage"

# Run specific test project
dotnet test APIUnitProject.Tests/APIUnitProject.Tests.csproj

Frontend Tests

cd app

# Run unit tests
ng test

# Run tests with coverage
ng test --code-coverage

# Run tests headless (CI/CD)
ng test --browsers=ChromeHeadless --watch=false

Integration Testing

Use Swagger UI or tools like Postman:

  1. Import Swagger Spec:

    • Export OpenAPI spec from /swagger/v1/swagger.json
    • Import into Postman
  2. Test Scenarios:

    • User registration and login flow
    • Property CRUD operations
    • Access log creation and retrieval
    • Email outbox processing

Load Testing

Use tools like Apache JMeter or k6:

# Install k6
brew install k6  # macOS
choco install k6  # Windows

# Run load test
k6 run load-test-script.js

🀝 Contributing

Development Workflow

  1. Fork the Repository

    # Click Fork button on GitHub
    git clone https://github.com/YOUR_USERNAME/testAngularAPIDocker.git
  2. Create Feature Branch

    git checkout -b feature/your-feature-name
  3. Make Changes

    • Follow coding standards
    • Add unit tests
    • Update documentation
  4. Commit Changes

    git add .
    git commit -m "feat: add your feature description"
  5. Push to Fork

    git push origin feature/your-feature-name
  6. Create Pull Request

    • Go to original repository
    • Click "New Pull Request"
    • Describe changes

Coding Standards

C# / .NET

  • Follow Microsoft C# Coding Conventions
  • Use async/await for asynchronous operations
  • Implement IDisposable for resource management
  • Use dependency injection
  • Write XML documentation for public APIs

TypeScript / Angular

  • Follow Angular Style Guide
  • Use TypeScript strict mode
  • Implement RxJS best practices
  • Use async pipe for subscriptions
  • Write JSDoc comments

Commit Message Convention

Follow Conventional Commits:

feat: add new feature
fix: bug fix
docs: documentation changes
style: formatting changes
refactor: code refactoring
test: add tests
chore: maintenance tasks

πŸ“ License

This project is proprietary and confidential. All rights reserved.

πŸ‘€ Author

Neville Colaco

πŸ™ Acknowledgments

Technologies & Frameworks

  • Microsoft .NET Team for ASP.NET Core
  • Angular Team for Angular framework
  • MediatR for CQRS pattern implementation
  • AutoMapper for object mapping
  • FluentValidation for validation
  • Serilog for structured logging
  • MongoDB team for the database
  • RabbitMQ team for messaging

Services

  • Microsoft Azure for App Service and Static Web Apps hosting
  • CloudAMQP for managed RabbitMQ
  • Resend for email delivery
  • GitHub for source control

πŸ“ž Support

For issues, questions, or contributions:

  1. GitHub Issues: https://github.com/NevilleColaco23/testAngularAPIDocker/issues
  2. Pull Requests: https://github.com/NevilleColaco23/testAngularAPIDocker/pulls
  3. Email: [Your contact email]

πŸ”„ Version History

Version 4.0 (Current - Mar2026 Branch)

  • Complete rewrite with Clean Architecture
  • Microservices with worker services
  • RabbitMQ message queue integration
  • MongoDB as primary database
  • Angular 21 frontend upgrade
  • Docker containerization
  • Azure App Service + Static Web Apps deployment

Version 3.0

  • Angular Material integration
  • Improved UI/UX
  • Enhanced authentication

Version 2.0

  • Initial Angular frontend
  • Basic CRUD operations
  • JWT authentication

Version 1.0

  • Initial release
  • .NET WebAPI
  • Basic property management

πŸ—ΊοΈ Roadmap

Planned Features

  • Azure Blob Storage for file uploads
  • Advanced search with Elasticsearch
  • Payment gateway integration (Stripe)
  • Multi-tenant support
  • Mobile app (React Native)
  • GraphQL API endpoint
  • Advanced reporting with charts
  • Notification system (push notifications)
  • Chat system with attachments
  • Calendar integration
  • Document management
  • Audit trail visualization
  • Performance monitoring dashboard
  • Automated testing suite expansion
  • CI/CD pipeline with GitHub Actions

Last Updated: January 2025
Status: Active Development
Branch: Mar2026
Maintainer: Neville Colaco

About

Full Stack Property Management app built with Angular and .NET Core, deployed on Azure.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages