A Flask-based REST API for managing events and RSVPs with different access levels. This API is designed to teach web security best practices through incremental improvements.
This repo was created as an assignment during my training as a QA Engineer. The Flask API itself was provided as starter code -- my task was to build a complete testing and CI/CD pipeline around it.
- Flask application with authentication, event, and RSVP endpoints (
app.py,models.py,config.py,routes/) - OpenAPI specification (
openapi.yaml) - Dependencies (
requirements.txt)
- Test suite -- API integration tests and unit tests with pytest (
tests/)- Client pattern (similar to Page Object Model) for better maintainability (
tests/api_clients/) - Fixtures and test data generation (
tests/conftest.py)
- Client pattern (similar to Page Object Model) for better maintainability (
- CI/CD pipeline -- GitHub Actions workflow that automatically builds and tests on every push (
.github/workflows/ci_workflow.yml) - Dockerization -- Dockerfile and .dockerignore for containerized execution
- README extension -- Documentation of Docker setup, CI/CD, test architecture, and Swagger UI
- Public Events: Anyone can RSVP without authentication
- Protected Events: Requires user authentication to RSVP
- Admin Events: Requires admin role to RSVP
- Flask 3.0.0
- Flask-SQLAlchemy (SQLite database)
- Flask-CORS
- Flask-JWT-Extended (JWT authentication)
-
Create and activate a virtual environment:
Windows:
python -m venv venv venv\Scripts\activate
Linux/Mac:
python3 -m venv venv source venv/bin/activate -
Install dependencies:
pip install -r requirements.txt- Run the application:
python app.pyThe API will be available at http://localhost:5000
The application can be run in a Docker container.
- Build the Docker image:
docker build -t events-api .- Run the container:
docker run -d -p 5000:5000 --name events_api_container events-api- Verify the API is running:
curl localhost:5000/api/health- Stop and remove the container:
docker stop events_api_container
docker rm events_api_containerThis project uses GitHub Actions for continuous integration. The pipeline is triggered on every push or pull request to main and performs the following steps:
- Checks out the repository
- Builds the Docker image
- Starts the container and runs a health check
- Sets up Python and installs dependencies
- Runs the full test suite against the containerized API
- Cleans up the container
The workflow configuration can be found in .github/workflows/ci_workflow.yml.
The API includes interactive Swagger UI documentation. After starting the server:
-
Open your browser and navigate to:
http://localhost:5000/apidocs -
You'll see an interactive API documentation interface where you can:
- Browse all available endpoints
- See request/response schemas
- Test endpoints directly from the browser
- Authenticate using the "Authorize" button (enter your JWT token)
-
To use the "Authorize" button:
- First, login via
/api/auth/loginto get your JWT token - Click the "Authorize" button at the top of the Swagger UI
- Enter:
Bearer <your_jwt_token>(replace<your_jwt_token>with your actual token) - Now you can test protected endpoints directly from Swagger UI
- First, login via
Alternative: You can also view the OpenAPI specification directly at http://localhost:5000/apispec_1.json
-
POST /api/auth/register- Register a new user{ "username": "user123", "password": "password123" } -
POST /api/auth/login- Login and get JWT token{ "username": "user123", "password": "password123" }
GET /api/events- Get all eventsGET /api/events/<id>- Get a specific eventPOST /api/events- Create a new event (requires authentication){ "title": "Python Meetup", "description": "Monthly Python developer meetup", "date": "2026-01-15T18:00:00", "location": "Tech Hub, Room 101", "capacity": 50, "is_public": true, "requires_admin": false }
-
POST /api/rsvps/event/<event_id>- RSVP to an event{ "attending": true } -
GET /api/rsvps/event/<event_id>- Get all RSVPs for an event
For protected endpoints, include the JWT token in the Authorization header:
Authorization: Bearer <your_jwt_token>
Tests are located in the tests/ directory and use pytest with requests for HTTP-based API testing.
tests/
api_clients/ # Client classes for API interaction
auth_client.py # AuthClient: register, login
events_client.py # EventsClient: create_event
rsvps_client.py # RSVPSClient: rsvp_to_event
conftest.py # Fixtures and shared test data
test_api.py # API integration tests
test_models.py # Unit tests for data models
The test suite follows a client pattern (similar to Page Object Model for UI tests): each API endpoint group has a dedicated client class that encapsulates HTTP calls. Tests use these clients instead of making raw requests calls, improving readability and maintainability.
- Install test dependencies:
pip install -r requirements-test.txt- Make sure the API is running (locally or in Docker), then:
pytest -vThis is a basic implementation designed for educational purposes. The following security considerations are intentionally simplified and can be improved in subsequent lessons:
- Password storage (currently using werkzeug, but can be improved)
- JWT token handling
- Input validation
- SQL injection prevention (SQLAlchemy helps, but can be improved)
- Rate limiting
- CORS configuration
- Error handling and information disclosure
The application uses SQLite by default. The database file (events.db) will be created automatically on first run.
Note: The first user registered automatically becomes an admin for demo purposes.