Skip to content

PioneersHub/fact_check_in

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

134 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Fact Check-in

REST API to validate conference attendees using multiple ticketing systems through a modular backend architecture.

Supported Ticketing Systems

  • Tito - Default backend with native activity support
  • Pretix - Full integration with category-based attribute mapping

Quick Start

Built-In attributes

The following attributes are built-in and default to False:

  • is_onsite
  • is_remote
  • online_access
  • is_speaker
  • is_sponsor
  • is_volunteer
  • is_organizer
  • is_guest

Prep: Setup Ticketing in Pretix

It's important to follow a base structure when setting up the tickets in Pretix already.

Roles can be assigned via:

1. Ticket Categories

"Product categories" in Pretix

The category defines on-site and remote access baseline (e.g. attributes: is_remote, is_onsite, online_access)

2. Tickets (incl. Variations)

"Products" in Pretix

This will update the attributes set in 1.

A usual use case is to add is_speaker for speaker tickets for example.

3. Order ID

'ABCDE-1', "Orders" in Pretix, note one order can have multiple items 'ABCDE-1, 'ABCDE-2',…

This will update the attributes set in 1. and 2.

This is mostly used to handle multiple roles if a person is:

  • organizer_and_speaker: The person is an organizer and gives a talk.
  • organizer_and_sponsor: The person is an organizer and the employer is also sponsor.
  • speaker_and_sponsor: The person is a speaker and the employer is also sponsor.
  • speaker_add_keynote: The person is a keynote speaker.
  • add_speaker: The person is a speaker but has a non-speaker ticket for some reason.

This is a direct assignment for that one ticket for that one person

Access rights Assignment

Access rights are assigned in the following order:

  1. Ticket category
  2. Ticket ID
  3. Order ID

Any step might change attributes. The best practice is to only add access, i,e. setting attributes to True. A mix of adding and removing access will be confusing.

Pitfalls

Use case: Social Event

You grant all ticket holders access to remote attendance online_access: True. But there are also social event tickets available for a +1, social event tickets does not include online_access

  • put event tickets in own category, e.g. Social Event
pretix_mapping:
  categories:
    by_id:
      999: # ID of social event category
        online_access: False
    # OR exclude one or multiple ticket IDs
    by_ticket_id:
      8888: # ID of social event ticket
        online_access: False
⚠️: Change of Category

The category can very easily be changed in the Pretix backend. Other people might do that to:

  • get a nicer look on the stats
  • improve the ticket shop order.

1. Install Dependencies

uv sync

2. Configure Ticketing System

Option A: Tito (Default)

# Create .env file
TITO_TOKEN="your_secret_token"
ACCOUNT_SLUG="account_slug_from_tito"
EVENT_SLUG="event_slug_from_tito"

Option B: Pretix

# Create .env file
PRETIX_TOKEN="your_pretix_api_token"
PRETIX_BASE_URL="https://pretix.eu/api/v1"
PRETIX_ORGANIZER_SLUG="your_organizer_slug"
PRETIX_EVENT_SLUG="your_event_slug"

# Set backend (environment variable takes precedence over config file)
TICKETING_BACKEND=pretix

2b. Configure Authentication (Optional)

The API supports OAuth2/OIDC authentication via Keycloak (or any OIDC-compliant provider). All /tickets/ endpoints require a valid JWT Bearer token when authentication is enabled. Healthcheck endpoints remain public.

Add to your .env file:

OIDC_ISSUER_URL="https://keycloak.example.com/realms/your-realm"
OIDC_AUDIENCE="your-keycloak-client-id"
# Optional: override signing algorithm (default: RS256)
# OIDC_ALGORITHMS="RS256"

When OIDC_ISSUER_URL is not set, authentication is disabled and all endpoints are open. This is the default for local development.

3. Configure Event Mapping (Pretix only)

Edit event_config.yml to map your event's ticket categories and special roles:

# Set backend
TICKETING_BACKEND: pretix

pretix_mapping:
  categories:
    by_id:
      227668: # Your category ID
        is_onsite: true
        online_access: true

    by_ticket_id:
      819314: # Speaker ticket ID
        is_speaker: true

  # Special multi-role assignments
  speaker_and_sponsor:
    - "C3UAP-1" # Ticket code

4. Run the Application

Option A: Direct Run

# IMPORTANT: Use single worker only!
uvicorn app.main:app --port 9898 --host "0.0.0.0"

Option B: Docker (Development)

Running docker compose up loads compose.override.yaml automatically, which starts a local Keycloak instance alongside the API for OAuth2 development.

# Starts fact_check_in + Keycloak (dev mode with hot-reload)
docker compose up

Keycloak quick setup for machine-to-machine access:

  1. Open http://localhost:8080 and login with admin / admin.
  2. Create realm fact-check-in.
  3. Create API client (the token audience):
    • Client ID: fact-check-in-api
    • Protocol: OpenID Connect
    • Client authentication: Off
  4. Create a caller client for each service that will call the API. Example:
    • Client ID: fact-check-in-caller
    • Protocol: OpenID Connect
    • Client authentication: On
    • Enable Service account roles
    • Copy client secret from Credentials
  5. Add audience mapper so caller tokens include API audience:
    • Create client scope fact-check-in-api-access
    • Add mapper type Audience with included audience fact-check-in-api
    • Assign that client scope to fact-check-in-caller

Set API env vars in .env:

# Docker: http://keycloak:8080 | Prod: https://auth.yourdomain.com | Local tools: add 127.0.0.1 keycloak to /etc/hosts
OIDC_ISSUER_URL=http://keycloak:8080/realms/fact-check-in
OIDC_AUDIENCE="fact-check-in-api"

Option C: Docker (Production)

In production, Keycloak should already be running (dedicated host or managed service). Use only compose.yaml to skip the dev override, and point your host nginx to port 9898.

# Build the image
# Set DOCKER_DEFAULT_PLATFORM to match server arch if building cross-platform.
# Configure image name/tag with IMAGE_NAME and IMAGE_TAG env vars.
# Example: `DOCKER_DEFAULT_PLATFORM=linux/amd64 IMAGE_NAME=validation.api IMAGE_TAG=latest docker compose build`
docker compose build

# Start without the dev Keycloak override
docker compose -f compose.yaml up -d

Note: Startup takes ~30 seconds while loading ticket data.

API Documentation: Once running, visit:

Features

  • OAuth2 Authentication: JWT validation via Keycloak or any OIDC provider, with OIDC auto-discovery, JWKS caching, and typed token claims
  • Modular Backend Architecture: Easily switch between ticketing systems or add new ones
  • Dynamic Configuration: Backend selection via environment variables or config files
  • Smart Validation:
    • Validate attendees by ticket code + name (with fuzzy matching)
    • Validate attendees by email
    • Configurable name matching thresholds
  • Flexible Attribute Mapping:
    • Tito: Native activity support
    • Pretix: Category and product name-based mapping
  • Special Attendee Types: Automatic detection of speakers, sponsors, volunteers, organizers
  • Access Level Detection: Distinguish between on-site, remote, and online attendees
  • Day Pass Support: Handle day-specific access (Monday, Tuesday, etc.)

Backend Architecture

The application uses a modular backend system that allows seamless switching between different ticketing platforms:

  • Abstract Interface: TicketingBackend base class defines the contract
  • Dynamic Loading: Backends are loaded at runtime based on configuration
  • Consistent API: Same REST endpoints work with any backend
  • Easy Extension: Add new backends by implementing the interface

API Endpoints

All /tickets/ endpoints require a valid Bearer token when authentication is enabled.

  • POST /tickets/validate_name/ - Validate by ticket ID and name
  • POST /tickets/validate_email/ - Validate by email
  • POST /tickets/validate_attendee/ - Validate by order ID and name (Pretix)
  • GET /tickets/ticket_types/ - List available ticket types
  • GET /tickets/ticket_count/ - Count of tickets in cache
  • GET /tickets/refresh_all/ - Force reload ticket data
  • GET /healthcheck/alive - Health check (public, no auth required)

Development

# Install with dev dependencies
uv sync

# Set up pre-commit hooks
prek install --hook-type pre-commit --hook-type pre-push

# Run tests
pytest

# Run linting/formatting
ruff check . --fix
ruff format .

Agentic API

This project was partially updated with Claude CLI. Instructions for Claude are in CLAUDE.md

Documentation

Other

There are issues of the library that created the social cards on macOS, the cairo svg library is required: brew install cairo.
Even if installed cairo might not be found. Fixes:

  • export DYLD_FALLBACK_LIBRARY_PATH=/opt/homebrew/lib
  • Add a symlink in project root: ln -s /opt/homebrew/opt/cairo/lib/libcairo.2.dylib

About

Validate if the attendee is registered for the conference e.g. by ticket code, name and email

Resources

Stars

Watchers

Forks

Sponsor this project

 

Contributors