Skip to content

PorticoEstate/OutlookBookingSync

Repository files navigation

OutlookBookingSync - Generic Calendar Bridge

A production-ready, extensible calendar synchronization platform that acts as a universal bridge between any calendar systems. Built with PHP/Slim4, this system can synchronize events between Outlook (Microsoft 365) and any other calendar system using REST APIs.

🎯 Overview

OutlookBookingSync has been transformed into a Generic Calendar Bridge - a flexible, extensible platform that can connect any calendar system to any other calendar system. While it started as an Outlook-specific solution, it now supports universal calendar synchronization.

What Makes This Universal:

  • 🌐 Bridge Pattern Architecture - Extensible to any calendar system
  • 🔗 REST API Communication - Standard HTTP interfaces for all integrations
  • 🏠 Self-Hosted Solution - Full control and customization
  • 🏢 Production Ready - Enterprise-grade reliability and monitoring
  • 👨‍💻 Developer Friendly - Easy to extend with new calendar adapters

🚀 Key Features

  • Universal Bridge System - Connect any calendar to any other calendar
  • Complete Bidirectional Sync - Events flow seamlessly between systems
  • Comprehensive Sync Status Tracking - Real-time monitoring, error recovery, and retry mechanisms
  • Automatic Deletion Handling - Detects and syncs deletions across systems
  • Resource Mapping Management - Map booking resources to calendar systems
  • Webhook-Free Operation - Works perfectly with polling (no public IP needed)
  • Real-time Webhooks - Optional instant sync for internet-accessible systems
  • RESTful API - Comprehensive endpoints for all operations including sync status management
  • Health Monitoring - Statistics, logs, and real-time sync status monitoring
  • Interactive Dashboard - Web-based monitoring interface with sync management controls
  • Docker Containerized - Easy deployment and scaling

🏗️ Architecture

┌─────────────────┐    REST API    ┌─────────────────┐    REST API    ┌─────────────────┐
│                 │◄──────────────►│                 │◄──────────────►│                 │
│ Booking System  │                │ Calendar Bridge │                │ Microsoft Graph │
│                 │                │   (Middleware)  │                │      API        │
└─────────────────┘                └─────────────────┘                └─────────────────┘

Supported Calendar Systems:

  • Microsoft Outlook/Graph API (Full implementation)
  • Generic Booking Systems (REST API)
  • 🔄 Google Calendar (Extensible - implement GoogleBridge)
  • 🔄 CalDAV Systems (Extensible - implement CalDAVBridge)
  • 🔄 Any Custom System (Implement AbstractCalendarBridge)

📋 System Requirements

  • PHP 8.4+
  • PostgreSQL Database
  • Docker & Docker Compose (recommended)
  • Microsoft Graph API Credentials (for Outlook integration)
  • Network access to target calendar systems

🏗️ Quick Start

1. Clone and Setup

git clone <repository-url>
cd OutlookBookingSync

2. Configure Environment

cp .env.example .env
cp .env.compose.example .env.compose
# Edit .env with your database and Microsoft Graph credentials

3. Setup Database

# Create bridge database schema
scripts/setup_bridge_database.sh

or just apply the database script directly in your PostgreSQL client.

database/bridge_schema.sql

4. Start the Bridge

# Using Docker (recommended)
docker compose up -d

# Or run directly with PHP
php -S localhost:8082 index.php

5. Verify Installation

# Check bridge health
curl -H "api_key: change-me-strong-random" http://localhost:8082/bridges/health

# List available bridges
curl -H "api_key: change-me-strong-random" http://localhost:8082/bridges

# Test resource discovery (example with outlook bridge)
curl -H "api_key: change-me-strong-random" http://localhost:8082/bridges/outlook/available-resources
curl -H "api_key: change-me-strong-random" http://localhost:8082/bridges/outlook/available-groups

# Test resource mapping API
curl -H "api_key: change-me-strong-random" http://localhost:8082/mappings/resources

6. Setup Your Booking System API

See README_BRIDGE.md for detailed booking system API requirements.

Roadmap and Operations

Authentication and Dashboard

  • Set an API key via .env (development) or .env.compose (Docker). The application checks $_ENV['API_KEY'].
  • The dashboard prompts for the API key on first load and stores it in your browser. Press Ctrl+K to update it.
  • For curl or scripts, send the header: api_key: <your key>.

Maintenance: sync log retention

  • Endpoint: POST /maintenance/cleanup-logs?days=30 removes old rows from bridge_sync_logs (defaults to 30 days if omitted).
  • Example:
curl -s -X POST "http://localhost:8082/maintenance/cleanup-logs?days=30" \
  -H "api_key: change-me-strong-random"
  • Cron: The container runs this daily at 03:00. Override retention via CLEANUP_DAYS in .env.compose.

🛡️ Production readiness

Use this checklist before exposing the service in production.

Security

  • Set a strong, unique API_KEY (store in .env.compose or a secret manager). Rotate periodically.
  • Disable legacy endpoints: set ENABLE_LEGACY_WEBHOOKS=false.
  • Terminate TLS at a reverse proxy (nginx/Traefik) and prefer private network exposure.
  • Add proxy protections: rate limiting, request size limits, and optional IP allowlist for admin endpoints and /dashboard.

Operations and resilience

  • Run with Docker restart policy and a container healthcheck.
  • Ensure PHP runs with production settings (display_errors off; error logging on).
  • Verify cron schedules do not overlap and timezone is correct; keep API_KEY available to cron (entrypoint already wires the header).

Observability

  • Centralize logs (Apache/PHP/app) and alert on /health/system degradation.
  • Track cron success/failure and set up basic metrics dashboards.

Data and database

  • Apply migrations on deploy; set up automated backups and retention.
  • Validate DB performance and connection limits under expected load.

CI/CD quality gates

  • Add a minimal pipeline: php -l, static analysis (PHPStan), and a few unit/integration tests.

Optional docker-compose hardening

services:
  portico_outlook:
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-fsS", "http://localhost/health"]
      interval: 30s
      timeout: 5s
      retries: 3

Example: Bridge-Based Deletion Handling

# Example: Handle booking system cancellation (sets event to inactive)
# The bridge system will automatically detect and sync the deletion to Outlook

# 1. Set booking system event to inactive (via your booking system)
curl -X PUT http://your-booking-system/api/events/123 \
  -d '{"status": "inactive"}'

# 2. Run deletion detection to sync to Outlook
curl -X POST -H "api_key: change-me-strong-random" http://localhost:8082/bridges/sync-deletions

# Example: Handle Outlook deletion
# When an Outlook event is deleted, webhooks or polling will detect it
# and automatically mark the corresponding booking system event as inactive

🆕 Advanced Features

Composite ID System

Universal event identification across different calendar systems:

  • Format: {type}_{original_id} (e.g., event_78269, booking_123)
  • Bidirectional Support: Works seamlessly in both sync directions
  • Type Safety: Preserves original event type and ID for accurate API calls
  • Universal Mapping: Enables correct addressing across any calendar system

Supported Event Types:

  • event_ - Standard calendar events (Priority: 1 - Highest)
  • booking_ - Booking system reservations (Priority: 2)
  • allocation_ - Resource allocation entries (Priority: 3 - Lowest)
  • meeting_ - Meeting room bookings (Priority: 2)
  • appointment_ - Appointment entries (Priority: 2)

Priority Filtering System

Intelligent conflict resolution for overlapping reservations:

  • Automatic Priority Resolution: Handles multiple events in the same time slot
  • Configurable Hierarchy: Event > Booking > Allocation priority levels
  • Conflict Logging: Detailed audit trail of all filtering decisions
  • Performance Optimized: Minimal overhead with efficient filtering algorithms

Session-Based Authentication

Enterprise-grade authentication for booking system integrations:

  • Login Flow: Secure session establishment with username/password
  • Session Management: Automatic token refresh and session maintenance
  • API Security: Session tokens used for all API communications
  • Fallback Support: Graceful handling of session expiration

🔧 Core Bridge Operations

Resource Discovery

# Discover available calendar resources
curl -X GET "http://localhost:8082/bridges/outlook/available-resources?query=conference&limit=10"

# Get calendar groups
curl -X GET "http://localhost:8082/bridges/outlook/available-groups?query=meeting&limit=5"

Event Synchronization with Composite IDs

# Sync events between systems (automatic composite ID handling)
curl -X POST "http://localhost:8082/bridges/sync/booking_system/outlook" \
  -H "Content-Type: application/json" \
  -d '{
    "source_calendar_id": "room_123",
    "target_calendar_id": "conference-room-a@company.com",
    "apply_priority_filter": true
  }'

# Response includes composite ID information
{
  "success": true,
  "synced_events": [
    {
      "composite_id": "event_78269",
      "priority": 1,
      "status": "synced"
    }
  ],
  "filtered_events": [
    {
      "composite_id": "booking_123",
      "priority": 2,
      "status": "filtered_due_to_priority"
    }
  ]
}

Resource Mapping Management

# Create resource mapping
curl -X POST "http://localhost:8082/mappings/resources" \
  -H "Content-Type: application/json" \
  -d '{
    "bridge_from": "booking_system",
    "bridge_to": "outlook",
    "resource_id": "room_123", 
    "calendar_id": "conference-room-a@company.com"
  }'

# Delete mapping by composite key
curl -X DELETE "http://localhost:8082/mappings/resources/by-key/booking_system/room_123/conference-room-a@company.com"

🔧 Configuration

Environment Variables

  • DB_HOST, DB_PORT, DB_NAME, DB_USER, DB_PASS - Database configuration
  • OUTLOOK_CLIENT_ID, OUTLOOK_CLIENT_SECRET, OUTLOOK_TENANT_ID, OUTLOOK_GROUP_ID - Microsoft Graph API
  • APP_BASE_URL - Base URL for this service (used in links/webhooks)
  • API_KEY - API key for endpoint security (send as header api_key)
  • CLEANUP_DAYS - Days to keep sync logs (used by daily cleanup cron)
  • RENEW_MINUTES - Renewal threshold in minutes for webhook subscriptions (hourly cron)

Bridge Configuration

Bridges are automatically registered on service startup using environment variables. Configure your credentials in the .env file:

# Microsoft Graph API
OUTLOOK_CLIENT_ID=your_client_id
OUTLOOK_CLIENT_SECRET=your_client_secret
OUTLOOK_TENANT_ID=your_tenant_id
OUTLOOK_GROUP_ID=your_group_id

# Booking System API (Session-based authentication)
BOOKING_SYSTEM_API_URL=http://your-booking-system/api
BOOKING_SYSTEM_LOGIN=your_username
BOOKING_SYSTEM_PASSWORD=your_password
BOOKING_SYSTEM_DOMAIN=your_domain
BOOKING_SYSTEM_THROW_ON_FAILURE=true

# Application
APP_BASE_URL=https://bridge.example.com
API_KEY=replace_me

The bridges will be automatically available once the service starts.

📊 API Endpoints

Bridge Management

  • GET /bridges - List all available bridges
  • GET /bridges/{bridge}/calendars - Get calendars for a bridge
  • GET /bridges/{bridge}/available-resources - Get available resources (rooms/equipment) for a bridge
  • GET /bridges/{bridge}/available-groups - Get available groups/collections for a bridge
  • GET /bridges/{bridge}/resources/{resourceId}/calendar-items - Get calendar items for a specific resource on a bridge
  • POST /bridges/sync/{from}/{to} - Sync events between bridges
  • POST /bridges/webhook/{bridge} - Handle bridge webhooks (legacy /webhook/outlook-notifications is redirected)
  • POST /bridges/{bridge}/subscriptions - Create webhook subscriptions for a bridge
  • GET /bridges/health - Get health status of all bridges

Resource Mapping

  • GET /mappings/resources - Get all resource mappings
  • POST /mappings/resources - Create new resource mapping
  • PUT /mappings/resources/{id} - Update resource mapping
  • DELETE /mappings/resources/by-key/{bridge_from}/{source_calendar_id}/{target_calendar_id} - Delete resource mapping by composite key
  • GET /mappings/resources/by-resource/{source_calendar_id} - Get mappings by booking system resource ID

Deletion & Cancellation Sync

  • POST /bridges/sync-deletions - Detect and sync deletions across bridge systems
  • POST /bridges/process-deletion-queue - Process webhook-based deletion notifications

Health & Monitoring

  • GET /health - Quick health check
  • GET /health/system - Comprehensive system health
  • GET /health/dashboard - Dashboard data
  • GET /health/sync-status - Detailed sync status
  • POST /health/re-enable-failed - Re-enable failed events (all bridges)
  • POST /bridges/process-pending-syncs[/{bridge}] - Process pending syncs
  • POST /bridges/re-enable-failed[/{bridge}] - Re-enable failed events
  • GET /bridges/sync-stats[/{bridge}] - Sync statistics
  • GET /bridges/cancelled-events[/{bridge}] - Cancelled events
  • GET /bridges/{bridge}/pending-events - Events pending sync
  • POST /alerts/check - Run alert checks
  • GET /alerts - Recent alerts
  • GET /alerts/stats - Alert statistics
  • POST /alerts/{id}/acknowledge - Acknowledge an alert
  • DELETE /alerts/old - Clear old alerts

Maintenance

  • POST /maintenance/cleanup-logs - Cleanup old sync logs (query: ?days=int, default 30)
  • POST /maintenance/renew-subscriptions - Renew expiring webhook subscriptions (query: ?bridge=outlook&renew_before_minutes=int&limit=int)

📖 Documentation

For complete technical documentation and API reference:

Legacy Endpoints (Redirected/Removed)

The following legacy endpoints have been removed or redirected to bridge equivalents:

  • POST /sync/to-outlook → Use POST /bridges/sync/booking_system/outlook
  • POST /sync/from-outlook → Use POST /bridges/sync/outlook/booking_system
  • GET /sync/pending-items → Use GET /mappings/resources
  • DELETE /cancel/reservation/{type}/{id}/{resourceId} → Use bridge deletion sync (/bridges/sync-deletions)
  • POST /cancel/bulk → Use POST /bridges/process-deletion-queue
  • GET /cancel/stats → Use health endpoints (/health/system, /bridges/sync-stats)
  • POST /webhook/outlook-notifications → Prefer POST /bridges/webhook/outlook (legacy is still supported)

⚙️ Automated Processing

The system supports automated processing through cron jobs that use bridge endpoints:

# Bidirectional bridge synchronization
*/5 * * * * curl -X POST http://localhost:8082/bridges/sync/booking_system/outlook \
  -H "Content-Type: application/json" \
  -d '{"start_date":"$(date +%Y-%m-%d)","end_date":"$(date -d \"+7 days\" +%Y-%m-%d)"}'

*/10 * * * * curl -X POST http://localhost:8082/bridges/sync/outlook/booking_system \
  -H "Content-Type: application/json" \
  -d '{"start_date":"$(date +%Y-%m-%d)","end_date":"$(date -d \"+7 days\" +%Y-%m-%d)"}'

# Enhanced deletion processing (recommended)
*/5 * * * * /scripts/enhanced_process_deletions.sh

# Alternative: Individual deletion sync calls
*/5 * * * * curl -X POST http://localhost:8082/bridges/process-deletion-queue
*/5 * * * * curl -X POST http://localhost:8082/bridges/sync-deletions

# Health monitoring
*/10 * * * * curl -X GET http://localhost:8082/bridges/health
*/15 * * * * curl -X GET http://localhost:8082/health/system

📚 Documentation

Comprehensive Guides:

Technical References:

Legacy Documentation:

🌐 Service Architecture

Current Implementation:

Generic Calendar Bridge (Port 8080)
├── Bridge Management API (/bridges/*)
├── Resource Mapping API (/mappings/*)
├── Health Monitoring (/health/*)
├── Deletion Sync Processing
└── Webhook Handling (Real-time sync)

Supported Integrations:

  • Microsoft Outlook/365 (Full webhook + API support)
  • Booking Systems (REST API)
  • 🔄 Extensible (Add new calendar systems by implementing AbstractCalendarBridge)

🚀 Getting Started

  1. For New Users: Start with README_BRIDGE.md - Complete setup guide
  2. For Developers: See booking system API requirements in README_BRIDGE.md
  3. For Testing: Use ./test_bridge.sh to validate all endpoints

🔍 Troubleshooting

Bridge Health Check

# Check overall bridge health
curl -H "api_key: your_key" http://localhost:8082/bridges/health

# Test specific bridge
curl -H "api_key: your_key" http://localhost:8082/bridges/outlook/calendars

# View dashboard data (JSON)
curl -H "api_key: your_key" http://localhost:8082/health/dashboard | jq

Common Issues

  • Ensure .env file is properly configured (DB, Outlook, API_KEY)
  • Verify Microsoft Graph API permissions
  • Confirm resource mappings exist before syncing
  • Run deletion processor if deletions aren’t syncing
  • Verify webhook subscriptions are active (if using webhooks)
  • Check database connectivity and credentials
  • Confirm network access to Microsoft 365

📝 Production Readiness

Verified Production Features:

  • Transaction safety with rollback support
  • Zero error rate in sync operations
  • Loop prevention mechanisms
  • Comprehensive audit logging
  • Real-time statistics and monitoring
  • Graceful error handling and recovery

🤝 Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Commit your changes
  4. Push to the branch
  5. Create a Pull Request

📄 License

See LICENSE file for details.

✅ Implementation Status

🎉 Transformation complete — ready for production

OutlookBookingSync has been successfully transformed into a Generic Calendar Bridge platform:

✅ Architecture Transformation (COMPLETED)

  • Bridge Pattern: Full migration to extensible bridge architecture
  • Generic Interface: AbstractCalendarBridge base class implemented
  • REST API: Pure REST communication for all calendar systems
  • Database Schema: Complete bridge schema for mappings and configurations

✅ Working Bridges (COMPLETED)

  • OutlookBridge: Microsoft Graph API with webhook support and resource discovery
  • BookingSystemBridge: Generic booking system with REST API + DB fallback and configurable endpoints
  • BridgeManager: Central orchestration service managing all bridges
  • Resource Discovery: All bridges support available-resources, available-groups, and user calendar queries

✅ Production Features (COMPLETED)

  • Bidirectional Sync: Events sync seamlessly between any bridge types
  • Deletion Handling: Robust deletion detection and synchronization
  • Real-time Webhooks: Instant updates via webhook notifications
  • Resource Mapping: Calendar resource management system
  • Health Monitoring: Comprehensive system monitoring and logging
  • API Security: Authentication and secure endpoint access

✅ Code Organization (COMPLETED)

  • Clean Architecture: Obsolete code moved to obsolete/ directories
  • Modern API: RESTful endpoints replacing legacy interfaces
  • Documentation: Complete guides and API documentation
  • Production Scripts: Setup, testing, and automation tools

🚀 Ready for Extension

The bridge platform is now ready to support additional calendar systems:

  • Google Calendar (implement GoogleCalendarBridge)
  • CalDAV systems (implement CalDAVBridge)
  • Exchange Server (implement ExchangeBridge)
  • Any custom calendar system (extend AbstractCalendarBridge)

About

Synchronize room bookings between the internal booking system and Outlook (Microsoft 365) room calendars, ensuring both systems reflect the current state of all room reservations.

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors