Skip to content

0xemrekaya/weather-app

Repository files navigation

Weather App API

This project is a RESTful API service developed with NestJS that allows users to query location-based weather data. The system incorporates modern and scalable backend architecture principles such as Role-Based Access Control (RBAC), external API integration (OpenWeather API), caching (Redis), database management (PostgreSQL & Prisma), and metric monitoring (Prometheus & Grafana).

Features

  • RESTful API: Clean, modular, and scalable API built with NestJS.
  • Role-Based Access Control (RBAC): Secure endpoints with admin and user roles.
  • Authentication: Secure user authentication with JWT (JSON Web Tokens).
  • Database: Efficient database management and optimization with PostgreSQL and Prisma ORM.
  • External API Integration: Fetching real-time weather data from the OpenWeather API.
  • Caching: Improving performance and efficiently using API limits by caching frequent requests with Redis.
  • Configuration Management: Centralized and environment-based configuration with @nestjs/config.
  • Validation: Automatic validation of incoming requests via DTOs using class-validator and class-transformer.
  • API Documentation: Auto-generated and interactive API documentation with Swagger (OpenAPI).
  • Security: Protection against brute-force attacks with Throttling (rate limiting).
  • Logging: Comprehensive logging for incoming requests, responses, and errors.
  • Monitoring and Metrics: Collection of metrics with Prometheus and visualization with Grafana.
  • CORS: Configurable Cross-Origin Resource Sharing.
  • Graceful Shutdown: Ensures the application terminates cleanly, preventing data loss.
  • Health Check: An endpoint to monitor application status.
  • Containerization: Easy setup and deployment with Docker and Docker Compose.
  • CI/CD Github Actions for testing and deployment.

System Architecture

The application is built on a monolithic NestJS architecture. Inter-service communication and separation of responsibilities are achieved through a modular structure. The following diagram illustrates the main components of the system and their interactions.

graph TD
    subgraph "Client"
        UserInterface["User / Admin"]
    end

    subgraph "Weather API Application (NestJS)"
        API["REST API <br> (Throttling, Guards)"]
        Auth["Auth Module <br> (JWT)"]
        User["User Module"]
        Weather["Weather Module"]
        Metrics["Metrics Module"]
        Cache["Cache Service <br> (Redis)"]
        DB["Database Service <br> (Prisma)"]
    end

    subgraph "External Services"
        OpenWeather["OpenWeather API"]
        Postgres[(PostgreSQL DB)]
        Redis[(Redis Cache)]
        Prometheus[Prometheus]
        Grafana[Grafana]
    end

    UserInterface -- "HTTPS" --> API
    API --> Auth
    API --> User
    API --> Weather
    API -- "Records Metrics" --> Metrics

    Auth -- "Validates User" --> DB
    User -- "Manages Users" --> DB
    Weather -- "Manages Weather Data" --> DB
    Weather -- "Caches Data" --> Cache
    Weather -- "Fetches Weather" --> OpenWeather

    Cache -- "Uses" --> Redis
    DB -- "Uses" --o Postgres

    Prometheus -- "Scrapes" --> Metrics
    Grafana -- "Visualizes" --> Prometheus
Loading

Database Schema

image

The database schema includes several indexes to optimize query performance. Below is a list of these indexes and their purposes:

  • User Model:

    • email and username have unique constraints, which also create indexes to prevent duplicates and speed up lookups.
  • WeatherQuery Model:

    • userId: Indexed to quickly retrieve all queries for a specific user.
    • userId, queryTime (Composite Index): Optimizes queries that filter by both user and the time of the query.
    • city, queryTime (Composite Index): Optimizes queries that filter by both city and the time of the query.
  • WeatherData Model:

    • weatherQueryId: Indexed with a unique constraint to ensure a fast, direct link to its corresponding WeatherQuery.

These indexes are crucial for maintaining performance, especially as the amount of data grows.

Project Folder Structure

The project follows the standard modular structure of NestJS. The main logic is located under the src/ directory.

/
├── prisma/               # Prisma schema and migration files
│   └── schema.prisma
├── src/
│   ├── common/           # Shared modules (guards, filters, decorators)
│   ├── module/           # Application's main modules
│   │   ├── auth/         # Authentication (login)
│   │   ├── cache/        # Redis cache service
│   │   ├── config/       # Environment variables and configuration
│   │   ├── database/     # Database connection (Prisma)
│   │   ├── metrics/      # Prometheus metrics
│   │   ├── user/         # User management
│   │   └── weather/      # Weather querying
│   ├── main.ts           # Application entry point
│   └── app.module.ts     # Main application module
├── .env.example          # Template for required environment variables
├── docker-compose.yml    # Docker Compose configuration
└── package.json          # Project dependencies and scripts

Installation and Setup

Prerequisites

1. Clone the Project

git clone https://github.com/0xemrekaya/weather-app
cd weather-app

2. Set Up Environment Variables

Copy the .env.example file to create a new file named .env and edit the values according to your configuration.

cp env.example .env

3. Running with Docker (Recommended)

You can start all services (PostgreSQL, Redis, Grafana, Prometheus, and Weather-App) with a single command using Docker and Docker Compose.

npm run docker:up
  • The application will be running at http://localhost:3000.
  • Prometheus will be accessible at http://localhost:9090.
  • Grafana will be accessible at http://localhost:8080.

To stop the services:

npm run docker:down

4. Running Locally (Without Docker)

If you are running the services (PostgreSQL, Redis) on your local machine, you can start the application locally.

# Install dependencies
npm install

# Run Prisma migrations
npx prisma migrate dev

# Start in development mode
npm run start:dev

5. Access the API

There is a already created a admin.

username = admin
password = password

Roles and Permissions

The system has two different user roles:

  • user:
    • Can only view their own weather query history.
    • Can make new weather queries.
  • admin:
    • Can list all users.
    • Can create new users.
    • Can query the weather history of any user by userId.

API Endpoints (Swagger)

Once the application is started, you can access the API documentation at http://localhost:3000/api/docs.

Auth

Method Endpoint Description Role
POST /api/v1/auth/login User login and get JWT token Public

Users

Method Endpoint Description Role
GET /api/v1/users Lists all users admin
POST /api/v1/users Creates a new user admin

Weather

Method Endpoint Description Role
GET /api/v1/weather Gets weather data for a specified city user, admin
GET /api/v1/weather/history Gets the query history of the logged-in user user, admin
GET /api/v1/weather/history/user/:id Gets the query history of a specific user admin

Metrics

Method Endpoint Description Role
GET /api/v1/metrics Serves Prometheus metrics Public

Health Check

Method Endpoint Description Role
GET /api/v1/health Checks the health of the application Public

Running Tests

# Unit tests
npm run test

# E2E tests
npm run test:e2e

# Test coverage report
npm run test:cov

Logging and Error Handling

The application implements a comprehensive logging and error handling strategy to ensure robustness and facilitate debugging.

  • LoggingInterceptor: This interceptor logs every incoming request and outgoing response. It captures the request method, URL, IP address, user agent, and the processing time. This provides a clear audit trail of all traffic.

  • GlobalExceptionFilter: This global filter catches all unhandled exceptions throughout the application. It normalizes errors into a consistent JSON response format and logs them with appropriate severity levels:

    • HTTP Exceptions: Handled gracefully, returning standard HTTP status codes.
    • Prisma Errors: Specific database errors (e.g., unique constraint violations, records not found) are caught and mapped to user-friendly error responses.
    • 5xx Errors: Logged as ERROR for critical issues.
    • 4xx Errors: Logged as WARN for client-side issues.

Monitoring

image

The project has monitoring capabilities with Prometheus and Grafana.

  • Prometheus: Accessible at http://localhost:9090. It automatically scrapes the http://weather-app:3000/api/v1/metrics endpoint.
  • Grafana: Accessible at http://localhost:8080. You can use a pre-configured dashboard by importing the grafana-dashboard.json file that comes with the project.

Environment Variables

Below is a description of the variables that should be in the .env file.

Variable Description Example Value
NODE_ENV Application environment (development or production) development
DATABASE_URL PostgreSQL database connection string postgresql://admin123:password123@localhost:5432/weather_app?schema=public
PORT The port the application will run on 3000
JWT_SECRET Secret key used to sign JWT tokens mysecretkeyforauthentication123456
JWT_SALT_ROUNDS Number of salt rounds for password hashing 12
CORS_ORIGIN Allowed origins (comma-separated) http://localhost:3000,http://localhost:3001
OPENWEATHER_API_KEY OpenWeatherMap API key OpenWeatherMap-API-Key
OPENWEATHER_GEOCODING_URL OpenWeatherMap Geocoding API URL http://api.openweathermap.org/geo/1.0/direct
OPENWEATHER_WEATHER_URL OpenWeatherMap Weather API URL https://api.openweathermap.org/data/2.5/weather
REDIS_HOST Redis server address localhost
REDIS_PORT Redis server port 6379
REDIS_PASSWORD Redis password redis_password_123
CACHE_TTL Cache data Time-To-Live in seconds 300
CACHE_MAX_ITEMS Maximum number of items to keep in cache 1000

License

This project is licensed under the MIT License. See the LICENSE file for more details.

About

Weather application with role-based access control, OpenWeather API integration.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages