Skip to content

A real-time web application for monitoring blog posts with intelligent notifications, Azure AD authentication, and web push support.

Notifications You must be signed in to change notification settings

vakesz/notification_app

Repository files navigation

Notification App

Notification App

Build Status Docker Image GitHub Pages Python Version License Linting: Ruff

A real-time web application for monitoring blog posts with intelligent notifications, Azure AD authentication, and web push support.

Description

This Flask-based application automatically monitors blog content and delivers personalized notifications to users. It features Microsoft Azure AD single sign-on authentication, customizable notification filters, and web push notifications for real-time updates.

Key Features

  • Real-time Blog Monitoring: Automatically polls blog APIs and parses new posts
  • Azure AD Authentication: Secure single sign-on with Microsoft accounts
  • Intelligent Filtering: Location-based and keyword-based notification filters
  • Web Push Notifications: Cross-platform push notifications with VAPID support
  • User Dashboard: Comprehensive interface for managing settings and viewing notifications
  • Multi-language Support: English, Hungarian, and Swedish language options
  • Responsive Design: Mobile-friendly web interface
  • Export Functionality: Export posts and notifications to JSON format
  • Session Management: Secure session handling with token validation

Installation Instructions

Prerequisites

  • Python 3.10 or higher
  • Azure AD application registration
  • VAPID keys for web push notifications

Local Development Setup

  1. Clone the repository

    git clone https://github.com/vakesz/notification_app.git
    cd notification_app
  2. Create a virtual environment

    python -m venv venv
    source venv/bin/activate  # On Windows: venv\Scripts\activate
  3. Install dependencies

    pip install -e .
  4. Environment Configuration

    Create a .env file in the project root:

    # Flask Configuration
    SECRET_KEY=your-secret-key-here
    FLASK_ENV=development
    
    # Azure AD Configuration
    AAD_CLIENT_ID=your-azure-ad-client-id
    AAD_CLIENT_SECRET=your-azure-ad-client-secret
    AAD_TENANT_ID=your-azure-ad-tenant-id
    AAD_REDIRECT_URI=http://localhost:5000/auth/callback
    
    # Blog API Configuration
    BLOG_API_URL=https://your-blog-api-url.com
    BLOG_API_AUTH_METHOD=none
    
    # Optional Blog API Authentication (choose one if needed)
    # For OAuth2:
    # BLOG_API_OAUTH2_CLIENT_ID=your-oauth2-client-id
    # BLOG_API_OAUTH2_CLIENT_SECRET=your-oauth2-client-secret
    # BLOG_API_OAUTH2_TOKEN_URL=https://your-oauth2-token-url.com
    
    # For MSAL:
    # BLOG_API_MSAL_CLIENT_ID=your-msal-client-id
    # BLOG_API_MSAL_CLIENT_SECRET=your-msal-client-secret
    # BLOG_API_MSAL_TENANT_ID=your-msal-tenant-id
    # BLOG_API_MSAL_SCOPE=your-msal-scope
    
    # For NTLM:
    # BLOG_API_NTLM_USER=your-ntlm-user
    # BLOG_API_NTLM_PASSWORD=your-ntlm-password
    # BLOG_API_NTLM_DOMAIN=your-ntlm-domain
    
    # For Cookie (session cookie on target blog domain):
    # BLOG_API_AUTH_METHOD=cookie
    # Option A: Multiple cookies (recommended when the site sets more than one)
    # BLOG_API_COOKIES=name1=value1; name2=value2
    # Option B: Single cookie (fallback)
    # BLOG_API_COOKIE_NAME=your-cookie-name
    # BLOG_API_COOKIE_VALUE=your-cookie-value
    # BLOG_API_COOKIE_DOMAIN=your-blog-domain.com   # optional, defaults to BLOG_API_URL host
    # BLOG_API_COOKIE_PATH=/                         # optional, defaults to '/'
    
    # Web Push Configuration
    PUSH_VAPID_PUBLIC_KEY=your-vapid-public-key
    PUSH_VAPID_PRIVATE_KEY=your-vapid-private-key
    PUSH_CONTACT_EMAIL=[email protected]
    
    # Token Encryption (required)
    # Generate with: python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
    TOKEN_ENCRYPTION_KEY=base64-urlsafe-32-byte-fernet-key
    
    # Application Settings
    APP_NAME=Blog Notifications Parser
    APP_DATABASE_PATH=db/posts.db
    POLLING_INTERVAL_MINUTES=15
    HTTP_TIMEOUT=30
    
    # Optional Advanced Settings
    # HTTP_MAX_RETRIES=3
    # HTTP_RETRY_BACKOFF=1
    # POLLING_BACKOFF_FACTOR=1.5
    # POLLING_MAX_BACKOFF=3600
    # AUTH_TOKEN_TTL_DAYS=30
    # PUSH_TTL=86400
  5. Database Setup

    mkdir -p db
    # Database will be automatically initialized on first run

Docker Deployment

Run with Docker

# Pull the latest image
docker pull ghcr.io/vakesz/notification_app:latest

# Run with environment variables
docker run -d \
  --name notification-app \
  -p 5000:5000 \
  -e SECRET_KEY=your-secret-key \
  -e AAD_CLIENT_ID=your-azure-ad-client-id \
  -e AAD_CLIENT_SECRET=your-azure-ad-client-secret \
  -e AAD_TENANT_ID=your-azure-ad-tenant-id \
  -e BLOG_API_URL=https://your-blog-api-url.com \
  -e PUSH_VAPID_PUBLIC_KEY=your-vapid-public-key \
  -e PUSH_VAPID_PRIVATE_KEY=your-vapid-private-key \
  -e [email protected] \
  -e TOKEN_ENCRYPTION_KEY=your-fernet-key \
  -v notification-db:/app/db \
  ghcr.io/vakesz/notification_app:latest

Run with Docker Compose

version: "3.8"
services:
  app:
    image: ghcr.io/vakesz/notification_app:latest
    ports:
      - "5000:5000"
    environment:
      - SECRET_KEY=your-secret-key
      - AAD_CLIENT_ID=your-client-id
      - AAD_CLIENT_SECRET=your-azure-ad-client-secret
      - AAD_TENANT_ID=your-tenant-id
      - AAD_REDIRECT_URI=http://localhost:5000/auth/callback
      - BLOG_API_URL=https://your-blog-api-url.com
      - PUSH_VAPID_PUBLIC_KEY=your-vapid-public-key
      - PUSH_VAPID_PRIVATE_KEY=your-vapid-private-key
      - [email protected]
      - TOKEN_ENCRYPTION_KEY=your-fernet-key
    volumes:
      - notification-db:/app/db
volumes:
  notification-db:

Note: The Docker image uses multi-architecture support (amd64/arm64) and runs with gunicorn -w 4 -b 0.0.0.0:5000 "app.web.main:create_app()" to properly initialize the Flask application factory.

Usage Instructions

Starting the Application

Development Mode:

export FLASK_APP=app.web.main
export FLASK_ENV=development
flask run

Production Mode:

gunicorn -w 4 -b 0.0.0.0:5000 "app.web.main:create_app()"

Accessing the Application

  1. Navigate to http://localhost:5000
  2. Click "Login with Microsoft" to authenticate
  3. Configure your notification preferences in the dashboard
  4. Enable push notifications when prompted by your browser

API Endpoints

The application provides several API endpoints:

  • POST /api/subscriptions - Subscribe to push notifications
  • DELETE /api/subscriptions - Unsubscribe from push notifications
  • GET /api/notifications/status - Get notification summary
  • POST /api/notifications/mark-read - Mark notifications as read
  • POST /api/notifications/settings - Update notification settings
  • GET /api/session/validate - Validate current session

Configuration Options

Notification Settings:

Users can customize their notification preferences through the dashboard:

  • Language: Choose from English, Hungarian, or Swedish
  • Location Filter: Filter notifications by specific locations (only receive notifications for selected locations)
  • Keyword Filter: Filter notifications by custom keywords (only receive notifications containing specified keywords)
  • Push Notifications: Enable/disable web push notifications (respects user opt-out preferences)

Intelligent Notification Filtering:

The application implements intelligent filtering to ensure users only receive relevant notifications:

  • Location-based Filtering: Users can select specific locations and will only receive notifications for posts from those locations
  • Keyword-based Filtering: Users can define custom keywords and will only receive notifications for posts containing those keywords
  • Push Opt-out: Users can disable push notifications while keeping other notification types active
  • Targeted Delivery: Push notifications are only sent to users whose filters match the post content, respecting individual preferences
  • Per-User Read State: Each user has their own read/unread status for notifications, allowing independent tracking

Blog API Authentication:

The application supports multiple authentication methods:

  • OAuth2 client credentials
  • Microsoft MSAL authentication
  • NTLM authentication
  • Cookie (session cookie supplied via environment)
  • No authentication (public APIs)

Architecture Overview

├── app/
│   ├── api/routes/          # Flask blueprints and routes
│   ├── core/               # Core configuration and security
│   ├── db/                 # Database models and management
│   ├── services/           # Business logic services
│   ├── utils/              # Utility functions
│   └── web/                # Web application entry point
├── static/                 # Frontend assets
├── templates/              # Jinja2 templates
└── db/                     # SQLite database files

Key Components

  • AuthService: Handles Azure AD authentication and token management
  • PollingService: Monitors blog APIs for new content
  • NotificationService: Manages user notifications and web push with intelligent filtering
  • DatabaseManager: Handles all database operations including user-targeted push subscriptions
  • ContentParser: Parses HTML content from blog APIs

Notification Filtering System

The application implements a sophisticated notification filtering system that ensures users only receive relevant content:

  1. Two-Stage Filtering:

    • Location-based filtering: Users can specify which locations they're interested in
    • Keyword-based filtering: Users can define keywords that must be present in posts
  2. Targeted Push Delivery:

    • Push notifications are only sent to users whose filters match the post content
    • The system queries for push subscriptions of matched users only, not all users
    • Individual push notification preferences are respected (users can opt-out of push while keeping other notifications)

Development

Development Dependencies

The project includes development tools configured in pyproject.toml:

  • pytest: Testing framework with coverage reporting
  • ruff: Linting, import sorting, and code formatting

All development dependencies are automatically installed with:

pip install -e .[dev]

Running Tests and Quality Checks

# Install development dependencies
pip install -e .[dev]

# Run tests
pytest

# Run with coverage
pytest --cov=app --maxfail=1 --disable-warnings -q

Code Quality

The project uses automated code quality tools that are also run in CI:

# Format code (Black-compatible)
ruff format app/

# Check formatting only
ruff format --check .

# Lint and sort imports (includes isort via rule I)
ruff check .

# Autofix lint and import issues
ruff check --fix .

# Only sort imports (if needed)
ruff check --select I --fix .

Continuous Integration

This project uses GitHub Actions for automated testing and code quality checks. The CI pipeline:

  • Multi-Python Testing: Tests against Python 3.10, 3.11, and 3.12
  • Code Formatting: Validates code formatting with Ruff
  • Import Sorting: Ensures consistent import organization with Ruff (isort rules)
  • Linting: Code quality checks with Ruff
  • Test Coverage: Automated test execution with coverage reporting

The CI workflow runs on every push to main and on pull requests, ensuring code quality and compatibility across Python versions.

🤝 Contribution Guidelines

Contributions are welcome. Open an issue or create a pull request.

Getting Started

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature/your-feature-name
  3. Make your changes following the coding standards below
  4. Write tests for new functionality
  5. Submit a pull request with a clear description

Coding Standards

  • Python Code: Follow PEP 8 style guidelines
  • Type Hints: Use type annotations for all functions
  • Documentation: Include docstrings for all classes and functions
  • Logging: Use the logging module instead of print statements
  • Error Handling: Implement comprehensive error handling

Reporting Issues

  • Use the GitHub issue tracker
  • Include detailed reproduction steps
  • Provide environment information (Python version, OS, etc.)
  • Include relevant log files when possible

License Information

This project is licensed under the MIT License.

Third-Party Dependencies

This project uses several open-source libraries:

  • Flask (BSD-3-Clause)
  • MSAL (MIT)
  • pywebpush (MIT)
  • APScheduler (MIT)
  • Beautiful Soup (MIT)

See pyproject.toml for a complete list of dependencies.

Support

Built with ❤️ for efficient company communication.

About

A real-time web application for monitoring blog posts with intelligent notifications, Azure AD authentication, and web push support.

Topics

Resources

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors 2

  •  
  •